source: trunk/libtransmission/net.c @ 12918

Last change on this file since 12918 was 12300, checked in by jch, 11 years ago

Reinstate including tcp.h in net.c.

Removed in r12225, this broke netSetCongestionControl.

  • Property svn:keywords set to Date Rev Author Id
File size: 18.1 KB
Line 
1/******************************************************************************
2 *
3 * $Id: net.c 12300 2011-04-02 16:43:17Z 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 sockaddr_storage ss;
304    socklen_t sslen;
305    sslen = setup_sockaddr( addr, port, &ss );
306
307    return UTP_Create( tr_utpSendTo, (void*)session,
308                       (struct sockaddr*)&ss, sslen );
309}
310
311static int
312tr_netBindTCPImpl( const tr_address * addr, tr_port port, bool suppressMsgs, int * errOut )
313{
314    static const int domains[NUM_TR_AF_INET_TYPES] = { AF_INET, AF_INET6 };
315    struct sockaddr_storage sock;
316    int fd;
317    int addrlen;
318    int optval;
319
320    assert( tr_address_is_valid( addr ) );
321
322    fd = socket( domains[addr->type], SOCK_STREAM, 0 );
323    if( fd < 0 ) {
324        *errOut = sockerrno;
325        return -1;
326    }
327
328    if( evutil_make_socket_nonblocking( fd ) < 0 ) {
329        *errOut = sockerrno;
330        tr_netCloseSocket( fd );
331        return -1;
332    }
333
334    optval = 1;
335    setsockopt( fd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval) );
336    setsockopt( fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval) );
337
338#ifdef IPV6_V6ONLY
339    if( addr->type == TR_AF_INET6 )
340        if( setsockopt( fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof( optval ) ) == -1 )
341            if( sockerrno != ENOPROTOOPT ) { /* if the kernel doesn't support it, ignore it */
342                *errOut = sockerrno;
343                return -1;
344            }
345#endif
346
347    addrlen = setup_sockaddr( addr, htons( port ), &sock );
348    if( bind( fd, (struct sockaddr *) &sock, addrlen ) ) {
349        const int err = sockerrno;
350        if( !suppressMsgs )
351        {
352            const char * fmt;
353            const char * hint;
354
355            if( err == EADDRINUSE )
356                hint = _( "Is another copy of Transmission already running?" );
357            else
358                hint = NULL;
359
360            if( hint == NULL )
361                fmt = _( "Couldn't bind port %d on %s: %s" );
362            else
363                fmt = _( "Couldn't bind port %d on %s: %s (%s)" );
364
365            tr_err( fmt, port, tr_address_to_string( addr ), tr_strerror( err ), hint );
366        }
367        tr_netCloseSocket( fd );
368        *errOut = err;
369        return -1;
370    }
371
372    if( !suppressMsgs )
373        tr_dbg( "Bound socket %d to port %d on %s", fd, port, tr_address_to_string( addr ) );
374
375    if( listen( fd, 128 ) == -1 ) {
376        *errOut = sockerrno;
377        tr_netCloseSocket( fd );
378        return -1;
379    }
380
381    return fd;
382}
383
384int
385tr_netBindTCP( const tr_address * addr, tr_port port, bool suppressMsgs )
386{
387    int unused;
388    return tr_netBindTCPImpl( addr, port, suppressMsgs, &unused );
389}
390
391bool
392tr_net_hasIPv6( tr_port port )
393{
394    static bool result = false;
395    static bool alreadyDone = false;
396
397    if( !alreadyDone )
398    {
399        int err;
400        int fd = tr_netBindTCPImpl( &tr_in6addr_any, port, true, &err );
401        if( fd >= 0 || err != EAFNOSUPPORT ) /* we support ipv6 */
402            result = true;
403        if( fd >= 0 )
404            tr_netCloseSocket( fd );
405        alreadyDone = true;
406    }
407
408    return result;
409}
410
411int
412tr_netAccept( tr_session  * session,
413              int           b,
414              tr_address  * addr,
415              tr_port     * port )
416{
417    int fd = tr_fdSocketAccept( session, b, addr, port );
418
419    if( fd>=0 && evutil_make_socket_nonblocking(fd)<0 ) {
420        tr_netClose( session, fd );
421        fd = -1;
422    }
423
424    return fd;
425}
426
427void
428tr_netCloseSocket( int fd )
429{
430    evutil_closesocket( fd );
431}
432
433void
434tr_netClose( tr_session * session, int s )
435{
436    tr_fdSocketClose( session, s );
437}
438
439/*
440   get_source_address() and global_unicast_address() were written by
441   Juliusz Chroboczek, and are covered under the same license as dht.c.
442   Please feel free to copy them into your software if it can help
443   unbreaking the double-stack Internet. */
444
445/* Get the source address used for a given destination address. Since
446   there is no official interface to get this information, we create
447   a connected UDP socket (connected UDP... hmm...) and check its source
448   address. */
449static int
450get_source_address( const struct sockaddr  * dst,
451                    socklen_t                dst_len,
452                    struct sockaddr        * src,
453                    socklen_t              * src_len )
454{
455    int s, rc, save;
456
457    s = socket(dst->sa_family, SOCK_DGRAM, 0);
458    if(s < 0)
459        goto fail;
460
461    /* Since it's a UDP socket, this doesn't actually send any packets. */
462    rc = connect(s, dst, dst_len);
463    if(rc < 0)
464        goto fail;
465
466    rc = getsockname(s, src, src_len);
467    if(rc < 0)
468        goto fail;
469
470    evutil_closesocket( s );
471
472    return rc;
473
474 fail:
475    save = errno;
476    evutil_closesocket( s );
477    errno = save;
478    return -1;
479}
480
481/* We all hate NATs. */
482static int
483global_unicast_address(struct sockaddr *sa)
484{
485    if(sa->sa_family == AF_INET) {
486        const unsigned char *a =
487            (unsigned char*)&((struct sockaddr_in*)sa)->sin_addr;
488        if(a[0] == 0 || a[0] == 127 || a[0] >= 224 ||
489           a[0] == 10 || (a[0] == 172 && a[1] >= 16 && a[1] <= 31) ||
490           (a[0] == 192 && a[1] == 168))
491            return 0;
492        return 1;
493    } else if(sa->sa_family == AF_INET6) {
494        const unsigned char *a =
495            (unsigned char*)&((struct sockaddr_in6*)sa)->sin6_addr;
496        /* 2000::/3 */
497        return (a[0] & 0xE0) == 0x20;
498    } else {
499        errno = EAFNOSUPPORT;
500        return -1;
501    }
502}
503
504static int
505tr_globalAddress( int af, void *addr, int *addr_len )
506{
507    struct sockaddr_storage ss;
508    socklen_t sslen = sizeof(ss);
509    struct sockaddr_in sin;
510    struct sockaddr_in6 sin6;
511    struct sockaddr *sa;
512    socklen_t salen;
513    int rc;
514
515    switch(af) {
516    case AF_INET:
517        memset(&sin, 0, sizeof(sin));
518        sin.sin_family = AF_INET;
519        evutil_inet_pton(AF_INET, "91.121.74.28", &sin.sin_addr);
520        sin.sin_port = htons(6969);
521        sa = (struct sockaddr*)&sin;
522        salen = sizeof(sin);
523        break;
524    case AF_INET6:
525        memset(&sin6, 0, sizeof(sin6));
526        sin6.sin6_family = AF_INET6;
527        /* In order for address selection to work right, this should be
528           a native IPv6 address, not Teredo or 6to4. */
529        evutil_inet_pton(AF_INET6, "2001:1890:1112:1::20", &sin6.sin6_addr);
530        sin6.sin6_port = htons(6969);
531        sa = (struct sockaddr*)&sin6;
532        salen = sizeof(sin6);
533        break;
534    default:
535        return -1;
536    }
537
538    rc = get_source_address( sa, salen, (struct sockaddr*)&ss, &sslen );
539
540    if( rc < 0 )
541        return -1;
542
543    if( !global_unicast_address( (struct sockaddr*)&ss) )
544        return -1;
545
546    switch(af) {
547    case AF_INET:
548        if(*addr_len < 4)
549            return -1;
550        memcpy(addr, &((struct sockaddr_in*)&ss)->sin_addr, 4);
551        *addr_len = 4;
552        return 1;
553    case AF_INET6:
554        if(*addr_len < 16)
555            return -1;
556        memcpy(addr, &((struct sockaddr_in6*)&ss)->sin6_addr, 16);
557        *addr_len = 16;
558        return 1;
559    default:
560        return -1;
561    }
562}
563
564/* Return our global IPv6 address, with caching. */
565
566const unsigned char *
567tr_globalIPv6( void )
568{
569    static unsigned char ipv6[16];
570    static time_t last_time = 0;
571    static int have_ipv6 = 0;
572    const time_t now = tr_time( );
573
574    /* Re-check every half hour */
575    if( last_time < now - 1800 )
576    {
577        int addrlen = 16;
578        const int rc = tr_globalAddress( AF_INET6, ipv6, &addrlen );
579        have_ipv6 = ( rc >= 0 ) && ( addrlen == 16 );
580        last_time = now;
581    }
582
583    return have_ipv6 ? ipv6 : NULL;
584}
585
586/***
587****
588****
589***/
590
591static bool
592isIPv4MappedAddress( const tr_address * addr )
593{
594    return ( addr->type == TR_AF_INET6 ) && IN6_IS_ADDR_V4MAPPED( &addr->addr.addr6 );
595}
596
597static bool
598isIPv6LinkLocalAddress( const tr_address * addr )
599{
600    return ( ( addr->type == TR_AF_INET6 )
601                  && IN6_IS_ADDR_LINKLOCAL( &addr->addr.addr6 ) );
602}
603
604/* isMartianAddr was written by Juliusz Chroboczek,
605   and is covered under the same license as third-party/dht/dht.c. */
606static bool
607isMartianAddr( const struct tr_address * a )
608{
609    static const unsigned char zeroes[16] =
610        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
611
612    assert( tr_address_is_valid( a ) );
613
614    switch( a->type )
615    {
616        case TR_AF_INET: {
617            const unsigned char * address = (const unsigned char*)&a->addr.addr4;
618            return (address[0] == 0) ||
619                   (address[0] == 127) ||
620                   ((address[0] & 0xE0) == 0xE0);
621            break;
622        }
623
624        case TR_AF_INET6: {
625            const unsigned char * address = (const unsigned char*)&a->addr.addr6;
626            return (address[0] == 0xFF) ||
627                   (memcmp(address, zeroes, 15) == 0 &&
628                    (address[15] == 0 || address[15] == 1)) ||
629                   /* Addresses outside of 2000::/3 are currently reserved,
630                      but might be allocated at some future time. Since
631                      there are a lot of buggy peers pushing around such
632                      addresses over PEX, we reject them until the end of
633                      the 13th Baktun. */
634                   (tr_time() < 1356130800 && (address[0] & 0xE0) != 0x20);
635            break;
636        }
637
638        default:
639            return true;
640    }
641}
642
643bool
644tr_address_is_valid_for_peers( const tr_address * addr, tr_port port )
645{
646    return ( port != 0 )
647        && ( tr_address_is_valid( addr ) )
648        && ( !isIPv6LinkLocalAddress( addr ) )
649        && ( !isIPv4MappedAddress( addr ) )
650        && ( !isMartianAddr( addr ) );
651}
Note: See TracBrowser for help on using the repository browser.