⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1980, 1986, 1993 *	The 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	8.3 (Berkeley) 1/4/94 * $Id: if.c,v 1.3 2002/01/31 21:40:46 joel Exp $ */#include <sys/param.h>#include <sys/queue.h>#include <sys/mbuf.h>#include <sys/systm.h>#include <sys/proc.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/protosw.h>#include <sys/kernel.h>#include <sys/ioctl.h>#include <sys/errno.h>#include <sys/syslog.h>#include <sys/sysctl.h>#include <net/if.h>#include <net/if_dl.h>#include <net/if_types.h>#include <net/radix.h>/* * System initialization */static int ifconf __P((int, caddr_t));       void ifinit __P((void *));static void if_qflush __P((struct ifqueue *));static void if_slowtimo __P((void *));static void link_rtrequest __P((int, struct rtentry *, struct sockaddr *));SYSINIT(interfaces, SI_SUB_PROTO_IF, SI_ORDER_FIRST, ifinit, NULL)int	ifqmaxlen = IFQ_MAXLEN;struct	ifnet *ifnet;/* * Network interface utility routines. * * Routines with ifa_ifwith* names take sockaddr *'s as * parameters. * * This routine assumes that it will be called at splimp() or higher. *//* ARGSUSED*/voidifinit(dummy)	void *dummy;{	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(0);}int if_index = 0;struct ifaddr **ifnet_addrs;/* * Attach an interface to the * list of "active" interfaces. */voidif_attach(ifp)	struct ifnet *ifp;{	unsigned socksize, ifasize;	int namelen, masklen;	char workbuf[64];	register struct ifnet **p = &ifnet;	register struct sockaddr_dl *sdl;	register struct ifaddr *ifa;	static int if_indexlim = 8;	while (*p)		p = &((*p)->if_next);	*p = ifp;	ifp->if_index = ++if_index;	microtime(&ifp->if_lastchange);	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);		bzero((caddr_t)q, n);		if (ifnet_addrs) {			bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);			free((caddr_t)ifnet_addrs, M_IFADDR);		}		ifnet_addrs = q;	}	/*	 * create a Link Level name for this device	 */	namelen = sprintf(workbuf, "%s%d", ifp->if_name, ifp->if_unit);#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))	masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + namelen;	socksize = masklen + 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) {		bzero((caddr_t)ifa, ifasize);		sdl = (struct sockaddr_dl *)(ifa + 1);		sdl->sdl_len = socksize;		sdl->sdl_family = AF_LINK;		bcopy(workbuf, sdl->sdl_data, namelen);		sdl->sdl_nlen = namelen;		sdl->sdl_index = ifp->if_index;		sdl->sdl_type = ifp->if_type;		ifnet_addrs[if_index - 1] = ifa;		ifa->ifa_ifp = ifp;		ifa->ifa_next = ifp->if_addrlist;		ifa->ifa_rtrequest = link_rtrequest;		ifp->if_addrlist = ifa;		ifa->ifa_addr = (struct sockaddr *)sdl;		sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);		ifa->ifa_netmask = (struct sockaddr *)sdl;		sdl->sdl_len = masklen;		while (namelen != 0)			sdl->sdl_data[--namelen] = 0xff;	}}/* * 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 (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr))				return (ifa);	}	return ((struct ifaddr *)0);}/* * Find an interface on a specific network.  If many, choice * is most specific found. */struct ifaddr *ifa_ifwithnet(addr)	struct sockaddr *addr;{	register struct ifnet *ifp;	register struct ifaddr *ifa;	struct ifaddr *ifa_maybe = (struct ifaddr *) 0;	u_int af = addr->sa_family;	char *addr_data = addr->sa_data, *cplim;	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;			if (ifa->ifa_addr->sa_family != af)				next: continue;			if (ifp->if_flags & IFF_POINTOPOINT) {				if (ifa->ifa_dstaddr != 0				    && equal(addr, ifa->ifa_dstaddr)) 					return (ifa);			} else {				/*				 * if we have a special address handler,				 * then use it instead of the generic one.				 */	          		if (ifa->ifa_claim_addr) {					if ((*ifa->ifa_claim_addr)(ifa, addr)) {						return (ifa);					} else {						continue;					}				}				/*				 * Scan all the bits in the ifa's address.				 * If a bit dissagrees with what we are				 * looking for, mask it with the netmask				 * to see if it really matters.				 * (A byte at a time)				 */				if (ifa->ifa_netmask == 0)					continue;				cp = addr_data;				cp2 = ifa->ifa_addr->sa_data;				cp3 = ifa->ifa_netmask->sa_data;				cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;				while (cp3 < cplim)					if ((*cp++ ^ *cp2++) & *cp3++)						goto next;				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 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;		if (ifa_maybe == 0)			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;		}		if (ifp->if_flags & IFF_POINTOPOINT) {			if (equal(addr, ifa->ifa_dstaddr))				return (ifa);		} else {			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);}#include <net/route.h>/* * 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. */static 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;	ifa = ifaof_ifpforaddr(dst, ifp);	if (ifa) {		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 splnet or eqivalent. */voidif_down(ifp)	register struct ifnet *ifp;{	register struct ifaddr *ifa;	ifp->if_flags &= ~IFF_UP;	microtime(&ifp->if_lastchange);	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_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 splnet or eqivalent. */voidif_up(ifp)	register struct ifnet *ifp;{	ifp->if_flags |= IFF_UP;	microtime(&ifp->if_lastchange);#ifdef notyet	register struct ifaddr *ifa;	/* this has no effect on IP, and will kill all iso connections XXX */	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)		pfctlinput(PRC_IFUP, ifa->ifa_addr);#endif	rt_ifmsg(ifp);}/* * Flush an interface queue.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -