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