xref: /netbsd-src/lib/libc/net/ethers.c (revision 9a513d96431ccbcc88e47c95deb796c0a8049327)
1*9a513d96Schristos /*	$NetBSD: ethers.c,v 1.25 2014/09/18 13:58:20 christos Exp $	*/
2ef0582f1Scgd 
36a386550Sderaadt /*
46a386550Sderaadt  * ethers(3N) a la Sun.
56a386550Sderaadt  *
66a386550Sderaadt  * Written by Roland McGrath <roland@frob.com> 10/14/93.
76a386550Sderaadt  * Public domain.
86a386550Sderaadt  */
96a386550Sderaadt 
1072eddcacSitojun #include <sys/cdefs.h>
1172eddcacSitojun #if defined(LIBC_SCCS) && !defined(lint)
12*9a513d96Schristos __RCSID("$NetBSD: ethers.c,v 1.25 2014/09/18 13:58:20 christos Exp $");
1372eddcacSitojun #endif /* LIBC_SCCS and not lint */
1472eddcacSitojun 
1543fa6fe3Sjtc #include "namespace.h"
16b48252f3Slukem #include <sys/param.h>
176a386550Sderaadt #include <sys/socket.h>
18b48252f3Slukem 
196a386550Sderaadt #include <net/if.h>
20bfb66aafSis #include <net/if_ether.h>
216a386550Sderaadt #include <netinet/in.h>
22b48252f3Slukem 
23b48252f3Slukem #include <assert.h>
246a386550Sderaadt #include <errno.h>
25b48252f3Slukem #include <paths.h>
266a386550Sderaadt #include <stdio.h>
27a5313a04Sjtc #include <stdlib.h>
28a5313a04Sjtc #include <string.h>
29b48252f3Slukem 
308d36d340Schristos #ifdef YP
318d36d340Schristos #include <rpcsvc/ypclnt.h>
328d36d340Schristos #endif
336a386550Sderaadt 
3443fa6fe3Sjtc #ifdef __weak_alias
__weak_alias(ether_aton,_ether_aton)3560549036Smycroft __weak_alias(ether_aton,_ether_aton)
3660549036Smycroft __weak_alias(ether_hostton,_ether_hostton)
3760549036Smycroft __weak_alias(ether_line,_ether_line)
3860549036Smycroft __weak_alias(ether_ntoa,_ether_ntoa)
3960549036Smycroft __weak_alias(ether_ntohost,_ether_ntohost)
4043fa6fe3Sjtc #endif
4143fa6fe3Sjtc 
426a386550Sderaadt #ifndef _PATH_ETHERS
436a386550Sderaadt #define _PATH_ETHERS "/etc/ethers"
446a386550Sderaadt #endif
456a386550Sderaadt 
466a386550Sderaadt char *
47504f8671Smatt ether_ntoa(const struct ether_addr *e)
486a386550Sderaadt {
49ec143cf9Smycroft 	static char a[18];
506a386550Sderaadt 
51b48252f3Slukem 	_DIAGASSERT(e != NULL);
52b48252f3Slukem 
53377e179dStron 	(void) snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x",
546a386550Sderaadt 	    e->ether_addr_octet[0], e->ether_addr_octet[1],
556a386550Sderaadt 	    e->ether_addr_octet[2], e->ether_addr_octet[3],
566a386550Sderaadt 	    e->ether_addr_octet[4], e->ether_addr_octet[5]);
576a386550Sderaadt 	return a;
586a386550Sderaadt }
596a386550Sderaadt 
606a386550Sderaadt struct ether_addr *
ether_aton(const char * s)61504f8671Smatt ether_aton(const char *s)
626a386550Sderaadt {
636a386550Sderaadt 	static struct ether_addr n;
646a386550Sderaadt 	u_int i[6];
656a386550Sderaadt 
66b48252f3Slukem 	_DIAGASSERT(s != NULL);
67b48252f3Slukem 
686a386550Sderaadt 	if (sscanf(s, " %x:%x:%x:%x:%x:%x ", &i[0], &i[1],
696a386550Sderaadt 	    &i[2], &i[3], &i[4], &i[5]) == 6) {
706a386550Sderaadt 		n.ether_addr_octet[0] = (u_char)i[0];
716a386550Sderaadt 		n.ether_addr_octet[1] = (u_char)i[1];
726a386550Sderaadt 		n.ether_addr_octet[2] = (u_char)i[2];
736a386550Sderaadt 		n.ether_addr_octet[3] = (u_char)i[3];
746a386550Sderaadt 		n.ether_addr_octet[4] = (u_char)i[4];
756a386550Sderaadt 		n.ether_addr_octet[5] = (u_char)i[5];
766a386550Sderaadt 		return &n;
776a386550Sderaadt 	}
786a386550Sderaadt 	return NULL;
796a386550Sderaadt }
806a386550Sderaadt 
81486b24efSmikel int
ether_ntohost(char * hostname,const struct ether_addr * e)82504f8671Smatt ether_ntohost(char *hostname, const struct ether_addr *e)
836a386550Sderaadt {
846a386550Sderaadt 	FILE *f;
85d96a1a93Slukem 	char *p;
866a386550Sderaadt 	struct ether_addr try;
876a386550Sderaadt 
88b48252f3Slukem 	_DIAGASSERT(hostname != NULL);
89b48252f3Slukem 	_DIAGASSERT(e != NULL);
90b48252f3Slukem 
91b48252f3Slukem #ifdef YP
92f2d4db7cSchristos 	char trybuf[sizeof "xx:xx:xx:xx:xx:xx"];
93f2d4db7cSchristos 	int trylen;
94d96a1a93Slukem 	trylen = snprintf(trybuf, sizeof trybuf, "%x:%x:%x:%x:%x:%x",
956a386550Sderaadt 	    e->ether_addr_octet[0], e->ether_addr_octet[1],
966a386550Sderaadt 	    e->ether_addr_octet[2], e->ether_addr_octet[3],
976a386550Sderaadt 	    e->ether_addr_octet[4], e->ether_addr_octet[5]);
986a386550Sderaadt #endif
996a386550Sderaadt 
100*9a513d96Schristos 	f = fopen(_PATH_ETHERS, "re");
1016a386550Sderaadt 	if (f == NULL)
1026a386550Sderaadt 		return -1;
103f2d4db7cSchristos 	for (p = NULL;;) {
104f2d4db7cSchristos 		free(p);
105f2d4db7cSchristos 		p = fparseln(f, NULL, NULL, NULL, FPARSELN_UNESCALL);
106f2d4db7cSchristos 		if (p == NULL)
107f2d4db7cSchristos 			break;
1086a386550Sderaadt #ifdef YP
1096a386550Sderaadt 		/* A + in the file means try YP now.  */
110f2d4db7cSchristos 		if (strcmp(p, "+") == 0) {
1116a386550Sderaadt 			char *ypbuf, *ypdom;
1126a386550Sderaadt 			int ypbuflen;
1136a386550Sderaadt 
1146a386550Sderaadt 			if (yp_get_default_domain(&ypdom))
1156a386550Sderaadt 				continue;
1166a386550Sderaadt 			if (yp_match(ypdom, "ethers.byaddr", trybuf,
1176a386550Sderaadt 			    trylen, &ypbuf, &ypbuflen))
1186a386550Sderaadt 				continue;
119f2d4db7cSchristos 			ypbuflen = ether_line(ypbuf, &try, hostname);
1206a386550Sderaadt 			free(ypbuf);
121f2d4db7cSchristos 			if (ypbuflen == 0)
122f2d4db7cSchristos 				goto done;
12346c1a166Sderaadt 			continue;
1246a386550Sderaadt 		}
1256a386550Sderaadt #endif
126d96a1a93Slukem 		if (ether_line(p, &try, hostname) == 0 &&
127f2d4db7cSchristos 		    memcmp(&try, e, sizeof try) == 0)
128f2d4db7cSchristos 			goto done;
1296a386550Sderaadt 	}
130f2d4db7cSchristos 	free(p);
1316a386550Sderaadt 	(void)fclose(f);
1326a386550Sderaadt 	errno = ENOENT;
1336a386550Sderaadt 	return -1;
134f2d4db7cSchristos done:
135f2d4db7cSchristos 	free(p);
136f2d4db7cSchristos 	(void)fclose(f);
137f2d4db7cSchristos 	return 0;
1386a386550Sderaadt }
1396a386550Sderaadt 
140486b24efSmikel int
ether_hostton(const char * hostname,struct ether_addr * e)141504f8671Smatt ether_hostton(const char *hostname, struct ether_addr *e)
1426a386550Sderaadt {
1436a386550Sderaadt 	FILE *f;
144d96a1a93Slukem 	char *p;
145d96a1a93Slukem 	char try[MAXHOSTNAMELEN + 1];
1466a386550Sderaadt #ifdef YP
147c5e820caSchristos 	int hostlen = (int)strlen(hostname);
1486a386550Sderaadt #endif
1496a386550Sderaadt 
150b48252f3Slukem 	_DIAGASSERT(hostname != NULL);
151b48252f3Slukem 	_DIAGASSERT(e != NULL);
152b48252f3Slukem 
153*9a513d96Schristos 	f = fopen(_PATH_ETHERS, "re");
1546a386550Sderaadt 	if (f == NULL)
1556a386550Sderaadt 		return -1;
1566a386550Sderaadt 
157f2d4db7cSchristos 	for (p = NULL;;) {
158f2d4db7cSchristos 		free(p);
159f2d4db7cSchristos 		p = fparseln(f, NULL, NULL, NULL, FPARSELN_UNESCALL);
160f2d4db7cSchristos 		if (p == NULL)
161f2d4db7cSchristos 			break;
1626a386550Sderaadt #ifdef YP
1636a386550Sderaadt 		/* A + in the file means try YP now.  */
164f2d4db7cSchristos 		if (strcmp(p, "+") == 0) {
1656a386550Sderaadt 			char *ypbuf, *ypdom;
1666a386550Sderaadt 			int ypbuflen;
1676a386550Sderaadt 
1686a386550Sderaadt 			if (yp_get_default_domain(&ypdom))
1696a386550Sderaadt 				continue;
1706a386550Sderaadt 			if (yp_match(ypdom, "ethers.byname", hostname, hostlen,
1716a386550Sderaadt 			    &ypbuf, &ypbuflen))
1726a386550Sderaadt 				continue;
173f2d4db7cSchristos 			ypbuflen = ether_line(ypbuf, e, try);
1746a386550Sderaadt 			free(ypbuf);
175f2d4db7cSchristos 			if (ypbuflen == 0)
176f2d4db7cSchristos 				goto done;
17746c1a166Sderaadt 			continue;
1786a386550Sderaadt 		}
1796a386550Sderaadt #endif
180f2d4db7cSchristos 		if (ether_line(p, e, try) == 0 && strcmp(hostname, try) == 0)
181f2d4db7cSchristos 			goto done;
1826a386550Sderaadt 	}
183f2d4db7cSchristos 	free(p);
1846a386550Sderaadt 	(void)fclose(f);
1856a386550Sderaadt 	errno = ENOENT;
1866a386550Sderaadt 	return -1;
187f2d4db7cSchristos done:
188f2d4db7cSchristos 	free(p);
189f2d4db7cSchristos 	(void)fclose(f);
190f2d4db7cSchristos 	return 0;
1916a386550Sderaadt }
1926a386550Sderaadt 
193486b24efSmikel int
ether_line(const char * l,struct ether_addr * e,char * hostname)194504f8671Smatt ether_line(const char *l, struct ether_addr *e, char *hostname)
1956a386550Sderaadt {
1966a386550Sderaadt 	u_int i[6];
197ae42ec16Ssommerfeld 
198ae42ec16Ssommerfeld #define S2(arg) #arg
199ae42ec16Ssommerfeld #define S1(arg) S2(arg)
200a5cb9c8fSmartin 	static const char fmt[] = " %x:%x:%x:%x:%x:%x"
201ae42ec16Ssommerfeld 	    " %" S1(MAXHOSTNAMELEN) "s\n";
202ae42ec16Ssommerfeld #undef S2
203ae42ec16Ssommerfeld #undef S1
2046a386550Sderaadt 
205b48252f3Slukem 	_DIAGASSERT(l != NULL);
206b48252f3Slukem 	_DIAGASSERT(e != NULL);
207b48252f3Slukem 	_DIAGASSERT(hostname != NULL);
208b48252f3Slukem 
209ae42ec16Ssommerfeld 	if (sscanf(l, fmt,
210d96a1a93Slukem 	    &i[0], &i[1], &i[2], &i[3], &i[4], &i[5], hostname) == 7) {
2116a386550Sderaadt 		e->ether_addr_octet[0] = (u_char)i[0];
2126a386550Sderaadt 		e->ether_addr_octet[1] = (u_char)i[1];
2136a386550Sderaadt 		e->ether_addr_octet[2] = (u_char)i[2];
2146a386550Sderaadt 		e->ether_addr_octet[3] = (u_char)i[3];
2156a386550Sderaadt 		e->ether_addr_octet[4] = (u_char)i[4];
2166a386550Sderaadt 		e->ether_addr_octet[5] = (u_char)i[5];
2176a386550Sderaadt 		return 0;
2186a386550Sderaadt 	}
2196a386550Sderaadt 	errno = EINVAL;
2206a386550Sderaadt 	return -1;
2216a386550Sderaadt }
222