]> rtime.felk.cvut.cz Git - can-eth-gw-linux.git/blob - net/bridge/br_netlink.c
bridge: implement BPDU blocking
[can-eth-gw-linux.git] / net / bridge / br_netlink.c
1 /*
2  *      Bridge netlink control interface
3  *
4  *      Authors:
5  *      Stephen Hemminger               <shemminger@osdl.org>
6  *
7  *      This program is free software; you can redistribute it and/or
8  *      modify it under the terms of the GNU General Public License
9  *      as published by the Free Software Foundation; either version
10  *      2 of the License, or (at your option) any later version.
11  */
12
13 #include <linux/kernel.h>
14 #include <linux/slab.h>
15 #include <linux/etherdevice.h>
16 #include <net/rtnetlink.h>
17 #include <net/net_namespace.h>
18 #include <net/sock.h>
19
20 #include "br_private.h"
21 #include "br_private_stp.h"
22
23 static inline size_t br_port_info_size(void)
24 {
25         return nla_total_size(1)        /* IFLA_BRPORT_STATE  */
26                 + nla_total_size(2)     /* IFLA_BRPORT_PRIORITY */
27                 + nla_total_size(4)     /* IFLA_BRPORT_COST */
28                 + nla_total_size(1)     /* IFLA_BRPORT_MODE */
29                 + nla_total_size(1)     /* IFLA_BRPORT_GUARD */
30                 + 0;
31 }
32
33 static inline size_t br_nlmsg_size(void)
34 {
35         return NLMSG_ALIGN(sizeof(struct ifinfomsg))
36                 + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
37                 + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
38                 + nla_total_size(4) /* IFLA_MASTER */
39                 + nla_total_size(4) /* IFLA_MTU */
40                 + nla_total_size(4) /* IFLA_LINK */
41                 + nla_total_size(1) /* IFLA_OPERSTATE */
42                 + nla_total_size(br_port_info_size()); /* IFLA_PROTINFO */
43 }
44
45 static int br_port_fill_attrs(struct sk_buff *skb,
46                               const struct net_bridge_port *p)
47 {
48         u8 mode = !!(p->flags & BR_HAIRPIN_MODE);
49
50         if (nla_put_u8(skb, IFLA_BRPORT_STATE, p->state) ||
51             nla_put_u16(skb, IFLA_BRPORT_PRIORITY, p->priority) ||
52             nla_put_u32(skb, IFLA_BRPORT_COST, p->path_cost) ||
53             nla_put_u8(skb, IFLA_BRPORT_MODE, mode) ||
54             nla_put_u8(skb, IFLA_BRPORT_GUARD, !!(p->flags & BR_BPDU_GUARD)))
55                 return -EMSGSIZE;
56
57         return 0;
58 }
59
60 /*
61  * Create one netlink message for one interface
62  * Contains port and master info as well as carrier and bridge state.
63  */
64 static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *port,
65                           u32 pid, u32 seq, int event, unsigned int flags)
66 {
67         const struct net_bridge *br = port->br;
68         const struct net_device *dev = port->dev;
69         struct ifinfomsg *hdr;
70         struct nlmsghdr *nlh;
71         u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
72
73         br_debug(br, "br_fill_info event %d port %s master %s\n",
74                      event, dev->name, br->dev->name);
75
76         nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
77         if (nlh == NULL)
78                 return -EMSGSIZE;
79
80         hdr = nlmsg_data(nlh);
81         hdr->ifi_family = AF_BRIDGE;
82         hdr->__ifi_pad = 0;
83         hdr->ifi_type = dev->type;
84         hdr->ifi_index = dev->ifindex;
85         hdr->ifi_flags = dev_get_flags(dev);
86         hdr->ifi_change = 0;
87
88         if (nla_put_string(skb, IFLA_IFNAME, dev->name) ||
89             nla_put_u32(skb, IFLA_MASTER, br->dev->ifindex) ||
90             nla_put_u32(skb, IFLA_MTU, dev->mtu) ||
91             nla_put_u8(skb, IFLA_OPERSTATE, operstate) ||
92             (dev->addr_len &&
93              nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
94             (dev->ifindex != dev->iflink &&
95              nla_put_u32(skb, IFLA_LINK, dev->iflink)))
96                 goto nla_put_failure;
97
98         if (event == RTM_NEWLINK) {
99                 struct nlattr *nest
100                         = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED);
101
102                 if (nest == NULL || br_port_fill_attrs(skb, port) < 0)
103                         goto nla_put_failure;
104                 nla_nest_end(skb, nest);
105         }
106
107         return nlmsg_end(skb, nlh);
108
109 nla_put_failure:
110         nlmsg_cancel(skb, nlh);
111         return -EMSGSIZE;
112 }
113
114 /*
115  * Notify listeners of a change in port information
116  */
117 void br_ifinfo_notify(int event, struct net_bridge_port *port)
118 {
119         struct net *net = dev_net(port->dev);
120         struct sk_buff *skb;
121         int err = -ENOBUFS;
122
123         br_debug(port->br, "port %u(%s) event %d\n",
124                  (unsigned int)port->port_no, port->dev->name, event);
125
126         skb = nlmsg_new(br_nlmsg_size(), GFP_ATOMIC);
127         if (skb == NULL)
128                 goto errout;
129
130         err = br_fill_ifinfo(skb, port, 0, 0, event, 0);
131         if (err < 0) {
132                 /* -EMSGSIZE implies BUG in br_nlmsg_size() */
133                 WARN_ON(err == -EMSGSIZE);
134                 kfree_skb(skb);
135                 goto errout;
136         }
137         rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
138         return;
139 errout:
140         if (err < 0)
141                 rtnl_set_sk_err(net, RTNLGRP_LINK, err);
142 }
143
144 /*
145  * Dump information about all ports, in response to GETLINK
146  */
147 int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
148                struct net_device *dev)
149 {
150         int err = 0;
151         struct net_bridge_port *port = br_port_get_rcu(dev);
152
153         /* not a bridge port */
154         if (!port)
155                 goto out;
156
157         err = br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, NLM_F_MULTI);
158 out:
159         return err;
160 }
161
162 static const struct nla_policy ifla_brport_policy[IFLA_BRPORT_MAX + 1] = {
163         [IFLA_BRPORT_STATE]     = { .type = NLA_U8 },
164         [IFLA_BRPORT_COST]      = { .type = NLA_U32 },
165         [IFLA_BRPORT_PRIORITY]  = { .type = NLA_U16 },
166         [IFLA_BRPORT_MODE]      = { .type = NLA_U8 },
167         [IFLA_BRPORT_GUARD]     = { .type = NLA_U8 },
168 };
169
170 /* Change the state of the port and notify spanning tree */
171 static int br_set_port_state(struct net_bridge_port *p, u8 state)
172 {
173         if (state > BR_STATE_BLOCKING)
174                 return -EINVAL;
175
176         /* if kernel STP is running, don't allow changes */
177         if (p->br->stp_enabled == BR_KERNEL_STP)
178                 return -EBUSY;
179
180         if (!netif_running(p->dev) ||
181             (!netif_carrier_ok(p->dev) && state != BR_STATE_DISABLED))
182                 return -ENETDOWN;
183
184         p->state = state;
185         br_log_state(p);
186         br_port_state_selection(p->br);
187         return 0;
188 }
189
190 /* Set/clear or port flags based on attribute */
191 static void br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[],
192                            int attrtype, unsigned long mask)
193 {
194         if (tb[attrtype]) {
195                 u8 flag = nla_get_u8(tb[attrtype]);
196                 if (flag)
197                         p->flags |= mask;
198                 else
199                         p->flags &= ~mask;
200         }
201 }
202
203 /* Process bridge protocol info on port */
204 static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
205 {
206         int err;
207
208         br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
209         br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
210
211         if (tb[IFLA_BRPORT_COST]) {
212                 err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST]));
213                 if (err)
214                         return err;
215         }
216
217         if (tb[IFLA_BRPORT_PRIORITY]) {
218                 err = br_stp_set_port_priority(p, nla_get_u16(tb[IFLA_BRPORT_PRIORITY]));
219                 if (err)
220                         return err;
221         }
222
223         if (tb[IFLA_BRPORT_STATE]) {
224                 err = br_set_port_state(p, nla_get_u8(tb[IFLA_BRPORT_STATE]));
225                 if (err)
226                         return err;
227         }
228         return 0;
229 }
230
231 /* Change state and parameters on port. */
232 int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
233 {
234         struct ifinfomsg *ifm;
235         struct nlattr *protinfo;
236         struct net_bridge_port *p;
237         struct nlattr *tb[IFLA_BRPORT_MAX];
238         int err;
239
240         ifm = nlmsg_data(nlh);
241
242         protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO);
243         if (!protinfo)
244                 return 0;
245
246         p = br_port_get_rtnl(dev);
247         if (!p)
248                 return -EINVAL;
249
250         if (protinfo->nla_type & NLA_F_NESTED) {
251                 err = nla_parse_nested(tb, IFLA_BRPORT_MAX,
252                                        protinfo, ifla_brport_policy);
253                 if (err)
254                         return err;
255
256                 spin_lock_bh(&p->br->lock);
257                 err = br_setport(p, tb);
258                 spin_unlock_bh(&p->br->lock);
259         } else {
260                 /* Binary compatability with old RSTP */
261                 if (nla_len(protinfo) < sizeof(u8))
262                         return -EINVAL;
263
264                 spin_lock_bh(&p->br->lock);
265                 err = br_set_port_state(p, nla_get_u8(protinfo));
266                 spin_unlock_bh(&p->br->lock);
267         }
268
269         if (err == 0)
270                 br_ifinfo_notify(RTM_NEWLINK, p);
271
272         return err;
273 }
274
275 static int br_validate(struct nlattr *tb[], struct nlattr *data[])
276 {
277         if (tb[IFLA_ADDRESS]) {
278                 if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
279                         return -EINVAL;
280                 if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
281                         return -EADDRNOTAVAIL;
282         }
283
284         return 0;
285 }
286
287 struct rtnl_link_ops br_link_ops __read_mostly = {
288         .kind           = "bridge",
289         .priv_size      = sizeof(struct net_bridge),
290         .setup          = br_dev_setup,
291         .validate       = br_validate,
292         .dellink        = br_dev_delete,
293 };
294
295 int __init br_netlink_init(void)
296 {
297         return rtnl_link_register(&br_link_ops);
298 }
299
300 void __exit br_netlink_fini(void)
301 {
302         rtnl_link_unregister(&br_link_ops);
303         rtnl_unregister_all(PF_BRIDGE);
304 }