17576Swpaul/*
2169520Srwatson * Copyright (c) 1995 Bill Paul <wpaul@ctr.columbia.edu>.
3169522Srwatson * Copyright (c) 2007 Robert N. M. Watson
4169520Srwatson * All rights reserved.
57576Swpaul *
67576Swpaul * Redistribution and use in source and binary forms, with or without
77576Swpaul * modification, are permitted provided that the following conditions
87576Swpaul * are met:
97576Swpaul * 1. Redistributions of source code must retain the above copyright
107576Swpaul *    notice, this list of conditions and the following disclaimer.
117576Swpaul * 2. Redistributions in binary form must reproduce the above copyright
127576Swpaul *    notice, this list of conditions and the following disclaimer in the
137576Swpaul *    documentation and/or other materials provided with the distribution.
147576Swpaul * 3. All advertising materials mentioning features or use of this software
157576Swpaul *    must display the following acknowledgement:
167576Swpaul *	This product includes software developed by Bill Paul.
177576Swpaul * 4. Neither the name of the author nor the names of any co-contributors
187576Swpaul *    may be used to endorse or promote products derived from this software
197576Swpaul *    without specific prior written permission.
207576Swpaul *
217576Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
227576Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
237576Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
247576Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
257576Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
267576Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
277576Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
287576Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
297576Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
307576Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
317576Swpaul * SUCH DAMAGE.
327576Swpaul *
337576Swpaul * ethernet address conversion and lookup routines
347576Swpaul *
357576Swpaul * Written by Bill Paul <wpaul@ctr.columbia.edu>
367576Swpaul * Center for Telecommunications Research
377576Swpaul * Columbia University, New York City
387576Swpaul */
397576Swpaul
4091725Seric#include <sys/cdefs.h>
4191725Seric__FBSDID("$FreeBSD$");
427576Swpaul
437576Swpaul#include <sys/types.h>
447576Swpaul#include <sys/param.h>
457576Swpaul#include <sys/socket.h>
46169520Srwatson
4720288Swollman#include <net/ethernet.h>
48169520Srwatson
497576Swpaul#ifdef YP
507576Swpaul#include <rpc/rpc.h>
517576Swpaul#include <rpcsvc/yp_prot.h>
527576Swpaul#include <rpcsvc/ypclnt.h>
537576Swpaul#endif
547576Swpaul
55169520Srwatson#include <paths.h>
56169520Srwatson#include <stdio.h>
57169520Srwatson#include <stdlib.h>
58169520Srwatson#include <string.h>
59169520Srwatson
607576Swpaul#ifndef _PATH_ETHERS
61169520Srwatson#define	_PATH_ETHERS	"/etc/ethers"
627576Swpaul#endif
637576Swpaul
647576Swpaul/*
65169520Srwatson * Parse a string of text containing an ethernet address and hostname and
66169520Srwatson * separate it into its component parts.
677576Swpaul */
6891725Sericint
69169520Srwatsonether_line(const char *l, struct ether_addr *e, char *hostname)
707576Swpaul{
71169522Srwatson	int i, o[6];
727576Swpaul
73169522Srwatson	i = sscanf(l, "%x:%x:%x:%x:%x:%x %s", &o[0], &o[1], &o[2], &o[3],
74169520Srwatson	    &o[4], &o[5], hostname);
75264592Sjmmv	if (i == 7) {
76264592Sjmmv		for (i = 0; i < 6; i++)
77264592Sjmmv			e->octet[i] = o[i];
78264592Sjmmv		return (0);
79264592Sjmmv	} else {
80264592Sjmmv		return (-1);
81264592Sjmmv	}
827576Swpaul}
837576Swpaul
847576Swpaul/*
85169520Srwatson * Convert an ASCII representation of an ethernet address to binary form.
867576Swpaul */
87169520Srwatsonstruct ether_addr *
88169522Srwatsonether_aton_r(const char *a, struct ether_addr *e)
897576Swpaul{
90169522Srwatson	int i;
9117141Sjkh	unsigned int o0, o1, o2, o3, o4, o5;
927576Swpaul
93169522Srwatson	i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5);
94169522Srwatson	if (i != 6)
95169522Srwatson		return (NULL);
96169522Srwatson	e->octet[0]=o0;
97169522Srwatson	e->octet[1]=o1;
98169522Srwatson	e->octet[2]=o2;
99169522Srwatson	e->octet[3]=o3;
100169522Srwatson	e->octet[4]=o4;
101169522Srwatson	e->octet[5]=o5;
102169522Srwatson	return (e);
1037576Swpaul}
1047576Swpaul
105169522Srwatsonstruct ether_addr *
106169522Srwatsonether_aton(const char *a)
107169522Srwatson{
108169522Srwatson	static struct ether_addr e;
109169522Srwatson
110169522Srwatson	return (ether_aton_r(a, &e));
111169522Srwatson}
112169522Srwatson
1137576Swpaul/*
114169520Srwatson * Convert a binary representation of an ethernet address to an ASCII string.
1157576Swpaul */
116169520Srwatsonchar *
117169522Srwatsonether_ntoa_r(const struct ether_addr *n, char *a)
118169522Srwatson{
119169522Srwatson	int i;
120169522Srwatson
121169522Srwatson	i = sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x", n->octet[0],
122169522Srwatson	    n->octet[1], n->octet[2], n->octet[3], n->octet[4], n->octet[5]);
123169522Srwatson	if (i < 17)
124169522Srwatson		return (NULL);
125169522Srwatson	return (a);
126169522Srwatson}
127169522Srwatson
128169522Srwatsonchar *
129169520Srwatsonether_ntoa(const struct ether_addr *n)
1307576Swpaul{
1317576Swpaul	static char a[18];
1327576Swpaul
133169522Srwatson	return (ether_ntoa_r(n, a));
1347576Swpaul}
1357576Swpaul
1367576Swpaul/*
137169520Srwatson * Map an ethernet address to a hostname. Use either /etc/ethers or NIS/YP.
1387576Swpaul */
13991725Sericint
140169520Srwatsonether_ntohost(char *hostname, const struct ether_addr *e)
1417576Swpaul{
1427576Swpaul	FILE *fp;
14320953Swpaul	char buf[BUFSIZ + 2];
1447576Swpaul	struct ether_addr local_ether;
1457576Swpaul	char local_host[MAXHOSTNAMELEN];
1467576Swpaul#ifdef YP
1477576Swpaul	char *result;
1487576Swpaul	int resultlen;
1497576Swpaul	char *ether_a;
1507576Swpaul	char *yp_domain;
1517576Swpaul#endif
152169520Srwatson
153254700Sjilles	if ((fp = fopen(_PATH_ETHERS, "re")) == NULL)
1547576Swpaul		return (1);
1557576Swpaul	while (fgets(buf,BUFSIZ,fp)) {
1567576Swpaul		if (buf[0] == '#')
1577576Swpaul			continue;
1587576Swpaul#ifdef YP
1597576Swpaul		if (buf[0] == '+') {
1607576Swpaul			if (yp_get_default_domain(&yp_domain))
1619978Swpaul				continue;
1627576Swpaul			ether_a = ether_ntoa(e);
1637576Swpaul			if (yp_match(yp_domain, "ethers.byaddr", ether_a,
164169520Srwatson			    strlen(ether_a), &result, &resultlen)) {
1659978Swpaul				continue;
1667576Swpaul			}
16720164Sjkh			strncpy(buf, result, resultlen);
16820953Swpaul			buf[resultlen] = '\0';
16920953Swpaul			free(result);
1707576Swpaul		}
1717576Swpaul#endif
17220164Sjkh		if (!ether_line(buf, &local_ether, local_host)) {
1737576Swpaul			if (!bcmp((char *)&local_ether.octet[0],
174169520Srwatson			    (char *)&e->octet[0], 6)) {
175169520Srwatson				/* We have a match. */
17620164Sjkh				strcpy(hostname, local_host);
1777576Swpaul				fclose(fp);
1787576Swpaul				return(0);
1797576Swpaul			}
1807576Swpaul		}
1817576Swpaul	}
1827576Swpaul	fclose(fp);
1837576Swpaul	return (1);
1847576Swpaul}
1857576Swpaul
1867576Swpaul/*
187169520Srwatson * Map a hostname to an ethernet address using /etc/ethers or NIS/YP.
1887576Swpaul */
18991725Sericint
190169520Srwatsonether_hostton(const char *hostname, struct ether_addr *e)
1917576Swpaul{
1927576Swpaul	FILE *fp;
19320953Swpaul	char buf[BUFSIZ + 2];
1947576Swpaul	struct ether_addr local_ether;
1957576Swpaul	char local_host[MAXHOSTNAMELEN];
1967576Swpaul#ifdef YP
1977576Swpaul	char *result;
1987576Swpaul	int resultlen;
1997576Swpaul	char *yp_domain;
2007576Swpaul#endif
201169520Srwatson
202254700Sjilles	if ((fp = fopen(_PATH_ETHERS, "re")) == NULL)
2037576Swpaul		return (1);
2047576Swpaul	while (fgets(buf,BUFSIZ,fp)) {
2057576Swpaul		if (buf[0] == '#')
2067576Swpaul			continue;
2077576Swpaul#ifdef YP
2087576Swpaul		if (buf[0] == '+') {
2097576Swpaul			if (yp_get_default_domain(&yp_domain))
2109978Swpaul				continue;
2117576Swpaul			if (yp_match(yp_domain, "ethers.byname", hostname,
212169520Srwatson			    strlen(hostname), &result, &resultlen)) {
2139978Swpaul				continue;
2147576Swpaul			}
21520164Sjkh			strncpy(buf, result, resultlen);
21620953Swpaul			buf[resultlen] = '\0';
2179978Swpaul			free(result);
2187576Swpaul		}
2197576Swpaul#endif
22020164Sjkh		if (!ether_line(buf, &local_ether, local_host)) {
22120164Sjkh			if (!strcmp(hostname, local_host)) {
222169520Srwatson				/* We have a match. */
2237576Swpaul				bcopy((char *)&local_ether.octet[0],
224169520Srwatson				    (char *)&e->octet[0], 6);
2257576Swpaul				fclose(fp);
2267576Swpaul				return(0);
2277576Swpaul			}
2287576Swpaul		}
2297576Swpaul	}
2307576Swpaul	fclose(fp);
2317576Swpaul	return (1);
2327576Swpaul}
233