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