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