1 #ifndef STUN_H
2 #define STUN_H
3 
4 #include <iostream>
5 #include <time.h>
6 
7 // if you change this version, change in makefile too
8 #define STUN_VERSION "0.96"
9 
10 #define STUN_MAX_STRING 256
11 #define STUN_MAX_UNKNOWN_ATTRIBUTES 8
12 #define STUN_MAX_MESSAGE_SIZE 2048
13 
14 #define STUN_PORT 3478
15 
16 // define some basic types
17 typedef unsigned char  UInt8;
18 typedef unsigned short UInt16;
19 typedef unsigned int   UInt32;
20 #if defined( WIN32 )
21 typedef unsigned __int64 UInt64;
22 #else
23 typedef unsigned long long UInt64;
24 #endif
25 typedef struct { unsigned char octet[16]; }  UInt128;
26 
27 /// define a structure to hold a stun address
28 const UInt8  IPv4Family = 0x01;
29 const UInt8  IPv6Family = 0x02;
30 
31 // define  flags
32 const UInt32 ChangeIpFlag   = 0x04;
33 const UInt32 ChangePortFlag = 0x02;
34 
35 // define  stun attribute
36 const UInt16 MappedAddress    = 0x0001;
37 const UInt16 ResponseAddress  = 0x0002;
38 const UInt16 ChangeRequest    = 0x0003;
39 const UInt16 SourceAddress    = 0x0004;
40 const UInt16 ChangedAddress   = 0x0005;
41 const UInt16 Username         = 0x0006;
42 const UInt16 Password         = 0x0007;
43 const UInt16 MessageIntegrity = 0x0008;
44 const UInt16 ErrorCode        = 0x0009;
45 const UInt16 UnknownAttribute = 0x000A;
46 const UInt16 ReflectedFrom    = 0x000B;
47 const UInt16 XorMappedAddress = 0x8020;
48 const UInt16 XorOnly          = 0x0021;
49 const UInt16 ServerName       = 0x8022;
50 const UInt16 SecondaryAddress = 0x8050; // Non standard extention
51 
52 // define types for a stun message
53 const UInt16 BindRequestMsg               = 0x0001;
54 const UInt16 BindResponseMsg              = 0x0101;
55 const UInt16 BindErrorResponseMsg         = 0x0111;
56 const UInt16 SharedSecretRequestMsg       = 0x0002;
57 const UInt16 SharedSecretResponseMsg      = 0x0102;
58 const UInt16 SharedSecretErrorResponseMsg = 0x0112;
59 
60 typedef struct
61 {
62       UInt16 msgType;
63       UInt16 msgLength;
64       UInt128 id;
65 } StunMsgHdr;
66 
67 
68 typedef struct
69 {
70       UInt16 type;
71       UInt16 length;
72 } StunAtrHdr;
73 
74 typedef struct
75 {
76       UInt16 port;
77       UInt32 addr;
78 } StunAddress4;
79 
80 typedef struct
81 {
82       UInt8 pad;
83       UInt8 family;
84       StunAddress4 ipv4;
85 } StunAtrAddress4;
86 
87 typedef struct
88 {
89       UInt32 value;
90 } StunAtrChangeRequest;
91 
92 typedef struct
93 {
94       UInt16 pad; // all 0
95       UInt8 errorClass;
96       UInt8 number;
97       char reason[STUN_MAX_STRING];
98       UInt16 sizeReason;
99 } StunAtrError;
100 
101 typedef struct
102 {
103       UInt16 attrType[STUN_MAX_UNKNOWN_ATTRIBUTES];
104       UInt16 numAttributes;
105 } StunAtrUnknown;
106 
107 typedef struct
108 {
109       char value[STUN_MAX_STRING];
110       UInt16 sizeValue;
111 } StunAtrString;
112 
113 typedef struct
114 {
115       char hash[20];
116 } StunAtrIntegrity;
117 
118 typedef enum
119 {
120    HmacUnkown=0,
121    HmacOK,
122    HmacBadUserName,
123    HmacUnkownUserName,
124    HmacFailed,
125 } StunHmacStatus;
126 
127 typedef struct
128 {
129       StunMsgHdr msgHdr;
130 
131       bool hasMappedAddress;
132       StunAtrAddress4  mappedAddress;
133 
134       bool hasResponseAddress;
135       StunAtrAddress4  responseAddress;
136 
137       bool hasChangeRequest;
138       StunAtrChangeRequest changeRequest;
139 
140       bool hasSourceAddress;
141       StunAtrAddress4 sourceAddress;
142 
143       bool hasChangedAddress;
144       StunAtrAddress4 changedAddress;
145 
146       bool hasUsername;
147       StunAtrString username;
148 
149       bool hasPassword;
150       StunAtrString password;
151 
152       bool hasMessageIntegrity;
153       StunAtrIntegrity messageIntegrity;
154 
155       bool hasErrorCode;
156       StunAtrError errorCode;
157 
158       bool hasUnknownAttributes;
159       StunAtrUnknown unknownAttributes;
160 
161       bool hasReflectedFrom;
162       StunAtrAddress4 reflectedFrom;
163 
164       bool hasXorMappedAddress;
165       StunAtrAddress4  xorMappedAddress;
166 
167       bool xorOnly;
168 
169       bool hasServerName;
170       StunAtrString serverName;
171 
172       bool hasSecondaryAddress;
173       StunAtrAddress4 secondaryAddress;
174 } StunMessage;
175 
176 
177 // Define enum with different types of NAT
178 typedef enum
179 {
180    StunTypeUnknown=0,
181    StunTypeFailure,
182    StunTypeOpen,
183    StunTypeBlocked,
184 
185    StunTypeIndependentFilter,
186    StunTypeDependentFilter,
187    StunTypePortDependedFilter,
188    StunTypeDependentMapping,
189 
190    //StunTypeConeNat,
191    //StunTypeRestrictedNat,
192    //StunTypePortRestrictedNat,
193    //StunTypeSymNat,
194 
195    StunTypeFirewall,
196 } NatType;
197 
198 #ifdef WIN32
199 typedef SOCKET Socket;
200 #else
201 typedef int Socket;
202 #endif
203 
204 #define MAX_MEDIA_RELAYS 500
205 #define MAX_RTP_MSG_SIZE 1500
206 #define MEDIA_RELAY_TIMEOUT 3*60
207 
208 typedef struct
209 {
210       int relayPort;       // media relay port
211       int fd;              // media relay file descriptor
212       StunAddress4 destination; // NAT IP:port
213       time_t expireTime;      // if no activity after time, close the socket
214 } StunMediaRelay;
215 
216 typedef struct
217 {
218       StunAddress4 myAddr;
219       StunAddress4 altAddr;
220       Socket myFd;
221       Socket altPortFd;
222       Socket altIpFd;
223       Socket altIpPortFd;
224       bool relay; // true if media relaying is to be done
225       StunMediaRelay relays[MAX_MEDIA_RELAYS];
226 } StunServerInfo;
227 
228 bool
229 stunParseMessage( char* buf,
230                   unsigned int bufLen,
231                   StunMessage& message,
232                   bool verbose );
233 
234 void
235 stunBuildReqSimple( StunMessage* msg,
236                     const StunAtrString& username,
237                     bool changePort, bool changeIp, unsigned int id=0 );
238 
239 unsigned int
240 stunEncodeMessage( const StunMessage& message,
241                    char* buf,
242                    unsigned int bufLen,
243                    const StunAtrString& password,
244                    bool verbose);
245 
246 void
247 stunCreateUserName(const StunAddress4& addr, StunAtrString* username);
248 
249 void
250 stunGetUserNameAndPassword(  const StunAddress4& dest,
251                              StunAtrString* username,
252                              StunAtrString* password);
253 
254 void
255 stunCreatePassword(const StunAtrString& username, StunAtrString* password);
256 
257 int
258 stunRand();
259 
260 UInt64
261 stunGetSystemTimeSecs();
262 
263 /// find the IP address of a the specified stun server - return false is fails parse
264 bool
265 stunParseServerName( char* serverName, StunAddress4& stunServerAddr);
266 
267 bool
268 stunParseHostName( char* peerName,
269                    UInt32& ip,
270                    UInt16& portVal,
271                    UInt16 defaultPort );
272 
273 /// return true if all is OK
274 /// Create a media relay and do the STERN thing if startMediaPort is non-zero
275 bool
276 stunInitServer(StunServerInfo& info,
277                const StunAddress4& myAddr,
278                const StunAddress4& altAddr,
279                int startMediaPort,
280                bool verbose);
281 
282 void
283 stunStopServer(StunServerInfo& info);
284 
285 /// return true if all is OK
286 bool
287 stunServerProcess(StunServerInfo& info, bool verbose);
288 
289 /// returns number of address found - take array or addres
290 int
291 stunFindLocalInterfaces(UInt32* addresses, int maxSize );
292 
293 void
294 stunTest( StunAddress4& dest, int testNum, bool verbose, StunAddress4* srcAddr=0 );
295 
296 NatType
297 stunNatType( StunAddress4& dest, bool verbose,
298              bool* preservePort=0, // if set, is return for if NAT preservers ports or not
299              bool* hairpin=0 ,  // if set, is the return for if NAT will hairpin packets
300              int port=0, // port to use for the test, 0 to choose random port
301              StunAddress4* sAddr=0 // NIC to use
302    );
303 
304 /// prints a StunAddress
305 std::ostream&
306 operator<<( std::ostream& strm, const StunAddress4& addr);
307 
308 std::ostream&
309 operator<< ( std::ostream& strm, const UInt128& );
310 
311 
312 bool
313 stunServerProcessMsg( char* buf,
314                       unsigned int bufLen,
315                       StunAddress4& from,
316                       StunAddress4& myAddr,
317                       StunAddress4& altAddr,
318                       StunMessage* resp,
319                       StunAddress4* destination,
320                       StunAtrString* hmacPassword,
321                       bool* changePort,
322                       bool* changeIp,
323                       bool verbose);
324 
325 int
326 stunOpenSocket( StunAddress4& dest,
327                 StunAddress4* mappedAddr,
328                 int port=0,
329                 StunAddress4* srcAddr=0,
330                 bool verbose=false );
331 
332 bool
333 stunOpenSocketPair( StunAddress4& dest, StunAddress4* mappedAddr,
334                     int* fd1, int* fd2,
335                     int srcPort=0,  StunAddress4* srcAddr=0,
336                     bool verbose=false);
337 
338 int
339 stunRandomPort();
340 
341 #endif
342 
343 
344 /* ====================================================================
345  * The Vovida Software License, Version 1.0
346  *
347  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
348  *
349  * Redistribution and use in source and binary forms, with or without
350  * modification, are permitted provided that the following conditions
351  * are met:
352  *
353  * 1. Redistributions of source code must retain the above copyright
354  *    notice, this list of conditions and the following disclaimer.
355  *
356  * 2. Redistributions in binary form must reproduce the above copyright
357  *    notice, this list of conditions and the following disclaimer in
358  *    the documentation and/or other materials provided with the
359  *    distribution.
360  *
361  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
362  *    and "Vovida Open Communication Application Library (VOCAL)" must
363  *    not be used to endorse or promote products derived from this
364  *    software without prior written permission. For written
365  *    permission, please contact vocal@vovida.org.
366  *
367  * 4. Products derived from this software may not be called "VOCAL", nor
368  *    may "VOCAL" appear in their name, without prior written
369  *    permission of Vovida Networks, Inc.
370  *
371  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
372  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
373  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
374  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
375  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
376  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
377  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
378  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
379  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
380  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
381  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
382  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
383  * DAMAGE.
384  *
385  * ====================================================================
386  *
387  * This software consists of voluntary contributions made by Vovida
388  * Networks, Inc. and many individuals on behalf of Vovida Networks,
389  * Inc.  For more information on Vovida Networks, Inc., please see
390  * <http://www.vovida.org/>.
391  *
392  */
393 
394 // Local Variables:
395 // mode:c++
396 // c-file-style:"ellemtel"
397 // c-file-offsets:((case-label . +))
398 // indent-tabs-mode:nil
399 // End:
400 
401