source: trunk/libtransmission/net.c @ 13631

Last change on this file since 13631 was 13631, checked in by jordan, 9 years ago

(trunk, libT) #5165: fix r13625 oops

  • Property svn:keywords set to Date Rev Author Id
File size: 18.0 KB
Line 
1/******************************************************************************
2 *
3 * $Id: net.c 13631 2012-12-07 01:53:31Z jordan $
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 #define _WIN32_WINNT   0x0501
34 #include <ws2tcpip.h>
35#else
36 #include <netinet/tcp.h>       /* TCP_CONGESTION */
37#endif
38
39#include <event2/util.h>
40
41#include <libutp/utp.h>
42
43#include "transmission.h"
44#include "fdlimit.h" /* tr_fdSocketClose () */
45#include "net.h"
46#include "peer-io.h" /* tr_peerIoAddrStr () FIXME this should be moved to net.h */
47#include "session.h" /* tr_sessionGetPublicAddress () */
48#include "tr-utp.h" /* tr_utpSendTo () */
49#include "utils.h" /* tr_time (), tr_dbg () */
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 int 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    FormatMessage (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
147int
148tr_netSetTOS (int s, int tos)
149{
150#ifdef IP_TOS
151    return setsockopt (s, IPPROTO_IP, IP_TOS, (char*)&tos, sizeof (tos));
152#else
153    return 0;
154#endif
155}
156
157int
158tr_netSetCongestionControl (int s UNUSED, const char *algorithm UNUSED)
159{
160#ifdef TCP_CONGESTION
161    return setsockopt (s, IPPROTO_TCP, TCP_CONGESTION,
162                       algorithm, strlen (algorithm) + 1);
163#else
164    errno = ENOSYS;
165    return -1;
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
225int
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    int                     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
239    assert (tr_address_is_valid (addr));
240
241    if (!tr_address_is_valid_for_peers (addr, port))
242        return -EINVAL;
243
244    s = tr_fdSocketCreate (session, domains[addr->type], SOCK_STREAM);
245    if (s < 0)
246        return -1;
247
248    /* seeds don't need much of a read buffer... */
249    if (clientIsSeed) {
250        int n = 8192;
251        if (setsockopt (s, SOL_SOCKET, SO_RCVBUF, &n, sizeof (n)))
252            tr_inf ("Unable to set SO_RCVBUF on socket %d: %s", s, tr_strerror (sockerrno));
253    }
254
255    if (evutil_make_socket_nonblocking (s) < 0) {
256        tr_netClose (session, s);
257        return -1;
258    }
259
260    addrlen = setup_sockaddr (addr, port, &sock);
261
262    /* set source address */
263    source_addr = tr_sessionGetPublicAddress (session, addr->type, NULL);
264    assert (source_addr);
265    sourcelen = setup_sockaddr (source_addr, 0, &source_sock);
266    if (bind (s, (struct sockaddr *) &source_sock, sourcelen))
267    {
268        tr_err (_("Couldn't set source address %s on %d: %s"),
269                tr_address_to_string (source_addr), s, tr_strerror (errno));
270        return -errno;
271    }
272
273    if ((connect (s, (struct sockaddr *) &sock,
274                  addrlen) < 0)
275#ifdef WIN32
276      && (sockerrno != WSAEWOULDBLOCK)
277#endif
278      && (sockerrno != EINPROGRESS))
279    {
280        int tmperrno;
281        tmperrno = sockerrno;
282        if ((tmperrno != ENETUNREACH && tmperrno != EHOSTUNREACH)
283                || addr->type == TR_AF_INET)
284            tr_err (_("Couldn't connect socket %d to %s, port %d (errno %d - %s)"),
285                    s, tr_address_to_string (addr), (int)ntohs (port), tmperrno,
286                    tr_strerror (tmperrno));
287        tr_netClose (session, s);
288        s = -tmperrno;
289    }
290
291    tr_deepLog (__FILE__, __LINE__, NULL, "New OUTGOING connection %d (%s)",
292               s, tr_peerIoAddrStr (addr, port));
293
294    return s;
295}
296
297struct UTPSocket *
298tr_netOpenPeerUTPSocket (tr_session        * session,
299                         const tr_address  * addr,
300                         tr_port             port,
301                         bool                clientIsSeed UNUSED)
302{
303  struct UTPSocket * ret = NULL;
304
305  if (tr_address_is_valid_for_peers (addr, port))
306    {
307      struct sockaddr_storage ss;
308      const socklen_t sslen = setup_sockaddr (addr, port, &ss);
309      ret = UTP_Create (tr_utpSendTo, session, (struct sockaddr*)&ss, sslen);
310    }
311
312  return ret;
313}
314
315static int
316tr_netBindTCPImpl (const tr_address * addr, tr_port port, bool suppressMsgs, int * errOut)
317{
318    static const int domains[NUM_TR_AF_INET_TYPES] = { AF_INET, AF_INET6 };
319    struct sockaddr_storage sock;
320    int fd;
321    int addrlen;
322    int optval;
323
324    assert (tr_address_is_valid (addr));
325
326    fd = socket (domains[addr->type], SOCK_STREAM, 0);
327    if (fd < 0) {
328        *errOut = sockerrno;
329        return -1;
330    }
331
332    if (evutil_make_socket_nonblocking (fd) < 0) {
333        *errOut = sockerrno;
334        tr_netCloseSocket (fd);
335        return -1;
336    }
337
338    optval = 1;
339    setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof (optval));
340    setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (optval));
341
342#ifdef IPV6_V6ONLY
343    if (addr->type == TR_AF_INET6)
344        if (setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof (optval)) == -1)
345            if (sockerrno != ENOPROTOOPT) { /* if the kernel doesn't support it, ignore it */
346                *errOut = sockerrno;
347                return -1;
348            }
349#endif
350
351    addrlen = setup_sockaddr (addr, htons (port), &sock);
352    if (bind (fd, (struct sockaddr *) &sock, addrlen)) {
353        const int err = sockerrno;
354        if (!suppressMsgs)
355        {
356            const char * fmt;
357            const char * hint;
358
359            if (err == EADDRINUSE)
360                hint = _("Is another copy of Transmission already running?");
361            else
362                hint = NULL;
363
364            if (hint == NULL)
365                fmt = _("Couldn't bind port %d on %s: %s");
366            else
367                fmt = _("Couldn't bind port %d on %s: %s (%s)");
368
369            tr_err (fmt, port, tr_address_to_string (addr), tr_strerror (err), hint);
370        }
371        tr_netCloseSocket (fd);
372        *errOut = err;
373        return -1;
374    }
375
376    if (!suppressMsgs)
377        tr_dbg ("Bound socket %d to port %d on %s", fd, port, tr_address_to_string (addr));
378
379    if (listen (fd, 128) == -1) {
380        *errOut = sockerrno;
381        tr_netCloseSocket (fd);
382        return -1;
383    }
384
385    return fd;
386}
387
388int
389tr_netBindTCP (const tr_address * addr, tr_port port, bool suppressMsgs)
390{
391    int unused;
392    return tr_netBindTCPImpl (addr, port, suppressMsgs, &unused);
393}
394
395bool
396tr_net_hasIPv6 (tr_port port)
397{
398    static bool result = false;
399    static bool alreadyDone = false;
400
401    if (!alreadyDone)
402    {
403        int err;
404        int fd = tr_netBindTCPImpl (&tr_in6addr_any, port, true, &err);
405        if (fd >= 0 || err != EAFNOSUPPORT) /* we support ipv6 */
406            result = true;
407        if (fd >= 0)
408            tr_netCloseSocket (fd);
409        alreadyDone = true;
410    }
411
412    return result;
413}
414
415int
416tr_netAccept (tr_session  * session,
417              int           b,
418              tr_address  * addr,
419              tr_port     * port)
420{
421    int fd = tr_fdSocketAccept (session, b, addr, port);
422
423    if (fd>=0 && evutil_make_socket_nonblocking (fd)<0) {
424        tr_netClose (session, fd);
425        fd = -1;
426    }
427
428    return fd;
429}
430
431void
432tr_netCloseSocket (int fd)
433{
434    evutil_closesocket (fd);
435}
436
437void
438tr_netClose (tr_session * session, int s)
439{
440    tr_fdSocketClose (session, s);
441}
442
443/*
444   get_source_address () and global_unicast_address () were written by
445   Juliusz Chroboczek, and are covered under the same license as dht.c.
446   Please feel free to copy them into your software if it can help
447   unbreaking the double-stack Internet. */
448
449/* Get the source address used for a given destination address. Since
450   there is no official interface to get this information, we create
451   a connected UDP socket (connected UDP... hmm...) and check its source
452   address. */
453static int
454get_source_address (const struct sockaddr  * dst,
455                    socklen_t                dst_len,
456                    struct sockaddr        * src,
457                    socklen_t              * src_len)
458{
459    int s, rc, save;
460
461    s = socket (dst->sa_family, SOCK_DGRAM, 0);
462    if (s < 0)
463        goto fail;
464
465    /* Since it's a UDP socket, this doesn't actually send any packets. */
466    rc = connect (s, dst, dst_len);
467    if (rc < 0)
468        goto fail;
469
470    rc = getsockname (s, src, src_len);
471    if (rc < 0)
472        goto fail;
473
474    evutil_closesocket (s);
475
476    return rc;
477
478 fail:
479    save = errno;
480    evutil_closesocket (s);
481    errno = save;
482    return -1;
483}
484
485/* We all hate NATs. */
486static int
487global_unicast_address (struct sockaddr *sa)
488{
489    if (sa->sa_family == AF_INET) {
490        const unsigned char *a =
491          (unsigned char*)& ((struct sockaddr_in*)sa)->sin_addr;
492        if (a[0] == 0 || a[0] == 127 || a[0] >= 224 ||
493           a[0] == 10 || (a[0] == 172 && a[1] >= 16 && a[1] <= 31) ||
494         (a[0] == 192 && a[1] == 168))
495            return 0;
496        return 1;
497    } else if (sa->sa_family == AF_INET6) {
498        const unsigned char *a =
499          (unsigned char*)& ((struct sockaddr_in6*)sa)->sin6_addr;
500        /* 2000::/3 */
501        return (a[0] & 0xE0) == 0x20;
502    } else {
503        errno = EAFNOSUPPORT;
504        return -1;
505    }
506}
507
508static int
509tr_globalAddress (int af, void *addr, int *addr_len)
510{
511    struct sockaddr_storage ss;
512    socklen_t sslen = sizeof (ss);
513    struct sockaddr_in sin;
514    struct sockaddr_in6 sin6;
515    struct sockaddr *sa;
516    socklen_t salen;
517    int rc;
518
519    switch (af) {
520    case AF_INET:
521        memset (&sin, 0, sizeof (sin));
522        sin.sin_family = AF_INET;
523        evutil_inet_pton (AF_INET, "91.121.74.28", &sin.sin_addr);
524        sin.sin_port = htons (6969);
525        sa = (struct sockaddr*)&sin;
526        salen = sizeof (sin);
527        break;
528    case AF_INET6:
529        memset (&sin6, 0, sizeof (sin6));
530        sin6.sin6_family = AF_INET6;
531        /* In order for address selection to work right, this should be
532           a native IPv6 address, not Teredo or 6to4. */
533        evutil_inet_pton (AF_INET6, "2001:1890:1112:1::20", &sin6.sin6_addr);
534        sin6.sin6_port = htons (6969);
535        sa = (struct sockaddr*)&sin6;
536        salen = sizeof (sin6);
537        break;
538    default:
539        return -1;
540    }
541
542    rc = get_source_address (sa, salen, (struct sockaddr*)&ss, &sslen);
543
544    if (rc < 0)
545        return -1;
546
547    if (!global_unicast_address ((struct sockaddr*)&ss))
548        return -1;
549
550    switch (af) {
551    case AF_INET:
552        if (*addr_len < 4)
553            return -1;
554        memcpy (addr, & ((struct sockaddr_in*)&ss)->sin_addr, 4);
555        *addr_len = 4;
556        return 1;
557    case AF_INET6:
558        if (*addr_len < 16)
559            return -1;
560        memcpy (addr, & ((struct sockaddr_in6*)&ss)->sin6_addr, 16);
561        *addr_len = 16;
562        return 1;
563    default:
564        return -1;
565    }
566}
567
568/* Return our global IPv6 address, with caching. */
569
570const unsigned char *
571tr_globalIPv6 (void)
572{
573    static unsigned char ipv6[16];
574    static time_t last_time = 0;
575    static int have_ipv6 = 0;
576    const time_t now = tr_time ();
577
578    /* Re-check every half hour */
579    if (last_time < now - 1800)
580    {
581        int addrlen = 16;
582        const int rc = tr_globalAddress (AF_INET6, ipv6, &addrlen);
583        have_ipv6 = (rc >= 0) && (addrlen == 16);
584        last_time = now;
585    }
586
587    return have_ipv6 ? ipv6 : NULL;
588}
589
590/***
591****
592****
593***/
594
595static bool
596isIPv4MappedAddress (const tr_address * addr)
597{
598    return (addr->type == TR_AF_INET6) && IN6_IS_ADDR_V4MAPPED (&addr->addr.addr6);
599}
600
601static bool
602isIPv6LinkLocalAddress (const tr_address * addr)
603{
604    return ((addr->type == TR_AF_INET6)
605                  && IN6_IS_ADDR_LINKLOCAL (&addr->addr.addr6));
606}
607
608/* isMartianAddr was written by Juliusz Chroboczek,
609   and is covered under the same license as third-party/dht/dht.c. */
610static bool
611isMartianAddr (const struct tr_address * a)
612{
613    static const unsigned char zeroes[16] =
614        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
615
616    assert (tr_address_is_valid (a));
617
618    switch (a->type)
619    {
620        case TR_AF_INET: {
621            const unsigned char * address = (const unsigned char*)&a->addr.addr4;
622            return (address[0] == 0) ||
623                 (address[0] == 127) ||
624                 ((address[0] & 0xE0) == 0xE0);
625            break;
626        }
627
628        case TR_AF_INET6: {
629            const unsigned char * address = (const unsigned char*)&a->addr.addr6;
630            return (address[0] == 0xFF) ||
631                 (memcmp (address, zeroes, 15) == 0 &&
632                  (address[15] == 0 || address[15] == 1)) ||
633                   /* Addresses outside of 2000::/3 are currently reserved,
634                      but might be allocated at some future time. Since
635                      there are a lot of buggy peers pushing around such
636                      addresses over PEX, we reject them until the end of
637                      the 13th Baktun. */
638                 (tr_time () < 1356130800 && (address[0] & 0xE0) != 0x20);
639            break;
640        }
641
642        default:
643            return true;
644    }
645}
646
647bool
648tr_address_is_valid_for_peers (const tr_address * addr, tr_port port)
649{
650    return (port != 0)
651        && (tr_address_is_valid (addr))
652        && (!isIPv6LinkLocalAddress (addr))
653        && (!isIPv4MappedAddress (addr))
654        && (!isMartianAddr (addr));
655}
Note: See TracBrowser for help on using the repository browser.