Statistics
| Branch: | Revision:

ml / util / stun.c @ 9eaee13e

History | View | Annotate | Download (26 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/time.h>
45
#include <sys/types.h> 
46

    
47
#include <fcntl.h>
48

    
49
#ifndef WIN32
50
#include <sys/ioctl.h>
51
#include <sys/socket.h>
52
#include <netdb.h>
53
#include <netinet/in.h>
54
//#include <arpa/nameser.h>
55
//#include <resolv.h>
56
#include <net/if.h>
57
#include <arpa/inet.h>
58

    
59
#else
60

    
61
#include <winsock2.h>
62
#include <ws2tcpip.h>
63

    
64
#endif
65

    
66
#include "ml_log.h"
67
#include "stun.h"
68
#include "udpSocket.h"
69

    
70
#define STUN_VERBOSE false
71

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

    
102
void pmtu_error_cb_stun(char *buf,int bufsize){
103

    
104
  error("error: MTU size of stun message too big !");
105

    
106
}
107

    
108
/* sends a request to a stun server */
109
int send_stun_request(const int udpSocket,struct sockaddr_in *stunServ)
110
{
111

    
112
  assert( sizeof(UInt8 ) == 1 );
113
  assert( sizeof(UInt16) == 2 );
114
  assert( sizeof(UInt32) == 4 );
115

    
116
  bool verbose = STUN_VERBOSE;
117
  
118
  //set the verbose mode 
119
  verbose = true;
120

    
121
  StunMessage req;
122
  memset(&req, 0, sizeof(StunMessage));
123

    
124
  StunAtrString username;
125
  StunAtrString password;
126
  username.sizeValue = 0;
127
  password.sizeValue = 0;
128

    
129
  /* build a stun request message  */
130
  /* creates a stun message struct with the given atributes  */
131
  stunBuildReqSimple( &req, username,
132
                      false , false ,
133
                      0x0c );
134

    
135
  /* buffer for the stun request  */
136
  char buf[STUN_MAX_MESSAGE_SIZE];
137
  int len = STUN_MAX_MESSAGE_SIZE;
138

    
139
  /* encode the stun message  */
140
  len = stunEncodeMessage( req, buf, len, password, verbose);
141

    
142
  struct iovec iov;
143
  iov.iov_len = len;
144
  iov.iov_base = buf;
145
debug("Sending STUN %d!!!!!\n",len); 
146
  sendPacket(udpSocket,&iov,1,stunServ);
147

    
148
  return 0;
149

    
150
}
151

    
152
/* sends a keep alive to a server  */
153
int send_stun_keep_alive(const int udpSocket,struct sockaddr_in *stunServ)
154
{
155

    
156
  send_stun_request(udpSocket,stunServ);
157

    
158
  return 0;
159
}
160

    
161
/* parses a given stun message and sets the refelxive address  */
162
int recv_stun_message(char *msgbuf,int msgLen,StunMessage *response){
163

    
164
  //StunMessage resp;
165
  //memset(&resp, 0, sizeof(StunMessage));
166
  int returnValue = 0;
167
  //bool verbose = true;
168
  bool verbose = STUN_VERBOSE;
169

    
170
  //debug("still alive 4 \n ");
171
  //if ( verbose ) info("Got a response \n");
172

    
173
  bool ok = stunParseMessage(msgbuf, msgLen, response, verbose );
174

    
175
  if (!ok){
176
    
177
    returnValue = 1;
178
    error("parse STUN message failed \n");
179

    
180
  }
181

    
182
      UInt32 ip_addr = response->mappedAddress.ipv4.addr;
183
      char mapped_addr[16];
184
      int length;
185
      length = sprintf(mapped_addr,"%d.%d.%d.%d",(ip_addr >> 24) & 0xff,(ip_addr >> 16) & 0xff,(ip_addr >> 8) & 0xff,ip_addr & 0xff);
186

    
187
      ip_addr = response->changedAddress.ipv4.addr;
188
      char changed_addr[16];
189
      length = sprintf(changed_addr,"%d.%d.%d.%d",(ip_addr >> 24) & 0xff,(ip_addr >> 16)\
190
              & 0xff,(ip_addr >> 8) & 0xff,ip_addr & 0xff);
191

    
192
  if ( verbose )
193
  {
194

    
195
      info( "\t mappedAddr= ipv4 %s port %d \n \t changedAddr= ipv4 %s port %d \n",
196
              mapped_addr ,
197
              response->mappedAddress.ipv4.port,
198
              changed_addr,
199
              response->changedAddress.ipv4.port);
200

    
201
      }
202

    
203
  //reflexiveAddr.sin_addr.s_addr = inet_addr(changed_addr);
204
  //reflexiveAddr->sin_addr.s_addr = inet_addr("1.1.1.1");
205
  //reflexiveAddr->sin_port = htons(resp.mappedAddress.ipv4.port);
206
  
207
  return returnValue;
208
}
209

    
210
bool 
211
stunParseAtrAddress( char* body, unsigned int hdrLen, StunAtrAddress4 *result, bool verbose )
212
{
213
   if ( hdrLen != 8 )
214
   {
215
      error("hdrlen is not 8 \n ");
216
      return false;
217
   }
218
   result->pad = *body++;
219
   result->family = *body++;
220

    
221
   if (result->family == IPv4Family)
222
   {
223

    
224
      UInt16 nport;
225
      memcpy(&nport, body, 2); body+=2;
226
      
227
      if (verbose) info("port %i \n",ntohs(nport));
228

    
229
      result->ipv4.port = ntohs(nport);
230

    
231
                
232
      UInt32 naddr;
233
      memcpy(&naddr, body, 4); body+=4;
234
      //debug("port %d \n",ntohl(naddr));
235
      
236
      if (verbose)
237
        {
238
      UInt32 ip_addr = ntohl(naddr);
239
      char str_p[20];
240

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

    
243
      info(" ipv4 as str %s \n  ",str_p);
244
        }
245

    
246
      result->ipv4.addr = ntohl(naddr);
247

    
248
      return true;
249
   }
250

    
251
   else if (result->family == IPv6Family)
252

    
253
   {
254
      warn("ipv6 not supported  \n");
255
   }
256
   else
257
   {
258
      error("bad address family: %i \n ",result->family );
259
   }
260
        
261
   return false;
262
}
263

    
264

    
265

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

    
512

    
513
void
514
stunBuildReqSimple(StunMessage* msg,
515
                    const StunAtrString username,
516
                    bool changePort, bool changeIp, unsigned int id )
517
{
518
   assert( msg );
519
   memset( msg , 0 , sizeof(*msg) );
520
        
521
   msg->msgHdr.msgType = BindRequestMsg;
522

    
523
   int i;        
524
   for (i=0; i<16; i=i+4 )
525
   {
526
      assert(i+3<16);
527
      int r = stunRand();
528
      msg->msgHdr.id.octet[i+0]= r>>0;
529
      msg->msgHdr.id.octet[i+1]= r>>8;
530
      msg->msgHdr.id.octet[i+2]= r>>16;
531
      msg->msgHdr.id.octet[i+3]= r>>24;
532
   }
533
        
534
   if ( id != 0 )
535
   {
536
      msg->msgHdr.id.octet[0] = id; 
537
   }
538
        
539
   msg->hasChangeRequest = true;
540
   msg->changeRequest.value =(changeIp?ChangeIpFlag:0) | 
541
      (changePort?ChangePortFlag:0);
542
        
543
   if ( username.sizeValue > 0 )
544
   {
545
      msg->hasUsername = true;
546
      msg->username = username;
547
   }
548
}
549

    
550

    
551
unsigned int
552
stunEncodeMessage( const StunMessage msg, 
553
                   char* buf, 
554
                   unsigned int bufLen, 
555
                   const StunAtrString password, 
556
                   bool verbose)
557
{
558
   assert(bufLen >= sizeof(StunMsgHdr));
559
   char* ptr = buf;
560
        
561
   ptr = encode16(ptr, msg.msgHdr.msgType);
562
   char* lengthp = ptr;
563
   ptr = encode16(ptr, 0);
564
   ptr = encode(ptr, (const char*)(msg.msgHdr.id.octet), sizeof(msg.msgHdr.id));
565
        
566
   if (verbose) debug("Encoding stun message: ");
567

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

    
644
   if (password.sizeValue > 0)
645
   {
646
     if (verbose) info("HMAC with password: %s \n ",password.value);
647
                
648
      StunAtrIntegrity integrity;
649
      //computeHmac(integrity.hash, buf, (int)(ptr-buf) , password.value, password.sizeValue);
650
      ptr = encodeAtrIntegrity(ptr, integrity);
651
   }
652
        
653
   encode16(lengthp, (UInt16)(ptr - buf - sizeof(StunMsgHdr)));
654
   return (int)(ptr - buf);
655
}
656

    
657

    
658
int 
659
stunRand()
660
{
661
   // return 32 bits of random stuff
662
   assert( sizeof(int) == 4 );
663
   static bool init=false;
664
   if ( !init )
665
   { 
666
      init = true;
667
                
668
      UInt64 tick;
669

    
670
#if defined(__GNUC__) && ( defined(__i686__) || defined(__i386__) || defined(__amd64__) )
671
      asm("rdtsc" : "=A" (tick));
672
#elif defined (__SUNPRO_CC) || defined( __sparc__ )        
673
      tick = gethrtime();
674
#elif defined(__MACH__) 
675
      int fd=open("/dev/random",O_RDONLY);
676
      read(fd,&tick,sizeof(tick));
677
      closesocket(fd);
678
#else
679
#     error Need some way to seed the random number generator 
680
#endif 
681
      int seed = (int)(tick);
682
#ifdef WIN32
683
      srand(seed);
684
#else
685
      srandom(seed);
686
#endif
687
   }
688
        
689

    
690
   return random(); 
691

    
692
}
693

    
694

    
695
UInt64
696
stunGetSystemTimeSecs()
697
{
698
   UInt64 time=0;
699
#if defined(WIN32)  
700
   SYSTEMTIME t;
701
   // CJ TODO - this probably has bug on wrap around every 24 hours
702
   GetSystemTime( &t );
703
   time = (t.wHour*60+t.wMinute)*60+t.wSecond; 
704
#else
705
   struct timeval now;
706
   gettimeofday( &now , NULL );
707
   //assert( now );
708
   time = now.tv_sec;
709
#endif
710
   return time;
711
}
712

    
713

    
714
bool
715
stunParseServerName( char* name, StunAddress4 addr)
716
{
717
   assert(name);
718
        
719
   // TODO - put in DNS SRV stuff.
720
        
721
   bool ret = stunParseHostName( name, addr.addr, addr.port, 3478); 
722
   if ( ret != true ) 
723
   {
724
       addr.port=0xFFFF;
725
   }        
726
   return ret;
727
}
728

    
729

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

    
778
   h = gethostbyname( host );
779
   if ( h == NULL )
780
   {
781
     //int err = getErrno();
782
      error("error was %d \n",errno);
783
      ip = ntohl( 0x7F000001L );
784
      return false;
785
   }
786
   else
787
   {
788
      sin_addr = *(struct in_addr*)h->h_addr;
789
      ip = ntohl( sin_addr.s_addr );
790
   }
791

    
792
        
793
   portVal = portNum;
794
        
795
   return true;
796
}
797

    
798

    
799

    
800
bool 
801
stunParseAtrChangeRequest( char* body, unsigned int hdrLen, StunAtrChangeRequest *result )
802
{
803
   if ( hdrLen != 4 )
804
   {
805
      error("hdr length = %d excepcting %ld \n ",hdrLen,sizeof(result));
806

    
807
      error("Incorrect size for ChangeRequest \n ");
808

    
809
      return false;
810
   }
811
   else
812
   {
813
      memcpy(&result->value, body, 4);
814
      result->value = ntohl(result->value);
815
      return true;
816
   }
817
}
818

    
819

    
820

    
821

    
822
bool 
823
stunParseAtrUnknown( char* body, unsigned int hdrLen,  StunAtrUnknown *result)
824
{
825
   if ( hdrLen >= sizeof(StunAtrUnknown) )
826
   {
827
      return false;
828
   }
829
   else
830
   {
831
      if (hdrLen % 4 != 0) return false;
832
      result->numAttributes = hdrLen / 4;
833
      int i;
834
      for (i=0; i<result->numAttributes; i++)
835
      {
836
         memcpy(&result->attrType[i], body, 2); body+=2;
837
         result->attrType[i] = ntohs(result->attrType[i]);
838
      }
839
      return true;
840
   }
841
}
842

    
843

    
844

    
845
bool 
846
stunParseAtrString( char* body, unsigned int hdrLen,  StunAtrString *result )
847
{
848
   if ( hdrLen >= STUN_MAX_STRING )
849
   {
850
     debug( "String is too large \n");
851
      return false;
852
   }
853
   else
854
   {
855
      if (hdrLen % 4 != 0)
856
      {
857
        debug("Bad length string %d \n ",hdrLen);
858
         return false;
859
      }
860
                
861
      result->sizeValue = hdrLen;
862
      memcpy(&result->value, body, hdrLen);
863
      result->value[hdrLen] = 0;
864
      return true;
865
   }
866
}
867

    
868

    
869
bool 
870
stunParseAtrIntegrity( char* body, unsigned int hdrLen,StunAtrIntegrity *result )
871
{
872
   if ( hdrLen != 20)
873
   {
874
     debug("MessageIntegrity must be 20 bytes \n");
875
      return false;
876
   }
877
   else
878
   {
879
      memcpy(&result->hash, body, hdrLen);
880
      return true;
881
   }
882
}
883

    
884

    
885
void
886
stunCreateErrorResponse(StunMessage response, int cl, int number, const char* msg)
887
{
888
   response.msgHdr.msgType = BindErrorResponseMsg;
889
   response.hasErrorCode = true;
890
   response.errorCode.errorClass = cl;
891
   response.errorCode.number = number;
892
   strcpy(response.errorCode.reason, msg);
893
}
894

    
895
bool
896
stunParseAtrError(char* body,unsigned int hdrLen,StunAtrError *result)
897
{
898
   if ( hdrLen >= sizeof(StunAtrError) )
899
   {
900
      debug("head on Error too large \n  ");
901
      return false;
902
   }
903
   else
904
   {
905
      memcpy(&result->pad, body, 2); body+=2;
906
      result->pad = ntohs(result->pad);
907
      result->errorClass = *body++;
908
      result->number = *body++;
909
                
910
      result->sizeReason = hdrLen - 4;
911
      memcpy(&result->reason, body, result->sizeReason);
912
      result->reason[result->sizeReason] = 0;
913
      return true;
914
   }
915
}
916

    
917

    
918
char* 
919
encodeAtrString(char* ptr, UInt16 type, const StunAtrString atr)
920
{
921
   assert(atr.sizeValue % 4 == 0);
922
        
923
   ptr = encode16(ptr, type);
924
   ptr = encode16(ptr, atr.sizeValue);
925
   ptr = encode(ptr, atr.value, atr.sizeValue);
926
   return ptr;
927
}
928

    
929

    
930
char* 
931
encodeAtrIntegrity(char* ptr, const StunAtrIntegrity atr)
932
{
933
   ptr = encode16(ptr, MessageIntegrity);
934
   ptr = encode16(ptr, 20);
935
   ptr = encode(ptr, atr.hash, sizeof(atr.hash));
936
   return ptr;
937
}
938

    
939
char* 
940
encodeAtrError(char* ptr, const StunAtrError atr)
941
{
942
   ptr = encode16(ptr, ErrorCode);
943
   ptr = encode16(ptr, 6 + atr.sizeReason);
944
   ptr = encode16(ptr, atr.pad);
945
   *ptr++ = atr.errorClass;
946
   *ptr++ = atr.number;
947
   ptr = encode(ptr, atr.reason, atr.sizeReason);
948
   return ptr;
949
}
950

    
951

    
952
char* 
953
encodeAtrUnknown(char* ptr, const StunAtrUnknown atr)
954
{
955
   ptr = encode16(ptr, UnknownAttribute);
956
   ptr = encode16(ptr, 2+2*atr.numAttributes);
957
   int i;
958
   for (i=0; i<atr.numAttributes; i++)
959
   {
960
      ptr = encode16(ptr, atr.attrType[i]);
961
   }
962
   return ptr;
963
}
964

    
965

    
966
char* 
967
encodeAtrAddress4(char* ptr, UInt16 type, const StunAtrAddress4 atr)
968
{
969
   ptr = encode16(ptr, type);
970
   ptr = encode16(ptr, 8);
971
   *ptr++ = atr.pad;
972
   *ptr++ = IPv4Family;
973
   ptr = encode16(ptr, atr.ipv4.port);
974
   ptr = encode32(ptr, atr.ipv4.addr);
975
        
976
   return ptr;
977
}
978

    
979

    
980
char* 
981
encodeAtrChangeRequest(char* ptr, const StunAtrChangeRequest atr)
982
{
983
   ptr = encode16(ptr, ChangeRequest);
984
   ptr = encode16(ptr, 4);
985
   ptr = encode32(ptr, atr.value);
986
   return ptr;
987
}
988

    
989
char* 
990
encodeXorOnly(char* ptr)
991
{
992
   ptr = encode16(ptr, XorOnly );
993
   return ptr;
994
}
995

    
996
char* 
997
encode(char* buf, const char* data, unsigned int length)
998
{
999
  memcpy(buf, data, length);
1000
  return buf + length;
1001
}
1002

    
1003
char* 
1004
encode16(char* buf, UInt16 data)
1005
{
1006
   UInt16 ndata = htons(data);
1007
   memcpy(buf, (void*)(&ndata), sizeof(UInt16));
1008
   return buf + sizeof(UInt16);
1009
}
1010

    
1011
char* 
1012
encode32(char* buf, UInt32 data)
1013
{
1014
   UInt32 ndata = htonl(data);
1015
   memcpy(buf, (void*)(&ndata), sizeof(UInt32));
1016
   return buf + sizeof(UInt32);
1017
}
1018

    
1019
/// return a random number to use as a port 
1020
int
1021
stunRandomPort()
1022
{
1023
   int min=0x4000;
1024
   int max=0x7FFF;
1025
        
1026
   int ret = stunRand();
1027
   ret = ret|min;
1028
   ret = ret&max;
1029
        
1030
   return ret;
1031
}
1032

    
1033

    
1034
void
1035
toHex(const char* buffer, int bufferSize, char* output) 
1036
{
1037
   static char hexmap[] = "0123456789abcdef";
1038
        
1039
   const char* p = buffer;
1040
   char* r = output;
1041
   int i;
1042
   for (i=0; i < bufferSize; i++)
1043
   {
1044
      unsigned char temp = *p++;
1045
                
1046
      int hi = (temp & 0xf0)>>4;
1047
      int low = (temp & 0xf);
1048
                
1049
      *r++ = hexmap[hi];
1050
      *r++ = hexmap[low];
1051
   }
1052
   *r = 0;
1053
}
1054

    
1055

    
1056