12874c5fdSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * Linux NET3: Internet Group Management Protocol [IGMP]
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Authors:
6113aa838SAlan Cox * Alan Cox <alan@lxorguk.ukuu.org.uk>
71da177e4SLinus Torvalds *
81da177e4SLinus Torvalds * Extended to talk the BSD extended IGMP protocol of mrouted 3.6
91da177e4SLinus Torvalds */
101da177e4SLinus Torvalds #ifndef _LINUX_IGMP_H
111da177e4SLinus Torvalds #define _LINUX_IGMP_H
121da177e4SLinus Torvalds
131da177e4SLinus Torvalds #include <linux/skbuff.h>
14d7fe0f24SAl Viro #include <linux/timer.h>
151da177e4SLinus Torvalds #include <linux/in.h>
16ba5ea614SLinus Lüssing #include <linux/ip.h>
178851ab52SReshetova, Elena #include <linux/refcount.h>
18ac62f606SJakub Kicinski #include <linux/sockptr.h>
19607ca46eSDavid Howells #include <uapi/linux/igmp.h>
201da177e4SLinus Torvalds
igmp_hdr(const struct sk_buff * skb)21cc32e054SJoe Perches static inline struct igmphdr *igmp_hdr(const struct sk_buff *skb)
22cc32e054SJoe Perches {
23cc32e054SJoe Perches return (struct igmphdr *)skb_transport_header(skb);
24cc32e054SJoe Perches }
25cc32e054SJoe Perches
26cc32e054SJoe Perches static inline struct igmpv3_report *
igmpv3_report_hdr(const struct sk_buff * skb)27cc32e054SJoe Perches igmpv3_report_hdr(const struct sk_buff *skb)
28cc32e054SJoe Perches {
29cc32e054SJoe Perches return (struct igmpv3_report *)skb_transport_header(skb);
30cc32e054SJoe Perches }
31cc32e054SJoe Perches
32cc32e054SJoe Perches static inline struct igmpv3_query *
igmpv3_query_hdr(const struct sk_buff * skb)33cc32e054SJoe Perches igmpv3_query_hdr(const struct sk_buff *skb)
34cc32e054SJoe Perches {
35cc32e054SJoe Perches return (struct igmpv3_query *)skb_transport_header(skb);
36cc32e054SJoe Perches }
37cc32e054SJoe Perches
38d94d9feeSEric Dumazet struct ip_sf_socklist {
391da177e4SLinus Torvalds unsigned int sl_max;
401da177e4SLinus Torvalds unsigned int sl_count;
41c85bb41eSFlavio Leitner struct rcu_head rcu;
420ead3364SGustavo A. R. Silva __be32 sl_addr[];
431da177e4SLinus Torvalds };
441da177e4SLinus Torvalds
451da177e4SLinus Torvalds #define IP_SFBLOCK 10 /* allocate this many at once */
461da177e4SLinus Torvalds
471da177e4SLinus Torvalds /* ip_mc_socklist is real list now. Speed is not argument;
481da177e4SLinus Torvalds this list never used in fast path code
491da177e4SLinus Torvalds */
501da177e4SLinus Torvalds
51d94d9feeSEric Dumazet struct ip_mc_socklist {
521d7138deSEric Dumazet struct ip_mc_socklist __rcu *next_rcu;
531da177e4SLinus Torvalds struct ip_mreqn multi;
541da177e4SLinus Torvalds unsigned int sfmode; /* MCAST_{INCLUDE,EXCLUDE} */
551d7138deSEric Dumazet struct ip_sf_socklist __rcu *sflist;
56c85bb41eSFlavio Leitner struct rcu_head rcu;
571da177e4SLinus Torvalds };
581da177e4SLinus Torvalds
59d94d9feeSEric Dumazet struct ip_sf_list {
601da177e4SLinus Torvalds struct ip_sf_list *sf_next;
611da177e4SLinus Torvalds unsigned long sf_count[2]; /* include/exclude counts */
620db355d4SEric Dumazet __be32 sf_inaddr;
631da177e4SLinus Torvalds unsigned char sf_gsresp; /* include in g & s response? */
641da177e4SLinus Torvalds unsigned char sf_oldin; /* change state */
651da177e4SLinus Torvalds unsigned char sf_crcount; /* retrans. left to send */
661da177e4SLinus Torvalds };
671da177e4SLinus Torvalds
68d94d9feeSEric Dumazet struct ip_mc_list {
691da177e4SLinus Torvalds struct in_device *interface;
70338fcf98SAlexey Dobriyan __be32 multiaddr;
711d7138deSEric Dumazet unsigned int sfmode;
721da177e4SLinus Torvalds struct ip_sf_list *sources;
731da177e4SLinus Torvalds struct ip_sf_list *tomb;
741da177e4SLinus Torvalds unsigned long sfcount[2];
751d7138deSEric Dumazet union {
761da177e4SLinus Torvalds struct ip_mc_list *next;
771d7138deSEric Dumazet struct ip_mc_list __rcu *next_rcu;
781d7138deSEric Dumazet };
79e9897071SEric Dumazet struct ip_mc_list __rcu *next_hash;
801da177e4SLinus Torvalds struct timer_list timer;
811da177e4SLinus Torvalds int users;
828851ab52SReshetova, Elena refcount_t refcnt;
831da177e4SLinus Torvalds spinlock_t lock;
841da177e4SLinus Torvalds char tm_running;
851da177e4SLinus Torvalds char reporter;
861da177e4SLinus Torvalds char unsolicit_count;
871da177e4SLinus Torvalds char loaded;
881da177e4SLinus Torvalds unsigned char gsquery; /* check source marks? */
891da177e4SLinus Torvalds unsigned char crcount;
901d7138deSEric Dumazet struct rcu_head rcu;
911da177e4SLinus Torvalds };
921da177e4SLinus Torvalds
931da177e4SLinus Torvalds /* V3 exponential field decoding */
941da177e4SLinus Torvalds #define IGMPV3_MASK(value, nb) ((nb)>=32 ? (value) : ((1<<(nb))-1) & (value))
951da177e4SLinus Torvalds #define IGMPV3_EXP(thresh, nbmant, nbexp, value) \
961da177e4SLinus Torvalds ((value) < (thresh) ? (value) : \
97fb47ddb2SDavid L Stevens ((IGMPV3_MASK(value, nbmant) | (1<<(nbmant))) << \
981da177e4SLinus Torvalds (IGMPV3_MASK((value) >> (nbmant), nbexp) + (nbexp))))
991da177e4SLinus Torvalds
1001da177e4SLinus Torvalds #define IGMPV3_QQIC(value) IGMPV3_EXP(0x80, 4, 3, value)
1011da177e4SLinus Torvalds #define IGMPV3_MRC(value) IGMPV3_EXP(0x80, 4, 3, value)
1021da177e4SLinus Torvalds
ip_mc_may_pull(struct sk_buff * skb,unsigned int len)103ba5ea614SLinus Lüssing static inline int ip_mc_may_pull(struct sk_buff *skb, unsigned int len)
104ba5ea614SLinus Lüssing {
105ba5ea614SLinus Lüssing if (skb_transport_offset(skb) + ip_transport_len(skb) < len)
106083b78a9SEric Dumazet return 0;
107ba5ea614SLinus Lüssing
108ba5ea614SLinus Lüssing return pskb_may_pull(skb, len);
109ba5ea614SLinus Lüssing }
110ba5ea614SLinus Lüssing
1112094acbbSAlexander Duyck extern int ip_check_mc_rcu(struct in_device *dev, __be32 mc_addr, __be32 src_addr, u8 proto);
1121da177e4SLinus Torvalds extern int igmp_rcv(struct sk_buff *);
1131da177e4SLinus Torvalds extern int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr);
1146e2059b5SHangbin Liu extern int ip_mc_join_group_ssm(struct sock *sk, struct ip_mreqn *imr,
1156e2059b5SHangbin Liu unsigned int mode);
1161da177e4SLinus Torvalds extern int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr);
1171da177e4SLinus Torvalds extern void ip_mc_drop_socket(struct sock *sk);
1181da177e4SLinus Torvalds extern int ip_mc_source(int add, int omode, struct sock *sk,
1191da177e4SLinus Torvalds struct ip_mreq_source *mreqs, int ifindex);
1201da177e4SLinus Torvalds extern int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf,int ifindex);
1211da177e4SLinus Torvalds extern int ip_mc_msfget(struct sock *sk, struct ip_msfilter *msf,
122728f064cSMartin KaFai Lau sockptr_t optval, sockptr_t optlen);
1231da177e4SLinus Torvalds extern int ip_mc_gsfget(struct sock *sk, struct group_filter *gsf,
124728f064cSMartin KaFai Lau sockptr_t optval, size_t offset);
125*33e972bdSEric Dumazet extern int ip_mc_sf_allow(const struct sock *sk, __be32 local, __be32 rmt,
12660d9b031SDavid Ahern int dif, int sdif);
1271da177e4SLinus Torvalds extern void ip_mc_init_dev(struct in_device *);
1281da177e4SLinus Torvalds extern void ip_mc_destroy_dev(struct in_device *);
1291da177e4SLinus Torvalds extern void ip_mc_up(struct in_device *);
1301da177e4SLinus Torvalds extern void ip_mc_down(struct in_device *);
13175c78500SMoni Shoua extern void ip_mc_unmap(struct in_device *);
13275c78500SMoni Shoua extern void ip_mc_remap(struct in_device *);
1339fb20801SFlorian Fainelli extern void __ip_mc_dec_group(struct in_device *in_dev, __be32 addr, gfp_t gfp);
ip_mc_dec_group(struct in_device * in_dev,__be32 addr)1349fb20801SFlorian Fainelli static inline void ip_mc_dec_group(struct in_device *in_dev, __be32 addr)
1359fb20801SFlorian Fainelli {
1369fb20801SFlorian Fainelli return __ip_mc_dec_group(in_dev, addr, GFP_KERNEL);
1379fb20801SFlorian Fainelli }
1389fb20801SFlorian Fainelli extern void __ip_mc_inc_group(struct in_device *in_dev, __be32 addr,
1399fb20801SFlorian Fainelli gfp_t gfp);
1408f935bbdSAl Viro extern void ip_mc_inc_group(struct in_device *in_dev, __be32 addr);
141ba5ea614SLinus Lüssing int ip_mc_check_igmp(struct sk_buff *skb);
142a816c7c7SJay Vosburgh
1431da177e4SLinus Torvalds #endif
144