Advertisement
Guest User

stun client

a guest
Aug 27th, 2012
4,281
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 16.46 KB | None | 0 0
  1. //(c) joric^proxium, 2010, public domain
  2.                    
  3.  
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <time.h>
  7. #include <memory.h>
  8.  
  9.  
  10. #ifndef __NET_H__
  11. #define __NET_H__
  12.  
  13. #ifdef _WIN32
  14. #include <malloc.h>
  15. #include <winsock2.h>
  16. #include <windows.h>
  17. //#include "md5.h"
  18. //#include "hmac.h"
  19. #define THREAD DWORD
  20. #else
  21. #include <sys/time.h>
  22. #include <sys/socket.h>
  23. #include <netinet/in.h>
  24. #include <arpa/inet.h>
  25. #include <netdb.h>
  26. #include <openssl/md5.h>
  27. #include <openssl/hmac.h>
  28. #include <pthread.h>
  29. #define SOCKET int
  30. #define THREAD pthread_t
  31. #define closesocket close
  32. #define Sleep(t) usleep(t*1000)
  33. #endif
  34.  
  35. #define ADDRESS struct sockaddr_in
  36.  
  37. #ifndef __HEX_H__
  38. #define __HEX_H__
  39.  
  40. int hex_encode(char *dest, char *src, int len)
  41. {
  42.     char *table = "0123456789abcdef";
  43.     int j;
  44.     for (j = 0; j < len; j++)
  45.     {
  46.         dest[j * 2] = table[((src[j] >> 4) & 0xF)];
  47.         dest[j * 2 + 1] = table[(src[j]) & 0x0F];
  48.     }
  49.     dest[len * 2] = 0;
  50.     return len * 2;
  51. }
  52.  
  53. void hex_decode(char *dest, char *src, int len)
  54. {
  55.     unsigned char v = 0;
  56.     char *d = dest;
  57.     char *p = src;
  58.     int res;
  59.  
  60.     while ((res = sscanf(p, "%02x", &v)) > 0)
  61.     {
  62.         *d++ = v;
  63.         p += res * 2;
  64.     }
  65. }
  66.  
  67. char *hex_string(char *buf, int len)
  68. {
  69.     static char msg[256];
  70.     hex_encode(msg, buf, len);
  71.     return msg;
  72. }
  73.  
  74. #endif //__HEX_H__
  75.  
  76. typedef struct
  77. {
  78.     char *buf;
  79.     int ofs;
  80.     int size;
  81.     int len;
  82. } PACKET;
  83.  
  84. int packet_init(PACKET * m, char *buf, int buf_size)
  85. {
  86.     m->buf = buf;
  87.     m->size = buf_size;
  88.     m->len = 0;
  89.     m->ofs = 0;
  90.     return 0;
  91. }
  92.  
  93. int packet_write(PACKET * m, int v)
  94. {
  95.     if (m && m->ofs < m->size - 1)
  96.     {
  97.         m->buf[m->ofs++] = v & 0xff;
  98.  
  99.         if (m->len < m->ofs)
  100.             m->len++;
  101.  
  102.         return 1;
  103.     }
  104.     return 0;
  105. }
  106.  
  107. unsigned long long packet_read(PACKET * m)
  108. {
  109.     return (m && (m->ofs < m->size - 1)) ? m->buf[m->ofs++] & 0xff : 0;
  110. }
  111.  
  112. #define w8(m, v) packet_write(m, v & 0xff)
  113. #define w16(m, v) w8(m, v >> 8) + w8(m, v)
  114. #define w32(m, v) w16(m, v >> 16) + w16(m, v)
  115. #define w64(m, v) w32(m, v >> 32) + w32(m, v)
  116. #define wBuf(m, buf, len) { int k = 0, i = 0; for (i = 0; i < len; i++) k += w8(m, buf[i]); }
  117. #define r8(m) packet_read(m)
  118. #define r16(m) (((r8(m) << 8) | r8(m)) & 0xffff)
  119. #define r32(m) ((r16(m) << 16) | r16(m))
  120. #define r64(m) ((r32(m) << 32) | r32(m))
  121. #define rBuf(m, buf, len) { int i= 0; for (i = 0; i < len; i++) buf[i] = r8(m); }
  122.  
  123. int round_int(int offset, int align)
  124. {
  125.     return offset + ((align - (offset % align)) % align);
  126. }
  127.  
  128. void random_data(char *buf, int a, int b, int len)
  129. {
  130.     int i;
  131.     for (i = 0; i < len; i++)
  132.         buf[i] = a + rand() % (b - a);
  133. }
  134.  
  135. typedef struct
  136. {
  137.     ADDRESS *addr;
  138.     SOCKET sock;
  139.     THREAD thread;
  140.     char *host;
  141.     int port;       //local port
  142.     int started;
  143. } LINK;
  144.  
  145. char *net_to_string(ADDRESS * addr)
  146. {
  147.     static char msg[64];
  148.     unsigned char *ip = (unsigned char *) &addr->sin_addr.s_addr;
  149.     sprintf(msg, "%d.%d.%d.%d:%d", ip[0], ip[1], ip[2], ip[3], ntohs(addr->sin_port));
  150.     return msg;
  151. }
  152.  
  153. void net_make_address(ADDRESS * addr, unsigned int ip, int port)
  154. {
  155.     memset(addr, 0, sizeof(ADDRESS));
  156.     addr->sin_family = AF_INET;
  157.     addr->sin_port = htons(port);
  158.     addr->sin_addr.s_addr = ip;
  159. }
  160.  
  161. int net_resolve_address(ADDRESS * addr, char *host, int port)
  162. {
  163.     net_make_address(addr, 0, port);
  164.     struct hostent *hp = (struct hostent *) gethostbyname(host);
  165.     if (hp)
  166.         *(int *) &addr->sin_addr.s_addr = *(int *) hp->h_addr_list[0];
  167. return 0;
  168. }
  169.  
  170. int net_is_local_address(ADDRESS * addr)
  171. {
  172.     SOCKET sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
  173.     ADDRESS loc_addr;
  174.     net_make_address(&loc_addr, addr->sin_addr.s_addr, 0);  //ephemeral
  175.  
  176.     printf("Checking NAT: trying to bind to %s\n", net_to_string(&loc_addr));
  177.  
  178.     if (bind(sock, (struct sockaddr *) &loc_addr, sizeof(ADDRESS)) == 0)
  179.     {
  180.         printf("success, no NAT\n");
  181.         closesocket(sock);
  182.         return 1;
  183.     }
  184.     printf("failed, NAT present\n");
  185.     return 0;
  186. }
  187.  
  188. extern void net_recv(char *buf, int len);
  189.  
  190. static void *net_thread(void *param)
  191. {
  192.     int buf_size = 8192;
  193.     char buf[8192];
  194.     int len = 0;
  195.  
  196.     LINK *link = (LINK *) param;
  197.  
  198.     printf("resolving host %s\n", link->host);
  199.  
  200.     if (link->host)
  201.         net_resolve_address(link->addr, link->host, link->port);
  202.  
  203.     printf("resolved to %s\n", net_to_string(link->addr));
  204.  
  205.     if ((link->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
  206.         goto cleanup;
  207.  
  208.  
  209.     {
  210.         link->port = 0; //ephemeral
  211.         ADDRESS loc_addr;
  212.         net_make_address(&loc_addr, INADDR_ANY, link->port);  
  213.  
  214.         if (bind(link->sock, (struct sockaddr *) &loc_addr, sizeof(ADDRESS)) < 0)
  215.             goto cleanup;
  216.  
  217.         //trying to figure out local port
  218.  
  219.         int addr_size = sizeof(ADDRESS);
  220.         getsockname(link->sock, (struct sockaddr *) &loc_addr, &addr_size);
  221.  
  222.         link->port = loc_addr.sin_port;
  223.  
  224.         printf("sitting on: %s\n", net_to_string(&loc_addr));
  225.     }
  226.  
  227.  
  228.     link->started = 1;
  229.  
  230.     while (link != NULL)
  231.     {
  232.         ADDRESS addr;
  233.         int addr_size = sizeof(ADDRESS);
  234.  
  235.         len = recvfrom(link->sock, buf, buf_size, 0, (struct sockaddr *) &addr, &addr_size);
  236.  
  237.         if (len >= 0)
  238.         {
  239.             printf("received %d bytes from %s\n", len, net_to_string(&addr));
  240.             net_recv(buf, len);
  241.         }
  242.  
  243.         Sleep(1);
  244.     }
  245.  
  246. cleanup:
  247.     closesocket(link->sock);
  248.  
  249.     return 0;
  250. }
  251.  
  252. int net_init()
  253. {
  254. #ifdef _WIN32
  255.     WSADATA wsa;
  256.     return WSAStartup(MAKEWORD(2, 2), &wsa) == 0;
  257. #endif
  258.     return 0;
  259. }
  260.  
  261. int net_open_link(LINK * link)
  262. {
  263. #ifdef _WIN32
  264.     CreateThread((LPSECURITY_ATTRIBUTES) NULL, 0, (LPTHREAD_START_ROUTINE) net_thread, link, 0, &link->thread);
  265. #else
  266.     pthread_create(&link->thread, NULL, net_thread, link);
  267. #endif
  268.     return 0;
  269. }
  270.  
  271. int net_send(LINK * link, char *buf, int len)
  272. {
  273.     printf("sending %d bytes to %s\n", len, net_to_string(link->addr));
  274.  
  275.     sendto(link->sock, buf, len, 0, (struct sockaddr *) link->addr, sizeof(struct sockaddr));
  276. return 0;
  277. }
  278.  
  279. #endif //__NET_H__
  280.  
  281. #ifndef __STUN_H__
  282. #define __STUN_H__
  283.  
  284.  
  285.  
  286. typedef struct
  287. {
  288.     ADDRESS base_address;
  289.     ADDRESS mapped_address;
  290.     ADDRESS changed_address;
  291.     LINK *link;
  292.     int state;
  293.     int received;
  294.     int test;
  295.     int nat;
  296.     int finished;
  297.     int send_time;
  298.     int results[8];
  299.     int timeout;
  300.     int mappedports[4];
  301.     int presport;
  302.     int fpresport;
  303.    
  304. } STUN;
  305.  
  306. #define TN(id) {static char buf[16]; sprintf(buf, "0x%04x", id); return buf; }
  307. #define T(id) if (type == id) return #id+5; else
  308.  
  309. enum
  310. {
  311.     STUN_HEADER_SIZE = 20,
  312.     STUN_MAGIC_COOKIE = 0x2112A442,
  313.     STUN_BINDING_METHOD = 1,
  314.     STUN_SHARED_SECRET_METHOD = 2,
  315.     STUN_ALLOCATE_METHOD = 3,
  316.     STUN_REFRESH_METHOD = 4,
  317.     STUN_SEND_METHOD = 6,
  318.     STUN_DATA_METHOD = 7,
  319.     STUN_CHANNEL_BIND_METHOD = 9,
  320.     STUN_REQUEST_CLASS = 0,
  321.     STUN_INDICATION_CLASS = 1,
  322.     STUN_SUCCESS_CLASS = 2,
  323.     STUN_ERROR_CLASS = 3,
  324. };
  325.  
  326. enum stun_vars
  327. {
  328.     STUN_MAPPED_ADDRESS = 0x0001,
  329.     STUN_RESPONSE_ADDRESS = 0x0002,
  330.     STUN_CHANGE_REQUEST = 0x0003,
  331.     STUN_SOURCE_ADDRESS = 0x0004,
  332.     STUN_CHANGED_ADDRESS = 0x0005,
  333.     STUN_USERNAME = 0x0006,
  334.     STUN_PASSWORD = 0x0007,
  335.     STUN_MESSAGE_INTEGRITY = 0x0008,
  336.     STUN_ERROR_CODE = 0x0009,
  337.     STUN_UNKNOWN_ATTRIBUTES = 0x000A,
  338.     STUN_REFLECTED_FROM = 0x000B,
  339.     STUN_CHANNEL_NUMBER = 0x000C,
  340.     STUN_LIFETIME = 0x000D,
  341.     STUN_BANDWIDTH = 0x0010,
  342.     STUN_PEER_ADDRESS = 0x0012,
  343.     STUN_DATA = 0x0013,
  344.     STUN_REALM = 0x0014,
  345.     STUN_NONCE = 0x0015,
  346.     STUN_RELAYED_ADDRESS = 0x0016,
  347.     STUN_REQUESTED_ADDRESS_TYPE = 0x0017,
  348.     STUN_REQUESTED_PROPS = 0x0018,
  349.     STUN_REQUESTED_TRANSPORT = 0x0019,
  350.     STUN_XOR_MAPPED_ADDRESS = 0x8020,
  351.     STUN_TIMER_VAL = 0x0021,
  352.     STUN_RESERVATION_TOKEN = 0x0022,
  353.     STUN_XOR_REFLECTED_FROM = 0x0023,
  354.     STUN_PRIORITY = 0x0024,
  355.     STUN_USE_CANDIDATE = 0x0025,
  356.     STUN_ICMP = 0x0030,
  357.     STUN_END_MANDATORY_ATTR,
  358.     STUN_START_EXTENDED_ATTR = 0x8021,
  359.     STUN_SOFTWARE = 0x8022,
  360.     STUN_ALTERNATE_SERVER = 0x8023,
  361.     STUN_REFRESH_INTERVAL = 0x8024,
  362.     STUN_FINGERPRINT = 0x8028,
  363.     STUN_ICE_CONTROLLED = 0x8029,
  364.     STUN_ICE_CONTROLLING = 0x802A,
  365. };
  366.  
  367. #define TN(id) {static char buf[16]; sprintf(buf, "0x%04x", id); return buf; }
  368. #define T(id) if (type == id) return #id+5; else
  369.  
  370. char *ATTR_NAME(int type)
  371. {
  372.     T(STUN_MAPPED_ADDRESS);
  373.     T(STUN_RESPONSE_ADDRESS);
  374.     T(STUN_CHANGE_REQUEST);
  375.     T(STUN_SOURCE_ADDRESS);
  376.     T(STUN_CHANGED_ADDRESS);
  377.     T(STUN_USERNAME);
  378.     T(STUN_PASSWORD);
  379.     T(STUN_MESSAGE_INTEGRITY);
  380.     T(STUN_ERROR_CODE);
  381.     T(STUN_UNKNOWN_ATTRIBUTES);
  382.     T(STUN_REFLECTED_FROM);
  383.     T(STUN_CHANNEL_NUMBER);
  384.     T(STUN_LIFETIME);
  385.     T(STUN_BANDWIDTH);
  386.     T(STUN_PEER_ADDRESS);
  387.     T(STUN_DATA);
  388.     T(STUN_REALM);
  389.     T(STUN_NONCE);
  390.     T(STUN_RELAYED_ADDRESS);
  391.     T(STUN_REQUESTED_ADDRESS_TYPE);
  392.     T(STUN_REQUESTED_PROPS);
  393.     T(STUN_REQUESTED_TRANSPORT);
  394.     T(STUN_XOR_MAPPED_ADDRESS);
  395.     T(STUN_TIMER_VAL);
  396.     T(STUN_RESERVATION_TOKEN);
  397.     T(STUN_XOR_REFLECTED_FROM);
  398.     T(STUN_PRIORITY);
  399.     T(STUN_USE_CANDIDATE);
  400.     T(STUN_ICMP);
  401.     T(STUN_END_MANDATORY_ATTR);
  402.     T(STUN_START_EXTENDED_ATTR);
  403.     T(STUN_SOFTWARE);
  404.     T(STUN_ALTERNATE_SERVER);
  405.     T(STUN_REFRESH_INTERVAL);
  406.     T(STUN_FINGERPRINT);
  407.     T(STUN_ICE_CONTROLLED);
  408.     T(STUN_ICE_CONTROLLING);
  409.     TN(type);
  410. };
  411.  
  412. void stun_write_header(PACKET * m, int type)
  413. {
  414.     char tsx_id[12];
  415.     random_data(tsx_id, 0, 0xff, 12);
  416.     w16(m, type);
  417.     w16(m, 0);
  418.     w32(m, STUN_MAGIC_COOKIE);
  419.     wBuf(m, tsx_id, 12);
  420. }
  421.  
  422. void stun_write_footer(PACKET * m)
  423. {
  424.     m->ofs = 2;
  425.     w16(m, m->len - STUN_HEADER_SIZE);
  426. }
  427.  
  428. int stun_xor_address(ADDRESS * addr)
  429. {
  430.     int i;
  431.     int x = htonl(STUN_MAGIC_COOKIE);
  432.     char *p = (char *) &x;
  433.     int msb = ((char *) &x)[0] << 8 | ((char *) &x)[1];
  434.     addr->sin_port ^= htons(msb);
  435.     char *ip = (char *) &addr->sin_addr.s_addr;
  436.     for (i = 0; i < 4; i++)
  437.         ip[i] ^= p[i];
  438. return 0;
  439. }
  440.  
  441. int stun_parse_address(PACKET * m, ADDRESS * addr)
  442. {
  443.     addr->sin_family = r16(m) == 1 ? 2 : 1;
  444.     addr->sin_port = htons(r16(m));
  445.     char *p = (char *) &addr->sin_addr.s_addr;
  446.     rBuf(m, p, 4);
  447. return 0;
  448. }
  449.  
  450. int stun_parse(STUN * stun, PACKET * m)
  451. {
  452.     m->ofs = 0;
  453.     int type = r16(m);
  454.     int length = r16(m);
  455.     int magic = r32(m);
  456.     char tsx_id[12];
  457.  
  458.     if (magic != STUN_MAGIC_COOKIE)
  459.         return 0;
  460.  
  461.     rBuf(m, tsx_id, 12);
  462.  
  463.     int msg = type & ~0x110;
  464.     int code = type & 0x110;
  465.  
  466.     printf(" Message: %d (%d)\n", msg, code);
  467.     printf("  hdr: length=%d, magic=0x%x, tsx_id=%s", length, magic, hex_string(tsx_id, 12));
  468.     printf("\n");
  469.     printf("  Attributes:\n");
  470.  
  471.     int offset = m->ofs;
  472.  
  473.     while ((offset - STUN_HEADER_SIZE) < length)
  474.     {
  475.         int attr = r16(m);
  476.         int len = r16(m);
  477.  
  478.         //printf(" 0x%04x length=%d, ", attr, len);
  479.         printf("  %s length=%d, ", ATTR_NAME(attr), len);
  480.  
  481.         switch (attr)
  482.         {
  483.             case STUN_MAPPED_ADDRESS:
  484.             case STUN_RESPONSE_ADDRESS:
  485.             case STUN_SOURCE_ADDRESS:
  486.             case STUN_CHANGED_ADDRESS:
  487.             case STUN_XOR_MAPPED_ADDRESS:
  488.             {
  489.                 ADDRESS addr;
  490.  
  491.                 stun_parse_address(m, &addr);
  492.  
  493.                 if (attr == STUN_XOR_MAPPED_ADDRESS)
  494.                     stun_xor_address(&addr);
  495.  
  496.                 printf(net_to_string(&addr));
  497.  
  498.                 if (attr == STUN_MAPPED_ADDRESS)
  499.                     memcpy(&stun->mapped_address, &addr, sizeof(ADDRESS));
  500.  
  501.                 if (attr == STUN_CHANGED_ADDRESS)
  502.                     memcpy(&stun->changed_address, &addr, sizeof(ADDRESS));
  503.  
  504.                 break;
  505.             }
  506.  
  507.             case STUN_SOFTWARE:
  508.                 printf(m->buf + m->ofs);
  509.                 break;
  510.  
  511.             default:
  512.                 printf(hex_string(m->buf + m->ofs, len));
  513.                 break;
  514.         }
  515.  
  516.         printf("\n");
  517.         len = round_int(len, 4);
  518.         offset += len + 4;
  519.         m->ofs = offset;
  520.  
  521.         stun->received = 1;
  522.     }
  523.  
  524.     return 1;
  525. }
  526.  
  527. void stun_write_attr(PACKET * m, int attr, char *buf, int len)
  528. {
  529.     int pad = round_int(len, 4) - len;
  530.     w16(m, attr);
  531.     w16(m, len);
  532.     wBuf(m, buf, len);
  533.     m->ofs += pad;
  534. }
  535.  
  536. #define stun_write_str(m,attr,str) stun_write_attr(m, attr, str, strlen(str));
  537. #define stun_write_uint(m,attr,value) w16(m, attr); w16(m, 4); w32(m, value);
  538.  
  539. void stun_recv(STUN * stun, char *buf, int len)
  540. {
  541.     PACKET m;
  542.     packet_init(&m, buf, len);
  543.     stun_parse(stun, &m);
  544. }
  545.  
  546. int stun_send_message(STUN * stun, int type)
  547. {
  548.     LINK *link = stun->link;
  549.     PACKET mp;
  550.     PACKET *m = &mp;
  551.  
  552.     char buf[1024];
  553.     int buf_size = 1024;
  554.  
  555.  
  556.     packet_init(m, buf, buf_size);
  557.  
  558.     switch (type)
  559.     {
  560.         case 1: // Test I
  561.             link->addr = &stun->base_address;
  562.             stun_write_header(m, STUN_BINDING_METHOD);
  563.             stun_write_footer(m);
  564.             break;
  565.  
  566.         case 2: // Test II
  567.             link->addr = &stun->base_address;
  568.             stun_write_header(m, STUN_BINDING_METHOD);
  569.             stun_write_uint(m, STUN_CHANGE_REQUEST, 4 + 2); //change addr & port
  570.             stun_write_footer(m);
  571.             break;
  572.  
  573.         case 3: // Test I(2)
  574.             link->addr = &stun->changed_address;
  575.             stun_write_header(m, STUN_BINDING_METHOD);
  576.             stun_write_footer(m);
  577.             break;
  578.  
  579.         case 4: // Test III
  580.             link->addr = &stun->base_address;
  581.             stun_write_header(m, STUN_BINDING_METHOD);
  582.             stun_write_uint(m, STUN_CHANGE_REQUEST, 2); //change port
  583.             stun_write_footer(m);
  584.             break;
  585.  
  586.         case 5:
  587.             net_resolve_address(link->addr,"216.93.246.14",3478);
  588.             stun_write_header(m, STUN_BINDING_METHOD);
  589.             stun_write_footer(m);
  590.             break;
  591.  
  592.         case 6:
  593.             net_resolve_address(link->addr,"216.93.246.14",3479);
  594.             stun_write_header(m, STUN_BINDING_METHOD);
  595.             stun_write_footer(m);
  596.             break;
  597.  
  598.         case 7:
  599.             net_resolve_address(link->addr,"216.93.246.15",3478);
  600.             stun_write_header(m, STUN_BINDING_METHOD);
  601.             stun_write_footer(m);
  602.             break;
  603.  
  604.  
  605.         case 8:
  606.             net_resolve_address(link->addr,"216.93.246.15",3479);
  607.             stun_write_header(m, STUN_BINDING_METHOD);
  608.             stun_write_footer(m);
  609.             break;
  610.  
  611.  
  612.         default:
  613.             break;
  614.     }
  615.  
  616.     if (m->len)
  617.     {
  618.         net_send(link, m->buf, m->len);
  619.         stun_parse(stun, m);
  620.     }
  621.  
  622.     return m->len;
  623. }
  624.  
  625. int stun_start(LINK * link, STUN * stun)
  626. {
  627.     stun->state = 0;
  628.     stun->finished = 0;
  629.     link->addr = &stun->base_address;
  630.     link->started = 0;
  631.     stun->test = 1;
  632.     stun->link = link;
  633.     net_open_link(stun->link);
  634. return 0;
  635. }
  636.  
  637. int stun_update(STUN * stun)
  638. {
  639.     int state = stun->state;
  640.  
  641.     switch (stun->state)
  642.     {
  643.         case 0: //starting
  644.             if (stun->link->started)
  645.             {
  646.                 int i;
  647.                 stun->timeout = 4;
  648.                 for (i = 0; i < 4; i++)
  649.                     stun->results[i] = 0;
  650.                 state = 1;
  651.             }
  652.             break;
  653.  
  654.         case 1: //send message
  655.             printf("\nTEST %d\n", stun->test);
  656.             stun_send_message(stun, stun->test);
  657.             stun->received = 0;
  658.             stun->send_time = time(0);
  659.             state = 2;
  660.             break;
  661.  
  662.         case 2: //wait result
  663.             if (time(0) - stun->send_time > stun->timeout)
  664.                 state = 3;
  665.             if (stun->received)
  666.                 state = 4;
  667.             break;
  668.  
  669.         case 3:
  670.             printf("[timeout]\n");
  671.  
  672.             if (stun->test == 1)
  673.                 stun->finished = 1;
  674.  
  675.             if (stun->test == 2 && !stun->nat)
  676.                 stun->finished = 1;
  677.  
  678.             stun->results[stun->test - 1] = 0;
  679.             stun->test++;
  680.             state = 1;
  681.             break;
  682.  
  683.         case 4:
  684.             printf("[received %d]\n", stun->test);
  685.             stun->timeout = time(0) - stun->send_time + 1;
  686.  
  687.             if (stun->test == 1)
  688.                 stun->nat = !net_is_local_address(&stun->mapped_address);
  689.  
  690.             if (stun->test != 1 && stun->test<5)
  691.                 stun->presport = (stun->mapped_address.sin_port == stun->link->port);
  692.            
  693.             if (stun->test == 1) // it's also important!
  694.                 stun->fpresport = (stun->mapped_address.sin_port == stun->link->port);
  695.             if(stun->test > 4)
  696.             {
  697.                 stun->mappedports[stun->test-5] = ntohs(stun->mapped_address.sin_port);
  698.             }
  699.  
  700.             stun->results[stun->test - 1] = 1;
  701.             stun->test++;
  702.             state = 1;
  703.             break;
  704.     }
  705.  
  706.     if (stun->test == 5 && state == 1){
  707.  
  708.     closesocket(stun->link->sock);
  709.     stun->link->port=3478;
  710.     net_open_link(stun->link);
  711.     stun->timeout = 4;
  712.     Sleep(1000);
  713.    
  714.     }
  715.     if (stun->test == 9)
  716.         stun->finished = 1;
  717.  
  718.     stun->state = state;
  719.  
  720.     return !stun->finished;
  721. }
  722.  
  723. #endif //__STUN_H__
  724.  
  725. STUN m_stun;
  726. LINK m_link;
  727.  
  728. void net_recv(char *buf, int len)
  729. {
  730.     stun_recv(&m_stun, buf, len);
  731. }
  732.  
  733. int main(int argc, char **argv)
  734. {
  735.     int port = 3478;
  736.     char *host = "stun.counterpath.net";
  737.  
  738.     if (argc > 1)
  739.         host = argv[1];
  740.  
  741.     net_init();
  742.  
  743.     LINK *link = &m_link;
  744.     STUN *stun = &m_stun;
  745.  
  746.     link->host = host;
  747.     link->port = port;
  748.  
  749.     stun_start(link, stun);
  750.  
  751.     while (stun_update(stun))
  752.         Sleep(5);
  753.  
  754.  
  755.     //make a mask for tests, i.e. 1,0,1,1 == 0x1011
  756.     int i, mask = 0;
  757.     for (i = 0; i < 4; i++)
  758.         mask |= stun->results[i] << (3 - i) * 4;
  759.  
  760.     char *type;
  761.     if(stun->results[3]==1)
  762.         type = "Address restricted NAT";
  763.     else
  764.         type = "Port restricted NAT";
  765.  
  766.  
  767.  
  768.     switch (mask)
  769.     {        
  770.         case 0x0000:
  771.             type = "UDP Blocked";
  772.             break;
  773.         case 0x1000:
  774.             type = "UDP Firewall";
  775.             break;
  776.         case 0x1100:
  777.             type = "Open Internet";
  778.             break;
  779.         case 0x1011:
  780.             type = "Full Cone NAT";
  781.             break;
  782.     }
  783.     printf("\n\nResults\n-------------------------------\n");
  784.     printf("tests: %04x\n", mask);
  785.     printf("NAT present: %d\n", stun->nat);
  786.     printf("first preserved port: %d\n", stun->fpresport);
  787.     printf("preserves port: %d\n", stun->presport);
  788.     if(stun->nat)
  789.     printf("type: %s\n", type);
  790.  
  791.     printf("mapped ports: ");
  792.     for(i = 0; i<4; i++)
  793.     printf("%d ",stun->mappedports[i]);
  794.  
  795.     printf("\n");
  796.  
  797.  
  798.  
  799. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement