source: mediastreamer2/linphone/oRTP/src/stun.c @ 223:6455410f996a

Last change on this file since 223:6455410f996a was 223:6455410f996a, checked in by aymeric <aymeric@…>, 4 years ago

Update stun to latest RFC.
Start TURN & ICE extensions.
Keep most old STUN capabilities.
Start changing/adding API for STUN/TURN

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@226 3f6dc0c8-ddfe-455d-9043-3cd528dc4637

File size: 72.8 KB
Line 
1 /*
2  The oRTP library is an RTP (Realtime Transport Protocol - rfc3550) stack.
3  Copyright (C) 2001  Simon MORLAT simon.morlat@linphone.org
4
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  Lesser General Public License for more details.
14
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18*/
19
20/* ====================================================================
21 * The Vovida Software License, Version 1.0
22 *
23 * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
24 *
25 * Redistribution and use in source and binary forms, with or without
26 * modification, are permitted provided that the following conditions
27 * are met:
28 *
29 * 1. Redistributions of source code must retain the above copyright
30 *    notice, this list of conditions and the following disclaimer.
31 *
32 * 2. Redistributions in binary form must reproduce the above copyright
33 *    notice, this list of conditions and the following disclaimer in
34 *    the documentation and/or other materials provided with the
35 *    distribution.
36 *
37 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
38 *    and "Vovida Open Communication Application Library (VOCAL)" must
39 *    not be used to endorse or promote products derived from this
40 *    software without prior written permission. For written
41 *    permission, please contact vocal@vovida.org.
42 *
43 * 4. Products derived from this software may not be called "VOCAL", nor
44 *    may "VOCAL" appear in their name, without prior written
45 *    permission of Vovida Networks, Inc.
46 *
47 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
48 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
49 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
50 * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
51 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
52 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
53 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
54 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
55 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
56 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
57 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
58 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
59 * DAMAGE.
60 *
61 * ====================================================================
62 *
63 * This software consists of voluntary contributions made by Vovida
64 * Networks, Inc. and many individuals on behalf of Vovida Networks,
65 * Inc.  For more information on Vovida Networks, Inc., please see
66 * <http://www.vovida.org/>.
67 *
68 */
69
70#ifndef _WIN32_WCE
71#include <errno.h>
72#endif
73
74#include <assert.h>
75
76#if defined(WIN32) || defined(_WIN32_WCE)
77#include <winsock2.h>
78#include <stdlib.h>
79/* #include <io.h> */
80#include <time.h>
81#include <ctype.h> /*for isdigit() */
82#else
83
84#include <stdlib.h>
85#include <unistd.h>
86#include <string.h>
87#include <sys/ioctl.h>
88#include <sys/socket.h>
89#include <sys/time.h>
90#include <sys/types.h>
91#include <arpa/inet.h>
92#include <fcntl.h>
93#include <netdb.h>
94#include <netinet/in.h>
95#include <arpa/nameser.h>
96#include <resolv.h>
97#include <net/if.h>
98
99#endif
100
101
102//#define NOSSL
103/*
104  #if defined(__sparc__) || defined(WIN32)
105  #define NOSSL
106  #endif
107  #define NOSSL
108*/
109
110#include "ortp/stun_udp.h"
111#include "ortp/stun.h"
112#include "ortp/ortp.h"
113
114static char *ipaddr(const StunAddress4 *addr)
115{
116   static char tmp[512];
117   struct in_addr inaddr;
118   char *atmp;
119   inaddr.s_addr = htonl(addr->addr);
120   atmp = (char *)inet_ntoa(inaddr);
121   
122   snprintf(tmp, 512, "%s:%i", atmp, addr->port);
123   return tmp;
124}
125
126static void
127computeHmac_longterm(char* hmac, const char* input, int length,
128                     const char *username, const char *realm, const char *password);
129static void
130computeHmac_shortterm(char* hmac, const char* input, int length, const char* key);
131
132static bool_t 
133stunParseAtrAddress( char* body, unsigned int hdrLen,  StunAtrAddress4 *result )
134{
135   if ( hdrLen != 8 )
136   {
137      ortp_error("stun: hdrLen wrong for Address\n");
138      return FALSE;
139   }
140   result->pad = *body++;
141   result->family = *body++;
142   if (result->family == IPv4Family)
143   {
144      UInt16 nport;
145      UInt32 naddr;
146      memcpy(&nport, body, 2); body+=2;
147      result->ipv4.port = ntohs(nport);
148
149      memcpy(&naddr, body, 4); body+=4;
150      result->ipv4.addr = ntohl(naddr);
151      return TRUE;
152   }
153   else if (result->family == IPv6Family)
154   {
155      ortp_error("stun: ipv6 not supported\n");
156   }
157   else
158   {
159      ortp_error("stun: bad address family: %i\n", result->family);
160   }
161       
162   return FALSE;
163}
164
165static bool_t 
166stunParseAtrChangeRequest( char* body, unsigned int hdrLen,  StunAtrChangeRequest *result )
167{
168   if ( hdrLen != 4 )
169   {
170     /* ortp_error("stun: hdr length = %i expecting %i\n",hdrLen, sizeof(result)); */
171               
172      ortp_error("stun: Incorrect size for SA_CHANGEREQUEST");
173      return FALSE;
174   }
175   else
176   {
177      memcpy(&result->value, body, 4);
178      result->value = ntohl(result->value);
179      return TRUE;
180   }
181}
182
183static bool_t 
184stunParseAtrError( char* body, unsigned int hdrLen,  StunAtrError *result )
185{
186   if ( hdrLen >= sizeof(StunAtrError) )
187   {
188      ortp_error("stun: Incorrect size for SA_ERRORCODE");
189      return FALSE;
190   }
191   else
192   {
193      memcpy(&result->pad, body, 2); body+=2;
194      result->pad = ntohs(result->pad);
195      result->errorClass = *body++;
196      result->number = *body++;
197               
198      result->sizeReason = hdrLen - 4;
199      memcpy(&result->reason, body, result->sizeReason);
200      result->reason[result->sizeReason] = 0;
201      return TRUE;
202   }
203}
204
205static bool_t 
206stunParseAtrUnknown( char* body, unsigned int hdrLen,  StunAtrUnknown *result )
207{
208   if ( hdrLen >= sizeof(result) )
209   {
210      ortp_error("stun: Incorrect size for SA_UNKNOWNATTRIBUTE");
211      return FALSE;
212   }
213   else
214   {
215      int i;
216      if (hdrLen % 4 != 0) return FALSE;
217      result->numAttributes = hdrLen / 4;
218      for (i=0; i<result->numAttributes; i++)
219      {
220         memcpy(&result->attrType[i], body, 2); body+=2;
221         result->attrType[i] = ntohs(result->attrType[i]);
222      }
223      return TRUE;
224   }
225}
226
227static bool_t 
228stunParseAtrString( char* body, unsigned int hdrLen,  StunAtrString *result )
229{
230   if ( hdrLen >= STUN_MAX_STRING )
231   {
232      ortp_error("stun: String is too large");
233      return FALSE;
234   }
235   else
236   {
237      result->sizeValue = hdrLen;
238      memcpy(&result->value, body, hdrLen);
239      result->value[hdrLen] = 0;
240      return TRUE;
241   }
242}
243
244
245static bool_t 
246stunParseAtrIntegrity( char* body, unsigned int hdrLen,  StunAtrIntegrity *result )
247{
248   if ( hdrLen != 20)
249   {
250      ortp_error("stun: SA_MESSAGEINTEGRITY must be 20 bytes");
251      return FALSE;
252   }
253   else
254   {
255      memcpy(&result->hash, body, hdrLen);
256      return TRUE;
257   }
258}
259
260static bool_t 
261turnParseAtrChannelNumber( char* body, unsigned int hdrLen,  TurnAtrChannelNumber *result )
262{
263   if ( hdrLen >= sizeof(result) )
264   {
265      ortp_error("stun: Incorrect size for TA_CHANNELNUMBER");
266      return FALSE;
267   }
268   else
269   {
270      if (hdrLen % 4 != 0) return FALSE;
271      memcpy(&result->channelNumber, body, 2);
272      body+=2;
273      result->channelNumber = ntohs(result->channelNumber);
274      memcpy(&result->rffu, body, 2);
275      body+=2;
276      result->rffu = ntohs(result->rffu);
277      return TRUE;
278   }
279}
280
281static bool_t 
282turnParseAtrLifetime( char* body, unsigned int hdrLen,  TurnAtrLifetime *result )
283{
284   if ( hdrLen != sizeof(result) )
285   {
286      ortp_error("stun: Incorrect size for TA_LIFETIME");
287      return FALSE;
288   }
289   else
290   {
291      memcpy(&result->lifetime, body, 4);
292      result->lifetime = ntohl(result->lifetime);
293      return TRUE;
294   }
295}
296
297static bool_t 
298turnParseAtrData( char* body, unsigned int hdrLen,  TurnAtrData *result )
299{
300   if ( hdrLen >= 1500 )
301   {
302      ortp_error("stun: Incorrect size for TA_DATA");
303      return FALSE;
304   }
305   else
306   {
307      result->sizeValue = hdrLen;
308      memcpy(&result->value, body, hdrLen);
309      result->value[hdrLen] = 0;
310      return TRUE;
311   }
312}
313
314static bool_t 
315turnParseAtrRequestedTransport( char* body, unsigned int hdrLen,  TurnAtrRequestedTransport *result )
316{
317   if ( hdrLen != 4 )
318   {
319      ortp_error("stun: Incorrect size for TA_REQUESTEDTRANSPORT");
320      return FALSE;
321   }
322   result->proto = *body++;
323   result->pad1 = *body++;
324   result->pad2 = *body++;
325   result->pad3 = *body++;
326   return TRUE;
327}
328
329#ifdef ORTP_BIGENDIAN
330#define htonq(n) n
331#define ntohq(n) n
332#else /* little endian */
333static inline UInt64
334htonq (UInt64 v)
335{
336  return htonl ((UInt32) (v >> 32))
337    | (UInt64) htonl ((UInt32) v) << 32;
338}
339static inline UInt64
340ntohq (UInt64 v)
341{
342  return ntohl ((UInt32) (v >> 32))
343    | (UInt64) ntohl ((UInt32) v) << 32;
344}
345#endif /* little endian */
346
347static bool_t 
348turnParseAtrReservationToken( char* body, unsigned int hdrLen,  TurnAtrReservationToken *result )
349{
350  if ( hdrLen != 8 )
351  {
352    ortp_error("stun: Incorrect size for TA_RESERVATIONTOKEN");
353    return FALSE;
354  }
355  memcpy(&result->value, body, 8);
356  result->value = ntohq(result->value);
357  return TRUE;
358}
359
360static bool_t 
361turnParseAtrFingerprint( char* body, unsigned int hdrLen, TurnAtrFingerprint *result )
362{
363  if ( hdrLen != 4 )
364  {
365    ortp_error("stun: Incorrect size for SA_FINGERPRINT");
366    return FALSE;
367  }
368
369  memcpy(&result->fingerprint, body, 4);
370  result->fingerprint = ntohl(result->fingerprint);
371  return TRUE;
372}
373
374static bool_t 
375iceParseAtrPriority( char* body, unsigned int hdrLen, IceAtrPriority *result )
376{
377  if ( hdrLen != sizeof(result) )
378  {
379    ortp_error("stun: Incorrect size for ICEA_PRIORITY");
380    return FALSE;
381  }
382
383  memcpy(&result->priority, body, 4);
384  result->priority = ntohl(result->priority);
385  return TRUE;
386}
387
388static bool_t 
389iceParseAtrIceControll( char* body, unsigned int hdrLen, IceAtrIceControll *result )
390{
391  if ( hdrLen != sizeof(result) )
392  {
393    ortp_error("stun: Incorrect size for ICEA_ICECONTROLLED/ICEA_ICECONTROLLING");
394    return FALSE;
395  }
396  memcpy(&result->value, body, 8);
397  result->value = ntohq(result->value);
398  return TRUE;
399} 
400
401bool_t
402stunParseMessage( char* buf, unsigned int bufLen, StunMessage *msg)
403{
404   char* body;
405   unsigned int size;
406         ortp_debug("stun: Received stun message: %i bytes\n", bufLen);
407   memset(msg, 0, sizeof(msg));
408       
409   if (sizeof(StunMsgHdr) > bufLen)
410   {
411      ortp_warning("stun: message too short\n");
412      return FALSE;
413   }
414
415   memcpy(&msg->msgHdr, buf, sizeof(StunMsgHdr));
416   msg->msgHdr.msgType = ntohs(msg->msgHdr.msgType);
417   msg->msgHdr.msgLength = ntohs(msg->msgHdr.msgLength);
418
419   if (msg->msgHdr.msgLength + sizeof(StunMsgHdr) != bufLen)
420   {
421      ortp_warning("stun: Message header length doesn't match message size: %i - %i\n", msg->msgHdr.msgLength, bufLen);
422      return FALSE;
423   }
424
425   body = buf + sizeof(StunMsgHdr);
426   size = msg->msgHdr.msgLength;
427       
428   /*ortp_message("stun: bytes after header = %i\n", size); */
429       
430   while ( size > 0 )
431   {
432      /* !jf! should check that there are enough bytes left in the buffer */
433               
434      StunAtrHdr* attr = (StunAtrHdr*)body; /*reinterpret_cast<StunAtrHdr*>(body);*/
435               
436      unsigned int attrLen = ntohs(attr->length);
437      int atrType = ntohs(attr->type);
438               
439      if ( attrLen+4 > size ) 
440      {
441         ortp_error("stun: claims attribute is larger than size of message (attribute type=%i)\n", atrType);
442         return FALSE;
443      }
444               
445      body += 4; /* skip the length and type in attribute header */
446      size -= 4;
447               
448      if (atrType == SA_MAPPEDADDRESS)
449      {
450            msg->hasMappedAddress = TRUE;
451            if ( stunParseAtrAddress(  body,  attrLen,  &msg->mappedAddress )== FALSE )
452            {
453               ortp_error("stun: problem parsing SA_MAPPEDADDRESS\n");
454               return FALSE;
455            }
456            else
457            {
458               ortp_debug("stun: SA_MAPPEDADDRESS = %s\n", ipaddr(&msg->mappedAddress.ipv4));
459            }
460                                       
461      }
462      else if (atrType == SA_RESPONSEADDRESS)
463      {
464            msg->hasResponseAddress = TRUE;
465            if ( stunParseAtrAddress(  body,  attrLen,  &msg->responseAddress )== FALSE )
466            {
467               ortp_error("stun: problem parsing SA_RESPONSEADDRESS");
468               return FALSE;
469            }
470            else
471            {
472               ortp_debug("stun: SA_RESPONSEADDRESS = %s\n", ipaddr(&msg->responseAddress.ipv4));
473            }
474      }
475      else if (atrType == SA_CHANGEREQUEST)
476      {
477            msg->hasChangeRequest = TRUE;
478            if (stunParseAtrChangeRequest( body, attrLen, &msg->changeRequest) == FALSE)
479            {
480               ortp_error("stun: problem parsing SA_CHANGEREQUEST\n");
481               return FALSE;
482            }
483            else
484            {
485               ortp_debug("stun: SA_CHANGEREQUEST = %i\n", msg->changeRequest.value);
486            }
487      }
488      else if (atrType == SA_SOURCEADDRESS)
489      {
490            msg->hasSourceAddress = TRUE;
491            if ( stunParseAtrAddress(  body,  attrLen,  &msg->sourceAddress )== FALSE )
492            {
493               ortp_error("stun: problem parsing SA_SOURCEADDRESS\n");
494               return FALSE;
495            }
496            else
497            {
498               ortp_debug("stun: SA_SOURCEADDRESS = %s\n", ipaddr(&msg->sourceAddress.ipv4) );
499            }
500      }
501      else if (atrType == SA_CHANGEDADDRESS)
502      {
503            msg->hasChangedAddress = TRUE;
504            if ( stunParseAtrAddress(  body,  attrLen,  &msg->changedAddress )== FALSE )
505            {
506               ortp_error("stun: problem parsing SA_CHANGEDADDRESS\n");
507               return FALSE;
508            }
509            else
510            {
511               ortp_debug("stun: SA_CHANGEDADDRESS = %s\n", ipaddr(&msg->changedAddress.ipv4));
512            }
513      }
514      else if (atrType == SA_USERNAME)
515      {
516            msg->hasUsername = TRUE;
517            if (stunParseAtrString( body, attrLen, &msg->username) == FALSE)
518            {
519               ortp_error("stun: problem parsing SA_USERNAME");
520               return FALSE;
521            }
522            else
523            {
524               ortp_debug("stun: SA_USERNAME = %s\n", msg->username.value );
525            }                                   
526      }
527      else if (atrType == SA_PASSWORD)
528      {
529            msg->hasPassword = TRUE;
530            if (stunParseAtrString( body, attrLen, &msg->password) == FALSE)
531            {
532               ortp_error("stun: problem parsing SA_PASSWORD");
533               return FALSE;
534            }
535            else
536            {
537               ortp_debug("stun: SA_PASSWORD = %s\n", msg->password.value );
538            }
539      }
540      else if (atrType == SA_MESSAGEINTEGRITY)
541      {
542            msg->hasMessageIntegrity = TRUE;
543            if (stunParseAtrIntegrity( body, attrLen, &msg->messageIntegrity) == FALSE)
544            {
545               ortp_error("stun: problem parsing SA_MESSAGEINTEGRITY");
546               return FALSE;
547            }                                   
548      }
549      else if (atrType == SA_ERRORCODE)
550      {
551            msg->hasErrorCode = TRUE;
552            if (stunParseAtrError(body, attrLen, &msg->errorCode) == FALSE)
553            {
554               ortp_error("stun: problem parsing SA_ERRORCODE");
555               return FALSE;
556            }
557            else
558            {
559               ortp_debug("stun: SA_ERRORCODE = %i %i %s\n",
560                                   msg->errorCode.errorClass ,
561                                   msg->errorCode.number ,
562                                   msg->errorCode.reason );
563            }
564                                         
565      }
566      else if (atrType == SA_UNKNOWNATTRIBUTE)
567      {
568           msg->hasUnknownAttributes = TRUE;
569            if (stunParseAtrUnknown(body, attrLen, &msg->unknownAttributes) == FALSE)
570            {
571               ortp_error("stun: problem parsing SA_UNKNOWNATTRIBUTE");
572               return FALSE;
573            }
574      }
575      else if (atrType == SA_REFLECTEDFROM)
576      {
577            msg->hasReflectedFrom = TRUE;
578            if ( stunParseAtrAddress(  body,  attrLen,  &msg->reflectedFrom ) == FALSE )
579            {
580               ortp_error("stun: problem parsing SA_REFLECTEDFROM");
581               return FALSE;
582            }
583      }
584      else if (atrType == SA_REALM)
585      {
586            msg->hasRealm = TRUE;
587            if (stunParseAtrString( body, attrLen, &msg->realmName) == FALSE)
588            {
589               ortp_error("stun: problem parsing SA_REALM");
590               return FALSE;
591            }
592            else
593            {
594               ortp_debug("stun: SA_REALM = %s\n", msg->realmName.value );
595            }
596      }
597      else if (atrType == SA_NONCE)
598      {
599            msg->hasNonce = TRUE;
600            if (stunParseAtrString( body, attrLen, &msg->nonceName) == FALSE)
601            {
602               ortp_error("stun: problem parsing SA_NONCE");
603               return FALSE;
604            }
605            else
606            {
607               ortp_debug("stun: SA_NONCE = %s\n", msg->nonceName.value );
608            }
609      }
610      else if (atrType == SA_XORMAPPEDADDRESS || atrType == SA_XORMAPPEDADDRESS2)
611      { 
612           msg->hasXorMappedAddress = TRUE;
613            if ( stunParseAtrAddress(  body,  attrLen,  &msg->xorMappedAddress ) == FALSE )
614            {
615               ortp_error("stun: problem parsing SA_XORMAPPEDADDRESS");
616               return FALSE;
617            }
618            else
619            {
620               ortp_debug("stun: SA_XORMAPPEDADDRESS = %s\n", ipaddr(&msg->xorMappedAddress.ipv4) );
621            }
622      }
623      else if (atrType == SA_XORONLY)
624      {
625            ortp_warning("stun: SA_XORONLY - non standard extension ignored\n" );
626      }
627      else if (atrType == SA_SECONDARYADDRESS)
628      {
629            ortp_debug("stun: SA_SECONDARYADDRESS - non standard extension ignored\n" );
630      }
631      else if (atrType == SA_SOFTWARE)
632      {
633            msg->hasSoftware = TRUE;
634            if (stunParseAtrString( body, attrLen, &msg->softwareName) == FALSE)
635            {
636               ortp_error("stun: problem parsing SA_SOFTWARE");
637               return FALSE;
638            }
639            else
640            {
641               ortp_debug("stun: SA_SOFTWARE = %s\n", msg->softwareName.value );
642            }
643      }
644      else if (atrType == TA_CHANNELNUMBER)
645      {
646           msg->hasChannelNumberAttributes = TRUE;
647            if (turnParseAtrChannelNumber(body, attrLen, &msg->channelNumberAttributes) == FALSE)
648            {
649               ortp_error("stun: problem parsing TA_CHANNELNUMBER");
650               return FALSE;
651            }                                   
652      }
653      else if (atrType == TA_LIFETIME)
654      {
655           msg->hasLifetimeAttributes = TRUE;
656            if (turnParseAtrLifetime(body, attrLen, &msg->lifetimeAttributes) == FALSE)
657            {
658               ortp_error("stun: problem parsing TA_LIFETIME");
659               return FALSE;
660            }                                   
661      }
662      else if (atrType == TA_DEPRECATEDBANDWIDTH)
663      {
664           ortp_warning("stun: deprecated attribute TA_DEPRECATEDBANDWIDTH");
665      }
666      else if (atrType == TA_XORPEERADDRESS)
667      {
668            msg->hasXorPeerAddress = TRUE;
669            if ( stunParseAtrAddress(  body,  attrLen,  &msg->xorPeerAddress )== FALSE )
670            {
671               ortp_error("stun: problem parsing SA_XORPEERADDRESS\n");
672               return FALSE;
673            }
674            else
675            {
676               ortp_debug("stun: SA_XORPEERADDRESS = %s\n", ipaddr(&msg->xorPeerAddress.ipv4));
677            }
678      }
679      else if (atrType == TA_DATA)
680      {
681            msg->hasData = TRUE;
682            if (turnParseAtrData( body, attrLen, &msg->data) == FALSE)
683            {
684               ortp_error("stun: problem parsing TA_DATA");
685               return FALSE;
686            }
687            else
688            {
689            }
690      }
691      else if (atrType == TA_XORRELAYEDADDRESS)
692      {
693            msg->hasXorRelayedAddress = TRUE;
694            if ( stunParseAtrAddress(  body,  attrLen,  &msg->xorRelayedAddress )== FALSE )
695            {
696               ortp_error("stun: problem parsing TA_XORRELAYEDADDRESS\n");
697               return FALSE;
698            }
699            else
700            {
701               ortp_debug("stun: TA_XORRELAYEDADDRESS = %s\n", ipaddr(&msg->xorRelayedAddress.ipv4));
702            }
703      }
704      else if (atrType == TA_EVENPORT)
705      {
706           ortp_warning("stun: do we need this... TA_EVENPORT");
707      }
708      else if (atrType == TA_REQUESTEDTRANSPORT)
709      {
710            msg->hasRequestedTransport = TRUE;
711            if ( turnParseAtrRequestedTransport(  body,  attrLen,  &msg->requestedTransport )== FALSE )
712            {
713               ortp_error("stun: problem parsing TA_REQUESTEDTRANSPORT\n");
714               return FALSE;
715            }
716      }
717      else if (atrType == TA_DONTFRAGMENT)
718      {
719            msg->hasDontFragment = TRUE;
720      }
721      else if (atrType == TA_DEPRECATEDTIMERVAL)
722      {
723           ortp_warning("stun: deprecated attribute TA_DEPRECATEDTIMERVAL");
724      }
725      else if (atrType == TA_RESERVATIONTOKEN)
726      {
727            msg->hasReservationToken = TRUE;
728            if ( turnParseAtrReservationToken(  body,  attrLen,  &msg->reservationToken)== FALSE )
729            {
730               ortp_error("stun: problem parsing TA_RESERVATIONTOKEN\n");
731               return FALSE;
732            }
733      }
734      else if (atrType == SA_FINGERPRINT)
735      {
736            msg->hasFingerprint = TRUE;
737            if ( turnParseAtrFingerprint(  body,  attrLen,  &msg->fingerprint)== FALSE )
738            {
739               ortp_error("stun: problem parsing SA_FINGERPRINT\n");
740               return FALSE;
741            }
742      }
743      else if (atrType == ICEA_PRIORITY)
744      {
745            msg->hasLifetimeAttributes = TRUE;
746            if (iceParseAtrPriority(body, attrLen, &msg->priority) == FALSE)
747            {
748               ortp_error("stun: problem parsing ICEA_PRIORITY");
749               return FALSE;
750            }                                   
751      }
752      else if (atrType == ICEA_USECANDIDATE)
753      {
754            msg->hasUseCandidate = TRUE;
755      }
756      else if (atrType == ICEA_ICECONTROLLED)
757      {
758           msg->hasIceControlled = TRUE;
759           if (iceParseAtrIceControll(body, attrLen, &msg->iceControlled) == FALSE)
760            {
761               ortp_error("stun: problem parsing ICEA_ICECONTROLLED");
762               return FALSE;
763            }
764      }
765      else if (atrType == ICEA_ICECONTROLLING)
766      {
767           msg->hasIceControlling = TRUE;
768           if (iceParseAtrIceControll(body, attrLen, &msg->iceControlling) == FALSE)
769            {
770               ortp_error("stun: problem parsing ICEA_ICECONTROLLING");
771               return FALSE;
772            }
773      }
774      else
775      {
776            if ( atrType <= 0x7FFF ) 
777            {
778              ortp_error("stun: Unknown Comprehension-Required attribute: %04x\n", atrType );
779              return FALSE;
780            }
781            else
782              ortp_warning("stun: Unknown attribute: %04x\n", atrType );
783      }
784               
785      if (attrLen%4>0)
786        attrLen += (4-(attrLen%4));
787     
788      body += attrLen;
789      size -= attrLen;
790   }
791   
792   return TRUE;
793}
794
795
796static char* 
797encode16(char* buf, UInt16 data)
798{
799   UInt16 ndata = htons(data);
800   memcpy(buf, &ndata, sizeof(UInt16));
801   return buf + sizeof(UInt16);
802}
803
804static char* 
805encode32(char* buf, UInt32 data)
806{
807   UInt32 ndata = htonl(data);
808   memcpy(buf, &ndata, sizeof(UInt32));
809   return buf + sizeof(UInt32);
810}
811
812
813static char* 
814encode(char* buf, const char* data, unsigned int length)
815{
816   memcpy(buf, data, length);
817   return buf + length;
818}
819
820
821static char* 
822encodeAtrAddress4(char* ptr, UInt16 type, const StunAtrAddress4 *atr)
823{
824   ptr = encode16(ptr, type);
825   ptr = encode16(ptr, 8);
826   *ptr++ = atr->pad;
827   *ptr++ = IPv4Family;
828   ptr = encode16(ptr, atr->ipv4.port);
829   ptr = encode32(ptr, atr->ipv4.addr);
830       
831   return ptr;
832}
833
834static char* 
835encodeAtrChangeRequest(char* ptr, const StunAtrChangeRequest *atr)
836{
837   ptr = encode16(ptr, SA_CHANGEREQUEST);
838   ptr = encode16(ptr, 4);
839   ptr = encode32(ptr, atr->value);
840   return ptr;
841}
842
843static char* 
844encodeAtrError(char* ptr, const StunAtrError *atr)
845{
846   ptr = encode16(ptr, SA_ERRORCODE);
847   ptr = encode16(ptr, 6 + atr->sizeReason);
848   ptr = encode16(ptr, atr->pad);
849   *ptr++ = atr->errorClass;
850   *ptr++ = atr->number;
851   ptr = encode(ptr, atr->reason, atr->sizeReason);
852   return ptr;
853}
854
855
856static char* 
857encodeAtrUnknown(char* ptr, const StunAtrUnknown *atr)
858{
859   int i;
860   ptr = encode16(ptr, SA_UNKNOWNATTRIBUTE);
861   ptr = encode16(ptr, 2+2*atr->numAttributes);
862   for (i=0; i<atr->numAttributes; i++)
863   {
864      ptr = encode16(ptr, atr->attrType[i]);
865   }
866   return ptr;
867}
868
869static char* 
870encodeAtrString(char* ptr, UInt16 type, const StunAtrString *atr)
871{
872   int padding;
873   int i;
874       
875   ptr = encode16(ptr, type);
876   ptr = encode16(ptr, atr->sizeValue);
877   ptr = encode(ptr, atr->value, atr->sizeValue);
878
879   padding = atr->sizeValue % 4;
880   if (padding>0)
881   {
882     for (i=0;i<4-padding;i++)
883     {
884       *ptr++ = 0;
885     }
886   }
887   return ptr;
888}
889
890
891static char* 
892encodeAtrIntegrity(char* ptr, const StunAtrIntegrity *atr)
893{
894   ptr = encode16(ptr, SA_MESSAGEINTEGRITY);
895   ptr = encode16(ptr, 20);
896   ptr = encode(ptr, atr->hash, sizeof(atr->hash));
897   return ptr;
898}
899
900
901static char* 
902encodeAtrRequestedTransport(char* ptr, const TurnAtrRequestedTransport *atr)
903{
904   ptr = encode16(ptr, TA_REQUESTEDTRANSPORT);
905   ptr = encode16(ptr, 4);
906   *ptr++ = atr->proto;
907   *ptr++ = atr->pad1;
908   *ptr++ = atr->pad2;
909   *ptr++ = atr->pad3;
910   return ptr;
911}
912
913static char* 
914encodeAtrLifeTime(char* ptr, const TurnAtrLifetime *atr)
915{
916   ptr = encode16(ptr, TA_LIFETIME);
917   ptr = encode16(ptr, 4);
918   ptr = encode32(ptr, atr->lifetime);
919   return ptr;
920}
921
922static char* 
923encodeAtrDontFragment(char* ptr)
924{
925   ptr = encode16(ptr, TA_DONTFRAGMENT);
926   ptr = encode16(ptr, 0);
927   return ptr;
928}
929
930unsigned int
931stunEncodeMessage( const StunMessage *msg, 
932                   char* buf, 
933                   unsigned int bufLen, 
934                   const StunAtrString *password)
935{
936   char* ptr = buf;
937   char* lengthp;
938   ptr = encode16(ptr, msg->msgHdr.msgType);
939   lengthp = ptr;
940   ptr = encode16(ptr, 0);
941   ptr = encode32(ptr, msg->msgHdr.magic_cookie);
942   ptr = encode(ptr, (const char*)msg->msgHdr.tr_id.octet, sizeof(msg->msgHdr.tr_id));
943       
944   ortp_debug("stun: Encoding stun message: ");
945
946   if (msg->hasRequestedTransport)
947   {
948      ortp_debug("stun: Encoding TA_REQUESTEDTRANSPORT: %i\n", msg->requestedTransport.proto );
949      ptr = encodeAtrRequestedTransport (ptr, &msg->requestedTransport);
950   }
951   if (msg->hasLifetimeAttributes)
952   {
953      ortp_debug("stun: Encoding TA_LIFETIME: %i\n", msg->lifetimeAttributes.lifetime );
954      ptr = encodeAtrLifeTime (ptr, &msg->lifetimeAttributes);
955   }
956   if (msg->hasDontFragment)
957   {
958      ortp_debug("stun: Encoding TA_DONTFRAGMENT: DF\n");
959      ptr = encodeAtrDontFragment (ptr);
960   }
961
962   if (msg->hasMappedAddress)
963   {
964      ortp_debug("stun: Encoding SA_MAPPEDADDRESS: %s\n", ipaddr(&msg->mappedAddress.ipv4) );
965      ptr = encodeAtrAddress4 (ptr, SA_MAPPEDADDRESS, &msg->mappedAddress);
966   }
967   if (msg->hasResponseAddress)
968   {
969      ortp_debug("stun: Encoding SA_RESPONSEADDRESS: %s\n", ipaddr(&msg->responseAddress.ipv4) );
970      ptr = encodeAtrAddress4(ptr, SA_RESPONSEADDRESS, &msg->responseAddress);
971   }
972   if (msg->hasChangeRequest)
973   {
974      ortp_debug("stun: Encoding SA_CHANGEREQUEST: %i\n", msg->changeRequest.value );
975      ptr = encodeAtrChangeRequest(ptr, &msg->changeRequest);
976   }
977   if (msg->hasSourceAddress)
978   {
979      ortp_debug("stun: Encoding SA_SOURCEADDRESS: %s\n", ipaddr(&msg->sourceAddress.ipv4) );
980      ptr = encodeAtrAddress4(ptr, SA_SOURCEADDRESS, &msg->sourceAddress);
981   }
982   if (msg->hasChangedAddress)
983   {
984      ortp_debug("stun: Encoding SA_CHANGEDADDRESS: %s\n", ipaddr(&msg->changedAddress.ipv4) );
985      ptr = encodeAtrAddress4(ptr, SA_CHANGEDADDRESS, &msg->changedAddress);
986   }
987   if (msg->hasUsername)
988   {
989      ortp_debug("stun: Encoding SA_USERNAME: %s\n", msg->username.value );
990      ptr = encodeAtrString(ptr, SA_USERNAME, &msg->username);
991   }
992   //if (msg->hasPassword)
993   //{
994   //   ortp_debug("stun: Encoding SA_PASSWORD: %s\n", msg->password.value );
995   //   ptr = encodeAtrString(ptr, SA_PASSWORD, &msg->password);
996   //}
997   if (msg->hasErrorCode)
998   {
999      ortp_debug("stun: Encoding SA_ERRORCODE: class=%i number=%i reason=%s\n" 
1000                          , msg->errorCode.errorClass
1001                          , msg->errorCode.number
1002                          , msg->errorCode.reason );
1003     
1004      ptr = encodeAtrError(ptr, &msg->errorCode);
1005   }
1006   if (msg->hasUnknownAttributes)
1007   {
1008      ortp_debug("stun: Encoding SA_UNKNOWNATTRIBUTE: ???");
1009      ptr = encodeAtrUnknown(ptr, &msg->unknownAttributes);
1010   }
1011   if (msg->hasReflectedFrom)
1012   {
1013      ortp_debug("stun: Encoding SA_REFLECTEDFROM: %s\n", ipaddr(&msg->reflectedFrom.ipv4) );
1014      ptr = encodeAtrAddress4(ptr, SA_REFLECTEDFROM, &msg->reflectedFrom);
1015   }
1016   if (msg->hasNonce)
1017   {
1018      ortp_debug("stun: Encoding SA_NONCE: %s\n", msg->nonceName.value );
1019      ptr = encodeAtrString(ptr, SA_NONCE, &msg->nonceName);
1020   }
1021   if (msg->hasRealm)
1022   {
1023      ortp_debug("stun: Encoding SA_REALM: %s\n", msg->realmName.value );
1024      ptr = encodeAtrString(ptr, SA_REALM, &msg->realmName);
1025   }
1026   
1027   if (msg->hasXorMappedAddress)
1028   {
1029      ortp_debug("stun: Encoding SA_XORMAPPEDADDRESS: %s\n", ipaddr(&msg->xorMappedAddress.ipv4) );
1030      ptr = encodeAtrAddress4 (ptr, SA_XORMAPPEDADDRESS, &msg->xorMappedAddress);
1031   }
1032   if (msg->hasSoftware)
1033   {
1034      ortp_debug("stun: Encoding SA_SOFTWARE: %s\n", msg->softwareName.value );
1035      ptr = encodeAtrString(ptr, SA_SOFTWARE, &msg->softwareName);
1036   }
1037
1038   if (msg->hasMessageIntegrity
1039     &&password!=NULL && password->sizeValue > 0
1040     &&msg->username.sizeValue>0
1041     &&msg->realmName.sizeValue>0)
1042   {
1043      StunAtrIntegrity integrity;
1044      //ortp_debug("stun: HMAC with password: %s\n", password->value );
1045
1046      encode16(lengthp, (UInt16)(ptr - buf - sizeof(StunMsgHdr)+24));
1047      computeHmac_longterm(integrity.hash, buf, (int)(ptr-buf) ,
1048        msg->username.value, msg->realmName.value, password->value);
1049      ptr = encodeAtrIntegrity(ptr, &integrity);
1050   }
1051   else if (msg->hasMessageIntegrity
1052     &&password!=NULL && password->sizeValue > 0
1053     &&msg->username.sizeValue>0)
1054   {
1055      StunAtrIntegrity integrity;
1056      //ortp_debug("stun: HMAC with password: %s\n", password->value );
1057
1058      encode16(lengthp, (UInt16)(ptr - buf - sizeof(StunMsgHdr)+24));
1059      computeHmac_shortterm(integrity.hash, buf, (int)(ptr-buf) ,
1060        password->value);
1061      ptr = encodeAtrIntegrity(ptr, &integrity);
1062   }
1063       
1064   encode16(lengthp, (UInt16)(ptr - buf - sizeof(StunMsgHdr)));
1065   return (int)(ptr - buf);
1066}
1067
1068int 
1069stunRand(void)
1070{
1071   /* return 32 bits of random stuff */
1072   /* assert( sizeof(int) == 4 ); */
1073   static bool_t init=FALSE;
1074   if ( !init )
1075   { 
1076      UInt64 tick;
1077      int seed;
1078      init = TRUE;
1079
1080#if defined(_WIN32_WCE)
1081      tick = GetTickCount ();
1082#elif defined(_MSC_VER)
1083      {
1084      volatile unsigned int lowtick=0,hightick=0;
1085      __asm
1086         {
1087            rdtsc
1088               mov lowtick, eax
1089               mov hightick, edx
1090               }
1091      tick = hightick;
1092      tick <<= 32;
1093      tick |= lowtick;
1094      }
1095#elif defined(__GNUC__) && ( defined(__i686__) || defined(__i386__) )
1096      asm("rdtsc" : "=A" (tick));
1097#elif defined(__GNUC__) && defined(__amd64__)
1098      asm("rdtsc" : "=A" (tick));
1099#elif defined (__SUNPRO_CC) && defined( __sparc__ )     
1100      tick = gethrtime();
1101#elif defined(__MACH__)
1102      {
1103        int fd=open("/dev/random",O_RDONLY);
1104        read(fd,&tick,sizeof(tick));
1105        closesocket(fd);
1106      }
1107#elif defined(__linux) || defined(HAVE_DEV_RANDOM)
1108      {
1109        fd_set fdSet;
1110        int maxFd=0;
1111        struct timeval tv;
1112        int e;
1113
1114        int fd=open("/dev/random",O_RDONLY);
1115
1116        if (fd<0)
1117        {
1118            ortp_message("stun: Failed to open random device\n");
1119            return random();
1120        }
1121        FD_ZERO(&fdSet);
1122        FD_SET(fd,&fdSet);
1123        maxFd=fd+1;
1124
1125        tv.tv_sec = 0;
1126        tv.tv_usec = 500;
1127
1128        e = select( maxFd, &fdSet, NULL,NULL, &tv );
1129        if (e <= 0)
1130        {
1131           ortp_error("stun: Failed to get data from random device\n");
1132           closesocket(fd);
1133           return random();
1134        }
1135        read(fd,&tick,sizeof(tick));
1136        closesocket(fd);
1137      }
1138#else
1139#     error Need some way to seed the random number generator
1140#endif
1141      seed = (int)(tick);
1142#if     defined(_WIN32) || defined(_WIN32_WCE)
1143      srand(seed);
1144#else
1145      srandom(seed);
1146#endif
1147   }
1148       
1149#if     defined(_WIN32) || defined(_WIN32_WCE)
1150   /* assert( RAND_MAX == 0x7fff ); */
1151   {
1152       int r1 = rand();
1153       int r2 = rand();
1154       int ret = (r1<<16) + r2;
1155       
1156       return ret;
1157   }
1158#else
1159   return random(); 
1160#endif
1161}
1162
1163
1164/* return a random number to use as a port */
1165static int
1166randomPort()
1167{
1168   int min=0x4000;
1169   int max=0x7FFF;
1170       
1171   int ret = stunRand();
1172   ret = ret|min;
1173   ret = ret&max;
1174       
1175   return ret;
1176}
1177
1178
1179#ifdef NOSSL
1180static void
1181computeHmac_longterm(char* hmac, const char* input, int length,
1182                     const char *username, const char *realm, const char *password)
1183{
1184   strncpy(hmac,"hmac-not-implemented",20);
1185}
1186static void
1187computeHmac_shortterm(char* hmac, const char* input, int length, const char* key)
1188{
1189   strncpy(hmac,"hmac-not-implemented",20);
1190}
1191#else
1192#include <openssl/hmac.h>
1193#include <openssl/md5.h>
1194
1195static void
1196computeHmac_longterm(char* hmac, const char* input, int length,
1197                     const char *username, const char *realm, const char *password)
1198{
1199   unsigned int resultSize=0;
1200   unsigned char HA1[16];
1201   unsigned char HA1_text[1024];
1202
1203   snprintf(HA1_text, sizeof(HA1_text), "%s:%s:%s", username, realm, password);
1204   MD5(HA1_text, strlen(HA1_text), HA1);
1205
1206   HMAC(EVP_sha1(), 
1207        HA1, 16, 
1208        (const unsigned char*) input, length, 
1209        (unsigned char*)hmac, &resultSize);
1210}
1211
1212static void
1213computeHmac_shortterm(char* hmac, const char* input, int length, const char* key)
1214{
1215   unsigned int resultSize=0;
1216   HMAC(EVP_sha1(), 
1217        key, strlen(key), 
1218        (const unsigned char*) input, length, 
1219        (unsigned char*)hmac, &resultSize);
1220}
1221#endif
1222
1223
1224static void
1225toHex(const char* buffer, int bufferSize, char* output) 
1226{
1227   int i;
1228   static char hexmap[] = "0123456789abcdef";
1229       
1230   const char* p = buffer;
1231   char* r = output;
1232   for (i=0; i < bufferSize; i++)
1233   {
1234      unsigned char temp = *p++;
1235               
1236      int hi = (temp & 0xf0)>>4;
1237      int low = (temp & 0xf);
1238               
1239      *r++ = hexmap[hi];
1240      *r++ = hexmap[low];
1241   }
1242   *r = 0;
1243}
1244
1245UInt64
1246stunGetSystemTimeSecs(void)
1247{
1248   UInt64 time=0;
1249#if     defined(_WIN32) || defined(_WIN32_WCE)
1250   SYSTEMTIME t;
1251   /*  CJ TODO - this probably has bug on wrap around every 24 hours */
1252   GetSystemTime( &t );
1253   time = (t.wHour*60+t.wMinute)*60+t.wSecond; 
1254#else
1255   struct timeval now;
1256   gettimeofday( &now , NULL );
1257   /* assert( now ); */
1258   time = now.tv_sec;
1259#endif
1260   return time;
1261}
1262
1263
1264/* returns TRUE if it scucceeded */
1265bool_t 
1266stunParseHostName( char* peerName,
1267                   UInt32* ip,
1268                   UInt16* portVal,
1269                   UInt16 defaultPort )
1270{
1271   struct in_addr sin_addr;
1272   
1273   char host[512];
1274   char* port = NULL;
1275   int portNum = defaultPort;
1276   char* sep;
1277   struct hostent* h;
1278
1279   strncpy(host,peerName,512);
1280   host[512-1]='\0';
1281       
1282   /* pull out the port part if present. */
1283   sep = strchr(host,':');
1284       
1285   if ( sep == NULL )
1286   {
1287      portNum = defaultPort;
1288   }
1289   else
1290   {
1291      char* endPtr=NULL;
1292      *sep = '\0';
1293      port = sep + 1;
1294      /* set port part */
1295     
1296               
1297      portNum = strtol(port,&endPtr,10);
1298               
1299      if ( endPtr != NULL )
1300      {
1301         if ( *endPtr != '\0' )
1302         {
1303            portNum = defaultPort;
1304         }
1305      }
1306   }
1307   
1308   if ( portNum < 1024 ) return FALSE;
1309   if ( portNum >= 0xFFFF ) return FALSE;
1310       
1311   /* figure out the host part */
1312       
1313#if     defined(_WIN32) || defined(_WIN32_WCE)
1314   /* assert( strlen(host) >= 1 ); */
1315   if ( isdigit( host[0] ) )
1316   {
1317      /* assume it is a ip address */
1318      unsigned long a = inet_addr(host);
1319      /* cerr << "a=0x" << hex << a << dec ); */
1320               
1321      *ip = ntohl( a );
1322   }
1323   else
1324   {
1325      /* assume it is a host name */
1326      h = gethostbyname( host );
1327               
1328      if ( h == NULL )
1329      {
1330         /*int err = getErrno();*/
1331
1332         /* ortp_message("stun: error was %i\n", err); */
1333         /* std::cerr << "error was " << err << std::endl; */
1334         /* assert( err != WSANOTINITIALISED ); */
1335                       
1336         *ip = ntohl( 0x7F000001L );
1337                       
1338         return FALSE;
1339      }
1340      else
1341      {
1342         sin_addr = *(struct in_addr*)h->h_addr;
1343         *ip = ntohl( sin_addr.s_addr );
1344      }
1345   }
1346       
1347#else
1348   h = gethostbyname( host );
1349   if ( h == NULL )
1350   {
1351      /*
1352         int err = getErrno();
1353         ortp_message("stun: error was %i\n", err);
1354      */
1355      *ip = ntohl( 0x7F000001L );
1356      return FALSE;
1357   }
1358   else
1359   {
1360      sin_addr = *(struct in_addr*)h->h_addr;
1361      *ip = ntohl( sin_addr.s_addr );
1362   }
1363#endif
1364       
1365   *portVal = portNum;
1366       
1367   return TRUE;
1368}
1369
1370
1371bool_t
1372stunParseServerName( char* name, StunAddress4 *addr)
1373{
1374   /* assert(name); */
1375       
1376   /* TODO - put in DNS SRV stuff. */
1377       
1378   bool_t ret = stunParseHostName( name, &addr->addr, &addr->port, 3478); 
1379   if ( ret != TRUE ) 
1380   {
1381       addr->port=0xFFFF;
1382   }   
1383   return ret;
1384}
1385
1386
1387static void
1388stunCreateErrorResponse(StunMessage *response, int cl, int number, const char* msg)
1389{
1390   response->msgHdr.msgType = (STUN_METHOD_BINDING | STUN_ERR_RESP);
1391   response->hasErrorCode = TRUE;
1392   response->errorCode.errorClass = cl;
1393   response->errorCode.number = number;
1394   strcpy(response->errorCode.reason, msg);
1395}
1396
1397#if 0
1398static void
1399stunCreateSharedSecretErrorResponse(StunMessage& response, int cl, int number, const char* msg)
1400{
1401   response.msgHdr.msgType = SharedSecretErrorResponseMsg;
1402   response.hasErrorCode = TRUE;
1403   response.errorCode.errorClass = cl;
1404   response.errorCode.number = number;
1405   strcpy(response.errorCode.reason, msg);
1406}
1407#endif
1408
1409#if 0
1410static void
1411stunCreateSharedSecretResponse(const StunMessage *request, const StunAddress4 *source, StunMessage *response)
1412{
1413   response->msgHdr.msgType = SharedSecretResponseMsg;
1414   response->msgHdr.tr_id = request->msgHdr.tr_id;
1415       
1416   response->hasUsername = TRUE;
1417   stunCreateUserName( source, &response->username);
1418       
1419   response->hasPassword = TRUE;
1420   stunCreatePassword( &response->username, &response->password);
1421}
1422#endif
1423
1424/* This funtion takes a single message sent to a stun server, parses
1425   and constructs an apropriate repsonse - returns TRUE if message is
1426   valid */
1427bool_t
1428stunServerProcessMsg( char* buf,
1429                      unsigned int bufLen,
1430                      StunAddress4 *from, 
1431                      StunAddress4 *myAddr,
1432                      StunAddress4 *altAddr, 
1433                      StunMessage *resp,
1434                      StunAddress4 *destination,
1435                      StunAtrString *hmacPassword,
1436                      bool_t* changePort,
1437                      bool_t* changeIp)
1438{
1439   int i;
1440   StunMessage req;
1441   StunAddress4 mapped;
1442   StunAddress4 respondTo;
1443   UInt32 flags;
1444   bool_t ok;
1445   /* set up information for default response */
1446       
1447   memset( &req, 0 , sizeof(req) );
1448   memset( resp, 0 , sizeof(*resp) );
1449       
1450   *changeIp = FALSE;
1451   *changePort = FALSE;
1452       
1453   ok = stunParseMessage( buf,bufLen, &req);
1454   
1455   if (!ok)      /* Complete garbage, drop it on the floor */
1456   {
1457      ortp_error("stun: Request did not parse");
1458      return FALSE;
1459   }
1460   //ortp_debug("stun: Request parsed ok");
1461       
1462   mapped = req.mappedAddress.ipv4;
1463   respondTo = req.responseAddress.ipv4;
1464   flags = req.changeRequest.value;
1465       
1466   if (req.msgHdr.msgType==(STUN_METHOD_BINDING|STUN_REQUEST))
1467   {
1468         if (!req.hasMessageIntegrity)
1469         {
1470            //ortp_debug("stun: BindRequest does not contain SA_MESSAGEINTEGRITY");
1471                               
1472            if (0) /* !jf! mustAuthenticate */
1473            {
1474               ortp_error("stun: Received BindRequest with no SA_MESSAGEINTEGRITY. Sending 401.");
1475               stunCreateErrorResponse(resp, 4, 1, "Missing SA_MESSAGEINTEGRITY");
1476               return TRUE;
1477            }
1478         }
1479         else
1480         {
1481            if (!req.hasUsername)
1482            {
1483               ortp_error("stun: No UserName. Send 432.");
1484               stunCreateErrorResponse(resp, 4, 32, "No UserName and contains SA_MESSAGEINTEGRITY");
1485               return TRUE;
1486            }
1487            else
1488            {
1489               //ortp_debug("stun: Validating username: %s", req.username.value );
1490               /* !jf! could retrieve associated password from provisioning here */
1491               if (strcmp(req.username.value, "test") == 0)
1492               {
1493                  if (0)
1494                  {
1495                     /* !jf! if the credentials are stale */
1496                     stunCreateErrorResponse(resp, 4, 30, "Stale credentials on BindRequest");
1497                     return TRUE;
1498                  }
1499                  else
1500                  {
1501                     unsigned char hmac[20];
1502                     //ortp_debug("stun: Validating SA_MESSAGEINTEGRITY");
1503                     /* need access to shared secret */
1504
1505#ifndef NOSSL
1506                     {
1507                        unsigned int hmacSize=20;
1508
1509                        HMAC(EVP_sha1(), 
1510                             "1234", 4, 
1511                             (const unsigned char*) buf, bufLen-20-4, 
1512                             hmac, &hmacSize);
1513                        /*HMAC(EVP_sha1(),
1514                             "1234", 4,
1515                             reinterpret_cast<const unsigned char*>(buf), bufLen-20-4,
1516                             hmac, &hmacSize);
1517                        //assert(hmacSize == 20);
1518                        */
1519                     }
1520#endif
1521                                                       
1522                     if (memcmp(buf, hmac, 20) != 0)
1523                     {
1524                        ortp_error("stun: SA_MESSAGEINTEGRITY is bad. Sending ");
1525                        stunCreateErrorResponse(resp, 4, 3, "Unknown username. Try test with password 1234");
1526                        return TRUE;
1527                     }
1528                                                       
1529                     /* need to compute this later after message is filled in */
1530                     resp->hasMessageIntegrity = TRUE;
1531                     /* assert(req.hasUsername); */
1532                     resp->hasUsername = TRUE;
1533                     resp->username = req.username; /* copy username in */
1534                  }
1535               }
1536               else
1537               {
1538                  ortp_error("stun: Invalid username: %s Send 430", req.username.value); 
1539               }
1540            }
1541         }
1542                       
1543         /* TODO !jf! should check for unknown attributes here and send 420 listing the
1544            unknown attributes. */
1545                       
1546         if ( respondTo.port == 0 )
1547         {
1548            /* respondTo = from; */
1549            memcpy(&respondTo, from, sizeof(StunAddress4));
1550         }
1551         if ( mapped.port == 0 ) 
1552         {
1553            /* mapped = from; */
1554            memcpy(&mapped, from, sizeof(StunAddress4));
1555         }
1556
1557         *changeIp   = ( flags & ChangeIpFlag )?TRUE:FALSE;
1558         *changePort = ( flags & ChangePortFlag )?TRUE:FALSE;
1559                       
1560         //ortp_debug("stun: Request is valid:\n");
1561         //ortp_debug("stun: \t flags= %i\n", flags );
1562         //ortp_debug("stun: \t changeIp= %i\n", *changeIp );
1563         //ortp_debug("stun: \t changePort=%i\n", *changePort );
1564         //ortp_debug("stun: \t from= %i\n", from->addr );
1565         //ortp_debug("stun: \t respond to= %i\n", respondTo.addr );
1566         //ortp_debug("stun: \t mapped= %i\n", mapped.addr );
1567                               
1568         /* form the outgoing message */
1569         resp->msgHdr.msgType = (STUN_METHOD_BINDING | STUN_SUCCESS_RESP);
1570         resp->msgHdr.magic_cookie = ntohl(req.msgHdr.magic_cookie);
1571         for (i=0; i<12; i++ )
1572         {
1573            resp->msgHdr.tr_id.octet[i] = req.msgHdr.tr_id.octet[i];
1574         }
1575               
1576         if (1) /* do xorMapped address or not */
1577         {
1578            UInt32 cookie = 0x2112A442;
1579            UInt16 cookie16;
1580            resp->hasXorMappedAddress = TRUE;
1581            cookie16 = ((UInt8*)&cookie)[0]<<8  | ((UInt8*)&cookie)[1];
1582            resp->xorMappedAddress.ipv4.port = mapped.port^cookie16;
1583            resp->xorMappedAddress.ipv4.addr = mapped.addr^cookie;
1584         }
1585         
1586         resp->hasSourceAddress = TRUE;
1587         resp->sourceAddress.ipv4.port = (*changePort) ? altAddr->port : myAddr->port;
1588         resp->sourceAddress.ipv4.addr = (*changeIp)   ? altAddr->addr : myAddr->addr;
1589                       
1590         resp->hasChangedAddress = TRUE;
1591         resp->changedAddress.ipv4.port = altAddr->port;
1592         resp->changedAddress.ipv4.addr = altAddr->addr;
1593       
1594         if ( req.hasUsername && req.username.sizeValue > 0 ) 
1595         {
1596            /* copy username in */
1597            resp->hasUsername = TRUE;
1598            /* assert( req.username.sizeValue % 4 == 0 ); */
1599            /* assert( req.username.sizeValue < STUN_MAX_STRING ); */
1600            memcpy( resp->username.value, req.username.value, req.username.sizeValue );
1601            resp->username.sizeValue = req.username.sizeValue;
1602         }
1603               
1604         if (1) /* add ServerName */
1605         {
1606            const char serverName[] = "oRTP   " STUN_VERSION; /* must pad to mult of 4 */
1607            resp->hasSoftware = TRUE;
1608           
1609            /* assert( sizeof(serverName) < STUN_MAX_STRING ); */
1610            /* cerr << "sizeof serverName is "  << sizeof(serverName) ); */
1611            /* assert( sizeof(serverName)%4 == 0 ); */
1612            memcpy( resp->softwareName.value, serverName, sizeof(serverName));
1613            resp->softwareName.sizeValue = sizeof(serverName);
1614         }
1615         
1616#if 0
1617         if ( req.hasMessageIntegrity & req.hasUsername ) 
1618         {
1619            /* this creates the password that will be used in the HMAC when then */
1620            /* messages is sent */
1621            stunCreatePassword( &req.username, hmacPassword );
1622         }
1623#endif
1624
1625         if (req.hasUsername && (req.username.sizeValue > 64 ) )
1626         {
1627            UInt32 source;
1628            /* assert( sizeof(int) == sizeof(UInt32) ); */
1629                                       
1630            sscanf(req.username.value, "%x", &source);
1631            resp->hasReflectedFrom = TRUE;
1632            resp->reflectedFrom.ipv4.port = 0;
1633            resp->reflectedFrom.ipv4.addr = source;
1634         }
1635                               
1636         destination->port = respondTo.port;
1637         destination->addr = respondTo.addr;
1638                       
1639         return TRUE;           
1640   }
1641   else
1642   {
1643         ortp_error("stun: Unknown or unsupported request ");
1644         return FALSE;
1645   }
1646       
1647   /* assert(0); */
1648   return FALSE;
1649}
1650
1651bool_t
1652stunInitServer(StunServerInfo *info, const StunAddress4 *myAddr, const StunAddress4 *altAddr, int startMediaPort)
1653{
1654   /* assert( myAddr.port != 0 ); */
1655   /* assert( altAddr.port!= 0 ); */
1656   /* assert( myAddr.addr  != 0 ); */
1657   /* assert( altAddr.addr != 0 ); */
1658       
1659   /* info->myAddr = myAddr; */
1660   info->myAddr.port = myAddr->port;
1661   info->myAddr.addr = myAddr->addr;
1662
1663   /* info->altAddr = altAddr; */
1664   info->altAddr.port = altAddr->port;
1665   info->altAddr.addr = altAddr->addr;
1666       
1667   info->myFd = INVALID_SOCKET;
1668   info->altPortFd = INVALID_SOCKET;
1669   info->altIpFd = INVALID_SOCKET;
1670   info->altIpPortFd = INVALID_SOCKET;
1671
1672   memset(info->relays, 0, sizeof(info->relays));
1673   if (startMediaPort > 0)
1674   {
1675      int i;
1676      info->relay = TRUE;
1677
1678      for (i=0; i<MAX_MEDIA_RELAYS; ++i)
1679      {
1680         StunMediaRelay* relay = &info->relays[i];
1681         relay->relayPort = startMediaPort+i;
1682         relay->fd = 0;
1683         relay->expireTime = 0;
1684      }
1685   }
1686   else
1687   {
1688      info->relay = FALSE;
1689   }
1690   
1691   if ((info->myFd = openPort(myAddr->port, myAddr->addr)) == INVALID_SOCKET)
1692   {
1693      ortp_error("stun: Can't open %i\n", myAddr->addr );
1694      stunStopServer(info);
1695
1696      return FALSE;
1697   }
1698
1699   if ((info->altPortFd = openPort(altAddr->port,myAddr->addr)) == INVALID_SOCKET)
1700   {
1701      ortp_error("stun: Can't open %i\n", myAddr->addr );
1702      stunStopServer(info);
1703      return FALSE;
1704   }
1705   
1706   
1707   info->altIpFd = INVALID_SOCKET;
1708   if (  altAddr->addr != 0 )
1709   {
1710      if ((info->altIpFd = openPort( myAddr->port, altAddr->addr)) == INVALID_SOCKET)
1711      {
1712         ortp_error("stun: Can't open %i\n", altAddr->addr );
1713         stunStopServer(info);
1714         return FALSE;
1715      }
1716   }
1717   
1718   info->altIpPortFd = INVALID_SOCKET;
1719   if (  altAddr->addr != 0 )
1720   {  if ((info->altIpPortFd = openPort(altAddr->port, altAddr->addr)) == INVALID_SOCKET)
1721      {
1722         ortp_error("stun: Can't open %i\n", altAddr->addr );
1723         stunStopServer(info);
1724         return FALSE;
1725      }
1726   }
1727   
1728   return TRUE;
1729}
1730
1731void
1732stunStopServer(StunServerInfo *info)
1733{
1734   if (info->myFd > 0) closesocket(info->myFd);
1735   if (info->altPortFd > 0) closesocket(info->altPortFd);
1736   if (info->altIpFd > 0) closesocket(info->altIpFd);
1737   if (info->altIpPortFd > 0) closesocket(info->altIpPortFd);
1738   
1739   if (info->relay)
1740   {
1741      int i;
1742      for (i=0; i<MAX_MEDIA_RELAYS; ++i)
1743      {
1744         StunMediaRelay* relay = &info->relays[i];
1745         if (relay->fd)
1746         {
1747            closesocket(relay->fd);
1748            relay->fd = 0;
1749         }
1750      }
1751   }
1752}
1753
1754int 
1755stunFindLocalInterfaces(UInt32* addresses,int maxRet)
1756{
1757#if defined(WIN32) || defined(_WIN32_WCE) || defined(__sparc__)
1758   return 0;
1759#else
1760   struct ifconf ifc;
1761   int e;
1762
1763   int s = socket( AF_INET, SOCK_DGRAM, 0 );
1764   int len = 100 * sizeof(struct ifreq);
1765   
1766   char buf[ 100 * sizeof(struct ifreq) ];
1767   char *ptr;
1768   int tl;
1769   int count=0;
1770
1771   ifc.ifc_len = len;
1772   ifc.ifc_buf = buf;
1773       
1774   e = ioctl(s,SIOCGIFCONF,&ifc);
1775   ptr = buf;
1776   tl = ifc.ifc_len;
1777   
1778   while ( (tl > 0) && ( count < maxRet) )
1779   {
1780      struct ifreq* ifr = (struct ifreq *)ptr;
1781      struct ifreq ifr2;
1782      struct sockaddr a;
1783      struct sockaddr_in* addr;
1784   
1785      UInt32 ai;
1786      int si = sizeof(ifr->ifr_name) + sizeof(struct sockaddr);
1787      tl -= si;
1788      ptr += si;
1789      /* char* name = ifr->ifr_ifrn.ifrn_name; */
1790      /* cerr << "name = " << name ); */
1791     
1792      ifr2 = *ifr;
1793     
1794      e = ioctl(s,SIOCGIFADDR,&ifr2);
1795      if ( e == -1 )
1796      {
1797         break;
1798      }
1799     
1800      /* cerr << "ioctl addr e = " << e ; */
1801     
1802      a = ifr2.ifr_addr;
1803      addr = (struct sockaddr_in*) &a;
1804     
1805      ai = ntohl( addr->sin_addr.s_addr );
1806      if ((int)((ai>>24)&0xFF) != 127)
1807      {
1808         addresses[count++] = ai;
1809      }
1810               
1811   }
1812   
1813   closesocket(s);
1814   
1815   return count;
1816#endif
1817}
1818
1819
1820void
1821stunBuildReqSimple( StunMessage* msg,
1822                    const StunAtrString *username,
1823                    bool_t changePort, bool_t changeIp, unsigned int id )
1824{
1825   int i;
1826   /* assert( msg ); */
1827   memset( msg , 0 , sizeof(*msg) );
1828       
1829   msg->msgHdr.msgType = (STUN_METHOD_BINDING|STUN_REQUEST);
1830       
1831   msg->msgHdr.magic_cookie = 0x2112A442;
1832   for ( i=0; i<12; i=i+4 )
1833   {
1834      /* assert(i+3<16); */
1835      int r = stunRand();
1836      msg->msgHdr.tr_id.octet[i+0]= r>>0;
1837      msg->msgHdr.tr_id.octet[i+1]= r>>8;
1838      msg->msgHdr.tr_id.octet[i+2]= r>>16;
1839      msg->msgHdr.tr_id.octet[i+3]= r>>24;
1840   }
1841       
1842   if ( id != 0 )
1843   {
1844      msg->msgHdr.tr_id.octet[0] = id; 
1845   }
1846       
1847   if (changePort==TRUE || changeIp==TRUE)
1848   {
1849     msg->hasChangeRequest = TRUE;
1850     msg->changeRequest.value =(changeIp?ChangeIpFlag:0) | 
1851        (changePort?ChangePortFlag:0);
1852   }
1853
1854   if ( username!=NULL && username->sizeValue > 0 )
1855   {
1856      msg->hasUsername = TRUE;
1857      /* msg->username = username; */
1858      memcpy(&msg->username, username, sizeof(StunAtrString));
1859   }
1860}
1861
1862
1863static void 
1864stunSendTest( Socket myFd, StunAddress4 *dest, 
1865              const StunAtrString *username, const StunAtrString *password, 
1866              int testNum )
1867{ 
1868   /* assert( dest.addr != 0 ); */
1869   /* assert( dest.port != 0 ); */
1870       
1871   bool_t changePort=FALSE;
1872   bool_t changeIP=FALSE;
1873   bool_t discard=FALSE;
1874
1875   StunMessage req;
1876   char buf[STUN_MAX_MESSAGE_SIZE];
1877   int len = STUN_MAX_MESSAGE_SIZE;
1878   
1879   switch (testNum)
1880   {
1881      case 1:
1882      case 10:
1883      case 11:
1884         break;
1885      case 2:
1886         /* changePort=TRUE; */
1887         changeIP=TRUE;
1888         break;
1889      case 3:
1890         changePort=TRUE;
1891         break;
1892      case 4:
1893         changeIP=TRUE;
1894         break;
1895      case 5:
1896         discard=TRUE;
1897         break;
1898      default:
1899         ortp_error("stun: Test %i is unkown\n", testNum);
1900         return ; /* error */
1901   }
1902   
1903   memset(&req, 0, sizeof(StunMessage));
1904       
1905   stunBuildReqSimple( &req, username, 
1906                       changePort , changeIP , 
1907                       testNum );
1908       
1909   len = stunEncodeMessage( &req, buf, len, password );
1910       
1911   //ortp_debug("stun: About to send msg of len %i to %s\n", len, ipaddr(dest) );
1912       
1913   sendMessage( myFd, buf, len, dest->addr, dest->port );
1914       
1915   /* add some delay so the packets don't get sent too quickly */
1916#if defined(_WIN32_WCE)
1917   Sleep (10);
1918#elif defined(WIN32)/* !cj! TODO - should fix this up in windows */
1919   {
1920       clock_t now = clock();
1921       /* assert( CLOCKS_PER_SEC == 1000 ); */
1922       while ( clock() <= now+10 ) { };
1923   }
1924#else
1925                 usleep(10*1000);
1926#endif
1927
1928}
1929
1930
1931#if 0
1932void
1933stunGetUserNameAndPassword(  const StunAddress4 *dest,
1934                             StunAtrString* username,
1935                             StunAtrString* password)
1936{
1937   /* !cj! This is totally bogus - need to make TLS connection to dest and get a */
1938   /* username and password to use */
1939   stunCreateUserName(dest, username);
1940   stunCreatePassword(username, password);
1941}
1942#endif
1943
1944int 
1945stunTest( StunAddress4 *dest, int testNum, StunAddress4* sAddr , StunAddress4 *sMappedAddr, StunAddress4* sChangedAddr)
1946{
1947   /* assert( dest.addr != 0 ); */
1948   /* assert( dest.port != 0 ); */
1949       
1950   int port = randomPort();
1951   UInt32 interfaceIp=0;
1952   Socket myFd;
1953   StunAtrString username;
1954   StunAtrString password;
1955   char msg[STUN_MAX_MESSAGE_SIZE];
1956   int msgLen = STUN_MAX_MESSAGE_SIZE;
1957   StunAddress4 from;
1958   StunMessage resp;
1959   bool_t ok;
1960
1961   if (sAddr)
1962   {
1963      interfaceIp = sAddr->addr;
1964      if ( sAddr->port != 0 )
1965      {
1966        port = sAddr->port;
1967      }
1968   }
1969   myFd = openPort(port,interfaceIp);
1970   if ( myFd == INVALID_SOCKET)
1971       return -1;
1972   
1973   username.sizeValue = 0;
1974   password.sizeValue = 0;
1975       
1976#if 0
1977   stunGetUserNameAndPassword( dest, &username, &password );
1978#endif
1979       
1980   stunSendTest( myFd, dest, &username, &password, testNum );
1981   
1982   ok = getMessage( myFd,
1983               msg,
1984               &msgLen,
1985               &from.addr,
1986               &from.port );
1987   closesocket(myFd);
1988   if (!ok)
1989       return -1;
1990
1991   memset(&resp, 0, sizeof(StunMessage));
1992       
1993   //ortp_debug("stun: Got a response");
1994   ok = stunParseMessage( msg,msgLen, &resp );
1995       
1996   //ortp_debug("stun: \t ok=%i\n", ok );
1997   //ortp_debug("stun: \t SA_MAPPEDADDRESS=%i\n", resp.mappedAddress.ipv4.addr );
1998   //ortp_debug("stun: \t SA_CHANGEDADDRESS=%i\n", resp.changedAddress.ipv4.addr );
1999       
2000   if (sAddr)
2001   {
2002       sAddr->port = port;
2003   }
2004
2005   if (sMappedAddr)
2006   {
2007      sMappedAddr->port = resp.mappedAddress.ipv4.port;
2008      sMappedAddr->addr = resp.mappedAddress.ipv4.addr;
2009   }
2010
2011   if (sChangedAddr)
2012   {
2013      sChangedAddr->port = resp.changedAddress.ipv4.port;
2014      sChangedAddr->addr = resp.changedAddress.ipv4.addr;
2015   }
2016
2017   if (ok)
2018       return 0;
2019   else
2020       return -1;
2021}
2022
2023
2024
2025
2026NatType
2027stunNatType( StunAddress4 *dest, 
2028             bool_t* preservePort, /* if set, is return for if NAT preservers ports or not */
2029             bool_t* hairpin,  /* if set, is the return for if NAT will hairpin packets */
2030             int port, /* port to use for the test, 0 to choose random port */
2031             StunAddress4* sAddr /* NIC to use */
2032   )
2033{ 
2034   /* assert( dest.addr != 0 ); */
2035   /* assert( dest.port != 0 ); */
2036   UInt32 interfaceIp=0;
2037   Socket myFd1;
2038   Socket myFd2;
2039
2040   bool_t respTestI=FALSE;
2041   bool_t isNat=TRUE;
2042   StunAddress4 testIchangedAddr;
2043   StunAddress4 testImappedAddr;
2044   bool_t respTestI2=FALSE; 
2045   bool_t mappedIpSame = TRUE;
2046   StunAddress4 testI2mappedAddr;
2047   /* StunAddress4 testI2dest=dest; */
2048   StunAddress4 testI2dest;
2049   bool_t respTestII=FALSE;
2050   bool_t respTestIII=FALSE;
2051   bool_t respTestHairpin=FALSE;
2052   StunAtrString username;
2053   StunAtrString password;
2054   int count=0;
2055   UInt64 second_started;
2056   UInt64 second_elapsed;
2057   Socket s;
2058
2059   if ( hairpin ) 
2060   {
2061      *hairpin = FALSE;
2062   }
2063       
2064   if ( port == 0 )
2065   {
2066      port = randomPort();
2067   }
2068
2069   if (sAddr)
2070   {
2071      interfaceIp = sAddr->addr;
2072   }
2073   myFd1 = openPort(port,interfaceIp);
2074   myFd2 = openPort(port+1,interfaceIp);
2075
2076   if ( ( myFd1 == INVALID_SOCKET) || ( myFd2 == INVALID_SOCKET) )
2077   {
2078      ortp_error("stun: Some problem opening port/interface to send on\n");
2079      return StunTypeFailure; 
2080   }
2081
2082   /* assert( myFd1 != INVALID_SOCKET ); */
2083   /* assert( myFd2 != INVALID_SOCKET ); */
2084   
2085   memcpy(&testI2dest, dest, sizeof(StunAddress4));
2086
2087   memset(&testImappedAddr,0,sizeof(testImappedAddr));
2088   
2089   username.sizeValue = 0;
2090   password.sizeValue = 0;
2091       
2092#if 0 
2093   stunGetUserNameAndPassword( dest, username, password );
2094#endif
2095       
2096   /* stunSendTest( myFd1, dest, username, password, 1 ); */
2097
2098   
2099   second_started = stunGetSystemTimeSecs();
2100   second_elapsed = 1;
2101
2102   while ( count < 3 && second_elapsed < 5)
2103   {
2104      struct timeval tv;
2105      fd_set fdSet; 
2106      int err;
2107      int e;
2108
2109#if defined(WIN32) || defined(_WIN32_WCE)
2110      unsigned int fdSetSize;
2111#else
2112      int fdSetSize;
2113#endif
2114
2115      second_elapsed = stunGetSystemTimeSecs() - second_started ;
2116
2117      FD_ZERO(&fdSet); fdSetSize=0;
2118      FD_SET(myFd1,&fdSet); fdSetSize = (myFd1+1>fdSetSize) ? myFd1+1 : fdSetSize;
2119      FD_SET(myFd2,&fdSet); fdSetSize = (myFd2+1>fdSetSize) ? myFd2+1 : fdSetSize;
2120      tv.tv_sec=0;
2121      tv.tv_usec=500*1000; /* 150 ms */
2122      if ( count == 0 ) tv.tv_usec=0;
2123               
2124      err = select(fdSetSize, &fdSet, NULL, NULL, &tv);
2125      e = getErrno();
2126      if ( err == SOCKET_ERROR )
2127      {
2128         /* error occured */
2129#if !defined(_WIN32_WCE)
2130         ortp_error("stun: Error %i %s in select\n", e, strerror(e));
2131#else
2132         ortp_error("stun: Error %i in select\n", e);
2133#endif
2134                 closesocket(myFd1); /* AMD */
2135         closesocket(myFd2); /* AMD */
2136         return StunTypeFailure;
2137     }
2138      else if ( err == 0 )
2139      {
2140         /* timeout occured */
2141         count++;
2142         if ( !respTestI ) 
2143         {
2144            stunSendTest( myFd1, dest, &username, &password, 1 );
2145         }         
2146                       
2147         if ( (!respTestI2) && respTestI ) 
2148         {
2149            /* check the address to send to if valid */
2150            if (  ( testI2dest.addr != 0 ) &&
2151                  ( testI2dest.port != 0 ) )
2152            {
2153               stunSendTest( myFd1, &testI2dest, &username, &password, 10 );
2154            }
2155         }
2156                       
2157         if ( !respTestII )
2158         {
2159            stunSendTest( myFd2, dest, &username, &password, 2 );
2160         }
2161                       
2162         if ( !respTestIII )
2163         {
2164            stunSendTest( myFd2, dest, &username, &password, 3 );
2165         }
2166                       
2167         if ( respTestI && (!respTestHairpin) )
2168         {
2169            if (  ( testImappedAddr.addr != 0 ) &&
2170                  ( testImappedAddr.port != 0 ) )
2171            {
2172               stunSendTest( myFd1, &testImappedAddr, &username, &password, 11 );
2173            }
2174         }
2175
2176      }
2177      else
2178      {
2179         int i;
2180         /* data is avialbe on some fd */
2181                       
2182         for ( i=0; i<2; i++)
2183         {
2184            Socket myFd;
2185            if ( i==0 ) 
2186            {
2187               myFd=myFd1;
2188            }
2189            else
2190            {
2191               myFd=myFd2;
2192            }
2193                               
2194            if ( myFd!=INVALID_SOCKET ) 
2195            {                                   
2196               if ( FD_ISSET(myFd,&fdSet) )
2197               {
2198                  char msg[STUN_MAX_MESSAGE_SIZE];
2199                  int msgLen = sizeof(msg);
2200                                                               
2201                  StunAddress4 from;
2202                  StunMessage resp;
2203
2204                  getMessage( myFd,
2205                              msg,
2206                              &msgLen,
2207                              &from.addr,
2208                              &from.port );
2209                 
2210                  memset(&resp, 0, sizeof(StunMessage));
2211                                               
2212                  stunParseMessage( msg,msgLen, &resp );
2213                                               
2214                  //ortp_debug("stun: Received message of type %i id=%i\n",
2215                          //resp.msgHdr.msgType,
2216                          //(int)(resp.msgHdr.tr_id.octet[0]) );
2217                                               
2218                  switch( resp.msgHdr.tr_id.octet[0] )
2219                  {
2220                     case 1:
2221                     {
2222                        if ( !respTestI )
2223                        {
2224                                                                       
2225                           testIchangedAddr.addr = resp.changedAddress.ipv4.addr;
2226                           testIchangedAddr.port = resp.changedAddress.ipv4.port;
2227                           testImappedAddr.addr = resp.mappedAddress.ipv4.addr;
2228                           testImappedAddr.port = resp.mappedAddress.ipv4.port;
2229                                                                       
2230                           if ( preservePort )
2231                           {
2232                              *preservePort = ( testImappedAddr.port == port );
2233                           }                                                           
2234                                                                       
2235                           testI2dest.addr = resp.changedAddress.ipv4.addr;
2236                                                                       
2237                           if (sAddr)
2238                           {
2239                              sAddr->port = testImappedAddr.port;
2240                              sAddr->addr = testImappedAddr.addr;
2241                           }
2242                                                                       
2243                           count = 0;
2244                        }               
2245                        respTestI=TRUE;
2246                     }
2247                     break;
2248                     case 2:
2249                     { 
2250                        respTestII=TRUE;
2251                     }
2252                     break;
2253                     case 3:
2254                     {
2255                        respTestIII=TRUE;
2256                     }
2257                     break;
2258                     case 10:
2259                     {
2260                        if ( !respTestI2 )
2261                        {
2262                           testI2mappedAddr.addr = resp.mappedAddress.ipv4.addr;
2263                           testI2mappedAddr.port = resp.mappedAddress.ipv4.port;
2264                                                               
2265                           mappedIpSame = FALSE;
2266                           if ( (testI2mappedAddr.addr  == testImappedAddr.addr ) &&
2267                                (testI2mappedAddr.port == testImappedAddr.port ))
2268                           { 
2269                              mappedIpSame = TRUE;
2270                           }
2271                                                               
2272                                                       
2273                        }
2274                        respTestI2=TRUE;
2275                     }
2276                     break;
2277                     case 11:
2278                     {
2279                                                       
2280                        if ( hairpin ) 
2281                        {
2282                           *hairpin = TRUE;
2283                        }
2284                        respTestHairpin = TRUE;
2285                     }
2286                     break;
2287                  }
2288               }
2289            }
2290         }
2291      }
2292   }
2293       
2294   closesocket(myFd1); /* AMD */
2295   closesocket(myFd2); /* AMD */
2296
2297   /* see if we can bind to this address */
2298   /* cerr << "try binding to " << testImappedAddr ); */
2299   s = openPort( 0/*use ephemeral*/, testImappedAddr.addr );
2300   if ( s != INVALID_SOCKET )
2301   {
2302      isNat = FALSE;
2303      /* cerr << "binding worked"); */
2304   }
2305   else
2306   {
2307      isNat = TRUE;
2308      /* cerr << "binding failed"); */
2309   }
2310
2311   closesocket(s); /* AMD */
2312       
2313   //ortp_debug("stun: test I = %i\n", respTestI );
2314   //ortp_debug("stun: test II = %i\n", respTestII );
2315   //ortp_debug("stun: test III = %i\n", respTestIII );
2316   //ortp_debug("stun: test I(2) = %i\n", respTestI2 );
2317   ortp_debug("stun: is nat  = %i\n", isNat);
2318   ortp_debug("stun: mapped IP same = %i\n", mappedIpSame );
2319       
2320   /* implement logic flow chart from draft RFC */
2321   if ( respTestI )
2322   {
2323      if ( isNat )
2324      {
2325         if (respTestII)
2326         {
2327            return StunTypeConeNat;
2328         }
2329         else
2330         {
2331            if ( mappedIpSame )
2332            {
2333               if ( respTestIII )
2334               {
2335                  return StunTypeRestrictedNat;
2336               }
2337               else
2338               {
2339                  return StunTypePortRestrictedNat;
2340               }
2341            }
2342            else
2343            {
2344               return StunTypeSymNat;
2345            }
2346         }
2347      }
2348      else
2349      {
2350         if (respTestII)
2351         {
2352            return StunTypeOpen;
2353         }
2354         else
2355         {
2356            return StunTypeSymFirewall;
2357         }
2358      }
2359   }
2360   else
2361   {
2362      return StunTypeBlocked;
2363   }
2364       
2365   return StunTypeUnknown;
2366}
2367
2368int
2369stunOpenSocket( StunAddress4 *dest, StunAddress4* mapAddr, 
2370                int port, StunAddress4* srcAddr )
2371{
2372   /* assert( dest.addr != 0 ); */
2373   /* assert( dest.port != 0 ); */
2374   /* assert( mapAddr );*/
2375   unsigned int interfaceIp = 0;
2376   Socket myFd;
2377   char msg[STUN_MAX_MESSAGE_SIZE];
2378   int msgLen = sizeof(msg);
2379       
2380   StunAtrString username;
2381   StunAtrString password;
2382
2383   StunAddress4 from;
2384   StunMessage resp;
2385   bool_t ok;
2386   StunAddress4 mappedAddr;
2387
2388   if ( port == 0 )
2389   {
2390      port = randomPort();
2391   }
2392
2393   if ( srcAddr )
2394   {
2395      interfaceIp = srcAddr->addr;
2396   }
2397   
2398   myFd = openPort(port,interfaceIp);
2399   if (myFd == INVALID_SOCKET)
2400   {
2401      return myFd;
2402   }
2403   
2404   username.sizeValue = 0;
2405   password.sizeValue = 0;
2406       
2407#if 0
2408   stunGetUserNameAndPassword( dest, username, password );
2409#endif
2410       
2411   stunSendTest(myFd, dest, &username, &password, 1 );
2412       
2413   getMessage( myFd, msg, &msgLen, &from.addr, &from.port );
2414
2415   memset(&resp, 0, sizeof(StunMessage));
2416       
2417   ok = stunParseMessage( msg, msgLen, &resp );
2418   if (!ok)
2419   {
2420       closesocket(myFd);
2421       return -1;
2422   }
2423
2424   if (resp.hasXorMappedAddress==TRUE)
2425   {
2426      UInt32 cookie = 0x2112A442;
2427      UInt16 cookie16 = 0x2112A442 >> 16;
2428      mappedAddr.port = resp.xorMappedAddress.ipv4.port^cookie16;
2429      mappedAddr.addr = resp.xorMappedAddress.ipv4.addr^cookie;
2430   }
2431   else
2432     mappedAddr = resp.mappedAddress.ipv4;
2433       
2434   /*
2435     ortp_message("stun: --- stunOpenSocket --- ");
2436     ortp_message("stun: \treq  id=" << req.id );
2437     ortp_message("stun: \tresp id=" << id );
2438     ortp_message("stun: \tmappedAddr=" << mappedAddr );
2439   */
2440
2441   *mapAddr = mappedAddr;
2442       
2443   return myFd;
2444}
2445
2446
2447bool_t
2448stunOpenSocketPair(StunAddress4 *dest,
2449                   StunAddress4* mapAddr_rtp, 
2450                   StunAddress4* mapAddr_rtcp, 
2451                   int* fd1, int* fd2, 
2452                   int port, StunAddress4* srcAddr )
2453{
2454   /* assert( dest.addr!= 0 ); */
2455   /* assert( dest.port != 0 ); */
2456   /* assert( mapAddr ); */
2457   
2458   const int NUM=2;
2459   char msg[STUN_MAX_MESSAGE_SIZE];
2460   int msgLen =sizeof(msg);
2461       
2462   StunAddress4 from;
2463   int fd[2/*NUM*/];
2464   int i;
2465       
2466   unsigned int interfaceIp = 0;
2467       
2468   StunAtrString username;
2469   StunAtrString password;
2470       
2471   StunAddress4 mappedAddr[2/*NUM*/];
2472
2473   if ( port == 0 )
2474   {
2475      port = randomPort();
2476   }
2477       
2478   *fd1=-1;
2479   *fd2=-1;
2480       
2481   if ( srcAddr )
2482   {
2483      interfaceIp = srcAddr->addr;
2484   }
2485
2486   for( i=0; i<NUM; i++)
2487   {
2488      fd[i] = openPort( (port == 0) ? 0 : (port + i), interfaceIp);
2489      if (fd[i] < 0) 
2490      {
2491         while (i > 0)
2492         {
2493            closesocket(fd[--i]);
2494         }
2495         return FALSE;
2496      }
2497   }
2498       
2499   username.sizeValue = 0;
2500   password.sizeValue = 0;
2501       
2502#if 0
2503   stunGetUserNameAndPassword( dest, username, password );
2504#endif
2505       
2506   for( i=0; i<NUM; i++)
2507   {
2508      stunSendTest(fd[i], dest, &username, &password, 1/*testNum*/ );
2509   }
2510   
2511   for( i=0; i<NUM; i++)
2512   {
2513      StunMessage resp;
2514      bool_t ok;
2515      msgLen = sizeof(msg)/sizeof(*msg);
2516      getMessage( fd[i],
2517                  msg,
2518                  &msgLen,
2519                  &from.addr,
2520                  &from.port);
2521     
2522      memset(&resp, 0, sizeof(StunMessage));
2523               
2524      ok = stunParseMessage( msg, msgLen, &resp );
2525      if (!ok) 
2526      { 
2527          for( i=0; i<NUM; i++)
2528          {
2529              closesocket(fd[i]);
2530          }
2531         return FALSE;
2532      }
2533         
2534      if (resp.hasXorMappedAddress==TRUE)
2535      {
2536        UInt32 cookie = 0x2112A442;
2537        UInt16 cookie16 = 0x2112A442 >> 16;
2538        mappedAddr[i].port = resp.xorMappedAddress.ipv4.port^cookie16;
2539        mappedAddr[i].addr = resp.xorMappedAddress.ipv4.addr^cookie;
2540      }
2541      else
2542        mappedAddr[i] = resp.mappedAddress.ipv4;
2543   }
2544       
2545   //ortp_debug("stun: --- stunOpenSocketPair --- \n");
2546   for( i=0; i<NUM; i++)
2547   {
2548      //ortp_debug("stun: \t mappedAddr=%s\n", ipaddr(&mappedAddr[i]) );
2549   }
2550       
2551    *mapAddr_rtp = mappedAddr[0];
2552    *mapAddr_rtcp = mappedAddr[1];
2553    *fd1 = fd[0];
2554    *fd2 = fd[1];
2555
2556   for( i=0; i<NUM; i++)
2557   {
2558      closesocket( fd[i] );
2559   }
2560       
2561   return TRUE;
2562}
2563
2564static void 
2565turnSendAllocate( Socket myFd, StunAddress4 *dest, 
2566              const StunAtrString *username, const StunAtrString *password,
2567              StunMessage *resp)
2568{ 
2569  bool_t discard=FALSE;
2570
2571  StunMessage req;
2572  char buf[STUN_MAX_MESSAGE_SIZE];
2573  int len = STUN_MAX_MESSAGE_SIZE;
2574  const char serverName[] = "oRTP   " STUN_VERSION; /* must pad to mult of 4 */
2575
2576  memset(&req, 0, sizeof(StunMessage));
2577
2578  stunBuildReqSimple( &req, username, 
2579                     FALSE , FALSE , 
2580                     0 );
2581  req.msgHdr.msgType = (TURN_MEDHOD_ALLOCATE|STUN_REQUEST);
2582
2583  req.hasSoftware = TRUE;
2584  memcpy( req.softwareName.value, serverName, sizeof(serverName));
2585  req.softwareName.sizeValue = sizeof(serverName);
2586
2587  req.hasRequestedTransport = TRUE;
2588  memset(&req.requestedTransport, 0, sizeof(req.requestedTransport));
2589  req.requestedTransport.proto = IPPROTO_UDP;
2590
2591  req.hasDontFragment = TRUE;
2592
2593  if (resp!=NULL
2594    && username!=NULL && username->sizeValue>0
2595    && password!=NULL && password->sizeValue>0
2596    && resp->hasRealm==TRUE
2597    && resp->hasNonce==TRUE)
2598  {
2599    req.hasUsername = TRUE;
2600    memcpy( req.username.value, username->value, username->sizeValue );
2601    req.username.sizeValue = username->sizeValue;
2602
2603    req.hasNonce = TRUE;
2604    memcpy( &req.nonceName, &resp->nonceName, sizeof(resp->nonceName));
2605
2606    req.hasRealm = TRUE;
2607    memcpy( &req.realmName, &resp->realmName, sizeof(resp->realmName));
2608
2609    req.hasMessageIntegrity = TRUE;
2610  }
2611
2612  len = stunEncodeMessage( &req, buf, len, password );
2613
2614  ortp_debug("stun: About to send msg of len %i to %s\n", len, ipaddr(dest) );
2615
2616  sendMessage( myFd, buf, len, dest->addr, dest->port);
2617
2618  /* add some delay so the packets don't get sent too quickly */
2619#if defined(_WIN32_WCE)
2620  Sleep (10);
2621#elif defined(WIN32)/* !cj! TODO - should fix this up in windows */
2622  {
2623    clock_t now = clock();
2624    /* assert( CLOCKS_PER_SEC == 1000 ); */
2625    while ( clock() <= now+10 ) { };
2626  }
2627#else
2628  usleep(10*1000);
2629#endif
2630}
2631
2632bool_t
2633turnAllocateSocketPair(StunAddress4 *dest,
2634                   StunAddress4* mapAddr_rtp, 
2635                   StunAddress4* mapAddr_rtcp, 
2636                   int* fd1, int* fd2, 
2637                   int port, StunAddress4* srcAddr)
2638{
2639   const int NUM=2;
2640   char msg[STUN_MAX_MESSAGE_SIZE];
2641   int msgLen =sizeof(msg);
2642       
2643   StunAddress4 from;
2644   int fd[2/*NUM*/];
2645   int i;
2646       
2647   unsigned int interfaceIp = 0;
2648       
2649   StunAtrString username;
2650   StunAtrString password;
2651       
2652   StunAddress4 mappedAddr[2/*NUM*/];
2653
2654   if ( port == 0 )
2655   {
2656      port = randomPort();
2657   }
2658       
2659   *fd1=-1;
2660   *fd2=-1;
2661       
2662   if ( srcAddr )
2663   {
2664      interfaceIp = srcAddr->addr;
2665   }
2666
2667   for( i=0; i<NUM; i++)
2668   {
2669      fd[i] = openPort( (port == 0) ? 0 : (port + i), 
2670                        interfaceIp);
2671      if (fd[i] < 0) 
2672      {
2673         while (i > 0)
2674         {
2675            closesocket(fd[--i]);
2676         }
2677         return FALSE;
2678      }
2679   }
2680       
2681   snprintf(username.value, sizeof(username.value), "antisip");
2682   username.sizeValue = strlen(username.value);
2683   snprintf(password.value, sizeof(password.value), "exosip");
2684   password.sizeValue = strlen(password.value);
2685       
2686   for( i=0; i<NUM; i++)
2687   {
2688      turnSendAllocate(fd[i], dest, NULL, NULL, NULL );
2689   }
2690   
2691   for( i=0; i<NUM; i++)
2692   {
2693      StunMessage resp;
2694      bool_t ok;
2695      msgLen = sizeof(msg)/sizeof(*msg);
2696      getMessage( fd[i],
2697                  msg,
2698                  &msgLen,
2699                  &from.addr,
2700                  &from.port);
2701     
2702      memset(&resp, 0, sizeof(StunMessage));
2703               
2704      ok = stunParseMessage( msg, msgLen, &resp );
2705      if (!ok) 
2706      { 
2707          for( i=0; i<NUM; i++)
2708          {
2709              closesocket(fd[i]);
2710          }
2711         return FALSE;
2712      }
2713
2714      if (STUN_IS_ERR_RESP(resp.msgHdr.msgType))
2715      {
2716        /* check if we need to authenticate */
2717        if (resp.hasErrorCode==TRUE
2718          && resp.errorCode.errorClass==4 && resp.errorCode.number==1
2719          && resp.hasNonce == TRUE
2720          && resp.hasRealm == TRUE)
2721        {
2722          turnSendAllocate(fd[i], dest, &username, &password, &resp);
2723          i--;
2724        }
2725      }
2726      else if (STUN_IS_SUCCESS_RESP(resp.msgHdr.msgType))
2727      {
2728        if (resp.hasXorRelayedAddress==TRUE)
2729        {
2730          UInt32 cookie = 0x2112A442;
2731          UInt16 cookie16 = 0x2112A442 >> 16;
2732          mappedAddr[i].port = resp.xorRelayedAddress.ipv4.port^cookie16;
2733          mappedAddr[i].addr = resp.xorRelayedAddress.ipv4.addr^cookie;
2734        }
2735        else
2736        {
2737          for( i=0; i<NUM; i++)
2738          {
2739            closesocket(fd[i]);
2740          }
2741          return FALSE;
2742        }
2743      }
2744   }
2745       
2746  for( i=0; i<NUM; i++)
2747  {
2748     ortp_message("stun: stunOpenSocketPair mappedAddr=%s\n", ipaddr(&mappedAddr[i]) );
2749  }
2750       
2751  *mapAddr_rtp = mappedAddr[0];
2752  *mapAddr_rtcp = mappedAddr[1];
2753  *fd1 = fd[0];
2754  *fd2 = fd[1];
2755
2756  for( i=0; i<NUM; i++)
2757  {
2758    closesocket( fd[i] );
2759  }
2760       
2761  return TRUE;
2762}
2763
2764/* Local Variables:
2765   mode:c
2766   c-file-style:"ellemtel"
2767   c-file-offsets:((case-label . +))
2768   indent-tabs-mode:nil
2769   End:
2770*/
2771
Note: See TracBrowser for help on using the repository browser.