Deleted Added
full compact
addrtoname.c (17681) addrtoname.c (17688)
1/*
2 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * Internet, ethernet, port, and protocol string to address
22 * and address to string conversion routines
23 */
24#ifndef lint
25static char rcsid[] =
26 "@(#) $Header: addrtoname.c,v 1.49 96/07/02 00:19:35 leres Exp $ (LBL)";
27#endif
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <sys/time.h>
32
33#if __STDC__
34struct mbuf;
35struct rtentry;
36#endif
37#include <net/if.h>
38
39#include <netinet/in.h>
40#include <netinet/if_ether.h>
41
42#include <arpa/inet.h>
43
44#include <ctype.h>
45#include <netdb.h>
46#include <pcap.h>
47#include <pcap-namedb.h>
48#include <signal.h>
49#include <stdio.h>
50#include <string.h>
51#include <stdlib.h>
52#include <unistd.h>
53
54#include "interface.h"
55#include "addrtoname.h"
56#include "llc.h"
57
58/* Forwards */
59static RETSIGTYPE nohostname(int);
60
61/*
62 * hash tables for whatever-to-name translations
63 */
64
65#define HASHNAMESIZE 4096
66
67struct hnamemem {
68 u_int32_t addr;
69 char *name;
70 struct hnamemem *nxt;
71};
72
73struct hnamemem hnametable[HASHNAMESIZE];
74struct hnamemem tporttable[HASHNAMESIZE];
75struct hnamemem uporttable[HASHNAMESIZE];
76struct hnamemem eprototable[HASHNAMESIZE];
77struct hnamemem dnaddrtable[HASHNAMESIZE];
78struct hnamemem llcsaptable[HASHNAMESIZE];
79
80struct enamemem {
81 u_short e_addr0;
82 u_short e_addr1;
83 u_short e_addr2;
84 char *e_name;
85 u_char *e_nsap; /* used only for nsaptable[] */
86 struct enamemem *e_nxt;
87};
88
89struct enamemem enametable[HASHNAMESIZE];
90struct enamemem nsaptable[HASHNAMESIZE];
91
92struct protoidmem {
93 u_int32_t p_oui;
94 u_short p_proto;
95 char *p_name;
96 struct protoidmem *p_nxt;
97};
98
99struct protoidmem protoidtable[HASHNAMESIZE];
100
101/*
102 * A faster replacement for inet_ntoa().
103 */
104char *
105intoa(u_int32_t addr)
106{
107 register char *cp;
108 register u_int byte;
109 register int n;
110 static char buf[sizeof(".xxx.xxx.xxx.xxx")];
111
112 NTOHL(addr);
113 cp = &buf[sizeof buf];
114 *--cp = '\0';
115
116 n = 4;
117 do {
118 byte = addr & 0xff;
119 *--cp = byte % 10 + '0';
120 byte /= 10;
121 if (byte > 0) {
122 *--cp = byte % 10 + '0';
123 byte /= 10;
124 if (byte > 0)
125 *--cp = byte + '0';
126 }
127 *--cp = '.';
128 addr >>= 8;
129 } while (--n > 0);
130
131 return cp + 1;
132}
133
134static u_int32_t f_netmask;
135static u_int32_t f_localnet;
136static u_int32_t netmask;
137
138/*
139 * "getname" is written in this atrocious way to make sure we don't
140 * wait forever while trying to get hostnames from yp.
141 */
142#include <setjmp.h>
143
144jmp_buf getname_env;
145
146static RETSIGTYPE
147nohostname(int signo)
148{
149 longjmp(getname_env, 1);
150}
151
152/*
153 * Return a name for the IP address pointed to by ap. This address
154 * is assumed to be in network byte order.
155 */
156char *
157getname(const u_char *ap)
158{
159 register struct hostent *hp;
160 u_int32_t addr;
161 static struct hnamemem *p; /* static for longjmp() */
162
163#ifndef LBL_ALIGN
164 addr = *(const u_int32_t *)ap;
165#else
166 /*
167 * Deal with alignment.
168 */
169 switch ((long)ap & 3) {
170
171 case 0:
172 addr = *(u_int32_t *)ap;
173 break;
174
175 case 2:
176#if BYTE_ORDER == LITTLE_ENDIAN
177 addr = ((u_int32_t)*(u_short *)(ap + 2) << 16) |
178 (u_int32_t)*(u_short *)ap;
179#else
180 addr = ((u_int32_t)*(u_short *)ap << 16) |
181 (u_int32_t)*(u_short *)(ap + 2);
182#endif
183 break;
184
185 default:
186#if BYTE_ORDER == LITTLE_ENDIAN
187 addr = ((u_int32_t)ap[3] << 24) |
188 ((u_int32_t)ap[2] << 16) |
189 ((u_int32_t)ap[1] << 8) |
190 (u_int32_t)ap[0];
191#else
192 addr = ((u_int32_t)ap[0] << 24) |
193 ((u_int32_t)ap[1] << 16) |
194 ((u_int32_t)ap[2] << 8) |
195 (u_int32_t)ap[3];
196#endif
197 break;
198 }
199#endif
200 p = &hnametable[addr & (HASHNAMESIZE-1)];
201 for (; p->nxt; p = p->nxt) {
202 if (p->addr == addr)
203 return (p->name);
204 }
205 p->addr = addr;
206 p->nxt = newhnamemem();
207
208 /*
209 * Only print names when:
210 * (1) -n was not given.
211 * (2) Address is foreign and -f was given. If -f was not
212 * present, f_netmask and f_local are 0 and the second
213 * test will succeed.
214 * (3) The host portion is not 0 (i.e., a network address).
215 * (4) The host portion is not broadcast.
216 */
217 if (!nflag && (addr & f_netmask) == f_localnet
218 && (addr &~ netmask) != 0 && (addr | netmask) != 0xffffffff) {
219 if (!setjmp(getname_env)) {
220 (void)signal(SIGALRM, nohostname);
221 (void)alarm(20);
222 hp = gethostbyaddr((char *)&addr, 4, AF_INET);
223 (void)alarm(0);
224 if (hp) {
225 char *dotp;
226
227 p->name = savestr(hp->h_name);
228 if (Nflag) {
229 /* Remove domain qualifications */
230 dotp = strchr(p->name, '.');
231 if (dotp)
232 *dotp = '\0';
233 }
234 return (p->name);
235 }
236 }
237 }
238 p->name = savestr(intoa(addr));
239 return (p->name);
240}
241
242static char hex[] = "0123456789abcdef";
243
244
245/* Find the hash node that corresponds the ether address 'ep' */
246
247static inline struct enamemem *
248lookup_emem(const u_char *ep)
249{
250 register u_int i, j, k;
251 struct enamemem *tp;
252
253 k = (ep[0] << 8) | ep[1];
254 j = (ep[2] << 8) | ep[3];
255 i = (ep[4] << 8) | ep[5];
256
257 tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)];
258 while (tp->e_nxt)
259 if (tp->e_addr0 == i &&
260 tp->e_addr1 == j &&
261 tp->e_addr2 == k)
262 return tp;
263 else
264 tp = tp->e_nxt;
265 tp->e_addr0 = i;
266 tp->e_addr1 = j;
267 tp->e_addr2 = k;
268 tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
269 if (tp->e_nxt == NULL)
270 error("lookup_emem: calloc");
271
272 return tp;
273}
274
275/* Find the hash node that corresponds the NSAP 'nsap' */
276
277static inline struct enamemem *
278lookup_nsap(register const u_char *nsap)
279{
280 register u_int i, j, k;
281 int nlen = *nsap;
282 struct enamemem *tp;
283 const u_char *ensap = nsap + nlen - 6;
284
285 if (nlen > 6) {
286 k = (ensap[0] << 8) | ensap[1];
287 j = (ensap[2] << 8) | ensap[3];
288 i = (ensap[4] << 8) | ensap[5];
289 }
290 else
291 i = j = k = 0;
292
293 tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)];
294 while (tp->e_nxt)
295 if (tp->e_addr0 == i &&
296 tp->e_addr1 == j &&
297 tp->e_addr2 == k &&
298 tp->e_nsap[0] == nlen &&
299 memcmp((char *)&(nsap[1]),
300 (char *)&(tp->e_nsap[1]), nlen) == 0)
301 return tp;
302 else
303 tp = tp->e_nxt;
304 tp->e_addr0 = i;
305 tp->e_addr1 = j;
306 tp->e_addr2 = k;
307 tp->e_nsap = (u_char *)malloc(nlen + 1);
308 if (tp->e_nsap == NULL)
309 error("lookup_nsap: malloc");
310 memcpy(tp->e_nsap, nsap, nlen + 1);
311 tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
312 if (tp->e_nxt == NULL)
313 error("lookup_nsap: calloc");
314
315 return tp;
316}
317
318/* Find the hash node that corresponds the protoid 'pi'. */
319
320static inline struct protoidmem *
321lookup_protoid(const u_char *pi)
322{
323 register u_int i, j;
324 struct protoidmem *tp;
325
326 /* 5 octets won't be aligned */
327 i = (((pi[0] << 8) + pi[1]) << 8) + pi[2];
328 j = (pi[3] << 8) + pi[4];
329 /* XXX should be endian-insensitive, but do big-endian testing XXX */
330
331 tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)];
332 while (tp->p_nxt)
333 if (tp->p_oui == i && tp->p_proto == j)
334 return tp;
335 else
336 tp = tp->p_nxt;
337 tp->p_oui = i;
338 tp->p_proto = j;
339 tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp));
340 if (tp->p_nxt == NULL)
341 error("lookup_protoid: calloc");
342
343 return tp;
344}
345
346char *
347etheraddr_string(register const u_char *ep)
348{
349 register u_int i, j;
350 register char *cp;
351 register struct enamemem *tp;
352 char buf[sizeof("00:00:00:00:00:00")];
353
354 tp = lookup_emem(ep);
355 if (tp->e_name)
356 return (tp->e_name);
357#ifdef HAVE_ETHER_NTOHOST
358 if (!nflag) {
359 char buf[128];
360 if (ether_ntohost(buf, (struct ether_addr *)ep) == 0) {
361 tp->e_name = savestr(buf);
362 return (tp->e_name);
363 }
364 }
365#endif
366 cp = buf;
367 if ((j = *ep >> 4) != 0)
368 *cp++ = hex[j];
369 *cp++ = hex[*ep++ & 0xf];
370 for (i = 5; (int)--i >= 0;) {
371 *cp++ = ':';
372 if ((j = *ep >> 4) != 0)
373 *cp++ = hex[j];
374 *cp++ = hex[*ep++ & 0xf];
375 }
376 *cp = '\0';
377 tp->e_name = savestr(buf);
378 return (tp->e_name);
379}
380
381char *
382etherproto_string(u_short port)
383{
384 register char *cp;
385 register struct hnamemem *tp;
386 register u_int32_t i = port;
387 char buf[sizeof("0000")];
388
389 for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
390 if (tp->addr == i)
391 return (tp->name);
392
393 tp->addr = i;
394 tp->nxt = newhnamemem();
395
396 cp = buf;
397 NTOHS(port);
398 *cp++ = hex[port >> 12 & 0xf];
399 *cp++ = hex[port >> 8 & 0xf];
400 *cp++ = hex[port >> 4 & 0xf];
401 *cp++ = hex[port & 0xf];
402 *cp++ = '\0';
403 tp->name = savestr(buf);
404 return (tp->name);
405}
406
407char *
408protoid_string(register const u_char *pi)
409{
410 register u_int i, j;
411 register char *cp;
412 register struct protoidmem *tp;
413 char buf[sizeof("00:00:00:00:00")];
414
415 tp = lookup_protoid(pi);
416 if (tp->p_name)
417 return tp->p_name;
418
419 cp = buf;
420 if ((j = *pi >> 4) != 0)
421 *cp++ = hex[j];
422 *cp++ = hex[*pi++ & 0xf];
423 for (i = 4; (int)--i >= 0;) {
424 *cp++ = ':';
425 if ((j = *pi >> 4) != 0)
426 *cp++ = hex[j];
427 *cp++ = hex[*pi++ & 0xf];
428 }
429 *cp = '\0';
430 tp->p_name = savestr(buf);
431 return (tp->p_name);
432}
433
434char *
435llcsap_string(u_char sap)
436{
437 register char *cp;
438 register struct hnamemem *tp;
439 register u_int32_t i = sap;
440 char buf[sizeof("sap 00")];
441
442 for (tp = &llcsaptable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
443 if (tp->addr == i)
444 return (tp->name);
445
446 tp->addr = i;
447 tp->nxt = newhnamemem();
448
449 cp = buf;
450 (void)strcpy(cp, "sap ");
451 cp += strlen(cp);
452 *cp++ = hex[sap >> 4 & 0xf];
453 *cp++ = hex[sap & 0xf];
454 *cp++ = '\0';
455 tp->name = savestr(buf);
456 return (tp->name);
457}
458
459char *
460isonsap_string(const u_char *nsap)
461{
462 register u_int i, nlen = nsap[0];
463 register char *cp;
464 register struct enamemem *tp;
465
466 tp = lookup_nsap(nsap);
467 if (tp->e_name)
468 return tp->e_name;
469
1/*
2 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * Internet, ethernet, port, and protocol string to address
22 * and address to string conversion routines
23 */
24#ifndef lint
25static char rcsid[] =
26 "@(#) $Header: addrtoname.c,v 1.49 96/07/02 00:19:35 leres Exp $ (LBL)";
27#endif
28
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <sys/time.h>
32
33#if __STDC__
34struct mbuf;
35struct rtentry;
36#endif
37#include <net/if.h>
38
39#include <netinet/in.h>
40#include <netinet/if_ether.h>
41
42#include <arpa/inet.h>
43
44#include <ctype.h>
45#include <netdb.h>
46#include <pcap.h>
47#include <pcap-namedb.h>
48#include <signal.h>
49#include <stdio.h>
50#include <string.h>
51#include <stdlib.h>
52#include <unistd.h>
53
54#include "interface.h"
55#include "addrtoname.h"
56#include "llc.h"
57
58/* Forwards */
59static RETSIGTYPE nohostname(int);
60
61/*
62 * hash tables for whatever-to-name translations
63 */
64
65#define HASHNAMESIZE 4096
66
67struct hnamemem {
68 u_int32_t addr;
69 char *name;
70 struct hnamemem *nxt;
71};
72
73struct hnamemem hnametable[HASHNAMESIZE];
74struct hnamemem tporttable[HASHNAMESIZE];
75struct hnamemem uporttable[HASHNAMESIZE];
76struct hnamemem eprototable[HASHNAMESIZE];
77struct hnamemem dnaddrtable[HASHNAMESIZE];
78struct hnamemem llcsaptable[HASHNAMESIZE];
79
80struct enamemem {
81 u_short e_addr0;
82 u_short e_addr1;
83 u_short e_addr2;
84 char *e_name;
85 u_char *e_nsap; /* used only for nsaptable[] */
86 struct enamemem *e_nxt;
87};
88
89struct enamemem enametable[HASHNAMESIZE];
90struct enamemem nsaptable[HASHNAMESIZE];
91
92struct protoidmem {
93 u_int32_t p_oui;
94 u_short p_proto;
95 char *p_name;
96 struct protoidmem *p_nxt;
97};
98
99struct protoidmem protoidtable[HASHNAMESIZE];
100
101/*
102 * A faster replacement for inet_ntoa().
103 */
104char *
105intoa(u_int32_t addr)
106{
107 register char *cp;
108 register u_int byte;
109 register int n;
110 static char buf[sizeof(".xxx.xxx.xxx.xxx")];
111
112 NTOHL(addr);
113 cp = &buf[sizeof buf];
114 *--cp = '\0';
115
116 n = 4;
117 do {
118 byte = addr & 0xff;
119 *--cp = byte % 10 + '0';
120 byte /= 10;
121 if (byte > 0) {
122 *--cp = byte % 10 + '0';
123 byte /= 10;
124 if (byte > 0)
125 *--cp = byte + '0';
126 }
127 *--cp = '.';
128 addr >>= 8;
129 } while (--n > 0);
130
131 return cp + 1;
132}
133
134static u_int32_t f_netmask;
135static u_int32_t f_localnet;
136static u_int32_t netmask;
137
138/*
139 * "getname" is written in this atrocious way to make sure we don't
140 * wait forever while trying to get hostnames from yp.
141 */
142#include <setjmp.h>
143
144jmp_buf getname_env;
145
146static RETSIGTYPE
147nohostname(int signo)
148{
149 longjmp(getname_env, 1);
150}
151
152/*
153 * Return a name for the IP address pointed to by ap. This address
154 * is assumed to be in network byte order.
155 */
156char *
157getname(const u_char *ap)
158{
159 register struct hostent *hp;
160 u_int32_t addr;
161 static struct hnamemem *p; /* static for longjmp() */
162
163#ifndef LBL_ALIGN
164 addr = *(const u_int32_t *)ap;
165#else
166 /*
167 * Deal with alignment.
168 */
169 switch ((long)ap & 3) {
170
171 case 0:
172 addr = *(u_int32_t *)ap;
173 break;
174
175 case 2:
176#if BYTE_ORDER == LITTLE_ENDIAN
177 addr = ((u_int32_t)*(u_short *)(ap + 2) << 16) |
178 (u_int32_t)*(u_short *)ap;
179#else
180 addr = ((u_int32_t)*(u_short *)ap << 16) |
181 (u_int32_t)*(u_short *)(ap + 2);
182#endif
183 break;
184
185 default:
186#if BYTE_ORDER == LITTLE_ENDIAN
187 addr = ((u_int32_t)ap[3] << 24) |
188 ((u_int32_t)ap[2] << 16) |
189 ((u_int32_t)ap[1] << 8) |
190 (u_int32_t)ap[0];
191#else
192 addr = ((u_int32_t)ap[0] << 24) |
193 ((u_int32_t)ap[1] << 16) |
194 ((u_int32_t)ap[2] << 8) |
195 (u_int32_t)ap[3];
196#endif
197 break;
198 }
199#endif
200 p = &hnametable[addr & (HASHNAMESIZE-1)];
201 for (; p->nxt; p = p->nxt) {
202 if (p->addr == addr)
203 return (p->name);
204 }
205 p->addr = addr;
206 p->nxt = newhnamemem();
207
208 /*
209 * Only print names when:
210 * (1) -n was not given.
211 * (2) Address is foreign and -f was given. If -f was not
212 * present, f_netmask and f_local are 0 and the second
213 * test will succeed.
214 * (3) The host portion is not 0 (i.e., a network address).
215 * (4) The host portion is not broadcast.
216 */
217 if (!nflag && (addr & f_netmask) == f_localnet
218 && (addr &~ netmask) != 0 && (addr | netmask) != 0xffffffff) {
219 if (!setjmp(getname_env)) {
220 (void)signal(SIGALRM, nohostname);
221 (void)alarm(20);
222 hp = gethostbyaddr((char *)&addr, 4, AF_INET);
223 (void)alarm(0);
224 if (hp) {
225 char *dotp;
226
227 p->name = savestr(hp->h_name);
228 if (Nflag) {
229 /* Remove domain qualifications */
230 dotp = strchr(p->name, '.');
231 if (dotp)
232 *dotp = '\0';
233 }
234 return (p->name);
235 }
236 }
237 }
238 p->name = savestr(intoa(addr));
239 return (p->name);
240}
241
242static char hex[] = "0123456789abcdef";
243
244
245/* Find the hash node that corresponds the ether address 'ep' */
246
247static inline struct enamemem *
248lookup_emem(const u_char *ep)
249{
250 register u_int i, j, k;
251 struct enamemem *tp;
252
253 k = (ep[0] << 8) | ep[1];
254 j = (ep[2] << 8) | ep[3];
255 i = (ep[4] << 8) | ep[5];
256
257 tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)];
258 while (tp->e_nxt)
259 if (tp->e_addr0 == i &&
260 tp->e_addr1 == j &&
261 tp->e_addr2 == k)
262 return tp;
263 else
264 tp = tp->e_nxt;
265 tp->e_addr0 = i;
266 tp->e_addr1 = j;
267 tp->e_addr2 = k;
268 tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
269 if (tp->e_nxt == NULL)
270 error("lookup_emem: calloc");
271
272 return tp;
273}
274
275/* Find the hash node that corresponds the NSAP 'nsap' */
276
277static inline struct enamemem *
278lookup_nsap(register const u_char *nsap)
279{
280 register u_int i, j, k;
281 int nlen = *nsap;
282 struct enamemem *tp;
283 const u_char *ensap = nsap + nlen - 6;
284
285 if (nlen > 6) {
286 k = (ensap[0] << 8) | ensap[1];
287 j = (ensap[2] << 8) | ensap[3];
288 i = (ensap[4] << 8) | ensap[5];
289 }
290 else
291 i = j = k = 0;
292
293 tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)];
294 while (tp->e_nxt)
295 if (tp->e_addr0 == i &&
296 tp->e_addr1 == j &&
297 tp->e_addr2 == k &&
298 tp->e_nsap[0] == nlen &&
299 memcmp((char *)&(nsap[1]),
300 (char *)&(tp->e_nsap[1]), nlen) == 0)
301 return tp;
302 else
303 tp = tp->e_nxt;
304 tp->e_addr0 = i;
305 tp->e_addr1 = j;
306 tp->e_addr2 = k;
307 tp->e_nsap = (u_char *)malloc(nlen + 1);
308 if (tp->e_nsap == NULL)
309 error("lookup_nsap: malloc");
310 memcpy(tp->e_nsap, nsap, nlen + 1);
311 tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp));
312 if (tp->e_nxt == NULL)
313 error("lookup_nsap: calloc");
314
315 return tp;
316}
317
318/* Find the hash node that corresponds the protoid 'pi'. */
319
320static inline struct protoidmem *
321lookup_protoid(const u_char *pi)
322{
323 register u_int i, j;
324 struct protoidmem *tp;
325
326 /* 5 octets won't be aligned */
327 i = (((pi[0] << 8) + pi[1]) << 8) + pi[2];
328 j = (pi[3] << 8) + pi[4];
329 /* XXX should be endian-insensitive, but do big-endian testing XXX */
330
331 tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)];
332 while (tp->p_nxt)
333 if (tp->p_oui == i && tp->p_proto == j)
334 return tp;
335 else
336 tp = tp->p_nxt;
337 tp->p_oui = i;
338 tp->p_proto = j;
339 tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp));
340 if (tp->p_nxt == NULL)
341 error("lookup_protoid: calloc");
342
343 return tp;
344}
345
346char *
347etheraddr_string(register const u_char *ep)
348{
349 register u_int i, j;
350 register char *cp;
351 register struct enamemem *tp;
352 char buf[sizeof("00:00:00:00:00:00")];
353
354 tp = lookup_emem(ep);
355 if (tp->e_name)
356 return (tp->e_name);
357#ifdef HAVE_ETHER_NTOHOST
358 if (!nflag) {
359 char buf[128];
360 if (ether_ntohost(buf, (struct ether_addr *)ep) == 0) {
361 tp->e_name = savestr(buf);
362 return (tp->e_name);
363 }
364 }
365#endif
366 cp = buf;
367 if ((j = *ep >> 4) != 0)
368 *cp++ = hex[j];
369 *cp++ = hex[*ep++ & 0xf];
370 for (i = 5; (int)--i >= 0;) {
371 *cp++ = ':';
372 if ((j = *ep >> 4) != 0)
373 *cp++ = hex[j];
374 *cp++ = hex[*ep++ & 0xf];
375 }
376 *cp = '\0';
377 tp->e_name = savestr(buf);
378 return (tp->e_name);
379}
380
381char *
382etherproto_string(u_short port)
383{
384 register char *cp;
385 register struct hnamemem *tp;
386 register u_int32_t i = port;
387 char buf[sizeof("0000")];
388
389 for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
390 if (tp->addr == i)
391 return (tp->name);
392
393 tp->addr = i;
394 tp->nxt = newhnamemem();
395
396 cp = buf;
397 NTOHS(port);
398 *cp++ = hex[port >> 12 & 0xf];
399 *cp++ = hex[port >> 8 & 0xf];
400 *cp++ = hex[port >> 4 & 0xf];
401 *cp++ = hex[port & 0xf];
402 *cp++ = '\0';
403 tp->name = savestr(buf);
404 return (tp->name);
405}
406
407char *
408protoid_string(register const u_char *pi)
409{
410 register u_int i, j;
411 register char *cp;
412 register struct protoidmem *tp;
413 char buf[sizeof("00:00:00:00:00")];
414
415 tp = lookup_protoid(pi);
416 if (tp->p_name)
417 return tp->p_name;
418
419 cp = buf;
420 if ((j = *pi >> 4) != 0)
421 *cp++ = hex[j];
422 *cp++ = hex[*pi++ & 0xf];
423 for (i = 4; (int)--i >= 0;) {
424 *cp++ = ':';
425 if ((j = *pi >> 4) != 0)
426 *cp++ = hex[j];
427 *cp++ = hex[*pi++ & 0xf];
428 }
429 *cp = '\0';
430 tp->p_name = savestr(buf);
431 return (tp->p_name);
432}
433
434char *
435llcsap_string(u_char sap)
436{
437 register char *cp;
438 register struct hnamemem *tp;
439 register u_int32_t i = sap;
440 char buf[sizeof("sap 00")];
441
442 for (tp = &llcsaptable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
443 if (tp->addr == i)
444 return (tp->name);
445
446 tp->addr = i;
447 tp->nxt = newhnamemem();
448
449 cp = buf;
450 (void)strcpy(cp, "sap ");
451 cp += strlen(cp);
452 *cp++ = hex[sap >> 4 & 0xf];
453 *cp++ = hex[sap & 0xf];
454 *cp++ = '\0';
455 tp->name = savestr(buf);
456 return (tp->name);
457}
458
459char *
460isonsap_string(const u_char *nsap)
461{
462 register u_int i, nlen = nsap[0];
463 register char *cp;
464 register struct enamemem *tp;
465
466 tp = lookup_nsap(nsap);
467 if (tp->e_name)
468 return tp->e_name;
469
470 tp->e_name = cp = (char *)malloc(nlen * 2 + 2);
470 tp->e_name = cp = (char *)malloc(nlen * 2 + 2 + (nlen>>1));
471 if (cp == NULL)
472 error("isonsap_string: malloc");
473
474 nsap++;
471 if (cp == NULL)
472 error("isonsap_string: malloc");
473
474 nsap++;
475 *cp++ = '/';
476 for (i = nlen; (int)--i >= 0;) {
475 for (i = 0; i < nlen; i++) {
477 *cp++ = hex[*nsap >> 4];
478 *cp++ = hex[*nsap++ & 0xf];
476 *cp++ = hex[*nsap >> 4];
477 *cp++ = hex[*nsap++ & 0xf];
478 if (((i & 1) == 0) && (i + 1 < nlen))
479 *cp++ = '.';
479 }
480 *cp = '\0';
481 return (tp->e_name);
482}
483
484char *
485tcpport_string(u_short port)
486{
487 register struct hnamemem *tp;
488 register u_int32_t i = port;
489 char buf[sizeof("00000")];
490
491 for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
492 if (tp->addr == i)
493 return (tp->name);
494
495 tp->addr = i;
496 tp->nxt = newhnamemem();
497
498 (void)sprintf(buf, "%u", i);
499 tp->name = savestr(buf);
500 return (tp->name);
501}
502
503char *
504udpport_string(register u_short port)
505{
506 register struct hnamemem *tp;
507 register u_int32_t i = port;
508 char buf[sizeof("00000")];
509
510 for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
511 if (tp->addr == i)
512 return (tp->name);
513
514 tp->addr = i;
515 tp->nxt = newhnamemem();
516
517 (void)sprintf(buf, "%u", i);
518 tp->name = savestr(buf);
519 return (tp->name);
520}
521
522static void
523init_servarray(void)
524{
525 struct servent *sv;
526 register struct hnamemem *table;
527 register int i;
528 char buf[sizeof("0000000000")];
529
530 while ((sv = getservent()) != NULL) {
531 int port = ntohs(sv->s_port);
532 i = port & (HASHNAMESIZE-1);
533 if (strcmp(sv->s_proto, "tcp") == 0)
534 table = &tporttable[i];
535 else if (strcmp(sv->s_proto, "udp") == 0)
536 table = &uporttable[i];
537 else
538 continue;
539
540 while (table->name)
541 table = table->nxt;
542 if (nflag) {
543 (void)sprintf(buf, "%d", port);
544 table->name = savestr(buf);
545 } else
546 table->name = savestr(sv->s_name);
547 table->addr = port;
548 table->nxt = newhnamemem();
549 }
550 endservent();
551}
552
553/*XXX from libbpfc.a */
554extern struct eproto {
555 char *s;
556 u_short p;
557} eproto_db[];
558
559static void
560init_eprotoarray(void)
561{
562 register int i;
563 register struct hnamemem *table;
564
565 for (i = 0; eproto_db[i].s; i++) {
566 int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1);
567 table = &eprototable[j];
568 while (table->name)
569 table = table->nxt;
570 table->name = eproto_db[i].s;
571 table->addr = ntohs(eproto_db[i].p);
572 table->nxt = newhnamemem();
573 }
574}
575
576/*
577 * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet
578 * types.
579 */
580static void
581init_protoidarray(void)
582{
583 register int i;
584 register struct protoidmem *tp;
585 u_char protoid[5];
586
587 protoid[0] = 0;
588 protoid[1] = 0;
589 protoid[2] = 0;
590 for (i = 0; eproto_db[i].s; i++) {
591 u_short etype = htons(eproto_db[i].p);
592
593 memcpy((char *)&protoid[3], (char *)&etype, 2);
594 tp = lookup_protoid(protoid);
595 tp->p_name = savestr(eproto_db[i].s);
596 }
597}
598
599static struct etherlist {
600 u_char addr[6];
601 char *name;
602} etherlist[] = {
603 {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" },
604 {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL }
605};
606
607/*
608 * Initialize the ethers hash table. We take two different approaches
609 * depending on whether or not the system provides the ethers name
610 * service. If it does, we just wire in a few names at startup,
611 * and etheraddr_string() fills in the table on demand. If it doesn't,
612 * then we suck in the entire /etc/ethers file at startup. The idea
613 * is that parsing the local file will be fast, but spinning through
614 * all the ethers entries via NIS & next_etherent might be very slow.
615 *
616 * XXX pcap_next_etherent doesn't belong in the pcap interface, but
617 * since the pcap module already does name-to-address translation,
618 * it's already does most of the work for the ethernet address-to-name
619 * translation, so we just pcap_next_etherent as a convenience.
620 */
621static void
622init_etherarray(void)
623{
624 register struct etherlist *el;
625 register struct enamemem *tp;
626#ifdef HAVE_ETHER_NTOHOST
627 char name[256];
628#else
629 register struct pcap_etherent *ep;
630 register FILE *fp;
631
632 /* Suck in entire ethers file */
633 fp = fopen(PCAP_ETHERS_FILE, "r");
634 if (fp != NULL) {
635 while ((ep = pcap_next_etherent(fp)) != NULL) {
636 tp = lookup_emem(ep->addr);
637 tp->e_name = savestr(ep->name);
638 }
639 (void)fclose(fp);
640 }
641#endif
642
643 /* Hardwire some ethernet names */
644 for (el = etherlist; el->name != NULL; ++el) {
645 tp = lookup_emem(el->addr);
646 /* Don't override existing name */
647 if (tp->e_name != NULL)
648 continue;
649
650#ifdef HAVE_ETHER_NTOHOST
651 /* Use yp/nis version of name if available */
652 if (ether_ntohost(name, (struct ether_addr *)el->addr) == 0) {
653 tp->e_name = savestr(name);
654 continue;
655 }
656#endif
657 tp->e_name = el->name;
658 }
659}
660
661static struct tok llcsap_db[] = {
662 { LLCSAP_NULL, "null" },
663 { LLCSAP_8021B_I, "802.1b-gsap" },
664 { LLCSAP_8021B_G, "802.1b-isap" },
665 { LLCSAP_IP, "ip-sap" },
666 { LLCSAP_PROWAYNM, "proway-nm" },
667 { LLCSAP_8021D, "802.1d" },
668 { LLCSAP_RS511, "eia-rs511" },
669 { LLCSAP_ISO8208, "x.25/llc2" },
670 { LLCSAP_PROWAY, "proway" },
671 { LLCSAP_ISONS, "iso-clns" },
672 { LLCSAP_GLOBAL, "global" },
673 { 0, NULL }
674};
675
676static void
677init_llcsaparray(void)
678{
679 register int i;
680 register struct hnamemem *table;
681
682 for (i = 0; llcsap_db[i].s != NULL; i++) {
683 table = &llcsaptable[llcsap_db[i].v];
684 while (table->name)
685 table = table->nxt;
686 table->name = llcsap_db[i].s;
687 table->addr = llcsap_db[i].v;
688 table->nxt = newhnamemem();
689 }
690}
691
692/*
693 * Initialize the address to name translation machinery. We map all
694 * non-local IP addresses to numeric addresses if fflag is true (i.e.,
695 * to prevent blocking on the nameserver). localnet is the IP address
696 * of the local network. mask is its subnet mask.
697 */
698void
699init_addrtoname(int fflag, u_int32_t localnet, u_int32_t mask)
700{
701 netmask = mask;
702 if (fflag) {
703 f_localnet = localnet;
704 f_netmask = mask;
705 }
706 if (nflag)
707 /*
708 * Simplest way to suppress names.
709 */
710 return;
711
712 init_etherarray();
713 init_servarray();
714 init_eprotoarray();
715 init_llcsaparray();
716 init_protoidarray();
717}
718
719char *
720dnaddr_string(u_short dnaddr)
721{
722 register struct hnamemem *tp;
723
724 for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != 0;
725 tp = tp->nxt)
726 if (tp->addr == dnaddr)
727 return (tp->name);
728
729 tp->addr = dnaddr;
730 tp->nxt = newhnamemem();
731 if (nflag)
732 tp->name = dnnum_string(dnaddr);
733 else
734 tp->name = dnname_string(dnaddr);
735
736 return(tp->name);
737}
738
739/* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */
740struct hnamemem *
741newhnamemem()
742{
743 register struct hnamemem *p;
744 static struct hnamemem *ptr = NULL;
745 static u_int num = 0;
746
747 if (num <= 0) {
748 num = 64;
749 ptr = (struct hnamemem *)calloc(num, sizeof (*ptr));
750 if (ptr == NULL)
751 error("newhnamemem: calloc");
752 }
753 --num;
754 p = ptr++;
755 return (p);
756}
480 }
481 *cp = '\0';
482 return (tp->e_name);
483}
484
485char *
486tcpport_string(u_short port)
487{
488 register struct hnamemem *tp;
489 register u_int32_t i = port;
490 char buf[sizeof("00000")];
491
492 for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
493 if (tp->addr == i)
494 return (tp->name);
495
496 tp->addr = i;
497 tp->nxt = newhnamemem();
498
499 (void)sprintf(buf, "%u", i);
500 tp->name = savestr(buf);
501 return (tp->name);
502}
503
504char *
505udpport_string(register u_short port)
506{
507 register struct hnamemem *tp;
508 register u_int32_t i = port;
509 char buf[sizeof("00000")];
510
511 for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt)
512 if (tp->addr == i)
513 return (tp->name);
514
515 tp->addr = i;
516 tp->nxt = newhnamemem();
517
518 (void)sprintf(buf, "%u", i);
519 tp->name = savestr(buf);
520 return (tp->name);
521}
522
523static void
524init_servarray(void)
525{
526 struct servent *sv;
527 register struct hnamemem *table;
528 register int i;
529 char buf[sizeof("0000000000")];
530
531 while ((sv = getservent()) != NULL) {
532 int port = ntohs(sv->s_port);
533 i = port & (HASHNAMESIZE-1);
534 if (strcmp(sv->s_proto, "tcp") == 0)
535 table = &tporttable[i];
536 else if (strcmp(sv->s_proto, "udp") == 0)
537 table = &uporttable[i];
538 else
539 continue;
540
541 while (table->name)
542 table = table->nxt;
543 if (nflag) {
544 (void)sprintf(buf, "%d", port);
545 table->name = savestr(buf);
546 } else
547 table->name = savestr(sv->s_name);
548 table->addr = port;
549 table->nxt = newhnamemem();
550 }
551 endservent();
552}
553
554/*XXX from libbpfc.a */
555extern struct eproto {
556 char *s;
557 u_short p;
558} eproto_db[];
559
560static void
561init_eprotoarray(void)
562{
563 register int i;
564 register struct hnamemem *table;
565
566 for (i = 0; eproto_db[i].s; i++) {
567 int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1);
568 table = &eprototable[j];
569 while (table->name)
570 table = table->nxt;
571 table->name = eproto_db[i].s;
572 table->addr = ntohs(eproto_db[i].p);
573 table->nxt = newhnamemem();
574 }
575}
576
577/*
578 * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet
579 * types.
580 */
581static void
582init_protoidarray(void)
583{
584 register int i;
585 register struct protoidmem *tp;
586 u_char protoid[5];
587
588 protoid[0] = 0;
589 protoid[1] = 0;
590 protoid[2] = 0;
591 for (i = 0; eproto_db[i].s; i++) {
592 u_short etype = htons(eproto_db[i].p);
593
594 memcpy((char *)&protoid[3], (char *)&etype, 2);
595 tp = lookup_protoid(protoid);
596 tp->p_name = savestr(eproto_db[i].s);
597 }
598}
599
600static struct etherlist {
601 u_char addr[6];
602 char *name;
603} etherlist[] = {
604 {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" },
605 {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL }
606};
607
608/*
609 * Initialize the ethers hash table. We take two different approaches
610 * depending on whether or not the system provides the ethers name
611 * service. If it does, we just wire in a few names at startup,
612 * and etheraddr_string() fills in the table on demand. If it doesn't,
613 * then we suck in the entire /etc/ethers file at startup. The idea
614 * is that parsing the local file will be fast, but spinning through
615 * all the ethers entries via NIS & next_etherent might be very slow.
616 *
617 * XXX pcap_next_etherent doesn't belong in the pcap interface, but
618 * since the pcap module already does name-to-address translation,
619 * it's already does most of the work for the ethernet address-to-name
620 * translation, so we just pcap_next_etherent as a convenience.
621 */
622static void
623init_etherarray(void)
624{
625 register struct etherlist *el;
626 register struct enamemem *tp;
627#ifdef HAVE_ETHER_NTOHOST
628 char name[256];
629#else
630 register struct pcap_etherent *ep;
631 register FILE *fp;
632
633 /* Suck in entire ethers file */
634 fp = fopen(PCAP_ETHERS_FILE, "r");
635 if (fp != NULL) {
636 while ((ep = pcap_next_etherent(fp)) != NULL) {
637 tp = lookup_emem(ep->addr);
638 tp->e_name = savestr(ep->name);
639 }
640 (void)fclose(fp);
641 }
642#endif
643
644 /* Hardwire some ethernet names */
645 for (el = etherlist; el->name != NULL; ++el) {
646 tp = lookup_emem(el->addr);
647 /* Don't override existing name */
648 if (tp->e_name != NULL)
649 continue;
650
651#ifdef HAVE_ETHER_NTOHOST
652 /* Use yp/nis version of name if available */
653 if (ether_ntohost(name, (struct ether_addr *)el->addr) == 0) {
654 tp->e_name = savestr(name);
655 continue;
656 }
657#endif
658 tp->e_name = el->name;
659 }
660}
661
662static struct tok llcsap_db[] = {
663 { LLCSAP_NULL, "null" },
664 { LLCSAP_8021B_I, "802.1b-gsap" },
665 { LLCSAP_8021B_G, "802.1b-isap" },
666 { LLCSAP_IP, "ip-sap" },
667 { LLCSAP_PROWAYNM, "proway-nm" },
668 { LLCSAP_8021D, "802.1d" },
669 { LLCSAP_RS511, "eia-rs511" },
670 { LLCSAP_ISO8208, "x.25/llc2" },
671 { LLCSAP_PROWAY, "proway" },
672 { LLCSAP_ISONS, "iso-clns" },
673 { LLCSAP_GLOBAL, "global" },
674 { 0, NULL }
675};
676
677static void
678init_llcsaparray(void)
679{
680 register int i;
681 register struct hnamemem *table;
682
683 for (i = 0; llcsap_db[i].s != NULL; i++) {
684 table = &llcsaptable[llcsap_db[i].v];
685 while (table->name)
686 table = table->nxt;
687 table->name = llcsap_db[i].s;
688 table->addr = llcsap_db[i].v;
689 table->nxt = newhnamemem();
690 }
691}
692
693/*
694 * Initialize the address to name translation machinery. We map all
695 * non-local IP addresses to numeric addresses if fflag is true (i.e.,
696 * to prevent blocking on the nameserver). localnet is the IP address
697 * of the local network. mask is its subnet mask.
698 */
699void
700init_addrtoname(int fflag, u_int32_t localnet, u_int32_t mask)
701{
702 netmask = mask;
703 if (fflag) {
704 f_localnet = localnet;
705 f_netmask = mask;
706 }
707 if (nflag)
708 /*
709 * Simplest way to suppress names.
710 */
711 return;
712
713 init_etherarray();
714 init_servarray();
715 init_eprotoarray();
716 init_llcsaparray();
717 init_protoidarray();
718}
719
720char *
721dnaddr_string(u_short dnaddr)
722{
723 register struct hnamemem *tp;
724
725 for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != 0;
726 tp = tp->nxt)
727 if (tp->addr == dnaddr)
728 return (tp->name);
729
730 tp->addr = dnaddr;
731 tp->nxt = newhnamemem();
732 if (nflag)
733 tp->name = dnnum_string(dnaddr);
734 else
735 tp->name = dnname_string(dnaddr);
736
737 return(tp->name);
738}
739
740/* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */
741struct hnamemem *
742newhnamemem()
743{
744 register struct hnamemem *p;
745 static struct hnamemem *ptr = NULL;
746 static u_int num = 0;
747
748 if (num <= 0) {
749 num = 64;
750 ptr = (struct hnamemem *)calloc(num, sizeof (*ptr));
751 if (ptr == NULL)
752 error("newhnamemem: calloc");
753 }
754 --num;
755 p = ptr++;
756 return (p);
757}