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, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)if.c 7.14 (Berkeley) 4/20/91 34 * $Id: if.c,v 1.6 1993/08/27 10:26:08 mycroft Exp $ 35 */ 36 37 #include "param.h" 38 #include "mbuf.h" 39 #include "systm.h" 40 #include "socket.h" 41 #include "socketvar.h" 42 #include "protosw.h" 43 #include "proc.h" 44 #include "kernel.h" 45 #include "ioctl.h" 46 47 #include "if.h" 48 #include "af.h" 49 #include "if_dl.h" 50 #include "if_types.h" 51 52 #include "ether.h" 53 54 int ifqmaxlen = IFQ_MAXLEN; 55 56 void if_slowtimo(caddr_t); 57 58 /* 59 * Network interface utility routines. 60 * 61 * Routines with ifa_ifwith* names take sockaddr *'s as 62 * parameters. 63 */ 64 65 void 66 ifinit() 67 { 68 register struct ifnet *ifp; 69 70 for (ifp = ifnet; ifp; ifp = ifp->if_next) 71 if (ifp->if_snd.ifq_maxlen == 0) 72 ifp->if_snd.ifq_maxlen = ifqmaxlen; 73 if_slowtimo(NULL); 74 } 75 76 #ifdef vax 77 /* 78 * Call each interface on a Unibus reset. 79 */ 80 ifubareset(uban) 81 int uban; 82 { 83 register struct ifnet *ifp; 84 85 for (ifp = ifnet; ifp; ifp = ifp->if_next) 86 if (ifp->if_reset) 87 (*ifp->if_reset)(ifp->if_unit, uban); 88 } 89 #endif 90 91 int if_index = 0; 92 struct ifaddr **ifnet_addrs; 93 static char *sprint_d(); 94 95 /* 96 * Attach an interface to the 97 * list of "active" interfaces. 98 */ 99 if_attach(ifp) 100 struct ifnet *ifp; 101 { 102 unsigned socksize, ifasize; 103 int namelen, unitlen; 104 char workbuf[12], *unitname; 105 register struct ifnet **p = &ifnet; 106 register struct sockaddr_dl *sdl; 107 register struct ifaddr *ifa; 108 static int if_indexlim = 8; 109 extern link_rtrequest(), ether_output(); 110 111 while (*p) 112 p = &((*p)->if_next); 113 *p = ifp; 114 ifp->if_index = ++if_index; 115 if (ifnet_addrs == 0 || if_index >= if_indexlim) { 116 unsigned n = (if_indexlim <<= 1) * sizeof(ifa); 117 struct ifaddr **q = (struct ifaddr **) 118 malloc(n, M_IFADDR, M_WAITOK); 119 if (ifnet_addrs) { 120 bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2); 121 free((caddr_t)ifnet_addrs, M_IFADDR); 122 } 123 ifnet_addrs = q; 124 } 125 #if defined(INET) && NETHER > 0 126 /* XXX -- Temporary fix before changing 10 ethernet drivers */ 127 if (ifp->if_output == ether_output) { 128 ifp->if_type = IFT_ETHER; 129 ifp->if_addrlen = 6; 130 ifp->if_hdrlen = 14; 131 } 132 #endif 133 /* 134 * create a Link Level name for this device 135 */ 136 unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf)); 137 namelen = strlen(ifp->if_name); 138 unitlen = strlen(unitname); 139 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 140 socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) + 141 unitlen + namelen + ifp->if_addrlen; 142 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 143 socksize = ROUNDUP(socksize); 144 if (socksize < sizeof(*sdl)) 145 socksize = sizeof(*sdl); 146 ifasize = sizeof(*ifa) + 2 * socksize; 147 ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); 148 if (ifa == 0) 149 return; 150 ifnet_addrs[if_index - 1] = ifa; 151 bzero((caddr_t)ifa, ifasize); 152 sdl = (struct sockaddr_dl *)(ifa + 1); 153 ifa->ifa_addr = (struct sockaddr *)sdl; 154 ifa->ifa_ifp = ifp; 155 sdl->sdl_len = socksize; 156 sdl->sdl_family = AF_LINK; 157 bcopy(ifp->if_name, sdl->sdl_data, namelen); 158 bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen); 159 sdl->sdl_nlen = (namelen += unitlen); 160 sdl->sdl_index = ifp->if_index; 161 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 162 ifa->ifa_netmask = (struct sockaddr *)sdl; 163 sdl->sdl_len = socksize - ifp->if_addrlen; 164 while (namelen != 0) 165 sdl->sdl_data[--namelen] = 0xff; 166 ifa->ifa_next = ifp->if_addrlist; 167 ifa->ifa_rtrequest = link_rtrequest; 168 ifp->if_addrlist = ifa; 169 } 170 /* 171 * Locate an interface based on a complete address. 172 */ 173 /*ARGSUSED*/ 174 struct ifaddr * 175 ifa_ifwithaddr(addr) 176 register struct sockaddr *addr; 177 { 178 register struct ifnet *ifp; 179 register struct ifaddr *ifa; 180 181 #define equal(a1, a2) \ 182 (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) 183 for (ifp = ifnet; ifp; ifp = ifp->if_next) 184 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 185 if (ifa->ifa_addr->sa_family != addr->sa_family) 186 continue; 187 if (equal(addr, ifa->ifa_addr)) 188 return (ifa); 189 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && 190 equal(ifa->ifa_broadaddr, addr)) 191 return (ifa); 192 } 193 return ((struct ifaddr *)0); 194 } 195 /* 196 * Locate the point to point interface with a given destination address. 197 */ 198 /*ARGSUSED*/ 199 struct ifaddr * 200 ifa_ifwithdstaddr(addr) 201 register struct sockaddr *addr; 202 { 203 register struct ifnet *ifp; 204 register struct ifaddr *ifa; 205 206 for (ifp = ifnet; ifp; ifp = ifp->if_next) 207 if (ifp->if_flags & IFF_POINTOPOINT) 208 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 209 if (ifa->ifa_addr->sa_family != addr->sa_family) 210 continue; 211 if (equal(addr, ifa->ifa_dstaddr)) 212 return (ifa); 213 } 214 return ((struct ifaddr *)0); 215 } 216 217 /* 218 * Find an interface on a specific network. If many, choice 219 * is first found. 220 */ 221 struct ifaddr * 222 ifa_ifwithnet(addr) 223 struct sockaddr *addr; 224 { 225 register struct ifnet *ifp; 226 register struct ifaddr *ifa; 227 u_int af = addr->sa_family; 228 229 if (af >= AF_MAX) 230 return (0); 231 if (af == AF_LINK) { 232 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; 233 if (sdl->sdl_index && sdl->sdl_index <= if_index) 234 return (ifnet_addrs[sdl->sdl_index - 1]); 235 } 236 for (ifp = ifnet; ifp; ifp = ifp->if_next) 237 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 238 register char *cp, *cp2, *cp3; 239 register char *cplim; 240 if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0) 241 continue; 242 cp = addr->sa_data; 243 cp2 = ifa->ifa_addr->sa_data; 244 cp3 = ifa->ifa_netmask->sa_data; 245 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 246 for (; cp3 < cplim; cp3++) 247 if ((*cp++ ^ *cp2++) & *cp3) 248 break; 249 if (cp3 == cplim) 250 return (ifa); 251 } 252 return ((struct ifaddr *)0); 253 } 254 255 /* 256 * Find an interface using a specific address family 257 */ 258 struct ifaddr * 259 ifa_ifwithaf(af) 260 register int af; 261 { 262 register struct ifnet *ifp; 263 register struct ifaddr *ifa; 264 265 for (ifp = ifnet; ifp; ifp = ifp->if_next) 266 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 267 if (ifa->ifa_addr->sa_family == af) 268 return (ifa); 269 return ((struct ifaddr *)0); 270 } 271 272 /* 273 * Find an interface address specific to an interface best matching 274 * a given address. 275 */ 276 struct ifaddr * 277 ifaof_ifpforaddr(addr, ifp) 278 struct sockaddr *addr; 279 register struct ifnet *ifp; 280 { 281 register struct ifaddr *ifa; 282 register char *cp, *cp2, *cp3; 283 register char *cplim; 284 struct ifaddr *ifa_maybe = 0; 285 u_int af = addr->sa_family; 286 287 if (af >= AF_MAX) 288 return (0); 289 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 290 if (ifa->ifa_addr->sa_family != af) 291 continue; 292 ifa_maybe = ifa; 293 if (ifa->ifa_netmask == 0) { 294 if (equal(addr, ifa->ifa_addr) || 295 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) 296 return (ifa); 297 continue; 298 } 299 cp = addr->sa_data; 300 cp2 = ifa->ifa_addr->sa_data; 301 cp3 = ifa->ifa_netmask->sa_data; 302 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 303 for (; cp3 < cplim; cp3++) 304 if ((*cp++ ^ *cp2++) & *cp3) 305 break; 306 if (cp3 == cplim) 307 return (ifa); 308 } 309 return (ifa_maybe); 310 } 311 #include "route.h" 312 /* 313 * Default action when installing a route with a Link Level gateway. 314 * Lookup an appropriate real ifa to point to. 315 * This should be moved to /sys/net/link.c eventually. 316 */ 317 link_rtrequest(cmd, rt, sa) 318 register struct rtentry *rt; 319 struct sockaddr *sa; 320 { 321 register struct ifaddr *ifa; 322 struct sockaddr *dst; 323 struct ifnet *ifp, *oldifnet = ifnet; 324 325 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 326 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 327 return; 328 if (ifa = ifaof_ifpforaddr(dst, ifp)) { 329 rt->rt_ifa = ifa; 330 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 331 ifa->ifa_rtrequest(cmd, rt, sa); 332 } 333 } 334 335 /* 336 * Mark an interface down and notify protocols of 337 * the transition. 338 * NOTE: must be called at splnet or eqivalent. 339 */ 340 if_down(ifp) 341 register struct ifnet *ifp; 342 { 343 register struct ifaddr *ifa; 344 345 ifp->if_flags &= ~IFF_UP; 346 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 347 pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 348 if_qflush(&ifp->if_snd); 349 } 350 351 /* 352 * Flush an interface queue. 353 */ 354 if_qflush(ifq) 355 register struct ifqueue *ifq; 356 { 357 register struct mbuf *m, *n; 358 359 n = ifq->ifq_head; 360 while (m = n) { 361 n = m->m_act; 362 m_freem(m); 363 } 364 ifq->ifq_head = 0; 365 ifq->ifq_tail = 0; 366 ifq->ifq_len = 0; 367 } 368 369 /* 370 * Handle interface watchdog timer routines. Called 371 * from softclock, we decrement timers (if set) and 372 * call the appropriate interface routine on expiration. 373 */ 374 /* ARGSUSED */ 375 void 376 if_slowtimo(caddr_t arg) 377 { 378 register struct ifnet *ifp; 379 int s = splimp(); 380 381 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 382 if (ifp->if_timer == 0 || --ifp->if_timer) 383 continue; 384 if (ifp->if_watchdog) 385 (*ifp->if_watchdog)(ifp->if_unit); 386 } 387 splx(s); 388 timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 389 } 390 391 /* 392 * Map interface name to 393 * interface structure pointer. 394 */ 395 struct ifnet * 396 ifunit(name) 397 register char *name; 398 { 399 register char *cp; 400 register struct ifnet *ifp; 401 int unit; 402 unsigned len; 403 char *ep, c; 404 405 for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 406 if (*cp >= '0' && *cp <= '9') 407 break; 408 if (*cp == '\0' || cp == name + IFNAMSIZ) 409 return ((struct ifnet *)0); 410 /* 411 * Save first char of unit, and pointer to it, 412 * so we can put a null there to avoid matching 413 * initial substrings of interface names. 414 */ 415 len = cp - name + 1; 416 c = *cp; 417 ep = cp; 418 for (unit = 0; *cp >= '0' && *cp <= '9'; ) 419 unit = unit * 10 + *cp++ - '0'; 420 *ep = 0; 421 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 422 if (bcmp(ifp->if_name, name, len)) 423 continue; 424 if (unit == ifp->if_unit) 425 break; 426 } 427 *ep = c; 428 return (ifp); 429 } 430 431 /* 432 * Interface ioctls. 433 */ 434 ifioctl(so, cmd, data, p) 435 struct socket *so; 436 int cmd; 437 caddr_t data; 438 struct proc *p; 439 { 440 register struct ifnet *ifp; 441 register struct ifreq *ifr; 442 int error; 443 444 switch (cmd) { 445 446 case SIOCGIFCONF: 447 case OSIOCGIFCONF: 448 return (ifconf(cmd, data)); 449 450 #if defined(INET) && NETHER > 0 451 case SIOCSARP: 452 case SIOCDARP: 453 if (error = suser(p->p_ucred, &p->p_acflag)) 454 return (error); 455 /* FALL THROUGH */ 456 case SIOCGARP: 457 case OSIOCGARP: 458 return (arpioctl(cmd, data)); 459 #endif 460 } 461 ifr = (struct ifreq *)data; 462 ifp = ifunit(ifr->ifr_name); 463 if (ifp == 0) 464 return (ENXIO); 465 switch (cmd) { 466 467 case SIOCGIFFLAGS: 468 ifr->ifr_flags = ifp->if_flags; 469 break; 470 471 case SIOCGIFMETRIC: 472 ifr->ifr_metric = ifp->if_metric; 473 break; 474 475 case SIOCSIFFLAGS: 476 if (error = suser(p->p_ucred, &p->p_acflag)) 477 return (error); 478 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 479 int s = splimp(); 480 if_down(ifp); 481 splx(s); 482 } 483 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 484 (ifr->ifr_flags &~ IFF_CANTCHANGE); 485 if (ifp->if_ioctl) 486 (void) (*ifp->if_ioctl)(ifp, cmd, data); 487 break; 488 489 case SIOCSIFMETRIC: 490 if (error = suser(p->p_ucred, &p->p_acflag)) 491 return (error); 492 ifp->if_metric = ifr->ifr_metric; 493 break; 494 495 case SIOCSIFMTU: 496 case SIOCGIFMTU: 497 case SIOCSIFASYNCMAP: 498 case SIOCGIFASYNCMAP: 499 if (!ifp->if_ioctl) 500 return (EOPNOTSUPP); 501 return ((*ifp->if_ioctl)(ifp, cmd, data)); 502 break; 503 504 default: 505 if (so->so_proto == 0) 506 return (EOPNOTSUPP); 507 #ifndef COMPAT_43 508 return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 509 cmd, data, ifp)); 510 #else 511 { 512 int ocmd = cmd; 513 514 switch (cmd) { 515 516 case SIOCSIFDSTADDR: 517 case SIOCSIFADDR: 518 case SIOCSIFBRDADDR: 519 case SIOCSIFNETMASK: 520 #if BYTE_ORDER != BIG_ENDIAN 521 if (ifr->ifr_addr.sa_family == 0 && 522 ifr->ifr_addr.sa_len < 16) { 523 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 524 ifr->ifr_addr.sa_len = 16; 525 } 526 #else 527 if (ifr->ifr_addr.sa_len == 0) 528 ifr->ifr_addr.sa_len = 16; 529 #endif 530 break; 531 532 case OSIOCGIFADDR: 533 cmd = SIOCGIFADDR; 534 break; 535 536 case OSIOCGIFDSTADDR: 537 cmd = SIOCGIFDSTADDR; 538 break; 539 540 case OSIOCGIFBRDADDR: 541 cmd = SIOCGIFBRDADDR; 542 break; 543 544 case OSIOCGIFNETMASK: 545 cmd = SIOCGIFNETMASK; 546 } 547 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 548 cmd, data, ifp)); 549 switch (ocmd) { 550 551 case OSIOCGIFADDR: 552 case OSIOCGIFDSTADDR: 553 case OSIOCGIFBRDADDR: 554 case OSIOCGIFNETMASK: 555 *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 556 } 557 return (error); 558 559 } 560 #endif 561 } 562 return (0); 563 } 564 565 /* 566 * Return interface configuration 567 * of system. List may be used 568 * in later ioctl's (above) to get 569 * other information. 570 */ 571 /*ARGSUSED*/ 572 ifconf(cmd, data) 573 int cmd; 574 caddr_t data; 575 { 576 register struct ifconf *ifc = (struct ifconf *)data; 577 register struct ifnet *ifp = ifnet; 578 register struct ifaddr *ifa; 579 register char *cp, *ep; 580 struct ifreq ifr, *ifrp; 581 int space = ifc->ifc_len, error = 0; 582 583 ifrp = ifc->ifc_req; 584 ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 585 for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 586 bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 587 for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 588 ; 589 *cp++ = '0' + ifp->if_unit; *cp = '\0'; 590 if ((ifa = ifp->if_addrlist) == 0) { 591 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 592 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 593 if (error) 594 break; 595 space -= sizeof (ifr), ifrp++; 596 } else 597 for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 598 register struct sockaddr *sa = ifa->ifa_addr; 599 #ifdef COMPAT_43 600 if (cmd == OSIOCGIFCONF) { 601 struct osockaddr *osa = 602 (struct osockaddr *)&ifr.ifr_addr; 603 ifr.ifr_addr = *sa; 604 osa->sa_family = sa->sa_family; 605 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 606 sizeof (ifr)); 607 ifrp++; 608 } else 609 #endif 610 if (sa->sa_len <= sizeof(*sa)) { 611 ifr.ifr_addr = *sa; 612 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 613 sizeof (ifr)); 614 ifrp++; 615 } else { 616 space -= sa->sa_len - sizeof(*sa); 617 if (space < sizeof (ifr)) 618 break; 619 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 620 sizeof (ifr.ifr_name)); 621 if (error == 0) 622 error = copyout((caddr_t)sa, 623 (caddr_t)&ifrp->ifr_addr, sa->sa_len); 624 ifrp = (struct ifreq *) 625 (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 626 } 627 if (error) 628 break; 629 space -= sizeof (ifr); 630 } 631 } 632 ifc->ifc_len -= space; 633 return (error); 634 } 635 636 static char * 637 sprint_d(n, buf, buflen) 638 u_int n; 639 char *buf; 640 int buflen; 641 { 642 register char *cp = buf + buflen - 1; 643 644 *cp = 0; 645 do { 646 cp--; 647 *cp = "0123456789"[n % 10]; 648 n /= 10; 649 } while (n != 0); 650 return (cp); 651 } 652