1*0a6a1f1dSLionel Sambuc /* $NetBSD: ethers.c,v 1.25 2014/09/18 13:58:20 christos Exp $ */
22fe8fb19SBen Gras
32fe8fb19SBen Gras /*
42fe8fb19SBen Gras * ethers(3N) a la Sun.
52fe8fb19SBen Gras *
62fe8fb19SBen Gras * Written by Roland McGrath <roland@frob.com> 10/14/93.
72fe8fb19SBen Gras * Public domain.
82fe8fb19SBen Gras */
92fe8fb19SBen Gras
102fe8fb19SBen Gras #include <sys/cdefs.h>
112fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
12*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: ethers.c,v 1.25 2014/09/18 13:58:20 christos Exp $");
132fe8fb19SBen Gras #endif /* LIBC_SCCS and not lint */
142fe8fb19SBen Gras
152fe8fb19SBen Gras #include "namespace.h"
162fe8fb19SBen Gras #include <sys/param.h>
172fe8fb19SBen Gras #include <sys/socket.h>
182fe8fb19SBen Gras
192fe8fb19SBen Gras #include <net/if.h>
202fe8fb19SBen Gras #include <net/if_ether.h>
212fe8fb19SBen Gras #include <netinet/in.h>
222fe8fb19SBen Gras
232fe8fb19SBen Gras #include <assert.h>
242fe8fb19SBen Gras #include <errno.h>
252fe8fb19SBen Gras #include <paths.h>
262fe8fb19SBen Gras #include <stdio.h>
272fe8fb19SBen Gras #include <stdlib.h>
282fe8fb19SBen Gras #include <string.h>
292fe8fb19SBen Gras
302fe8fb19SBen Gras #ifdef YP
312fe8fb19SBen Gras #include <rpcsvc/ypclnt.h>
322fe8fb19SBen Gras #endif
332fe8fb19SBen Gras
342fe8fb19SBen Gras #ifdef __weak_alias
__weak_alias(ether_aton,_ether_aton)352fe8fb19SBen Gras __weak_alias(ether_aton,_ether_aton)
362fe8fb19SBen Gras __weak_alias(ether_hostton,_ether_hostton)
372fe8fb19SBen Gras __weak_alias(ether_line,_ether_line)
382fe8fb19SBen Gras __weak_alias(ether_ntoa,_ether_ntoa)
392fe8fb19SBen Gras __weak_alias(ether_ntohost,_ether_ntohost)
402fe8fb19SBen Gras #endif
412fe8fb19SBen Gras
422fe8fb19SBen Gras #ifndef _PATH_ETHERS
432fe8fb19SBen Gras #define _PATH_ETHERS "/etc/ethers"
442fe8fb19SBen Gras #endif
452fe8fb19SBen Gras
462fe8fb19SBen Gras char *
47f14fb602SLionel Sambuc ether_ntoa(const struct ether_addr *e)
482fe8fb19SBen Gras {
492fe8fb19SBen Gras static char a[18];
502fe8fb19SBen Gras
512fe8fb19SBen Gras _DIAGASSERT(e != NULL);
522fe8fb19SBen Gras
532fe8fb19SBen Gras (void) snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x",
542fe8fb19SBen Gras e->ether_addr_octet[0], e->ether_addr_octet[1],
552fe8fb19SBen Gras e->ether_addr_octet[2], e->ether_addr_octet[3],
562fe8fb19SBen Gras e->ether_addr_octet[4], e->ether_addr_octet[5]);
572fe8fb19SBen Gras return a;
582fe8fb19SBen Gras }
592fe8fb19SBen Gras
602fe8fb19SBen Gras struct ether_addr *
ether_aton(const char * s)61f14fb602SLionel Sambuc ether_aton(const char *s)
622fe8fb19SBen Gras {
632fe8fb19SBen Gras static struct ether_addr n;
642fe8fb19SBen Gras u_int i[6];
652fe8fb19SBen Gras
662fe8fb19SBen Gras _DIAGASSERT(s != NULL);
672fe8fb19SBen Gras
682fe8fb19SBen Gras if (sscanf(s, " %x:%x:%x:%x:%x:%x ", &i[0], &i[1],
692fe8fb19SBen Gras &i[2], &i[3], &i[4], &i[5]) == 6) {
702fe8fb19SBen Gras n.ether_addr_octet[0] = (u_char)i[0];
712fe8fb19SBen Gras n.ether_addr_octet[1] = (u_char)i[1];
722fe8fb19SBen Gras n.ether_addr_octet[2] = (u_char)i[2];
732fe8fb19SBen Gras n.ether_addr_octet[3] = (u_char)i[3];
742fe8fb19SBen Gras n.ether_addr_octet[4] = (u_char)i[4];
752fe8fb19SBen Gras n.ether_addr_octet[5] = (u_char)i[5];
762fe8fb19SBen Gras return &n;
772fe8fb19SBen Gras }
782fe8fb19SBen Gras return NULL;
792fe8fb19SBen Gras }
802fe8fb19SBen Gras
812fe8fb19SBen Gras int
ether_ntohost(char * hostname,const struct ether_addr * e)82f14fb602SLionel Sambuc ether_ntohost(char *hostname, const struct ether_addr *e)
832fe8fb19SBen Gras {
842fe8fb19SBen Gras FILE *f;
852fe8fb19SBen Gras char *p;
862fe8fb19SBen Gras struct ether_addr try;
872fe8fb19SBen Gras
882fe8fb19SBen Gras _DIAGASSERT(hostname != NULL);
892fe8fb19SBen Gras _DIAGASSERT(e != NULL);
902fe8fb19SBen Gras
912fe8fb19SBen Gras #ifdef YP
92*0a6a1f1dSLionel Sambuc char trybuf[sizeof "xx:xx:xx:xx:xx:xx"];
93*0a6a1f1dSLionel Sambuc int trylen;
942fe8fb19SBen Gras trylen = snprintf(trybuf, sizeof trybuf, "%x:%x:%x:%x:%x:%x",
952fe8fb19SBen Gras e->ether_addr_octet[0], e->ether_addr_octet[1],
962fe8fb19SBen Gras e->ether_addr_octet[2], e->ether_addr_octet[3],
972fe8fb19SBen Gras e->ether_addr_octet[4], e->ether_addr_octet[5]);
982fe8fb19SBen Gras #endif
992fe8fb19SBen Gras
100*0a6a1f1dSLionel Sambuc f = fopen(_PATH_ETHERS, "re");
1012fe8fb19SBen Gras if (f == NULL)
1022fe8fb19SBen Gras return -1;
103*0a6a1f1dSLionel Sambuc for (p = NULL;;) {
104*0a6a1f1dSLionel Sambuc free(p);
105*0a6a1f1dSLionel Sambuc p = fparseln(f, NULL, NULL, NULL, FPARSELN_UNESCALL);
106*0a6a1f1dSLionel Sambuc if (p == NULL)
107*0a6a1f1dSLionel Sambuc break;
1082fe8fb19SBen Gras #ifdef YP
1092fe8fb19SBen Gras /* A + in the file means try YP now. */
110*0a6a1f1dSLionel Sambuc if (strcmp(p, "+") == 0) {
1112fe8fb19SBen Gras char *ypbuf, *ypdom;
1122fe8fb19SBen Gras int ypbuflen;
1132fe8fb19SBen Gras
1142fe8fb19SBen Gras if (yp_get_default_domain(&ypdom))
1152fe8fb19SBen Gras continue;
1162fe8fb19SBen Gras if (yp_match(ypdom, "ethers.byaddr", trybuf,
1172fe8fb19SBen Gras trylen, &ypbuf, &ypbuflen))
1182fe8fb19SBen Gras continue;
119*0a6a1f1dSLionel Sambuc ypbuflen = ether_line(ypbuf, &try, hostname);
1202fe8fb19SBen Gras free(ypbuf);
121*0a6a1f1dSLionel Sambuc if (ypbuflen == 0)
122*0a6a1f1dSLionel Sambuc goto done;
1232fe8fb19SBen Gras continue;
1242fe8fb19SBen Gras }
1252fe8fb19SBen Gras #endif
1262fe8fb19SBen Gras if (ether_line(p, &try, hostname) == 0 &&
127*0a6a1f1dSLionel Sambuc memcmp(&try, e, sizeof try) == 0)
128*0a6a1f1dSLionel Sambuc goto done;
1292fe8fb19SBen Gras }
130*0a6a1f1dSLionel Sambuc free(p);
1312fe8fb19SBen Gras (void)fclose(f);
1322fe8fb19SBen Gras errno = ENOENT;
1332fe8fb19SBen Gras return -1;
134*0a6a1f1dSLionel Sambuc done:
135*0a6a1f1dSLionel Sambuc free(p);
136*0a6a1f1dSLionel Sambuc (void)fclose(f);
137*0a6a1f1dSLionel Sambuc return 0;
1382fe8fb19SBen Gras }
1392fe8fb19SBen Gras
1402fe8fb19SBen Gras int
ether_hostton(const char * hostname,struct ether_addr * e)141f14fb602SLionel Sambuc ether_hostton(const char *hostname, struct ether_addr *e)
1422fe8fb19SBen Gras {
1432fe8fb19SBen Gras FILE *f;
1442fe8fb19SBen Gras char *p;
1452fe8fb19SBen Gras char try[MAXHOSTNAMELEN + 1];
1462fe8fb19SBen Gras #ifdef YP
147f14fb602SLionel Sambuc int hostlen = (int)strlen(hostname);
1482fe8fb19SBen Gras #endif
1492fe8fb19SBen Gras
1502fe8fb19SBen Gras _DIAGASSERT(hostname != NULL);
1512fe8fb19SBen Gras _DIAGASSERT(e != NULL);
1522fe8fb19SBen Gras
153*0a6a1f1dSLionel Sambuc f = fopen(_PATH_ETHERS, "re");
1542fe8fb19SBen Gras if (f == NULL)
1552fe8fb19SBen Gras return -1;
1562fe8fb19SBen Gras
157*0a6a1f1dSLionel Sambuc for (p = NULL;;) {
158*0a6a1f1dSLionel Sambuc free(p);
159*0a6a1f1dSLionel Sambuc p = fparseln(f, NULL, NULL, NULL, FPARSELN_UNESCALL);
160*0a6a1f1dSLionel Sambuc if (p == NULL)
161*0a6a1f1dSLionel Sambuc break;
1622fe8fb19SBen Gras #ifdef YP
1632fe8fb19SBen Gras /* A + in the file means try YP now. */
164*0a6a1f1dSLionel Sambuc if (strcmp(p, "+") == 0) {
1652fe8fb19SBen Gras char *ypbuf, *ypdom;
1662fe8fb19SBen Gras int ypbuflen;
1672fe8fb19SBen Gras
1682fe8fb19SBen Gras if (yp_get_default_domain(&ypdom))
1692fe8fb19SBen Gras continue;
1702fe8fb19SBen Gras if (yp_match(ypdom, "ethers.byname", hostname, hostlen,
1712fe8fb19SBen Gras &ypbuf, &ypbuflen))
1722fe8fb19SBen Gras continue;
173*0a6a1f1dSLionel Sambuc ypbuflen = ether_line(ypbuf, e, try);
1742fe8fb19SBen Gras free(ypbuf);
175*0a6a1f1dSLionel Sambuc if (ypbuflen == 0)
176*0a6a1f1dSLionel Sambuc goto done;
1772fe8fb19SBen Gras continue;
1782fe8fb19SBen Gras }
1792fe8fb19SBen Gras #endif
180*0a6a1f1dSLionel Sambuc if (ether_line(p, e, try) == 0 && strcmp(hostname, try) == 0)
181*0a6a1f1dSLionel Sambuc goto done;
1822fe8fb19SBen Gras }
183*0a6a1f1dSLionel Sambuc free(p);
1842fe8fb19SBen Gras (void)fclose(f);
1852fe8fb19SBen Gras errno = ENOENT;
1862fe8fb19SBen Gras return -1;
187*0a6a1f1dSLionel Sambuc done:
188*0a6a1f1dSLionel Sambuc free(p);
189*0a6a1f1dSLionel Sambuc (void)fclose(f);
190*0a6a1f1dSLionel Sambuc return 0;
1912fe8fb19SBen Gras }
1922fe8fb19SBen Gras
1932fe8fb19SBen Gras int
ether_line(const char * l,struct ether_addr * e,char * hostname)194f14fb602SLionel Sambuc ether_line(const char *l, struct ether_addr *e, char *hostname)
1952fe8fb19SBen Gras {
1962fe8fb19SBen Gras u_int i[6];
1972fe8fb19SBen Gras
1982fe8fb19SBen Gras #define S2(arg) #arg
1992fe8fb19SBen Gras #define S1(arg) S2(arg)
2002fe8fb19SBen Gras static const char fmt[] = " %x:%x:%x:%x:%x:%x"
2012fe8fb19SBen Gras " %" S1(MAXHOSTNAMELEN) "s\n";
2022fe8fb19SBen Gras #undef S2
2032fe8fb19SBen Gras #undef S1
2042fe8fb19SBen Gras
2052fe8fb19SBen Gras _DIAGASSERT(l != NULL);
2062fe8fb19SBen Gras _DIAGASSERT(e != NULL);
2072fe8fb19SBen Gras _DIAGASSERT(hostname != NULL);
2082fe8fb19SBen Gras
2092fe8fb19SBen Gras if (sscanf(l, fmt,
2102fe8fb19SBen Gras &i[0], &i[1], &i[2], &i[3], &i[4], &i[5], hostname) == 7) {
2112fe8fb19SBen Gras e->ether_addr_octet[0] = (u_char)i[0];
2122fe8fb19SBen Gras e->ether_addr_octet[1] = (u_char)i[1];
2132fe8fb19SBen Gras e->ether_addr_octet[2] = (u_char)i[2];
2142fe8fb19SBen Gras e->ether_addr_octet[3] = (u_char)i[3];
2152fe8fb19SBen Gras e->ether_addr_octet[4] = (u_char)i[4];
2162fe8fb19SBen Gras e->ether_addr_octet[5] = (u_char)i[5];
2172fe8fb19SBen Gras return 0;
2182fe8fb19SBen Gras }
2192fe8fb19SBen Gras errno = EINVAL;
2202fe8fb19SBen Gras return -1;
2212fe8fb19SBen Gras }
222