#include <net/ndisc.h>
#include <net/addrconf.h>
#include <net/ip6_route.h>
+#include <net/inet_common.h>
#include <net/ip6_checksum.h>
/* Big mc list lock for all the sockets */
static DEFINE_RWLOCK(ipv6_sk_mc_lock);
-int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr);
-
static void igmp6_join_group(struct ifmcaddr6 *ma);
static void igmp6_leave_group(struct ifmcaddr6 *ma);
static void igmp6_timer_handler(unsigned long data);
* socket join on multicast group
*/
-int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
+int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
{
struct net_device *dev = NULL;
struct ipv6_mc_socklist *mc_lst;
/*
* socket leave on multicast group
*/
-int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
+int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
{
struct ipv6_pinfo *np = inet6_sk(sk);
struct ipv6_mc_socklist *mc_lst, **lnk;
return err;
}
-int inet6_mc_check(struct sock *sk, struct in6_addr *mc_addr,
- struct in6_addr *src_addr)
+int inet6_mc_check(struct sock *sk, const struct in6_addr *mc_addr,
+ const struct in6_addr *src_addr)
{
struct ipv6_pinfo *np = inet6_sk(sk);
struct ipv6_mc_socklist *mc;
/*
* device multicast group inc (add if not found)
*/
-int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
+int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr)
{
struct ifmcaddr6 *mc;
struct inet6_dev *idev;
/*
* device multicast group del
*/
-int __ipv6_dev_mc_dec(struct inet6_dev *idev, struct in6_addr *addr)
+int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr)
{
struct ifmcaddr6 *ma, **map;
return -ENOENT;
}
-int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr)
+int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr)
{
struct inet6_dev *idev = in6_dev_get(dev);
int err;
/*
* check if the interface/address pair is valid
*/
-int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *group,
- struct in6_addr *src_addr)
+int ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
+ const struct in6_addr *src_addr)
{
struct inet6_dev *idev;
struct ifmcaddr6 *mc;
struct sk_buff *skb;
struct mld2_report *pmr;
struct in6_addr addr_buf;
+ const struct in6_addr *saddr;
int err;
u8 ra[8] = { IPPROTO_ICMPV6, 0,
IPV6_TLV_ROUTERALERT, 2, 0, 0,
IPV6_TLV_PADN, 0 };
/* we assume size > sizeof(ra) here */
- skb = sock_alloc_send_skb(sk, size + LL_RESERVED_SPACE(dev), 1, &err);
+ skb = sock_alloc_send_skb(sk, size + LL_ALLOCATED_SPACE(dev), 1, &err);
if (!skb)
return NULL;
* use unspecified address as the source address
* when a valid link-local address is not available.
*/
- memset(&addr_buf, 0, sizeof(addr_buf));
- }
+ saddr = &in6addr_any;
+ } else
+ saddr = &addr_buf;
- ip6_nd_hdr(sk, skb, dev, &addr_buf, &mld2_all_mcr, NEXTHDR_HOP, 0);
+ ip6_nd_hdr(sk, skb, dev, saddr, &mld2_all_mcr, NEXTHDR_HOP, 0);
memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra));
struct inet6_dev *idev;
struct sk_buff *skb;
struct icmp6hdr *hdr;
- struct in6_addr *snd_addr;
+ const struct in6_addr *snd_addr, *saddr;
struct in6_addr *addrp;
struct in6_addr addr_buf;
- struct in6_addr all_routers;
int err, len, payload_len, full_len;
u8 ra[8] = { IPPROTO_ICMPV6, 0,
IPV6_TLV_ROUTERALERT, 2, 0, 0,
IP6_INC_STATS(__in6_dev_get(dev),
IPSTATS_MIB_OUTREQUESTS);
rcu_read_unlock();
- snd_addr = addr;
- if (type == ICMPV6_MGM_REDUCTION) {
- snd_addr = &all_routers;
- ipv6_addr_all_routers(&all_routers);
- }
+ if (type == ICMPV6_MGM_REDUCTION)
+ snd_addr = &in6addr_linklocal_allrouters;
+ else
+ snd_addr = addr;
len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
payload_len = len + sizeof(ra);
full_len = sizeof(struct ipv6hdr) + payload_len;
- skb = sock_alloc_send_skb(sk, LL_RESERVED_SPACE(dev) + full_len, 1, &err);
+ skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + full_len, 1, &err);
if (skb == NULL) {
rcu_read_lock();
* use unspecified address as the source address
* when a valid link-local address is not available.
*/
- memset(&addr_buf, 0, sizeof(addr_buf));
- }
+ saddr = &in6addr_any;
+ } else
+ saddr = &addr_buf;
- ip6_nd_hdr(sk, skb, dev, &addr_buf, snd_addr, NEXTHDR_HOP, payload_len);
+ ip6_nd_hdr(sk, skb, dev, saddr, snd_addr, NEXTHDR_HOP, payload_len);
memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra));
addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr));
ipv6_addr_copy(addrp, addr);
- hdr->icmp6_cksum = csum_ipv6_magic(&addr_buf, snd_addr, len,
+ hdr->icmp6_cksum = csum_ipv6_magic(saddr, snd_addr, len,
IPPROTO_ICMPV6,
csum_partial((__u8 *) hdr, len, 0));
void ipv6_mc_destroy_dev(struct inet6_dev *idev)
{
struct ifmcaddr6 *i;
- struct in6_addr maddr;
/* Deactivate timers */
ipv6_mc_down(idev);
/* Delete all-nodes address. */
- ipv6_addr_all_nodes(&maddr);
-
/* We cannot call ipv6_dev_mc_dec() directly, our caller in
* addrconf.c has NULL'd out dev->ip6_ptr so in6_dev_get() will
* fail.
*/
- __ipv6_dev_mc_dec(idev, &maddr);
+ __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allnodes);
- if (idev->cnf.forwarding) {
- ipv6_addr_all_routers(&maddr);
- __ipv6_dev_mc_dec(idev, &maddr);
- }
+ if (idev->cnf.forwarding)
+ __ipv6_dev_mc_dec(idev, &in6addr_linklocal_allrouters);
write_lock_bh(&idev->lock);
while ((i = idev->mc_list) != NULL) {
static int igmp6_net_init(struct net *net)
{
- struct ipv6_pinfo *np;
- struct socket *sock;
- struct sock *sk;
int err;
- err = sock_create_kern(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &sock);
+ err = inet_ctl_sock_create(&net->ipv6.igmp_sk, PF_INET6,
+ SOCK_RAW, IPPROTO_ICMPV6, net);
if (err < 0) {
printk(KERN_ERR
"Failed to initialize the IGMP6 control socket (err %d).\n",
goto out;
}
- net->ipv6.igmp_sk = sk = sock->sk;
- sk_change_net(sk, net);
- sk->sk_allocation = GFP_ATOMIC;
- sk->sk_prot->unhash(sk);
-
- np = inet6_sk(sk);
- np->hop_limit = 1;
+ inet6_sk(net->ipv6.igmp_sk)->hop_limit = 1;
err = igmp6_proc_init(net);
if (err)
return err;
out_sock_create:
- sk_release_kernel(net->ipv6.igmp_sk);
+ inet_ctl_sock_destroy(net->ipv6.igmp_sk);
goto out;
}
static void igmp6_net_exit(struct net *net)
{
- sk_release_kernel(net->ipv6.igmp_sk);
+ inet_ctl_sock_destroy(net->ipv6.igmp_sk);
igmp6_proc_exit(net);
}