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