Bug Summary

File:builds/wireshark/wireshark/epan/addr_resolv.c
Warning:line 774, column 9
Value of 'errno' was not checked and may be overwritten by function 'fgets'

Annotated Source Code

Press '?' to see keyboard shortcuts

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