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);
757576Swpaul	if (i != 7)
76169522Srwatson		return (i);
77169522Srwatson	for (i=0; i<6; i++)
78169522Srwatson		e->octet[i] = o[i];
79169522Srwatson	return (0);
807576Swpaul}
817576Swpaul
827576Swpaul/*
83169520Srwatson * Convert an ASCII representation of an ethernet address to binary form.
847576Swpaul */
85169520Srwatsonstruct ether_addr *
86169522Srwatsonether_aton_r(const char *a, struct ether_addr *e)
877576Swpaul{
88169522Srwatson	int i;
8917141Sjkh	unsigned int o0, o1, o2, o3, o4, o5;
907576Swpaul
91169522Srwatson	i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5);
92169522Srwatson	if (i != 6)
93169522Srwatson		return (NULL);
94169522Srwatson	e->octet[0]=o0;
95169522Srwatson	e->octet[1]=o1;
96169522Srwatson	e->octet[2]=o2;
97169522Srwatson	e->octet[3]=o3;
98169522Srwatson	e->octet[4]=o4;
99169522Srwatson	e->octet[5]=o5;
100169522Srwatson	return (e);
1017576Swpaul}
1027576Swpaul
103169522Srwatsonstruct ether_addr *
104169522Srwatsonether_aton(const char *a)
105169522Srwatson{
106169522Srwatson	static struct ether_addr e;
107169522Srwatson
108169522Srwatson	return (ether_aton_r(a, &e));
109169522Srwatson}
110169522Srwatson
1117576Swpaul/*
112169520Srwatson * Convert a binary representation of an ethernet address to an ASCII string.
1137576Swpaul */
114169520Srwatsonchar *
115169522Srwatsonether_ntoa_r(const struct ether_addr *n, char *a)
116169522Srwatson{
117169522Srwatson	int i;
118169522Srwatson
119169522Srwatson	i = sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x", n->octet[0],
120169522Srwatson	    n->octet[1], n->octet[2], n->octet[3], n->octet[4], n->octet[5]);
121169522Srwatson	if (i < 17)
122169522Srwatson		return (NULL);
123169522Srwatson	return (a);
124169522Srwatson}
125169522Srwatson
126169522Srwatsonchar *
127169520Srwatsonether_ntoa(const struct ether_addr *n)
1287576Swpaul{
1297576Swpaul	static char a[18];
1307576Swpaul
131169522Srwatson	return (ether_ntoa_r(n, a));
1327576Swpaul}
1337576Swpaul
1347576Swpaul/*
135169520Srwatson * Map an ethernet address to a hostname. Use either /etc/ethers or NIS/YP.
1367576Swpaul */
13791725Sericint
138169520Srwatsonether_ntohost(char *hostname, const struct ether_addr *e)
1397576Swpaul{
1407576Swpaul	FILE *fp;
14120953Swpaul	char buf[BUFSIZ + 2];
1427576Swpaul	struct ether_addr local_ether;
1437576Swpaul	char local_host[MAXHOSTNAMELEN];
1447576Swpaul#ifdef YP
1457576Swpaul	char *result;
1467576Swpaul	int resultlen;
1477576Swpaul	char *ether_a;
1487576Swpaul	char *yp_domain;
1497576Swpaul#endif
150169520Srwatson
1517576Swpaul	if ((fp = fopen(_PATH_ETHERS, "r")) == NULL)
1527576Swpaul		return (1);
1537576Swpaul	while (fgets(buf,BUFSIZ,fp)) {
1547576Swpaul		if (buf[0] == '#')
1557576Swpaul			continue;
1567576Swpaul#ifdef YP
1577576Swpaul		if (buf[0] == '+') {
1587576Swpaul			if (yp_get_default_domain(&yp_domain))
1599978Swpaul				continue;
1607576Swpaul			ether_a = ether_ntoa(e);
1617576Swpaul			if (yp_match(yp_domain, "ethers.byaddr", ether_a,
162169520Srwatson			    strlen(ether_a), &result, &resultlen)) {
1639978Swpaul				continue;
1647576Swpaul			}
16520164Sjkh			strncpy(buf, result, resultlen);
16620953Swpaul			buf[resultlen] = '\0';
16720953Swpaul			free(result);
1687576Swpaul		}
1697576Swpaul#endif
17020164Sjkh		if (!ether_line(buf, &local_ether, local_host)) {
1717576Swpaul			if (!bcmp((char *)&local_ether.octet[0],
172169520Srwatson			    (char *)&e->octet[0], 6)) {
173169520Srwatson				/* We have a match. */
17420164Sjkh				strcpy(hostname, local_host);
1757576Swpaul				fclose(fp);
1767576Swpaul				return(0);
1777576Swpaul			}
1787576Swpaul		}
1797576Swpaul	}
1807576Swpaul	fclose(fp);
1817576Swpaul	return (1);
1827576Swpaul}
1837576Swpaul
1847576Swpaul/*
185169520Srwatson * Map a hostname to an ethernet address using /etc/ethers or NIS/YP.
1867576Swpaul */
18791725Sericint
188169520Srwatsonether_hostton(const char *hostname, struct ether_addr *e)
1897576Swpaul{
1907576Swpaul	FILE *fp;
19120953Swpaul	char buf[BUFSIZ + 2];
1927576Swpaul	struct ether_addr local_ether;
1937576Swpaul	char local_host[MAXHOSTNAMELEN];
1947576Swpaul#ifdef YP
1957576Swpaul	char *result;
1967576Swpaul	int resultlen;
1977576Swpaul	char *yp_domain;
1987576Swpaul#endif
199169520Srwatson
2007576Swpaul	if ((fp = fopen(_PATH_ETHERS, "r")) == NULL)
2017576Swpaul		return (1);
2027576Swpaul	while (fgets(buf,BUFSIZ,fp)) {
2037576Swpaul		if (buf[0] == '#')
2047576Swpaul			continue;
2057576Swpaul#ifdef YP
2067576Swpaul		if (buf[0] == '+') {
2077576Swpaul			if (yp_get_default_domain(&yp_domain))
2089978Swpaul				continue;
2097576Swpaul			if (yp_match(yp_domain, "ethers.byname", hostname,
210169520Srwatson			    strlen(hostname), &result, &resultlen)) {
2119978Swpaul				continue;
2127576Swpaul			}
21320164Sjkh			strncpy(buf, result, resultlen);
21420953Swpaul			buf[resultlen] = '\0';
2159978Swpaul			free(result);
2167576Swpaul		}
2177576Swpaul#endif
21820164Sjkh		if (!ether_line(buf, &local_ether, local_host)) {
21920164Sjkh			if (!strcmp(hostname, local_host)) {
220169520Srwatson				/* We have a match. */
2217576Swpaul				bcopy((char *)&local_ether.octet[0],
222169520Srwatson				    (char *)&e->octet[0], 6);
2237576Swpaul				fclose(fp);
2247576Swpaul				return(0);
2257576Swpaul			}
2267576Swpaul		}
2277576Swpaul	}
2287576Swpaul	fclose(fp);
2297576Swpaul	return (1);
2307576Swpaul}
231