aboutsummaryrefslogtreecommitdiffstats
path: root/net/bridge
diff options
context:
space:
mode:
Diffstat (limited to 'net/bridge')
-rw-r--r--net/bridge/br_device.c2
-rw-r--r--net/bridge/br_netlink.c73
-rw-r--r--net/bridge/br_private.h3
3 files changed, 18 insertions, 60 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 070e8a68cfc6..63b5b088e80f 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -313,6 +313,8 @@ static const struct net_device_ops br_netdev_ops = {
313 .ndo_fdb_add = br_fdb_add, 313 .ndo_fdb_add = br_fdb_add,
314 .ndo_fdb_del = br_fdb_delete, 314 .ndo_fdb_del = br_fdb_delete,
315 .ndo_fdb_dump = br_fdb_dump, 315 .ndo_fdb_dump = br_fdb_dump,
316 .ndo_bridge_getlink = br_getlink,
317 .ndo_bridge_setlink = br_setlink,
316}; 318};
317 319
318static void br_dev_free(struct net_device *dev) 320static void br_dev_free(struct net_device *dev)
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 093f527276a3..743511bb7319 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -111,54 +111,33 @@ errout:
111/* 111/*
112 * Dump information about all ports, in response to GETLINK 112 * Dump information about all ports, in response to GETLINK
113 */ 113 */
114static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) 114int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
115 struct net_device *dev)
115{ 116{
116 struct net *net = sock_net(skb->sk); 117 int err = 0;
117 struct net_device *dev; 118 struct net_bridge_port *port = br_port_get_rcu(dev);
118 int idx; 119
119 120 /* not a bridge port */
120 idx = 0; 121 if (!port)
121 rcu_read_lock(); 122 goto out;
122 for_each_netdev_rcu(net, dev) {
123 struct net_bridge_port *port = br_port_get_rcu(dev);
124
125 /* not a bridge port */
126 if (!port || idx < cb->args[0])
127 goto skip;
128
129 if (br_fill_ifinfo(skb, port,
130 NETLINK_CB(cb->skb).portid,
131 cb->nlh->nlmsg_seq, RTM_NEWLINK,
132 NLM_F_MULTI) < 0)
133 break;
134skip:
135 ++idx;
136 }
137 rcu_read_unlock();
138 cb->args[0] = idx;
139 123
140 return skb->len; 124 err = br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, NLM_F_MULTI);
125out:
126 return err;
141} 127}
142 128
143/* 129/*
144 * Change state of port (ie from forwarding to blocking etc) 130 * Change state of port (ie from forwarding to blocking etc)
145 * Used by spanning tree in user space. 131 * Used by spanning tree in user space.
146 */ 132 */
147static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 133int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
148{ 134{
149 struct net *net = sock_net(skb->sk);
150 struct ifinfomsg *ifm; 135 struct ifinfomsg *ifm;
151 struct nlattr *protinfo; 136 struct nlattr *protinfo;
152 struct net_device *dev;
153 struct net_bridge_port *p; 137 struct net_bridge_port *p;
154 u8 new_state; 138 u8 new_state;
155 139
156 if (nlmsg_len(nlh) < sizeof(*ifm))
157 return -EINVAL;
158
159 ifm = nlmsg_data(nlh); 140 ifm = nlmsg_data(nlh);
160 if (ifm->ifi_family != AF_BRIDGE)
161 return -EPFNOSUPPORT;
162 141
163 protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO); 142 protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO);
164 if (!protinfo || nla_len(protinfo) < sizeof(u8)) 143 if (!protinfo || nla_len(protinfo) < sizeof(u8))
@@ -168,10 +147,6 @@ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
168 if (new_state > BR_STATE_BLOCKING) 147 if (new_state > BR_STATE_BLOCKING)
169 return -EINVAL; 148 return -EINVAL;
170 149
171 dev = __dev_get_by_index(net, ifm->ifi_index);
172 if (!dev)
173 return -ENODEV;
174
175 p = br_port_get_rtnl(dev); 150 p = br_port_get_rtnl(dev);
176 if (!p) 151 if (!p)
177 return -EINVAL; 152 return -EINVAL;
@@ -218,29 +193,7 @@ struct rtnl_link_ops br_link_ops __read_mostly = {
218 193
219int __init br_netlink_init(void) 194int __init br_netlink_init(void)
220{ 195{
221 int err; 196 return rtnl_link_register(&br_link_ops);
222
223 err = rtnl_link_register(&br_link_ops);
224 if (err < 0)
225 goto err1;
226
227 err = __rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL,
228 br_dump_ifinfo, NULL);
229 if (err)
230 goto err2;
231 err = __rtnl_register(PF_BRIDGE, RTM_SETLINK,
232 br_rtm_setlink, NULL, NULL);
233 if (err)
234 goto err3;
235
236 return 0;
237
238err3:
239 rtnl_unregister_all(PF_BRIDGE);
240err2:
241 rtnl_link_unregister(&br_link_ops);
242err1:
243 return err;
244} 197}
245 198
246void __exit br_netlink_fini(void) 199void __exit br_netlink_fini(void)
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 9b278c4ebee1..fdcd5f626ca6 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -553,6 +553,9 @@ extern struct rtnl_link_ops br_link_ops;
553extern int br_netlink_init(void); 553extern int br_netlink_init(void);
554extern void br_netlink_fini(void); 554extern void br_netlink_fini(void);
555extern void br_ifinfo_notify(int event, struct net_bridge_port *port); 555extern void br_ifinfo_notify(int event, struct net_bridge_port *port);
556extern int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg);
557extern int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
558 struct net_device *dev);
556 559
557#ifdef CONFIG_SYSFS 560#ifdef CONFIG_SYSFS
558/* br_sysfs_if.c */ 561/* br_sysfs_if.c */