1 /*
2  * drivers/net/bond/bond_netlink.c - Netlink interface for bonding
3  * Copyright (c) 2013 Jiri Pirko <jiri@resnulli.us>
4  * Copyright (c) 2013 Scott Feldman <sfeldma@cumulusnetworks.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  */
11 
12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13 
14 #include <linux/module.h>
15 #include <linux/errno.h>
16 #include <linux/netdevice.h>
17 #include <linux/etherdevice.h>
18 #include <linux/if_link.h>
19 #include <linux/if_ether.h>
20 #include <net/netlink.h>
21 #include <net/rtnetlink.h>
22 #include "bonding.h"
23 
24 static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
25 	[IFLA_BOND_MODE]		= { .type = NLA_U8 },
26 	[IFLA_BOND_ACTIVE_SLAVE]	= { .type = NLA_U32 },
27 	[IFLA_BOND_MIIMON]		= { .type = NLA_U32 },
28 };
29 
30 static int bond_validate(struct nlattr *tb[], struct nlattr *data[])
31 {
32 	if (tb[IFLA_ADDRESS]) {
33 		if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
34 			return -EINVAL;
35 		if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
36 			return -EADDRNOTAVAIL;
37 	}
38 	return 0;
39 }
40 
41 static int bond_changelink(struct net_device *bond_dev,
42 			   struct nlattr *tb[], struct nlattr *data[])
43 {
44 	struct bonding *bond = netdev_priv(bond_dev);
45 	int err;
46 
47 	if (!data)
48 		return 0;
49 
50 	if (data[IFLA_BOND_MODE]) {
51 		int mode = nla_get_u8(data[IFLA_BOND_MODE]);
52 
53 		err = bond_option_mode_set(bond, mode);
54 		if (err)
55 			return err;
56 	}
57 	if (data[IFLA_BOND_ACTIVE_SLAVE]) {
58 		int ifindex = nla_get_u32(data[IFLA_BOND_ACTIVE_SLAVE]);
59 		struct net_device *slave_dev;
60 
61 		if (ifindex == 0) {
62 			slave_dev = NULL;
63 		} else {
64 			slave_dev = __dev_get_by_index(dev_net(bond_dev),
65 						       ifindex);
66 			if (!slave_dev)
67 				return -ENODEV;
68 		}
69 		err = bond_option_active_slave_set(bond, slave_dev);
70 		if (err)
71 			return err;
72 	}
73 	if (data[IFLA_BOND_MIIMON]) {
74 		int miimon = nla_get_u32(data[IFLA_BOND_MIIMON]);
75 
76 		err = bond_option_miimon_set(bond, miimon);
77 		if (err)
78 			return err;
79 	}
80 	return 0;
81 }
82 
83 static int bond_newlink(struct net *src_net, struct net_device *bond_dev,
84 			struct nlattr *tb[], struct nlattr *data[])
85 {
86 	int err;
87 
88 	err = bond_changelink(bond_dev, tb, data);
89 	if (err < 0)
90 		return err;
91 
92 	return register_netdevice(bond_dev);
93 }
94 
95 static size_t bond_get_size(const struct net_device *bond_dev)
96 {
97 	return nla_total_size(sizeof(u8)) +	/* IFLA_BOND_MODE */
98 		nla_total_size(sizeof(u32)) +	/* IFLA_BOND_ACTIVE_SLAVE */
99 		nla_total_size(sizeof(u32)) +	/* IFLA_BOND_MIIMON */
100 		0;
101 }
102 
103 static int bond_fill_info(struct sk_buff *skb,
104 			  const struct net_device *bond_dev)
105 {
106 	struct bonding *bond = netdev_priv(bond_dev);
107 	struct net_device *slave_dev = bond_option_active_slave_get(bond);
108 
109 	if (nla_put_u8(skb, IFLA_BOND_MODE, bond->params.mode))
110 		goto nla_put_failure;
111 
112 	if (slave_dev &&
113 	    nla_put_u32(skb, IFLA_BOND_ACTIVE_SLAVE, slave_dev->ifindex))
114 		goto nla_put_failure;
115 
116 	if (nla_put_u32(skb, IFLA_BOND_MIIMON, bond->params.miimon))
117 		goto nla_put_failure;
118 
119 	return 0;
120 
121 nla_put_failure:
122 	return -EMSGSIZE;
123 }
124 
125 struct rtnl_link_ops bond_link_ops __read_mostly = {
126 	.kind			= "bond",
127 	.priv_size		= sizeof(struct bonding),
128 	.setup			= bond_setup,
129 	.maxtype		= IFLA_BOND_MAX,
130 	.policy			= bond_policy,
131 	.validate		= bond_validate,
132 	.newlink		= bond_newlink,
133 	.changelink		= bond_changelink,
134 	.get_size		= bond_get_size,
135 	.fill_info		= bond_fill_info,
136 	.get_num_tx_queues	= bond_get_num_tx_queues,
137 	.get_num_rx_queues	= bond_get_num_tx_queues, /* Use the same number
138 							     as for TX queues */
139 };
140 
141 int __init bond_netlink_init(void)
142 {
143 	return rtnl_link_register(&bond_link_ops);
144 }
145 
146 void bond_netlink_fini(void)
147 {
148 	rtnl_link_unregister(&bond_link_ops);
149 }
150 
151 MODULE_ALIAS_RTNL_LINK("bond");
152