1 /* $NetBSD: device.c,v 1.6 2003/04/20 00:17:22 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 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Mats O Jansson. 17 * 4. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 __RCSID("$NetBSD: device.c,v 1.6 2003/04/20 00:17:22 christos Exp $"); 35 #endif 36 37 #include "os.h" 38 #include "common.h" 39 #include "device.h" 40 #include "mopdef.h" 41 #include "pf.h" 42 #include "log.h" 43 44 struct if_info *iflist; /* Interface List */ 45 46 void deviceOpen __P((char *, u_short, int)); 47 48 #ifdef DEV_NEW_CONF 49 /* 50 * Return ethernet adress for interface 51 */ 52 53 void 54 deviceEthAddr(ifname, eaddr) 55 char *ifname; 56 u_char *eaddr; 57 { 58 char inbuf[8192]; 59 struct ifconf ifc; 60 struct ifreq *ifr; 61 struct sockaddr_dl *sdl; 62 int fd; 63 int i, len; 64 65 /* We cannot use SIOCGIFADDR on the BPF descriptor. 66 We must instead get all the interfaces with SIOCGIFCONF 67 and find the right one. */ 68 69 /* Use datagram socket to get Ethernet address. */ 70 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 71 mopLogErr("deviceEthAddr: socket"); 72 73 ifc.ifc_len = sizeof(inbuf); 74 ifc.ifc_buf = inbuf; 75 if (ioctl(fd, SIOCGIFCONF, (caddr_t)&ifc) < 0 || 76 ifc.ifc_len < sizeof(struct ifreq)) 77 mopLogErr("deviceEthAddr: SIOGIFCONF"); 78 ifr = ifc.ifc_req; 79 for (i = 0; i < ifc.ifc_len; 80 i += len, ifr = (struct ifreq *)((caddr_t)ifr + len)) { 81 len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len; 82 sdl = (struct sockaddr_dl *)&ifr->ifr_addr; 83 if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER || 84 sdl->sdl_alen != 6) 85 continue; 86 if (!strncmp(ifr->ifr_name, ifname, sizeof(ifr->ifr_name))) { 87 memmove((caddr_t)eaddr, (caddr_t)LLADDR(sdl), 6); 88 return; 89 } 90 } 91 92 mopLogErrX("deviceEthAddr: Never saw interface `%s'!", ifname); 93 } 94 #endif /* DEV_NEW_CONF */ 95 96 void 97 deviceOpen(ifname, proto, trans) 98 char *ifname; 99 u_short proto; 100 int trans; 101 { 102 struct if_info *p, tmp; 103 104 strlcpy(tmp.if_name, ifname, sizeof(tmp.if_name)); 105 tmp.iopen = pfInit; 106 107 switch (proto) { 108 case MOP_K_PROTO_RC: 109 tmp.read = mopReadRC; 110 tmp.fd = mopOpenRC(&tmp, trans); 111 break; 112 case MOP_K_PROTO_DL: 113 tmp.read = mopReadDL; 114 tmp.fd = mopOpenDL(&tmp, trans); 115 break; 116 default: 117 break; 118 } 119 120 if (tmp.fd != -1) { 121 122 p = (struct if_info *)malloc(sizeof(*p)); 123 if (p == 0) 124 mopLogErr("deviceOpen: malloc"); 125 126 p->next = iflist; 127 iflist = p; 128 129 strcpy(p->if_name,tmp.if_name); 130 p->iopen = tmp.iopen; 131 p->write = pfWrite; 132 p->read = tmp.read; 133 memset((char *)p->eaddr, 0, sizeof(p->eaddr)); 134 p->fd = tmp.fd; 135 136 #ifdef DEV_NEW_CONF 137 deviceEthAddr(p->if_name,&p->eaddr[0]); 138 #else 139 p->eaddr[0]= tmp.eaddr[0]; 140 p->eaddr[1]= tmp.eaddr[1]; 141 p->eaddr[2]= tmp.eaddr[2]; 142 p->eaddr[3]= tmp.eaddr[3]; 143 p->eaddr[4]= tmp.eaddr[4]; 144 p->eaddr[5]= tmp.eaddr[5]; 145 #endif /* DEV_NEW_CONF */ 146 147 } 148 } 149 150 void 151 deviceInitOne(ifname) 152 char *ifname; 153 { 154 char interface[IFNAME_SIZE]; 155 struct if_info *p; 156 int trans; 157 #ifdef _AIX 158 char dev[IFNAME_SIZE]; 159 int unit,j; 160 161 unit = 0; 162 for (j = 0; j < strlen(ifname); j++) { 163 if (isalpha(ifname[j])) { 164 dev[j] = ifname[j]; 165 } else { 166 if (isdigit(ifname[j])) { 167 unit = unit*10 + ifname[j] - '0'; 168 dev[j] = '\0'; 169 } 170 } 171 } 172 173 if ((strlen(dev) == 2) && 174 (dev[0] == 'e') && 175 ((dev[1] == 'n') || (dev[1] == 't'))) { 176 snprintf(interface, sizeof(interface), "ent%d\0", unit); 177 } else { 178 snprintf(interface, sizeof(interface), "%s%d\0", dev, unit); 179 } 180 #else 181 snprintf(interface, sizeof(interface), "%s", ifname); 182 #endif /* _AIX */ 183 184 /* Ok, init it just once */ 185 186 p = iflist; 187 for (p = iflist; p; p = p->next) { 188 if (strcmp(p->if_name,interface) == 0) { 189 return; 190 } 191 } 192 193 if (!mopInteractive) 194 syslog(LOG_INFO, "Initialized %s", interface); 195 196 /* Ok, get transport information */ 197 198 trans = pfTrans(interface); 199 200 #ifndef NORC 201 /* Start with MOP Remote Console */ 202 203 switch (trans) { 204 case TRANS_ETHER: 205 deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER); 206 break; 207 case TRANS_8023: 208 deviceOpen(interface,MOP_K_PROTO_RC,TRANS_8023); 209 break; 210 case TRANS_ETHER+TRANS_8023: 211 deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER); 212 deviceOpen(interface,MOP_K_PROTO_RC,TRANS_8023); 213 break; 214 case TRANS_ETHER+TRANS_8023+TRANS_AND: 215 deviceOpen(interface,MOP_K_PROTO_RC,TRANS_ETHER+TRANS_8023); 216 break; 217 } 218 #endif 219 220 #ifndef NODL 221 /* and next MOP Dump/Load */ 222 223 switch (trans) { 224 case TRANS_ETHER: 225 deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER); 226 break; 227 case TRANS_8023: 228 deviceOpen(interface,MOP_K_PROTO_DL,TRANS_8023); 229 break; 230 case TRANS_ETHER+TRANS_8023: 231 deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER); 232 deviceOpen(interface,MOP_K_PROTO_DL,TRANS_8023); 233 break; 234 case TRANS_ETHER+TRANS_8023+TRANS_AND: 235 deviceOpen(interface,MOP_K_PROTO_DL,TRANS_ETHER+TRANS_8023); 236 break; 237 } 238 #endif 239 240 } 241 242 /* 243 * Initialize all "candidate" interfaces that are in the system 244 * configuration list. A "candidate" is up, not loopback and not 245 * point to point. 246 */ 247 void 248 deviceInitAll() 249 { 250 #ifdef DEV_NEW_CONF 251 char inbuf[8192]; 252 struct ifconf ifc; 253 struct ifreq *ifr; 254 struct sockaddr_dl *sdl; 255 int fd; 256 int i, len; 257 258 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 259 mopLogErr("deviceInitAll: socket"); 260 261 ifc.ifc_len = sizeof(inbuf); 262 ifc.ifc_buf = inbuf; 263 if (ioctl(fd, SIOCGIFCONF, (caddr_t)&ifc) < 0 || 264 ifc.ifc_len < sizeof(struct ifreq)) 265 mopLogErr("deviceInitAll: SIOCGIFCONF"); 266 ifr = ifc.ifc_req; 267 for (i = 0; i < ifc.ifc_len; 268 i += len, ifr = (struct ifreq *)((caddr_t)ifr + len)) { 269 len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len; 270 sdl = (struct sockaddr_dl *)&ifr->ifr_addr; 271 if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER || 272 sdl->sdl_alen != 6) 273 continue; 274 if (ioctl(fd, SIOCGIFFLAGS, (caddr_t)ifr) < 0) { 275 mopLogWarn("deviceInitAll: SIOCGIFFLAGS"); 276 continue; 277 } 278 if ((ifr->ifr_flags & 279 (IFF_UP | IFF_LOOPBACK | IFF_POINTOPOINT)) != IFF_UP) 280 continue; 281 deviceInitOne(ifr->ifr_name); 282 } 283 (void) close(fd); 284 #else 285 int fd; 286 int n; 287 struct ifreq ibuf[8], *ifrp; 288 struct ifconf ifc; 289 290 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 291 mopLogErr("deviceInitAll: old socket"); 292 ifc.ifc_len = sizeof ibuf; 293 ifc.ifc_buf = (caddr_t)ibuf; 294 if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 || 295 ifc.ifc_len < sizeof(struct ifreq)) 296 mopLogErr("deviceInitAll: old SIOCGIFCONF"); 297 ifrp = ibuf; 298 n = ifc.ifc_len / sizeof(*ifrp); 299 for (; --n >= 0; ++ifrp) { 300 if (ioctl(fd, SIOCGIFFLAGS, (char *)ifrp) < 0) { 301 continue; 302 } 303 if (/*(ifrp->ifr_flags & IFF_UP) == 0 ||*/ 304 ifrp->ifr_flags & IFF_LOOPBACK || 305 ifrp->ifr_flags & IFF_POINTOPOINT) 306 continue; 307 deviceInitOne(ifrp->ifr_name); 308 } 309 310 (void) close(fd); 311 #endif /* DEV_NEW_CONF */ 312 } 313