From 086034b37999801ac4eeff522741f9cc6fce60e3 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Sat, 30 Apr 2011 16:28:42 +0200 Subject: [PATCH] sending of options now works --- src/fb_dummy.c | 23 +++---- src/xt_fblock.c | 43 +++++++++++++ src/xt_fblock.h | 11 +++- src/xt_user.c | 188 +++++++++++++++++++++++++++++--------------------------- 4 files changed, 161 insertions(+), 104 deletions(-) diff --git a/src/fb_dummy.c b/src/fb_dummy.c index 8fa09a0..c0bfbc8 100644 --- a/src/fb_dummy.c +++ b/src/fb_dummy.c @@ -46,37 +46,34 @@ static int fb_dummy_event(struct notifier_block *self, unsigned long cmd, { int ret = NOTIFY_OK; unsigned long flags; - struct fblock_bind_msg *msg; struct fblock *fb = container_of(self, struct fblock_notifier, nb)->self; struct fb_dummy_priv *fb_priv = fb->private_data; printk("Got event %lu on %p!\n", cmd, fb); switch (cmd) { - case FBLOCK_BIND_IDP: - msg = args; + case FBLOCK_BIND_IDP: { + struct fblock_bind_msg *msg = args; spin_lock_irqsave(&fb_priv->lock, flags); if (fb_priv->port[msg->dir] == IDP_UNKNOWN) fb_priv->port[msg->dir] = msg->idp; else ret = NOTIFY_BAD; spin_unlock_irqrestore(&fb_priv->lock, flags); - break; - case FBLOCK_UNBIND_IDP: - msg = args; + } break; + case FBLOCK_UNBIND_IDP: { + struct fblock_bind_msg *msg = args; spin_lock_irqsave(&fb_priv->lock, flags); if (fb_priv->port[msg->dir] == msg->idp) fb_priv->port[msg->dir] = IDP_UNKNOWN; else ret = NOTIFY_BAD; spin_unlock_irqrestore(&fb_priv->lock, flags); - break; - case FBLOCK_XCHG_IDP: - msg = args; - spin_lock_irqsave(&fb_priv->lock, flags); - fb_priv->port[msg->dir] = msg->idp; - spin_unlock_irqrestore(&fb_priv->lock, flags); - break; + } break; + case FBLOCK_SET_OPT: { + struct fblock_opt_msg *msg = args; + printk("Set option %s to %s!\n", msg->key, msg->val); + } break; default: break; } diff --git a/src/xt_fblock.c b/src/xt_fblock.c index 4e59556..4c53447 100644 --- a/src/xt_fblock.c +++ b/src/xt_fblock.c @@ -188,6 +188,49 @@ struct fblock *search_fblock_n(char *name) } EXPORT_SYMBOL_GPL(search_fblock_n); +/* opt_string must be of type "key=val" and 0-terminated */ +int __fblock_set_option(struct fblock *fb, char *opt_string) +{ + int ret = 0; + char *val = opt_string; + struct fblock_opt_msg msg; + /* Hack: we let the fb think that this belongs to his own chain to + * get the reference back to itself. */ + struct fblock_notifier fbn; + + memset(&fbn, 0, sizeof(fbn)); + memset(&msg, 0, sizeof(msg)); + + msg.key = opt_string; + while (*val != '=' && *val != '\0') + val++; + if (*val == '\0') + return -EINVAL; + val++; + *(val - 1) = '\0'; + msg.val = val; + fbn.self = fb; + + get_fblock(fb); + ret = fb->ops->event_rx(&fbn.nb, FBLOCK_SET_OPT, &msg); + put_fblock(fb); + + return ret; +} +EXPORT_SYMBOL_GPL(__fblock_set_option); + +int fblock_set_option(struct fblock *fb, char *opt_string) +{ + int ret; + if (unlikely(!opt_string || !fb)) + return -EINVAL; + rcu_read_lock(); + ret = __fblock_set_option(fb, opt_string); + rcu_read_unlock(); + return ret; +} +EXPORT_SYMBOL_GPL(fblock_set_option); + /* * fb1 on top of fb2 in the stack */ diff --git a/src/xt_fblock.h b/src/xt_fblock.h index e3283ad..2957a14 100644 --- a/src/xt_fblock.h +++ b/src/xt_fblock.h @@ -33,7 +33,7 @@ enum path_type { #define FBLOCK_BIND_IDP 0x0001 #define FBLOCK_UNBIND_IDP 0x0002 -#define FBLOCK_XCHG_IDP 0x0003 +#define FBLOCK_SET_OPT 0x0003 #define FBLOCK_DOWN_PREPARE 0x0004 #define FBLOCK_DOWN 0x0005 @@ -51,6 +51,11 @@ struct fblock_bind_msg { idp_t idp; }; +struct fblock_opt_msg { + char *key; + char *val; +}; + struct fblock; struct fblock_ops { @@ -126,6 +131,10 @@ extern struct fblock *__search_fblock(idp_t idp); extern struct fblock *search_fblock_n(char *name); extern struct fblock *__search_fblock_n(char *name); +/* Notify fblock of new option. */ +extern int fblock_set_option(struct fblock *fb, char *opt_string); +extern int __fblock_set_option(struct fblock *fb, char *opt_string); + /* Binds two fblock objects, increments refcount each. */ extern int fblock_bind(struct fblock *fb1, struct fblock *fb2); extern int __fblock_bind(struct fblock *fb1, struct fblock *fb2); diff --git a/src/xt_user.c b/src/xt_user.c index c7eaad4..6e57a3c 100644 --- a/src/xt_user.c +++ b/src/xt_user.c @@ -37,117 +37,125 @@ static int __userctl_rcv(struct sk_buff *skb, struct nlmsghdr *nlh) switch (lmsg->cmd) { case NETLINK_USERCTL_CMD_ADD: { - struct fblock *fb; - struct lananlmsg_add *msg = - (struct lananlmsg_add *) lmsg->buff; - fb = build_fblock_object(msg->type, msg->name); - if (!fb) - return -ENOMEM; + struct fblock *fb; + struct lananlmsg_add *msg = + (struct lananlmsg_add *) lmsg->buff; + fb = build_fblock_object(msg->type, msg->name); + if (!fb) + return -ENOMEM; } break; case NETLINK_USERCTL_CMD_SET: { -// struct lananlmsg_set *msg = -// (struct lananlmsg_set *) lmsg->buff; + int ret; + struct fblock *fb; + struct lananlmsg_set *msg = + (struct lananlmsg_set *) lmsg->buff; + fb = search_fblock_n(msg->name); + if (!fb) + return -EINVAL; + ret = fblock_set_option(fb, msg->option); + put_fblock(fb); + return ret; } break; case NETLINK_USERCTL_CMD_REPLACE: { -// struct lananlmsg_replace *msg = -// (struct lananlmsg_replace *) lmsg->buff; +// struct lananlmsg_replace *msg = +// (struct lananlmsg_replace *) lmsg->buff; } break; case NETLINK_USERCTL_CMD_SUBSCRIBE: { - int ret; - struct fblock *fb1, *fb2; - struct lananlmsg_subscribe *msg = - (struct lananlmsg_subscribe *) lmsg->buff; - fb1 = search_fblock_n(msg->name1); - if (!fb1) - return -EINVAL; - fb2 = search_fblock_n(msg->name2); - if (!fb2) { - put_fblock(fb1); - return -EINVAL; - } - /* - * fb1 is remote block, fb2 is the one that - * wishes to be notified. - */ - ret = subscribe_to_remote_fblock(fb2, fb1); + int ret; + struct fblock *fb1, *fb2; + struct lananlmsg_subscribe *msg = + (struct lananlmsg_subscribe *) lmsg->buff; + fb1 = search_fblock_n(msg->name1); + if (!fb1) + return -EINVAL; + fb2 = search_fblock_n(msg->name2); + if (!fb2) { put_fblock(fb1); - put_fblock(fb2); - return ret; + return -EINVAL; + } + /* + * fb1 is remote block, fb2 is the one that + * wishes to be notified. + */ + ret = subscribe_to_remote_fblock(fb2, fb1); + put_fblock(fb1); + put_fblock(fb2); + return ret; } break; case NETLINK_USERCTL_CMD_UNSUBSCRIBE: { - struct fblock *fb1, *fb2; - struct lananlmsg_unsubscribe *msg = - (struct lananlmsg_unsubscribe *) lmsg->buff; - fb1 = search_fblock_n(msg->name1); - if (!fb1) - return -EINVAL; - fb2 = search_fblock_n(msg->name2); - if (!fb2) { - put_fblock(fb1); - return -EINVAL; - } - unsubscribe_from_remote_fblock(fb2, fb1); + struct fblock *fb1, *fb2; + struct lananlmsg_unsubscribe *msg = + (struct lananlmsg_unsubscribe *) lmsg->buff; + fb1 = search_fblock_n(msg->name1); + if (!fb1) + return -EINVAL; + fb2 = search_fblock_n(msg->name2); + if (!fb2) { put_fblock(fb1); - put_fblock(fb2); + return -EINVAL; + } + unsubscribe_from_remote_fblock(fb2, fb1); + put_fblock(fb1); + put_fblock(fb2); } break; case NETLINK_USERCTL_CMD_RM: { - struct fblock *fb; - struct lananlmsg_rm *msg = - (struct lananlmsg_rm *) lmsg->buff; - fb = search_fblock_n(msg->name); - if (!fb) - return -EINVAL; - if (atomic_read(&fb->refcnt) > 2) { - /* Still in use by others */ - put_fblock(fb); - return -EBUSY; - } - unregister_fblock_namespace(fb); + struct fblock *fb; + struct lananlmsg_rm *msg = + (struct lananlmsg_rm *) lmsg->buff; + fb = search_fblock_n(msg->name); + if (!fb) + return -EINVAL; + if (atomic_read(&fb->refcnt) > 2) { + /* Still in use by others */ put_fblock(fb); + return -EBUSY; + } + unregister_fblock_namespace(fb); + put_fblock(fb); } break; case NETLINK_USERCTL_CMD_BIND: { - int ret; - struct fblock *fb1, *fb2; - struct lananlmsg_bind *msg = - (struct lananlmsg_bind *) lmsg->buff; - fb1 = search_fblock_n(msg->name1); - if (!fb1) - return -EINVAL; - fb2 = search_fblock_n(msg->name2); - if (!fb2) { - put_fblock(fb1); - return -EINVAL; - } - ret = fblock_bind(fb1, fb2); - if (ret) { - put_fblock(fb1); - put_fblock(fb2); - return ret; - } + int ret; + struct fblock *fb1, *fb2; + struct lananlmsg_bind *msg = + (struct lananlmsg_bind *) lmsg->buff; + fb1 = search_fblock_n(msg->name1); + if (!fb1) + return -EINVAL; + fb2 = search_fblock_n(msg->name2); + if (!fb2) { + put_fblock(fb1); + return -EINVAL; + } + ret = fblock_bind(fb1, fb2); + if (ret) { put_fblock(fb1); put_fblock(fb2); + return ret; + } + put_fblock(fb1); + put_fblock(fb2); } break; case NETLINK_USERCTL_CMD_UNBIND: { - int ret; - struct fblock *fb1, *fb2; - struct lananlmsg_unbind *msg = - (struct lananlmsg_unbind *) lmsg->buff; - fb1 = search_fblock_n(msg->name1); - if (!fb1) - return -EINVAL; - fb2 = search_fblock_n(msg->name2); - if (!fb2) { - put_fblock(fb1); - return -EINVAL; - } - ret = fblock_unbind(fb1, fb2); - if (ret) { - put_fblock(fb1); - put_fblock(fb2); - return ret; - } + int ret; + struct fblock *fb1, *fb2; + struct lananlmsg_unbind *msg = + (struct lananlmsg_unbind *) lmsg->buff; + fb1 = search_fblock_n(msg->name1); + if (!fb1) + return -EINVAL; + fb2 = search_fblock_n(msg->name2); + if (!fb2) { + put_fblock(fb1); + return -EINVAL; + } + ret = fblock_unbind(fb1, fb2); + if (ret) { put_fblock(fb1); put_fblock(fb2); + return ret; + } + put_fblock(fb1); + put_fblock(fb2); } break; default: printk("[lana] Unknown command!\n"); -- 2.11.4.GIT