source: mediastreamer2/linphone/oRTP/src/stun.c @ 15:0e361358def7

Last change on this file since 15:0e361358def7 was 15:0e361358def7, checked in by smorlat <smorlat@…>, 5 years ago
  • stun improvements (untested)
  • support for one relay (work in progress)

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

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