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