source: trunk/libtransmission/net.c @ 12147

Last change on this file since 12147 was 12147, checked in by jordan, 11 years ago

(trunk libT) use libevent2's portability wrappers for inet_ntop() and inet_pton().

We currently implement our own versions of these on mingw because that platform doesn't have them... but why reinvent the wheel; libevent has already done the same thing. Let's use libevent2's implementation.
has already done it for us.

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