diff options
Diffstat (limited to 'net/sctp')
| -rw-r--r-- | net/sctp/associola.c | 27 | ||||
| -rw-r--r-- | net/sctp/bind_addr.c | 8 | ||||
| -rw-r--r-- | net/sctp/endpointola.c | 11 | ||||
| -rw-r--r-- | net/sctp/ipv6.c | 3 | ||||
| -rw-r--r-- | net/sctp/outqueue.c | 9 | ||||
| -rw-r--r-- | net/sctp/protocol.c | 7 | ||||
| -rw-r--r-- | net/sctp/sm_make_chunk.c | 14 | ||||
| -rw-r--r-- | net/sctp/sm_sideeffect.c | 12 | ||||
| -rw-r--r-- | net/sctp/sm_statefuns.c | 8 | ||||
| -rw-r--r-- | net/sctp/socket.c | 74 | ||||
| -rw-r--r-- | net/sctp/transport.c | 9 |
11 files changed, 134 insertions, 48 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 9d05e13e92f6..27329ce9c311 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
| @@ -441,7 +441,8 @@ void sctp_assoc_set_primary(struct sctp_association *asoc, | |||
| 441 | /* If the primary path is changing, assume that the | 441 | /* If the primary path is changing, assume that the |
| 442 | * user wants to use this new path. | 442 | * user wants to use this new path. |
| 443 | */ | 443 | */ |
| 444 | if (transport->state != SCTP_INACTIVE) | 444 | if ((transport->state == SCTP_ACTIVE) || |
| 445 | (transport->state == SCTP_UNKNOWN)) | ||
| 445 | asoc->peer.active_path = transport; | 446 | asoc->peer.active_path = transport; |
| 446 | 447 | ||
| 447 | /* | 448 | /* |
| @@ -532,11 +533,11 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
| 532 | port = addr->v4.sin_port; | 533 | port = addr->v4.sin_port; |
| 533 | 534 | ||
| 534 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ", | 535 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_add_peer:association %p addr: ", |
| 535 | " port: %d state:%s\n", | 536 | " port: %d state:%d\n", |
| 536 | asoc, | 537 | asoc, |
| 537 | addr, | 538 | addr, |
| 538 | addr->v4.sin_port, | 539 | addr->v4.sin_port, |
| 539 | peer_state == SCTP_UNKNOWN?"UNKNOWN":"ACTIVE"); | 540 | peer_state); |
| 540 | 541 | ||
| 541 | /* Set the port if it has not been set yet. */ | 542 | /* Set the port if it has not been set yet. */ |
| 542 | if (0 == asoc->peer.port) | 543 | if (0 == asoc->peer.port) |
| @@ -545,9 +546,12 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
| 545 | /* Check to see if this is a duplicate. */ | 546 | /* Check to see if this is a duplicate. */ |
| 546 | peer = sctp_assoc_lookup_paddr(asoc, addr); | 547 | peer = sctp_assoc_lookup_paddr(asoc, addr); |
| 547 | if (peer) { | 548 | if (peer) { |
| 548 | if (peer_state == SCTP_ACTIVE && | 549 | if (peer->state == SCTP_UNKNOWN) { |
| 549 | peer->state == SCTP_UNKNOWN) | 550 | if (peer_state == SCTP_ACTIVE) |
| 550 | peer->state = SCTP_ACTIVE; | 551 | peer->state = SCTP_ACTIVE; |
| 552 | if (peer_state == SCTP_UNCONFIRMED) | ||
| 553 | peer->state = SCTP_UNCONFIRMED; | ||
| 554 | } | ||
| 551 | return peer; | 555 | return peer; |
| 552 | } | 556 | } |
| 553 | 557 | ||
| @@ -739,7 +743,8 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
| 739 | list_for_each(pos, &asoc->peer.transport_addr_list) { | 743 | list_for_each(pos, &asoc->peer.transport_addr_list) { |
| 740 | t = list_entry(pos, struct sctp_transport, transports); | 744 | t = list_entry(pos, struct sctp_transport, transports); |
| 741 | 745 | ||
| 742 | if (t->state == SCTP_INACTIVE) | 746 | if ((t->state == SCTP_INACTIVE) || |
| 747 | (t->state == SCTP_UNCONFIRMED)) | ||
| 743 | continue; | 748 | continue; |
| 744 | if (!first || t->last_time_heard > first->last_time_heard) { | 749 | if (!first || t->last_time_heard > first->last_time_heard) { |
| 745 | second = first; | 750 | second = first; |
| @@ -759,7 +764,8 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
| 759 | * [If the primary is active but not most recent, bump the most | 764 | * [If the primary is active but not most recent, bump the most |
| 760 | * recently used transport.] | 765 | * recently used transport.] |
| 761 | */ | 766 | */ |
| 762 | if (asoc->peer.primary_path->state != SCTP_INACTIVE && | 767 | if (((asoc->peer.primary_path->state == SCTP_ACTIVE) || |
| 768 | (asoc->peer.primary_path->state == SCTP_UNKNOWN)) && | ||
| 763 | first != asoc->peer.primary_path) { | 769 | first != asoc->peer.primary_path) { |
| 764 | second = first; | 770 | second = first; |
| 765 | first = asoc->peer.primary_path; | 771 | first = asoc->peer.primary_path; |
| @@ -1054,7 +1060,7 @@ void sctp_assoc_update(struct sctp_association *asoc, | |||
| 1054 | transports); | 1060 | transports); |
| 1055 | if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr)) | 1061 | if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr)) |
| 1056 | sctp_assoc_add_peer(asoc, &trans->ipaddr, | 1062 | sctp_assoc_add_peer(asoc, &trans->ipaddr, |
| 1057 | GFP_ATOMIC, SCTP_ACTIVE); | 1063 | GFP_ATOMIC, trans->state); |
| 1058 | } | 1064 | } |
| 1059 | 1065 | ||
| 1060 | asoc->ctsn_ack_point = asoc->next_tsn - 1; | 1066 | asoc->ctsn_ack_point = asoc->next_tsn - 1; |
| @@ -1094,7 +1100,8 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
| 1094 | 1100 | ||
| 1095 | /* Try to find an active transport. */ | 1101 | /* Try to find an active transport. */ |
| 1096 | 1102 | ||
| 1097 | if (t->state != SCTP_INACTIVE) { | 1103 | if ((t->state == SCTP_ACTIVE) || |
| 1104 | (t->state == SCTP_UNKNOWN)) { | ||
| 1098 | break; | 1105 | break; |
| 1099 | } else { | 1106 | } else { |
| 1100 | /* Keep track of the next transport in case | 1107 | /* Keep track of the next transport in case |
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 2b962627f631..2b9c12a170e5 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c | |||
| @@ -146,7 +146,7 @@ void sctp_bind_addr_free(struct sctp_bind_addr *bp) | |||
| 146 | 146 | ||
| 147 | /* Add an address to the bind address list in the SCTP_bind_addr structure. */ | 147 | /* Add an address to the bind address list in the SCTP_bind_addr structure. */ |
| 148 | int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, | 148 | int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, |
| 149 | gfp_t gfp) | 149 | __u8 use_as_src, gfp_t gfp) |
| 150 | { | 150 | { |
| 151 | struct sctp_sockaddr_entry *addr; | 151 | struct sctp_sockaddr_entry *addr; |
| 152 | 152 | ||
| @@ -163,6 +163,8 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new, | |||
| 163 | if (!addr->a.v4.sin_port) | 163 | if (!addr->a.v4.sin_port) |
| 164 | addr->a.v4.sin_port = bp->port; | 164 | addr->a.v4.sin_port = bp->port; |
| 165 | 165 | ||
| 166 | addr->use_as_src = use_as_src; | ||
| 167 | |||
| 166 | INIT_LIST_HEAD(&addr->list); | 168 | INIT_LIST_HEAD(&addr->list); |
| 167 | list_add_tail(&addr->list, &bp->address_list); | 169 | list_add_tail(&addr->list, &bp->address_list); |
| 168 | SCTP_DBG_OBJCNT_INC(addr); | 170 | SCTP_DBG_OBJCNT_INC(addr); |
| @@ -274,7 +276,7 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list, | |||
| 274 | } | 276 | } |
| 275 | 277 | ||
| 276 | af->from_addr_param(&addr, rawaddr, port, 0); | 278 | af->from_addr_param(&addr, rawaddr, port, 0); |
| 277 | retval = sctp_add_bind_addr(bp, &addr, gfp); | 279 | retval = sctp_add_bind_addr(bp, &addr, 1, gfp); |
| 278 | if (retval) { | 280 | if (retval) { |
| 279 | /* Can't finish building the list, clean up. */ | 281 | /* Can't finish building the list, clean up. */ |
| 280 | sctp_bind_addr_clean(bp); | 282 | sctp_bind_addr_clean(bp); |
| @@ -367,7 +369,7 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, | |||
| 367 | (((AF_INET6 == addr->sa.sa_family) && | 369 | (((AF_INET6 == addr->sa.sa_family) && |
| 368 | (flags & SCTP_ADDR6_ALLOWED) && | 370 | (flags & SCTP_ADDR6_ALLOWED) && |
| 369 | (flags & SCTP_ADDR6_PEERSUPP)))) | 371 | (flags & SCTP_ADDR6_PEERSUPP)))) |
| 370 | error = sctp_add_bind_addr(dest, addr, gfp); | 372 | error = sctp_add_bind_addr(dest, addr, 1, gfp); |
| 371 | } | 373 | } |
| 372 | 374 | ||
| 373 | return error; | 375 | return error; |
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 67bd53070ee0..ffda1d680529 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
| @@ -158,6 +158,12 @@ void sctp_endpoint_add_asoc(struct sctp_endpoint *ep, | |||
| 158 | void sctp_endpoint_free(struct sctp_endpoint *ep) | 158 | void sctp_endpoint_free(struct sctp_endpoint *ep) |
| 159 | { | 159 | { |
| 160 | ep->base.dead = 1; | 160 | ep->base.dead = 1; |
| 161 | |||
| 162 | ep->base.sk->sk_state = SCTP_SS_CLOSED; | ||
| 163 | |||
| 164 | /* Unlink this endpoint, so we can't find it again! */ | ||
| 165 | sctp_unhash_endpoint(ep); | ||
| 166 | |||
| 161 | sctp_endpoint_put(ep); | 167 | sctp_endpoint_put(ep); |
| 162 | } | 168 | } |
| 163 | 169 | ||
| @@ -166,11 +172,6 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep) | |||
| 166 | { | 172 | { |
| 167 | SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return); | 173 | SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return); |
| 168 | 174 | ||
| 169 | ep->base.sk->sk_state = SCTP_SS_CLOSED; | ||
| 170 | |||
| 171 | /* Unlink this endpoint, so we can't find it again! */ | ||
| 172 | sctp_unhash_endpoint(ep); | ||
| 173 | |||
| 174 | /* Free up the HMAC transform. */ | 175 | /* Free up the HMAC transform. */ |
| 175 | sctp_crypto_free_tfm(sctp_sk(ep->base.sk)->hmac); | 176 | sctp_crypto_free_tfm(sctp_sk(ep->base.sk)->hmac); |
| 176 | 177 | ||
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 8ef08070c8b6..99c0cefc04e0 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
| @@ -290,7 +290,8 @@ static void sctp_v6_get_saddr(struct sctp_association *asoc, | |||
| 290 | sctp_read_lock(addr_lock); | 290 | sctp_read_lock(addr_lock); |
| 291 | list_for_each(pos, &bp->address_list) { | 291 | list_for_each(pos, &bp->address_list) { |
| 292 | laddr = list_entry(pos, struct sctp_sockaddr_entry, list); | 292 | laddr = list_entry(pos, struct sctp_sockaddr_entry, list); |
| 293 | if ((laddr->a.sa.sa_family == AF_INET6) && | 293 | if ((laddr->use_as_src) && |
| 294 | (laddr->a.sa.sa_family == AF_INET6) && | ||
| 294 | (scope <= sctp_scope(&laddr->a))) { | 295 | (scope <= sctp_scope(&laddr->a))) { |
| 295 | bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); | 296 | bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); |
| 296 | if (!baddr || (matchlen < bmatchlen)) { | 297 | if (!baddr || (matchlen < bmatchlen)) { |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index e5faa351aaad..30b710c54e64 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
| @@ -691,7 +691,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
| 691 | 691 | ||
| 692 | if (!new_transport) { | 692 | if (!new_transport) { |
| 693 | new_transport = asoc->peer.active_path; | 693 | new_transport = asoc->peer.active_path; |
| 694 | } else if (new_transport->state == SCTP_INACTIVE) { | 694 | } else if ((new_transport->state == SCTP_INACTIVE) || |
| 695 | (new_transport->state == SCTP_UNCONFIRMED)) { | ||
| 695 | /* If the chunk is Heartbeat or Heartbeat Ack, | 696 | /* If the chunk is Heartbeat or Heartbeat Ack, |
| 696 | * send it to chunk->transport, even if it's | 697 | * send it to chunk->transport, even if it's |
| 697 | * inactive. | 698 | * inactive. |
| @@ -848,7 +849,8 @@ int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
| 848 | */ | 849 | */ |
| 849 | new_transport = chunk->transport; | 850 | new_transport = chunk->transport; |
| 850 | if (!new_transport || | 851 | if (!new_transport || |
| 851 | new_transport->state == SCTP_INACTIVE) | 852 | ((new_transport->state == SCTP_INACTIVE) || |
| 853 | (new_transport->state == SCTP_UNCONFIRMED))) | ||
| 852 | new_transport = asoc->peer.active_path; | 854 | new_transport = asoc->peer.active_path; |
| 853 | 855 | ||
| 854 | /* Change packets if necessary. */ | 856 | /* Change packets if necessary. */ |
| @@ -1464,7 +1466,8 @@ static void sctp_check_transmitted(struct sctp_outq *q, | |||
| 1464 | /* Mark the destination transport address as | 1466 | /* Mark the destination transport address as |
| 1465 | * active if it is not so marked. | 1467 | * active if it is not so marked. |
| 1466 | */ | 1468 | */ |
| 1467 | if (transport->state == SCTP_INACTIVE) { | 1469 | if ((transport->state == SCTP_INACTIVE) || |
| 1470 | (transport->state == SCTP_UNCONFIRMED)) { | ||
| 1468 | sctp_assoc_control_transport( | 1471 | sctp_assoc_control_transport( |
| 1469 | transport->asoc, | 1472 | transport->asoc, |
| 1470 | transport, | 1473 | transport, |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 816c033d7886..1ab03a27a76e 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
| @@ -240,7 +240,7 @@ int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope, | |||
| 240 | (((AF_INET6 == addr->a.sa.sa_family) && | 240 | (((AF_INET6 == addr->a.sa.sa_family) && |
| 241 | (copy_flags & SCTP_ADDR6_ALLOWED) && | 241 | (copy_flags & SCTP_ADDR6_ALLOWED) && |
| 242 | (copy_flags & SCTP_ADDR6_PEERSUPP)))) { | 242 | (copy_flags & SCTP_ADDR6_PEERSUPP)))) { |
| 243 | error = sctp_add_bind_addr(bp, &addr->a, | 243 | error = sctp_add_bind_addr(bp, &addr->a, 1, |
| 244 | GFP_ATOMIC); | 244 | GFP_ATOMIC); |
| 245 | if (error) | 245 | if (error) |
| 246 | goto end_copy; | 246 | goto end_copy; |
| @@ -486,6 +486,8 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
| 486 | list_for_each(pos, &bp->address_list) { | 486 | list_for_each(pos, &bp->address_list) { |
| 487 | laddr = list_entry(pos, struct sctp_sockaddr_entry, | 487 | laddr = list_entry(pos, struct sctp_sockaddr_entry, |
| 488 | list); | 488 | list); |
| 489 | if (!laddr->use_as_src) | ||
| 490 | continue; | ||
| 489 | sctp_v4_dst_saddr(&dst_saddr, dst, bp->port); | 491 | sctp_v4_dst_saddr(&dst_saddr, dst, bp->port); |
| 490 | if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a)) | 492 | if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a)) |
| 491 | goto out_unlock; | 493 | goto out_unlock; |
| @@ -506,7 +508,8 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
| 506 | list_for_each(pos, &bp->address_list) { | 508 | list_for_each(pos, &bp->address_list) { |
| 507 | laddr = list_entry(pos, struct sctp_sockaddr_entry, list); | 509 | laddr = list_entry(pos, struct sctp_sockaddr_entry, list); |
| 508 | 510 | ||
| 509 | if (AF_INET == laddr->a.sa.sa_family) { | 511 | if ((laddr->use_as_src) && |
| 512 | (AF_INET == laddr->a.sa.sa_family)) { | ||
| 510 | fl.fl4_src = laddr->a.v4.sin_addr.s_addr; | 513 | fl.fl4_src = laddr->a.v4.sin_addr.s_addr; |
| 511 | if (!ip_route_output_key(&rt, &fl)) { | 514 | if (!ip_route_output_key(&rt, &fl)) { |
| 512 | dst = &rt->u.dst; | 515 | dst = &rt->u.dst; |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 2a8773691695..4f11f5858209 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
| @@ -1493,7 +1493,7 @@ no_hmac: | |||
| 1493 | 1493 | ||
| 1494 | /* Also, add the destination address. */ | 1494 | /* Also, add the destination address. */ |
| 1495 | if (list_empty(&retval->base.bind_addr.address_list)) { | 1495 | if (list_empty(&retval->base.bind_addr.address_list)) { |
| 1496 | sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest, | 1496 | sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest, 1, |
| 1497 | GFP_ATOMIC); | 1497 | GFP_ATOMIC); |
| 1498 | } | 1498 | } |
| 1499 | 1499 | ||
| @@ -2017,7 +2017,7 @@ static int sctp_process_param(struct sctp_association *asoc, | |||
| 2017 | af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); | 2017 | af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); |
| 2018 | scope = sctp_scope(peer_addr); | 2018 | scope = sctp_scope(peer_addr); |
| 2019 | if (sctp_in_scope(&addr, scope)) | 2019 | if (sctp_in_scope(&addr, scope)) |
| 2020 | if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_ACTIVE)) | 2020 | if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED)) |
| 2021 | return 0; | 2021 | return 0; |
| 2022 | break; | 2022 | break; |
| 2023 | 2023 | ||
| @@ -2418,7 +2418,7 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
| 2418 | * Due to Resource Shortage'. | 2418 | * Due to Resource Shortage'. |
| 2419 | */ | 2419 | */ |
| 2420 | 2420 | ||
| 2421 | peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_ACTIVE); | 2421 | peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_UNCONFIRMED); |
| 2422 | if (!peer) | 2422 | if (!peer) |
| 2423 | return SCTP_ERROR_RSRC_LOW; | 2423 | return SCTP_ERROR_RSRC_LOW; |
| 2424 | 2424 | ||
| @@ -2565,6 +2565,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, | |||
| 2565 | union sctp_addr_param *addr_param; | 2565 | union sctp_addr_param *addr_param; |
| 2566 | struct list_head *pos; | 2566 | struct list_head *pos; |
| 2567 | struct sctp_transport *transport; | 2567 | struct sctp_transport *transport; |
| 2568 | struct sctp_sockaddr_entry *saddr; | ||
| 2568 | int retval = 0; | 2569 | int retval = 0; |
| 2569 | 2570 | ||
| 2570 | addr_param = (union sctp_addr_param *) | 2571 | addr_param = (union sctp_addr_param *) |
| @@ -2578,7 +2579,11 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, | |||
| 2578 | case SCTP_PARAM_ADD_IP: | 2579 | case SCTP_PARAM_ADD_IP: |
| 2579 | sctp_local_bh_disable(); | 2580 | sctp_local_bh_disable(); |
| 2580 | sctp_write_lock(&asoc->base.addr_lock); | 2581 | sctp_write_lock(&asoc->base.addr_lock); |
| 2581 | retval = sctp_add_bind_addr(bp, &addr, GFP_ATOMIC); | 2582 | list_for_each(pos, &bp->address_list) { |
| 2583 | saddr = list_entry(pos, struct sctp_sockaddr_entry, list); | ||
| 2584 | if (sctp_cmp_addr_exact(&saddr->a, &addr)) | ||
| 2585 | saddr->use_as_src = 1; | ||
| 2586 | } | ||
| 2582 | sctp_write_unlock(&asoc->base.addr_lock); | 2587 | sctp_write_unlock(&asoc->base.addr_lock); |
| 2583 | sctp_local_bh_enable(); | 2588 | sctp_local_bh_enable(); |
| 2584 | break; | 2589 | break; |
| @@ -2591,6 +2596,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, | |||
| 2591 | list_for_each(pos, &asoc->peer.transport_addr_list) { | 2596 | list_for_each(pos, &asoc->peer.transport_addr_list) { |
| 2592 | transport = list_entry(pos, struct sctp_transport, | 2597 | transport = list_entry(pos, struct sctp_transport, |
| 2593 | transports); | 2598 | transports); |
| 2599 | dst_release(transport->dst); | ||
| 2594 | sctp_transport_route(transport, NULL, | 2600 | sctp_transport_route(transport, NULL, |
| 2595 | sctp_sk(asoc->base.sk)); | 2601 | sctp_sk(asoc->base.sk)); |
| 2596 | } | 2602 | } |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index c5beb2ad7ef7..9c10bdec1afe 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
| @@ -430,7 +430,11 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | |||
| 430 | /* The check for association's overall error counter exceeding the | 430 | /* The check for association's overall error counter exceeding the |
| 431 | * threshold is done in the state function. | 431 | * threshold is done in the state function. |
| 432 | */ | 432 | */ |
| 433 | asoc->overall_error_count++; | 433 | /* When probing UNCONFIRMED addresses, the association overall |
| 434 | * error count is NOT incremented | ||
| 435 | */ | ||
| 436 | if (transport->state != SCTP_UNCONFIRMED) | ||
| 437 | asoc->overall_error_count++; | ||
| 434 | 438 | ||
| 435 | if (transport->state != SCTP_INACTIVE && | 439 | if (transport->state != SCTP_INACTIVE && |
| 436 | (transport->error_count++ >= transport->pathmaxrxt)) { | 440 | (transport->error_count++ >= transport->pathmaxrxt)) { |
| @@ -610,7 +614,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, | |||
| 610 | /* Mark the destination transport address as active if it is not so | 614 | /* Mark the destination transport address as active if it is not so |
| 611 | * marked. | 615 | * marked. |
| 612 | */ | 616 | */ |
| 613 | if (t->state == SCTP_INACTIVE) | 617 | if ((t->state == SCTP_INACTIVE) || (t->state == SCTP_UNCONFIRMED)) |
| 614 | sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, | 618 | sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, |
| 615 | SCTP_HEARTBEAT_SUCCESS); | 619 | SCTP_HEARTBEAT_SUCCESS); |
| 616 | 620 | ||
| @@ -620,6 +624,10 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, | |||
| 620 | */ | 624 | */ |
| 621 | hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data; | 625 | hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data; |
| 622 | sctp_transport_update_rto(t, (jiffies - hbinfo->sent_at)); | 626 | sctp_transport_update_rto(t, (jiffies - hbinfo->sent_at)); |
| 627 | |||
| 628 | /* Update the heartbeat timer. */ | ||
| 629 | if (!mod_timer(&t->hb_timer, sctp_transport_timeout(t))) | ||
| 630 | sctp_transport_hold(t); | ||
| 623 | } | 631 | } |
| 624 | 632 | ||
| 625 | /* Helper function to do a transport reset at the expiry of the hearbeat | 633 | /* Helper function to do a transport reset at the expiry of the hearbeat |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 9e58144f4851..ead3f1b0ea3d 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -846,6 +846,7 @@ static sctp_disposition_t sctp_sf_heartbeat(const struct sctp_endpoint *ep, | |||
| 846 | hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t)); | 846 | hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t)); |
| 847 | hbinfo.daddr = transport->ipaddr; | 847 | hbinfo.daddr = transport->ipaddr; |
| 848 | hbinfo.sent_at = jiffies; | 848 | hbinfo.sent_at = jiffies; |
| 849 | hbinfo.hb_nonce = transport->hb_nonce; | ||
| 849 | 850 | ||
| 850 | /* Send a heartbeat to our peer. */ | 851 | /* Send a heartbeat to our peer. */ |
| 851 | paylen = sizeof(sctp_sender_hb_info_t); | 852 | paylen = sizeof(sctp_sender_hb_info_t); |
| @@ -1048,6 +1049,10 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, | |||
| 1048 | return SCTP_DISPOSITION_DISCARD; | 1049 | return SCTP_DISPOSITION_DISCARD; |
| 1049 | } | 1050 | } |
| 1050 | 1051 | ||
| 1052 | /* Validate the 64-bit random nonce. */ | ||
| 1053 | if (hbinfo->hb_nonce != link->hb_nonce) | ||
| 1054 | return SCTP_DISPOSITION_DISCARD; | ||
| 1055 | |||
| 1051 | max_interval = link->hbinterval + link->rto; | 1056 | max_interval = link->hbinterval + link->rto; |
| 1052 | 1057 | ||
| 1053 | /* Check if the timestamp looks valid. */ | 1058 | /* Check if the timestamp looks valid. */ |
| @@ -5278,7 +5283,6 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
| 5278 | datalen -= sizeof(sctp_data_chunk_t); | 5283 | datalen -= sizeof(sctp_data_chunk_t); |
| 5279 | 5284 | ||
| 5280 | deliver = SCTP_CMD_CHUNK_ULP; | 5285 | deliver = SCTP_CMD_CHUNK_ULP; |
| 5281 | chunk->data_accepted = 1; | ||
| 5282 | 5286 | ||
| 5283 | /* Think about partial delivery. */ | 5287 | /* Think about partial delivery. */ |
| 5284 | if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) { | 5288 | if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) { |
| @@ -5357,6 +5361,8 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
| 5357 | if (SCTP_CMD_CHUNK_ULP == deliver) | 5361 | if (SCTP_CMD_CHUNK_ULP == deliver) |
| 5358 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn)); | 5362 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn)); |
| 5359 | 5363 | ||
| 5364 | chunk->data_accepted = 1; | ||
| 5365 | |||
| 5360 | /* Note: Some chunks may get overcounted (if we drop) or overcounted | 5366 | /* Note: Some chunks may get overcounted (if we drop) or overcounted |
| 5361 | * if we renege and the chunk arrives again. | 5367 | * if we renege and the chunk arrives again. |
| 5362 | */ | 5368 | */ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 0a2c71d0d8aa..54722e622e6d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -369,7 +369,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) | |||
| 369 | 369 | ||
| 370 | /* Use GFP_ATOMIC since BHs are disabled. */ | 370 | /* Use GFP_ATOMIC since BHs are disabled. */ |
| 371 | addr->v4.sin_port = ntohs(addr->v4.sin_port); | 371 | addr->v4.sin_port = ntohs(addr->v4.sin_port); |
| 372 | ret = sctp_add_bind_addr(bp, addr, GFP_ATOMIC); | 372 | ret = sctp_add_bind_addr(bp, addr, 1, GFP_ATOMIC); |
| 373 | addr->v4.sin_port = htons(addr->v4.sin_port); | 373 | addr->v4.sin_port = htons(addr->v4.sin_port); |
| 374 | sctp_write_unlock(&ep->base.addr_lock); | 374 | sctp_write_unlock(&ep->base.addr_lock); |
| 375 | sctp_local_bh_enable(); | 375 | sctp_local_bh_enable(); |
| @@ -491,6 +491,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk, | |||
| 491 | struct sctp_chunk *chunk; | 491 | struct sctp_chunk *chunk; |
| 492 | struct sctp_sockaddr_entry *laddr; | 492 | struct sctp_sockaddr_entry *laddr; |
| 493 | union sctp_addr *addr; | 493 | union sctp_addr *addr; |
| 494 | union sctp_addr saveaddr; | ||
| 494 | void *addr_buf; | 495 | void *addr_buf; |
| 495 | struct sctp_af *af; | 496 | struct sctp_af *af; |
| 496 | struct list_head *pos; | 497 | struct list_head *pos; |
| @@ -558,14 +559,26 @@ static int sctp_send_asconf_add_ip(struct sock *sk, | |||
| 558 | } | 559 | } |
| 559 | 560 | ||
| 560 | retval = sctp_send_asconf(asoc, chunk); | 561 | retval = sctp_send_asconf(asoc, chunk); |
| 562 | if (retval) | ||
| 563 | goto out; | ||
| 561 | 564 | ||
| 562 | /* FIXME: After sending the add address ASCONF chunk, we | 565 | /* Add the new addresses to the bind address list with |
| 563 | * cannot append the address to the association's binding | 566 | * use_as_src set to 0. |
| 564 | * address list, because the new address may be used as the | ||
| 565 | * source of a message sent to the peer before the ASCONF | ||
| 566 | * chunk is received by the peer. So we should wait until | ||
| 567 | * ASCONF_ACK is received. | ||
| 568 | */ | 567 | */ |
| 568 | sctp_local_bh_disable(); | ||
| 569 | sctp_write_lock(&asoc->base.addr_lock); | ||
| 570 | addr_buf = addrs; | ||
| 571 | for (i = 0; i < addrcnt; i++) { | ||
| 572 | addr = (union sctp_addr *)addr_buf; | ||
| 573 | af = sctp_get_af_specific(addr->v4.sin_family); | ||
| 574 | memcpy(&saveaddr, addr, af->sockaddr_len); | ||
| 575 | saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port); | ||
| 576 | retval = sctp_add_bind_addr(bp, &saveaddr, 0, | ||
| 577 | GFP_ATOMIC); | ||
| 578 | addr_buf += af->sockaddr_len; | ||
| 579 | } | ||
| 580 | sctp_write_unlock(&asoc->base.addr_lock); | ||
| 581 | sctp_local_bh_enable(); | ||
| 569 | } | 582 | } |
| 570 | 583 | ||
| 571 | out: | 584 | out: |
| @@ -676,12 +689,15 @@ static int sctp_send_asconf_del_ip(struct sock *sk, | |||
| 676 | struct sctp_sock *sp; | 689 | struct sctp_sock *sp; |
| 677 | struct sctp_endpoint *ep; | 690 | struct sctp_endpoint *ep; |
| 678 | struct sctp_association *asoc; | 691 | struct sctp_association *asoc; |
| 692 | struct sctp_transport *transport; | ||
| 679 | struct sctp_bind_addr *bp; | 693 | struct sctp_bind_addr *bp; |
| 680 | struct sctp_chunk *chunk; | 694 | struct sctp_chunk *chunk; |
| 681 | union sctp_addr *laddr; | 695 | union sctp_addr *laddr; |
| 696 | union sctp_addr saveaddr; | ||
| 682 | void *addr_buf; | 697 | void *addr_buf; |
| 683 | struct sctp_af *af; | 698 | struct sctp_af *af; |
| 684 | struct list_head *pos; | 699 | struct list_head *pos, *pos1; |
| 700 | struct sctp_sockaddr_entry *saddr; | ||
| 685 | int i; | 701 | int i; |
| 686 | int retval = 0; | 702 | int retval = 0; |
| 687 | 703 | ||
| @@ -748,14 +764,42 @@ static int sctp_send_asconf_del_ip(struct sock *sk, | |||
| 748 | goto out; | 764 | goto out; |
| 749 | } | 765 | } |
| 750 | 766 | ||
| 751 | retval = sctp_send_asconf(asoc, chunk); | 767 | /* Reset use_as_src flag for the addresses in the bind address |
| 768 | * list that are to be deleted. | ||
| 769 | */ | ||
| 770 | sctp_local_bh_disable(); | ||
| 771 | sctp_write_lock(&asoc->base.addr_lock); | ||
| 772 | addr_buf = addrs; | ||
| 773 | for (i = 0; i < addrcnt; i++) { | ||
| 774 | laddr = (union sctp_addr *)addr_buf; | ||
| 775 | af = sctp_get_af_specific(laddr->v4.sin_family); | ||
| 776 | memcpy(&saveaddr, laddr, af->sockaddr_len); | ||
| 777 | saveaddr.v4.sin_port = ntohs(saveaddr.v4.sin_port); | ||
| 778 | list_for_each(pos1, &bp->address_list) { | ||
| 779 | saddr = list_entry(pos1, | ||
| 780 | struct sctp_sockaddr_entry, | ||
| 781 | list); | ||
| 782 | if (sctp_cmp_addr_exact(&saddr->a, &saveaddr)) | ||
| 783 | saddr->use_as_src = 0; | ||
| 784 | } | ||
| 785 | addr_buf += af->sockaddr_len; | ||
| 786 | } | ||
| 787 | sctp_write_unlock(&asoc->base.addr_lock); | ||
| 788 | sctp_local_bh_enable(); | ||
| 752 | 789 | ||
| 753 | /* FIXME: After sending the delete address ASCONF chunk, we | 790 | /* Update the route and saddr entries for all the transports |
| 754 | * cannot remove the addresses from the association's bind | 791 | * as some of the addresses in the bind address list are |
| 755 | * address list, because there maybe some packet send to | 792 | * about to be deleted and cannot be used as source addresses. |
| 756 | * the delete addresses, so we should wait until ASCONF_ACK | ||
| 757 | * packet is received. | ||
| 758 | */ | 793 | */ |
| 794 | list_for_each(pos1, &asoc->peer.transport_addr_list) { | ||
| 795 | transport = list_entry(pos1, struct sctp_transport, | ||
| 796 | transports); | ||
| 797 | dst_release(transport->dst); | ||
| 798 | sctp_transport_route(transport, NULL, | ||
| 799 | sctp_sk(asoc->base.sk)); | ||
| 800 | } | ||
| 801 | |||
| 802 | retval = sctp_send_asconf(asoc, chunk); | ||
| 759 | } | 803 | } |
| 760 | out: | 804 | out: |
| 761 | return retval; | 805 | return retval; |
| @@ -4977,7 +5021,7 @@ static struct sctp_bind_bucket *sctp_bucket_create( | |||
| 4977 | /* Caller must hold hashbucket lock for this tb with local BH disabled */ | 5021 | /* Caller must hold hashbucket lock for this tb with local BH disabled */ |
| 4978 | static void sctp_bucket_destroy(struct sctp_bind_bucket *pp) | 5022 | static void sctp_bucket_destroy(struct sctp_bind_bucket *pp) |
| 4979 | { | 5023 | { |
| 4980 | if (hlist_empty(&pp->owner)) { | 5024 | if (pp && hlist_empty(&pp->owner)) { |
| 4981 | if (pp->next) | 5025 | if (pp->next) |
| 4982 | pp->next->pprev = pp->pprev; | 5026 | pp->next->pprev = pp->pprev; |
| 4983 | *(pp->pprev) = pp->next; | 5027 | *(pp->pprev) = pp->next; |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 160f62ad1cc5..2763aa93de1a 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | */ | 49 | */ |
| 50 | 50 | ||
| 51 | #include <linux/types.h> | 51 | #include <linux/types.h> |
| 52 | #include <linux/random.h> | ||
| 52 | #include <net/sctp/sctp.h> | 53 | #include <net/sctp/sctp.h> |
| 53 | #include <net/sctp/sm.h> | 54 | #include <net/sctp/sm.h> |
| 54 | 55 | ||
| @@ -85,7 +86,6 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
| 85 | 86 | ||
| 86 | peer->init_sent_count = 0; | 87 | peer->init_sent_count = 0; |
| 87 | 88 | ||
| 88 | peer->state = SCTP_ACTIVE; | ||
| 89 | peer->param_flags = SPP_HB_DISABLE | | 89 | peer->param_flags = SPP_HB_DISABLE | |
| 90 | SPP_PMTUD_ENABLE | | 90 | SPP_PMTUD_ENABLE | |
| 91 | SPP_SACKDELAY_ENABLE; | 91 | SPP_SACKDELAY_ENABLE; |
| @@ -109,6 +109,9 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
| 109 | peer->hb_timer.function = sctp_generate_heartbeat_event; | 109 | peer->hb_timer.function = sctp_generate_heartbeat_event; |
| 110 | peer->hb_timer.data = (unsigned long)peer; | 110 | peer->hb_timer.data = (unsigned long)peer; |
| 111 | 111 | ||
| 112 | /* Initialize the 64-bit random nonce sent with heartbeat. */ | ||
| 113 | get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce)); | ||
| 114 | |||
| 112 | atomic_set(&peer->refcnt, 1); | 115 | atomic_set(&peer->refcnt, 1); |
| 113 | peer->dead = 0; | 116 | peer->dead = 0; |
| 114 | 117 | ||
| @@ -517,7 +520,9 @@ void sctp_transport_lower_cwnd(struct sctp_transport *transport, | |||
| 517 | unsigned long sctp_transport_timeout(struct sctp_transport *t) | 520 | unsigned long sctp_transport_timeout(struct sctp_transport *t) |
| 518 | { | 521 | { |
| 519 | unsigned long timeout; | 522 | unsigned long timeout; |
| 520 | timeout = t->hbinterval + t->rto + sctp_jitter(t->rto); | 523 | timeout = t->rto + sctp_jitter(t->rto); |
| 524 | if (t->state != SCTP_UNCONFIRMED) | ||
| 525 | timeout += t->hbinterval; | ||
| 521 | timeout += jiffies; | 526 | timeout += jiffies; |
| 522 | return timeout; | 527 | return timeout; |
| 523 | } | 528 | } |
