2 * Multicast support for IPv6
3 * Linux INET6 implementation
6 * Pedro Roque <roque@di.fc.ul.pt>
8 * $Id: mcast.c,v 1.26 1999/08/31 07:04:08 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 #define __NO_VERSION__
19 #include <linux/config.h>
20 #include <linux/module.h>
21 #include <linux/errno.h>
22 #include <linux/types.h>
23 #include <linux/string.h>
24 #include <linux/socket.h>
25 #include <linux/sockios.h>
26 #include <linux/sched.h>
27 #include <linux/net.h>
28 #include <linux/in6.h>
29 #include <linux/netdevice.h>
30 #include <linux/if_arp.h>
31 #include <linux/route.h>
32 #include <linux/init.h>
33 #include <linux/proc_fs.h>
39 #include <net/protocol.h>
40 #include <net/if_inet6.h>
41 #include <net/ndisc.h>
42 #include <net/addrconf.h>
43 #include <net/ip6_route.h>
45 #include <net/checksum.h>
47 /* Set to 3 to get tracing... */
51 #define MDBG(x) printk x
56 /* Big mc list lock for all the sockets */
57 static rwlock_t ipv6_sk_mc_lock
= RW_LOCK_UNLOCKED
;
59 static struct socket
*igmp6_socket
;
61 static void igmp6_join_group(struct ifmcaddr6
*ma
);
62 static void igmp6_leave_group(struct ifmcaddr6
*ma
);
63 void igmp6_timer_handler(unsigned long data
);
65 #define IGMP6_UNSOLICITED_IVAL (10*HZ)
68 * socket join on multicast group
71 int ipv6_sock_mc_join(struct sock
*sk
, int ifindex
, struct in6_addr
*addr
)
73 struct net_device
*dev
= NULL
;
74 struct ipv6_mc_socklist
*mc_lst
;
75 struct ipv6_pinfo
*np
= &sk
->net_pinfo
.af_inet6
;
78 if (!(ipv6_addr_type(addr
) & IPV6_ADDR_MULTICAST
))
81 mc_lst
= sock_kmalloc(sk
, sizeof(struct ipv6_mc_socklist
), GFP_KERNEL
);
87 memcpy(&mc_lst
->addr
, addr
, sizeof(struct in6_addr
));
88 mc_lst
->ifindex
= ifindex
;
92 rt
= rt6_lookup(addr
, NULL
, 0, 0);
96 dst_release(&rt
->u
.dst
);
99 dev
= dev_get_by_index(ifindex
);
102 sock_kfree_s(sk
, mc_lst
, sizeof(*mc_lst
));
107 * now add/increase the group membership on the device
110 err
= ipv6_dev_mc_inc(dev
, addr
);
113 sock_kfree_s(sk
, mc_lst
, sizeof(*mc_lst
));
118 write_lock_bh(&ipv6_sk_mc_lock
);
119 mc_lst
->next
= np
->ipv6_mc_list
;
120 np
->ipv6_mc_list
= mc_lst
;
121 write_unlock_bh(&ipv6_sk_mc_lock
);
129 * socket leave on multicast group
131 int ipv6_sock_mc_drop(struct sock
*sk
, int ifindex
, struct in6_addr
*addr
)
133 struct ipv6_pinfo
*np
= &sk
->net_pinfo
.af_inet6
;
134 struct ipv6_mc_socklist
*mc_lst
, **lnk
;
136 write_lock_bh(&ipv6_sk_mc_lock
);
137 for (lnk
= &np
->ipv6_mc_list
; (mc_lst
= *lnk
) !=NULL
; lnk
= &mc_lst
->next
) {
138 if (mc_lst
->ifindex
== ifindex
&&
139 ipv6_addr_cmp(&mc_lst
->addr
, addr
) == 0) {
140 struct net_device
*dev
;
143 write_unlock_bh(&ipv6_sk_mc_lock
);
145 if ((dev
= dev_get_by_index(ifindex
)) != NULL
) {
146 ipv6_dev_mc_dec(dev
, &mc_lst
->addr
);
149 sock_kfree_s(sk
, mc_lst
, sizeof(*mc_lst
));
153 write_unlock_bh(&ipv6_sk_mc_lock
);
158 void ipv6_sock_mc_close(struct sock
*sk
)
160 struct ipv6_pinfo
*np
= &sk
->net_pinfo
.af_inet6
;
161 struct ipv6_mc_socklist
*mc_lst
;
163 write_lock_bh(&ipv6_sk_mc_lock
);
164 while ((mc_lst
= np
->ipv6_mc_list
) != NULL
) {
165 struct net_device
*dev
;
167 np
->ipv6_mc_list
= mc_lst
->next
;
168 write_unlock_bh(&ipv6_sk_mc_lock
);
170 dev
= dev_get_by_index(mc_lst
->ifindex
);
172 ipv6_dev_mc_dec(dev
, &mc_lst
->addr
);
176 sock_kfree_s(sk
, mc_lst
, sizeof(*mc_lst
));
178 write_lock_bh(&ipv6_sk_mc_lock
);
180 write_unlock_bh(&ipv6_sk_mc_lock
);
183 int inet6_mc_check(struct sock
*sk
, struct in6_addr
*addr
)
185 struct ipv6_mc_socklist
*mc
;
187 read_lock(&ipv6_sk_mc_lock
);
188 for (mc
= sk
->net_pinfo
.af_inet6
.ipv6_mc_list
; mc
; mc
=mc
->next
) {
189 if (ipv6_addr_cmp(&mc
->addr
, addr
) == 0) {
190 read_unlock(&ipv6_sk_mc_lock
);
194 read_unlock(&ipv6_sk_mc_lock
);
199 static int igmp6_group_added(struct ifmcaddr6
*mc
)
201 struct net_device
*dev
= mc
->idev
->dev
;
202 char buf
[MAX_ADDR_LEN
];
204 if (!(mc
->mca_flags
&MAF_LOADED
)) {
205 mc
->mca_flags
|= MAF_LOADED
;
206 if (ndisc_mc_map(&mc
->mca_addr
, buf
, dev
, 0) == 0)
207 dev_mc_add(dev
, buf
, dev
->addr_len
, 0);
210 if (dev
->flags
&IFF_UP
)
211 igmp6_join_group(mc
);
215 static int igmp6_group_dropped(struct ifmcaddr6
*mc
)
217 struct net_device
*dev
= mc
->idev
->dev
;
218 char buf
[MAX_ADDR_LEN
];
220 if (mc
->mca_flags
&MAF_LOADED
) {
221 mc
->mca_flags
&= ~MAF_LOADED
;
222 if (ndisc_mc_map(&mc
->mca_addr
, buf
, dev
, 0) == 0)
223 dev_mc_delete(dev
, buf
, dev
->addr_len
, 0);
226 if (dev
->flags
&IFF_UP
)
227 igmp6_leave_group(mc
);
233 * device multicast group inc (add if not found)
235 int ipv6_dev_mc_inc(struct net_device
*dev
, struct in6_addr
*addr
)
237 struct ifmcaddr6
*mc
;
238 struct inet6_dev
*idev
;
240 idev
= in6_dev_get(dev
);
245 write_lock_bh(&idev
->lock
);
247 write_unlock_bh(&idev
->lock
);
252 for (mc
= idev
->mc_list
; mc
; mc
= mc
->next
) {
253 if (ipv6_addr_cmp(&mc
->mca_addr
, addr
) == 0) {
254 atomic_inc(&mc
->mca_users
);
255 write_unlock_bh(&idev
->lock
);
262 * not found: create a new one.
265 mc
= kmalloc(sizeof(struct ifmcaddr6
), GFP_ATOMIC
);
268 write_unlock_bh(&idev
->lock
);
273 memset(mc
, 0, sizeof(struct ifmcaddr6
));
274 mc
->mca_timer
.function
= igmp6_timer_handler
;
275 mc
->mca_timer
.data
= (unsigned long) mc
;
277 memcpy(&mc
->mca_addr
, addr
, sizeof(struct in6_addr
));
279 atomic_set(&mc
->mca_users
, 1);
281 mc
->next
= idev
->mc_list
;
284 igmp6_group_added(mc
);
286 write_unlock_bh(&idev
->lock
);
292 * device multicast group del
294 int ipv6_dev_mc_dec(struct net_device
*dev
, struct in6_addr
*addr
)
296 struct inet6_dev
*idev
;
297 struct ifmcaddr6
*ma
, **map
;
299 idev
= in6_dev_get(dev
);
303 write_lock_bh(&idev
->lock
);
304 for (map
= &idev
->mc_list
; (ma
=*map
) != NULL
; map
= &ma
->next
) {
305 if (ipv6_addr_cmp(&ma
->mca_addr
, addr
) == 0) {
306 if (atomic_dec_and_test(&ma
->mca_users
)) {
308 write_unlock_bh(&idev
->lock
);
310 igmp6_group_dropped(ma
);
313 __in6_dev_put(ma
->idev
);
319 write_unlock_bh(&idev
->lock
);
324 write_unlock_bh(&idev
->lock
);
331 * check if the interface/address pair is valid
333 int ipv6_chk_mcast_addr(struct net_device
*dev
, struct in6_addr
*addr
)
335 struct inet6_dev
*idev
;
336 struct ifmcaddr6
*mc
;
338 idev
= in6_dev_get(dev
);
340 read_lock_bh(&idev
->lock
);
341 for (mc
= idev
->mc_list
; mc
; mc
=mc
->next
) {
342 if (ipv6_addr_cmp(&mc
->mca_addr
, addr
) == 0) {
343 read_unlock_bh(&idev
->lock
);
348 read_unlock_bh(&idev
->lock
);
355 * IGMP handling (alias multicast ICMPv6 messages)
358 static void igmp6_group_queried(struct ifmcaddr6
*ma
, unsigned long resptime
)
360 unsigned long delay
= resptime
;
362 /* Do not start timer for addresses with link/host scope */
363 if (ipv6_addr_type(&ma
->mca_addr
)&(IPV6_ADDR_LINKLOCAL
|IPV6_ADDR_LOOPBACK
))
366 if (del_timer(&ma
->mca_timer
))
367 delay
= ma
->mca_timer
.expires
- jiffies
;
369 if (delay
>= resptime
) {
371 delay
= net_random() % resptime
;
376 ma
->mca_flags
|= MAF_TIMER_RUNNING
;
377 ma
->mca_timer
.expires
= jiffies
+ delay
;
378 add_timer(&ma
->mca_timer
);
381 int igmp6_event_query(struct sk_buff
*skb
, struct icmp6hdr
*hdr
, int len
)
383 struct ifmcaddr6
*ma
;
384 struct in6_addr
*addrp
;
385 unsigned long resptime
;
386 struct inet6_dev
*idev
;
389 if (len
< sizeof(struct icmp6hdr
) + sizeof(struct in6_addr
))
392 /* Drop queries with not link local source */
393 if (!(ipv6_addr_type(&skb
->nh
.ipv6h
->saddr
)&IPV6_ADDR_LINKLOCAL
))
396 resptime
= ntohs(hdr
->icmp6_maxdelay
);
397 /* Translate milliseconds to jiffies */
398 resptime
= (resptime
<<10)/(1024000/HZ
);
400 addrp
= (struct in6_addr
*) (hdr
+ 1);
402 idev
= in6_dev_get(skb
->dev
);
407 read_lock(&idev
->lock
);
408 if (ipv6_addr_any(addrp
)) {
409 for (ma
= idev
->mc_list
; ma
; ma
=ma
->next
)
410 igmp6_group_queried(ma
, resptime
);
412 for (ma
= idev
->mc_list
; ma
; ma
=ma
->next
) {
413 if (ipv6_addr_cmp(addrp
, &ma
->mca_addr
) == 0) {
414 igmp6_group_queried(ma
, resptime
);
419 read_unlock(&idev
->lock
);
426 int igmp6_event_report(struct sk_buff
*skb
, struct icmp6hdr
*hdr
, int len
)
428 struct ifmcaddr6
*ma
;
429 struct in6_addr
*addrp
;
430 struct inet6_dev
*idev
;
432 /* Our own report looped back. Ignore it. */
433 if (skb
->pkt_type
== PACKET_LOOPBACK
)
436 if (len
< sizeof(struct icmp6hdr
) + sizeof(struct in6_addr
))
439 /* Drop reports with not link local source */
440 if (!(ipv6_addr_type(&skb
->nh
.ipv6h
->saddr
)&IPV6_ADDR_LINKLOCAL
))
443 addrp
= (struct in6_addr
*) (hdr
+ 1);
445 idev
= in6_dev_get(skb
->dev
);
450 * Cancel the timer for this group
453 read_lock(&idev
->lock
);
454 for (ma
= idev
->mc_list
; ma
; ma
=ma
->next
) {
455 if (ipv6_addr_cmp(&ma
->mca_addr
, addrp
) == 0) {
456 if (ma
->mca_flags
& MAF_TIMER_RUNNING
) {
457 del_timer(&ma
->mca_timer
);
458 ma
->mca_flags
&= ~MAF_TIMER_RUNNING
;
461 ma
->mca_flags
&= ~MAF_LAST_REPORTER
;
465 read_unlock(&idev
->lock
);
470 void igmp6_send(struct in6_addr
*addr
, struct net_device
*dev
, int type
)
472 struct sock
*sk
= igmp6_socket
->sk
;
474 struct icmp6hdr
*hdr
;
475 struct in6_addr
*snd_addr
;
476 struct in6_addr
*addrp
;
477 struct in6_addr addr_buf
;
478 struct in6_addr all_routers
;
479 int err
, len
, payload_len
, full_len
;
480 u8 ra
[8] = { IPPROTO_ICMPV6
, 0,
481 IPV6_TLV_ROUTERALERT
, 0, 0, 0,
485 if (type
== ICMPV6_MGM_REDUCTION
) {
486 snd_addr
= &all_routers
;
487 ipv6_addr_all_routers(&all_routers
);
490 len
= sizeof(struct icmp6hdr
) + sizeof(struct in6_addr
);
491 payload_len
= len
+ sizeof(ra
);
492 full_len
= sizeof(struct ipv6hdr
) + payload_len
;
494 skb
= sock_alloc_send_skb(sk
, dev
->hard_header_len
+ full_len
+ 15, 0, 0, &err
);
499 skb_reserve(skb
, (dev
->hard_header_len
+ 15) & ~15);
500 if (dev
->hard_header
) {
501 unsigned char ha
[MAX_ADDR_LEN
];
502 ndisc_mc_map(snd_addr
, ha
, dev
, 1);
503 dev
->hard_header(skb
, dev
, ETH_P_IPV6
, ha
, NULL
, full_len
);
506 if (ipv6_get_lladdr(dev
, &addr_buf
)) {
508 printk(KERN_DEBUG
"igmp6: %s no linklocal address\n",
514 ip6_nd_hdr(sk
, skb
, dev
, &addr_buf
, snd_addr
, NEXTHDR_HOP
, payload_len
);
516 memcpy(skb_put(skb
, sizeof(ra
)), ra
, sizeof(ra
));
518 hdr
= (struct icmp6hdr
*) skb_put(skb
, sizeof(struct icmp6hdr
));
519 memset(hdr
, 0, sizeof(struct icmp6hdr
));
520 hdr
->icmp6_type
= type
;
522 addrp
= (struct in6_addr
*) skb_put(skb
, sizeof(struct in6_addr
));
523 ipv6_addr_copy(addrp
, addr
);
525 hdr
->icmp6_cksum
= csum_ipv6_magic(&addr_buf
, snd_addr
, len
,
527 csum_partial((__u8
*) hdr
, len
, 0));
530 if (type
== ICMPV6_MGM_REDUCTION
)
531 icmpv6_statistics
.Icmp6OutGroupMembReductions
++;
533 icmpv6_statistics
.Icmp6OutGroupMembResponses
++;
534 icmpv6_statistics
.Icmp6OutMsgs
++;
537 static void igmp6_join_group(struct ifmcaddr6
*ma
)
542 addr_type
= ipv6_addr_type(&ma
->mca_addr
);
544 if ((addr_type
& (IPV6_ADDR_LINKLOCAL
|IPV6_ADDR_LOOPBACK
)))
547 igmp6_send(&ma
->mca_addr
, ma
->idev
->dev
, ICMPV6_MGM_REPORT
);
549 delay
= net_random() % IGMP6_UNSOLICITED_IVAL
;
550 if (del_timer(&ma
->mca_timer
))
551 delay
= ma
->mca_timer
.expires
- jiffies
;
553 ma
->mca_timer
.expires
= jiffies
+ delay
;
555 add_timer(&ma
->mca_timer
);
556 ma
->mca_flags
|= MAF_TIMER_RUNNING
| MAF_LAST_REPORTER
;
559 static void igmp6_leave_group(struct ifmcaddr6
*ma
)
563 addr_type
= ipv6_addr_type(&ma
->mca_addr
);
565 if ((addr_type
& IPV6_ADDR_LINKLOCAL
))
568 if (ma
->mca_flags
& MAF_LAST_REPORTER
)
569 igmp6_send(&ma
->mca_addr
, ma
->idev
->dev
, ICMPV6_MGM_REDUCTION
);
571 if (ma
->mca_flags
& MAF_TIMER_RUNNING
)
572 del_timer(&ma
->mca_timer
);
575 void igmp6_timer_handler(unsigned long data
)
577 struct ifmcaddr6
*ma
= (struct ifmcaddr6
*) data
;
579 ma
->mca_flags
|= MAF_LAST_REPORTER
;
580 igmp6_send(&ma
->mca_addr
, ma
->idev
->dev
, ICMPV6_MGM_REPORT
);
581 ma
->mca_flags
&= ~MAF_TIMER_RUNNING
;
584 /* Device going down */
586 void ipv6_mc_down(struct inet6_dev
*idev
)
589 struct in6_addr maddr
;
591 /* Withdraw multicast list */
593 read_lock_bh(&idev
->lock
);
594 for (i
= idev
->mc_list
; i
; i
=i
->next
)
595 igmp6_group_dropped(i
);
596 read_unlock_bh(&idev
->lock
);
598 /* Delete all-nodes address. */
600 ipv6_addr_all_nodes(&maddr
);
601 ipv6_dev_mc_dec(idev
->dev
, &maddr
);
604 /* Device going up */
606 void ipv6_mc_up(struct inet6_dev
*idev
)
609 struct in6_addr maddr
;
611 /* Add all-nodes address. */
613 ipv6_addr_all_nodes(&maddr
);
614 ipv6_dev_mc_inc(idev
->dev
, &maddr
);
616 /* Install multicast list, except for all-nodes (already installed) */
618 read_lock_bh(&idev
->lock
);
619 for (i
= idev
->mc_list
; i
; i
=i
->next
)
620 igmp6_group_added(i
);
621 read_unlock_bh(&idev
->lock
);
625 * Device is about to be destroyed: clean up.
628 void ipv6_mc_destroy_dev(struct inet6_dev
*idev
)
632 write_lock_bh(&idev
->lock
);
633 while ((i
= idev
->mc_list
) != NULL
) {
634 idev
->mc_list
= i
->next
;
635 write_unlock_bh(&idev
->lock
);
637 igmp6_group_dropped(i
);
640 in6_dev_put(i
->idev
);
643 write_lock_bh(&idev
->lock
);
645 write_unlock_bh(&idev
->lock
);
648 #ifdef CONFIG_PROC_FS
649 static int igmp6_read_proc(char *buffer
, char **start
, off_t offset
,
650 int length
, int *eof
, void *data
)
652 off_t pos
=0, begin
=0;
653 struct ifmcaddr6
*im
;
655 struct net_device
*dev
;
657 read_lock(&dev_base_lock
);
658 for (dev
= dev_base
; dev
; dev
= dev
->next
) {
659 struct inet6_dev
*idev
;
661 if ((idev
= in6_dev_get(dev
)) == NULL
)
664 read_lock_bh(&idev
->lock
);
665 for (im
= idev
->mc_list
; im
; im
= im
->next
) {
668 len
+= sprintf(buffer
+len
,"%-4d %-15s ", dev
->ifindex
, dev
->name
);
671 len
+= sprintf(buffer
+len
, "%02x", im
->mca_addr
.s6_addr
[i
]);
673 len
+=sprintf(buffer
+len
,
675 atomic_read(&im
->mca_users
),
677 (im
->mca_flags
&MAF_TIMER_RUNNING
) ? im
->mca_timer
.expires
-jiffies
: 0);
684 if (pos
> offset
+length
) {
685 read_unlock_bh(&idev
->lock
);
690 read_unlock_bh(&idev
->lock
);
696 read_unlock(&dev_base_lock
);
698 *start
=buffer
+(offset
-begin
);
708 int __init
igmp6_init(struct net_proto_family
*ops
)
713 igmp6_socket
= sock_alloc();
714 if (igmp6_socket
== NULL
) {
716 "Failed to create the IGMP6 control socket.\n");
719 igmp6_socket
->inode
->i_uid
= 0;
720 igmp6_socket
->inode
->i_gid
= 0;
721 igmp6_socket
->type
= SOCK_RAW
;
723 if((err
= ops
->create(igmp6_socket
, IPPROTO_ICMPV6
)) < 0) {
725 "Failed to initialize the IGMP6 control socket (err %d).\n",
727 sock_release(igmp6_socket
);
728 igmp6_socket
= NULL
; /* For safety. */
732 sk
= igmp6_socket
->sk
;
733 sk
->allocation
= GFP_ATOMIC
;
734 sk
->prot
->unhash(sk
);
736 sk
->net_pinfo
.af_inet6
.hop_limit
= 1;
737 #ifdef CONFIG_PROC_FS
738 create_proc_read_entry("net/igmp6", 0, 0, igmp6_read_proc
, NULL
);
745 void igmp6_cleanup(void)
747 sock_release(igmp6_socket
);
748 igmp6_socket
= NULL
; /* for safety */
749 #ifdef CONFIG_PROC_FS
750 remove_proc_entry("net/igmp6", 0);