#include <linux/module.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/jiffies.h>
#include <linux/net.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/route.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/pkt_sched.h>
#include <net/mld.h>
#include <linux/workqueue.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv6.h>
#include <net/net_namespace.h>
#include <net/sock.h>
#include <net/snmp.h>
#include <net/ipv6.h>
#include <net/protocol.h>
#include <net/if_inet6.h>
#include <net/ndisc.h>
#include <net/addrconf.h>
#include <net/ip6_route.h>
#include <net/inet_common.h>
#include <net/ip6_checksum.h>
static int __mld2_query_bugs[] __attribute__((__unused__)) = …;
static struct workqueue_struct *mld_wq;
static struct in6_addr mld2_all_mcr = …;
static void igmp6_join_group(struct ifmcaddr6 *ma);
static void igmp6_leave_group(struct ifmcaddr6 *ma);
static void mld_mca_work(struct work_struct *work);
static void mld_ifc_event(struct inet6_dev *idev);
static bool mld_in_v1_mode(const struct inet6_dev *idev);
static int sf_setstate(struct ifmcaddr6 *pmc);
static void sf_markstate(struct ifmcaddr6 *pmc);
static void ip6_mc_clear_src(struct ifmcaddr6 *pmc);
static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *pmca,
int sfmode, int sfcount, const struct in6_addr *psfsrc,
int delta);
static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,
int sfmode, int sfcount, const struct in6_addr *psfsrc,
int delta);
static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
struct inet6_dev *idev);
static int __ipv6_dev_mc_inc(struct net_device *dev,
const struct in6_addr *addr, unsigned int mode);
#define MLD_QRV_DEFAULT …
#define MLD_QI_DEFAULT …
#define MLD_QRI_DEFAULT …
#define MLD_V1_QUERY_LEN …
#define MLD_V2_QUERY_LEN_MIN …
#define IPV6_MLD_MAX_MSF …
int sysctl_mld_max_msf __read_mostly = …;
int sysctl_mld_qrv __read_mostly = …;
#define mc_dereference(e, idev) …
#define sock_dereference(e, sk) …
#define for_each_pmc_socklock(np, sk, pmc) …
#define for_each_pmc_rcu(np, pmc) …
#define for_each_psf_mclock(mc, psf) …
#define for_each_psf_rcu(mc, psf) …
#define for_each_psf_tomb(mc, psf) …
#define for_each_mc_mclock(idev, mc) …
#define for_each_mc_rcu(idev, mc) …
#define for_each_mc_tomb(idev, mc) …
static int unsolicited_report_interval(struct inet6_dev *idev)
{ … }
static int __ipv6_sock_mc_join(struct sock *sk, int ifindex,
const struct in6_addr *addr, unsigned int mode)
{ … }
int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
{ … }
EXPORT_SYMBOL(…);
int ipv6_sock_mc_join_ssm(struct sock *sk, int ifindex,
const struct in6_addr *addr, unsigned int mode)
{ … }
int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
{ … }
EXPORT_SYMBOL(…);
static struct inet6_dev *ip6_mc_find_dev_rtnl(struct net *net,
const struct in6_addr *group,
int ifindex)
{ … }
void __ipv6_sock_mc_close(struct sock *sk)
{ … }
void ipv6_sock_mc_close(struct sock *sk)
{ … }
int ip6_mc_source(int add, int omode, struct sock *sk,
struct group_source_req *pgsr)
{ … }
int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf,
struct sockaddr_storage *list)
{ … }
int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf,
sockptr_t optval, size_t ss_offset)
{ … }
bool inet6_mc_check(const struct sock *sk, const struct in6_addr *mc_addr,
const struct in6_addr *src_addr)
{ … }
static void igmp6_group_added(struct ifmcaddr6 *mc)
{ … }
static void igmp6_group_dropped(struct ifmcaddr6 *mc)
{ … }
static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
{ … }
static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im)
{ … }
static void mld_clear_delrec(struct inet6_dev *idev)
{ … }
static void mld_clear_query(struct inet6_dev *idev)
{ … }
static void mld_clear_report(struct inet6_dev *idev)
{ … }
static void mca_get(struct ifmcaddr6 *mc)
{ … }
static void ma_put(struct ifmcaddr6 *mc)
{ … }
static struct ifmcaddr6 *mca_alloc(struct inet6_dev *idev,
const struct in6_addr *addr,
unsigned int mode)
{ … }
static int __ipv6_dev_mc_inc(struct net_device *dev,
const struct in6_addr *addr, unsigned int mode)
{ … }
int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr)
{ … }
EXPORT_SYMBOL(…);
int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr)
{ … }
int ipv6_dev_mc_dec(struct net_device *dev, const struct in6_addr *addr)
{ … }
EXPORT_SYMBOL(…);
bool ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
const struct in6_addr *src_addr)
{ … }
static void mld_gq_start_work(struct inet6_dev *idev)
{ … }
static void mld_gq_stop_work(struct inet6_dev *idev)
{ … }
static void mld_ifc_start_work(struct inet6_dev *idev, unsigned long delay)
{ … }
static void mld_ifc_stop_work(struct inet6_dev *idev)
{ … }
static void mld_dad_start_work(struct inet6_dev *idev, unsigned long delay)
{ … }
static void mld_dad_stop_work(struct inet6_dev *idev)
{ … }
static void mld_query_stop_work(struct inet6_dev *idev)
{ … }
static void mld_report_stop_work(struct inet6_dev *idev)
{ … }
static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime)
{ … }
static bool mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs,
const struct in6_addr *srcs)
{ … }
static bool mld_marksources(struct ifmcaddr6 *pmc, int nsrcs,
const struct in6_addr *srcs)
{ … }
static int mld_force_mld_version(const struct inet6_dev *idev)
{ … }
static bool mld_in_v2_mode_only(const struct inet6_dev *idev)
{ … }
static bool mld_in_v1_mode_only(const struct inet6_dev *idev)
{ … }
static bool mld_in_v1_mode(const struct inet6_dev *idev)
{ … }
static void mld_set_v1_mode(struct inet6_dev *idev)
{ … }
static void mld_update_qrv(struct inet6_dev *idev,
const struct mld2_query *mlh2)
{ … }
static void mld_update_qi(struct inet6_dev *idev,
const struct mld2_query *mlh2)
{ … }
static void mld_update_qri(struct inet6_dev *idev,
const struct mld2_query *mlh2)
{ … }
static int mld_process_v1(struct inet6_dev *idev, struct mld_msg *mld,
unsigned long *max_delay, bool v1_query)
{ … }
static void mld_process_v2(struct inet6_dev *idev, struct mld2_query *mld,
unsigned long *max_delay)
{ … }
void igmp6_event_query(struct sk_buff *skb)
{ … }
static void __mld_query_work(struct sk_buff *skb)
{ … }
static void mld_query_work(struct work_struct *work)
{ … }
void igmp6_event_report(struct sk_buff *skb)
{ … }
static void __mld_report_work(struct sk_buff *skb)
{ … }
static void mld_report_work(struct work_struct *work)
{ … }
static bool is_in(struct ifmcaddr6 *pmc, struct ip6_sf_list *psf, int type,
int gdeleted, int sdeleted)
{ … }
static int
mld_scount(struct ifmcaddr6 *pmc, int type, int gdeleted, int sdeleted)
{ … }
static void ip6_mc_hdr(const struct sock *sk, struct sk_buff *skb,
struct net_device *dev, const struct in6_addr *saddr,
const struct in6_addr *daddr, int proto, int len)
{ … }
static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu)
{ … }
static void mld_sendpack(struct sk_buff *skb)
{ … }
static int grec_size(struct ifmcaddr6 *pmc, int type, int gdel, int sdel)
{ … }
static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc,
int type, struct mld2_grec **ppgr, unsigned int mtu)
{ … }
#define AVAILABLE(skb) …
static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc,
int type, int gdeleted, int sdeleted,
int crsend)
{ … }
static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc)
{ … }
static void mld_clear_zeros(struct ip6_sf_list __rcu **ppsf, struct inet6_dev *idev)
{ … }
static void mld_send_cr(struct inet6_dev *idev)
{ … }
static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
{ … }
static void mld_send_initial_cr(struct inet6_dev *idev)
{ … }
void ipv6_mc_dad_complete(struct inet6_dev *idev)
{ … }
static void mld_dad_work(struct work_struct *work)
{ … }
static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
const struct in6_addr *psfsrc)
{ … }
static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *pmca,
int sfmode, int sfcount, const struct in6_addr *psfsrc,
int delta)
{ … }
static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode,
const struct in6_addr *psfsrc)
{ … }
static void sf_markstate(struct ifmcaddr6 *pmc)
{ … }
static int sf_setstate(struct ifmcaddr6 *pmc)
{ … }
static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,
int sfmode, int sfcount, const struct in6_addr *psfsrc,
int delta)
{ … }
static void ip6_mc_clear_src(struct ifmcaddr6 *pmc)
{ … }
static void igmp6_join_group(struct ifmcaddr6 *ma)
{ … }
static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml,
struct inet6_dev *idev)
{ … }
static void igmp6_leave_group(struct ifmcaddr6 *ma)
{ … }
static void mld_gq_work(struct work_struct *work)
{ … }
static void mld_ifc_work(struct work_struct *work)
{ … }
static void mld_ifc_event(struct inet6_dev *idev)
{ … }
static void mld_mca_work(struct work_struct *work)
{ … }
void ipv6_mc_unmap(struct inet6_dev *idev)
{ … }
void ipv6_mc_remap(struct inet6_dev *idev)
{ … }
void ipv6_mc_down(struct inet6_dev *idev)
{ … }
static void ipv6_mc_reset(struct inet6_dev *idev)
{ … }
void ipv6_mc_up(struct inet6_dev *idev)
{ … }
void ipv6_mc_init_dev(struct inet6_dev *idev)
{ … }
void ipv6_mc_destroy_dev(struct inet6_dev *idev)
{ … }
static void ipv6_mc_rejoin_groups(struct inet6_dev *idev)
{ … }
static int ipv6_mc_netdev_event(struct notifier_block *this,
unsigned long event,
void *ptr)
{ … }
static struct notifier_block igmp6_netdev_notifier = …;
#ifdef CONFIG_PROC_FS
struct igmp6_mc_iter_state { … };
#define igmp6_mc_seq_private(seq) …
static inline struct ifmcaddr6 *igmp6_mc_get_first(struct seq_file *seq)
{ … }
static struct ifmcaddr6 *igmp6_mc_get_next(struct seq_file *seq, struct ifmcaddr6 *im)
{ … }
static struct ifmcaddr6 *igmp6_mc_get_idx(struct seq_file *seq, loff_t pos)
{ … }
static void *igmp6_mc_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(RCU)
{ … }
static void *igmp6_mc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{ … }
static void igmp6_mc_seq_stop(struct seq_file *seq, void *v)
__releases(RCU)
{ … }
static int igmp6_mc_seq_show(struct seq_file *seq, void *v)
{ … }
static const struct seq_operations igmp6_mc_seq_ops = …;
struct igmp6_mcf_iter_state { … };
#define igmp6_mcf_seq_private(seq) …
static inline struct ip6_sf_list *igmp6_mcf_get_first(struct seq_file *seq)
{ … }
static struct ip6_sf_list *igmp6_mcf_get_next(struct seq_file *seq, struct ip6_sf_list *psf)
{ … }
static struct ip6_sf_list *igmp6_mcf_get_idx(struct seq_file *seq, loff_t pos)
{ … }
static void *igmp6_mcf_seq_start(struct seq_file *seq, loff_t *pos)
__acquires(RCU)
{ … }
static void *igmp6_mcf_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{ … }
static void igmp6_mcf_seq_stop(struct seq_file *seq, void *v)
__releases(RCU)
{ … }
static int igmp6_mcf_seq_show(struct seq_file *seq, void *v)
{ … }
static const struct seq_operations igmp6_mcf_seq_ops = …;
static int __net_init igmp6_proc_init(struct net *net)
{ … }
static void __net_exit igmp6_proc_exit(struct net *net)
{ … }
#else
static inline int igmp6_proc_init(struct net *net)
{
return 0;
}
static inline void igmp6_proc_exit(struct net *net)
{
}
#endif
static int __net_init igmp6_net_init(struct net *net)
{ … }
static void __net_exit igmp6_net_exit(struct net *net)
{ … }
static struct pernet_operations igmp6_net_ops = …;
int __init igmp6_init(void)
{ … }
int __init igmp6_late_init(void)
{ … }
void igmp6_cleanup(void)
{ … }
void igmp6_late_cleanup(void)
{ … }