Statistics
| Branch: | Revision:

ml / util / stun.c @ 11fce711

History | View | Annotate | Download (25.9 KB)

1
/*
2
 *          Policy Management
3
 *
4
 *          NEC Europe Ltd. PROPRIETARY INFORMATION
5
 *
6
 * This software is supplied under the terms of a license agreement
7
 * or nondisclosure agreement with NEC Europe Ltd. and may not be
8
 * copied or disclosed except in accordance with the terms of that
9
 * agreement.
10
 *
11
 *      Copyright (c) 2009 NEC Europe Ltd. All Rights Reserved.
12
 *
13
 * Authors: Kristian Beckers  <beckers@nw.neclab.eu>
14
 *    Sebastian Kiesel  <kiesel@nw.neclab.eu>
15
 *          
16
 *
17
 * NEC Europe Ltd. DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED,
18
 * INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY
19
 * AND FITNESS FOR A PARTICULAR PURPOSE AND THE WARRANTY AGAINST LATENT
20
 * DEFECTS, WITH RESPECT TO THE PROGRAM AND THE ACCOMPANYING
21
 * DOCUMENTATION.
22
 *
23
 * No Liability For Consequential Damages IN NO EVENT SHALL NEC Europe
24
 * Ltd., NEC Corporation OR ANY OF ITS SUBSIDIARIES BE LIABLE FOR ANY
25
 * DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS
26
 * OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF INFORMATION, OR
27
 * OTHER PECUNIARY LOSS AND INDIRECT, CONSEQUENTIAL, INCIDENTAL,
28
 * ECONOMIC OR PUNITIVE DAMAGES) ARISING OUT OF THE USE OF OR INABILITY
29
 * TO USE THIS PROGRAM, EVEN IF NEC Europe Ltd. HAS BEEN ADVISED OF THE
30
 * POSSIBILITY OF SUCH DAMAGES.
31
 *
32
 *     THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
33
 */
34

    
35
#include <assert.h>
36
#include <stdlib.h>   
37
#include <unistd.h>
38
#include <errno.h>
39
#include <string.h>
40

    
41
#include <stdio.h> 
42
#include <unistd.h>
43

    
44
#include <sys/ioctl.h>
45
#include <sys/socket.h>
46
#include <sys/time.h>
47
#include <sys/types.h> 
48
#include <arpa/inet.h>
49

    
50
#include <fcntl.h>
51
#include <netdb.h>
52
#include <netinet/in.h>
53
//#include <arpa/nameser.h>
54
//#include <resolv.h>
55
#include <net/if.h>
56

    
57
#include "ml_log.h"
58
#include "stun.h"
59
#include "udpSocket.h"
60

    
61
/// define a structure to hold a stun address             
62
const UInt8  IPv4Family = 0x01;
63
const UInt8  IPv6Family = 0x02;
64
// define  flags                                             
65
const UInt32 ChangeIpFlag   = 0x04;
66
const UInt32 ChangePortFlag = 0x02;
67
// define  stun attributes        
68
const UInt16 MappedAddress    = 0x0001;
69
const UInt16 ResponseAddress  = 0x0002;
70
const UInt16 ChangeRequest    = 0x0003;
71
const UInt16 SourceAddress    = 0x0004;
72
const UInt16 ChangedAddress   = 0x0005;
73
const UInt16 Username         = 0x0006;
74
const UInt16 Password         = 0x0007;
75
const UInt16 MessageIntegrity = 0x0008;
76
const UInt16 ErrorCode        = 0x0009;
77
const UInt16 UnknownAttribute = 0x000A;
78
const UInt16 ReflectedFrom    = 0x000B;
79
const UInt16 XorMappedAddress = 0x8020;
80
const UInt16 XorOnly          = 0x0021;
81
const UInt16 ServerName       = 0x8022;
82
const UInt16 SecondaryAddress = 0x8050; // Non standard extention       
83
// define types for a stun message                                 
84
const UInt16 BindRequestMsg               = 0x0001;
85
const UInt16 BindResponseMsg              = 0x0101;
86
const UInt16 BindErrorResponseMsg         = 0x0111;
87
const UInt16 SharedSecretRequestMsg       = 0x0002;
88
const UInt16 SharedSecretResponseMsg      = 0x0102;
89
const UInt16 SharedSecretErrorResponseMsg = 0x0112;
90

    
91
void pmtu_error_cb_stun(char *buf,int bufsize){
92

    
93
  printf("error: MTU size of stun message too big !");
94

    
95
}
96

    
97
/* sends a request to a stun server */
98
int send_stun_request(const int udpSocket,struct sockaddr_in *stunServ)
99
{
100

    
101
  assert( sizeof(UInt8 ) == 1 );
102
  assert( sizeof(UInt16) == 2 );
103
  assert( sizeof(UInt32) == 4 );
104

    
105
  bool verbose = false;
106
  
107
  //set the verbose mode 
108
  verbose = true;
109

    
110
  StunMessage req;
111
  memset(&req, 0, sizeof(StunMessage));
112

    
113
  StunAtrString username;
114
  StunAtrString password;
115
  username.sizeValue = 0;
116
  password.sizeValue = 0;
117

    
118
  /* build a stun request message  */
119
  /* creates a stun message struct with the given atributes  */
120
  stunBuildReqSimple( &req, username,
121
                      false , false ,
122
                      0x0c );
123

    
124
  /* buffer for the stun request  */
125
  char buf[STUN_MAX_MESSAGE_SIZE];
126
  int len = STUN_MAX_MESSAGE_SIZE;
127

    
128
  /* encode the stun message  */
129
  len = stunEncodeMessage( req, buf, len, password, verbose);
130

    
131
  struct iovec iov;
132
  iov.iov_len = len;
133
  iov.iov_base = buf;
134
  sendPacket(udpSocket,&iov,1,stunServ);
135

    
136
  return 0;
137

    
138
}
139

    
140
/* sends a keep alive to a server  */
141
int send_stun_keep_alive(const int udpSocket,struct sockaddr_in *stunServ)
142
{
143

    
144
  send_stun_request(udpSocket,stunServ);
145

    
146
  return 0;
147
}
148

    
149
/* parses a given stun message and sets the refelxive address  */
150
int recv_stun_message(char *msgbuf,int msgLen,StunMessage *response){
151

    
152
  //StunMessage resp;
153
  //memset(&resp, 0, sizeof(StunMessage));
154
  int returnValue = 0;
155
  //bool verbose = true;
156
  bool verbose = false;
157

    
158
  //printf("still alive 4 \n ");
159
  //if ( verbose ) printf("Got a response \n");
160

    
161
  bool ok = stunParseMessage(msgbuf, msgLen, response, verbose );
162

    
163
  if (!ok){
164
    
165
    returnValue = 1;
166
    error("parse STUN message failed \n");
167

    
168
  }
169

    
170
      UInt32 ip_addr = response->mappedAddress.ipv4.addr;
171
      char mapped_addr[16];
172
      int length;
173
      length = sprintf(mapped_addr,"%d.%d.%d.%d",(ip_addr >> 24) & 0xff,(ip_addr >> 16) & 0xff,(ip_addr >> 8) & 0xff,ip_addr & 0xff);
174

    
175
      ip_addr = response->changedAddress.ipv4.addr;
176
      char changed_addr[16];
177
      length = sprintf(changed_addr,"%d.%d.%d.%d",(ip_addr >> 24) & 0xff,(ip_addr >> 16)\
178
              & 0xff,(ip_addr >> 8) & 0xff,ip_addr & 0xff);
179

    
180
  if ( verbose )
181
  {
182

    
183
      info( "\t mappedAddr= ipv4 %s port %d \n \t changedAddr= ipv4 %s port %d \n",
184
              mapped_addr ,
185
              response->mappedAddress.ipv4.port,
186
              changed_addr,
187
              response->changedAddress.ipv4.port);
188

    
189
      }
190
  debug("still here");
191

    
192
  //reflexiveAddr.sin_addr.s_addr = inet_addr(changed_addr);
193
  //reflexiveAddr->sin_addr.s_addr = inet_addr("1.1.1.1");
194
  //reflexiveAddr->sin_port = htons(resp.mappedAddress.ipv4.port);
195
  
196
  return returnValue;
197
}
198

    
199
bool 
200
stunParseAtrAddress( char* body, unsigned int hdrLen, StunAtrAddress4 *result, bool verbose )
201
{
202
   if ( hdrLen != 8 )
203
   {
204
      error("hdrlen is not 8 \n ");
205
      return false;
206
   }
207
   result->pad = *body++;
208
   result->family = *body++;
209

    
210
   if (result->family == IPv4Family)
211
   {
212

    
213
      UInt16 nport;
214
      memcpy(&nport, body, 2); body+=2;
215
      
216
      if (verbose) info("port %i \n",ntohs(nport));
217

    
218
      result->ipv4.port = ntohs(nport);
219

    
220
                
221
      UInt32 naddr;
222
      memcpy(&naddr, body, 4); body+=4;
223
      //printf("port %d \n",ntohl(naddr));
224
      
225
      if (verbose)
226
        {
227
      UInt32 ip_addr = ntohl(naddr);
228
      char str_p[20];
229

    
230
      sprintf(str_p,"%d.%d.%d.%d",(ip_addr >> 24) & 0xff,(ip_addr >> 16) & 0xff,(ip_addr >> 8) & 0xff,ip_addr & 0xff);          
231

    
232
      info(" ipv4 as str %s \n  ",str_p);
233
        }
234

    
235
      result->ipv4.addr = ntohl(naddr);
236

    
237
      return true;
238
   }
239

    
240
   else if (result->family == IPv6Family)
241

    
242
   {
243
      warn("ipv6 not supported  \n");
244
   }
245
   else
246
   {
247
      error("bad address family: %i \n ",result->family );
248
   }
249
        
250
   return false;
251
}
252

    
253

    
254

    
255
bool
256
stunParseMessage( char* buf, unsigned int bufLen, StunMessage *msg, bool verbose)
257
{
258
  if (verbose) info("Received stun message: %d bytes \n",bufLen);
259
   memset(msg, 0, sizeof(msg));
260
        
261
   if (sizeof(StunMsgHdr) > bufLen)
262
   {
263
     error("Bad message \n");
264
      return false;
265
   }
266
        
267
   memcpy(&msg->msgHdr, buf, sizeof(StunMsgHdr));
268
   msg->msgHdr.msgType = ntohs(msg->msgHdr.msgType);
269
   msg->msgHdr.msgLength = ntohs(msg->msgHdr.msgLength);
270
        
271
   if (msg->msgHdr.msgLength + sizeof(StunMsgHdr) != bufLen)
272
   {
273
     error("Message header length doesn't match message size: %d - %d \n"
274
            ,msg->msgHdr.msgLength,bufLen);
275
      return false;
276
   }
277
        
278
   char* body = buf + sizeof(StunMsgHdr);
279
   unsigned int size = msg->msgHdr.msgLength;
280
        
281
   debug("bytes after header = %d",size);
282
        
283
   while ( size > 0 )
284
   {
285
      // !jf! should check that there are enough bytes left in the buffer
286
                
287
     StunAtrHdr* attr = (StunAtrHdr*)(body);
288
                
289
      unsigned int attrLen = ntohs(attr->length);
290
      int atrType = ntohs(attr->type);
291
                
292
      //if (verbose) clog << "Found attribute type=" << AttrNames[atrType] << " length=" << attrLen << endl;
293
      if ( attrLen+4 > size ) 
294
      {
295
        debug( "claims attribute is larger than size of message " \
296
                "(attribute type= %d \n" ,atrType);
297
         return false;
298
      }
299
                
300
      body += 4; // skip the length and type in attribute header
301
      size -= 4;
302
                
303
      if( atrType == MappedAddress)
304
      { 
305
        msg->hasMappedAddress = true;
306
        //printf("has mapped address \n");
307
        if ( stunParseAtrAddress(body, attrLen, &msg->mappedAddress, verbose) == false)
308
            {
309
                debug("problem parsing MappedAddress \n");
310
               return false;
311
            }
312
            else
313
            {
314
              if (verbose) {info("MappedAddress -------------------\n");}
315
            }
316
                                        
317
      }else 
318
      if (atrType == ResponseAddress)
319
        {
320
            msg->hasResponseAddress = true;
321
            if ( stunParseAtrAddress(  body,  attrLen,  &msg->responseAddress, verbose )== false )
322
            {
323
                    debug("problem parsing ResponseAddress \n");
324
              return false;
325
            }
326
            else
327
            {
328
              if (verbose) {info("ResponseAddress ---------------------\n");}
329
            }
330
             
331
        }else if(atrType == ChangeRequest)
332
        {
333
            msg->hasChangeRequest = true;
334
            if (stunParseAtrChangeRequest( body, attrLen, &msg->changeRequest) == false)
335
            {
336
                    debug("problem parsing ChangeRequest \n");
337
               return false;
338
            }
339
            else
340
            {
341
              if (verbose) info("ChangeRequest = %i \n",(int)&msg->changeRequest.value);
342
            }
343
            
344
        } else if (atrType == SourceAddress)
345
        {
346
            msg->hasSourceAddress = true;
347
            if ( stunParseAtrAddress(  body,  attrLen,  &msg->sourceAddress, verbose )== false )
348
            {
349
                    debug("problem parsing SourceAddress \n");
350
               return false;
351
            }
352
            else
353
            {
354
              if (verbose) info("SourceAddress ------------------\n");
355
            }
356
        } else if (atrType ==  ChangedAddress)
357
        {
358
            msg->hasChangedAddress = true;
359
            if ( stunParseAtrAddress(  body,  attrLen, &msg->changedAddress, verbose )== false )
360
            {
361
                    debug("problem parsing ChangedAddress \n");
362
               return false;
363
            }
364
            else
365
            {
366
              if (verbose) info("ChangedAddress = ---------------------\n");
367
            }
368
        } else if (atrType ==  Username) 
369
        {
370
            msg->hasUsername = true;
371
            if (stunParseAtrString( body, attrLen, &msg->username) == false)
372
            {
373
                    debug("problem parsing Username \n");
374
               return false;
375
            }
376
            else
377
            {
378
              if (verbose) info("Username = %s \n",msg->username.value);
379
            }
380
        }else if (atrType ==  Password) 
381
         {
382
            msg->hasPassword = true;
383
            if (stunParseAtrString( body, attrLen, &msg->password) == false)
384
            {
385
              debug("problem parsing Password \n");
386
               return false;
387
            }
388
            else
389
            {
390
              if (verbose) info("Password = %s \n",(char *)&msg->password.value);
391
            }
392
         }else if (atrType == MessageIntegrity)
393
        {
394
            msg->hasMessageIntegrity = true;
395
            if (stunParseAtrIntegrity( body, attrLen,&msg->messageIntegrity) == false)
396
            {
397
              debug("problem parsing MessageIntegrity \n");
398
               return false;
399
            }
400
            else
401
            {
402
               //if (verbose) clog << "MessageIntegrity = " << msg.messageIntegrity.hash << endl;
403
            }
404
                                        
405
            // read the current HMAC
406
            // look up the password given the user of given the transaction id 
407
            // compute the HMAC on the buffer
408
            // decide if they match or not
409
          
410
        } else if (atrType == ErrorCode)
411
        {
412
            msg->hasErrorCode = true;
413
            if (stunParseAtrError(body, attrLen, &msg->errorCode) == false)
414
            {
415
              debug("problem parsing ErrorCode \n");
416
               return false;
417
            }
418
            else
419
            {
420
              if (verbose) info("ErrorCode = %d %d %s \n",(int)(msg->errorCode.errorClass)                                 ,(int)(msg->errorCode.number)
421
                                 ,msg->errorCode.reason);
422
            }
423
                                        
424
        } else if (atrType == UnknownAttribute)
425
        {                        
426
            msg->hasUnknownAttributes = true;
427
            if (stunParseAtrUnknown(body, attrLen,&msg->unknownAttributes) == false)
428
            {
429
              debug("problem parsing UnknownAttribute \n");
430
               return false;
431
            }
432
        } else if (atrType == ReflectedFrom)
433
        {
434
            msg->hasReflectedFrom = true;
435
            if ( stunParseAtrAddress(  body,  attrLen,  &msg->reflectedFrom, verbose ) == false )
436
            {
437
              debug("problem parsing ReflectedFrom \n");
438
               return false;
439
            }
440
        } else if (atrType == XorMappedAddress)
441
        {                
442
            msg->hasXorMappedAddress = true;
443
            if ( stunParseAtrAddress(  body,  attrLen,  &msg->xorMappedAddress, verbose ) == false )
444
            {
445
              debug("problem parsing XorMappedAddress \n");
446
               return false;
447
            }
448
            else
449
            {
450
              if (verbose) info("XorMappedAddress ------------------- \n");
451
            }
452
        } else if (atrType == XorOnly)
453
        {
454
            msg->xorOnly = true;
455
            if (verbose) 
456
            {
457
              debug("xorOnly = true \n");
458
            }
459
        } else if (atrType == ServerName) 
460
        {                        
461
            msg->hasServerName = true;
462
            if (stunParseAtrString( body, attrLen, &msg->serverName) == false)
463
            {
464
              debug("problem parsing ServerName \n");
465
               return false;
466
            }
467
            else
468
            {
469
              if (verbose) info("ServerName = %s \n",(char *)&msg->serverName.value);
470
            }
471
        } else if (atrType == SecondaryAddress)
472
        {
473
            msg->hasSecondaryAddress = true;
474
            if ( stunParseAtrAddress(  body,  attrLen, &msg->secondaryAddress, verbose ) == false )
475
            {
476
              debug("problem parsing secondaryAddress \n");
477
               return false;
478
            }
479
            else
480
            {
481
              if (verbose) info("SecondaryAddress ---------------- \n");
482
            }
483
        }  else 
484
        {                                
485
         
486
           if (verbose) info("Unknown attribute: %i \n",atrType);
487
            if ( atrType <= 0x7FFF ) 
488
            {
489
               return false;
490
            }
491
        }
492
   
493
                
494
      body += attrLen;
495
      size -= attrLen;
496
   }
497
    
498
   return true;
499
}
500

    
501

    
502
void
503
stunBuildReqSimple(StunMessage* msg,
504
                    const StunAtrString username,
505
                    bool changePort, bool changeIp, unsigned int id )
506
{
507
   assert( msg );
508
   memset( msg , 0 , sizeof(*msg) );
509
        
510
   msg->msgHdr.msgType = BindRequestMsg;
511

    
512
   int i;        
513
   for (i=0; i<16; i=i+4 )
514
   {
515
      assert(i+3<16);
516
      int r = stunRand();
517
      msg->msgHdr.id.octet[i+0]= r>>0;
518
      msg->msgHdr.id.octet[i+1]= r>>8;
519
      msg->msgHdr.id.octet[i+2]= r>>16;
520
      msg->msgHdr.id.octet[i+3]= r>>24;
521
   }
522
        
523
   if ( id != 0 )
524
   {
525
      msg->msgHdr.id.octet[0] = id; 
526
   }
527
        
528
   msg->hasChangeRequest = true;
529
   msg->changeRequest.value =(changeIp?ChangeIpFlag:0) | 
530
      (changePort?ChangePortFlag:0);
531
        
532
   if ( username.sizeValue > 0 )
533
   {
534
      msg->hasUsername = true;
535
      msg->username = username;
536
   }
537
}
538

    
539

    
540
unsigned int
541
stunEncodeMessage( const StunMessage msg, 
542
                   char* buf, 
543
                   unsigned int bufLen, 
544
                   const StunAtrString password, 
545
                   bool verbose)
546
{
547
   assert(bufLen >= sizeof(StunMsgHdr));
548
   char* ptr = buf;
549
        
550
   ptr = encode16(ptr, msg.msgHdr.msgType);
551
   char* lengthp = ptr;
552
   ptr = encode16(ptr, 0);
553
   ptr = encode(ptr, (const char*)(msg.msgHdr.id.octet), sizeof(msg.msgHdr.id));
554
        
555
   if (verbose) debug("Encoding stun message: ");
556

    
557
   if (msg.hasMappedAddress)
558
   {
559
     //if (verbose) info("Encoding MappedAddress: %s \n",msg.mappedAddress.ipv4);
560
      ptr = encodeAtrAddress4 (ptr, MappedAddress, msg.mappedAddress);
561
   }
562
   if (msg.hasResponseAddress)
563
   {
564
     //if (verbose) info("Encoding ResponseAddress: %s \n",msg.responseAddress.ipv4);
565
      ptr = encodeAtrAddress4(ptr, ResponseAddress, msg.responseAddress);
566
   }
567
   if (msg.hasChangeRequest)
568
   {
569
     //if (verbose) info("Encoding ChangeRequest: %s \n",msg.changeRequest.value);
570
      ptr = encodeAtrChangeRequest(ptr, msg.changeRequest);
571
   }
572
   if (msg.hasSourceAddress)
573
   {
574
     //if (verbose) info("Encoding SourceAddress: %s \n ",msg.sourceAddress.ipv4);
575
      ptr = encodeAtrAddress4(ptr, SourceAddress, msg.sourceAddress);
576
   }
577
   if (msg.hasChangedAddress)
578
   {
579
     //if (verbose) info("Encoding ChangedAddress: %s \n ",msg.changedAddress.ipv4);
580
      ptr = encodeAtrAddress4(ptr, ChangedAddress, msg.changedAddress);
581
   }
582
   if (msg.hasUsername)
583
   {
584
     if (verbose) info("Encoding Username: %s \n", msg.username.value);
585
      ptr = encodeAtrString(ptr, Username, msg.username);
586
   }
587
   if (msg.hasPassword)
588
   {
589
     if (verbose) info("Encoding Password: %s \n ",msg.password.value);
590
      ptr = encodeAtrString(ptr, Password, msg.password);
591
   }
592
   if (msg.hasErrorCode)
593
   {
594
     if (verbose) info("Encoding ErrorCode: class= %d number= %d reason= %s \n"
595
                         ,(int)msg.errorCode.errorClass  
596
                         ,(int)msg.errorCode.number 
597
                         ,msg.errorCode.reason 
598
                         );
599
                
600
      ptr = encodeAtrError(ptr, msg.errorCode);
601
   }
602
   if (msg.hasUnknownAttributes)
603
   {
604
     if (verbose) info("Encoding UnknownAttribute: ??? \n");
605
      ptr = encodeAtrUnknown(ptr, msg.unknownAttributes);
606
   }
607
   if (msg.hasReflectedFrom)
608
   {
609
     //if (verbose) info("Encoding ReflectedFrom: %s \n ",msg.reflectedFrom.ipv4);
610
      ptr = encodeAtrAddress4(ptr, ReflectedFrom, msg.reflectedFrom);
611
   }
612
   if (msg.hasXorMappedAddress)
613
   {
614
     //if (verbose) info("Encoding XorMappedAddress: %s \n ",msg.xorMappedAddress.ipv4 );
615
      ptr = encodeAtrAddress4 (ptr, XorMappedAddress, msg.xorMappedAddress);
616
   }
617
   if (msg.xorOnly)
618
   {
619
     if (verbose) info("Encoding xorOnly: \n");
620
      ptr = encodeXorOnly( ptr );
621
   }
622
   if (msg.hasServerName)
623
   {
624
     if (verbose) info("Encoding ServerName: %s \n ",msg.serverName.value);
625
      ptr = encodeAtrString(ptr, ServerName, msg.serverName);
626
   }
627
   if (msg.hasSecondaryAddress)
628
   {
629
     //if (verbose) info("Encoding SecondaryAddress: %s \n", msg.secondaryAddress.ipv4);
630
      ptr = encodeAtrAddress4 (ptr, SecondaryAddress, msg.secondaryAddress);
631
   }
632

    
633
   if (password.sizeValue > 0)
634
   {
635
     if (verbose) info("HMAC with password: %s \n ",password.value);
636
                
637
      StunAtrIntegrity integrity;
638
      //computeHmac(integrity.hash, buf, (int)(ptr-buf) , password.value, password.sizeValue);
639
      ptr = encodeAtrIntegrity(ptr, integrity);
640
   }
641
        
642
   encode16(lengthp, (UInt16)(ptr - buf - sizeof(StunMsgHdr)));
643
   return (int)(ptr - buf);
644
}
645

    
646

    
647
int 
648
stunRand()
649
{
650
   // return 32 bits of random stuff
651
   assert( sizeof(int) == 4 );
652
   static bool init=false;
653
   if ( !init )
654
   { 
655
      init = true;
656
                
657
      UInt64 tick;
658

    
659
#if defined(__GNUC__) && ( defined(__i686__) || defined(__i386__) || defined(__amd64__) )
660
      asm("rdtsc" : "=A" (tick));
661
#elif defined (__SUNPRO_CC) || defined( __sparc__ )        
662
      tick = gethrtime();
663
#elif defined(__MACH__) 
664
      int fd=open("/dev/random",O_RDONLY);
665
      read(fd,&tick,sizeof(tick));
666
      closesocket(fd);
667
#else
668
#     error Need some way to seed the random number generator 
669
#endif 
670
      int seed = (int)(tick);
671
#ifdef WIN32
672
      srand(seed);
673
#else
674
      srandom(seed);
675
#endif
676
   }
677
        
678

    
679
   return random(); 
680

    
681
}
682

    
683

    
684
UInt64
685
stunGetSystemTimeSecs()
686
{
687
   UInt64 time=0;
688
#if defined(WIN32)  
689
   SYSTEMTIME t;
690
   // CJ TODO - this probably has bug on wrap around every 24 hours
691
   GetSystemTime( &t );
692
   time = (t.wHour*60+t.wMinute)*60+t.wSecond; 
693
#else
694
   struct timeval now;
695
   gettimeofday( &now , NULL );
696
   //assert( now );
697
   time = now.tv_sec;
698
#endif
699
   return time;
700
}
701

    
702

    
703
bool
704
stunParseServerName( char* name, StunAddress4 addr)
705
{
706
   assert(name);
707
        
708
   // TODO - put in DNS SRV stuff.
709
        
710
   bool ret = stunParseHostName( name, addr.addr, addr.port, 3478); 
711
   if ( ret != true ) 
712
   {
713
       addr.port=0xFFFF;
714
   }        
715
   return ret;
716
}
717

    
718

    
719
// returns true if it scucceeded
720
bool 
721
stunParseHostName( char* peerName,
722
               UInt32 ip,
723
               UInt16 portVal,
724
               UInt16 defaultPort )
725
{
726
   struct in_addr sin_addr;
727
    
728
   char host[512];
729
   strncpy(host,peerName,512);
730
   host[512-1]='\0';
731
   char* port = NULL;
732
        
733
   int portNum = defaultPort;
734
        
735
   // pull out the port part if present.
736
   char* sep = strchr(host,':');
737
        
738
   if ( sep == NULL )
739
   {
740
      portNum = defaultPort;
741
   }
742
   else
743
   {
744
      *sep = '\0';
745
      port = sep + 1;
746
      // set port part
747
                
748
      char* endPtr=NULL;
749
                
750
      portNum = strtol(port,&endPtr,10);
751
                
752
      if ( endPtr != NULL )
753
      {
754
         if ( *endPtr != '\0' )
755
         {
756
            portNum = defaultPort;
757
         }
758
      }
759
   }
760
    
761
   if ( portNum < 1024 ) return false;
762
   if ( portNum >= 0xFFFF ) return false;
763
        
764
   // figure out the host part 
765
   struct hostent* h;
766

    
767
   h = gethostbyname( host );
768
   if ( h == NULL )
769
   {
770
     //int err = getErrno();
771
      error("error was %d \n",errno);
772
      ip = ntohl( 0x7F000001L );
773
      return false;
774
   }
775
   else
776
   {
777
      sin_addr = *(struct in_addr*)h->h_addr;
778
      ip = ntohl( sin_addr.s_addr );
779
   }
780

    
781
        
782
   portVal = portNum;
783
        
784
   return true;
785
}
786

    
787

    
788

    
789
bool 
790
stunParseAtrChangeRequest( char* body, unsigned int hdrLen, StunAtrChangeRequest *result )
791
{
792
   if ( hdrLen != 4 )
793
   {
794
      error("hdr length = %d excepcting %d \n ",hdrLen,sizeof(result));
795

    
796
      error("Incorrect size for ChangeRequest \n ");
797

    
798
      return false;
799
   }
800
   else
801
   {
802
      memcpy(&result->value, body, 4);
803
      result->value = ntohl(result->value);
804
      return true;
805
   }
806
}
807

    
808

    
809

    
810

    
811
bool 
812
stunParseAtrUnknown( char* body, unsigned int hdrLen,  StunAtrUnknown *result)
813
{
814
   if ( hdrLen >= sizeof(StunAtrUnknown) )
815
   {
816
      return false;
817
   }
818
   else
819
   {
820
      if (hdrLen % 4 != 0) return false;
821
      result->numAttributes = hdrLen / 4;
822
      int i;
823
      for (i=0; i<result->numAttributes; i++)
824
      {
825
         memcpy(&result->attrType[i], body, 2); body+=2;
826
         result->attrType[i] = ntohs(result->attrType[i]);
827
      }
828
      return true;
829
   }
830
}
831

    
832

    
833

    
834
bool 
835
stunParseAtrString( char* body, unsigned int hdrLen,  StunAtrString *result )
836
{
837
   if ( hdrLen >= STUN_MAX_STRING )
838
   {
839
     debug( "String is too large \n");
840
      return false;
841
   }
842
   else
843
   {
844
      if (hdrLen % 4 != 0)
845
      {
846
        debug("Bad length string %d \n ",hdrLen);
847
         return false;
848
      }
849
                
850
      result->sizeValue = hdrLen;
851
      memcpy(&result->value, body, hdrLen);
852
      result->value[hdrLen] = 0;
853
      return true;
854
   }
855
}
856

    
857

    
858
bool 
859
stunParseAtrIntegrity( char* body, unsigned int hdrLen,StunAtrIntegrity *result )
860
{
861
   if ( hdrLen != 20)
862
   {
863
     debug("MessageIntegrity must be 20 bytes \n");
864
      return false;
865
   }
866
   else
867
   {
868
      memcpy(&result->hash, body, hdrLen);
869
      return true;
870
   }
871
}
872

    
873

    
874
void
875
stunCreateErrorResponse(StunMessage response, int cl, int number, const char* msg)
876
{
877
   response.msgHdr.msgType = BindErrorResponseMsg;
878
   response.hasErrorCode = true;
879
   response.errorCode.errorClass = cl;
880
   response.errorCode.number = number;
881
   strcpy(response.errorCode.reason, msg);
882
}
883

    
884
bool
885
stunParseAtrError(char* body,unsigned int hdrLen,StunAtrError *result)
886
{
887
   if ( hdrLen >= sizeof(StunAtrError) )
888
   {
889
      debug("head on Error too large \n  ");
890
      return false;
891
   }
892
   else
893
   {
894
      memcpy(&result->pad, body, 2); body+=2;
895
      result->pad = ntohs(result->pad);
896
      result->errorClass = *body++;
897
      result->number = *body++;
898
                
899
      result->sizeReason = hdrLen - 4;
900
      memcpy(&result->reason, body, result->sizeReason);
901
      result->reason[result->sizeReason] = 0;
902
      return true;
903
   }
904
}
905

    
906

    
907
char* 
908
encodeAtrString(char* ptr, UInt16 type, const StunAtrString atr)
909
{
910
   assert(atr.sizeValue % 4 == 0);
911
        
912
   ptr = encode16(ptr, type);
913
   ptr = encode16(ptr, atr.sizeValue);
914
   ptr = encode(ptr, atr.value, atr.sizeValue);
915
   return ptr;
916
}
917

    
918

    
919
char* 
920
encodeAtrIntegrity(char* ptr, const StunAtrIntegrity atr)
921
{
922
   ptr = encode16(ptr, MessageIntegrity);
923
   ptr = encode16(ptr, 20);
924
   ptr = encode(ptr, atr.hash, sizeof(atr.hash));
925
   return ptr;
926
}
927

    
928
char* 
929
encodeAtrError(char* ptr, const StunAtrError atr)
930
{
931
   ptr = encode16(ptr, ErrorCode);
932
   ptr = encode16(ptr, 6 + atr.sizeReason);
933
   ptr = encode16(ptr, atr.pad);
934
   *ptr++ = atr.errorClass;
935
   *ptr++ = atr.number;
936
   ptr = encode(ptr, atr.reason, atr.sizeReason);
937
   return ptr;
938
}
939

    
940

    
941
char* 
942
encodeAtrUnknown(char* ptr, const StunAtrUnknown atr)
943
{
944
   ptr = encode16(ptr, UnknownAttribute);
945
   ptr = encode16(ptr, 2+2*atr.numAttributes);
946
   int i;
947
   for (i=0; i<atr.numAttributes; i++)
948
   {
949
      ptr = encode16(ptr, atr.attrType[i]);
950
   }
951
   return ptr;
952
}
953

    
954

    
955
char* 
956
encodeAtrAddress4(char* ptr, UInt16 type, const StunAtrAddress4 atr)
957
{
958
   ptr = encode16(ptr, type);
959
   ptr = encode16(ptr, 8);
960
   *ptr++ = atr.pad;
961
   *ptr++ = IPv4Family;
962
   ptr = encode16(ptr, atr.ipv4.port);
963
   ptr = encode32(ptr, atr.ipv4.addr);
964
        
965
   return ptr;
966
}
967

    
968

    
969
char* 
970
encodeAtrChangeRequest(char* ptr, const StunAtrChangeRequest atr)
971
{
972
   ptr = encode16(ptr, ChangeRequest);
973
   ptr = encode16(ptr, 4);
974
   ptr = encode32(ptr, atr.value);
975
   return ptr;
976
}
977

    
978
char* 
979
encodeXorOnly(char* ptr)
980
{
981
   ptr = encode16(ptr, XorOnly );
982
   return ptr;
983
}
984

    
985
char* 
986
encode(char* buf, const char* data, unsigned int length)
987
{
988
  memcpy(buf, data, length);
989
  return buf + length;
990
}
991

    
992
char* 
993
encode16(char* buf, UInt16 data)
994
{
995
   UInt16 ndata = htons(data);
996
   memcpy(buf, (void*)(&ndata), sizeof(UInt16));
997
   return buf + sizeof(UInt16);
998
}
999

    
1000
char* 
1001
encode32(char* buf, UInt32 data)
1002
{
1003
   UInt32 ndata = htonl(data);
1004
   memcpy(buf, (void*)(&ndata), sizeof(UInt32));
1005
   return buf + sizeof(UInt32);
1006
}
1007

    
1008
/// return a random number to use as a port 
1009
int
1010
stunRandomPort()
1011
{
1012
   int min=0x4000;
1013
   int max=0x7FFF;
1014
        
1015
   int ret = stunRand();
1016
   ret = ret|min;
1017
   ret = ret&max;
1018
        
1019
   return ret;
1020
}
1021

    
1022

    
1023
void
1024
toHex(const char* buffer, int bufferSize, char* output) 
1025
{
1026
   static char hexmap[] = "0123456789abcdef";
1027
        
1028
   const char* p = buffer;
1029
   char* r = output;
1030
   int i;
1031
   for (i=0; i < bufferSize; i++)
1032
   {
1033
      unsigned char temp = *p++;
1034
                
1035
      int hi = (temp & 0xf0)>>4;
1036
      int low = (temp & 0xf);
1037
                
1038
      *r++ = hexmap[hi];
1039
      *r++ = hexmap[low];
1040
   }
1041
   *r = 0;
1042
}
1043

    
1044

    
1045