comparison libfdcore/sctp.c @ 1544:7bad8025e69d

merge
author Thomas Klausner <tk@giga.or.at>
date Mon, 25 May 2020 10:34:47 +0200
parents 9222d31123b1 3365e95bed57
children 566bb46cc73f
comparison
equal deleted inserted replaced
1543:9222d31123b1 1544:7bad8025e69d
56 /* Temper with the retransmission timers to try and improve disconnection detection response? Undef this to keep the defaults of SCTP stack */ 56 /* Temper with the retransmission timers to try and improve disconnection detection response? Undef this to keep the defaults of SCTP stack */
57 #ifndef USE_DEFAULT_SCTP_RTX_PARAMS /* make this a configuration option if useful */ 57 #ifndef USE_DEFAULT_SCTP_RTX_PARAMS /* make this a configuration option if useful */
58 #define ADJUST_RTX_PARAMS 58 #define ADJUST_RTX_PARAMS
59 #endif /* USE_DEFAULT_SCTP_RTX_PARAMS */ 59 #endif /* USE_DEFAULT_SCTP_RTX_PARAMS */
60 60
61
62 DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_array, sSA * saddrs, int saddrs_count)
63 {
64 union {
65 sSA *sa;
66 uint8_t *buf;
67 } ptr;
68 int i;
69 int salen;
70
71 FD_DUMP_HANDLE_OFFSET();
72
73 ptr.sa = saddrs;
74 for (i = 0; i < saddrs_count; i++) {
75 salen = sSAlen(ptr.sa);
76 if (salen == 0) {
77 LOG_E("fd_sa_dump_array: Unknown sockaddr family");
78 break;
79 }
80 if (i > 0) {
81 CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " "), return NULL);
82 }
83 CHECK_MALLOC_DO( fd_sa_dump( FD_DUMP_STD_PARAMS, ptr.sa, NI_NUMERICHOST | NI_NUMERICSERV), return NULL);
84 ptr.buf += salen;
85 }
86 return *buf;
87 }
88
61 /* Pre-binding socket options -- # streams read in config */ 89 /* Pre-binding socket options -- # streams read in config */
62 static int fd_setsockopt_prebind(int sk) 90 static int fd_setsockopt_prebind(int sk)
63 { 91 {
64 socklen_t sz; 92 socklen_t sz;
65 93
812 if (!count) { 840 if (!count) {
813 /* None of the addresses in the list came from configuration, we bind to default */ 841 /* None of the addresses in the list came from configuration, we bind to default */
814 bind_default = 1; 842 bind_default = 1;
815 goto redo; 843 goto redo;
816 } 844 }
817 845
818 #if 0 846 /* Debug: show bound addresses */
819 union { 847 {
820 sSA *sa; 848 char * buf = NULL;
821 uint8_t *buf; 849 size_t len = 0;
822 } ptr; 850 CHECK_MALLOC_DO( fd_sa_dump_array( &buf, &len, 0, sar, count), );
823 int i; 851 LOG_D("SCTP server binding local addresses: %s", buf);
824 ptr.sa = sar; 852 free(buf);
825 fd_log_debug("Calling sctp_bindx with the following address array:"); 853 }
826 for (i = 0; i < count; i++) { 854
827 TRACE_sSA(FD_LOG_DEBUG, FULL, " - ", ptr.sa, NI_NUMERICHOST | NI_NUMERICSERV, "" );
828 ptr.buf += (ptr.sa->sa_family == AF_INET) ? sizeof(sSA4) : sizeof(sSA6) ;
829 }
830 #endif
831
832 /* Bind to this array */ 855 /* Bind to this array */
833 CHECK_SYS( sctp_bindx(*sock, sar, count, SCTP_BINDX_ADD_ADDR) ); 856 CHECK_SYS( sctp_bindx(*sock, sar, count, SCTP_BINDX_ADD_ADDR) );
834 857
835 /* We don't need sar anymore */ 858 /* We don't need sar anymore */
836 free(sar); 859 free(sar);
838 861
839 /* Now, the server is bound, set remaining sockopt */ 862 /* Now, the server is bound, set remaining sockopt */
840 CHECK_FCT( fd_setsockopt_postbind(*sock, bind_default) ); 863 CHECK_FCT( fd_setsockopt_postbind(*sock, bind_default) );
841 864
842 /* Debug: show all local listening addresses */ 865 /* Debug: show all local listening addresses */
843 #if 0 866 {
844 sSA *sar; 867 sSA *sar = NULL;
845 union { 868 int sz = 0;
846 sSA *sa; 869 char * buf = NULL;
847 uint8_t *buf; 870 size_t len = 0;
848 } ptr; 871
849 int sz;
850
851 CHECK_SYS( sz = sctp_getladdrs(*sock, 0, &sar) ); 872 CHECK_SYS( sz = sctp_getladdrs(*sock, 0, &sar) );
852 873
853 fd_log_debug("SCTP server bound on :"); 874 CHECK_MALLOC_DO( fd_sa_dump_array( &buf, &len, 0, sar, sz), );
854 for (ptr.sa = sar; sz-- > 0; ptr.buf += (ptr.sa->sa_family == AF_INET) ? sizeof(sSA4) : sizeof(sSA6)) { 875 LOG_D("SCTP server locally bound addresses: %s", buf);
855 TRACE_sSA(FD_LOG_DEBUG, FULL, " - ", ptr.sa, NI_NUMERICHOST | NI_NUMERICSERV, "" );
856 }
857 sctp_freeladdrs(sar); 876 sctp_freeladdrs(sar);
858 #endif 877 free(buf);
878 }
859 879
860 return 0; 880 return 0;
861 } 881 }
862 882
863 /* Allow clients connections on server sockets */ 883 /* Allow clients connections on server sockets */
867 CHECK_SYS( listen(sock, 5) ); 887 CHECK_SYS( listen(sock, 5) );
868 return 0; 888 return 0;
869 } 889 }
870 890
871 /* Create a client socket and connect to remote server */ 891 /* Create a client socket and connect to remote server */
872 int fd_sctp_client( int *sock, int no_ip6, uint16_t port, struct fd_list * list ) 892 int fd_sctp_client( int *sock, int no_ip6, uint16_t port, struct fd_list * list, struct fd_list * src_list )
873 { 893 {
874 int family; 894 int family;
875 union { 895 union {
876 uint8_t *buf; 896 uint8_t *buf;
877 sSA *sa; 897 sSA *sa;
878 } sar; 898 } sar;
879 size_t size = 0; 899 size_t size = 0;
880 int count = 0; 900 int count = 0;
881 int ret; 901 int ret;
902 int bind_default = 1; /* enable ASCONF in postbind */
882 903
883 sar.buf = NULL; 904 sar.buf = NULL;
884 905
885 TRACE_ENTRY("%p %i %hu %p", sock, no_ip6, port, list); 906 TRACE_ENTRY("%p %i %hu %p %p", sock, no_ip6, port, list, src_list);
886 CHECK_PARAMS( sock && list && (!FD_IS_LIST_EMPTY(list)) ); 907 CHECK_PARAMS( sock && list && (!FD_IS_LIST_EMPTY(list)) );
908 CHECK_PARAMS( !src_list || (src_list && (!FD_IS_LIST_EMPTY(src_list))) );
887 909
888 if (no_ip6) { 910 if (no_ip6) {
889 family = AF_INET; 911 family = AF_INET;
890 } else { 912 } else {
891 family = AF_INET6; 913 family = AF_INET6;
897 /* Cleanup if we are cancelled */ 919 /* Cleanup if we are cancelled */
898 pthread_cleanup_push(fd_cleanup_socket, sock); 920 pthread_cleanup_push(fd_cleanup_socket, sock);
899 921
900 /* Set the socket options */ 922 /* Set the socket options */
901 CHECK_FCT_DO( ret = fd_setsockopt_prebind(*sock), goto out ); 923 CHECK_FCT_DO( ret = fd_setsockopt_prebind(*sock), goto out );
902 924
925 /* Bind to explicit source addresses if requested */
926 if (src_list && !FD_IS_LIST_EMPTY(src_list)) {
927 sSA * bindsar = NULL; /* array of addresses */
928 size_t sz = 0; /* size of the array */
929 int sarcount = 0; /* number of sock addr in the array */
930
931 /* Create the array of configured addresses */
932 CHECK_FCT_DO( ret = add_addresses_from_list_mask((void *)&bindsar, &sz, &sarcount, family, 0, src_list, EP_FL_CONF, EP_FL_CONF), goto out );
933
934 if (sarcount) {
935 char * buf = NULL;
936 size_t len = 0;
937 CHECK_MALLOC_DO( fd_sa_dump_array( &buf, &len, 0, bindsar, sarcount), goto out );
938 LOG_A("SCTP client binding local addresses: %s", buf);
939 free(buf);
940
941 CHECK_SYS_DO( ret = sctp_bindx(*sock, bindsar, sarcount, SCTP_BINDX_ADD_ADDR), goto out );
942 }
943
944 /* Disable ASCONF option in postbind */
945 bind_default = 0;
946
947 /* We don't need bindsar anymore */
948 free(bindsar);
949 }
950
903 /* Create the array of addresses, add first the configured addresses, then the discovered, then the other ones */ 951 /* Create the array of addresses, add first the configured addresses, then the discovered, then the other ones */
904 CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &size, &count, family, htons(port), list, EP_FL_CONF, EP_FL_CONF ), goto out ); 952 CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &size, &count, family, htons(port), list, EP_FL_CONF, EP_FL_CONF ), goto out );
905 CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &size, &count, family, htons(port), list, EP_FL_CONF | EP_FL_DISC, EP_FL_DISC ), goto out ); 953 CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &size, &count, family, htons(port), list, EP_FL_CONF | EP_FL_DISC, EP_FL_DISC ), goto out );
906 CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &size, &count, family, htons(port), list, EP_FL_CONF | EP_FL_DISC, 0 ), goto out ); 954 CHECK_FCT_DO( ret = add_addresses_from_list_mask(&sar.buf, &size, &count, family, htons(port), list, EP_FL_CONF | EP_FL_DISC, 0 ), goto out );
907 955
908 /* Try connecting */ 956 /* Try connecting */
909 LOG_A("Attempting SCTP connection (%d addresses attempted) ", count); 957 {
910 958 char * buf = NULL;
911 #if 0 959 size_t len = 0;
912 /* Dump the SAs */ 960 CHECK_MALLOC_DO( fd_sa_dump_array( &buf, &len, 0, sar.sa, count), goto out );
913 union { 961 LOG_A("SCTP client connecting to addresses: %s", buf);
914 uint8_t *buf; 962 free(buf);
915 sSA *sa; 963 }
916 sSA4 *sin; 964
917 sSA6 *sin6;
918 } ptr;
919 int i;
920 ptr.buf = sar.buf;
921 for (i=0; i< count; i++) {
922 TRACE_sSA(FD_LOG_DEBUG, FULL, " - ", ptr.sa, NI_NUMERICHOST | NI_NUMERICSERV, "" );
923 ptr.buf += (ptr.sa->sa_family == AF_INET) ? sizeof(sSA4) : sizeof(sSA6);
924 }
925 #endif
926
927 /* Bug in some Linux kernel, the sctp_connectx is not a cancellation point. To avoid blocking freeDiameter, we allow async cancel here */ 965 /* Bug in some Linux kernel, the sctp_connectx is not a cancellation point. To avoid blocking freeDiameter, we allow async cancel here */
928 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); 966 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
929 #ifdef SCTP_CONNECTX_4_ARGS 967 #ifdef SCTP_CONNECTX_4_ARGS
930 ret = sctp_connectx(*sock, sar.sa, count, NULL); 968 ret = sctp_connectx(*sock, sar.sa, count, NULL);
931 #else /* SCTP_CONNECTX_4_ARGS */ 969 #else /* SCTP_CONNECTX_4_ARGS */
942 } 980 }
943 981
944 free(sar.buf); sar.buf = NULL; 982 free(sar.buf); sar.buf = NULL;
945 983
946 /* Set the remaining sockopts */ 984 /* Set the remaining sockopts */
947 CHECK_FCT_DO( ret = fd_setsockopt_postbind(*sock, 1), 985 CHECK_FCT_DO( ret = fd_setsockopt_postbind(*sock, bind_default),
948 { 986 {
949 CHECK_SYS_DO( shutdown(*sock, SHUT_RDWR), /* continue */ ); 987 CHECK_SYS_DO( shutdown(*sock, SHUT_RDWR), /* continue */ );
950 } ); 988 } );
951 989
952 out: 990 out:
980 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %zd", sz, sizeof(status)); 1018 TRACE_DEBUG(INFO, "Invalid size of socket option: %d / %zd", sz, sizeof(status));
981 return ENOTSUP; 1019 return ENOTSUP;
982 } 1020 }
983 #if 0 1021 #if 0
984 char sa_buf[sSA_DUMP_STRLEN]; 1022 char sa_buf[sSA_DUMP_STRLEN];
985 fd_sa_sdump_numeric(sa_buf, &status.sstat_primary.spinfo_address); 1023 fd_sa_sdump_numeric(sa_buf, (sSA *)&status.sstat_primary.spinfo_address);
986 fd_log_debug( "SCTP_STATUS : sstat_state : %i" , status.sstat_state); 1024 fd_log_debug( "SCTP_STATUS : sstat_state : %i" , status.sstat_state);
987 fd_log_debug( " sstat_rwnd : %u" , status.sstat_rwnd); 1025 fd_log_debug( " sstat_rwnd : %u" , status.sstat_rwnd);
988 fd_log_debug( " sstat_unackdata : %hu", status.sstat_unackdata); 1026 fd_log_debug( " sstat_unackdata : %hu", status.sstat_unackdata);
989 fd_log_debug( " sstat_penddata : %hu", status.sstat_penddata); 1027 fd_log_debug( " sstat_penddata : %hu", status.sstat_penddata);
990 fd_log_debug( " sstat_instrms : %hu", status.sstat_instrms); 1028 fd_log_debug( " sstat_instrms : %hu", status.sstat_instrms);
1216 } 1254 }
1217 1255
1218 /* Handle the case where the data received is a notification */ 1256 /* Handle the case where the data received is a notification */
1219 if (mhdr.msg_flags & MSG_NOTIFICATION) { 1257 if (mhdr.msg_flags & MSG_NOTIFICATION) {
1220 union sctp_notification * notif = (union sctp_notification *) data; 1258 union sctp_notification * notif = (union sctp_notification *) data;
1259 char sa_buf[sSA_DUMP_STRLEN];
1221 1260
1222 TRACE_DEBUG(FULL, "Received %zdb data of notification on socket %d", datasize, conn->cc_socket); 1261 TRACE_DEBUG(FULL, "Received %zdb data of notification on socket %d", datasize, conn->cc_socket);
1223 1262
1224 switch (notif->sn_header.sn_type) { 1263 switch (notif->sn_header.sn_type) {
1225 1264
1233 *event = FDEVP_CNX_EP_CHANGE; 1272 *event = FDEVP_CNX_EP_CHANGE;
1234 break; 1273 break;
1235 1274
1236 case SCTP_PEER_ADDR_CHANGE: 1275 case SCTP_PEER_ADDR_CHANGE:
1237 TRACE_DEBUG(FULL, "Received SCTP_PEER_ADDR_CHANGE notification"); 1276 TRACE_DEBUG(FULL, "Received SCTP_PEER_ADDR_CHANGE notification");
1238 /* TRACE_sSA(FD_LOG_DEBUG, ANNOYING, " intf_change : ", &(notif->sn_paddr_change.spc_aaddr), NI_NUMERICHOST | NI_NUMERICSERV, "" ); */ 1277 fd_sa_sdump_numeric(sa_buf, (sSA *)&(notif->sn_paddr_change.spc_aaddr));
1278 TRACE_DEBUG(ANNOYING, " intf_change : %s", sa_buf);
1239 TRACE_DEBUG(ANNOYING, " state : %d", notif->sn_paddr_change.spc_state); 1279 TRACE_DEBUG(ANNOYING, " state : %d", notif->sn_paddr_change.spc_state);
1240 TRACE_DEBUG(ANNOYING, " error : %d", notif->sn_paddr_change.spc_error); 1280 TRACE_DEBUG(ANNOYING, " error : %d", notif->sn_paddr_change.spc_error);
1241 1281
1242 *event = FDEVP_CNX_EP_CHANGE; 1282 *event = FDEVP_CNX_EP_CHANGE;
1243 break; 1283 break;
"Welcome to our mercurial repository"