Bug Summary

File:builds/wireshark/wireshark/epan/addr_resolv.c
Warning:line 3333, column 42
An undefined value may be read from 'errno'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name addr_resolv.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan -isystem /builds/wireshark/wireshark/build/epan -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /usr/include/lua5.4 -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -D epan_EXPORTS -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2026-01-25-100340-3605-1 -x c /builds/wireshark/wireshark/epan/addr_resolv.c
1/* addr_resolv.c
2 * Routines for network object lookup
3 *
4 * Laurent Deniel <[email protected]>
5 *
6 * Add option to resolv VLAN ID to describing name
7 * Uli Heilmeier, March 2016
8 *
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <[email protected]>
11 * Copyright 1998 Gerald Combs
12 *
13 * SPDX-License-Identifier: GPL-2.0-or-later
14 */
15
16#include "config.h"
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <errno(*__errno_location ()).h>
22
23#include <wsutil/strtoi.h>
24#include <wsutil/ws_assert.h>
25
26#include "enterprises.h"
27#include "manuf.h"
28
29/*
30 * Win32 doesn't have SIGALRM (and it's the OS where name lookup calls
31 * are most likely to take a long time, given the way address-to-name
32 * lookups are done over NBNS).
33 *
34 * macOS does have SIGALRM, but if you longjmp() out of a name resolution
35 * call in a signal handler, you might crash, because the state of the
36 * resolution code that sends messages to lookupd might be inconsistent
37 * if you jump out of it in middle of a call.
38 *
39 * There's no guarantee that longjmp()ing out of name resolution calls
40 * will work on *any* platform; OpenBSD got rid of the alarm/longjmp
41 * code in tcpdump, to avoid those sorts of problems, and that was
42 * picked up by tcpdump.org tcpdump.
43 *
44 * So, for now, we do not use alarm() and SIGALRM to time out host name
45 * lookups. If we get a lot of complaints about lookups taking a long time,
46 * we can reconsider that decision. (Note that tcpdump originally added
47 * such a timeout mechanism that for the benefit of systems using NIS to
48 * look up host names; that might now be fixed in NIS implementations, for
49 * those sites still using NIS rather than DNS for that.... tcpdump no
50 * longer does that, for the same reasons that we don't.)
51 *
52 * If we're using an asynchronous DNS resolver, that shouldn't be an issue.
53 * If we're using a synchronous name lookup mechanism (which we'd do mainly
54 * to support resolving addresses and host names using more mechanisms than
55 * just DNS, such as NIS, NBNS, or Mr. Hosts File), we could do that in
56 * a separate thread, making it, in effect, asynchronous.
57 */
58
59#ifdef HAVE_NETINET_IN_H1
60# include <netinet/in.h>
61#endif
62
63#ifdef HAVE_NETDB_H1
64#include <netdb.h>
65#endif
66
67#ifdef HAVE_SYS_SOCKET_H1
68#include <sys/socket.h> /* needed to define AF_ values on UNIX */
69#endif
70
71#ifdef _WIN32
72#include <winsock2.h> /* needed to define AF_ values on Windows */
73#include <ws2tcpip.h>
74#endif
75
76#ifdef _WIN32
77# define socklen_t unsigned int
78#endif
79#include <ares.h>
80#include <ares_version.h>
81
82#include <glib.h>
83
84#include <epan/packet.h>
85#include "addr_resolv.h"
86#include "wsutil/filesystem.h"
87
88#include <wsutil/report_message.h>
89#include <wsutil/file_util.h>
90#include <wsutil/pint.h>
91#include <wsutil/inet_cidr.h>
92
93#include <epan/strutil.h>
94#include <epan/to_str.h>
95#include <epan/maxmind_db.h>
96#include <epan/prefs.h>
97#include <epan/uat.h>
98#include "services.h"
99
100#define ENAME_HOSTS"hosts" "hosts"
101#define ENAME_SUBNETS"subnets" "subnets"
102#define ENAME_ETHERS"ethers" "ethers"
103#define ENAME_IPXNETS"ipxnets" "ipxnets"
104#define ENAME_MANUF"manuf" "manuf"
105#define ENAME_WKA"wka" "wka"
106#define ENAME_SERVICES"services" "services"
107#define ENAME_VLANS"vlans" "vlans"
108#define ENAME_SS7PCS"ss7pcs" "ss7pcs"
109#define ENAME_ENTERPRISES"enterprises" "enterprises"
110#define ENAME_TACS"tacs" "tacs"
111
112#define HASHETHSIZE2048 2048
113#define HASHHOSTSIZE2048 2048
114#define HASHIPXNETSIZE256 256
115#define SUBNETLENGTHSIZE32 32 /*1-32 inc.*/
116
117/* hash table used for IPv4 lookup */
118
119#define HASH_IPV4_ADDRESS(addr)((((((guint32) ( (((guint32) (addr) & (guint32) 0x000000ffU
) << 24) | (((guint32) (addr) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (addr) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (addr) & (guint32) 0xff000000U
) >> 24)))))) & (2048 - 1))
(g_htonl(addr)(((((guint32) ( (((guint32) (addr) & (guint32) 0x000000ffU
) << 24) | (((guint32) (addr) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (addr) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (addr) & (guint32) 0xff000000U
) >> 24))))))
& (HASHHOSTSIZE2048 - 1))
120
121
122typedef struct sub_net_hashipv4 {
123 unsigned addr;
124 /* XXX: No longer needed?*/
125 uint8_t flags; /* B0 dummy_entry, B1 resolve, B2 If the address is used in the trace */
126 struct sub_net_hashipv4 *next;
127 char name[MAXNAMELEN64];
128} sub_net_hashipv4_t;
129
130/* Array of entries of subnets of different lengths */
131typedef struct {
132 size_t mask_length; /*1-32*/
133 uint32_t mask; /* e.g. 255.255.255.*/
134 sub_net_hashipv4_t** subnet_addresses; /* Hash table of subnet addresses */
135} subnet_length_entry_t;
136
137
138/* hash table used for IPX network lookup */
139
140/* XXX - check goodness of hash function */
141
142#define HASH_IPX_NET(net)((net) & (256 - 1)) ((net) & (HASHIPXNETSIZE256 - 1))
143
144typedef struct hashipxnet {
145 unsigned addr;
146 struct hashipxnet *next;
147 char name[MAXNAMELEN64];
148} hashipxnet_t;
149
150typedef struct hashvlan {
151 unsigned id;
152/* struct hashvlan *next; */
153 char name[MAXVLANNAMELEN128];
154} hashvlan_t;
155
156typedef struct ss7pc {
157 uint32_t id; /* 1st byte NI, 3 following bytes: Point Code */
158 char pc_addr[MAXNAMELEN64];
159 char name[MAXNAMELEN64];
160} hashss7pc_t;
161
162/* hash tables used for ethernet and manufacturer lookup */
163struct hashether {
164 uint8_t flags; /* (See above) */
165 uint8_t addr[6];
166 char hexaddr[6*3];
167 char resolved_name[MAXNAMELEN64];
168};
169
170struct hasheui64 {
171 uint8_t flags; /* (See above) */
172 uint8_t addr[EUI64_ADDR_LEN8];
173 char hexaddr[EUI64_ADDR_LEN8*3];
174 char resolved_name[MAXNAMELEN64];
175};
176
177struct hashwka {
178 uint8_t flags; /* (See above) */
179 char* name;
180};
181
182struct hashmanuf {
183 uint8_t flags; /* (See above) */
184 uint8_t addr[3];
185 char hexaddr[3*3];
186 char resolved_name[MAXNAMELEN64];
187 char resolved_longname[MAXNAMELEN64];
188};
189
190/* internal type used when reading ethers file (or wka, manuf) */
191typedef struct _ether
192{
193 uint8_t addr[8];
194 char name[MAXNAMELEN64];
195 char longname[MAXNAMELEN64];
196} ether_t;
197
198/* internal ipxnet type */
199typedef struct _ipxnet
200{
201 unsigned addr;
202 char name[MAXNAMELEN64];
203} ipxnet_t;
204
205/* internal vlan type */
206typedef struct _vlan
207{
208 unsigned id;
209 char name[MAXVLANNAMELEN128];
210} vlan_t;
211
212static wmem_allocator_t *addr_resolv_scope;
213
214// Maps unsigned -> hashipxnet_t*
215static wmem_map_t *ipxnet_hash_table;
216static wmem_map_t *ipv4_hash_table;
217static wmem_map_t *ipv6_hash_table;
218// Maps unsigned -> hashvlan_t*
219static wmem_map_t *vlan_hash_table;
220static wmem_map_t *ss7pc_hash_table;
221static wmem_map_t *tac_hash_table;
222
223// Maps IP address -> manually set hostname.
224static wmem_map_t *manually_resolved_ipv4_list;
225static wmem_map_t *manually_resolved_ipv6_list;
226
227static addrinfo_lists_t addrinfo_lists;
228
229struct cb_serv_data {
230 char *service;
231 port_type proto;
232};
233
234// Maps unsigned -> hashmanuf_t*
235// XXX: Note that hashmanuf_t* only accommodates 24-bit OUIs.
236// We might want to store vendor names from MA-M and MA-S to
237// present in the Resolved Addresses dialog.
238static wmem_map_t *manuf_hashtable;
239// Maps address -> hashwka_t*
240static wmem_map_t *wka_hashtable;
241// Maps address -> hashether_t*
242static wmem_map_t *eth_hashtable;
243// Maps address -> hasheui64_t*
244static wmem_map_t *eui64_hashtable;
245// Maps unsigned -> serv_port_t*
246static wmem_map_t *serv_port_hashtable;
247static wmem_map_t *serv_port_custom_hashtable;
248
249// Maps enterprise-id -> enterprise-desc (only used for user additions)
250static GHashTable *enterprises_hashtable;
251
252static subnet_length_entry_t subnet_length_entries[SUBNETLENGTHSIZE32]; /* Ordered array of entries */
253static bool_Bool have_subnet_entry;
254
255static bool_Bool new_resolved_objects;
256
257static GPtrArray* extra_hosts_files;
258
259static hashether_t *add_eth_name(const uint8_t *addr, const char *name, bool_Bool static_entry);
260static hasheui64_t *add_eui64_name(const uint8_t *addr, const char *name, bool_Bool static_entry);
261static void add_serv_port_cb(const uint32_t port, void *ptr);
262
263/* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx#existing
264 * One-at-a-Time hash
265 */
266unsigned
267ipv6_oat_hash(const void *key)
268{
269 int len = 16;
270 const unsigned char *p = (const unsigned char *)key;
271 unsigned h = 0;
272 int i;
273
274 for ( i = 0; i < len; i++ ) {
275 h += p[i];
276 h += ( h << 10 );
277 h ^= ( h >> 6 );
278 }
279
280 h += ( h << 3 );
281 h ^= ( h >> 11 );
282 h += ( h << 15 );
283
284 return h;
285}
286
287unsigned
288ws_ipv6_hash(const void* key)
289{
290#ifdef HAVE_XXHASH1
291 return wmem_strong_hash(key, 16);
292#else
293 return ipv6_oat_hash(key);
294#endif
295}
296
297gboolean
298ipv6_equal(const void *v1, const void *v2)
299{
300
301 if (memcmp(v1, v2, sizeof (ws_in6_addr)) == 0) {
302 return true1;
303 }
304
305 return false0;
306}
307
308/*
309 * Flag controlling what names to resolve.
310 */
311e_addr_resolve gbl_resolv_flags = {
312 true1, /* mac_name */
313 false0, /* network_name */
314 false0, /* transport_name */
315 true1, /* dns_pkt_addr_resolution */
316 false0, /* handshake_sni_addr_resolution */
317 true1, /* use_external_net_name_resolver */
318 false0, /* vlan_name */
319 false0, /* ss7 point code names */
320 true1, /* maxmind_geoip */
321 false0, /* tac_name */
322};
323
324/* XXX - ares_init_options(3) says:
325 * "The recommended concurrent query limit is about 32k queries"
326 */
327static unsigned name_resolve_concurrency = 500;
328static bool_Bool resolve_synchronously;
329
330/*
331 * Global variables (can be changed in GUI sections)
332 * XXX - they could be changed in GUI code, but there's currently no
333 * GUI code to change them.
334 */
335
336char *g_ethers_path; /* global ethers file */
337char *g_pethers_path; /* personal ethers file */
338char *g_wka_path; /* global well-known-addresses file */
339char *g_manuf_path; /* global manuf file */
340char *g_pmanuf_path; /* personal manuf file */
341char *g_ipxnets_path; /* global ipxnets file */
342char *g_pipxnets_path; /* personal ipxnets file */
343char *g_services_path; /* global services file */
344char *g_pservices_path; /* personal services file */
345char *g_pvlan_path; /* personal vlans file */
346char *g_ss7pcs_path; /* personal ss7pcs file */
347char *g_enterprises_path; /* global enterprises file */
348char *g_penterprises_path; /* personal enterprises file */
349 /* first resolving call */
350
351/*
352 * Submitted asynchronous queries trigger a callback (c_ares_ghba_cb()).
353 * Queries are added to c_ares_queue_head. During processing, queries are
354 * popped off the front of c_ares_queue_head and submitted using
355 * ares_gethostbyaddr().
356 * The callback processes the response, then frees the request.
357 */
358typedef struct _async_dns_queue_msg
359{
360 union {
361 uint32_t ip4;
362 ws_in6_addr ip6;
363 } addr;
364 int family;
365} async_dns_queue_msg_t;
366
367typedef struct _async_hostent {
368 int addr_size;
369 int copied;
370 void *addrp;
371} async_hostent_t;
372
373static void
374c_ares_ghba_cb(void *arg, int status, int timeouts _U___attribute__((unused)), struct hostent *he);
375
376/*
377 * Submitted synchronous queries trigger a callback (c_ares_ghba_sync_cb()).
378 * The callback processes the response, sets completed to true if
379 * completed is non-NULL, then frees the request.
380 */
381typedef struct _sync_dns_data
382{
383 union {
384 uint32_t ip4;
385 ws_in6_addr ip6;
386 } addr;
387 int family;
388 bool_Bool *completed;
389} sync_dns_data_t;
390
391static ares_channel ghba_chan; /* ares_gethostbyaddr -- Usually non-interactive, no timeout */
392static ares_channel ghbn_chan; /* ares_gethostbyname -- Usually interactive, timeout */
393
394static bool_Bool async_dns_initialized;
395static unsigned async_dns_in_flight;
396static wmem_list_t *async_dns_queue_head;
397static GMutex async_dns_queue_mtx;
398
399//UAT for providing a list of DNS servers to C-ARES for name resolution
400bool_Bool use_custom_dns_server_list;
401struct dns_server_data {
402 char *ipaddr;
403 uint32_t udp_port;
404 uint32_t tcp_port;
405};
406
407UAT_CSTRING_CB_DEF(dnsserverlist_uats, ipaddr, struct dns_server_data)static void dnsserverlist_uats_ipaddr_set_cb(void* rec, const
char* buf, unsigned len, const void* u1 __attribute__((unused
)), const void* u2 __attribute__((unused))) { char* new_buf =
g_strndup(buf,len); g_free((((struct dns_server_data*)rec)->
ipaddr)); (((struct dns_server_data*)rec)->ipaddr) = new_buf
; } static void dnsserverlist_uats_ipaddr_tostr_cb(void* rec,
char** out_ptr, unsigned* out_len, const void* u1 __attribute__
((unused)), const void* u2 __attribute__((unused))) { if (((struct
dns_server_data*)rec)->ipaddr ) { *out_ptr = g_strdup_inline
((((struct dns_server_data*)rec)->ipaddr)); *out_len = (unsigned
)strlen((((struct dns_server_data*)rec)->ipaddr)); } else {
*out_ptr = g_strdup_inline (""); *out_len = 0; } }
408UAT_DEC_CB_DEF(dnsserverlist_uats, tcp_port, struct dns_server_data)static void dnsserverlist_uats_tcp_port_set_cb(void* rec, const
char* buf, unsigned len, const void* u1 __attribute__((unused
)), const void* u2 __attribute__((unused))) { char* tmp_str =
g_strndup(buf,len); ws_strtou32(tmp_str, ((void*)0), &((
struct dns_server_data*)rec)->tcp_port); g_free(tmp_str); }
static void dnsserverlist_uats_tcp_port_tostr_cb(void* rec, char
** out_ptr, unsigned* out_len, const void* u1 __attribute__((
unused)), const void* u2 __attribute__((unused))) { *out_ptr =
wmem_strdup_printf(((void*)0), "%u",((struct dns_server_data
*)rec)->tcp_port); *out_len = (unsigned)strlen(*out_ptr); }
409UAT_DEC_CB_DEF(dnsserverlist_uats, udp_port, struct dns_server_data)static void dnsserverlist_uats_udp_port_set_cb(void* rec, const
char* buf, unsigned len, const void* u1 __attribute__((unused
)), const void* u2 __attribute__((unused))) { char* tmp_str =
g_strndup(buf,len); ws_strtou32(tmp_str, ((void*)0), &((
struct dns_server_data*)rec)->udp_port); g_free(tmp_str); }
static void dnsserverlist_uats_udp_port_tostr_cb(void* rec, char
** out_ptr, unsigned* out_len, const void* u1 __attribute__((
unused)), const void* u2 __attribute__((unused))) { *out_ptr =
wmem_strdup_printf(((void*)0), "%u",((struct dns_server_data
*)rec)->udp_port); *out_len = (unsigned)strlen(*out_ptr); }
410
411static uat_t *dnsserver_uat;
412static struct dns_server_data *dnsserverlist_uats;
413static unsigned ndnsservers;
414
415static void
416dns_server_free_cb(void *data)
417{
418 struct dns_server_data *h = (struct dns_server_data*)data;
419
420 g_free(h->ipaddr);
421}
422
423static void*
424dns_server_copy_cb(void *dst_, const void *src_, size_t len _U___attribute__((unused)))
425{
426 const struct dns_server_data *src = (const struct dns_server_data *)src_;
427 struct dns_server_data *dst = (struct dns_server_data *)dst_;
428
429 dst->ipaddr = g_strdup(src->ipaddr)g_strdup_inline (src->ipaddr);
430 dst->udp_port = src->udp_port;
431 dst->tcp_port = src->tcp_port;
432
433 return dst;
434}
435
436static bool_Bool
437dnsserver_uat_fld_ip_chk_cb(void* r _U___attribute__((unused)), const char* ipaddr, unsigned len _U___attribute__((unused)), const void* u1 _U___attribute__((unused)), const void* u2 _U___attribute__((unused)), char** err)
438{
439 //Check for a valid IPv4 or IPv6 address.
440 if (ipaddr && g_hostname_is_ip_address(ipaddr)) {
441 *err = NULL((void*)0);
442 return true1;
443 }
444
445 *err = ws_strdup_printf("No valid IP address given.")wmem_strdup_printf(((void*)0), "No valid IP address given.");
446 return false0;
447}
448
449static bool_Bool
450dnsserver_uat_fld_port_chk_cb(void* r _U___attribute__((unused)), const char* p, unsigned len _U___attribute__((unused)), const void* u1 _U___attribute__((unused)), const void* u2 _U___attribute__((unused)), char** err)
451{
452 if (!p || strlen(p) == 0u) {
453 // This should be removed in favor of Decode As. Make it optional.
454 *err = NULL((void*)0);
455 return true1;
456 }
457
458 if (strcmp(p, "53") != 0){
459 uint16_t port;
460 if (!ws_strtou16(p, NULL((void*)0), &port)) {
461 *err = g_strdup("Invalid port given.")g_strdup_inline ("Invalid port given.");
462 return false0;
463 }
464 }
465
466 *err = NULL((void*)0);
467 return true1;
468}
469
470static void
471c_ares_ghba_sync_cb(void *arg, int status, int timeouts _U___attribute__((unused)), struct hostent *he) {
472 sync_dns_data_t *sdd = (sync_dns_data_t *)arg;
473 char **p;
474
475 if (status == ARES_SUCCESS) {
476 for (p = he->h_addr_list; *p != NULL((void*)0); p++) {
477 switch(sdd->family) {
478 case AF_INET2:
479 add_ipv4_name(sdd->addr.ip4, he->h_name, false0);
480 break;
481 case AF_INET610:
482 add_ipv6_name(&sdd->addr.ip6, he->h_name, false0);
483 break;
484 default:
485 /* Throw an exception? */
486 break;
487 }
488 }
489
490 }
491
492 /*
493 * Let our caller know that this is complete.
494 */
495 *sdd->completed = true1;
496
497 /*
498 * Free the structure for this call.
499 */
500 g_free(sdd);
501}
502
503static void
504wait_for_sync_resolv(bool_Bool *completed) {
505 int nfds;
506 fd_set rfds, wfds;
507 struct timeval tv;
508
509 while (!*completed) {
510 /*
511 * Not yet resolved; wait for something to show up on the
512 * address-to-name C-ARES channel.
513 *
514 * To quote the source code for ares_timeout() as of C-ARES
515 * 1.12.0, "WARNING: Beware that this is linear in the number
516 * of outstanding requests! You are probably far better off
517 * just calling ares_process() once per second, rather than
518 * calling ares_timeout() to figure out when to next call
519 * ares_process().", although we should have only one request
520 * outstanding.
521 * As of C-ARES 1.20.0, the ares_timeout() function is now O(1),
522 * but we don't require that minimum version.
523 * https://github.com/c-ares/c-ares/commit/cf99c025cfb3e21295b59923876a31a68ea2cb4b
524 *
525 * And, yes, we have to reset it each time, as select(), in
526 * some OSes modifies the timeout to reflect the time remaining
527 * (e.g., Linux) and select() in other OSes doesn't (most if not
528 * all other UN*Xes, Windows?), so we can't rely on *either*
529 * behavior.
530 */
531 tv.tv_sec = 1;
532 tv.tv_usec = 0;
533
534 FD_ZERO(&rfds)do { unsigned int __i; fd_set *__arr = (&rfds); for (__i =
0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) ((__arr
)->__fds_bits)[__i] = 0; } while (0)
;
535 FD_ZERO(&wfds)do { unsigned int __i; fd_set *__arr = (&wfds); for (__i =
0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) ((__arr
)->__fds_bits)[__i] = 0; } while (0)
;
536 nfds = ares_fds(ghba_chan, &rfds, &wfds);
537 if (nfds > 0) {
538 if (select(nfds, &rfds, &wfds, NULL((void*)0), &tv) == -1) { /* call to select() failed */
539 /* If it's interrupted by a signal, no need to put out a message */
540 if (errno(*__errno_location ()) != EINTR4)
541 fprintf(stderrstderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno(*__errno_location ())));
542 return;
543 }
544 ares_process(ghba_chan, &rfds, &wfds);
545 }
546 }
547}
548
549static void
550process_async_dns_queue(void)
551{
552 wmem_list_frame_t* head;
553 async_dns_queue_msg_t *caqm;
554
555 if (async_dns_queue_head == NULL((void*)0))
556 return;
557
558 if (!g_mutex_trylock(&async_dns_queue_mtx))
559 return;
560
561 head = wmem_list_head(async_dns_queue_head);
562
563 while (head != NULL((void*)0) && async_dns_in_flight <= name_resolve_concurrency) {
564 caqm = (async_dns_queue_msg_t *)wmem_list_frame_data(head);
565 wmem_list_remove_frame(async_dns_queue_head, head);
566 if (caqm->family == AF_INET2) {
567 ares_gethostbyaddr(ghba_chan, &caqm->addr.ip4, sizeof(uint32_t), AF_INET2,
568 c_ares_ghba_cb, caqm);
569 async_dns_in_flight++;
570 } else if (caqm->family == AF_INET610) {
571 ares_gethostbyaddr(ghba_chan, &caqm->addr.ip6, sizeof(ws_in6_addr),
572 AF_INET610, c_ares_ghba_cb, caqm);
573 async_dns_in_flight++;
574 }
575
576 head = wmem_list_head(async_dns_queue_head);
577 }
578
579 g_mutex_unlock(&async_dns_queue_mtx);
580}
581
582static void
583wait_for_async_queue(void)
584{
585 struct timeval tv = { 0, 0 };
586 int nfds;
587 fd_set rfds, wfds;
588
589 new_resolved_objects = false0;
590
591 if (!async_dns_initialized) {
592 maxmind_db_lookup_process();
593 return;
594 }
595
596 while (1) {
597 /* We're switching to synchronous lookups, so process anything in
598 * the asynchronous queue. There might be more in the queue than
599 * name_resolve_concurrency allows, so check each cycle.
600 */
601 process_async_dns_queue();
602
603 FD_ZERO(&rfds)do { unsigned int __i; fd_set *__arr = (&rfds); for (__i =
0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) ((__arr
)->__fds_bits)[__i] = 0; } while (0)
;
604 FD_ZERO(&wfds)do { unsigned int __i; fd_set *__arr = (&wfds); for (__i =
0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) ((__arr
)->__fds_bits)[__i] = 0; } while (0)
;
605 nfds = ares_fds(ghba_chan, &rfds, &wfds);
606 if (nfds == 0) {
607 /* No more requests waiting for reply; we're done here. */
608 break;
609 }
610
611 /* See comment in wait_for_sync_resolv() about ares_timeout() being
612 * O(N) in the number of outstanding requests until c-ares 1.20, and
613 * why we might as well just set a 1 second to select().
614 */
615 tv.tv_sec = 1;
616 tv.tv_usec = 0;
617
618 if (select(nfds, &rfds, &wfds, NULL((void*)0), &tv) == -1) { /* call to select() failed */
619 /* If it's interrupted by a signal, no need to put out a message */
620 if (errno(*__errno_location ()) != EINTR4)
621 fprintf(stderrstderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno(*__errno_location ())));
622 return;
623 }
624 ares_process(ghba_chan, &rfds, &wfds);
625 }
626
627 maxmind_db_lookup_process();
628 return;
629}
630
631static void
632sync_lookup_ip4(const uint32_t addr)
633{
634 bool_Bool completed = false0;
635 sync_dns_data_t *sdd;
636
637 if (!async_dns_initialized) {
638 /*
639 * c-ares not initialized. Bail out.
640 */
641 return;
642 }
643
644 /*
645 * Start the request.
646 */
647 sdd = g_new(sync_dns_data_t, 1)((sync_dns_data_t *) g_malloc_n ((1), sizeof (sync_dns_data_t
)))
;
648 sdd->family = AF_INET2;
649 sdd->addr.ip4 = addr;
650 sdd->completed = &completed;
651 ares_gethostbyaddr(ghba_chan, &addr, sizeof(uint32_t), AF_INET2,
652 c_ares_ghba_sync_cb, sdd);
653
654 /*
655 * Now wait for it to finish.
656 */
657 wait_for_sync_resolv(&completed);
658}
659
660static void
661sync_lookup_ip6(const ws_in6_addr *addrp)
662{
663 bool_Bool completed = false0;
664 sync_dns_data_t *sdd;
665
666 if (!async_dns_initialized) {
667 /*
668 * c-ares not initialized. Bail out.
669 */
670 return;
671 }
672
673 /*
674 * Start the request.
675 */
676 sdd = g_new(sync_dns_data_t, 1)((sync_dns_data_t *) g_malloc_n ((1), sizeof (sync_dns_data_t
)))
;
677 sdd->family = AF_INET610;
678 memcpy(&sdd->addr.ip6, addrp, sizeof(sdd->addr.ip6));
679 sdd->completed = &completed;
680 ares_gethostbyaddr(ghba_chan, addrp, sizeof(ws_in6_addr), AF_INET610,
681 c_ares_ghba_sync_cb, sdd);
682
683 /*
684 * Now wait for it to finish.
685 */
686 wait_for_sync_resolv(&completed);
687}
688
689void
690set_resolution_synchrony(bool_Bool synchronous)
691{
692 resolve_synchronously = synchronous;
693 maxmind_db_set_synchrony(synchronous);
694
695 if (synchronous) {
696 wait_for_async_queue();
697 }
698}
699
700static void
701c_ares_set_dns_servers(void)
702{
703 if ((!async_dns_initialized) || (!use_custom_dns_server_list))
704 return;
705
706 if (ndnsservers == 0) {
707 //clear the list of servers. This may effectively disable name resolution
708 ares_set_servers_ports(ghba_chan, NULL((void*)0));
709 ares_set_servers_ports(ghbn_chan, NULL((void*)0));
710 } else {
711 struct ares_addr_port_node* servers = wmem_alloc_array(NULL, struct ares_addr_port_node, ndnsservers)((struct ares_addr_port_node*)wmem_alloc((((void*)0)), (((((ndnsservers
)) <= 0) || ((size_t)sizeof(struct ares_addr_port_node) >
(9223372036854775807L / (size_t)((ndnsservers))))) ? 0 : (sizeof
(struct ares_addr_port_node) * ((ndnsservers))))))
;
712 ws_in4_addr ipv4addr;
713 ws_in6_addr ipv6addr;
714 bool_Bool invalid_IP_found = false0;
715 struct ares_addr_port_node* server;
716 unsigned i;
717 for (i = 0, server = servers; i < ndnsservers-1; i++, server++) {
718 if (ws_inet_pton6(dnsserverlist_uats[i].ipaddr, &ipv6addr)) {
719 server->family = AF_INET610;
720 memcpy(&server->addr.addr6, &ipv6addr, 16);
721 } else if (ws_inet_pton4(dnsserverlist_uats[i].ipaddr, &ipv4addr)) {
722 server->family = AF_INET2;
723 memcpy(&server->addr.addr4, &ipv4addr, 4);
724 } else {
725 //This shouldn't happen, but just in case...
726 invalid_IP_found = true1;
727 server->family = 0;
728 memset(&server->addr.addr4, 0, 4);
729 break;
730 }
731
732 server->udp_port = (int)dnsserverlist_uats[i].udp_port;
733 server->tcp_port = (int)dnsserverlist_uats[i].tcp_port;
734
735 server->next = (server+1);
736 }
737 if (!invalid_IP_found) {
738 if (ws_inet_pton6(dnsserverlist_uats[i].ipaddr, &ipv6addr)) {
739 server->family = AF_INET610;
740 memcpy(&server->addr.addr6, &ipv6addr, 16);
741 }
742 else if (ws_inet_pton4(dnsserverlist_uats[i].ipaddr, &ipv4addr)) {
743 server->family = AF_INET2;
744 memcpy(&server->addr.addr4, &ipv4addr, 4);
745 } else {
746 //This shouldn't happen, but just in case...
747 server->family = 0;
748 memset(&server->addr.addr4, 0, 4);
749 }
750 }
751 server->udp_port = (int)dnsserverlist_uats[i].udp_port;
752 server->tcp_port = (int)dnsserverlist_uats[i].tcp_port;
753
754 server->next = NULL((void*)0);
755
756 ares_set_servers_ports(ghba_chan, servers);
757 ares_set_servers_ports(ghbn_chan, servers);
758 wmem_free(NULL((void*)0), servers);
759 }
760}
761
762typedef struct {
763 uint32_t mask;
764 size_t mask_length;
765 const char* name; /* Shallow copy */
766} subnet_entry_t;
767
768/* Maximum supported line length of hosts, services, manuf, etc. */
769#define MAX_LINELEN1024 1024
770
771/** Read a line without trailing (CR)LF. Returns -1 on failure. */
772static int
773fgetline(char *buf, int size, FILE *fp)
774{
775 if (fgets(buf, size, fp)) {
776 int len = (int)strcspn(buf, "\r\n");
777 buf[len] = '\0';
778 return len;
779 }
780 return -1;
781
782} /* fgetline */
783
784
785/*
786 * Local function definitions
787 */
788static subnet_entry_t subnet_lookup(const uint32_t addr);
789static void subnet_entry_set(uint32_t subnet_addr, const uint8_t mask_length, const char* name);
790
791static unsigned serv_port_custom_hash(const void *k)
792{
793 const serv_port_key_t *key = (const serv_port_key_t*)k;
794 return key->port + (key->type << 16);
795}
796
797static gboolean serv_port_custom_equal(const void *k1, const void *k2)
798{
799 const serv_port_key_t *key1 = (const serv_port_key_t*)k1;
800 const serv_port_key_t *key2 = (const serv_port_key_t*)k2;
801
802 return (key1->port == key2->port) && (key1->type == key2->type);
803}
804
805static void
806add_custom_service_name(port_type proto, const unsigned port, const char *service_name)
807{
808 char *name;
809 serv_port_key_t *key, *orig_key;
810
811 key = wmem_new(addr_resolv_scope, serv_port_key_t)((serv_port_key_t*)wmem_alloc((addr_resolv_scope), sizeof(serv_port_key_t
)))
;
812 key->port = (uint16_t)port;
813 key->type = proto;
814
815 if (wmem_map_lookup_extended(serv_port_custom_hashtable, key, (const void**)&orig_key, (void**)&name)) {
816 wmem_free(addr_resolv_scope, orig_key);
817 wmem_free(addr_resolv_scope, name);
818 }
819
820 name = wmem_strdup(addr_resolv_scope, service_name);
821 wmem_map_insert(serv_port_custom_hashtable, key, name);
822
823 // A new custom entry is not a new resolved object.
824 // new_resolved_objects = true;
825}
826
827static void
828add_service_name(port_type proto, const unsigned port, const char *service_name)
829{
830 serv_port_key_t *key = wmem_new(addr_resolv_scope, serv_port_key_t)((serv_port_key_t*)wmem_alloc((addr_resolv_scope), sizeof(serv_port_key_t
)))
;
831 key->port = (uint16_t)port;
832 key->type = proto;
833
834 wmem_map_insert(serv_port_hashtable, key, (void*)service_name);
835
836 new_resolved_objects = true1;
837}
838
839static void
840parse_service_line (char *line)
841{
842 char *cp;
843 char *service;
844 char *port;
845 port_type proto;
846 struct cb_serv_data cb_data;
847 range_t *port_rng = NULL((void*)0);
848
849 if ((cp = strchr(line, '#')))
850 *cp = '\0';
851
852 if ((cp = strtok(line, " \t")) == NULL((void*)0))
853 return;
854
855 service = cp;
856
857 if ((cp = strtok(NULL((void*)0), " \t")) == NULL((void*)0))
858 return;
859
860 port = cp;
861
862 if (strtok(cp, "/") == NULL((void*)0))
863 return;
864
865 if (range_convert_str(NULL((void*)0), &port_rng, port, UINT16_MAX(65535)) != CVT_NO_ERROR) {
866 wmem_free (NULL((void*)0), port_rng);
867 return;
868 }
869
870 while ((cp = strtok(NULL((void*)0), "/")) != NULL((void*)0)) {
871 if (strcmp(cp, "tcp") == 0) {
872 proto = PT_TCP;
873 }
874 else if (strcmp(cp, "udp") == 0) {
875 proto = PT_UDP;
876 }
877 else if (strcmp(cp, "sctp") == 0) {
878 proto = PT_SCTP;
879 }
880 else if (strcmp(cp, "dccp") == 0) {
881 proto = PT_DCCP;
882 }
883 else {
884 break;
885 }
886 cb_data.service = service;
887 cb_data.proto = proto;
888 range_foreach(port_rng, add_serv_port_cb, &cb_data);
889 }
890
891 wmem_free (NULL((void*)0), port_rng);
892} /* parse_service_line */
893
894
895static void
896add_serv_port_cb(const uint32_t port, void *ptr)
897{
898 struct cb_serv_data *cb_data = (struct cb_serv_data *)ptr;
899
900 if ( port ) {
901 add_custom_service_name(cb_data->proto, port, cb_data->service);
902 }
903}
904
905
906static bool_Bool
907parse_services_file(const char * path)
908{
909 FILE *serv_p;
910 char buf[MAX_LINELEN1024];
911
912 /* services hash table initialization */
913 serv_p = ws_fopenfopen(path, "r");
914
915 if (serv_p == NULL((void*)0))
916 return false0;
917
918 while (fgetline(buf, sizeof(buf), serv_p) >= 0) {
919 parse_service_line(buf);
920 }
921
922 fclose(serv_p);
923 return true1;
924}
925
926/* -----------------
927 * unsigned integer to ascii
928 */
929static char *
930wmem_utoa(wmem_allocator_t *allocator, unsigned port)
931{
932 char *bp = (char *)wmem_alloc(allocator, MAXNAMELEN64);
933
934 /* XXX, uint32_to_str() ? */
935 uint32_to_str_buf(port, bp, MAXNAMELEN64);
936 return bp;
937}
938
939static const char *
940_serv_name_lookup(port_type proto, unsigned port)
941{
942 const char* name = NULL((void*)0);
943 ws_services_proto_t p;
944 ws_services_entry_t const *serv;
945
946 const serv_port_key_t custom_key = { (uint16_t)port, proto };
947 /* Look in the cache. Use an extended lookup so we can distinguish a port
948 * we already tried but had no name from one we haven't tried. */
949 if (!wmem_map_lookup_extended(serv_port_hashtable, &custom_key, NULL((void*)0), (void **)&name)) {
950 /* Try the user custom table */
951 name = wmem_map_lookup(serv_port_custom_hashtable, &custom_key);
952
953 if (name == NULL((void*)0)) {
954 /* now look in the global tables */
955 bool_Bool valid_proto = true1;
956 switch(proto) {
957 case PT_TCP: p = ws_tcp; break;
958 case PT_UDP: p = ws_udp; break;
959 case PT_SCTP: p = ws_sctp; break;
960 case PT_DCCP: p = ws_dccp; break;
961 default: valid_proto = false0;
962 }
963 if (valid_proto) {
964 serv = global_services_lookup(port, p);
965 if (serv) {
966 name = serv->name;
967 }
968 }
969 }
970
971 /* Cache result (even if NULL, so we can know we have no result.) */
972 add_service_name(proto, port, name);
973 }
974
975 return name;
976}
977
978const char *
979try_serv_name_lookup(port_type proto, unsigned port)
980{
981 return (proto == PT_NONE) ? NULL((void*)0) : _serv_name_lookup(proto, port);
982}
983
984const char *
985serv_name_lookup(port_type proto, unsigned port)
986{
987 const char *name;
988
989 /* first look for the name */
990 name = _serv_name_lookup(proto, port);
991 if (name != NULL((void*)0))
992 return name;
993
994 /* No resolved name. Do we have a cached numeric string? */
995 const serv_port_key_t key = { (uint16_t)port, PT_NONE };
996 name = (const char*)wmem_map_lookup(serv_port_hashtable, &key);
997 /* No name; create the numeric string. */
998 if (name == NULL((void*)0)) {
999 name = wmem_strdup_printf(addr_resolv_scope, "%u", port);
1000 add_service_name(PT_NONE, port, name);
1001 }
1002
1003 return name;
1004}
1005
1006static void
1007initialize_services(const char* app_env_var_prefix)
1008{
1009 ws_assert(serv_port_hashtable == NULL)do { if ((1) && !(serv_port_hashtable == ((void*)0)))
ws_log_fatal_full("", LOG_LEVEL_ERROR, "epan/addr_resolv.c",
1009, __func__, "assertion failed: %s", "serv_port_hashtable == ((void*)0)"
); } while (0)
;
1010 serv_port_hashtable = wmem_map_new(addr_resolv_scope, serv_port_custom_hash, serv_port_custom_equal);
1011 ws_assert(serv_port_custom_hashtable == NULL)do { if ((1) && !(serv_port_custom_hashtable == ((void
*)0))) ws_log_fatal_full("", LOG_LEVEL_ERROR, "epan/addr_resolv.c"
, 1011, __func__, "assertion failed: %s", "serv_port_custom_hashtable == ((void*)0)"
); } while (0)
;
1012 serv_port_custom_hashtable = wmem_map_new(addr_resolv_scope, serv_port_custom_hash, serv_port_custom_equal);
1013
1014 /* Compute the pathname of the global services file. */
1015 if (g_services_path == NULL((void*)0)) {
1016 g_services_path = get_datafile_path(ENAME_SERVICES"services", app_env_var_prefix);
1017 }
1018 parse_services_file(g_services_path);
1019
1020 /* Compute the pathname of the personal services file */
1021 if (g_pservices_path == NULL((void*)0)) {
1022 /* Check profile directory before personal configuration */
1023 g_pservices_path = get_persconffile_path(ENAME_SERVICES"services", true1, app_env_var_prefix);
1024 if (!parse_services_file(g_pservices_path)) {
1025 g_free(g_pservices_path);
1026 g_pservices_path = get_persconffile_path(ENAME_SERVICES"services", false0, app_env_var_prefix);
1027 parse_services_file(g_pservices_path);
1028 }
1029 }
1030}
1031
1032static void
1033service_name_lookup_cleanup(void)
1034{
1035 serv_port_hashtable = NULL((void*)0);
1036 serv_port_custom_hashtable = NULL((void*)0);
1037 g_free(g_services_path);
1038 g_services_path = NULL((void*)0);
1039 g_free(g_pservices_path);
1040 g_pservices_path = NULL((void*)0);
1041}
1042
1043static void
1044parse_enterprises_line (char *line)
1045{
1046 char *tok, *dec_str, *org_str;
1047 uint32_t dec;
1048 bool_Bool had_comment = false0;
1049
1050 /* Stop the line at any comment found */
1051 if ((tok = strchr(line, '#'))) {
1052 *tok = '\0';
1053 had_comment = true1;
1054 }
1055 /* Get enterprise number */
1056 dec_str = strtok(line, " \t");
1057 if (!dec_str)
1058 return;
1059 /* Get enterprise name */
1060 org_str = strtok(NULL((void*)0), ""); /* everything else */
1061 if (org_str && had_comment) {
1062 /* Only need to strip after (between name and where comment was) */
1063 org_str = g_strchomp(org_str);
1064 }
1065 if (!org_str)
1066 return;
1067
1068 /* Add entry using number as key */
1069 if (!ws_strtou32(dec_str, NULL((void*)0), &dec))
1070 return;
1071 g_hash_table_insert(enterprises_hashtable, GUINT_TO_POINTER(dec)((gpointer) (gulong) (dec)), g_strdup(org_str)g_strdup_inline (org_str));
1072}
1073
1074
1075static bool_Bool
1076parse_enterprises_file(const char * path)
1077{
1078 FILE *fp;
1079 char buf[MAX_LINELEN1024];
1080
1081 fp = ws_fopenfopen(path, "r");
1082 if (fp == NULL((void*)0))
1083 return false0;
1084
1085 while (fgetline(buf, sizeof(buf), fp) >= 0) {
1086 parse_enterprises_line(buf);
1087 }
1088
1089 fclose(fp);
1090 return true1;
1091}
1092
1093static void
1094initialize_enterprises(const char* app_env_var_prefix)
1095{
1096 ws_assert(enterprises_hashtable == NULL)do { if ((1) && !(enterprises_hashtable == ((void*)0)
)) ws_log_fatal_full("", LOG_LEVEL_ERROR, "epan/addr_resolv.c"
, 1096, __func__, "assertion failed: %s", "enterprises_hashtable == ((void*)0)"
); } while (0)
;
1097 enterprises_hashtable = g_hash_table_new_full(NULL((void*)0), NULL((void*)0), NULL((void*)0), g_free);
1098
1099 if (g_enterprises_path == NULL((void*)0)) {
1100 g_enterprises_path = get_datafile_path(ENAME_ENTERPRISES"enterprises", app_env_var_prefix);
1101 }
1102 parse_enterprises_file(g_enterprises_path);
1103
1104 /* Populate entries from profile or personal */
1105 if (g_penterprises_path == NULL((void*)0)) {
1106 /* Check profile directory before personal configuration */
1107 g_penterprises_path = get_persconffile_path(ENAME_ENTERPRISES"enterprises", true1, app_env_var_prefix);
1108 if (!file_exists(g_penterprises_path)) {
1109 g_free(g_penterprises_path);
1110 g_penterprises_path = get_persconffile_path(ENAME_ENTERPRISES"enterprises", false0, app_env_var_prefix);
1111 }
1112 }
1113 /* Parse personal file (if present) */
1114 parse_enterprises_file(g_penterprises_path);
1115}
1116
1117const char *
1118try_enterprises_lookup(uint32_t value)
1119{
1120 /* Trying extra entries first. N.B. This does allow entries to be overwritten and found.. */
1121 const char *name = (const char *)g_hash_table_lookup(enterprises_hashtable, GUINT_TO_POINTER(value)((gpointer) (gulong) (value)));
1122 if (name) {
1123 return name;
1124 }
1125 else {
1126 return global_enterprises_lookup(value);
1127 }
1128}
1129
1130const char *
1131enterprises_lookup(uint32_t value, const char *unknown_str)
1132{
1133 const char *s;
1134
1135 s = try_enterprises_lookup(value);
1136 if (s != NULL((void*)0))
1137 return s;
1138 if (unknown_str != NULL((void*)0))
1139 return unknown_str;
1140 return "<Unknown>";
1141}
1142
1143void
1144enterprises_base_custom(char *buf, uint32_t value)
1145{
1146 const char *s;
1147
1148 if ((s = try_enterprises_lookup(value)) == NULL((void*)0))
1149 s = ITEM_LABEL_UNKNOWN_STR"Unknown";
1150 snprintf(buf, ITEM_LABEL_LENGTH240, "%s (%u)", s, value);
1151}
1152
1153static void
1154enterprises_cleanup(void)
1155{
1156 ws_assert(enterprises_hashtable)do { if ((1) && !(enterprises_hashtable)) ws_log_fatal_full
("", LOG_LEVEL_ERROR, "epan/addr_resolv.c", 1156, __func__, "assertion failed: %s"
, "enterprises_hashtable"); } while (0)
;
1157 g_hash_table_destroy(enterprises_hashtable);
1158 enterprises_hashtable = NULL((void*)0);
1159 g_free(g_enterprises_path);
1160 g_enterprises_path = NULL((void*)0);
1161 g_free(g_penterprises_path);
1162 g_penterprises_path = NULL((void*)0);
1163}
1164
1165/* Fill in an IP4 structure with info from subnets file or just with the
1166 * string form of the address.
1167 */
1168bool_Bool
1169fill_dummy_ip4(const unsigned addr, hashipv4_t* volatile tp)
1170{
1171 subnet_entry_t subnet_entry;
1172
1173 /* return value : true if addr matches any subnet */
1174 bool_Bool cidr_covered = false0;
1175
1176 /* Overwrite if we get async DNS reply */
1177
1178 /* Do we have a subnet for this address? */
1179 subnet_entry = subnet_lookup(addr);
1180 if (0 != subnet_entry.mask) {
1181 /* Print name, then '.' then IP address after subnet mask */
1182 uint32_t host_addr;
1183 char buffer[WS_INET_ADDRSTRLEN16];
1184 char* paddr;
1185 size_t i;
1186
1187 host_addr = addr & (~subnet_entry.mask);
1188 ip_addr_to_str_buf(&host_addr, buffer, WS_INET_ADDRSTRLEN16);
1189 paddr = buffer;
1190
1191 /* Skip to first octet that is not totally masked
1192 * If length of mask is 32, we chomp the whole address.
1193 * If the address string starts '.' (should not happen?),
1194 * we skip that '.'.
1195 */
1196 i = subnet_entry.mask_length / 8;
1197 while(*(paddr) != '\0' && i > 0) {
1198 if (*(++paddr) == '.') {
1199 --i;
1200 }
1201 }
1202
1203 /* There are more efficient ways to do this, but this is safe if we
1204 * trust snprintf and MAXDNSNAMELEN
1205 */
1206 snprintf(tp->name, MAXDNSNAMELEN256, "%s%s", subnet_entry.name, paddr);
1207
1208 /* Evaluate the subnet in CIDR notation
1209 * Reuse buffers built above
1210 */
1211 uint32_t subnet_addr;
1212 subnet_addr = addr & subnet_entry.mask;
1213
1214 char buffer_subnet[WS_INET_ADDRSTRLEN16];
1215 ip_addr_to_str_buf(&subnet_addr, buffer_subnet, WS_INET_ADDRSTRLEN16);
1216
1217 char buffer_cidr[WS_INET_CIDRADDRSTRLEN19];
1218 snprintf(buffer_cidr, WS_INET_CIDRADDRSTRLEN19, "%s%s%u", buffer_subnet, "/", (unsigned)subnet_entry.mask_length);
1219
1220 snprintf(tp->cidr_addr, WS_INET_CIDRADDRSTRLEN19, "%s%s%u", buffer_subnet, "/", (unsigned)subnet_entry.mask_length);
1221 cidr_covered = true1;
1222 } else {
1223 /* XXX: This means we end up printing "1.2.3.4 (1.2.3.4)" in many cases */
1224 ip_addr_to_str_buf(&addr, tp->name, MAXDNSNAMELEN256);
1225
1226 /* IP does not belong to any known subnet, just indicate this IP without "/.32" */
1227 ip_addr_to_str_buf(&addr, tp->cidr_addr, MAXDNSNAMELEN256);
1228 }
1229 return cidr_covered;
1230}
1231
1232
1233/* Fill in an IP6 structure with the string form of the address.
1234 */
1235static void
1236fill_dummy_ip6(hashipv6_t* volatile tp)
1237{
1238 /* Overwrite if we get async DNS reply */
1239 (void) g_strlcpy(tp->name, tp->ip6, MAXDNSNAMELEN256);
1240}
1241
1242static void
1243c_ares_ghba_cb(void *arg, int status, int timeouts _U___attribute__((unused)), struct hostent *he) {
1244 async_dns_queue_msg_t *caqm = (async_dns_queue_msg_t *)arg;
1245 char **p;
1246
1247 if (!caqm) return;
1248 /* XXX, what to do if async_dns_in_flight == 0? */
1249 async_dns_in_flight--;
1250
1251 if (status == ARES_SUCCESS) {
1252 for (p = he->h_addr_list; *p != NULL((void*)0); p++) {
1253 switch(caqm->family) {
1254 case AF_INET2:
1255 add_ipv4_name(caqm->addr.ip4, he->h_name, false0);
1256 break;
1257 case AF_INET610:
1258 add_ipv6_name(&caqm->addr.ip6, he->h_name, false0);
1259 break;
1260 default:
1261 /* Throw an exception? */
1262 break;
1263 }
1264 }
1265 }
1266 wmem_free(addr_resolv_scope, caqm);
1267}
1268
1269/* --------------- */
1270hashipv4_t *
1271new_ipv4(const unsigned addr)
1272{
1273 hashipv4_t *tp = wmem_new(addr_resolv_scope, hashipv4_t)((hashipv4_t*)wmem_alloc((addr_resolv_scope), sizeof(hashipv4_t
)))
;
1274 tp->addr = addr;
1275 tp->flags = 0;
1276 tp->name[0] = '\0';
1277 ip_addr_to_str_buf(&addr, tp->ip, sizeof(tp->ip));
1278 return tp;
1279}
1280
1281static hashipv4_t *
1282host_lookup(const unsigned addr)
1283{
1284 hashipv4_t * volatile tp;
1285
1286 tp = (hashipv4_t *)wmem_map_lookup(ipv4_hash_table, GUINT_TO_POINTER(addr)((gpointer) (gulong) (addr)));
1287 if (tp == NULL((void*)0)) {
1288 /*
1289 * We don't already have an entry for this host name; create one,
1290 * and then try to resolve it.
1291 */
1292 tp = new_ipv4(addr);
1293 fill_dummy_ip4(addr, tp);
1294 wmem_map_insert(ipv4_hash_table, GUINT_TO_POINTER(addr)((gpointer) (gulong) (addr)), tp);
1295 } else if (tp->flags & TRIED_OR_RESOLVED_MASK((1U<<0) | (1U<<1))) {
1296 return tp;
1297 }
1298
1299 /*
1300 * This hasn't been resolved yet, and we haven't tried to
1301 * resolve it already.
1302 */
1303
1304 if (!gbl_resolv_flags.network_name)
1305 return tp;
1306
1307 if (gbl_resolv_flags.use_external_net_name_resolver) {
1308 tp->flags |= TRIED_RESOLVE_ADDRESS(1U<<0);
1309
1310 if (async_dns_initialized) {
1311 /* c-ares is initialized, so we can use it */
1312 if (resolve_synchronously || name_resolve_concurrency == 0) {
1313 /*
1314 * Either all names are to be resolved synchronously or
1315 * the concurrency level is 0; do the resolution
1316 * synchronously.
1317 */
1318 sync_lookup_ip4(addr);
1319 } else {
1320 /*
1321 * Names are to be resolved asynchronously, and we
1322 * allow at least one asynchronous request in flight;
1323 * post an asynchronous request.
1324 */
1325 async_dns_queue_msg_t *caqm;
1326
1327 caqm = wmem_new(addr_resolv_scope, async_dns_queue_msg_t)((async_dns_queue_msg_t*)wmem_alloc((addr_resolv_scope), sizeof
(async_dns_queue_msg_t)))
;
1328 caqm->family = AF_INET2;
1329 caqm->addr.ip4 = addr;
1330 wmem_list_append(async_dns_queue_head, (void *) caqm);
1331 }
1332 }
1333 }
1334
1335 return tp;
1336
1337} /* host_lookup */
1338
1339/* --------------- */
1340static hashipv6_t *
1341new_ipv6(const ws_in6_addr *addr)
1342{
1343 hashipv6_t *tp = wmem_new(addr_resolv_scope, hashipv6_t)((hashipv6_t*)wmem_alloc((addr_resolv_scope), sizeof(hashipv6_t
)))
;
1344 memcpy(tp->addr, addr->bytes, sizeof tp->addr);
1345 tp->flags = 0;
1346 tp->name[0] = '\0';
1347 ip6_to_str_buf(addr, tp->ip6, sizeof(tp->ip6));
1348 return tp;
1349}
1350
1351/* ------------------------------------ */
1352static hashipv6_t *
1353host_lookup6(const ws_in6_addr *addr)
1354{
1355 hashipv6_t * volatile tp;
1356
1357 tp = (hashipv6_t *)wmem_map_lookup(ipv6_hash_table, addr);
1358 if (tp == NULL((void*)0)) {
1359 /*
1360 * We don't already have an entry for this host name; create one,
1361 * and then try to resolve it.
1362 */
1363 ws_in6_addr *addr_key;
1364
1365 addr_key = wmem_new(addr_resolv_scope, ws_in6_addr)((ws_in6_addr*)wmem_alloc((addr_resolv_scope), sizeof(ws_in6_addr
)))
;
1366 tp = new_ipv6(addr);
1367 memcpy(addr_key, addr, 16);
1368 fill_dummy_ip6(tp);
1369 wmem_map_insert(ipv6_hash_table, addr_key, tp);
1370 } else if (tp->flags & TRIED_OR_RESOLVED_MASK((1U<<0) | (1U<<1))) {
1371 return tp;
1372 }
1373
1374 /*
1375 * This hasn't been resolved yet, and we haven't tried to
1376 * resolve it already.
1377 */
1378
1379 if (!gbl_resolv_flags.network_name)
1380 return tp;
1381
1382 if (gbl_resolv_flags.use_external_net_name_resolver) {
1383 tp->flags |= TRIED_RESOLVE_ADDRESS(1U<<0);
1384
1385 if (async_dns_initialized) {
1386 /* c-ares is initialized, so we can use it */
1387 if (resolve_synchronously || name_resolve_concurrency == 0) {
1388 /*
1389 * Either all names are to be resolved synchronously or
1390 * the concurrency level is 0; do the resolution
1391 * synchronously.
1392 */
1393 sync_lookup_ip6(addr);
1394 } else {
1395 /*
1396 * Names are to be resolved asynchronously, and we
1397 * allow at least one asynchronous request in flight;
1398 * post an asynchronous request.
1399 */
1400 async_dns_queue_msg_t *caqm;
1401
1402 caqm = wmem_new(addr_resolv_scope, async_dns_queue_msg_t)((async_dns_queue_msg_t*)wmem_alloc((addr_resolv_scope), sizeof
(async_dns_queue_msg_t)))
;
1403 caqm->family = AF_INET610;
1404 memcpy(&caqm->addr.ip6, addr, sizeof(caqm->addr.ip6));
1405 wmem_list_append(async_dns_queue_head, (void *) caqm);
1406 }
1407 }
1408 }
1409
1410 return tp;
1411
1412} /* host_lookup6 */
1413
1414/*
1415 * Ethernet / manufacturer resolution
1416 *
1417 * The following functions implement ethernet address resolution and
1418 * ethers files parsing (see ethers(4)).
1419 *
1420 * The manuf file has the same format as ethers(4) except that names are
1421 * truncated to MAXMANUFLEN-1 (8) characters and that an address contains
1422 * only 3 bytes (instead of 6).
1423 *
1424 * Notes:
1425 *
1426 * I decide to not use the existing functions (see ethers(3) on some
1427 * operating systems) for the following reasons:
1428 * - performance gains (use of hash tables and some other enhancements),
1429 * - use of two ethers files (system-wide and per user),
1430 * - avoid the use of NIS maps,
1431 * - lack of these functions on some systems.
1432 *
1433 * So the following functions do _not_ behave as the standard ones.
1434 *
1435 * -- Laurent.
1436 */
1437
1438/*
1439 * Converts Ethernet addresses of the form aa:bb:cc or aa:bb:cc:dd:ee:ff/28.
1440 * '-' is also supported as a separator. The
1441 * octets must be exactly two hexadecimal characters and the mask must be either
1442 * 28 or 36. Pre-condition: cp MUST be at least 21 bytes.
1443 */
1444static bool_Bool
1445parse_ether_address_fast(const unsigned char *cp, ether_t *eth, unsigned int *mask,
1446 const bool_Bool accept_mask)
1447{
1448 /* XXX copied from strutil.c */
1449 /* a map from ASCII hex chars to their value */
1450 static const int8_t str_to_nibble[256] = {
1451 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1452 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1453 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1454 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
1455 -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1456 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1457 -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1458 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1459 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1460 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1461 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1462 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1463 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1464 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1465 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
1466 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
1467 };
1468 const uint8_t *str_to_nibble_usg = (const uint8_t *)str_to_nibble;
1469
1470 unsigned char sep = cp[2];
1471 if ((sep != ':' && sep != '-') || cp[5] != sep) {
1472 /* Unexpected separators. */
1473 return false0;
1474 }
1475
1476 /* N.B. store octet values in an int to detect invalid (-1) entries */
1477 int num0 = (str_to_nibble_usg[cp[0]] << 4) | (int8_t)str_to_nibble_usg[cp[1]];
1478 int num1 = (str_to_nibble_usg[cp[3]] << 4) | (int8_t)str_to_nibble_usg[cp[4]];
1479 int num2 = (str_to_nibble_usg[cp[6]] << 4) | (int8_t)str_to_nibble_usg[cp[7]];
1480
1481 if ((num0 | num1 | num2) & 0x100) {
1482 /* Not hexadecimal numbers. */
1483 return false0;
1484 }
1485
1486 eth->addr[0] = (uint8_t)num0;
1487 eth->addr[1] = (uint8_t)num1;
1488 eth->addr[2] = (uint8_t)num2;
1489
1490 if (cp[8] == '\0' && accept_mask) {
1491 /* Indicate that this is a manufacturer ID (0 is not allowed as a mask). */
1492 *mask = 0;
1493 return true1;
1494 } else if (cp[8] != sep || !accept_mask) {
1495 /* Format not handled by this fast path. */
1496 return false0;
1497 }
1498
1499 /* N.B. store octet values in an int to detect invalid (-1) entries */
1500 int num3 = (str_to_nibble_usg[cp[9]] << 4) | (int8_t)str_to_nibble_usg[cp[10]];
1501 int num4 = (str_to_nibble_usg[cp[12]] << 4) | (int8_t)str_to_nibble_usg[cp[13]];
1502 int num5 = (str_to_nibble_usg[cp[15]] << 4) | (int8_t)str_to_nibble_usg[cp[16]];
1503
1504 if (((num3 | num4 | num5) & 0x100) || cp[11] != sep || cp[14] != sep) {
1505 /* Not hexadecimal numbers or invalid separators. */
1506 return false0;
1507 }
1508
1509 eth->addr[3] = (uint8_t)num3;
1510 eth->addr[4] = (uint8_t)num4;
1511 eth->addr[5] = (uint8_t)num5;
1512 if (cp[17] == '\0') {
1513 /* We got 6 bytes, so this is a MAC address (48 is not allowed as a mask). */
1514 *mask = 48;
1515 return true1;
1516 } else if (cp[17] != '/' || cp[20] != '\0') {
1517 /* Format not handled by this fast path. */
1518 return false0;
1519 }
1520
1521 int m1 = cp[18];
1522 int m2 = cp[19];
1523 if (m1 == '3' && m2 == '6') { /* Mask /36 */
1524 eth->addr[4] &= 0xf0;
1525 eth->addr[5] = 0;
1526 *mask = 36;
1527 return true1;
1528 }
1529 if (m1 == '2' && m2 == '8') { /* Mask /28 */
1530 eth->addr[3] &= 0xf0;
1531 eth->addr[4] = 0;
1532 eth->addr[5] = 0;
1533 *mask = 28;
1534 return true1;
1535 }
1536 /* Unsupported mask */
1537 return false0;
1538}
1539
1540/*
1541 * If "accept_mask" is false, cp must point to an address that consists
1542 * of exactly 6 (EUI-48) or 8 (EUI-64) bytes.
1543 * If "accept_mask" is true, parse an up-to-6-byte sequence with an optional
1544 * mask.
1545 */
1546static bool_Bool
1547parse_ether_address(const char *cp, ether_t *eth, unsigned int *mask,
1548 const bool_Bool accept_mask)
1549{
1550 int i;
1551 unsigned long num;
1552 char *p;
1553 char sep = '\0';
1554
1555 for (i = 0; i < EUI64_ADDR_LEN8; i++) {
1556 /* Get a hex number, 1 or 2 digits, no sign characters allowed. */
1557 if (!g_ascii_isxdigit(*cp)((g_ascii_table[(guchar) (*cp)] & G_ASCII_XDIGIT) != 0))
1558 return false0;
1559 num = strtoul(cp, &p, 16);
1560 if (p == cp)
1561 return false0; /* failed */
1562 if (num > 0xFF)
1563 return false0; /* not a valid octet */
1564 eth->addr[i] = (uint8_t) num;
1565 cp = p; /* skip past the number */
1566
1567 /* OK, what character terminated the octet? */
1568 if (*cp == '/') {
1569 /* "/" - this has a mask. */
1570 if (!accept_mask) {
1571 /* Entries with masks are not allowed in this file. */
1572 return false0;
1573 }
1574 cp++; /* skip past the '/' to get to the mask */
1575 if (!g_ascii_isdigit(*cp)((g_ascii_table[(guchar) (*cp)] & G_ASCII_DIGIT) != 0))
1576 return false0; /* no sign allowed */
1577 num = strtoul(cp, &p, 10);
1578 if (p == cp)
1579 return false0; /* failed */
1580 cp = p; /* skip past the number */
1581 if (*cp != '\0' && !g_ascii_isspace(*cp)((g_ascii_table[(guchar) (*cp)] & G_ASCII_SPACE) != 0))
1582 return false0; /* bogus terminator */
1583 if (num == 0 || num >= 48)
1584 return false0; /* bogus mask */
1585 /* Mask out the bits not covered by the mask */
1586 *mask = (int)num;
1587 for (i = 0; num >= 8; i++, num -= 8)
1588 ; /* skip octets entirely covered by the mask */
1589 /* Mask out the first masked octet */
1590 eth->addr[i] &= (0xFF << (8 - num));
1591 i++;
1592 /* Mask out completely-masked-out octets */
1593 for (; i < 6; i++)
1594 eth->addr[i] = 0;
1595 return true1;
1596 }
1597 if (*cp == '\0') {
1598 /* We're at the end of the address, and there's no mask. */
1599 if (i == 2) {
1600 /* We got 3 bytes, so this is a manufacturer ID. */
1601 if (!accept_mask) {
1602 /* Manufacturer IDs are not allowed in this file */
1603 return false0;
1604 }
1605 /* Indicate that this is a manufacturer ID (0 is not allowed
1606 as a mask). */
1607 *mask = 0;
1608 return true1;
1609 }
1610
1611 if (i == 5) {
1612 /* We got 6 bytes, so this is a MAC address (48 is not allowed as a mask). */
1613 if (mask) {
1614 *mask = 48;
1615 }
1616 return true1;
1617 }
1618
1619 if (i == 7) {
1620 /* We got 8 bytes, so this is a EUI-64 address (64 is not allowed as a mask). */
1621 if (mask) {
1622 *mask = 64;
1623 }
1624 return true1;
1625 }
1626
1627 /* We didn't get 3 or 6 or 8 bytes, and there's no mask; this is
1628 illegal. */
1629 return false0;
1630 } else {
1631 if (sep == '\0') {
1632 /* We don't know the separator used in this number; it can either
1633 be ':', '-', or '.'. */
1634 if (*cp != ':' && *cp != '-' && *cp != '.')
1635 return false0;
1636 sep = *cp; /* subsequent separators must be the same */
1637 } else {
1638 /* It has to be the same as the first separator */
1639 if (*cp != sep)
1640 return false0;
1641 }
1642 }
1643 cp++;
1644 }
1645
1646 return true1;
1647}
1648
1649static int
1650parse_ether_line(char *line, ether_t *eth, unsigned int *mask,
1651 const bool_Bool accept_mask)
1652{
1653 /*
1654 * See the ethers(4) or ethers(5) man page for ethers file format
1655 * (not available on all systems).
1656 * We allow both ethernet address separators (':' and '-'),
1657 * as well as Wireshark's '.' separator.
1658 */
1659
1660 char *cp;
1661
1662 line = g_strstrip(line)g_strchomp (g_strchug (line));
1663 if (line[0] == '\0' || line[0] == '#')
1664 return -1;
1665
1666 if ((cp = strchr(line, '#'))) {
1667 *cp = '\0';
1668 g_strchomp(line);
1669 }
1670
1671 if ((cp = strtok(line, " \t")) == NULL((void*)0))
1672 return -1;
1673
1674 /* First try to match the common format for the large ethers file. */
1675 if (!parse_ether_address_fast((const uint8_t*)cp, eth, mask, accept_mask)) {
1676 /* Fallback for the well-known addresses (wka) file. */
1677 if (!parse_ether_address(cp, eth, mask, accept_mask))
1678 return -1;
1679 }
1680
1681 if ((cp = strtok(NULL((void*)0), " \t")) == NULL((void*)0))
1682 return -1;
1683
1684 (void) g_strlcpy(eth->name, cp, MAXNAMELEN64);
1685
1686 if ((cp = strtok(NULL((void*)0), "\t")) != NULL((void*)0))
1687 {
1688 (void) g_strlcpy(eth->longname, cp, MAXNAMELEN64);
1689 } else {
1690 /* Make the long name the short name */
1691 (void) g_strlcpy(eth->longname, eth->name, MAXNAMELEN64);
1692 }
1693
1694 return 0;
1695
1696} /* parse_ether_line */
1697
1698static FILE *eth_p;
1699
1700static void
1701set_ethent(char *path)
1702{
1703 if (eth_p)
1704 rewind(eth_p);
1705 else
1706 eth_p = ws_fopenfopen(path, "r");
1707}
1708
1709static void
1710end_ethent(void)
1711{
1712 if (eth_p) {
1713 fclose(eth_p);
1714 eth_p = NULL((void*)0);
1715 }
1716}
1717
1718static ether_t *
1719get_ethent(unsigned int *mask, const bool_Bool accept_mask)
1720{
1721
1722 static ether_t eth;
1723 char buf[MAX_LINELEN1024];
1724
1725 if (eth_p == NULL((void*)0))
1726 return NULL((void*)0);
1727
1728 while (fgetline(buf, sizeof(buf), eth_p) >= 0) {
1729 if (parse_ether_line(buf, &eth, mask, accept_mask) == 0) {
1730 return &eth;
1731 }
1732 }
1733
1734 return NULL((void*)0);
1735
1736} /* get_ethent */
1737
1738static hashmanuf_t *
1739manuf_hash_new_entry(const uint8_t *addr, const char* name, const char* longname)
1740{
1741 unsigned manuf_key;
1742 hashmanuf_t *manuf_value;
1743 char *endp;
1744
1745 /* manuf needs only the 3 most significant octets of the ethernet address */
1746 manuf_key = (addr[0] << 16) + (addr[1] << 8) + addr[2];
1747 manuf_value = wmem_new(addr_resolv_scope, hashmanuf_t)((hashmanuf_t*)wmem_alloc((addr_resolv_scope), sizeof(hashmanuf_t
)))
;
1748
1749 memcpy(manuf_value->addr, addr, 3);
1750 if (name != NULL((void*)0)) {
1751 (void) g_strlcpy(manuf_value->resolved_name, name, MAXNAMELEN64);
1752 manuf_value->flags = NAME_RESOLVED(1U<<1);
1753 if (longname != NULL((void*)0)) {
1754 (void) g_strlcpy(manuf_value->resolved_longname, longname, MAXNAMELEN64);
1755 }
1756 else {
1757 (void) g_strlcpy(manuf_value->resolved_longname, name, MAXNAMELEN64);
1758 }
1759 }
1760 else {
1761 manuf_value->flags = 0;
1762 manuf_value->resolved_name[0] = '\0';
1763 manuf_value->resolved_longname[0] = '\0';
1764 }
1765 /* Values returned by bytes_to_hexstr_punct() are *not* null-terminated */
1766 endp = bytes_to_hexstr_punct(manuf_value->hexaddr, addr, sizeof(manuf_value->addr), ':');
1767 *endp = '\0';
1768
1769 wmem_map_insert(manuf_hashtable, GUINT_TO_POINTER(manuf_key)((gpointer) (gulong) (manuf_key)), manuf_value);
1770 return manuf_value;
1771}
1772
1773static hashwka_t*
1774wka_hash_new_entry(const uint8_t *addr, char* name)
1775{
1776 uint8_t *wka_key;
1777 hashwka_t *wka_value;
1778
1779 wka_key = (uint8_t *)wmem_alloc(addr_resolv_scope, 6);
1780 memcpy(wka_key, addr, 6);
1781
1782 wka_value = (hashwka_t*)wmem_new(addr_resolv_scope, hashwka_t)((hashwka_t*)wmem_alloc((addr_resolv_scope), sizeof(hashwka_t
)))
;
1783 wka_value->flags = NAME_RESOLVED(1U<<1);
1784 wka_value->name = wmem_strdup(addr_resolv_scope, name);
1785
1786 wmem_map_insert(wka_hashtable, wka_key, wka_value);
1787 return wka_value;
1788}
1789
1790static void
1791add_manuf_name(const uint8_t *addr, unsigned int mask, char *name, char *longname)
1792{
1793 switch (mask)
1794 {
1795 case 0:
1796 {
1797 /* This is a manufacturer ID; add it to the manufacturer ID hash table */
1798 hashmanuf_t *entry = manuf_hash_new_entry(addr, name, longname);
1799 entry->flags |= STATIC_HOSTNAME(1U<<3);
1800 break;
1801 }
1802 case 48:
1803 {
1804 /* This is a well-known MAC address; add it to the Ethernet hash table */
1805 add_eth_name(addr, name, true1);
1806 break;
1807 }
1808 default:
1809 {
1810 /* This is a range of well-known addresses; add it to the well-known-address table */
1811 hashwka_t *entry = wka_hash_new_entry(addr, name);
1812 entry->flags |= STATIC_HOSTNAME(1U<<3);
1813 break;
1814 }
1815 }
1816} /* add_manuf_name */
1817
1818/* XXX: manuf_name_lookup returns a hashmanuf_t*, which cannot hold a 28 or
1819 * 36 bit MA-M or MA-S. So it returns those as unresolved. For EUI-48 and
1820 * EUI-64, MA-M and MA-S should be checked for separately in the global
1821 * tables.
1822 *
1823 * XXX - size_t is used only in a ws_return_val_if() that checks
1824 * whether the argument has at least 3 bytes; that's done only if
1825 * assertions are enabled, so it's used only if assertions are
1826 * enabled. This means that, if assertions aren't enabled, a
1827 * warning that the argument is unused will be issued by at least
1828 * some compilers, so we mark it as unused. Should we do that
1829 * check unconditionally, and just emit a warning if assertions
1830 * are enabled?
1831 */
1832static hashmanuf_t *
1833manuf_name_lookup(const uint8_t *addr, size_t size _U___attribute__((unused)))
1834{
1835 uint32_t manuf_key;
1836 uint8_t oct;
1837 hashmanuf_t *manuf_value;
1838
1839 ws_return_val_if(size < 3, NULL)do { if (1 && (size < 3)) { ws_log_full("InvalidArg"
, LOG_LEVEL_WARNING, "epan/addr_resolv.c", 1839, __func__, "invalid argument: %s"
, "size < 3"); return (((void*)0)); } } while (0)
;
1840
1841 /* manuf needs only the 3 most significant octets of the ethernet address */
1842 manuf_key = addr[0];
1843 manuf_key = manuf_key<<8;
1844 oct = addr[1];
1845 manuf_key = manuf_key | oct;
1846 manuf_key = manuf_key<<8;
1847 oct = addr[2];
1848 manuf_key = manuf_key | oct;
1849
1850
1851 /* first try to find a "perfect match" */
1852 manuf_value = (hashmanuf_t*)wmem_map_lookup(manuf_hashtable, GUINT_TO_POINTER(manuf_key)((gpointer) (gulong) (manuf_key)));
1853 if (manuf_value != NULL((void*)0)) {
1854 manuf_value->flags |= TRIED_RESOLVE_ADDRESS(1U<<0);
1855 return manuf_value;
1856 }
1857
1858 /* Mask out the broadcast/multicast flag but not the locally
1859 * administered flag as locally administered means: not assigned
1860 * by the IEEE but the local administrator instead.
1861 * 0x01 multicast / broadcast bit
1862 * 0x02 locally administered bit */
1863 if ((manuf_key & 0x00010000) != 0) {
1864 manuf_key &= 0x00FEFFFF;
1865 manuf_value = (hashmanuf_t*)wmem_map_lookup(manuf_hashtable, GUINT_TO_POINTER(manuf_key)((gpointer) (gulong) (manuf_key)));
1866 if (manuf_value != NULL((void*)0)) {
1867 manuf_value->flags |= TRIED_RESOLVE_ADDRESS(1U<<0);
1868 return manuf_value;
1869 }
1870 }
1871
1872 /* Try the global manuf tables. */
1873 const char *short_name, *long_name;
1874 /* We can't insert a 28 or 36 bit entry into the used hash table. */
1875 short_name = ws_manuf_lookup_oui24(addr, &long_name);
1876 if (short_name != NULL((void*)0)) {
1877 /* Found it */
1878 manuf_value = manuf_hash_new_entry(addr, short_name, long_name);
1879 } else {
1880 /* Add the address as a hex string */
1881 manuf_value = manuf_hash_new_entry(addr, NULL((void*)0), NULL((void*)0));
1882 }
1883
1884 manuf_value->flags |= TRIED_RESOLVE_ADDRESS(1U<<0);
1885 return manuf_value;
1886
1887} /* manuf_name_lookup */
1888
1889static char *
1890wka_name_lookup(const uint8_t *addr, const unsigned int mask)
1891{
1892 uint8_t masked_addr[6];
1893 unsigned num;
1894 int i;
1895 hashwka_t *value;
1896
1897 if (wka_hashtable == NULL((void*)0)) {
1898 return NULL((void*)0);
1899 }
1900 /* Get the part of the address covered by the mask. */
1901 for (i = 0, num = mask; num >= 8; i++, num -= 8)
1902 masked_addr[i] = addr[i]; /* copy octets entirely covered by the mask */
1903 /* Mask out the first masked octet */
1904 masked_addr[i] = addr[i] & (0xFF << (8 - num));
1905 i++;
1906 /* Zero out completely-masked-out octets */
1907 for (; i < 6; i++)
1908 masked_addr[i] = 0;
1909
1910 value = (hashwka_t*)wmem_map_lookup(wka_hashtable, masked_addr);
1911
1912 if (value) {
1913 value->flags |= TRIED_RESOLVE_ADDRESS(1U<<0);
1914 return value->name;
1915 }
1916
1917 return NULL((void*)0);
1918
1919} /* wka_name_lookup */
1920
1921unsigned get_hash_ether_status(hashether_t* ether)
1922{
1923 return ether->flags;
1924}
1925
1926bool_Bool get_hash_ether_used(hashether_t* ether)
1927{
1928 return ((ether->flags & TRIED_OR_RESOLVED_MASK((1U<<0) | (1U<<1))) == TRIED_OR_RESOLVED_MASK((1U<<0) | (1U<<1)));
1929}
1930
1931char* get_hash_ether_hexaddr(hashether_t* ether)
1932{
1933 return ether->hexaddr;
1934}
1935
1936char* get_hash_ether_resolved_name(hashether_t* ether)
1937{
1938 return ether->resolved_name;
1939}
1940
1941bool_Bool get_hash_wka_used(hashwka_t* wka)
1942{
1943 return ((wka->flags & TRIED_OR_RESOLVED_MASK((1U<<0) | (1U<<1))) == TRIED_OR_RESOLVED_MASK((1U<<0) | (1U<<1)));
1944}
1945
1946char* get_hash_wka_resolved_name(hashwka_t* wka)
1947{
1948 return wka->name;
1949}
1950
1951static unsigned
1952eth_addr_hash(const void *key)
1953{
1954 return wmem_strong_hash((const uint8_t *)key, 6);
1955}
1956
1957static gboolean
1958eth_addr_cmp(const void *a, const void *b)
1959{
1960 return (memcmp(a, b, 6) == 0);
1961}
1962
1963static unsigned
1964eui64_addr_hash(const void *key)
1965{
1966 return wmem_strong_hash((const uint8_t *)key, EUI64_ADDR_LEN8);
1967}
1968
1969static gboolean
1970eui64_addr_cmp(const void *a, const void *b)
1971{
1972 return (memcmp(a, b, EUI64_ADDR_LEN8) == 0);
1973}
1974
1975static void
1976initialize_ethers(const char* app_env_var_prefix)
1977{
1978 ether_t *eth;
1979 unsigned mask = 0;
1980
1981 /* hash table initialization */
1982 ws_assert(wka_hashtable == NULL)do { if ((1) && !(wka_hashtable == ((void*)0))) ws_log_fatal_full
("", LOG_LEVEL_ERROR, "epan/addr_resolv.c", 1982, __func__, "assertion failed: %s"
, "wka_hashtable == ((void*)0)"); } while (0)
;
1983 wka_hashtable = wmem_map_new(addr_resolv_scope, eth_addr_hash, eth_addr_cmp);
1984 ws_assert(manuf_hashtable == NULL)do { if ((1) && !(manuf_hashtable == ((void*)0))) ws_log_fatal_full
("", LOG_LEVEL_ERROR, "epan/addr_resolv.c", 1984, __func__, "assertion failed: %s"
, "manuf_hashtable == ((void*)0)"); } while (0)
;
1985 manuf_hashtable = wmem_map_new(addr_resolv_scope, g_direct_hash, g_direct_equal);
1986 ws_assert(eth_hashtable == NULL)do { if ((1) && !(eth_hashtable == ((void*)0))) ws_log_fatal_full
("", LOG_LEVEL_ERROR, "epan/addr_resolv.c", 1986, __func__, "assertion failed: %s"
, "eth_hashtable == ((void*)0)"); } while (0)
;
1987 eth_hashtable = wmem_map_new(addr_resolv_scope, eth_addr_hash, eth_addr_cmp);
1988 ws_assert(eui64_hashtable == NULL)do { if ((1) && !(eui64_hashtable == ((void*)0))) ws_log_fatal_full
("", LOG_LEVEL_ERROR, "epan/addr_resolv.c", 1988, __func__, "assertion failed: %s"
, "eui64_hashtable == ((void*)0)"); } while (0)
;
1989 eui64_hashtable = wmem_map_new(addr_resolv_scope, eui64_addr_hash, eui64_addr_cmp);
1990
1991 /* Compute the pathname of the ethers file. */
1992 if (g_ethers_path == NULL((void*)0)) {
1993 g_ethers_path = g_build_filename(get_systemfile_dir(app_env_var_prefix), ENAME_ETHERS"ethers", NULL((void*)0));
1994 }
1995
1996 /* Compute the pathname of the personal ethers file. */
1997 if (g_pethers_path == NULL((void*)0)) {
1998 /* Check profile directory before personal configuration */
1999 g_pethers_path = get_persconffile_path(ENAME_ETHERS"ethers", true1, app_env_var_prefix);
2000 if (!file_exists(g_pethers_path)) {
2001 g_free(g_pethers_path);
2002 g_pethers_path = get_persconffile_path(ENAME_ETHERS"ethers", false0, app_env_var_prefix);
2003 }
2004 }
2005
2006 /* Compute the pathname of the global manuf file */
2007 if (g_manuf_path == NULL((void*)0))
2008 g_manuf_path = get_datafile_path(ENAME_MANUF"manuf", app_env_var_prefix);
2009 /* Read it and initialize the hash table */
2010 if (file_exists(g_manuf_path)) {
2011 set_ethent(g_manuf_path);
2012 while ((eth = get_ethent(&mask, true1))) {
2013 add_manuf_name(eth->addr, mask, eth->name, eth->longname);
2014 }
2015 end_ethent();
2016 }
2017
2018 /* Compute the pathname of the personal manuf file */
2019 if (g_pmanuf_path == NULL((void*)0)) {
2020 /* Check profile directory before personal configuration */
2021 g_pmanuf_path = get_persconffile_path(ENAME_MANUF"manuf", true1, app_env_var_prefix);
2022 if (!file_exists(g_pmanuf_path)) {
2023 g_free(g_pmanuf_path);
2024 g_pmanuf_path = get_persconffile_path(ENAME_MANUF"manuf", false0, app_env_var_prefix);
2025 }
2026 }
2027 /* Read it and initialize the hash table */
2028 if (file_exists(g_pmanuf_path)) {
2029 set_ethent(g_pmanuf_path);
2030 while ((eth = get_ethent(&mask, true1))) {
2031 add_manuf_name(eth->addr, mask, eth->name, eth->longname);
2032 }
2033 end_ethent();
2034 }
2035
2036 /* Compute the pathname of the wka file */
2037 if (g_wka_path == NULL((void*)0))
2038 g_wka_path = get_datafile_path(ENAME_WKA"wka", app_env_var_prefix);
2039
2040 /* Read it and initialize the hash table */
2041 set_ethent(g_wka_path);
2042 while ((eth = get_ethent(&mask, true1))) {
2043 add_manuf_name(eth->addr, mask, eth->name, eth->longname);
2044 }
2045 end_ethent();
2046
2047 /* Look at the ethers files last. These are set as static names,
2048 * so they override earlier entries, and the ones we read last
2049 * take precedence. Order of precedence is personal ethers file,
2050 * global ethers file, wka file, personal manuf file, global manuf
2051 * file, and then non-static sources like ARP Eth -> IP hostname
2052 * discovery (if enabled), NRB entries (if wiretap adds support for
2053 * EUI-48 in NRBs), etc.
2054 * XXX: What _is_ the proper order of precedence, and should it
2055 * be configurable? (cf. #18075) */
2056 set_ethent(g_ethers_path);
2057 while ((eth = get_ethent(&mask, false0))) {
2058 if (mask == 48) {
2059 add_eth_name(eth->addr, eth->name, true1);
2060 } else if (mask == 64) {
2061 add_eui64_name(eth->addr, eth->name, true1);
2062 }
2063 }
2064 end_ethent();
2065
2066 if (file_exists(g_pethers_path)) {
2067 set_ethent(g_pethers_path);
2068 while ((eth = get_ethent(&mask, false0))) {
2069 if (mask == 48) {
2070 add_eth_name(eth->addr, eth->name, true1);
2071 } else if (mask == 64) {
2072 add_eui64_name(eth->addr, eth->name, true1);
2073 }
2074 }
2075 end_ethent();
2076 }
2077
2078} /* initialize_ethers */
2079
2080static void
2081ethers_cleanup(void)
2082{
2083 wka_hashtable = NULL((void*)0);
2084 manuf_hashtable = NULL((void*)0);
2085 eth_hashtable = NULL((void*)0);
2086 eui64_hashtable = NULL((void*)0);
2087 g_free(g_ethers_path);
2088 g_ethers_path = NULL((void*)0);
2089 g_free(g_pethers_path);
2090 g_pethers_path = NULL((void*)0);
2091 g_free(g_manuf_path);
2092 g_manuf_path = NULL((void*)0);
2093 g_free(g_pmanuf_path);
2094 g_pmanuf_path = NULL((void*)0);
2095 g_free(g_wka_path);
2096 g_wka_path = NULL((void*)0);
2097}
2098
2099static void
2100eth_resolved_name_fill(hashether_t *tp, const char *name, unsigned mask, const uint8_t *addr)
2101{
2102 switch (mask) {
2103 case 24:
2104 snprintf(tp->resolved_name, MAXNAMELEN64, "%s_%02x:%02x:%02x",
2105 name, addr[3], addr[4], addr[5]);
2106 break;
2107 case 28:
2108 snprintf(tp->resolved_name, MAXNAMELEN64, "%s_%01x:%02x:%02x",
2109 name, addr[3] & 0x0F, addr[4], addr[5]);
2110 break;
2111 case 36:
2112 snprintf(tp->resolved_name, MAXNAMELEN64, "%s_%01x:%02x",
2113 name, addr[4] & 0x0F, addr[5]);
2114 break;
2115 default: // Future-proof generic algorithm
2116 {
2117 unsigned bytes = mask / 8;
2118 unsigned bitmask = mask % 8;
2119
2120 int pos = snprintf(tp->resolved_name, MAXNAMELEN64, "%s", name);
2121 if (pos >= MAXNAMELEN64) return;
2122
2123 if (bytes < 6) {
2124 pos += snprintf(tp->resolved_name + pos, MAXNAMELEN64 - pos,
2125 bitmask >= 4 ? "_%01x" : "_%02x",
2126 addr[bytes] & (0xFF >> bitmask));
2127 bytes++;
2128 }
2129
2130 while (bytes < 6) {
2131 if (pos >= MAXNAMELEN64) return;
2132 pos += snprintf(tp->resolved_name + pos, MAXNAMELEN64 - pos, ":%02x",
2133 addr[bytes]);
2134 bytes++;
2135 }
2136 }
2137 }
2138}
2139
2140/* Resolve ethernet address */
2141static hashether_t *
2142eth_addr_resolve(hashether_t *tp) {
2143 hashmanuf_t *manuf_value;
2144 const uint8_t *addr = tp->addr;
2145 size_t addr_size = sizeof(tp->addr);
2146
2147 if (!(tp->flags & NAME_RESOLVED(1U<<1))) {
2148 unsigned mask;
2149 char *name;
2150 address ether_addr;
2151
2152 /* Unknown name. Try looking for it in the well-known-address
2153 tables for well-known address ranges smaller than 2^24. */
2154 mask = 7;
2155 do {
2156 /* Only the topmost 5 bytes participate fully */
2157 if ((name = wka_name_lookup(addr, mask+40)) != NULL((void*)0)) {
2158 snprintf(tp->resolved_name, MAXNAMELEN64, "%s_%02x",
2159 name, addr[5] & (0xFF >> mask));
2160 tp->flags |= NAME_RESOLVED(1U<<1) | NAME_RESOLVED_PREFIX(1U<<4);
2161 return tp;
2162 }
2163 } while (mask--);
2164
2165 mask = 7;
2166 do {
2167 /* Only the topmost 4 bytes participate fully */
2168 if ((name = wka_name_lookup(addr, mask+32)) != NULL((void*)0)) {
2169 snprintf(tp->resolved_name, MAXNAMELEN64, "%s_%02x:%02x",
2170 name, addr[4] & (0xFF >> mask), addr[5]);
2171 tp->flags |= NAME_RESOLVED(1U<<1) | NAME_RESOLVED_PREFIX(1U<<4);
2172 return tp;
2173 }
2174 } while (mask--);
2175
2176 mask = 7;
2177 do {
2178 /* Only the topmost 3 bytes participate fully */
2179 if ((name = wka_name_lookup(addr, mask+24)) != NULL((void*)0)) {
2180 snprintf(tp->resolved_name, MAXNAMELEN64, "%s_%02x:%02x:%02x",
2181 name, addr[3] & (0xFF >> mask), addr[4], addr[5]);
2182 tp->flags |= NAME_RESOLVED(1U<<1) | NAME_RESOLVED_PREFIX(1U<<4);
2183 return tp;
2184 }
2185 } while (mask--);
2186
2187 /* Now try looking in the manufacturer table. */
2188 manuf_value = manuf_name_lookup(addr, addr_size);
2189 if ((manuf_value != NULL((void*)0)) && ((manuf_value->flags & NAME_RESOLVED(1U<<1)) == NAME_RESOLVED(1U<<1))) {
2190 snprintf(tp->resolved_name, MAXNAMELEN64, "%.*s_%02x:%02x:%02x",
2191 MAXNAMELEN64 - 10, manuf_value->resolved_name, addr[3], addr[4], addr[5]);
2192 tp->flags |= NAME_RESOLVED(1U<<1) | NAME_RESOLVED_PREFIX(1U<<4);
2193 return tp;
2194 }
2195
2196 /* Now try looking for it in the well-known-address
2197 tables for well-known address ranges larger than 2^24. */
2198 mask = 7;
2199 do {
2200 /* Only the topmost 2 bytes participate fully */
2201 if ((name = wka_name_lookup(addr, mask+16)) != NULL((void*)0)) {
2202 snprintf(tp->resolved_name, MAXNAMELEN64, "%s_%02x:%02x:%02x:%02x",
2203 name, addr[2] & (0xFF >> mask), addr[3], addr[4],
2204 addr[5]);
2205 tp->flags |= NAME_RESOLVED(1U<<1) | NAME_RESOLVED_PREFIX(1U<<4);
2206 return tp;
2207 }
2208 } while (mask--);
2209
2210 mask = 7;
2211 do {
2212 /* Only the topmost byte participates fully */
2213 if ((name = wka_name_lookup(addr, mask+8)) != NULL((void*)0)) {
2214 snprintf(tp->resolved_name, MAXNAMELEN64, "%s_%02x:%02x:%02x:%02x:%02x",
2215 name, addr[1] & (0xFF >> mask), addr[2], addr[3],
2216 addr[4], addr[5]);
2217 tp->flags |= NAME_RESOLVED(1U<<1) | NAME_RESOLVED_PREFIX(1U<<4);
2218 return tp;
2219 }
2220 } while (mask--);
2221
2222 mask = 7;
2223 do {
2224 /* Not even the topmost byte participates fully */
2225 if ((name = wka_name_lookup(addr, mask)) != NULL((void*)0)) {
2226 snprintf(tp->resolved_name, MAXNAMELEN64, "%s_%02x:%02x:%02x:%02x:%02x:%02x",
2227 name, addr[0] & (0xFF >> mask), addr[1], addr[2],
2228 addr[3], addr[4], addr[5]);
2229 tp->flags |= NAME_RESOLVED(1U<<1) | NAME_RESOLVED_PREFIX(1U<<4);
2230 return tp;
2231 }
2232 } while (--mask); /* Work down to the last bit */
2233
2234 /* Now try looking in the global manuf data for a MA-M or MA-S
2235 * match. We do this last so that the other files override this
2236 * result.
2237 */
2238 const char *short_name, *long_name;
2239 short_name = ws_manuf_lookup(addr, &long_name, &mask);
2240 if (short_name != NULL((void*)0)) {
2241 if (mask == 24) {
2242 /* This shouldn't happen as it should be handled above,
2243 * but it doesn't hurt.
2244 */
2245 manuf_hash_new_entry(addr, short_name, long_name);
2246 }
2247 eth_resolved_name_fill(tp, short_name, mask, addr);
2248 tp->flags |= NAME_RESOLVED(1U<<1) | NAME_RESOLVED_PREFIX(1U<<4);
2249 return tp;
2250 }
2251 /* No match whatsoever. */
2252 set_address(&ether_addr, AT_ETHER, 6, addr);
2253 address_to_str_buf(&ether_addr, tp->resolved_name, MAXNAMELEN64);
2254 return tp;
2255 }
2256 return tp;
2257} /* eth_addr_resolve */
2258
2259static hashether_t *
2260eth_hash_new_entry(const uint8_t *addr, const bool_Bool resolve)
2261{
2262 hashether_t *tp;
2263 char *endp;
2264
2265 tp = wmem_new(addr_resolv_scope, hashether_t)((hashether_t*)wmem_alloc((addr_resolv_scope), sizeof(hashether_t
)))
;
2266 memcpy(tp->addr, addr, sizeof(tp->addr));
2267 tp->flags = 0;
2268 /* Values returned by bytes_to_hexstr_punct() are *not* null-terminated */
2269 endp = bytes_to_hexstr_punct(tp->hexaddr, addr, sizeof(tp->addr), ':');
2270 *endp = '\0';
2271 tp->resolved_name[0] = '\0';
2272
2273 if (resolve)
2274 eth_addr_resolve(tp);
2275
2276 wmem_map_insert(eth_hashtable, tp->addr, tp);
2277
2278 return tp;
2279} /* eth_hash_new_entry */
2280
2281static hashether_t *
2282add_eth_name(const uint8_t *addr, const char *name, bool_Bool static_entry)
2283{
2284 hashether_t *tp;
2285
2286 tp = (hashether_t *)wmem_map_lookup(eth_hashtable, addr);
2287
2288 if (tp == NULL((void*)0)) {
2289 tp = eth_hash_new_entry(addr, false0);
2290 }
2291
2292 if (strcmp(tp->resolved_name, name) != 0 && (static_entry || !(tp->flags & STATIC_HOSTNAME(1U<<3)))) {
2293 (void) g_strlcpy(tp->resolved_name, name, MAXNAMELEN64);
2294 tp->flags |= NAME_RESOLVED(1U<<1);
2295 if (static_entry) {
2296 tp->flags |= STATIC_HOSTNAME(1U<<3);
2297 }
2298 new_resolved_objects = true1;
2299 }
2300
2301 return tp;
2302} /* add_eth_name */
2303
2304static hashether_t *
2305eth_name_lookup(const uint8_t *addr, const bool_Bool resolve)
2306{
2307 hashether_t *tp;
2308
2309 tp = (hashether_t *)wmem_map_lookup(eth_hashtable, addr);
2310
2311 if (tp == NULL((void*)0)) {
2312 tp = eth_hash_new_entry(addr, resolve);
2313 } else {
2314 if (resolve && !(tp->flags & TRIED_OR_RESOLVED_MASK((1U<<0) | (1U<<1)))) {
2315 eth_addr_resolve(tp); /* Found but needs to be resolved */
2316 }
2317 }
2318 if (resolve) {
2319 tp->flags |= TRIED_RESOLVE_ADDRESS(1U<<0);
2320 }
2321
2322 return tp;
2323
2324} /* eth_name_lookup */
2325
2326static void
2327eui64_resolved_name_fill(hasheui64_t *tp, const char *name, unsigned mask, const uint8_t *addr)
2328{
2329 switch (mask) {
2330 case 24:
2331 snprintf(tp->resolved_name, MAXNAMELEN64, "%s_%02x:%02x:%02x:%02x:%02x",
2332 name, addr[3], addr[4], addr[5], addr[6], addr[7]);
2333 break;
2334 case 28:
2335 snprintf(tp->resolved_name, MAXNAMELEN64, "%s_%01x:%02x:%02x:%02x:%02x",
2336 name, addr[3] & 0x0F, addr[4], addr[5], addr[6], addr[7]);
2337 break;
2338 case 36:
2339 snprintf(tp->resolved_name, MAXNAMELEN64, "%s_%01x:%02x:%02x:%02x",
2340 name, addr[4] & 0x0F, addr[5], addr[6], addr[7]);
2341 break;
2342 default: // Future-proof generic algorithm
2343 {
2344 unsigned bytes = mask / 8;
2345 unsigned bitmask = mask % 8;
2346
2347 int pos = snprintf(tp->resolved_name, MAXNAMELEN64, "%s", name);
2348 if (pos >= MAXNAMELEN64) return;
2349
2350 if (bytes < EUI64_ADDR_LEN8) {
2351 pos += snprintf(tp->resolved_name + pos, MAXNAMELEN64 - pos,
2352 bitmask >= 4 ? "_%01x" : "_%02x",
2353 addr[bytes] & (0xFF >> bitmask));
2354 bytes++;
2355 }
2356
2357 while (bytes < EUI64_ADDR_LEN8) {
2358 if (pos >= MAXNAMELEN64) return;
2359 pos += snprintf(tp->resolved_name + pos, MAXNAMELEN64 - pos, ":%02x",
2360 addr[bytes]);
2361 bytes++;
2362 }
2363 }
2364 }
2365}
2366
2367/* Resolve EUI-64 address */
2368static hasheui64_t *
2369eui64_addr_resolve(hasheui64_t *tp)
2370{
2371 hashmanuf_t *manuf_value;
2372 const uint8_t *addr = tp->addr;
2373 size_t addr_size = sizeof(tp->addr);
2374
2375 if (!(tp->flags & NAME_RESOLVED(1U<<1))) {
2376 unsigned mask;
2377 address eui64_addr;
2378 /* manuf_name_lookup returns a hashmanuf_t* that covers an entire /24,
2379 * so we can't properly use it for MA-M and MA-S. We do want to check
2380 * it first so it also covers the user-defined tables.
2381 */
2382 manuf_value = manuf_name_lookup(addr, addr_size);
2383 if ((manuf_value != NULL((void*)0)) && ((manuf_value->flags & NAME_RESOLVED(1U<<1)) == NAME_RESOLVED(1U<<1))) {
2384 snprintf(tp->resolved_name, MAXNAMELEN64, "%.*s_%02x:%02x:%02x:%02x:%02x",
2385 MAXNAMELEN64 - 16, manuf_value->resolved_name, addr[3], addr[4], addr[5], addr[6], addr[7]);
2386 tp->flags |= NAME_RESOLVED(1U<<1) | NAME_RESOLVED_PREFIX(1U<<4);
2387 return tp;
2388 }
2389
2390 /* Now try looking in the global manuf data for a MA-M or MA-S
2391 * match. We do this last so that the other files override this
2392 * result.
2393 */
2394 const char *short_name, *long_name;
2395 short_name = ws_manuf_lookup(addr, &long_name, &mask);
2396 if (short_name != NULL((void*)0)) {
2397 if (mask == 24) {
2398 /* This shouldn't happen as it should be handled above,
2399 * but it doesn't hurt.
2400 */
2401 manuf_hash_new_entry(addr, short_name, long_name);
2402 }
2403 eui64_resolved_name_fill(tp, short_name, mask, addr);
2404 tp->flags |= NAME_RESOLVED(1U<<1) | NAME_RESOLVED_PREFIX(1U<<4);
2405 return tp;
2406 }
2407 /* No match whatsoever. */
2408 set_address(&eui64_addr, AT_EUI64, 8, addr);
2409 address_to_str_buf(&eui64_addr, tp->resolved_name, MAXNAMELEN64);
2410 return tp;
2411 }
2412
2413 return tp;
2414} /* eui64_addr_resolve */
2415
2416static hasheui64_t *
2417eui64_hash_new_entry(const uint8_t *addr, const bool_Bool resolve)
2418{
2419 hasheui64_t *tp;
2420 char *endp;
2421
2422 tp = wmem_new(addr_resolv_scope, hasheui64_t)((hasheui64_t*)wmem_alloc((addr_resolv_scope), sizeof(hasheui64_t
)))
;
2423 memcpy(tp->addr, addr, sizeof(tp->addr));
2424 tp->flags = 0;
2425 /* Values returned by bytes_to_hexstr_punct() are *not* null-terminated */
2426 endp = bytes_to_hexstr_punct(tp->hexaddr, addr, sizeof(tp->addr), ':');
2427 *endp = '\0';
2428 tp->resolved_name[0] = '\0';
2429
2430 if (resolve)
2431 eui64_addr_resolve(tp);
2432
2433 wmem_map_insert(eui64_hashtable, tp->addr, tp);
2434
2435 return tp;
2436} /* eui64_hash_new_entry */
2437
2438static hasheui64_t *
2439add_eui64_name(const uint8_t *addr, const char *name, bool_Bool static_entry)
2440{
2441 hasheui64_t *tp;
2442
2443 tp = (hasheui64_t *)wmem_map_lookup(eui64_hashtable, addr);
2444
2445 if (tp == NULL((void*)0)) {
2446 tp = eui64_hash_new_entry(addr, false0);
2447 }
2448
2449 if (strcmp(tp->resolved_name, name) != 0 && (static_entry || !(tp->flags & STATIC_HOSTNAME(1U<<3)))) {
2450 (void) g_strlcpy(tp->resolved_name, name, MAXNAMELEN64);
2451 tp->flags |= NAME_RESOLVED(1U<<1);
2452 if (static_entry) {
2453 tp->flags |= STATIC_HOSTNAME(1U<<3);
2454 }
2455 new_resolved_objects = true1;
2456 }
2457
2458 return tp;
2459} /* add_eui64_name */
2460
2461static hasheui64_t *
2462eui64_name_lookup(const uint8_t *addr, const bool_Bool resolve)
2463{
2464 hasheui64_t *tp;
2465
2466 tp = (hasheui64_t *)wmem_map_lookup(eui64_hashtable, addr);
2467
2468 if (tp == NULL((void*)0)) {
2469 tp = eui64_hash_new_entry(addr, resolve);
2470 } else {
2471 if (resolve && !(tp->flags & TRIED_OR_RESOLVED_MASK((1U<<0) | (1U<<1)))) {
2472 eui64_addr_resolve(tp); /* Found but needs to be resolved */
2473 }
2474 }
2475 if (resolve) {
2476 tp->flags |= TRIED_RESOLVE_ADDRESS(1U<<0);
2477 }
2478
2479 return tp;
2480
2481} /* eui64_name_lookup */
2482
2483/* IPXNETS */
2484static int
2485parse_ipxnets_line(char *line, ipxnet_t *ipxnet)
2486{
2487 /*
2488 * We allow three address separators (':', '-', and '.'),
2489 * as well as no separators
2490 */
2491
2492 char *cp;
2493 uint32_t a, a0, a1, a2, a3;
2494 bool_Bool found_single_number = false0;
2495
2496 if ((cp = strchr(line, '#')))
2497 *cp = '\0';
2498
2499 if ((cp = strtok(line, " \t\n")) == NULL((void*)0))
2500 return -1;
2501
2502 /* Either fill a0,a1,a2,a3 and found_single_number is false,
2503 * fill a and found_single_number is true,
2504 * or return -1
2505 */
2506 if (sscanf(cp, "%x:%x:%x:%x", &a0, &a1, &a2, &a3) != 4) {
2507 if (sscanf(cp, "%x-%x-%x-%x", &a0, &a1, &a2, &a3) != 4) {
2508 if (sscanf(cp, "%x.%x.%x.%x", &a0, &a1, &a2, &a3) != 4) {
2509 if (sscanf(cp, "%x", &a) == 1) {
2510 found_single_number = true1;
2511 }
2512 else {
2513 return -1;
2514 }
2515 }
2516 }
2517 }
2518
2519 if ((cp = strtok(NULL((void*)0), " \t\n")) == NULL((void*)0))
2520 return -1;
2521
2522 if (found_single_number) {
2523 ipxnet->addr = a;
2524 }
2525 else {
2526 ipxnet->addr = (a0 << 24) | (a1 << 16) | (a2 << 8) | a3;
2527 }
2528
2529 (void) g_strlcpy(ipxnet->name, cp, MAXNAMELEN64);
2530
2531 return 0;
2532
2533} /* parse_ipxnets_line */
2534
2535static FILE *ipxnet_p;
2536
2537static void
2538set_ipxnetent(char *path)
2539{
2540 if (ipxnet_p)
2541 rewind(ipxnet_p);
2542 else
2543 ipxnet_p = ws_fopenfopen(path, "r");
2544}
2545
2546static void
2547end_ipxnetent(void)
2548{
2549 if (ipxnet_p) {
2550 fclose(ipxnet_p);
2551 ipxnet_p = NULL((void*)0);
2552 }
2553}
2554
2555static ipxnet_t *
2556get_ipxnetent(void)
2557{
2558
2559 static ipxnet_t ipxnet;
2560 char buf[MAX_LINELEN1024];
2561
2562 if (ipxnet_p == NULL((void*)0))
2563 return NULL((void*)0);
2564
2565 while (fgetline(buf, sizeof(buf), ipxnet_p) >= 0) {
2566 if (parse_ipxnets_line(buf, &ipxnet) == 0) {
2567 return &ipxnet;
2568 }
2569 }
2570
2571 return NULL((void*)0);
2572
2573} /* get_ipxnetent */
2574
2575static ipxnet_t *
2576get_ipxnetbyaddr(uint32_t addr)
2577{
2578 ipxnet_t *ipxnet;
2579
2580 set_ipxnetent(g_ipxnets_path);
2581
2582 while (((ipxnet = get_ipxnetent()) != NULL((void*)0)) && (addr != ipxnet->addr) ) ;
2583
2584 if (ipxnet == NULL((void*)0)) {
2585 end_ipxnetent();
2586
2587 set_ipxnetent(g_pipxnets_path);
2588
2589 while (((ipxnet = get_ipxnetent()) != NULL((void*)0)) && (addr != ipxnet->addr) )
2590 ;
2591
2592 end_ipxnetent();
2593 }
2594
2595 return ipxnet;
2596
2597} /* get_ipxnetbyaddr */
2598
2599static void
2600initialize_ipxnets(const char* app_env_var_prefix)
2601{
2602 /* Compute the pathname of the ipxnets file.
2603 *
2604 * XXX - is there a notion of an "ipxnets file" in any flavor of
2605 * UNIX, or with any add-on Netware package for UNIX? If not,
2606 * should the UNIX version of the ipxnets file be in the datafile
2607 * directory as well?
2608 */
2609 if (g_ipxnets_path == NULL((void*)0)) {
2610 g_ipxnets_path = wmem_strdup_printf(addr_resolv_scope, "%s" G_DIR_SEPARATOR_S"/" "%s",
2611 get_systemfile_dir(app_env_var_prefix), ENAME_IPXNETS"ipxnets");
2612 }
2613
2614 /* Set g_pipxnets_path here, but don't actually do anything
2615 * with it. It's used in get_ipxnetbyaddr().
2616 */
2617 if (g_pipxnets_path == NULL((void*)0)) {
2618 /* Check profile directory before personal configuration */
2619 g_pipxnets_path = get_persconffile_path(ENAME_IPXNETS"ipxnets", true1, app_env_var_prefix);
2620 if (!file_exists(g_pipxnets_path)) {
2621 g_free(g_pipxnets_path);
2622 g_pipxnets_path = get_persconffile_path(ENAME_IPXNETS"ipxnets", false0, app_env_var_prefix);
2623 }
2624 }
2625
2626} /* initialize_ipxnets */
2627
2628static void
2629ipx_name_lookup_cleanup(void)
2630{
2631 g_ipxnets_path = NULL((void*)0);
2632 g_free(g_pipxnets_path);
2633 g_pipxnets_path = NULL((void*)0);
2634}
2635
2636static char *
2637ipxnet_name_lookup(wmem_allocator_t *allocator, const unsigned addr)
2638{
2639 hashipxnet_t *tp;
2640 ipxnet_t *ipxnet;
2641
2642 tp = (hashipxnet_t *)wmem_map_lookup(ipxnet_hash_table, GUINT_TO_POINTER(addr)((gpointer) (gulong) (addr)));
2643 if (tp == NULL((void*)0)) {
2644 tp = wmem_new(addr_resolv_scope, hashipxnet_t)((hashipxnet_t*)wmem_alloc((addr_resolv_scope), sizeof(hashipxnet_t
)))
;
2645 wmem_map_insert(ipxnet_hash_table, GUINT_TO_POINTER(addr)((gpointer) (gulong) (addr)), tp);
2646 } else {
2647 return wmem_strdup(allocator, tp->name);
2648 }
2649
2650 /* fill in a new entry */
2651
2652 tp->addr = addr;
2653
2654 if ( (ipxnet = get_ipxnetbyaddr(addr)) == NULL((void*)0)) {
2655 /* unknown name */
2656 snprintf(tp->name, MAXNAMELEN64, "%X", addr);
2657
2658 } else {
2659 (void) g_strlcpy(tp->name, ipxnet->name, MAXNAMELEN64);
2660 }
2661
2662 return wmem_strdup(allocator, tp->name);
2663
2664} /* ipxnet_name_lookup */
2665
2666/* VLANS */
2667static int
2668parse_vlan_line(char *line, vlan_t *vlan)
2669{
2670 char *cp;
2671 uint16_t id;
2672
2673 if ((cp = strchr(line, '#')))
2674 *cp = '\0';
2675
2676 if ((cp = strtok(line, " \t\n")) == NULL((void*)0))
2677 return -1;
2678
2679 if (sscanf(cp, "%" SCNu16"hu", &id) == 1) {
2680 vlan->id = id;
2681 }
2682 else {
2683 return -1;
2684 }
2685
2686 if ((cp = strtok(NULL((void*)0), "\t\n")) == NULL((void*)0))
2687 return -1;
2688
2689 (void) g_strlcpy(vlan->name, cp, MAXVLANNAMELEN128);
2690
2691 return 0;
2692
2693} /* parse_vlan_line */
2694
2695static FILE *vlan_p;
2696
2697static void
2698set_vlanent(char *path)
2699{
2700 if (vlan_p)
2701 rewind(vlan_p);
2702 else
2703 vlan_p = ws_fopenfopen(path, "r");
2704}
2705
2706static void
2707end_vlanent(void)
2708{
2709 if (vlan_p) {
2710 fclose(vlan_p);
2711 vlan_p = NULL((void*)0);
2712 }
2713}
2714
2715static vlan_t *
2716get_vlanent(void)
2717{
2718
2719 static vlan_t vlan;
2720 char buf[MAX_LINELEN1024];
2721
2722 if (vlan_p == NULL((void*)0))
2723 return NULL((void*)0);
2724
2725 while (fgetline(buf, sizeof(buf), vlan_p) >= 0) {
2726 if (parse_vlan_line(buf, &vlan) == 0) {
2727 return &vlan;
2728 }
2729 }
2730
2731 return NULL((void*)0);
2732
2733} /* get_vlanent */
2734
2735static vlan_t *
2736get_vlannamebyid(uint16_t id)
2737{
2738 vlan_t *vlan;
2739
2740 set_vlanent(g_pvlan_path);
2741
2742 while (((vlan = get_vlanent()) != NULL((void*)0)) && (id != vlan->id) ) ;
2743
2744 if (vlan == NULL((void*)0)) {
2745 end_vlanent();
2746
2747 }
2748
2749 return vlan;
2750
2751} /* get_vlannamebyid */
2752
2753static void
2754initialize_vlans(const char* app_env_var_prefix)
2755{
2756 ws_assert(vlan_hash_table == NULL)do { if ((1) && !(vlan_hash_table == ((void*)0))) ws_log_fatal_full
("", LOG_LEVEL_ERROR, "epan/addr_resolv.c", 2756, __func__, "assertion failed: %s"
, "vlan_hash_table == ((void*)0)"); } while (0)
;
2757 vlan_hash_table = wmem_map_new(addr_resolv_scope, g_direct_hash, g_direct_equal);
2758
2759 /* Set g_pvlan_path here, but don't actually do anything
2760 * with it. It's used in get_vlannamebyid()
2761 */
2762 if (g_pvlan_path == NULL((void*)0)) {
2763 /* Check profile directory before personal configuration */
2764 g_pvlan_path = get_persconffile_path(ENAME_VLANS"vlans", true1, app_env_var_prefix);
2765 if (!file_exists(g_pvlan_path)) {
2766 g_free(g_pvlan_path);
2767 g_pvlan_path = get_persconffile_path(ENAME_VLANS"vlans", false0, app_env_var_prefix);
2768 }
2769 }
2770} /* initialize_vlans */
2771
2772static void
2773vlan_name_lookup_cleanup(void)
2774{
2775 end_vlanent();
2776 vlan_hash_table = NULL((void*)0);
2777 g_free(g_pvlan_path);
2778 g_pvlan_path = NULL((void*)0);
2779}
2780
2781static const char *
2782vlan_name_lookup(const unsigned id)
2783{
2784 hashvlan_t *tp;
2785 vlan_t *vlan;
2786
2787 tp = (hashvlan_t *)wmem_map_lookup(vlan_hash_table, GUINT_TO_POINTER(id)((gpointer) (gulong) (id)));
2788 if (tp == NULL((void*)0)) {
2789 tp = wmem_new(addr_resolv_scope, hashvlan_t)((hashvlan_t*)wmem_alloc((addr_resolv_scope), sizeof(hashvlan_t
)))
;
2790 wmem_map_insert(vlan_hash_table, GUINT_TO_POINTER(id)((gpointer) (gulong) (id)), tp);
2791 } else {
2792 return tp->name;
2793 }
2794
2795 /* fill in a new entry */
2796
2797 tp->id = id;
2798
2799 if ( (vlan = get_vlannamebyid(id)) == NULL((void*)0)) {
2800 /* unknown name */
2801 snprintf(tp->name, MAXVLANNAMELEN128, "<%u>", id);
2802
2803 } else {
2804 (void) g_strlcpy(tp->name, vlan->name, MAXVLANNAMELEN128);
2805 }
2806
2807 return tp->name;
2808
2809} /* vlan_name_lookup */
2810/* VLAN END */
2811
2812static bool_Bool
2813read_hosts_file (const char *hostspath, bool_Bool store_entries)
2814{
2815 FILE *hf;
2816 char line[MAX_LINELEN1024];
2817 char *cp;
2818 union {
2819 uint32_t ip4_addr;
2820 ws_in6_addr ip6_addr;
2821 } host_addr;
2822 bool_Bool is_ipv6, entry_found = false0;
2823
2824 /*
2825 * See the hosts(4) or hosts(5) man page for hosts file format
2826 * (not available on all systems).
2827 */
2828 if ((hf = ws_fopenfopen(hostspath, "r")) == NULL((void*)0))
2829 return false0;
2830
2831 while (fgetline(line, sizeof(line), hf) >= 0) {
2832 if ((cp = strchr(line, '#')))
2833 *cp = '\0';
2834
2835 if ((cp = strtok(line, " \t")) == NULL((void*)0))
2836 continue; /* no tokens in the line */
2837
2838 if (ws_inet_pton6(cp, &host_addr.ip6_addr)) {
2839 /* Valid IPv6 */
2840 is_ipv6 = true1;
2841 } else if (ws_inet_pton4(cp, &host_addr.ip4_addr)) {
2842 /* Valid IPv4 */
2843 is_ipv6 = false0;
2844 } else {
2845 continue;
2846 }
2847
2848 if ((cp = strtok(NULL((void*)0), " \t")) == NULL((void*)0))
2849 continue; /* no host name */
2850
2851 entry_found = true1;
2852 if (store_entries) {
2853 if (is_ipv6) {
2854 add_ipv6_name(&host_addr.ip6_addr, cp, true1);
2855 } else {
2856 add_ipv4_name(host_addr.ip4_addr, cp, true1);
2857 }
2858 }
2859 }
2860
2861 fclose(hf);
2862 return entry_found ? true1 : false0;
2863} /* read_hosts_file */
2864
2865bool_Bool
2866add_hosts_file (const char *hosts_file)
2867{
2868 bool_Bool found = false0;
2869 unsigned i;
2870
2871 if (!hosts_file)
2872 return false0;
2873
2874 if (!extra_hosts_files)
2875 extra_hosts_files = g_ptr_array_new();
2876
2877 for (i = 0; i < extra_hosts_files->len; i++) {
2878 if (strcmp(hosts_file, (const char *) g_ptr_array_index(extra_hosts_files, i)((extra_hosts_files)->pdata)[i]) == 0)
2879 found = true1;
2880 }
2881
2882 if (!found) {
2883 g_ptr_array_add(extra_hosts_files, wmem_strdup(wmem_epan_scope(), hosts_file));
2884 return read_hosts_file (hosts_file, false0);
2885 }
2886 return true1;
2887}
2888
2889bool_Bool
2890add_ip_name_from_string (const char *addr, const char *name)
2891{
2892 union {
2893 uint32_t ip4_addr;
2894 ws_in6_addr ip6_addr;
2895 } host_addr;
2896 bool_Bool is_ipv6;
2897 resolved_name_t *resolved_entry;
2898
2899 if (ws_inet_pton6(addr, &host_addr.ip6_addr)) {
2900 is_ipv6 = true1;
2901 } else if (ws_inet_pton4(addr, &host_addr.ip4_addr)) {
2902 is_ipv6 = false0;
2903 } else {
2904 return false0;
2905 }
2906
2907 if (is_ipv6) {
2908 resolved_entry = (resolved_name_t*)wmem_map_lookup(manually_resolved_ipv6_list, &host_addr.ip6_addr);
2909 if (resolved_entry)
2910 {
2911 // If we found a previous matching key (IP address), then just update the value (custom hostname);
2912 (void) g_strlcpy(resolved_entry->name, name, MAXDNSNAMELEN256);
2913 }
2914 else
2915 {
2916 // Add a new mapping entry, if this IP address isn't already in the list.
2917 ws_in6_addr* addr_key = wmem_new(wmem_epan_scope(), ws_in6_addr)((ws_in6_addr*)wmem_alloc((wmem_epan_scope()), sizeof(ws_in6_addr
)))
;
2918 memcpy(addr_key, &host_addr.ip6_addr, sizeof(ws_in6_addr));
2919
2920 resolved_entry = wmem_new(wmem_epan_scope(), resolved_name_t)((resolved_name_t*)wmem_alloc((wmem_epan_scope()), sizeof(resolved_name_t
)))
;
2921 (void) g_strlcpy(resolved_entry->name, name, MAXDNSNAMELEN256);
2922
2923 wmem_map_insert(manually_resolved_ipv6_list, addr_key, resolved_entry);
2924 }
2925 } else {
2926 resolved_entry = (resolved_name_t*)wmem_map_lookup(manually_resolved_ipv4_list, GUINT_TO_POINTER(host_addr.ip4_addr)((gpointer) (gulong) (host_addr.ip4_addr)));
2927 if (resolved_entry)
2928 {
2929 // If we found a previous matching key (IP address), then just update the value (custom hostname);
2930 (void) g_strlcpy(resolved_entry->name, name, MAXDNSNAMELEN256);
2931 }
2932 else
2933 {
2934 // Add a new mapping entry, if this IP address isn't already in the list.
2935 resolved_entry = wmem_new(wmem_epan_scope(), resolved_name_t)((resolved_name_t*)wmem_alloc((wmem_epan_scope()), sizeof(resolved_name_t
)))
;
2936 (void) g_strlcpy(resolved_entry->name, name, MAXDNSNAMELEN256);
2937
2938 wmem_map_insert(manually_resolved_ipv4_list, GUINT_TO_POINTER(host_addr.ip4_addr)((gpointer) (gulong) (host_addr.ip4_addr)), resolved_entry);
2939 }
2940 }
2941
2942 return true1;
2943} /* add_ip_name_from_string */
2944
2945extern resolved_name_t* get_edited_resolved_name(const char* addr)
2946{
2947 uint32_t ip4_addr;
2948 ws_in6_addr ip6_addr;
2949 resolved_name_t* resolved_entry = NULL((void*)0);
2950
2951 if (ws_inet_pton6(addr, &ip6_addr)) {
2952 resolved_entry = (resolved_name_t*)wmem_map_lookup(manually_resolved_ipv6_list, &ip6_addr);
2953 }
2954 else if (ws_inet_pton4(addr, &ip4_addr)) {
2955 resolved_entry = (resolved_name_t*)wmem_map_lookup(manually_resolved_ipv4_list, GUINT_TO_POINTER(ip4_addr)((gpointer) (gulong) (ip4_addr)));
2956 }
2957
2958 return resolved_entry;
2959}
2960
2961/*
2962 * Add the resolved addresses that are in use to the list used to create the pcapng NRB
2963 */
2964static void
2965ipv4_hash_table_resolved_to_list(void *key _U___attribute__((unused)), void *value, void *user_data)
2966{
2967 addrinfo_lists_t *lists = (addrinfo_lists_t *)user_data;
2968 hashipv4_t *ipv4_hash_table_entry = (hashipv4_t *)value;
2969
2970 if ((ipv4_hash_table_entry->flags & USED_AND_RESOLVED_MASK((1U<<1) | (1U<<2))) == USED_AND_RESOLVED_MASK((1U<<1) | (1U<<2))) {
2971 lists->ipv4_addr_list = g_list_prepend(lists->ipv4_addr_list, ipv4_hash_table_entry);
2972 }
2973}
2974
2975/*
2976 * Add the resolved addresses that are in use to the list used to create the pcapng NRB
2977 */
2978static void
2979ipv6_hash_table_resolved_to_list(void *key _U___attribute__((unused)), void *value, void *user_data)
2980{
2981 addrinfo_lists_t *lists = (addrinfo_lists_t *)user_data;
2982 hashipv6_t *ipv6_hash_table_entry = (hashipv6_t *)value;
2983
2984 if ((ipv6_hash_table_entry->flags & USED_AND_RESOLVED_MASK((1U<<1) | (1U<<2))) == USED_AND_RESOLVED_MASK((1U<<1) | (1U<<2))) {
2985 lists->ipv6_addr_list = g_list_prepend(lists->ipv6_addr_list, ipv6_hash_table_entry);
2986 }
2987}
2988
2989addrinfo_lists_t *
2990get_addrinfo_list(void)
2991{
2992 if (ipv4_hash_table) {
2993 wmem_map_foreach(ipv4_hash_table, ipv4_hash_table_resolved_to_list, &addrinfo_lists);
2994 }
2995
2996 if (ipv6_hash_table) {
2997 wmem_map_foreach(ipv6_hash_table, ipv6_hash_table_resolved_to_list, &addrinfo_lists);
2998 }
2999
3000 return &addrinfo_lists;
3001}
3002
3003/* Read in a list of subnet definition - name pairs.
3004 * <line> = <comment> | <entry> | <whitespace>
3005 * <comment> = <whitespace>#<any>
3006 * <entry> = <subnet_definition> <whitespace> <subnet_name> [<comment>|<whitespace><any>]
3007 * <subnet_definition> = <ipv4_address> / <subnet_mask_length>
3008 * <ipv4_address> is a full address; it will be masked to get the subnet-ID.
3009 * <subnet_mask_length> is a decimal 1-31
3010 * <subnet_name> is a string containing no whitespace.
3011 * <whitespace> = (space | tab)+
3012 * Any malformed entries are ignored.
3013 * Any trailing data after the subnet_name is ignored.
3014 *
3015 * XXX Support IPv6
3016 */
3017static bool_Bool
3018read_subnets_file (const char *subnetspath)
3019{
3020 FILE *hf;
3021 char line[MAX_LINELEN1024];
3022 char *cp, *cp2;
3023 uint32_t host_addr; /* IPv4 ONLY */
3024 uint8_t mask_length;
3025
3026 if ((hf = ws_fopenfopen(subnetspath, "r")) == NULL((void*)0))
3027 return false0;
3028
3029 while (fgetline(line, sizeof(line), hf) >= 0) {
3030 if ((cp = strchr(line, '#')))
3031 *cp = '\0';
3032
3033 if ((cp = strtok(line, " \t")) == NULL((void*)0))
3034 continue; /* no tokens in the line */
3035
3036
3037 /* Expected format is <IP4 address>/<subnet length> */
3038 cp2 = strchr(cp, '/');
3039 if (NULL((void*)0) == cp2) {
3040 /* No length */
3041 continue;
3042 }
3043 *cp2 = '\0'; /* Cut token */
3044 ++cp2 ;
3045
3046 /* Check if this is a valid IPv4 address */
3047 if (!str_to_ip(cp, &host_addr)) {
3048 continue; /* no */
3049 }
3050
3051 if (!ws_strtou8(cp2, NULL((void*)0), &mask_length) || mask_length == 0 || mask_length > 32) {
3052 continue; /* invalid mask length */
3053 }
3054
3055 if ((cp = strtok(NULL((void*)0), " \t")) == NULL((void*)0))
3056 continue; /* no subnet name */
3057
3058 subnet_entry_set(host_addr, mask_length, cp);
3059 }
3060
3061 fclose(hf);
3062 return true1;
3063} /* read_subnets_file */
3064
3065static subnet_entry_t
3066subnet_lookup(const uint32_t addr)
3067{
3068 subnet_entry_t subnet_entry;
3069 uint32_t i;
3070
3071 /* Search mask lengths linearly, longest first */
3072
3073 i = SUBNETLENGTHSIZE32;
3074 while(have_subnet_entry && i > 0) {
3075 uint32_t masked_addr;
3076 subnet_length_entry_t* length_entry;
3077
3078 /* Note that we run from 31 (length 32) to 0 (length 1) */
3079 --i;
3080 ws_assert(i < SUBNETLENGTHSIZE)do { if ((1) && !(i < 32)) ws_log_fatal_full("", LOG_LEVEL_ERROR
, "epan/addr_resolv.c", 3080, __func__, "assertion failed: %s"
, "i < 32"); } while (0)
;
3081
3082
3083 length_entry = &subnet_length_entries[i];
3084
3085 if (NULL((void*)0) != length_entry->subnet_addresses) {
3086 sub_net_hashipv4_t * tp;
3087 uint32_t hash_idx;
3088
3089 masked_addr = addr & length_entry->mask;
3090 hash_idx = HASH_IPV4_ADDRESS(masked_addr)((((((guint32) ( (((guint32) (masked_addr) & (guint32) 0x000000ffU
) << 24) | (((guint32) (masked_addr) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (masked_addr) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (masked_addr) & (guint32) 0xff000000U
) >> 24)))))) & (2048 - 1))
;
3091
3092 tp = length_entry->subnet_addresses[hash_idx];
3093 while(tp != NULL((void*)0) && tp->addr != masked_addr) {
3094 tp = tp->next;
3095 }
3096
3097 if (NULL((void*)0) != tp) {
3098 subnet_entry.mask = length_entry->mask;
3099 subnet_entry.mask_length = i + 1; /* Length is offset + 1 */
3100 subnet_entry.name = tp->name;
3101 return subnet_entry;
3102 }
3103 }
3104 }
3105
3106 subnet_entry.mask = 0;
3107 subnet_entry.mask_length = 0;
3108 subnet_entry.name = NULL((void*)0);
3109
3110 return subnet_entry;
3111}
3112
3113/* Add a subnet-definition - name pair to the set.
3114 * The definition is taken by masking the address passed in with the mask of the
3115 * given length.
3116 */
3117static void
3118subnet_entry_set(uint32_t subnet_addr, const uint8_t mask_length, const char* name)
3119{
3120 subnet_length_entry_t* entry;
3121 sub_net_hashipv4_t * tp;
3122 size_t hash_idx;
3123
3124 ws_assert(mask_length > 0 && mask_length <= 32)do { if ((1) && !(mask_length > 0 && mask_length
<= 32)) ws_log_fatal_full("", LOG_LEVEL_ERROR, "epan/addr_resolv.c"
, 3124, __func__, "assertion failed: %s", "mask_length > 0 && mask_length <= 32"
); } while (0)
;
3125
3126 entry = &subnet_length_entries[mask_length - 1];
3127
3128 subnet_addr &= entry->mask;
3129
3130 hash_idx = HASH_IPV4_ADDRESS(subnet_addr)((((((guint32) ( (((guint32) (subnet_addr) & (guint32) 0x000000ffU
) << 24) | (((guint32) (subnet_addr) & (guint32) 0x0000ff00U
) << 8) | (((guint32) (subnet_addr) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (subnet_addr) & (guint32) 0xff000000U
) >> 24)))))) & (2048 - 1))
;
3131
3132 if (NULL((void*)0) == entry->subnet_addresses) {
3133 entry->subnet_addresses = (sub_net_hashipv4_t**)wmem_alloc0(addr_resolv_scope, sizeof(sub_net_hashipv4_t*) * HASHHOSTSIZE2048);
3134 }
3135
3136 if (NULL((void*)0) != (tp = entry->subnet_addresses[hash_idx])) {
3137 sub_net_hashipv4_t * new_tp;
3138
3139 while (tp->next) {
3140 if (tp->addr == subnet_addr) {
3141 return; /* XXX provide warning that an address was repeated? */
3142 } else {
3143 tp = tp->next;
3144 }
3145 }
3146
3147 new_tp = wmem_new(addr_resolv_scope, sub_net_hashipv4_t)((sub_net_hashipv4_t*)wmem_alloc((addr_resolv_scope), sizeof(
sub_net_hashipv4_t)))
;
3148 tp->next = new_tp;
3149 tp = new_tp;
3150 } else {
3151 tp = entry->subnet_addresses[hash_idx] = wmem_new(addr_resolv_scope, sub_net_hashipv4_t)((sub_net_hashipv4_t*)wmem_alloc((addr_resolv_scope), sizeof(
sub_net_hashipv4_t)))
;
3152 }
3153
3154 tp->next = NULL((void*)0);
3155 tp->addr = subnet_addr;
3156 (void) g_strlcpy(tp->name, name, MAXNAMELEN64); /* This is longer than subnet names can actually be */
3157 have_subnet_entry = true1;
3158}
3159
3160static void
3161subnet_name_lookup_init(const char* app_env_var_prefix)
3162{
3163 char* subnetspath;
3164 uint32_t i;
3165
3166 for(i = 0; i < SUBNETLENGTHSIZE32; ++i) {
3167 uint32_t length = i + 1;
3168
3169 subnet_length_entries[i].subnet_addresses = NULL((void*)0);
3170 subnet_length_entries[i].mask_length = length;
3171 subnet_length_entries[i].mask = g_htonl(ws_ipv4_get_subnet_mask(length))(((((guint32) ( (((guint32) (ws_ipv4_get_subnet_mask(length))
& (guint32) 0x000000ffU) << 24) | (((guint32) (ws_ipv4_get_subnet_mask
(length)) & (guint32) 0x0000ff00U) << 8) | (((guint32
) (ws_ipv4_get_subnet_mask(length)) & (guint32) 0x00ff0000U
) >> 8) | (((guint32) (ws_ipv4_get_subnet_mask(length))
& (guint32) 0xff000000U) >> 24))))))
;
3172 }
3173
3174 /* Check profile directory before personal configuration */
3175 subnetspath = get_persconffile_path(ENAME_SUBNETS"subnets", true1, app_env_var_prefix);
3176 if (!read_subnets_file(subnetspath)) {
3177 if (errno(*__errno_location ()) != ENOENT2) {
3178 report_open_failure(subnetspath, errno(*__errno_location ()), false0);
3179 }
3180
3181 g_free(subnetspath);
3182 subnetspath = get_persconffile_path(ENAME_SUBNETS"subnets", false0, app_env_var_prefix);
3183 if (!read_subnets_file(subnetspath) && errno(*__errno_location ()) != ENOENT2) {
3184 report_open_failure(subnetspath, errno(*__errno_location ()), false0);
3185 }
3186 }
3187 g_free(subnetspath);
3188
3189 /*
3190 * Load the global subnets file, if we have one.
3191 */
3192 subnetspath = get_datafile_path(ENAME_SUBNETS"subnets", app_env_var_prefix);
3193 if (!read_subnets_file(subnetspath) && errno(*__errno_location ()) != ENOENT2) {
3194 report_open_failure(subnetspath, errno(*__errno_location ()), false0);
3195 }
3196 g_free(subnetspath);
3197}
3198
3199/* SS7 PC Name Resolution Portion */
3200static hashss7pc_t *
3201new_ss7pc(const uint8_t ni, const uint32_t pc)
3202{
3203 hashss7pc_t *tp = wmem_new(addr_resolv_scope, hashss7pc_t)((hashss7pc_t*)wmem_alloc((addr_resolv_scope), sizeof(hashss7pc_t
)))
;
3204 tp->id = (ni<<24) + (pc&0xffffff);
3205 tp->pc_addr[0] = '\0';
3206 tp->name[0] = '\0';
3207
3208 return tp;
3209}
3210
3211static hashss7pc_t *
3212host_lookup_ss7pc(const uint8_t ni, const uint32_t pc)
3213{
3214 hashss7pc_t * volatile tp;
3215 uint32_t id;
3216
3217 id = (ni<<24) + (pc&0xffffff);
3218
3219 tp = (hashss7pc_t *)wmem_map_lookup(ss7pc_hash_table, GUINT_TO_POINTER(id)((gpointer) (gulong) (id)));
3220 if (tp == NULL((void*)0)) {
3221 tp = new_ss7pc(ni, pc);
3222 wmem_map_insert(ss7pc_hash_table, GUINT_TO_POINTER(id)((gpointer) (gulong) (id)), tp);
3223 }
3224
3225 return tp;
3226}
3227
3228void fill_unresolved_ss7pc(const char * pc_addr, const uint8_t ni, const uint32_t pc)
3229{
3230 hashss7pc_t *tp = host_lookup_ss7pc(ni, pc);
3231
3232 (void) g_strlcpy(tp->pc_addr, pc_addr, MAXNAMELEN64);
3233}
3234
3235const char *
3236get_hostname_ss7pc(const uint8_t ni, const uint32_t pc)
3237{
3238 hashss7pc_t *tp = host_lookup_ss7pc(ni, pc);
3239
3240 /* never resolved yet*/
3241 if (tp->pc_addr[0] == '\0')
3242 return tp->pc_addr;
3243
3244 /* Don't have name in file */
3245 if (tp->name[0] == '\0')
3246 return tp->pc_addr;
3247
3248 if (!gbl_resolv_flags.ss7pc_name)
3249 return tp->pc_addr;
3250
3251 return tp->name;
3252}
3253
3254static void
3255add_ss7pc_name(const uint8_t ni, uint32_t pc, const char *name)
3256{
3257 hashss7pc_t *tp;
3258 uint32_t id;
3259
3260 if (!name || name[0] == '\0')
3261 return;
3262
3263 id = (ni<<24) + (pc&0xffffff);
3264 tp = (hashss7pc_t *)wmem_map_lookup(ss7pc_hash_table, GUINT_TO_POINTER(id)((gpointer) (gulong) (id)));
3265 if (!tp) {
3266 tp = new_ss7pc(ni, pc);
3267 wmem_map_insert(ss7pc_hash_table, GUINT_TO_POINTER(id)((gpointer) (gulong) (id)), tp);
3268 }
3269
3270 if (g_ascii_strcasecmp(tp->name, name)) {
3271 (void) g_strlcpy(tp->name, name, MAXNAMELEN64);
3272 }
3273}
3274
3275static bool_Bool
3276read_ss7pcs_file(const char *ss7pcspath)
3277{
3278 FILE *hf;
3279 char line[MAX_LINELEN1024];
3280 char *cp;
3281 uint8_t ni;
3282 uint32_t pc;
3283 bool_Bool entry_found = false0;
3284
3285 /*
3286 * File format is Network Indicator (decimal)<dash>Point Code (Decimal)<tab/space>Hostname
3287 */
3288 if ((hf = ws_fopenfopen(ss7pcspath, "r")) == NULL((void*)0))
34
Taking false branch
3289 return false0;
3290
3291 while (fgetline(line, sizeof(line), hf) >= 0) {
35
Loop condition is false. Execution continues on line 3316
3292 if ((cp = strchr(line, '#')))
3293 *cp = '\0';
3294
3295 if ((cp = strtok(line, "-")) == NULL((void*)0))
3296 continue; /*no ni-pc separator*/
3297 if (!ws_strtou8(cp, NULL((void*)0), &ni))
3298 continue;
3299 if (ni > 3)
3300 continue;
3301
3302 if ((cp = strtok(NULL((void*)0), " \t")) == NULL((void*)0))
3303 continue; /* no tokens for pc and name */
3304 if (!ws_strtou32(cp, NULL((void*)0), &pc))
3305 continue;
3306 if (pc >> 24 > 0)
3307 continue;
3308
3309 if ((cp = strtok(NULL((void*)0), " \t")) == NULL((void*)0))
3310 continue; /* no host name */
3311
3312 entry_found = true1;
3313 add_ss7pc_name(ni, pc, cp);
3314 }
3315
3316 fclose(hf);
36
Assuming that 'fclose' is successful; 'errno' becomes undefined after the call
3317 return entry_found
36.1
'entry_found' is false
? true1 : false0;
37
'?' condition is false
3318}
3319
3320static void
3321ss7pc_name_lookup_init(const char* app_env_var_prefix)
3322{
3323 char *ss7pcspath;
3324
3325 ws_assert(ss7pc_hash_table == NULL)do { if ((1) && !(ss7pc_hash_table == ((void*)0))) ws_log_fatal_full
("", LOG_LEVEL_ERROR, "epan/addr_resolv.c", 3325, __func__, "assertion failed: %s"
, "ss7pc_hash_table == ((void*)0)"); } while (0)
;
30
Assuming 'ss7pc_hash_table' is equal to null
31
Taking false branch
32
Loop condition is false. Exiting loop
3326
3327 ss7pc_hash_table = wmem_map_new(addr_resolv_scope, g_direct_hash, g_direct_equal);
3328
3329 /*
3330 * Load the user's ss7pcs file
3331 */
3332 ss7pcspath = get_persconffile_path(ENAME_SS7PCS"ss7pcs", true1, app_env_var_prefix);
3333 if (!read_ss7pcs_file(ss7pcspath) && errno(*__errno_location ()) != ENOENT2) {
33
Calling 'read_ss7pcs_file'
38
Returning from 'read_ss7pcs_file'
39
An undefined value may be read from 'errno'
3334 report_open_failure(ss7pcspath, errno(*__errno_location ()), false0);
3335 }
3336 g_free(ss7pcspath);
3337}
3338
3339/* SS7PC Name Resolution End*/
3340
3341/* TACS */
3342static bool_Bool
3343read_tacs_file(const char *tacspath)
3344{
3345 FILE *hf;
3346 char line[MAX_LINELEN1024];
3347 char *cp;
3348 uint16_t id;
3349 wmem_strbuf_t *tac_name = NULL((void*)0);
3350
3351 /*
3352 * File format is TAC(decimal)<tab/space>TACName (no spaces)
3353 */
3354 if ((hf = ws_fopenfopen(tacspath, "r")) == NULL((void*)0))
3355 return false0;
3356
3357 while (fgetline(line, sizeof(line), hf) >= 0) {
3358 if ((cp = strchr(line, '#')))
3359 *cp = '\0';
3360
3361 if ((cp = strtok(line, " \t")) == NULL((void*)0))
3362 continue;
3363
3364 if (sscanf(cp, "%" SCNu16"hu", &id) != 1) {
3365 continue;
3366 }
3367
3368 if ((cp = strtok(NULL((void*)0), " \t\n")) == NULL((void*)0))
3369 continue; /* no TAC name */
3370
3371 if (!wmem_map_lookup(tac_hash_table, GUINT_TO_POINTER(id)((gpointer) (gulong) (id)))) {
3372 tac_name = wmem_strbuf_new(addr_resolv_scope, cp);
3373 wmem_map_insert(tac_hash_table, GUINT_TO_POINTER(id)((gpointer) (gulong) (id)), (void *)wmem_strbuf_get_str(tac_name));
3374 }
3375 }
3376
3377 fclose(hf);
3378 return true1;
3379}
3380
3381static void
3382initialize_tacs(const char* app_env_var_prefix)
3383{
3384 char *tacspath;
3385 ws_assert(tac_hash_table == NULL)do { if ((1) && !(tac_hash_table == ((void*)0))) ws_log_fatal_full
("", LOG_LEVEL_ERROR, "epan/addr_resolv.c", 3385, __func__, "assertion failed: %s"
, "tac_hash_table == ((void*)0)"); } while (0)
;
3386 tac_hash_table = wmem_map_new(addr_resolv_scope, g_direct_hash, g_direct_equal);
3387
3388 tacspath = get_persconffile_path(ENAME_TACS"tacs", true1, app_env_var_prefix);
3389 if (!read_tacs_file(tacspath) && errno(*__errno_location ()) != ENOENT2) {
3390 report_open_failure(tacspath, errno(*__errno_location ()), false0);
3391 }
3392 g_free(tacspath);
3393}
3394
3395static void
3396tac_name_lookup_cleanup(void)
3397{
3398 tac_hash_table = NULL((void*)0);
3399}
3400
3401const char *
3402tac_name_lookup(const unsigned id)
3403{
3404 return (const char *)wmem_map_lookup(tac_hash_table, GUINT_TO_POINTER(id)((gpointer) (gulong) (id)));
3405}
3406/* TAC END */
3407
3408/*
3409 * External Functions
3410 */
3411
3412void
3413addr_resolve_pref_init(module_t *nameres)
3414{
3415 prefs_register_bool_preference(nameres, "mac_name",
3416 "Resolve MAC addresses",
3417 "Resolve Ethernet MAC addresses to host names from the preferences"
3418 " or system's Ethers file, or to a manufacturer based name.",
3419 &gbl_resolv_flags.mac_name);
3420
3421 prefs_register_bool_preference(nameres, "transport_name",
3422 "Resolve transport names",
3423 "Resolve TCP/UDP ports into service names",
3424 &gbl_resolv_flags.transport_name);
3425
3426 prefs_register_bool_preference(nameres, "network_name",
3427 "Resolve network (IP) addresses",
3428 "Resolve IPv4, IPv6, and IPX addresses into host names."
3429 " The next set of check boxes determines how name resolution should be performed."
3430 " If no other options are checked name resolution is made from Wireshark's host file"
3431 " and capture file name resolution blocks.",
3432 &gbl_resolv_flags.network_name);
3433
3434 prefs_register_bool_preference(nameres, "dns_pkt_addr_resolution",
3435 "Use captured DNS packet data for name resolution",
3436 "Use address/name pairs found in captured DNS packets for name resolution.",
3437 &gbl_resolv_flags.dns_pkt_addr_resolution);
3438
3439 prefs_register_bool_preference(nameres, "handshake_sni_addr_resolution",
3440 "Use SNI information from captured handshake packets",
3441 "Use the Server Name Indication found in TLS handshakes for name resolution.",
3442 &gbl_resolv_flags.handshake_sni_addr_resolution);
3443
3444 prefs_register_bool_preference(nameres, "use_external_name_resolver",
3445 "Use your system's DNS settings for name resolution",
3446 "Use your system's configured name resolver"
3447 " (usually DNS) to resolve network names."
3448 " Only applies when network name resolution"
3449 " is enabled.",
3450 &gbl_resolv_flags.use_external_net_name_resolver);
3451
3452 prefs_register_bool_preference(nameres, "use_custom_dns_servers",
3453 "Use a custom list of DNS servers for name resolution",
3454 "Use a DNS Servers list to resolve network names if true. If false, default information is used",
3455 &use_custom_dns_server_list);
3456
3457 static uat_field_t dns_server_uats_flds[] = {
3458 UAT_FLD_CSTRING_OTHER(dnsserverlist_uats, ipaddr, "IP address", dnsserver_uat_fld_ip_chk_cb, "IPv4 or IPv6 address"){"ipaddr", "IP address", PT_TXTMOD_STRING,{ dnsserver_uat_fld_ip_chk_cb
,dnsserverlist_uats_ipaddr_set_cb,dnsserverlist_uats_ipaddr_tostr_cb
},{0,0,0},0,"IPv4 or IPv6 address",((void*)0)}
,
3459 UAT_FLD_CSTRING_OTHER(dnsserverlist_uats, tcp_port, "TCP Port", dnsserver_uat_fld_port_chk_cb, "Port Number (TCP)"){"tcp_port", "TCP Port", PT_TXTMOD_STRING,{ dnsserver_uat_fld_port_chk_cb
,dnsserverlist_uats_tcp_port_set_cb,dnsserverlist_uats_tcp_port_tostr_cb
},{0,0,0},0,"Port Number (TCP)",((void*)0)}
,
3460 UAT_FLD_CSTRING_OTHER(dnsserverlist_uats, udp_port, "UDP Port", dnsserver_uat_fld_port_chk_cb, "Port Number (UDP)"){"udp_port", "UDP Port", PT_TXTMOD_STRING,{ dnsserver_uat_fld_port_chk_cb
,dnsserverlist_uats_udp_port_set_cb,dnsserverlist_uats_udp_port_tostr_cb
},{0,0,0},0,"Port Number (UDP)",((void*)0)}
,
3461 UAT_END_FIELDS{((void*)0),((void*)0),PT_TXTMOD_NONE,{0,0,0},{0,0,0},0,0,((void
*)0)}
3462 };
3463
3464 dnsserver_uat = uat_new("DNS Servers",
3465 sizeof(struct dns_server_data),
3466 "addr_resolve_dns_servers", /* filename */
3467 true1, /* from_profile */
3468 &dnsserverlist_uats, /* data_ptr */
3469 &ndnsservers, /* numitems_ptr */
3470 UAT_AFFECTS_DISSECTION0x00000001,
3471 NULL((void*)0),
3472 dns_server_copy_cb,
3473 NULL((void*)0),
3474 dns_server_free_cb,
3475 c_ares_set_dns_servers,
3476 NULL((void*)0),
3477 dns_server_uats_flds);
3478 static const char *dnsserver_uat_defaults[] = { NULL((void*)0), "53", "53" };
3479 uat_set_default_values(dnsserver_uat, dnsserver_uat_defaults);
3480 prefs_register_uat_preference(nameres, "dns_servers",
3481 "DNS Servers",
3482 "A table of IPv4 and IPv6 addresses of DNS servers to be used to resolve IP names and addresses",
3483 dnsserver_uat);
3484
3485 prefs_register_obsolete_preference(nameres, "concurrent_dns");
3486
3487 prefs_register_uint_preference(nameres, "name_resolve_concurrency",
3488 "Maximum concurrent requests",
3489 "The maximum number of DNS requests that may"
3490 " be active at any time. A large value (many"
3491 " thousands) might overload the network or make"
3492 " your DNS server behave badly.",
3493 10,
3494 &name_resolve_concurrency);
3495
3496 prefs_register_obsolete_preference(nameres, "hosts_file_handling");
3497
3498 prefs_register_bool_preference(nameres, "vlan_name",
3499 "Resolve VLAN IDs",
3500 "Resolve VLAN IDs to network names from the preferences \"vlans\" file."
3501 " Format of the file is: \"ID<Tab>Name\"."
3502 " One line per VLAN, e.g.: 1 Management",
3503 &gbl_resolv_flags.vlan_name);
3504
3505 prefs_register_bool_preference(nameres, "ss7_pc_name",
3506 "Resolve SS7 PCs",
3507 "Resolve SS7 Point Codes to node names from the profiles \"ss7pcs\" file."
3508 " Format of the file is: \"Network_Indicator<Dash>PC_Decimal<Tab>Name\"."
3509 " One line per Point Code, e.g.: 2-1234 MyPointCode1",
3510 &gbl_resolv_flags.ss7pc_name);
3511
3512 prefs_register_bool_preference(nameres, "tac_name",
3513 "Resolve TAC",
3514 "Resolve TAC to area names from the preferences \"tac\" file."
3515 " Format of the file is: \"TAC(decimail)<Tab/space>Name\"."
3516 " One line per TAC, e.g.: 30123 City1",
3517 &gbl_resolv_flags.tac_name);
3518
3519}
3520
3521void addr_resolve_pref_apply(void)
3522{
3523 c_ares_set_dns_servers();
3524 maxmind_db_pref_apply();
3525}
3526
3527void
3528disable_name_resolution(void) {
3529 gbl_resolv_flags.mac_name = false0;
3530 gbl_resolv_flags.network_name = false0;
3531 gbl_resolv_flags.transport_name = false0;
3532 gbl_resolv_flags.dns_pkt_addr_resolution = false0;
3533 gbl_resolv_flags.handshake_sni_addr_resolution = false0;
3534 gbl_resolv_flags.use_external_net_name_resolver = false0;
3535 gbl_resolv_flags.vlan_name = false0;
3536 gbl_resolv_flags.ss7pc_name = false0;
3537 gbl_resolv_flags.maxmind_geoip = false0;
3538 gbl_resolv_flags.tac_name = false0;
3539}
3540
3541bool_Bool
3542host_name_lookup_process(void) {
3543 struct timeval tv = { 0, 0 };
3544 int nfds;
3545 fd_set rfds, wfds;
3546 bool_Bool nro = new_resolved_objects;
3547
3548 new_resolved_objects = false0;
3549 nro |= maxmind_db_lookup_process();
3550
3551 if (!async_dns_initialized)
3552 /* c-ares not initialized. Bail out and cancel timers. */
3553 return nro;
3554
3555 process_async_dns_queue();
3556
3557 FD_ZERO(&rfds)do { unsigned int __i; fd_set *__arr = (&rfds); for (__i =
0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) ((__arr
)->__fds_bits)[__i] = 0; } while (0)
;
3558 FD_ZERO(&wfds)do { unsigned int __i; fd_set *__arr = (&wfds); for (__i =
0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) ((__arr
)->__fds_bits)[__i] = 0; } while (0)
;
3559 nfds = ares_fds(ghba_chan, &rfds, &wfds);
3560 if (nfds > 0) {
3561 if (select(nfds, &rfds, &wfds, NULL((void*)0), &tv) == -1) { /* call to select() failed */
3562 /* If it's interrupted by a signal, no need to put out a message */
3563 if (errno(*__errno_location ()) != EINTR4)
3564 fprintf(stderrstderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno(*__errno_location ())));
3565 return nro;
3566 }
3567 ares_process(ghba_chan, &rfds, &wfds);
3568 }
3569
3570 /* Any new entries? */
3571 return nro;
3572}
3573
3574static void
3575_host_name_lookup_cleanup(void) {
3576 async_dns_queue_head = NULL((void*)0);
3577
3578 if (async_dns_initialized) {
3579 ares_destroy(ghba_chan);
3580 ares_destroy(ghbn_chan);
3581 }
3582#ifdef CARES_HAVE_ARES_LIBRARY_INIT1
3583 ares_library_cleanup();
3584#endif
3585 async_dns_initialized = false0;
3586}
3587
3588const char *
3589get_hostname(const unsigned addr)
3590{
3591 /* XXX why do we call this if we're not resolving? To create hash entries?
3592 * Why? So that we can return a const char*?
3593 *
3594 * Note the returned string is in addr_resolv_scope, which has a similar
3595 * life to the global file scope (slightly larger, in that the resolved
3596 * addresses need to be available during dissector registration, e.g.
3597 * for RADIUS and enterprises), so if not copied it is possible to use
3598 * it after freeing.
3599 *
3600 * Should this be deprecated in favor of get_hostname_wmem so that
3601 * host name lookups don't increase persistent memory usage even when
3602 * hostname lookups are disabled? (An alternative would be to return
3603 * NULL when lookups are disabled, but callers don't expect that.)
3604 */
3605 hashipv4_t *tp = host_lookup(addr);
3606
3607 if (!gbl_resolv_flags.network_name)
3608 return tp->ip;
3609
3610 tp->flags |= RESOLVED_ADDRESS_USED(1U<<2);
3611
3612 return tp->name;
3613}
3614
3615char *
3616get_hostname_wmem(wmem_allocator_t *allocator, const unsigned addr)
3617{
3618 if (!gbl_resolv_flags.network_name)
3619 return ip_addr_to_str(allocator, &addr);
3620
3621 hashipv4_t *tp = host_lookup(addr);
3622
3623 tp->flags |= RESOLVED_ADDRESS_USED(1U<<2);
3624
3625 return wmem_strdup(allocator, tp->name);
3626}
3627/* -------------------------- */
3628
3629const char *
3630get_hostname6(const ws_in6_addr *addr)
3631{
3632 /* XXX why do we call this if we're not resolving? To create hash entries?
3633 * Why? The same comments as get_hostname above apply.
3634 */
3635 hashipv6_t *tp = host_lookup6(addr);
3636
3637 if (!gbl_resolv_flags.network_name)
3638 return tp->ip6;
3639
3640 tp->flags |= RESOLVED_ADDRESS_USED(1U<<2);
3641
3642 return tp->name;
3643}
3644
3645char *
3646get_hostname6_wmem(wmem_allocator_t *allocator, const ws_in6_addr *addr)
3647{
3648 if (!gbl_resolv_flags.network_name)
3649 return ip6_to_str(allocator, addr);
3650
3651 hashipv6_t *tp = host_lookup6(addr);
3652
3653 tp->flags |= RESOLVED_ADDRESS_USED(1U<<2);
3654
3655 return wmem_strdup(allocator, tp->name);
3656}
3657/* -------------------------- */
3658void
3659add_ipv4_name(const unsigned addr, const char *name, bool_Bool static_entry)
3660{
3661 hashipv4_t *tp;
3662
3663 /*
3664 * Don't add zero-length names; apparently, some resolvers will return
3665 * them if they get them from DNS.
3666 */
3667 if (!name || name[0] == '\0')
3668 return;
3669
3670 tp = (hashipv4_t *)wmem_map_lookup(ipv4_hash_table, GUINT_TO_POINTER(addr)((gpointer) (gulong) (addr)));
3671 if (!tp) {
3672 tp = new_ipv4(addr);
3673 wmem_map_insert(ipv4_hash_table, GUINT_TO_POINTER(addr)((gpointer) (gulong) (addr)), tp);
3674 }
3675
3676 if (g_ascii_strcasecmp(tp->name, name) && (static_entry || !(tp->flags & STATIC_HOSTNAME(1U<<3)))) {
3677 (void) g_strlcpy(tp->name, name, MAXDNSNAMELEN256);
3678 new_resolved_objects = true1;
3679 if (static_entry)
3680 tp->flags |= STATIC_HOSTNAME(1U<<3);
3681 }
3682 tp->flags |= TRIED_RESOLVE_ADDRESS(1U<<0)|NAME_RESOLVED(1U<<1);
3683} /* add_ipv4_name */
3684
3685/* -------------------------- */
3686void
3687add_ipv6_name(const ws_in6_addr *addrp, const char *name, const bool_Bool static_entry)
3688{
3689 hashipv6_t *tp;
3690
3691 /*
3692 * Don't add zero-length names; apparently, some resolvers will return
3693 * them if they get them from DNS.
3694 */
3695 if (!name || name[0] == '\0')
3696 return;
3697
3698 tp = (hashipv6_t *)wmem_map_lookup(ipv6_hash_table, addrp);
3699 if (!tp) {
3700 ws_in6_addr *addr_key;
3701
3702 addr_key = wmem_new(addr_resolv_scope, ws_in6_addr)((ws_in6_addr*)wmem_alloc((addr_resolv_scope), sizeof(ws_in6_addr
)))
;
3703 tp = new_ipv6(addrp);
3704 memcpy(addr_key, addrp, 16);
3705 wmem_map_insert(ipv6_hash_table, addr_key, tp);
3706 }
3707
3708 if (g_ascii_strcasecmp(tp->name, name) && (static_entry || !(tp->flags & STATIC_HOSTNAME(1U<<3)))) {
3709 (void) g_strlcpy(tp->name, name, MAXDNSNAMELEN256);
3710 new_resolved_objects = true1;
3711 if (static_entry)
3712 tp->flags |= STATIC_HOSTNAME(1U<<3);
3713 }
3714 tp->flags |= TRIED_RESOLVE_ADDRESS(1U<<0)|NAME_RESOLVED(1U<<1);
3715} /* add_ipv6_name */
3716
3717static void
3718add_manually_resolved_ipv4(void *key, void *value, void *user_data _U___attribute__((unused)))
3719{
3720 resolved_name_t *resolved_ipv4_entry = (resolved_name_t*)value;
3721 add_ipv4_name(GPOINTER_TO_UINT(key)((guint) (gulong) (key)), resolved_ipv4_entry->name, true1);
3722}
3723
3724static void
3725add_manually_resolved_ipv6(void *key, void *value, void *user_data _U___attribute__((unused)))
3726{
3727 resolved_name_t *resolved_ipv6_entry = (resolved_name_t*)value;
3728 add_ipv6_name((ws_in6_addr*)key, resolved_ipv6_entry->name, true1);
3729}
3730
3731static void
3732add_manually_resolved(void)
3733{
3734 if (manually_resolved_ipv4_list) {
3735 wmem_map_foreach(manually_resolved_ipv4_list, add_manually_resolved_ipv4, NULL((void*)0));
3736 }
3737
3738 if (manually_resolved_ipv6_list) {
3739 wmem_map_foreach(manually_resolved_ipv6_list, add_manually_resolved_ipv6, NULL((void*)0));
3740 }
3741}
3742
3743static void
3744host_name_lookup_init(const char* app_env_var_prefix)
3745{
3746 char *hostspath;
3747 unsigned i;
3748
3749 ws_assert(ipxnet_hash_table == NULL)do { if ((1) && !(ipxnet_hash_table == ((void*)0))) ws_log_fatal_full
("", LOG_LEVEL_ERROR, "epan/addr_resolv.c", 3749, __func__, "assertion failed: %s"
, "ipxnet_hash_table == ((void*)0)"); } while (0)
;
5
Assuming 'ipxnet_hash_table' is equal to null
6
Taking false branch
7
Loop condition is false. Exiting loop
3750 ipxnet_hash_table = wmem_map_new(addr_resolv_scope, g_direct_hash, g_direct_equal);
3751
3752 ws_assert(ipv4_hash_table == NULL)do { if ((1) && !(ipv4_hash_table == ((void*)0))) ws_log_fatal_full
("", LOG_LEVEL_ERROR, "epan/addr_resolv.c", 3752, __func__, "assertion failed: %s"
, "ipv4_hash_table == ((void*)0)"); } while (0)
;
8
Assuming 'ipv4_hash_table' is equal to null
9
Taking false branch
10
Loop condition is false. Exiting loop
3753 ipv4_hash_table = wmem_map_new(addr_resolv_scope, g_direct_hash, g_direct_equal);
3754
3755 ws_assert(ipv6_hash_table == NULL)do { if ((1) && !(ipv6_hash_table == ((void*)0))) ws_log_fatal_full
("", LOG_LEVEL_ERROR, "epan/addr_resolv.c", 3755, __func__, "assertion failed: %s"
, "ipv6_hash_table == ((void*)0)"); } while (0)
;
11
Assuming 'ipv6_hash_table' is equal to null
12
Taking false branch
13
Loop condition is false. Exiting loop
3756 ipv6_hash_table = wmem_map_new(addr_resolv_scope, ipv6_oat_hash, ipv6_equal);
3757
3758 ws_assert(async_dns_queue_head == NULL)do { if ((1) && !(async_dns_queue_head == ((void*)0))
) ws_log_fatal_full("", LOG_LEVEL_ERROR, "epan/addr_resolv.c"
, 3758, __func__, "assertion failed: %s", "async_dns_queue_head == ((void*)0)"
); } while (0)
;
14
Assuming 'async_dns_queue_head' is equal to null
15
Taking false branch
16
Loop condition is false. Exiting loop
3759 async_dns_queue_head = wmem_list_new(addr_resolv_scope);
3760
3761 /*
3762 * The manually resolved lists are the only address resolution maps
3763 * that are not reset by addr_resolv_cleanup(), because they are
3764 * the only ones that do not have entries from personal configuration
3765 * files that can change when changing configurations. All their
3766 * entries must also be in epan scope.
3767 */
3768 if (manually_resolved_ipv4_list == NULL((void*)0))
17
Assuming 'manually_resolved_ipv4_list' is not equal to NULL
18
Taking false branch
3769 manually_resolved_ipv4_list = wmem_map_new(wmem_epan_scope(), g_direct_hash, g_direct_equal);
3770
3771 if (manually_resolved_ipv6_list == NULL((void*)0))
19
Assuming 'manually_resolved_ipv6_list' is not equal to NULL
20
Taking false branch
3772 manually_resolved_ipv6_list = wmem_map_new(wmem_epan_scope(), ws_ipv6_hash, ipv6_equal);
3773
3774 /*
3775 * Load the global hosts file, if we have one.
3776 */
3777 hostspath = get_datafile_path(ENAME_HOSTS"hosts", app_env_var_prefix);
3778 if (!read_hosts_file(hostspath, true1) && errno(*__errno_location ()) != ENOENT2) {
21
Assuming the condition is false
22
Taking false branch
3779 report_open_failure(hostspath, errno(*__errno_location ()), false0);
3780 }
3781 g_free(hostspath);
3782 /*
3783 * Load the user's hosts file no matter what, if they have one.
3784 */
3785 hostspath = get_persconffile_path(ENAME_HOSTS"hosts", true1, app_env_var_prefix);
3786 if (!read_hosts_file(hostspath, true1) && errno(*__errno_location ()) != ENOENT2) {
23
Assuming the condition is false
24
Taking false branch
3787 report_open_failure(hostspath, errno(*__errno_location ()), false0);
3788 }
3789 g_free(hostspath);
3790#ifdef CARES_HAVE_ARES_LIBRARY_INIT1
3791 if (ares_library_init(ARES_LIB_INIT_ALL((1 << 0))) == ARES_SUCCESS) {
25
Assuming the condition is false
26
Taking false branch
3792#endif
3793 /* XXX - Check which options we should set */
3794 if (ares_init_options(&ghba_chan, NULL((void*)0), 0) == ARES_SUCCESS && ares_init_options(&ghbn_chan, NULL((void*)0), 0) == ARES_SUCCESS) {
3795 async_dns_initialized = true1;
3796 c_ares_set_dns_servers();
3797 }
3798#ifdef CARES_HAVE_ARES_LIBRARY_INIT1
3799 }
3800#endif
3801
3802 if (extra_hosts_files) {
27
Assuming 'extra_hosts_files' is null
28
Taking false branch
3803 for (i = 0; i < extra_hosts_files->len; i++) {
3804 read_hosts_file((const char *) g_ptr_array_index(extra_hosts_files, i)((extra_hosts_files)->pdata)[i], true1);
3805 }
3806 }
3807
3808 subnet_name_lookup_init(app_env_var_prefix);
3809
3810 add_manually_resolved();
3811
3812 ss7pc_name_lookup_init(app_env_var_prefix);
29
Calling 'ss7pc_name_lookup_init'
3813}
3814
3815static void
3816host_name_lookup_cleanup(void)
3817{
3818 uint32_t i, j;
3819 sub_net_hashipv4_t *entry, *next_entry;
3820
3821 _host_name_lookup_cleanup();
3822
3823 ipxnet_hash_table = NULL((void*)0);
3824 ipv4_hash_table = NULL((void*)0);
3825 ipv6_hash_table = NULL((void*)0);
3826 ss7pc_hash_table = NULL((void*)0);
3827
3828 for(i = 0; i < SUBNETLENGTHSIZE32; ++i) {
3829 if (subnet_length_entries[i].subnet_addresses != NULL((void*)0)) {
3830 for (j = 0; j < HASHHOSTSIZE2048; j++) {
3831 for (entry = subnet_length_entries[i].subnet_addresses[j];
3832 entry != NULL((void*)0); entry = next_entry) {
3833 next_entry = entry->next;
3834 wmem_free(addr_resolv_scope, entry);
3835 }
3836 }
3837 wmem_free(addr_resolv_scope, subnet_length_entries[i].subnet_addresses);
3838 subnet_length_entries[i].subnet_addresses = NULL((void*)0);
3839 }
3840 }
3841
3842 have_subnet_entry = false0;
3843 new_resolved_objects = false0;
3844}
3845
3846
3847void host_name_lookup_reset(const char* app_env_var_prefix)
3848{
3849 addr_resolv_cleanup();
3850 addr_resolv_init(app_env_var_prefix);
1
Calling 'addr_resolv_init'
3851}
3852
3853char *
3854udp_port_to_display(wmem_allocator_t *allocator, unsigned port)
3855{
3856
3857 if (!gbl_resolv_flags.transport_name) {
3858 return wmem_utoa(allocator, port);
3859 }
3860
3861 return wmem_strdup(allocator, serv_name_lookup(PT_UDP, port));
3862
3863} /* udp_port_to_display */
3864
3865char *
3866dccp_port_to_display(wmem_allocator_t *allocator, unsigned port)
3867{
3868
3869 if (!gbl_resolv_flags.transport_name) {
3870 return wmem_utoa(allocator, port);
3871 }
3872
3873 return wmem_strdup(allocator, serv_name_lookup(PT_DCCP, port));
3874
3875} /* dccp_port_to_display */
3876
3877char *
3878tcp_port_to_display(wmem_allocator_t *allocator, unsigned port)
3879{
3880
3881 if (!gbl_resolv_flags.transport_name) {
3882 return wmem_utoa(allocator, port);
3883 }
3884
3885 return wmem_strdup(allocator, serv_name_lookup(PT_TCP, port));
3886
3887} /* tcp_port_to_display */
3888
3889char *
3890sctp_port_to_display(wmem_allocator_t *allocator, unsigned port)
3891{
3892
3893 if (!gbl_resolv_flags.transport_name) {
3894 return wmem_utoa(allocator, port);
3895 }
3896
3897 return wmem_strdup(allocator, serv_name_lookup(PT_SCTP, port));
3898
3899} /* sctp_port_to_display */
3900
3901char *
3902port_with_resolution_to_str(wmem_allocator_t *scope, port_type proto, unsigned port)
3903{
3904 const char *port_str;
3905
3906 if (!gbl_resolv_flags.transport_name || (proto == PT_NONE)) {
3907 /* No name resolution support, just return port string */
3908 return wmem_strdup_printf(scope, "%u", port);
3909 }
3910 port_str = serv_name_lookup(proto, port);
3911 ws_assert(port_str)do { if ((1) && !(port_str)) ws_log_fatal_full("", LOG_LEVEL_ERROR
, "epan/addr_resolv.c", 3911, __func__, "assertion failed: %s"
, "port_str"); } while (0)
;
3912 return wmem_strdup_printf(scope, "%s (%u)", port_str, port);
3913}
3914
3915int
3916port_with_resolution_to_str_buf(char *buf, unsigned long buf_size, port_type proto, unsigned port)
3917{
3918 const char *port_str;
3919
3920 if (!gbl_resolv_flags.transport_name || (proto == PT_NONE)) {
3921 /* No name resolution support, just return port string */
3922 return snprintf(buf, buf_size, "%u", port);
3923 }
3924 port_str = serv_name_lookup(proto, port);
3925 ws_assert(port_str)do { if ((1) && !(port_str)) ws_log_fatal_full("", LOG_LEVEL_ERROR
, "epan/addr_resolv.c", 3925, __func__, "assertion failed: %s"
, "port_str"); } while (0)
;
3926 return snprintf(buf, buf_size, "%s (%u)", port_str, port);
3927}
3928
3929const char *
3930get_ether_name(const uint8_t *addr)
3931{
3932 hashether_t *tp;
3933 bool_Bool resolve = gbl_resolv_flags.mac_name;
3934
3935 tp = eth_name_lookup(addr, resolve);
3936
3937 return resolve ? tp->resolved_name : tp->hexaddr;
3938
3939} /* get_ether_name */
3940
3941const char *
3942tvb_get_ether_name(tvbuff_t *tvb, unsigned offset)
3943{
3944 return get_ether_name(tvb_get_ptr(tvb, offset, 6));
3945}
3946
3947/* Look for a (non-dummy) ether name in the hash, and return it if found.
3948 * If it's not found, simply return NULL.
3949 */
3950const char *
3951get_ether_name_if_known(const uint8_t *addr)
3952{
3953 hashether_t *tp;
3954
3955 /* Initialize ether structs if we're the first
3956 * ether-related function called */
3957 if (!gbl_resolv_flags.mac_name)
3958 return NULL((void*)0);
3959
3960 /* eth_name_lookup will create a (resolved) hash entry
3961 * if it doesn't exist, so it never returns NULL */
3962 tp = eth_name_lookup(addr, true1);
3963
3964 if ((tp->flags & (NAME_RESOLVED(1U<<1) | NAME_RESOLVED_PREFIX(1U<<4))) == NAME_RESOLVED(1U<<1)) {
3965 /* Name is from an exact match, not a prefix/OUI */
3966 return tp->resolved_name;
3967 }
3968 else {
3969 /* Name was created */
3970 return NULL((void*)0);
3971 }
3972}
3973
3974void
3975add_ether_byip(const unsigned ip, const uint8_t *eth)
3976{
3977 hashipv4_t *tp;
3978
3979 /* first check that IP address can be resolved */
3980 if (!gbl_resolv_flags.network_name)
3981 return;
3982
3983 tp = host_lookup(ip);
3984
3985 /*
3986 * Was this IP address resolved to a host name?
3987 */
3988 if (tp->flags & NAME_RESOLVED(1U<<1)) {
3989 /*
3990 * Yes, so add an entry in the ethers hashtable resolving
3991 * the MAC address to that name.
3992 */
3993 add_eth_name(eth, tp->name, false0);
3994 }
3995
3996} /* add_ether_byip */
3997
3998char *
3999get_ipxnet_name(wmem_allocator_t *allocator, const uint32_t addr)
4000{
4001
4002 if (!gbl_resolv_flags.network_name) {
4003 return ipxnet_to_str_punct(allocator, addr, '\0');
4004 }
4005
4006 return ipxnet_name_lookup(allocator, addr);
4007
4008} /* get_ipxnet_name */
4009
4010char *
4011get_vlan_name(wmem_allocator_t *allocator, const uint16_t id)
4012{
4013
4014 if (!gbl_resolv_flags.vlan_name) {
4015 return NULL((void*)0);
4016 }
4017
4018 return wmem_strdup(allocator, vlan_name_lookup(id));
4019
4020} /* get_vlan_name */
4021
4022const char *
4023get_manuf_name(const uint8_t *addr, size_t size)
4024{
4025 hashmanuf_t *manuf_value;
4026
4027 ws_return_val_if(size < 3, NULL)do { if (1 && (size < 3)) { ws_log_full("InvalidArg"
, LOG_LEVEL_WARNING, "epan/addr_resolv.c", 4027, __func__, "invalid argument: %s"
, "size < 3"); return (((void*)0)); } } while (0)
;
4028
4029 manuf_value = manuf_name_lookup(addr, size);
4030 if (gbl_resolv_flags.mac_name && ((manuf_value->flags & NAME_RESOLVED(1U<<1)) == NAME_RESOLVED(1U<<1)))
4031 return manuf_value->resolved_name;
4032
4033 return manuf_value->hexaddr;
4034
4035} /* get_manuf_name */
4036
4037const char *
4038tvb_get_manuf_name(tvbuff_t *tvb, unsigned offset)
4039{
4040 uint8_t buf[3] = { 0 };
4041 tvb_memcpy(tvb, buf, offset, 3);
4042 return get_manuf_name(buf, sizeof(buf));
4043}
4044
4045const char *
4046get_manuf_name_if_known(const uint8_t *addr, size_t size)
4047{
4048 hashmanuf_t *manuf_value;
4049
4050 ws_return_val_if(size < 3, NULL)do { if (1 && (size < 3)) { ws_log_full("InvalidArg"
, LOG_LEVEL_WARNING, "epan/addr_resolv.c", 4050, __func__, "invalid argument: %s"
, "size < 3"); return (((void*)0)); } } while (0)
;
4051
4052 manuf_value = manuf_name_lookup(addr, size);
4053 if (manuf_value != NULL((void*)0) && ((manuf_value->flags & NAME_RESOLVED(1U<<1)) == NAME_RESOLVED(1U<<1))) {
4054 return manuf_value->resolved_longname;
4055 }
4056
4057 if (size >= 6) {
4058 /* Try the global manuf tables. */
4059 const char *short_name, *long_name;
4060 short_name = ws_manuf_lookup_str(addr, &long_name);
4061 if (short_name != NULL((void*)0)) {
4062 /* Found it */
4063 return long_name;
4064 }
4065 }
4066
4067 return NULL((void*)0);
4068
4069} /* get_manuf_name_if_known */
4070
4071const char *
4072uint_get_manuf_name_if_known(const uint32_t manuf_key)
4073{
4074 uint8_t addr[6] = { 0 };
4075 addr[0] = (manuf_key >> 16) & 0xFF;
4076 addr[1] = (manuf_key >> 8) & 0xFF;
4077 addr[2] = manuf_key & 0xFF;
4078
4079 return get_manuf_name_if_known(addr, sizeof(addr));
4080}
4081
4082const char *
4083tvb_get_manuf_name_if_known(tvbuff_t *tvb, unsigned offset)
4084{
4085 uint8_t buf[3] = { 0 };
4086 tvb_memcpy(tvb, buf, offset, 3);
4087 return get_manuf_name_if_known(buf, sizeof(buf));
4088}
4089
4090bool_Bool get_hash_manuf_used(hashmanuf_t* manuf)
4091{
4092 return ((manuf->flags & TRIED_OR_RESOLVED_MASK((1U<<0) | (1U<<1))) == TRIED_OR_RESOLVED_MASK((1U<<0) | (1U<<1)));
4093}
4094
4095char* get_hash_manuf_resolved_name(hashmanuf_t* manuf)
4096{
4097 return manuf->resolved_longname;
4098}
4099
4100const char *
4101get_eui64_name(const uint8_t *addr)
4102{
4103 hasheui64_t *tp;
4104 bool_Bool resolve = gbl_resolv_flags.mac_name;
4105
4106 tp = eui64_name_lookup(addr, resolve);
4107
4108 return resolve ? tp->resolved_name : tp->hexaddr;
4109
4110} /* get_eui64_name */
4111
4112char *
4113eui64_to_display(wmem_allocator_t *allocator, const uint64_t addr_eui64)
4114{
4115 uint8_t addr[EUI64_ADDR_LEN8];
4116
4117 phtonu64(addr, addr_eui64);
4118
4119 const char *result = get_eui64_name(addr);
4120
4121 return wmem_strdup(allocator, result);
4122} /* eui64_to_display */
4123
4124#define GHI_TIMEOUT(250 * 1000) (250 * 1000)
4125static void
4126c_ares_ghi_cb(void *arg, int status, int timeouts _U___attribute__((unused)), struct hostent *hp) {
4127 /*
4128 * XXX - If we wanted to be really fancy we could cache results here and
4129 * look them up in get_host_ipaddr* below.
4130 *
4131 * XXX - This only gets the first host address if there's more than one.
4132 */
4133 async_hostent_t *ahp = (async_hostent_t *)arg;
4134 if (status == ARES_SUCCESS && hp && ahp && hp->h_length == ahp->addr_size) {
4135 memcpy(ahp->addrp, hp->h_addrh_addr_list[0], hp->h_length);
4136 ahp->copied = hp->h_length;
4137 }
4138}
4139
4140/* Translate a string, assumed either to be a dotted-quad IPv4 address or
4141 * a host name, to a numeric IPv4 address. Return true if we succeed and
4142 * set "*addrp" to that numeric IPv4 address; return false if we fail. */
4143bool_Bool
4144get_host_ipaddr(const char *host, uint32_t *addrp)
4145{
4146 struct timeval tv = { 0, GHI_TIMEOUT(250 * 1000) }, *tvp;
4147 int nfds;
4148 fd_set rfds, wfds;
4149 async_hostent_t ahe;
4150
4151 /*
4152 * XXX - are there places where this is used to translate something
4153 * that's *only* supposed to be an IPv4 address, and where it
4154 * *shouldn't* translate host names?
4155 */
4156 if (!ws_inet_pton4(host, addrp)) {
4157
4158 /* It's not a valid dotted-quad IP address; is it a valid
4159 * host name?
4160 */
4161
4162 /* If we're not allowed to do name resolution, don't do name
4163 * resolution...
4164 * XXX - What if we're allowed to do name resolution, and the name
4165 * is in a DNS packet we've dissected or in a Name Resolution Block,
4166 * or a user-entered manual name resolution?
4167 */
4168 if (!gbl_resolv_flags.network_name ||
4169 !gbl_resolv_flags.use_external_net_name_resolver) {
4170 return false0;
4171 }
4172
4173 if (!async_dns_initialized || name_resolve_concurrency < 1) {
4174 return false0;
4175 }
4176 ahe.addr_size = (int) sizeof (struct in_addr);
4177 ahe.copied = 0;
4178 ahe.addrp = addrp;
4179 ares_gethostbyname(ghbn_chan, host, AF_INET2, c_ares_ghi_cb, &ahe);
4180 FD_ZERO(&rfds)do { unsigned int __i; fd_set *__arr = (&rfds); for (__i =
0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) ((__arr
)->__fds_bits)[__i] = 0; } while (0)
;
4181 FD_ZERO(&wfds)do { unsigned int __i; fd_set *__arr = (&wfds); for (__i =
0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) ((__arr
)->__fds_bits)[__i] = 0; } while (0)
;
4182 nfds = ares_fds(ghbn_chan, &rfds, &wfds);
4183 if (nfds > 0) {
4184 tvp = ares_timeout(ghbn_chan, &tv, &tv);
4185 if (select(nfds, &rfds, &wfds, NULL((void*)0), tvp) == -1) { /* call to select() failed */
4186 /* If it's interrupted by a signal, no need to put out a message */
4187 if (errno(*__errno_location ()) != EINTR4)
4188 fprintf(stderrstderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno(*__errno_location ())));
4189 return false0;
4190 }
4191 ares_process(ghbn_chan, &rfds, &wfds);
4192 }
4193 ares_cancel(ghbn_chan);
4194 if (ahe.addr_size == ahe.copied) {
4195 return true1;
4196 }
4197 return false0;
4198 }
4199
4200 return true1;
4201}
4202
4203/*
4204 * Translate IPv6 numeric address or FQDN hostname into binary IPv6 address.
4205 * Return true if we succeed and set "*addrp" to that numeric IPv6 address;
4206 * return false if we fail.
4207 */
4208bool_Bool
4209get_host_ipaddr6(const char *host, ws_in6_addr *addrp)
4210{
4211 struct timeval tv = { 0, GHI_TIMEOUT(250 * 1000) }, *tvp;
4212 int nfds;
4213 fd_set rfds, wfds;
4214 async_hostent_t ahe;
4215
4216 if (str_to_ip6(host, addrp))
4217 return true1;
4218
4219 /* It's not a valid dotted-quad IP address; is it a valid
4220 * host name?
4221 *
4222 * XXX - are there places where this is used to translate something
4223 * that's *only* supposed to be an IPv6 address, and where it
4224 * *shouldn't* translate host names?
4225 */
4226
4227 /* If we're not allowed to do name resolution, don't do name
4228 * resolution...
4229 * XXX - What if we're allowed to do name resolution, and the name
4230 * is in a DNS packet we've dissected or in a Name Resolution Block,
4231 * or a user-entered manual name resolution?
4232 */
4233 if (!gbl_resolv_flags.network_name ||
4234 !gbl_resolv_flags.use_external_net_name_resolver) {
4235 return false0;
4236 }
4237
4238 /* try FQDN */
4239 if (!async_dns_initialized || name_resolve_concurrency < 1) {
4240 return false0;
4241 }
4242 ahe.addr_size = (int) sizeof (ws_in6_addr);
4243 ahe.copied = 0;
4244 ahe.addrp = addrp;
4245 ares_gethostbyname(ghbn_chan, host, AF_INET610, c_ares_ghi_cb, &ahe);
4246 FD_ZERO(&rfds)do { unsigned int __i; fd_set *__arr = (&rfds); for (__i =
0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) ((__arr
)->__fds_bits)[__i] = 0; } while (0)
;
4247 FD_ZERO(&wfds)do { unsigned int __i; fd_set *__arr = (&wfds); for (__i =
0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) ((__arr
)->__fds_bits)[__i] = 0; } while (0)
;
4248 nfds = ares_fds(ghbn_chan, &rfds, &wfds);
4249 if (nfds > 0) {
4250 tvp = ares_timeout(ghbn_chan, &tv, &tv);
4251 if (select(nfds, &rfds, &wfds, NULL((void*)0), tvp) == -1) { /* call to select() failed */
4252 /* If it's interrupted by a signal, no need to put out a message */
4253 if (errno(*__errno_location ()) != EINTR4)
4254 fprintf(stderrstderr, "Warning: call to select() failed, error is %s\n", g_strerror(errno(*__errno_location ())));
4255 return false0;
4256 }
4257 ares_process(ghbn_chan, &rfds, &wfds);
4258 }
4259 ares_cancel(ghbn_chan);
4260 if (ahe.addr_size == ahe.copied) {
4261 return true1;
4262 }
4263
4264 return false0;
4265}
4266
4267wmem_map_t *
4268get_manuf_hashtable(void)
4269{
4270 return manuf_hashtable;
4271}
4272
4273wmem_map_t *
4274get_wka_hashtable(void)
4275{
4276 return wka_hashtable;
4277}
4278
4279wmem_map_t *
4280get_eth_hashtable(void)
4281{
4282 return eth_hashtable;
4283}
4284
4285wmem_map_t *
4286get_serv_port_hashtable(void)
4287{
4288 return serv_port_hashtable;
4289}
4290
4291wmem_map_t *
4292get_ipxnet_hash_table(void)
4293{
4294 return ipxnet_hash_table;
4295}
4296
4297wmem_map_t *
4298get_vlan_hash_table(void)
4299{
4300 return vlan_hash_table;
4301}
4302
4303wmem_map_t *
4304get_ipv4_hash_table(void)
4305{
4306 return ipv4_hash_table;
4307}
4308
4309wmem_map_t *
4310get_ipv6_hash_table(void)
4311{
4312 return ipv6_hash_table;
4313}
4314/* Initialize all the address resolution subsystems in this file */
4315void
4316addr_resolv_init(const char* app_env_var_prefix)
4317{
4318 ws_assert(addr_resolv_scope == NULL)do { if ((1) && !(addr_resolv_scope == ((void*)0))) ws_log_fatal_full
("", LOG_LEVEL_ERROR, "epan/addr_resolv.c", 4318, __func__, "assertion failed: %s"
, "addr_resolv_scope == ((void*)0)"); } while (0)
;
2
Taking false branch
3
Loop condition is false. Exiting loop
4319 addr_resolv_scope = wmem_allocator_new(WMEM_ALLOCATOR_BLOCK);
4320 initialize_services(app_env_var_prefix);
4321 initialize_ethers(app_env_var_prefix);
4322 initialize_ipxnets(app_env_var_prefix);
4323 initialize_vlans(app_env_var_prefix);
4324 initialize_enterprises(app_env_var_prefix);
4325 host_name_lookup_init(app_env_var_prefix);
4
Calling 'host_name_lookup_init'
4326 initialize_tacs(app_env_var_prefix);
4327}
4328
4329/* Clean up all the address resolution subsystems in this file */
4330void
4331addr_resolv_cleanup(void)
4332{
4333 vlan_name_lookup_cleanup();
4334 service_name_lookup_cleanup();
4335 ethers_cleanup();
4336 ipx_name_lookup_cleanup();
4337 enterprises_cleanup();
4338 host_name_lookup_cleanup();
4339 tac_name_lookup_cleanup();
4340
4341 wmem_destroy_allocator(addr_resolv_scope);
4342 addr_resolv_scope = NULL((void*)0);
4343}
4344
4345bool_Bool
4346str_to_ip(const char *str, void *dst)
4347{
4348 return ws_inet_pton4(str, (uint32_t *)dst);
4349}
4350
4351bool_Bool
4352str_to_ip6(const char *str, void *dst)
4353{
4354 return ws_inet_pton6(str, (ws_in6_addr *)dst);
4355}
4356
4357/*
4358 * convert a 0-terminated string that contains an ethernet address into
4359 * the corresponding sequence of 6 bytes
4360 * eth_bytes is a buffer >= 6 bytes that was allocated by the caller
4361 */
4362bool_Bool
4363str_to_eth(const char *str, uint8_t (*eth_bytes)[6])
4364{
4365 ether_t eth;
4366 unsigned mask;
4367
4368 if (!parse_ether_address(str, &eth, &mask, false0))
4369 return false0;
4370
4371 if (mask == 48) {
4372 memcpy(eth_bytes, eth.addr, 6);
4373 }
4374 return true1;
4375}
4376
4377/*
4378 * Editor modelines - https://www.wireshark.org/tools/modelines.html
4379 *
4380 * Local variables:
4381 * c-basic-offset: 4
4382 * tab-width: 8
4383 * indent-tabs-mode: nil
4384 * End:
4385 *
4386 * vi: set shiftwidth=4 tabstop=8 expandtab:
4387 * :indentSize=4:tabSize=8:noTabs=true:
4388 */