Removed definition "LIB= rpc". We want libc.a to contain librpc.a, not
[unix-history] / .ref-386BSD-0.1-patchkit / usr / src / contrib / tcpdump / tcpdump / addrtoname.c
CommitLineData
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
25static 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
52struct hnamemem {
53 u_long addr;
54 char *name;
55 struct hnamemem *nxt;
56};
57
58struct hnamemem hnametable[HASHNAMESIZE];
59struct hnamemem tporttable[HASHNAMESIZE];
60struct hnamemem uporttable[HASHNAMESIZE];
61struct hnamemem eprototable[HASHNAMESIZE];
62
63struct 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
71struct enamemem enametable[HASHNAMESIZE];
72
73
74/*
75 * A faster replacement for inet_ntoa().
76 */
77char *
78intoa(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
108static u_long f_netmask;
109static u_long f_localnet;
110static 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
118jmp_buf getname_env;
119
120static void
121nohostname()
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 */
130char *
131getname(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
222static char hex[] = "0123456789abcdef";
223
224
225/* Find the hash node that corresponds the ether address 'ep'. */
226
227static inline struct enamemem *
228lookup_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
254char *
255etheraddr_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
290char *
291etherproto_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
315char *
316tcpport_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
334char *
335udpport_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
354static void
355init_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. */
393struct 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
413static void
414init_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
430static void
431init_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 */
458void
459init_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}