Ignore:
Timestamp:
Nov 27, 2007, 3:39:59 PM (13 years ago)
Author:
charles
Message:

housekeeping. revert r3984 at tiennou's request

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/platform.c

    r3984 r4001  
    4444#include <sys/types.h>
    4545#include <dirent.h>
    46 #include <unistd.h> /* getuid getpid */
     46#include <fcntl.h>
     47#include <unistd.h> /* getuid getpid close */
    4748
    4849#include "transmission.h"
     
    625626    return buf;
    626627}
     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
     643static uint8_t *
     644getroute( int * buflen );
     645static int
     646parseroutes( uint8_t * buf, int len, struct in_addr * addr );
     647
     648int
     649tr_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
     677static uint8_t *
     678getroute( 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
     723static int
     724parseroutes( 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
     789static int
     790getsock( void );
     791static uint8_t *
     792getroute( int fd, unsigned int * buflen );
     793static int
     794parseroutes( uint8_t * buf, unsigned int len, struct in_addr * addr );
     795
     796int
     797tr_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
     828static int
     829getsock( 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
     876static uint8_t *
     877getroute( 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
     928static int
     929parseroutes( 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
     998int
     999tr_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.