]> The Tcpdump Group git mirrors - libpcap/blob - nametoaddr.c
8fc2e8d9f2bfad3f648377f42cba23612d7d0ce6
[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 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #ifdef DECNETLIB
30 #include <sys/types.h>
31 #include <netdnet/dnetdb.h>
32 #endif
33
34 #ifdef _WIN32
35 #include <pcap-stdinc.h>
36
37 #ifdef INET6
38 /*
39 * To quote the MSDN page for getaddrinfo() at
40 *
41 * https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx
42 *
43 * "Support for getaddrinfo on Windows 2000 and older versions
44 * The getaddrinfo function was added to the Ws2_32.dll on Windows XP and
45 * later. To execute an application that uses this function on earlier
46 * versions of Windows, then you need to include the Ws2tcpip.h and
47 * Wspiapi.h files. When the Wspiapi.h include file is added, the
48 * getaddrinfo function is defined to the WspiapiGetAddrInfo inline
49 * function in the Wspiapi.h file. At runtime, the WspiapiGetAddrInfo
50 * function is implemented in such a way that if the Ws2_32.dll or the
51 * Wship6.dll (the file containing getaddrinfo in the IPv6 Technology
52 * Preview for Windows 2000) does not include getaddrinfo, then a
53 * version of getaddrinfo is implemented inline based on code in the
54 * Wspiapi.h header file. This inline code will be used on older Windows
55 * platforms that do not natively support the getaddrinfo function."
56 *
57 * We use getaddrinfo(), so we include Wspiapi.h here. pcap-stdinc.h
58 * includes Ws2tcpip.h, so we don't need to include it ourselves.
59 */
60 #include <Wspiapi.h>
61 #endif
62
63 #else /* _WIN32 */
64
65 #include <sys/param.h>
66 #include <sys/types.h> /* concession to AIX */
67 #include <sys/socket.h>
68 #include <sys/time.h>
69
70 #include <netinet/in.h>
71 #endif /* _WIN32 */
72
73 #ifndef _WIN32
74 #ifdef HAVE_ETHER_HOSTTON
75 /*
76 * XXX - do we need any of this if <netinet/if_ether.h> doesn't declare
77 * ether_hostton()?
78 */
79 #ifdef HAVE_NETINET_IF_ETHER_H
80 struct mbuf; /* Squelch compiler warnings on some platforms for */
81 struct rtentry; /* declarations in <net/if.h> */
82 #include <net/if.h> /* for "struct ifnet" in "struct arpcom" on Solaris */
83 #include <netinet/if_ether.h>
84
85 /*
86 * NetBSD insists on having <net/if.h> pull in <net/dlt.h>, so that
87 * including <net/if.h> defines a bunch of stuff we later define in our
88 * pcap/dlt.h; those definitions will be different, if they haven't
89 * picked up all of our changes yet.
90 *
91 * Undefine some of the offending items.
92 */
93 #ifdef __NetBSD__
94 #undef DLT_USB /* we now define it as DLT_FREEBSD_USB */
95 #undef DLT_MATCHING_MAX /* we may define more DLT_ values than they do */
96 #endif
97
98 #endif /* HAVE_NETINET_IF_ETHER_H */
99 #ifdef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON
100 #include <netinet/ether.h>
101 #endif /* NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */
102 #endif /* HAVE_ETHER_HOSTTON */
103 #include <arpa/inet.h>
104 #include <netdb.h>
105 #endif /* _WIN32 */
106
107 #include <ctype.h>
108 #include <errno.h>
109 #include <stdlib.h>
110 #include <string.h>
111 #include <stdio.h>
112
113 #include "pcap-int.h"
114
115 #include "gencode.h"
116 #include <pcap/namedb.h>
117 #include "nametoaddr.h"
118
119 #ifdef HAVE_OS_PROTO_H
120 #include "os-proto.h"
121 #endif
122
123 #ifndef NTOHL
124 #define NTOHL(x) (x) = ntohl(x)
125 #define NTOHS(x) (x) = ntohs(x)
126 #endif
127
128 static inline int xdtoi(int);
129
130 /*
131 * Convert host name to internet address.
132 * Return 0 upon failure.
133 */
134 bpf_u_int32 **
135 pcap_nametoaddr(const char *name)
136 {
137 #ifndef h_addr
138 static bpf_u_int32 *hlist[2];
139 #endif
140 bpf_u_int32 **p;
141 struct hostent *hp;
142
143 if ((hp = gethostbyname(name)) != NULL) {
144 #ifndef h_addr
145 hlist[0] = (bpf_u_int32 *)hp->h_addr;
146 NTOHL(hp->h_addr);
147 return hlist;
148 #else
149 for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p)
150 NTOHL(**p);
151 return (bpf_u_int32 **)hp->h_addr_list;
152 #endif
153 }
154 else
155 return 0;
156 }
157
158 #ifdef INET6
159 struct addrinfo *
160 pcap_nametoaddrinfo(const char *name)
161 {
162 struct addrinfo hints, *res;
163 int error;
164
165 memset(&hints, 0, sizeof(hints));
166 hints.ai_family = PF_UNSPEC;
167 hints.ai_socktype = SOCK_STREAM; /*not really*/
168 hints.ai_protocol = IPPROTO_TCP; /*not really*/
169 error = getaddrinfo(name, NULL, &hints, &res);
170 if (error)
171 return NULL;
172 else
173 return res;
174 }
175 #endif /*INET6*/
176
177 /*
178 * Convert net name to internet address.
179 * Return 0 upon failure.
180 */
181 bpf_u_int32
182 pcap_nametonetaddr(const char *name)
183 {
184 #ifndef _WIN32
185 struct netent *np;
186
187 if ((np = getnetbyname(name)) != NULL)
188 return np->n_net;
189 else
190 return 0;
191 #else
192 /*
193 * There's no "getnetbyname()" on Windows.
194 *
195 * XXX - I guess we could use the BSD code to read
196 * C:\Windows\System32\drivers\etc/networks, assuming
197 * that's its home on all the versions of Windows
198 * we use, but that file probably just has the loopback
199 * network on 127/24 on 99 44/100% of Windows machines.
200 *
201 * (Heck, these days it probably just has that on 99 44/100%
202 * of *UN*X* machines.)
203 */
204 return 0;
205 #endif
206 }
207
208 /*
209 * Convert a port name to its port and protocol numbers.
210 * We assume only TCP or UDP.
211 * Return 0 upon failure.
212 */
213 int
214 pcap_nametoport(const char *name, int *port, int *proto)
215 {
216 struct servent *sp;
217 int tcp_port = -1;
218 int udp_port = -1;
219
220 /*
221 * We need to check /etc/services for ambiguous entries.
222 * If we find the ambiguous entry, and it has the
223 * same port number, change the proto to PROTO_UNDEF
224 * so both TCP and UDP will be checked.
225 */
226 sp = getservbyname(name, "tcp");
227 if (sp != NULL) tcp_port = ntohs(sp->s_port);
228 sp = getservbyname(name, "udp");
229 if (sp != NULL) udp_port = ntohs(sp->s_port);
230 if (tcp_port >= 0) {
231 *port = tcp_port;
232 *proto = IPPROTO_TCP;
233 if (udp_port >= 0) {
234 if (udp_port == tcp_port)
235 *proto = PROTO_UNDEF;
236 #ifdef notdef
237 else
238 /* Can't handle ambiguous names that refer
239 to different port numbers. */
240 warning("ambiguous port %s in /etc/services",
241 name);
242 #endif
243 }
244 return 1;
245 }
246 if (udp_port >= 0) {
247 *port = udp_port;
248 *proto = IPPROTO_UDP;
249 return 1;
250 }
251 #if defined(ultrix) || defined(__osf__)
252 /* Special hack in case NFS isn't in /etc/services */
253 if (strcmp(name, "nfs") == 0) {
254 *port = 2049;
255 *proto = PROTO_UNDEF;
256 return 1;
257 }
258 #endif
259 return 0;
260 }
261
262 /*
263 * Convert a string in the form PPP-PPP, where correspond to ports, to
264 * a starting and ending port in a port range.
265 * Return 0 on failure.
266 */
267 int
268 pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto)
269 {
270 u_int p1, p2;
271 char *off, *cpy;
272 int save_proto;
273
274 if (sscanf(name, "%d-%d", &p1, &p2) != 2) {
275 if ((cpy = strdup(name)) == NULL)
276 return 0;
277
278 if ((off = strchr(cpy, '-')) == NULL) {
279 free(cpy);
280 return 0;
281 }
282
283 *off = '\0';
284
285 if (pcap_nametoport(cpy, port1, proto) == 0) {
286 free(cpy);
287 return 0;
288 }
289 save_proto = *proto;
290
291 if (pcap_nametoport(off + 1, port2, proto) == 0) {
292 free(cpy);
293 return 0;
294 }
295 free(cpy);
296
297 if (*proto != save_proto)
298 *proto = PROTO_UNDEF;
299 } else {
300 *port1 = p1;
301 *port2 = p2;
302 *proto = PROTO_UNDEF;
303 }
304
305 return 1;
306 }
307
308 int
309 pcap_nametoproto(const char *str)
310 {
311 struct protoent *p;
312
313 p = getprotobyname(str);
314 if (p != 0)
315 return p->p_proto;
316 else
317 return PROTO_UNDEF;
318 }
319
320 #include "ethertype.h"
321
322 struct eproto {
323 const char *s;
324 u_short p;
325 };
326
327 /*
328 * Static data base of ether protocol types.
329 * tcpdump used to import this, and it's declared as an export on
330 * Debian, at least, so make it a public symbol, even though we
331 * don't officially export it by declaring it in a header file.
332 * (Programs *should* do this themselves, as tcpdump now does.)
333 */
334 PCAP_API_DEF struct eproto eproto_db[] = {
335 { "pup", ETHERTYPE_PUP },
336 { "xns", ETHERTYPE_NS },
337 { "ip", ETHERTYPE_IP },
338 #ifdef INET6
339 { "ip6", ETHERTYPE_IPV6 },
340 #endif
341 { "arp", ETHERTYPE_ARP },
342 { "rarp", ETHERTYPE_REVARP },
343 { "sprite", ETHERTYPE_SPRITE },
344 { "mopdl", ETHERTYPE_MOPDL },
345 { "moprc", ETHERTYPE_MOPRC },
346 { "decnet", ETHERTYPE_DN },
347 { "lat", ETHERTYPE_LAT },
348 { "sca", ETHERTYPE_SCA },
349 { "lanbridge", ETHERTYPE_LANBRIDGE },
350 { "vexp", ETHERTYPE_VEXP },
351 { "vprod", ETHERTYPE_VPROD },
352 { "atalk", ETHERTYPE_ATALK },
353 { "atalkarp", ETHERTYPE_AARP },
354 { "loopback", ETHERTYPE_LOOPBACK },
355 { "decdts", ETHERTYPE_DECDTS },
356 { "decdns", ETHERTYPE_DECDNS },
357 { (char *)0, 0 }
358 };
359
360 int
361 pcap_nametoeproto(const char *s)
362 {
363 struct eproto *p = eproto_db;
364
365 while (p->s != 0) {
366 if (strcmp(p->s, s) == 0)
367 return p->p;
368 p += 1;
369 }
370 return PROTO_UNDEF;
371 }
372
373 #include "llc.h"
374
375 /* Static data base of LLC values. */
376 static struct eproto llc_db[] = {
377 { "iso", LLCSAP_ISONS },
378 { "stp", LLCSAP_8021D },
379 { "ipx", LLCSAP_IPX },
380 { "netbeui", LLCSAP_NETBEUI },
381 { (char *)0, 0 }
382 };
383
384 int
385 pcap_nametollc(const char *s)
386 {
387 struct eproto *p = llc_db;
388
389 while (p->s != 0) {
390 if (strcmp(p->s, s) == 0)
391 return p->p;
392 p += 1;
393 }
394 return PROTO_UNDEF;
395 }
396
397 /* Hex digit to integer. */
398 static inline int
399 xdtoi(c)
400 register int c;
401 {
402 if (isdigit(c))
403 return c - '0';
404 else if (islower(c))
405 return c - 'a' + 10;
406 else
407 return c - 'A' + 10;
408 }
409
410 int
411 __pcap_atoin(const char *s, bpf_u_int32 *addr)
412 {
413 u_int n;
414 int len;
415
416 *addr = 0;
417 len = 0;
418 while (1) {
419 n = 0;
420 while (*s && *s != '.')
421 n = n * 10 + *s++ - '0';
422 *addr <<= 8;
423 *addr |= n & 0xff;
424 len += 8;
425 if (*s == '\0')
426 return len;
427 ++s;
428 }
429 /* NOTREACHED */
430 }
431
432 int
433 __pcap_atodn(const char *s, bpf_u_int32 *addr)
434 {
435 #define AREASHIFT 10
436 #define AREAMASK 0176000
437 #define NODEMASK 01777
438
439 u_int node, area;
440
441 if (sscanf(s, "%d.%d", &area, &node) != 2)
442 return(0);
443
444 *addr = (area << AREASHIFT) & AREAMASK;
445 *addr |= (node & NODEMASK);
446
447 return(32);
448 }
449
450 /*
451 * Convert 's', which can have the one of the forms:
452 *
453 * "xx:xx:xx:xx:xx:xx"
454 * "xx.xx.xx.xx.xx.xx"
455 * "xx-xx-xx-xx-xx-xx"
456 * "xxxx.xxxx.xxxx"
457 * "xxxxxxxxxxxx"
458 *
459 * (or various mixes of ':', '.', and '-') into a new
460 * ethernet address. Assumes 's' is well formed.
461 */
462 u_char *
463 pcap_ether_aton(const char *s)
464 {
465 register u_char *ep, *e;
466 register u_int d;
467
468 e = ep = (u_char *)malloc(6);
469 if (e == NULL)
470 return (NULL);
471
472 while (*s) {
473 if (*s == ':' || *s == '.' || *s == '-')
474 s += 1;
475 d = xdtoi(*s++);
476 if (isxdigit((unsigned char)*s)) {
477 d <<= 4;
478 d |= xdtoi(*s++);
479 }
480 *ep++ = d;
481 }
482
483 return (e);
484 }
485
486 #ifndef HAVE_ETHER_HOSTTON
487 /* Roll our own */
488 u_char *
489 pcap_ether_hostton(const char *name)
490 {
491 register struct pcap_etherent *ep;
492 register u_char *ap;
493 static FILE *fp = NULL;
494 static int init = 0;
495
496 if (!init) {
497 fp = fopen(PCAP_ETHERS_FILE, "r");
498 ++init;
499 if (fp == NULL)
500 return (NULL);
501 } else if (fp == NULL)
502 return (NULL);
503 else
504 rewind(fp);
505
506 while ((ep = pcap_next_etherent(fp)) != NULL) {
507 if (strcmp(ep->name, name) == 0) {
508 ap = (u_char *)malloc(6);
509 if (ap != NULL) {
510 memcpy(ap, ep->addr, 6);
511 return (ap);
512 }
513 break;
514 }
515 }
516 return (NULL);
517 }
518 #else
519
520 #if !defined(HAVE_DECL_ETHER_HOSTTON) || !HAVE_DECL_ETHER_HOSTTON
521 #ifndef HAVE_STRUCT_ETHER_ADDR
522 struct ether_addr {
523 unsigned char ether_addr_octet[6];
524 };
525 #endif
526 extern int ether_hostton(const char *, struct ether_addr *);
527 #endif
528
529 /* Use the os supplied routines */
530 u_char *
531 pcap_ether_hostton(const char *name)
532 {
533 register u_char *ap;
534 u_char a[6];
535
536 ap = NULL;
537 if (ether_hostton(name, (struct ether_addr *)a) == 0) {
538 ap = (u_char *)malloc(6);
539 if (ap != NULL)
540 memcpy((char *)ap, (char *)a, 6);
541 }
542 return (ap);
543 }
544 #endif
545
546 int
547 __pcap_nametodnaddr(const char *name, u_short *res)
548 {
549 #ifdef DECNETLIB
550 struct nodeent *getnodebyname();
551 struct nodeent *nep;
552
553 nep = getnodebyname(name);
554 if (nep == ((struct nodeent *)0))
555 return(0);
556
557 memcpy((char *)res, (char *)nep->n_addr, sizeof(unsigned short));
558 return(1);
559 #else
560 return(0);
561 #endif
562 }