1 /* 2 * Copyright (c) 1980, 1986 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)if.c 7.8 (Berkeley) 05/05/89 18 */ 19 20 #include "param.h" 21 #include "mbuf.h" 22 #include "systm.h" 23 #include "socket.h" 24 #include "socketvar.h" 25 #include "protosw.h" 26 #include "user.h" 27 #include "kernel.h" 28 #include "ioctl.h" 29 #include "errno.h" 30 31 #include "if.h" 32 #include "af.h" 33 34 #include "ether.h" 35 36 int ifqmaxlen = IFQ_MAXLEN; 37 38 /* 39 * Network interface utility routines. 40 * 41 * Routines with ifa_ifwith* names take sockaddr *'s as 42 * parameters. 43 */ 44 45 ifinit() 46 { 47 register struct ifnet *ifp; 48 49 for (ifp = ifnet; ifp; ifp = ifp->if_next) 50 if (ifp->if_snd.ifq_maxlen == 0) 51 ifp->if_snd.ifq_maxlen = ifqmaxlen; 52 if_slowtimo(); 53 } 54 55 #ifdef vax 56 /* 57 * Call each interface on a Unibus reset. 58 */ 59 ifubareset(uban) 60 int uban; 61 { 62 register struct ifnet *ifp; 63 64 for (ifp = ifnet; ifp; ifp = ifp->if_next) 65 if (ifp->if_reset) 66 (*ifp->if_reset)(ifp->if_unit, uban); 67 } 68 #endif 69 70 /* 71 * Attach an interface to the 72 * list of "active" interfaces. 73 */ 74 if_attach(ifp) 75 struct ifnet *ifp; 76 { 77 register struct ifnet **p = &ifnet; 78 79 while (*p) 80 p = &((*p)->if_next); 81 *p = ifp; 82 } 83 84 /* 85 * Locate an interface based on a complete address. 86 */ 87 /*ARGSUSED*/ 88 struct ifaddr * 89 ifa_ifwithaddr(addr) 90 register struct sockaddr *addr; 91 { 92 register struct ifnet *ifp; 93 register struct ifaddr *ifa; 94 95 #define equal(a1, a2) \ 96 (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) 97 for (ifp = ifnet; ifp; ifp = ifp->if_next) 98 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 99 if (ifa->ifa_addr->sa_family != addr->sa_family) 100 continue; 101 if (equal(addr, ifa->ifa_addr)) 102 return (ifa); 103 if ((ifp->if_flags & IFF_BROADCAST) && 104 equal(&ifa->ifa_broadaddr, addr)) 105 return (ifa); 106 } 107 return ((struct ifaddr *)0); 108 } 109 /* 110 * Locate the point to point interface with a given destination address. 111 */ 112 /*ARGSUSED*/ 113 struct ifaddr * 114 ifa_ifwithdstaddr(addr) 115 register struct sockaddr *addr; 116 { 117 register struct ifnet *ifp; 118 register struct ifaddr *ifa; 119 120 for (ifp = ifnet; ifp; ifp = ifp->if_next) 121 if (ifp->if_flags & IFF_POINTOPOINT) 122 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 123 if (ifa->ifa_addr->sa_family != addr->sa_family) 124 continue; 125 if (equal(addr, ifa->ifa_dstaddr)) 126 return (ifa); 127 } 128 return ((struct ifaddr *)0); 129 } 130 131 /* 132 * Find an interface on a specific network. If many, choice 133 * is first found. 134 */ 135 struct ifaddr * 136 ifa_ifwithnet(addr) 137 struct sockaddr *addr; 138 { 139 register struct ifnet *ifp; 140 register struct ifaddr *ifa; 141 register char *cp, *cp2, *cp3; 142 register char *cplim; 143 u_int af = addr->sa_family; 144 145 if (af >= AF_MAX) 146 return (0); 147 for (ifp = ifnet; ifp; ifp = ifp->if_next) 148 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 149 if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0) 150 continue; 151 cp = addr->sa_data; 152 cp2 = ifa->ifa_addr->sa_data; 153 cp3 = ifa->ifa_netmask->sa_data; 154 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 155 for (; cp3 < cplim; cp3++) 156 if ((*cp++ ^ *cp2++) & *cp3) 157 break; 158 if (cp3 == cplim) 159 return (ifa); 160 } 161 return ((struct ifaddr *)0); 162 } 163 164 #ifdef notdef 165 /* 166 * Find an interface using a specific address family 167 */ 168 struct ifaddr * 169 ifa_ifwithaf(af) 170 register int af; 171 { 172 register struct ifnet *ifp; 173 register struct ifaddr *ifa; 174 175 for (ifp = ifnet; ifp; ifp = ifp->if_next) 176 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 177 if (ifa->ifa_addr->sa_family == af) 178 return (ifa); 179 return ((struct ifaddr *)0); 180 } 181 #endif 182 183 /* 184 * Mark an interface down and notify protocols of 185 * the transition. 186 * NOTE: must be called at splnet or eqivalent. 187 */ 188 if_down(ifp) 189 register struct ifnet *ifp; 190 { 191 register struct ifaddr *ifa; 192 193 ifp->if_flags &= ~IFF_UP; 194 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 195 pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 196 if_qflush(&ifp->if_snd); 197 } 198 199 /* 200 * Flush an interface queue. 201 */ 202 if_qflush(ifq) 203 register struct ifqueue *ifq; 204 { 205 register struct mbuf *m, *n; 206 207 n = ifq->ifq_head; 208 while (m = n) { 209 n = m->m_act; 210 m_freem(m); 211 } 212 ifq->ifq_head = 0; 213 ifq->ifq_tail = 0; 214 ifq->ifq_len = 0; 215 } 216 217 /* 218 * Handle interface watchdog timer routines. Called 219 * from softclock, we decrement timers (if set) and 220 * call the appropriate interface routine on expiration. 221 */ 222 if_slowtimo() 223 { 224 register struct ifnet *ifp; 225 int s = splimp(); 226 227 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 228 if (ifp->if_timer == 0 || --ifp->if_timer) 229 continue; 230 if (ifp->if_watchdog) 231 (*ifp->if_watchdog)(ifp->if_unit); 232 } 233 splx(s); 234 timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 235 } 236 237 /* 238 * Map interface name to 239 * interface structure pointer. 240 */ 241 struct ifnet * 242 ifunit(name) 243 register char *name; 244 { 245 register char *cp; 246 register struct ifnet *ifp; 247 int unit; 248 unsigned len; 249 char *ep, c; 250 251 for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 252 if (*cp >= '0' && *cp <= '9') 253 break; 254 if (*cp == '\0' || cp == name + IFNAMSIZ) 255 return ((struct ifnet *)0); 256 /* 257 * Save first char of unit, and pointer to it, 258 * so we can put a null there to avoid matching 259 * initial substrings of interface names. 260 */ 261 len = cp - name + 1; 262 c = *cp; 263 ep = cp; 264 for (unit = 0; *cp >= '0' && *cp <= '9'; ) 265 unit = unit * 10 + *cp++ - '0'; 266 *ep = 0; 267 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 268 if (bcmp(ifp->if_name, name, len)) 269 continue; 270 if (unit == ifp->if_unit) 271 break; 272 } 273 *ep = c; 274 return (ifp); 275 } 276 277 /* 278 * Interface ioctls. 279 */ 280 ifioctl(so, cmd, data) 281 struct socket *so; 282 int cmd; 283 caddr_t data; 284 { 285 register struct ifnet *ifp; 286 register struct ifreq *ifr; 287 int error; 288 289 switch (cmd) { 290 291 case SIOCGIFCONF: 292 case OSIOCGIFCONF: 293 return (ifconf(cmd, data)); 294 295 #if defined(INET) && NETHER > 0 296 case SIOCSARP: 297 case SIOCDARP: 298 if (error = suser(u.u_cred, &u.u_acflag)) 299 return (error); 300 /* FALL THROUGH */ 301 case SIOCGARP: 302 case OSIOCGARP: 303 return (arpioctl(cmd, data)); 304 #endif 305 } 306 ifr = (struct ifreq *)data; 307 ifp = ifunit(ifr->ifr_name); 308 if (ifp == 0) 309 return (ENXIO); 310 switch (cmd) { 311 312 case SIOCGIFFLAGS: 313 ifr->ifr_flags = ifp->if_flags; 314 break; 315 316 case SIOCGIFMETRIC: 317 ifr->ifr_metric = ifp->if_metric; 318 break; 319 320 case SIOCSIFFLAGS: 321 if (error = suser(u.u_cred, &u.u_acflag)) 322 return (error); 323 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 324 int s = splimp(); 325 if_down(ifp); 326 splx(s); 327 } 328 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 329 (ifr->ifr_flags &~ IFF_CANTCHANGE); 330 if (ifp->if_ioctl) 331 (void) (*ifp->if_ioctl)(ifp, cmd, data); 332 break; 333 334 case SIOCSIFMETRIC: 335 if (error = suser(u.u_cred, &u.u_acflag)) 336 return (error); 337 ifp->if_metric = ifr->ifr_metric; 338 break; 339 340 default: 341 if (so->so_proto == 0) 342 return (EOPNOTSUPP); 343 #ifndef COMPAT_43 344 return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 345 cmd, data, ifp)); 346 #else 347 { 348 int error, ocmd = cmd; 349 350 switch (cmd) { 351 352 case SIOCSIFDSTADDR: 353 case SIOCSIFADDR: 354 case SIOCSIFBRDADDR: 355 case SIOCSIFNETMASK: 356 #if BYTE_ORDER != BIG_ENDIAN 357 if (ifr->ifr_addr.sa_family == 0 && 358 ifr->ifr_addr.sa_len < 16) { 359 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 360 ifr->ifr_addr.sa_len = 16; 361 } 362 #else 363 if (ifr->ifr_addr.sa_len == 0) 364 ifr->ifr_addr.sa_len = 16; 365 #endif 366 break; 367 368 case OSIOCGIFADDR: 369 cmd = SIOCGIFADDR; 370 break; 371 372 case OSIOCGIFDSTADDR: 373 cmd = SIOCGIFDSTADDR; 374 break; 375 376 case OSIOCGIFBRDADDR: 377 cmd = SIOCGIFBRDADDR; 378 break; 379 380 case OSIOCGIFNETMASK: 381 cmd = SIOCGIFNETMASK; 382 } 383 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 384 cmd, data, ifp)); 385 switch (ocmd) { 386 387 case OSIOCGIFADDR: 388 case OSIOCGIFDSTADDR: 389 case OSIOCGIFBRDADDR: 390 case OSIOCGIFNETMASK: 391 *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 392 } 393 return (error); 394 395 } 396 #endif 397 } 398 return (0); 399 } 400 401 /* 402 * Return interface configuration 403 * of system. List may be used 404 * in later ioctl's (above) to get 405 * other information. 406 */ 407 /*ARGSUSED*/ 408 ifconf(cmd, data) 409 int cmd; 410 caddr_t data; 411 { 412 register struct ifconf *ifc = (struct ifconf *)data; 413 register struct ifnet *ifp = ifnet; 414 register struct ifaddr *ifa; 415 register char *cp, *ep; 416 struct ifreq ifr, *ifrp; 417 int space = ifc->ifc_len, error = 0; 418 419 ifrp = ifc->ifc_req; 420 ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 421 for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 422 bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 423 for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 424 ; 425 *cp++ = '0' + ifp->if_unit; *cp = '\0'; 426 if ((ifa = ifp->if_addrlist) == 0) { 427 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 428 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 429 if (error) 430 break; 431 space -= sizeof (ifr), ifrp++; 432 } else 433 for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 434 register struct sockaddr *sa = ifa->ifa_addr; 435 #ifdef COMPAT_43 436 if (cmd == OSIOCGIFCONF) { 437 struct osockaddr *osa = 438 (struct osockaddr *)&ifr.ifr_addr; 439 ifr.ifr_addr = *sa; 440 osa->sa_family = sa->sa_family; 441 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 442 sizeof (ifr)); 443 ifrp++; 444 } else 445 #endif 446 if (sa->sa_len <= sizeof(*sa)) { 447 ifr.ifr_addr = *sa; 448 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 449 sizeof (ifr)); 450 ifrp++; 451 } else { 452 space -= sa->sa_len - sizeof(*sa); 453 if (space < sizeof (ifr)) 454 break; 455 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 456 sizeof (ifr.ifr_name)); 457 if (error == 0) 458 error = copyout((caddr_t)sa, 459 (caddr_t)&ifrp->ifr_addr, sa->sa_len); 460 ifrp = (struct ifreq *) 461 (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 462 } 463 if (error) 464 break; 465 space -= sizeof (ifr); 466 } 467 } 468 ifc->ifc_len -= space; 469 return (error); 470 } 471