static int packet_mc_drop(struct sock *sk, struct packet_mreq *mreq) { struct packet_mclist *ml, **mlp; rtnl_lock(); for (mlp = &pkt_sk(sk)->mclist; (ml = *mlp) != NULL; mlp = &ml->next) { if (ml->ifindex == mreq->mr_ifindex && ml->type == mreq->mr_type && ml->alen == mreq->mr_alen && memcmp(ml->addr, mreq->mr_address, ml->alen) == 0) { if (--ml->count == 0) { struct net_device *dev; *mlp = ml->next; dev = dev_get_by_index(ml->ifindex); if (dev) { packet_dev_mc(dev, ml, -1); dev_put(dev); } kfree(ml); } rtnl_unlock(); return 0; } } rtnl_unlock(); return -EADDRNOTAVAIL; }
static void packet_dev_mclist(struct net_device *dev, struct packet_mclist *i, int what) { for ( ; i; i=i->next) { if (i->ifindex == dev->ifindex) packet_dev_mc(dev, i, what); } }
static int packet_mc_add(struct sock *sk, struct packet_mreq *mreq) { struct packet_sock *po = pkt_sk(sk); struct packet_mclist *ml, *i; struct net_device *dev; int err; rtnl_lock(); err = -ENODEV; dev = __dev_get_by_index(mreq->mr_ifindex); if (!dev) goto done; err = -EINVAL; if (mreq->mr_alen > dev->addr_len) goto done; err = -ENOBUFS; i = (struct packet_mclist *)kmalloc(sizeof(*i), GFP_KERNEL); if (i == NULL) goto done; err = 0; for (ml = po->mclist; ml; ml = ml->next) { if (ml->ifindex == mreq->mr_ifindex && ml->type == mreq->mr_type && ml->alen == mreq->mr_alen && memcmp(ml->addr, mreq->mr_address, ml->alen) == 0) { ml->count++; /* Free the new element ... */ kfree(i); goto done; } } i->type = mreq->mr_type; i->ifindex = mreq->mr_ifindex; i->alen = mreq->mr_alen; memcpy(i->addr, mreq->mr_address, i->alen); i->count = 1; i->next = po->mclist; po->mclist = i; packet_dev_mc(dev, i, +1); done: rtnl_unlock(); return err; }
static void packet_flush_mclist(struct sock *sk) { struct packet_mclist *ml; if (sk->protinfo.af_packet->mclist == NULL) return; rtnl_lock(); while ((ml=sk->protinfo.af_packet->mclist) != NULL) { struct net_device *dev; sk->protinfo.af_packet->mclist = ml->next; if ((dev = dev_get_by_index(ml->ifindex)) != NULL) { packet_dev_mc(dev, ml, -1); dev_put(dev); } kfree(ml); } rtnl_unlock(); }
static void packet_flush_mclist(struct sock *sk) { struct packet_sock *po = pkt_sk(sk); struct packet_mclist *ml; if (!po->mclist) return; rtnl_lock(); while ((ml = po->mclist) != NULL) { struct net_device *dev; po->mclist = ml->next; if ((dev = dev_get_by_index(ml->ifindex)) != NULL) { packet_dev_mc(dev, ml, -1); dev_put(dev); } kfree(ml); } rtnl_unlock(); }