Use CBitcoinAddress ti store change destination
[novacoin.git] / src / stun.cpp
1 /*
2  * Get External IP address by STUN protocol
3  *
4  * Based on project Minimalistic STUN client "ministun"
5  * https://code.google.com/p/ministun/
6  *
7  * This program is free software, distributed under the terms of
8  * the GNU General Public License Version 2. See the LICENSE file
9  * at the top of the source tree.
10  *
11  * STUN is described in RFC3489 and it is based on the exchange
12  * of UDP packets between a client and one or more servers to
13  * determine the externally visible address (and port) of the client
14  * once it has gone through the NAT boxes that connect it to the
15  * outside.
16  * The simplest request packet is just the header defined in
17  * struct stun_header, and from the response we may just look at
18  * one attribute, STUN_MAPPED_ADDRESS, that we find in the response.
19  * By doing more transactions with different server addresses we
20  * may determine more about the behaviour of the NAT boxes, of
21  * course - the details are in the RFC.
22  *
23  * All STUN packets start with a simple header made of a type,
24  * length (excluding the header) and a 16-byte random transaction id.
25  * Following the header we may have zero or more attributes, each
26  * structured as a type, length and a value (whose format depends
27  * on the type, but often contains addresses).
28  * Of course all fields are in network format.
29  */
30
31 #include <stdio.h>
32 #include <inttypes.h>
33 #include <limits>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #ifdef WIN32
38 #include <winsock2.h>
39 #else
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <arpa/inet.h>
43 #include <netdb.h>
44 #endif
45 #ifndef WIN32
46 #include <unistd.h>
47 #endif
48 #include <time.h>
49 #include <errno.h>
50
51 #include "ministun.h"
52 #include "netbase.h"
53
54 extern int GetRandInt(int nMax);
55 extern uint64_t GetRand(uint64_t nMax);
56
57 /*---------------------------------------------------------------------*/
58
59 struct StunSrv {
60     char     name[30];
61     uint16_t port;
62 };
63
64 /*---------------------------------------------------------------------*/
65 static const int StunSrvListQty = 263; // Must be PRIME!!!!!
66
67 static struct StunSrv StunSrvList[263] = {
68     {"23.21.150.121", 3478},
69     {"iphone-stun.strato-iphone.de", 3478},
70     {"numb.viagenie.ca", 3478},
71     {"s1.taraba.net", 3478},
72     {"s2.taraba.net", 3478},
73     {"stun.12connect.com", 3478},
74     {"stun.12voip.com", 3478},
75     {"stun.1und1.de", 3478},
76     {"stun.2talk.co.nz", 3478},
77     {"stun.2talk.com", 3478},
78     {"stun.3clogic.com", 3478},
79     {"stun.3cx.com", 3478},
80     {"stun.a-mm.tv", 3478},
81     {"stun.aa.net.uk", 3478},
82     {"stun.acrobits.cz", 3478},
83     {"stun.actionvoip.com", 3478},
84     {"stun.advfn.com", 3478},
85     {"stun.aeta-audio.com", 3478},
86     {"stun.aeta.com", 3478},
87     {"stun.alltel.com.au", 3478},
88     {"stun.altar.com.pl", 3478},
89     {"stun.annatel.net", 3478},
90     {"stun.arbuz.ru", 3478},
91     {"stun.avigora.com", 3478},
92     {"stun.avigora.fr", 3478},
93     {"stun.awa-shima.com", 3478},
94     {"stun.awt.be", 3478},
95     {"stun.b2b2c.ca", 3478},
96     {"stun.bahnhof.net", 3478},
97     {"stun.barracuda.com", 3478},
98     {"stun.bluesip.net", 3478},
99     {"stun.bmwgs.cz", 3478},
100     {"stun.botonakis.com", 3478},
101     {"stun.budgetphone.nl", 3478},
102     {"stun.budgetsip.com", 3478},
103     {"stun.cablenet-as.net", 3478},
104     {"stun.callromania.ro", 3478},
105     {"stun.callwithus.com", 3478},
106     {"stun.cbsys.net", 3478},
107     {"stun.chathelp.ru", 3478},
108     {"stun.cheapvoip.com", 3478},
109     {"stun.ciktel.com", 3478},
110     {"stun.cloopen.com", 3478},
111     {"stun.colouredlines.com.au", 3478},
112     {"stun.comfi.com", 3478},
113     {"stun.commpeak.com", 3478},
114     {"stun.comtube.com", 3478},
115     {"stun.comtube.ru", 3478},
116     {"stun.cope.es", 3478},
117     {"stun.counterpath.com", 3478},
118     {"stun.counterpath.net", 3478},
119     {"stun.cryptonit.net", 3478},
120     {"stun.darioflaccovio.it", 3478},
121     {"stun.datamanagement.it", 3478},
122     {"stun.dcalling.de", 3478},
123     {"stun.decanet.fr", 3478},
124     {"stun.demos.ru", 3478},
125     {"stun.develz.org", 3478},
126     {"stun.dingaling.ca", 3478},
127     {"stun.doublerobotics.com", 3478},
128     {"stun.drogon.net", 3478},
129     {"stun.duocom.es", 3478},
130     {"stun.dus.net", 3478},
131     {"stun.e-fon.ch", 3478},
132     {"stun.easybell.de", 3478},
133     {"stun.easycall.pl", 3478},
134     {"stun.easyvoip.com", 3478},
135     {"stun.efficace-factory.com", 3478},
136     {"stun.einsundeins.com", 3478},
137     {"stun.einsundeins.de", 3478},
138     {"stun.ekiga.net", 3478},
139     {"stun.epygi.com", 3478},
140     {"stun.etoilediese.fr", 3478},
141     {"stun.eyeball.com", 3478},
142     {"stun.faktortel.com.au", 3478},
143     {"stun.freecall.com", 3478},
144     {"stun.freeswitch.org", 3478},
145     {"stun.freevoipdeal.com", 3478},
146     {"stun.fuzemeeting.com", 3478},
147     {"stun.gmx.de", 3478},
148     {"stun.gmx.net", 3478},
149     {"stun.gradwell.com", 3478},
150     {"stun.halonet.pl", 3478},
151     {"stun.hoiio.com", 3478},
152     {"stun.hosteurope.de", 3478},
153     {"stun.ideasip.com", 3478},
154     {"stun.imesh.com", 3478},
155     {"stun.infra.net", 3478},
156     {"stun.internetcalls.com", 3478},
157     {"stun.intervoip.com", 3478},
158     {"stun.ipcomms.net", 3478},
159     {"stun.ipfire.org", 3478},
160     {"stun.ippi.fr", 3478},
161     {"stun.ipshka.com", 3478},
162     {"stun.iptel.org", 3478},
163     {"stun.irian.at", 3478},
164     {"stun.it1.hr", 3478},
165     {"stun.ivao.aero", 3478},
166     {"stun.jappix.com", 3478},
167     {"stun.jumblo.com", 3478},
168     {"stun.justvoip.com", 3478},
169     {"stun.kanet.ru", 3478},
170     {"stun.kiwilink.co.nz", 3478},
171     {"stun.kundenserver.de", 3478},
172     {"stun.l.google.com", 19302},
173     {"stun.linea7.net", 3478},
174     {"stun.linphone.org", 3478},
175     {"stun.liveo.fr", 3478},
176     {"stun.lowratevoip.com", 3478},
177     {"stun.lugosoft.com", 3478},
178     {"stun.lundimatin.fr", 3478},
179     {"stun.magnet.ie", 3478},
180     {"stun.manle.com", 3478},
181     {"stun.mgn.ru", 3478},
182     {"stun.mit.de", 3478},
183     {"stun.mitake.com.tw", 3478},
184     {"stun.miwifi.com", 3478},
185     {"stun.modulus.gr", 3478},
186     {"stun.mozcom.com", 3478},
187     {"stun.myvoiptraffic.com", 3478},
188     {"stun.mywatson.it", 3478},
189     {"stun.nas.net", 3478},
190     {"stun.neotel.co.za", 3478},
191     {"stun.netappel.com", 3478},
192     {"stun.netappel.fr", 3478},
193     {"stun.netgsm.com.tr", 3478},
194     {"stun.nfon.net", 3478},
195     {"stun.noblogs.org", 3478},
196     {"stun.noc.ams-ix.net", 3478},
197     {"stun.node4.co.uk", 3478},
198     {"stun.nonoh.net", 3478},
199     {"stun.nottingham.ac.uk", 3478},
200     {"stun.nova.is", 3478},
201     {"stun.nventure.com", 3478},
202     {"stun.on.net.mk", 3478},
203     {"stun.ooma.com", 3478},
204     {"stun.ooonet.ru", 3478},
205     {"stun.outland-net.de", 3478},
206     {"stun.ozekiphone.com", 3478},
207     {"stun.patlive.com", 3478},
208     {"stun.personal-voip.de", 3478},
209     {"stun.petcube.com", 3478},
210     {"stun.phone.com", 3478},
211     {"stun.phoneserve.com", 3478},
212     {"stun.pjsip.org", 3478},
213     {"stun.poivy.com", 3478},
214     {"stun.powerpbx.org", 3478},
215     {"stun.powervoip.com", 3478},
216     {"stun.ppdi.com", 3478},
217     {"stun.prizee.com", 3478},
218     {"stun.qq.com", 3478},
219     {"stun.qvod.com", 3478},
220     {"stun.rackco.com", 3478},
221     {"stun.rapidnet.de", 3478},
222     {"stun.rb-net.com", 3478},
223     {"stun.remote-learner.net", 3478},
224     {"stun.rixtelecom.se", 3478},
225     {"stun.rockenstein.de", 3478},
226     {"stun.rolmail.net", 3478},
227     {"stun.rounds.com", 3478},
228     {"stun.rynga.com", 3478},
229     {"stun.samsungsmartcam.com", 3478},
230     {"stun.schlund.de", 3478},
231     {"stun.services.mozilla.com", 3478},
232     {"stun.sigmavoip.com", 3478},
233     {"stun.sip.us", 3478},
234     {"stun.sipdiscount.com", 3478},
235     {"stun.sipgate.net", 10000},
236     {"stun.sipgate.net", 3478},
237     {"stun.siplogin.de", 3478},
238     {"stun.sipnet.net", 3478},
239     {"stun.sipnet.ru", 3478},
240     {"stun.siportal.it", 3478},
241     {"stun.sippeer.dk", 3478},
242     {"stun.siptraffic.com", 3478},
243     {"stun.skylink.ru", 3478},
244     {"stun.sma.de", 3478},
245     {"stun.smartvoip.com", 3478},
246     {"stun.smsdiscount.com", 3478},
247     {"stun.snafu.de", 3478},
248     {"stun.softjoys.com", 3478},
249     {"stun.solcon.nl", 3478},
250     {"stun.solnet.ch", 3478},
251     {"stun.sonetel.com", 3478},
252     {"stun.sonetel.net", 3478},
253     {"stun.sovtest.ru", 3478},
254     {"stun.speedy.com.ar", 3478},
255     {"stun.spokn.com", 3478},
256     {"stun.srce.hr", 3478},
257     {"stun.ssl7.net", 3478},
258     {"stun.stunprotocol.org", 3478},
259     {"stun.symform.com", 3478},
260     {"stun.symplicity.com", 3478},
261     {"stun.sysadminman.net", 3478},
262     {"stun.t-online.de", 3478},
263     {"stun.tagan.ru", 3478},
264     {"stun.tatneft.ru", 3478},
265     {"stun.teachercreated.com", 3478},
266     {"stun.tel.lu", 3478},
267     {"stun.telbo.com", 3478},
268     {"stun.telefacil.com", 3478},
269     {"stun.tis-dialog.ru", 3478},
270     {"stun.tng.de", 3478},
271     {"stun.twt.it", 3478},
272     {"stun.u-blox.com", 3478},
273     {"stun.ucallweconn.net", 3478},
274     {"stun.ucsb.edu", 3478},
275     {"stun.ucw.cz", 3478},
276     {"stun.uls.co.za", 3478},
277     {"stun.unseen.is", 3478},
278     {"stun.usfamily.net", 3478},
279     {"stun.veoh.com", 3478},
280     {"stun.vidyo.com", 3478},
281     {"stun.vipgroup.net", 3478},
282     {"stun.virtual-call.com", 3478},
283     {"stun.viva.gr", 3478},
284     {"stun.vivox.com", 3478},
285     {"stun.vline.com", 3478},
286     {"stun.vo.lu", 3478},
287     {"stun.vodafone.ro", 3478},
288     {"stun.voicetrading.com", 3478},
289     {"stun.voip.aebc.com", 3478},
290     {"stun.voip.blackberry.com", 3478},
291     {"stun.voip.eutelia.it", 3478},
292     {"stun.voiparound.com", 3478},
293     {"stun.voipblast.com", 3478},
294     {"stun.voipbuster.com", 3478},
295     {"stun.voipbusterpro.com", 3478},
296     {"stun.voipcheap.co.uk", 3478},
297     {"stun.voipcheap.com", 3478},
298     {"stun.voipfibre.com", 3478},
299     {"stun.voipgain.com", 3478},
300     {"stun.voipgate.com", 3478},
301     {"stun.voipinfocenter.com", 3478},
302     {"stun.voipplanet.nl", 3478},
303     {"stun.voippro.com", 3478},
304     {"stun.voipraider.com", 3478},
305     {"stun.voipstunt.com", 3478},
306     {"stun.voipwise.com", 3478},
307     {"stun.voipzoom.com", 3478},
308     {"stun.voxgratia.org", 3478},
309     {"stun.voxox.com", 3478},
310     {"stun.voys.nl", 3478},
311     {"stun.voztele.com", 3478},
312     {"stun.vyke.com", 3478},
313     {"stun.webcalldirect.com", 3478},
314     {"stun.whoi.edu", 3478},
315     {"stun.wifirst.net", 3478},
316     {"stun.wwdl.net", 3478},
317     {"stun.xs4all.nl", 3478},
318     {"stun.xtratelecom.es", 3478},
319     {"stun.yesss.at", 3478},
320     {"stun.zadarma.com", 3478},
321     {"stun.zadv.com", 3478},
322     {"stun.zoiper.com", 3478},
323     {"stun1.faktortel.com.au", 3478},
324     {"stun1.l.google.com", 19302},
325     {"stun1.voiceeclipse.net", 3478},
326     {"stun2.l.google.com", 19302},
327     {"stun3.l.google.com", 19302},
328     {"stun4.l.google.com", 19302},
329     {"stunserver.org", 3478},
330     {"stun.antisip.com",    3478}
331 };
332
333
334 /* wrapper to send an STUN message */
335 static int stun_send(int s, struct sockaddr_in *dst, struct stun_header *resp)
336 {
337     return sendto(s, (const char *)resp, ntohs(resp->msglen) + sizeof(*resp), 0,
338                   (struct sockaddr *)dst, sizeof(*dst));
339 }
340
341 /* helper function to generate a random request id */
342 static uint64_t randfiller = GetRand(std::numeric_limits<uint64_t>::max());
343 static void stun_req_id(struct stun_header *req)
344 {
345     const uint64_t *S_block = (const uint64_t *)StunSrvList;
346     req->id.id[0] = GetRandInt(std::numeric_limits<int32_t>::max());
347     req->id.id[1] = GetRandInt(std::numeric_limits<int32_t>::max());
348     req->id.id[2] = GetRandInt(std::numeric_limits<int32_t>::max());
349     req->id.id[3] = GetRandInt(std::numeric_limits<int32_t>::max());
350
351     req->id.id[0] |= 0x55555555;
352     req->id.id[1] &= 0x55555555;
353     req->id.id[2] |= 0x55555555;
354     req->id.id[3] &= 0x55555555;
355     char x = 20;
356     do {
357         uint32_t s_elm = S_block[(uint8_t)randfiller];
358         randfiller ^= (randfiller << 5) | (randfiller >> (64 - 5));
359         randfiller += s_elm ^ x;
360         req->id.id[x & 3] ^= randfiller + (randfiller >> 13);
361     } while(--x);
362 }
363
364 /* callback type to be invoked on stun responses. */
365 typedef int (stun_cb_f)(struct stun_attr *attr, void *arg);
366
367 /* handle an incoming STUN message.
368  *
369  * Do some basic sanity checks on packet size and content,
370  * try to extract a bit of information, and possibly reply.
371  * At the moment this only processes BIND requests, and returns
372  * the externally visible address of the request.
373  * If a callback is specified, invoke it with the attribute.
374  */
375 static int stun_handle_packet(int s, struct sockaddr_in *src,
376                               unsigned char *data, size_t len, stun_cb_f *stun_cb, void *arg)
377 {
378     struct stun_header *hdr = (struct stun_header *)data;
379     struct stun_attr *attr;
380     int ret = len;
381     unsigned int x;
382
383     /* On entry, 'len' is the length of the udp payload. After the
384    * initial checks it becomes the size of unprocessed options,
385    * while 'data' is advanced accordingly.
386    */
387     if (len < sizeof(struct stun_header))
388         return -20;
389
390     len -= sizeof(struct stun_header);
391     data += sizeof(struct stun_header);
392     x = ntohs(hdr->msglen); /* len as advertised in the message */
393     if(x < len)
394         len = x;
395
396     while (len) {
397         if (len < sizeof(struct stun_attr)) {
398             ret = -21;
399             break;
400         }
401         attr = (struct stun_attr *)data;
402         /* compute total attribute length */
403         x = ntohs(attr->len) + sizeof(struct stun_attr);
404         if (x > len) {
405             ret = -22;
406             break;
407         }
408         stun_cb(attr, arg);
409         //if (stun_process_attr(&st, attr)) {
410         //  ret = -23;
411         //  break;
412         // }
413         /* Clear attribute id: in case previous entry was a string,
414      * this will act as the terminator for the string.
415      */
416         attr->attr = 0;
417         data += x;
418         len -= x;
419     } // while
420     /* Null terminate any string.
421    * XXX NOTE, we write past the size of the buffer passed by the
422    * caller, so this is potentially dangerous. The only thing that
423    * saves us is that usually we read the incoming message in a
424    * much larger buffer
425    */
426     *data = '\0';
427
428     /* Now prepare to generate a reply, which at the moment is done
429    * only for properly formed (len == 0) STUN_BINDREQ messages.
430    */
431
432     return ret;
433 }
434
435 /* Extract the STUN_MAPPED_ADDRESS from the stun response.
436  * This is used as a callback for stun_handle_response
437  * when called from stun_request.
438  */
439 static int stun_get_mapped(struct stun_attr *attr, void *arg)
440 {
441     struct stun_addr *addr = (struct stun_addr *)(attr + 1);
442     struct sockaddr_in *sa = (struct sockaddr_in *)arg;
443
444     if (ntohs(attr->attr) != STUN_MAPPED_ADDRESS || ntohs(attr->len) != 8)
445         return 1; /* not us. */
446     sa->sin_port = addr->port;
447     sa->sin_addr.s_addr = addr->addr;
448     return 0;
449 }
450
451 /*---------------------------------------------------------------------*/
452
453 static int StunRequest2(int sock, struct sockaddr_in *server, struct sockaddr_in *mapped) {
454
455     struct stun_header *req;
456     unsigned char reqdata[1024];
457
458     req = (struct stun_header *)reqdata;
459     stun_req_id(req);
460     unsigned short reqlen = 0;
461     req->msgtype = 0;
462     req->msglen = 0;
463     req->msglen = htons(reqlen);
464     req->msgtype = htons(STUN_BINDREQ);
465
466     unsigned char reply_buf[1024];
467     fd_set rfds;
468     struct timeval to = { STUN_TIMEOUT, 0 };
469     struct sockaddr_in src;
470 #ifdef WIN32
471     int srclen;
472 #else
473     socklen_t srclen;
474 #endif
475
476     int res = stun_send(sock, server, req);
477     if(res < 0)
478         return -10;
479     FD_ZERO(&rfds);
480     FD_SET(sock, &rfds);
481     res = select(sock + 1, &rfds, NULL, NULL, &to);
482     if (res <= 0)  /* timeout or error */
483         return -11;
484     memset(&src, 0, sizeof(src));
485     srclen = sizeof(src);
486     /* XXX pass -1 in the size, because stun_handle_packet might
487    * write past the end of the buffer.
488    */
489     res = recvfrom(sock, (char *)reply_buf, sizeof(reply_buf) - 1,
490                    0, (struct sockaddr *)&src, &srclen);
491     if (res <= 0)
492         return -12;
493     memset(mapped, 0, sizeof(struct sockaddr_in));
494     return stun_handle_packet(sock, &src, reply_buf, res, stun_get_mapped, mapped);
495 } // StunRequest2
496
497 /*---------------------------------------------------------------------*/
498 static int StunRequest(const char *host, uint16_t port, struct sockaddr_in *mapped) {
499     struct hostent *hostinfo = gethostbyname(host);
500     if(hostinfo == NULL)
501         return -1;
502
503     SOCKET sock = INVALID_SOCKET;
504     struct sockaddr_in server, client;
505     memset(&server, 0, sizeof(server));
506     memset(&client, 0, sizeof(client));
507     server.sin_family = client.sin_family = AF_INET;
508
509     server.sin_addr = *(struct in_addr*) hostinfo->h_addr;
510     server.sin_port = htons(port);
511
512     sock = socket(AF_INET, SOCK_DGRAM, 0);
513     if(sock == INVALID_SOCKET)
514         return -2;
515
516     client.sin_addr.s_addr = htonl(INADDR_ANY);
517
518     int rc = -3;
519     if(bind(sock, (struct sockaddr*)&client, sizeof(client)) >= 0)
520         rc = StunRequest2(sock, &server, mapped);
521     CloseSocket(sock);
522     return rc;
523 } // StunRequest
524
525 /*---------------------------------------------------------------------*/
526 // Input: two random values (pos, step) for generate uniuqe way over server
527 // list
528 // Output: populate struct struct mapped
529 // Retval:
530
531 int GetExternalIPbySTUN(uint64_t rnd, struct sockaddr_in *mapped, const char **srv) {
532     randfiller    = rnd;
533     uint16_t pos  = rnd;
534     uint16_t step;
535     do {
536         rnd = (rnd >> 8) | 0xff00000000000000LL;
537         step = rnd % StunSrvListQty;
538     } while(step == 0);
539
540     uint16_t attempt;
541     for(attempt = 1; attempt < StunSrvListQty * 2; attempt++) {
542         pos = (pos + step) % StunSrvListQty;
543         int rc = StunRequest(*srv = StunSrvList[pos].name, StunSrvList[pos].port, mapped);
544         if(rc >= 0)
545             return attempt;
546         // fprintf(stderr, "Lookup: %s:%u\t%s\t%d\n", StunSrvList[pos].name,
547         // StunSrvList[pos].port, inet_ntoa(mapped->sin_addr), rc);
548     }
549     return -1;
550 }