source: trunk/libtransmission/net.c @ 10498

Last change on this file since 10498 was 10498, checked in by charles, 12 years ago

(trunk libT) #3047 "Periodic disk access in idle state" -- added to trunk for 2.00 by committing a patch by klapaucjusz into this svn code repository

  • Property svn:keywords set to Date Rev Author Id
File size: 17.6 KB
Line 
1/******************************************************************************
2 *
3 * $Id: net.c 10498 2010-04-20 03:44:45Z 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 #include <winsock2.h> /* inet_addr */
36 #include <WS2tcpip.h>
37#else
38 #include <arpa/inet.h> /* inet_addr */
39 #include <netdb.h>
40 #include <fcntl.h>
41#endif
42#include <unistd.h>
43
44#include <stdarg.h> /* some 1.4.x versions of evutil.h need this */
45#include <evutil.h>
46
47#include "transmission.h"
48#include "fdlimit.h"
49#include "natpmp.h"
50#include "net.h"
51#include "peer-io.h"
52#include "platform.h"
53#include "session.h"
54#include "utils.h"
55
56#ifndef IN_MULTICAST
57#define IN_MULTICAST( a ) ( ( ( a ) & 0xf0000000 ) == 0xe0000000 )
58#endif
59
60const tr_address tr_in6addr_any = { TR_AF_INET6, { IN6ADDR_ANY_INIT } };
61const tr_address tr_inaddr_any = { TR_AF_INET, { { { { INADDR_ANY, 0x00, 0x00, 0x00 } } } } };
62
63#ifdef WIN32
64static const char *
65inet_ntop( int af, const void *src, char *dst, socklen_t cnt )
66{
67    if (af == AF_INET)
68    {
69        struct sockaddr_in in;
70        memset( &in, 0, sizeof( in ) );
71        in.sin_family = AF_INET;
72        memcpy( &in.sin_addr, src, sizeof( struct in_addr ) );
73        getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in),
74                    dst, cnt, NULL, 0, NI_NUMERICHOST);
75        return dst;
76    }
77    else if (af == AF_INET6)
78    {
79        struct sockaddr_in6 in;
80        memset( &in, 0, sizeof( in ) );
81        in.sin6_family = AF_INET6;
82        memcpy( &in.sin6_addr, src, sizeof( struct in_addr6 ) );
83        getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6),
84                    dst, cnt, NULL, 0, NI_NUMERICHOST);
85        return dst;
86    }
87    return NULL;
88}
89
90static int
91inet_pton(int af, const char *src, void *dst)
92{
93    struct addrinfo hints;
94    struct addrinfo *res;
95    struct addrinfo *ressave;
96
97    memset(&hints, 0, sizeof(struct addrinfo));
98    hints.ai_family = af;
99
100    if (getaddrinfo(src, NULL, &hints, &res) != 0)
101        return -1;
102
103    ressave = res;
104
105    while (res)
106    {
107        memcpy(dst, res->ai_addr, res->ai_addrlen);
108        res = res->ai_next;
109    }
110
111    freeaddrinfo(ressave);
112    return 0;
113}
114
115#endif
116
117
118void
119tr_netInit( void )
120{
121    static int initialized = FALSE;
122
123    if( !initialized )
124    {
125#ifdef WIN32
126        WSADATA wsaData;
127        WSAStartup( MAKEWORD( 2, 2 ), &wsaData );
128#endif
129        initialized = TRUE;
130    }
131}
132
133const char *
134tr_ntop( const tr_address * src, char * dst, int size )
135{
136    assert( tr_isAddress( src ) );
137
138    if( src->type == TR_AF_INET )
139        return inet_ntop( AF_INET, &src->addr, dst, size );
140    else
141        return inet_ntop( AF_INET6, &src->addr, dst, size );
142}
143
144/*
145 * Non-threadsafe version of tr_ntop, which uses a static memory area for a buffer.
146 * This function is suitable to be called from libTransmission's networking code,
147 * which is single-threaded.
148 */
149const char *
150tr_ntop_non_ts( const tr_address * src )
151{
152    static char buf[INET6_ADDRSTRLEN];
153    return tr_ntop( src, buf, sizeof( buf ) );
154}
155
156tr_address *
157tr_pton( const char * src, tr_address * dst )
158{
159    int retval = inet_pton( AF_INET, src, &dst->addr );
160    assert( dst );
161    if( retval < 0 )
162        return NULL;
163    else if( retval == 0 )
164        retval = inet_pton( AF_INET6, src, &dst->addr );
165    else
166    {
167        dst->type = TR_AF_INET;
168        return dst;
169    }
170
171    if( retval < 1 )
172        return NULL;
173    dst->type = TR_AF_INET6;
174    return dst;
175}
176
177/*
178 * Compare two tr_address structures.
179 * Returns:
180 * <0 if a < b
181 * >0 if a > b
182 * 0  if a == b
183 */
184int
185tr_compareAddresses( const tr_address * a, const tr_address * b)
186{
187    static const int sizes[2] = { sizeof(struct in_addr), sizeof(struct in6_addr) };
188
189    assert( tr_isAddress( a ) );
190    assert( tr_isAddress( b ) );
191
192    /* IPv6 addresses are always "greater than" IPv4 */
193    if( a->type != b->type )
194        return a->type == TR_AF_INET ? 1 : -1;
195
196    return memcmp( &a->addr, &b->addr, sizes[a->type] );
197}
198
199/***********************************************************************
200 * TCP sockets
201 **********************************************************************/
202
203int
204tr_netSetTOS( int s, int tos )
205{
206#ifdef IP_TOS
207    return setsockopt( s, IPPROTO_IP, IP_TOS, (char*)&tos, sizeof( tos ) );
208#else
209    return 0;
210#endif
211}
212
213static socklen_t
214setup_sockaddr( const tr_address        * addr,
215                tr_port                   port,
216                struct sockaddr_storage * sockaddr)
217{
218    assert( tr_isAddress( addr ) );
219
220    if( addr->type == TR_AF_INET )
221    {
222        struct sockaddr_in  sock4;
223        memset( &sock4, 0, sizeof( sock4 ) );
224        sock4.sin_family      = AF_INET;
225        sock4.sin_addr.s_addr = addr->addr.addr4.s_addr;
226        sock4.sin_port        = port;
227        memcpy( sockaddr, &sock4, sizeof( sock4 ) );
228        return sizeof( struct sockaddr_in );
229    }
230    else
231    {
232        struct sockaddr_in6 sock6;
233        memset( &sock6, 0, sizeof( sock6 ) );
234        sock6.sin6_family   = AF_INET6;
235        sock6.sin6_port     = port;
236        sock6.sin6_flowinfo = 0;
237        sock6.sin6_addr     = addr->addr.addr6;
238        memcpy( sockaddr, &sock6, sizeof( sock6 ) );
239        return sizeof( struct sockaddr_in6 );
240    }
241}
242
243int
244tr_netOpenPeerSocket( tr_session        * session,
245                      const tr_address  * addr,
246                      tr_port             port,
247                      tr_bool             clientIsSeed )
248{
249    static const int domains[NUM_TR_AF_INET_TYPES] = { AF_INET, AF_INET6 };
250    int                     s;
251    struct sockaddr_storage sock;
252    socklen_t               addrlen;
253    const tr_address      * source_addr;
254    socklen_t               sourcelen;
255    struct sockaddr_storage source_sock;
256
257    assert( tr_isAddress( addr ) );
258
259    if( !tr_isValidPeerAddress( addr, port ) )
260        return -EINVAL;
261
262    s = tr_fdSocketCreate( session, domains[addr->type], SOCK_STREAM );
263    if( s < 0 )
264        return -1;
265
266    /* seeds don't need much of a read buffer... */
267    if( clientIsSeed ) {
268        int n = 8192;
269        if( setsockopt( s, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n) ) )
270            tr_inf( "Unable to set SO_RCVBUF on socket %d: %s", s, tr_strerror( sockerrno ) );
271    }
272
273    if( evutil_make_socket_nonblocking( s ) < 0 ) {
274        tr_netClose( session, s );
275        return -1;
276    }
277
278    addrlen = setup_sockaddr( addr, port, &sock );
279
280    /* set source address */
281    source_addr = tr_sessionGetPublicAddress( session, addr->type );
282    assert( source_addr );
283    sourcelen = setup_sockaddr( source_addr, 0, &source_sock );
284    if( bind( s, ( struct sockaddr * ) &source_sock, sourcelen ) )
285    {
286        tr_err( _( "Couldn't set source address %s on %d: %s" ),
287                tr_ntop_non_ts( source_addr ), s, tr_strerror( errno ) );
288        return -errno;
289    }
290
291    if( ( connect( s, (struct sockaddr *) &sock,
292                  addrlen ) < 0 )
293#ifdef WIN32
294      && ( sockerrno != WSAEWOULDBLOCK )
295#endif
296      && ( sockerrno != EINPROGRESS ) )
297    {
298        int tmperrno;
299        tmperrno = sockerrno;
300        if( ( tmperrno != ENETUNREACH && tmperrno != EHOSTUNREACH )
301                || addr->type == TR_AF_INET )
302            tr_err( _( "Couldn't connect socket %d to %s, port %d (errno %d - %s)" ),
303                    s, tr_ntop_non_ts( addr ), (int)port, tmperrno,
304                    tr_strerror( tmperrno ) );
305        tr_netClose( session, s );
306        s = -tmperrno;
307    }
308
309    tr_deepLog( __FILE__, __LINE__, NULL, "New OUTGOING connection %d (%s)",
310               s, tr_peerIoAddrStr( addr, port ) );
311
312    return s;
313}
314
315static int
316tr_netBindTCPImpl( const tr_address * addr, tr_port port, tr_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_isAddress( 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_ntop_non_ts( 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_ntop_non_ts( 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, tr_bool suppressMsgs )
390{
391    int unused;
392    return tr_netBindTCPImpl( addr, port, suppressMsgs, &unused );
393}
394
395tr_bool
396tr_net_hasIPv6( tr_port port )
397{
398    static tr_bool result = FALSE;
399    static tr_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        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        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 tr_bool
596isIPv4MappedAddress( const tr_address * addr )
597{
598    return ( addr->type == TR_AF_INET6 ) && IN6_IS_ADDR_V4MAPPED( &addr->addr.addr6 );
599}
600
601static tr_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 tr_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_isAddress( 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
647tr_bool
648tr_isValidPeerAddress( const tr_address * addr, tr_port port )
649{
650    return ( port != 0 )
651        && ( tr_isAddress( addr ) )
652        && ( !isIPv6LinkLocalAddress( addr ) )
653        && ( !isIPv4MappedAddress( addr ) )
654        && ( !isMartianAddr( addr ) );
655}
Note: See TracBrowser for help on using the repository browser.