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