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 --- |