Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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