?? if.c
字號:
/* if.c - network interface utility routines *//* Copyright 1984-1996 Wind River Systems, Inc. */#include "copyright_wrs.h"/* $NetBSD: if.c,v 1.18 1994/10/30 21:48:46 cgd Exp $ *//* * 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 *//*modification history--------------------01j,10mar00,ann Added the callback to the m2Lib routine01i,24mar99,ead Added a call to m2SetIfLastChange() in ifioctl() when the interfaces operational status changes. (SPR #23290)01h,16jul98,n_s fixed ifioctl to pass correct flags to driver Ioctl. SPR 21124 01g,16dec97,vin fixed if_dettach SPR 9970.01f,10dec97,vin added spl protection to ifreset, if_dettach, if_attach, ifIndexToIfp SPR 9987.01e,05oct97,vin fixed if_dettach, for changes in multicast code.01d,12aug97,rjc made if_index global to support non ip interfaces (SPR 9060).01c,02jul97,vin fixed warnings. added _rtIfaceMsgHook for scaling out routing sockets.01b,05dec96,vin moved ifafree() from route.c(), added ifIndexToIfp(), deleted ifnet_addrs in ifattach(), made if_index static. made ifqmaxlen static, replaced calloc with MALLOC, replaced free(..) with FREE(..)01a,03mar96,vin created from BSD4.4 stuff,integrated with 02t of if.c. rewrote if_dettach(), added in_ifaddr_remove in if_dettach*//*DESCRIPTION*/#include "vxWorks.h"#include "sys/socket.h"#include "net/socketvar.h"#include "net/protosw.h"#include "net/route.h"#include "net/if_dl.h"#include "net/if_subr.h"#include "sys/ioctl.h"#include "errno.h"#include "net/if.h"#include "wdLib.h"#include "net/systm.h"#include "net/mbuf.h"#ifdef INET#include "netinet/in_var.h"#endif /* INET */#include "m2Lib.h"IMPORT void netJobAdd ();extern pfctlinput(int cmd, struct sockaddr * sa);extern sysClkRateGet();extern void in_ifaddr_remove ();extern arpioctl (int cmd, caddr_t data); /* XXX temporary fix should be removed after updating all drivers */extern void ether_ifattach(struct ifnet * ifp);extern int ether_output (); int ifAttachChange; /* Set when a change in the Net I/F list occurs */struct ifnet *ifnet; /* head of linked list of interfaces *//* locals */LOCAL WDOG_ID ifslowtimoWd; /* watchdog timer for slowtimo routine */static int ifqmaxlen = IFQ_MAXLEN;static char * sprint_d(unsigned int, char *, int);/* globals */int if_index = 0;/* * Network interface utility routines. * * Routines with ifa_ifwith* names take sockaddr *'s as * parameters. */void 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; /* XXX using watchdogs good idea? -gae */ ifslowtimoWd = wdCreate (); if_slowtimo (); }/* * Call each interface on a reset. */void ifreset () { register struct ifnet *ifp; int s; s = splnet (); for (ifp = ifnet; ifp; ifp = ifp->if_next) if (ifp->if_reset) (*ifp->if_reset)(ifp->if_unit); splx (s); }/* * Attach an interface to the list of "active" interfaces. */void if_attach(ifp) struct ifnet *ifp; { unsigned socksize, ifasize; int namelen, unitlen, masklen; char workbuf[12], *unitname; register struct ifnet **p = &ifnet; register struct sockaddr_dl *sdl; register struct ifaddr *ifa; extern void link_rtrequest(); int s; /* make interface not use trailer protocol by default */ ifp->if_flags |= IFF_NOTRAILERS; /* make send queue maxlen be default if none specified; * this relaxes the requirement that all interfaces be attached * before calling ifinit */ if (ifp->if_snd.ifq_maxlen == 0) ifp->if_snd.ifq_maxlen = ifqmaxlen; s = splnet (); while (*p) p = &((*p)->if_next); splx (s); *p = ifp; /* Notify MIB-II of change */ ifAttachChange++; ifp->if_index = ++if_index; /* * 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)) masklen = _offsetof(struct sockaddr_dl, sdl_data[0]) + unitlen + 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; MALLOC (ifa, struct ifaddr *, ifasize, MT_IFADDR, M_WAIT); if (ifa == 0) return; bzero((caddr_t)ifa, ifasize); sdl = (struct sockaddr_dl *)(ifa + 1); 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->sdl_type = ifp->if_type; 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; m2IfTableUpdate(ifp, M2_IF_TABLE_INSERT); /* XXX Temporary fix before changing ethernet drivers */ s = splnet (); if (ifp->if_output == ether_output) ether_ifattach (ifp); splx (s); }/***************************************************************************** if_dettach - dettaches an interface from the linked list of interfaces** if_dettach is used to dettach an interface from the linked list of* all available interfaces. This function needs to be used with* if_down () when shutting down a network interface.*/void if_dettach (ifp) struct ifnet *ifp; /* inteface pointer */ { FAST struct ifnet ** pPtrIfp; FAST struct ifaddr * pIfAddr; FAST struct ifaddr ** pPtrIfAddr; int s; pPtrIfp = &ifnet; s = splnet (); while (*pPtrIfp != NULL) { if (*pPtrIfp == ifp) { pPtrIfAddr = &(*pPtrIfp)->if_addrlist; while (*pPtrIfAddr != NULL) { pIfAddr = *pPtrIfAddr; *pPtrIfAddr = (*pPtrIfAddr)->ifa_next; #ifdef INET if (pIfAddr->ifa_addr->sa_family == AF_INET) in_ifaddr_remove (pIfAddr); else #endif /* INET */ { IFAFREE (pIfAddr); } }#ifdef INET if ((*pPtrIfp)->pInmMblk != NULL) in_delmulti ((*pPtrIfp)->pInmMblk, NULL);#endif /* INET */ *pPtrIfp = (*pPtrIfp)->if_next; break; } pPtrIfp = &(*pPtrIfp)->if_next; } /* Notify MIB-II of change */ ifAttachChange++; m2IfTableUpdate(ifp, M2_IF_TABLE_REMOVE); splx (s); }/********************************************************************************* ifIndexToIfp - obtain the ifnet pointer from the index** This function obtains the ifnet pointer from the if_index.* The interface index is unique for every new interface added.* * NOMANUAL** RETURNS ifnet/NULL*/struct ifnet * ifIndexToIfp ( int ifIndex /* index of the interface to find */ ) { register struct ifnet * pIfp = NULL; int s; /* traverse the list of ifnet structures in the system */ s = splnet (); for (pIfp = ifnet; pIfp != NULL; pIfp = pIfp->if_next) { if (pIfp->if_index == ifIndex) break; } splx (s); return (pIfp); }/* * 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 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; /* eliminated need for ifnet_addrs array*/ if (sdl->sdl_index && sdl->sdl_index <= if_index) { ifp = ifIndexToIfp (sdl->sdl_index); for (ifa = ifp->if_addrlist; ifa != NULL; ifa = ifa->ifa_next) if (ifa->ifa_addr->sa_family == af) break; return (ifa); } } 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 || ifa->ifa_netmask == 0) next: 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 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);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -