?? proxyarplib.c
字號:
* This routine prints the list of enabled ports.** RETURNS: TRUE (always)** NOMANUAL*/LOCAL BOOL proxyPortPrint ( PORT_NODE * pPort /* port node */ ) { printf (" port %d\n", pPort->port); return (TRUE); }/********************************************************************************* proxyBroadcastInput - hook routine for broadcasts** This routine is the hook routine that forwards a broadcast datagram* <pMbuf> which was received on interface <pIf> to and from proxy interfaces.* As a measure of control, it only forwards broadcasts that are destined for* ports that have been previously enabled (with proxyPortFwdOn()).* proxyBroadcastInput() gets called from routine ipintr(), in file ip_input.c.* It assumes the datagram is whole (i.e., if the datagram was fragmented,* then it was previously reassembled).** If the broadcast datagram came from a main network, then forward the* broadcast to all proxy network's that have the input interface as their* main network. If the broadcast came from a proxy network, then forward* the broadcast to all other proxy networks that have that proxy network's main* network as their main network (and forward it to the main network as well).** INTERNAL* Would we ever want to forward anything beyond UDP broadcasts (what* about ICMP?)? The old backplane driver makes a local copy of broadcasts* so we'll get an extra copy of broadcast packets if we are using the old* backplane driver.** RETURNS: N/A** NOMANUAL*/LOCAL void proxyBroadcastInput ( struct mbuf * pMbuf, /* mbuf chain */ struct ifnet * pIf /* interface pointer */ ) { struct in_addr inputAddr; /* input interface */ PROXY_NET * pNet; /* proxy network */ struct in_addr mainAddr; /* main interface */ struct ifaddr * pIfa; /* if address */ struct sockaddr_in sin; /* sin structure */ struct ip * pIP; /* ip header pointer */ int hlen; /* ip header length */ struct udphdr * pUDP; /* udp header */ if (!proxyBroadcastFwd) /* broadcasts got turned off */ return; if (pMbuf->m_len < sizeof (struct ip) && (pMbuf = m_pullup(pMbuf, sizeof (struct ip))) == 0) return; pIP = mtod (pMbuf, struct ip *); /* pulled tight in ip_input */ /* * Only forward UDP broadcast packets. */ if (pIP->ip_p != IPPROTO_UDP) return; hlen = pIP->ip_hl << 2; /* * make sure IP header (with options) and UDP header fit into the * first mbuf. */ if (pMbuf->m_len < (hlen + sizeof (struct udphdr))) { if ((pMbuf = m_pullup (pMbuf, hlen + sizeof (struct udphdr))) == 0) return; pIP = mtod (pMbuf, struct ip *); } pUDP = (struct udphdr *) ((u_char *) pIP + hlen); if (!portTblFind (ntohs (pUDP->uh_dport)) && !portTblFind ((u_short) 0)) return; semTake (proxySemId, WAIT_FOREVER); inputAddr.s_addr = ((struct arpcom *) pIf)->ac_ipaddr.s_addr; /* Validate the interface which received the original broadcast message. */ pNet = proxyNetFind (&inputAddr); if (pNet == NULL && !proxyIsAMainNet (&inputAddr)) { /* * The receiving interface is not part of any proxy network or * main network. Don't forward the broadcast message. */ semGive (proxySemId); return; } if (pNet) { /* * Input interface was a proxy network. Find main network associated * with that proxy network (and the interface to the main network) * and forward the datagram onto it. */ mainAddr.s_addr = pNet->mainAddr.s_addr; SIN_FILL(&sin, AF_INET, pNet->mainAddr.s_addr, 0); if ((pIfa = ifa_ifwithaddr ((struct sockaddr *) &sin)) != NULL) proxyBroadcast (pIfa->ifa_ifp, pMbuf, pIP->ip_ttl - 1); } else { mainAddr.s_addr = inputAddr.s_addr; } for (pNet = (PROXY_NET *) lstFirst (&proxyNetList); (pNet != NULL); pNet = (PROXY_NET *) lstNext (&pNet->netNode)) { /* * Forward packet to all appropriate proxy networks. (A copy is not * sent to any proxy network which contained the original broadcast). */ if ((pNet->mainAddr.s_addr == mainAddr.s_addr) && (pNet->proxyAddr.s_addr != inputAddr.s_addr)) { /* find proxy interface and ship it off */ SIN_FILL(&sin, AF_INET, pNet->proxyAddr.s_addr, 0); if ((pIfa = ifa_ifwithaddr ((struct sockaddr *) &sin)) != NULL) proxyBroadcast (pIfa->ifa_ifp, pMbuf, 1); } } semGive (proxySemId); }/********************************************************************************* proxyBroadcast - send a broadcast** This routine sends a copy of the broadcast message <pMbuf> on the interface* <pIf> so that all (physically separated) hosts on a logical subnet receive* the expected broadcasts.** RETURNS: N/A** NOMANUAL*/LOCAL void proxyBroadcast ( FAST struct ifnet * pIf, /* output interface pointer */ struct mbuf * pMbuf, /* mbuf chain */ int ttl /* time to live */ ) { struct mbuf * pMbufCopy; /* mbuf chain (copy) */ struct sockaddr_in sin; /* address */ struct ip * pIP; /* ip header pointer */ /* * Copy the message to protect forwarded packet from changes made by * upper layers. */ if ((pMbufCopy = (struct mbuf *) proxyPacketDup (pMbuf)) == NULL) return; pMbufCopy->mBlkHdr.mFlags |= M_PROXY; pIP = mtod (pMbufCopy, struct ip *); if (proxyBroadcastVerbose) logMsg ("forward broadcast (if:0x%x) src 0x%x [%d] dst 0x%x [%d]\n", ((struct arpcom *) pIf)->ac_ipaddr.s_addr, pIP->ip_src.s_addr, ((struct udpiphdr *) pIP)->ui_sport, pIP->ip_dst.s_addr, ((struct udpiphdr *) pIP)->ui_dport, 0); SIN_FILL(&sin, AF_INET, pIP->ip_dst.s_addr, 0); /* Adjust the IP packet length (modified in receive processing). */ pIP->ip_len += pIP->ip_hl << 2; /* Convert appropriate header fields to network order for transmission. */ pIP->ip_id = htons ((u_short) pIP->ip_id); pIP->ip_len = htons ((u_short) pIP->ip_len); pIP->ip_off = htons ((u_short) pIP->ip_off); pIP->ip_ttl = ttl; pIP->ip_sum = 0; pIP->ip_sum = in_cksum (pMbufCopy, pIP->ip_hl << 2); (*pIf->if_output)(pIf, pMbufCopy, (struct sockaddr *) &sin, (struct rtentry *) NULL); }/********************************************************************************* proxyMsgInput - input routine for proxy messages** This routine is the input hook routine for proxy messages. It handles* the probe, client register and client unregister messages. For a probe* message it just sends an ACK. PROXY_REG and PROXY_UNREG messages cause* the proxy server to add the client (via proxyClientAdd()) and delete the* (via proxyClientDelete()), respectively then reply with an ACK.** <pArpcom> is the arpcom structure for the input interface. <pMbuf> is the* mbuf chain. <len> is the length of the message.** RETURNS: N/A** NOMANUAL*/LOCAL void proxyMsgInput ( FAST struct arpcom * pArpcom, /* arpcom structure */ FAST struct mbuf * pMbuf, /* mbuf chain */ int len /* length */ ) { PROXY_MSG * pMsg; /* proxy message */ int op; /* operation */ BOOL sendACK = FALSE;/* send client ack */ if (pMbuf->m_len < sizeof (PROXY_MSG)) /* check message length */ { m_freem (pMbuf); return; } pMsg = mtod (pMbuf, PROXY_MSG *); op = ntohl (pMsg->op); if (proxyArpVerbose) logMsg ("(%d) from 0x%x [%s]\n", op, ntohl (pMsg->clientAddr.s_addr), (int) ether_sprintf (pMsg->clientHwAddr), 0, 0, 0); if (proxyLibInitialized) { if (op == PROXY_PROBE) /* probe message */ sendACK = TRUE; semTake (proxySemId, WAIT_FOREVER); if (op == PROXY_REG) /* add client message */ { if (proxyIsAClient (&pMsg->clientAddr)) sendACK = TRUE; /* Acknowledge duplicate registrations. */ else if (proxyClientAdd (pArpcom, &pMsg->clientAddr, pMsg->clientHwAddr) == OK) sendACK = TRUE; } if (op == PROXY_UNREG) /* delete client message */ { (void) proxyClientDelete (&pMsg->clientAddr); sendACK = TRUE; } semGive (proxySemId); if (sendACK) { struct ether_header * pEh; /* ether header */ struct sockaddr sa; /* sockaddr structure */ struct ifnet * pIf; /* interface pointer */ /* fill in proxy message */ pMsg->op = htonl (PROXY_ACK); pMsg->serverAddr.s_addr = pArpcom->ac_ipaddr.s_addr; bcopy ((caddr_t) pArpcom->ac_enaddr, (caddr_t) pMsg->serverHwAddr, sizeof (pMsg->serverHwAddr)); if (proxyArpVerbose) logMsg ("proxy ACK sent to 0x%x\n", ntohl (pMsg->clientAddr.s_addr), 0, 0, 0, 0, 0); bzero ((caddr_t) &sa, sizeof (sa)); sa.sa_family = AF_UNSPEC; /* fill in ethernet header */ pEh = (struct ether_header *) sa.sa_data; pEh->ether_type = PROXY_TYPE; pIf = (struct ifnet *) pArpcom; bcopy ((caddr_t) pMsg->clientHwAddr, (caddr_t) pEh->ether_dhost, sizeof (pEh->ether_dhost)); (*pIf->if_output) (pIf, pMbuf, &sa, (struct rtentry *) NULL); return; } } m_freem (pMbuf); }/********************************************************************************* proxyRouteCmd - add and delete a proxy client routes** This routine adds and deletes routes to the proxy clients with the netmask* of 0xffffffff so that arp route entries to the proxy clients can be cloned* from the route added by this routine.** RETURNS: OK, or ERROR if unsuccessful.** NOMANUAL*/LOCAL STATUS proxyRouteCmd ( int destInetAddr, /* destination adrs */ int gateInetAddr, /* gateway adrs */ int ioctlCmd /* route command */ ) { struct sockaddr destAddr; struct sockaddr gateWayAddr; struct sockaddr netMask; bzero((char *)(&destAddr), sizeof(struct sockaddr)); destAddr.sa_family = AF_INET; destAddr.sa_len = sizeof(struct sockaddr_in); ((struct sockaddr_in *)&destAddr)->sin_addr.s_addr = (u_long)destInetAddr; /* zero out sockaddr_in, fill in gateway info */ bzero ((char *)&gateWayAddr, sizeof(struct sockaddr)); gateWayAddr.sa_family = AF_INET; gateWayAddr.sa_len = sizeof(struct sockaddr_in); ((struct sockaddr_in *)&gateWayAddr)->sin_addr.s_addr = (u_long)gateInetAddr; /* initialize the netmask to 0xffffffff */ netMask.sa_family = AF_INET; netMask.sa_len = 8; ((struct sockaddr_in *)&netMask)->sin_addr.s_addr = 0xffffffff; in_socktrim ((struct sockaddr_in *)&netMask); return (rtrequest (((ioctlCmd == SIOCADDRT) ? RTM_ADD : RTM_DELETE), &destAddr, &gateWayAddr, &netMask, RTF_CLONING, NULL)); }/********************************************************************************* proxyClientRemove - clear client structures** This routine deletes the client routes from the route table.** NOMANUAL*/LOCAL void proxyClientRemove ( PROXY_CLNT * pClient ) { int flags = ATF_PROXY; (void) hashTblRemove (clientTbl, &pClient->hashNode); /* Remove proxy ARP entry explicitly */ (void) arpCmd (SIOCDARP, &pClient->ipaddr, (u_char *) NULL, &flags); /* Remove regular ARP entry */ (void) arpCmd (SIOCDARP, &pClient->ipaddr, (u_char *) NULL, (int *) NULL); (void) proxyRouteCmd (pClient->ipaddr.s_addr, pClient->pNet->proxyAddr.s_addr, SIOCDELRT); }/********************************************************************************* proxyPacketDup - copies IP header, dups the rest of the packet** This routine makes a new mbuf chain copying the IP header of the* original packet to a newly allocated cluster and copying by reference* the rest of the packet. This kind of copying is necessary if the IP* header must be altered to reflect a new TTL when broadcast packets* are forwarded.** RETURNS: An M_BLK_ID for the new mbuf chain if successful, NULL* otherwise.** NOMANUAL*/LOCAL M_BLK_ID proxyPacketDup ( M_BLK_ID pMblk /* pointer to source mBlk */ ) { M_BLK_ID pNewMblk = NULL; M_BLK_ID pPktMblk = NULL; int ipHeaderSize = sizeof (struct ip); int bytesDuped = 0; if (pMblk == NULL) return (NULL); /* First mbuf must have enough room for link layer header */ if ((pNewMblk = netTupleGet (_pNetDpool, max_linkhdr + ipHeaderSize, M_DONTWAIT, MT_DATA, TRUE)) == NULL) return (NULL); /* Copy IP header which is in the first mbuf (done by m_pullup) */ pNewMblk->mBlkHdr.mData += max_linkhdr; /* Leave room */ bcopy (pMblk->mBlkHdr.mData, pNewMblk->mBlkHdr.mData, ipHeaderSize); pNewMblk->mBlkHdr.mLen = ipHeaderSize; if (pMblk->mBlkHdr.mFlags & M_PKTHDR) { /* Copy packet header information */ pNewMblk->mBlkPktHdr = pMblk->mBlkPktHdr; pNewMblk->mBlkHdr.mFlags = pMblk->mBlkHdr.mFlags; } /* Copy by reference the rest of the packet */ bytesDuped = pMblk->mBlkPktHdr.len - ipHeaderSize; pPktMblk = netMblkChainDup (_pNetDpool, pMblk, ipHeaderSize, bytesDuped, M_DONTWAIT); if (pPktMblk == NULL) { netMblkClChainFree(pNewMblk); return (NULL); } /* Make chain */ pNewMblk->mBlkPktHdr.len = pMblk->mBlkPktHdr.len; pNewMblk->mBlkHdr.mNext = pPktMblk; return (pNewMblk); }
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -