Ignore:
Timestamp:
Nov 26, 2007, 8:21:52 PM (13 years ago)
Author:
charles
Message:

move tr_getDefaultRoute() to natpmp.c because it's the only code that uses it

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/platform.c

    r3838 r3984  
    4444#include <sys/types.h>
    4545#include <dirent.h>
    46 #include <fcntl.h>
    47 #include <unistd.h> /* getuid getpid close */
     46#include <unistd.h> /* getuid getpid */
    4847
    4948#include "transmission.h"
     
    626625    return buf;
    627626}
    628 
    629 /***
    630 ****  SOCKETS
    631 ***/
    632 
    633 #ifdef BSD
    634 
    635 #include <sys/types.h>
    636 #include <sys/socket.h>
    637 #include <netinet/in.h>
    638 #include <arpa/inet.h>
    639 #include <netinet/in.h> /* struct in_addr */
    640 #include <sys/sysctl.h>
    641 #include <net/route.h>
    642 
    643 static uint8_t *
    644 getroute( int * buflen );
    645 static int
    646 parseroutes( uint8_t * buf, int len, struct in_addr * addr );
    647 
    648 int
    649 tr_getDefaultRoute( struct in_addr * addr )
    650 {
    651     uint8_t * buf;
    652     int len;
    653 
    654     buf = getroute( &len );
    655     if( NULL == buf )
    656     {
    657         tr_err( "failed to get default route (BSD)" );
    658         return 1;
    659     }
    660 
    661     len = parseroutes( buf, len, addr );
    662     free( buf );
    663 
    664     return len;
    665 }
    666 
    667 #ifndef SA_SIZE
    668 #define ROUNDUP( a, size ) \
    669     ( ( (a) & ( (size) - 1 ) ) ? ( 1 + ( (a) | ( (size) - 1 ) ) ) : (a) )
    670 #define SA_SIZE( sap ) \
    671     ( sap->sa_len ? ROUNDUP( (sap)->sa_len, sizeof( u_long ) ) : \
    672                     sizeof( u_long ) )
    673 #endif /* !SA_SIZE */
    674 #define NEXT_SA( sap ) \
    675     (struct sockaddr *) ( (caddr_t) (sap) + ( SA_SIZE( (sap) ) ) )
    676 
    677 static uint8_t *
    678 getroute( int * buflen )
    679 {
    680     int     mib[6];
    681     size_t  len;
    682     uint8_t * buf;
    683 
    684     mib[0] = CTL_NET;
    685     mib[1] = PF_ROUTE;
    686     mib[2] = 0;
    687     mib[3] = AF_INET;
    688     mib[4] = NET_RT_FLAGS;
    689     mib[5] = RTF_GATEWAY;
    690 
    691     if( sysctl( mib, 6, NULL, &len, NULL, 0 ) )
    692     {
    693         if( ENOENT != errno )
    694         {
    695             tr_err( "sysctl net.route.0.inet.flags.gateway failed (%s)",
    696                     strerror( sockerrno ) );
    697         }
    698         *buflen = 0;
    699         return NULL;
    700     }
    701 
    702     buf = malloc( len );
    703     if( NULL == buf )
    704     {
    705         *buflen = 0;
    706         return NULL;
    707     }
    708 
    709     if( sysctl( mib, 6, buf, &len, NULL, 0 ) )
    710     {
    711         tr_err( "sysctl net.route.0.inet.flags.gateway failed (%s)",
    712                 strerror( sockerrno ) );
    713         free( buf );
    714         *buflen = 0;
    715         return NULL;
    716     }
    717 
    718     *buflen = len;
    719 
    720     return buf;
    721 }
    722 
    723 static int
    724 parseroutes( uint8_t * buf, int len, struct in_addr * addr )
    725 {
    726     uint8_t            * end;
    727     struct rt_msghdr   * rtm;
    728     struct sockaddr    * sa;
    729     struct sockaddr_in * sin;
    730     int                  ii;
    731     struct in_addr       dest, gw;
    732 
    733     end = buf + len;
    734     while( end > buf + sizeof( *rtm ) )
    735     {
    736         rtm = (struct rt_msghdr *) buf;
    737         buf += rtm->rtm_msglen;
    738         if( end >= buf )
    739         {
    740             dest.s_addr = INADDR_NONE;
    741             gw.s_addr   = INADDR_NONE;
    742             sa = (struct sockaddr *) ( rtm + 1 );
    743 
    744             for( ii = 0; ii < RTAX_MAX && (uint8_t *) sa < buf; ii++ )
    745             {
    746                 if( buf < (uint8_t *) NEXT_SA( sa ) )
    747                 {
    748                     break;
    749                 }
    750 
    751                 if( rtm->rtm_addrs & ( 1 << ii ) )
    752                 {
    753                     if( AF_INET == sa->sa_family )
    754                     {
    755                         sin = (struct sockaddr_in *) sa;
    756                         switch( ii )
    757                         {
    758                             case RTAX_DST:
    759                                 dest = sin->sin_addr;
    760                                 break;
    761                             case RTAX_GATEWAY:
    762                                 gw = sin->sin_addr;
    763                                 break;
    764                         }
    765                     }
    766                     sa = NEXT_SA( sa );
    767                 }
    768             }
    769 
    770             if( INADDR_ANY == dest.s_addr && INADDR_NONE != gw.s_addr )
    771             {
    772                 *addr = gw;
    773                 return 0;
    774             }
    775         }
    776     }
    777 
    778     return 1;
    779 }
    780 
    781 #elif defined( linux ) || defined( __linux ) || defined( __linux__ )
    782 
    783 #include <linux/types.h>
    784 #include <linux/netlink.h>
    785 #include <linux/rtnetlink.h>
    786 
    787 #define SEQNUM 195909
    788 
    789 static int
    790 getsock( void );
    791 static uint8_t *
    792 getroute( int fd, unsigned int * buflen );
    793 static int
    794 parseroutes( uint8_t * buf, unsigned int len, struct in_addr * addr );
    795 
    796 int
    797 tr_getDefaultRoute( struct in_addr * addr )
    798 {
    799     int fd, ret;
    800     unsigned int len;
    801     uint8_t * buf;
    802 
    803     ret = 1;
    804     fd = getsock();
    805     if( 0 <= fd )
    806     {
    807         while( ret )
    808         {
    809             buf = getroute( fd, &len );
    810             if( NULL == buf )
    811             {
    812                 break;
    813             }
    814             ret = parseroutes( buf, len, addr );
    815             free( buf );
    816         }
    817         close( fd );
    818     }
    819 
    820     if( ret )
    821     {
    822         tr_err( "failed to get default route (Linux)" );
    823     }
    824 
    825     return ret;
    826 }
    827 
    828 static int
    829 getsock( void )
    830 {
    831     int fd, flags;
    832     struct
    833     {
    834         struct nlmsghdr nlh;
    835         struct rtgenmsg rtg;
    836     } req;
    837     struct sockaddr_nl snl;
    838 
    839     fd = socket( PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE );
    840     if( 0 > fd )
    841     {
    842         tr_err( "failed to create routing socket (%s)", strerror( sockerrno ) );
    843         return -1;
    844     }
    845 
    846     flags = fcntl( fd, F_GETFL );
    847     if( 0 > flags || 0 > fcntl( fd, F_SETFL, O_NONBLOCK | flags ) )
    848     {
    849         tr_err( "failed to set socket nonblocking (%s)", strerror( sockerrno ) );
    850         close( fd );
    851         return -1;
    852     }
    853 
    854     bzero( &snl, sizeof( snl ) );
    855     snl.nl_family = AF_NETLINK;
    856 
    857     bzero( &req, sizeof( req ) );
    858     req.nlh.nlmsg_len = NLMSG_LENGTH( sizeof( req.rtg ) );
    859     req.nlh.nlmsg_type = RTM_GETROUTE;
    860     req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
    861     req.nlh.nlmsg_seq = SEQNUM;
    862     req.nlh.nlmsg_pid = 0;
    863     req.rtg.rtgen_family = AF_INET;
    864 
    865     if( 0 > sendto( fd, &req, sizeof( req ), 0,
    866                     (struct sockaddr *) &snl, sizeof( snl ) ) )
    867     {
    868         tr_err( "failed to write to routing socket (%s)", strerror( sockerrno ) );
    869         close( fd );
    870         return -1;
    871     }
    872 
    873     return fd;
    874 }
    875 
    876 static uint8_t *
    877 getroute( int fd, unsigned int * buflen )
    878 {
    879     void             * buf;
    880     unsigned int       len;
    881     ssize_t            res;
    882     struct sockaddr_nl snl;
    883     socklen_t          slen;
    884 
    885     len = 8192;
    886     buf = calloc( 1, len );
    887     if( NULL == buf )
    888     {
    889         *buflen = 0;
    890         return NULL;
    891     }
    892 
    893     for( ;; )
    894     {
    895         bzero( &snl, sizeof( snl ) );
    896         slen = sizeof( snl );
    897         res = recvfrom( fd, buf, len, 0, (struct sockaddr *) &snl, &slen );
    898         if( 0 > res )
    899         {
    900             if( EAGAIN != sockerrno )
    901             {
    902                 tr_err( "failed to read from routing socket (%s)",
    903                         strerror( sockerrno ) );
    904             }
    905             free( buf );
    906             *buflen = 0;
    907             return NULL;
    908         }
    909         if( slen < sizeof( snl ) || AF_NETLINK != snl.nl_family )
    910         {
    911             tr_err( "bad address" );
    912             free( buf );
    913             *buflen = 0;
    914             return NULL;
    915         }
    916 
    917         if( 0 == snl.nl_pid )
    918         {
    919             break;
    920         }
    921     }
    922 
    923     *buflen = res;
    924 
    925     return buf;
    926 }
    927 
    928 static int
    929 parseroutes( uint8_t * buf, unsigned int len, struct in_addr * addr )
    930 {
    931     struct nlmsghdr * nlm;
    932     struct nlmsgerr * nle;
    933     struct rtmsg    * rtm;
    934     struct rtattr   * rta;
    935     int               rtalen;
    936     struct in_addr    gw, dst;
    937 
    938     nlm = ( struct nlmsghdr * ) buf;
    939     while( NLMSG_OK( nlm, len ) )
    940     {
    941         gw.s_addr = INADDR_ANY;
    942         dst.s_addr = INADDR_ANY;
    943         if( NLMSG_ERROR == nlm->nlmsg_type )
    944         {
    945             nle = (struct nlmsgerr *) NLMSG_DATA( nlm );
    946             if( NLMSG_LENGTH( NLMSG_ALIGN( sizeof( struct nlmsgerr ) ) ) >
    947                 nlm->nlmsg_len )
    948             {
    949                 tr_err( "truncated netlink error" );
    950             }
    951             else
    952             {
    953                 tr_err( "netlink error (%s)", strerror( nle->error ) );
    954             }
    955             return 1;
    956         }
    957         else if( RTM_NEWROUTE == nlm->nlmsg_type && SEQNUM == nlm->nlmsg_seq &&
    958                  getpid() == (pid_t) nlm->nlmsg_pid &&
    959                  NLMSG_LENGTH( sizeof( struct rtmsg ) ) <= nlm->nlmsg_len )
    960         {
    961             rtm = NLMSG_DATA( nlm );
    962             rta = RTM_RTA( rtm );
    963             rtalen = RTM_PAYLOAD( nlm );
    964 
    965             while( RTA_OK( rta, rtalen ) )
    966             {
    967                 if( sizeof( struct in_addr ) <= RTA_PAYLOAD( rta ) )
    968                 {
    969                     switch( rta->rta_type )
    970                     {
    971                         case RTA_GATEWAY:
    972                             memcpy( &gw, RTA_DATA( rta ), sizeof( gw ) );
    973                             break;
    974                         case RTA_DST:
    975                             memcpy( &dst, RTA_DATA( rta ), sizeof( dst ) );
    976                             break;
    977                     }
    978                 }
    979                 rta = RTA_NEXT( rta, rtalen );
    980             }
    981         }
    982 
    983         if( INADDR_NONE != gw.s_addr && INADDR_ANY != gw.s_addr &&
    984             INADDR_ANY == dst.s_addr )
    985         {
    986             *addr = gw;
    987             return 0;
    988         }
    989 
    990         nlm = NLMSG_NEXT( nlm, len );
    991     }
    992 
    993     return 1;
    994 }
    995 
    996 #else /* not BSD or Linux */
    997 
    998 int
    999 tr_getDefaultRoute( struct in_addr * addr UNUSED )
    1000 {
    1001     tr_inf( "don't know how to get default route on this platform" );
    1002     return 1;
    1003 }
    1004 
    1005 #endif
Note: See TracChangeset for help on using the changeset viewer.