📄 if.c
字号:
if (ifa_maybe == 0 || rn_refines((caddr_t)ifa->ifa_netmask, (caddr_t)ifa_maybe->ifa_netmask)) ifa_maybe = ifa; } return (ifa_maybe);}/* * Find an interface using a specific address family */struct ifaddr *ifa_ifwithaf(af) register int af;{ register struct ifnet *ifp; register struct ifaddr *ifa; for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) if (ifa->ifa_addr->sa_family == af) return (ifa); return (NULL);}/* * Find an interface address specific to an interface best matching * a given address. */struct ifaddr *ifaof_ifpforaddr(addr, ifp) struct sockaddr *addr; register struct ifnet *ifp;{ register struct ifaddr *ifa; register char *cp, *cp2, *cp3; register char *cplim; struct ifaddr *ifa_maybe = 0; u_int af = addr->sa_family; if (af >= AF_MAX) return (NULL); for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) { if (ifa->ifa_addr->sa_family != af) continue; ifa_maybe = ifa; if (ifa->ifa_netmask == 0) { if (equal(addr, ifa->ifa_addr) || (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))) return (ifa); continue; } cp = addr->sa_data; cp2 = ifa->ifa_addr->sa_data; cp3 = ifa->ifa_netmask->sa_data; cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask; for (; cp3 < cplim; cp3++) if ((*cp++ ^ *cp2++) & *cp3) break; if (cp3 == cplim) return (ifa); } return (ifa_maybe);}/* * Default action when installing a route with a Link Level gateway. * Lookup an appropriate real ifa to point to. * This should be moved to /sys/net/link.c eventually. */voidlink_rtrequest(cmd, rt, sa) int cmd; register struct rtentry *rt; struct sockaddr *sa;{ register struct ifaddr *ifa; struct sockaddr *dst; struct ifnet *ifp; if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) || ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0)) return; if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) { IFAFREE(rt->rt_ifa); rt->rt_ifa = ifa; ifa->ifa_refcnt++; if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) ifa->ifa_rtrequest(cmd, rt, sa); }}/* * Mark an interface down and notify protocols of * the transition. * NOTE: must be called at splsoftnet or equivalent. */voidif_down(ifp) register struct ifnet *ifp;{ register struct ifaddr *ifa; ifp->if_flags &= ~IFF_UP; for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) pfctlinput(PRC_IFDOWN, ifa->ifa_addr); if_qflush(&ifp->if_snd); rt_ifmsg(ifp);}/* * Mark an interface up and notify protocols of * the transition. * NOTE: must be called at splsoftnet or equivalent. */voidif_up(ifp) register struct ifnet *ifp;{#ifdef notyet register struct ifaddr *ifa;#endif ifp->if_flags |= IFF_UP;#ifdef notyet /* this has no effect on IP, and will kill all ISO connections XXX */ for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) pfctlinput(PRC_IFUP, ifa->ifa_addr);#endif rt_ifmsg(ifp);#ifdef INET6 in6_if_up(ifp);#endif}/* * Flush an interface queue. */voidif_qflush(ifq) register struct ifqueue *ifq;{ register struct mbuf *m, *n; n = ifq->ifq_head; while ((m = n) != NULL) { n = m->m_act; m_freem(m); } ifq->ifq_head = 0; ifq->ifq_tail = 0; ifq->ifq_len = 0;}/* * Handle interface watchdog timer routines. Called * from softclock, we decrement timers (if set) and * call the appropriate interface routine on expiration. */voidif_slowtimo(arg) void *arg;{ register struct ifnet *ifp; int s = splimp(); for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) { if (ifp->if_timer == 0 || --ifp->if_timer) continue; if (ifp->if_watchdog) (*ifp->if_watchdog)(ifp); } splx(s); timeout(if_slowtimo, NULL, hz / IFNET_SLOWHZ);}/* * Map interface name to * interface structure pointer. */struct ifnet *ifunit(name) register char *name;{ register struct ifnet *ifp; for (ifp = ifnet.tqh_first; ifp != 0; ifp = ifp->if_list.tqe_next) if (strcmp(ifp->if_xname, name) == 0) return (ifp); return (NULL);}/* * Map interface name in a sockaddr_dl to * interface structure pointer. */struct ifnet *if_withname(sa) struct sockaddr *sa;{ char ifname[IFNAMSIZ+1]; struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; if ( (sa->sa_family != AF_LINK) || (sdl->sdl_nlen == 0) || (sdl->sdl_nlen > IFNAMSIZ) ) return NULL; /* * ifunit wants a null-terminated name. It may not be null-terminated * in the sockaddr. We don't want to change the caller's sockaddr, * and there might not be room to put the trailing null anyway, so we * make a local copy that we know we can null terminate safely. */ bcopy(sdl->sdl_data, ifname, sdl->sdl_nlen); ifname[sdl->sdl_nlen] = '\0'; return ifunit(ifname);}/* * Interface ioctls. */intifioctl(so, cmd, data, p) struct socket *so; u_long cmd; caddr_t data; struct proc *p;{ register struct ifnet *ifp; register struct ifreq *ifr; int error = 0; short oif_flags; switch (cmd) { case SIOCGIFCONF: case OSIOCGIFCONF: return (ifconf(cmd, data)); } ifr = (struct ifreq *)data; ifp = ifunit(ifr->ifr_name); if (ifp == 0) return (ENXIO); oif_flags = ifp->if_flags; switch (cmd) { case SIOCGIFFLAGS: ifr->ifr_flags = ifp->if_flags; break; case SIOCGIFMETRIC: ifr->ifr_metric = ifp->if_metric; break; case SIOCGIFDATA: error = copyout((caddr_t)&ifp->if_data, ifr->ifr_data, sizeof(ifp->if_data)); break; case SIOCSIFFLAGS:#ifndef __ECOS if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) return (error);#endif if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) { int s = splimp(); if_down(ifp); splx(s); } if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) { int s = splimp(); if_up(ifp); splx(s); } ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | (ifr->ifr_flags &~ IFF_CANTCHANGE); if (ifp->if_ioctl) (void) (*ifp->if_ioctl)(ifp, cmd, data); break; case SIOCSIFMETRIC:#ifndef __ECOS if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) return (error);#endif ifp->if_metric = ifr->ifr_metric; break; case SIOCADDMULTI: case SIOCDELMULTI: case SIOCSIFMEDIA:#ifndef __ECOS if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) return (error);#endif /* FALLTHROUGH */#ifdef SIOCGIFSTATS case SIOCGIFSTATS:#ifdef SIOCGIFSTATSUD case SIOCGIFSTATSUD:#endif#endif // SIOCGIFSTATS case SIOCGIFMEDIA: if (ifp->if_ioctl == 0) return (EOPNOTSUPP); error = (*ifp->if_ioctl)(ifp, cmd, data); break; default: if (so->so_proto == 0) return (EOPNOTSUPP);#if !defined(COMPAT_43) && !defined(COMPAT_LINUX) && !defined(COMPAT_SVR4) error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, (struct mbuf *) cmd, (struct mbuf *) data, (struct mbuf *) ifp));#else { u_long ocmd = cmd; switch (cmd) { case SIOCSIFADDR: case SIOCSIFDSTADDR: case SIOCSIFBRDADDR: case SIOCSIFNETMASK:#if BYTE_ORDER != BIG_ENDIAN if (ifr->ifr_addr.sa_family == 0 && ifr->ifr_addr.sa_len < 16) { ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len; ifr->ifr_addr.sa_len = 16; }#else if (ifr->ifr_addr.sa_len == 0) ifr->ifr_addr.sa_len = 16;#endif break; case OSIOCGIFADDR: cmd = SIOCGIFADDR; break; case OSIOCGIFDSTADDR: cmd = SIOCGIFDSTADDR; break; case OSIOCGIFBRDADDR: cmd = SIOCGIFBRDADDR; break; case OSIOCGIFNETMASK: cmd = SIOCGIFNETMASK; } error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, (struct mbuf *) cmd, (struct mbuf *) data, (struct mbuf *) ifp)); switch (ocmd) { case OSIOCGIFADDR: case OSIOCGIFDSTADDR: case OSIOCGIFBRDADDR: case OSIOCGIFNETMASK: *(u_int16_t *)&ifr->ifr_addr = ifr->ifr_addr.sa_family; } }#endif break; } if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {#ifdef INET6 if ((ifp->if_flags & IFF_UP) != 0) { int s = splimp(); in6_if_up(ifp); splx(s); }#endif } return (error);}/* * Return interface configuration * of system. List may be used * in later ioctl's (above) to get * other information. *//*ARGSUSED*/intifconf(cmd, data) u_long cmd; caddr_t data;{ register struct ifconf *ifc = (struct ifconf *)data; register struct ifnet *ifp; register struct ifaddr *ifa; struct ifreq ifr, *ifrp; int space = ifc->ifc_len, error = 0; /* If ifc->ifc_len is 0, fill it in with the needed size and return. */ if (space == 0) { for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next) { register struct sockaddr *sa; if ((ifa = ifp->if_addrlist.tqh_first) == 0) space += sizeof (ifr); else for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) { sa = ifa->ifa_addr;#if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4) if (cmd != OSIOCGIFCONF)#endif if (sa->sa_len > sizeof(*sa)) space += sa->sa_len - sizeof (*sa); space += sizeof (ifr); } } ifc->ifc_len = space; return(0); } ifrp = ifc->ifc_req; for (ifp = ifnet.tqh_first; space >= sizeof (ifr) && ifp != 0; ifp = ifp->if_list.tqe_next) { bcopy(ifp->if_xname, ifr.ifr_name, IFNAMSIZ); if ((ifa = ifp->if_addrlist.tqh_first) == 0) { bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof(ifr)); if (error) break; space -= sizeof (ifr), ifrp++; } else for (; space >= sizeof (ifr) && ifa != 0; ifa = ifa->ifa_list.tqe_next) { register struct sockaddr *sa = ifa->ifa_addr;#if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4) if (cmd == OSIOCGIFCONF) { struct osockaddr *osa = (struct osockaddr *)&ifr.ifr_addr; ifr.ifr_addr = *sa; osa->sa_family = sa->sa_family; error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); ifrp++; } else#endif if (sa->sa_len <= sizeof(*sa)) { ifr.ifr_addr = *sa; error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr)); ifrp++; } else { space -= sa->sa_len - sizeof(*sa); if (space < sizeof (ifr)) break; error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr.ifr_name)); if (error == 0) error = copyout((caddr_t)sa, (caddr_t)&ifrp->ifr_addr, sa->sa_len); ifrp = (struct ifreq *)(sa->sa_len + (caddr_t)&ifrp->ifr_addr); } if (error) break; space -= sizeof (ifr); } } ifc->ifc_len -= space; return (error);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -