Commit | Line | Data |
---|---|---|
14675b17 DG |
1 | /* |
2 | * Copyright (c) 1988, 1990 The Regents of the University of California. | |
3 | * 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 | |
25 | static char rcsid[] = | |
26 | "@(#) $Header: addrtoname.c,v 1.14 92/05/25 14:29:07 mccanne Exp $ (LBL)"; | |
27 | #endif | |
28 | ||
29 | #include <stdio.h> | |
30 | #include <strings.h> | |
31 | #include <ctype.h> | |
32 | #include <sys/types.h> | |
33 | #include <sys/socket.h> | |
34 | #include <net/if.h> | |
35 | #include <netdb.h> | |
36 | #include <netinet/in.h> | |
37 | #include <netinet/if_ether.h> | |
38 | #include <arpa/inet.h> | |
39 | #include <signal.h> | |
40 | ||
41 | #include "interface.h" | |
42 | #include "addrtoname.h" | |
43 | #include "nametoaddr.h" | |
44 | #include "etherent.h" | |
45 | ||
46 | /* | |
47 | * hash tables for whatever-to-name translations | |
48 | */ | |
49 | ||
50 | #define HASHNAMESIZE 4096 | |
51 | ||
52 | struct hnamemem { | |
53 | u_long addr; | |
54 | char *name; | |
55 | struct hnamemem *nxt; | |
56 | }; | |
57 | ||
58 | struct hnamemem hnametable[HASHNAMESIZE]; | |
59 | struct hnamemem tporttable[HASHNAMESIZE]; | |
60 | struct hnamemem uporttable[HASHNAMESIZE]; | |
61 | struct hnamemem eprototable[HASHNAMESIZE]; | |
62 | ||
63 | struct enamemem { | |
64 | u_short e_addr0; | |
65 | u_short e_addr1; | |
66 | u_short e_addr2; | |
67 | char *e_name; | |
68 | struct enamemem *e_nxt; | |
69 | }; | |
70 | ||
71 | struct enamemem enametable[HASHNAMESIZE]; | |
72 | ||
73 | ||
74 | /* | |
75 | * A faster replacement for inet_ntoa(). | |
76 | */ | |
77 | char * | |
78 | intoa(addr) | |
79 | u_long addr; | |
80 | { | |
81 | register char *cp; | |
82 | register u_int byte; | |
83 | register int n; | |
84 | static char buf[sizeof(".xxx.xxx.xxx.xxx")]; | |
85 | ||
86 | NTOHL(addr); | |
87 | cp = &buf[sizeof buf]; | |
88 | *--cp = '\0'; | |
89 | ||
90 | n = 4; | |
91 | do { | |
92 | byte = addr & 0xff; | |
93 | *--cp = byte % 10 + '0'; | |
94 | byte /= 10; | |
95 | if (byte > 0) { | |
96 | *--cp = byte % 10 + '0'; | |
97 | byte /= 10; | |
98 | if (byte > 0) | |
99 | *--cp = byte + '0'; | |
100 | } | |
101 | *--cp = '.'; | |
102 | addr >>= 8; | |
103 | } while (--n > 0); | |
104 | ||
105 | return cp + 1; | |
106 | } | |
107 | ||
108 | static u_long f_netmask; | |
109 | static u_long f_localnet; | |
110 | static u_long netmask; | |
111 | ||
112 | /* | |
113 | * "getname" is written in this atrocious way to make sure we don't | |
114 | * wait forever while trying to get hostnames from yp. | |
115 | */ | |
116 | #include <setjmp.h> | |
117 | ||
118 | jmp_buf getname_env; | |
119 | ||
120 | static void | |
121 | nohostname() | |
122 | { | |
123 | longjmp(getname_env, 1); | |
124 | } | |
125 | ||
126 | /* | |
127 | * Return a name for the IP address pointed to by ap. This address | |
128 | * is assumed to be in network byte order. | |
129 | */ | |
130 | char * | |
131 | getname(ap) | |
132 | u_char *ap; | |
133 | { | |
134 | register struct hnamemem *p; | |
135 | register struct hostent *hp; | |
136 | register char *cp; | |
137 | u_long addr; | |
138 | ||
139 | #ifndef TCPDUMP_ALIGN | |
140 | addr = *(u_long *)ap; | |
141 | #else | |
142 | /* | |
143 | * Deal with alignment. | |
144 | */ | |
145 | switch ((int)ap & 3) { | |
146 | ||
147 | case 0: | |
148 | addr = *(u_long *)ap; | |
149 | break; | |
150 | ||
151 | case 2: | |
152 | #if BYTE_ORDER == LITTLE_ENDIAN | |
153 | addr = ((u_long)*(u_short *)(ap + 2) << 16) | | |
154 | (u_long)*(u_short *)ap; | |
155 | #else | |
156 | addr = ((u_long)*(u_short *)ap << 16) | | |
157 | (u_long)*(u_short *)(ap + 2); | |
158 | #endif | |
159 | break; | |
160 | ||
161 | default: | |
162 | #if BYTE_ORDER == LITTLE_ENDIAN | |
163 | addr = ((u_long)ap[0] << 24) | | |
164 | ((u_long)ap[1] << 16) | | |
165 | ((u_long)ap[2] << 8) | | |
166 | (u_long)ap[3]; | |
167 | #else | |
168 | addr = ((u_long)ap[3] << 24) | | |
169 | ((u_long)ap[2] << 16) | | |
170 | ((u_long)ap[1] << 8) | | |
171 | (u_long)ap[0]; | |
172 | #endif | |
173 | break; | |
174 | } | |
175 | #endif | |
176 | p = &hnametable[addr & (HASHNAMESIZE-1)]; | |
177 | for (; p->nxt; p = p->nxt) { | |
178 | if (p->addr == addr) | |
179 | return (p->name); | |
180 | } | |
181 | p->addr = addr; | |
182 | p->nxt = (struct hnamemem *)calloc(1, sizeof (*p)); | |
183 | ||
184 | /* | |
185 | * Only print names when: | |
186 | * (1) -n was not given. | |
187 | * (2) Address is foreign and -f was given. If -f was not | |
188 | * present, f_netmask and f_local are 0 and the second | |
189 | * test will succeed. | |
190 | * (3) The host portion is not 0 (i.e., a network address). | |
191 | * (4) The host portion is not broadcast. | |
192 | */ | |
193 | if (!nflag && (addr & f_netmask) == f_localnet | |
194 | && (addr &~ netmask) != 0 && (addr | netmask) != 0xffffffff) { | |
195 | if (!setjmp(getname_env)) { | |
196 | (void)signal(SIGALRM, nohostname); | |
197 | (void)alarm(20); | |
198 | hp = gethostbyaddr((char *)&addr, 4, AF_INET); | |
199 | (void)alarm(0); | |
200 | if (hp) { | |
201 | char *index(); | |
202 | char *dotp; | |
203 | u_int len = strlen(hp->h_name) + 1; | |
204 | p->name = (char *)malloc(len); | |
205 | (void)strcpy(p->name, hp->h_name); | |
206 | if (Nflag) { | |
207 | /* Remove domain qualifications */ | |
208 | dotp = index(p->name, '.'); | |
209 | if (dotp) | |
210 | *dotp = 0; | |
211 | } | |
212 | return (p->name); | |
213 | } | |
214 | } | |
215 | } | |
216 | cp = intoa(addr); | |
217 | p->name = (char *)malloc((unsigned)(strlen(cp) + 1)); | |
218 | (void)strcpy(p->name, cp); | |
219 | return (p->name); | |
220 | } | |
221 | ||
222 | static char hex[] = "0123456789abcdef"; | |
223 | ||
224 | ||
225 | /* Find the hash node that corresponds the ether address 'ep'. */ | |
226 | ||
227 | static inline struct enamemem * | |
228 | lookup_emem(ep) | |
229 | u_char *ep; | |
230 | { | |
231 | register u_int i, j, k; | |
232 | struct enamemem *tp; | |
233 | ||
234 | k = (ep[0] << 8) | ep[1]; | |
235 | j = (ep[2] << 8) | ep[3]; | |
236 | i = (ep[4] << 8) | ep[5]; | |
237 | ||
238 | tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)]; | |
239 | while (tp->e_nxt) | |
240 | if (tp->e_addr0 == i && | |
241 | tp->e_addr1 == j && | |
242 | tp->e_addr2 == k) | |
243 | return tp; | |
244 | else | |
245 | tp = tp->e_nxt; | |
246 | tp->e_addr0 = i; | |
247 | tp->e_addr1 = j; | |
248 | tp->e_addr2 = k; | |
249 | tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); | |
250 | ||
251 | return tp; | |
252 | } | |
253 | ||
254 | char * | |
255 | etheraddr_string(ep) | |
256 | register u_char *ep; | |
257 | { | |
258 | register u_int i, j; | |
259 | register char *cp; | |
260 | register struct enamemem *tp; | |
261 | ||
262 | tp = lookup_emem(ep); | |
263 | if (tp->e_name) | |
264 | return tp->e_name; | |
265 | ||
266 | #ifdef ETHER_SERVICE | |
267 | if (!nflag) { | |
268 | cp = ETHER_ntohost(ep); | |
269 | if (cp) { | |
270 | tp->e_name = cp; | |
271 | return cp; | |
272 | } | |
273 | } | |
274 | #endif | |
275 | tp->e_name = cp = (char *)malloc(sizeof("00:00:00:00:00:00")); | |
276 | ||
277 | if (j = *ep >> 4) | |
278 | *cp++ = hex[j]; | |
279 | *cp++ = hex[*ep++ & 0xf]; | |
280 | for (i = 5; (int)--i >= 0;) { | |
281 | *cp++ = ':'; | |
282 | if (j = *ep >> 4) | |
283 | *cp++ = hex[j]; | |
284 | *cp++ = hex[*ep++ & 0xf]; | |
285 | } | |
286 | *cp = '\0'; | |
287 | return (tp->e_name); | |
288 | } | |
289 | ||
290 | char * | |
291 | etherproto_string(port) | |
292 | u_short port; | |
293 | { | |
294 | register char *cp; | |
295 | register struct hnamemem *tp; | |
296 | register u_long i = port; | |
297 | ||
298 | for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) | |
299 | if (tp->addr == i) | |
300 | return (tp->name); | |
301 | ||
302 | tp->name = cp = (char *)malloc(sizeof("0000")); | |
303 | tp->addr = i; | |
304 | tp->nxt = (struct hnamemem *)calloc(1, sizeof (*tp)); | |
305 | ||
306 | NTOHS(port); | |
307 | *cp++ = hex[port >> 12 & 0xf]; | |
308 | *cp++ = hex[port >> 8 & 0xf]; | |
309 | *cp++ = hex[port >> 4 & 0xf]; | |
310 | *cp++ = hex[port & 0xf]; | |
311 | *cp++ = '\0'; | |
312 | return (tp->name); | |
313 | } | |
314 | ||
315 | char * | |
316 | tcpport_string(port) | |
317 | u_short port; | |
318 | { | |
319 | register struct hnamemem *tp; | |
320 | register int i = port; | |
321 | ||
322 | for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) | |
323 | if (tp->addr == i) | |
324 | return (tp->name); | |
325 | ||
326 | tp->name = (char *)malloc(sizeof("00000")); | |
327 | tp->addr = i; | |
328 | tp->nxt = (struct hnamemem *)calloc(1, sizeof (*tp)); | |
329 | ||
330 | (void)sprintf(tp->name, "%d", i); | |
331 | return (tp->name); | |
332 | } | |
333 | ||
334 | char * | |
335 | udpport_string(port) | |
336 | register u_short port; | |
337 | { | |
338 | register struct hnamemem *tp; | |
339 | register int i = port; | |
340 | ||
341 | for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) | |
342 | if (tp->addr == i) | |
343 | return (tp->name); | |
344 | ||
345 | tp->name = (char *)malloc(sizeof("00000")); | |
346 | tp->addr = i; | |
347 | tp->nxt = (struct hnamemem *)calloc(1, sizeof(*tp)); | |
348 | ||
349 | (void)sprintf(tp->name, "%d", i); | |
350 | ||
351 | return (tp->name); | |
352 | } | |
353 | ||
354 | static void | |
355 | init_servarray() | |
356 | { | |
357 | struct servent *sv; | |
358 | register struct hnamemem *table; | |
359 | register int i; | |
360 | ||
361 | while (sv = getservent()) { | |
362 | NTOHS(sv->s_port); | |
363 | i = sv->s_port & (HASHNAMESIZE-1); | |
364 | if (strcmp(sv->s_proto, "tcp") == 0) | |
365 | table = &tporttable[i]; | |
366 | else if (strcmp(sv->s_proto, "udp") == 0) | |
367 | table = &uporttable[i]; | |
368 | else | |
369 | continue; | |
370 | ||
371 | while (table->name) | |
372 | table = table->nxt; | |
373 | if (nflag) { | |
374 | char buf[32]; | |
375 | ||
376 | (void)sprintf(buf, "%d", sv->s_port); | |
377 | table->name = (char *)malloc((unsigned)strlen(buf)+1); | |
378 | (void)strcpy(table->name, buf); | |
379 | } else { | |
380 | table->name = | |
381 | (char *)malloc((unsigned)strlen(sv->s_name)+1); | |
382 | (void)strcpy(table->name, sv->s_name); | |
383 | } | |
384 | table->addr = sv->s_port; | |
385 | table->nxt = (struct hnamemem *)calloc(1, sizeof(*table)); | |
386 | } | |
387 | endservent(); | |
388 | } | |
389 | ||
390 | #include "etherproto.h" | |
391 | ||
392 | /* Static data base of ether protocol types. */ | |
393 | struct eproto eproto_db[] = { | |
394 | { "pup", ETHERTYPE_PUP }, | |
395 | { "xns", ETHERTYPE_NS }, | |
396 | { "ip", ETHERTYPE_IP }, | |
397 | { "arp", ETHERTYPE_ARP }, | |
398 | { "rarp", ETHERTYPE_REVARP }, | |
399 | { "sprite", ETHERTYPE_SPRITE }, | |
400 | { "mopdl", ETHERTYPE_MOPDL }, | |
401 | { "moprc", ETHERTYPE_MOPRC }, | |
402 | { "decnet", ETHERTYPE_DN }, | |
403 | { "lat", ETHERTYPE_LAT }, | |
404 | { "lanbridge", ETHERTYPE_LANBRIDGE }, | |
405 | { "vexp", ETHERTYPE_VEXP }, | |
406 | { "vprod", ETHERTYPE_VPROD }, | |
407 | { "atalk", ETHERTYPE_ATALK }, | |
408 | { "atalkarp", ETHERTYPE_AARP }, | |
409 | { "loopback", ETHERTYPE_LOOPBACK }, | |
410 | { (char *)0, 0 } | |
411 | }; | |
412 | ||
413 | static void | |
414 | init_eprotoarray() | |
415 | { | |
416 | register int i; | |
417 | register struct hnamemem *table; | |
418 | ||
419 | for (i = 0; eproto_db[i].s; i++) { | |
420 | int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1); | |
421 | table = &eprototable[j]; | |
422 | while (table->name) | |
423 | table = table->nxt; | |
424 | table->name = eproto_db[i].s; | |
425 | table->addr = ntohs(eproto_db[i].p); | |
426 | table->nxt = (struct hnamemem *)calloc(1, sizeof(*table)); | |
427 | } | |
428 | } | |
429 | ||
430 | static void | |
431 | init_etherarray() | |
432 | { | |
433 | #ifndef ETHER_SERVICE | |
434 | FILE *fp; | |
435 | struct etherent *ep; | |
436 | struct enamemem *tp; | |
437 | ||
438 | fp = fopen(ETHERS_FILE, "r"); | |
439 | if (fp == 0) | |
440 | /* No data base; will have to settle for | |
441 | numeric addresses. */ | |
442 | return; | |
443 | ||
444 | while (ep = next_etherent(fp)) { | |
445 | tp = lookup_emem(ep->addr); | |
446 | tp->e_name = (char *)malloc((unsigned)strlen(ep->name)+1); | |
447 | strcpy(tp->e_name, ep->name); | |
448 | } | |
449 | #endif | |
450 | } | |
451 | ||
452 | /* | |
453 | * Initialize the address to name translation machinery. We map all | |
454 | * non-local IP addresses to numeric addresses if fflag is true (i.e., | |
455 | * to prevent blocking on the nameserver). localnet is the IP address | |
456 | * of the local network. mask is its subnet mask. | |
457 | */ | |
458 | void | |
459 | init_addrtoname(fflag, localnet, mask) | |
460 | int fflag; | |
461 | u_long localnet; | |
462 | u_long mask; | |
463 | { | |
464 | netmask = mask; | |
465 | if (fflag) { | |
466 | f_localnet = localnet; | |
467 | f_netmask = mask; | |
468 | } | |
469 | if (nflag) | |
470 | /* | |
471 | * Simplest way to suppress names. | |
472 | */ | |
473 | return; | |
474 | ||
475 | init_etherarray(); | |
476 | init_servarray(); | |
477 | init_eprotoarray(); | |
478 | } |