Home | History | Annotate | Line # | Download | only in net
ethers.c revision 1.25
      1 /*	$NetBSD: ethers.c,v 1.25 2014/09/18 13:58:20 christos Exp $	*/
      2 
      3 /*
      4  * ethers(3N) a la Sun.
      5  *
      6  * Written by Roland McGrath <roland (at) frob.com> 10/14/93.
      7  * Public domain.
      8  */
      9 
     10 #include <sys/cdefs.h>
     11 #if defined(LIBC_SCCS) && !defined(lint)
     12 __RCSID("$NetBSD: ethers.c,v 1.25 2014/09/18 13:58:20 christos Exp $");
     13 #endif /* LIBC_SCCS and not lint */
     14 
     15 #include "namespace.h"
     16 #include <sys/param.h>
     17 #include <sys/socket.h>
     18 
     19 #include <net/if.h>
     20 #include <net/if_ether.h>
     21 #include <netinet/in.h>
     22 
     23 #include <assert.h>
     24 #include <errno.h>
     25 #include <paths.h>
     26 #include <stdio.h>
     27 #include <stdlib.h>
     28 #include <string.h>
     29 
     30 #ifdef YP
     31 #include <rpcsvc/ypclnt.h>
     32 #endif
     33 
     34 #ifdef __weak_alias
     35 __weak_alias(ether_aton,_ether_aton)
     36 __weak_alias(ether_hostton,_ether_hostton)
     37 __weak_alias(ether_line,_ether_line)
     38 __weak_alias(ether_ntoa,_ether_ntoa)
     39 __weak_alias(ether_ntohost,_ether_ntohost)
     40 #endif
     41 
     42 #ifndef _PATH_ETHERS
     43 #define _PATH_ETHERS "/etc/ethers"
     44 #endif
     45 
     46 char *
     47 ether_ntoa(const struct ether_addr *e)
     48 {
     49 	static char a[18];
     50 
     51 	_DIAGASSERT(e != NULL);
     52 
     53 	(void) snprintf(a, sizeof a, "%02x:%02x:%02x:%02x:%02x:%02x",
     54 	    e->ether_addr_octet[0], e->ether_addr_octet[1],
     55 	    e->ether_addr_octet[2], e->ether_addr_octet[3],
     56 	    e->ether_addr_octet[4], e->ether_addr_octet[5]);
     57 	return a;
     58 }
     59 
     60 struct ether_addr *
     61 ether_aton(const char *s)
     62 {
     63 	static struct ether_addr n;
     64 	u_int i[6];
     65 
     66 	_DIAGASSERT(s != NULL);
     67 
     68 	if (sscanf(s, " %x:%x:%x:%x:%x:%x ", &i[0], &i[1],
     69 	    &i[2], &i[3], &i[4], &i[5]) == 6) {
     70 		n.ether_addr_octet[0] = (u_char)i[0];
     71 		n.ether_addr_octet[1] = (u_char)i[1];
     72 		n.ether_addr_octet[2] = (u_char)i[2];
     73 		n.ether_addr_octet[3] = (u_char)i[3];
     74 		n.ether_addr_octet[4] = (u_char)i[4];
     75 		n.ether_addr_octet[5] = (u_char)i[5];
     76 		return &n;
     77 	}
     78 	return NULL;
     79 }
     80 
     81 int
     82 ether_ntohost(char *hostname, const struct ether_addr *e)
     83 {
     84 	FILE *f;
     85 	char *p;
     86 	struct ether_addr try;
     87 
     88 	_DIAGASSERT(hostname != NULL);
     89 	_DIAGASSERT(e != NULL);
     90 
     91 #ifdef YP
     92 	char trybuf[sizeof "xx:xx:xx:xx:xx:xx"];
     93 	int trylen;
     94 	trylen = snprintf(trybuf, sizeof trybuf, "%x:%x:%x:%x:%x:%x",
     95 	    e->ether_addr_octet[0], e->ether_addr_octet[1],
     96 	    e->ether_addr_octet[2], e->ether_addr_octet[3],
     97 	    e->ether_addr_octet[4], e->ether_addr_octet[5]);
     98 #endif
     99 
    100 	f = fopen(_PATH_ETHERS, "re");
    101 	if (f == NULL)
    102 		return -1;
    103 	for (p = NULL;;) {
    104 		free(p);
    105 		p = fparseln(f, NULL, NULL, NULL, FPARSELN_UNESCALL);
    106 		if (p == NULL)
    107 			break;
    108 #ifdef YP
    109 		/* A + in the file means try YP now.  */
    110 		if (strcmp(p, "+") == 0) {
    111 			char *ypbuf, *ypdom;
    112 			int ypbuflen;
    113 
    114 			if (yp_get_default_domain(&ypdom))
    115 				continue;
    116 			if (yp_match(ypdom, "ethers.byaddr", trybuf,
    117 			    trylen, &ypbuf, &ypbuflen))
    118 				continue;
    119 			ypbuflen = ether_line(ypbuf, &try, hostname);
    120 			free(ypbuf);
    121 			if (ypbuflen == 0)
    122 				goto done;
    123 			continue;
    124 		}
    125 #endif
    126 		if (ether_line(p, &try, hostname) == 0 &&
    127 		    memcmp(&try, e, sizeof try) == 0)
    128 			goto done;
    129 	}
    130 	free(p);
    131 	(void)fclose(f);
    132 	errno = ENOENT;
    133 	return -1;
    134 done:
    135 	free(p);
    136 	(void)fclose(f);
    137 	return 0;
    138 }
    139 
    140 int
    141 ether_hostton(const char *hostname, struct ether_addr *e)
    142 {
    143 	FILE *f;
    144 	char *p;
    145 	char try[MAXHOSTNAMELEN + 1];
    146 #ifdef YP
    147 	int hostlen = (int)strlen(hostname);
    148 #endif
    149 
    150 	_DIAGASSERT(hostname != NULL);
    151 	_DIAGASSERT(e != NULL);
    152 
    153 	f = fopen(_PATH_ETHERS, "re");
    154 	if (f == NULL)
    155 		return -1;
    156 
    157 	for (p = NULL;;) {
    158 		free(p);
    159 		p = fparseln(f, NULL, NULL, NULL, FPARSELN_UNESCALL);
    160 		if (p == NULL)
    161 			break;
    162 #ifdef YP
    163 		/* A + in the file means try YP now.  */
    164 		if (strcmp(p, "+") == 0) {
    165 			char *ypbuf, *ypdom;
    166 			int ypbuflen;
    167 
    168 			if (yp_get_default_domain(&ypdom))
    169 				continue;
    170 			if (yp_match(ypdom, "ethers.byname", hostname, hostlen,
    171 			    &ypbuf, &ypbuflen))
    172 				continue;
    173 			ypbuflen = ether_line(ypbuf, e, try);
    174 			free(ypbuf);
    175 			if (ypbuflen == 0)
    176 				goto done;
    177 			continue;
    178 		}
    179 #endif
    180 		if (ether_line(p, e, try) == 0 && strcmp(hostname, try) == 0)
    181 			goto done;
    182 	}
    183 	free(p);
    184 	(void)fclose(f);
    185 	errno = ENOENT;
    186 	return -1;
    187 done:
    188 	free(p);
    189 	(void)fclose(f);
    190 	return 0;
    191 }
    192 
    193 int
    194 ether_line(const char *l, struct ether_addr *e, char *hostname)
    195 {
    196 	u_int i[6];
    197 
    198 #define S2(arg) #arg
    199 #define S1(arg) S2(arg)
    200 	static const char fmt[] = " %x:%x:%x:%x:%x:%x"
    201 	    " %" S1(MAXHOSTNAMELEN) "s\n";
    202 #undef S2
    203 #undef S1
    204 
    205 	_DIAGASSERT(l != NULL);
    206 	_DIAGASSERT(e != NULL);
    207 	_DIAGASSERT(hostname != NULL);
    208 
    209 	if (sscanf(l, fmt,
    210 	    &i[0], &i[1], &i[2], &i[3], &i[4], &i[5], hostname) == 7) {
    211 		e->ether_addr_octet[0] = (u_char)i[0];
    212 		e->ether_addr_octet[1] = (u_char)i[1];
    213 		e->ether_addr_octet[2] = (u_char)i[2];
    214 		e->ether_addr_octet[3] = (u_char)i[3];
    215 		e->ether_addr_octet[4] = (u_char)i[4];
    216 		e->ether_addr_octet[5] = (u_char)i[5];
    217 		return 0;
    218 	}
    219 	errno = EINVAL;
    220 	return -1;
    221 }
    222