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.4 1993/06/27 06:02:26 andrew 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 /* XXX -- Temporary fix before changing 10 ethernet drivers */ 126 if (ifp->if_output == ether_output) { 127 ifp->if_type = IFT_ETHER; 128 ifp->if_addrlen = 6; 129 ifp->if_hdrlen = 14; 130 } 131 /* 132 * create a Link Level name for this device 133 */ 134 unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf)); 135 namelen = strlen(ifp->if_name); 136 unitlen = strlen(unitname); 137 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) 138 socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) + 139 unitlen + namelen + ifp->if_addrlen; 140 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) 141 socksize = ROUNDUP(socksize); 142 if (socksize < sizeof(*sdl)) 143 socksize = sizeof(*sdl); 144 ifasize = sizeof(*ifa) + 2 * socksize; 145 ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); 146 if (ifa == 0) 147 return; 148 ifnet_addrs[if_index - 1] = ifa; 149 bzero((caddr_t)ifa, ifasize); 150 sdl = (struct sockaddr_dl *)(ifa + 1); 151 ifa->ifa_addr = (struct sockaddr *)sdl; 152 ifa->ifa_ifp = ifp; 153 sdl->sdl_len = socksize; 154 sdl->sdl_family = AF_LINK; 155 bcopy(ifp->if_name, sdl->sdl_data, namelen); 156 bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen); 157 sdl->sdl_nlen = (namelen += unitlen); 158 sdl->sdl_index = ifp->if_index; 159 sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); 160 ifa->ifa_netmask = (struct sockaddr *)sdl; 161 sdl->sdl_len = socksize - ifp->if_addrlen; 162 while (namelen != 0) 163 sdl->sdl_data[--namelen] = 0xff; 164 ifa->ifa_next = ifp->if_addrlist; 165 ifa->ifa_rtrequest = link_rtrequest; 166 ifp->if_addrlist = ifa; 167 } 168 /* 169 * Locate an interface based on a complete address. 170 */ 171 /*ARGSUSED*/ 172 struct ifaddr * 173 ifa_ifwithaddr(addr) 174 register struct sockaddr *addr; 175 { 176 register struct ifnet *ifp; 177 register struct ifaddr *ifa; 178 179 #define equal(a1, a2) \ 180 (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) 181 for (ifp = ifnet; ifp; ifp = ifp->if_next) 182 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 183 if (ifa->ifa_addr->sa_family != addr->sa_family) 184 continue; 185 if (equal(addr, ifa->ifa_addr)) 186 return (ifa); 187 if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && 188 equal(ifa->ifa_broadaddr, addr)) 189 return (ifa); 190 } 191 return ((struct ifaddr *)0); 192 } 193 /* 194 * Locate the point to point interface with a given destination address. 195 */ 196 /*ARGSUSED*/ 197 struct ifaddr * 198 ifa_ifwithdstaddr(addr) 199 register struct sockaddr *addr; 200 { 201 register struct ifnet *ifp; 202 register struct ifaddr *ifa; 203 204 for (ifp = ifnet; ifp; ifp = ifp->if_next) 205 if (ifp->if_flags & IFF_POINTOPOINT) 206 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 207 if (ifa->ifa_addr->sa_family != addr->sa_family) 208 continue; 209 if (equal(addr, ifa->ifa_dstaddr)) 210 return (ifa); 211 } 212 return ((struct ifaddr *)0); 213 } 214 215 /* 216 * Find an interface on a specific network. If many, choice 217 * is first found. 218 */ 219 struct ifaddr * 220 ifa_ifwithnet(addr) 221 struct sockaddr *addr; 222 { 223 register struct ifnet *ifp; 224 register struct ifaddr *ifa; 225 u_int af = addr->sa_family; 226 227 if (af >= AF_MAX) 228 return (0); 229 if (af == AF_LINK) { 230 register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; 231 if (sdl->sdl_index && sdl->sdl_index <= if_index) 232 return (ifnet_addrs[sdl->sdl_index - 1]); 233 } 234 for (ifp = ifnet; ifp; ifp = ifp->if_next) 235 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 236 register char *cp, *cp2, *cp3; 237 register char *cplim; 238 if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0) 239 continue; 240 cp = addr->sa_data; 241 cp2 = ifa->ifa_addr->sa_data; 242 cp3 = ifa->ifa_netmask->sa_data; 243 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 244 for (; cp3 < cplim; cp3++) 245 if ((*cp++ ^ *cp2++) & *cp3) 246 break; 247 if (cp3 == cplim) 248 return (ifa); 249 } 250 return ((struct ifaddr *)0); 251 } 252 253 /* 254 * Find an interface using a specific address family 255 */ 256 struct ifaddr * 257 ifa_ifwithaf(af) 258 register int af; 259 { 260 register struct ifnet *ifp; 261 register struct ifaddr *ifa; 262 263 for (ifp = ifnet; ifp; ifp = ifp->if_next) 264 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 265 if (ifa->ifa_addr->sa_family == af) 266 return (ifa); 267 return ((struct ifaddr *)0); 268 } 269 270 /* 271 * Find an interface address specific to an interface best matching 272 * a given address. 273 */ 274 struct ifaddr * 275 ifaof_ifpforaddr(addr, ifp) 276 struct sockaddr *addr; 277 register struct ifnet *ifp; 278 { 279 register struct ifaddr *ifa; 280 register char *cp, *cp2, *cp3; 281 register char *cplim; 282 struct ifaddr *ifa_maybe = 0; 283 u_int af = addr->sa_family; 284 285 if (af >= AF_MAX) 286 return (0); 287 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { 288 if (ifa->ifa_addr->sa_family != af) 289 continue; 290 ifa_maybe = ifa; 291 if (ifa->ifa_netmask == 0) { 292 if (equal(addr, ifa->ifa_addr) || 293 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) 294 return (ifa); 295 continue; 296 } 297 cp = addr->sa_data; 298 cp2 = ifa->ifa_addr->sa_data; 299 cp3 = ifa->ifa_netmask->sa_data; 300 cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; 301 for (; cp3 < cplim; cp3++) 302 if ((*cp++ ^ *cp2++) & *cp3) 303 break; 304 if (cp3 == cplim) 305 return (ifa); 306 } 307 return (ifa_maybe); 308 } 309 #include "route.h" 310 /* 311 * Default action when installing a route with a Link Level gateway. 312 * Lookup an appropriate real ifa to point to. 313 * This should be moved to /sys/net/link.c eventually. 314 */ 315 link_rtrequest(cmd, rt, sa) 316 register struct rtentry *rt; 317 struct sockaddr *sa; 318 { 319 register struct ifaddr *ifa; 320 struct sockaddr *dst; 321 struct ifnet *ifp, *oldifnet = ifnet; 322 323 if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || 324 ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) 325 return; 326 if (ifa = ifaof_ifpforaddr(dst, ifp)) { 327 rt->rt_ifa = ifa; 328 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) 329 ifa->ifa_rtrequest(cmd, rt, sa); 330 } 331 } 332 333 /* 334 * Mark an interface down and notify protocols of 335 * the transition. 336 * NOTE: must be called at splnet or eqivalent. 337 */ 338 if_down(ifp) 339 register struct ifnet *ifp; 340 { 341 register struct ifaddr *ifa; 342 343 ifp->if_flags &= ~IFF_UP; 344 for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) 345 pfctlinput(PRC_IFDOWN, ifa->ifa_addr); 346 if_qflush(&ifp->if_snd); 347 } 348 349 /* 350 * Flush an interface queue. 351 */ 352 if_qflush(ifq) 353 register struct ifqueue *ifq; 354 { 355 register struct mbuf *m, *n; 356 357 n = ifq->ifq_head; 358 while (m = n) { 359 n = m->m_act; 360 m_freem(m); 361 } 362 ifq->ifq_head = 0; 363 ifq->ifq_tail = 0; 364 ifq->ifq_len = 0; 365 } 366 367 /* 368 * Handle interface watchdog timer routines. Called 369 * from softclock, we decrement timers (if set) and 370 * call the appropriate interface routine on expiration. 371 */ 372 /* ARGSUSED */ 373 void 374 if_slowtimo(caddr_t arg) 375 { 376 register struct ifnet *ifp; 377 int s = splimp(); 378 379 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 380 if (ifp->if_timer == 0 || --ifp->if_timer) 381 continue; 382 if (ifp->if_watchdog) 383 (*ifp->if_watchdog)(ifp->if_unit); 384 } 385 splx(s); 386 timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); 387 } 388 389 /* 390 * Map interface name to 391 * interface structure pointer. 392 */ 393 struct ifnet * 394 ifunit(name) 395 register char *name; 396 { 397 register char *cp; 398 register struct ifnet *ifp; 399 int unit; 400 unsigned len; 401 char *ep, c; 402 403 for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) 404 if (*cp >= '0' && *cp <= '9') 405 break; 406 if (*cp == '\0' || cp == name + IFNAMSIZ) 407 return ((struct ifnet *)0); 408 /* 409 * Save first char of unit, and pointer to it, 410 * so we can put a null there to avoid matching 411 * initial substrings of interface names. 412 */ 413 len = cp - name + 1; 414 c = *cp; 415 ep = cp; 416 for (unit = 0; *cp >= '0' && *cp <= '9'; ) 417 unit = unit * 10 + *cp++ - '0'; 418 *ep = 0; 419 for (ifp = ifnet; ifp; ifp = ifp->if_next) { 420 if (bcmp(ifp->if_name, name, len)) 421 continue; 422 if (unit == ifp->if_unit) 423 break; 424 } 425 *ep = c; 426 return (ifp); 427 } 428 429 /* 430 * Interface ioctls. 431 */ 432 ifioctl(so, cmd, data, p) 433 struct socket *so; 434 int cmd; 435 caddr_t data; 436 struct proc *p; 437 { 438 register struct ifnet *ifp; 439 register struct ifreq *ifr; 440 int error; 441 442 switch (cmd) { 443 444 case SIOCGIFCONF: 445 case OSIOCGIFCONF: 446 return (ifconf(cmd, data)); 447 448 #if defined(INET) && NETHER > 0 449 case SIOCSARP: 450 case SIOCDARP: 451 if (error = suser(p->p_ucred, &p->p_acflag)) 452 return (error); 453 /* FALL THROUGH */ 454 case SIOCGARP: 455 case OSIOCGARP: 456 return (arpioctl(cmd, data)); 457 #endif 458 } 459 ifr = (struct ifreq *)data; 460 ifp = ifunit(ifr->ifr_name); 461 if (ifp == 0) 462 return (ENXIO); 463 switch (cmd) { 464 465 case SIOCGIFFLAGS: 466 ifr->ifr_flags = ifp->if_flags; 467 break; 468 469 case SIOCGIFMETRIC: 470 ifr->ifr_metric = ifp->if_metric; 471 break; 472 473 case SIOCSIFFLAGS: 474 if (error = suser(p->p_ucred, &p->p_acflag)) 475 return (error); 476 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { 477 int s = splimp(); 478 if_down(ifp); 479 splx(s); 480 } 481 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | 482 (ifr->ifr_flags &~ IFF_CANTCHANGE); 483 if (ifp->if_ioctl) 484 (void) (*ifp->if_ioctl)(ifp, cmd, data); 485 break; 486 487 case SIOCSIFMETRIC: 488 if (error = suser(p->p_ucred, &p->p_acflag)) 489 return (error); 490 ifp->if_metric = ifr->ifr_metric; 491 break; 492 493 default: 494 if (so->so_proto == 0) 495 return (EOPNOTSUPP); 496 #ifndef COMPAT_43 497 return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 498 cmd, data, ifp)); 499 #else 500 { 501 int ocmd = cmd; 502 503 switch (cmd) { 504 505 case SIOCSIFDSTADDR: 506 case SIOCSIFADDR: 507 case SIOCSIFBRDADDR: 508 case SIOCSIFNETMASK: 509 #if BYTE_ORDER != BIG_ENDIAN 510 if (ifr->ifr_addr.sa_family == 0 && 511 ifr->ifr_addr.sa_len < 16) { 512 ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; 513 ifr->ifr_addr.sa_len = 16; 514 } 515 #else 516 if (ifr->ifr_addr.sa_len == 0) 517 ifr->ifr_addr.sa_len = 16; 518 #endif 519 break; 520 521 case OSIOCGIFADDR: 522 cmd = SIOCGIFADDR; 523 break; 524 525 case OSIOCGIFDSTADDR: 526 cmd = SIOCGIFDSTADDR; 527 break; 528 529 case OSIOCGIFBRDADDR: 530 cmd = SIOCGIFBRDADDR; 531 break; 532 533 case OSIOCGIFNETMASK: 534 cmd = SIOCGIFNETMASK; 535 } 536 error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, 537 cmd, data, ifp)); 538 switch (ocmd) { 539 540 case OSIOCGIFADDR: 541 case OSIOCGIFDSTADDR: 542 case OSIOCGIFBRDADDR: 543 case OSIOCGIFNETMASK: 544 *(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; 545 } 546 return (error); 547 548 } 549 #endif 550 } 551 return (0); 552 } 553 554 /* 555 * Return interface configuration 556 * of system. List may be used 557 * in later ioctl's (above) to get 558 * other information. 559 */ 560 /*ARGSUSED*/ 561 ifconf(cmd, data) 562 int cmd; 563 caddr_t data; 564 { 565 register struct ifconf *ifc = (struct ifconf *)data; 566 register struct ifnet *ifp = ifnet; 567 register struct ifaddr *ifa; 568 register char *cp, *ep; 569 struct ifreq ifr, *ifrp; 570 int space = ifc->ifc_len, error = 0; 571 572 ifrp = ifc->ifc_req; 573 ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; 574 for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { 575 bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); 576 for (cp = ifr.ifr_name; cp < ep && *cp; cp++) 577 ; 578 *cp++ = '0' + ifp->if_unit; *cp = '\0'; 579 if ((ifa = ifp->if_addrlist) == 0) { 580 bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); 581 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); 582 if (error) 583 break; 584 space -= sizeof (ifr), ifrp++; 585 } else 586 for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { 587 register struct sockaddr *sa = ifa->ifa_addr; 588 #ifdef COMPAT_43 589 if (cmd == OSIOCGIFCONF) { 590 struct osockaddr *osa = 591 (struct osockaddr *)&ifr.ifr_addr; 592 ifr.ifr_addr = *sa; 593 osa->sa_family = sa->sa_family; 594 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 595 sizeof (ifr)); 596 ifrp++; 597 } else 598 #endif 599 if (sa->sa_len <= sizeof(*sa)) { 600 ifr.ifr_addr = *sa; 601 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 602 sizeof (ifr)); 603 ifrp++; 604 } else { 605 space -= sa->sa_len - sizeof(*sa); 606 if (space < sizeof (ifr)) 607 break; 608 error = copyout((caddr_t)&ifr, (caddr_t)ifrp, 609 sizeof (ifr.ifr_name)); 610 if (error == 0) 611 error = copyout((caddr_t)sa, 612 (caddr_t)&ifrp->ifr_addr, sa->sa_len); 613 ifrp = (struct ifreq *) 614 (sa->sa_len + (caddr_t)&ifrp->ifr_addr); 615 } 616 if (error) 617 break; 618 space -= sizeof (ifr); 619 } 620 } 621 ifc->ifc_len -= space; 622 return (error); 623 } 624 625 static char * 626 sprint_d(n, buf, buflen) 627 u_int n; 628 char *buf; 629 int buflen; 630 { 631 register char *cp = buf + buflen - 1; 632 633 *cp = 0; 634 do { 635 cp--; 636 *cp = "0123456789"[n % 10]; 637 n /= 10; 638 } while (n != 0); 639 return (cp); 640 } 641