Bug Summary

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