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