Mixe for Privacy and Anonymity in the Internet
CADynaNetworking.cpp
Go to the documentation of this file.
1 /*
2 Copyright (c) 2000, The JAP-Team
3 All rights reserved.
4 Redistribution and use in source and binary forms, with or without modification,
5 are permitted provided that the following conditions are met:
6 
7  - Redistributions of source code must retain the above copyright notice,
8  this list of conditions and the following disclaimer.
9 
10  - Redistributions in binary form must reproduce the above copyright notice,
11  this list of conditions and the following disclaimer in the documentation and/or
12  other materials provided with the distribution.
13 
14  - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors
15  may be used to endorse or promote products derived from this software without specific
16  prior written permission.
17 
18 
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
20 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
21 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS
22 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
27 */
28 
29 
30 #include "StdAfx.h"
31 #ifdef DYNAMIC_MIX
32 
33 #include "CADynaNetworking.hpp"
34 #include "CASocket.hpp"
35 #include "CASocketAddrINet.hpp"
36 #include "CAHttpClient.hpp"
37 #include "CACmdLnOptions.hpp"
38 #include "CASocketAddr.hpp"
39 #include "xml/DOM_Output.hpp"
40 
41 CADynaNetworking::CADynaNetworking() : CAInfoServiceAware()
42  {
43  }
44 
45 CADynaNetworking::~CADynaNetworking()
46  {
47  }
48 
63 SINT32 CADynaNetworking::updateNetworkConfiguration(UINT16 a_port)
64  {
65  UINT8 internalIp[255];
66  UINT8 externalIp[255];
67  UINT32 len = 255;
68 
69  if( resolveInternalIp( internalIp ) == E_UNKNOWN )
70  {
71  return E_UNKNOWN;
72  }
73  if( resolveExternalIp( externalIp, len ) == E_UNKNOWN )
74  {
75  return E_UNKNOWN;
76  }
77 
78  // Beware! This resets all information abount ListenerInterfaces!
79  pglobalOptions->resetNetworkConfiguration();
80 
81  DOM_Document doc;
82  pglobalOptions->getMixXml(doc);
83  DOM_Element elemRoot = doc.getDocumentElement();
84  DOM_Element elemListeners;
85  getDOMChildByName(elemRoot,(UINT8*)"ListenerInterfaces",elemListeners,false);
86  if(elemListeners == NULL)
87  {
88  elemListeners = doc.createElement("ListenerInterfaces");
89  elemRoot.appendChild( elemListeners );
90  }
91 
92  if(strcmp((char*)internalIp, (char*)externalIp) == 0)
93  {
94  /* External IP == Internal IP, wonderful */
95  createListenerInterface( elemListeners, doc, internalIp, a_port, false, false);
96  return E_SUCCESS;
97  }
98  createListenerInterface( elemListeners, doc, internalIp, a_port, true, false);
99  createListenerInterface( elemListeners, doc, externalIp, a_port, false, true);
100 
101 
102 #ifdef DEBUG
103  UINT8* buff = DOM_Output::dumpToMem(doc,&len);
104  CAMsg::printMsg(LOG_CRIT, (char*)buff);
105 #endif
106  return E_SUCCESS;
107  }
108 
121 SINT32 CADynaNetworking::createListenerInterface(DOM_Element r_elemListeners, DOM_Document a_ownerDoc,const UINT8 *a_ip, UINT32 a_port, bool a_bHidden, bool a_bVirtual)
122  {
123  DOM_Element elemTmp;
124 
125  DOM_Element elemListener=a_ownerDoc.createElement("ListenerInterface");
126  if( a_bHidden )
127  {
128  elemListener.setAttribute("hidden", "True");
129  }
130 
131  if( a_bVirtual )
132  {
133  elemListener.setAttribute("virtual", "True");
134  }
135  r_elemListeners.appendChild(elemListener);
136  elemTmp=a_ownerDoc.createElement("Port");
137  setDOMElementValue(elemTmp,a_port);
138  elemListener.appendChild(elemTmp);
139  elemTmp=a_ownerDoc.createElement("NetworkProtocol");
140  setDOMElementValue(elemTmp,(UINT8*)"RAW/TCP");
141  elemListener.appendChild(elemTmp);
142  elemTmp=a_ownerDoc.createElement("IP");
143  setDOMElementValue(elemTmp, a_ip);
144  elemListener.appendChild(elemTmp);
145 #ifdef DEBUG
146  UINT32 len;
147  UINT8* buff = DOM_Output::dumpToMem(elemListener, &len);
148  CAMsg::printMsg(LOG_CRIT, "%s\n",(char*)buff);
149 #endif
150 
151  pglobalOptions->addListenerInterface(elemListener);
152  return E_SUCCESS;
153 }
154 
160 CAListenerInterface *CADynaNetworking::getWorkingListenerInterface()
161 {
162  UINT32 interfaces = pglobalOptions->getListenerInterfaceCount();
163  CAListenerInterface *pListener = NULL;
164  for( UINT32 i = 1; i <= interfaces; i++ )
165  {
166  pListener = pglobalOptions->getListenerInterface(i);
167  if(!pListener->isVirtual())
168  break;
169  delete pListener;
170  pListener=NULL;
171  }
172  return pListener;
173 }
174 
180 static THREAD_RETURN ConnectivityLoop(void *p)
181 {
182  INIT_STACK;
183  BEGIN_STACK("CADynaNetworking::ConnectivityLoop");
184 
185  CADynaNetworking* parent = (CADynaNetworking*)p;
186  char buff[1024];
187  UINT32 len = 1024;
188  SINT32 rLen;
189  char *pechoRequest = NULL;
190 
191 #ifdef DEBUG
192  CAMsg::printMsg(LOG_DEBUG, "CADynaNetworking - ConnectivityLoop() started\n");
193 #endif
194  CAListenerInterface *pListener = parent->getWorkingListenerInterface();
195  if(pListener == NULL)
196  {
197  CAMsg::printMsg(LOG_DEBUG, "CADynaNetworking - ConnectivityLoop - No valid ListenerInterface found, aborting\n");
199  }
200 
201  CASocket serverSocket;
202  CASocket socket;
203  CASocketAddrINet *address = (CASocketAddrINet*)pListener->getAddr();
204  if( serverSocket.listen( *address ) != E_SUCCESS )
205  {
206  CAMsg::printMsg(LOG_ERR, "CADynaNetworking - ConnectivityLoop - Unable to listen to standard port, aborting\n");
207  goto EXIT;
208  }
209 #ifdef DEBUG
210  CAMsg::printMsg(LOG_ERR, "CADynaNetworking - ConnectivityLoop - Ok, listening...\n");
211 #endif
212  if( serverSocket.accept(socket) != E_SUCCESS)
213  {
214  CAMsg::printMsg(LOG_ERR, "CADynaNetworking - ConnectivityLoop - Unable to accept on standard port, aborting\n");
215  goto EXIT;
216  }
217 #ifdef DEBUG
218  CAMsg::printMsg(LOG_ERR, "CADynaNetworking - ConnectivityLoop - Ok, i accepted\n");
219 #endif
220  rLen = socket.receive( (UINT8*)buff, len );
221 #ifdef DEBUG
222  CAMsg::printMsg(LOG_DEBUG, "CADynaNetworking - ConnectivityLoop - Received %i Bits: (%s)\n", rLen, buff);
223 #endif
224  pechoRequest = new char[rLen+1];
225  strncpy(pechoRequest, buff, rLen+1);
226 #ifdef DEBUG
227  CAMsg::printMsg(LOG_DEBUG, "CADynaNetworking - ConnectivityLoop - echoRequest: (%s)\n", pechoRequest);
228  CAMsg::printMsg(LOG_DEBUG, "CADynaNetworking - ConnectivityLoop - Will send: %i chars, %s\n", strlen(pechoRequest), pechoRequest);
229 
230 #endif
231  socket.send( (const UINT8*)pechoRequest, rLen);
232  delete pechoRequest;
233  pechoRequest = NULL;
234 EXIT:
235  FINISH_STACK("CADynaNetworking::ConnectivityLoop");
236 
237  delete address;
238  address = NULL;
239  socket.close();
240  serverSocket.close();
242 }
243 
255 SINT32 CADynaNetworking::verifyConnectivity()
256 {
257  SINT32 ret = E_UNKNOWN;
258  DOM_Element elemRoot;
259  DOM_Node elemRes;
260  UINT8 res[255];
261  UINT32 len=255;
262 
263  CAThread* m_pthreadConnectivtyLoop = new CAThread((UINT8*)"ConnectivityThread");
264  m_pthreadConnectivtyLoop->setMainLoop(ConnectivityLoop);
265  // 1, 3+4)
266  m_pthreadConnectivtyLoop->start(this);
267 
268  //@todo FIXME We have a race condition here between the sending of the request to the infoservice and our m_pthreadConnectivtyLoop thread listenting
269  // on the port!
270  msSleep(1000);
271  // 2 + 5)
272  CAListenerInterface *pListener = getWorkingListenerInterface();
273 
274  if(pListener == NULL)
275  {
276  CAMsg::printMsg( LOG_DEBUG, "Didn't find a useable ListenerInterface, exiting\n");
277  // Well, if we can't get a working ListenerInterface, the Thread should't either and return to us
278  m_pthreadConnectivtyLoop->join();
279  return E_UNKNOWN;
280  }
281  CASocketAddrINet *addr = (CASocketAddrINet*)pListener->getAddr();
282  UINT16 port = addr->getPort();
283  delete pListener;
284  pListener = NULL;
285  // End Fixme
286 
287  CASocket tmpSock;
288 
289  if( sendConnectivityRequest( &elemRoot, port) != E_SUCCESS )
290  {
291  CAMsg::printMsg(LOG_DEBUG, "CADynaNetworking - verifyConnectivity - Unable to query Infoservice for connectivity! This might becomes a problem soon!\n");
292  // Release the Thread, maybe it is still blocking in accept
294  tmpSock.connect(*addr);
295  tmpSock.close();
296  m_pthreadConnectivtyLoop->join();
297  goto error;
298  }
300  tmpSock.connect(*addr);
301  tmpSock.close();
302  m_pthreadConnectivtyLoop->join();
303 
304  if(elemRoot == NULL)
305  {
306  CAMsg::printMsg(LOG_ERR, "CADynaNetworking - verifyConnectivity - InfoService answer was not parsable\n");
307  goto error;
308  }
309 
310  if(getDOMChildByName(elemRoot,(UINT8*)"Result",elemRes)!=E_SUCCESS)
311  {
312  CAMsg::printMsg(LOG_ERR, "CADynaNetworking - verifyConnectivity - InfoService answer was not parsable\n");
313  goto error;
314  }
315 
316  if( getDOMElementValue(elemRes, res, &len) != E_SUCCESS )
317  {
318  CAMsg::printMsg(LOG_ERR, "CADynaNetworking - verifyConnectivity - InfoService answer was not parsable\n");
319  goto error;
320  }
321 
322  if( strcmp( (const char*)res, "OK" ) == 0)
323  ret = E_SUCCESS;
324 error:
325  delete m_pthreadConnectivtyLoop;
326  m_pthreadConnectivtyLoop = NULL;
327  delete addr;
328  addr = NULL;
329  return ret;
330 }
331 
340 SINT32 CADynaNetworking::sendConnectivityRequest( DOM_Element *r_elemRoot, UINT32 a_port )
341 {
342  DOM_Document doc = DOM_Document::createDocument();
343  DOM_Element elemRoot = doc.createElement("ConnectivityCheck");
344  doc.appendChild(elemRoot);
345  DOM_Element elemPort = doc.createElement("Port");
346  setDOMElementValue(elemPort,(UINT32)a_port);
347  elemRoot.appendChild(elemPort);
348 
349  UINT32 lenOut;
350  UINT8* buffOut = DOM_Output::dumpToMem(doc,&lenOut);
351  sendRandomInfoserviceRequest( (UINT8*)"/connectivity", r_elemRoot, buffOut, lenOut);
352 
353  return E_SUCCESS;
354 }
355 
364 SINT32 CADynaNetworking::resolveInternalIp(UINT8* r_ip)
365 {
366  struct in_addr in;
367  struct hostent *hent;
368  char hostname[256];
369  UINT32 internalIp;
370  if (gethostname(hostname, sizeof(hostname)) < 0)
371  {
372  return E_UNKNOWN;
373  }
374  /* Maybe we are lucky ;-) */
375  in.s_addr=inet_addr(hostname);
376  if (in.s_addr==INADDR_NONE)
377  {
378  hent = (struct hostent *)gethostbyname(hostname);
379  if(hent)
380  {
381  assert(hent->h_length == 4);
382  memcpy( &in.s_addr, hent->h_addr, hent->h_length );
383 
384  if( isInternalIp( ntohl(in.s_addr) ) )
385  {
386  /* Maybe it resolved to 127.0.0.1 or sth., we ask the interface itself*/
387  if( getInterfaceIp(&internalIp) == E_SUCCESS)
388  {
389  in.s_addr = internalIp;
390  }
391  }
392  }
393  else
394  {
395  if( getInterfaceIp(&internalIp) == E_SUCCESS )
396  {
397  in.s_addr = internalIp;
398  }
399  }
400  }
401  char* tmp = inet_ntoa(in);
402  strcpy((char*)r_ip, tmp);
403  return E_SUCCESS;
404 }
405 
415 SINT32 CADynaNetworking::getInterfaceIp(UINT32 *r_addr)
416 {
417  CASocket *sock = new CASocket();
418  sock->create();
419  CASocketAddrINet test;
420  // FIXME We could use an InfoService here
421  test.setAddr((const UINT8*)"18.0.0.1", 0);
422  sock->setSendTimeOut(1);
423  sock->connect( test );
424  sock->getLocalIP(r_addr);
425 #ifdef DEBUG
426  in_addr t;
427  t.s_addr = *r_addr;
428  CAMsg::printMsg(LOG_DEBUG, "Local IP is: %s\n", inet_ntoa(t));
429 #endif
430  sock->close();
431 
432  delete sock;
433  sock = NULL;
434  return E_SUCCESS;
435 }
436 
445 SINT32 CADynaNetworking::resolveExternalIp(UINT8 *r_ip, UINT32 a_len)
446 {
447  UINT8 request[255];
448 
449  sprintf((char*) request, "/echoip");
450 
451  DOM_Element elemRoot;
452  if( sendRandomInfoserviceGetRequest(request, &elemRoot) != E_SUCCESS )
453  {
454  CAMsg::printMsg(LOG_DEBUG, "CAInfoService::getPublicIp - Unable to query Infoservice for public IP! This will be a problem soon!\n");
455  return E_UNKNOWN;
456  }
457 
458  if(elemRoot == NULL)
459  {
460  CAMsg::printMsg(LOG_ERR, "CAInfoService::getPublicIp - Answer was not parsable\n");
461  return E_UNKNOWN;
462  }
463  DOM_Node elemIp;
464 
465  if(getDOMChildByName(elemRoot,(UINT8*)"IP",elemIp)!=E_SUCCESS)
466  {
467  CAMsg::printMsg(LOG_ERR, "CAInfoService::getPublicIp - Answer was not parsable!\n");
468  return E_UNKNOWN;
469  }
470 
471  if( getDOMElementValue(elemIp, r_ip, &a_len) != E_SUCCESS )
472  {
473  CAMsg::printMsg(LOG_ERR, "CAInfoService::getPublicIp - Answer was not parsable!\n");
474  return E_UNKNOWN;
475  }
476 
477  CAMsg::printMsg(LOG_DEBUG, "Public IP is: %s\n", (char*)r_ip);
478  return E_SUCCESS;
479 }
480 
481 bool CADynaNetworking::isInternalIp(UINT32 a_ip)
482 {
483  if (((a_ip & 0xff000000) == 0x0a000000) || /* 10/8 */
484  ((a_ip & 0xff000000) == 0x00000000) || /* 0/8 */
485  ((a_ip & 0xff000000) == 0x7f000000) || /* 127/8 */
486  ((a_ip & 0xffff0000) == 0xa9fe0000) || /* 169.254/16 */
487  ((a_ip & 0xfff00000) == 0xac100000) || /* 172.16/12 */
488  ((a_ip & 0xffff0000) == 0xc0a80000)) /* 192.168/16 */
489  return true;
490  return false;
491 }
492 
493 #endif //DYNAMIC_MIX
#define INIT_STACK
Definition: CAThread.hpp:48
#define BEGIN_STACK(methodName)
Definition: CAThread.hpp:49
#define FINISH_STACK(methodName)
Definition: CAThread.hpp:50
SINT32 getDOMElementValue(const DOMNode *const pElem, UINT8 *value, UINT32 *valuelen)
Returns the content of the text node(s) under elem as null-terminated C String.
Definition: CAUtil.cpp:746
SINT32 setDOMElementValue(DOMElement *pElem, SINT32 value)
Definition: CAUtil.cpp:939
SINT32 getDOMChildByName(const DOMNode *pNode, const char *const name, DOMElement *&child, bool deep)
Definition: CAUtil.cpp:458
SINT32 msSleep(UINT32 ms)
Sleeps ms milliseconds.
Definition: CAUtil.cpp:406
#define INADDR_NONE
Definition: StdAfx.h:479
#define THREAD_RETURN_ERROR
Definition: StdAfx.h:541
#define THREAD_RETURN
Definition: StdAfx.h:540
#define THREAD_RETURN_SUCCESS
Definition: StdAfx.h:542
unsigned short UINT16
Definition: basetypedefs.h:133
signed int SINT32
Definition: basetypedefs.h:132
unsigned char UINT8
Definition: basetypedefs.h:135
unsigned int UINT32
Definition: basetypedefs.h:131
CASocketAddr * getAddr() const
static SINT32 printMsg(UINT32 typ, const char *format,...)
Writes a given message to the log.
Definition: CAMsg.cpp:251
This class represents a socket address for Internet (IP) connections.
SINT32 setAddr(const UINT8 *szIP, UINT16 port)
Sets the address to szIP and port.
UINT16 getPort() const
Returns the port value of the address.
virtual SINT32 receive(UINT8 *buff, UINT32 len)
Will receive some bytes from the socket.
Definition: CASocket.cpp:645
virtual SINT32 listen(const CASocketAddr &psa)
Starts listening on address psa.
Definition: CASocket.cpp:142
virtual SINT32 send(const UINT8 *buff, UINT32 len)
Sends some data over the network.
Definition: CASocket.cpp:400
virtual SINT32 setSendTimeOut(UINT32 msTimeOut)
Definition: CASocket.cpp:883
virtual SINT32 accept(CASocket &s)
Accepts a new connection.
Definition: CASocket.cpp:192
virtual SINT32 create()
Definition: CASocket.cpp:73
virtual SINT32 getLocalIP(UINT8 r_Ip[4])
LERNGRUPPE Returns the source address of the socket.
Definition: CASocket.cpp:801
virtual SINT32 close()
Definition: CASocket.cpp:351
virtual SINT32 connect(const CASocketAddr &psa)
Definition: CASocket.hpp:64
SINT32 start(void *param, bool bDaemon=false, bool bSilent=false)
Starts the execution of the main function of this thread.
Definition: CAThread.cpp:115
SINT32 setMainLoop(THREAD_MAIN_TYP fnc)
Sets the main function which will be executed within this thread.
Definition: CAThread.hpp:148
SINT32 join()
Waits for the main function to finish execution.
Definition: CAThread.cpp:187
static SINT32 dumpToMem(const DOMNode *node, UINT8 *buff, UINT32 *size)
Dumps the node and all childs into buff.
Definition: DOM_Output.hpp:161
const SINT32 E_SUCCESS
Definition: errorcodes.hpp:2
#define E_UNKNOWN
Definition: errorcodes.hpp:3
UINT16 len
Definition: typedefs.hpp:0