source: trunk/libtransmission/net.c

Last change on this file was 14578, checked in by mikedld, 5 years ago

#5992: Remove now obsolete check for 13th Baktun (already happened)

  • Property svn:keywords set to Date Rev Author Id
File size: 19.0 KB
Line 
1/******************************************************************************
2 *
3 * $Id: net.c 14578 2015-10-16 19:49:07Z mikedld $
4 *
5 * Copyright (c) Transmission authors and contributors
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 *****************************************************************************/
25
26#include <errno.h>
27#include <string.h>
28#include <assert.h>
29
30#include <sys/types.h>
31
32#ifdef _WIN32
33 #include <ws2tcpip.h>
34#else
35 #include <netinet/tcp.h>       /* TCP_CONGESTION */
36#endif
37
38#include <event2/util.h>
39
40#include <libutp/utp.h>
41
42#include "transmission.h"
43#include "fdlimit.h" /* tr_fdSocketClose () */
44#include "net.h"
45#include "peer-io.h" /* tr_peerIoAddrStr () FIXME this should be moved to net.h */
46#include "session.h" /* tr_sessionGetPublicAddress () */
47#include "tr-utp.h" /* tr_utpSendTo () */
48#include "log.h"
49#include "utils.h" /* tr_time (), tr_logAddDebug () */
50
51#ifndef IN_MULTICAST
52#define IN_MULTICAST(a) (((a) & 0xf0000000) == 0xe0000000)
53#endif
54
55const tr_address tr_in6addr_any = { TR_AF_INET6, { IN6ADDR_ANY_INIT } };
56const tr_address tr_inaddr_any = { TR_AF_INET, { { { { INADDR_ANY, 0x00, 0x00, 0x00 } } } } };
57
58char *
59tr_net_strerror (char * buf, size_t buflen, int err)
60{
61    *buf = '\0';
62#ifdef _WIN32
63    DWORD len = FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM, NULL, err, 0, buf, buflen, NULL);
64    while (len > 0 && buf[len - 1] >= '\0' && buf[len - 1] <= ' ')
65      buf[--len] = '\0';
66#else
67    tr_strlcpy (buf, tr_strerror (err), buflen);
68#endif
69    return buf;
70}
71
72const char *
73tr_address_to_string_with_buf (const tr_address * addr, char * buf, size_t buflen)
74{
75    assert (tr_address_is_valid (addr));
76
77    if (addr->type == TR_AF_INET)
78        return evutil_inet_ntop (AF_INET, &addr->addr, buf, buflen);
79    else
80        return evutil_inet_ntop (AF_INET6, &addr->addr, buf, buflen);
81}
82
83/*
84 * Non-threadsafe version of tr_address_to_string_with_buf ()
85 * and uses a static memory area for a buffer.
86 * This function is suitable to be called from libTransmission's networking code,
87 * which is single-threaded.
88 */
89const char *
90tr_address_to_string (const tr_address * addr)
91{
92    static char buf[INET6_ADDRSTRLEN];
93    return tr_address_to_string_with_buf (addr, buf, sizeof (buf));
94}
95
96bool
97tr_address_from_string (tr_address * dst, const char * src)
98{
99    bool ok;
100
101    if ((ok = evutil_inet_pton (AF_INET, src, &dst->addr) == 1))
102        dst->type = TR_AF_INET;
103
104    if (!ok) /* try IPv6 */
105        if ((ok = evutil_inet_pton (AF_INET6, src, &dst->addr) == 1))
106            dst->type = TR_AF_INET6;
107
108    return ok;
109}
110
111/*
112 * Compare two tr_address structures.
113 * Returns:
114 * <0 if a < b
115 * >0 if a > b
116 * 0  if a == b
117 */
118int
119tr_address_compare (const tr_address * a, const tr_address * b)
120{
121    static const int sizes[2] = { sizeof (struct in_addr), sizeof (struct in6_addr) };
122
123    /* IPv6 addresses are always "greater than" IPv4 */
124    if (a->type != b->type)
125        return a->type == TR_AF_INET ? 1 : -1;
126
127    return memcmp (&a->addr, &b->addr, sizes[a->type]);
128}
129
130/***********************************************************************
131 * TCP sockets
132 **********************************************************************/
133
134void
135tr_netSetTOS (tr_socket_t s,
136              int         tos)
137{
138#if defined (IP_TOS) && !defined (_WIN32)
139    if (setsockopt (s, IPPROTO_IP, IP_TOS, (const void *) &tos, sizeof (tos)) == -1)
140    {
141        char err_buf[512];
142        tr_logAddNamedInfo ("Net", "Can't set TOS '%d': %s", tos,
143                            tr_net_strerror (err_buf, sizeof (err_buf), sockerrno));
144    }
145#else
146    (void) s;
147    (void) tos;
148#endif
149}
150
151void
152tr_netSetCongestionControl (tr_socket_t   s,
153                            const char  * algorithm)
154{
155#ifdef TCP_CONGESTION
156    if (setsockopt (s, IPPROTO_TCP, TCP_CONGESTION,
157                    (const void *) algorithm, strlen (algorithm) + 1) == -1)
158    {
159        char err_buf[512];
160        tr_logAddNamedInfo ("Net", "Can't set congestion control algorithm '%s': %s",
161                            algorithm, tr_net_strerror (err_buf, sizeof (err_buf), sockerrno));
162    }
163#else
164    (void) s;
165    (void) algorithm;
166#endif
167}
168
169bool
170tr_address_from_sockaddr_storage (tr_address                     * setme_addr,
171                                  tr_port                        * setme_port,
172                                  const struct sockaddr_storage  * from)
173{
174    if (from->ss_family == AF_INET)
175    {
176        struct sockaddr_in * sin = (struct sockaddr_in *)from;
177        setme_addr->type = TR_AF_INET;
178        setme_addr->addr.addr4.s_addr = sin->sin_addr.s_addr;
179        *setme_port = sin->sin_port;
180        return true;
181    }
182
183    if (from->ss_family == AF_INET6)
184    {
185        struct sockaddr_in6 *sin6 = (struct sockaddr_in6*) from;
186        setme_addr->type = TR_AF_INET6;
187        setme_addr->addr.addr6 = sin6->sin6_addr;
188        *setme_port = sin6->sin6_port;
189        return true;
190    }
191
192    return false;
193}
194
195static socklen_t
196setup_sockaddr (const tr_address        * addr,
197                tr_port                   port,
198                struct sockaddr_storage * sockaddr)
199{
200    assert (tr_address_is_valid (addr));
201
202    if (addr->type == TR_AF_INET)
203    {
204        struct sockaddr_in  sock4;
205        memset (&sock4, 0, sizeof (sock4));
206        sock4.sin_family      = AF_INET;
207        sock4.sin_addr.s_addr = addr->addr.addr4.s_addr;
208        sock4.sin_port        = port;
209        memcpy (sockaddr, &sock4, sizeof (sock4));
210        return sizeof (struct sockaddr_in);
211    }
212    else
213    {
214        struct sockaddr_in6 sock6;
215        memset (&sock6, 0, sizeof (sock6));
216        sock6.sin6_family   = AF_INET6;
217        sock6.sin6_port     = port;
218        sock6.sin6_flowinfo = 0;
219        sock6.sin6_addr     = addr->addr.addr6;
220        memcpy (sockaddr, &sock6, sizeof (sock6));
221        return sizeof (struct sockaddr_in6);
222    }
223}
224
225tr_socket_t
226tr_netOpenPeerSocket (tr_session        * session,
227                      const tr_address  * addr,
228                      tr_port             port,
229                      bool                clientIsSeed)
230{
231    static const int domains[NUM_TR_AF_INET_TYPES] = { AF_INET, AF_INET6 };
232    tr_socket_t             s;
233    struct sockaddr_storage sock;
234    socklen_t               addrlen;
235    const tr_address      * source_addr;
236    socklen_t               sourcelen;
237    struct sockaddr_storage source_sock;
238    char err_buf[512];
239
240    assert (tr_address_is_valid (addr));
241
242    if (!tr_address_is_valid_for_peers (addr, port))
243        return TR_BAD_SOCKET; /* -EINVAL */
244
245    s = tr_fdSocketCreate (session, domains[addr->type], SOCK_STREAM);
246    if (s == TR_BAD_SOCKET)
247        return TR_BAD_SOCKET;
248
249    /* seeds don't need much of a read buffer... */
250    if (clientIsSeed) {
251        int n = 8192;
252        if (setsockopt (s, SOL_SOCKET, SO_RCVBUF, (const void *) &n, sizeof (n)))
253            tr_logAddInfo ("Unable to set SO_RCVBUF on socket %"TR_PRI_SOCK": %s", s,
254                           tr_net_strerror (err_buf, sizeof (err_buf), sockerrno));
255    }
256
257    if (evutil_make_socket_nonblocking (s) < 0) {
258        tr_netClose (session, s);
259        return TR_BAD_SOCKET;
260    }
261
262    addrlen = setup_sockaddr (addr, port, &sock);
263
264    /* set source address */
265    source_addr = tr_sessionGetPublicAddress (session, addr->type, NULL);
266    assert (source_addr);
267    sourcelen = setup_sockaddr (source_addr, 0, &source_sock);
268    if (bind (s, (struct sockaddr *) &source_sock, sourcelen))
269    {
270        tr_logAddError (_("Couldn't set source address %s on %"TR_PRI_SOCK": %s"),
271                        tr_address_to_string (source_addr), s,
272                        tr_net_strerror (err_buf, sizeof (err_buf), sockerrno));
273        tr_netClose (session, s);
274        return TR_BAD_SOCKET; /* -errno */
275    }
276
277    if ((connect (s, (struct sockaddr *) &sock,
278                  addrlen) < 0)
279#ifdef _WIN32
280      && (sockerrno != WSAEWOULDBLOCK)
281#endif
282      && (sockerrno != EINPROGRESS))
283    {
284        int tmperrno;
285        tmperrno = sockerrno;
286        if ((tmperrno != ENETUNREACH && tmperrno != EHOSTUNREACH) || addr->type == TR_AF_INET)
287        {
288            tr_logAddError (_("Couldn't connect socket %"TR_PRI_SOCK" to %s, port %d (errno %d - %s)"),
289                            s, tr_address_to_string (addr), (int)ntohs (port), tmperrno,
290                            tr_net_strerror (err_buf, sizeof (err_buf), tmperrno));
291        }
292        tr_netClose (session, s);
293        s = TR_BAD_SOCKET; /* -tmperrno */
294    }
295
296    tr_logAddDeep (__FILE__, __LINE__, NULL, "New OUTGOING connection %"TR_PRI_SOCK" (%s)",
297                   s, tr_peerIoAddrStr (addr, port));
298
299    return s;
300}
301
302struct UTPSocket *
303tr_netOpenPeerUTPSocket (tr_session        * session,
304                         const tr_address  * addr,
305                         tr_port             port,
306                         bool                clientIsSeed UNUSED)
307{
308  struct UTPSocket * ret = NULL;
309
310  if (tr_address_is_valid_for_peers (addr, port))
311    {
312      struct sockaddr_storage ss;
313      const socklen_t sslen = setup_sockaddr (addr, port, &ss);
314      ret = UTP_Create (tr_utpSendTo, session, (struct sockaddr*)&ss, sslen);
315    }
316
317  return ret;
318}
319
320static tr_socket_t
321tr_netBindTCPImpl (const tr_address * addr,
322                   tr_port            port,
323                   bool               suppressMsgs,
324                   int              * errOut)
325{
326    static const int domains[NUM_TR_AF_INET_TYPES] = { AF_INET, AF_INET6 };
327    struct sockaddr_storage sock;
328    tr_socket_t fd;
329    int addrlen;
330    int optval;
331
332    assert (tr_address_is_valid (addr));
333
334    fd = socket (domains[addr->type], SOCK_STREAM, 0);
335    if (fd == TR_BAD_SOCKET) {
336        *errOut = sockerrno;
337        return TR_BAD_SOCKET;
338    }
339
340    if (evutil_make_socket_nonblocking (fd) < 0) {
341        *errOut = sockerrno;
342        tr_netCloseSocket (fd);
343        return TR_BAD_SOCKET;
344    }
345
346    optval = 1;
347    setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, (const void *) &optval, sizeof (optval));
348    setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &optval, sizeof (optval));
349
350#ifdef IPV6_V6ONLY
351    if (addr->type == TR_AF_INET6)
352        if (setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void *) &optval, sizeof (optval)) == -1)
353            if (sockerrno != ENOPROTOOPT) { /* if the kernel doesn't support it, ignore it */
354                *errOut = sockerrno;
355                tr_netCloseSocket (fd);
356                return TR_BAD_SOCKET;
357            }
358#endif
359
360    addrlen = setup_sockaddr (addr, htons (port), &sock);
361    if (bind (fd, (struct sockaddr *) &sock, addrlen)) {
362        const int err = sockerrno;
363        if (!suppressMsgs)
364        {
365            const char * fmt;
366            const char * hint;
367            char err_buf[512];
368
369            if (err == EADDRINUSE)
370                hint = _("Is another copy of Transmission already running?");
371            else
372                hint = NULL;
373
374            if (hint == NULL)
375                fmt = _("Couldn't bind port %d on %s: %s");
376            else
377                fmt = _("Couldn't bind port %d on %s: %s (%s)");
378
379            tr_logAddError (fmt, port, tr_address_to_string (addr),
380                            tr_net_strerror (err_buf, sizeof (err_buf), err), hint);
381        }
382        tr_netCloseSocket (fd);
383        *errOut = err;
384        return TR_BAD_SOCKET;
385    }
386
387    if (!suppressMsgs)
388        tr_logAddDebug ("Bound socket %"TR_PRI_SOCK" to port %d on %s", fd, port, tr_address_to_string (addr));
389
390    if (listen (fd, 128) == -1) {
391        *errOut = sockerrno;
392        tr_netCloseSocket (fd);
393        return TR_BAD_SOCKET;
394    }
395
396    return fd;
397}
398
399tr_socket_t
400tr_netBindTCP (const tr_address * addr,
401               tr_port            port,
402               bool               suppressMsgs)
403{
404    int unused;
405    return tr_netBindTCPImpl (addr, port, suppressMsgs, &unused);
406}
407
408bool
409tr_net_hasIPv6 (tr_port port)
410{
411    static bool result = false;
412    static bool alreadyDone = false;
413
414    if (!alreadyDone)
415    {
416        int err;
417        tr_socket_t fd = tr_netBindTCPImpl (&tr_in6addr_any, port, true, &err);
418        if (fd != TR_BAD_SOCKET || err != EAFNOSUPPORT) /* we support ipv6 */
419            result = true;
420        if (fd != TR_BAD_SOCKET)
421            tr_netCloseSocket (fd);
422        alreadyDone = true;
423    }
424
425    return result;
426}
427
428tr_socket_t
429tr_netAccept (tr_session  * session,
430              tr_socket_t   b,
431              tr_address  * addr,
432              tr_port     * port)
433{
434    tr_socket_t fd = tr_fdSocketAccept (session, b, addr, port);
435
436    if (fd != TR_BAD_SOCKET && evutil_make_socket_nonblocking (fd) < 0) {
437        tr_netClose (session, fd);
438        fd = TR_BAD_SOCKET;
439    }
440
441    return fd;
442}
443
444void
445tr_netCloseSocket (tr_socket_t fd)
446{
447    evutil_closesocket (fd);
448}
449
450void
451tr_netClose (tr_session  * session,
452             tr_socket_t   s)
453{
454    tr_fdSocketClose (session, s);
455}
456
457/*
458   get_source_address () and global_unicast_address () were written by
459   Juliusz Chroboczek, and are covered under the same license as dht.c.
460   Please feel free to copy them into your software if it can help
461   unbreaking the double-stack Internet. */
462
463/* Get the source address used for a given destination address. Since
464   there is no official interface to get this information, we create
465   a connected UDP socket (connected UDP... hmm...) and check its source
466   address. */
467static int
468get_source_address (const struct sockaddr  * dst,
469                    socklen_t                dst_len,
470                    struct sockaddr        * src,
471                    socklen_t              * src_len)
472{
473    tr_socket_t s;
474    int rc, save;
475
476    s = socket (dst->sa_family, SOCK_DGRAM, 0);
477    if (s == TR_BAD_SOCKET)
478        goto fail;
479
480    /* Since it's a UDP socket, this doesn't actually send any packets. */
481    rc = connect (s, dst, dst_len);
482    if (rc < 0)
483        goto fail;
484
485    rc = getsockname (s, src, src_len);
486    if (rc < 0)
487        goto fail;
488
489    evutil_closesocket (s);
490
491    return rc;
492
493 fail:
494    save = errno;
495    evutil_closesocket (s);
496    errno = save;
497    return -1;
498}
499
500/* We all hate NATs. */
501static int
502global_unicast_address (struct sockaddr *sa)
503{
504    if (sa->sa_family == AF_INET) {
505        const unsigned char *a =
506          (unsigned char*)& ((struct sockaddr_in*)sa)->sin_addr;
507        if (a[0] == 0 || a[0] == 127 || a[0] >= 224 ||
508           a[0] == 10 || (a[0] == 172 && a[1] >= 16 && a[1] <= 31) ||
509         (a[0] == 192 && a[1] == 168))
510            return 0;
511        return 1;
512    } else if (sa->sa_family == AF_INET6) {
513        const unsigned char *a =
514          (unsigned char*)& ((struct sockaddr_in6*)sa)->sin6_addr;
515        /* 2000::/3 */
516        return (a[0] & 0xE0) == 0x20;
517    } else {
518        errno = EAFNOSUPPORT;
519        return -1;
520    }
521}
522
523static int
524tr_globalAddress (int af, void *addr, int *addr_len)
525{
526    struct sockaddr_storage ss;
527    socklen_t sslen = sizeof (ss);
528    struct sockaddr_in sin;
529    struct sockaddr_in6 sin6;
530    struct sockaddr *sa;
531    socklen_t salen;
532    int rc;
533
534    switch (af) {
535    case AF_INET:
536        memset (&sin, 0, sizeof (sin));
537        sin.sin_family = AF_INET;
538        evutil_inet_pton (AF_INET, "91.121.74.28", &sin.sin_addr);
539        sin.sin_port = htons (6969);
540        sa = (struct sockaddr*)&sin;
541        salen = sizeof (sin);
542        break;
543    case AF_INET6:
544        memset (&sin6, 0, sizeof (sin6));
545        sin6.sin6_family = AF_INET6;
546        /* In order for address selection to work right, this should be
547           a native IPv6 address, not Teredo or 6to4. */
548        evutil_inet_pton (AF_INET6, "2001:1890:1112:1::20", &sin6.sin6_addr);
549        sin6.sin6_port = htons (6969);
550        sa = (struct sockaddr*)&sin6;
551        salen = sizeof (sin6);
552        break;
553    default:
554        return -1;
555    }
556
557    rc = get_source_address (sa, salen, (struct sockaddr*)&ss, &sslen);
558
559    if (rc < 0)
560        return -1;
561
562    if (!global_unicast_address ((struct sockaddr*)&ss))
563        return -1;
564
565    switch (af) {
566    case AF_INET:
567        if (*addr_len < 4)
568            return -1;
569        memcpy (addr, & ((struct sockaddr_in*)&ss)->sin_addr, 4);
570        *addr_len = 4;
571        return 1;
572    case AF_INET6:
573        if (*addr_len < 16)
574            return -1;
575        memcpy (addr, & ((struct sockaddr_in6*)&ss)->sin6_addr, 16);
576        *addr_len = 16;
577        return 1;
578    default:
579        return -1;
580    }
581}
582
583/* Return our global IPv6 address, with caching. */
584
585const unsigned char *
586tr_globalIPv6 (void)
587{
588    static unsigned char ipv6[16];
589    static time_t last_time = 0;
590    static bool have_ipv6 = false;
591    const time_t now = tr_time ();
592
593    /* Re-check every half hour */
594    if (last_time < now - 1800)
595    {
596        int addrlen = 16;
597        const int rc = tr_globalAddress (AF_INET6, ipv6, &addrlen);
598        have_ipv6 = (rc >= 0) && (addrlen == 16);
599        last_time = now;
600    }
601
602    return have_ipv6 ? ipv6 : NULL;
603}
604
605/***
606****
607****
608***/
609
610static bool
611isIPv4MappedAddress (const tr_address * addr)
612{
613    return (addr->type == TR_AF_INET6) && IN6_IS_ADDR_V4MAPPED (&addr->addr.addr6);
614}
615
616static bool
617isIPv6LinkLocalAddress (const tr_address * addr)
618{
619    return ((addr->type == TR_AF_INET6)
620                  && IN6_IS_ADDR_LINKLOCAL (&addr->addr.addr6));
621}
622
623/* isMartianAddr was written by Juliusz Chroboczek,
624   and is covered under the same license as third-party/dht/dht.c. */
625static bool
626isMartianAddr (const struct tr_address * a)
627{
628    static const unsigned char zeroes[16] =
629        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
630
631    assert (tr_address_is_valid (a));
632
633    switch (a->type)
634    {
635        case TR_AF_INET: {
636            const unsigned char * address = (const unsigned char*)&a->addr.addr4;
637            return (address[0] == 0) ||
638                 (address[0] == 127) ||
639                 ((address[0] & 0xE0) == 0xE0);
640        }
641
642        case TR_AF_INET6: {
643            const unsigned char * address = (const unsigned char*)&a->addr.addr6;
644            return (address[0] == 0xFF) ||
645                 (memcmp (address, zeroes, 15) == 0 &&
646                  (address[15] == 0 || address[15] == 1));
647        }
648
649        default:
650            return true;
651    }
652}
653
654bool
655tr_address_is_valid_for_peers (const tr_address * addr, tr_port port)
656{
657    return (port != 0)
658        && (tr_address_is_valid (addr))
659        && (!isIPv6LinkLocalAddress (addr))
660        && (!isIPv4MappedAddress (addr))
661        && (!isMartianAddr (addr));
662}
Note: See TracBrowser for help on using the repository browser.