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