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

📄 if.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 3 页
字号:
//==========================================================================////      src/sys/net/if.c////==========================================================================//####BSDCOPYRIGHTBEGIN####//// -------------------------------------------//// Portions of this software may have been derived from OpenBSD, // FreeBSD or other sources, and are covered by the appropriate// copyright disclaimers included herein.//// Portions created by Red Hat are// Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.//// -------------------------------------------////####BSDCOPYRIGHTEND####//==========================================================================/* * 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 * $FreeBSD: src/sys/net/if.c,v 1.85.2.9 2001/07/24 19:10:17 brooks Exp $ */#include <sys/param.h>#include <sys/malloc.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/socketvar.h>#include <sys/protosw.h>#include <sys/sockio.h>#include <sys/sysctl.h>#include <net/if.h>#include <net/if_arp.h>#include <net/if_dl.h>#include <net/if_types.h>#include <net/radix.h>#include <net/route.h>#if defined(INET) || defined(INET6)/*XXX*/#include <netinet/in.h>#include <netinet/in_var.h>#ifdef INET6#include <netinet6/in6_var.h>#include <netinet6/in6_ifattach.h>#endif#endif/* * System initialization */static int ifconf __P((u_long, caddr_t));static 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 *));static int  if_rtdel __P((struct radix_node *, void *));SYSINIT(interfaces, SI_SUB_PROTO_IF, SI_ORDER_FIRST, ifinit, NULL)int	ifqmaxlen = IFQ_MAXLEN;struct	ifnethead ifnet;	/* depend on static init XXX */#ifdef INET6/* * XXX: declare here to avoid to include many inet6 related files.. * should be more generalized? */extern void	nd6_setmtu __P((struct ifnet *));#endifstruct if_clone *if_clone_lookup __P((const char *, int *));int if_clone_list __P((struct if_clonereq *));LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);int if_cloners_count;/* * Network interface utility routines. * * Routines with ifa_ifwith* names take sockaddr *'s as * parameters. *//* ARGSUSED*/voidifinit(dummy)	void *dummy;{#ifdef DEBUG_IFINIT	struct ifnet *ifp;	int s;	s = splimp();	for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next) {            log(LOG_INIT, "IFP: %p, next: %p\n", ifp, ifp->if_link.tqe_next);        }	splx(s);#endif	if_slowtimo(0);}int if_index = 0;struct ifaddr **ifnet_addrs;struct ifnet **ifindex2ifnet = NULL;char *_sa(struct ifaddr *ifa){    struct sockaddr *sa = ifa->ifa_addr;    static char _unknown[128];    switch (sa->sa_family) {    case AF_INET:        return inet_ntoa((struct in_addr)((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr);#ifdef INET6    case AF_INET6:        diag_sprintf(_unknown, "%s/%d", ip6_sprintf(IFA_IN6(ifa)),                      in6_mask2len(&((struct in6_ifaddr *)ifa)->ia_prefixmask.sin6_addr, NULL));        return _unknown;#endif    case AF_LINK:        diag_sprintf(_unknown, "<<%p>>", sa);        return _unknown;    default:        diag_sprintf(_unknown, "[%d]", sa->sa_family);        return _unknown;    }}void_show_ifp(struct ifnet *ifp){    log_(LOG_ADDR) {        struct ifaddr *ifa;        diag_printf("IFP: %p (%s%d)\n", ifp, ifp->if_name, ifp->if_unit);        TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {            diag_printf("IFA: %p - %s\n", ifa, _sa(ifa));        }    }}/* * 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 sockaddr_dl *sdl;	register struct ifaddr *ifa;	static int if_indexlim = 8;	static int inited;	if (!inited) {		TAILQ_INIT(&ifnet);		inited = 1;	}        if (ifp->if_snd.ifq_maxlen == 0) {            ifp->if_snd.ifq_maxlen = ifqmaxlen;        }	TAILQ_INSERT_TAIL(&ifnet, ifp, if_link);	ifp->if_index = ++if_index;	/*	 * XXX -	 * The old code would work if the interface passed a pre-existing	 * chain of ifaddrs to this code.  We don't trust our callers to	 * properly initialize the tailq, however, so we no longer allow	 * this unlikely case.	 */	TAILQ_INIT(&ifp->if_addrhead);                log_(LOG_ADDR) {            diag_printf("%s.%d - After initialize list %p\n",                           __FUNCTION__, __LINE__,                                                 &ifp->if_addrlist);                                         _show_ifp(ifp);                                             }	TAILQ_INIT(&ifp->if_prefixhead);	LIST_INIT(&ifp->if_multiaddrs);	getmicrotime(&ifp->if_lastchange);	if (ifnet_addrs == 0 || if_index >= if_indexlim) {		unsigned n = (if_indexlim <<= 1) * sizeof(ifa);		caddr_t q = malloc(n, M_IFADDR, M_WAITOK);		bzero(q, n);		if (ifnet_addrs) {			bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);			free((caddr_t)ifnet_addrs, M_IFADDR);		}		ifnet_addrs = (struct ifaddr **)q;		/* grow ifindex2ifnet */		n = if_indexlim * sizeof(struct ifnet *);		q = malloc(n, M_IFADDR, M_WAITOK);		bzero(q, n);		if (ifindex2ifnet) {			bcopy((caddr_t)ifindex2ifnet, q, n/2);			free((caddr_t)ifindex2ifnet, M_IFADDR);		}		ifindex2ifnet = (struct ifnet **)q;	}	ifindex2ifnet[if_index] = ifp;	/*	 * create a Link Level name for this device	 */	namelen = snprintf(workbuf, sizeof(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)))	if (socksize < sizeof(*sdl))		socksize = sizeof(*sdl);	socksize = ROUNDUP(socksize);	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_rtrequest = link_rtrequest;		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;		TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link);                log_(LOG_ADDR) {                    diag_printf("%s.%d - After inserting %p into list %p\n",                                 __FUNCTION__, __LINE__,                                ifa, &ifp->if_addrlist);                    _show_ifp(ifp);                }	}#ifdef ALTQ	ifp->if_snd.altq_type = 0;	ifp->if_snd.altq_disc = NULL;	ifp->if_snd.altq_flags &= ALTQF_CANTCHANGE;	ifp->if_snd.altq_tbr  = NULL;	ifp->if_snd.altq_ifp  = ifp;#endif}/* * Detach an interface, removing it from the * list of "active" interfaces. */voidif_detach(ifp)	struct ifnet *ifp;{	struct ifaddr *ifa;	struct radix_node_head	*rnh;	int s;	int i;	/*	 * Remove routes and flush queues.	 */	s = splnet();	if_down(ifp);#ifdef ALTQ	if (ALTQ_IS_ENABLED(&ifp->if_snd))		altq_disable(&ifp->if_snd);	if (ALTQ_IS_ATTACHED(&ifp->if_snd))		altq_detach(&ifp->if_snd);#endif	/*	 * Remove address from ifnet_addrs[] and maybe decrement if_index.	 * Clean up all addresses.	 */	ifnet_addrs[ifp->if_index - 1] = 0;	while (if_index > 0 && ifnet_addrs[if_index - 1] == 0)		if_index--;	for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa;	     ifa = TAILQ_FIRST(&ifp->if_addrhead)) {#ifdef INET		/* XXX: Ugly!! ad hoc just for INET */		if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET) {			struct ifaliasreq ifr;			bzero(&ifr, sizeof(ifr));			ifr.ifra_addr = *ifa->ifa_addr;			if (ifa->ifa_dstaddr)				ifr.ifra_broadaddr = *ifa->ifa_dstaddr;			if (in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr, ifp,			    NULL) == 0)				continue;		}#endif /* INET */#ifdef INET6		if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET6) {			in6_purgeaddr(ifa);			/* ifp_addrhead is already updated */			continue;		}#endif /* INET6 */		TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link);		IFAFREE(ifa);	}#ifdef INET6	/*	 * Remove all IPv6 kernel structs related to ifp.  This should be done	 * before removing routing entries below, since IPv6 interface direct	 * routes are expected to be removed by the IPv6-specific kernel API.	 * Otherwise, the kernel will detect some inconsistency and bark it.	 */	in6_ifdetach(ifp);#endif	/*	 * Delete all remaining routes using this interface	 * Unfortuneatly the only way to do this is to slog through	 * the entire routing table looking for routes which point	 * to this interface...oh well...	 */	for (i = 1; i <= AF_MAX; i++) {		if ((rnh = rt_tables[i]) == NULL)			continue;		(void) rnh->rnh_walktree(rnh, if_rtdel, ifp);	}	TAILQ_REMOVE(&ifnet, ifp, if_link);	splx(s);}/* * Delete Routes for a Network Interface *  * Called for each routing entry via the rnh->rnh_walktree() call above * to delete all route entries referencing a detaching network interface. * * Arguments: *	rn	pointer to node in the routing table *	arg	argument passed to rnh->rnh_walktree() - detaching interface * * Returns: *	0	successful *	errno	failed - reason indicated * */static intif_rtdel(rn, arg)	struct radix_node	*rn;	void			*arg;{	struct rtentry	*rt = (struct rtentry *)rn;	struct ifnet	*ifp = arg;	int		err;	if (rt->rt_ifp == ifp) {		/*		 * Protect (sorta) against walktree recursion problems		 * with cloned routes		 */		if ((rt->rt_flags & RTF_UP) == 0)			return (0);		err = rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway,				rt_mask(rt), rt->rt_flags,				(struct rtentry **) NULL);		if (err) {			log(LOG_WARNING, "if_rtdel: error %d\n", err);		}	}	return (0);}/* * Create a clone network interface. */intif_clone_create(name, len)	char *name;	int len;{	struct if_clone *ifc;	char *dp;	int wildcard;	int unit;	int err;	ifc = if_clone_lookup(name, &unit);	if (ifc == NULL)		return (EINVAL);	if (ifunit(name) != NULL)		return (EEXIST);	wildcard = (unit < 0);	err = (*ifc->ifc_create)(ifc, &unit);	if (err != 0)		return (err);	/* In the wildcard case, we need to update the name. */	if (wildcard) {		for (dp = name; *dp != '\0'; dp++);		if (snprintf(dp, len - (dp-name), "%d", unit) >		    len - (dp-name) - 1) {			/*			 * This can only be a programmer error and			 * there's no straightforward way to recover if			 * it happens.			 */			panic("if_clone_create(): interface name too long");		}				}	return (0);}/* * Destroy a clone network interface. */intif_clone_destroy(name)	const char *name;{	struct if_clone *ifc;	struct ifnet *ifp;	ifc = if_clone_lookup(name, NULL);	if (ifc == NULL)		return (EINVAL);	ifp = ifunit(name);	if (ifp == NULL)		return (ENXIO);	if (ifc->ifc_destroy == NULL)		return (EOPNOTSUPP);	(*ifc->ifc_destroy)(ifp);	return (0);}/* * Look up a network interface cloner. */struct if_clone *if_clone_lookup(name, unitp)	const char *name;	int *unitp;{	struct if_clone *ifc;	const char *cp;	int i;	for (ifc = LIST_FIRST(&if_cloners); ifc != NULL;) {		for (cp = name, i = 0; i < ifc->ifc_namelen; i++, cp++) {			if (ifc->ifc_name[i] != *cp)				goto next_ifc;		}		goto found_name; next_ifc:		ifc = LIST_NEXT(ifc, ifc_list);	}	/* No match. */	return ((struct if_clone *)NULL); found_name:	if (*cp == '\0') {		i = -1;	} else {		for (i = 0; *cp != '\0'; cp++) {			if (*cp < '0' || *cp > '9') {				/* Bogus unit number. */				return (NULL);			}			i = (i * 10) + (*cp - '0');		}	}	if (unitp != NULL)		*unitp = i;	return (ifc);}/* * Register a network interface cloner. */voidif_clone_attach(ifc)	struct if_clone *ifc;{	LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);	if_cloners_count++;}/* * Unregister a network interface cloner. */voidif_clone_detach(ifc)	struct if_clone *ifc;{	LIST_REMOVE(ifc, ifc_list);	if_cloners_count--;}/* * Provide list of interface cloners to userspace. */intif_clone_list(ifcr)	struct if_clonereq *ifcr;{	char outbuf[IFNAMSIZ], *dst;	struct if_clone *ifc;	int count, error = 0;	ifcr->ifcr_total = if_cloners_count;	if ((dst = ifcr->ifcr_buffer) == NULL) {		/* Just asking how many there are. */		return (0);	}	if (ifcr->ifcr_count < 0)		return (EINVAL);

⌨️ 快捷键说明

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