xref: /freebsd/contrib/libpcap/nametoaddr.c (revision ee3e76337136982bd2409a691664d03bdf9cafc6)
18cf6c252SPaul Traina /*
28cf6c252SPaul Traina  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
38cf6c252SPaul Traina  *	The Regents of the University of California.  All rights reserved.
48cf6c252SPaul Traina  *
58cf6c252SPaul Traina  * Redistribution and use in source and binary forms, with or without
68cf6c252SPaul Traina  * modification, are permitted provided that: (1) source code distributions
78cf6c252SPaul Traina  * retain the above copyright notice and this paragraph in its entirety, (2)
88cf6c252SPaul Traina  * distributions including binary code include the above copyright notice and
98cf6c252SPaul Traina  * this paragraph in its entirety in the documentation or other materials
108cf6c252SPaul Traina  * provided with the distribution, and (3) all advertising materials mentioning
118cf6c252SPaul Traina  * features or use of this software display the following acknowledgement:
128cf6c252SPaul Traina  * ``This product includes software developed by the University of California,
138cf6c252SPaul Traina  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
148cf6c252SPaul Traina  * the University nor the names of its contributors may be used to endorse
158cf6c252SPaul Traina  * or promote products derived from this software without specific prior
168cf6c252SPaul Traina  * written permission.
178cf6c252SPaul Traina  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
188cf6c252SPaul Traina  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
198cf6c252SPaul Traina  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
208cf6c252SPaul Traina  *
218cf6c252SPaul Traina  * Name to id translation routines used by the scanner.
228cf6c252SPaul Traina  * These functions are not time critical.
238cf6c252SPaul Traina  */
248cf6c252SPaul Traina 
258cf6c252SPaul Traina #ifndef lint
268cf6c252SPaul Traina static char rcsid[] =
278cf6c252SPaul Traina     "@(#) $Header: nametoaddr.c,v 1.43 96/07/17 00:11:41 leres Exp $ (LBL)";
288cf6c252SPaul Traina #endif
298cf6c252SPaul Traina 
308cf6c252SPaul Traina #include <sys/param.h>
318cf6c252SPaul Traina #include <sys/types.h>				/* concession to AIX */
328cf6c252SPaul Traina #include <sys/socket.h>
33628d2ac1SGarrett Wollman #include <sys/time.h>
348cf6c252SPaul Traina 
358cf6c252SPaul Traina #if __STDC__
368cf6c252SPaul Traina struct mbuf;
378cf6c252SPaul Traina struct rtentry;
388cf6c252SPaul Traina #endif
398cf6c252SPaul Traina 
408cf6c252SPaul Traina #include <net/if.h>
41ee3e7633SGarrett Wollman #include <net/ethernet.h>
428cf6c252SPaul Traina #include <netinet/in.h>
438cf6c252SPaul Traina #include <arpa/inet.h>
448cf6c252SPaul Traina 
458cf6c252SPaul Traina #include <ctype.h>
468cf6c252SPaul Traina #include <errno.h>
478cf6c252SPaul Traina #include <stdlib.h>
488cf6c252SPaul Traina #include <memory.h>
498cf6c252SPaul Traina #include <netdb.h>
508cf6c252SPaul Traina #include <stdio.h>
518cf6c252SPaul Traina 
528cf6c252SPaul Traina #include "pcap-int.h"
538cf6c252SPaul Traina 
548cf6c252SPaul Traina #include "gencode.h"
558cf6c252SPaul Traina #include <pcap-namedb.h>
568cf6c252SPaul Traina 
578cf6c252SPaul Traina #include "gnuc.h"
588cf6c252SPaul Traina #ifdef HAVE_OS_PROTO_H
598cf6c252SPaul Traina #include "os-proto.h"
608cf6c252SPaul Traina #endif
618cf6c252SPaul Traina 
628cf6c252SPaul Traina #ifndef NTOHL
638cf6c252SPaul Traina #define NTOHL(x) (x) = ntohl(x)
648cf6c252SPaul Traina #define NTOHS(x) (x) = ntohs(x)
658cf6c252SPaul Traina #endif
668cf6c252SPaul Traina 
678cf6c252SPaul Traina static inline int xdtoi(int);
688cf6c252SPaul Traina 
698cf6c252SPaul Traina /*
708cf6c252SPaul Traina  *  Convert host name to internet address.
718cf6c252SPaul Traina  *  Return 0 upon failure.
728cf6c252SPaul Traina  */
738cf6c252SPaul Traina bpf_u_int32 **
748cf6c252SPaul Traina pcap_nametoaddr(const char *name)
758cf6c252SPaul Traina {
768cf6c252SPaul Traina #ifndef h_addr
778cf6c252SPaul Traina 	static bpf_u_int32 *hlist[2];
788cf6c252SPaul Traina #endif
798cf6c252SPaul Traina 	bpf_u_int32 **p;
808cf6c252SPaul Traina 	struct hostent *hp;
818cf6c252SPaul Traina 
828cf6c252SPaul Traina 	if ((hp = gethostbyname(name)) != NULL) {
838cf6c252SPaul Traina #ifndef h_addr
848cf6c252SPaul Traina 		hlist[0] = (bpf_u_int32 *)hp->h_addr;
858cf6c252SPaul Traina 		NTOHL(hp->h_addr);
868cf6c252SPaul Traina 		return hlist;
878cf6c252SPaul Traina #else
888cf6c252SPaul Traina 		for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p)
898cf6c252SPaul Traina 			NTOHL(**p);
908cf6c252SPaul Traina 		return (bpf_u_int32 **)hp->h_addr_list;
918cf6c252SPaul Traina #endif
928cf6c252SPaul Traina 	}
938cf6c252SPaul Traina 	else
948cf6c252SPaul Traina 		return 0;
958cf6c252SPaul Traina }
968cf6c252SPaul Traina 
978cf6c252SPaul Traina /*
988cf6c252SPaul Traina  *  Convert net name to internet address.
998cf6c252SPaul Traina  *  Return 0 upon failure.
1008cf6c252SPaul Traina  */
1018cf6c252SPaul Traina bpf_u_int32
1028cf6c252SPaul Traina pcap_nametonetaddr(const char *name)
1038cf6c252SPaul Traina {
1048cf6c252SPaul Traina 	struct netent *np;
1058cf6c252SPaul Traina 
1068cf6c252SPaul Traina 	if ((np = getnetbyname(name)) != NULL)
1078cf6c252SPaul Traina 		return np->n_net;
1088cf6c252SPaul Traina 	else
1098cf6c252SPaul Traina 		return 0;
1108cf6c252SPaul Traina }
1118cf6c252SPaul Traina 
1128cf6c252SPaul Traina /*
1138cf6c252SPaul Traina  * Convert a port name to its port and protocol numbers.
1148cf6c252SPaul Traina  * We assume only TCP or UDP.
1158cf6c252SPaul Traina  * Return 0 upon failure.
1168cf6c252SPaul Traina  */
1178cf6c252SPaul Traina int
1188cf6c252SPaul Traina pcap_nametoport(const char *name, int *port, int *proto)
1198cf6c252SPaul Traina {
1208cf6c252SPaul Traina 	struct servent *sp;
1218cf6c252SPaul Traina 	char *other;
1228cf6c252SPaul Traina 
1238cf6c252SPaul Traina 	sp = getservbyname(name, (char *)0);
1248cf6c252SPaul Traina 	if (sp != NULL) {
1258cf6c252SPaul Traina 		NTOHS(sp->s_port);
1268cf6c252SPaul Traina 		*port = sp->s_port;
1278cf6c252SPaul Traina 		*proto = pcap_nametoproto(sp->s_proto);
1288cf6c252SPaul Traina 		/*
1298cf6c252SPaul Traina 		 * We need to check /etc/services for ambiguous entries.
1308cf6c252SPaul Traina 		 * If we find the ambiguous entry, and it has the
1318cf6c252SPaul Traina 		 * same port number, change the proto to PROTO_UNDEF
1328cf6c252SPaul Traina 		 * so both TCP and UDP will be checked.
1338cf6c252SPaul Traina 		 */
1348cf6c252SPaul Traina 		if (*proto == IPPROTO_TCP)
1358cf6c252SPaul Traina 			other = "udp";
1368cf6c252SPaul Traina 		else
1378cf6c252SPaul Traina 			other = "tcp";
1388cf6c252SPaul Traina 
1398cf6c252SPaul Traina 		sp = getservbyname(name, other);
1408cf6c252SPaul Traina 		if (sp != 0) {
1418cf6c252SPaul Traina 			NTOHS(sp->s_port);
1428cf6c252SPaul Traina #ifdef notdef
1438cf6c252SPaul Traina 			if (*port != sp->s_port)
1448cf6c252SPaul Traina 				/* Can't handle ambiguous names that refer
1458cf6c252SPaul Traina 				   to different port numbers. */
1468cf6c252SPaul Traina 				warning("ambiguous port %s in /etc/services",
1478cf6c252SPaul Traina 					name);
1488cf6c252SPaul Traina #endif
1498cf6c252SPaul Traina 			*proto = PROTO_UNDEF;
1508cf6c252SPaul Traina 		}
1518cf6c252SPaul Traina 		return 1;
1528cf6c252SPaul Traina 	}
1538cf6c252SPaul Traina #if defined(ultrix) || defined(__osf__)
1548cf6c252SPaul Traina 	/* Special hack in case NFS isn't in /etc/services */
1558cf6c252SPaul Traina 	if (strcmp(name, "nfs") == 0) {
1568cf6c252SPaul Traina 		*port = 2049;
1578cf6c252SPaul Traina 		*proto = PROTO_UNDEF;
1588cf6c252SPaul Traina 		return 1;
1598cf6c252SPaul Traina 	}
1608cf6c252SPaul Traina #endif
1618cf6c252SPaul Traina 	return 0;
1628cf6c252SPaul Traina }
1638cf6c252SPaul Traina 
1648cf6c252SPaul Traina int
1658cf6c252SPaul Traina pcap_nametoproto(const char *str)
1668cf6c252SPaul Traina {
1678cf6c252SPaul Traina 	struct protoent *p;
1688cf6c252SPaul Traina 
1698cf6c252SPaul Traina 	p = getprotobyname(str);
1708cf6c252SPaul Traina 	if (p != 0)
1718cf6c252SPaul Traina 		return p->p_proto;
1728cf6c252SPaul Traina 	else
1738cf6c252SPaul Traina 		return PROTO_UNDEF;
1748cf6c252SPaul Traina }
1758cf6c252SPaul Traina 
1768cf6c252SPaul Traina #include "ethertype.h"
1778cf6c252SPaul Traina 
1788cf6c252SPaul Traina struct eproto {
1798cf6c252SPaul Traina 	char *s;
1808cf6c252SPaul Traina 	u_short p;
1818cf6c252SPaul Traina };
1828cf6c252SPaul Traina 
1838cf6c252SPaul Traina /* Static data base of ether protocol types. */
1848cf6c252SPaul Traina struct eproto eproto_db[] = {
1858cf6c252SPaul Traina 	{ "pup", ETHERTYPE_PUP },
1868cf6c252SPaul Traina 	{ "xns", ETHERTYPE_NS },
1878cf6c252SPaul Traina 	{ "ip", ETHERTYPE_IP },
1888cf6c252SPaul Traina 	{ "arp", ETHERTYPE_ARP },
1898cf6c252SPaul Traina 	{ "rarp", ETHERTYPE_REVARP },
1908cf6c252SPaul Traina 	{ "sprite", ETHERTYPE_SPRITE },
1918cf6c252SPaul Traina 	{ "mopdl", ETHERTYPE_MOPDL },
1928cf6c252SPaul Traina 	{ "moprc", ETHERTYPE_MOPRC },
1938cf6c252SPaul Traina 	{ "atalk", ETHERTYPE_ATALK },
1948cf6c252SPaul Traina 	{ "decnet", ETHERTYPE_DN },
1958cf6c252SPaul Traina 	{ "lat", ETHERTYPE_LAT },
1968cf6c252SPaul Traina 	{ "sca", ETHERTYPE_SCA },
1978cf6c252SPaul Traina 	{ "lanbridge", ETHERTYPE_LANBRIDGE },
1988cf6c252SPaul Traina 	{ "vexp", ETHERTYPE_VEXP },
1998cf6c252SPaul Traina 	{ "vprod", ETHERTYPE_VPROD },
2008cf6c252SPaul Traina 	{ "atalk", ETHERTYPE_ATALK },
2018cf6c252SPaul Traina 	{ "atalkarp", ETHERTYPE_AARP },
2028cf6c252SPaul Traina 	{ "loopback", ETHERTYPE_LOOPBACK },
2038cf6c252SPaul Traina 	{ "decdts", ETHERTYPE_DECDTS },
2048cf6c252SPaul Traina 	{ "decdns", ETHERTYPE_DECDNS },
2058cf6c252SPaul Traina 	{ (char *)0, 0 }
2068cf6c252SPaul Traina };
2078cf6c252SPaul Traina 
2088cf6c252SPaul Traina int
2098cf6c252SPaul Traina pcap_nametoeproto(const char *s)
2108cf6c252SPaul Traina {
2118cf6c252SPaul Traina 	struct eproto *p = eproto_db;
2128cf6c252SPaul Traina 
2138cf6c252SPaul Traina 	while (p->s != 0) {
2148cf6c252SPaul Traina 		if (strcmp(p->s, s) == 0)
2158cf6c252SPaul Traina 			return p->p;
2168cf6c252SPaul Traina 		p += 1;
2178cf6c252SPaul Traina 	}
2188cf6c252SPaul Traina 	return PROTO_UNDEF;
2198cf6c252SPaul Traina }
2208cf6c252SPaul Traina 
2218cf6c252SPaul Traina /* Hex digit to integer. */
2228cf6c252SPaul Traina static inline int
2238cf6c252SPaul Traina xdtoi(c)
2248cf6c252SPaul Traina 	register int c;
2258cf6c252SPaul Traina {
2268cf6c252SPaul Traina 	if (isdigit(c))
2278cf6c252SPaul Traina 		return c - '0';
2288cf6c252SPaul Traina 	else if (islower(c))
2298cf6c252SPaul Traina 		return c - 'a' + 10;
2308cf6c252SPaul Traina 	else
2318cf6c252SPaul Traina 		return c - 'A' + 10;
2328cf6c252SPaul Traina }
2338cf6c252SPaul Traina 
2348cf6c252SPaul Traina int
2358cf6c252SPaul Traina __pcap_atoin(const char *s, bpf_u_int32 *addr)
2368cf6c252SPaul Traina {
2378cf6c252SPaul Traina 	u_int n;
2388cf6c252SPaul Traina 	int len;
2398cf6c252SPaul Traina 
2408cf6c252SPaul Traina 	*addr = 0;
2418cf6c252SPaul Traina 	len = 0;
2428cf6c252SPaul Traina 	while (1) {
2438cf6c252SPaul Traina 		n = 0;
2448cf6c252SPaul Traina 		while (*s && *s != '.')
2458cf6c252SPaul Traina 			n = n * 10 + *s++ - '0';
2468cf6c252SPaul Traina 		*addr <<= 8;
2478cf6c252SPaul Traina 		*addr |= n & 0xff;
2488cf6c252SPaul Traina 		len += 8;
2498cf6c252SPaul Traina 		if (*s == '\0')
2508cf6c252SPaul Traina 			return len;
2518cf6c252SPaul Traina 		++s;
2528cf6c252SPaul Traina 	}
2538cf6c252SPaul Traina 	/* NOTREACHED */
2548cf6c252SPaul Traina }
2558cf6c252SPaul Traina 
2568cf6c252SPaul Traina int
2578cf6c252SPaul Traina __pcap_atodn(const char *s, bpf_u_int32 *addr)
2588cf6c252SPaul Traina {
2598cf6c252SPaul Traina #define AREASHIFT 10
2608cf6c252SPaul Traina #define AREAMASK 0176000
2618cf6c252SPaul Traina #define NODEMASK 01777
2628cf6c252SPaul Traina 
2638cf6c252SPaul Traina 	u_int node, area;
2648cf6c252SPaul Traina 
2658cf6c252SPaul Traina 	if (sscanf((char *)s, "%d.%d", &area, &node) != 2)
2668cf6c252SPaul Traina 		bpf_error("malformed decnet address '%s'", s);
2678cf6c252SPaul Traina 
2688cf6c252SPaul Traina 	*addr = (area << AREASHIFT) & AREAMASK;
2698cf6c252SPaul Traina 	*addr |= (node & NODEMASK);
2708cf6c252SPaul Traina 
2718cf6c252SPaul Traina 	return(32);
2728cf6c252SPaul Traina }
2738cf6c252SPaul Traina 
2748cf6c252SPaul Traina /*
2758cf6c252SPaul Traina  * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new
2768cf6c252SPaul Traina  * ethernet address.  Assumes 's' is well formed.
2778cf6c252SPaul Traina  */
2788cf6c252SPaul Traina u_char *
2798cf6c252SPaul Traina pcap_ether_aton(const char *s)
2808cf6c252SPaul Traina {
2818cf6c252SPaul Traina 	register u_char *ep, *e;
2828cf6c252SPaul Traina 	register u_int d;
2838cf6c252SPaul Traina 
2848cf6c252SPaul Traina 	e = ep = (u_char *)malloc(6);
2858cf6c252SPaul Traina 
2868cf6c252SPaul Traina 	while (*s) {
2878cf6c252SPaul Traina 		if (*s == ':')
2888cf6c252SPaul Traina 			s += 1;
2898cf6c252SPaul Traina 		d = xdtoi(*s++);
2908cf6c252SPaul Traina 		if (isxdigit(*s)) {
2918cf6c252SPaul Traina 			d <<= 4;
2928cf6c252SPaul Traina 			d |= xdtoi(*s++);
2938cf6c252SPaul Traina 		}
2948cf6c252SPaul Traina 		*ep++ = d;
2958cf6c252SPaul Traina 	}
2968cf6c252SPaul Traina 
2978cf6c252SPaul Traina 	return (e);
2988cf6c252SPaul Traina }
2998cf6c252SPaul Traina 
3008cf6c252SPaul Traina #ifndef HAVE_ETHER_HOSTTON
3018cf6c252SPaul Traina /* Roll our own */
3028cf6c252SPaul Traina u_char *
3038cf6c252SPaul Traina pcap_ether_hostton(const char *name)
3048cf6c252SPaul Traina {
3058cf6c252SPaul Traina 	register struct pcap_etherent *ep;
3068cf6c252SPaul Traina 	register u_char *ap;
3078cf6c252SPaul Traina 	static FILE *fp = NULL;
3088cf6c252SPaul Traina 	static init = 0;
3098cf6c252SPaul Traina 
3108cf6c252SPaul Traina 	if (!init) {
3118cf6c252SPaul Traina 		fp = fopen(PCAP_ETHERS_FILE, "r");
3128cf6c252SPaul Traina 		++init;
3138cf6c252SPaul Traina 		if (fp == NULL)
3148cf6c252SPaul Traina 			return (NULL);
3158cf6c252SPaul Traina 	} else if (fp == NULL)
3168cf6c252SPaul Traina 		return (NULL);
3178cf6c252SPaul Traina 	else
3188cf6c252SPaul Traina 		rewind(fp);
3198cf6c252SPaul Traina 
3208cf6c252SPaul Traina 	while ((ep = pcap_next_etherent(fp)) != NULL) {
3218cf6c252SPaul Traina 		if (strcmp(ep->name, name) == 0) {
3228cf6c252SPaul Traina 			ap = (u_char *)malloc(6);
3238cf6c252SPaul Traina 			if (ap != NULL) {
3248cf6c252SPaul Traina 				memcpy(ap, ep->addr, 6);
3258cf6c252SPaul Traina 				return (ap);
3268cf6c252SPaul Traina 			}
3278cf6c252SPaul Traina 			break;
3288cf6c252SPaul Traina 		}
3298cf6c252SPaul Traina 	}
3308cf6c252SPaul Traina 	return (NULL);
3318cf6c252SPaul Traina }
3328cf6c252SPaul Traina #else
3338cf6c252SPaul Traina 
3348cf6c252SPaul Traina #ifndef sgi
3358cf6c252SPaul Traina extern int ether_hostton(char *, struct ether_addr *);
3368cf6c252SPaul Traina #endif
3378cf6c252SPaul Traina 
3388cf6c252SPaul Traina /* Use the os supplied routines */
3398cf6c252SPaul Traina u_char *
3408cf6c252SPaul Traina pcap_ether_hostton(const char *name)
3418cf6c252SPaul Traina {
3428cf6c252SPaul Traina 	register u_char *ap;
3438cf6c252SPaul Traina 	u_char a[6];
3448cf6c252SPaul Traina 
3458cf6c252SPaul Traina 	ap = NULL;
3468cf6c252SPaul Traina 	if (ether_hostton((char *)name, (struct ether_addr *)a) == 0) {
3478cf6c252SPaul Traina 		ap = (u_char *)malloc(6);
3488cf6c252SPaul Traina 		if (ap != NULL)
3498cf6c252SPaul Traina 			memcpy(ap, a, 6);
3508cf6c252SPaul Traina 	}
3518cf6c252SPaul Traina 	return (ap);
3528cf6c252SPaul Traina }
3538cf6c252SPaul Traina #endif
3548cf6c252SPaul Traina 
3558cf6c252SPaul Traina u_short
3568cf6c252SPaul Traina __pcap_nametodnaddr(const char *name)
3578cf6c252SPaul Traina {
3588cf6c252SPaul Traina #ifdef	DECNETLIB
3598cf6c252SPaul Traina 	struct nodeent *getnodebyname();
3608cf6c252SPaul Traina 	struct nodeent *nep;
3618cf6c252SPaul Traina 	unsigned short res;
3628cf6c252SPaul Traina 
3638cf6c252SPaul Traina 	nep = getnodebyname(name);
3648cf6c252SPaul Traina 	if (nep == ((struct nodeent *)0))
3658cf6c252SPaul Traina 		bpf_error("unknown decnet host name '%s'\n", name);
3668cf6c252SPaul Traina 
3678cf6c252SPaul Traina 	memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short));
3688cf6c252SPaul Traina 	return(res);
3698cf6c252SPaul Traina #else
3708cf6c252SPaul Traina 	bpf_error("decnet name support not included, '%s' cannot be translated\n",
3718cf6c252SPaul Traina 		name);
3728cf6c252SPaul Traina #endif
3738cf6c252SPaul Traina }
374