|
|
1.1 ! root 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.4 (Berkeley) 6/27/88 ! 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 "dir.h" ! 27: #include "user.h" ! 28: #include "kernel.h" ! 29: #include "ioctl.h" ! 30: #include "errno.h" ! 31: ! 32: #include "if.h" ! 33: #include "af.h" ! 34: ! 35: #include "ether.h" ! 36: ! 37: int ifqmaxlen = IFQ_MAXLEN; ! 38: ! 39: /* ! 40: * Network interface utility routines. ! 41: * ! 42: * Routines with ifa_ifwith* names take sockaddr *'s as ! 43: * parameters. ! 44: */ ! 45: ! 46: ifinit() ! 47: { ! 48: register struct ifnet *ifp; ! 49: ! 50: for (ifp = ifnet; ifp; ifp = ifp->if_next) ! 51: if (ifp->if_snd.ifq_maxlen == 0) ! 52: ifp->if_snd.ifq_maxlen = ifqmaxlen; ! 53: if_slowtimo(); ! 54: } ! 55: ! 56: #ifdef vax ! 57: /* ! 58: * Call each interface on a Unibus reset. ! 59: */ ! 60: ifubareset(uban) ! 61: int uban; ! 62: { ! 63: register struct ifnet *ifp; ! 64: ! 65: for (ifp = ifnet; ifp; ifp = ifp->if_next) ! 66: if (ifp->if_reset) ! 67: (*ifp->if_reset)(ifp->if_unit, uban); ! 68: } ! 69: #endif ! 70: ! 71: /* ! 72: * Attach an interface to the ! 73: * list of "active" interfaces. ! 74: */ ! 75: if_attach(ifp) ! 76: struct ifnet *ifp; ! 77: { ! 78: register struct ifnet **p = &ifnet; ! 79: ! 80: while (*p) ! 81: p = &((*p)->if_next); ! 82: *p = ifp; ! 83: } ! 84: ! 85: /* ! 86: * Locate an interface based on a complete address. ! 87: */ ! 88: /*ARGSUSED*/ ! 89: struct ifaddr * ! 90: ifa_ifwithaddr(addr) ! 91: struct sockaddr *addr; ! 92: { ! 93: register struct ifnet *ifp; ! 94: register struct ifaddr *ifa; ! 95: ! 96: #define equal(a1, a2) \ ! 97: (bcmp((caddr_t)((a1)->sa_data), (caddr_t)((a2)->sa_data), 14) == 0) ! 98: for (ifp = ifnet; ifp; ifp = ifp->if_next) ! 99: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { ! 100: if (ifa->ifa_addr.sa_family != addr->sa_family) ! 101: continue; ! 102: if (equal(&ifa->ifa_addr, addr)) ! 103: return (ifa); ! 104: if ((ifp->if_flags & IFF_BROADCAST) && ! 105: equal(&ifa->ifa_broadaddr, addr)) ! 106: return (ifa); ! 107: } ! 108: return ((struct ifaddr *)0); ! 109: } ! 110: /* ! 111: * Locate the point to point interface with a given destination address. ! 112: */ ! 113: /*ARGSUSED*/ ! 114: struct ifaddr * ! 115: ifa_ifwithdstaddr(addr) ! 116: struct sockaddr *addr; ! 117: { ! 118: register struct ifnet *ifp; ! 119: register struct ifaddr *ifa; ! 120: ! 121: for (ifp = ifnet; ifp; ifp = ifp->if_next) ! 122: if (ifp->if_flags & IFF_POINTOPOINT) ! 123: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { ! 124: if (ifa->ifa_addr.sa_family != addr->sa_family) ! 125: continue; ! 126: if (equal(&ifa->ifa_dstaddr, addr)) ! 127: return (ifa); ! 128: } ! 129: return ((struct ifaddr *)0); ! 130: } ! 131: ! 132: /* ! 133: * Find an interface on a specific network. If many, choice ! 134: * is first found. ! 135: */ ! 136: struct ifaddr * ! 137: ifa_ifwithnet(addr) ! 138: register struct sockaddr *addr; ! 139: { ! 140: register struct ifnet *ifp; ! 141: register struct ifaddr *ifa; ! 142: register u_int af = addr->sa_family; ! 143: register int (*netmatch)(); ! 144: ! 145: if (af >= AF_MAX) ! 146: return (0); ! 147: netmatch = afswitch[af].af_netmatch; ! 148: for (ifp = ifnet; ifp; ifp = ifp->if_next) ! 149: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { ! 150: if (ifa->ifa_addr.sa_family != addr->sa_family) ! 151: continue; ! 152: if ((*netmatch)(&ifa->ifa_addr, addr)) ! 153: return (ifa); ! 154: } ! 155: return ((struct ifaddr *)0); ! 156: } ! 157: ! 158: #ifdef notdef ! 159: /* ! 160: * Find an interface using a specific address family ! 161: */ ! 162: struct ifaddr * ! 163: ifa_ifwithaf(af) ! 164: register int af; ! 165: { ! 166: register struct ifnet *ifp; ! 167: register struct ifaddr *ifa; ! 168: ! 169: for (ifp = ifnet; ifp; ifp = ifp->if_next) ! 170: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) ! 171: if (ifa->ifa_addr.sa_family == af) ! 172: return (ifa); ! 173: return ((struct ifaddr *)0); ! 174: } ! 175: #endif ! 176: ! 177: /* ! 178: * Mark an interface down and notify protocols of ! 179: * the transition. ! 180: * NOTE: must be called at splnet or eqivalent. ! 181: */ ! 182: if_down(ifp) ! 183: register struct ifnet *ifp; ! 184: { ! 185: register struct ifaddr *ifa; ! 186: ! 187: ifp->if_flags &= ~IFF_UP; ! 188: for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) ! 189: pfctlinput(PRC_IFDOWN, &ifa->ifa_addr); ! 190: if_qflush(&ifp->if_snd); ! 191: } ! 192: ! 193: /* ! 194: * Flush an interface queue. ! 195: */ ! 196: if_qflush(ifq) ! 197: register struct ifqueue *ifq; ! 198: { ! 199: register struct mbuf *m, *n; ! 200: ! 201: n = ifq->ifq_head; ! 202: while (m = n) { ! 203: n = m->m_act; ! 204: m_freem(m); ! 205: } ! 206: ifq->ifq_head = 0; ! 207: ifq->ifq_tail = 0; ! 208: ifq->ifq_len = 0; ! 209: } ! 210: ! 211: /* ! 212: * Handle interface watchdog timer routines. Called ! 213: * from softclock, we decrement timers (if set) and ! 214: * call the appropriate interface routine on expiration. ! 215: */ ! 216: if_slowtimo() ! 217: { ! 218: register struct ifnet *ifp; ! 219: ! 220: for (ifp = ifnet; ifp; ifp = ifp->if_next) { ! 221: if (ifp->if_timer == 0 || --ifp->if_timer) ! 222: continue; ! 223: if (ifp->if_watchdog) ! 224: (*ifp->if_watchdog)(ifp->if_unit); ! 225: } ! 226: timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ); ! 227: } ! 228: ! 229: /* ! 230: * Map interface name to ! 231: * interface structure pointer. ! 232: */ ! 233: struct ifnet * ! 234: ifunit(name) ! 235: register char *name; ! 236: { ! 237: register char *cp; ! 238: register struct ifnet *ifp; ! 239: int unit; ! 240: ! 241: for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) ! 242: if (*cp >= '0' && *cp <= '9') ! 243: break; ! 244: if (*cp == '\0' || cp == name + IFNAMSIZ) ! 245: return ((struct ifnet *)0); ! 246: unit = *cp - '0'; ! 247: for (ifp = ifnet; ifp; ifp = ifp->if_next) { ! 248: if (bcmp(ifp->if_name, name, (unsigned)(cp - name))) ! 249: continue; ! 250: if (unit == ifp->if_unit) ! 251: break; ! 252: } ! 253: return (ifp); ! 254: } ! 255: ! 256: /* ! 257: * Interface ioctls. ! 258: */ ! 259: ifioctl(so, cmd, data) ! 260: struct socket *so; ! 261: int cmd; ! 262: caddr_t data; ! 263: { ! 264: register struct ifnet *ifp; ! 265: register struct ifreq *ifr; ! 266: ! 267: switch (cmd) { ! 268: ! 269: case SIOCGIFCONF: ! 270: return (ifconf(cmd, data)); ! 271: ! 272: #if defined(INET) && NETHER > 0 ! 273: case SIOCSARP: ! 274: case SIOCDARP: ! 275: if (!suser()) ! 276: return (u.u_error); ! 277: /* FALL THROUGH */ ! 278: case SIOCGARP: ! 279: return (arpioctl(cmd, data)); ! 280: #endif ! 281: } ! 282: ifr = (struct ifreq *)data; ! 283: ifp = ifunit(ifr->ifr_name); ! 284: if (ifp == 0) ! 285: return (ENXIO); ! 286: switch (cmd) { ! 287: ! 288: case SIOCGIFFLAGS: ! 289: ifr->ifr_flags = ifp->if_flags; ! 290: break; ! 291: ! 292: case SIOCGIFMETRIC: ! 293: ifr->ifr_metric = ifp->if_metric; ! 294: break; ! 295: ! 296: case SIOCSIFFLAGS: ! 297: if (!suser()) ! 298: return (u.u_error); ! 299: if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { ! 300: int s = splimp(); ! 301: if_down(ifp); ! 302: splx(s); ! 303: } ! 304: ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | ! 305: (ifr->ifr_flags &~ IFF_CANTCHANGE); ! 306: if (ifp->if_ioctl) ! 307: (void) (*ifp->if_ioctl)(ifp, cmd, data); ! 308: break; ! 309: ! 310: case SIOCSIFMETRIC: ! 311: if (!suser()) ! 312: return (u.u_error); ! 313: ifp->if_metric = ifr->ifr_metric; ! 314: break; ! 315: ! 316: default: ! 317: if (so->so_proto == 0) ! 318: return (EOPNOTSUPP); ! 319: return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, ! 320: cmd, data, ifp)); ! 321: } ! 322: return (0); ! 323: } ! 324: ! 325: /* ! 326: * Return interface configuration ! 327: * of system. List may be used ! 328: * in later ioctl's (above) to get ! 329: * other information. ! 330: */ ! 331: /*ARGSUSED*/ ! 332: ifconf(cmd, data) ! 333: int cmd; ! 334: caddr_t data; ! 335: { ! 336: register struct ifconf *ifc = (struct ifconf *)data; ! 337: register struct ifnet *ifp = ifnet; ! 338: register struct ifaddr *ifa; ! 339: register char *cp, *ep; ! 340: struct ifreq ifr, *ifrp; ! 341: int space = ifc->ifc_len, error = 0; ! 342: ! 343: ifrp = ifc->ifc_req; ! 344: ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2; ! 345: for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { ! 346: bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2); ! 347: for (cp = ifr.ifr_name; cp < ep && *cp; cp++) ! 348: ; ! 349: *cp++ = '0' + ifp->if_unit; *cp = '\0'; ! 350: if ((ifa = ifp->if_addrlist) == 0) { ! 351: bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); ! 352: error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); ! 353: if (error) ! 354: break; ! 355: space -= sizeof (ifr), ifrp++; ! 356: } else ! 357: for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { ! 358: ifr.ifr_addr = ifa->ifa_addr; ! 359: error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); ! 360: if (error) ! 361: break; ! 362: space -= sizeof (ifr), ifrp++; ! 363: } ! 364: } ! 365: ifc->ifc_len -= space; ! 366: return (error); ! 367: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.