2 * Routines for network object lookup
6 * Laurent Deniel <laurent.deniel@free.fr>
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
36 * Win32 doesn't have SIGALRM (and it's the OS where name lookup calls
37 * are most likely to take a long time, given the way address-to-name
38 * lookups are done over NBNS).
40 * Mac OS X does have SIGALRM, but if you longjmp() out of a name resolution
41 * call in a signal handler, you might crash, because the state of the
42 * resolution code that sends messages to lookupd might be inconsistent
43 * if you jump out of it in middle of a call.
45 * In at least some Linux distributions (e.g., RedHat Linux 9), if ADNS
46 * is used, we appear to hang in host_name_lookup6() in a gethostbyaddr()
47 * call (and possibly in other gethostbyaddr() calls), because there's
48 * a mutex lock held in gethostbyaddr() and it doesn't get released
49 * if we longjmp out of it.
51 * There's no guarantee that longjmp()ing out of name resolution calls
52 * will work on *any* platform; OpenBSD got rid of the alarm/longjmp
53 * code in tcpdump, to avoid those sorts of problems, and that was
54 * picked up by tcpdump.org tcpdump.
56 * So, for now, we do not define AVOID_DNS_TIMEOUT. If we get a
57 * significantly more complaints about lookups taking a long time,
58 * we can reconsider that decision. (Note that tcpdump originally
59 * added that for the benefit of systems using NIS to look up host
60 * names; that might now be fixed in NIS implementations, for those
61 * sites still using NIS rather than DNS for that....)
68 #ifdef HAVE_NETINET_IN_H
69 # include <netinet/in.h>
76 #ifdef HAVE_ARPA_INET_H
77 #include <arpa/inet.h>
82 #ifdef HAVE_SYS_SOCKET_H
83 #include <sys/socket.h> /* needed to define AF_ values on UNIX */
86 #ifdef HAVE_WINSOCK2_H
87 #include <winsock2.h> /* needed to define AF_ values on Windows */
90 #ifndef HAVE_INET_ATON_H
91 # include "wsutil/inet_aton.h"
94 #ifdef NEED_INET_V6DEFS_H
95 # include "wsutil/inet_v6defs.h"
98 #if defined(_WIN32) && defined(INET6)
99 # include <ws2tcpip.h>
103 # if defined(_WIN32) && !defined(INET6)
104 # define socklen_t unsigned int
107 # include <ares_version.h>
109 # ifdef HAVE_GNU_ADNS
112 # if defined(inet_aton) && defined(_WIN32)
115 # endif /* HAVE_GNU_ADNS */
116 #endif /* HAVE_C_ARES */
122 #include "addr_and_mask.h"
123 #include "ipv6-utils.h"
124 #include "addr_resolv.h"
125 #include "filesystem.h"
127 #include <wsutil/report_err.h>
128 #include <wsutil/file_util.h>
129 #include <wsutil/pint.h>
131 #include <epan/strutil.h>
132 #include <epan/prefs.h>
133 #include <epan/emem.h>
135 #define ENAME_HOSTS "hosts"
136 #define ENAME_SUBNETS "subnets"
137 #define ENAME_ETHERS "ethers"
138 #define ENAME_IPXNETS "ipxnets"
139 #define ENAME_MANUF "manuf"
140 #define ENAME_SERVICES "services"
142 #define HASHETHSIZE 2048
143 #define HASHHOSTSIZE 2048
144 #define HASHIPXNETSIZE 256
145 #define SUBNETLENGTHSIZE 32 /*1-32 inc.*/
147 /* g_int64_hash() and g_int64_equal() first appear in GLib 2.22, make a local copy here */
148 #if !GLIB_CHECK_VERSION(2,22,0)
151 * @v1: a pointer to a #gint64 key
152 * @v2: a pointer to a #gint64 key to compare with @v1
154 * Compares the two #gint64 values being pointed to and returns
155 * %TRUE if they are equal.
156 * It can be passed to g_hash_table_new() as the @key_equal_func
157 * parameter, when using non-%NULL pointers to 64-bit integers as keys in a
160 * Returns: %TRUE if the two keys match.
165 g_int64_equal (gconstpointer v1
,
168 return *((const gint64
*) v1
) == *((const gint64
*) v2
);
173 * @v: a pointer to a #gint64 key
175 * Converts a pointer to a #gint64 to a hash value.
177 * It can be passed to g_hash_table_new() as the @hash_func parameter,
178 * when using non-%NULL pointers to 64-bit integer values as keys in a
181 * Returns: a hash value corresponding to the key.
186 g_int64_hash (gconstpointer v
)
188 return (guint
) *(const gint64
*) v
;
191 #endif /* GLIB_CHECK_VERSION(2,22,0) */
192 /* hash table used for IPv4 lookup */
194 #define HASH_IPV4_ADDRESS(addr) (g_htonl(addr) & (HASHHOSTSIZE - 1))
197 typedef struct sub_net_hashipv4
{
199 guint8 flags
; /* B0 dummy_entry, B1 resolve, B2 If the address is used in the trace */
200 struct sub_net_hashipv4
*next
;
202 gchar name
[MAXNAMELEN
];
203 } sub_net_hashipv4_t
;
205 /* Array of entries of subnets of different lengths */
207 gsize mask_length
; /*1-32*/
208 guint32 mask
; /* e.g. 255.255.255.*/
209 sub_net_hashipv4_t
** subnet_addresses
; /* Hash table of subnet addresses */
210 } subnet_length_entry_t
;
214 typedef struct serv_port
{
221 /* hash table used for IPX network lookup */
223 /* XXX - check goodness of hash function */
225 #define HASH_IPX_NET(net) ((net) & (HASHIPXNETSIZE - 1))
227 typedef struct hashipxnet
{
229 struct hashipxnet
*next
;
230 gchar name
[MAXNAMELEN
];
233 /* hash tables used for ethernet and manufacturer lookup */
234 #define HASHETHER_STATUS_UNRESOLVED 1
235 #define HASHETHER_STATUS_RESOLVED_DUMMY 2
236 #define HASHETHER_STATUS_RESOLVED_NAME 3
239 typedef struct hashether
{
240 struct hashether
*next
;
241 guint status
; /* (See above) */
244 char resolved_name
[MAXNAMELEN
];
247 /* internal ethernet type */
249 typedef struct _ether
252 char name
[MAXNAMELEN
];
255 /* internal ipxnet type */
257 typedef struct _ipxnet
260 char name
[MAXNAMELEN
];
263 static GHashTable
*ipxnet_hash_table
= NULL
;
264 static GHashTable
*ipv4_hash_table
= NULL
;
265 static GHashTable
*ipv6_hash_table
= NULL
;
267 static GSList
*manually_resolved_ipv4_list
= NULL
;
268 static GSList
*manually_resolved_ipv6_list
= NULL
;
270 typedef struct _resolved_ipv4
273 char name
[MAXNAMELEN
];
276 typedef struct _resolved_ipv6
278 struct e_in6_addr ip6_addr
;
279 char name
[MAXNAMELEN
];
282 static addrinfo_lists_t addrinfo_lists
= { NULL
, NULL
};
284 static gchar
*cb_service
;
285 static port_type cb_proto
= PT_NONE
;
288 static GHashTable
*manuf_hashtable
= NULL
;
289 static GHashTable
*wka_hashtable
= NULL
;
290 static GHashTable
*eth_hashtable
= NULL
;
291 static GHashTable
*serv_port_hashtable
= NULL
;
293 static subnet_length_entry_t subnet_length_entries
[SUBNETLENGTHSIZE
]; /* Ordered array of entries */
294 static gboolean have_subnet_entry
= FALSE
;
296 static gboolean new_resolved_objects
= FALSE
;
298 static GPtrArray
* extra_hosts_files
= NULL
;
300 static hashether_t
*add_eth_name(const guint8
*addr
, const gchar
*name
);
301 static void add_serv_port_cb(const guint32 port
);
304 /* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx#existing
308 ipv6_oat_hash(gconstpointer key
)
311 const unsigned char *p
= (const unsigned char *)key
;
315 for ( i
= 0; i
< len
; i
++ ) {
329 ipv6_equal(gconstpointer v1
, gconstpointer v2
)
332 if( memcmp(v1
, v2
, sizeof (struct e_in6_addr
)) == 0 ) {
340 * Flag controlling what names to resolve.
342 e_addr_resolve gbl_resolv_flags
= {TRUE
, FALSE
, TRUE
, TRUE
, TRUE
, FALSE
};
343 #if defined(HAVE_C_ARES) || defined(HAVE_GNU_ADNS)
344 static guint name_resolve_concurrency
= 500;
348 * Global variables (can be changed in GUI sections)
349 * XXX - they could be changed in GUI code, but there's currently no
350 * GUI code to change them.
353 gchar
*g_ethers_path
= NULL
; /* global ethers file */
354 gchar
*g_pethers_path
= NULL
; /* personal ethers file */
355 gchar
*g_ipxnets_path
= NULL
; /* global ipxnets file */
356 gchar
*g_pipxnets_path
= NULL
; /* personal ipxnets file */
357 gchar
*g_services_path
= NULL
; /* global services file */
358 gchar
*g_pservices_path
= NULL
; /* personal services file */
359 /* first resolving call */
364 * Submitted queries trigger a callback (c_ares_ghba_cb()).
365 * Queries are added to c_ares_queue_head. During processing, queries are
366 * popped off the front of c_ares_queue_head and submitted using
367 * ares_gethostbyaddr().
368 * The callback processes the response, then frees the request.
371 typedef struct _async_dns_queue_msg
375 struct e_in6_addr ip6
;
378 } async_dns_queue_msg_t
;
380 typedef struct _async_hostent
{
386 #if ( ( ARES_VERSION_MAJOR < 1 ) \
387 || ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
388 static void c_ares_ghba_cb(void *arg
, int status
, struct hostent
*hostent
);
390 static void c_ares_ghba_cb(void *arg
, int status
, int timeouts _U_
, struct hostent
*hostent
);
393 ares_channel ghba_chan
; /* ares_gethostbyaddr -- Usually non-interactive, no timeout */
394 ares_channel ghbn_chan
; /* ares_gethostbyname -- Usually interactive, timeout */
401 * Submitted queries have to be checked individually using adns_check().
402 * Queries are added to adns_queue_head. During processing, the list is
403 * iterated twice: once to request queries up to the concurrency limit,
404 * and once to check the status of each query.
409 typedef struct _async_dns_queue_msg
415 } async_dns_queue_msg_t
;
417 #endif /* HAVE_GNU_ADNS */
418 #endif /* HAVE_C_ARES */
420 static gboolean async_dns_initialized
= FALSE
;
421 static guint async_dns_in_flight
= 0;
422 static GList
*async_dns_queue_head
= NULL
;
424 /* push a dns request */
426 add_async_dns_ipv4(int type
, guint32 addr
)
428 async_dns_queue_msg_t
*msg
;
430 msg
= g_new(async_dns_queue_msg_t
,1);
433 msg
->addr
.ip4
= addr
;
436 msg
->ip4_addr
= addr
;
437 msg
->submitted
= FALSE
;
439 async_dns_queue_head
= g_list_append(async_dns_queue_head
, (gpointer
) msg
);
447 const gchar
* name
; /* Shallow copy */
451 * Miscellaneous functions
455 fgetline(char **buf
, int *size
, FILE *fp
)
460 if (fp
== NULL
|| buf
== NULL
)
467 *buf
= (char *)g_malloc(*size
);
477 while ((c
= getc(fp
)) != EOF
&& c
!= '\r' && c
!= '\n') {
478 if (len
+1 >= *size
) {
479 *buf
= (char *)g_realloc(*buf
, *size
+= BUFSIZ
);
484 if (len
== 0 && c
== EOF
)
495 * Local function definitions
497 static subnet_entry_t
subnet_lookup(const guint32 addr
);
498 static void subnet_entry_set(guint32 subnet_addr
, const guint32 mask_length
, const gchar
* name
);
502 add_service_name(port_type proto
, const guint port
, const char *service_name
)
504 serv_port_t
*serv_port_table
;
507 key
= (int *)g_new(int, 1);
510 serv_port_table
= (serv_port_t
*)g_hash_table_lookup(serv_port_hashtable
, &port
);
511 if (serv_port_table
== NULL
) {
512 serv_port_table
= g_new0(serv_port_t
,1);
513 g_hash_table_insert(serv_port_hashtable
, key
, serv_port_table
);
521 g_free(serv_port_table
->tcp_name
);
522 serv_port_table
->tcp_name
= g_strdup(service_name
);
525 g_free(serv_port_table
->udp_name
);
526 serv_port_table
->udp_name
= g_strdup(service_name
);
529 g_free(serv_port_table
->sctp_name
);
530 serv_port_table
->sctp_name
= g_strdup(service_name
);
533 g_free(serv_port_table
->dccp_name
);
534 serv_port_table
->dccp_name
= g_strdup(service_name
);
538 /* Should not happen */
541 new_resolved_objects
= TRUE
;
546 parse_service_line (char *line
)
549 * See the services(4) or services(5) man page for services file format
550 * (not available on all systems).
558 range_t
*port_rng
= NULL
;
559 guint32 max_port
= MAX_UDP_PORT
;
561 if ((cp
= strchr(line
, '#')))
564 if ((cp
= strtok(line
, " \t")) == NULL
)
569 if ((cp
= strtok(NULL
, " \t")) == NULL
)
574 if (strtok(cp
, "/") == NULL
)
577 if ((cp
= strtok(NULL
, "/")) == NULL
)
580 /* seems we got all interesting things from the file */
581 if(strcmp(cp
, "tcp") == 0) {
582 max_port
= MAX_TCP_PORT
;
585 else if(strcmp(cp
, "udp") == 0) {
586 max_port
= MAX_UDP_PORT
;
589 else if(strcmp(cp
, "sctp") == 0) {
590 max_port
= MAX_SCTP_PORT
;
593 else if(strcmp(cp
, "dccp") == 0) {
594 max_port
= MAX_DCCP_PORT
;
600 if(CVT_NO_ERROR
!= range_convert_str(&port_rng
, port
, max_port
) ) {
601 /* some assertion here? */
605 cb_service
= service
;
607 range_foreach(port_rng
, add_serv_port_cb
);
610 } /* parse_service_line */
614 add_serv_port_cb(const guint32 port
)
617 add_service_name(cb_proto
, port
, cb_service
);
623 parse_services_file(const char * path
)
627 static char *buf
= NULL
;
629 /* services hash table initialization */
630 serv_p
= ws_fopen(path
, "r");
635 while (fgetline(&buf
, &size
, serv_p
) >= 0) {
636 parse_service_line (buf
);
643 * unsigned integer to ascii
648 gchar
*bp
= (gchar
*)ep_alloc(MAXNAMELEN
);
650 /* XXX, guint32_to_str() ? */
651 guint32_to_str_buf(port
, bp
, MAXNAMELEN
);
657 *serv_name_lookup(const guint port
, const port_type proto
)
659 serv_port_t
*serv_port_table
;
662 serv_port_table
= (serv_port_t
*)g_hash_table_lookup(serv_port_hashtable
, &port
);
665 /* Set which table we should look up port in */
668 if(serv_port_table
->udp_name
){
669 return serv_port_table
->udp_name
;
673 if(serv_port_table
->tcp_name
){
674 return serv_port_table
->tcp_name
;
678 if(serv_port_table
->sctp_name
){
679 return serv_port_table
->sctp_name
;
683 if(serv_port_table
->dccp_name
){
684 return serv_port_table
->dccp_name
;
688 /* not yet implemented */
694 /* getservbyport() was used here but it was to expensive, if the functionality is desired
695 * it would be better to pre parse etc/services or C:\Windows\System32\drivers\etc at
698 name
= (gchar
*)g_malloc(16);
699 guint32_to_str_buf(port
, name
, 16);
701 if(serv_port_table
== NULL
){
704 key
= (int *)g_new(int, 1);
706 serv_port_table
= g_new0(serv_port_t
,1);
707 g_hash_table_insert(serv_port_hashtable
, key
, serv_port_table
);
711 serv_port_table
->udp_name
= name
;
714 serv_port_table
->tcp_name
= name
;
717 serv_port_table
->sctp_name
= name
;
720 serv_port_table
->dccp_name
= name
;
728 } /* serv_name_lookup */
731 destroy_serv_port(gpointer data
)
733 serv_port_t
*table
= (serv_port_t
*)data
;
734 g_free(table
->udp_name
);
735 g_free(table
->tcp_name
);
736 g_free(table
->sctp_name
);
737 g_free(table
->dccp_name
);
742 initialize_services(void)
747 static char rootpath_nt
[] = "\\system32\\drivers\\etc\\services";
750 /* the hash table won't ignore duplicates, so use the personal path first */
751 g_assert(serv_port_hashtable
== NULL
);
752 serv_port_hashtable
= g_hash_table_new_full(g_int_hash
, g_int_equal
, g_free
, destroy_serv_port
);
754 /* Read the system services file first */
757 sysroot
= getenv_utf8("WINDIR");
758 if (sysroot
!= NULL
) {
760 * The file should be under WINDIR.
761 * If this is Windows NT (NT 4.0,2K,XP,Server2K3), it's in
762 * %WINDIR%\system32\drivers\etc\services.
764 hostspath
= g_strconcat(sysroot
, rootpath_nt
, NULL
);
765 parse_services_file(hostspath
);
769 parse_services_file("/etc/services");
773 /* set personal services path */
774 if (g_pservices_path
== NULL
)
775 g_pservices_path
= get_persconffile_path(ENAME_SERVICES
, FALSE
);
777 parse_services_file(g_pservices_path
);
779 /* Compute the pathname of the services file. */
780 if (g_services_path
== NULL
) {
781 g_services_path
= get_datafile_path(ENAME_SERVICES
);
784 parse_services_file(g_services_path
);
786 } /* initialize_services */
789 service_name_lookup_cleanup(void)
791 if(serv_port_hashtable
){
792 g_hash_table_destroy(serv_port_hashtable
);
793 serv_port_hashtable
= NULL
;
797 /* Fill in an IP4 structure with info from subnets file or just with the
798 * string form of the address.
801 fill_dummy_ip4(const guint addr
, hashipv4_t
* volatile tp
)
803 subnet_entry_t subnet_entry
;
805 if ((tp
->flags
& DUMMY_ADDRESS_ENTRY
) == DUMMY_ADDRESS_ENTRY
)
806 return; /* already done */
808 tp
->flags
= tp
->flags
| DUMMY_ADDRESS_ENTRY
; /* Overwrite if we get async DNS reply */
810 /* Do we have a subnet for this address? */
811 subnet_entry
= subnet_lookup(addr
);
812 if(0 != subnet_entry
.mask
) {
813 /* Print name, then '.' then IP address after subnet mask */
815 gchar buffer
[MAX_IP_STR_LEN
];
819 host_addr
= addr
& (~(guint32
)subnet_entry
.mask
);
820 ip_to_str_buf((guint8
*)&host_addr
, buffer
, MAX_IP_STR_LEN
);
823 /* Skip to first octet that is not totally masked
824 * If length of mask is 32, we chomp the whole address.
825 * If the address string starts '.' (should not happen?),
828 i
= subnet_entry
.mask_length
/ 8;
829 while(*(paddr
) != '\0' && i
> 0) {
830 if(*(++paddr
) == '.') {
835 /* There are more efficient ways to do this, but this is safe if we
836 * trust g_snprintf and MAXNAMELEN
838 g_snprintf(tp
->name
, MAXNAMELEN
, "%s%s", subnet_entry
.name
, paddr
);
840 ip_to_str_buf((const guint8
*)&addr
, tp
->name
, MAXNAMELEN
);
850 #if ( ( ARES_VERSION_MAJOR < 1 ) \
851 || ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
859 async_dns_queue_msg_t
*caqm
= (async_dns_queue_msg_t
*)arg
;
863 /* XXX, what to do if async_dns_in_flight == 0? */
864 async_dns_in_flight
--;
866 if (status
== ARES_SUCCESS
) {
867 for (p
= he
->h_addr_list
; *p
!= NULL
; p
++) {
868 switch(caqm
->family
) {
870 add_ipv4_name(caqm
->addr
.ip4
, he
->h_name
);
873 add_ipv6_name(&caqm
->addr
.ip6
, he
->h_name
);
876 /* Throw an exception? */
883 #endif /* HAVE_C_ARES */
885 /* --------------- */
887 new_ipv4(const guint addr
)
889 hashipv4_t
*tp
= g_new(hashipv4_t
, 1);
892 ip_to_str_buf((const guint8
*)&addr
, tp
->ip
, sizeof(tp
->ip
));
897 host_lookup(const guint addr
, gboolean
*found
)
899 hashipv4_t
* volatile tp
;
903 tp
= (hashipv4_t
*)g_hash_table_lookup(ipv4_hash_table
, &addr
);
907 key
= (int *)g_new(int, 1);
910 g_hash_table_insert(ipv4_hash_table
, key
, tp
);
912 if ((tp
->flags
& DUMMY_AND_RESOLVE_FLGS
) == DUMMY_ADDRESS_ENTRY
){
915 if ((tp
->flags
& DUMMY_ADDRESS_ENTRY
) == DUMMY_ADDRESS_ENTRY
){
922 if (gbl_resolv_flags
.network_name
&& gbl_resolv_flags
.use_external_net_name_resolver
) {
923 tp
->flags
= tp
->flags
|TRIED_RESOLVE_ADDRESS
;
926 if (gbl_resolv_flags
.concurrent_dns
&&
927 name_resolve_concurrency
> 0 &&
928 async_dns_initialized
) {
929 add_async_dns_ipv4(AF_INET
, addr
);
930 /* XXX found is set to TRUE, which seems a bit odd, but I'm not
931 * going to risk changing the semantics.
933 fill_dummy_ip4(addr
, tp
);
936 #endif /* ASYNC_DNS */
938 /* unknown host or DNS timeout */
944 fill_dummy_ip4(addr
, tp
);
949 /* --------------- */
951 new_ipv6(const struct e_in6_addr
*addr
)
953 hashipv6_t
*tp
= g_new(hashipv6_t
,1);
956 ip6_to_str_buf(addr
, tp
->ip6
);
960 /* ------------------------------------ */
962 host_lookup6(const struct e_in6_addr
*addr
, gboolean
*found
)
964 hashipv6_t
* volatile tp
;
967 async_dns_queue_msg_t
*caqm
;
968 #endif /* HAVE_C_ARES */
973 tp
= (hashipv6_t
*)g_hash_table_lookup(ipv6_hash_table
, addr
);
975 struct e_in6_addr
*addr_key
;
977 addr_key
= g_new(struct e_in6_addr
,1);
979 memcpy(addr_key
, addr
, 16);
980 g_hash_table_insert(ipv6_hash_table
, addr_key
, tp
);
982 if ((tp
->flags
& DUMMY_AND_RESOLVE_FLGS
) == DUMMY_ADDRESS_ENTRY
){
985 if ((tp
->flags
& DUMMY_ADDRESS_ENTRY
) == DUMMY_ADDRESS_ENTRY
){
992 if (gbl_resolv_flags
.network_name
&&
993 gbl_resolv_flags
.use_external_net_name_resolver
) {
994 tp
->flags
= tp
->flags
|TRIED_RESOLVE_ADDRESS
;
998 if ((gbl_resolv_flags
.concurrent_dns
) &&
999 name_resolve_concurrency
> 0 &&
1000 async_dns_initialized
) {
1001 caqm
= g_new(async_dns_queue_msg_t
,1);
1002 caqm
->family
= AF_INET6
;
1003 memcpy(&caqm
->addr
.ip6
, addr
, sizeof(caqm
->addr
.ip6
));
1004 async_dns_queue_head
= g_list_append(async_dns_queue_head
, (gpointer
) caqm
);
1006 /* XXX found is set to TRUE, which seems a bit odd, but I'm not
1007 * going to risk changing the semantics.
1009 if ((tp
->flags
& DUMMY_ADDRESS_ENTRY
) == 0){
1010 g_strlcpy(tp
->name
, tp
->ip6
, MAXNAMELEN
);
1011 ip6_to_str_buf(addr
, tp
->name
);
1012 tp
->flags
= tp
->flags
| DUMMY_ADDRESS_ENTRY
;
1016 #endif /* HAVE_C_ARES */
1021 /* unknown host or DNS timeout */
1022 if ((tp
->flags
& DUMMY_ADDRESS_ENTRY
) == 0) {
1023 tp
->flags
= tp
->flags
| DUMMY_ADDRESS_ENTRY
;
1024 g_strlcpy(tp
->name
, tp
->ip6
, MAXNAMELEN
);
1029 } /* host_lookup6 */
1031 static const gchar
*
1032 solve_address_to_name(const address
*addr
)
1034 switch (addr
->type
) {
1037 return get_ether_name((const guint8
*)addr
->data
);
1041 memcpy(&ip4_addr
, addr
->data
, sizeof ip4_addr
);
1042 return get_hostname(ip4_addr
);
1046 struct e_in6_addr ip6_addr
;
1047 memcpy(&ip6_addr
.bytes
, addr
->data
, sizeof ip6_addr
.bytes
);
1048 return get_hostname6(&ip6_addr
);
1052 return (const gchar
*)addr
->data
;
1059 static const gchar
*
1060 se_solve_address_to_name(const address
*addr
)
1062 switch (addr
->type
) {
1065 return get_ether_name((const guint8
*)addr
->data
);
1069 memcpy(&ip4_addr
, addr
->data
, sizeof ip4_addr
);
1070 return get_hostname(ip4_addr
);
1074 struct e_in6_addr ip6_addr
;
1075 memcpy(&ip6_addr
.bytes
, addr
->data
, sizeof ip6_addr
.bytes
);
1076 return get_hostname6(&ip6_addr
);
1080 return se_strdup((const gchar
*)addr
->data
);
1088 * Ethernet / manufacturer resolution
1090 * The following functions implement ethernet address resolution and
1091 * ethers files parsing (see ethers(4)).
1093 * The manuf file has the same format as ethers(4) except that names are
1094 * truncated to MAXMANUFLEN-1 (8) characters and that an address contains
1095 * only 3 bytes (instead of 6).
1099 * I decide to not use the existing functions (see ethers(3) on some
1100 * operating systems) for the following reasons:
1101 * - performance gains (use of hash tables and some other enhancements),
1102 * - use of two ethers files (system-wide and per user),
1103 * - avoid the use of NIS maps,
1104 * - lack of these functions on some systems.
1106 * So the following functions do _not_ behave as the standard ones.
1113 * If "manuf_file" is FALSE, parse a 6-byte MAC address.
1114 * If "manuf_file" is TRUE, parse an up-to-6-byte sequence with an optional
1118 parse_ether_address(const char *cp
, ether_t
*eth
, unsigned int *mask
,
1119 const gboolean manuf_file
)
1126 for (i
= 0; i
< 6; i
++) {
1127 /* Get a hex number, 1 or 2 digits, no sign characters allowed. */
1128 if (!isxdigit((unsigned char)*cp
))
1130 num
= strtoul(cp
, &p
, 16);
1132 return FALSE
; /* failed */
1134 return FALSE
; /* not a valid octet */
1135 eth
->addr
[i
] = (guint8
) num
;
1136 cp
= p
; /* skip past the number */
1138 /* OK, what character terminated the octet? */
1140 /* "/" - this has a mask. */
1142 /* Entries with masks are allowed only in the "manuf" files. */
1145 cp
++; /* skip past the '/' to get to the mask */
1146 if (!isdigit((unsigned char)*cp
))
1147 return FALSE
; /* no sign allowed */
1148 num
= strtoul(cp
, &p
, 10);
1150 return FALSE
; /* failed */
1151 cp
= p
; /* skip past the number */
1152 if (*cp
!= '\0' && !isspace((unsigned char)*cp
))
1153 return FALSE
; /* bogus terminator */
1154 if (num
== 0 || num
>= 48)
1155 return FALSE
; /* bogus mask */
1156 /* Mask out the bits not covered by the mask */
1158 for (i
= 0; num
>= 8; i
++, num
-= 8)
1159 ; /* skip octets entirely covered by the mask */
1160 /* Mask out the first masked octet */
1161 eth
->addr
[i
] &= (0xFF << (8 - num
));
1163 /* Mask out completely-masked-out octets */
1169 /* We're at the end of the address, and there's no mask. */
1171 /* We got 3 bytes, so this is a manufacturer ID. */
1173 /* Manufacturer IDs are only allowed in the "manuf"
1177 /* Indicate that this is a manufacturer ID (0 is not allowed
1184 /* We got 6 bytes, so this is a MAC address.
1185 If we're reading one of the "manuf" files, indicate that
1186 this is a MAC address (48 is not allowed as a mask). */
1192 /* We didn't get 3 or 6 bytes, and there's no mask; this is
1197 /* We don't know the separator used in this number; it can either
1198 be ':', '-', or '.'. */
1199 if (*cp
!= ':' && *cp
!= '-' && *cp
!= '.')
1201 sep
= *cp
; /* subsequent separators must be the same */
1203 /* It has to be the same as the first separator */
1215 parse_ether_line(char *line
, ether_t
*eth
, unsigned int *mask
,
1216 const gboolean manuf_file
)
1219 * See the ethers(4) or ethers(5) man page for ethers file format
1220 * (not available on all systems).
1221 * We allow both ethernet address separators (':' and '-'),
1222 * as well as Wireshark's '.' separator.
1227 if ((cp
= strchr(line
, '#')))
1230 if ((cp
= strtok(line
, " \t")) == NULL
)
1233 if (!parse_ether_address(cp
, eth
, mask
, manuf_file
))
1236 if ((cp
= strtok(NULL
, " \t")) == NULL
)
1239 g_strlcpy(eth
->name
, cp
, MAXNAMELEN
);
1243 } /* parse_ether_line */
1245 static FILE *eth_p
= NULL
;
1248 set_ethent(char *path
)
1253 eth_p
= ws_fopen(path
, "r");
1266 get_ethent(unsigned int *mask
, const gboolean manuf_file
)
1270 static int size
= 0;
1271 static char *buf
= NULL
;
1276 while (fgetline(&buf
, &size
, eth_p
) >= 0) {
1277 if (parse_ether_line(buf
, ð
, mask
, manuf_file
) == 0) {
1288 get_ethbyname(const gchar
*name
)
1292 set_ethent(g_pethers_path
);
1294 while (((eth
= get_ethent(NULL
, FALSE
)) != NULL
) && strncmp(name
, eth
->name
, MAXNAMELEN
) != 0)
1300 set_ethent(g_ethers_path
);
1302 while (((eth
= get_ethent(NULL
, FALSE
)) != NULL
) && strncmp(name
, eth
->name
, MAXNAMELEN
) != 0)
1310 } /* get_ethbyname */
1314 get_ethbyaddr(const guint8
*addr
)
1319 set_ethent(g_pethers_path
);
1321 while (((eth
= get_ethent(NULL
, FALSE
)) != NULL
) && memcmp(addr
, eth
->addr
, 6) != 0)
1327 set_ethent(g_ethers_path
);
1329 while (((eth
= get_ethent(NULL
, FALSE
)) != NULL
) && memcmp(addr
, eth
->addr
, 6) != 0)
1337 } /* get_ethbyaddr */
1341 add_manuf_name(const guint8
*addr
, unsigned int mask
, gchar
*name
)
1344 gint64 eth_as_int64
, *wka_key
;
1345 int eth_as_int
, *manuf_key
;
1348 * XXX - can we use Standard Annotation Language annotations to
1349 * note that mask, as returned by parse_ethe)r_address() (and thus
1350 * by the routines that call it, and thus passed to us) cannot be > 48,
1351 * or is SAL too weak to express that?
1354 /* This is a well-known MAC address; just add this to the Ethernet
1356 add_eth_name(addr
, name
);
1360 eth_as_int64
= addr
[0];
1361 eth_as_int64
= eth_as_int64
<<8;
1363 eth_as_int64
= eth_as_int64
| oct
;
1364 eth_as_int64
= eth_as_int64
<<8;
1366 eth_as_int64
= eth_as_int64
| oct
;
1367 eth_as_int64
= eth_as_int64
<<8;
1369 eth_as_int64
= eth_as_int64
| oct
;
1370 eth_as_int64
= eth_as_int64
<<8;
1372 eth_as_int64
= eth_as_int64
| oct
;
1373 eth_as_int64
= eth_as_int64
<<8;
1375 eth_as_int64
= eth_as_int64
| oct
;
1378 /* This is a manufacturer ID; add it to the manufacturer ID hash table */
1380 /* manuf needs only the 3 most significant octets of the ethernet address */
1381 manuf_key
= (int *)g_new(int, 1);
1382 eth_as_int
= (int)(eth_as_int64
>>24)&0xffffff;
1383 *manuf_key
= eth_as_int
;
1385 g_hash_table_insert(manuf_hashtable
, manuf_key
, g_strdup(name
));
1389 /* This is a range of well-known addresses; add it to the appropriate
1390 well-known-address table, creating that table if necessary. */
1392 wka_key
= (gint64
*)g_new(gint64
, 1);
1393 *wka_key
= eth_as_int64
;
1395 g_hash_table_insert(wka_hashtable
, wka_key
, g_strdup(name
));
1397 } /* add_manuf_name */
1400 manuf_name_lookup(const guint8
*addr
)
1402 gint32 manuf_key
= 0;
1406 /* manuf needs only the 3 most significant octets of the ethernet address */
1407 manuf_key
= addr
[0];
1408 manuf_key
= manuf_key
<<8;
1410 manuf_key
= manuf_key
| oct
;
1411 manuf_key
= manuf_key
<<8;
1413 manuf_key
= manuf_key
| oct
;
1416 /* first try to find a "perfect match" */
1417 name
= (gchar
*)g_hash_table_lookup(manuf_hashtable
, &manuf_key
);
1422 /* Mask out the broadcast/multicast flag but not the locally
1423 * administered flag as localy administered means: not assigend
1424 * by the IEEE but the local administrator instead.
1425 * 0x01 multicast / broadcast bit
1426 * 0x02 locally administered bit */
1427 if((manuf_key
& 0x00010000) != 0){
1428 manuf_key
&= 0x00FEFFFF;
1429 name
= (gchar
*)g_hash_table_lookup(manuf_hashtable
, &manuf_key
);
1437 } /* manuf_name_lookup */
1440 wka_name_lookup(const guint8
*addr
, const unsigned int mask
)
1442 guint8 masked_addr
[6];
1445 gint64 eth_as_int64
;
1449 if(wka_hashtable
== NULL
){
1452 /* Get the part of the address covered by the mask. */
1453 for (i
= 0, num
= mask
; num
>= 8; i
++, num
-= 8)
1454 masked_addr
[i
] = addr
[i
]; /* copy octets entirely covered by the mask */
1455 /* Mask out the first masked octet */
1456 masked_addr
[i
] = addr
[i
] & (0xFF << (8 - num
));
1458 /* Zero out completely-masked-out octets */
1462 eth_as_int64
= masked_addr
[0];
1463 eth_as_int64
= eth_as_int64
<<8;
1464 oct
= masked_addr
[1];
1465 eth_as_int64
= eth_as_int64
| oct
;
1466 eth_as_int64
= eth_as_int64
<<8;
1467 oct
= masked_addr
[2];
1468 eth_as_int64
= eth_as_int64
| oct
;
1469 eth_as_int64
= eth_as_int64
<<8;
1470 oct
= masked_addr
[3];
1471 eth_as_int64
= eth_as_int64
| oct
;
1472 eth_as_int64
= eth_as_int64
<<8;
1473 oct
= masked_addr
[4];
1474 eth_as_int64
= eth_as_int64
| oct
;
1475 eth_as_int64
= eth_as_int64
<<8;
1476 oct
= masked_addr
[5];
1477 eth_as_int64
= eth_as_int64
| oct
;
1479 name
= (gchar
*)g_hash_table_lookup(wka_hashtable
, ð_as_int64
);
1483 } /* wka_name_lookup */
1486 initialize_ethers(void)
1492 /* hash table initialization */
1493 wka_hashtable
= g_hash_table_new_full(g_int64_hash
, g_int64_equal
, g_free
, g_free
);
1494 manuf_hashtable
= g_hash_table_new_full(g_int_hash
, g_int_equal
, g_free
, g_free
);
1495 eth_hashtable
= g_hash_table_new_full(g_int64_hash
, g_int64_equal
, g_free
, g_free
);
1497 /* Compute the pathname of the ethers file. */
1498 if (g_ethers_path
== NULL
) {
1499 g_ethers_path
= g_strdup_printf("%s" G_DIR_SEPARATOR_S
"%s",
1500 get_systemfile_dir(), ENAME_ETHERS
);
1503 /* Set g_pethers_path here, but don't actually do anything
1504 * with it. It's used in get_ethbyname() and get_ethbyaddr()
1506 if (g_pethers_path
== NULL
)
1507 g_pethers_path
= get_persconffile_path(ENAME_ETHERS
, FALSE
);
1509 /* Compute the pathname of the manuf file */
1510 manuf_path
= get_datafile_path(ENAME_MANUF
);
1512 /* Read it and initialize the hash table */
1513 set_ethent(manuf_path
);
1515 while ((eth
= get_ethent(&mask
, TRUE
))) {
1516 add_manuf_name(eth
->addr
, mask
, eth
->name
);
1523 } /* initialize_ethers */
1525 /* this is only needed when shuting down application (if at all) */
1527 eth_name_lookup_cleanup(void)
1530 if(manuf_hashtable
) {
1531 g_hash_table_destroy(manuf_hashtable
);
1532 manuf_hashtable
= NULL
;
1535 g_hash_table_destroy(wka_hashtable
);
1536 wka_hashtable
= NULL
;
1540 g_hash_table_destroy(eth_hashtable
);
1541 eth_hashtable
= NULL
;
1546 /* Resolve ethernet address */
1547 static hashether_t
*
1548 eth_addr_resolve(hashether_t
*tp
) {
1550 const guint8
*addr
= tp
->addr
;
1552 if ( (eth
= get_ethbyaddr(addr
)) != NULL
) {
1553 g_strlcpy(tp
->resolved_name
, eth
->name
, MAXNAMELEN
);
1554 tp
->status
= HASHETHER_STATUS_RESOLVED_NAME
;
1560 /* Unknown name. Try looking for it in the well-known-address
1561 tables for well-known address ranges smaller than 2^24. */
1564 /* Only the topmost 5 bytes participate fully */
1565 if ((name
= wka_name_lookup(addr
, mask
+40)) != NULL
) {
1566 g_snprintf(tp
->resolved_name
, MAXNAMELEN
, "%s_%02x",
1567 name
, addr
[5] & (0xFF >> mask
));
1568 tp
->status
= HASHETHER_STATUS_RESOLVED_DUMMY
;
1578 /* Only the topmost 4 bytes participate fully */
1579 if ((name
= wka_name_lookup(addr
, mask
+32)) != NULL
) {
1580 g_snprintf(tp
->resolved_name
, MAXNAMELEN
, "%s_%02x:%02x",
1581 name
, addr
[4] & (0xFF >> mask
), addr
[5]);
1582 tp
->status
= HASHETHER_STATUS_RESOLVED_DUMMY
;
1592 /* Only the topmost 3 bytes participate fully */
1593 if ((name
= wka_name_lookup(addr
, mask
+24)) != NULL
) {
1594 g_snprintf(tp
->resolved_name
, MAXNAMELEN
, "%s_%02x:%02x:%02x",
1595 name
, addr
[3] & (0xFF >> mask
), addr
[4], addr
[5]);
1596 tp
->status
= HASHETHER_STATUS_RESOLVED_DUMMY
;
1604 /* Now try looking in the manufacturer table. */
1605 if ((name
= manuf_name_lookup(addr
)) != NULL
) {
1606 g_snprintf(tp
->resolved_name
, MAXNAMELEN
, "%s_%02x:%02x:%02x",
1607 name
, addr
[3], addr
[4], addr
[5]);
1608 tp
->status
= HASHETHER_STATUS_RESOLVED_DUMMY
;
1612 /* Now try looking for it in the well-known-address
1613 tables for well-known address ranges larger than 2^24. */
1616 /* Only the topmost 2 bytes participate fully */
1617 if ((name
= wka_name_lookup(addr
, mask
+16)) != NULL
) {
1618 g_snprintf(tp
->resolved_name
, MAXNAMELEN
, "%s_%02x:%02x:%02x:%02x",
1619 name
, addr
[2] & (0xFF >> mask
), addr
[3], addr
[4],
1621 tp
->status
= HASHETHER_STATUS_RESOLVED_DUMMY
;
1631 /* Only the topmost byte participates fully */
1632 if ((name
= wka_name_lookup(addr
, mask
+8)) != NULL
) {
1633 g_snprintf(tp
->resolved_name
, MAXNAMELEN
, "%s_%02x:%02x:%02x:%02x:%02x",
1634 name
, addr
[1] & (0xFF >> mask
), addr
[2], addr
[3],
1636 tp
->status
= HASHETHER_STATUS_RESOLVED_DUMMY
;
1644 for (mask
= 7; mask
> 0; mask
--) {
1645 /* Not even the topmost byte participates fully */
1646 if ((name
= wka_name_lookup(addr
, mask
)) != NULL
) {
1647 g_snprintf(tp
->resolved_name
, MAXNAMELEN
, "%s_%02x:%02x:%02x:%02x:%02x:%02x",
1648 name
, addr
[0] & (0xFF >> mask
), addr
[1], addr
[2],
1649 addr
[3], addr
[4], addr
[5]);
1650 tp
->status
= HASHETHER_STATUS_RESOLVED_DUMMY
;
1655 /* No match whatsoever. */
1656 g_snprintf(tp
->resolved_name
, MAXNAMELEN
, "%s", ether_to_str(addr
));
1657 tp
->status
= HASHETHER_STATUS_RESOLVED_DUMMY
;
1660 g_assert_not_reached();
1661 } /* eth_addr_resolve */
1664 eth_to_int64(const guint8
*addr
)
1667 gint64 eth_as_int64
;
1669 eth_as_int64
= addr
[0];
1670 eth_as_int64
= eth_as_int64
<<8;
1672 eth_as_int64
= eth_as_int64
| oct
;
1673 eth_as_int64
= eth_as_int64
<<8;
1675 eth_as_int64
= eth_as_int64
| oct
;
1676 eth_as_int64
= eth_as_int64
<<8;
1678 eth_as_int64
= eth_as_int64
| oct
;
1679 eth_as_int64
= eth_as_int64
<<8;
1681 eth_as_int64
= eth_as_int64
| oct
;
1682 eth_as_int64
= eth_as_int64
<<8;
1684 eth_as_int64
= eth_as_int64
| oct
;
1686 return eth_as_int64
;
1689 static hashether_t
*
1690 eth_hash_new_entry(const guint8
*addr
, const gboolean resolve
)
1693 gint64 eth_as_int64
, *key
;
1695 eth_as_int64
= eth_to_int64(addr
);
1697 key
= (gint64
*)g_new(gint64
, 1);
1698 *key
= eth_as_int64
;
1700 tp
= g_new(hashether_t
, 1);
1701 memcpy(tp
->addr
, addr
, sizeof(tp
->addr
));
1702 tp
->status
= HASHETHER_STATUS_UNRESOLVED
;
1703 g_strlcpy(tp
->hexaddr
, bytestring_to_str(addr
, sizeof(tp
->addr
), ':'), sizeof(tp
->hexaddr
));
1704 tp
->resolved_name
[0] = '\0';
1707 eth_addr_resolve(tp
);
1709 g_hash_table_insert(eth_hashtable
, key
, tp
);
1712 } /* eth_hash_new_entry */
1714 static hashether_t
*
1715 add_eth_name(const guint8
*addr
, const gchar
*name
)
1718 gint64 eth_as_int64
;
1720 eth_as_int64
= eth_to_int64(addr
);
1722 tp
= (hashether_t
*)g_hash_table_lookup(eth_hashtable
, ð_as_int64
);
1725 tp
= eth_hash_new_entry(addr
, FALSE
);
1728 g_strlcpy(tp
->resolved_name
, name
, MAXNAMELEN
);
1729 tp
->status
= HASHETHER_STATUS_RESOLVED_NAME
;
1730 new_resolved_objects
= TRUE
;
1733 } /* add_eth_name */
1735 static hashether_t
*
1736 eth_name_lookup(const guint8
*addr
, const gboolean resolve
)
1739 gint64 eth_as_int64
;
1741 eth_as_int64
= eth_to_int64(addr
);
1743 tp
= (hashether_t
*)g_hash_table_lookup(eth_hashtable
, ð_as_int64
);
1745 tp
= eth_hash_new_entry(addr
, resolve
);
1747 if (resolve
&& (tp
->status
== HASHETHER_STATUS_UNRESOLVED
)){
1748 eth_addr_resolve(tp
); /* Found but needs to be resolved */
1754 } /* eth_name_lookup */
1757 eth_addr_lookup(const gchar
*name _U_
)
1760 /* XXX Do we need reverse lookup??? */
1763 hashether_t
**table
= eth_table
;
1766 /* to be optimized (hash table from name to addr) */
1767 for (i
= 0; i
< HASHETHSIZE
; i
++) {
1770 if (strcmp(tp
->resolved_name
, name
) == 0)
1776 /* not in hash table : performs a file lookup */
1778 if ((eth
= get_ethbyname(name
)) == NULL
)
1781 /* add new entry in hash table */
1783 tp
= add_eth_name(eth
->addr
, name
);
1789 } /* eth_addr_lookup */
1794 parse_ipxnets_line(char *line
, ipxnet_t
*ipxnet
)
1797 * We allow three address separators (':', '-', and '.'),
1798 * as well as no separators
1802 guint32 a
, a0
, a1
, a2
, a3
;
1803 gboolean found_single_number
= FALSE
;
1805 if ((cp
= strchr(line
, '#')))
1808 if ((cp
= strtok(line
, " \t\n")) == NULL
)
1811 /* Either fill a0,a1,a2,a3 and found_single_number is FALSE,
1812 * fill a and found_single_number is TRUE,
1815 if (sscanf(cp
, "%x:%x:%x:%x", &a0
, &a1
, &a2
, &a3
) != 4) {
1816 if (sscanf(cp
, "%x-%x-%x-%x", &a0
, &a1
, &a2
, &a3
) != 4) {
1817 if (sscanf(cp
, "%x.%x.%x.%x", &a0
, &a1
, &a2
, &a3
) != 4) {
1818 if (sscanf(cp
, "%x", &a
) == 1) {
1819 found_single_number
= TRUE
;
1828 if ((cp
= strtok(NULL
, " \t\n")) == NULL
)
1831 if (found_single_number
) {
1835 ipxnet
->addr
= (a0
<< 24) | (a1
<< 16) | (a2
<< 8) | a3
;
1838 g_strlcpy(ipxnet
->name
, cp
, MAXNAMELEN
);
1842 } /* parse_ipxnets_line */
1844 static FILE *ipxnet_p
= NULL
;
1847 set_ipxnetent(char *path
)
1852 ipxnet_p
= ws_fopen(path
, "r");
1868 static ipxnet_t ipxnet
;
1869 static int size
= 0;
1870 static char *buf
= NULL
;
1872 if (ipxnet_p
== NULL
)
1875 while (fgetline(&buf
, &size
, ipxnet_p
) >= 0) {
1876 if (parse_ipxnets_line(buf
, &ipxnet
) == 0) {
1883 } /* get_ipxnetent */
1888 get_ipxnetbyname(const gchar
*name
)
1892 set_ipxnetent(g_ipxnets_path
);
1894 while (((ipxnet
= get_ipxnetent()) != NULL
) && strncmp(name
, ipxnet
->name
, MAXNAMELEN
) != 0)
1897 if (ipxnet
== NULL
) {
1900 set_ipxnetent(g_pipxnets_path
);
1902 while (((ipxnet
= get_ipxnetent()) != NULL
) && strncmp(name
, ipxnet
->name
, MAXNAMELEN
) != 0)
1910 } /* get_ipxnetbyname */
1914 get_ipxnetbyaddr(guint32 addr
)
1918 set_ipxnetent(g_ipxnets_path
);
1920 while (((ipxnet
= get_ipxnetent()) != NULL
) && (addr
!= ipxnet
->addr
) ) ;
1922 if (ipxnet
== NULL
) {
1925 set_ipxnetent(g_pipxnets_path
);
1927 while (((ipxnet
= get_ipxnetent()) != NULL
) && (addr
!= ipxnet
->addr
) )
1935 } /* get_ipxnetbyaddr */
1938 initialize_ipxnets(void)
1940 /* Compute the pathname of the ipxnets file.
1942 * XXX - is there a notion of an "ipxnets file" in any flavor of
1943 * UNIX, or with any add-on Netware package for UNIX? If not,
1944 * should the UNIX version of the ipxnets file be in the datafile
1945 * directory as well?
1947 if (g_ipxnets_path
== NULL
) {
1948 g_ipxnets_path
= g_strdup_printf("%s" G_DIR_SEPARATOR_S
"%s",
1949 get_systemfile_dir(), ENAME_IPXNETS
);
1952 /* Set g_pipxnets_path here, but don't actually do anything
1953 * with it. It's used in get_ipxnetbyname() and get_ipxnetbyaddr()
1955 if (g_pipxnets_path
== NULL
)
1956 g_pipxnets_path
= get_persconffile_path(ENAME_IPXNETS
, FALSE
);
1958 } /* initialize_ipxnets */
1961 ipx_name_lookup_cleanup(void)
1963 if(ipxnet_hash_table
){
1964 g_hash_table_destroy(ipxnet_hash_table
);
1965 ipxnet_hash_table
= NULL
;
1971 static hashipxnet_t
*
1972 add_ipxnet_name(guint addr
, const gchar
*name
)
1976 tp
= (hashipxnet_t
*)g_hash_table_lookup(ipxnet_hash_table
, &addr
);
1978 g_strlcpy(tp
->name
, name
, MAXNAMELEN
);
1982 key
= (int *)g_new(int, 1);
1984 tp
= g_new(hashipxnet_t
,1);
1985 g_strlcpy(tp
->name
, name
, MAXNAMELEN
);
1986 g_hash_table_insert(ipxnet_hash_table
, key
, tp
);
1990 g_strlcpy(tp
->name
, name
, MAXNAMELEN
);
1992 new_resolved_objects
= TRUE
;
1996 } /* add_ipxnet_name */
2000 ipxnet_name_lookup(const guint addr
)
2005 tp
= (hashipxnet_t
*)g_hash_table_lookup(ipxnet_hash_table
, &addr
);
2009 key
= (int *)g_new(int, 1);
2011 tp
= g_new(hashipxnet_t
, 1);
2012 g_hash_table_insert(ipxnet_hash_table
, key
, tp
);
2017 /* fill in a new entry */
2021 if ( (ipxnet
= get_ipxnetbyaddr(addr
)) == NULL
) {
2023 g_snprintf(tp
->name
, MAXNAMELEN
, "%X", addr
);
2026 g_strlcpy(tp
->name
, ipxnet
->name
, MAXNAMELEN
);
2031 } /* ipxnet_name_lookup */
2034 ipxnet_addr_lookup(const gchar
*name _U_
, gboolean
*success
)
2039 /* XXX Do we need reverse lookup??? */
2042 hashipxnet_t
**table
= ipxnet_table
;
2045 /* to be optimized (hash table from name to addr) */
2046 for (i
= 0; i
< HASHIPXNETSIZE
; i
++) {
2049 if (strcmp(tp
->name
, name
) == 0) {
2057 /* not in hash table : performs a file lookup */
2059 if ((ipxnet
= get_ipxnetbyname(name
)) == NULL
) {
2064 /* add new entry in hash table */
2066 tp
= add_ipxnet_name(ipxnet
->addr
, name
);
2071 } /* ipxnet_addr_lookup */
2074 read_hosts_file (const char *hostspath
)
2080 guint32 host_addr
[4]; /* IPv4 or IPv6 */
2081 struct e_in6_addr ip6_addr
;
2086 * See the hosts(4) or hosts(5) man page for hosts file format
2087 * (not available on all systems).
2089 if ((hf
= ws_fopen(hostspath
, "r")) == NULL
)
2092 while (fgetline(&line
, &size
, hf
) >= 0) {
2093 if ((cp
= strchr(line
, '#')))
2096 if ((cp
= strtok(line
, " \t")) == NULL
)
2097 continue; /* no tokens in the line */
2099 ret
= inet_pton(AF_INET6
, cp
, &host_addr
);
2101 continue; /* error parsing */
2106 /* Not valid IPv6 - valid IPv4? */
2107 if (inet_pton(AF_INET
, cp
, &host_addr
) <= 0)
2112 if ((cp
= strtok(NULL
, " \t")) == NULL
)
2113 continue; /* no host name */
2116 memcpy(&ip6_addr
, host_addr
, sizeof ip6_addr
);
2117 add_ipv6_name(&ip6_addr
, cp
);
2119 add_ipv4_name(host_addr
[0], cp
);
2122 * Add the aliases, too, if there are any.
2123 * XXX - host_lookup() only returns the first entry.
2125 while ((cp
= strtok(NULL
, " \t")) != NULL
) {
2127 memcpy(&ip6_addr
, host_addr
, sizeof ip6_addr
);
2128 add_ipv6_name(&ip6_addr
, cp
);
2130 add_ipv4_name(host_addr
[0], cp
);
2137 } /* read_hosts_file */
2140 add_hosts_file (const char *hosts_file
)
2142 gboolean found
= FALSE
;
2148 if (!extra_hosts_files
)
2149 extra_hosts_files
= g_ptr_array_new();
2151 for (i
= 0; i
< extra_hosts_files
->len
; i
++) {
2152 if (strcmp(hosts_file
, (const char *) g_ptr_array_index(extra_hosts_files
, i
)) == 0)
2157 g_ptr_array_add(extra_hosts_files
, g_strdup(hosts_file
));
2158 return read_hosts_file (hosts_file
);
2164 add_ip_name_from_string (const char *addr
, const char *name
)
2166 guint32 host_addr
[4]; /* IPv4 */
2167 struct e_in6_addr ip6_addr
; /* IPv6 */
2170 resolved_ipv4_t
*resolved_ipv4_entry
;
2171 resolved_ipv6_t
*resolved_ipv6_entry
;
2173 ret
= inet_pton(AF_INET6
, addr
, &ip6_addr
);
2175 /* Error parsing address */
2182 /* Not valid IPv6 - valid IPv4? */
2183 if (inet_pton(AF_INET
, addr
, &host_addr
) <= 0)
2184 return FALSE
; /* no */
2189 resolved_ipv6_entry
= g_new(resolved_ipv6_t
, 1);
2190 memcpy(&(resolved_ipv6_entry
->ip6_addr
), &ip6_addr
, 16);
2191 g_strlcpy(resolved_ipv6_entry
->name
, name
, MAXNAMELEN
);
2192 manually_resolved_ipv6_list
= g_slist_prepend(manually_resolved_ipv6_list
, resolved_ipv6_entry
);
2194 resolved_ipv4_entry
= g_new(resolved_ipv4_t
, 1);
2195 resolved_ipv4_entry
->host_addr
= host_addr
[0];
2196 g_strlcpy(resolved_ipv4_entry
->name
, name
, MAXNAMELEN
);
2197 manually_resolved_ipv4_list
= g_slist_prepend(manually_resolved_ipv4_list
, resolved_ipv4_entry
);
2201 } /* add_ip_name_from_string */
2204 * Add the resolved addresses that are in use to the list used to create the NRB
2207 ipv4_hash_table_resolved_to_list(gpointer key _U_
, gpointer value
, gpointer user_data
)
2209 addrinfo_lists_t
*lists
= (addrinfo_lists_t
*)user_data
;
2210 hashipv4_t
*ipv4_hash_table_entry
= (hashipv4_t
*)value
;
2212 if((ipv4_hash_table_entry
->flags
& USED_AND_RESOLVED_MASK
) == RESOLVED_ADDRESS_USED
){
2213 lists
->ipv4_addr_list
= g_list_prepend (lists
->ipv4_addr_list
, ipv4_hash_table_entry
);
2219 * Add the resolved addresses that are in use to the list used to create the NRB
2223 ipv6_hash_table_resolved_to_list(gpointer key _U_
, gpointer value
, gpointer user_data
)
2225 addrinfo_lists_t
*lists
= (addrinfo_lists_t
*)user_data
;
2226 hashipv6_t
*ipv6_hash_table_entry
= (hashipv6_t
*)value
;
2228 if((ipv6_hash_table_entry
->flags
& USED_AND_RESOLVED_MASK
) == RESOLVED_ADDRESS_USED
){
2229 lists
->ipv6_addr_list
= g_list_prepend (lists
->ipv6_addr_list
, ipv6_hash_table_entry
);
2235 get_addrinfo_list(void) {
2237 if(ipv4_hash_table
){
2238 g_hash_table_foreach(ipv4_hash_table
, ipv4_hash_table_resolved_to_list
, &addrinfo_lists
);
2241 if(ipv6_hash_table
){
2242 g_hash_table_foreach(ipv6_hash_table
, ipv6_hash_table_resolved_to_list
, &addrinfo_lists
);
2245 return &addrinfo_lists
;
2248 /* Read in a list of subnet definition - name pairs.
2249 * <line> = <comment> | <entry> | <whitespace>
2250 * <comment> = <whitespace>#<any>
2251 * <entry> = <subnet_definition> <whitespace> <subnet_name> [<comment>|<whitespace><any>]
2252 * <subnet_definition> = <ipv4_address> / <subnet_mask_length>
2253 * <ipv4_address> is a full address; it will be masked to get the subnet-ID.
2254 * <subnet_mask_length> is a decimal 1-31
2255 * <subnet_name> is a string containing no whitespace.
2256 * <whitespace> = (space | tab)+
2257 * Any malformed entries are ignored.
2258 * Any trailing data after the subnet_name is ignored.
2263 read_subnets_file (const char *subnetspath
)
2269 guint32 host_addr
; /* IPv4 ONLY */
2272 if ((hf
= ws_fopen(subnetspath
, "r")) == NULL
)
2275 while (fgetline(&line
, &size
, hf
) >= 0) {
2276 if ((cp
= strchr(line
, '#')))
2279 if ((cp
= strtok(line
, " \t")) == NULL
)
2280 continue; /* no tokens in the line */
2283 /* Expected format is <IP4 address>/<subnet length> */
2284 cp2
= strchr(cp
, '/');
2289 *cp2
= '\0'; /* Cut token */
2292 /* Check if this is a valid IPv4 address */
2293 if (inet_pton(AF_INET
, cp
, &host_addr
) <= 0) {
2297 mask_length
= atoi(cp2
);
2298 if(0 >= mask_length
|| mask_length
> 31) {
2299 continue; /* invalid mask length */
2302 if ((cp
= strtok(NULL
, " \t")) == NULL
)
2303 continue; /* no subnet name */
2305 subnet_entry_set(host_addr
, (guint32
)mask_length
, cp
);
2311 } /* read_subnets_file */
2313 static subnet_entry_t
2314 subnet_lookup(const guint32 addr
)
2316 subnet_entry_t subnet_entry
;
2319 /* Search mask lengths linearly, longest first */
2321 i
= SUBNETLENGTHSIZE
;
2322 while(have_subnet_entry
&& i
> 0) {
2323 guint32 masked_addr
;
2324 subnet_length_entry_t
* length_entry
;
2326 /* Note that we run from 31 (length 32) to 0 (length 1) */
2328 g_assert(i
< SUBNETLENGTHSIZE
);
2331 length_entry
= &subnet_length_entries
[i
];
2333 if(NULL
!= length_entry
->subnet_addresses
) {
2334 sub_net_hashipv4_t
* tp
;
2337 masked_addr
= addr
& length_entry
->mask
;
2338 hash_idx
= HASH_IPV4_ADDRESS(masked_addr
);
2340 tp
= length_entry
->subnet_addresses
[hash_idx
];
2341 while(tp
!= NULL
&& tp
->addr
!= masked_addr
) {
2346 subnet_entry
.mask
= length_entry
->mask
;
2347 subnet_entry
.mask_length
= i
+ 1; /* Length is offset + 1 */
2348 subnet_entry
.name
= tp
->name
;
2349 return subnet_entry
;
2354 subnet_entry
.mask
= 0;
2355 subnet_entry
.mask_length
= 0;
2356 subnet_entry
.name
= NULL
;
2358 return subnet_entry
;
2361 /* Add a subnet-definition - name pair to the set.
2362 * The definition is taken by masking the address passed in with the mask of the
2366 subnet_entry_set(guint32 subnet_addr
, const guint32 mask_length
, const gchar
* name
)
2368 subnet_length_entry_t
* entry
;
2369 sub_net_hashipv4_t
* tp
;
2372 g_assert(mask_length
> 0 && mask_length
<= 32);
2374 entry
= &subnet_length_entries
[mask_length
- 1];
2376 subnet_addr
&= entry
->mask
;
2378 hash_idx
= HASH_IPV4_ADDRESS(subnet_addr
);
2380 if(NULL
== entry
->subnet_addresses
) {
2381 entry
->subnet_addresses
= (sub_net_hashipv4_t
**) se_alloc0(sizeof(sub_net_hashipv4_t
*) * HASHHOSTSIZE
);
2384 if(NULL
!= (tp
= entry
->subnet_addresses
[hash_idx
])) {
2385 if(tp
->addr
== subnet_addr
) {
2386 return; /* XXX provide warning that an address was repeated? */
2388 sub_net_hashipv4_t
* new_tp
= se_new(sub_net_hashipv4_t
);
2393 tp
= entry
->subnet_addresses
[hash_idx
] = se_new(sub_net_hashipv4_t
);
2397 tp
->addr
= subnet_addr
;
2398 /* Clear DUMMY_ADDRESS_ENTRY */
2399 tp
->flags
= tp
->flags
& 0xfe; /*Never used again...*/
2400 g_strlcpy(tp
->name
, name
, MAXNAMELEN
); /* This is longer than subnet names can actually be */
2401 have_subnet_entry
= TRUE
;
2405 subnet_name_lookup_init(void)
2410 for(i
= 0; i
< SUBNETLENGTHSIZE
; ++i
) {
2411 guint32 length
= i
+ 1;
2413 subnet_length_entries
[i
].subnet_addresses
= NULL
;
2414 subnet_length_entries
[i
].mask_length
= length
;
2415 subnet_length_entries
[i
].mask
= g_htonl(ip_get_subnet_mask(length
));
2418 subnetspath
= get_persconffile_path(ENAME_SUBNETS
, FALSE
);
2419 if (!read_subnets_file(subnetspath
) && errno
!= ENOENT
) {
2420 report_open_failure(subnetspath
, errno
, FALSE
);
2422 g_free(subnetspath
);
2425 * Load the global subnets file, if we have one.
2427 subnetspath
= get_datafile_path(ENAME_SUBNETS
);
2428 if (!read_subnets_file(subnetspath
) && errno
!= ENOENT
) {
2429 report_open_failure(subnetspath
, errno
, FALSE
);
2431 g_free(subnetspath
);
2436 * External Functions
2440 addr_resolve_pref_init(module_t
*nameres
)
2442 prefs_register_bool_preference(nameres
, "mac_name",
2443 "Resolve MAC addresses",
2444 "Resolve Ethernet MAC address to manufacturer names",
2445 &gbl_resolv_flags
.mac_name
);
2447 prefs_register_bool_preference(nameres
, "transport_name",
2448 "Resolve transport names",
2449 "Resolve TCP/UDP ports into service names",
2450 &gbl_resolv_flags
.transport_name
);
2452 prefs_register_bool_preference(nameres
, "network_name",
2453 "Resolve network (IP) addresses",
2454 "Resolve IPv4, IPv6, and IPX addresses into host names."
2455 " The next set of check boxes determines how name resolution should be performed."
2456 " If no other options are checked name resolution is made from Wireshark's host file,"
2457 " capture file name resolution blocks and DNS packets in the capture.",
2458 &gbl_resolv_flags
.network_name
);
2460 prefs_register_bool_preference(nameres
, "use_external_name_resolver",
2461 "Use an external network name resolver",
2462 "Use your system's configured name resolver"
2463 " (usually DNS) to resolve network names."
2464 " Only applies when network name resolution"
2466 &gbl_resolv_flags
.use_external_net_name_resolver
);
2468 #if defined(HAVE_C_ARES) || defined(HAVE_GNU_ADNS)
2469 prefs_register_bool_preference(nameres
, "concurrent_dns",
2470 "Enable concurrent DNS name resolution",
2471 "Enable concurrent DNS name resolution. Only"
2472 " applies when network name resolution is"
2473 " enabled. You probably want to enable this.",
2474 &gbl_resolv_flags
.concurrent_dns
);
2476 prefs_register_uint_preference(nameres
, "name_resolve_concurrency",
2477 "Maximum concurrent requests",
2478 "The maximum number of DNS requests that may"
2479 " be active at any time. A large value (many"
2480 " thousands) might overload the network or make"
2481 " your DNS server behave badly.",
2483 &name_resolve_concurrency
);
2485 prefs_register_static_text_preference(nameres
, "concurrent_dns",
2486 "Enable concurrent DNS name resolution: N/A",
2487 "Support for concurrent DNS name resolution was not"
2488 " compiled into this version of Wireshark");
2491 prefs_register_bool_preference(nameres
, "hosts_file_handling",
2492 "Only use the profile \"hosts\" file",
2493 "By default \"hosts\" files will be loaded from multiple sources."
2494 " Checking this box only loads the \"hosts\" in the current profile.",
2495 &gbl_resolv_flags
.load_hosts_file_from_profile_only
);
2501 host_name_lookup_process(void) {
2502 async_dns_queue_msg_t
*caqm
;
2503 struct timeval tv
= { 0, 0 };
2506 gboolean nro
= new_resolved_objects
;
2508 new_resolved_objects
= FALSE
;
2510 if (!async_dns_initialized
)
2511 /* c-ares not initialized. Bail out and cancel timers. */
2514 async_dns_queue_head
= g_list_first(async_dns_queue_head
);
2516 while (async_dns_queue_head
!= NULL
&& async_dns_in_flight
<= name_resolve_concurrency
) {
2517 caqm
= (async_dns_queue_msg_t
*) async_dns_queue_head
->data
;
2518 async_dns_queue_head
= g_list_remove(async_dns_queue_head
, (void *) caqm
);
2519 if (caqm
->family
== AF_INET
) {
2520 ares_gethostbyaddr(ghba_chan
, &caqm
->addr
.ip4
, sizeof(guint32
), AF_INET
,
2521 c_ares_ghba_cb
, caqm
);
2522 async_dns_in_flight
++;
2523 } else if (caqm
->family
== AF_INET6
) {
2524 ares_gethostbyaddr(ghba_chan
, &caqm
->addr
.ip6
, sizeof(struct e_in6_addr
),
2525 AF_INET6
, c_ares_ghba_cb
, caqm
);
2526 async_dns_in_flight
++;
2532 nfds
= ares_fds(ghba_chan
, &rfds
, &wfds
);
2534 if (select(nfds
, &rfds
, &wfds
, NULL
, &tv
) == -1) { /* call to select() failed */
2535 fprintf(stderr
, "Warning: call to select() failed, error is %s\n", strerror(errno
));
2538 ares_process(ghba_chan
, &rfds
, &wfds
);
2541 /* Any new entries? */
2546 _host_name_lookup_cleanup(void) {
2549 cur
= g_list_first(async_dns_queue_head
);
2552 cur
= g_list_next (cur
);
2555 g_list_free(async_dns_queue_head
);
2556 async_dns_queue_head
= NULL
;
2558 if (async_dns_initialized
) {
2559 ares_destroy(ghba_chan
);
2560 ares_destroy(ghbn_chan
);
2562 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2563 ares_library_cleanup();
2565 async_dns_initialized
= FALSE
;
2568 #elif defined(HAVE_GNU_ADNS)
2570 /* XXX - The ADNS "documentation" isn't very clear:
2571 * - Do we need to keep our query structures around?
2574 host_name_lookup_process(void) {
2575 async_dns_queue_msg_t
*almsg
;
2577 char addr_str
[] = "111.222.333.444.in-addr.arpa.";
2582 gboolean nro
= new_resolved_objects
;
2584 new_resolved_objects
= FALSE
;
2585 async_dns_queue_head
= g_list_first(async_dns_queue_head
);
2587 cur
= async_dns_queue_head
;
2588 while (cur
&& async_dns_in_flight
<= name_resolve_concurrency
) {
2589 almsg
= (async_dns_queue_msg_t
*) cur
->data
;
2590 if (! almsg
->submitted
&& almsg
->type
== AF_INET
) {
2591 addr_bytes
= (guint8
*) &almsg
->ip4_addr
;
2592 g_snprintf(addr_str
, sizeof addr_str
, "%u.%u.%u.%u.in-addr.arpa.", addr_bytes
[3],
2593 addr_bytes
[2], addr_bytes
[1], addr_bytes
[0]);
2594 /* XXX - what if it fails? */
2595 adns_submit (ads
, addr_str
, adns_r_ptr
, adns_qf_none
, NULL
, &almsg
->query
);
2596 almsg
->submitted
= TRUE
;
2597 async_dns_in_flight
++;
2602 cur
= async_dns_queue_head
;
2605 almsg
= (async_dns_queue_msg_t
*) cur
->data
;
2606 if (almsg
->submitted
) {
2607 ret
= adns_check(ads
, &almsg
->query
, &ans
, NULL
);
2609 if (ans
->status
== adns_s_ok
) {
2610 add_ipv4_name(almsg
->ip4_addr
, *ans
->rrs
.str
);
2617 async_dns_queue_head
= g_list_remove(async_dns_queue_head
, (void *) almsg
);
2619 /* XXX, what to do if async_dns_in_flight == 0? */
2620 async_dns_in_flight
--;
2624 /* Keep the timeout in place */
2629 _host_name_lookup_cleanup(void) {
2632 async_dns_queue_head
= g_list_first(async_dns_queue_head
);
2633 while (async_dns_queue_head
) {
2634 qdata
= async_dns_queue_head
->data
;
2635 async_dns_queue_head
= g_list_remove(async_dns_queue_head
, qdata
);
2639 if (async_dns_initialized
)
2641 async_dns_initialized
= FALSE
;
2644 #else /* HAVE_GNU_ADNS */
2647 host_name_lookup_process(void) {
2648 gboolean nro
= new_resolved_objects
;
2650 new_resolved_objects
= FALSE
;
2656 _host_name_lookup_cleanup(void) {
2659 #endif /* HAVE_C_ARES */
2662 get_hostname(const guint addr
)
2666 /* XXX why do we call this if we're not resolving? To create hash entries?
2669 hashipv4_t
*tp
= host_lookup(addr
, &found
);
2671 if (!gbl_resolv_flags
.network_name
)
2674 tp
->flags
= tp
->flags
| RESOLVED_ADDRESS_USED
;
2679 /* -------------------------- */
2682 get_hostname6(const struct e_in6_addr
*addr
)
2686 /* XXX why do we call this if we're not resolving? To create hash entries?
2689 hashipv6_t
*tp
= host_lookup6(addr
, &found
);
2691 if (!gbl_resolv_flags
.network_name
)
2694 tp
->flags
= tp
->flags
| RESOLVED_ADDRESS_USED
;
2699 /* -------------------------- */
2701 add_ipv4_name(const guint addr
, const gchar
*name
)
2706 * Don't add zero-length names; apparently, some resolvers will return
2707 * them if they get them from DNS.
2709 if (name
[0] == '\0')
2713 tp
= (hashipv4_t
*)g_hash_table_lookup(ipv4_hash_table
, &addr
);
2715 g_strlcpy(tp
->name
, name
, MAXNAMELEN
);
2719 key
= (int *)g_new(int, 1);
2721 tp
= new_ipv4(addr
);
2722 g_strlcpy(tp
->name
, name
, MAXNAMELEN
);
2723 g_hash_table_insert(ipv4_hash_table
, key
, tp
);
2726 g_strlcpy(tp
->name
, name
, MAXNAMELEN
);
2727 tp
->flags
= tp
->flags
| TRIED_RESOLVE_ADDRESS
;
2728 new_resolved_objects
= TRUE
;
2730 } /* add_ipv4_name */
2732 /* -------------------------- */
2734 add_ipv6_name(const struct e_in6_addr
*addrp
, const gchar
*name
)
2739 * Don't add zero-length names; apparently, some resolvers will return
2740 * them if they get them from DNS.
2742 if (name
[0] == '\0')
2745 tp
= (hashipv6_t
*)g_hash_table_lookup(ipv6_hash_table
, addrp
);
2747 g_strlcpy(tp
->name
, name
, MAXNAMELEN
);
2749 struct e_in6_addr
*addr_key
;
2751 addr_key
= g_new(struct e_in6_addr
,1);
2752 tp
= new_ipv6(addrp
);
2753 memcpy(addr_key
, addrp
, 16);
2754 g_strlcpy(tp
->name
, name
, MAXNAMELEN
);
2755 g_hash_table_insert(ipv6_hash_table
, addr_key
, tp
);
2758 g_strlcpy(tp
->name
, name
, MAXNAMELEN
);
2759 tp
->flags
= tp
->flags
| TRIED_RESOLVE_ADDRESS
;
2760 new_resolved_objects
= TRUE
;
2762 } /* add_ipv6_name */
2765 add_manually_resolved_ipv4(gpointer data
, gpointer user_data _U_
)
2767 resolved_ipv4_t
*resolved_ipv4_entry
= (resolved_ipv4_t
*)data
;
2769 add_ipv4_name(resolved_ipv4_entry
->host_addr
, resolved_ipv4_entry
->name
);
2773 add_manually_resolved_ipv6(gpointer data
, gpointer user_data _U_
)
2775 resolved_ipv6_t
*resolved_ipv6_entry
= (resolved_ipv6_t
*)data
;
2777 add_ipv6_name(&(resolved_ipv6_entry
->ip6_addr
), resolved_ipv6_entry
->name
);
2781 add_manually_resolved(void)
2783 if(manually_resolved_ipv4_list
){
2784 g_slist_foreach(manually_resolved_ipv4_list
, add_manually_resolved_ipv4
, NULL
);
2787 if(manually_resolved_ipv6_list
){
2788 g_slist_foreach(manually_resolved_ipv6_list
, add_manually_resolved_ipv6
, NULL
);
2793 host_name_lookup_init(void)
2798 #ifdef HAVE_GNU_ADNS
2801 static char rootpath_nt
[] = "\\system32\\drivers\\etc\\hosts";
2802 static char rootpath_ot
[] = "\\hosts";
2804 #endif /*GNU_ADNS */
2806 g_assert(ipxnet_hash_table
== NULL
);
2807 ipxnet_hash_table
= g_hash_table_new_full(g_int_hash
, g_int_equal
, g_free
, g_free
);
2809 g_assert(ipv4_hash_table
== NULL
);
2810 ipv4_hash_table
= g_hash_table_new_full(g_int_hash
, g_int_equal
, g_free
, g_free
);
2812 g_assert(ipv6_hash_table
== NULL
);
2813 ipv6_hash_table
= g_hash_table_new_full(ipv6_oat_hash
, ipv6_equal
, g_free
, g_free
);
2816 * Load the global hosts file, if we have one.
2818 if(!gbl_resolv_flags
.load_hosts_file_from_profile_only
){
2819 hostspath
= get_datafile_path(ENAME_HOSTS
);
2820 if (!read_hosts_file(hostspath
) && errno
!= ENOENT
) {
2821 report_open_failure(hostspath
, errno
, FALSE
);
2826 * Load the user's hosts file no matter what, if they have one.
2828 hostspath
= get_persconffile_path(ENAME_HOSTS
, TRUE
);
2829 if (!read_hosts_file(hostspath
) && errno
!= ENOENT
) {
2830 report_open_failure(hostspath
, errno
, FALSE
);
2834 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2835 if (ares_library_init(ARES_LIB_INIT_ALL
) == ARES_SUCCESS
) {
2837 if (ares_init(&ghba_chan
) == ARES_SUCCESS
&& ares_init(&ghbn_chan
) == ARES_SUCCESS
) {
2838 async_dns_initialized
= TRUE
;
2840 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
2844 #ifdef HAVE_GNU_ADNS
2846 * We're using GNU ADNS, which doesn't check the system hosts file;
2847 * we load that file ourselves.
2851 sysroot
= getenv_utf8("WINDIR");
2852 if (sysroot
!= NULL
) {
2854 * The file should be under WINDIR.
2855 * If this is Windows NT (NT 4.0,2K,XP,Server2K3), it's in
2856 * %WINDIR%\system32\drivers\etc\hosts.
2857 * If this is Windows OT (95,98,Me), it's in %WINDIR%\hosts.
2859 * XXX - should we base it on the dwPlatformId value from
2862 if(!gbl_resolv_flags
.load_hosts_file_from_profile_only
){
2863 hostspath
= g_strconcat(sysroot
, rootpath_nt
, NULL
);
2864 if (!read_hosts_file(hostspath
)) {
2866 hostspath
= g_strconcat(sysroot
, rootpath_ot
, NULL
);
2867 read_hosts_file(hostspath
);
2873 if(!gbl_resolv_flags
.load_hosts_file_from_profile_only
){
2874 read_hosts_file("/etc/hosts");
2878 /* XXX - Any flags we should be using? */
2879 /* XXX - We could provide config settings for DNS servers, and
2880 pass them to ADNS with adns_init_strcfg */
2881 if (adns_init(&ads
, adns_if_none
, 0 /*0=>stderr*/) != 0) {
2883 * XXX - should we report the error? I'm assuming that some crashes
2884 * reported on a Windows machine with TCP/IP not configured are due
2885 * to "adns_init()" failing (due to the lack of TCP/IP) and leaving
2886 * ADNS in a state where it crashes due to that. We'll still try
2887 * doing name resolution anyway.
2891 async_dns_initialized
= TRUE
;
2892 async_dns_in_flight
= 0;
2893 #endif /* HAVE_GNU_ADNS */
2894 #endif /* HAVE_C_ARES */
2896 if(extra_hosts_files
&& !gbl_resolv_flags
.load_hosts_file_from_profile_only
){
2897 for (i
= 0; i
< extra_hosts_files
->len
; i
++) {
2898 read_hosts_file((const char *) g_ptr_array_index(extra_hosts_files
, i
));
2902 subnet_name_lookup_init();
2904 add_manually_resolved();
2908 host_name_lookup_cleanup(void)
2910 _host_name_lookup_cleanup();
2912 if(ipxnet_hash_table
){
2913 g_hash_table_destroy(ipxnet_hash_table
);
2914 ipxnet_hash_table
= NULL
;
2917 if(ipv4_hash_table
){
2918 g_hash_table_destroy(ipv4_hash_table
);
2919 ipv4_hash_table
= NULL
;
2922 if(ipv6_hash_table
){
2923 g_hash_table_destroy(ipv6_hash_table
);
2924 ipv6_hash_table
= NULL
;
2927 memset(subnet_length_entries
, 0, sizeof(subnet_length_entries
));
2929 have_subnet_entry
= FALSE
;
2930 new_resolved_objects
= FALSE
;
2934 free_manually_resolved_ipv4(gpointer data
, gpointer user_data _U_
)
2936 resolved_ipv4_t
*resolved_ipv4_entry
= (resolved_ipv4_t
*)data
;
2938 g_free(resolved_ipv4_entry
);
2943 free_manually_resolved_ipv6(gpointer data
, gpointer user_data _U_
)
2945 resolved_ipv6_t
*resolved_ipv6_entry
= (resolved_ipv6_t
*)data
;
2947 g_free(resolved_ipv6_entry
);
2952 manually_resolve_cleanup(void)
2954 if(manually_resolved_ipv4_list
){
2955 g_slist_foreach(manually_resolved_ipv4_list
, free_manually_resolved_ipv4
, NULL
);
2956 g_slist_free(manually_resolved_ipv4_list
);
2957 manually_resolved_ipv4_list
= NULL
;
2960 if(manually_resolved_ipv6_list
){
2961 g_slist_foreach(manually_resolved_ipv6_list
, free_manually_resolved_ipv6
, NULL
);
2962 g_slist_free(manually_resolved_ipv6_list
);
2963 manually_resolved_ipv6_list
= NULL
;
2969 get_udp_port(guint port
)
2972 if (!gbl_resolv_flags
.transport_name
) {
2973 return ep_utoa(port
);
2976 return serv_name_lookup(port
, PT_UDP
);
2978 } /* get_udp_port */
2981 get_dccp_port(guint port
)
2984 if (!gbl_resolv_flags
.transport_name
) {
2985 return ep_utoa(port
);
2988 return serv_name_lookup(port
, PT_DCCP
);
2990 } /* get_dccp_port */
2993 get_tcp_port(guint port
)
2996 if (!gbl_resolv_flags
.transport_name
) {
2997 return ep_utoa(port
);
3000 return serv_name_lookup(port
, PT_TCP
);
3002 } /* get_tcp_port */
3005 get_sctp_port(guint port
)
3008 if (!gbl_resolv_flags
.transport_name
) {
3009 return ep_utoa(port
);
3012 return serv_name_lookup(port
, PT_SCTP
);
3014 } /* get_sctp_port */
3017 get_addr_name(const address
*addr
)
3019 const gchar
*result
;
3021 result
= solve_address_to_name(addr
);
3026 /* if it gets here, either it is of type AT_NONE, */
3027 /* or it should be solvable in address_to_str -unless addr->type is wrongly defined */
3029 if (addr
->type
== AT_NONE
){
3033 /* We need an ephemeral allocated string */
3034 return ep_address_to_str(addr
);
3038 se_get_addr_name(const address
*addr
)
3040 const gchar
*result
;
3042 result
= se_solve_address_to_name(addr
);
3047 /* if it gets here, either it is of type AT_NONE, */
3048 /* or it should be solvable in se_address_to_str -unless addr->type is wrongly defined */
3050 if (addr
->type
== AT_NONE
){
3054 /* We need a "permanently" allocated string */
3055 return se_address_to_str(addr
);
3059 get_addr_name_buf(const address
*addr
, gchar
*buf
, gsize size
)
3061 const gchar
*result
= get_addr_name(addr
);
3063 g_strlcpy(buf
, result
, size
);
3064 } /* get_addr_name_buf */
3068 get_ether_name(const guint8
*addr
)
3071 gboolean resolve
= gbl_resolv_flags
.mac_name
;
3073 tp
= eth_name_lookup(addr
, resolve
);
3075 return resolve
? tp
->resolved_name
: tp
->hexaddr
;
3077 } /* get_ether_name */
3079 /* Look for a (non-dummy) ether name in the hash, and return it if found.
3080 * If it's not found, simply return NULL.
3083 get_ether_name_if_known(const guint8
*addr
)
3087 /* Initialize ether structs if we're the first
3088 * ether-related function called */
3089 if (!gbl_resolv_flags
.mac_name
)
3092 /* eth_name_lookup will create a (resolved) hash entry if it doesn't exist */
3093 tp
= eth_name_lookup(addr
, TRUE
);
3094 g_assert(tp
!= NULL
);
3096 if (tp
->status
== HASHETHER_STATUS_RESOLVED_NAME
) {
3097 /* Name is from an ethers file (or is a "well-known" MAC address name from the manuf file) */
3098 return tp
->resolved_name
;
3101 /* Name was created */
3107 get_ether_addr(const gchar
*name
)
3110 /* force resolution (do not check gbl_resolv_flags) */
3111 return eth_addr_lookup(name
);
3113 } /* get_ether_addr */
3116 add_ether_byip(const guint ip
, const guint8
*eth
)
3121 /* first check that IP address can be resolved */
3122 if (!gbl_resolv_flags
.network_name
)
3125 tp
= host_lookup(ip
, &found
);
3127 /* ok, we can add this entry in the ethers hashtable */
3128 add_eth_name(eth
, tp
->name
);
3131 } /* add_ether_byip */
3134 get_ipxnet_name(const guint32 addr
)
3137 if (!gbl_resolv_flags
.network_name
) {
3138 return ipxnet_to_str_punct(addr
, '\0');
3141 return ipxnet_name_lookup(addr
);
3143 } /* get_ipxnet_name */
3146 get_ipxnet_addr(const gchar
*name
, gboolean
*known
)
3151 /* force resolution (do not check gbl_resolv_flags) */
3152 addr
= ipxnet_addr_lookup(name
, &success
);
3157 } /* get_ipxnet_addr */
3160 get_manuf_name(const guint8
*addr
)
3166 /* manuf needs only the 3 most significant octets of the ethernet address */
3167 manuf_key
= addr
[0];
3168 manuf_key
= manuf_key
<<8;
3170 manuf_key
= manuf_key
| oct
;
3171 manuf_key
= manuf_key
<<8;
3173 manuf_key
= manuf_key
| oct
;
3175 if (!gbl_resolv_flags
.mac_name
|| ((cur
= (gchar
*)g_hash_table_lookup(manuf_hashtable
, &manuf_key
)) == NULL
)) {
3176 cur
=ep_strdup_printf("%02x:%02x:%02x", addr
[0], addr
[1], addr
[2]);
3182 } /* get_manuf_name */
3185 uint_get_manuf_name(const guint oid
)
3189 addr
[0] = (oid
>> 16) & 0xFF;
3190 addr
[1] = (oid
>> 8) & 0xFF;
3191 addr
[2] = (oid
>> 0) & 0xFF;
3192 return get_manuf_name(addr
);
3196 tvb_get_manuf_name(tvbuff_t
*tvb
, gint offset
)
3198 return get_manuf_name(tvb_get_ptr(tvb
, offset
, 3));
3202 get_manuf_name_if_known(const guint8
*addr
)
3208 /* manuf needs only the 3 most significant octets of the ethernet address */
3209 manuf_key
= addr
[0];
3210 manuf_key
= manuf_key
<<8;
3212 manuf_key
= manuf_key
| oct
;
3213 manuf_key
= manuf_key
<<8;
3215 manuf_key
= manuf_key
| oct
;
3217 if ((cur
= (gchar
*)g_hash_table_lookup(manuf_hashtable
, &manuf_key
)) == NULL
) {
3223 } /* get_manuf_name_if_known */
3226 uint_get_manuf_name_if_known(const guint manuf_key
)
3230 if ((cur
= (gchar
*)g_hash_table_lookup(manuf_hashtable
, &manuf_key
)) == NULL
) {
3238 tvb_get_manuf_name_if_known(tvbuff_t
*tvb
, gint offset
)
3240 return get_manuf_name_if_known(tvb_get_ptr(tvb
, offset
, 3));
3244 get_eui64_name(const guint64 addr_eui64
)
3247 guint8
*addr
= (guint8
*)ep_alloc(8);
3249 /* Copy and convert the address to network byte order. */
3250 *(guint64
*)(void *)(addr
) = pntoh64(&(addr_eui64
));
3252 if (!gbl_resolv_flags
.mac_name
|| ((name
= manuf_name_lookup(addr
)) == NULL
)) {
3253 cur
=ep_strdup_printf("%02x:%02x:%02x%02x:%02x:%02x%02x:%02x", addr
[0], addr
[1], addr
[2], addr
[3], addr
[4], addr
[5], addr
[6], addr
[7]);
3256 cur
=ep_strdup_printf("%s_%02x:%02x:%02x:%02x:%02x", name
, addr
[3], addr
[4], addr
[5], addr
[6], addr
[7]);
3259 } /* get_eui64_name */
3263 get_eui64_name_if_known(const guint64 addr_eui64
)
3266 guint8
*addr
= (guint8
*)ep_alloc(8);
3268 /* Copy and convert the address to network byte order. */
3269 *(guint64
*)(void *)(addr
) = pntoh64(&(addr_eui64
));
3271 if ((name
= manuf_name_lookup(addr
)) == NULL
) {
3275 cur
=ep_strdup_printf("%s_%02x:%02x:%02x:%02x:%02x", name
, addr
[3], addr
[4], addr
[5], addr
[6], addr
[7]);
3278 } /* get_eui64_name_if_known */
3281 #define GHI_TIMEOUT (250 * 1000)
3286 #if ( ( ARES_VERSION_MAJOR < 1 ) \
3287 || ( 1 == ARES_VERSION_MAJOR && ARES_VERSION_MINOR < 5 ) )
3296 * XXX - If we wanted to be really fancy we could cache results here and
3297 * look them up in get_host_ipaddr* below.
3299 async_hostent_t
*ahp
= (async_hostent_t
*)arg
;
3300 if (status
== ARES_SUCCESS
&& hp
&& ahp
&& hp
->h_length
== ahp
->addr_size
) {
3301 memcpy(ahp
->addrp
, hp
->h_addr
, hp
->h_length
);
3302 ahp
->copied
= hp
->h_length
;
3305 #endif /* HAVE_C_ARES */
3307 /* Translate a string, assumed either to be a dotted-quad IP address or
3308 * a host name, to a numeric IP address. Return TRUE if we succeed and
3309 * set "*addrp" to that numeric IP address; return FALSE if we fail.
3310 * Used more in the dfilter parser rather than in packet dissectors */
3312 get_host_ipaddr(const char *host
, guint32
*addrp
)
3314 struct in_addr ipaddr
;
3316 struct timeval tv
= { 0, GHI_TIMEOUT
}, *tvp
;
3319 async_hostent_t ahe
;
3320 #else /* HAVE_C_ARES */
3322 #endif /* HAVE_C_ARES */
3325 * don't change it to inet_pton(AF_INET), they are not 100% compatible.
3326 * inet_pton(AF_INET) does not support hexadecimal notation nor
3327 * less-than-4 octet notation.
3329 if (!inet_aton(host
, &ipaddr
)) {
3331 /* It's not a valid dotted-quad IP address; is it a valid
3335 /* If we're not allowed to do name resolution, don't do name
3338 if (!gbl_resolv_flags
.network_name
||
3339 !gbl_resolv_flags
.use_external_net_name_resolver
) {
3344 if (! (gbl_resolv_flags
.concurrent_dns
) ||
3345 name_resolve_concurrency
< 1 ||
3346 ! async_dns_initialized
) {
3349 ahe
.addr_size
= (int) sizeof (struct in_addr
);
3352 ares_gethostbyname(ghbn_chan
, host
, AF_INET
, c_ares_ghi_cb
, &ahe
);
3355 nfds
= ares_fds(ghbn_chan
, &rfds
, &wfds
);
3357 tvp
= ares_timeout(ghbn_chan
, &tv
, &tv
);
3358 if (select(nfds
, &rfds
, &wfds
, NULL
, tvp
) == -1) { /* call to select() failed */
3359 fprintf(stderr
, "Warning: call to select() failed, error is %s\n", strerror(errno
));
3362 ares_process(ghbn_chan
, &rfds
, &wfds
);
3364 ares_cancel(ghbn_chan
);
3365 if (ahe
.addr_size
== ahe
.copied
) {
3369 #else /* ! HAVE_C_ARES */
3370 hp
= gethostbyname(host
);
3374 /* Apparently, some versions of gethostbyaddr can
3375 * return IPv6 addresses. */
3376 } else if (hp
->h_length
<= (int) sizeof (struct in_addr
)) {
3377 memcpy(&ipaddr
, hp
->h_addr
, hp
->h_length
);
3381 #endif /* HAVE_C_ARES */
3383 /* Does the string really contain dotted-quad IP?
3384 * Check against inet_atons that accept strings such as
3385 * "130.230" as valid addresses and try to convert them
3386 * to some form of a classful (host.net) notation.
3388 unsigned int a0
, a1
, a2
, a3
;
3389 if (sscanf(host
, "%u.%u.%u.%u", &a0
, &a1
, &a2
, &a3
) != 4)
3393 *addrp
= ipaddr
.s_addr
;
3398 * Translate IPv6 numeric address or FQDN hostname, into binary IPv6 address.
3399 * Return TRUE if we succeed and set "*addrp" to that numeric IP address;
3400 * return FALSE if we fail.
3403 get_host_ipaddr6(const char *host
, struct e_in6_addr
*addrp
)
3406 struct timeval tv
= { 0, GHI_TIMEOUT
}, *tvp
;
3409 async_hostent_t ahe
;
3410 #elif defined(HAVE_GETHOSTBYNAME2)
3412 #endif /* HAVE_C_ARES */
3414 if (inet_pton(AF_INET6
, host
, addrp
) > 0)
3417 /* It's not a valid dotted-quad IP address; is it a valid
3421 /* If we're not allowed to do name resolution, don't do name
3424 if (!gbl_resolv_flags
.network_name
||
3425 !gbl_resolv_flags
.use_external_net_name_resolver
) {
3431 if (! (gbl_resolv_flags
.concurrent_dns
) ||
3432 name_resolve_concurrency
< 1 ||
3433 ! async_dns_initialized
) {
3436 ahe
.addr_size
= (int) sizeof (struct e_in6_addr
);
3439 ares_gethostbyname(ghbn_chan
, host
, AF_INET6
, c_ares_ghi_cb
, &ahe
);
3442 nfds
= ares_fds(ghbn_chan
, &rfds
, &wfds
);
3444 tvp
= ares_timeout(ghbn_chan
, &tv
, &tv
);
3445 if (select(nfds
, &rfds
, &wfds
, NULL
, tvp
) == -1) { /* call to select() failed */
3446 fprintf(stderr
, "Warning: call to select() failed, error is %s\n", strerror(errno
));
3449 ares_process(ghbn_chan
, &rfds
, &wfds
);
3451 ares_cancel(ghbn_chan
);
3452 if (ahe
.addr_size
== ahe
.copied
) {
3455 #elif defined(HAVE_GETHOSTBYNAME2)
3456 hp
= gethostbyname2(host
, AF_INET6
);
3457 if (hp
!= NULL
&& hp
->h_length
== sizeof(struct e_in6_addr
)) {
3458 memcpy(addrp
, hp
->h_addr
, hp
->h_length
);
3467 * Find out whether a hostname resolves to an ip or ipv6 address
3468 * Return "ip6" if it is IPv6, "ip" otherwise (including the case
3469 * that we don't know)
3471 const char* host_ip_af(const char *host
3472 #ifndef HAVE_GETHOSTBYNAME2
3477 #ifdef HAVE_GETHOSTBYNAME2
3479 return (h
= gethostbyname2(host
, AF_INET6
)) && h
->h_addrtype
== AF_INET6
? "ip6" : "ip";
3486 get_manuf_hashtable(void)
3488 return manuf_hashtable
;
3492 get_wka_hashtable(void)
3494 return wka_hashtable
;
3498 get_eth_hashtable(void)
3500 return eth_hashtable
;
3504 get_serv_port_hashtable(void)
3506 return serv_port_hashtable
;
3510 get_ipxnet_hash_table(void)
3512 return ipxnet_hash_table
;
3516 get_ipv4_hash_table(void)
3518 return ipv4_hash_table
;
3522 get_ipv6_hash_table(void)
3524 return ipv6_hash_table
;
3526 /* Initialize all the address resolution subsystems in this file */
3528 addr_resolv_init(void)
3530 initialize_services();
3531 initialize_ethers();
3532 initialize_ipxnets();
3533 /* host name initialization is done on a per-capture-file basis */
3534 /*host_name_lookup_init();*/
3537 /* Clean up all the address resolution subsystems in this file */
3539 addr_resolv_cleanup(void)
3541 service_name_lookup_cleanup();
3542 eth_name_lookup_cleanup();
3543 ipx_name_lookup_cleanup();
3544 /* host name initialization is done on a per-capture-file basis */
3545 /*host_name_lookup_cleanup();*/
3549 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3554 * indent-tabs-mode: nil
3557 * vi: set shiftwidth=4 tabstop=8 expandtab:
3558 * :indentSize=4:tabSize=8:noTabs=true: