@@ -975,9 +975,6 @@ static int br_ip4_multicast_igmp3_report(struct net_bridge *br,
975
975
int err = 0 ;
976
976
__be32 group ;
977
977
978
- if (!pskb_may_pull (skb , sizeof (* ih )))
979
- return - EINVAL ;
980
-
981
978
ih = igmpv3_report_hdr (skb );
982
979
num = ntohs (ih -> ngrec );
983
980
len = sizeof (* ih );
@@ -1248,25 +1245,14 @@ static int br_ip4_multicast_query(struct net_bridge *br,
1248
1245
max_delay = 10 * HZ ;
1249
1246
group = 0 ;
1250
1247
}
1251
- } else {
1252
- if (!pskb_may_pull (skb , sizeof (struct igmpv3_query ))) {
1253
- err = - EINVAL ;
1254
- goto out ;
1255
- }
1256
-
1248
+ } else if (skb -> len >= sizeof (* ih3 )) {
1257
1249
ih3 = igmpv3_query_hdr (skb );
1258
1250
if (ih3 -> nsrcs )
1259
1251
goto out ;
1260
1252
1261
1253
max_delay = ih3 -> code ?
1262
1254
IGMPV3_MRC (ih3 -> code ) * (HZ / IGMP_TIMER_SCALE ) : 1 ;
1263
- }
1264
-
1265
- /* RFC2236+RFC3376 (IGMPv2+IGMPv3) require the multicast link layer
1266
- * all-systems destination addresses (224.0.0.1) for general queries
1267
- */
1268
- if (!group && iph -> daddr != htonl (INADDR_ALLHOSTS_GROUP )) {
1269
- err = - EINVAL ;
1255
+ } else {
1270
1256
goto out ;
1271
1257
}
1272
1258
@@ -1329,12 +1315,6 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1329
1315
(port && port -> state == BR_STATE_DISABLED ))
1330
1316
goto out ;
1331
1317
1332
- /* RFC2710+RFC3810 (MLDv1+MLDv2) require link-local source addresses */
1333
- if (!(ipv6_addr_type (& ip6h -> saddr ) & IPV6_ADDR_LINKLOCAL )) {
1334
- err = - EINVAL ;
1335
- goto out ;
1336
- }
1337
-
1338
1318
if (skb -> len == sizeof (* mld )) {
1339
1319
if (!pskb_may_pull (skb , sizeof (* mld ))) {
1340
1320
err = - EINVAL ;
@@ -1358,14 +1338,6 @@ static int br_ip6_multicast_query(struct net_bridge *br,
1358
1338
1359
1339
is_general_query = group && ipv6_addr_any (group );
1360
1340
1361
- /* RFC2710+RFC3810 (MLDv1+MLDv2) require the multicast link layer
1362
- * all-nodes destination address (ff02::1) for general queries
1363
- */
1364
- if (is_general_query && !ipv6_addr_is_ll_all_nodes (& ip6h -> daddr )) {
1365
- err = - EINVAL ;
1366
- goto out ;
1367
- }
1368
-
1369
1341
if (is_general_query ) {
1370
1342
saddr .proto = htons (ETH_P_IPV6 );
1371
1343
saddr .u .ip6 = ip6h -> saddr ;
@@ -1557,66 +1529,22 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
1557
1529
struct sk_buff * skb ,
1558
1530
u16 vid )
1559
1531
{
1560
- struct sk_buff * skb2 = skb ;
1561
- const struct iphdr * iph ;
1532
+ struct sk_buff * skb_trimmed = NULL ;
1562
1533
struct igmphdr * ih ;
1563
- unsigned int len ;
1564
- unsigned int offset ;
1565
1534
int err ;
1566
1535
1567
- /* We treat OOM as packet loss for now. */
1568
- if (!pskb_may_pull (skb , sizeof (* iph )))
1569
- return - EINVAL ;
1570
-
1571
- iph = ip_hdr (skb );
1572
-
1573
- if (iph -> ihl < 5 || iph -> version != 4 )
1574
- return - EINVAL ;
1575
-
1576
- if (!pskb_may_pull (skb , ip_hdrlen (skb )))
1577
- return - EINVAL ;
1578
-
1579
- iph = ip_hdr (skb );
1536
+ err = ip_mc_check_igmp (skb , & skb_trimmed );
1580
1537
1581
- if (unlikely (ip_fast_csum ((u8 * )iph , iph -> ihl )))
1582
- return - EINVAL ;
1583
-
1584
- if (iph -> protocol != IPPROTO_IGMP ) {
1585
- if (!ipv4_is_local_multicast (iph -> daddr ))
1538
+ if (err == - ENOMSG ) {
1539
+ if (!ipv4_is_local_multicast (ip_hdr (skb )-> daddr ))
1586
1540
BR_INPUT_SKB_CB (skb )-> mrouters_only = 1 ;
1587
1541
return 0 ;
1542
+ } else if (err < 0 ) {
1543
+ return err ;
1588
1544
}
1589
1545
1590
- len = ntohs (iph -> tot_len );
1591
- if (skb -> len < len || len < ip_hdrlen (skb ))
1592
- return - EINVAL ;
1593
-
1594
- if (skb -> len > len ) {
1595
- skb2 = skb_clone (skb , GFP_ATOMIC );
1596
- if (!skb2 )
1597
- return - ENOMEM ;
1598
-
1599
- err = pskb_trim_rcsum (skb2 , len );
1600
- if (err )
1601
- goto err_out ;
1602
- }
1603
-
1604
- len -= ip_hdrlen (skb2 );
1605
- offset = skb_network_offset (skb2 ) + ip_hdrlen (skb2 );
1606
- __skb_pull (skb2 , offset );
1607
- skb_reset_transport_header (skb2 );
1608
-
1609
- err = - EINVAL ;
1610
- if (!pskb_may_pull (skb2 , sizeof (* ih )))
1611
- goto out ;
1612
-
1613
- if (skb_checksum_simple_validate (skb2 ))
1614
- goto out ;
1615
-
1616
- err = 0 ;
1617
-
1618
1546
BR_INPUT_SKB_CB (skb )-> igmp = 1 ;
1619
- ih = igmp_hdr (skb2 );
1547
+ ih = igmp_hdr (skb );
1620
1548
1621
1549
switch (ih -> type ) {
1622
1550
case IGMP_HOST_MEMBERSHIP_REPORT :
@@ -1625,21 +1553,19 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
1625
1553
err = br_ip4_multicast_add_group (br , port , ih -> group , vid );
1626
1554
break ;
1627
1555
case IGMPV3_HOST_MEMBERSHIP_REPORT :
1628
- err = br_ip4_multicast_igmp3_report (br , port , skb2 , vid );
1556
+ err = br_ip4_multicast_igmp3_report (br , port , skb_trimmed , vid );
1629
1557
break ;
1630
1558
case IGMP_HOST_MEMBERSHIP_QUERY :
1631
- err = br_ip4_multicast_query (br , port , skb2 , vid );
1559
+ err = br_ip4_multicast_query (br , port , skb_trimmed , vid );
1632
1560
break ;
1633
1561
case IGMP_HOST_LEAVE_MESSAGE :
1634
1562
br_ip4_multicast_leave_group (br , port , ih -> group , vid );
1635
1563
break ;
1636
1564
}
1637
1565
1638
- out :
1639
- __skb_push (skb2 , offset );
1640
- err_out :
1641
- if (skb2 != skb )
1642
- kfree_skb (skb2 );
1566
+ if (skb_trimmed )
1567
+ kfree_skb (skb_trimmed );
1568
+
1643
1569
return err ;
1644
1570
}
1645
1571
@@ -1649,126 +1575,42 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
1649
1575
struct sk_buff * skb ,
1650
1576
u16 vid )
1651
1577
{
1652
- struct sk_buff * skb2 ;
1653
- const struct ipv6hdr * ip6h ;
1654
- u8 icmp6_type ;
1655
- u8 nexthdr ;
1656
- __be16 frag_off ;
1657
- unsigned int len ;
1658
- int offset ;
1578
+ struct sk_buff * skb_trimmed = NULL ;
1579
+ struct mld_msg * mld ;
1659
1580
int err ;
1660
1581
1661
- if (!pskb_may_pull (skb , sizeof (* ip6h )))
1662
- return - EINVAL ;
1582
+ err = ipv6_mc_check_mld (skb , & skb_trimmed );
1663
1583
1664
- ip6h = ipv6_hdr (skb );
1665
-
1666
- /*
1667
- * We're interested in MLD messages only.
1668
- * - Version is 6
1669
- * - MLD has always Router Alert hop-by-hop option
1670
- * - But we do not support jumbrograms.
1671
- */
1672
- if (ip6h -> version != 6 )
1673
- return 0 ;
1674
-
1675
- /* Prevent flooding this packet if there is no listener present */
1676
- if (!ipv6_addr_is_ll_all_nodes (& ip6h -> daddr ))
1677
- BR_INPUT_SKB_CB (skb )-> mrouters_only = 1 ;
1678
-
1679
- if (ip6h -> nexthdr != IPPROTO_HOPOPTS ||
1680
- ip6h -> payload_len == 0 )
1681
- return 0 ;
1682
-
1683
- len = ntohs (ip6h -> payload_len ) + sizeof (* ip6h );
1684
- if (skb -> len < len )
1685
- return - EINVAL ;
1686
-
1687
- nexthdr = ip6h -> nexthdr ;
1688
- offset = ipv6_skip_exthdr (skb , sizeof (* ip6h ), & nexthdr , & frag_off );
1689
-
1690
- if (offset < 0 || nexthdr != IPPROTO_ICMPV6 )
1584
+ if (err == - ENOMSG ) {
1585
+ if (!ipv6_addr_is_ll_all_nodes (& ipv6_hdr (skb )-> daddr ))
1586
+ BR_INPUT_SKB_CB (skb )-> mrouters_only = 1 ;
1691
1587
return 0 ;
1692
-
1693
- /* Okay, we found ICMPv6 header */
1694
- skb2 = skb_clone (skb , GFP_ATOMIC );
1695
- if (!skb2 )
1696
- return - ENOMEM ;
1697
-
1698
- err = - EINVAL ;
1699
- if (!pskb_may_pull (skb2 , offset + sizeof (struct icmp6hdr )))
1700
- goto out ;
1701
-
1702
- len -= offset - skb_network_offset (skb2 );
1703
-
1704
- __skb_pull (skb2 , offset );
1705
- skb_reset_transport_header (skb2 );
1706
- skb_postpull_rcsum (skb2 , skb_network_header (skb2 ),
1707
- skb_network_header_len (skb2 ));
1708
-
1709
- icmp6_type = icmp6_hdr (skb2 )-> icmp6_type ;
1710
-
1711
- switch (icmp6_type ) {
1712
- case ICMPV6_MGM_QUERY :
1713
- case ICMPV6_MGM_REPORT :
1714
- case ICMPV6_MGM_REDUCTION :
1715
- case ICMPV6_MLD2_REPORT :
1716
- break ;
1717
- default :
1718
- err = 0 ;
1719
- goto out ;
1720
- }
1721
-
1722
- /* Okay, we found MLD message. Check further. */
1723
- if (skb2 -> len > len ) {
1724
- err = pskb_trim_rcsum (skb2 , len );
1725
- if (err )
1726
- goto out ;
1727
- err = - EINVAL ;
1588
+ } else if (err < 0 ) {
1589
+ return err ;
1728
1590
}
1729
1591
1730
- ip6h = ipv6_hdr (skb2 );
1731
-
1732
- if (skb_checksum_validate (skb2 , IPPROTO_ICMPV6 , ip6_compute_pseudo ))
1733
- goto out ;
1734
-
1735
- err = 0 ;
1736
-
1737
1592
BR_INPUT_SKB_CB (skb )-> igmp = 1 ;
1593
+ mld = (struct mld_msg * )skb_transport_header (skb );
1738
1594
1739
- switch (icmp6_type ) {
1595
+ switch (mld -> mld_type ) {
1740
1596
case ICMPV6_MGM_REPORT :
1741
- {
1742
- struct mld_msg * mld ;
1743
- if (!pskb_may_pull (skb2 , sizeof (* mld ))) {
1744
- err = - EINVAL ;
1745
- goto out ;
1746
- }
1747
- mld = (struct mld_msg * )skb_transport_header (skb2 );
1748
1597
BR_INPUT_SKB_CB (skb )-> mrouters_only = 1 ;
1749
1598
err = br_ip6_multicast_add_group (br , port , & mld -> mld_mca , vid );
1750
1599
break ;
1751
- }
1752
1600
case ICMPV6_MLD2_REPORT :
1753
- err = br_ip6_multicast_mld2_report (br , port , skb2 , vid );
1601
+ err = br_ip6_multicast_mld2_report (br , port , skb_trimmed , vid );
1754
1602
break ;
1755
1603
case ICMPV6_MGM_QUERY :
1756
- err = br_ip6_multicast_query (br , port , skb2 , vid );
1604
+ err = br_ip6_multicast_query (br , port , skb_trimmed , vid );
1757
1605
break ;
1758
1606
case ICMPV6_MGM_REDUCTION :
1759
- {
1760
- struct mld_msg * mld ;
1761
- if (!pskb_may_pull (skb2 , sizeof (* mld ))) {
1762
- err = - EINVAL ;
1763
- goto out ;
1764
- }
1765
- mld = (struct mld_msg * )skb_transport_header (skb2 );
1766
1607
br_ip6_multicast_leave_group (br , port , & mld -> mld_mca , vid );
1767
- }
1608
+ break ;
1768
1609
}
1769
1610
1770
- out :
1771
- kfree_skb (skb2 );
1611
+ if (skb_trimmed )
1612
+ kfree_skb (skb_trimmed );
1613
+
1772
1614
return err ;
1773
1615
}
1774
1616
#endif
0 commit comments