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

📄 proxyarplib.c

📁 vxworks源码源码解读是学习vxworks的最佳途径
💻 C
📖 第 1 页 / 共 4 页
字号:
*/LOCAL void proxyArpInput    (    struct arpcom *		pArpcom,	/* arpcom structure 	*/    struct mbuf *		pMbuf		/* mbuf chain		*/    )    {    struct ether_arp *		pArp;		/* ARP message 		*/    struct in_addr		srcAddr;	/* source address	*/    struct in_addr		dstAddr;	/* destination address	*/    u_short			arpOp;		/* ARP operation	*/    pArp = mtod (pMbuf, struct ether_arp *);	/* len checked in arpinput */    arpOp = ntohs(pArp->arp_op);    bcopy ((caddr_t) pArp->arp_spa, (caddr_t) &srcAddr, sizeof (srcAddr));    bcopy ((caddr_t) pArp->arp_tpa, (caddr_t) &dstAddr, sizeof (dstAddr));    if (arpDebug)				/* ARP debugging info */	{    	logMsg ("op:%s (if 0x%x) src: 0x%x [%s] dst: 0x%x ",		(arpOp == ARPOP_REQUEST) ? (int) "request" : (int) "reply",		ntohl (pArpcom->ac_ipaddr.s_addr), ntohl (srcAddr.s_addr),		(int) ether_sprintf (pArp->arp_sha), ntohl (dstAddr.s_addr), 0);	if (arpOp != ARPOP_REQUEST)	    logMsg ("[%s]", (int) ether_sprintf (pArp->arp_tha), 0, 0, 0, 0 ,0);	logMsg ("\n", 0, 0, 0, 0, 0, 0);	}    						/* sanity checks */    if ((bcmp ((caddr_t) pArp->arp_sha, (caddr_t) etherbroadcastaddr,               sizeof (pArp->arp_sha)) == 0) || 	in_broadcast (srcAddr, (struct ifnet *)pArpcom))        return;    semTake (proxySemId, WAIT_FOREVER);    switch (arpOp)	{	case ARPOP_REQUEST:	    if (proxyIsAproxyNet (&pArpcom->ac_ipaddr))	        {	        /*	         * Received an ARP request from a proxy network.  Add		 * client if it is not registered (and arpRegister is enabled).		 * Update client entry in the ARP cache.	         */		if (arpRegister && !proxyIsAClient (&srcAddr))	            (void) proxyClientAdd (pArpcom, &srcAddr);	        (void) arpCmd (SIOCSARP, &srcAddr, pArp->arp_sha, NULL);	        }	    if ((proxyIsAproxyNet (&dstAddr) || proxyIsAMainNet (&dstAddr)) &&	        (dstAddr.s_addr != pArpcom->ac_ipaddr.s_addr))		{		/*	         * An ARP request for either a proxy or main interface on	         * which the source doesn't reside.  Answer it.  Otherwise	         * the interfaces will be hidden.	         */		proxyArpReply (pArpcom, pMbuf, ntohs (pArp->arp_pro));		if (proxySendTrailer (pArpcom, pArp))		    proxyArpReply (pArpcom, pMbuf, ETHERTYPE_TRAIL);		semGive (proxySemId);		return;		}	    if (proxyIsAClient (&dstAddr))	/* dest is a proxy client */		{		/*		 * The destination is a proxy client.  If the client does not		 * reside on the interface from where the request was generated,		 * then reply (otherwise the client should answer for itself).		 * Send a trailer response if trailers are enabled on interface.		 */		if (!proxyIsAClientOnNet (&pArpcom->ac_ipaddr, &dstAddr))		    {		    proxyArpReply (pArpcom, pMbuf, ntohs (pArp->arp_pro));		    if (proxySendTrailer (pArpcom, pArp))			proxyArpReply (pArpcom, pMbuf, ETHERTYPE_TRAIL);		    }	        }	    else				/* dest not a proxy client */		{		if (proxyIsAClient (&srcAddr))		    {		    /*		     * The ARP request came from a proxy client so we must try 		     * to resolve it.  First look into the ARP cache.  If we 		     * know about the destination, send a reply.  Otherwise, try		     * to resolve the address by forwarding the ARP request onto		     * the client's main network.  (Note: we only have to 		     * forward it to the main network because all other proxy 		     * client's we should know about).		     */		    if (arpCmd (SIOCGARP, &dstAddr, (u_char *) NULL,			        (int *) NULL) == OK)			{			/*			 * It is ok if the entry times out after we			 * reply to the client because we will just reARP for 			 * the host anyway.			 */		        proxyArpReply (pArpcom, pMbuf, ntohs (pArp->arp_pro));		        if (proxySendTrailer (pArpcom, pArp))			    proxyArpReply (pArpcom, pMbuf, ETHERTYPE_TRAIL);		        }		    else			proxyArpRequestFwd (&srcAddr, pMbuf);		    }		}	    break;	case ARPOP_REPLY:    	    /*     	     * Received an ARP reply.  If it is for a proxy client and we	     * previously sent it out to be resolved (hwaddr is for us) then	     * forward it on to the client.     	     */	    if ((proxyIsAClient (&dstAddr)) &&	        (!proxyIsAClientOnNet (&pArpcom->ac_ipaddr, &dstAddr)) &&	        (bcmp ((caddr_t) pArp->arp_tha, (caddr_t) pArpcom->ac_enaddr,		       sizeof (pArpcom->ac_enaddr)) == 0))	        {	        proxyArpReplyFwd (&dstAddr, pMbuf);	        if ((arpCmd (SIOCGARP, &srcAddr, (u_char *) NULL,			     (int *) NULL) == ERROR) && (errno == ENXIO))		    {		    /*		     * if the source of the reply in not in the ARP cache,		     * then send a trailer response if we want to negotiate		     * trailers on the input interface.  Only do this when		     * adding the host for the first time.		     */	    	    if ((pArpcom->ac_if.if_flags & IFF_NOTRAILERS) == 0)		        proxyArpReply (pArpcom, pMbuf, ETHERTYPE_TRAIL);		    }	        (void) arpCmd (SIOCSARP, &srcAddr, pArp->arp_sha, (int *) NULL);	        }	    break;	default:	    break;	}    semGive (proxySemId);    }/********************************************************************************* proxyArpReply - generate an ARP reply** This routine responds to an ARP request message.  It converts the request* into a reply and ships it out on the same interface from which it* arrived.  The proxyArpReply() routine gets called when an ARP request* comes in for a proxy client (from a host on a different interface), or* when a proxy client generates an ARP request for an non proxy host (that* we know about).** <pArpcom> is the `arpcom' structure of the interface where the ARP message* arrived.  <pMbuf> is the mbuf chain of the original ARP message.  <proto>* specifies the format of the ARP reply protocol type (it is either* ETHERTYPE_IP or ETHERTYPE_TRAILERS).** RETURNS: N/A*/LOCAL void proxyArpReply    (    FAST struct arpcom *		pArpcom,	/* arpcom structure   */    FAST struct mbuf *			pMbuf,		/* mbuf chain 	      */    int 			 	proto		/* format of protocol */    )    {    struct ether_arp *			pArp;		/* ARP message	      */    struct in_addr			srcAddr;	/* source address     */    pArp = mtod (pMbuf, struct ether_arp *);    /*     * Add the source to ARP cache because chances are the destination will     * (shortly) be ARPing for source.  If the source is already in the ARP     * cache, this updates the ARP timers and prevents the ARP entries from     * timing out.     */    bcopy ((caddr_t) pArp->arp_spa, (caddr_t) &srcAddr, sizeof (srcAddr));    (void) arpCmd (SIOCSARP, &srcAddr, (u_char *)pArp->arp_sha,  (int *) NULL);    /*  switch source and target addresses */    proxyArpSend ((struct ifnet *) pArpcom, ARPOP_REPLY, proto,		  pArp->arp_tpa, pArp->arp_sha, pArp->arp_spa);    }/********************************************************************************* proxyArpRequestFwd - forward an ARP request** This routine forwards an ARP request message, pointed to by* <pMbuf>, from a proxy client, specified by <pClientAddr>, onto the* client's main network.  It gets called when a proxy client ARPs for an* unknown non proxy client.  Caller must have taken `proxySemId' before this* routine is called.** RETURNS:  N/A*/LOCAL void proxyArpRequestFwd    (    struct in_addr *		pClientAddr,		/* proxy client addr */    struct mbuf * 		pMbuf			/* mbuf chain	     */    )    {    PROXY_CLNT *		pClient;		/* proxy client	     */    struct ether_arp *		pArp;			/* ARP message 	     */    struct sockaddr_in		sin;			/* interface sin     */    struct ifaddr *		pIfa;			/* interface address */    /* find the client's main network interface */    if ((pClient = proxyClientFind (pClientAddr)) == NULL)	return;    SIN_FILL (&sin, AF_INET, pClient->pNet->mainAddr.s_addr, 0);    if ((pIfa = ifa_ifwithaddr ((struct sockaddr *) &sin)) == NULL)	return;    if (proxyArpVerbose)			/* print debugging info */	logMsg ("(forward to if 0x%x) ", ntohl (pClient->pNet->mainAddr.s_addr),		0, 0, 0, 0, 0);    /*     * Leave the client as the source protocol address so when the reply     * comes back we know where to forward the reply.     */    pArp = mtod (pMbuf, struct ether_arp *);    proxyArpSend (pIfa->ifa_ifp, ntohs (pArp->arp_op), ntohs (pArp->arp_pro),		  pArp->arp_spa, pArp->arp_tha, pArp->arp_tpa);    }/********************************************************************************* proxyArpReplyFwd - forward an ARP reply** This routine forwards an ARP reply, pointed to by <pMbuf>, to the proxy* client specified by <pClientAddr>.  The ARP reply resolves an ARP request* previously forwarded by proxyArpRequestFwd().  Trailers responses are not* forwarded onto non trailer interfaces.  Caller must have taken `proxySemId'* before this routine is called.** INTERNAL* The ARP cache timeout in the proxy server, for the proxy client, must be* greater than the ARP retry time on the client.  That is, the client must* stay in the proxy server ARP cache for at least as long as it takes the* client to timeout and retransmit the ARP request.  Otherwise, the server* could falsely throw away an ARP reply and cause the client to send another* ARP request.  This, however, is not critical and doesn't seem to be a* problem since the ARP cache timeout on a completed entry is 20 minutes.** RETURNS: N/A*/LOCAL void proxyArpReplyFwd    (    struct in_addr *		pClientAddr,		/* proxy client addr */    struct mbuf * 		pMbuf			/* mbuf chain	     */    )    {    PROXY_CLNT *		pClient;		/* proxy client	     */    struct sockaddr_in		sin;			/* interface sin     */    struct ifaddr *		pIfa;			/* interface address */    struct ether_arp *		pArp;			/* ARP message 	     */    u_short 			arpProto;		/* ARP type	     */    u_char			hwAddr [6];		/* client hw address */    /* find the client's the proxy interface */    if ((pClient = proxyClientFind (pClientAddr)) == NULL)	return;    SIN_FILL (&sin, AF_INET, pClient->pNet->proxyAddr.s_addr, 0);    if ((pIfa = ifa_ifwithaddr ((struct sockaddr *) &sin)) == NULL)	return;    if (proxyArpVerbose)			/* print debugging info */	logMsg ("(forward to if 0x%x)", ntohl (pClient->pNet->mainAddr.s_addr),		0, 0, 0, 0, 0);    pArp = mtod (pMbuf, struct ether_arp *);    /*     * Don't forward trailer packets onto non-trailer interfaces.  We probably     * could eat this packet entirely since trailer responses are additional     * but who really knows what other machines are doing, so to be cautious     * and pass it through as a normal IP proto type.     */    if ((ntohs (pArp->arp_pro) == ETHERTYPE_TRAIL) &&	(((struct arpcom *)(pIfa->ifa_ifp))->ac_if.if_flags & IFF_NOTRAILERS))	arpProto = ETHERTYPE_IP;    else	arpProto = ntohs (pArp->arp_pro);    /*  the clients hardware address is the target hardware address */    if (arpCmd (SIOCGARP, pClientAddr, hwAddr, (int *) NULL) == OK)	proxyArpSend (pIfa->ifa_ifp, ntohs (pArp->arp_op), arpProto,		      pArp->arp_spa, hwAddr, pArp->arp_tpa);    }/********************************************************************************* proxyArpSend - generate and send an ARP message** This routine constructs and sends an ARP message over the network interface* specified by <pIf>.  <op> specifies the ARP operation, <proto> is the format* of protocol address.  <srcProtoAddr> is the source protocol address,* <dstHwAddr> is the destination hardware address and <dstProtoAddr> is the* destination protocol addresses.** RETURNS: N/A*/LOCAL void proxyArpSend    (    struct ifnet *		pIf,		/* interface pointer 	*/    int				op,		/* ARP op		*/    int				proto,		/* ARP protocol		*/    u_char *			srcProtoAddr,	/* src ip address	*/    u_char *			dstHwAddr,	/* dest hw address	*/    u_char *			dstProtoAddr	/* dest ip address	*/    )    {    FAST struct mbuf *		pMbuf;		/* mbuf chain		*/    FAST struct ether_arp *	pArp;		/* ARP message		*/    struct ether_header *	pEh;		/* ether header		*/    struct sockaddr 		sa;		/* sockaddr structure	*/    if ((pMbuf = mHdrClGet(M_DONTWAIT, MT_DATA, sizeof(*pArp), TRUE)) == NULL)	return;    pMbuf->m_len = sizeof(*pArp);    pMbuf->m_pkthdr.len = sizeof(*pArp);    MH_ALIGN(pMbuf, sizeof(*pArp));    pArp = mtod(pMbuf, struct ether_arp *);	/* fill in ARP message */    bzero ((caddr_t) pArp, sizeof (struct ether_arp));    pArp->arp_hrd = htons (ARPHRD_ETHER);    pArp->arp_pro = htons (proto);    pArp->arp_hln = sizeof (pArp->arp_sha);    pArp->arp_pln = sizeof (pArp->arp_spa);    pArp->arp_op  = htons (op);    bcopy ((caddr_t) ((struct arpcom *) pIf)->ac_enaddr,	   (caddr_t) pArp->arp_sha, sizeof (pArp->arp_sha));    bcopy ((caddr_t) srcProtoAddr, (caddr_t) pArp->arp_spa,	   sizeof (pArp->arp_spa));    bcopy ((caddr_t) dstProtoAddr, (caddr_t) pArp->arp_tpa,	   sizeof (pArp->arp_tpa));    bzero ((caddr_t) &sa, sizeof (sa));    sa.sa_family = AF_UNSPEC;    pEh = (struct ether_header *) sa.sa_data;    pEh->ether_type = ETHERTYPE_ARP;		/* switched in ether_output */    if (op == ARPOP_REQUEST)	{    	bcopy ((caddr_t) etherbroadcastaddr, (caddr_t) pEh->ether_dhost,	       sizeof (pEh->ether_dhost));	}    else	{    	bcopy ((caddr_t) dstHwAddr, (caddr_t) pArp->arp_tha,	       sizeof (pArp->arp_tha));    	bcopy ((caddr_t) dstHwAddr, (caddr_t) pEh->ether_dhost,	       sizeof (pEh->ether_dhost));	}    if (proxyArpVerbose)	{    	logMsg ("%s (%x): src: 0x%x [%s] dst : 0x%x ", (op == ARPOP_REQUEST) ?		(int) "request" : (int) "reply", proto,		*((int *) pArp->arp_spa), (int) ether_sprintf (pArp->arp_sha),		*((int *) pArp->arp_tpa), 0);	if (op != ARPOP_REQUEST)	    logMsg ("[%s]", (int) ether_sprintf (pArp->arp_tha), 0, 0, 0, 0, 0);	logMsg ("\n", 0, 0, 0, 0, 0, 0);	}    (*pIf->if_output) (pIf, pMbuf, &sa, (struct rtentry *) NULL);    }/********************************************************************************* proxyNetCreate - create a proxy ARP network** This routine creates a proxy network with the interface <proxyAddr> as the* proxy network and the interface <mainAddr> as the main network.  The* interfaces and the routing tables must be set up correctly, prior to* calling this routine.  That is, the interfaces must be attached, addresses* must be set, and there should be a network route to <mainAddr> and no* routes to <proxyAddr>.** <proxyAddr> and <mainAddr> must reside in the same network address space.** RETURNS: OK, or ERROR if unsuccessful.** ERRNO:*  S_proxyArpLib_INVALID_INTERFACE*  S_proxyArpLib_INVALID_ADDRESS** INTERNAL* The `proxyArpParanoia' flag does extra checking to make sure the* user is using proxy ARP the way we intended (i.e., over the backplane).* Otherwise, unless the person is careful, serious network problems can* occur.**/STATUS proxyNetCreate    (

⌨️ 快捷键说明

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