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