From ee795f10b4285ba74eb257f6af5754dd125e68eb Mon Sep 17 00:00:00 2001 From: Santiago Carot-Nemesio Date: Sun, 11 Oct 2020 17:44:27 +0200 Subject: [PATCH] Provide destroy function for registered addresses This patch tries to fix the problem of usrsctp calling callbacks even after the usrsctp_close function is invoked. Usrsctp seems to keep the asociation around until the teardown procedure is completed. The problem is that sometimes it is not possible to complete the shutdown procedure if the lower transport is gone like SCTP running on top of DTLS. In such case, callbacks triggered from usrsctp are providing an pointer address to an applications which could have been deallocated. To let applications know when they can safetely deallocate memory registered with an association, we are storing a destroy function which will be used for usrsctp to notify applications when the association is gone. Related issues: https://github.com/sctplab/usrsctp/issues/405 https://github.com/sctplab/usrsctp/issues/147 --- usrsctplib/netinet/sctp_pcb.c | 17 +++++++++++++++++ usrsctplib/netinet/sctp_pcb.h | 8 ++++++++ usrsctplib/user_socket.c | 13 ++++++++++--- usrsctplib/usrsctp.h | 3 +++ 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/usrsctplib/netinet/sctp_pcb.c b/usrsctplib/netinet/sctp_pcb.c index 89a66bce8..78cac42aa 100755 --- a/usrsctplib/netinet/sctp_pcb.c +++ b/usrsctplib/netinet/sctp_pcb.c @@ -334,6 +334,13 @@ sctp_free_ifa(struct sctp_ifa *sctp_ifap) if (sctp_ifap->ifn_p) { sctp_free_ifn(sctp_ifap->ifn_p); } + if (sctp_ifap->destroy_address) { + /* sctp_ifap->address is struct sockaddr_conn */ + if (sctp_ifap->address.sconn.sconn_addr) { + sctp_ifap->destroy_address (sctp_ifap->address.sconn.sconn_addr); + } + sctp_ifap->address.sconn.sconn_addr = NULL; + } SCTP_FREE(sctp_ifap, SCTP_M_IFA); atomic_subtract_int(&SCTP_BASE_INFO(ipi_count_ifas), 1); } @@ -535,6 +542,15 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index, uint32_t ifn_type, const char *if_name, void *ifa, struct sockaddr *addr, uint32_t ifa_flags, int dynamic_add) +{ + return sctp_add_addr_to_vrf_full (vrf_id, ifn, ifn_index, ifn_type, if_name, ifa, addr, ifa_flags, dynamic_add, NULL); +} + +struct sctp_ifa * +sctp_add_addr_to_vrf_full(uint32_t vrf_id, void *ifn, uint32_t ifn_index, + uint32_t ifn_type, const char *if_name, void *ifa, + struct sockaddr *addr, uint32_t ifa_flags, + int dynamic_add, void (*destroy)(void *)) { struct sctp_vrf *vrf; struct sctp_ifn *sctp_ifnp, *new_sctp_ifnp; @@ -690,6 +706,7 @@ sctp_add_addr_to_vrf(uint32_t vrf_id, void *ifn, uint32_t ifn_index, #endif sctp_ifap->localifa_flags = SCTP_ADDR_VALID | SCTP_ADDR_DEFER_USE; sctp_ifap->flags = ifa_flags; + sctp_ifap->destroy_address = destroy; /* Set scope */ switch (sctp_ifap->address.sa.sa_family) { #ifdef INET diff --git a/usrsctplib/netinet/sctp_pcb.h b/usrsctplib/netinet/sctp_pcb.h index 0382430d2..7549c0ca7 100755 --- a/usrsctplib/netinet/sctp_pcb.h +++ b/usrsctplib/netinet/sctp_pcb.h @@ -111,6 +111,7 @@ struct sctp_ifa { * appropriate locks. This is for V6. */ union sctp_sockstore address; + void (*destroy_address)(void *); uint32_t refcount; /* number of folks referring to this */ uint32_t flags; uint32_t localifa_flags; @@ -708,6 +709,13 @@ sctp_add_addr_to_vrf(uint32_t vrfid, void *ifa, struct sockaddr *addr, uint32_t ifa_flags, int dynamic_add); +struct sctp_ifa * +sctp_add_addr_to_vrf_full(uint32_t vrfid, + void *ifn, uint32_t ifn_index, uint32_t ifn_type, + const char *if_name, + void *ifa, struct sockaddr *addr, uint32_t ifa_flags, + int dynamic_add, void (*destroy)(void *)); + void sctp_update_ifn_mtu(uint32_t ifn_index, uint32_t mtu); void sctp_free_ifn(struct sctp_ifn *sctp_ifnp); diff --git a/usrsctplib/user_socket.c b/usrsctplib/user_socket.c index 74c7939d5..0eb111779 100755 --- a/usrsctplib/user_socket.c +++ b/usrsctplib/user_socket.c @@ -3139,7 +3139,7 @@ void sctp_userspace_ip6_output(int *result, struct mbuf *o_pak, #endif void -usrsctp_register_address(void *addr) +usrsctp_register_address_full(void *addr, void (*destroy)(void *)) { struct sockaddr_conn sconn; @@ -3150,7 +3150,7 @@ usrsctp_register_address(void *addr) #endif sconn.sconn_port = 0; sconn.sconn_addr = addr; - sctp_add_addr_to_vrf(SCTP_DEFAULT_VRFID, + sctp_add_addr_to_vrf_full(SCTP_DEFAULT_VRFID, NULL, 0xffffffff, 0, @@ -3158,7 +3158,14 @@ usrsctp_register_address(void *addr) NULL, (struct sockaddr *)&sconn, 0, - 0); + 0, + destroy); +} + +void +usrsctp_register_address(void *addr) +{ + usrsctp_register_address_full (addr, NULL); } void diff --git a/usrsctplib/usrsctp.h b/usrsctplib/usrsctp.h index b7192904e..38b8aa1a0 100644 --- a/usrsctplib/usrsctp.h +++ b/usrsctplib/usrsctp.h @@ -1027,6 +1027,9 @@ usrsctp_get_non_blocking(struct socket *); void usrsctp_register_address(void *); +void +usrsctp_register_address_full(void *, void (*)(void *)); + void usrsctp_deregister_address(void *);