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@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