diff options
author | Lorenzo Colitti <lorenzo@google.com> | 2011-03-10 20:24:12 -0800 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:38:31 -0800 |
commit | c0b779e1c5220b812c5690727fb646b731101fff (patch) | |
tree | 626e2c338338d797854490a35f646b29b421b477 /net/ipv6 | |
parent | fafc4cc382454fbf40af9263e64473ae4d955b0c (diff) |
net: Support nuking IPv6 sockets as well as IPv4.
On Linux, when an interface goes down all its IPv6
addresses are deleted, so relying on knowing the previous
IPv6 addresses on the interface is brittle. Instead,
support nuking all sockets that are bound to IP addresses
that are not configured and up on the system. This
behaviour is triggered by specifying the unspecified
address (:: or 0.0.0.0). If an IP address is specified, the
behaviour is unchanged, except the ioctl now supports IPv6
as well as IPv4.
Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/af_inet6.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 4eb4d74d0a96..4252b3cc183d 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -494,6 +494,21 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr, EXPORT_SYMBOL(inet6_getname); +int inet6_killaddr_ioctl(struct net *net, void __user *arg) { + struct in6_ifreq ireq; + struct sockaddr_in6 sin6; + + if (!capable(CAP_NET_ADMIN)) + return -EACCES; + + if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq))) + return -EFAULT; + + sin6.sin6_family = AF_INET6; + ipv6_addr_copy(&sin6.sin6_addr, &ireq.ifr6_addr); + return tcp_nuke_addr(net, (struct sockaddr *) &sin6); +} + int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct sock *sk = sock->sk; @@ -518,6 +533,8 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return addrconf_del_ifaddr(net, (void __user *) arg); case SIOCSIFDSTADDR: return addrconf_set_dstaddr(net, (void __user *) arg); + case SIOCKILLADDR: + return inet6_killaddr_ioctl(net, (void __user *) arg); default: if (!sk->sk_prot->ioctl) return -ENOIOCTLCMD; |