igmp.c (1da177e4c3f41524e886b7f1b8a0c1fc7321cac2) igmp.c (ca9b907d140a5f249250d19f956129dbbbf84f73)
1/*
2 * Linux NET3: Internet Group Management Protocol [IGMP]
3 *
4 * This code implements the IGMP protocol as defined in RFC1112. There has
5 * been a further revision of this protocol since which is now supported.
6 *
7 * If you have trouble with this module be careful what gcc you have used,
8 * the older version didn't come out right using gcc 2.5.8, the newer one

--- 1601 unchanged lines hidden (view full) ---

1610
1611/*
1612 * Join a multicast group
1613 */
1614int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
1615{
1616 int err;
1617 u32 addr = imr->imr_multiaddr.s_addr;
1/*
2 * Linux NET3: Internet Group Management Protocol [IGMP]
3 *
4 * This code implements the IGMP protocol as defined in RFC1112. There has
5 * been a further revision of this protocol since which is now supported.
6 *
7 * If you have trouble with this module be careful what gcc you have used,
8 * the older version didn't come out right using gcc 2.5.8, the newer one

--- 1601 unchanged lines hidden (view full) ---

1610
1611/*
1612 * Join a multicast group
1613 */
1614int ip_mc_join_group(struct sock *sk , struct ip_mreqn *imr)
1615{
1616 int err;
1617 u32 addr = imr->imr_multiaddr.s_addr;
1618 struct ip_mc_socklist *iml, *i;
1618 struct ip_mc_socklist *iml=NULL, *i;
1619 struct in_device *in_dev;
1620 struct inet_sock *inet = inet_sk(sk);
1619 struct in_device *in_dev;
1620 struct inet_sock *inet = inet_sk(sk);
1621 int ifindex;
1621 int count = 0;
1622
1623 if (!MULTICAST(addr))
1624 return -EINVAL;
1625
1626 rtnl_shlock();
1627
1628 in_dev = ip_mc_find_dev(imr);
1629
1630 if (!in_dev) {
1631 iml = NULL;
1632 err = -ENODEV;
1633 goto done;
1634 }
1635
1622 int count = 0;
1623
1624 if (!MULTICAST(addr))
1625 return -EINVAL;
1626
1627 rtnl_shlock();
1628
1629 in_dev = ip_mc_find_dev(imr);
1630
1631 if (!in_dev) {
1632 iml = NULL;
1633 err = -ENODEV;
1634 goto done;
1635 }
1636
1636 iml = (struct ip_mc_socklist *)sock_kmalloc(sk, sizeof(*iml), GFP_KERNEL);
1637
1638 err = -EADDRINUSE;
1637 err = -EADDRINUSE;
1638 ifindex = imr->imr_ifindex;
1639 for (i = inet->mc_list; i; i = i->next) {
1639 for (i = inet->mc_list; i; i = i->next) {
1640 if (memcmp(&i->multi, imr, sizeof(*imr)) == 0) {
1641 /* New style additions are reference counted */
1642 if (imr->imr_address.s_addr == 0) {
1643 i->count++;
1644 err = 0;
1645 }
1640 if (i->multi.imr_multiaddr.s_addr == addr &&
1641 i->multi.imr_ifindex == ifindex)
1646 goto done;
1642 goto done;
1647 }
1648 count++;
1649 }
1650 err = -ENOBUFS;
1643 count++;
1644 }
1645 err = -ENOBUFS;
1651 if (iml == NULL || count >= sysctl_igmp_max_memberships)
1646 if (count >= sysctl_igmp_max_memberships)
1652 goto done;
1647 goto done;
1648 iml = (struct ip_mc_socklist *)sock_kmalloc(sk,sizeof(*iml),GFP_KERNEL);
1649 if (iml == NULL)
1650 goto done;
1651
1653 memcpy(&iml->multi, imr, sizeof(*imr));
1654 iml->next = inet->mc_list;
1652 memcpy(&iml->multi, imr, sizeof(*imr));
1653 iml->next = inet->mc_list;
1655 iml->count = 1;
1656 iml->sflist = NULL;
1657 iml->sfmode = MCAST_EXCLUDE;
1658 inet->mc_list = iml;
1659 ip_mc_inc_group(in_dev, addr);
1654 iml->sflist = NULL;
1655 iml->sfmode = MCAST_EXCLUDE;
1656 inet->mc_list = iml;
1657 ip_mc_inc_group(in_dev, addr);
1660 iml = NULL;
1661 err = 0;
1658 err = 0;
1662
1663done:
1664 rtnl_shunlock();
1659done:
1660 rtnl_shunlock();
1665 if (iml)
1666 sock_kfree_s(sk, iml, sizeof(*iml));
1667 return err;
1668}
1669
1670static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,
1671 struct in_device *in_dev)
1672{
1673 int err;
1674

--- 24 unchanged lines hidden (view full) ---

1699 if (iml->multi.imr_multiaddr.s_addr==imr->imr_multiaddr.s_addr &&
1700 iml->multi.imr_address.s_addr==imr->imr_address.s_addr &&
1701 (!imr->imr_ifindex || iml->multi.imr_ifindex==imr->imr_ifindex)) {
1702 struct in_device *in_dev;
1703
1704 in_dev = inetdev_by_index(iml->multi.imr_ifindex);
1705 if (in_dev)
1706 (void) ip_mc_leave_src(sk, iml, in_dev);
1661 return err;
1662}
1663
1664static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,
1665 struct in_device *in_dev)
1666{
1667 int err;
1668

--- 24 unchanged lines hidden (view full) ---

1693 if (iml->multi.imr_multiaddr.s_addr==imr->imr_multiaddr.s_addr &&
1694 iml->multi.imr_address.s_addr==imr->imr_address.s_addr &&
1695 (!imr->imr_ifindex || iml->multi.imr_ifindex==imr->imr_ifindex)) {
1696 struct in_device *in_dev;
1697
1698 in_dev = inetdev_by_index(iml->multi.imr_ifindex);
1699 if (in_dev)
1700 (void) ip_mc_leave_src(sk, iml, in_dev);
1707 if (--iml->count) {
1708 rtnl_unlock();
1709 if (in_dev)
1710 in_dev_put(in_dev);
1711 return 0;
1712 }
1713
1714 *imlp = iml->next;
1715
1716 if (in_dev) {
1717 ip_mc_dec_group(in_dev, imr->imr_multiaddr.s_addr);
1718 in_dev_put(in_dev);
1719 }
1720 rtnl_unlock();

--- 29 unchanged lines hidden (view full) ---

1750
1751 if (!in_dev) {
1752 err = -ENODEV;
1753 goto done;
1754 }
1755 err = -EADDRNOTAVAIL;
1756
1757 for (pmc=inet->mc_list; pmc; pmc=pmc->next) {
1701
1702 *imlp = iml->next;
1703
1704 if (in_dev) {
1705 ip_mc_dec_group(in_dev, imr->imr_multiaddr.s_addr);
1706 in_dev_put(in_dev);
1707 }
1708 rtnl_unlock();

--- 29 unchanged lines hidden (view full) ---

1738
1739 if (!in_dev) {
1740 err = -ENODEV;
1741 goto done;
1742 }
1743 err = -EADDRNOTAVAIL;
1744
1745 for (pmc=inet->mc_list; pmc; pmc=pmc->next) {
1758 if (memcmp(&pmc->multi, mreqs, 2*sizeof(__u32)) == 0)
1746 if (pmc->multi.imr_multiaddr.s_addr == imr.imr_multiaddr.s_addr
1747 && pmc->multi.imr_ifindex == imr.imr_ifindex)
1759 break;
1760 }
1761 if (!pmc) /* must have a prior join */
1762 goto done;
1763 /* if a source filter was set, must be the same mode as before */
1764 if (pmc->sflist) {
1765 if (pmc->sfmode != omode)
1766 goto done;

--- 707 unchanged lines hidden ---
1748 break;
1749 }
1750 if (!pmc) /* must have a prior join */
1751 goto done;
1752 /* if a source filter was set, must be the same mode as before */
1753 if (pmc->sflist) {
1754 if (pmc->sfmode != omode)
1755 goto done;

--- 707 unchanged lines hidden ---