]>
git.saurik.com Git - apple/network_cmds.git/blob - tcpdump.tproj/addrtoname.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
25 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
26 * The Regents of the University of California. All rights reserved.
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that: (1) source code distributions
30 * retain the above copyright notice and this paragraph in its entirety, (2)
31 * distributions including binary code include the above copyright notice and
32 * this paragraph in its entirety in the documentation or other materials
33 * provided with the distribution, and (3) all advertising materials mentioning
34 * features or use of this software display the following acknowledgement:
35 * ``This product includes software developed by the University of California,
36 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
37 * the University nor the names of its contributors may be used to endorse
38 * or promote products derived from this software without specific prior
40 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
41 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
42 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
44 * Internet, ethernet, port, and protocol string to address
45 * and address to string conversion routines
48 static const char rcsid
[] =
49 "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/addrtoname.c,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL)";
52 #include <sys/types.h>
53 #include <sys/socket.h>
62 #include <netinet/in.h>
63 #include <netinet/if_ether.h>
65 #include <arpa/inet.h>
70 #include <pcap-namedb.h>
77 #include "interface.h"
78 #include "addrtoname.h"
82 static RETSIGTYPE
nohostname(int);
85 * hash tables for whatever-to-name translations
88 #define HASHNAMESIZE 4096
96 struct hnamemem hnametable
[HASHNAMESIZE
];
97 struct hnamemem tporttable
[HASHNAMESIZE
];
98 struct hnamemem uporttable
[HASHNAMESIZE
];
99 struct hnamemem eprototable
[HASHNAMESIZE
];
100 struct hnamemem dnaddrtable
[HASHNAMESIZE
];
101 struct hnamemem llcsaptable
[HASHNAMESIZE
];
108 u_char
*e_nsap
; /* used only for nsaptable[] */
109 struct enamemem
*e_nxt
;
112 struct enamemem enametable
[HASHNAMESIZE
];
113 struct enamemem nsaptable
[HASHNAMESIZE
];
119 struct protoidmem
*p_nxt
;
122 struct protoidmem protoidtable
[HASHNAMESIZE
];
125 * A faster replacement for inet_ntoa().
128 intoa(u_int32_t addr
)
133 static char buf
[sizeof(".xxx.xxx.xxx.xxx")];
136 cp
= &buf
[sizeof buf
];
142 *--cp
= byte
% 10 + '0';
145 *--cp
= byte
% 10 + '0';
157 static u_int32_t f_netmask
;
158 static u_int32_t f_localnet
;
159 static u_int32_t netmask
;
162 * "getname" is written in this atrocious way to make sure we don't
163 * wait forever while trying to get hostnames from yp.
170 nohostname(int signo
)
172 longjmp(getname_env
, 1);
176 * Return a name for the IP address pointed to by ap. This address
177 * is assumed to be in network byte order.
180 getname(const u_char
*ap
)
182 register struct hostent
*hp
;
184 static struct hnamemem
*p
; /* static for longjmp() */
187 addr
= *(const u_int32_t
*)ap
;
190 * Extract 32 bits in network order, dealing with alignment.
192 switch ((long)ap
& 3) {
195 addr
= *(u_int32_t
*)ap
;
199 #ifdef WORDS_BIGENDIAN
200 addr
= ((u_int32_t
)*(u_short
*)ap
<< 16) |
201 (u_int32_t
)*(u_short
*)(ap
+ 2);
203 addr
= ((u_int32_t
)*(u_short
*)(ap
+ 2) << 16) |
204 (u_int32_t
)*(u_short
*)ap
;
209 #ifdef WORDS_BIGENDIAN
210 addr
= ((u_int32_t
)ap
[0] << 24) |
211 ((u_int32_t
)ap
[1] << 16) |
212 ((u_int32_t
)ap
[2] << 8) |
215 addr
= ((u_int32_t
)ap
[3] << 24) |
216 ((u_int32_t
)ap
[2] << 16) |
217 ((u_int32_t
)ap
[1] << 8) |
223 p
= &hnametable
[addr
& (HASHNAMESIZE
-1)];
224 for (; p
->nxt
; p
= p
->nxt
) {
229 p
->nxt
= newhnamemem();
232 * Only print names when:
233 * (1) -n was not given.
234 * (2) Address is foreign and -f was given. If -f was not
235 * present, f_netmask and f_local are 0 and the second
237 * (3) The host portion is not 0 (i.e., a network address).
238 * (4) The host portion is not broadcast.
240 if (!nflag
&& (addr
& f_netmask
) == f_localnet
241 && (addr
&~ netmask
) != 0 && (addr
| netmask
) != 0xffffffff) {
242 if (!setjmp(getname_env
)) {
243 (void)signal(SIGALRM
, nohostname
);
245 hp
= gethostbyaddr((char *)&addr
, 4, AF_INET
);
250 p
->name
= savestr(hp
->h_name
);
252 /* Remove domain qualifications */
253 dotp
= strchr(p
->name
, '.');
261 p
->name
= savestr(intoa(addr
));
265 static char hex
[] = "0123456789abcdef";
268 /* Find the hash node that corresponds the ether address 'ep' */
270 static inline struct enamemem
*
271 lookup_emem(const u_char
*ep
)
273 register u_int i
, j
, k
;
276 k
= (ep
[0] << 8) | ep
[1];
277 j
= (ep
[2] << 8) | ep
[3];
278 i
= (ep
[4] << 8) | ep
[5];
280 tp
= &enametable
[(i
^ j
) & (HASHNAMESIZE
-1)];
282 if (tp
->e_addr0
== i
&&
291 tp
->e_nxt
= (struct enamemem
*)calloc(1, sizeof(*tp
));
292 if (tp
->e_nxt
== NULL
)
293 error("lookup_emem: calloc");
298 /* Find the hash node that corresponds the NSAP 'nsap' */
300 static inline struct enamemem
*
301 lookup_nsap(register const u_char
*nsap
)
303 register u_int i
, j
, k
;
306 const u_char
*ensap
= nsap
+ nlen
- 6;
309 k
= (ensap
[0] << 8) | ensap
[1];
310 j
= (ensap
[2] << 8) | ensap
[3];
311 i
= (ensap
[4] << 8) | ensap
[5];
316 tp
= &nsaptable
[(i
^ j
) & (HASHNAMESIZE
-1)];
318 if (tp
->e_addr0
== i
&&
321 tp
->e_nsap
[0] == nlen
&&
322 memcmp((char *)&(nsap
[1]),
323 (char *)&(tp
->e_nsap
[1]), nlen
) == 0)
330 tp
->e_nsap
= (u_char
*)malloc(nlen
+ 1);
331 if (tp
->e_nsap
== NULL
)
332 error("lookup_nsap: malloc");
333 memcpy(tp
->e_nsap
, nsap
, nlen
+ 1);
334 tp
->e_nxt
= (struct enamemem
*)calloc(1, sizeof(*tp
));
335 if (tp
->e_nxt
== NULL
)
336 error("lookup_nsap: calloc");
341 /* Find the hash node that corresponds the protoid 'pi'. */
343 static inline struct protoidmem
*
344 lookup_protoid(const u_char
*pi
)
347 struct protoidmem
*tp
;
349 /* 5 octets won't be aligned */
350 i
= (((pi
[0] << 8) + pi
[1]) << 8) + pi
[2];
351 j
= (pi
[3] << 8) + pi
[4];
352 /* XXX should be endian-insensitive, but do big-endian testing XXX */
354 tp
= &protoidtable
[(i
^ j
) & (HASHNAMESIZE
-1)];
356 if (tp
->p_oui
== i
&& tp
->p_proto
== j
)
362 tp
->p_nxt
= (struct protoidmem
*)calloc(1, sizeof(*tp
));
363 if (tp
->p_nxt
== NULL
)
364 error("lookup_protoid: calloc");
370 etheraddr_string(register const u_char
*ep
)
374 register struct enamemem
*tp
;
375 char buf
[sizeof("00:00:00:00:00:00")];
377 tp
= lookup_emem(ep
);
380 #ifdef HAVE_ETHER_NTOHOST
383 if (ether_ntohost(buf
, (struct ether_addr
*)ep
) == 0) {
384 tp
->e_name
= savestr(buf
);
390 if ((j
= *ep
>> 4) != 0)
392 *cp
++ = hex
[*ep
++ & 0xf];
393 for (i
= 5; (int)--i
>= 0;) {
395 if ((j
= *ep
>> 4) != 0)
397 *cp
++ = hex
[*ep
++ & 0xf];
400 tp
->e_name
= savestr(buf
);
405 etherproto_string(u_short port
)
408 register struct hnamemem
*tp
;
409 register u_int32_t i
= port
;
410 char buf
[sizeof("0000")];
412 for (tp
= &eprototable
[i
& (HASHNAMESIZE
-1)]; tp
->nxt
; tp
= tp
->nxt
)
417 tp
->nxt
= newhnamemem();
421 *cp
++ = hex
[port
>> 12 & 0xf];
422 *cp
++ = hex
[port
>> 8 & 0xf];
423 *cp
++ = hex
[port
>> 4 & 0xf];
424 *cp
++ = hex
[port
& 0xf];
426 tp
->name
= savestr(buf
);
431 protoid_string(register const u_char
*pi
)
435 register struct protoidmem
*tp
;
436 char buf
[sizeof("00:00:00:00:00")];
438 tp
= lookup_protoid(pi
);
443 if ((j
= *pi
>> 4) != 0)
445 *cp
++ = hex
[*pi
++ & 0xf];
446 for (i
= 4; (int)--i
>= 0;) {
448 if ((j
= *pi
>> 4) != 0)
450 *cp
++ = hex
[*pi
++ & 0xf];
453 tp
->p_name
= savestr(buf
);
458 llcsap_string(u_char sap
)
461 register struct hnamemem
*tp
;
462 register u_int32_t i
= sap
;
463 char buf
[sizeof("sap 00")];
465 for (tp
= &llcsaptable
[i
& (HASHNAMESIZE
-1)]; tp
->nxt
; tp
= tp
->nxt
)
470 tp
->nxt
= newhnamemem();
473 (void)strcpy(cp
, "sap ");
475 *cp
++ = hex
[sap
>> 4 & 0xf];
476 *cp
++ = hex
[sap
& 0xf];
478 tp
->name
= savestr(buf
);
483 isonsap_string(const u_char
*nsap
)
485 register u_int i
, nlen
= nsap
[0];
487 register struct enamemem
*tp
;
489 tp
= lookup_nsap(nsap
);
493 tp
->e_name
= cp
= (char *)malloc(nlen
* 2 + 2);
495 error("isonsap_string: malloc");
499 for (i
= nlen
; (int)--i
>= 0;) {
500 *cp
++ = hex
[*nsap
>> 4];
501 *cp
++ = hex
[*nsap
++ & 0xf];
508 tcpport_string(u_short port
)
510 register struct hnamemem
*tp
;
511 register u_int32_t i
= port
;
512 char buf
[sizeof("00000")];
514 for (tp
= &tporttable
[i
& (HASHNAMESIZE
-1)]; tp
->nxt
; tp
= tp
->nxt
)
519 tp
->nxt
= newhnamemem();
521 (void)sprintf(buf
, "%u", i
);
522 tp
->name
= savestr(buf
);
527 udpport_string(register u_short port
)
529 register struct hnamemem
*tp
;
530 register u_int32_t i
= port
;
531 char buf
[sizeof("00000")];
533 for (tp
= &uporttable
[i
& (HASHNAMESIZE
-1)]; tp
->nxt
; tp
= tp
->nxt
)
538 tp
->nxt
= newhnamemem();
540 (void)sprintf(buf
, "%u", i
);
541 tp
->name
= savestr(buf
);
549 register struct hnamemem
*table
;
551 char buf
[sizeof("0000000000")];
553 while ((sv
= getservent()) != NULL
) {
554 int port
= ntohs(sv
->s_port
);
555 i
= port
& (HASHNAMESIZE
-1);
556 if (strcmp(sv
->s_proto
, "tcp") == 0)
557 table
= &tporttable
[i
];
558 else if (strcmp(sv
->s_proto
, "udp") == 0)
559 table
= &uporttable
[i
];
566 (void)sprintf(buf
, "%d", port
);
567 table
->name
= savestr(buf
);
569 table
->name
= savestr(sv
->s_name
);
571 table
->nxt
= newhnamemem();
576 /*XXX from libbpfc.a */
577 extern struct eproto
{
583 init_eprotoarray(void)
586 register struct hnamemem
*table
;
588 for (i
= 0; eproto_db
[i
].s
; i
++) {
589 int j
= ntohs(eproto_db
[i
].p
) & (HASHNAMESIZE
-1);
590 table
= &eprototable
[j
];
593 table
->name
= eproto_db
[i
].s
;
594 table
->addr
= ntohs(eproto_db
[i
].p
);
595 table
->nxt
= newhnamemem();
600 * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet
604 init_protoidarray(void)
607 register struct protoidmem
*tp
;
613 for (i
= 0; eproto_db
[i
].s
; i
++) {
614 u_short etype
= htons(eproto_db
[i
].p
);
616 memcpy((char *)&protoid
[3], (char *)&etype
, 2);
617 tp
= lookup_protoid(protoid
);
618 tp
->p_name
= savestr(eproto_db
[i
].s
);
622 static struct etherlist
{
626 {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" },
627 {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL
}
631 * Initialize the ethers hash table. We take two different approaches
632 * depending on whether or not the system provides the ethers name
633 * service. If it does, we just wire in a few names at startup,
634 * and etheraddr_string() fills in the table on demand. If it doesn't,
635 * then we suck in the entire /etc/ethers file at startup. The idea
636 * is that parsing the local file will be fast, but spinning through
637 * all the ethers entries via NIS & next_etherent might be very slow.
639 * XXX pcap_next_etherent doesn't belong in the pcap interface, but
640 * since the pcap module already does name-to-address translation,
641 * it's already does most of the work for the ethernet address-to-name
642 * translation, so we just pcap_next_etherent as a convenience.
645 init_etherarray(void)
647 register struct etherlist
*el
;
648 register struct enamemem
*tp
;
649 #ifdef HAVE_ETHER_NTOHOST
652 register struct pcap_etherent
*ep
;
655 /* Suck in entire ethers file */
656 fp
= fopen(PCAP_ETHERS_FILE
, "r");
658 while ((ep
= pcap_next_etherent(fp
)) != NULL
) {
659 tp
= lookup_emem(ep
->addr
);
660 tp
->e_name
= savestr(ep
->name
);
666 /* Hardwire some ethernet names */
667 for (el
= etherlist
; el
->name
!= NULL
; ++el
) {
668 tp
= lookup_emem(el
->addr
);
669 /* Don't override existing name */
670 if (tp
->e_name
!= NULL
)
673 #ifdef HAVE_ETHER_NTOHOST
674 /* Use yp/nis version of name if available */
675 if (ether_ntohost(name
, (struct ether_addr
*)el
->addr
) == 0) {
676 tp
->e_name
= savestr(name
);
680 tp
->e_name
= el
->name
;
684 static struct tok llcsap_db
[] = {
685 { LLCSAP_NULL
, "null" },
686 { LLCSAP_8021B_I
, "802.1b-gsap" },
687 { LLCSAP_8021B_G
, "802.1b-isap" },
688 { LLCSAP_IP
, "ip-sap" },
689 { LLCSAP_PROWAYNM
, "proway-nm" },
690 { LLCSAP_8021D
, "802.1d" },
691 { LLCSAP_RS511
, "eia-rs511" },
692 { LLCSAP_ISO8208
, "x.25/llc2" },
693 { LLCSAP_PROWAY
, "proway" },
694 { LLCSAP_ISONS
, "iso-clns" },
695 { LLCSAP_GLOBAL
, "global" },
700 init_llcsaparray(void)
703 register struct hnamemem
*table
;
705 for (i
= 0; llcsap_db
[i
].s
!= NULL
; i
++) {
706 table
= &llcsaptable
[llcsap_db
[i
].v
];
709 table
->name
= llcsap_db
[i
].s
;
710 table
->addr
= llcsap_db
[i
].v
;
711 table
->nxt
= newhnamemem();
716 * Initialize the address to name translation machinery. We map all
717 * non-local IP addresses to numeric addresses if fflag is true (i.e.,
718 * to prevent blocking on the nameserver). localnet is the IP address
719 * of the local network. mask is its subnet mask.
722 init_addrtoname(int fflag
, u_int32_t localnet
, u_int32_t mask
)
726 f_localnet
= localnet
;
731 * Simplest way to suppress names.
743 dnaddr_string(u_short dnaddr
)
745 register struct hnamemem
*tp
;
747 for (tp
= &dnaddrtable
[dnaddr
& (HASHNAMESIZE
-1)]; tp
->nxt
!= 0;
749 if (tp
->addr
== dnaddr
)
753 tp
->nxt
= newhnamemem();
755 tp
->name
= dnnum_string(dnaddr
);
757 tp
->name
= dnname_string(dnaddr
);
762 /* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */
766 register struct hnamemem
*p
;
767 static struct hnamemem
*ptr
= NULL
;
768 static u_int num
= 0;
772 ptr
= (struct hnamemem
*)calloc(num
, sizeof (*ptr
));
774 error("newhnamemem: calloc");