diff options
author | tuexen <tuexen@FreeBSD.org> | 2009-11-17 13:11:23 +0000 |
---|---|---|
committer | tuexen <tuexen@FreeBSD.org> | 2009-11-17 13:11:23 +0000 |
commit | ca50a585fce88097cae9f5c40c6222d40b0f3a18 (patch) | |
tree | 6d5eff54ac440aa5984dcee10bc8065542f34d88 /sys/netinet/sctp_asconf.c | |
parent | b4f7d47afa49deeb7727a9dee766b8a1344818e4 (diff) | |
download | FreeBSD-src-ca50a585fce88097cae9f5c40c6222d40b0f3a18.zip FreeBSD-src-ca50a585fce88097cae9f5c40c6222d40b0f3a18.tar.gz |
Do not start the iterator when there are no associations.
This fixes a bug found by Irene Ruengeler.
Approved by: rrs (mentor)
MFC after: 1 month
Diffstat (limited to 'sys/netinet/sctp_asconf.c')
-rw-r--r-- | sys/netinet/sctp_asconf.c | 74 |
1 files changed, 38 insertions, 36 deletions
diff --git a/sys/netinet/sctp_asconf.c b/sys/netinet/sctp_asconf.c index 404b5ad..9c46e79 100644 --- a/sys/netinet/sctp_asconf.c +++ b/sys/netinet/sctp_asconf.c @@ -3180,24 +3180,6 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa, ifa = NULL; } if (ifa != NULL) { - /* add this address */ - struct sctp_asconf_iterator *asc; - struct sctp_laddr *wi; - - SCTP_MALLOC(asc, struct sctp_asconf_iterator *, - sizeof(struct sctp_asconf_iterator), - SCTP_M_ASC_IT); - if (asc == NULL) { - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM); - return (ENOMEM); - } - wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), - struct sctp_laddr); - if (wi == NULL) { - SCTP_FREE(asc, SCTP_M_ASC_IT); - SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM); - return (ENOMEM); - } if (type == SCTP_ADD_IP_ADDRESS) { sctp_add_local_addr_ep(inp, ifa, type); } else if (type == SCTP_DEL_IP_ADDRESS) { @@ -3205,8 +3187,6 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa, if (inp->laddr_count < 2) { /* can't delete the last local address */ - SCTP_FREE(asc, SCTP_M_ASC_IT); - SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_laddr), wi); SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EINVAL); return (EINVAL); } @@ -3218,27 +3198,49 @@ sctp_addr_mgmt_ep_sa(struct sctp_inpcb *inp, struct sockaddr *sa, } } } - LIST_INIT(&asc->list_of_work); - asc->cnt = 1; - SCTP_INCR_LADDR_COUNT(); - wi->ifa = ifa; - wi->action = type; - atomic_add_int(&ifa->refcount, 1); - LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr); - (void)sctp_initiate_iterator(sctp_asconf_iterator_ep, - sctp_asconf_iterator_stcb, - sctp_asconf_iterator_ep_end, - SCTP_PCB_ANY_FLAGS, - SCTP_PCB_ANY_FEATURES, - SCTP_ASOC_ANY_STATE, - (void *)asc, 0, - sctp_asconf_iterator_end, inp, 0); + if (!LIST_EMPTY(&inp->sctp_asoc_list)) { + /* + * There is no need to start the iterator if the inp + * has no associations. + */ + struct sctp_asconf_iterator *asc; + struct sctp_laddr *wi; + + SCTP_MALLOC(asc, struct sctp_asconf_iterator *, + sizeof(struct sctp_asconf_iterator), + SCTP_M_ASC_IT); + if (asc == NULL) { + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM); + return (ENOMEM); + } + wi = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_laddr), struct sctp_laddr); + if (wi == NULL) { + SCTP_FREE(asc, SCTP_M_ASC_IT); + SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_ASCONF, ENOMEM); + return (ENOMEM); + } + LIST_INIT(&asc->list_of_work); + asc->cnt = 1; + SCTP_INCR_LADDR_COUNT(); + wi->ifa = ifa; + wi->action = type; + atomic_add_int(&ifa->refcount, 1); + LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr); + (void)sctp_initiate_iterator(sctp_asconf_iterator_ep, + sctp_asconf_iterator_stcb, + sctp_asconf_iterator_ep_end, + SCTP_PCB_ANY_FLAGS, + SCTP_PCB_ANY_FEATURES, + SCTP_ASOC_ANY_STATE, + (void *)asc, 0, + sctp_asconf_iterator_end, inp, 0); + } + return (0); } else { /* invalid address! */ SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_ASCONF, EADDRNOTAVAIL); return (EADDRNOTAVAIL); } - return (0); } void |