1/* $NetBSD: device.c,v 1.11 2009/11/17 18:58:07 drochner 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 <sys/cdefs.h> 28#ifndef lint 29__RCSID("$NetBSD: device.c,v 1.11 2009/11/17 18:58:07 drochner 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#ifdef DEV_NEW_CONF 44/* 45 * Return ethernet address for interface 46 */ 47 48void 49deviceEthAddr(const char *ifname, u_char *eaddr) 50{ 51 struct sockaddr_dl *sdl; 52 struct ifaddrs *ifap, *ifa; 53 54 if (getifaddrs(&ifap) != 0) 55 mopLogErr("deviceEthAddr: getifaddrs"); 56 57 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 58 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 59 if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER || 60 sdl->sdl_alen != 6) 61 continue; 62 if (!strcmp(ifa->ifa_name, ifname)) { 63 memmove((caddr_t)eaddr, (caddr_t)LLADDR(sdl), 6); 64 freeifaddrs(ifap); 65 return; 66 } 67 } 68 69 freeifaddrs(ifap); 70 mopLogErrX("deviceEthAddr: Never saw interface `%s'!", ifname); 71} 72#endif /* DEV_NEW_CONF */ 73 74void 75deviceOpen(const char *ifname, u_short proto, int trans) 76{ 77 struct if_info *p, tmp; 78 79 strlcpy(tmp.if_name, ifname, sizeof(tmp.if_name)); 80 tmp.iopen = pfInit; 81 82 switch (proto) { 83 case MOP_K_PROTO_RC: 84 tmp.read = mopReadRC; 85 tmp.fd = mopOpenRC(&tmp, trans); 86 break; 87 case MOP_K_PROTO_DL: 88 tmp.read = mopReadDL; 89 tmp.fd = mopOpenDL(&tmp, trans); 90 break; 91 default: 92 break; 93 } 94 95 if (tmp.fd != -1) { 96 p = (struct if_info *)malloc(sizeof(*p)); 97 if (p == 0) 98 mopLogErr("deviceOpen: malloc"); 99 100 p->next = iflist; 101 iflist = p; 102 103 strlcpy(p->if_name, tmp.if_name, sizeof(p->if_name)); 104 p->iopen = tmp.iopen; 105 p->write = pfWrite; 106 p->read = tmp.read; 107 memset((char *)p->eaddr, 0, sizeof(p->eaddr)); 108 p->fd = tmp.fd; 109 110#ifdef DEV_NEW_CONF 111 deviceEthAddr(p->if_name,&p->eaddr[0]); 112#else 113 p->eaddr[0]= tmp.eaddr[0]; 114 p->eaddr[1]= tmp.eaddr[1]; 115 p->eaddr[2]= tmp.eaddr[2]; 116 p->eaddr[3]= tmp.eaddr[3]; 117 p->eaddr[4]= tmp.eaddr[4]; 118 p->eaddr[5]= tmp.eaddr[5]; 119#endif /* DEV_NEW_CONF */ 120 121 } 122} 123 124void 125deviceInitOne(const char *ifname) 126{ 127 char interface[IFNAME_SIZE]; 128 struct if_info *p; 129 int trans; 130#ifdef _AIX 131 char dev[IFNAME_SIZE]; 132 int unit,j; 133 134 unit = 0; 135 for (j = 0; j < strlen(ifname); j++) { 136 if (isalpha(ifname[j])) { 137 dev[j] = ifname[j]; 138 } else { 139 if (isdigit(ifname[j])) { 140 unit = unit*10 + ifname[j] - '0'; 141 dev[j] = '\0'; 142 } 143 } 144 } 145 146 if ((strlen(dev) == 2) && 147 (dev[0] == 'e') && 148 ((dev[1] == 'n') || (dev[1] == 't'))) { 149 snprintf(interface, sizeof(interface), "ent%d\0", unit); 150 } else { 151 snprintf(interface, sizeof(interface), "%s%d\0", dev, unit); 152 } 153#else 154 snprintf(interface, sizeof(interface), "%s", ifname); 155#endif /* _AIX */ 156 157 /* Ok, init it just once */ 158 159 p = iflist; 160 for (p = iflist; p; p = p->next) { 161 if (strcmp(p->if_name,interface) == 0) { 162 return; 163 } 164 } 165 166 if (!mopInteractive) 167 syslog(LOG_INFO, "Initialized %s", interface); 168 169 /* Ok, get transport information */ 170 171 trans = pfTrans(interface); 172 173#ifndef NORC 174 /* Start with MOP Remote Console */ 175 176 switch (trans) { 177 case TRANS_ETHER: 178 deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER); 179 break; 180 case TRANS_8023: 181 deviceOpen(interface,MOP_K_PROTO_RC,TRANS_8023); 182 break; 183 case TRANS_ETHER+TRANS_8023: 184 deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER); 185 deviceOpen(interface,MOP_K_PROTO_RC,TRANS_8023); 186 break; 187 case TRANS_ETHER+TRANS_8023+TRANS_AND: 188 deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER+TRANS_8023); 189 break; 190 } 191#endif 192 193#ifndef NODL 194 /* and next MOP Dump/Load */ 195 196 switch (trans) { 197 case TRANS_ETHER: 198 deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER); 199 break; 200 case TRANS_8023: 201 deviceOpen(interface,MOP_K_PROTO_DL,TRANS_8023); 202 break; 203 case TRANS_ETHER+TRANS_8023: 204 deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER); 205 deviceOpen(interface,MOP_K_PROTO_DL,TRANS_8023); 206 break; 207 case TRANS_ETHER+TRANS_8023+TRANS_AND: 208 deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER+TRANS_8023); 209 break; 210 } 211#endif 212 213} 214 215/* 216 * Initialize all "candidate" interfaces that are in the system 217 * configuration list. A "candidate" is up, not loopback and not 218 * point to point. 219 */ 220void 221deviceInitAll(void) 222{ 223#ifdef DEV_NEW_CONF 224 struct sockaddr_dl *sdl; 225 struct ifaddrs *ifap, *ifa; 226 227 if (getifaddrs(&ifap) != 0) 228 mopLogErr("deviceInitAll: socket"); 229 230 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 231 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 232 if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER || 233 sdl->sdl_alen != 6) 234 continue; 235 if ((ifa->ifa_flags & 236 (IFF_UP | IFF_LOOPBACK | IFF_POINTOPOINT)) != IFF_UP) 237 continue; 238 deviceInitOne(ifa->ifa_name); 239 } 240 241 freeifaddrs(ifap); 242#else 243 struct ifaddrs *ifap, *ifa; 244 245 if (getifaddrs(&ifap) != 0) 246 mopLogErr("deviceInitAll: old socket"); 247 248 for (ifa = ifap; ifa; ifa = ifa->ifa_next) { 249 if (/*(ifa->ifa_flags & IFF_UP) == 0 ||*/ 250 ifa->ifa_flags & IFF_LOOPBACK || 251 ifa->ifa_flags & IFF_POINTOPOINT) 252 continue; 253 deviceInitOne(ifa->ifa_name); 254 } 255 256 freeifaddrs(ifap); 257#endif /* DEV_NEW_CONF */ 258} 259