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