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