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