| /* |
| * 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, |
| }; |