1/* $NetBSD: ethers.c,v 1.24 2014/06/19 15:09:07 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.24 2014/06/19 15:09:07 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 46char * 47ether_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 60struct ether_addr * 61ether_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 81int 82ether_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; 134done: 135 free(p); 136 (void)fclose(f); 137 return 0; 138} 139 140int 141ether_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; 187done: 188 free(p); 189 (void)fclose(f); 190 return 0; 191} 192 193int 194ether_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