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