rtnetlink.c (905cf0abe8c2c892313f08e38d808eee4e794987) rtnetlink.c (2d011be8c07b50e8b3699d06ee11af5f5914b09a)
1/*
2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * Routing netlink socket interface: protocol independent part.
7 *
8 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>

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

4016 nlmsg_end(skb, nlh);
4017 return 0;
4018nla_put_failure:
4019 nlmsg_cancel(skb, nlh);
4020 return err ? err : -EMSGSIZE;
4021}
4022EXPORT_SYMBOL_GPL(ndo_dflt_bridge_getlink);
4023
1/*
2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * Routing netlink socket interface: protocol independent part.
7 *
8 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>

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

4016 nlmsg_end(skb, nlh);
4017 return 0;
4018nla_put_failure:
4019 nlmsg_cancel(skb, nlh);
4020 return err ? err : -EMSGSIZE;
4021}
4022EXPORT_SYMBOL_GPL(ndo_dflt_bridge_getlink);
4023
4024static int valid_bridge_getlink_req(const struct nlmsghdr *nlh,
4025 bool strict_check, u32 *filter_mask,
4026 struct netlink_ext_ack *extack)
4027{
4028 struct nlattr *tb[IFLA_MAX+1];
4029 int err, i;
4030
4031 if (strict_check) {
4032 struct ifinfomsg *ifm;
4033
4034 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
4035 NL_SET_ERR_MSG(extack, "Invalid header for bridge link dump");
4036 return -EINVAL;
4037 }
4038
4039 ifm = nlmsg_data(nlh);
4040 if (ifm->__ifi_pad || ifm->ifi_type || ifm->ifi_flags ||
4041 ifm->ifi_change || ifm->ifi_index) {
4042 NL_SET_ERR_MSG(extack, "Invalid values in header for bridge link dump request");
4043 return -EINVAL;
4044 }
4045
4046 err = nlmsg_parse_strict(nlh, sizeof(struct ifinfomsg), tb,
4047 IFLA_MAX, ifla_policy, extack);
4048 } else {
4049 err = nlmsg_parse(nlh, sizeof(struct ifinfomsg), tb,
4050 IFLA_MAX, ifla_policy, extack);
4051 }
4052 if (err < 0)
4053 return err;
4054
4055 /* new attributes should only be added with strict checking */
4056 for (i = 0; i <= IFLA_MAX; ++i) {
4057 if (!tb[i])
4058 continue;
4059
4060 switch (i) {
4061 case IFLA_EXT_MASK:
4062 *filter_mask = nla_get_u32(tb[i]);
4063 break;
4064 default:
4065 if (strict_check) {
4066 NL_SET_ERR_MSG(extack, "Unsupported attribute in bridge link dump request");
4067 return -EINVAL;
4068 }
4069 }
4070 }
4071
4072 return 0;
4073}
4074
4024static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
4025{
4075static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
4076{
4077 const struct nlmsghdr *nlh = cb->nlh;
4026 struct net *net = sock_net(skb->sk);
4027 struct net_device *dev;
4028 int idx = 0;
4029 u32 portid = NETLINK_CB(cb->skb).portid;
4078 struct net *net = sock_net(skb->sk);
4079 struct net_device *dev;
4080 int idx = 0;
4081 u32 portid = NETLINK_CB(cb->skb).portid;
4030 u32 seq = cb->nlh->nlmsg_seq;
4082 u32 seq = nlh->nlmsg_seq;
4031 u32 filter_mask = 0;
4032 int err;
4033
4083 u32 filter_mask = 0;
4084 int err;
4085
4034 if (nlmsg_len(cb->nlh) > sizeof(struct ifinfomsg)) {
4035 struct nlattr *extfilt;
4086 err = valid_bridge_getlink_req(nlh, cb->strict_check, &filter_mask,
4087 cb->extack);
4088 if (err < 0 && cb->strict_check)
4089 return err;
4036
4090
4037 extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct ifinfomsg),
4038 IFLA_EXT_MASK);
4039 if (extfilt) {
4040 if (nla_len(extfilt) < sizeof(filter_mask))
4041 return -EINVAL;
4042
4043 filter_mask = nla_get_u32(extfilt);
4044 }
4045 }
4046
4047 rcu_read_lock();
4048 for_each_netdev_rcu(net, dev) {
4049 const struct net_device_ops *ops = dev->netdev_ops;
4050 struct net_device *br_dev = netdev_master_upper_dev_get(dev);
4051
4052 if (br_dev && br_dev->netdev_ops->ndo_bridge_getlink) {
4053 if (idx >= cb->args[0]) {
4054 err = br_dev->netdev_ops->ndo_bridge_getlink(

--- 865 unchanged lines hidden ---
4091 rcu_read_lock();
4092 for_each_netdev_rcu(net, dev) {
4093 const struct net_device_ops *ops = dev->netdev_ops;
4094 struct net_device *br_dev = netdev_master_upper_dev_get(dev);
4095
4096 if (br_dev && br_dev->netdev_ops->ndo_bridge_getlink) {
4097 if (idx >= cb->args[0]) {
4098 err = br_dev->netdev_ops->ndo_bridge_getlink(

--- 865 unchanged lines hidden ---