Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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