1 /*- 2 * SPDX-License-Identifier: BSD-4-Clause 3 * 4 * Copyright (c) 1995 Bill Paul <wpaul@ctr.columbia.edu>. 5 * Copyright (c) 2007 Robert N. M. Watson 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Bill Paul. 19 * 4. Neither the name of the author nor the names of any co-contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * ethernet address conversion and lookup routines 36 * 37 * Written by Bill Paul <wpaul@ctr.columbia.edu> 38 * Center for Telecommunications Research 39 * Columbia University, New York City 40 */ 41 42 #include <sys/param.h> 43 #include <sys/socket.h> 44 45 #include <net/ethernet.h> 46 47 #ifdef YP 48 #include <rpc/rpc.h> 49 #include <rpcsvc/yp_prot.h> 50 #include <rpcsvc/ypclnt.h> 51 #endif 52 53 #include <paths.h> 54 #include <stdio.h> 55 #include <stdlib.h> 56 #include <string.h> 57 58 #ifndef _PATH_ETHERS 59 #define _PATH_ETHERS "/etc/ethers" 60 #endif 61 62 /* 63 * Parse a string of text containing an ethernet address and hostname and 64 * separate it into its component parts. 65 */ 66 int 67 ether_line(const char *l, struct ether_addr *e, char *hostname) 68 { 69 int i, o[6]; 70 71 i = sscanf(l, "%x:%x:%x:%x:%x:%x %s", &o[0], &o[1], &o[2], &o[3], 72 &o[4], &o[5], hostname); 73 if (i == 7) { 74 for (i = 0; i < 6; i++) 75 e->octet[i] = o[i]; 76 return (0); 77 } else { 78 return (-1); 79 } 80 } 81 82 /* 83 * Convert an ASCII representation of an ethernet address to binary form. 84 */ 85 struct ether_addr * 86 ether_aton_r(const char *a, struct ether_addr *e) 87 { 88 int i; 89 unsigned int o0, o1, o2, o3, o4, o5; 90 91 i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5); 92 if (i != 6) 93 return (NULL); 94 e->octet[0]=o0; 95 e->octet[1]=o1; 96 e->octet[2]=o2; 97 e->octet[3]=o3; 98 e->octet[4]=o4; 99 e->octet[5]=o5; 100 return (e); 101 } 102 103 struct ether_addr * 104 ether_aton(const char *a) 105 { 106 static struct ether_addr e; 107 108 return (ether_aton_r(a, &e)); 109 } 110 111 /* 112 * Convert a binary representation of an ethernet address to an ASCII string. 113 */ 114 char * 115 ether_ntoa_r(const struct ether_addr *n, char *a) 116 { 117 int i; 118 119 i = sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x", n->octet[0], 120 n->octet[1], n->octet[2], n->octet[3], n->octet[4], n->octet[5]); 121 if (i < 17) 122 return (NULL); 123 return (a); 124 } 125 126 char * 127 ether_ntoa(const struct ether_addr *n) 128 { 129 static char a[18]; 130 131 return (ether_ntoa_r(n, a)); 132 } 133 134 /* 135 * Map an ethernet address to a hostname. Use either /etc/ethers or NIS/YP. 136 */ 137 int 138 ether_ntohost(char *hostname, const struct ether_addr *e) 139 { 140 FILE *fp; 141 char buf[BUFSIZ + 2]; 142 struct ether_addr local_ether; 143 char local_host[MAXHOSTNAMELEN]; 144 #ifdef YP 145 char *result; 146 int resultlen; 147 char *ether_a; 148 char *yp_domain; 149 #endif 150 151 if ((fp = fopen(_PATH_ETHERS, "re")) == NULL) 152 return (1); 153 while (fgets(buf,BUFSIZ,fp)) { 154 if (buf[0] == '#') 155 continue; 156 #ifdef YP 157 if (buf[0] == '+') { 158 if (yp_get_default_domain(&yp_domain)) 159 continue; 160 ether_a = ether_ntoa(e); 161 if (yp_match(yp_domain, "ethers.byaddr", ether_a, 162 strlen(ether_a), &result, &resultlen)) { 163 continue; 164 } 165 strncpy(buf, result, resultlen); 166 buf[resultlen] = '\0'; 167 free(result); 168 } 169 #endif 170 if (!ether_line(buf, &local_ether, local_host)) { 171 if (!bcmp((char *)&local_ether.octet[0], 172 (char *)&e->octet[0], 6)) { 173 /* We have a match. */ 174 strcpy(hostname, local_host); 175 fclose(fp); 176 return(0); 177 } 178 } 179 } 180 fclose(fp); 181 return (1); 182 } 183 184 /* 185 * Map a hostname to an ethernet address using /etc/ethers or NIS/YP. 186 */ 187 int 188 ether_hostton(const char *hostname, struct ether_addr *e) 189 { 190 FILE *fp; 191 char buf[BUFSIZ + 2]; 192 struct ether_addr local_ether; 193 char local_host[MAXHOSTNAMELEN]; 194 #ifdef YP 195 char *result; 196 int resultlen; 197 char *yp_domain; 198 #endif 199 200 if ((fp = fopen(_PATH_ETHERS, "re")) == NULL) 201 return (1); 202 while (fgets(buf,BUFSIZ,fp)) { 203 if (buf[0] == '#') 204 continue; 205 #ifdef YP 206 if (buf[0] == '+') { 207 if (yp_get_default_domain(&yp_domain)) 208 continue; 209 if (yp_match(yp_domain, "ethers.byname", hostname, 210 strlen(hostname), &result, &resultlen)) { 211 continue; 212 } 213 strncpy(buf, result, resultlen); 214 buf[resultlen] = '\0'; 215 free(result); 216 } 217 #endif 218 if (!ether_line(buf, &local_ether, local_host)) { 219 if (!strcmp(hostname, local_host)) { 220 /* We have a match. */ 221 bcopy((char *)&local_ether.octet[0], 222 (char *)&e->octet[0], 6); 223 fclose(fp); 224 return(0); 225 } 226 } 227 } 228 fclose(fp); 229 return (1); 230 } 231