1/* $NetBSD: device.c,v 1.13 2016/06/08 01:11:49 christos Exp $ */ 2 3/* 4 * Copyright (c) 1993-95 Mats O Jansson. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include "port.h" 28#ifndef lint 29__RCSID("$NetBSD: device.c,v 1.13 2016/06/08 01:11:49 christos Exp $"); 30#endif 31 32#include "os.h" 33#include "common.h" 34#include "device.h" 35#include "mopdef.h" 36#include "pf.h" 37#include "log.h" 38 39struct if_info *iflist; /* Interface List */ 40 41void deviceOpen(const char *, u_short, int); 42 43/* 44 * Return ethernet address for interface 45 */ 46 47void 48deviceEthAddr(const char *ifname, u_char *eaddr) 49{ 50#ifndef AF_LINK 51 int fd; 52 struct ifreq ifr; 53 54 /* Use datagram socket to get Ethernet address. */ 55 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 56 mopLogErr("deviceEthAddr: socket"); 57 58 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 59 if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) 60 mopLogErr("deviceEthAddr: SIOGIFHWADDR"); 61 memcpy(eaddr, ifr.ifr_hwaddr.sa_data, 6); 62 close(fd); 63#else 64 struct sockaddr_dl *sdl; 65 struct ifaddrs *ifap, *ifa; 66 67 if (getifaddrs(&ifap) != 0) 68 mopLogErr("deviceEthAddr: getifaddrs"); 69 70 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 71 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 72 if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER || 73 sdl->sdl_alen != 6) 74 continue; 75 if (!strcmp(ifa->ifa_name, ifname)) { 76 memmove((caddr_t)eaddr, (caddr_t)LLADDR(sdl), 6); 77 freeifaddrs(ifap); 78 return; 79 } 80 } 81 82 freeifaddrs(ifap); 83 mopLogErrX("deviceEthAddr: Never saw interface `%s'!", ifname); 84#endif 85} 86 87void 88deviceOpen(const char *ifname, u_short proto, int trans) 89{ 90 struct if_info *p, tmp; 91 92 strlcpy(tmp.if_name, ifname, sizeof(tmp.if_name)); 93 tmp.iopen = pfInit; 94 95 switch (proto) { 96 case MOP_K_PROTO_RC: 97 tmp.read = mopReadRC; 98 tmp.fd = mopOpenRC(&tmp, trans); 99 break; 100 case MOP_K_PROTO_DL: 101 tmp.read = mopReadDL; 102 tmp.fd = mopOpenDL(&tmp, trans); 103 break; 104 default: 105 break; 106 } 107 108 if (tmp.fd != -1) { 109 p = malloc(sizeof(*p)); 110 if (p == 0) 111 mopLogErr("deviceOpen: malloc"); 112 113 p->next = iflist; 114 iflist = p; 115 116 strlcpy(p->if_name, tmp.if_name, sizeof(p->if_name)); 117 p->iopen = tmp.iopen; 118 p->write = pfWrite; 119 p->read = tmp.read; 120 memset((char *)p->eaddr, 0, sizeof(p->eaddr)); 121 p->fd = tmp.fd; 122 123#ifdef DEV_NEW_CONF 124 deviceEthAddr(p->if_name,&p->eaddr[0]); 125#else 126 p->eaddr[0]= tmp.eaddr[0]; 127 p->eaddr[1]= tmp.eaddr[1]; 128 p->eaddr[2]= tmp.eaddr[2]; 129 p->eaddr[3]= tmp.eaddr[3]; 130 p->eaddr[4]= tmp.eaddr[4]; 131 p->eaddr[5]= tmp.eaddr[5]; 132#endif /* DEV_NEW_CONF */ 133 134 } 135} 136 137void 138deviceInitOne(const char *ifname) 139{ 140 char interface[IFNAME_SIZE]; 141 struct if_info *p; 142 int trans; 143#ifdef _AIX 144 char dev[IFNAME_SIZE]; 145 int unit,j; 146 147 unit = 0; 148 for (j = 0; j < strlen(ifname); j++) { 149 if (isalpha(ifname[j])) { 150 dev[j] = ifname[j]; 151 } else { 152 if (isdigit(ifname[j])) { 153 unit = unit*10 + ifname[j] - '0'; 154 dev[j] = '\0'; 155 } 156 } 157 } 158 159 if ((strlen(dev) == 2) && 160 (dev[0] == 'e') && 161 ((dev[1] == 'n') || (dev[1] == 't'))) { 162 snprintf(interface, sizeof(interface), "ent%d\0", unit); 163 } else { 164 snprintf(interface, sizeof(interface), "%s%d\0", dev, unit); 165 } 166#else 167 snprintf(interface, sizeof(interface), "%s", ifname); 168#endif /* _AIX */ 169 170 /* Ok, init it just once */ 171 172 p = iflist; 173 for (p = iflist; p; p = p->next) { 174 if (strcmp(p->if_name,interface) == 0) { 175 return; 176 } 177 } 178 179 if (!mopInteractive) 180 syslog(LOG_INFO, "Initialized %s", interface); 181 182 /* Ok, get transport information */ 183 184 trans = pfTrans(interface); 185 186#ifndef NORC 187 /* Start with MOP Remote Console */ 188 189 switch (trans) { 190 case TRANS_ETHER: 191 deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER); 192 break; 193 case TRANS_8023: 194 deviceOpen(interface,MOP_K_PROTO_RC,TRANS_8023); 195 break; 196 case TRANS_ETHER+TRANS_8023: 197 deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER); 198 deviceOpen(interface,MOP_K_PROTO_RC,TRANS_8023); 199 break; 200 case TRANS_ETHER+TRANS_8023+TRANS_AND: 201 deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER+TRANS_8023); 202 break; 203 } 204#endif 205 206#ifndef NODL 207 /* and next MOP Dump/Load */ 208 209 switch (trans) { 210 case TRANS_ETHER: 211 deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER); 212 break; 213 case TRANS_8023: 214 deviceOpen(interface,MOP_K_PROTO_DL,TRANS_8023); 215 break; 216 case TRANS_ETHER+TRANS_8023: 217 deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER); 218 deviceOpen(interface,MOP_K_PROTO_DL,TRANS_8023); 219 break; 220 case TRANS_ETHER+TRANS_8023+TRANS_AND: 221 deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER+TRANS_8023); 222 break; 223 } 224#endif 225 226} 227 228/* 229 * Initialize all "candidate" interfaces that are in the system 230 * configuration list. A "candidate" is up, not loopback and not 231 * point to point. 232 */ 233void 234deviceInitAll(void) 235{ 236 struct ifaddrs *ifap, *ifa; 237 238 if (getifaddrs(&ifap) != 0) 239 mopLogErr("deviceInitAll: socket"); 240 241 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 242#ifdef AF_LINK 243 struct sockaddr_dl *sdl; 244 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 245 if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER || 246 sdl->sdl_alen != 6) 247 continue; 248#endif 249 if ((ifa->ifa_flags & 250 (IFF_UP | IFF_LOOPBACK | IFF_POINTOPOINT)) != IFF_UP) 251 continue; 252 deviceInitOne(ifa->ifa_name); 253 } 254 255 freeifaddrs(ifap); 256} 257