source: trunk/libtransmission/net.c @ 11311

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

(trunk libT) silence minor compiler warning

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