aboutsummaryrefslogtreecommitdiffstats
path: root/net/dcb/dcbnl.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dcb/dcbnl.c')
-rw-r--r--net/dcb/dcbnl.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 656c7c75b192..5520e431b072 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -196,6 +196,34 @@ static const struct nla_policy dcbnl_featcfg_nest[DCB_FEATCFG_ATTR_MAX + 1] = {
196static LIST_HEAD(dcb_app_list); 196static LIST_HEAD(dcb_app_list);
197static DEFINE_SPINLOCK(dcb_lock); 197static DEFINE_SPINLOCK(dcb_lock);
198 198
199static struct sk_buff *dcbnl_newmsg(int type, u8 cmd, u32 port, u32 seq,
200 u32 flags, struct nlmsghdr **nlhp)
201{
202 struct sk_buff *skb;
203 struct dcbmsg *dcb;
204 struct nlmsghdr *nlh;
205
206 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
207 if (!skb)
208 return NULL;
209
210 nlh = nlmsg_put(skb, port, seq, type, sizeof(*dcb), flags);
211 if (!nlh) {
212 /* header should always fit, allocation must be buggy */
213 BUG();
214 }
215
216 dcb = nlmsg_data(nlh);
217 dcb->dcb_family = AF_UNSPEC;
218 dcb->cmd = cmd;
219 dcb->dcb_pad = 0;
220
221 if (nlhp)
222 *nlhp = nlh;
223
224 return skb;
225}
226
199/* standard netlink reply call */ 227/* standard netlink reply call */
200static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid, 228static int dcbnl_reply(u8 value, u8 event, u8 cmd, u8 attr, u32 pid,
201 u32 seq, u16 flags) 229 u32 seq, u16 flags)
@@ -1922,6 +1950,19 @@ static int dcbnl_cee_get(struct net_device *netdev, struct nlattr **tb,
1922 return err; 1950 return err;
1923} 1951}
1924 1952
1953struct reply_func {
1954 /* reply netlink message type */
1955 int type;
1956
1957 /* function to fill message contents */
1958 int (*cb)(struct net_device *, struct nlmsghdr *, u32,
1959 struct nlattr **, struct sk_buff *);
1960};
1961
1962static const struct reply_func reply_funcs[DCB_CMD_MAX+1] = {
1963 /* FIXME: add reply defs */
1964};
1965
1925static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 1966static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1926{ 1967{
1927 struct net *net = sock_net(skb->sk); 1968 struct net *net = sock_net(skb->sk);
@@ -1930,6 +1971,9 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1930 struct nlattr *tb[DCB_ATTR_MAX + 1]; 1971 struct nlattr *tb[DCB_ATTR_MAX + 1];
1931 u32 pid = skb ? NETLINK_CB(skb).pid : 0; 1972 u32 pid = skb ? NETLINK_CB(skb).pid : 0;
1932 int ret = -EINVAL; 1973 int ret = -EINVAL;
1974 struct sk_buff *reply_skb;
1975 struct nlmsghdr *reply_nlh;
1976 const struct reply_func *fn;
1933 1977
1934 if (!net_eq(net, &init_net)) 1978 if (!net_eq(net, &init_net))
1935 return -EINVAL; 1979 return -EINVAL;
@@ -1939,6 +1983,14 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1939 if (ret < 0) 1983 if (ret < 0)
1940 return ret; 1984 return ret;
1941 1985
1986 if (dcb->cmd > DCB_CMD_MAX)
1987 return -EINVAL;
1988
1989 /* check if a reply function has been defined for the command */
1990 fn = &reply_funcs[dcb->cmd];
1991 if (!fn->cb)
1992 return -EOPNOTSUPP;
1993
1942 if (!tb[DCB_ATTR_IFNAME]) 1994 if (!tb[DCB_ATTR_IFNAME])
1943 return -EINVAL; 1995 return -EINVAL;
1944 1996
@@ -1949,6 +2001,25 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
1949 if (!netdev->dcbnl_ops) 2001 if (!netdev->dcbnl_ops)
1950 goto errout; 2002 goto errout;
1951 2003
2004 reply_skb = dcbnl_newmsg(fn->type, dcb->cmd, pid, nlh->nlmsg_seq,
2005 nlh->nlmsg_flags, &reply_nlh);
2006 if (!reply_skb) {
2007 ret = -ENOBUFS;
2008 goto out;
2009 }
2010
2011 ret = fn->cb(netdev, nlh, nlh->nlmsg_seq, tb, reply_skb);
2012 if (ret < 0) {
2013 nlmsg_free(reply_skb);
2014 goto out;
2015 }
2016
2017 nlmsg_end(reply_skb, reply_nlh);
2018
2019 ret = rtnl_unicast(reply_skb, &init_net, pid);
2020 if (ret)
2021 goto out;
2022
1952 switch (dcb->cmd) { 2023 switch (dcb->cmd) {
1953 case DCB_CMD_GSTATE: 2024 case DCB_CMD_GSTATE:
1954 ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq, 2025 ret = dcbnl_getstate(netdev, tb, pid, nlh->nlmsg_seq,