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