replace same ds with generic one
[ana-net.git] / src / xt_user.c
blob75bd651d8852fea615002f87c0a1c7c5a6d19cae
1 /*
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)
8 * Subject to the GPL.
9 */
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>
19 #include <net/sock.h>
21 #include "xt_idp.h"
22 #include "xt_user.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)
30 struct fblock *fb;
31 struct lananlmsg_add *msg = (struct lananlmsg_add *) lmsg->buff;
33 fb = search_fblock_n(msg->name);
34 if (fb) {
35 put_fblock(fb);
36 return -EINVAL;
39 fb = build_fblock_object(msg->type, msg->name);
41 return !fb ? -ENOMEM : 0;
44 static int userctl_set(struct lananlmsg *lmsg)
46 int ret;
47 struct fblock *fb;
48 struct lananlmsg_set *msg = (struct lananlmsg_set *) lmsg->buff;
50 fb = search_fblock_n(msg->name);
51 if (!fb)
52 return -EINVAL;
54 ret = fblock_set_option(fb, msg->option);
56 put_fblock(fb);
58 return ret;
61 static int userctl_replace(struct lananlmsg *lmsg)
63 int ret;
64 struct fblock *fb1, *fb2;
65 struct lananlmsg_replace *msg = (struct lananlmsg_replace *) lmsg->buff;
67 fb1 = search_fblock_n(msg->name1);
68 if (!fb1)
69 return -EINVAL;
71 fb2 = search_fblock_n(msg->name2);
72 if (!fb2) {
73 put_fblock(fb1);
74 return -EINVAL;
77 if (atomic_read(&fb2->refcnt) > 2) {
78 /* Still in use by others */
79 printk(KERN_ERR "[lana] %s is still in use by others. "
80 "Drop refs first!\n", fb2->name);
81 put_fblock(fb1);
82 put_fblock(fb2);
83 return -EBUSY;
86 unregister_fblock_namespace_no_rcu(fb2);
88 if (!strncmp(fb1->factory->type, fb2->factory->type,
89 sizeof(fb1->factory->type)) && !msg->drop_priv)
90 fblock_migrate_p(fb2, fb1);
91 fblock_migrate_r(fb2, fb1);
93 unregister_fblock(fb1);
95 ret = register_fblock(fb2, fb2->idp);
97 put_fblock(fb1);
98 put_fblock(fb2);
100 return ret;
103 static int userctl_subscribe(struct lananlmsg *lmsg)
105 int ret;
106 struct fblock *fb1, *fb2;
107 struct lananlmsg_tuple *msg = (struct lananlmsg_tuple *) lmsg->buff;
109 fb1 = search_fblock_n(msg->name1);
110 if (!fb1)
111 return -EINVAL;
113 fb2 = search_fblock_n(msg->name2);
114 if (!fb2) {
115 put_fblock(fb1);
116 return -EINVAL;
119 * fb1 is remote block, fb2 is the one that
120 * wishes to be notified.
122 ret = subscribe_to_remote_fblock(fb2, fb1);
124 put_fblock(fb1);
125 put_fblock(fb2);
127 return ret;
130 static int userctl_unsubscribe(struct lananlmsg *lmsg)
132 struct fblock *fb1, *fb2;
133 struct lananlmsg_tuple *msg = (struct lananlmsg_tuple *) lmsg->buff;
135 fb1 = search_fblock_n(msg->name1);
136 if (!fb1)
137 return -EINVAL;
139 fb2 = search_fblock_n(msg->name2);
140 if (!fb2) {
141 put_fblock(fb1);
142 return -EINVAL;
145 unsubscribe_from_remote_fblock(fb2, fb1);
147 put_fblock(fb1);
148 put_fblock(fb2);
150 return 0;
153 static int userctl_remove(struct lananlmsg *lmsg)
155 struct fblock *fb;
156 struct lananlmsg_rm *msg = (struct lananlmsg_rm *) lmsg->buff;
158 fb = search_fblock_n(msg->name);
159 if (!fb)
160 return -EINVAL;
162 if (atomic_read(&fb->refcnt) > 2) {
163 /* Still in use by others */
164 put_fblock(fb);
165 return -EBUSY;
168 unregister_fblock_namespace(fb);
169 put_fblock(fb);
171 return 0;
174 static int userctl_bind(struct lananlmsg *lmsg)
176 int ret;
177 struct fblock *fb1, *fb2;
178 struct lananlmsg_tuple *msg = (struct lananlmsg_tuple *) lmsg->buff;
180 fb1 = search_fblock_n(msg->name1);
181 if (!fb1)
182 return -EINVAL;
184 fb2 = search_fblock_n(msg->name2);
185 if (!fb2) {
186 put_fblock(fb1);
187 return -EINVAL;
190 ret = fblock_bind(fb1, fb2);
192 put_fblock(fb1);
193 put_fblock(fb2);
195 return ret;
198 static int userctl_unbind(struct lananlmsg *lmsg)
200 int ret;
201 struct fblock *fb1, *fb2;
202 struct lananlmsg_tuple *msg = (struct lananlmsg_tuple *) lmsg->buff;
204 fb1 = search_fblock_n(msg->name1);
205 if (!fb1)
206 return -EINVAL;
208 fb2 = search_fblock_n(msg->name2);
209 if (!fb2) {
210 put_fblock(fb1);
211 return -EINVAL;
214 ret = fblock_unbind(fb1, fb2);
216 put_fblock(fb1);
217 put_fblock(fb2);
219 return ret;
222 static int __userctl_rcv(struct sk_buff *skb, struct nlmsghdr *nlh)
224 int ret = 0;
225 struct lananlmsg *lmsg;
227 if (security_netlink_recv(skb, CAP_NET_ADMIN))
228 return -EPERM;
229 if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct lananlmsg)))
230 return 0;
232 lmsg = NLMSG_DATA(nlh);
234 switch (lmsg->cmd) {
235 case NETLINK_USERCTL_CMD_ADD:
236 ret = userctl_add(lmsg);
237 break;
238 case NETLINK_USERCTL_CMD_SET:
239 ret = userctl_set(lmsg);
240 break;
241 case NETLINK_USERCTL_CMD_REPLACE:
242 ret = userctl_replace(lmsg);
243 break;
244 case NETLINK_USERCTL_CMD_SUBSCRIBE:
245 ret = userctl_subscribe(lmsg);
246 break;
247 case NETLINK_USERCTL_CMD_UNSUBSCRIBE:
248 ret = userctl_unsubscribe(lmsg);
249 break;
250 case NETLINK_USERCTL_CMD_RM:
251 ret = userctl_remove(lmsg);
252 break;
253 case NETLINK_USERCTL_CMD_BIND:
254 ret = userctl_bind(lmsg);
255 break;
256 case NETLINK_USERCTL_CMD_UNBIND:
257 ret = userctl_unbind(lmsg);
258 break;
259 default:
260 printk(KERN_INFO "[lana] Unknown command!\n");
261 ret = -ENOENT;
262 break;
265 return ret;
268 static void userctl_rcv(struct sk_buff *skb)
270 netlink_rcv_skb(skb, &__userctl_rcv);
273 int init_userctl_system(void)
275 userctl_sock = netlink_kernel_create(&init_net, NETLINK_USERCTL,
276 USERCTLGRP_MAX, userctl_rcv,
277 NULL, THIS_MODULE);
278 return !userctl_sock ? -ENOMEM : 0;
280 EXPORT_SYMBOL_GPL(init_userctl_system);
282 void cleanup_userctl_system(void)
284 netlink_kernel_release(userctl_sock);
286 EXPORT_SYMBOL_GPL(cleanup_userctl_system);