Advertisement
joric

STUN Client

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