xref: /freebsd/contrib/libpcap/nametoaddr.c (revision b52b9d56d4e96089873a75f9e29062eec19fabba)
1 /*
2  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
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  * Name to id translation routines used by the scanner.
22  * These functions are not time critical.
23  *
24  * $FreeBSD$
25  */
26 
27 #ifndef lint
28 static const char rcsid[] =
29     "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.60 2001/07/28 22:56:35 guy Exp $ (LBL)";
30 #endif
31 
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35 
36 #include <sys/param.h>
37 #include <sys/types.h>				/* concession to AIX */
38 #include <sys/socket.h>
39 #include <sys/time.h>
40 
41 struct mbuf;
42 struct rtentry;
43 #include <net/if.h>
44 #include <netinet/in.h>
45 #ifdef HAVE_NETINET_IF_ETHER_H
46 #include <netinet/if_ether.h>
47 #endif
48 #include <arpa/inet.h>
49 #ifdef INET6
50 #include <netdb.h>
51 #include <sys/socket.h>
52 #endif /*INET6*/
53 
54 #include <ctype.h>
55 #include <errno.h>
56 #include <stdlib.h>
57 #include <memory.h>
58 #include <netdb.h>
59 #include <stdio.h>
60 
61 #include "pcap-int.h"
62 
63 #include "gencode.h"
64 #include <pcap-namedb.h>
65 
66 #ifdef HAVE_OS_PROTO_H
67 #include "os-proto.h"
68 #endif
69 
70 #ifndef NTOHL
71 #define NTOHL(x) (x) = ntohl(x)
72 #define NTOHS(x) (x) = ntohs(x)
73 #endif
74 
75 static inline int xdtoi(int);
76 
77 /*
78  *  Convert host name to internet address.
79  *  Return 0 upon failure.
80  */
81 bpf_u_int32 **
82 pcap_nametoaddr(const char *name)
83 {
84 #ifndef h_addr
85 	static bpf_u_int32 *hlist[2];
86 #endif
87 	bpf_u_int32 **p;
88 	struct hostent *hp;
89 
90 	if ((hp = gethostbyname(name)) != NULL) {
91 #ifndef h_addr
92 		hlist[0] = (bpf_u_int32 *)hp->h_addr;
93 		NTOHL(hp->h_addr);
94 		return hlist;
95 #else
96 		for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p)
97 			NTOHL(**p);
98 		return (bpf_u_int32 **)hp->h_addr_list;
99 #endif
100 	}
101 	else
102 		return 0;
103 }
104 
105 #ifdef INET6
106 struct addrinfo *
107 pcap_nametoaddrinfo(const char *name)
108 {
109 	struct addrinfo hints, *res;
110 	int error;
111 
112 	memset(&hints, 0, sizeof(hints));
113 	hints.ai_family = PF_UNSPEC;
114 	hints.ai_socktype = SOCK_STREAM;	/*not really*/
115 	error = getaddrinfo(name, NULL, &hints, &res);
116 	if (error)
117 		return NULL;
118 	else
119 		return res;
120 }
121 #endif /*INET6*/
122 
123 /*
124  *  Convert net name to internet address.
125  *  Return 0 upon failure.
126  */
127 bpf_u_int32
128 pcap_nametonetaddr(const char *name)
129 {
130 	struct netent *np;
131 
132 	if ((np = getnetbyname(name)) != NULL)
133 		return np->n_net;
134 	else
135 		return 0;
136 }
137 
138 /*
139  * Convert a port name to its port and protocol numbers.
140  * We assume only TCP or UDP.
141  * Return 0 upon failure.
142  */
143 int
144 pcap_nametoport(const char *name, int *port, int *proto)
145 {
146 	struct servent *sp;
147 	char *other;
148 
149 	sp = getservbyname(name, (char *)0);
150 	if (sp != NULL) {
151 		NTOHS(sp->s_port);
152 		*port = sp->s_port;
153 		*proto = pcap_nametoproto(sp->s_proto);
154 		/*
155 		 * We need to check /etc/services for ambiguous entries.
156 		 * If we find the ambiguous entry, and it has the
157 		 * same port number, change the proto to PROTO_UNDEF
158 		 * so both TCP and UDP will be checked.
159 		 */
160 		if (*proto == IPPROTO_TCP)
161 			other = "udp";
162 		else
163 			other = "tcp";
164 
165 		sp = getservbyname(name, other);
166 		if (sp != 0) {
167 			NTOHS(sp->s_port);
168 #ifdef notdef
169 			if (*port != sp->s_port)
170 				/* Can't handle ambiguous names that refer
171 				   to different port numbers. */
172 				warning("ambiguous port %s in /etc/services",
173 					name);
174 #endif
175 			*proto = PROTO_UNDEF;
176 		}
177 		return 1;
178 	}
179 #if defined(ultrix) || defined(__osf__)
180 	/* Special hack in case NFS isn't in /etc/services */
181 	if (strcmp(name, "nfs") == 0) {
182 		*port = 2049;
183 		*proto = PROTO_UNDEF;
184 		return 1;
185 	}
186 #endif
187 	return 0;
188 }
189 
190 int
191 pcap_nametoproto(const char *str)
192 {
193 	struct protoent *p;
194 
195 	p = getprotobyname(str);
196 	if (p != 0)
197 		return p->p_proto;
198 	else
199 		return PROTO_UNDEF;
200 }
201 
202 #include "ethertype.h"
203 
204 struct eproto {
205 	char *s;
206 	u_short p;
207 };
208 
209 /* Static data base of ether protocol types. */
210 struct eproto eproto_db[] = {
211 #if 0
212 	/* The FreeBSD elf linker generates a request to copy this array
213 	 * (including its size) when you link with -lpcap.  In order to
214 	 * not bump the major version number of this libpcap.so, we need
215 	 * to ensure that the array stays the same size.  Since PUP is
216 	 * likely never seen in real life any more, it's the first to
217 	 * be sacrificed (in favor of ip6).
218 	 */
219 	{ "pup", ETHERTYPE_PUP },
220 #endif
221 	{ "xns", ETHERTYPE_NS },
222 	{ "ip", ETHERTYPE_IP },
223 #ifdef INET6
224 	{ "ip6", ETHERTYPE_IPV6 },
225 #endif
226 	{ "arp", ETHERTYPE_ARP },
227 	{ "rarp", ETHERTYPE_REVARP },
228 	{ "sprite", ETHERTYPE_SPRITE },
229 	{ "mopdl", ETHERTYPE_MOPDL },
230 	{ "moprc", ETHERTYPE_MOPRC },
231 	{ "decnet", ETHERTYPE_DN },
232 	{ "lat", ETHERTYPE_LAT },
233 	{ "sca", ETHERTYPE_SCA },
234 	{ "lanbridge", ETHERTYPE_LANBRIDGE },
235 	{ "vexp", ETHERTYPE_VEXP },
236 	{ "vprod", ETHERTYPE_VPROD },
237 	{ "atalk", ETHERTYPE_ATALK },
238 	{ "atalkarp", ETHERTYPE_AARP },
239 	{ "loopback", ETHERTYPE_LOOPBACK },
240 	{ "decdts", ETHERTYPE_DECDTS },
241 	{ "decdns", ETHERTYPE_DECDNS },
242 	{ (char *)0, 0 }
243 };
244 
245 int
246 pcap_nametoeproto(const char *s)
247 {
248 	struct eproto *p = eproto_db;
249 
250 	while (p->s != 0) {
251 		if (strcmp(p->s, s) == 0)
252 			return p->p;
253 		p += 1;
254 	}
255 	return PROTO_UNDEF;
256 }
257 
258 /* Hex digit to integer. */
259 static inline int
260 xdtoi(c)
261 	register int c;
262 {
263 	if (isdigit(c))
264 		return c - '0';
265 	else if (islower(c))
266 		return c - 'a' + 10;
267 	else
268 		return c - 'A' + 10;
269 }
270 
271 int
272 __pcap_atoin(const char *s, bpf_u_int32 *addr)
273 {
274 	u_int n;
275 	int len;
276 
277 	*addr = 0;
278 	len = 0;
279 	while (1) {
280 		n = 0;
281 		while (*s && *s != '.')
282 			n = n * 10 + *s++ - '0';
283 		*addr <<= 8;
284 		*addr |= n & 0xff;
285 		len += 8;
286 		if (*s == '\0')
287 			return len;
288 		++s;
289 	}
290 	/* NOTREACHED */
291 }
292 
293 int
294 __pcap_atodn(const char *s, bpf_u_int32 *addr)
295 {
296 #define AREASHIFT 10
297 #define AREAMASK 0176000
298 #define NODEMASK 01777
299 
300 	u_int node, area;
301 
302 	if (sscanf((char *)s, "%d.%d", &area, &node) != 2)
303 		bpf_error("malformed decnet address '%s'", s);
304 
305 	*addr = (area << AREASHIFT) & AREAMASK;
306 	*addr |= (node & NODEMASK);
307 
308 	return(32);
309 }
310 
311 /*
312  * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new
313  * ethernet address.  Assumes 's' is well formed.
314  */
315 u_char *
316 pcap_ether_aton(const char *s)
317 {
318 	register u_char *ep, *e;
319 	register u_int d;
320 
321 	e = ep = (u_char *)malloc(6);
322 
323 	while (*s) {
324 		if (*s == ':')
325 			s += 1;
326 		d = xdtoi(*s++);
327 		if (isxdigit((unsigned char)*s)) {
328 			d <<= 4;
329 			d |= xdtoi(*s++);
330 		}
331 		*ep++ = d;
332 	}
333 
334 	return (e);
335 }
336 
337 #ifndef HAVE_ETHER_HOSTTON
338 /* Roll our own */
339 u_char *
340 pcap_ether_hostton(const char *name)
341 {
342 	register struct pcap_etherent *ep;
343 	register u_char *ap;
344 	static FILE *fp = NULL;
345 	static int init = 0;
346 
347 	if (!init) {
348 		fp = fopen(PCAP_ETHERS_FILE, "r");
349 		++init;
350 		if (fp == NULL)
351 			return (NULL);
352 	} else if (fp == NULL)
353 		return (NULL);
354 	else
355 		rewind(fp);
356 
357 	while ((ep = pcap_next_etherent(fp)) != NULL) {
358 		if (strcmp(ep->name, name) == 0) {
359 			ap = (u_char *)malloc(6);
360 			if (ap != NULL) {
361 				memcpy(ap, ep->addr, 6);
362 				return (ap);
363 			}
364 			break;
365 		}
366 	}
367 	return (NULL);
368 }
369 #else
370 
371 /*
372  * XXX - perhaps this should, instead, be declared in "lbl/os-XXX.h" files,
373  * for those OS versions that don't declare it, rather than being declared
374  * here?  That way, for example, we could declare it on FreeBSD 2.x (which
375  * doesn't declare it), but not on FreeBSD 3.x (which declares it like
376  * this) or FreeBSD 4.x (which declares it with its first argument as
377  * "const char *", so no matter how we declare it here, it'll fail to
378  * compile on one of 3.x or 4.x).
379  */
380 #if !defined(sgi) && !defined(__NetBSD__) && !defined(__FreeBSD__)
381 extern int ether_hostton(char *, struct ether_addr *);
382 #endif
383 
384 /* Use the os supplied routines */
385 u_char *
386 pcap_ether_hostton(const char *name)
387 {
388 	register u_char *ap;
389 	u_char a[6];
390 
391 	ap = NULL;
392 	if (ether_hostton((char *)name, (struct ether_addr *)a) == 0) {
393 		ap = (u_char *)malloc(6);
394 		if (ap != NULL)
395 			memcpy((char *)ap, (char *)a, 6);
396 	}
397 	return (ap);
398 }
399 #endif
400 
401 u_short
402 __pcap_nametodnaddr(const char *name)
403 {
404 #ifdef	DECNETLIB
405 	struct nodeent *getnodebyname();
406 	struct nodeent *nep;
407 	unsigned short res;
408 
409 	nep = getnodebyname(name);
410 	if (nep == ((struct nodeent *)0))
411 		bpf_error("unknown decnet host name '%s'\n", name);
412 
413 	memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short));
414 	return(res);
415 #else
416 	bpf_error("decnet name support not included, '%s' cannot be translated\n",
417 		name);
418 	return(0);
419 #endif
420 }
421