|
@@ -1,7 +1,7 @@
|
|
/*
|
|
/*
|
|
* net/tipc/netlink.c: TIPC configuration handling
|
|
* net/tipc/netlink.c: TIPC configuration handling
|
|
*
|
|
*
|
|
- * Copyright (c) 2005-2006, Ericsson AB
|
|
|
|
|
|
+ * Copyright (c) 2005-2006, 2014, Ericsson AB
|
|
* Copyright (c) 2005-2007, Wind River Systems
|
|
* Copyright (c) 2005-2007, Wind River Systems
|
|
* All rights reserved.
|
|
* All rights reserved.
|
|
*
|
|
*
|
|
@@ -36,6 +36,7 @@
|
|
|
|
|
|
#include "core.h"
|
|
#include "core.h"
|
|
#include "config.h"
|
|
#include "config.h"
|
|
|
|
+#include "bearer.h"
|
|
#include <net/genetlink.h>
|
|
#include <net/genetlink.h>
|
|
|
|
|
|
static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
|
|
static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
|
|
@@ -68,6 +69,12 @@ static int handle_cmd(struct sk_buff *skb, struct genl_info *info)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static const struct nla_policy tipc_nl_policy[TIPC_NLA_MAX + 1] = {
|
|
|
|
+ [TIPC_NLA_UNSPEC] = { .type = NLA_UNSPEC, },
|
|
|
|
+ [TIPC_NLA_BEARER] = { .type = NLA_NESTED, },
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/* Legacy ASCII API */
|
|
static struct genl_family tipc_genl_family = {
|
|
static struct genl_family tipc_genl_family = {
|
|
.id = GENL_ID_GENERATE,
|
|
.id = GENL_ID_GENERATE,
|
|
.name = TIPC_GENL_NAME,
|
|
.name = TIPC_GENL_NAME,
|
|
@@ -76,6 +83,7 @@ static struct genl_family tipc_genl_family = {
|
|
.maxattr = 0,
|
|
.maxattr = 0,
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+/* Legacy ASCII API */
|
|
static struct genl_ops tipc_genl_ops[] = {
|
|
static struct genl_ops tipc_genl_ops[] = {
|
|
{
|
|
{
|
|
.cmd = TIPC_GENL_CMD,
|
|
.cmd = TIPC_GENL_CMD,
|
|
@@ -83,11 +91,42 @@ static struct genl_ops tipc_genl_ops[] = {
|
|
},
|
|
},
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+/* Users of the legacy API (tipc-config) can't handle that we add operations,
|
|
|
|
+ * so we have a separate genl handling for the new API.
|
|
|
|
+ */
|
|
|
|
+struct genl_family tipc_genl_v2_family = {
|
|
|
|
+ .id = GENL_ID_GENERATE,
|
|
|
|
+ .name = TIPC_GENL_V2_NAME,
|
|
|
|
+ .version = TIPC_GENL_V2_VERSION,
|
|
|
|
+ .hdrsize = 0,
|
|
|
|
+ .maxattr = TIPC_NLA_MAX,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static const struct genl_ops tipc_genl_v2_ops[] = {
|
|
|
|
+ {
|
|
|
|
+ .cmd = TIPC_NL_BEARER_DISABLE,
|
|
|
|
+ .doit = tipc_nl_bearer_disable,
|
|
|
|
+ .policy = tipc_nl_policy,
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ .cmd = TIPC_NL_BEARER_ENABLE,
|
|
|
|
+ .doit = tipc_nl_bearer_enable,
|
|
|
|
+ .policy = tipc_nl_policy,
|
|
|
|
+ }
|
|
|
|
+};
|
|
|
|
+
|
|
int tipc_netlink_start(void)
|
|
int tipc_netlink_start(void)
|
|
{
|
|
{
|
|
int res;
|
|
int res;
|
|
|
|
|
|
res = genl_register_family_with_ops(&tipc_genl_family, tipc_genl_ops);
|
|
res = genl_register_family_with_ops(&tipc_genl_family, tipc_genl_ops);
|
|
|
|
+ if (res) {
|
|
|
|
+ pr_err("Failed to register legacy interface\n");
|
|
|
|
+ return res;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ res = genl_register_family_with_ops(&tipc_genl_v2_family,
|
|
|
|
+ tipc_genl_v2_ops);
|
|
if (res) {
|
|
if (res) {
|
|
pr_err("Failed to register netlink interface\n");
|
|
pr_err("Failed to register netlink interface\n");
|
|
return res;
|
|
return res;
|
|
@@ -98,4 +137,5 @@ int tipc_netlink_start(void)
|
|
void tipc_netlink_stop(void)
|
|
void tipc_netlink_stop(void)
|
|
{
|
|
{
|
|
genl_unregister_family(&tipc_genl_family);
|
|
genl_unregister_family(&tipc_genl_family);
|
|
|
|
+ genl_unregister_family(&tipc_genl_v2_family);
|
|
}
|
|
}
|