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/rtnetlink.h> 15 #include <net/netlink.h> 16 #include "br_private.h" 17 18 static inline size_t br_nlmsg_size(void) 19 { 20 return NLMSG_ALIGN(sizeof(struct ifinfomsg)) 21 + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ 22 + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ 23 + nla_total_size(4) /* IFLA_MASTER */ 24 + nla_total_size(4) /* IFLA_MTU */ 25 + nla_total_size(4) /* IFLA_LINK */ 26 + nla_total_size(1) /* IFLA_OPERSTATE */ 27 + nla_total_size(1); /* IFLA_PROTINFO */ 28 } 29 30 /* 31 * Create one netlink message for one interface 32 * Contains port and master info as well as carrier and bridge state. 33 */ 34 static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *port, 35 u32 pid, u32 seq, int event, unsigned int flags) 36 { 37 const struct net_bridge *br = port->br; 38 const struct net_device *dev = port->dev; 39 struct ifinfomsg *hdr; 40 struct nlmsghdr *nlh; 41 u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN; 42 43 pr_debug("br_fill_info event %d port %s master %s\n", 44 event, dev->name, br->dev->name); 45 46 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags); 47 if (nlh == NULL) 48 return -EMSGSIZE; 49 50 hdr = nlmsg_data(nlh); 51 hdr->ifi_family = AF_BRIDGE; 52 hdr->__ifi_pad = 0; 53 hdr->ifi_type = dev->type; 54 hdr->ifi_index = dev->ifindex; 55 hdr->ifi_flags = dev_get_flags(dev); 56 hdr->ifi_change = 0; 57 58 NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); 59 NLA_PUT_U32(skb, IFLA_MASTER, br->dev->ifindex); 60 NLA_PUT_U32(skb, IFLA_MTU, dev->mtu); 61 NLA_PUT_U8(skb, IFLA_OPERSTATE, operstate); 62 63 if (dev->addr_len) 64 NLA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); 65 66 if (dev->ifindex != dev->iflink) 67 NLA_PUT_U32(skb, IFLA_LINK, dev->iflink); 68 69 if (event == RTM_NEWLINK) 70 NLA_PUT_U8(skb, IFLA_PROTINFO, port->state); 71 72 return nlmsg_end(skb, nlh); 73 74 nla_put_failure: 75 nlmsg_cancel(skb, nlh); 76 return -EMSGSIZE; 77 } 78 79 /* 80 * Notify listeners of a change in port information 81 */ 82 void br_ifinfo_notify(int event, struct net_bridge_port *port) 83 { 84 struct sk_buff *skb; 85 int err = -ENOBUFS; 86 87 pr_debug("bridge notify event=%d\n", event); 88 skb = nlmsg_new(br_nlmsg_size(), GFP_ATOMIC); 89 if (skb == NULL) 90 goto errout; 91 92 err = br_fill_ifinfo(skb, port, 0, 0, event, 0); 93 if (err < 0) { 94 /* -EMSGSIZE implies BUG in br_nlmsg_size() */ 95 WARN_ON(err == -EMSGSIZE); 96 kfree_skb(skb); 97 goto errout; 98 } 99 err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); 100 errout: 101 if (err < 0) 102 rtnl_set_sk_err(RTNLGRP_LINK, err); 103 } 104 105 /* 106 * Dump information about all ports, in response to GETLINK 107 */ 108 static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) 109 { 110 struct net_device *dev; 111 int idx; 112 113 read_lock(&dev_base_lock); 114 for (dev = dev_base, idx = 0; dev; dev = dev->next) { 115 /* not a bridge port */ 116 if (dev->br_port == NULL || idx < cb->args[0]) 117 goto skip; 118 119 if (br_fill_ifinfo(skb, dev->br_port, NETLINK_CB(cb->skb).pid, 120 cb->nlh->nlmsg_seq, RTM_NEWLINK, 121 NLM_F_MULTI) < 0) 122 break; 123 skip: 124 ++idx; 125 } 126 read_unlock(&dev_base_lock); 127 128 cb->args[0] = idx; 129 130 return skb->len; 131 } 132 133 /* 134 * Change state of port (ie from forwarding to blocking etc) 135 * Used by spanning tree in user space. 136 */ 137 static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 138 { 139 struct ifinfomsg *ifm; 140 struct nlattr *protinfo; 141 struct net_device *dev; 142 struct net_bridge_port *p; 143 u8 new_state; 144 145 if (nlmsg_len(nlh) < sizeof(*ifm)) 146 return -EINVAL; 147 148 ifm = nlmsg_data(nlh); 149 if (ifm->ifi_family != AF_BRIDGE) 150 return -EPFNOSUPPORT; 151 152 protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO); 153 if (!protinfo || nla_len(protinfo) < sizeof(u8)) 154 return -EINVAL; 155 156 new_state = nla_get_u8(protinfo); 157 if (new_state > BR_STATE_BLOCKING) 158 return -EINVAL; 159 160 dev = __dev_get_by_index(ifm->ifi_index); 161 if (!dev) 162 return -ENODEV; 163 164 p = dev->br_port; 165 if (!p) 166 return -EINVAL; 167 168 /* if kernel STP is running, don't allow changes */ 169 if (p->br->stp_enabled) 170 return -EBUSY; 171 172 if (!netif_running(dev) || 173 (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED)) 174 return -ENETDOWN; 175 176 p->state = new_state; 177 br_log_state(p); 178 return 0; 179 } 180 181 182 static struct rtnetlink_link bridge_rtnetlink_table[RTM_NR_MSGTYPES] = { 183 [RTM_GETLINK - RTM_BASE] = { .dumpit = br_dump_ifinfo, }, 184 [RTM_SETLINK - RTM_BASE] = { .doit = br_rtm_setlink, }, 185 }; 186 187 void __init br_netlink_init(void) 188 { 189 rtnetlink_links[PF_BRIDGE] = bridge_rtnetlink_table; 190 } 191 192 void __exit br_netlink_fini(void) 193 { 194 rtnetlink_links[PF_BRIDGE] = NULL; 195 } 196 197