@@ -1505,3 +1505,151 @@ void br_vlan_port_event(struct net_bridge_port *p, unsigned long event)
1505
1505
break ;
1506
1506
}
1507
1507
}
1508
+
1509
+ static bool br_vlan_fill_vids (struct sk_buff * skb , u16 vid , u16 flags )
1510
+ {
1511
+ struct bridge_vlan_info info ;
1512
+ struct nlattr * nest ;
1513
+
1514
+ nest = nla_nest_start (skb , BRIDGE_VLANDB_ENTRY );
1515
+ if (!nest )
1516
+ return false;
1517
+
1518
+ memset (& info , 0 , sizeof (info ));
1519
+ info .vid = vid ;
1520
+ if (flags & BRIDGE_VLAN_INFO_UNTAGGED )
1521
+ info .flags |= BRIDGE_VLAN_INFO_UNTAGGED ;
1522
+ if (flags & BRIDGE_VLAN_INFO_PVID )
1523
+ info .flags |= BRIDGE_VLAN_INFO_PVID ;
1524
+
1525
+ if (nla_put (skb , BRIDGE_VLANDB_ENTRY_INFO , sizeof (info ), & info ))
1526
+ goto out_err ;
1527
+
1528
+ nla_nest_end (skb , nest );
1529
+
1530
+ return true;
1531
+
1532
+ out_err :
1533
+ nla_nest_cancel (skb , nest );
1534
+ return false;
1535
+ }
1536
+
1537
+ static int br_vlan_dump_dev (const struct net_device * dev ,
1538
+ struct sk_buff * skb ,
1539
+ struct netlink_callback * cb )
1540
+ {
1541
+ struct net_bridge_vlan_group * vg ;
1542
+ int idx = 0 , s_idx = cb -> args [1 ];
1543
+ struct nlmsghdr * nlh = NULL ;
1544
+ struct net_bridge_vlan * v ;
1545
+ struct net_bridge_port * p ;
1546
+ struct br_vlan_msg * bvm ;
1547
+ struct net_bridge * br ;
1548
+ int err = 0 ;
1549
+ u16 pvid ;
1550
+
1551
+ if (!netif_is_bridge_master (dev ) && !netif_is_bridge_port (dev ))
1552
+ return - EINVAL ;
1553
+
1554
+ if (netif_is_bridge_master (dev )) {
1555
+ br = netdev_priv (dev );
1556
+ vg = br_vlan_group_rcu (br );
1557
+ p = NULL ;
1558
+ } else {
1559
+ p = br_port_get_rcu (dev );
1560
+ if (WARN_ON (!p ))
1561
+ return - EINVAL ;
1562
+ vg = nbp_vlan_group_rcu (p );
1563
+ br = p -> br ;
1564
+ }
1565
+
1566
+ if (!vg )
1567
+ return 0 ;
1568
+
1569
+ nlh = nlmsg_put (skb , NETLINK_CB (cb -> skb ).portid , cb -> nlh -> nlmsg_seq ,
1570
+ RTM_NEWVLAN , sizeof (* bvm ), NLM_F_MULTI );
1571
+ if (!nlh )
1572
+ return - EMSGSIZE ;
1573
+ bvm = nlmsg_data (nlh );
1574
+ memset (bvm , 0 , sizeof (* bvm ));
1575
+ bvm -> family = PF_BRIDGE ;
1576
+ bvm -> ifindex = dev -> ifindex ;
1577
+ pvid = br_get_pvid (vg );
1578
+
1579
+ list_for_each_entry_rcu (v , & vg -> vlan_list , vlist ) {
1580
+ if (!br_vlan_should_use (v ))
1581
+ continue ;
1582
+ if (idx < s_idx )
1583
+ goto skip ;
1584
+ if (!br_vlan_fill_vids (skb , v -> vid , br_vlan_flags (v , pvid ))) {
1585
+ err = - EMSGSIZE ;
1586
+ break ;
1587
+ }
1588
+ skip :
1589
+ idx ++ ;
1590
+ }
1591
+ if (err )
1592
+ cb -> args [1 ] = idx ;
1593
+ else
1594
+ cb -> args [1 ] = 0 ;
1595
+ nlmsg_end (skb , nlh );
1596
+
1597
+ return err ;
1598
+ }
1599
+
1600
+ static int br_vlan_rtm_dump (struct sk_buff * skb , struct netlink_callback * cb )
1601
+ {
1602
+ int idx = 0 , err = 0 , s_idx = cb -> args [0 ];
1603
+ struct net * net = sock_net (skb -> sk );
1604
+ struct br_vlan_msg * bvm ;
1605
+ struct net_device * dev ;
1606
+
1607
+ err = nlmsg_parse (cb -> nlh , sizeof (* bvm ), NULL , 0 , NULL , cb -> extack );
1608
+ if (err < 0 )
1609
+ return err ;
1610
+
1611
+ bvm = nlmsg_data (cb -> nlh );
1612
+
1613
+ rcu_read_lock ();
1614
+ if (bvm -> ifindex ) {
1615
+ dev = dev_get_by_index_rcu (net , bvm -> ifindex );
1616
+ if (!dev ) {
1617
+ err = - ENODEV ;
1618
+ goto out_err ;
1619
+ }
1620
+ err = br_vlan_dump_dev (dev , skb , cb );
1621
+ if (err && err != - EMSGSIZE )
1622
+ goto out_err ;
1623
+ } else {
1624
+ for_each_netdev_rcu (net , dev ) {
1625
+ if (idx < s_idx )
1626
+ goto skip ;
1627
+
1628
+ err = br_vlan_dump_dev (dev , skb , cb );
1629
+ if (err == - EMSGSIZE )
1630
+ break ;
1631
+ skip :
1632
+ idx ++ ;
1633
+ }
1634
+ }
1635
+ cb -> args [0 ] = idx ;
1636
+ rcu_read_unlock ();
1637
+
1638
+ return skb -> len ;
1639
+
1640
+ out_err :
1641
+ rcu_read_unlock ();
1642
+
1643
+ return err ;
1644
+ }
1645
+
1646
+ void br_vlan_rtnl_init (void )
1647
+ {
1648
+ rtnl_register_module (THIS_MODULE , PF_BRIDGE , RTM_GETVLAN , NULL ,
1649
+ br_vlan_rtm_dump , 0 );
1650
+ }
1651
+
1652
+ void br_vlan_rtnl_uninit (void )
1653
+ {
1654
+ rtnl_unregister (PF_BRIDGE , RTM_GETVLAN );
1655
+ }
0 commit comments