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