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

housekeeping. revert r3984 at tiennou's request

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/natpmp.c

    r3984 r4001  
    2929#include <time.h>
    3030
    31 #include <unistd.h> /* close */
    32 #include <fcntl.h> /* fcntl */
    33 
    3431#ifdef __BEOS__
    3532    #include <netdb.h>
     
    4138#include "natpmp.h"
    4239#include "net.h"
     40#include "platform.h" /* tr_getDefaultRoute() */
    4341#include "utils.h"
    4442
     
    6664#define PMP_FROMBUF16( buf )    ( htons( *( (uint16_t *) (buf) ) ) )
    6765#define PMP_FROMBUF32( buf )    ( htonl( *( (uint32_t *) (buf) ) ) )
    68 
    69 static int tr_getDefaultRoute( struct in_addr * addr );
    7066
    7167typedef struct tr_natpmp_uptime_s
     
    826822    return TR_NET_OK;
    827823}
    828 
    829 /***
    830 ****  tr_getDefaultRoute()
    831 ***/
    832 
    833 #ifdef BSD
    834 
    835 #include <sys/types.h>
    836 #include <sys/socket.h>
    837 #include <netinet/in.h>
    838 #include <arpa/inet.h>
    839 #include <netinet/in.h> /* struct in_addr */
    840 #include <sys/sysctl.h>
    841 #include <net/route.h>
    842 
    843 static uint8_t *
    844 getroute( int * buflen );
    845 static int
    846 parseroutes( uint8_t * buf, int len, struct in_addr * addr );
    847 
    848 static int
    849 tr_getDefaultRoute( struct in_addr * addr )
    850 {
    851     uint8_t * buf;
    852     int len;
    853 
    854     buf = getroute( &len );
    855     if( NULL == buf )
    856     {
    857         tr_err( "failed to get default route (BSD)" );
    858         return 1;
    859     }
    860 
    861     len = parseroutes( buf, len, addr );
    862     free( buf );
    863 
    864     return len;
    865 }
    866 
    867 #ifndef SA_SIZE
    868 #define ROUNDUP( a, size ) \
    869     ( ( (a) & ( (size) - 1 ) ) ? ( 1 + ( (a) | ( (size) - 1 ) ) ) : (a) )
    870 #define SA_SIZE( sap ) \
    871     ( sap->sa_len ? ROUNDUP( (sap)->sa_len, sizeof( u_long ) ) : \
    872                     sizeof( u_long ) )
    873 #endif /* !SA_SIZE */
    874 #define NEXT_SA( sap ) \
    875     (struct sockaddr *) ( (caddr_t) (sap) + ( SA_SIZE( (sap) ) ) )
    876 
    877 static uint8_t *
    878 getroute( int * buflen )
    879 {
    880     int     mib[6];
    881     size_t  len;
    882     uint8_t * buf;
    883 
    884     mib[0] = CTL_NET;
    885     mib[1] = PF_ROUTE;
    886     mib[2] = 0;
    887     mib[3] = AF_INET;
    888     mib[4] = NET_RT_FLAGS;
    889     mib[5] = RTF_GATEWAY;
    890 
    891     if( sysctl( mib, 6, NULL, &len, NULL, 0 ) )
    892     {
    893         if( ENOENT != errno )
    894         {
    895             tr_err( "sysctl net.route.0.inet.flags.gateway failed (%s)",
    896                     strerror( sockerrno ) );
    897         }
    898         *buflen = 0;
    899         return NULL;
    900     }
    901 
    902     buf = malloc( len );
    903     if( NULL == buf )
    904     {
    905         *buflen = 0;
    906         return NULL;
    907     }
    908 
    909     if( sysctl( mib, 6, buf, &len, NULL, 0 ) )
    910     {
    911         tr_err( "sysctl net.route.0.inet.flags.gateway failed (%s)",
    912                 strerror( sockerrno ) );
    913         free( buf );
    914         *buflen = 0;
    915         return NULL;
    916     }
    917 
    918     *buflen = len;
    919 
    920     return buf;
    921 }
    922 
    923 static int
    924 parseroutes( uint8_t * buf, int len, struct in_addr * addr )
    925 {
    926     uint8_t            * end;
    927     struct rt_msghdr   * rtm;
    928     struct sockaddr    * sa;
    929     struct sockaddr_in * sin;
    930     int                  ii;
    931     struct in_addr       dest, gw;
    932 
    933     end = buf + len;
    934     while( end > buf + sizeof( *rtm ) )
    935     {
    936         rtm = (struct rt_msghdr *) buf;
    937         buf += rtm->rtm_msglen;
    938         if( end >= buf )
    939         {
    940             dest.s_addr = INADDR_NONE;
    941             gw.s_addr   = INADDR_NONE;
    942             sa = (struct sockaddr *) ( rtm + 1 );
    943 
    944             for( ii = 0; ii < RTAX_MAX && (uint8_t *) sa < buf; ii++ )
    945             {
    946                 if( buf < (uint8_t *) NEXT_SA( sa ) )
    947                 {
    948                     break;
    949                 }
    950 
    951                 if( rtm->rtm_addrs & ( 1 << ii ) )
    952                 {
    953                     if( AF_INET == sa->sa_family )
    954                     {
    955                         sin = (struct sockaddr_in *) sa;
    956                         switch( ii )
    957                         {
    958                             case RTAX_DST:
    959                                 dest = sin->sin_addr;
    960                                 break;
    961                             case RTAX_GATEWAY:
    962                                 gw = sin->sin_addr;
    963                                 break;
    964                         }
    965                     }
    966                     sa = NEXT_SA( sa );
    967                 }
    968             }
    969 
    970             if( INADDR_ANY == dest.s_addr && INADDR_NONE != gw.s_addr )
    971             {
    972                 *addr = gw;
    973                 return 0;
    974             }
    975         }
    976     }
    977 
    978     return 1;
    979 }
    980 
    981 #elif defined( linux ) || defined( __linux ) || defined( __linux__ )
    982 
    983 #include <linux/types.h>
    984 #include <linux/netlink.h>
    985 #include <linux/rtnetlink.h>
    986 
    987 #define SEQNUM 195909
    988 
    989 static int
    990 getsock( void );
    991 static uint8_t *
    992 getroute( int fd, unsigned int * buflen );
    993 static int
    994 parseroutes( uint8_t * buf, unsigned int len, struct in_addr * addr );
    995 
    996 int
    997 tr_getDefaultRoute( struct in_addr * addr )
    998 {
    999     int fd, ret;
    1000     unsigned int len;
    1001     uint8_t * buf;
    1002 
    1003     ret = 1;
    1004     fd = getsock();
    1005     if( 0 <= fd )
    1006     {
    1007         while( ret )
    1008         {
    1009             buf = getroute( fd, &len );
    1010             if( NULL == buf )
    1011             {
    1012                 break;
    1013             }
    1014             ret = parseroutes( buf, len, addr );
    1015             free( buf );
    1016         }
    1017         close( fd );
    1018     }
    1019 
    1020     if( ret )
    1021     {
    1022         tr_err( "failed to get default route (Linux)" );
    1023     }
    1024 
    1025     return ret;
    1026 }
    1027 
    1028 static int
    1029 getsock( void )
    1030 {
    1031     int fd, flags;
    1032     struct
    1033     {
    1034         struct nlmsghdr nlh;
    1035         struct rtgenmsg rtg;
    1036     } req;
    1037     struct sockaddr_nl snl;
    1038 
    1039     fd = socket( PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE );
    1040     if( 0 > fd )
    1041     {
    1042         tr_err( "failed to create routing socket (%s)", strerror( sockerrno ) );
    1043         return -1;
    1044     }
    1045 
    1046     flags = fcntl( fd, F_GETFL );
    1047     if( 0 > flags || 0 > fcntl( fd, F_SETFL, O_NONBLOCK | flags ) )
    1048     {
    1049         tr_err( "failed to set socket nonblocking (%s)", strerror( sockerrno ) );
    1050         close( fd );
    1051         return -1;
    1052     }
    1053 
    1054     bzero( &snl, sizeof( snl ) );
    1055     snl.nl_family = AF_NETLINK;
    1056 
    1057     bzero( &req, sizeof( req ) );
    1058     req.nlh.nlmsg_len = NLMSG_LENGTH( sizeof( req.rtg ) );
    1059     req.nlh.nlmsg_type = RTM_GETROUTE;
    1060     req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
    1061     req.nlh.nlmsg_seq = SEQNUM;
    1062     req.nlh.nlmsg_pid = 0;
    1063     req.rtg.rtgen_family = AF_INET;
    1064 
    1065     if( 0 > sendto( fd, &req, sizeof( req ), 0,
    1066                     (struct sockaddr *) &snl, sizeof( snl ) ) )
    1067     {
    1068         tr_err( "failed to write to routing socket (%s)", strerror( sockerrno ) );
    1069         close( fd );
    1070         return -1;
    1071     }
    1072 
    1073     return fd;
    1074 }
    1075 
    1076 static uint8_t *
    1077 getroute( int fd, unsigned int * buflen )
    1078 {
    1079     void             * buf;
    1080     unsigned int       len;
    1081     ssize_t            res;
    1082     struct sockaddr_nl snl;
    1083     socklen_t          slen;
    1084 
    1085     len = 8192;
    1086     buf = calloc( 1, len );
    1087     if( NULL == buf )
    1088     {
    1089         *buflen = 0;
    1090         return NULL;
    1091     }
    1092 
    1093     for( ;; )
    1094     {
    1095         bzero( &snl, sizeof( snl ) );
    1096         slen = sizeof( snl );
    1097         res = recvfrom( fd, buf, len, 0, (struct sockaddr *) &snl, &slen );
    1098         if( 0 > res )
    1099         {
    1100             if( EAGAIN != sockerrno )
    1101             {
    1102                 tr_err( "failed to read from routing socket (%s)",
    1103                         strerror( sockerrno ) );
    1104             }
    1105             free( buf );
    1106             *buflen = 0;
    1107             return NULL;
    1108         }
    1109         if( slen < sizeof( snl ) || AF_NETLINK != snl.nl_family )
    1110         {
    1111             tr_err( "bad address" );
    1112             free( buf );
    1113             *buflen = 0;
    1114             return NULL;
    1115         }
    1116 
    1117         if( 0 == snl.nl_pid )
    1118         {
    1119             break;
    1120         }
    1121     }
    1122 
    1123     *buflen = res;
    1124 
    1125     return buf;
    1126 }
    1127 
    1128 static int
    1129 parseroutes( uint8_t * buf, unsigned int len, struct in_addr * addr )
    1130 {
    1131     struct nlmsghdr * nlm;
    1132     struct nlmsgerr * nle;
    1133     struct rtmsg    * rtm;
    1134     struct rtattr   * rta;
    1135     int               rtalen;
    1136     struct in_addr    gw, dst;
    1137 
    1138     nlm = ( struct nlmsghdr * ) buf;
    1139     while( NLMSG_OK( nlm, len ) )
    1140     {
    1141         gw.s_addr = INADDR_ANY;
    1142         dst.s_addr = INADDR_ANY;
    1143         if( NLMSG_ERROR == nlm->nlmsg_type )
    1144         {
    1145             nle = (struct nlmsgerr *) NLMSG_DATA( nlm );
    1146             if( NLMSG_LENGTH( NLMSG_ALIGN( sizeof( struct nlmsgerr ) ) ) >
    1147                 nlm->nlmsg_len )
    1148             {
    1149                 tr_err( "truncated netlink error" );
    1150             }
    1151             else
    1152             {
    1153                 tr_err( "netlink error (%s)", strerror( nle->error ) );
    1154             }
    1155             return 1;
    1156         }
    1157         else if( RTM_NEWROUTE == nlm->nlmsg_type && SEQNUM == nlm->nlmsg_seq &&
    1158                  getpid() == (pid_t) nlm->nlmsg_pid &&
    1159                  NLMSG_LENGTH( sizeof( struct rtmsg ) ) <= nlm->nlmsg_len )
    1160         {
    1161             rtm = NLMSG_DATA( nlm );
    1162             rta = RTM_RTA( rtm );
    1163             rtalen = RTM_PAYLOAD( nlm );
    1164 
    1165             while( RTA_OK( rta, rtalen ) )
    1166             {
    1167                 if( sizeof( struct in_addr ) <= RTA_PAYLOAD( rta ) )
    1168                 {
    1169                     switch( rta->rta_type )
    1170                     {
    1171                         case RTA_GATEWAY:
    1172                             memcpy( &gw, RTA_DATA( rta ), sizeof( gw ) );
    1173                             break;
    1174                         case RTA_DST:
    1175                             memcpy( &dst, RTA_DATA( rta ), sizeof( dst ) );
    1176                             break;
    1177                     }
    1178                 }
    1179                 rta = RTA_NEXT( rta, rtalen );
    1180             }
    1181         }
    1182 
    1183         if( INADDR_NONE != gw.s_addr && INADDR_ANY != gw.s_addr &&
    1184             INADDR_ANY == dst.s_addr )
    1185         {
    1186             *addr = gw;
    1187             return 0;
    1188         }
    1189 
    1190         nlm = NLMSG_NEXT( nlm, len );
    1191     }
    1192 
    1193     return 1;
    1194 }
    1195 
    1196 #else /* not BSD or Linux */
    1197 
    1198 int
    1199 tr_getDefaultRoute( struct in_addr * addr UNUSED )
    1200 {
    1201     tr_inf( "don't know how to get default route on this platform" );
    1202     return 1;
    1203 }
    1204 
    1205 #endif
Note: See TracChangeset for help on using the changeset viewer.