Mixe for Privacy and Anonymity in the Internet
CADynaNetworking.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright (c) 2000, The JAP-Team 
00003 All rights reserved.
00004 Redistribution and use in source and binary forms, with or without modification, 
00005 are permitted provided that the following conditions are met:
00006  
00007   - Redistributions of source code must retain the above copyright notice, 
00008     this list of conditions and the following disclaimer.
00009  
00010   - Redistributions in binary form must reproduce the above copyright notice, 
00011     this list of conditions and the following disclaimer in the documentation and/or 
00012     other materials provided with the distribution.
00013  
00014   - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors 
00015     may be used to endorse or promote products derived from this software without specific 
00016     prior written permission. 
00017  
00018   
00019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS 
00020 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
00021 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
00022 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00023 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
00024 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 
00025 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
00026 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00027 */
00028 
00029 
00030 #include "StdAfx.h"
00031 #ifdef DYNAMIC_MIX
00032 
00033 #include "CADynaNetworking.hpp"
00034 #include "CASocket.hpp"
00035 #include "CASocketAddrINet.hpp"
00036 #include "CAHttpClient.hpp"
00037 #include "CACmdLnOptions.hpp"
00038 #include "CASocketAddr.hpp"
00039 #include "xml/DOM_Output.hpp"
00040 
00041 CADynaNetworking::CADynaNetworking() : CAInfoServiceAware()
00042   {
00043   }
00044 
00045 CADynaNetworking::~CADynaNetworking()
00046   {
00047   }
00048 
00063 SINT32 CADynaNetworking::updateNetworkConfiguration(UINT16 a_port)
00064   {
00065     UINT8 internalIp[255];
00066     UINT8 externalIp[255];
00067     UINT32 len = 255;
00068 
00069     if( resolveInternalIp( internalIp ) == E_UNKNOWN )
00070     {
00071         return E_UNKNOWN;
00072     }
00073     if( resolveExternalIp( externalIp, len ) == E_UNKNOWN )
00074     {
00075         return E_UNKNOWN;
00076     }
00077 
00078     // Beware! This resets all information abount ListenerInterfaces!
00079     pglobalOptions->resetNetworkConfiguration();
00080 
00081     DOM_Document doc;
00082     pglobalOptions->getMixXml(doc);
00083     DOM_Element elemRoot = doc.getDocumentElement();
00084     DOM_Element elemListeners;
00085     getDOMChildByName(elemRoot,(UINT8*)"ListenerInterfaces",elemListeners,false);
00086     if(elemListeners == NULL)
00087     {
00088         elemListeners = doc.createElement("ListenerInterfaces");
00089         elemRoot.appendChild( elemListeners );
00090     }
00091 
00092     if(strcmp((char*)internalIp, (char*)externalIp) == 0)
00093     {
00094         /* External IP == Internal IP, wonderful */
00095         createListenerInterface( elemListeners, doc, internalIp, a_port, false, false);
00096         return E_SUCCESS;
00097     }
00098     createListenerInterface( elemListeners, doc, internalIp, a_port, true, false);
00099     createListenerInterface( elemListeners, doc, externalIp, a_port, false, true);
00100 
00101 
00102 #ifdef DEBUG
00103     UINT8* buff = DOM_Output::dumpToMem(doc,&len);
00104     CAMsg::printMsg(LOG_CRIT, (char*)buff);
00105 #endif
00106     return E_SUCCESS;
00107   }
00108 
00121 SINT32 CADynaNetworking::createListenerInterface(DOM_Element r_elemListeners, DOM_Document a_ownerDoc,const UINT8 *a_ip, UINT32 a_port, bool a_bHidden, bool a_bVirtual)
00122   {
00123     DOM_Element elemTmp;
00124 
00125     DOM_Element elemListener=a_ownerDoc.createElement("ListenerInterface");
00126     if( a_bHidden )
00127     {
00128         elemListener.setAttribute("hidden", "True");
00129     }
00130 
00131     if( a_bVirtual )
00132     {
00133         elemListener.setAttribute("virtual", "True");
00134     }
00135     r_elemListeners.appendChild(elemListener);
00136     elemTmp=a_ownerDoc.createElement("Port");
00137     setDOMElementValue(elemTmp,a_port);
00138     elemListener.appendChild(elemTmp);
00139     elemTmp=a_ownerDoc.createElement("NetworkProtocol");
00140     setDOMElementValue(elemTmp,(UINT8*)"RAW/TCP");
00141     elemListener.appendChild(elemTmp);
00142     elemTmp=a_ownerDoc.createElement("IP");
00143     setDOMElementValue(elemTmp, a_ip);
00144     elemListener.appendChild(elemTmp);
00145 #ifdef DEBUG
00146     UINT32 len;
00147     UINT8* buff = DOM_Output::dumpToMem(elemListener, &len);
00148     CAMsg::printMsg(LOG_CRIT, "%s\n",(char*)buff);
00149 #endif
00150 
00151     pglobalOptions->addListenerInterface(elemListener);
00152     return E_SUCCESS;
00153 }
00154 
00160 CAListenerInterface *CADynaNetworking::getWorkingListenerInterface()
00161 {
00162     UINT32 interfaces = pglobalOptions->getListenerInterfaceCount();
00163     CAListenerInterface *pListener = NULL;
00164     for( UINT32 i = 1; i <= interfaces; i++ )
00165     {
00166         pListener = pglobalOptions->getListenerInterface(i);
00167         if(!pListener->isVirtual())
00168             break;
00169         delete pListener;
00170         pListener=NULL;
00171     }
00172     return pListener;
00173 }
00174 
00180 static THREAD_RETURN ConnectivityLoop(void *p)
00181 {
00182   INIT_STACK;
00183   BEGIN_STACK("CADynaNetworking::ConnectivityLoop");
00184   
00185     CADynaNetworking* parent = (CADynaNetworking*)p;
00186     char buff[1024];
00187     UINT32 len = 1024;
00188     SINT32 rLen;
00189     char *pechoRequest = NULL;
00190 
00191 #ifdef DEBUG
00192     CAMsg::printMsg(LOG_DEBUG, "CADynaNetworking - ConnectivityLoop() started\n");
00193 #endif
00194     CAListenerInterface *pListener = parent->getWorkingListenerInterface();
00195     if(pListener == NULL)
00196     {
00197         CAMsg::printMsg(LOG_DEBUG, "CADynaNetworking - ConnectivityLoop - No valid ListenerInterface found, aborting\n");
00198         THREAD_RETURN_ERROR;
00199     }
00200 
00201     CASocket serverSocket;
00202     CASocket socket;
00203     CASocketAddrINet *address = (CASocketAddrINet*)pListener->getAddr();
00204     if( serverSocket.listen( *address )  != E_SUCCESS )
00205     {
00206         CAMsg::printMsg(LOG_ERR, "CADynaNetworking - ConnectivityLoop - Unable to listen to standard port, aborting\n");
00207         goto EXIT;
00208     }
00209 #ifdef DEBUG
00210     CAMsg::printMsg(LOG_ERR, "CADynaNetworking - ConnectivityLoop - Ok, listening...\n");
00211 #endif
00212     if( serverSocket.accept(socket) != E_SUCCESS)
00213     {
00214         CAMsg::printMsg(LOG_ERR, "CADynaNetworking - ConnectivityLoop - Unable to accept on standard port, aborting\n");
00215         goto EXIT;
00216     }
00217 #ifdef DEBUG
00218     CAMsg::printMsg(LOG_ERR, "CADynaNetworking - ConnectivityLoop - Ok, i accepted\n");
00219 #endif
00220     rLen = socket.receive( (UINT8*)buff, len );
00221 #ifdef DEBUG
00222     CAMsg::printMsg(LOG_DEBUG, "CADynaNetworking - ConnectivityLoop - Received %i Bits: (%s)\n", rLen, buff);
00223 #endif
00224     pechoRequest = new char[rLen+1];
00225     strncpy(pechoRequest, buff, rLen+1);
00226 #ifdef DEBUG
00227     CAMsg::printMsg(LOG_DEBUG, "CADynaNetworking - ConnectivityLoop - echoRequest: (%s)\n", pechoRequest);
00228     CAMsg::printMsg(LOG_DEBUG, "CADynaNetworking - ConnectivityLoop - Will send: %i chars, %s\n", strlen(pechoRequest), pechoRequest);
00229 
00230 #endif
00231     socket.send( (const UINT8*)pechoRequest, rLen);
00232     delete pechoRequest;
00233     pechoRequest = NULL;
00234 EXIT:
00235   FINISH_STACK("CADynaNetworking::ConnectivityLoop");
00236 
00237     delete address;
00238     address = NULL;
00239     socket.close();
00240     serverSocket.close();
00241     THREAD_RETURN_SUCCESS;
00242 }
00243 
00255 SINT32 CADynaNetworking::verifyConnectivity()
00256 {
00257     SINT32 ret = E_UNKNOWN;
00258     DOM_Element elemRoot;
00259     DOM_Node elemRes;
00260     UINT8 res[255];
00261     UINT32 len=255;
00262 
00263     CAThread* m_pthreadConnectivtyLoop = new CAThread((UINT8*)"ConnectivityThread");
00264     m_pthreadConnectivtyLoop->setMainLoop(ConnectivityLoop);
00265     // 1, 3+4)
00266     m_pthreadConnectivtyLoop->start(this);
00267 
00268     //@todo FIXME We have a race condition here between the sending of the request to the infoservice and our m_pthreadConnectivtyLoop thread listenting
00269     // on the port!
00270     msSleep(1000);
00271     // 2 + 5)
00272     CAListenerInterface *pListener = getWorkingListenerInterface();
00273 
00274     if(pListener == NULL)
00275     {
00276         CAMsg::printMsg( LOG_DEBUG, "Didn't find a useable ListenerInterface, exiting\n");
00277         // Well, if we can't get a working ListenerInterface, the Thread should't either and return to us
00278         m_pthreadConnectivtyLoop->join();
00279         return E_UNKNOWN;
00280     }
00281     CASocketAddrINet *addr = (CASocketAddrINet*)pListener->getAddr();    
00282     UINT16 port = addr->getPort();
00283     delete pListener;
00284     pListener = NULL;
00285     // End Fixme
00286 
00287     CASocket tmpSock;
00288     
00289     if( sendConnectivityRequest( &elemRoot, port) != E_SUCCESS )
00290     {
00291         CAMsg::printMsg(LOG_DEBUG, "CADynaNetworking - verifyConnectivity - Unable to query Infoservice for connectivity! This might becomes a problem soon!\n");
00292        // Release the Thread, maybe it is still blocking in accept
00294         tmpSock.connect(*addr);
00295         tmpSock.close();
00296         m_pthreadConnectivtyLoop->join();
00297   goto error;
00298     }
00300     tmpSock.connect(*addr);
00301     tmpSock.close();
00302     m_pthreadConnectivtyLoop->join();
00303 
00304     if(elemRoot == NULL)
00305     {
00306         CAMsg::printMsg(LOG_ERR, "CADynaNetworking - verifyConnectivity - InfoService answer was not parsable\n");
00307   goto error;
00308     }
00309     
00310     if(getDOMChildByName(elemRoot,(UINT8*)"Result",elemRes)!=E_SUCCESS)
00311     {
00312         CAMsg::printMsg(LOG_ERR, "CADynaNetworking - verifyConnectivity - InfoService answer was not parsable\n");
00313   goto error;
00314     }
00315 
00316     if( getDOMElementValue(elemRes, res, &len)  != E_SUCCESS )
00317     {
00318         CAMsg::printMsg(LOG_ERR, "CADynaNetworking - verifyConnectivity - InfoService answer was not parsable\n");
00319         goto error;
00320     }
00321 
00322     if( strcmp( (const char*)res, "OK" ) == 0)
00323         ret = E_SUCCESS;
00324 error:
00325     delete m_pthreadConnectivtyLoop;
00326     m_pthreadConnectivtyLoop = NULL;
00327     delete addr;
00328     addr = NULL;
00329     return ret;
00330 }
00331 
00340 SINT32 CADynaNetworking::sendConnectivityRequest( DOM_Element *r_elemRoot, UINT32 a_port )
00341 {
00342     DOM_Document doc = DOM_Document::createDocument();
00343     DOM_Element elemRoot = doc.createElement("ConnectivityCheck");
00344     doc.appendChild(elemRoot);
00345     DOM_Element elemPort = doc.createElement("Port");
00346     setDOMElementValue(elemPort,(UINT32)a_port);
00347     elemRoot.appendChild(elemPort);
00348 
00349     UINT32 lenOut;
00350     UINT8* buffOut = DOM_Output::dumpToMem(doc,&lenOut);
00351     sendRandomInfoserviceRequest( (UINT8*)"/connectivity", r_elemRoot, buffOut, lenOut);
00352 
00353     return E_SUCCESS;
00354 }
00355 
00364 SINT32 CADynaNetworking::resolveInternalIp(UINT8* r_ip)
00365 {
00366     struct in_addr in;
00367     struct hostent *hent;
00368     char hostname[256];
00369     UINT32 internalIp;
00370     if (gethostname(hostname, sizeof(hostname)) < 0)
00371     {
00372         return E_UNKNOWN;
00373     }
00374     /* Maybe we are lucky ;-) */
00375     in.s_addr=inet_addr(hostname);
00376     if (in.s_addr==INADDR_NONE)
00377     {
00378         hent = (struct hostent *)gethostbyname(hostname);
00379         if(hent)
00380         {
00381             assert(hent->h_length == 4);
00382             memcpy( &in.s_addr, hent->h_addr, hent->h_length );
00383 
00384             if( isInternalIp( ntohl(in.s_addr) ) )
00385             {
00386                 /* Maybe it resolved to 127.0.0.1 or sth., we ask the interface itself*/
00387                 if( getInterfaceIp(&internalIp) == E_SUCCESS)
00388                 {
00389                     in.s_addr = internalIp;
00390                 }
00391             }
00392         }
00393         else
00394         {
00395             if( getInterfaceIp(&internalIp) == E_SUCCESS )
00396             {
00397                 in.s_addr = internalIp;
00398             }
00399         }
00400     }
00401     char* tmp = inet_ntoa(in);
00402     strcpy((char*)r_ip, tmp);
00403     return E_SUCCESS;
00404 }
00405 
00415 SINT32 CADynaNetworking::getInterfaceIp(UINT32 *r_addr)
00416 {
00417     CASocket *sock = new CASocket();
00418     sock->create();
00419     CASocketAddrINet test;
00420     // FIXME We could use an InfoService here
00421     test.setAddr((const UINT8*)"18.0.0.1", 0);
00422     sock->setSendTimeOut(1);
00423     sock->connect( test );
00424     sock->getLocalIP(r_addr);
00425 #ifdef DEBUG
00426     in_addr t;
00427     t.s_addr = *r_addr;
00428     CAMsg::printMsg(LOG_DEBUG, "Local IP is: %s\n", inet_ntoa(t));
00429 #endif
00430     sock->close();
00431 
00432     delete sock;
00433     sock = NULL;
00434     return E_SUCCESS;
00435 }
00436 
00445 SINT32 CADynaNetworking::resolveExternalIp(UINT8 *r_ip, UINT32 a_len)
00446 {
00447     UINT8 request[255];
00448 
00449     sprintf((char*) request, "/echoip");
00450 
00451     DOM_Element elemRoot;
00452     if( sendRandomInfoserviceGetRequest(request, &elemRoot) != E_SUCCESS )
00453     {
00454         CAMsg::printMsg(LOG_DEBUG, "CAInfoService::getPublicIp - Unable to query Infoservice for public IP! This will be a problem soon!\n");
00455         return E_UNKNOWN;
00456     }
00457 
00458     if(elemRoot == NULL)
00459     {
00460         CAMsg::printMsg(LOG_ERR, "CAInfoService::getPublicIp - Answer was not parsable\n");
00461         return E_UNKNOWN;
00462     }
00463     DOM_Node elemIp;
00464 
00465     if(getDOMChildByName(elemRoot,(UINT8*)"IP",elemIp)!=E_SUCCESS)
00466     {
00467         CAMsg::printMsg(LOG_ERR, "CAInfoService::getPublicIp - Answer was not parsable!\n");
00468         return E_UNKNOWN;
00469     }
00470 
00471     if( getDOMElementValue(elemIp, r_ip, &a_len)  != E_SUCCESS )
00472     {
00473         CAMsg::printMsg(LOG_ERR, "CAInfoService::getPublicIp - Answer was not parsable!\n");
00474         return E_UNKNOWN;
00475     }
00476 
00477     CAMsg::printMsg(LOG_DEBUG, "Public IP is: %s\n", (char*)r_ip);
00478     return E_SUCCESS;
00479 }
00480 
00481 bool CADynaNetworking::isInternalIp(UINT32 a_ip)
00482 {
00483     if (((a_ip & 0xff000000) == 0x0a000000) || /*       10/8 */
00484             ((a_ip & 0xff000000) == 0x00000000) || /*        0/8 */
00485             ((a_ip & 0xff000000) == 0x7f000000) || /*      127/8 */
00486             ((a_ip & 0xffff0000) == 0xa9fe0000) || /* 169.254/16 */
00487             ((a_ip & 0xfff00000) == 0xac100000) || /*  172.16/12 */
00488             ((a_ip & 0xffff0000) == 0xc0a80000))   /* 192.168/16 */
00489         return true;
00490     return false;
00491 }
00492 
00493 #endif //DYNAMIC_MIX