Mercurial > hg > freeDiameter
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; |