📄 if.c
字号:
/* $Id: if.c,v 1.3 1998/12/28 14:13:11 nigel Exp $ *//* * Copyright (c) 1980, 1986 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)if.c 7.14 (Berkeley) 4/20/91 */#include "param.h"#include "mbuf.h"#include "systm.h"#include "socket.h"#include "socketvar.h"#include "protosw.h"#include "proc.h"#include "kernel.h"#include "ioctl.h"#include "if.h"#include "af.h"#include "if_dl.h"#include "if_types.h"#include "ether.h"#ifdef PROMconst int ifqmaxlen = IFQ_MAXLEN;#elseint ifqmaxlen = IFQ_MAXLEN;#endif/* * Network interface utility routines. * * Routines with ifa_ifwith* names take sockaddr *'s as * parameters. */ifinit(){ register struct ifnet *ifp; for (ifp = ifnet; ifp; ifp = ifp->if_next) if (ifp->if_snd.ifq_maxlen == 0) ifp->if_snd.ifq_maxlen = ifqmaxlen; if_slowtimo();}#if defined(vax) || defined(PROM)/* * Call each interface on a Unibus/PROM reset. */ifubareset(uban) int uban;{ register struct ifnet *ifp; for (ifp = ifnet; ifp; ifp = ifp->if_next) if (ifp->if_reset) (*ifp->if_reset)(ifp->if_unit, uban);}#endifint if_index;struct ifaddr **ifnet_addrs;static char *sprint_d();/* * Attach an interface to the * list of "active" interfaces. */if_attach(ifp) struct ifnet *ifp;{ unsigned socksize, ifasize; int namelen, unitlen; char workbuf[12], *unitname; register struct ifnet **p = &ifnet; register struct sockaddr_dl *sdl; register struct ifaddr *ifa;#ifdef NO_DATA static int if_indexlim;#else static int if_indexlim = 8;#endif extern link_rtrequest();#if NETHER > 0 extern ether_output();#endif while (*p) p = &((*p)->if_next); *p = ifp; ifp->if_index = ++if_index;#ifdef NO_DATA if (ifnet_addrs == 0) if_indexlim = 8;#endif if (ifnet_addrs == 0 || if_index >= if_indexlim) { unsigned n = (if_indexlim <<= 1) * sizeof(ifa); struct ifaddr **q = (struct ifaddr **) malloc(n, M_IFADDR, M_WAITOK); if (ifnet_addrs) { bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2); free((caddr_t)ifnet_addrs, M_IFADDR); } ifnet_addrs = q; }#if NETHER > 0 /* XXX -- Temporary fix before changing 10 ethernet drivers */ if (ifp->if_output == ether_output) { ifp->if_type = IFT_ETHER; ifp->if_addrlen = 6; ifp->if_hdrlen = 14; }#endif /* * create a Link Level name for this device */ unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf)); namelen = strlen(ifp->if_name); unitlen = strlen(unitname);#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m)) socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) + unitlen + namelen + ifp->if_addrlen;#define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1))) socksize = ROUNDUP(socksize); if (socksize < sizeof(*sdl)) socksize = sizeof(*sdl); ifasize = sizeof(*ifa) + 2 * socksize; ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK); if (ifa == 0) return; ifnet_addrs[if_index - 1] = ifa; bzero((caddr_t)ifa, ifasize); sdl = (struct sockaddr_dl *)(ifa + 1); ifa->ifa_addr = (struct sockaddr *)sdl; ifa->ifa_ifp = ifp; sdl->sdl_len = socksize; sdl->sdl_family = AF_LINK; bcopy(ifp->if_name, sdl->sdl_data, namelen); bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen); sdl->sdl_nlen = (namelen += unitlen); sdl->sdl_index = ifp->if_index; sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl); ifa->ifa_netmask = (struct sockaddr *)sdl; sdl->sdl_len = socksize - ifp->if_addrlen; while (namelen != 0) sdl->sdl_data[--namelen] = 0xff; ifa->ifa_next = ifp->if_addrlist; ifa->ifa_rtrequest = link_rtrequest; ifp->if_addrlist = ifa;}/* * Update the link-layer address and/or type for an existing interface. * We assume that ifp->if_hdrlen is correct, and that the sockaddr_dl * created in if_attach is large enough (i.e., if_hdrlen will not increase). */voidif_newaddr(ifp, type, laddr) register struct ifnet *ifp; int type; caddr_t laddr;{ register struct ifaddr *ifa; register struct sockaddr_dl *sdl; for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && sdl->sdl_family == AF_LINK) { sdl->sdl_type = type; sdl->sdl_alen = ifp->if_addrlen; bcopy(laddr, LLADDR(sdl), ifp->if_addrlen); break; }}/* * Locate an interface based on a complete address. *//*ARGSUSED*/struct ifaddr *ifa_ifwithaddr(addr) register struct sockaddr *addr;{ register struct ifnet *ifp; register struct ifaddr *ifa;#define equal(a1, a2) \ (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0) for (ifp = ifnet; ifp; ifp = ifp->if_next) for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family != addr->sa_family) continue; if (equal(addr, ifa->ifa_addr)) return (ifa); if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr && equal(ifa->ifa_broadaddr, addr)) return (ifa); } return ((struct ifaddr *)0);}/* * Locate the point to point interface with a given destination address. *//*ARGSUSED*/struct ifaddr *ifa_ifwithdstaddr(addr) register struct sockaddr *addr;{ register struct ifnet *ifp; register struct ifaddr *ifa; for (ifp = ifnet; ifp; ifp = ifp->if_next) if (ifp->if_flags & IFF_POINTOPOINT) for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { if (ifa->ifa_addr->sa_family != addr->sa_family) continue; if (equal(addr, ifa->ifa_dstaddr)) return (ifa); } return ((struct ifaddr *)0);}/* * Find an interface on a specific network. If many, choice * is first found. */struct ifaddr *ifa_ifwithnet(addr) struct sockaddr *addr;{ register struct ifnet *ifp; register struct ifaddr *ifa; u_int af = addr->sa_family; if (af >= AF_MAX) return (0); if (af == AF_LINK) { register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr; if (sdl->sdl_index && sdl->sdl_index <= if_index) return (ifnet_addrs[sdl->sdl_index - 1]); } for (ifp = ifnet; ifp; ifp = ifp->if_next) for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) { register char *cp, *cp2, *cp3; register char *cplim; if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0) 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 ((struct ifaddr *)0);}/* * 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; ifp; ifp = ifp->if_next) for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) if (ifa->ifa_addr->sa_family == af) return (ifa); return ((struct ifaddr *)0);}/* * 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 (0); for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -