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