?? proxyarplib.c
字號:
*/ pArp = mtod (pMbuf, struct ether_arp *); arpOp = ntohs (pArp->arp_op); bcopy (pArp->arp_spa, (char *)&srcAddr, sizeof (srcAddr)); bcopy (pArp->arp_tpa, (char *)&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); } /* Ignore any messages containing a broadcast address as the source. */ if (!(bcmp (pArp->arp_sha, etherbroadcastaddr, sizeof (pArp->arp_sha)))) { m_freem (pMbuf); return (TRUE); /* Invalid message - skip standard ARP processing. */ } semTake (proxySemId, WAIT_FOREVER); switch (arpOp) { case ARPOP_REQUEST: /* * Handle any ARP requests which must cross a network boundary * that the proxy server hides. The standard ARP processing * cannot manage those situations. It will handle all requests * from a main network since proxy ARP entries exist for all * hosts on the proxy network. */ if ((pNet = proxyNetFind (&pArpcom->ac_ipaddr)) != NULL) { /* * Received an ARP request from a proxy network. * Add new client if enabled by arpRegister setting. */ if (arpRegister && !proxyIsAClient (&srcAddr)) (void) proxyClientAdd (pArpcom, &srcAddr, pArp->arp_sha); pClient = proxyClientFind (&dstAddr); if (pClient) { /* * The destination of the request is also a proxy client. * If it is on the same proxy network, ignore the request * since the client will reply for itself. If it is on * a different proxy network, the standard ARP processing * will reply correctly based on the proxy ARP entry. */ if (pClient->pNet->proxyAddr.s_addr == pArpcom->ac_ipaddr.s_addr) { /* Client will answer - avoid proxy reply. */ semGive (proxySemId); m_freem (pMbuf); return (TRUE); } } else { /* * The destination is not a proxy client. These ARP * requests from a proxy client for a different host on * the main network cannot be handled by the standard * ARP processing. If the destination's hardware address * is available, send a reply giving ours as an alias. * Otherwise, forward the request to the main network. */ if (arpCmd (SIOCGARP, &dstAddr, (u_char *)NULL, (int *) NULL) == OK || pNet->proxyAddr.s_addr == dstAddr.s_addr || pNet->mainAddr.s_addr == dstAddr.s_addr) proxyArpReply (pArpcom, pMbuf, ntohs (pArp->arp_pro)); else proxyArpRequestFwd (&srcAddr, pMbuf); semGive (proxySemId); m_freem (pMbuf); return (TRUE); /* Skip standard ARP processing. */ } } break; case ARPOP_REPLY: /* * Received an ARP reply. If it is a response to an earlier * (forwarded) request, generate a reply to the proxy client * supplying our hardware address as an alias. Once the * hardware address of the actual destination is in the * ARP cache, the proxy server will be able to transparently * forward packets from the proxy network to that host. */ pClient = proxyClientFind (&dstAddr); if (pClient && (pClient->pNet->mainAddr.s_addr == pArpcom->ac_ipaddr.s_addr)) { /* * Note: the second condition of the previous test is a * sanity check preventing the forwarding of replies * between proxy networks, although those messages should * never be sent since requests are not forwarded between * proxy networks in the first place. */ proxyArpReplyFwd (pClient, pMbuf); /* * The standard ARP processing would only refresh an existing * entry, not create a new one, so add the entry for the * actual destination of the original ARP request. */ arpCmd (SIOCSARP, &srcAddr, pArp->arp_sha, (int *) NULL); semGive (proxySemId); m_freem (pMbuf); return (TRUE); /* Skip (redundant) standard ARP processing. */ } break; default: break; } semGive (proxySemId); return (FALSE); /* Standard ARP processing handles remaining cases. */ }/********************************************************************************* proxyArpReply - generate an ARP reply** This routine responds to ARP request messages which would ordinarily* require forwarding across a network boundary hidden by the proxy server.* The server advertises the hardware address of its local interface instead* of the actual hardware address of the destination host. It will forward* the incoming data to the correct destination on the separate network.** This routine usually handles ARP requests from the proxy network for a host* on the main network. The standard ARP processing is capable of responding* to requests from the main network since registering the proxy clients* creates the necessary proxy ARP entries, but hosts on a main network are* not registered.** The <pArpcom> parameter identifies the interface which received the* ARP message contained in the <pMbuf> mbuf chain. The <proto> parameter* identifies the type of the protocol information for the new ARP message.* Currently, it is always ETHERTYPE_IP (0x800). ** RETURNS: N/A** NOMANUAL*/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 original source to the ARP cache so that the server can * transparently forward data from the proxy client to that host. * Ignore failures caused if an entry already exists. */ bcopy (pArp->arp_spa, (char *)&srcAddr, sizeof (srcAddr)); 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 relays an ARP request message from a proxy network to a* main network when a proxy client attempts to contact a host across the* network boundary which the proxy server conceals. The server supplies* the hardware address of the local interface to the host on the main* network so that all traffic will be transparently forwarded to the* proxy client. The <pMbuf> parameter contains the original ARP request* sent by the proxy client using the <pClientAddr> address.** RETURNS: N/A** NOMANUAL*/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 ("(forwarding request 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 relays an ARP reply message from a main network to a* proxy network following an earlier transfer in the opposite direction.* The server supplies the hardware address of the local interface instead* of the actual destination host on the main network so that all traffic* from the proxy client will be transparently forwarded. The <pMbuf>* mbuf chain contains the original ARP reply intended for the proxy client* indicated by the <pClient> parameter.** RETURNS: N/A** NOMANUAL*/LOCAL void proxyArpReplyFwd ( PROXY_CLNT * pClient, /* proxy client registration data */ struct mbuf * pMbuf /* original ARP message */ ) { struct sockaddr_in sin; /* interface sin */ struct ifaddr * pIfa; /* interface address */ struct ether_arp * pArp; /* ARP message */ u_short arpProto; /* ARP type */ /* Find the interface connected to the proxy client. */ 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 ("(forwarding reply to if 0x%x)", ntohl (pClient->pNet->proxyAddr.s_addr), 0, 0, 0, 0, 0); pArp = mtod (pMbuf, struct ether_arp *); /* * Replace (deprecated) trailer packets with the standard type value. It * is theoretically possible to consume those messages since trailer * responses are additional replies, but forward them anyway for safety. */ if (ntohs (pArp->arp_pro) == ETHERTYPE_TRAIL) arpProto = ETHERTYPE_IP; else arpProto = ntohs (pArp->arp_pro); /* * The client's registration data contains a snapshot of the hardware * address at that time. Since all clients must register, the lack of * dynamic updates (available with an ARP entry) is unimportant. */ proxyArpSend (pIfa->ifa_ifp, ntohs (pArp->arp_op), arpProto, pArp->arp_spa, pClient->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** NOMANUAL*/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 activates proxy services between the proxy network connected* to the interface with the <proxyAddr> IP address and the main network* connected to the interface with the <mainAddr> address. Once registration* is complete, the proxy server will disguise the physically separated* networks as a single logical network. ** The corresponding interfaces must be attached and configured with IP* addresses before calling this routine. If the proxy network shares the* same logical subnet number as the main network, the corresponding interface* to the proxy network must use a value of 255.255.255.255 for the netmask.** RETURNS: OK, or ERROR if unsuccessful.** ERRNO:* S_proxyArpLib_INVALID_ADDRESS*/STATUS proxyNetCreate ( char * proxyAddr, /* address of proxy network interface */ char * mainAddr /* address of main network interface */ ) { struct sockaddr_in proxyAddrKey; struct sockaddr_in mainAddrKey; PROXY_NET * pNet; struct ifaddr * pIfa; int flags; /* * Verify that local interfaces can reach the addresses of the * proxy and main networks. */ SIN_FILL (&proxyAddrKey, AF_INET, inet_addr (proxyAddr), 0); SIN_FILL (&mainAddrKey, AF_INET, inet_addr (mainAddr), 0); if ( (ifa_ifwithaddr ( (struct sockaddr *)&mainAddrKey) == NULL) || ( (pIfa = ifa_ifwithaddr ( (struct sockaddr *)&proxyAddrKey)) == NULL)) { errno = S_proxyArpLib_INVALID_ADDRESS; return (ERROR); } if ((pNet = (PROXY_NET *) calloc (1, sizeof (PROXY_NET))) == NULL) return (ERROR); semTake (proxySemId, WAIT_FOREVER); /* Replace any existing proxy network entry with the new values. */ proxyNetDelete (proxyAddr); pNet->proxyAddr = proxyAddrKey.sin_addr; pNet->mainAddr = mainAddrKey.sin_addr; lstInit (&pNet->clientList); lstAdd (&proxyNetList, &pNet->netNode); /* * Add a proxy ARP entry allowing the standard ARP processing * to reply to requests for this local interface from hosts on * other networks. The ATF_PROXY flag indicates a "wildcard" hardware * address. Ignore failures caused if an entry already exists. */ flags = ATF_PUBL | ATF_PROXY | ATF_PERM; arpCmd (SIOCSARP, &pNet->proxyAddr, NULL, &flags);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -