mcast.c (b173ee488dcc545e77ed482158a2f0d06d7a5860) mcast.c (8965779d2c0e6ab246c82a405236b1fb2adae6b2)
1/*
2 * Multicast support for IPv6
3 * Linux INET6 implementation
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c

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

1346 hdr->payload_len = htons(len);
1347 hdr->nexthdr = proto;
1348 hdr->hop_limit = inet6_sk(sk)->hop_limit;
1349
1350 hdr->saddr = *saddr;
1351 hdr->daddr = *daddr;
1352}
1353
1/*
2 * Multicast support for IPv6
3 * Linux INET6 implementation
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c

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

1346 hdr->payload_len = htons(len);
1347 hdr->nexthdr = proto;
1348 hdr->hop_limit = inet6_sk(sk)->hop_limit;
1349
1350 hdr->saddr = *saddr;
1351 hdr->daddr = *daddr;
1352}
1353
1354static struct sk_buff *mld_newpack(struct net_device *dev, int size)
1354static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size)
1355{
1355{
1356 struct net_device *dev = idev->dev;
1356 struct net *net = dev_net(dev);
1357 struct sock *sk = net->ipv6.igmp_sk;
1358 struct sk_buff *skb;
1359 struct mld2_report *pmr;
1360 struct in6_addr addr_buf;
1361 const struct in6_addr *saddr;
1362 int hlen = LL_RESERVED_SPACE(dev);
1363 int tlen = dev->needed_tailroom;

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

1372 size = min_t(int, size, SKB_MAX_ORDER(0, 0));
1373 skb = sock_alloc_send_skb(sk, size, 1, &err);
1374
1375 if (!skb)
1376 return NULL;
1377
1378 skb_reserve(skb, hlen);
1379
1357 struct net *net = dev_net(dev);
1358 struct sock *sk = net->ipv6.igmp_sk;
1359 struct sk_buff *skb;
1360 struct mld2_report *pmr;
1361 struct in6_addr addr_buf;
1362 const struct in6_addr *saddr;
1363 int hlen = LL_RESERVED_SPACE(dev);
1364 int tlen = dev->needed_tailroom;

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

1373 size = min_t(int, size, SKB_MAX_ORDER(0, 0));
1374 skb = sock_alloc_send_skb(sk, size, 1, &err);
1375
1376 if (!skb)
1377 return NULL;
1378
1379 skb_reserve(skb, hlen);
1380
1380 if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) {
1381 if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) {
1381 /* <draft-ietf-magma-mld-source-05.txt>:
1382 * use unspecified address as the source address
1383 * when a valid link-local address is not available.
1384 */
1385 saddr = &in6addr_any;
1386 } else
1387 saddr = &addr_buf;
1388

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

1469static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc,
1470 int type, struct mld2_grec **ppgr)
1471{
1472 struct net_device *dev = pmc->idev->dev;
1473 struct mld2_report *pmr;
1474 struct mld2_grec *pgr;
1475
1476 if (!skb)
1382 /* <draft-ietf-magma-mld-source-05.txt>:
1383 * use unspecified address as the source address
1384 * when a valid link-local address is not available.
1385 */
1386 saddr = &in6addr_any;
1387 } else
1388 saddr = &addr_buf;
1389

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

1470static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc,
1471 int type, struct mld2_grec **ppgr)
1472{
1473 struct net_device *dev = pmc->idev->dev;
1474 struct mld2_report *pmr;
1475 struct mld2_grec *pgr;
1476
1477 if (!skb)
1477 skb = mld_newpack(dev, dev->mtu);
1478 skb = mld_newpack(pmc->idev, dev->mtu);
1478 if (!skb)
1479 return NULL;
1480 pgr = (struct mld2_grec *)skb_put(skb, sizeof(struct mld2_grec));
1481 pgr->grec_type = type;
1482 pgr->grec_auxwords = 0;
1483 pgr->grec_nsrcs = 0;
1484 pgr->grec_mca = pmc->mca_addr; /* structure copy */
1485 pmr = (struct mld2_report *)skb_transport_header(skb);
1486 pmr->mld2r_ngrec = htons(ntohs(pmr->mld2r_ngrec)+1);
1487 *ppgr = pgr;
1488 return skb;
1489}
1490
1491#define AVAILABLE(skb) ((skb) ? ((skb)->dev ? (skb)->dev->mtu - (skb)->len : \
1492 skb_tailroom(skb)) : 0)
1493
1494static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc,
1495 int type, int gdeleted, int sdeleted)
1496{
1479 if (!skb)
1480 return NULL;
1481 pgr = (struct mld2_grec *)skb_put(skb, sizeof(struct mld2_grec));
1482 pgr->grec_type = type;
1483 pgr->grec_auxwords = 0;
1484 pgr->grec_nsrcs = 0;
1485 pgr->grec_mca = pmc->mca_addr; /* structure copy */
1486 pmr = (struct mld2_report *)skb_transport_header(skb);
1487 pmr->mld2r_ngrec = htons(ntohs(pmr->mld2r_ngrec)+1);
1488 *ppgr = pgr;
1489 return skb;
1490}
1491
1492#define AVAILABLE(skb) ((skb) ? ((skb)->dev ? (skb)->dev->mtu - (skb)->len : \
1493 skb_tailroom(skb)) : 0)
1494
1495static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc,
1496 int type, int gdeleted, int sdeleted)
1497{
1497 struct net_device *dev = pmc->idev->dev;
1498 struct inet6_dev *idev = pmc->idev;
1499 struct net_device *dev = idev->dev;
1498 struct mld2_report *pmr;
1499 struct mld2_grec *pgr = NULL;
1500 struct ip6_sf_list *psf, *psf_next, *psf_prev, **psf_list;
1501 int scount, stotal, first, isquery, truncate;
1502
1503 if (pmc->mca_flags & MAF_NOREPORT)
1504 return skb;
1505

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

1518 pmr = skb ? (struct mld2_report *)skb_transport_header(skb) : NULL;
1519
1520 /* EX and TO_EX get a fresh packet, if needed */
1521 if (truncate) {
1522 if (pmr && pmr->mld2r_ngrec &&
1523 AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) {
1524 if (skb)
1525 mld_sendpack(skb);
1500 struct mld2_report *pmr;
1501 struct mld2_grec *pgr = NULL;
1502 struct ip6_sf_list *psf, *psf_next, *psf_prev, **psf_list;
1503 int scount, stotal, first, isquery, truncate;
1504
1505 if (pmc->mca_flags & MAF_NOREPORT)
1506 return skb;
1507

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

1520 pmr = skb ? (struct mld2_report *)skb_transport_header(skb) : NULL;
1521
1522 /* EX and TO_EX get a fresh packet, if needed */
1523 if (truncate) {
1524 if (pmr && pmr->mld2r_ngrec &&
1525 AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) {
1526 if (skb)
1527 mld_sendpack(skb);
1526 skb = mld_newpack(dev, dev->mtu);
1528 skb = mld_newpack(idev, dev->mtu);
1527 }
1528 }
1529 first = 1;
1530 psf_prev = NULL;
1531 for (psf=*psf_list; psf; psf=psf_next) {
1532 struct in6_addr *psrc;
1533
1534 psf_next = psf->sf_next;

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

1545 if (AVAILABLE(skb) < sizeof(*psrc) +
1546 first*sizeof(struct mld2_grec)) {
1547 if (truncate && !first)
1548 break; /* truncate these */
1549 if (pgr)
1550 pgr->grec_nsrcs = htons(scount);
1551 if (skb)
1552 mld_sendpack(skb);
1529 }
1530 }
1531 first = 1;
1532 psf_prev = NULL;
1533 for (psf=*psf_list; psf; psf=psf_next) {
1534 struct in6_addr *psrc;
1535
1536 psf_next = psf->sf_next;

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

1547 if (AVAILABLE(skb) < sizeof(*psrc) +
1548 first*sizeof(struct mld2_grec)) {
1549 if (truncate && !first)
1550 break; /* truncate these */
1551 if (pgr)
1552 pgr->grec_nsrcs = htons(scount);
1553 if (skb)
1554 mld_sendpack(skb);
1553 skb = mld_newpack(dev, dev->mtu);
1555 skb = mld_newpack(idev, dev->mtu);
1554 first = 1;
1555 scount = 0;
1556 }
1557 if (first) {
1558 skb = add_grhead(skb, pmc, type, &pgr);
1559 first = 0;
1560 }
1561 if (!skb)

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

1600 return skb;
1601}
1602
1603static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc)
1604{
1605 struct sk_buff *skb = NULL;
1606 int type;
1607
1556 first = 1;
1557 scount = 0;
1558 }
1559 if (first) {
1560 skb = add_grhead(skb, pmc, type, &pgr);
1561 first = 0;
1562 }
1563 if (!skb)

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

1602 return skb;
1603}
1604
1605static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc)
1606{
1607 struct sk_buff *skb = NULL;
1608 int type;
1609
1610 read_lock_bh(&idev->lock);
1608 if (!pmc) {
1611 if (!pmc) {
1609 read_lock_bh(&idev->lock);
1610 for (pmc=idev->mc_list; pmc; pmc=pmc->next) {
1611 if (pmc->mca_flags & MAF_NOREPORT)
1612 continue;
1613 spin_lock_bh(&pmc->mca_lock);
1614 if (pmc->mca_sfcount[MCAST_EXCLUDE])
1615 type = MLD2_MODE_IS_EXCLUDE;
1616 else
1617 type = MLD2_MODE_IS_INCLUDE;
1618 skb = add_grec(skb, pmc, type, 0, 0);
1619 spin_unlock_bh(&pmc->mca_lock);
1620 }
1612 for (pmc=idev->mc_list; pmc; pmc=pmc->next) {
1613 if (pmc->mca_flags & MAF_NOREPORT)
1614 continue;
1615 spin_lock_bh(&pmc->mca_lock);
1616 if (pmc->mca_sfcount[MCAST_EXCLUDE])
1617 type = MLD2_MODE_IS_EXCLUDE;
1618 else
1619 type = MLD2_MODE_IS_INCLUDE;
1620 skb = add_grec(skb, pmc, type, 0, 0);
1621 spin_unlock_bh(&pmc->mca_lock);
1622 }
1621 read_unlock_bh(&idev->lock);
1622 } else {
1623 spin_lock_bh(&pmc->mca_lock);
1624 if (pmc->mca_sfcount[MCAST_EXCLUDE])
1625 type = MLD2_MODE_IS_EXCLUDE;
1626 else
1627 type = MLD2_MODE_IS_INCLUDE;
1628 skb = add_grec(skb, pmc, type, 0, 0);
1629 spin_unlock_bh(&pmc->mca_lock);
1630 }
1623 } else {
1624 spin_lock_bh(&pmc->mca_lock);
1625 if (pmc->mca_sfcount[MCAST_EXCLUDE])
1626 type = MLD2_MODE_IS_EXCLUDE;
1627 else
1628 type = MLD2_MODE_IS_INCLUDE;
1629 skb = add_grec(skb, pmc, type, 0, 0);
1630 spin_unlock_bh(&pmc->mca_lock);
1631 }
1632 read_unlock_bh(&idev->lock);
1631 if (skb)
1632 mld_sendpack(skb);
1633}
1634
1635/*
1636 * remove zero-count source records from a source filter list
1637 */
1638static void mld_clear_zeros(struct ip6_sf_list **ppsf)

--- 1091 unchanged lines hidden ---
1633 if (skb)
1634 mld_sendpack(skb);
1635}
1636
1637/*
1638 * remove zero-count source records from a source filter list
1639 */
1640static void mld_clear_zeros(struct ip6_sf_list **ppsf)

--- 1091 unchanged lines hidden ---