source: trunk/libtransmission/net.c @ 10858

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

(trunk libT) #3311 "MingW build of Transmission" -- apply further win32 diffs from rb07

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