*
* Chih-Jen Chang : Tried to revise IGMP to Version 2
* Tsu-Sheng Tsao E-mail: chihjenc@scf.usc.edu and tsusheng@scf.usc.edu
- * The enhancements are mainly based on Steve Deering's
+ * The enhancements are mainly based on Steve Deering's
* ipmulti-3.5 source code.
* Chih-Jen Chang : Added the igmp_get_mrouter_info and
* Tsu-Sheng Tsao igmp_set_mrouter_info to keep track of
* Alan Cox : Stop IGMP from 0.0.0.0 being accepted.
* Alan Cox : Use GFP_ATOMIC in the right places.
* Christian Daudt : igmp timer wasn't set for local group
- * memberships but was being deleted,
- * which caused a "del_timer() called
+ * memberships but was being deleted,
+ * which caused a "del_timer() called
* from %p with timer not initialized\n"
* message (960131).
- * Christian Daudt : removed del_timer from
+ * Christian Daudt : removed del_timer from
* igmp_timer_expire function (960205).
* Christian Daudt : igmp_heard_report now only calls
* igmp_timer_expire if tm->running is
* Vinay Kulkarni
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <asm/uaccess.h>
#include <asm/system.h>
time_before(jiffies, (in_dev)->mr_v2_seen)))
static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im);
-static void igmpv3_del_delrec(struct in_device *in_dev, __u32 multiaddr);
+static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr);
static void igmpv3_clear_delrec(struct in_device *in_dev);
static int sf_setstate(struct ip_mc_list *pmc);
static void sf_markstate(struct ip_mc_list *pmc);
#endif
static void ip_mc_clear_src(struct ip_mc_list *pmc);
-static int ip_mc_add_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
- int sfcount, __u32 *psfsrc, int delta);
+static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
+ int sfcount, __be32 *psfsrc, int delta);
static void ip_ma_put(struct ip_mc_list *im)
{
skb_reserve(skb, LL_RESERVED_SPACE(dev));
- skb->nh.iph = pip =(struct iphdr *)skb_put(skb, sizeof(struct iphdr)+4);
+ skb_reset_network_header(skb);
+ pip = ip_hdr(skb);
+ skb_put(skb, sizeof(struct iphdr) + 4);
pip->version = 4;
pip->ihl = (sizeof(struct iphdr)+4)>>2;
((u8*)&pip[1])[2] = 0;
((u8*)&pip[1])[3] = 0;
- pig =(struct igmpv3_report *)skb_put(skb, sizeof(*pig));
- skb->h.igmph = (struct igmphdr *)pig;
+ skb->h.raw = skb_put(skb, sizeof(*pig));
+ pig = igmpv3_report_hdr(skb);
pig->type = IGMPV3_HOST_MEMBERSHIP_REPORT;
pig->resv1 = 0;
pig->csum = 0;
static int igmpv3_sendpack(struct sk_buff *skb)
{
- struct iphdr *pip = skb->nh.iph;
- struct igmphdr *pig = skb->h.igmph;
- int iplen, igmplen;
+ struct iphdr *pip = ip_hdr(skb);
+ struct igmphdr *pig = igmp_hdr(skb);
+ const int iplen = skb->tail - skb->nh.raw;
+ const int igmplen = skb->tail - skb->h.raw;
- iplen = skb->tail - (unsigned char *)skb->nh.iph;
pip->tot_len = htons(iplen);
ip_send_check(pip);
-
- igmplen = skb->tail - (unsigned char *)skb->h.igmph;
- pig->csum = ip_compute_csum((void *)skb->h.igmph, igmplen);
+ pig->csum = ip_compute_csum(igmp_hdr(skb), igmplen);
return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dev,
dst_output);
pgr->grec_auxwords = 0;
pgr->grec_nsrcs = 0;
pgr->grec_mca = pmc->multiaddr;
- pih = (struct igmpv3_report *)skb->h.igmph;
+ pih = igmpv3_report_hdr(skb);
pih->ngrec = htons(ntohs(pih->ngrec)+1);
*ppgr = pgr;
return skb;
if (!*psf_list)
goto empty_source;
- pih = skb ? (struct igmpv3_report *)skb->h.igmph : NULL;
+ pih = skb ? igmpv3_report_hdr(skb) : NULL;
/* EX and TO_EX get a fresh packet, if needed */
if (truncate) {
first = 1;
psf_prev = NULL;
for (psf=*psf_list; psf; psf=psf_next) {
- u32 *psrc;
+ __be32 *psrc;
psf_next = psf->sf_next;
if (isquery)
psf->sf_gsresp = 0;
- if (AVAILABLE(skb) < sizeof(u32) +
+ if (AVAILABLE(skb) < sizeof(__be32) +
first*sizeof(struct igmpv3_grec)) {
if (truncate && !first)
break; /* truncate these */
skb = add_grhead(skb, pmc, type, &pgr);
first = 0;
}
- psrc = (u32 *)skb_put(skb, sizeof(u32));
+ if (!skb)
+ return NULL;
+ psrc = (__be32 *)skb_put(skb, sizeof(__be32));
*psrc = psf->sf_inaddr;
scount++; stotal++;
if ((type == IGMPV3_ALLOW_NEW_SOURCES ||
struct igmphdr *ih;
struct rtable *rt;
struct net_device *dev = in_dev->dev;
- u32 group = pmc ? pmc->multiaddr : 0;
- u32 dst;
+ __be32 group = pmc ? pmc->multiaddr : 0;
+ __be32 dst;
if (type == IGMPV3_HOST_MEMBERSHIP_REPORT)
return igmpv3_send_report(in_dev, pmc);
skb_reserve(skb, LL_RESERVED_SPACE(dev));
- skb->nh.iph = iph = (struct iphdr *)skb_put(skb, sizeof(struct iphdr)+4);
+ skb_reset_network_header(skb);
+ iph = ip_hdr(skb);
+ skb_put(skb, sizeof(struct iphdr) + 4);
iph->version = 4;
iph->ihl = (sizeof(struct iphdr)+4)>>2;
{
if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev))
return;
- in_dev->mr_ifc_count = in_dev->mr_qrv ? in_dev->mr_qrv :
+ in_dev->mr_ifc_count = in_dev->mr_qrv ? in_dev->mr_qrv :
IGMP_Unsolicited_Report_Count;
igmp_ifc_start_timer(in_dev, 1);
}
}
/* mark EXCLUDE-mode sources */
-static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs)
+static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs)
{
struct ip_sf_list *psf;
int i, scount;
return 1;
}
-static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs)
+static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __be32 *srcs)
{
struct ip_sf_list *psf;
int i, scount;
return 1;
}
-static void igmp_heard_report(struct in_device *in_dev, u32 group)
+static void igmp_heard_report(struct in_device *in_dev, __be32 group)
{
struct ip_mc_list *im;
static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
int len)
{
- struct igmphdr *ih = skb->h.igmph;
- struct igmpv3_query *ih3 = (struct igmpv3_query *)ih;
+ struct igmphdr *ih = igmp_hdr(skb);
+ struct igmpv3_query *ih3 = igmpv3_query_hdr(skb);
struct ip_mc_list *im;
- u32 group = ih->group;
+ __be32 group = ih->group;
int max_delay;
int mark = 0;
if (len == 8) {
if (ih->code == 0) {
/* Alas, old v1 router presents here. */
-
+
max_delay = IGMP_Query_Response_Interval;
in_dev->mr_v1_seen = jiffies +
IGMP_V1_Router_Present_Timeout;
} else { /* v3 */
if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)))
return;
-
- ih3 = (struct igmpv3_query *) skb->h.raw;
+
+ ih3 = igmpv3_query_hdr(skb);
if (ih3->nsrcs) {
- if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)
- + ntohs(ih3->nsrcs)*sizeof(__u32)))
+ if (!pskb_may_pull(skb, sizeof(struct igmpv3_query)
+ + ntohs(ih3->nsrcs)*sizeof(__be32)))
return;
- ih3 = (struct igmpv3_query *) skb->h.raw;
+ ih3 = igmpv3_query_hdr(skb);
}
max_delay = IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE);
else
im->gsquery = mark;
changed = !im->gsquery ||
- igmp_marksources(im, ntohs(ih3->nsrcs), ih3->srcs);
+ igmp_marksources(im, ntohs(ih3->nsrcs), ih3->srcs);
spin_unlock_bh(&im->lock);
if (changed)
igmp_mod_timer(im, max_delay);
goto drop;
switch (skb->ip_summed) {
- case CHECKSUM_HW:
- if (!(u16)csum_fold(skb->csum))
+ case CHECKSUM_COMPLETE:
+ if (!csum_fold(skb->csum))
break;
/* fall through */
case CHECKSUM_NONE:
goto drop;
}
- ih = skb->h.igmph;
+ ih = igmp_hdr(skb);
switch (ih->type) {
case IGMP_HOST_MEMBERSHIP_QUERY:
igmp_heard_query(in_dev, skb, len);
* Add a filter to a device
*/
-static void ip_mc_filter_add(struct in_device *in_dev, u32 addr)
+static void ip_mc_filter_add(struct in_device *in_dev, __be32 addr)
{
char buf[MAX_ADDR_LEN];
struct net_device *dev = in_dev->dev;
* Remove a filter from a device
*/
-static void ip_mc_filter_del(struct in_device *in_dev, u32 addr)
+static void ip_mc_filter_del(struct in_device *in_dev, __be32 addr)
{
char buf[MAX_ADDR_LEN];
struct net_device *dev = in_dev->dev;
* for deleted items allows change reports to use common code with
* non-deleted or query-response MCA's.
*/
- pmc = kmalloc(sizeof(*pmc), GFP_KERNEL);
+ pmc = kzalloc(sizeof(*pmc), GFP_KERNEL);
if (!pmc)
return;
- memset(pmc, 0, sizeof(*pmc));
spin_lock_bh(&im->lock);
pmc->interface = im->interface;
in_dev_hold(in_dev);
spin_unlock_bh(&in_dev->mc_tomb_lock);
}
-static void igmpv3_del_delrec(struct in_device *in_dev, __u32 multiaddr)
+static void igmpv3_del_delrec(struct in_device *in_dev, __be32 multiaddr)
{
struct ip_mc_list *pmc, *pmc_prev;
struct ip_sf_list *psf, *psf_next;
* A socket has joined a multicast group on device dev.
*/
-void ip_mc_inc_group(struct in_device *in_dev, u32 addr)
+void ip_mc_inc_group(struct in_device *in_dev, __be32 addr)
{
struct ip_mc_list *im;
}
/*
+ * Resend IGMP JOIN report; used for bonding.
+ */
+void ip_mc_rejoin_group(struct ip_mc_list *im)
+{
+#ifdef CONFIG_IP_MULTICAST
+ struct in_device *in_dev = im->interface;
+
+ if (im->multiaddr == IGMP_ALL_HOSTS)
+ return;
+
+ if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev)) {
+ igmp_mod_timer(im, IGMP_Initial_Report_Delay);
+ return;
+ }
+ /* else, v3 */
+ im->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
+ IGMP_Unsolicited_Report_Count;
+ igmp_ifc_event(in_dev);
+#endif
+}
+
+/*
* A socket has left a multicast group on device dev
*/
-void ip_mc_dec_group(struct in_device *in_dev, u32 addr)
+void ip_mc_dec_group(struct in_device *in_dev, __be32 addr)
{
struct ip_mc_list *i, **ip;
-
+
ASSERT_RTNL();
-
+
for (ip=&in_dev->mc_list; (i=*ip)!=NULL; ip=&i->next) {
if (i->multiaddr==addr) {
if (--i->users == 0) {
/*
* Join a socket to a group
*/
-int sysctl_igmp_max_memberships = IP_MAX_MEMBERSHIPS;
-int sysctl_igmp_max_msf = IP_MAX_MSF;
+int sysctl_igmp_max_memberships __read_mostly = IP_MAX_MEMBERSHIPS;
+int sysctl_igmp_max_msf __read_mostly = IP_MAX_MSF;
static int ip_mc_del1_src(struct ip_mc_list *pmc, int sfmode,
- __u32 *psfsrc)
+ __be32 *psfsrc)
{
struct ip_sf_list *psf, *psf_prev;
int rv = 0;
#ifdef CONFIG_IP_MULTICAST
if (psf->sf_oldin &&
!IGMP_V1_SEEN(in_dev) && !IGMP_V2_SEEN(in_dev)) {
- psf->sf_crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
+ psf->sf_crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
IGMP_Unsolicited_Report_Count;
psf->sf_next = pmc->tomb;
pmc->tomb = psf;
#define igmp_ifc_event(x) do { } while (0)
#endif
-static int ip_mc_del_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
- int sfcount, __u32 *psfsrc, int delta)
+static int ip_mc_del_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
+ int sfcount, __be32 *psfsrc, int delta)
{
struct ip_mc_list *pmc;
int changerec = 0;
/* filter mode change */
pmc->sfmode = MCAST_INCLUDE;
#ifdef CONFIG_IP_MULTICAST
- pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
+ pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
IGMP_Unsolicited_Report_Count;
in_dev->mr_ifc_count = pmc->crcount;
for (psf=pmc->sources; psf; psf = psf->sf_next)
* Add multicast single-source filter to the interface list
*/
static int ip_mc_add1_src(struct ip_mc_list *pmc, int sfmode,
- __u32 *psfsrc, int delta)
+ __be32 *psfsrc, int delta)
{
struct ip_sf_list *psf, *psf_prev;
psf_prev = psf;
}
if (!psf) {
- psf = kmalloc(sizeof(*psf), GFP_ATOMIC);
+ psf = kzalloc(sizeof(*psf), GFP_ATOMIC);
if (!psf)
return -ENOBUFS;
- memset(psf, 0, sizeof(*psf));
psf->sf_inaddr = *psfsrc;
if (psf_prev) {
psf_prev->sf_next = psf;
/*
* Add multicast source filter list to the interface list
*/
-static int ip_mc_add_src(struct in_device *in_dev, __u32 *pmca, int sfmode,
- int sfcount, __u32 *psfsrc, int delta)
+static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
+ int sfcount, __be32 *psfsrc, int delta)
{
struct ip_mc_list *pmc;
int isexclude;
#ifdef CONFIG_IP_MULTICAST
/* else no filters; keep old mode for reports */
- pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
+ pmc->crcount = in_dev->mr_qrv ? in_dev->mr_qrv :
IGMP_Unsolicited_Report_Count;
in_dev->mr_ifc_count = pmc->crcount;
for (psf=pmc->sources; psf; psf = psf->sf_next)
int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
{
int err;
- u32 addr = imr->imr_multiaddr.s_addr;
+ __be32 addr = imr->imr_multiaddr.s_addr;
struct ip_mc_socklist *iml=NULL, *i;
struct in_device *in_dev;
struct inet_sock *inet = inet_sk(sk);
struct inet_sock *inet = inet_sk(sk);
struct ip_mc_socklist *iml, **imlp;
struct in_device *in_dev;
- u32 group = imr->imr_multiaddr.s_addr;
+ __be32 group = imr->imr_multiaddr.s_addr;
u32 ifindex;
+ int ret = -EADDRNOTAVAIL;
rtnl_lock();
in_dev = ip_mc_find_dev(imr);
- if (!in_dev) {
- rtnl_unlock();
- return -ENODEV;
- }
ifindex = imr->imr_ifindex;
for (imlp = &inet->mc_list; (iml = *imlp) != NULL; imlp = &iml->next) {
- if (iml->multi.imr_multiaddr.s_addr == group &&
- iml->multi.imr_ifindex == ifindex) {
- (void) ip_mc_leave_src(sk, iml, in_dev);
+ if (iml->multi.imr_multiaddr.s_addr != group)
+ continue;
+ if (ifindex) {
+ if (iml->multi.imr_ifindex != ifindex)
+ continue;
+ } else if (imr->imr_address.s_addr && imr->imr_address.s_addr !=
+ iml->multi.imr_address.s_addr)
+ continue;
+
+ (void) ip_mc_leave_src(sk, iml, in_dev);
- *imlp = iml->next;
+ *imlp = iml->next;
+ if (in_dev)
ip_mc_dec_group(in_dev, group);
- rtnl_unlock();
- sock_kfree_s(sk, iml, sizeof(*iml));
- return 0;
- }
+ rtnl_unlock();
+ sock_kfree_s(sk, iml, sizeof(*iml));
+ return 0;
}
+ if (!in_dev)
+ ret = -ENODEV;
rtnl_unlock();
- return -EADDRNOTAVAIL;
+ return ret;
}
int ip_mc_source(int add, int omode, struct sock *sk, struct
{
int err;
struct ip_mreqn imr;
- u32 addr = mreqs->imr_multiaddr;
+ __be32 addr = mreqs->imr_multiaddr;
struct ip_mc_socklist *pmc;
struct in_device *in_dev = NULL;
struct inet_sock *inet = inet_sk(sk);
} else if (pmc->sfmode != omode) {
/* allow mode switches for empty-set filters */
ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 0, NULL, 0);
- ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, pmc->sfmode, 0,
+ ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, pmc->sfmode, 0,
NULL, 0);
pmc->sfmode = omode;
}
rv = !0;
for (i=0; i<psl->sl_count; i++) {
rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
- sizeof(__u32));
+ sizeof(__be32));
if (rv == 0)
break;
}
}
/* update the interface filter */
- ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, omode, 1,
+ ip_mc_del_src(in_dev, &mreqs->imr_multiaddr, omode, 1,
&mreqs->imr_sourceaddr, 1);
for (j=i+1; j<psl->sl_count; j++)
rv = 1; /* > 0 for insert logic below if sl_count is 0 */
for (i=0; i<psl->sl_count; i++) {
rv = memcmp(&psl->sl_addr[i], &mreqs->imr_sourceaddr,
- sizeof(__u32));
+ sizeof(__be32));
if (rv == 0)
break;
}
psl->sl_count++;
err = 0;
/* update the interface list */
- ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 1,
+ ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 1,
&mreqs->imr_sourceaddr, 1);
done:
rtnl_unlock();
{
int err = 0;
struct ip_mreqn imr;
- u32 addr = msf->imsf_multiaddr;
+ __be32 addr = msf->imsf_multiaddr;
struct ip_mc_socklist *pmc;
struct in_device *in_dev;
struct inet_sock *inet = inet_sk(sk);
{
int err, len, count, copycount;
struct ip_mreqn imr;
- u32 addr = msf->imsf_multiaddr;
+ __be32 addr = msf->imsf_multiaddr;
struct ip_mc_socklist *pmc;
struct in_device *in_dev;
struct inet_sock *inet = inet_sk(sk);
{
int err, i, count, copycount;
struct sockaddr_in *psin;
- u32 addr;
+ __be32 addr;
struct ip_mc_socklist *pmc;
struct inet_sock *inet = inet_sk(sk);
struct ip_sf_socklist *psl;
/*
* check if a multicast source filter allows delivery for a given <src,dst,intf>
*/
-int ip_mc_sf_allow(struct sock *sk, u32 loc_addr, u32 rmt_addr, int dif)
+int ip_mc_sf_allow(struct sock *sk, __be32 loc_addr, __be32 rmt_addr, int dif)
{
struct inet_sock *inet = inet_sk(sk);
struct ip_mc_socklist *pmc;
struct in_device *in_dev;
inet->mc_list = iml->next;
- if ((in_dev = inetdev_by_index(iml->multi.imr_ifindex)) != NULL) {
- (void) ip_mc_leave_src(sk, iml, in_dev);
+ in_dev = inetdev_by_index(iml->multi.imr_ifindex);
+ (void) ip_mc_leave_src(sk, iml, in_dev);
+ if (in_dev != NULL) {
ip_mc_dec_group(in_dev, iml->multi.imr_multiaddr.s_addr);
in_dev_put(in_dev);
}
sock_kfree_s(sk, iml, sizeof(*iml));
-
}
rtnl_unlock();
}
-int ip_check_mc(struct in_device *in_dev, u32 mc_addr, u32 src_addr, u16 proto)
+int ip_check_mc(struct in_device *in_dev, __be32 mc_addr, __be32 src_addr, u16 proto)
{
struct ip_mc_list *im;
struct ip_sf_list *psf;
struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq);
for (state->dev = dev_base, state->in_dev = NULL;
- state->dev;
+ state->dev;
state->dev = state->dev->next) {
struct in_device *in_dev;
in_dev = in_dev_get(state->dev);
static int igmp_mc_seq_show(struct seq_file *seq, void *v)
{
if (v == SEQ_START_TOKEN)
- seq_puts(seq,
+ seq_puts(seq,
"Idx\tDevice : Count Querier\tGroup Users Timer\tReporter\n");
else {
struct ip_mc_list *im = (struct ip_mc_list *)v;
}
seq_printf(seq,
- "\t\t\t\t%08lX %5d %d:%08lX\t\t%d\n",
+ "\t\t\t\t%08X %5d %d:%08lX\t\t%d\n",
im->multiaddr, im->users,
im->tm_running, im->tm_running ?
jiffies_to_clock_t(im->timer.expires-jiffies) : 0,
return 0;
}
-static struct seq_operations igmp_mc_seq_ops = {
+static const struct seq_operations igmp_mc_seq_ops = {
.start = igmp_mc_seq_start,
.next = igmp_mc_seq_next,
.stop = igmp_mc_seq_stop,
{
struct seq_file *seq;
int rc = -ENOMEM;
- struct igmp_mc_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ struct igmp_mc_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s)
goto out;
seq = file->private_data;
seq->private = s;
- memset(s, 0, sizeof(*s));
out:
return rc;
out_kfree:
goto out;
}
-static struct file_operations igmp_mc_seq_fops = {
+static const struct file_operations igmp_mc_seq_fops = {
.owner = THIS_MODULE,
.open = igmp_mc_seq_open,
.read = seq_read,
struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
for (state->dev = dev_base, state->idev = NULL, state->im = NULL;
- state->dev;
+ state->dev;
state->dev = state->dev->next) {
struct in_device *idev;
idev = in_dev_get(state->dev);
struct igmp_mcf_iter_state *state = igmp_mcf_seq_private(seq);
if (v == SEQ_START_TOKEN) {
- seq_printf(seq,
+ seq_printf(seq,
"%3s %6s "
"%10s %10s %6s %6s\n", "Idx",
"Device", "MCA",
} else {
seq_printf(seq,
"%3d %6.6s 0x%08x "
- "0x%08x %6lu %6lu\n",
- state->dev->ifindex, state->dev->name,
+ "0x%08x %6lu %6lu\n",
+ state->dev->ifindex, state->dev->name,
ntohl(state->im->multiaddr),
ntohl(psf->sf_inaddr),
psf->sf_count[MCAST_INCLUDE],
return 0;
}
-static struct seq_operations igmp_mcf_seq_ops = {
+static const struct seq_operations igmp_mcf_seq_ops = {
.start = igmp_mcf_seq_start,
.next = igmp_mcf_seq_next,
.stop = igmp_mcf_seq_stop,
{
struct seq_file *seq;
int rc = -ENOMEM;
- struct igmp_mcf_iter_state *s = kmalloc(sizeof(*s), GFP_KERNEL);
+ struct igmp_mcf_iter_state *s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s)
goto out;
seq = file->private_data;
seq->private = s;
- memset(s, 0, sizeof(*s));
out:
return rc;
out_kfree:
goto out;
}
-static struct file_operations igmp_mcf_seq_fops = {
+static const struct file_operations igmp_mcf_seq_fops = {
.owner = THIS_MODULE,
.open = igmp_mcf_seq_open,
.read = seq_read,
EXPORT_SYMBOL(ip_mc_dec_group);
EXPORT_SYMBOL(ip_mc_inc_group);
EXPORT_SYMBOL(ip_mc_join_group);
+EXPORT_SYMBOL(ip_mc_rejoin_group);