diff options
| author | Vlad Yasevich <vladislav.yasevich@hp.com> | 2007-12-07 01:50:54 -0500 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2007-12-07 04:07:49 -0500 |
| commit | 8e71a11c9f3c09a01fcb445772ffd61b140f2479 (patch) | |
| tree | a0fb2c002d472252ea060c88f8dfda6ddb23b3fc | |
| parent | f26f7c480555812ca7c4037e0a50fa54afe2cb4a (diff) | |
[SCTP]: Fix the bind_addr info during migration.
During accept/migrate the code attempts to copy the addresses from
the parent endpoint to the new endpoint. However, if the parent
was bound to a wildcard address, then we end up pointlessly copying
all of the current addresses on the system.
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | include/net/sctp/structs.h | 3 | ||||
| -rw-r--r-- | net/sctp/bind_addr.c | 26 | ||||
| -rw-r--r-- | net/sctp/socket.c | 12 |
3 files changed, 31 insertions, 10 deletions
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index eb3113c38a94..002a00a4e6be 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
| @@ -1184,6 +1184,9 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest, | |||
| 1184 | const struct sctp_bind_addr *src, | 1184 | const struct sctp_bind_addr *src, |
| 1185 | sctp_scope_t scope, gfp_t gfp, | 1185 | sctp_scope_t scope, gfp_t gfp, |
| 1186 | int flags); | 1186 | int flags); |
| 1187 | int sctp_bind_addr_dup(struct sctp_bind_addr *dest, | ||
| 1188 | const struct sctp_bind_addr *src, | ||
| 1189 | gfp_t gfp); | ||
| 1187 | int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *, | 1190 | int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *, |
| 1188 | __u8 use_as_src, gfp_t gfp); | 1191 | __u8 use_as_src, gfp_t gfp); |
| 1189 | int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *); | 1192 | int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *); |
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index cae95af9a8cc..6a7d01091f0c 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c | |||
| @@ -105,6 +105,32 @@ out: | |||
| 105 | return error; | 105 | return error; |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | /* Exactly duplicate the address lists. This is necessary when doing | ||
| 109 | * peer-offs and accepts. We don't want to put all the current system | ||
| 110 | * addresses into the endpoint. That's useless. But we do want duplicat | ||
| 111 | * the list of bound addresses that the older endpoint used. | ||
| 112 | */ | ||
| 113 | int sctp_bind_addr_dup(struct sctp_bind_addr *dest, | ||
| 114 | const struct sctp_bind_addr *src, | ||
| 115 | gfp_t gfp) | ||
| 116 | { | ||
| 117 | struct sctp_sockaddr_entry *addr; | ||
| 118 | struct list_head *pos; | ||
| 119 | int error = 0; | ||
| 120 | |||
| 121 | /* All addresses share the same port. */ | ||
| 122 | dest->port = src->port; | ||
| 123 | |||
| 124 | list_for_each(pos, &src->address_list) { | ||
| 125 | addr = list_entry(pos, struct sctp_sockaddr_entry, list); | ||
| 126 | error = sctp_add_bind_addr(dest, &addr->a, 1, gfp); | ||
| 127 | if (error < 0) | ||
| 128 | break; | ||
| 129 | } | ||
| 130 | |||
| 131 | return error; | ||
| 132 | } | ||
| 133 | |||
| 108 | /* Initialize the SCTP_bind_addr structure for either an endpoint or | 134 | /* Initialize the SCTP_bind_addr structure for either an endpoint or |
| 109 | * an association. | 135 | * an association. |
| 110 | */ | 136 | */ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 9f5d7930f54d..ea9649ca0b2a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -6326,7 +6326,6 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
| 6326 | struct sk_buff *skb, *tmp; | 6326 | struct sk_buff *skb, *tmp; |
| 6327 | struct sctp_ulpevent *event; | 6327 | struct sctp_ulpevent *event; |
| 6328 | struct sctp_bind_hashbucket *head; | 6328 | struct sctp_bind_hashbucket *head; |
| 6329 | int flags = 0; | ||
| 6330 | 6329 | ||
| 6331 | /* Migrate socket buffer sizes and all the socket level options to the | 6330 | /* Migrate socket buffer sizes and all the socket level options to the |
| 6332 | * new socket. | 6331 | * new socket. |
| @@ -6356,15 +6355,8 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
| 6356 | /* Copy the bind_addr list from the original endpoint to the new | 6355 | /* Copy the bind_addr list from the original endpoint to the new |
| 6357 | * endpoint so that we can handle restarts properly | 6356 | * endpoint so that we can handle restarts properly |
| 6358 | */ | 6357 | */ |
| 6359 | if (PF_INET6 == assoc->base.sk->sk_family) | 6358 | sctp_bind_addr_dup(&newsp->ep->base.bind_addr, |
| 6360 | flags = SCTP_ADDR6_ALLOWED; | 6359 | &oldsp->ep->base.bind_addr, GFP_KERNEL); |
| 6361 | if (assoc->peer.ipv4_address) | ||
| 6362 | flags |= SCTP_ADDR4_PEERSUPP; | ||
| 6363 | if (assoc->peer.ipv6_address) | ||
| 6364 | flags |= SCTP_ADDR6_PEERSUPP; | ||
| 6365 | sctp_bind_addr_copy(&newsp->ep->base.bind_addr, | ||
| 6366 | &oldsp->ep->base.bind_addr, | ||
| 6367 | SCTP_SCOPE_GLOBAL, GFP_KERNEL, flags); | ||
| 6368 | 6360 | ||
| 6369 | /* Move any messages in the old socket's receive queue that are for the | 6361 | /* Move any messages in the old socket's receive queue that are for the |
| 6370 | * peeled off association to the new socket's receive queue. | 6362 | * peeled off association to the new socket's receive queue. |
