162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Netlink routines for CIFS
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2020 Samuel Cabrero <scabrero@suse.de>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <net/genetlink.h>
962306a36Sopenharmony_ci#include <uapi/linux/cifs/cifs_netlink.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include "netlink.h"
1262306a36Sopenharmony_ci#include "cifsglob.h"
1362306a36Sopenharmony_ci#include "cifs_debug.h"
1462306a36Sopenharmony_ci#include "cifs_swn.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_cistatic const struct nla_policy cifs_genl_policy[CIFS_GENL_ATTR_MAX + 1] = {
1762306a36Sopenharmony_ci	[CIFS_GENL_ATTR_SWN_REGISTRATION_ID]	= { .type = NLA_U32 },
1862306a36Sopenharmony_ci	[CIFS_GENL_ATTR_SWN_NET_NAME]		= { .type = NLA_STRING },
1962306a36Sopenharmony_ci	[CIFS_GENL_ATTR_SWN_SHARE_NAME]		= { .type = NLA_STRING },
2062306a36Sopenharmony_ci	[CIFS_GENL_ATTR_SWN_IP]			= { .len = sizeof(struct sockaddr_storage) },
2162306a36Sopenharmony_ci	[CIFS_GENL_ATTR_SWN_NET_NAME_NOTIFY]	= { .type = NLA_FLAG },
2262306a36Sopenharmony_ci	[CIFS_GENL_ATTR_SWN_SHARE_NAME_NOTIFY]	= { .type = NLA_FLAG },
2362306a36Sopenharmony_ci	[CIFS_GENL_ATTR_SWN_IP_NOTIFY]		= { .type = NLA_FLAG },
2462306a36Sopenharmony_ci	[CIFS_GENL_ATTR_SWN_KRB_AUTH]		= { .type = NLA_FLAG },
2562306a36Sopenharmony_ci	[CIFS_GENL_ATTR_SWN_USER_NAME]		= { .type = NLA_STRING },
2662306a36Sopenharmony_ci	[CIFS_GENL_ATTR_SWN_PASSWORD]		= { .type = NLA_STRING },
2762306a36Sopenharmony_ci	[CIFS_GENL_ATTR_SWN_DOMAIN_NAME]	= { .type = NLA_STRING },
2862306a36Sopenharmony_ci	[CIFS_GENL_ATTR_SWN_NOTIFICATION_TYPE]	= { .type = NLA_U32 },
2962306a36Sopenharmony_ci	[CIFS_GENL_ATTR_SWN_RESOURCE_STATE]	= { .type = NLA_U32 },
3062306a36Sopenharmony_ci	[CIFS_GENL_ATTR_SWN_RESOURCE_NAME]	= { .type = NLA_STRING},
3162306a36Sopenharmony_ci};
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_cistatic const struct genl_ops cifs_genl_ops[] = {
3462306a36Sopenharmony_ci	{
3562306a36Sopenharmony_ci		.cmd = CIFS_GENL_CMD_SWN_NOTIFY,
3662306a36Sopenharmony_ci		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
3762306a36Sopenharmony_ci		.doit = cifs_swn_notify,
3862306a36Sopenharmony_ci	},
3962306a36Sopenharmony_ci};
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistatic const struct genl_multicast_group cifs_genl_mcgrps[] = {
4262306a36Sopenharmony_ci	[CIFS_GENL_MCGRP_SWN] = { .name = CIFS_GENL_MCGRP_SWN_NAME },
4362306a36Sopenharmony_ci};
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistruct genl_family cifs_genl_family = {
4662306a36Sopenharmony_ci	.name		= CIFS_GENL_NAME,
4762306a36Sopenharmony_ci	.version	= CIFS_GENL_VERSION,
4862306a36Sopenharmony_ci	.hdrsize	= 0,
4962306a36Sopenharmony_ci	.maxattr	= CIFS_GENL_ATTR_MAX,
5062306a36Sopenharmony_ci	.module		= THIS_MODULE,
5162306a36Sopenharmony_ci	.policy		= cifs_genl_policy,
5262306a36Sopenharmony_ci	.ops		= cifs_genl_ops,
5362306a36Sopenharmony_ci	.n_ops		= ARRAY_SIZE(cifs_genl_ops),
5462306a36Sopenharmony_ci	.resv_start_op	= CIFS_GENL_CMD_SWN_NOTIFY + 1,
5562306a36Sopenharmony_ci	.mcgrps		= cifs_genl_mcgrps,
5662306a36Sopenharmony_ci	.n_mcgrps	= ARRAY_SIZE(cifs_genl_mcgrps),
5762306a36Sopenharmony_ci};
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci/**
6062306a36Sopenharmony_ci * cifs_genl_init - Register generic netlink family
6162306a36Sopenharmony_ci *
6262306a36Sopenharmony_ci * Return zero if initialized successfully, otherwise non-zero.
6362306a36Sopenharmony_ci */
6462306a36Sopenharmony_ciint cifs_genl_init(void)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	int ret;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	ret = genl_register_family(&cifs_genl_family);
6962306a36Sopenharmony_ci	if (ret < 0) {
7062306a36Sopenharmony_ci		cifs_dbg(VFS, "%s: failed to register netlink family\n",
7162306a36Sopenharmony_ci				__func__);
7262306a36Sopenharmony_ci		return ret;
7362306a36Sopenharmony_ci	}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	return 0;
7662306a36Sopenharmony_ci}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci/**
7962306a36Sopenharmony_ci * cifs_genl_exit - Unregister generic netlink family
8062306a36Sopenharmony_ci */
8162306a36Sopenharmony_civoid cifs_genl_exit(void)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	int ret;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	ret = genl_unregister_family(&cifs_genl_family);
8662306a36Sopenharmony_ci	if (ret < 0) {
8762306a36Sopenharmony_ci		cifs_dbg(VFS, "%s: failed to unregister netlink family\n",
8862306a36Sopenharmony_ci				__func__);
8962306a36Sopenharmony_ci	}
9062306a36Sopenharmony_ci}
91