source: trunk/libtransmission/net.c @ 11610

Last change on this file since 11610 was 11610, checked in by charles, 11 years ago

(trunk libT) #3528 "TR_PREFS_KEY_BIND_ADDRESS_IPV4 breaks IPv6-only trackers" -- Implement suggestion #2 from Harry

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