diff options
author | Michio Honda <micchie@sfc.wide.ad.jp> | 2011-04-26 19:32:51 +0900 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-06-02 02:04:53 -0700 |
commit | 9f7d653b67aed2d92540fbb0a8adaf32fcf352ae (patch) | |
tree | 1e128f1465135dd70f202b8720c32cbfd536cb68 /net/sctp/socket.c | |
parent | 3ced2dddf10f26f0aaff96f3345a3d876cea62f8 (diff) |
sctp: Add Auto-ASCONF support (core).
SCTP reconfigure the IP addresses in the association by using
ASCONF chunks as mentioned in RFC5061. For example, we can
start to use the newly configured IP address in the existing
association. This patch implements automatic ASCONF operation
in the SCTP stack with address events in the host computer,
which is called auto_asconf.
Signed-off-by: Michio Honda <micchie@sfc.wide.ad.jp>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Acked-by: Wei Yongjun <yjwei@cn.fujitsu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp/socket.c')
-rw-r--r-- | net/sctp/socket.c | 46 |
1 files changed, 42 insertions, 4 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 6766913a53e..7eb1f1a736f 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -811,6 +811,28 @@ out: return retval; } +/* set addr events to assocs in the endpoint. ep and addr_wq must be locked */ +int sctp_asconf_mgmt(struct sctp_sock *sp, struct sctp_sockaddr_entry *addrw) +{ + struct sock *sk = sctp_opt2sk(sp); + union sctp_addr *addr; + struct sctp_af *af; + + /* It is safe to write port space in caller. */ + addr = &addrw->a; + addr->v4.sin_port = htons(sp->ep->base.bind_addr.port); + af = sctp_get_af_specific(addr->sa.sa_family); + if (!af) + return -EINVAL; + if (sctp_verify_addr(sk, addr, af->sockaddr_len)) + return -EINVAL; + + if (addrw->state == SCTP_ADDR_NEW) + return sctp_send_asconf_add_ip(sk, (struct sockaddr *)addr, 1); + else + return sctp_send_asconf_del_ip(sk, (struct sockaddr *)addr, 1); +} + /* Helper for tunneling sctp_bindx() requests through sctp_setsockopt() * * API 8.1 @@ -3763,6 +3785,12 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) local_bh_disable(); percpu_counter_inc(&sctp_sockets_allocated); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); + if (sctp_default_auto_asconf) { + list_add_tail(&sp->auto_asconf_list, + &sctp_auto_asconf_splist); + sp->do_auto_asconf = 1; + } else + sp->do_auto_asconf = 0; local_bh_enable(); return 0; @@ -3771,13 +3799,17 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) /* Cleanup any SCTP per socket resources. */ SCTP_STATIC void sctp_destroy_sock(struct sock *sk) { - struct sctp_endpoint *ep; + struct sctp_sock *sp; SCTP_DEBUG_PRINTK("sctp_destroy_sock(sk: %p)\n", sk); /* Release our hold on the endpoint. */ - ep = sctp_sk(sk)->ep; - sctp_endpoint_free(ep); + sp = sctp_sk(sk); + if (sp->do_auto_asconf) { + sp->do_auto_asconf = 0; + list_del(&sp->auto_asconf_list); + } + sctp_endpoint_free(sp->ep); local_bh_disable(); percpu_counter_dec(&sctp_sockets_allocated); sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); @@ -6512,6 +6544,7 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, struct sk_buff *skb, *tmp; struct sctp_ulpevent *event; struct sctp_bind_hashbucket *head; + struct list_head tmplist; /* Migrate socket buffer sizes and all the socket level options to the * new socket. @@ -6519,7 +6552,12 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, newsk->sk_sndbuf = oldsk->sk_sndbuf; newsk->sk_rcvbuf = oldsk->sk_rcvbuf; /* Brute force copy old sctp opt. */ - inet_sk_copy_descendant(newsk, oldsk); + if (oldsp->do_auto_asconf) { + memcpy(&tmplist, &newsp->auto_asconf_list, sizeof(tmplist)); + inet_sk_copy_descendant(newsk, oldsk); + memcpy(&newsp->auto_asconf_list, &tmplist, sizeof(tmplist)); + } else + inet_sk_copy_descendant(newsk, oldsk); /* Restore the ep value that was overwritten with the above structure * copy. |