📄 proxyarplib.c
字号:
char * proxyAddr, /* proxy network address */ char * mainAddr /* main network address */ ) { struct sockaddr_in proxyAddrSin; /* proxy net sin structure */ struct sockaddr_in mainAddrSin; /* main net sin structure */ PROXY_NET * pNet; /* proxy network structure */ struct ifaddr * pIfa; /* pointer to ifaddr */ /* make sure addresses for both proxy and main are local interfaces */ SIN_FILL (&proxyAddrSin, AF_INET, inet_addr (proxyAddr), 0); SIN_FILL (&mainAddrSin, AF_INET, inet_addr (mainAddr), 0); if ((ifa_ifwithaddr ((struct sockaddr *) &mainAddrSin) == NULL) || ((pIfa = ifa_ifwithaddr ((struct sockaddr *) &proxyAddrSin)) == NULL)) { errno = S_proxyArpLib_INVALID_INTERFACE; return (ERROR); } if (in_netof (mainAddrSin.sin_addr) != in_netof (proxyAddrSin.sin_addr)) { errno = S_proxyArpLib_INVALID_ADDRESS; return (ERROR); } /* proxy only for backplane interfaces */ if (proxyArpParanoia && (strcmp (pIfa->ifa_ifp->if_name, "bp") != 0) && (strcmp (pIfa->ifa_ifp->if_name, "sm") != 0)) { logMsg ("proxying for non backplane device\n", 0, 0, 0, 0, 0, 0); return (ERROR); } if ((pNet = (PROXY_NET *) calloc (1, sizeof (PROXY_NET))) == NULL) return (ERROR); semTake (proxySemId, WAIT_FOREVER); /* * delete any existing proxy network (with the passed address), * create a new one then link it in. */ (void) proxyNetDelete (proxyAddr); pNet->proxyAddr = proxyAddrSin.sin_addr; pNet->mainAddr = mainAddrSin.sin_addr; lstInit (&pNet->clientList); lstAdd (&proxyNetList, &pNet->netNode); semGive (proxySemId); return (OK); }/********************************************************************************* proxyNetDelete - delete a proxy network** This routine deletes the proxy network specified by <proxyAddr>. It also* removes all the proxy clients that exist on that network.** RETURNS: OK, or ERROR if unsuccessful.**/STATUS proxyNetDelete ( char * proxyAddr /* proxy net address */ ) { PROXY_NET * pNet; /* proxy network */ NODE * pNode; /* client node */ PROXY_CLNT * pClient; /* proxy client */ STATUS status = ERROR; /* return value */ struct in_addr proxyAddrIn; semTake (proxySemId, WAIT_FOREVER); proxyAddrIn.s_addr = inet_addr (proxyAddr); if ((pNet = proxyNetFind (&proxyAddrIn)) != NULL) { /* clear out the clients */ for (pNode = lstFirst (&pNet->clientList); pNode != NULL;) { pClient = NODE_TO_CLIENT (pNode); proxyClientRemove (pClient); pNode = lstNext (pNode); free ((caddr_t) pClient); } lstDelete (&proxyNetList, &pNet->netNode); free ((caddr_t) pNet); status = OK; } semGive (proxySemId); return (status); }/********************************************************************************* proxyNetFind - find a proxy network structure** This routine finds the proxy network structure associated * with <proxyAddr>. The `proxySemId' semaphore must already * be taken before calling this routine.** RETURNS: A PROXY_NET pointer if found, otherwise NULL.** ERRNO: * S_proxyArpLib_INVALID_NET**/LOCAL PROXY_NET * proxyNetFind ( struct in_addr * pProxyAddr /* proxy address */ ) { PROXY_NET * pNet; /* proxy network */ for (pNet = (PROXY_NET *) lstFirst (&proxyNetList); (pNet != NULL); pNet = (PROXY_NET *) lstNext (&pNet->netNode)) if (pNet->proxyAddr.s_addr == pProxyAddr->s_addr) return (pNet); errno = S_proxyArpLib_INVALID_PROXY_NET; return (NULL); }/********************************************************************************* proxyIsAMainNet - is the interface a main network ?** This routine determines if <mainAddr> is a main network. * `proxySemId' must already be taken before this routine is called.** RETURNS: TRUE if a main network, FALSE otherwise.*/LOCAL BOOL proxyIsAMainNet ( struct in_addr * pMainAddr /* main address */ ) { PROXY_NET * pNet; /* proxy network */ for (pNet = (PROXY_NET *) lstFirst (&proxyNetList); (pNet != NULL); pNet = (PROXY_NET *) lstNext (&pNet->netNode)) if (pNet->mainAddr.s_addr == pMainAddr->s_addr) return (TRUE); return (FALSE); }/********************************************************************************* proxyIsAClientOnNet - is the client a resident of the proxy network?** This routine determines if the proxy client <clientAddr> resides* on proxy network specified by <proxyAddr>. `proxySemId' must already be* taken before this routine is called.** RETURNS: TRUE if client is a resident, FALSE otherwise.*/LOCAL BOOL proxyIsAClientOnNet ( struct in_addr * pProxyAddr, /* proxy address */ struct in_addr * pClientAddr /* client address */ ) { PROXY_CLNT * pClient; /* proxy client */ return (((pClient = proxyClientFind (pClientAddr)) != NULL) && (pClient->pNet->proxyAddr.s_addr == pProxyAddr->s_addr)); }/********************************************************************************* proxyNetShow - show proxy ARP networks** This routine displays the proxy networks and their associated clients.** EXAMPLE* .CS* -> proxyNetShow* main interface 147.11.1.182 proxy interface 147.11.1.183* client 147.11.1.184* .CE** RETURNS: N/A** INTERNAL* calls printf while semaphore taken.*/void proxyNetShow (void) { PROXY_NET * pNet; /* proxy net */ PROXY_CLNT * pClient; /* proxy client */ NODE * pNode; /* pointer to node */ /* address in ascii */ char asciiAddr [ INET_ADDR_LEN ]; semTake (proxySemId, WAIT_FOREVER); for (pNet = (PROXY_NET *) lstFirst (&proxyNetList); pNet != NULL; pNet = (PROXY_NET *) lstNext (&pNet->netNode)) { inet_ntoa_b (pNet->mainAddr, asciiAddr); printf ("main interface %s ", asciiAddr); inet_ntoa_b (pNet->proxyAddr, asciiAddr); printf ("proxy interface %s\n", asciiAddr); for (pNode = lstFirst (&pNet->clientList); pNode != NULL; pNode = lstNext (pNode)) { pClient = NODE_TO_CLIENT (pNode); inet_ntoa_b (pClient->ipaddr, asciiAddr); printf (" client:%s\n", asciiAddr); } } semGive (proxySemId); }/********************************************************************************* proxyClientAdd - add a proxy client** This routine adds the client, whose ip address is <pArpcom>.ac_ipaddr, onto * the proxy network identified by <pProxyNetAddr>. The client address must be* in the same network address space as the proxy network address.** RETURNS: OK, or ERROR if unsuccessful.** ERRNO:* S_proxyArpLib_INVALID_ADDRESS** NOMANUAL** INTERNAL:* Since clients get added dynamically (either by client add messages or by* ARP messages) this should probably not get called via the user and therefore* be LOCAL. However, for additional functionality it is made global.*/STATUS proxyClientAdd ( struct arpcom * pArpcom, struct in_addr * pClientAddr /* client internet addr */ ) { PROXY_NET * pNet; /* proxy net */ PROXY_CLNT * pClient; /* proxy client */ struct sockaddr_in sin; /* sin structure */ struct ifaddr * pIfa; /* interface address */ struct in_addr * pProxyNetAddr; /* proxy net address */ /* validate addresses */ pProxyNetAddr = &pArpcom->ac_ipaddr; if ((in_netof (*pProxyNetAddr) != in_netof (*pClientAddr)) || in_broadcast (*pClientAddr, (struct ifnet *)pArpcom)) { errno = S_proxyArpLib_INVALID_ADDRESS; return (ERROR); } if ((pClient = (PROXY_CLNT *) calloc (1, sizeof (PROXY_CLNT))) == NULL) return (ERROR); semTake (proxySemId, WAIT_FOREVER); if (!proxyIsAproxyNet (pClientAddr) && ((pNet = (PROXY_NET *) proxyNetFind (pProxyNetAddr)) != NULL)) { /* find main interface */ SIN_FILL (&sin, AF_INET, pNet->mainAddr.s_addr, 0); if ((pIfa = ifa_ifwithaddr ((struct sockaddr *) &sin)) != NULL) { (void) proxyClientDelete (pClientAddr); /* * Add client to routing tables. Fill in and add client * structure. Generate a gratuitous ARP on main * interface for client (to update host ARP caches). */ if (proxyRouteCmd (pClientAddr->s_addr, pProxyNetAddr->s_addr, SIOCADDRT) == OK) { pClient->pNet = pNet; pClient->ipaddr = *pClientAddr; hashTblPut (clientTbl, &pClient->hashNode); lstAdd (&pNet->clientList, &pClient->clientNode); proxyArpSend (pIfa->ifa_ifp, ARPOP_REQUEST, ETHERTYPE_IP, (u_char *) pClientAddr, (u_char *) NULL, (u_char *) pClientAddr); if (proxyArpVerbose) logMsg ("added client 0x%x proxyNet 0x%x\n", ntohl (pClientAddr->s_addr), ntohl (pProxyNetAddr->s_addr), 0, 0, 0, 0); semGive (proxySemId); return (OK); } } else { if (proxyArpVerbose) logMsg ("proxyClientAdd: no main if 0x%x\n", ntohl (pNet->mainAddr.s_addr), 0, 0, 0, 0, 0); } } semGive (proxySemId); free ((caddr_t) pClient); return (ERROR); }/********************************************************************************* proxyClientDelete - delete a proxy client** This routines deletes the proxy client specified by <pClientAddr>.** RETURNS: OK, or ERROR if unsuccessful.** NOMANUAL*/STATUS proxyClientDelete ( struct in_addr * pClientAddr /* client address */ ) { PROXY_CLNT * pClient; /* proxy client */ STATUS status = ERROR; /* return status */ semTake (proxySemId, WAIT_FOREVER); if ((pClient = proxyClientFind (pClientAddr)) != NULL) { proxyClientRemove (pClient); lstDelete (&pClient->pNet->clientList, &pClient->clientNode); if (proxyArpVerbose) logMsg ("deleted client 0x%x\n", ntohl (pClientAddr->s_addr), 0, 0, 0, 0, 0); status = OK; } semGive (proxySemId); if (pClient != NULL) free ((caddr_t) pClient); return (status); }/********************************************************************************* proxyClientFind - find a proxy client** This routine finds the proxy client structure associated with <pClientAddr>.* Caller must have taken `proxySemId' before this routine is called.** RETURNS: Pointer to PROXY_CLNT if found, NULL otherwise.** ERRNO:* S_proxyArpLib_INVALID_CLIENT*/LOCAL PROXY_CLNT * proxyClientFind ( struct in_addr * pClientAddr /* client address */ ) { PROXY_CLNT client; /* client to find */ PROXY_CLNT * pClient; /* pointer to client */ client.ipaddr.s_addr = pClientAddr->s_addr; if ((pClient = (PROXY_CLNT *) hashTblFind (clientTbl, &client.hashNode, 0)) == NULL) errno = S_proxyArpLib_INVALID_CLIENT; return (pClient); }/********************************************************************************* proxyPortFwdOn - enable broadcast forwarding for a particular port** This routine enables broadcasts destined for the port, <port>, to be * forwarded to and from the proxy network. To enable all ports, specify * zero for <port>.** RETURNS: OK, or ERROR if unsuccessful.*/STATUS proxyPortFwdOn ( int port /* port number */ ) { PORT_NODE * pPort; /* port node */ if ((pPort = (PORT_NODE *) calloc (1, sizeof (PORT_NODE))) == NULL) return (ERROR); semTake (portTblSemId, WAIT_FOREVER); if (portTblFind (port) != NULL) /* already enabled so ok */ { semGive (portTblSemId); free ((caddr_t) pPort); return (OK); } pPort->port = (int) port; (void) hashTblPut (portTbl, &pPort->hashNode); semGive (portTblSemId); return (OK);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -