diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2009-11-10 03:57:34 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-13 22:56:50 -0500 |
commit | 409b95aff3583c05ac7a9247fa3d8c9aa7f9cae3 (patch) | |
tree | a8cd8135f974b8f1c6ef9d092755e1ac5b190b2f /net/sctp/socket.c | |
parent | d792c1006fe92448217b71513d3955868358271d (diff) |
sctp: Set source addresses on the association before adding transports
Recent commit 8da645e101a8c20c6073efda3c7cc74eec01b87f
sctp: Get rid of an extra routing lookup when adding a transport
introduced a regression in the connection setup. The behavior was
different between IPv4 and IPv6. IPv4 case ended up working because the
route lookup routing returned a NULL route, which triggered another
route lookup later in the output patch that succeeded. In the IPv6 case,
a valid route was returned for first call, but we could not find a valid
source address at the time since the source addresses were not set on the
association yet. Thus resulted in a hung connection.
The solution is to set the source addresses on the association prior to
adding peers.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 22 |
1 files changed, 12 insertions, 10 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index c8d05758661d..bf705ba97231 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 | */ |
@@ -1689,6 +1691,11 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1689 | goto out_unlock; | 1691 | goto out_unlock; |
1690 | } | 1692 | } |
1691 | asoc = new_asoc; | 1693 | asoc = new_asoc; |
1694 | err = sctp_assoc_set_bind_addr_from_ep(asoc, scope, GFP_KERNEL); | ||
1695 | if (err < 0) { | ||
1696 | err = -ENOMEM; | ||
1697 | goto out_free; | ||
1698 | } | ||
1692 | 1699 | ||
1693 | /* If the SCTP_INIT ancillary data is specified, set all | 1700 | /* If the SCTP_INIT ancillary data is specified, set all |
1694 | * the association init values accordingly. | 1701 | * the association init values accordingly. |
@@ -1718,11 +1725,6 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1718 | err = -ENOMEM; | 1725 | err = -ENOMEM; |
1719 | goto out_free; | 1726 | goto out_free; |
1720 | } | 1727 | } |
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 | } | 1728 | } |
1727 | 1729 | ||
1728 | /* ASSERT: we have a valid association at this point. */ | 1730 | /* ASSERT: we have a valid association at this point. */ |