2 * Lightweight Autonomic Network Architecture
4 * LANA NETLINK handler for Functional Block userspace control.
6 * Copyright 2011 Daniel Borkmann <dborkma@tik.ee.ethz.ch>,
7 * Swiss federal institute of technology (ETH Zurich)
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/socket.h>
15 #include <linux/net.h>
16 #include <linux/skbuff.h>
17 #include <linux/rcupdate.h>
18 #include <net/netlink.h>
23 #include "xt_fblock.h"
24 #include "xt_builder.h"
26 static struct sock
*userctl_sock
= NULL
;
28 static int userctl_add(struct lananlmsg
*lmsg
)
31 struct lananlmsg_add
*msg
= (struct lananlmsg_add
*) lmsg
->buff
;
33 fb
= search_fblock_n(msg
->name
);
39 fb
= build_fblock_object(msg
->type
, msg
->name
);
41 return !fb
? -ENOMEM
: 0;
44 static int userctl_set(struct lananlmsg
*lmsg
)
48 struct lananlmsg_set
*msg
= (struct lananlmsg_set
*) lmsg
->buff
;
50 fb
= search_fblock_n(msg
->name
);
54 ret
= fblock_set_option(fb
, msg
->option
);
61 static int userctl_replace(struct lananlmsg
*lmsg
)
64 struct fblock
*fb1
, *fb2
;
65 struct lananlmsg_replace
*msg
= (struct lananlmsg_replace
*) lmsg
->buff
;
68 * XXX: vlink blocks may not be replaced during runtime, since they
69 * are directly bound to hardware. Fuckup? Yes or no? Too many side
70 * effects. These blocks should not be changed anyway.
73 fb1
= search_fblock_n(msg
->name1
);
74 if (!fb1
|| !fb1
->factory
)
77 fb2
= search_fblock_n(msg
->name2
);
78 if (!fb2
|| !fb2
->factory
) {
83 if (atomic_read(&fb2
->refcnt
) > 2) {
84 /* Still in use by others */
85 printk(KERN_ERR
"[lana] %s is still in use by others. "
86 "Drop refs first!\n", fb2
->name
);
92 unregister_fblock_namespace_no_rcu(fb2
);
94 if (!strncmp(fb1
->factory
->type
, fb2
->factory
->type
,
95 sizeof(fb1
->factory
->type
)) && !msg
->drop_priv
)
96 fblock_migrate_p(fb2
, fb1
);
97 fblock_migrate_r(fb2
, fb1
);
99 unregister_fblock(fb1
);
101 ret
= register_fblock(fb2
, fb2
->idp
);
109 static int userctl_subscribe(struct lananlmsg
*lmsg
)
112 struct fblock
*fb1
, *fb2
;
113 struct lananlmsg_tuple
*msg
= (struct lananlmsg_tuple
*) lmsg
->buff
;
115 fb1
= search_fblock_n(msg
->name1
);
119 fb2
= search_fblock_n(msg
->name2
);
125 * fb1 is remote block, fb2 is the one that
126 * wishes to be notified.
128 ret
= subscribe_to_remote_fblock(fb2
, fb1
);
136 static int userctl_unsubscribe(struct lananlmsg
*lmsg
)
138 struct fblock
*fb1
, *fb2
;
139 struct lananlmsg_tuple
*msg
= (struct lananlmsg_tuple
*) lmsg
->buff
;
141 fb1
= search_fblock_n(msg
->name1
);
145 fb2
= search_fblock_n(msg
->name2
);
151 unsubscribe_from_remote_fblock(fb2
, fb1
);
159 static int userctl_remove(struct lananlmsg
*lmsg
)
162 struct lananlmsg_rm
*msg
= (struct lananlmsg_rm
*) lmsg
->buff
;
164 fb
= search_fblock_n(msg
->name
);
168 /* vlink types have no factory */
173 if (atomic_read(&fb
->refcnt
) > 2) {
174 /* Still in use by others */
179 unregister_fblock_namespace(fb
);
185 static int userctl_bind(struct lananlmsg
*lmsg
)
188 struct fblock
*fb1
, *fb2
;
189 struct lananlmsg_tuple
*msg
= (struct lananlmsg_tuple
*) lmsg
->buff
;
191 fb1
= search_fblock_n(msg
->name1
);
195 fb2
= search_fblock_n(msg
->name2
);
201 ret
= fblock_bind(fb1
, fb2
);
209 static int userctl_unbind(struct lananlmsg
*lmsg
)
212 struct fblock
*fb1
, *fb2
;
213 struct lananlmsg_tuple
*msg
= (struct lananlmsg_tuple
*) lmsg
->buff
;
215 fb1
= search_fblock_n(msg
->name1
);
219 fb2
= search_fblock_n(msg
->name2
);
225 ret
= fblock_unbind(fb1
, fb2
);
233 static int __userctl_rcv(struct sk_buff
*skb
, struct nlmsghdr
*nlh
)
236 struct lananlmsg
*lmsg
;
238 if (security_netlink_recv(skb
, CAP_NET_ADMIN
))
240 if (nlh
->nlmsg_len
< NLMSG_LENGTH(sizeof(struct lananlmsg
)))
243 lmsg
= NLMSG_DATA(nlh
);
246 case NETLINK_USERCTL_CMD_ADD
:
247 ret
= userctl_add(lmsg
);
249 case NETLINK_USERCTL_CMD_SET
:
250 ret
= userctl_set(lmsg
);
252 case NETLINK_USERCTL_CMD_REPLACE
:
253 ret
= userctl_replace(lmsg
);
255 case NETLINK_USERCTL_CMD_SUBSCRIBE
:
256 ret
= userctl_subscribe(lmsg
);
258 case NETLINK_USERCTL_CMD_UNSUBSCRIBE
:
259 ret
= userctl_unsubscribe(lmsg
);
261 case NETLINK_USERCTL_CMD_RM
:
262 ret
= userctl_remove(lmsg
);
264 case NETLINK_USERCTL_CMD_BIND
:
265 ret
= userctl_bind(lmsg
);
267 case NETLINK_USERCTL_CMD_UNBIND
:
268 ret
= userctl_unbind(lmsg
);
271 printk(KERN_INFO
"[lana] Unknown command!\n");
279 static void userctl_rcv(struct sk_buff
*skb
)
281 netlink_rcv_skb(skb
, &__userctl_rcv
);
284 int init_userctl_system(void)
286 userctl_sock
= netlink_kernel_create(&init_net
, NETLINK_USERCTL
,
287 USERCTLGRP_MAX
, userctl_rcv
,
289 return !userctl_sock
? -ENOMEM
: 0;
291 EXPORT_SYMBOL_GPL(init_userctl_system
);
293 void cleanup_userctl_system(void)
295 netlink_kernel_release(userctl_sock
);
297 EXPORT_SYMBOL_GPL(cleanup_userctl_system
);