diff options
author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2007-08-01 10:56:43 -0400 |
---|---|---|
committer | Vlad Yasevich <vladislav.yasevich@hp.com> | 2007-08-01 11:19:06 -0400 |
commit | e4d1feab5df035312494ce3037ac5f041d0f5fc9 (patch) | |
tree | 9ed83f1037b0df8478c29143357ea4e66314d364 /net/sctp/socket.c | |
parent | b225b884a18a1932db5414abd3ef94a45e4e348e (diff) |
SCTP: IPv4 mapped addr not returned in SCTPv6 accept()
When issuing a connect call on an AF_INET6 sctp socket with
a IPv4-mapped destination, the peer address that is returned
by getpeeraddr() should be v4-mapped as well.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index be743d4a7c09..01c6364245b7 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -975,7 +975,7 @@ static int __sctp_connect(struct sock* sk, | |||
975 | int err = 0; | 975 | int err = 0; |
976 | int addrcnt = 0; | 976 | int addrcnt = 0; |
977 | int walk_size = 0; | 977 | int walk_size = 0; |
978 | union sctp_addr *sa_addr; | 978 | union sctp_addr *sa_addr = NULL; |
979 | void *addr_buf; | 979 | void *addr_buf; |
980 | unsigned short port; | 980 | unsigned short port; |
981 | unsigned int f_flags = 0; | 981 | unsigned int f_flags = 0; |
@@ -1009,7 +1009,10 @@ static int __sctp_connect(struct sock* sk, | |||
1009 | goto out_free; | 1009 | goto out_free; |
1010 | } | 1010 | } |
1011 | 1011 | ||
1012 | err = sctp_verify_addr(sk, sa_addr, af->sockaddr_len); | 1012 | /* Save current address so we can work with it */ |
1013 | memcpy(&to, sa_addr, af->sockaddr_len); | ||
1014 | |||
1015 | err = sctp_verify_addr(sk, &to, af->sockaddr_len); | ||
1013 | if (err) | 1016 | if (err) |
1014 | goto out_free; | 1017 | goto out_free; |
1015 | 1018 | ||
@@ -1019,12 +1022,11 @@ static int __sctp_connect(struct sock* sk, | |||
1019 | if (asoc && asoc->peer.port && asoc->peer.port != port) | 1022 | if (asoc && asoc->peer.port && asoc->peer.port != port) |
1020 | goto out_free; | 1023 | goto out_free; |
1021 | 1024 | ||
1022 | memcpy(&to, sa_addr, af->sockaddr_len); | ||
1023 | 1025 | ||
1024 | /* Check if there already is a matching association on the | 1026 | /* Check if there already is a matching association on the |
1025 | * endpoint (other than the one created here). | 1027 | * endpoint (other than the one created here). |
1026 | */ | 1028 | */ |
1027 | asoc2 = sctp_endpoint_lookup_assoc(ep, sa_addr, &transport); | 1029 | asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport); |
1028 | if (asoc2 && asoc2 != asoc) { | 1030 | if (asoc2 && asoc2 != asoc) { |
1029 | if (asoc2->state >= SCTP_STATE_ESTABLISHED) | 1031 | if (asoc2->state >= SCTP_STATE_ESTABLISHED) |
1030 | err = -EISCONN; | 1032 | err = -EISCONN; |
@@ -1037,7 +1039,7 @@ static int __sctp_connect(struct sock* sk, | |||
1037 | * make sure that there is no peeled-off association matching | 1039 | * make sure that there is no peeled-off association matching |
1038 | * the peer address even on another socket. | 1040 | * the peer address even on another socket. |
1039 | */ | 1041 | */ |
1040 | if (sctp_endpoint_is_peeled_off(ep, sa_addr)) { | 1042 | if (sctp_endpoint_is_peeled_off(ep, &to)) { |
1041 | err = -EADDRNOTAVAIL; | 1043 | err = -EADDRNOTAVAIL; |
1042 | goto out_free; | 1044 | goto out_free; |
1043 | } | 1045 | } |
@@ -1068,7 +1070,7 @@ static int __sctp_connect(struct sock* sk, | |||
1068 | } | 1070 | } |
1069 | } | 1071 | } |
1070 | 1072 | ||
1071 | scope = sctp_scope(sa_addr); | 1073 | scope = sctp_scope(&to); |
1072 | asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); | 1074 | asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); |
1073 | if (!asoc) { | 1075 | if (!asoc) { |
1074 | err = -ENOMEM; | 1076 | err = -ENOMEM; |
@@ -1077,7 +1079,7 @@ static int __sctp_connect(struct sock* sk, | |||
1077 | } | 1079 | } |
1078 | 1080 | ||
1079 | /* Prime the peer's transport structures. */ | 1081 | /* Prime the peer's transport structures. */ |
1080 | transport = sctp_assoc_add_peer(asoc, sa_addr, GFP_KERNEL, | 1082 | transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL, |
1081 | SCTP_UNKNOWN); | 1083 | SCTP_UNKNOWN); |
1082 | if (!transport) { | 1084 | if (!transport) { |
1083 | err = -ENOMEM; | 1085 | err = -ENOMEM; |
@@ -1101,8 +1103,8 @@ static int __sctp_connect(struct sock* sk, | |||
1101 | 1103 | ||
1102 | /* Initialize sk's dport and daddr for getpeername() */ | 1104 | /* Initialize sk's dport and daddr for getpeername() */ |
1103 | inet_sk(sk)->dport = htons(asoc->peer.port); | 1105 | inet_sk(sk)->dport = htons(asoc->peer.port); |
1104 | af = sctp_get_af_specific(to.sa.sa_family); | 1106 | af = sctp_get_af_specific(sa_addr->sa.sa_family); |
1105 | af->to_sk_daddr(&to, sk); | 1107 | af->to_sk_daddr(sa_addr, sk); |
1106 | sk->sk_err = 0; | 1108 | sk->sk_err = 0; |
1107 | 1109 | ||
1108 | /* in-kernel sockets don't generally have a file allocated to them | 1110 | /* in-kernel sockets don't generally have a file allocated to them |