aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-06-04 00:43:52 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-04 00:43:52 -0400
commita8c617eae4dc2ea9f3d64472233f2d3dc3c9993c (patch)
tree2a4bdf0b610c0bbdec5c1dd452b475a09b47d42f /net
parent2307f866f542f3397d24f78d0efd74f4ab214a96 (diff)
parentc6ba68a26645dbc5029a9faa5687ebe6fcfc53e4 (diff)
Merge branch 'net-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vxy/lksctp-dev
Diffstat (limited to 'net')
-rw-r--r--net/sctp/associola.c64
-rw-r--r--net/sctp/sm_make_chunk.c16
-rw-r--r--net/sctp/sm_sideeffect.c8
-rw-r--r--net/sctp/sm_statefuns.c14
-rw-r--r--net/sctp/sm_statetable.c2
-rw-r--r--net/sctp/socket.c42
-rw-r--r--net/sctp/sysctl.c6
7 files changed, 96 insertions, 56 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. */
1272struct sctp_transport *sctp_assoc_choose_init_transport( 1288struct 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. */
1299struct 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;
1485retry: 1477retry:
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;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 6851ee94e974..61cc6075b0df 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -2864,19 +2864,19 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
2864 switch (addr_param->v4.param_hdr.type) { 2864 switch (addr_param->v4.param_hdr.type) {
2865 case SCTP_PARAM_IPV6_ADDRESS: 2865 case SCTP_PARAM_IPV6_ADDRESS:
2866 if (!asoc->peer.ipv6_address) 2866 if (!asoc->peer.ipv6_address)
2867 return SCTP_ERROR_INV_PARAM; 2867 return SCTP_ERROR_DNS_FAILED;
2868 break; 2868 break;
2869 case SCTP_PARAM_IPV4_ADDRESS: 2869 case SCTP_PARAM_IPV4_ADDRESS:
2870 if (!asoc->peer.ipv4_address) 2870 if (!asoc->peer.ipv4_address)
2871 return SCTP_ERROR_INV_PARAM; 2871 return SCTP_ERROR_DNS_FAILED;
2872 break; 2872 break;
2873 default: 2873 default:
2874 return SCTP_ERROR_INV_PARAM; 2874 return SCTP_ERROR_DNS_FAILED;
2875 } 2875 }
2876 2876
2877 af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type)); 2877 af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type));
2878 if (unlikely(!af)) 2878 if (unlikely(!af))
2879 return SCTP_ERROR_INV_PARAM; 2879 return SCTP_ERROR_DNS_FAILED;
2880 2880
2881 af->from_addr_param(&addr, addr_param, htons(asoc->peer.port), 0); 2881 af->from_addr_param(&addr, addr_param, htons(asoc->peer.port), 0);
2882 2882
@@ -2886,7 +2886,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
2886 * make sure we check for that) 2886 * make sure we check for that)
2887 */ 2887 */
2888 if (!af->is_any(&addr) && !af->addr_valid(&addr, NULL, asconf->skb)) 2888 if (!af->is_any(&addr) && !af->addr_valid(&addr, NULL, asconf->skb))
2889 return SCTP_ERROR_INV_PARAM; 2889 return SCTP_ERROR_DNS_FAILED;
2890 2890
2891 switch (asconf_param->param_hdr.type) { 2891 switch (asconf_param->param_hdr.type) {
2892 case SCTP_PARAM_ADD_IP: 2892 case SCTP_PARAM_ADD_IP:
@@ -2954,12 +2954,12 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
2954 2954
2955 peer = sctp_assoc_lookup_paddr(asoc, &addr); 2955 peer = sctp_assoc_lookup_paddr(asoc, &addr);
2956 if (!peer) 2956 if (!peer)
2957 return SCTP_ERROR_INV_PARAM; 2957 return SCTP_ERROR_DNS_FAILED;
2958 2958
2959 sctp_assoc_set_primary(asoc, peer); 2959 sctp_assoc_set_primary(asoc, peer);
2960 break; 2960 break;
2961 default: 2961 default:
2962 return SCTP_ERROR_INV_PARAM; 2962 return SCTP_ERROR_UNKNOWN_PARAM;
2963 break; 2963 break;
2964 } 2964 }
2965 2965
@@ -3273,7 +3273,7 @@ int sctp_process_asconf_ack(struct sctp_association *asoc,
3273 retval = 1; 3273 retval = 1;
3274 break; 3274 break;
3275 3275
3276 case SCTP_ERROR_INV_PARAM: 3276 case SCTP_ERROR_UNKNOWN_PARAM:
3277 /* Disable sending this type of asconf parameter in 3277 /* Disable sending this type of asconf parameter in
3278 * future. 3278 * future.
3279 */ 3279 */
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index e2020eb2c8ca..86426aac1600 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -686,7 +686,8 @@ static void sctp_cmd_setup_t2(sctp_cmd_seq_t *cmds,
686{ 686{
687 struct sctp_transport *t; 687 struct sctp_transport *t;
688 688
689 t = sctp_assoc_choose_shutdown_transport(asoc); 689 t = sctp_assoc_choose_alter_transport(asoc,
690 asoc->shutdown_last_sent_to);
690 asoc->shutdown_last_sent_to = t; 691 asoc->shutdown_last_sent_to = t;
691 asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = t->rto; 692 asoc->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] = t->rto;
692 chunk->transport = t; 693 chunk->transport = t;
@@ -777,7 +778,7 @@ static void sctp_cmd_setup_t4(sctp_cmd_seq_t *cmds,
777{ 778{
778 struct sctp_transport *t; 779 struct sctp_transport *t;
779 780
780 t = asoc->peer.active_path; 781 t = sctp_assoc_choose_alter_transport(asoc, chunk->transport);
781 asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = t->rto; 782 asoc->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = t->rto;
782 chunk->transport = t; 783 chunk->transport = t;
783} 784}
@@ -1379,7 +1380,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
1379 1380
1380 case SCTP_CMD_INIT_CHOOSE_TRANSPORT: 1381 case SCTP_CMD_INIT_CHOOSE_TRANSPORT:
1381 chunk = cmd->obj.ptr; 1382 chunk = cmd->obj.ptr;
1382 t = sctp_assoc_choose_init_transport(asoc); 1383 t = sctp_assoc_choose_alter_transport(asoc,
1384 asoc->init_last_sent_to);
1383 asoc->init_last_sent_to = t; 1385 asoc->init_last_sent_to = t;
1384 chunk->transport = t; 1386 chunk->transport = t;
1385 t->init_sent_count++; 1387 t->init_sent_count++;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 55a61aa69662..7288192f7df5 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -5432,9 +5432,13 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep,
5432 if (!reply) 5432 if (!reply)
5433 goto nomem; 5433 goto nomem;
5434 5434
5435 /* Do some failure management (Section 8.2). */ 5435 /* Do some failure management (Section 8.2).
5436 sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, 5436 * If we remove the transport an SHUTDOWN was last sent to, don't
5437 SCTP_TRANSPORT(asoc->shutdown_last_sent_to)); 5437 * do failure management.
5438 */
5439 if (asoc->shutdown_last_sent_to)
5440 sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE,
5441 SCTP_TRANSPORT(asoc->shutdown_last_sent_to));
5438 5442
5439 /* Set the transport for the SHUTDOWN/ACK chunk and the timeout for 5443 /* Set the transport for the SHUTDOWN/ACK chunk and the timeout for
5440 * the T2-shutdown timer. 5444 * the T2-shutdown timer.
@@ -5471,7 +5475,9 @@ sctp_disposition_t sctp_sf_t4_timer_expire(
5471 * detection on the appropriate destination address as defined in 5475 * detection on the appropriate destination address as defined in
5472 * RFC2960 [5] section 8.1 and 8.2. 5476 * RFC2960 [5] section 8.1 and 8.2.
5473 */ 5477 */
5474 sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE, SCTP_TRANSPORT(transport)); 5478 if (transport)
5479 sctp_add_cmd_sf(commands, SCTP_CMD_STRIKE,
5480 SCTP_TRANSPORT(transport));
5475 5481
5476 /* Reconfig T4 timer and transport. */ 5482 /* Reconfig T4 timer and transport. */
5477 sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T4, SCTP_CHUNK(chunk)); 5483 sctp_add_cmd_sf(commands, SCTP_CMD_SETUP_T4, SCTP_CHUNK(chunk));
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c
index 5c8186d88c61..6d9b3aafcc5d 100644
--- a/net/sctp/sm_statetable.c
+++ b/net/sctp/sm_statetable.c
@@ -698,7 +698,7 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
698 TYPE_SCTP_FUNC(sctp_sf_do_prm_asconf), \ 698 TYPE_SCTP_FUNC(sctp_sf_do_prm_asconf), \
699 /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ 699 /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \
700 TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \ 700 TYPE_SCTP_FUNC(sctp_sf_error_shutdown), \
701} /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */ 701} /* TYPE_SCTP_PRIMITIVE_ASCONF */
702 702
703/* The primary index for this table is the primitive type. 703/* The primary index for this table is the primitive type.
704 * The secondary index for this table is the state. 704 * The secondary index for this table is the state.
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 5fb3a8c9792e..7c3dfd2d9489 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1100,6 +1100,15 @@ static int __sctp_connect(struct sock* sk,
1100 goto out_free; 1100 goto out_free;
1101 } 1101 }
1102 1102
1103 /* In case the user of sctp_connectx() wants an association
1104 * id back, assign one now.
1105 */
1106 if (assoc_id) {
1107 err = sctp_assoc_set_id(asoc, GFP_KERNEL);
1108 if (err < 0)
1109 goto out_free;
1110 }
1111
1103 err = sctp_primitive_ASSOCIATE(asoc, NULL); 1112 err = sctp_primitive_ASSOCIATE(asoc, NULL);
1104 if (err < 0) { 1113 if (err < 0) {
1105 goto out_free; 1114 goto out_free;
@@ -1120,7 +1129,7 @@ static int __sctp_connect(struct sock* sk,
1120 timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK); 1129 timeo = sock_sndtimeo(sk, f_flags & O_NONBLOCK);
1121 1130
1122 err = sctp_wait_for_connect(asoc, &timeo); 1131 err = sctp_wait_for_connect(asoc, &timeo);
1123 if (!err && assoc_id) 1132 if ((err == 0 || err == -EINPROGRESS) && assoc_id)
1124 *assoc_id = asoc->assoc_id; 1133 *assoc_id = asoc->assoc_id;
1125 1134
1126 /* Don't free association on exit. */ 1135 /* Don't free association on exit. */
@@ -1264,6 +1273,34 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
1264 return assoc_id; 1273 return assoc_id;
1265} 1274}
1266 1275
1276/*
1277 * New (hopefully final) interface for the API. The option buffer is used
1278 * both for the returned association id and the addresses.
1279 */
1280SCTP_STATIC int sctp_getsockopt_connectx3(struct sock* sk, int len,
1281 char __user *optval,
1282 int __user *optlen)
1283{
1284 sctp_assoc_t assoc_id = 0;
1285 int err = 0;
1286
1287 if (len < sizeof(assoc_id))
1288 return -EINVAL;
1289
1290 err = __sctp_setsockopt_connectx(sk,
1291 (struct sockaddr __user *)(optval + sizeof(assoc_id)),
1292 len - sizeof(assoc_id), &assoc_id);
1293
1294 if (err == 0 || err == -EINPROGRESS) {
1295 if (copy_to_user(optval, &assoc_id, sizeof(assoc_id)))
1296 return -EFAULT;
1297 if (put_user(sizeof(assoc_id), optlen))
1298 return -EFAULT;
1299 }
1300
1301 return err;
1302}
1303
1267/* API 3.1.4 close() - UDP Style Syntax 1304/* API 3.1.4 close() - UDP Style Syntax
1268 * Applications use close() to perform graceful shutdown (as described in 1305 * Applications use close() to perform graceful shutdown (as described in
1269 * Section 10.1 of [SCTP]) on ALL the associations currently represented 1306 * Section 10.1 of [SCTP]) on ALL the associations currently represented
@@ -5578,6 +5615,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
5578 retval = sctp_getsockopt_local_addrs(sk, len, optval, 5615 retval = sctp_getsockopt_local_addrs(sk, len, optval,
5579 optlen); 5616 optlen);
5580 break; 5617 break;
5618 case SCTP_SOCKOPT_CONNECTX3:
5619 retval = sctp_getsockopt_connectx3(sk, len, optval, optlen);
5620 break;
5581 case SCTP_DEFAULT_SEND_PARAM: 5621 case SCTP_DEFAULT_SEND_PARAM:
5582 retval = sctp_getsockopt_default_send_param(sk, len, 5622 retval = sctp_getsockopt_default_send_param(sk, len,
5583 optval, optlen); 5623 optval, optlen);
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index f58e994e6852..63eabbc71298 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -49,8 +49,8 @@ static int zero = 0;
49static int one = 1; 49static int one = 1;
50static int timer_max = 86400000; /* ms in one day */ 50static int timer_max = 86400000; /* ms in one day */
51static int int_max = INT_MAX; 51static int int_max = INT_MAX;
52static long sack_timer_min = 1; 52static int sack_timer_min = 1;
53static long sack_timer_max = 500; 53static int sack_timer_max = 500;
54 54
55extern int sysctl_sctp_mem[3]; 55extern int sysctl_sctp_mem[3];
56extern int sysctl_sctp_rmem[3]; 56extern int sysctl_sctp_rmem[3];
@@ -223,7 +223,7 @@ static ctl_table sctp_table[] = {
223 .ctl_name = NET_SCTP_SACK_TIMEOUT, 223 .ctl_name = NET_SCTP_SACK_TIMEOUT,
224 .procname = "sack_timeout", 224 .procname = "sack_timeout",
225 .data = &sctp_sack_timeout, 225 .data = &sctp_sack_timeout,
226 .maxlen = sizeof(long), 226 .maxlen = sizeof(int),
227 .mode = 0644, 227 .mode = 0644,
228 .proc_handler = proc_dointvec_minmax, 228 .proc_handler = proc_dointvec_minmax,
229 .strategy = sysctl_intvec, 229 .strategy = sysctl_intvec,