fixed description in fbctl
[ana-net.git] / src / xt_user.c
blob23f003b84ce8d2068fc6e4b1dd7bbf5d3f209641
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 <net/netlink.h>
18 #include <net/sock.h>
20 #include "xt_idp.h"
21 #include "xt_user.h"
22 #include "xt_fblock.h"
23 #include "xt_builder.h"
25 static struct sock *userctl_sock = NULL;
27 static int __userctl_rcv(struct sk_buff *skb, struct nlmsghdr *nlh)
29 struct lananlmsg *lmsg;
31 if (security_netlink_recv(skb, CAP_NET_ADMIN))
32 return -EPERM;
33 if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct lananlmsg)))
34 return 0;
36 lmsg = NLMSG_DATA(nlh);
38 switch (lmsg->cmd) {
39 case NETLINK_USERCTL_CMD_ADD: {
40 struct fblock *fb;
41 struct lananlmsg_add *msg =
42 (struct lananlmsg_add *) lmsg->buff;
43 fb = build_fblock_object(msg->type, msg->name);
44 if (!fb)
45 return -ENOMEM;
46 } break;
47 case NETLINK_USERCTL_CMD_SET: {
48 int ret;
49 struct fblock *fb;
50 struct lananlmsg_set *msg =
51 (struct lananlmsg_set *) lmsg->buff;
52 fb = search_fblock_n(msg->name);
53 if (!fb)
54 return -EINVAL;
55 ret = fblock_set_option(fb, msg->option);
56 put_fblock(fb);
57 return ret;
58 } break;
59 case NETLINK_USERCTL_CMD_REPLACE: {
60 int ret;
61 struct fblock *fb1, *fb2;
62 struct lananlmsg_replace *msg =
63 (struct lananlmsg_replace *) lmsg->buff;
64 fb1 = search_fblock_n(msg->name1);
65 if (!fb1)
66 return -EINVAL;
67 fb2 = search_fblock_n(msg->name2);
68 if (!fb2) {
69 put_fblock(fb1);
70 return -EINVAL;
72 if (atomic_read(&fb2->refcnt) > 2) {
73 /* Still in use by others */
74 put_fblock(fb1);
75 printk(KERN_ERR "[lana] %s is still in use by others. "
76 "Drop refs first!\n", fb2->name);
77 put_fblock(fb2);
78 return -EBUSY;
80 unregister_fblock_namespace_no_rcu(fb2);
81 ret = fblock_migrate(fb2, fb1);
82 if (ret) {
83 put_fblock(fb1);
84 /* We loose fb2 */
85 printk("[lana] fblock migration failed! "
86 "Destination fblock lost!\n");
87 put_fblock(fb2);
88 put_fblock(fb2);
89 return -EIO;
91 unregister_fblock(fb1);
92 put_fblock(fb1);
93 ret = register_fblock(fb2, fb2->idp);
94 put_fblock(fb2);
95 return ret;
96 #if 0
97 /* Now fb2 cannot be used anymore. */
98 fb2->idp = fb1->idp;
99 strlcpy(fb2->name, fb1->name,sizeof(fb2->name));
100 /* Care about private data transfer ... */
101 if (!strncmp(fb1->factory->type, fb2->factory->type,
102 sizeof(fb1->factory->type)) && !drop_priv) {
103 /* Free our private_data */
104 rcu_assign_pointer(fb2->private_data,
105 fb1->private_data);
106 /* Now, make sure, we don't free private_data */
107 } else {
108 /* Free fb1 private_data */
110 /* Copy subscribtions */
111 /* Drop fb1, register fb2 as fb1 */
112 #endif
113 } break;
114 case NETLINK_USERCTL_CMD_SUBSCRIBE: {
115 int ret;
116 struct fblock *fb1, *fb2;
117 struct lananlmsg_subscribe *msg =
118 (struct lananlmsg_subscribe *) lmsg->buff;
119 fb1 = search_fblock_n(msg->name1);
120 if (!fb1)
121 return -EINVAL;
122 fb2 = search_fblock_n(msg->name2);
123 if (!fb2) {
124 put_fblock(fb1);
125 return -EINVAL;
128 * fb1 is remote block, fb2 is the one that
129 * wishes to be notified.
131 ret = subscribe_to_remote_fblock(fb2, fb1);
132 put_fblock(fb1);
133 put_fblock(fb2);
134 return ret;
135 } break;
136 case NETLINK_USERCTL_CMD_UNSUBSCRIBE: {
137 struct fblock *fb1, *fb2;
138 struct lananlmsg_unsubscribe *msg =
139 (struct lananlmsg_unsubscribe *) lmsg->buff;
140 fb1 = search_fblock_n(msg->name1);
141 if (!fb1)
142 return -EINVAL;
143 fb2 = search_fblock_n(msg->name2);
144 if (!fb2) {
145 put_fblock(fb1);
146 return -EINVAL;
148 unsubscribe_from_remote_fblock(fb2, fb1);
149 put_fblock(fb1);
150 put_fblock(fb2);
151 } break;
152 case NETLINK_USERCTL_CMD_RM: {
153 struct fblock *fb;
154 struct lananlmsg_rm *msg =
155 (struct lananlmsg_rm *) lmsg->buff;
156 fb = search_fblock_n(msg->name);
157 if (!fb)
158 return -EINVAL;
159 if (atomic_read(&fb->refcnt) > 2) {
160 /* Still in use by others */
161 put_fblock(fb);
162 return -EBUSY;
164 unregister_fblock_namespace(fb);
165 put_fblock(fb);
166 } break;
167 case NETLINK_USERCTL_CMD_BIND: {
168 int ret;
169 struct fblock *fb1, *fb2;
170 struct lananlmsg_bind *msg =
171 (struct lananlmsg_bind *) lmsg->buff;
172 fb1 = search_fblock_n(msg->name1);
173 if (!fb1)
174 return -EINVAL;
175 fb2 = search_fblock_n(msg->name2);
176 if (!fb2) {
177 put_fblock(fb1);
178 return -EINVAL;
180 ret = fblock_bind(fb1, fb2);
181 if (ret) {
182 put_fblock(fb1);
183 put_fblock(fb2);
184 return ret;
186 put_fblock(fb1);
187 put_fblock(fb2);
188 } break;
189 case NETLINK_USERCTL_CMD_UNBIND: {
190 int ret;
191 struct fblock *fb1, *fb2;
192 struct lananlmsg_unbind *msg =
193 (struct lananlmsg_unbind *) lmsg->buff;
194 fb1 = search_fblock_n(msg->name1);
195 if (!fb1)
196 return -EINVAL;
197 fb2 = search_fblock_n(msg->name2);
198 if (!fb2) {
199 put_fblock(fb1);
200 return -EINVAL;
202 ret = fblock_unbind(fb1, fb2);
203 if (ret) {
204 put_fblock(fb1);
205 put_fblock(fb2);
206 return ret;
208 put_fblock(fb1);
209 put_fblock(fb2);
210 } break;
211 default:
212 printk("[lana] Unknown command!\n");
213 break;
216 return 0;
219 static void userctl_rcv(struct sk_buff *skb)
221 netlink_rcv_skb(skb, &__userctl_rcv);
224 int init_userctl_system(void)
226 userctl_sock = netlink_kernel_create(&init_net, NETLINK_USERCTL,
227 USERCTLGRP_MAX, userctl_rcv,
228 NULL, THIS_MODULE);
229 if (!userctl_sock)
230 return -ENOMEM;
231 return 0;
233 EXPORT_SYMBOL_GPL(init_userctl_system);
235 void cleanup_userctl_system(void)
237 netlink_kernel_release(userctl_sock);
239 EXPORT_SYMBOL_GPL(cleanup_userctl_system);