📄 proxyarplib.c
字号:
/* proxyArpLib.c - proxy Address Resolution Protocol (ARP) library *//* Copyright 1984-1992 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01h,09feb99,fle doc: put the library description chart inside .CS / .CE markups + and removed dash line to stay in the INTERNAL field01g,14dec97,jdi doc: cleanup.01f,25oct97,kbw fixed man page problems found in beta review01e,15apr97,kbw fixed minor format problems in man page01d,29jan97,vin replaced routeCmd with proxyRouteCmd which adds an explicit network mask of 0xffffffff. Always added the route before adding the arp entry.01c,22nov96,vin added cluster support replaced m_gethdr(..) with mHdrClGet(..).01h,11aug93,jmm Changed ioctl.h and socket.h to sys/ioctl.h and sys/socket.h01g,13nov92,dnw added include of semLibP.h01f,21sep92,jdi Documentation cleanup.01e,16aug92,elh documentation changes.01d,15jun92,elh changed parameters, general cleanup. 01c,04jun92,ajm quieted ansi warnings on netTypeAdd parameters01b,26may92,rrr the tree shuffle -changed includes to have absolute path from h/01a,20sep91,elh written.*//*DESCRIPTIONThis library provides transparent network access by using the AddressResolution Protocol (ARP) to make logically distinct networks appear asone logical network (that is, the networks share the same address space).This module implements a proxy ARP scheme which provides an alternatemethod (to subnets) of access to the WRS backplane.This module implements the proxy server. The proxy server is the multi-homed target which provides network transparency over the backplane by watching for and answering ARP requests. This implementation supports only a single tier of backplane networks (thatis, only targets on directly attached interfaces are proxied for). Only one proxy server resides on a particular backplane network.This library is initialized by calling proxyArpLibInit(). Proxy networksare created by calling proxyNetCreate() and deleted by callingproxyNetDelete(). The proxyNetShow() routine displays the proxy and mainnetworks and the clients that reside on them.A VxWorks backplane target registers itself as a target (proxy client) on the proxy network by calling proxyReg(). It unregisters itself by calling proxyUnreg(). These routines are provided in proxyLib.To minimize and control backplane (proxy network) broadcast traffic, theproxy server must be configured to pass through broadcasts to a certainset of destination ports. Ports are enabled with the callproxyPortFwdOn() and are disabled with the call proxyPortFwdOff(). To seethe ports currently enabled use proxyPortShow(). By default, only theBOOTP server port is enabled.For more information on proxy ARP, see the .I "VxWorks Programmer's Guide: Network"INCLUDE FILES: proxyArpLib.hSEE ALSO: proxyLib, RFC 925, RFC 1027, RFC 826,.I "Network Programmer's Guide".pG NetworkINTERNALProxy Server StructuresThe proxy server must hold information about each of the proxy networks.A proxy network is defined by a proxy network structure (PROXY_NET).Although typically the server will only have one proxy network (i.e. thebackplane), a list of proxy network structures is provided for extensibilityand generality. These proxy network structures are kept on a linked listpointed to proxyNetList.Proxy ClientsA proxy client corresponds to a node on a proxy network. The proxy serverstores information about each proxy client in the PROXY_CLNT structure.Clients are added and deleted dynamically.A proxy client structure for a particular proxy client can be accessedin two ways: (1) by a hash table and (2) by a linked list. A hash table(called clientTbl) of client structures is used for fast look up. The keyis the client IP address. Clients can also be accessed by the proxy networkon with they reside. Each proxy network structure has a pointer to the listof clients (clientList) that reside on that network. This method of accessis convenient when a search of all clients on a particular proxy networkis desired.The combined collection of proxy ARP structures (i.e the proxyNetList, andthe clientTbl) are protected by a single semaphore, called proxySem. Thatis, before any of these structures are being accessed the proxySem must betaken.Registering and Unregistering Proxy ClientsA vxWorks target registers and unregisters itself as a a proxy client bygenerating and sending messages, of ethernet type proxy, over the backplane.These messages are defined by the PROXY_MSG structure and have eitheroperation type PROXY_REG or PROXY_UNREG. Once the proxy server receivesone these messages it performs the appropriate action by either addingor deleting the node as a proxy client. The server then notifies theclient on completion by sending back an ACK message.Proxy ARP client registration can be done more dynamically with ARP messages(hence the flag arpRegister). That is, whenever the proxy server seesa message from a proxy network, it adds the source as a proxy client.However, the problem with this approach is a client only gets registered,the first time it wants to speak over the network. Although this might seem resonable at first. It doesn't work with BOOTP.Network Hooks:There are three main hooks into this library from the network modules. Thefirst hook is for the ARP processing and is in routine in_arpinput, in the fileif_ether.c. The proxyArpHook is a function pointer to the routineproxyArpInput and the hook looks something like: if (proxyArpHook != NULL) (* proxyArpHook) (ac, m);The second hook is for broadcasts. It gets called in the routine ipintr,in file ip_input.c. The broadcast hook, proxyBroadcastHook, lookssomething like: if ((broadcast) && (proxyBroadcastHook != NULL)) (* proxyBroadcastHook) (m, ifp);The hook routine proxyBroadcastInput, gets called right before the switch tohigher level protocols. It gets called this late so the datagram is whole (andthus there is no need to worry about fragmentation, etc.)The third hook is for proxy messages and gets called fromdo_protocol(_with_type). Etherhooks didn't seem a reasonable solutionhere since every packet must be examined (at least one additional functioncall - with checking) it would most likely affect normal IP processing.The hook routine is proxyMsgInput.It would have been nice to do this with A UDP server but we need to knowwhat interface the message arrived on (so we know which proxy network theclient resides on). This isn't available at the socket level.Trailer Negotiation:Trailer negotiation makes things a little more complicated. We negotiatetrailers only if the interface wants to use trailers. We generate a trailerresponse when we respond to an ARP request (along with the normal ARP reply).We also generate a trailer response when we get a reply from a request wegenerated. It would be nice to not support trailers like sunOS.Still to doadd example of setting up under section 5.3.potential effects on performance for routing.memory usages (size of modules, data size, how much mallocable space)network security aspects.servers whose clients overlap.Structure Chart:.CS v v v proxyArpLibInit proxyNetShow proxyArpRemove (in_arpinput) v ----------------proxyArpInput------------------------------------------/ / | \ \ \ \ \ v | | | | | || proxyArpReplyFwd------|---------------|--|-|-------------------|-------->| | v | | | | |v | proxyArpRequestFwd---- -|--|-|-------------------|-------->proxyArpReply | / | | | | | | | | | | | | | v v v | | | | | proxyArpSend | | | | | | | | | | | | | | | (ipintr) | | | | | v | | | | | --proxyBroadcastInput-----------------|--> | | | / | \ | | | | | v ------ <-----------/ | | (do_protocol) | |proxyBroadcast | | | | v | | | | | | proxyMsgInput-----> | |----/ | | v | | | | | |proxyIsAClientOnNet| | | | | v | | | | | | proxyIsAMainNet | | | | | v | | /---/ | | |proxyNetCreate| | | | | | v | | | v | |proxyNetDelete| ----------------------|-proxyClientAdd| | v v / | v v | | proxyNetFind<-/ |proxyClientDelete| | v v | \ proxyClientFind<-/ ------------\ v | v vproxyPortFwdOn | proxyPortFwdOff proxyPortShow | | | | | \------------------>|<-------/<--------------------/ v v proxyPortPrint proxyPortTblFind.CE*//* includes */#include "vxWorks.h"#include "netinet/if_ether.h"#include "proxyArpLib.h"#include "sys/socket.h"#include "net/if_arp.h"#include "net/route.h"#include "net/if.h"#include "net/mbuf.h"#include "netinet/in_systm.h"#include "netinet/ip.h"#include "sys/ioctl.h"#include "netinet/in.h"#include "errno.h"#include "hashLib.h"#include "netinet/ip_var.h"#include "netinet/udp.h"#include "netinet/udp_var.h"#include "inetLib.h"#include "string.h"#include "stdlib.h"#include "logLib.h"#include "arpLib.h"#include "routeLib.h"#include "stdio.h"#include "bootpLib.h"#include "net/unixLib.h"#include "net/if_subr.h"#include "private/semLibP.h"/* defines */#define CLNT_TBL_SZ 8 /* default client table sz 2^8 */#define PORT_TBL_SZ 8 /* default port table sz 2^8 *//* useful macros */#define proxyIsAproxyNet(pAddr) ((proxyNetFind (pAddr) == NULL) ? \ (FALSE) : (TRUE))#define proxyIsAClient(pAddr) ((proxyClientFind ((pAddr)) == NULL) ? \ (FALSE) : (TRUE))#define NODE_TO_CLIENT(pNode) (PROXY_CLNT *) \ ((u_long)(pNode + 1) - sizeof (PROXY_CLNT))#define proxyClientRemove(pClient) \ { \ (void) hashTblRemove (clientTbl, &(pClient)->hashNode); \ (void) arpCmd (SIOCDARP, &((pClient)->ipaddr), (u_char *) NULL, \ (int *) NULL); \ (void) proxyRouteCmd ((pClient)->ipaddr.s_addr, \ (pClient)->pNet->proxyAddr.s_addr, SIOCDELRT); \ } /* delete from netlist */#define proxySendTrailer(pArpcom, pArp) \ ((ntohs ((pArp)->arp_pro) == ETHERTYPE_IP) && \ (((pArpcom)->ac_if.if_flags & IFF_NOTRAILERS) == 0)) /* fill in sockaddr_in structure */#define SIN_FILL(pSin, family, addr, port) \ { \ bzero ((caddr_t) (pSin), sizeof (struct sockaddr_in)); \ (pSin)->sin_len = sizeof(struct sockaddr_in); \ (pSin)->sin_family = (family); \ (pSin)->sin_addr.s_addr = (addr); \ (pSin)->sin_port = (port); \ }/* globals *//* debug variables */BOOL arpDebug = FALSE; /* ARP debug messages */BOOL proxyArpVerbose = FALSE; /* proxy ARP messages */BOOL proxyBroadcastVerbose = FALSE; /* broadcast messages *//* enabling variables */BOOL proxyBroadcastFwd = TRUE; /* forward broadcasts */BOOL proxyArpParanoia = TRUE; /* be paranoid */BOOL arpRegister = TRUE; /* use ARP message to */ /* to register clients */int clientTblSizeDefault = CLNT_TBL_SZ; /* default size */int portTblSizeDefault = PORT_TBL_SZ; /* default size *//* locals *//* * proxy semahore & semid and options and structures * protected by proxySem (clientTbl, proxyNetList) */LOCAL SEMAPHORE proxySem; /* proxy ARP semphore */LOCAL SEM_ID proxySemId = &proxySem;int proxySemOptions = (SEM_Q_FIFO | SEM_DELETE_SAFE );LOCAL HASH_ID clientTbl = NULL; /* hashed clients */LOCAL LIST proxyNetList; /* proxy network list *//* port table sem semid and options, and port table*/LOCAL SEMAPHORE portTblSem;LOCAL SEM_ID portTblSemId = &portTblSem;int portTblSemOptions = (SEM_Q_FIFO | SEM_DELETE_SAFE );LOCAL HASH_ID portTbl = NULL; /* hashed ports */LOCAL BOOL proxyLibInitialized = FALSE; /* server initialized */LOCAL int hashKeyArg = 425871; /* hash key *//* forward declarations */IMPORT FUNCPTR proxyArpHook;IMPORT FUNCPTR proxyBroadcastHook;IMPORT in_cksum ();IMPORT in_broadcast ();/* locals */ /* hook routines */LOCAL void proxyBroadcastInput (struct mbuf *pMbuf, struct ifnet * pIf);LOCAL void proxyArpInput (struct arpcom * pArpcom, struct mbuf * pMbuf);LOCAL void proxyMsgInput (struct arpcom * pArpcom, struct mbuf * pMbuf, int len);LOCAL void proxyArpReply (struct arpcom * pArpcom, struct mbuf * pMbuf, int proto);LOCAL void proxyArpRequestFwd (struct in_addr * pClientAddr, struct mbuf * pMbuf);LOCAL void proxyArpReplyFwd (struct in_addr * pClientAddr, struct mbuf * pMbuf);LOCAL void proxyArpSend (struct ifnet * pIf, int op, int proto, u_char * srcProtoAddr, u_char * dstHwAddr, u_char * dstProtoAddr);LOCAL void proxyBroadcast (struct ifnet * pIf, struct mbuf * pMbuf, int ttl);LOCAL PROXY_NET * proxyNetFind (struct in_addr * pProxyAddr);LOCAL PROXY_CLNT * proxyClientFind (struct in_addr * clientAddr);LOCAL BOOL proxyIsAMainNet (struct in_addr * pMainAddr);LOCAL BOOL proxyIsAClientOnNet (struct in_addr * pProxyAddr, struct in_addr * pClientAddr);LOCAL PORT_NODE * portTblFind (int port);LOCAL BOOL proxyPortPrint (PORT_NODE * pPort);LOCAL STATUS proxyRouteCmd (int destInetAddr, int gateInetAddr, int ioctlCmd); /********************************************************************************* proxyArpLibInit - initialize proxy ARP** This routine initializes the proxy ARP library by initializing tables and* structures and adding the hooks to process ARP, proxy messages, and* broadcasts. <clientSizeLog2> specifies the client hash table size as a* power of two. <portSizeLog2> specifies the port hash table as a power of* two. If either of these parameters is zero, a default value will be* used. By default, proxyArpLibInit() enables broadcast forwarding of the* BOOTP server port. ** This routine should be called only once; subsequent calls have no effect.** RETURNS: OK, or ERROR if unsuccessful.*/STATUS proxyArpLibInit ( int clientSizeLog2, /* client table size as power of two */ int portSizeLog2 /* port table size as power of two */ ) { if (proxyLibInitialized) /* already initialized */ return (OK); /* use default values if zero passed */ clientSizeLog2 = (clientSizeLog2 == 0) ? clientTblSizeDefault : clientSizeLog2; portSizeLog2 = (portSizeLog2 == 0) ? portTblSizeDefault : portSizeLog2; lstInit (&proxyNetList); if ((semMInit (&proxySem, proxySemOptions) == ERROR) || (semMInit (&portTblSem, portTblSemOptions) == ERROR) || ((clientTbl = hashTblCreate (clientSizeLog2, hashKeyCmp, hashFuncModulo, hashKeyArg)) == NULL)) return (ERROR); if ((portTbl = hashTblCreate (portSizeLog2, hashKeyCmp, hashFuncModulo, hashKeyArg)) == NULL) { hashTblDelete (clientTbl); return (ERROR); } (void) proxyPortFwdOn (IPPORT_BOOTPS); proxyBroadcastHook = (FUNCPTR) proxyBroadcastInput; netTypeAdd (PROXY_TYPE, (FUNCPTR) proxyMsgInput); proxyArpHook = (FUNCPTR) proxyArpInput; proxyLibInitialized = TRUE; return (OK); }/********************************************************************************* proxyArpInput - proxy ARP input hook** This routine is the hook used to intercept ARP type messages. It gets* called from the routine arpinput in file if_ether.c. The proxyArpInput()* routine provides the gateway transparency by doing the protocol processing* for proxy ARP. It was designed as a hook (as opposed to hacking up* if_ether), so a minimal a number of modifications get made to the network* modules.** <pArpcom> is the `arpcom' structure of the interface where the ARP message* arrived, <pMbuf> points to the mbuf chain containing the ARP message.** RETURNS: N/A
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -