📄 proxyarplib.c
字号:
}/********************************************************************************* proxyPortFwdOff - disable broadcast forwarding for a particular port** This routine disables broadcast forwarding on port number <port>. To* disable the (previously enabled) forwarding of all ports via* proxyPortFwdOn(), specify zero for <port>.** RETURNS: OK, or ERROR if unsuccessful.*/STATUS proxyPortFwdOff ( int port /* port number */ ) { PORT_NODE * pPort; /* port node */ semTake (portTblSemId, WAIT_FOREVER); if ((pPort = portTblFind (port)) == NULL) { /* not in port table so ok */ semGive (portTblSemId); return (OK); } (void) hashTblRemove (portTbl, &pPort->hashNode); semGive (portTblSemId); free ((caddr_t) pPort); return (OK); }/********************************************************************************* portTblFind - find the port node** This routine finds the port node associated with port number <port>.** RETURNS: A pointer to the port node, or NULL if not found.*/LOCAL PORT_NODE * portTblFind ( int port /* port number */ ) { PORT_NODE portNode; /* port node */ portNode.port = (int) port; return ((PORT_NODE *) hashTblFind (portTbl, &portNode.hashNode, 0)); }/********************************************************************************* proxyPortShow - show enabled ports** This routine displays the ports currently enabled.** EXAMPLE* .CS* -> proxyPortShow* enabled ports:* port 67* .CE** RETURNS: N/A** INTERNAL* calls printf() while semaphore taken.*/void proxyPortShow (void) { semTake (portTblSemId, WAIT_FOREVER); printf ("enabled ports:\n"); if (portTblFind (0) != NULL) printf (" all ports enabled\n"); else hashTblEach (portTbl, proxyPortPrint, 0); semGive (portTblSemId); }/********************************************************************************* proxyPortPrint - print ports enabled** This routine prints the list of enabled ports.** RETURNS: TRUE (always)*/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).** Datagrams forwarded onto a proxy network are given a TTL of 1. This is so* they never actually leave the proxy network. This is a precaution to prevent* broadcast storms and network meltdown. Datagrams forwarded on the ethernet* have their original ttl - 1.** 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*/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 */ /* * If ttl goes to zero don't forward the datagram. * Also only forward UDP packets with the ports enabled. */ if ((pIP->ip_ttl <= IPTTLDEC) || (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 (pUDP->uh_dport) && !portTblFind ((u_short) 0)) return; semTake (proxySemId, WAIT_FOREVER); inputAddr.s_addr = ((struct arpcom *) pIf)->ac_ipaddr.s_addr; if ((pNet = proxyNetFind (&inputAddr)) != NULL) { /* * 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); } else { /* interface not a proxy network, make sure it's a main network */ if (!proxyIsAMainNet (&inputAddr)) { semGive (proxySemId); return; } mainAddr.s_addr = inputAddr.s_addr; } for (pNet = (PROXY_NET *) lstFirst (&proxyNetList); (pNet != NULL); pNet = (PROXY_NET *) lstNext (&pNet->netNode)) { /* * Forward datagram to all proxy networks that have the main network * as their main network (with ttl as 1). Don't forward to * originating network, however. */ 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> out on on* interface <pIf> with a new time-to-live value of <ttl>. It changes the* fields back into network byte order, and re checksums the header.** RETURNS: N/A*/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 */ if ((pMbufCopy = (struct mbuf *) m_copy (pMbuf, 0, M_COPYALL)) == NULL) return; 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); pIP->ip_len += pIP->ip_hl << 2; pIP->ip_id = htons ((u_short) pIP->ip_id); /* convert to network format */ 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); /* checksum */ (*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*/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 ( (proxyClientAdd (pArpcom, &pMsg->clientAddr) == OK) && (arpCmd (SIOCSARP, &pMsg->clientAddr, pMsg->clientHwAddr, (int *) NULL) == 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)); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -