📄 if.c
字号:
* Mark an interface down and notify protocols of * the transition. Change routes. * NOTE: must be called at splnet or eqivalent. */if_down(ifp) register struct ifnet *ifp;{ register struct ifaddr *ifa; ifp->if_flags &= ~IFF_UP; for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { pfctlinput(PRC_ROUTEDEAD, (caddr_t)&ifa->ifa_addr); }}/* * Handle interface watchdog timer routines. Called * from softclock, we decrement timers (if set) and * call the appropriate interface routine on expiration. */if_slowtimo(){ register struct ifnet *ifp; int saveaffinity; for (ifp = ifnet; ifp; ifp = ifp->if_next) { if (ifp->if_timer == 0 || --ifp->if_timer) continue; if (ifp->if_watchdog){ CALL_TO_NONSMP_DRIVER( (*ifp), saveaffinity); (*ifp->if_watchdog)(ifp->if_unit); RETURN_FROM_NONSMP_DRIVER( (*ifp), saveaffinity); } } timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ);}/* * Map interface name to * interface structure pointer. */struct ifnet *ifunit(name) register char *name;{ register char *cp, *cp2; register struct ifnet *ifp; int unit; for (cp = name; cp < name + IFNAMSIZ && *cp; cp++) if (*cp >= '0' && *cp <= '9') break; if (*cp == '\0' || cp == name + IFNAMSIZ) return ((struct ifnet *)0); for (unit = 0, cp2 = cp; cp2 < name + IFNAMSIZ && *cp2; cp2++) unit = unit * 10 + (*cp2 - '0'); for (ifp = ifnet; ifp; ifp = ifp->if_next) { if ((unsigned)(cp - name) != strlen(ifp->if_name)) continue; /* * Following lines for se/ln compatibility */ if (((unsigned)(cp - name) == 2) && (!bcmp(name, "se", 2))) { if (bcmp(ifp->if_name, "ln", 2)) continue; } else { if (bcmp(ifp->if_name, name, (unsigned)(cp - name))) continue; } if (unit == ifp->if_unit) break; } return (ifp);}/* * From an ifp, generate the name of an interface. */ifname(ifp, name) struct ifnet *ifp; char *name;{ register int i = 0, unit = ifp->if_unit; char digits[6], *p = ifp->if_name; /* * Copy the interfaces base name (assume everythings ok). */ while (*p) *name++ = *p++; /* * Calculate the unit's digits in reverse order. */ do { digits[i++] = (unit % 10) + '0'; unit = unit/10; } while (unit); /* * Append the digits in reverse order. This will * result in a correct number. */ while (i--) *name++ = digits[i]; *name = '\0';}/* * Interface ioctls. */ifioctl(so, cmd, data) struct socket *so; int cmd; caddr_t data;{ register struct ifnet *ifp; register struct ifreq *ifr; int saveaffinity; int error; int s; int owner = 0; /* SMP */ switch (cmd) { case SIOCSCREENON: case SIOCSCREEN: case SIOCSCREENSTATS: return(screen_control(so, cmd, data, (struct ifnet *)0)); case SIOCGIFCONF: if (smp_owner(&so->lk_socket)){ smp_unlock(&so->lk_socket); owner=1; } error = ifconf(cmd,data); if (owner) { SO_LOCK(so); } return (error);#if defined(INET) && ( NETHER > 0 || NFDDI > 0) case SIOCSARP: case SIOCDARP: if (!suser()) return (u.u_error); /* FALL THROUGH */ case SIOCGARP: return (arpioctl(cmd, data));#endif } ifr = (struct ifreq *)data; ifp = ifunit(ifr->ifr_name); if (ifp == 0) return (ENXIO); switch (cmd) { case SIOCGIFFLAGS: ifr->ifr_flags = ifp->if_flags; break; case SIOCGIFMETRIC: ifr->ifr_metric = ifp->if_metric; break; case SIOCSIFFLAGS: if (!suser()) return (u.u_error); if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { s = splnet(); /* * must obey lock ordering */ if (smp_owner(&so->lk_socket)){ so->ref = 32; owner = 1; smp_unlock(&so->lk_socket); } if_down(ifp); if (owner){ smp_lock(&so->lk_socket,LK_RETRY); so->ref = 0; owner = 0; } splx(s); } if ((ifr->ifr_flags & IFF_802HDR) && (ifp->if_type == IFT_ETHER)) { s = splnet(); ifp->if_type = IFT_ISO88023; ifp->if_flags &= (IFF_NOTRAILERS|IFF_802HDR); ifp->if_mtu = ETHERMTU - sizeof (struct llc); splx(s); } ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | (ifr->ifr_flags &~ IFF_CANTCHANGE); /* Note that we don't do an affinity flag check here as * an optimization where if set, we could go to the driver * without unlocking. The reason we do not do that here, * is that so far, the network drivers can sleep for DECnet. * When we eleminate sleeps in the drivers, we can delete the * owner check and unlocks here. */ if (smp_owner(&so->lk_socket)){ so->ref = 8; owner = 1; smp_unlock(&so->lk_socket); } if (ifp->if_ioctl){ CALL_TO_NONSMP_DRIVER( (*ifp), saveaffinity); (void) (*ifp->if_ioctl)(ifp, cmd, data); RETURN_FROM_NONSMP_DRIVER( (*ifp), saveaffinity); } if (owner){ smp_lock(&so->lk_socket,LK_RETRY); so->ref = 0; owner = 0; } break; case SIOCSIFMETRIC: if (!suser()) return (u.u_error); ifp->if_metric = ifr->ifr_metric; break; case SIOCENABLBACK: case SIOCDISABLBACK: case SIOCSPHYSADDR: case SIOCDELMULTI: case SIOCADDMULTI: case SIOCRDZCTRS: case SIOCIFRESET: case SIOCEEUPDATE: if(!suser()) return(u.u_error); /* FALL THROUGH */ case SIOCRDCTRS: case SIOCRPHYSADDR: if (ifp->if_ioctl == 0) return (EOPNOTSUPP); if (smp_owner(&so->lk_socket)){ owner = 1; so->ref = 8; smp_unlock(&so->lk_socket); } CALL_TO_NONSMP_DRIVER( (*ifp), saveaffinity); error = (*ifp->if_ioctl)(ifp, cmd, data); RETURN_FROM_NONSMP_DRIVER( (*ifp), saveaffinity); if (owner){ smp_lock(&so->lk_socket,LK_RETRY); so->ref = 0; owner = 0; } return(error); case SIOCARPREQ: if (suser()) if (nINET == 1) return (arpwhohas(ifp,ifr->ifr_addr.sa_data)); else return (ENETDOWN); else return (EACCES); /* * protocol specific ioctls that must deal with the interface * are handled in the default case by the protocol specific * usrreq routine. */ default: if (so->so_proto == 0) { mprintf("ifioctl: no socket proto\n"); return (EOPNOTSUPP); } return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, cmd, data, ifp)); } return (0);}/* * Return interface configuration * of system. List may be used * in later ioctl's (above) to get * other information. *//*ARGSUSED*/ifconf(cmd, data) int cmd; caddr_t data;{ register struct ifconf *ifc = (struct ifconf *)data; register struct ifnet *ifp = ifnet; register struct ifaddr *ifa; struct ifreq ifr, *ifrp; struct ifreq *u_sptr, *u_tmp ; int space = ifc->ifc_len; int space_tmp = ifc->ifc_len; int s; int error; KM_ALLOC( u_sptr, struct ifreq *, space, KM_TEMP, KM_CLEAR); u_tmp = u_sptr; ifrp = ifc->ifc_req; for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) { ifname(ifp, ifr.ifr_name); if ((ifa = ifp->if_addrlist) == 0) { bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); /* bcopy((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); */ bcopy((caddr_t)&ifr, (caddr_t)u_sptr, sizeof (ifr)); space -= sizeof (ifr), u_sptr++; } else for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) { ifr.ifr_addr = ifa->ifa_addr; bcopy((caddr_t)&ifr, (caddr_t)u_sptr, sizeof (ifr)); space -= sizeof (ifr), u_sptr++; } } error =copyout((caddr_t)u_tmp, (caddr_t)ifrp, ifc->ifc_len-space); KM_FREE(u_tmp, KM_TEMP); ifc->ifc_len -= space; return (error);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -