aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-11-17 03:05:02 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-17 03:05:02 -0500
commita2bfbc072e279ff81e6b336acff612b9bc2e5281 (patch)
tree89cfe21911e1539e1b7f89d8a10d42abecba2a18 /net/sctp
parent5c427ff9e4cc61625d48172ea082ae99e21eea6a (diff)
parent82b3cc1a2f5e46300a9dec4a8cc8106dc20a4c23 (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: drivers/net/can/Kconfig
Diffstat (limited to 'net/sctp')
-rw-r--r--net/sctp/associola.c4
-rw-r--r--net/sctp/sm_statefuns.c15
-rw-r--r--net/sctp/socket.c40
-rw-r--r--net/sctp/transport.c3
4 files changed, 37 insertions, 25 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 8450960df24f..7eed77a39d0d 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1485,15 +1485,13 @@ void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned len)
1485 * local endpoint and the remote peer. 1485 * local endpoint and the remote peer.
1486 */ 1486 */
1487int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc, 1487int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc,
1488 gfp_t gfp) 1488 sctp_scope_t scope, gfp_t gfp)
1489{ 1489{
1490 sctp_scope_t scope;
1491 int flags; 1490 int flags;
1492 1491
1493 /* Use scoping rules to determine the subset of addresses from 1492 /* Use scoping rules to determine the subset of addresses from
1494 * the endpoint. 1493 * the endpoint.
1495 */ 1494 */
1496 scope = sctp_scope(&asoc->peer.active_path->ipaddr);
1497 flags = (PF_INET6 == asoc->base.sk->sk_family) ? SCTP_ADDR6_ALLOWED : 0; 1495 flags = (PF_INET6 == asoc->base.sk->sk_family) ? SCTP_ADDR6_ALLOWED : 0;
1498 if (asoc->peer.ipv4_address) 1496 if (asoc->peer.ipv4_address)
1499 flags |= SCTP_ADDR4_PEERSUPP; 1497 flags |= SCTP_ADDR4_PEERSUPP;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index c8fae1983dd1..d4df45022ffa 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -384,6 +384,11 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
384 if (!new_asoc) 384 if (!new_asoc)
385 goto nomem; 385 goto nomem;
386 386
387 if (sctp_assoc_set_bind_addr_from_ep(new_asoc,
388 sctp_scope(sctp_source(chunk)),
389 GFP_ATOMIC) < 0)
390 goto nomem_init;
391
387 /* The call, sctp_process_init(), can fail on memory allocation. */ 392 /* The call, sctp_process_init(), can fail on memory allocation. */
388 if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, 393 if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type,
389 sctp_source(chunk), 394 sctp_source(chunk),
@@ -401,9 +406,6 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,
401 len = ntohs(err_chunk->chunk_hdr->length) - 406 len = ntohs(err_chunk->chunk_hdr->length) -
402 sizeof(sctp_chunkhdr_t); 407 sizeof(sctp_chunkhdr_t);
403 408
404 if (sctp_assoc_set_bind_addr_from_ep(new_asoc, GFP_ATOMIC) < 0)
405 goto nomem_init;
406
407 repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len); 409 repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len);
408 if (!repl) 410 if (!repl)
409 goto nomem_init; 411 goto nomem_init;
@@ -1452,6 +1454,10 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
1452 if (!new_asoc) 1454 if (!new_asoc)
1453 goto nomem; 1455 goto nomem;
1454 1456
1457 if (sctp_assoc_set_bind_addr_from_ep(new_asoc,
1458 sctp_scope(sctp_source(chunk)), GFP_ATOMIC) < 0)
1459 goto nomem;
1460
1455 /* In the outbound INIT ACK the endpoint MUST copy its current 1461 /* In the outbound INIT ACK the endpoint MUST copy its current
1456 * Verification Tag and Peers Verification tag into a reserved 1462 * Verification Tag and Peers Verification tag into a reserved
1457 * place (local tie-tag and per tie-tag) within the state cookie. 1463 * place (local tie-tag and per tie-tag) within the state cookie.
@@ -1488,9 +1494,6 @@ static sctp_disposition_t sctp_sf_do_unexpected_init(
1488 sizeof(sctp_chunkhdr_t); 1494 sizeof(sctp_chunkhdr_t);
1489 } 1495 }
1490 1496
1491 if (sctp_assoc_set_bind_addr_from_ep(new_asoc, GFP_ATOMIC) < 0)
1492 goto nomem;
1493
1494 repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len); 1497 repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len);
1495 if (!repl) 1498 if (!repl)
1496 goto nomem; 1499 goto nomem;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 4085db99033d..66b1f02b17ba 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1080,6 +1080,13 @@ static int __sctp_connect(struct sock* sk,
1080 err = -ENOMEM; 1080 err = -ENOMEM;
1081 goto out_free; 1081 goto out_free;
1082 } 1082 }
1083
1084 err = sctp_assoc_set_bind_addr_from_ep(asoc, scope,
1085 GFP_KERNEL);
1086 if (err < 0) {
1087 goto out_free;
1088 }
1089
1083 } 1090 }
1084 1091
1085 /* Prime the peer's transport structures. */ 1092 /* Prime the peer's transport structures. */
@@ -1095,11 +1102,6 @@ static int __sctp_connect(struct sock* sk,
1095 walk_size += af->sockaddr_len; 1102 walk_size += af->sockaddr_len;
1096 } 1103 }
1097 1104
1098 err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL);
1099 if (err < 0) {
1100 goto out_free;
1101 }
1102
1103 /* In case the user of sctp_connectx() wants an association 1105 /* In case the user of sctp_connectx() wants an association
1104 * id back, assign one now. 1106 * id back, assign one now.
1105 */ 1107 */
@@ -1274,22 +1276,30 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
1274} 1276}
1275 1277
1276/* 1278/*
1277 * New (hopefully final) interface for the API. The option buffer is used 1279 * New (hopefully final) interface for the API.
1278 * both for the returned association id and the addresses. 1280 * We use the sctp_getaddrs_old structure so that use-space library
1281 * can avoid any unnecessary allocations. The only defferent part
1282 * is that we store the actual length of the address buffer into the
1283 * addrs_num structure member. That way we can re-use the existing
1284 * code.
1279 */ 1285 */
1280SCTP_STATIC int sctp_getsockopt_connectx3(struct sock* sk, int len, 1286SCTP_STATIC int sctp_getsockopt_connectx3(struct sock* sk, int len,
1281 char __user *optval, 1287 char __user *optval,
1282 int __user *optlen) 1288 int __user *optlen)
1283{ 1289{
1290 struct sctp_getaddrs_old param;
1284 sctp_assoc_t assoc_id = 0; 1291 sctp_assoc_t assoc_id = 0;
1285 int err = 0; 1292 int err = 0;
1286 1293
1287 if (len < sizeof(assoc_id)) 1294 if (len < sizeof(param))
1288 return -EINVAL; 1295 return -EINVAL;
1289 1296
1297 if (copy_from_user(&param, optval, sizeof(param)))
1298 return -EFAULT;
1299
1290 err = __sctp_setsockopt_connectx(sk, 1300 err = __sctp_setsockopt_connectx(sk,
1291 (struct sockaddr __user *)(optval + sizeof(assoc_id)), 1301 (struct sockaddr __user *)param.addrs,
1292 len - sizeof(assoc_id), &assoc_id); 1302 param.addr_num, &assoc_id);
1293 1303
1294 if (err == 0 || err == -EINPROGRESS) { 1304 if (err == 0 || err == -EINPROGRESS) {
1295 if (copy_to_user(optval, &assoc_id, sizeof(assoc_id))) 1305 if (copy_to_user(optval, &assoc_id, sizeof(assoc_id)))
@@ -1689,6 +1699,11 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
1689 goto out_unlock; 1699 goto out_unlock;
1690 } 1700 }
1691 asoc = new_asoc; 1701 asoc = new_asoc;
1702 err = sctp_assoc_set_bind_addr_from_ep(asoc, scope, GFP_KERNEL);
1703 if (err < 0) {
1704 err = -ENOMEM;
1705 goto out_free;
1706 }
1692 1707
1693 /* If the SCTP_INIT ancillary data is specified, set all 1708 /* If the SCTP_INIT ancillary data is specified, set all
1694 * the association init values accordingly. 1709 * the association init values accordingly.
@@ -1718,11 +1733,6 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
1718 err = -ENOMEM; 1733 err = -ENOMEM;
1719 goto out_free; 1734 goto out_free;
1720 } 1735 }
1721 err = sctp_assoc_set_bind_addr_from_ep(asoc, GFP_KERNEL);
1722 if (err < 0) {
1723 err = -ENOMEM;
1724 goto out_free;
1725 }
1726 } 1736 }
1727 1737
1728 /* ASSERT: we have a valid association at this point. */ 1738 /* ASSERT: we have a valid association at this point. */
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index c256e4839316..3b141bb32faf 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -308,7 +308,8 @@ void sctp_transport_route(struct sctp_transport *transport,
308 /* Initialize sk->sk_rcv_saddr, if the transport is the 308 /* Initialize sk->sk_rcv_saddr, if the transport is the
309 * association's active path for getsockname(). 309 * association's active path for getsockname().
310 */ 310 */
311 if (asoc && (transport == asoc->peer.active_path)) 311 if (asoc && (!asoc->peer.primary_path ||
312 (transport == asoc->peer.active_path)))
312 opt->pf->af->to_sk_saddr(&transport->saddr, 313 opt->pf->af->to_sk_saddr(&transport->saddr,
313 asoc->base.sk); 314 asoc->base.sk);
314 } else 315 } else