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