diff options
Diffstat (limited to 'sys/netinet/sctp_asconf.c')
-rw-r--r-- | sys/netinet/sctp_asconf.c | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c index d4f088b..5eaa7cd 100644 --- a/sys/netinet/sctp_asconf.c +++ b/sys/netinet/sctp_asconf.c @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$"); #include <netinet/sctp_header.h> #include <netinet/sctputil.h> #include <netinet/sctp_output.h> -#include <netinet/sctp_bsd_addr.h> #include <netinet/sctp_asconf.h> /* @@ -1054,6 +1053,7 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, uint16_t type /* take the entry off the appropriate list */ sctp_asconf_addr_mgmt_ack(stcb, aa->ifa, type, 1); /* free the entry */ + sctp_free_ifa(aa->ifa); SCTP_FREE(aa); return (-1); } @@ -1074,6 +1074,7 @@ sctp_asconf_queue_add(struct sctp_tcb *stcb, struct sctp_ifa *ifa, uint16_t type /* top level elements are "networked" during send */ aa->ap.aph.ph.param_type = type; aa->ifa = ifa; + atomic_add_int(&ifa->refcount, 1); /* correlation_id filled in during send routine later... */ if (ifa->address.sa.sa_family == AF_INET6) { /* IPv6 address */ @@ -1150,6 +1151,7 @@ static uint32_t sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa, uint16_t type) { + struct sctp_ifa *ifa; struct sctp_asconf_addr *aa, *aa_next; uint32_t vrf_id; @@ -1178,6 +1180,7 @@ sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa, /* delete the existing entry in the queue */ TAILQ_REMOVE(&stcb->asoc.asconf_queue, aa, next); /* free the entry */ + sctp_free_ifa(aa->ifa); SCTP_FREE(aa); return (-1); } else if (type == SCTP_DEL_IP_ADDRESS && @@ -1189,11 +1192,22 @@ sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa, /* take the entry off the appropriate list */ sctp_asconf_addr_mgmt_ack(stcb, aa->ifa, type, 1); /* free the entry */ + sctp_free_ifa(aa->ifa); SCTP_FREE(aa); return (-1); } } /* for each aa */ + if (stcb) { + vrf_id = stcb->asoc.vrf_id; + } else { + vrf_id = SCTP_DEFAULT_VRFID; + } + ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0); + if (ifa == NULL) { + /* Invalid address */ + return (-1); + } /* adding new request to the queue */ SCTP_MALLOC(aa, struct sctp_asconf_addr *, sizeof(*aa), "AsconfAddr"); if (aa == NULL) { @@ -1207,9 +1221,9 @@ sctp_asconf_queue_add_sa(struct sctp_tcb *stcb, struct sockaddr *sa, } /* fill in asconf address parameter fields */ /* top level elements are "networked" during send */ - vrf_id = SCTP_DEFAULT_VRFID; aa->ap.aph.ph.param_type = type; - aa->ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0); + aa->ifa = ifa; + atomic_add_int(&ifa->refcount, 1); /* correlation_id filled in during send routine later... */ if (sa->sa_family == AF_INET6) { /* IPv6 address */ @@ -1372,6 +1386,7 @@ sctp_asconf_process_param_ack(struct sctp_tcb *stcb, /* remove the param and free it */ TAILQ_REMOVE(&stcb->asoc.asconf_queue, aparam, next); + sctp_free_ifa(aparam->ifa); SCTP_FREE(aparam); } @@ -2413,7 +2428,12 @@ sctp_process_initack_addresses(struct sctp_tcb *stcb, struct mbuf *m, } /* see if this address really (still) exists */ - vrf_id = SCTP_DEFAULT_VRFID; + if (stcb) { + vrf_id = stcb->asoc.vrf_id; + } else { + vrf_id = SCTP_DEFAULT_VRFID; + } + sctp_ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0); if (sctp_ifa == NULL) { /* address doesn't exist anymore */ @@ -2626,7 +2646,11 @@ sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset, struct sctp_ifa *sctp_ifa; uint32_t vrf_id; - vrf_id = SCTP_DEFAULT_VRFID; + if (stcb) { + vrf_id = stcb->asoc.vrf_id; + } else { + vrf_id = SCTP_DEFAULT_VRFID; + } vrf = sctp_find_vrf(vrf_id); if (vrf == NULL) { return; |