added *_no_* ops, socket release
[ana-net.git] / src / fb_pflana.c
blob0d2a6cad8a8907ddf336021e1e00b522e7feb994
1 /*
2 * Lightweight Autonomic Network Architecture
4 * PF_LANA userspace module.
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/spinlock.h>
14 #include <linux/notifier.h>
15 #include <linux/rcupdate.h>
16 #include <linux/seqlock.h>
17 #include <linux/percpu.h>
18 #include <linux/prefetch.h>
19 #include <net/sock.h>
21 #include "xt_fblock.h"
22 #include "xt_builder.h"
23 #include "xt_idp.h"
24 #include "xt_skb.h"
25 #include "xt_engine.h"
26 #include "xt_builder.h"
28 #define AF_LANA 66 /* For now.. */
29 #define PF_LANA AF_LANA
31 struct fb_pflana_priv {
32 idp_t port[NUM_TYPES];
33 seqlock_t lock;
36 static struct proto lana_proto;
37 static const struct proto_ops lana_ui_ops;
39 static int fb_pflana_netrx(const struct fblock * const fb,
40 struct sk_buff * const skb,
41 enum path_type * const dir)
43 return PPE_SUCCESS;
46 static int fb_pflana_event(struct notifier_block *self, unsigned long cmd,
47 void *args)
49 return 0;
52 struct lana_sock {
53 /* struct sock must be the first member of lana_sock */
54 struct sock sk;
55 /* ... */
58 static int lana_backlog_rcv(struct sock *sk, struct sk_buff *skb)
60 printk(KERN_INFO "packet in backlog queue\n");
61 kfree_skb(skb);
62 return 0;
65 static void lana_ui_sk_init(struct socket *sock, struct sock *sk)
67 sock_graft(sk, sock);
68 sk->sk_type = sock->type;
69 sock->ops = &lana_ui_ops;
72 static void lana_sk_init(struct sock* sk)
74 /* default struct vals*/
75 sk->sk_backlog_rcv = lana_backlog_rcv;
78 static struct sock *lana_sk_alloc(struct net *net, int family, gfp_t priority,
79 struct proto *prot)
81 struct sock *sk = sk_alloc(net, family, priority, prot);
82 if (!sk)
83 return NULL;
84 lana_sk_init(sk);
85 sock_init_data(NULL, sk);
86 return sk;
89 static void lana_sk_free(struct sock *sk)
91 skb_queue_purge(&sk->sk_receive_queue);
92 skb_queue_purge(&sk->sk_write_queue);
93 sock_put(sk);
96 static int lana_ui_create(struct net *net, struct socket *sock, int protocol,
97 int kern)
99 struct sock *sk;
100 int rc = -ESOCKTNOSUPPORT;
102 if (!net_eq(net, &init_net))
103 return -EAFNOSUPPORT;
104 if (likely(sock->type == SOCK_DGRAM ||
105 sock->type == SOCK_STREAM)) {
106 rc = -ENOMEM;
107 sk = lana_sk_alloc(net, PF_LANA, GFP_KERNEL, &lana_proto);
108 if (sk) {
109 rc = 0;
110 lana_ui_sk_init(sock, sk);
113 return rc;
116 static int lana_ui_release(struct socket *sock)
118 struct sock *sk = sock->sk;
120 if (unlikely(sk == NULL))
121 return 0;
122 sock_hold(sk);
123 lock_sock(sk);
124 release_sock(sk);
125 //TODO dev_put();
126 sock_put(sk);
127 lana_sk_free(sk);
128 return 0;
131 static const struct net_proto_family lana_ui_family_ops = {
132 .family = PF_LANA,
133 .create = lana_ui_create,
134 .owner = THIS_MODULE,
137 static const struct proto_ops lana_ui_ops = {
138 .family = PF_LANA,
139 .owner = THIS_MODULE,
140 .release = lana_ui_release,
141 .bind = sock_no_bind,
142 .connect = sock_no_connect,
143 .socketpair = sock_no_socketpair,
144 .accept = sock_no_accept,
145 .getname = sock_no_getname,
146 .poll = sock_no_poll,
147 .ioctl = sock_no_ioctl,
148 .listen = sock_no_listen,
149 .shutdown = sock_no_shutdown,
150 .setsockopt = sock_no_setsockopt,
151 .getsockopt = sock_no_getsockopt,
152 .sendmsg = sock_no_sendmsg,
153 .recvmsg = sock_no_recvmsg,
154 .mmap = sock_no_mmap,
155 .sendpage = sock_no_sendpage,
158 static struct proto lana_proto = {
159 .name = "LANA",
160 .owner = THIS_MODULE,
161 .obj_size = sizeof(struct lana_sock),
162 .slab_flags = SLAB_DESTROY_BY_RCU,
165 static int init_fb_pflana(void)
167 int ret;
168 ret = proto_register(&lana_proto, 0);
169 if (ret)
170 return ret;
171 ret = sock_register(&lana_ui_family_ops);
172 if (ret) {
173 proto_unregister(&lana_proto);
174 return ret;
176 return 0;
179 static void cleanup_fb_pflana(void)
181 sock_unregister(PF_LANA);
182 proto_unregister(&lana_proto);
185 static struct fblock *fb_pflana_ctor(char *name)
187 int i, ret = 0;
188 unsigned int cpu;
189 struct fblock *fb;
190 struct fb_pflana_priv __percpu *fb_priv;
192 return NULL;
193 fb = alloc_fblock(GFP_ATOMIC);
194 if (!fb)
195 return NULL;
197 fb_priv = alloc_percpu(struct fb_pflana_priv);
198 if (!fb_priv)
199 goto err;
201 get_online_cpus();
202 for_each_online_cpu(cpu) {
203 struct fb_pflana_priv *fb_priv_cpu;
204 fb_priv_cpu = per_cpu_ptr(fb_priv, cpu);
205 seqlock_init(&fb_priv_cpu->lock);
206 for (i = 0; i < NUM_TYPES; ++i)
207 fb_priv_cpu->port[i] = IDP_UNKNOWN;
209 put_online_cpus();
211 ret = init_fblock(fb, name, fb_priv);
212 if (ret)
213 goto err2;
214 fb->netfb_rx = fb_pflana_netrx;
215 fb->event_rx = fb_pflana_event;
216 ret = register_fblock_namespace(fb);
217 if (ret)
218 goto err3;
219 __module_get(THIS_MODULE);
220 return fb;
221 err3:
222 cleanup_fblock_ctor(fb);
223 err2:
224 free_percpu(fb_priv);
225 err:
226 kfree_fblock(fb);
227 fb = NULL;
228 return NULL;
231 static void fb_pflana_dtor(struct fblock *fb)
233 free_percpu(rcu_dereference_raw(fb->private_data));
234 module_put(THIS_MODULE);
237 static struct fblock_factory fb_pflana_factory = {
238 .type = "pflana",
239 .mode = MODE_SINK,
240 .ctor = fb_pflana_ctor,
241 .dtor = fb_pflana_dtor,
242 .owner = THIS_MODULE,
245 static int __init init_fb_pflana_module(void)
247 int ret;
248 ret = init_fb_pflana();
249 if (ret)
250 return ret;
251 ret = register_fblock_type(&fb_pflana_factory);
252 if (ret)
253 cleanup_fb_pflana();
254 return ret;
257 static void __exit cleanup_fb_pflana_module(void)
259 cleanup_fb_pflana();
260 unregister_fblock_type(&fb_pflana_factory);
263 module_init(init_fb_pflana_module);
264 module_exit(cleanup_fb_pflana_module);
266 MODULE_LICENSE("GPL");
267 MODULE_AUTHOR("Daniel Borkmann <dborkma@tik.ee.ethz.ch>");
268 MODULE_DESCRIPTION("LANA PF_LANA module");