source: trunk/libtransmission/net.c @ 14527

Last change on this file since 14527 was 14527, checked in by mikedld, 6 years ago

Fix some issues revealed by coverity

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