Merge with Linux 2.5.48.
[linux-2.6/linux-mips.git] / net / ipv6 / mcast.c
blob16870b1d3d50482586b94df8eef1a26410aac5d7
1 /*
2 * Multicast support for IPv6
3 * Linux INET6 implementation
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
8 * $Id: mcast.c,v 1.40 2002/02/08 03:57:19 davem Exp $
10 * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
18 /* Changes:
20 * yoshfuji : fix format of router-alert option
21 * YOSHIFUJI Hideaki @USAGI:
22 * Fixed source address for MLD message based on
23 * <draft-ietf-magma-mld-source-02.txt>.
24 * YOSHIFUJI Hideaki @USAGI:
25 * - Ignore Queries for invalid addresses.
26 * - MLD for link-local addresses.
29 #define __NO_VERSION__
30 #include <linux/config.h>
31 #include <linux/module.h>
32 #include <linux/errno.h>
33 #include <linux/types.h>
34 #include <linux/string.h>
35 #include <linux/socket.h>
36 #include <linux/sockios.h>
37 #include <linux/jiffies.h>
38 #include <linux/net.h>
39 #include <linux/in6.h>
40 #include <linux/netdevice.h>
41 #include <linux/if_arp.h>
42 #include <linux/route.h>
43 #include <linux/init.h>
44 #include <linux/proc_fs.h>
46 #include <net/sock.h>
47 #include <net/snmp.h>
49 #include <net/ipv6.h>
50 #include <net/protocol.h>
51 #include <net/if_inet6.h>
52 #include <net/ndisc.h>
53 #include <net/addrconf.h>
54 #include <net/ip6_route.h>
56 #include <net/checksum.h>
58 /* Set to 3 to get tracing... */
59 #define MCAST_DEBUG 2
61 #if MCAST_DEBUG >= 3
62 #define MDBG(x) printk x
63 #else
64 #define MDBG(x)
65 #endif
67 /* Big mc list lock for all the sockets */
68 static rwlock_t ipv6_sk_mc_lock = RW_LOCK_UNLOCKED;
70 static struct socket *igmp6_socket;
72 static void igmp6_join_group(struct ifmcaddr6 *ma);
73 static void igmp6_leave_group(struct ifmcaddr6 *ma);
74 static void igmp6_timer_handler(unsigned long data);
76 #define IGMP6_UNSOLICITED_IVAL (10*HZ)
79 * socket join on multicast group
82 int ipv6_sock_mc_join(struct sock *sk, int ifindex, struct in6_addr *addr)
84 struct net_device *dev = NULL;
85 struct ipv6_mc_socklist *mc_lst;
86 struct ipv6_pinfo *np = inet6_sk(sk);
87 int err;
89 if (!(ipv6_addr_type(addr) & IPV6_ADDR_MULTICAST))
90 return -EINVAL;
92 mc_lst = sock_kmalloc(sk, sizeof(struct ipv6_mc_socklist), GFP_KERNEL);
94 if (mc_lst == NULL)
95 return -ENOMEM;
97 mc_lst->next = NULL;
98 memcpy(&mc_lst->addr, addr, sizeof(struct in6_addr));
100 if (ifindex == 0) {
101 struct rt6_info *rt;
102 rt = rt6_lookup(addr, NULL, 0, 0);
103 if (rt) {
104 dev = rt->rt6i_dev;
105 dev_hold(dev);
106 dst_release(&rt->u.dst);
108 } else
109 dev = dev_get_by_index(ifindex);
111 if (dev == NULL) {
112 sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
113 return -ENODEV;
116 mc_lst->ifindex = dev->ifindex;
119 * now add/increase the group membership on the device
122 err = ipv6_dev_mc_inc(dev, addr);
124 if (err) {
125 sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
126 dev_put(dev);
127 return err;
130 write_lock_bh(&ipv6_sk_mc_lock);
131 mc_lst->next = np->ipv6_mc_list;
132 np->ipv6_mc_list = mc_lst;
133 write_unlock_bh(&ipv6_sk_mc_lock);
135 dev_put(dev);
137 return 0;
141 * socket leave on multicast group
143 int ipv6_sock_mc_drop(struct sock *sk, int ifindex, struct in6_addr *addr)
145 struct ipv6_pinfo *np = inet6_sk(sk);
146 struct ipv6_mc_socklist *mc_lst, **lnk;
148 write_lock_bh(&ipv6_sk_mc_lock);
149 for (lnk = &np->ipv6_mc_list; (mc_lst = *lnk) !=NULL ; lnk = &mc_lst->next) {
150 if ((ifindex == 0 || mc_lst->ifindex == ifindex) &&
151 ipv6_addr_cmp(&mc_lst->addr, addr) == 0) {
152 struct net_device *dev;
154 *lnk = mc_lst->next;
155 write_unlock_bh(&ipv6_sk_mc_lock);
157 if ((dev = dev_get_by_index(mc_lst->ifindex)) != NULL) {
158 ipv6_dev_mc_dec(dev, &mc_lst->addr);
159 dev_put(dev);
161 sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
162 return 0;
165 write_unlock_bh(&ipv6_sk_mc_lock);
167 return -ENOENT;
170 void ipv6_sock_mc_close(struct sock *sk)
172 struct ipv6_pinfo *np = inet6_sk(sk);
173 struct ipv6_mc_socklist *mc_lst;
175 write_lock_bh(&ipv6_sk_mc_lock);
176 while ((mc_lst = np->ipv6_mc_list) != NULL) {
177 struct net_device *dev;
179 np->ipv6_mc_list = mc_lst->next;
180 write_unlock_bh(&ipv6_sk_mc_lock);
182 dev = dev_get_by_index(mc_lst->ifindex);
183 if (dev) {
184 ipv6_dev_mc_dec(dev, &mc_lst->addr);
185 dev_put(dev);
188 sock_kfree_s(sk, mc_lst, sizeof(*mc_lst));
190 write_lock_bh(&ipv6_sk_mc_lock);
192 write_unlock_bh(&ipv6_sk_mc_lock);
195 int inet6_mc_check(struct sock *sk, struct in6_addr *addr)
197 struct ipv6_pinfo *np = inet6_sk(sk);
198 struct ipv6_mc_socklist *mc;
200 read_lock(&ipv6_sk_mc_lock);
201 for (mc = np->ipv6_mc_list; mc; mc = mc->next) {
202 if (ipv6_addr_cmp(&mc->addr, addr) == 0) {
203 read_unlock(&ipv6_sk_mc_lock);
204 return 1;
207 read_unlock(&ipv6_sk_mc_lock);
209 return 0;
212 static void ma_put(struct ifmcaddr6 *mc)
214 if (atomic_dec_and_test(&mc->mca_refcnt)) {
215 in6_dev_put(mc->idev);
216 kfree(mc);
220 static int igmp6_group_added(struct ifmcaddr6 *mc)
222 struct net_device *dev = mc->idev->dev;
223 char buf[MAX_ADDR_LEN];
225 spin_lock_bh(&mc->mca_lock);
226 if (!(mc->mca_flags&MAF_LOADED)) {
227 mc->mca_flags |= MAF_LOADED;
228 if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0)
229 dev_mc_add(dev, buf, dev->addr_len, 0);
231 spin_unlock_bh(&mc->mca_lock);
233 if (dev->flags&IFF_UP)
234 igmp6_join_group(mc);
235 return 0;
238 static int igmp6_group_dropped(struct ifmcaddr6 *mc)
240 struct net_device *dev = mc->idev->dev;
241 char buf[MAX_ADDR_LEN];
243 spin_lock_bh(&mc->mca_lock);
244 if (mc->mca_flags&MAF_LOADED) {
245 mc->mca_flags &= ~MAF_LOADED;
246 if (ndisc_mc_map(&mc->mca_addr, buf, dev, 0) == 0)
247 dev_mc_delete(dev, buf, dev->addr_len, 0);
249 spin_unlock_bh(&mc->mca_lock);
251 if (dev->flags&IFF_UP)
252 igmp6_leave_group(mc);
253 return 0;
258 * device multicast group inc (add if not found)
260 int ipv6_dev_mc_inc(struct net_device *dev, struct in6_addr *addr)
262 struct ifmcaddr6 *mc;
263 struct inet6_dev *idev;
265 idev = in6_dev_get(dev);
267 if (idev == NULL)
268 return -EINVAL;
270 write_lock_bh(&idev->lock);
271 if (idev->dead) {
272 write_unlock_bh(&idev->lock);
273 in6_dev_put(idev);
274 return -ENODEV;
277 for (mc = idev->mc_list; mc; mc = mc->next) {
278 if (ipv6_addr_cmp(&mc->mca_addr, addr) == 0) {
279 mc->mca_users++;
280 write_unlock_bh(&idev->lock);
281 in6_dev_put(idev);
282 return 0;
287 * not found: create a new one.
290 mc = kmalloc(sizeof(struct ifmcaddr6), GFP_ATOMIC);
292 if (mc == NULL) {
293 write_unlock_bh(&idev->lock);
294 in6_dev_put(idev);
295 return -ENOMEM;
298 memset(mc, 0, sizeof(struct ifmcaddr6));
299 init_timer(&mc->mca_timer);
300 mc->mca_timer.function = igmp6_timer_handler;
301 mc->mca_timer.data = (unsigned long) mc;
303 memcpy(&mc->mca_addr, addr, sizeof(struct in6_addr));
304 mc->idev = idev;
305 mc->mca_users = 1;
306 atomic_set(&mc->mca_refcnt, 2);
307 mc->mca_lock = SPIN_LOCK_UNLOCKED;
309 mc->next = idev->mc_list;
310 idev->mc_list = mc;
311 write_unlock_bh(&idev->lock);
313 igmp6_group_added(mc);
314 ma_put(mc);
315 return 0;
319 * device multicast group del
321 int ipv6_dev_mc_dec(struct net_device *dev, struct in6_addr *addr)
323 struct inet6_dev *idev;
324 struct ifmcaddr6 *ma, **map;
326 idev = in6_dev_get(dev);
327 if (idev == NULL)
328 return -ENODEV;
330 write_lock_bh(&idev->lock);
331 for (map = &idev->mc_list; (ma=*map) != NULL; map = &ma->next) {
332 if (ipv6_addr_cmp(&ma->mca_addr, addr) == 0) {
333 if (--ma->mca_users == 0) {
334 *map = ma->next;
335 write_unlock_bh(&idev->lock);
337 igmp6_group_dropped(ma);
339 ma_put(ma);
340 in6_dev_put(idev);
341 return 0;
343 write_unlock_bh(&idev->lock);
344 in6_dev_put(idev);
345 return 0;
348 write_unlock_bh(&idev->lock);
349 in6_dev_put(idev);
351 return -ENOENT;
355 * check if the interface/address pair is valid
357 int ipv6_chk_mcast_addr(struct net_device *dev, struct in6_addr *addr)
359 struct inet6_dev *idev;
360 struct ifmcaddr6 *mc;
362 idev = in6_dev_get(dev);
363 if (idev) {
364 read_lock_bh(&idev->lock);
365 for (mc = idev->mc_list; mc; mc=mc->next) {
366 if (ipv6_addr_cmp(&mc->mca_addr, addr) == 0) {
367 read_unlock_bh(&idev->lock);
368 in6_dev_put(idev);
369 return 1;
372 read_unlock_bh(&idev->lock);
373 in6_dev_put(idev);
375 return 0;
379 * IGMP handling (alias multicast ICMPv6 messages)
382 static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime)
384 unsigned long delay = resptime;
386 /* Do not start timer for addresses with link/host scope */
387 if (ipv6_addr_type(&ma->mca_addr)&(IPV6_ADDR_LINKLOCAL|IPV6_ADDR_LOOPBACK))
388 return;
390 spin_lock(&ma->mca_lock);
391 if (del_timer(&ma->mca_timer)) {
392 atomic_dec(&ma->mca_refcnt);
393 delay = ma->mca_timer.expires - jiffies;
396 if (delay >= resptime) {
397 if (resptime)
398 delay = net_random() % resptime;
399 else
400 delay = 1;
403 ma->mca_timer.expires = jiffies + delay;
404 if (!mod_timer(&ma->mca_timer, jiffies + delay))
405 atomic_inc(&ma->mca_refcnt);
406 spin_unlock(&ma->mca_lock);
409 int igmp6_event_query(struct sk_buff *skb)
411 struct ifmcaddr6 *ma;
412 struct in6_addr *addrp;
413 unsigned long resptime;
414 struct inet6_dev *idev;
415 struct icmp6hdr *hdr;
416 int addr_type;
418 if (!pskb_may_pull(skb, sizeof(struct in6_addr)))
419 return -EINVAL;
421 hdr = (struct icmp6hdr*) skb->h.raw;
423 /* Drop queries with not link local source */
424 if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr)&IPV6_ADDR_LINKLOCAL))
425 return -EINVAL;
427 resptime = ntohs(hdr->icmp6_maxdelay);
428 /* Translate milliseconds to jiffies */
429 resptime = (resptime<<10)/(1024000/HZ);
431 addrp = (struct in6_addr *) (hdr + 1);
432 addr_type = ipv6_addr_type(addrp);
434 if (addr_type != IPV6_ADDR_ANY &&
435 !(addr_type&IPV6_ADDR_MULTICAST))
436 return -EINVAL;
438 idev = in6_dev_get(skb->dev);
440 if (idev == NULL)
441 return 0;
443 read_lock(&idev->lock);
444 if (addr_type == IPV6_ADDR_ANY) {
445 for (ma = idev->mc_list; ma; ma=ma->next)
446 igmp6_group_queried(ma, resptime);
447 } else {
448 for (ma = idev->mc_list; ma; ma=ma->next) {
449 if (ipv6_addr_cmp(addrp, &ma->mca_addr) == 0) {
450 igmp6_group_queried(ma, resptime);
451 break;
455 read_unlock(&idev->lock);
456 in6_dev_put(idev);
458 return 0;
462 int igmp6_event_report(struct sk_buff *skb)
464 struct ifmcaddr6 *ma;
465 struct in6_addr *addrp;
466 struct inet6_dev *idev;
467 struct icmp6hdr *hdr;
468 int addr_type;
470 /* Our own report looped back. Ignore it. */
471 if (skb->pkt_type == PACKET_LOOPBACK)
472 return 0;
474 if (!pskb_may_pull(skb, sizeof(struct in6_addr)))
475 return -EINVAL;
477 hdr = (struct icmp6hdr*) skb->h.raw;
479 /* Drop reports with not link local source */
480 addr_type = ipv6_addr_type(&skb->nh.ipv6h->saddr);
481 if (addr_type != IPV6_ADDR_ANY &&
482 !(addr_type&IPV6_ADDR_LINKLOCAL))
483 return -EINVAL;
485 addrp = (struct in6_addr *) (hdr + 1);
487 idev = in6_dev_get(skb->dev);
488 if (idev == NULL)
489 return -ENODEV;
492 * Cancel the timer for this group
495 read_lock(&idev->lock);
496 for (ma = idev->mc_list; ma; ma=ma->next) {
497 if (ipv6_addr_cmp(&ma->mca_addr, addrp) == 0) {
498 spin_lock(&ma->mca_lock);
499 if (del_timer(&ma->mca_timer))
500 atomic_dec(&ma->mca_refcnt);
501 ma->mca_flags &= ~(MAF_LAST_REPORTER|MAF_TIMER_RUNNING);
502 spin_unlock(&ma->mca_lock);
503 break;
506 read_unlock(&idev->lock);
507 in6_dev_put(idev);
508 return 0;
511 static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
513 struct sock *sk = igmp6_socket->sk;
514 struct sk_buff *skb;
515 struct icmp6hdr *hdr;
516 struct in6_addr *snd_addr;
517 struct in6_addr *addrp;
518 struct in6_addr addr_buf;
519 struct in6_addr all_routers;
520 int err, len, payload_len, full_len;
521 u8 ra[8] = { IPPROTO_ICMPV6, 0,
522 IPV6_TLV_ROUTERALERT, 2, 0, 0,
523 IPV6_TLV_PADN, 0 };
525 snd_addr = addr;
526 if (type == ICMPV6_MGM_REDUCTION) {
527 snd_addr = &all_routers;
528 ipv6_addr_all_routers(&all_routers);
531 len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
532 payload_len = len + sizeof(ra);
533 full_len = sizeof(struct ipv6hdr) + payload_len;
535 skb = sock_alloc_send_skb(sk, dev->hard_header_len + full_len + 15, 0, &err);
537 if (skb == NULL)
538 return;
540 skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
541 if (dev->hard_header) {
542 unsigned char ha[MAX_ADDR_LEN];
543 ndisc_mc_map(snd_addr, ha, dev, 1);
544 if (dev->hard_header(skb, dev, ETH_P_IPV6, ha, NULL, full_len) < 0)
545 goto out;
548 if (ipv6_get_lladdr(dev, &addr_buf)) {
549 /* <draft-ietf-magma-mld-source-02.txt>:
550 * use unspecified address as the source address
551 * when a valid link-local address is not available.
553 memset(&addr_buf, 0, sizeof(addr_buf));
556 ip6_nd_hdr(sk, skb, dev, &addr_buf, snd_addr, NEXTHDR_HOP, payload_len);
558 memcpy(skb_put(skb, sizeof(ra)), ra, sizeof(ra));
560 hdr = (struct icmp6hdr *) skb_put(skb, sizeof(struct icmp6hdr));
561 memset(hdr, 0, sizeof(struct icmp6hdr));
562 hdr->icmp6_type = type;
564 addrp = (struct in6_addr *) skb_put(skb, sizeof(struct in6_addr));
565 ipv6_addr_copy(addrp, addr);
567 hdr->icmp6_cksum = csum_ipv6_magic(&addr_buf, snd_addr, len,
568 IPPROTO_ICMPV6,
569 csum_partial((__u8 *) hdr, len, 0));
571 dev_queue_xmit(skb);
572 if (type == ICMPV6_MGM_REDUCTION)
573 ICMP6_INC_STATS(Icmp6OutGroupMembReductions);
574 else
575 ICMP6_INC_STATS(Icmp6OutGroupMembResponses);
576 ICMP6_INC_STATS(Icmp6OutMsgs);
577 return;
579 out:
580 kfree_skb(skb);
583 static void igmp6_join_group(struct ifmcaddr6 *ma)
585 unsigned long delay;
587 if (IPV6_ADDR_MC_SCOPE(&ma->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL ||
588 ipv6_addr_is_ll_all_nodes(&ma->mca_addr))
589 return;
591 igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);
593 delay = net_random() % IGMP6_UNSOLICITED_IVAL;
595 spin_lock_bh(&ma->mca_lock);
596 if (del_timer(&ma->mca_timer)) {
597 atomic_dec(&ma->mca_refcnt);
598 delay = ma->mca_timer.expires - jiffies;
601 if (!mod_timer(&ma->mca_timer, jiffies + delay))
602 atomic_inc(&ma->mca_refcnt);
603 ma->mca_flags |= MAF_TIMER_RUNNING | MAF_LAST_REPORTER;
604 spin_unlock_bh(&ma->mca_lock);
607 static void igmp6_leave_group(struct ifmcaddr6 *ma)
609 if (IPV6_ADDR_MC_SCOPE(&ma->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL ||
610 ipv6_addr_is_ll_all_nodes(&ma->mca_addr))
611 return;
613 if (ma->mca_flags & MAF_LAST_REPORTER)
614 igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REDUCTION);
616 spin_lock_bh(&ma->mca_lock);
617 if (del_timer(&ma->mca_timer))
618 atomic_dec(&ma->mca_refcnt);
619 spin_unlock_bh(&ma->mca_lock);
622 static void igmp6_timer_handler(unsigned long data)
624 struct ifmcaddr6 *ma = (struct ifmcaddr6 *) data;
626 igmp6_send(&ma->mca_addr, ma->idev->dev, ICMPV6_MGM_REPORT);
628 spin_lock(&ma->mca_lock);
629 ma->mca_flags |= MAF_LAST_REPORTER;
630 ma->mca_flags &= ~MAF_TIMER_RUNNING;
631 spin_unlock(&ma->mca_lock);
632 ma_put(ma);
635 /* Device going down */
637 void ipv6_mc_down(struct inet6_dev *idev)
639 struct ifmcaddr6 *i;
641 /* Withdraw multicast list */
643 read_lock_bh(&idev->lock);
644 for (i = idev->mc_list; i; i=i->next)
645 igmp6_group_dropped(i);
646 read_unlock_bh(&idev->lock);
650 /* Device going up */
652 void ipv6_mc_up(struct inet6_dev *idev)
654 struct ifmcaddr6 *i;
656 /* Install multicast list, except for all-nodes (already installed) */
658 read_lock_bh(&idev->lock);
659 for (i = idev->mc_list; i; i=i->next)
660 igmp6_group_added(i);
661 read_unlock_bh(&idev->lock);
664 /* IPv6 device initialization. */
666 void ipv6_mc_init_dev(struct inet6_dev *idev)
668 struct in6_addr maddr;
670 /* Add all-nodes address. */
671 ipv6_addr_all_nodes(&maddr);
672 ipv6_dev_mc_inc(idev->dev, &maddr);
676 * Device is about to be destroyed: clean up.
679 void ipv6_mc_destroy_dev(struct inet6_dev *idev)
681 struct ifmcaddr6 *i;
682 struct in6_addr maddr;
684 /* Delete all-nodes address. */
685 ipv6_addr_all_nodes(&maddr);
686 ipv6_dev_mc_dec(idev->dev, &maddr);
688 write_lock_bh(&idev->lock);
689 while ((i = idev->mc_list) != NULL) {
690 idev->mc_list = i->next;
691 write_unlock_bh(&idev->lock);
693 igmp6_group_dropped(i);
694 ma_put(i);
696 write_lock_bh(&idev->lock);
698 write_unlock_bh(&idev->lock);
701 #ifdef CONFIG_PROC_FS
702 static int igmp6_read_proc(char *buffer, char **start, off_t offset,
703 int length, int *eof, void *data)
705 off_t pos=0, begin=0;
706 struct ifmcaddr6 *im;
707 int len=0;
708 struct net_device *dev;
710 read_lock(&dev_base_lock);
711 for (dev = dev_base; dev; dev = dev->next) {
712 struct inet6_dev *idev;
714 if ((idev = in6_dev_get(dev)) == NULL)
715 continue;
717 read_lock_bh(&idev->lock);
718 for (im = idev->mc_list; im; im = im->next) {
719 int i;
721 len += sprintf(buffer+len,"%-4d %-15s ", dev->ifindex, dev->name);
723 for (i=0; i<16; i++)
724 len += sprintf(buffer+len, "%02x", im->mca_addr.s6_addr[i]);
726 len+=sprintf(buffer+len,
727 " %5d %08X %ld\n",
728 im->mca_users,
729 im->mca_flags,
730 (im->mca_flags&MAF_TIMER_RUNNING) ? im->mca_timer.expires-jiffies : 0);
732 pos=begin+len;
733 if (pos < offset) {
734 len=0;
735 begin=pos;
737 if (pos > offset+length) {
738 read_unlock_bh(&idev->lock);
739 in6_dev_put(idev);
740 goto done;
743 read_unlock_bh(&idev->lock);
744 in6_dev_put(idev);
746 *eof = 1;
748 done:
749 read_unlock(&dev_base_lock);
751 *start=buffer+(offset-begin);
752 len-=(offset-begin);
753 if(len>length)
754 len=length;
755 if (len<0)
756 len=0;
757 return len;
759 #endif
761 int __init igmp6_init(struct net_proto_family *ops)
763 struct ipv6_pinfo *np;
764 struct sock *sk;
765 int err;
767 err = sock_create(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6, &igmp6_socket);
768 if (err < 0) {
769 printk(KERN_ERR
770 "Failed to initialize the IGMP6 control socket (err %d).\n",
771 err);
772 igmp6_socket = NULL; /* For safety. */
773 return err;
776 sk = igmp6_socket->sk;
777 sk->allocation = GFP_ATOMIC;
778 sk->prot->unhash(sk);
780 np = inet6_sk(sk);
781 np->hop_limit = 1;
782 #ifdef CONFIG_PROC_FS
783 create_proc_read_entry("net/igmp6", 0, 0, igmp6_read_proc, NULL);
784 #endif
786 return 0;
789 void igmp6_cleanup(void)
791 sock_release(igmp6_socket);
792 igmp6_socket = NULL; /* for safety */
793 #ifdef CONFIG_PROC_FS
794 remove_proc_entry("net/igmp6", 0);
795 #endif