1 /* $NetBSD: ethers.c,v 1.23 2012/03/20 17:44:18 matt Exp $ */ 2 3 /* 4 * ethers(3N) a la Sun. 5 * 6 * Written by Roland McGrath <roland@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.23 2012/03/20 17:44:18 matt 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 size_t len; 87 struct ether_addr try; 88 #ifdef YP 89 char trybuf[sizeof "xx:xx:xx:xx:xx:xx"]; 90 int trylen; 91 #endif 92 93 _DIAGASSERT(hostname != NULL); 94 _DIAGASSERT(e != NULL); 95 96 #ifdef YP 97 trylen = snprintf(trybuf, sizeof trybuf, "%x:%x:%x:%x:%x:%x", 98 e->ether_addr_octet[0], e->ether_addr_octet[1], 99 e->ether_addr_octet[2], e->ether_addr_octet[3], 100 e->ether_addr_octet[4], e->ether_addr_octet[5]); 101 #endif 102 103 f = fopen(_PATH_ETHERS, "r"); 104 if (f == NULL) 105 return -1; 106 while ((p = fgetln(f, &len)) != NULL) { 107 if (p[len - 1] != '\n') 108 continue; /* skip lines w/o \n */ 109 p[--len] = '\0'; 110 #ifdef YP 111 /* A + in the file means try YP now. */ 112 if (len == 1 && *p == '+') { 113 char *ypbuf, *ypdom; 114 int ypbuflen; 115 116 if (yp_get_default_domain(&ypdom)) 117 continue; 118 if (yp_match(ypdom, "ethers.byaddr", trybuf, 119 trylen, &ypbuf, &ypbuflen)) 120 continue; 121 if (ether_line(ypbuf, &try, hostname) == 0) { 122 free(ypbuf); 123 (void)fclose(f); 124 return 0; 125 } 126 free(ypbuf); 127 continue; 128 } 129 #endif 130 if (ether_line(p, &try, hostname) == 0 && 131 memcmp(&try, e, sizeof try) == 0) { 132 (void)fclose(f); 133 return 0; 134 } 135 } 136 (void)fclose(f); 137 errno = ENOENT; 138 return -1; 139 } 140 141 int 142 ether_hostton(const char *hostname, struct ether_addr *e) 143 { 144 FILE *f; 145 char *p; 146 size_t len; 147 char try[MAXHOSTNAMELEN + 1]; 148 #ifdef YP 149 int hostlen = (int)strlen(hostname); 150 #endif 151 152 _DIAGASSERT(hostname != NULL); 153 _DIAGASSERT(e != NULL); 154 155 f = fopen(_PATH_ETHERS, "r"); 156 if (f==NULL) 157 return -1; 158 159 while ((p = fgetln(f, &len)) != NULL) { 160 if (p[len - 1] != '\n') 161 continue; /* skip lines w/o \n */ 162 p[--len] = '\0'; 163 #ifdef YP 164 /* A + in the file means try YP now. */ 165 if (len == 1 && *p == '+') { 166 char *ypbuf, *ypdom; 167 int ypbuflen; 168 169 if (yp_get_default_domain(&ypdom)) 170 continue; 171 if (yp_match(ypdom, "ethers.byname", hostname, hostlen, 172 &ypbuf, &ypbuflen)) 173 continue; 174 if (ether_line(ypbuf, e, try) == 0) { 175 free(ypbuf); 176 (void)fclose(f); 177 return 0; 178 } 179 free(ypbuf); 180 continue; 181 } 182 #endif 183 if (ether_line(p, e, try) == 0 && strcmp(hostname, try) == 0) { 184 (void)fclose(f); 185 return 0; 186 } 187 } 188 (void)fclose(f); 189 errno = ENOENT; 190 return -1; 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