Changeset 3984
- Timestamp:
- Nov 26, 2007, 8:21:52 PM (13 years ago)
- Location:
- trunk/libtransmission
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/libtransmission/natpmp.c
r3775 r3984 29 29 #include <time.h> 30 30 31 #include <unistd.h> /* close */ 32 #include <fcntl.h> /* fcntl */ 33 31 34 #ifdef __BEOS__ 32 35 #include <netdb.h> … … 38 41 #include "natpmp.h" 39 42 #include "net.h" 40 #include "platform.h" /* tr_getDefaultRoute() */41 43 #include "utils.h" 42 44 … … 64 66 #define PMP_FROMBUF16( buf ) ( htons( *( (uint16_t *) (buf) ) ) ) 65 67 #define PMP_FROMBUF32( buf ) ( htonl( *( (uint32_t *) (buf) ) ) ) 68 69 static int tr_getDefaultRoute( struct in_addr * addr ); 66 70 67 71 typedef struct tr_natpmp_uptime_s … … 822 826 return TR_NET_OK; 823 827 } 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 -
trunk/libtransmission/platform.c
r3838 r3984 44 44 #include <sys/types.h> 45 45 #include <dirent.h> 46 #include <fcntl.h> 47 #include <unistd.h> /* getuid getpid close */ 46 #include <unistd.h> /* getuid getpid */ 48 47 49 48 #include "transmission.h" … … 626 625 return buf; 627 626 } 628 629 /***630 **** SOCKETS631 ***/632 633 #ifdef BSD634 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 int646 parseroutes( uint8_t * buf, int len, struct in_addr * addr );647 648 int649 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_SIZE668 #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 int724 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 195909788 789 static int790 getsock( void );791 static uint8_t *792 getroute( int fd, unsigned int * buflen );793 static int794 parseroutes( uint8_t * buf, unsigned int len, struct in_addr * addr );795 796 int797 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 int829 getsock( void )830 {831 int fd, flags;832 struct833 {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 int929 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 else952 {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 int999 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 -
trunk/libtransmission/platform.h
r3838 r3984 22 22 * DEALINGS IN THE SOFTWARE. 23 23 *****************************************************************************/ 24 24 25 #ifndef TR_PLATFORM_H 25 26 #define TR_PLATFORM_H … … 49 50 void tr_condWait ( tr_cond *, tr_lock * ); 50 51 51 struct in_addr; /* forward declaration to calm gcc down */52 int53 tr_getDefaultRoute( struct in_addr * addr );54 55 52 #endif
Note: See TracChangeset
for help on using the changeset viewer.