Ignore:
Timestamp:
Dec 8, 2007, 7:34:15 PM (13 years ago)
Author:
charles
Message:

Use libnatpmp for port mapping. rewrite the upnp/natpmp manager.

NOTE: this will break the xpjets build until SoftwareElves? or a volunteer patches the xcode project file to make a libnatpmp library just like was done for libminiupnp.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/platform.c

    r4089 r4092  
    444444    return buf;
    445445}
    446 
    447 /***
    448 ****  SOCKETS
    449 ***/
    450 
    451 #ifdef BSD
    452 
    453 #include <sys/types.h>
    454 #include <sys/socket.h>
    455 #include <netinet/in.h>
    456 #include <arpa/inet.h>
    457 #include <netinet/in.h> /* struct in_addr */
    458 #include <sys/sysctl.h>
    459 #include <net/route.h>
    460 
    461 static uint8_t *
    462 getroute( int * buflen );
    463 static int
    464 parseroutes( uint8_t * buf, int len, struct in_addr * addr );
    465 
    466 int
    467 tr_getDefaultRoute( struct in_addr * addr )
    468 {
    469     uint8_t * buf;
    470     int len;
    471 
    472     buf = getroute( &len );
    473     if( NULL == buf )
    474     {
    475         tr_err( "failed to get default route (BSD)" );
    476         return 1;
    477     }
    478 
    479     len = parseroutes( buf, len, addr );
    480     free( buf );
    481 
    482     return len;
    483 }
    484 
    485 #ifndef SA_SIZE
    486 #define ROUNDUP( a, size ) \
    487     ( ( (a) & ( (size) - 1 ) ) ? ( 1 + ( (a) | ( (size) - 1 ) ) ) : (a) )
    488 #define SA_SIZE( sap ) \
    489     ( sap->sa_len ? ROUNDUP( (sap)->sa_len, sizeof( u_long ) ) : \
    490                     sizeof( u_long ) )
    491 #endif /* !SA_SIZE */
    492 #define NEXT_SA( sap ) \
    493     (struct sockaddr *) ( (caddr_t) (sap) + ( SA_SIZE( (sap) ) ) )
    494 
    495 static uint8_t *
    496 getroute( int * buflen )
    497 {
    498     int     mib[6];
    499     size_t  len;
    500     uint8_t * buf;
    501 
    502     mib[0] = CTL_NET;
    503     mib[1] = PF_ROUTE;
    504     mib[2] = 0;
    505     mib[3] = AF_INET;
    506     mib[4] = NET_RT_FLAGS;
    507     mib[5] = RTF_GATEWAY;
    508 
    509     if( sysctl( mib, 6, NULL, &len, NULL, 0 ) )
    510     {
    511         if( ENOENT != errno )
    512         {
    513             tr_err( "sysctl net.route.0.inet.flags.gateway failed (%s)",
    514                     strerror( sockerrno ) );
    515         }
    516         *buflen = 0;
    517         return NULL;
    518     }
    519 
    520     buf = malloc( len );
    521     if( NULL == buf )
    522     {
    523         *buflen = 0;
    524         return NULL;
    525     }
    526 
    527     if( sysctl( mib, 6, buf, &len, NULL, 0 ) )
    528     {
    529         tr_err( "sysctl net.route.0.inet.flags.gateway failed (%s)",
    530                 strerror( sockerrno ) );
    531         free( buf );
    532         *buflen = 0;
    533         return NULL;
    534     }
    535 
    536     *buflen = len;
    537 
    538     return buf;
    539 }
    540 
    541 static int
    542 parseroutes( uint8_t * buf, int len, struct in_addr * addr )
    543 {
    544     uint8_t            * end;
    545     struct rt_msghdr   * rtm;
    546     struct sockaddr    * sa;
    547     struct sockaddr_in * sin;
    548     int                  ii;
    549     struct in_addr       dest, gw;
    550 
    551     end = buf + len;
    552     while( end > buf + sizeof( *rtm ) )
    553     {
    554         rtm = (struct rt_msghdr *) buf;
    555         buf += rtm->rtm_msglen;
    556         if( end >= buf )
    557         {
    558             dest.s_addr = INADDR_NONE;
    559             gw.s_addr   = INADDR_NONE;
    560             sa = (struct sockaddr *) ( rtm + 1 );
    561 
    562             for( ii = 0; ii < RTAX_MAX && (uint8_t *) sa < buf; ii++ )
    563             {
    564                 if( buf < (uint8_t *) NEXT_SA( sa ) )
    565                 {
    566                     break;
    567                 }
    568 
    569                 if( rtm->rtm_addrs & ( 1 << ii ) )
    570                 {
    571                     if( AF_INET == sa->sa_family )
    572                     {
    573                         sin = (struct sockaddr_in *) sa;
    574                         switch( ii )
    575                         {
    576                             case RTAX_DST:
    577                                 dest = sin->sin_addr;
    578                                 break;
    579                             case RTAX_GATEWAY:
    580                                 gw = sin->sin_addr;
    581                                 break;
    582                         }
    583                     }
    584                     sa = NEXT_SA( sa );
    585                 }
    586             }
    587 
    588             if( INADDR_ANY == dest.s_addr && INADDR_NONE != gw.s_addr )
    589             {
    590                 *addr = gw;
    591                 return 0;
    592             }
    593         }
    594     }
    595 
    596     return 1;
    597 }
    598 
    599 #elif defined( linux ) || defined( __linux ) || defined( __linux__ )
    600 
    601 #include <linux/types.h>
    602 #include <linux/netlink.h>
    603 #include <linux/rtnetlink.h>
    604 
    605 #define SEQNUM 195909
    606 
    607 static int
    608 getsock( void );
    609 static uint8_t *
    610 getroute( int fd, unsigned int * buflen );
    611 static int
    612 parseroutes( uint8_t * buf, unsigned int len, struct in_addr * addr );
    613 
    614 int
    615 tr_getDefaultRoute( struct in_addr * addr )
    616 {
    617     int fd, ret;
    618     unsigned int len;
    619     uint8_t * buf;
    620 
    621     ret = 1;
    622     fd = getsock();
    623     if( 0 <= fd )
    624     {
    625         while( ret )
    626         {
    627             buf = getroute( fd, &len );
    628             if( NULL == buf )
    629             {
    630                 break;
    631             }
    632             ret = parseroutes( buf, len, addr );
    633             free( buf );
    634         }
    635         close( fd );
    636     }
    637 
    638     if( ret )
    639     {
    640         tr_err( "failed to get default route (Linux)" );
    641     }
    642 
    643     return ret;
    644 }
    645 
    646 static int
    647 getsock( void )
    648 {
    649     int fd, flags;
    650     struct
    651     {
    652         struct nlmsghdr nlh;
    653         struct rtgenmsg rtg;
    654     } req;
    655     struct sockaddr_nl snl;
    656 
    657     fd = socket( PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE );
    658     if( 0 > fd )
    659     {
    660         tr_err( "failed to create routing socket (%s)", strerror( sockerrno ) );
    661         return -1;
    662     }
    663 
    664     flags = fcntl( fd, F_GETFL );
    665     if( 0 > flags || 0 > fcntl( fd, F_SETFL, O_NONBLOCK | flags ) )
    666     {
    667         tr_err( "failed to set socket nonblocking (%s)", strerror( sockerrno ) );
    668         close( fd );
    669         return -1;
    670     }
    671 
    672     memset( &snl, 0, sizeof(snl) );
    673     snl.nl_family = AF_NETLINK;
    674 
    675     memset( &req, 0, sizeof(req) );
    676     req.nlh.nlmsg_len = NLMSG_LENGTH( sizeof( req.rtg ) );
    677     req.nlh.nlmsg_type = RTM_GETROUTE;
    678     req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
    679     req.nlh.nlmsg_seq = SEQNUM;
    680     req.nlh.nlmsg_pid = 0;
    681     req.rtg.rtgen_family = AF_INET;
    682 
    683     if( 0 > sendto( fd, &req, sizeof( req ), 0,
    684                     (struct sockaddr *) &snl, sizeof( snl ) ) )
    685     {
    686         tr_err( "failed to write to routing socket (%s)", strerror( sockerrno ) );
    687         close( fd );
    688         return -1;
    689     }
    690 
    691     return fd;
    692 }
    693 
    694 static uint8_t *
    695 getroute( int fd, unsigned int * buflen )
    696 {
    697     void             * buf;
    698     unsigned int       len;
    699     ssize_t            res;
    700     struct sockaddr_nl snl;
    701     socklen_t          slen;
    702 
    703     len = 8192;
    704     buf = calloc( 1, len );
    705     if( NULL == buf )
    706     {
    707         *buflen = 0;
    708         return NULL;
    709     }
    710 
    711     for( ;; )
    712     {
    713         slen = sizeof( snl );
    714         memset( &snl, 0, slen );
    715         res = recvfrom( fd, buf, len, 0, (struct sockaddr *) &snl, &slen );
    716         if( 0 > res )
    717         {
    718             if( EAGAIN != sockerrno )
    719             {
    720                 tr_err( "failed to read from routing socket (%s)",
    721                         strerror( sockerrno ) );
    722             }
    723             free( buf );
    724             *buflen = 0;
    725             return NULL;
    726         }
    727         if( slen < sizeof( snl ) || AF_NETLINK != snl.nl_family )
    728         {
    729             tr_err( "bad address" );
    730             free( buf );
    731             *buflen = 0;
    732             return NULL;
    733         }
    734 
    735         if( 0 == snl.nl_pid )
    736         {
    737             break;
    738         }
    739     }
    740 
    741     *buflen = res;
    742 
    743     return buf;
    744 }
    745 
    746 static int
    747 parseroutes( uint8_t * buf, unsigned int len, struct in_addr * addr )
    748 {
    749     struct nlmsghdr * nlm;
    750     struct nlmsgerr * nle;
    751     struct rtmsg    * rtm;
    752     struct rtattr   * rta;
    753     int               rtalen;
    754     struct in_addr    gw, dst;
    755 
    756     nlm = ( struct nlmsghdr * ) buf;
    757     while( NLMSG_OK( nlm, len ) )
    758     {
    759         gw.s_addr = INADDR_ANY;
    760         dst.s_addr = INADDR_ANY;
    761         if( NLMSG_ERROR == nlm->nlmsg_type )
    762         {
    763             nle = (struct nlmsgerr *) NLMSG_DATA( nlm );
    764             if( NLMSG_LENGTH( NLMSG_ALIGN( sizeof( struct nlmsgerr ) ) ) >
    765                 nlm->nlmsg_len )
    766             {
    767                 tr_err( "truncated netlink error" );
    768             }
    769             else
    770             {
    771                 tr_err( "netlink error (%s)", strerror( nle->error ) );
    772             }
    773             return 1;
    774         }
    775         else if( RTM_NEWROUTE == nlm->nlmsg_type && SEQNUM == nlm->nlmsg_seq &&
    776                  getpid() == (pid_t) nlm->nlmsg_pid &&
    777                  NLMSG_LENGTH( sizeof( struct rtmsg ) ) <= nlm->nlmsg_len )
    778         {
    779             rtm = NLMSG_DATA( nlm );
    780             rta = RTM_RTA( rtm );
    781             rtalen = RTM_PAYLOAD( nlm );
    782 
    783             while( RTA_OK( rta, rtalen ) )
    784             {
    785                 if( sizeof( struct in_addr ) <= RTA_PAYLOAD( rta ) )
    786                 {
    787                     switch( rta->rta_type )
    788                     {
    789                         case RTA_GATEWAY:
    790                             memcpy( &gw, RTA_DATA( rta ), sizeof( gw ) );
    791                             break;
    792                         case RTA_DST:
    793                             memcpy( &dst, RTA_DATA( rta ), sizeof( dst ) );
    794                             break;
    795                     }
    796                 }
    797                 rta = RTA_NEXT( rta, rtalen );
    798             }
    799         }
    800 
    801         if( INADDR_NONE != gw.s_addr && INADDR_ANY != gw.s_addr &&
    802             INADDR_ANY == dst.s_addr )
    803         {
    804             *addr = gw;
    805             return 0;
    806         }
    807 
    808         nlm = NLMSG_NEXT( nlm, len );
    809     }
    810 
    811     return 1;
    812 }
    813 
    814 #else /* not BSD or Linux */
    815 
    816 int
    817 tr_getDefaultRoute( struct in_addr * addr UNUSED )
    818 {
    819     tr_inf( "don't know how to get default route on this platform" );
    820     return 1;
    821 }
    822 
    823 #endif
Note: See TracChangeset for help on using the changeset viewer.