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