diff options
Diffstat (limited to 'net/sctp/associola.c')
-rw-r--r-- | net/sctp/associola.c | 64 |
1 files changed, 28 insertions, 36 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index f4b23043b610..525864bf4f07 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -293,7 +293,8 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
293 | * told otherwise. | 293 | * told otherwise. |
294 | */ | 294 | */ |
295 | asoc->peer.ipv4_address = 1; | 295 | asoc->peer.ipv4_address = 1; |
296 | asoc->peer.ipv6_address = 1; | 296 | if (asoc->base.sk->sk_family == PF_INET6) |
297 | asoc->peer.ipv6_address = 1; | ||
297 | INIT_LIST_HEAD(&asoc->asocs); | 298 | INIT_LIST_HEAD(&asoc->asocs); |
298 | 299 | ||
299 | asoc->autoclose = sp->autoclose; | 300 | asoc->autoclose = sp->autoclose; |
@@ -566,6 +567,21 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc, | |||
566 | if (asoc->init_last_sent_to == peer) | 567 | if (asoc->init_last_sent_to == peer) |
567 | asoc->init_last_sent_to = NULL; | 568 | asoc->init_last_sent_to = NULL; |
568 | 569 | ||
570 | /* If we remove the transport an SHUTDOWN was last sent to, set it | ||
571 | * to NULL. Combined with the update of the retran path above, this | ||
572 | * will cause the next SHUTDOWN to be sent to the next available | ||
573 | * transport, maintaining the cycle. | ||
574 | */ | ||
575 | if (asoc->shutdown_last_sent_to == peer) | ||
576 | asoc->shutdown_last_sent_to = NULL; | ||
577 | |||
578 | /* If we remove the transport an ASCONF was last sent to, set it to | ||
579 | * NULL. | ||
580 | */ | ||
581 | if (asoc->addip_last_asconf && | ||
582 | asoc->addip_last_asconf->transport == peer) | ||
583 | asoc->addip_last_asconf->transport = NULL; | ||
584 | |||
569 | asoc->peer.transport_count--; | 585 | asoc->peer.transport_count--; |
570 | 586 | ||
571 | sctp_transport_free(peer); | 587 | sctp_transport_free(peer); |
@@ -1268,49 +1284,21 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
1268 | ntohs(t->ipaddr.v4.sin_port)); | 1284 | ntohs(t->ipaddr.v4.sin_port)); |
1269 | } | 1285 | } |
1270 | 1286 | ||
1271 | /* Choose the transport for sending a INIT packet. */ | 1287 | /* Choose the transport for sending retransmit packet. */ |
1272 | struct sctp_transport *sctp_assoc_choose_init_transport( | 1288 | struct sctp_transport *sctp_assoc_choose_alter_transport( |
1273 | struct sctp_association *asoc) | 1289 | struct sctp_association *asoc, struct sctp_transport *last_sent_to) |
1274 | { | ||
1275 | struct sctp_transport *t; | ||
1276 | |||
1277 | /* Use the retran path. If the last INIT was sent over the | ||
1278 | * retran path, update the retran path and use it. | ||
1279 | */ | ||
1280 | if (!asoc->init_last_sent_to) { | ||
1281 | t = asoc->peer.active_path; | ||
1282 | } else { | ||
1283 | if (asoc->init_last_sent_to == asoc->peer.retran_path) | ||
1284 | sctp_assoc_update_retran_path(asoc); | ||
1285 | t = asoc->peer.retran_path; | ||
1286 | } | ||
1287 | |||
1288 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" | ||
1289 | " %p addr: ", | ||
1290 | " port: %d\n", | ||
1291 | asoc, | ||
1292 | (&t->ipaddr), | ||
1293 | ntohs(t->ipaddr.v4.sin_port)); | ||
1294 | |||
1295 | return t; | ||
1296 | } | ||
1297 | |||
1298 | /* Choose the transport for sending a SHUTDOWN packet. */ | ||
1299 | struct sctp_transport *sctp_assoc_choose_shutdown_transport( | ||
1300 | struct sctp_association *asoc) | ||
1301 | { | 1290 | { |
1302 | /* If this is the first time SHUTDOWN is sent, use the active path, | 1291 | /* If this is the first time packet is sent, use the active path, |
1303 | * else use the retran path. If the last SHUTDOWN was sent over the | 1292 | * else use the retran path. If the last packet was sent over the |
1304 | * retran path, update the retran path and use it. | 1293 | * retran path, update the retran path and use it. |
1305 | */ | 1294 | */ |
1306 | if (!asoc->shutdown_last_sent_to) | 1295 | if (!last_sent_to) |
1307 | return asoc->peer.active_path; | 1296 | return asoc->peer.active_path; |
1308 | else { | 1297 | else { |
1309 | if (asoc->shutdown_last_sent_to == asoc->peer.retran_path) | 1298 | if (last_sent_to == asoc->peer.retran_path) |
1310 | sctp_assoc_update_retran_path(asoc); | 1299 | sctp_assoc_update_retran_path(asoc); |
1311 | return asoc->peer.retran_path; | 1300 | return asoc->peer.retran_path; |
1312 | } | 1301 | } |
1313 | |||
1314 | } | 1302 | } |
1315 | 1303 | ||
1316 | /* Update the association's pmtu and frag_point by going through all the | 1304 | /* Update the association's pmtu and frag_point by going through all the |
@@ -1482,6 +1470,10 @@ int sctp_assoc_set_id(struct sctp_association *asoc, gfp_t gfp) | |||
1482 | { | 1470 | { |
1483 | int assoc_id; | 1471 | int assoc_id; |
1484 | int error = 0; | 1472 | int error = 0; |
1473 | |||
1474 | /* If the id is already assigned, keep it. */ | ||
1475 | if (asoc->assoc_id) | ||
1476 | return error; | ||
1485 | retry: | 1477 | retry: |
1486 | if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp))) | 1478 | if (unlikely(!idr_pre_get(&sctp_assocs_id, gfp))) |
1487 | return -ENOMEM; | 1479 | return -ENOMEM; |