blob: 323788131d7e517e9ee7918ecf1d1c2e2faba3cb [file] [log] [blame]
/*
* Fastpath Netlink Interface
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU FP_ERR( Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#define pr_fmt(fmt) "mfp" " netlink:%s:%d: " fmt, __func__, __LINE__
#include "fp_common.h"
#include "fp_core.h"
#include "fp_netlink.h"
struct nla_policy fp_netlink_policy[FASTPATH_NL_A_MAX + 1] __maybe_unused = {
[FASTPATH_NL_A_MSG] = { .type = NLA_NUL_STRING },
};
/* Optional: Add rule parsing to avoid blocking all entries */
static int fp_netlink_ipt_notify(struct sk_buff *skb, struct genl_info *info)
{
struct fastpath_module *m = fp_module_get_by_name("fp_learner");
int ret = -EINVAL;
if (!m) {
pr_err("failed to get fp_learner module\n");
return -EINVAL;
}
if (m->ops && m->ops->ioctl) {
ret = m->ops->ioctl(m, FASTPATH_NL_C_IPT_NOTIFY, NULL);
goto out;
}
out:
fp_module_put(m);
return ret;
}
static struct genl_ops fp_netlink_genl_ops[] = {
FASTPATH_NL_OP(FASTPATH_NL_C_IPT_NOTIFY, fp_netlink_ipt_notify),
};
static struct genl_family fp_netlink_family = {
.hdrsize = 0,
.name = "FASTPATH",
.version = 1,
.maxattr = FASTPATH_NL_A_MAX,
.ops = fp_netlink_genl_ops,
.n_ops = ARRAY_SIZE(fp_netlink_genl_ops),
};
static struct attribute *fp_netlink_attrs[] = {
NULL, /* need to NULL terminate the list of attributes */
};
static void fp_netlink_release(struct kobject *kobj)
{
struct fastpath_module *module = to_fpmod(kobj);
genl_unregister_family(&fp_netlink_family);
pr_debug("fp_netlink released\n");
kfree(module);
}
static struct kobj_type ktype_netlink = {
.sysfs_ops = &fp_sysfs_ops,
.default_attrs = fp_netlink_attrs,
.release = fp_netlink_release,
};
static int fp_netlink_probe(struct fastpath_module *module)
{
int ret;
module->priv = NULL;
snprintf(module->name, sizeof(module->name),"fp_netlink");
ret = genl_register_family(&fp_netlink_family);
kobject_init(&module->kobj, &ktype_netlink);
ret = kobject_add(&module->kobj, module->fastpath->kobj, "%s", module->name);
if (ret < 0) {
pr_err("kobject_add failed (%d)\n", ret);
goto err_register_ops;
}
kobject_uevent(&module->kobj, KOBJ_ADD);
pr_debug("fp_netlink probed\n");
return 0;
err_register_ops:
kobject_put(&module->kobj);
genl_unregister_family(&fp_netlink_family);
return ret;
}
static int fp_netlink_remove(struct fastpath_module *module)
{
kobject_put(&module->kobj);
pr_debug("fp_netlink removed\n");
return 0;
}
struct fastpath_module_ops fp_netlink_ops = {
.probe = fp_netlink_probe,
.remove = fp_netlink_remove,
};