source: trunk/libtransmission/net.c @ 12954

Last change on this file since 12954 was 12954, checked in by jordan, 9 years ago

(trunk) #4490 "Transmission 2.40b1 fails to build: undefined references" -- fixed.

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