xref: /openbsd-src/lib/libpcap/nametoaddr.c (revision 5262edafad5bc5784d91cd8e4a68ecd2668ca51e)
1 /*	$OpenBSD: nametoaddr.c,v 1.2 1996/03/04 15:47:22 mickey Exp $	*/
2 /*	$NetBSD: nametoaddr.c,v 1.3 1995/04/29 05:42:23 cgd Exp $	*/
3 
4 /*
5  * Copyright (c) 1990, 1991, 1992, 1993, 1994
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that: (1) source code distributions
10  * retain the above copyright notice and this paragraph in its entirety, (2)
11  * distributions including binary code include the above copyright notice and
12  * this paragraph in its entirety in the documentation or other materials
13  * provided with the distribution, and (3) all advertising materials mentioning
14  * features or use of this software display the following acknowledgement:
15  * ``This product includes software developed by the University of California,
16  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
17  * the University nor the names of its contributors may be used to endorse
18  * or promote products derived from this software without specific prior
19  * written permission.
20  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
21  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
22  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23  *
24  * Name to id translation routines used by the scanner.
25  * These functions are not time critical.
26  */
27 
28 #ifndef lint
29 static char rcsid[] =
30     "@(#) Header: nametoaddr.c,v 1.21 94/06/20 19:07:54 leres Exp (LBL)";
31 #endif
32 
33 #include <sys/param.h>
34 #include <sys/socket.h>
35 #include <net/if.h>
36 #include <netinet/in.h>
37 #include <netinet/if_ether.h>
38 #include <arpa/inet.h>
39 
40 #include <ctype.h>
41 #include <errno.h>
42 #include <netdb.h>
43 #include <pcap.h>
44 #include <pcap-namedb.h>
45 #include <stdio.h>
46 #ifdef __NetBSD__
47 #include <stdlib.h>
48 #include <string.h>
49 #endif
50 
51 #include "gencode.h"
52 
53 #ifndef __GNUC__
54 #define inline
55 #endif
56 
57 #ifndef NTOHL
58 #define NTOHL(x) (x) = ntohl(x)
59 #define NTOHS(x) (x) = ntohs(x)
60 #endif
61 
62 static inline int xdtoi(int);
63 
64 /*
65  *  Convert host name to internet address.
66  *  Return 0 upon failure.
67  */
68 u_long **
69 pcap_nametoaddr(const char *name)
70 {
71 #ifndef h_addr
72 	static u_long *hlist[2];
73 #endif
74 	u_long **p;
75 	struct hostent *hp;
76 
77 	if ((hp = gethostbyname(name)) != NULL) {
78 #ifndef h_addr
79 		hlist[0] = (u_long *)hp->h_addr;
80 		NTOHL(hp->h_addr);
81 		return hlist;
82 #else
83 		for (p = (u_long **)hp->h_addr_list; *p; ++p)
84 			NTOHL(**p);
85 		return (u_long **)hp->h_addr_list;
86 #endif
87 	}
88 	else
89 		return 0;
90 }
91 
92 /*
93  *  Convert net name to internet address.
94  *  Return 0 upon failure.
95  */
96 u_long
97 pcap_nametonetaddr(const char *name)
98 {
99 	struct netent *np;
100 
101 	if ((np = getnetbyname(name)) != NULL)
102 		return np->n_net;
103 	else
104 		return 0;
105 }
106 
107 /*
108  * Convert a port name to its port and protocol numbers.
109  * We assume only TCP or UDP.
110  * Return 0 upon failure.
111  */
112 int
113 pcap_nametoport(const char *name, int *port, int *proto)
114 {
115 	struct servent *sp;
116 	char *other;
117 
118 	sp = getservbyname(name, (char *)0);
119 	if (sp != NULL) {
120 		NTOHS(sp->s_port);
121 		*port = sp->s_port;
122 		*proto = pcap_nametoproto(sp->s_proto);
123 		/*
124 		 * We need to check /etc/services for ambiguous entries.
125 		 * If we find the ambiguous entry, and it has the
126 		 * same port number, change the proto to PROTO_UNDEF
127 		 * so both TCP and UDP will be checked.
128 		 */
129 		if (*proto == IPPROTO_TCP)
130 			other = "udp";
131 		else
132 			other = "tcp";
133 
134 		sp = getservbyname(name, other);
135 		if (sp != 0) {
136 			NTOHS(sp->s_port);
137 			if (*port != sp->s_port)
138 				/* Can't handle ambiguous names that refer
139 				   to different port numbers. */
140 #ifdef notdef
141 				warning("ambiguous port %s in /etc/services",
142 					name);
143 #else
144 			;
145 #endif
146 			*proto = PROTO_UNDEF;
147 		}
148 		return 1;
149 	}
150 #if defined(ultrix) || defined(__osf__)
151 	/* Special hack in case NFS isn't in /etc/services */
152 	if (strcmp(name, "nfs") == 0) {
153 		*port = 2049;
154 		*proto = PROTO_UNDEF;
155 		return 1;
156 	}
157 #endif
158 	return 0;
159 }
160 
161 int
162 pcap_nametoproto(const char *str)
163 {
164 	struct protoent *p;
165 
166 	p = getprotobyname(str);
167 	if (p != 0)
168 		return p->p_proto;
169 	else
170 		return PROTO_UNDEF;
171 }
172 
173 #include "ethertype.h"
174 
175 struct eproto {
176 	char *s;
177 	u_short p;
178 };
179 
180 /* Static data base of ether protocol types. */
181 struct eproto eproto_db[] = {
182 	{ "pup", ETHERTYPE_PUP },
183 	{ "xns", ETHERTYPE_NS },
184 	{ "ip", ETHERTYPE_IP },
185 	{ "arp", ETHERTYPE_ARP },
186 	{ "rarp", ETHERTYPE_REVARP },
187 	{ "sprite", ETHERTYPE_SPRITE },
188 	{ "mopdl", ETHERTYPE_MOPDL },
189 	{ "moprc", ETHERTYPE_MOPRC },
190 	{ "decnet", ETHERTYPE_DN },
191 	{ "lat", ETHERTYPE_LAT },
192 	{ "lanbridge", ETHERTYPE_LANBRIDGE },
193 	{ "vexp", ETHERTYPE_VEXP },
194 	{ "vprod", ETHERTYPE_VPROD },
195 	{ "atalk", ETHERTYPE_ATALK },
196 	{ "atalkarp", ETHERTYPE_AARP },
197 	{ "loopback", ETHERTYPE_LOOPBACK },
198 	{ "decdts", ETHERTYPE_DECDTS },
199 	{ "decdns", ETHERTYPE_DECDNS },
200 	{ (char *)0, 0 }
201 };
202 
203 int
204 pcap_nametoeproto(const char *s)
205 {
206 	struct eproto *p = eproto_db;
207 
208 	while (p->s != 0) {
209 		if (strcmp(p->s, s) == 0)
210 			return p->p;
211 		p += 1;
212 	}
213 	return PROTO_UNDEF;
214 }
215 
216 /* Hex digit to integer. */
217 static inline int
218 xdtoi(c)
219 	register int c;
220 {
221 	if (isdigit(c))
222 		return c - '0';
223 	else if (islower(c))
224 		return c - 'a' + 10;
225 	else
226 		return c - 'A' + 10;
227 }
228 
229 u_long
230 __pcap_atoin(const char *s)
231 {
232 	u_long addr = 0;
233 	u_int n;
234 
235 	while (1) {
236 		n = 0;
237 		while (*s && *s != '.')
238 			n = n * 10 + *s++ - '0';
239 		addr <<= 8;
240 		addr |= n & 0xff;
241 		if (*s == '\0')
242 			return addr;
243 		++s;
244 	}
245 	/* NOTREACHED */
246 }
247 
248 u_long
249 __pcap_atodn(const char *s)
250 {
251 #define AREASHIFT 10
252 #define AREAMASK 0176000
253 #define NODEMASK 01777
254 
255 	u_long addr = 0;
256 	u_int node, area;
257 
258 	if (sscanf((char *)s, "%d.%d", &area, &node) != 2)
259 		bpf_error("malformed decnet address '%s'", s);
260 
261 	addr = (area << AREASHIFT) & AREAMASK;
262 	addr |= (node & NODEMASK);
263 
264 	return(addr);
265 }
266 
267 /*
268  * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new
269  * ethernet address.  Assumes 's' is well formed.
270  */
271 u_char *
272 pcap_ether_aton(const char *s)
273 {
274 	register u_char *ep, *e;
275 	register u_int d;
276 
277 	e = ep = (u_char *)malloc(6);
278 
279 	while (*s) {
280 		if (*s == ':')
281 			s += 1;
282 		d = xdtoi(*s++);
283 		if (isxdigit(*s)) {
284 			d <<= 4;
285 			d |= xdtoi(*s++);
286 		}
287 		*ep++ = d;
288 	}
289 
290 	return (e);
291 }
292 
293 #ifndef ETHER_SERVICE
294 /* Roll our own */
295 u_char *
296 pcap_ether_hostton(const char *name)
297 {
298 	register struct pcap_etherent *ep;
299 	register u_char *ap;
300 	static FILE *fp = NULL;
301 	static init = 0;
302 
303 	if (!init) {
304 		fp = fopen(PCAP_ETHERS_FILE, "r");
305 		++init;
306 		if (fp == NULL)
307 			return (NULL);
308 	} else if (fp == NULL)
309 		return (NULL);
310 	else
311 		rewind(fp);
312 
313 	while ((ep = pcap_next_etherent(fp)) != NULL) {
314 		if (strcmp(ep->name, name) == 0) {
315 			ap = (u_char *)malloc(6);
316 			if (ap != NULL) {
317 				memcpy(ap, ep->addr, 6);
318 				return (ap);
319 			}
320 			break;
321 		}
322 	}
323 	return (NULL);
324 }
325 #else
326 /* Use the os supplied routines */
327 u_char *
328 pcap_ether_hostton(const char *name)
329 {
330 	register u_char *ap;
331 	u_char a[6];
332 #ifndef sgi
333 	extern int ether_hostton(char *, struct ether_addr *);
334 #endif
335 
336 	ap = NULL;
337 	if (ether_hostton((char*)name, (struct ether_addr *)a) == 0) {
338 		ap = (u_char *)malloc(6);
339 		if (ap != NULL)
340 			memcpy(ap, a, 6);
341 	}
342 	return (ap);
343 }
344 #endif
345 
346 u_short
347 __pcap_nametodnaddr(const char *name)
348 {
349 #ifdef	DECNETLIB
350 	struct nodeent *getnodebyname();
351 	struct nodeent *nep;
352 	unsigned short res;
353 
354 	nep = getnodebyname(name);
355 	if (nep == ((struct nodeent *)0))
356 		bpf_error("unknown decnet host name '%s'\n", name);
357 
358 	memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short));
359 	return(res);
360 #else
361 	bpf_error("decnet name support not included, '%s' cannot be translated\n",
362 		name);
363 #endif
364 }
365