1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Netlink routines for CIFS
4 *
5 * Copyright (c) 2020 Samuel Cabrero <scabrero@suse.de>
6 */
7
8#include <net/genetlink.h>
9#include <uapi/linux/cifs/cifs_netlink.h>
10
11#include "netlink.h"
12#include "cifsglob.h"
13#include "cifs_debug.h"
14#include "cifs_swn.h"
15
16static const struct nla_policy cifs_genl_policy[CIFS_GENL_ATTR_MAX + 1] = {
17	[CIFS_GENL_ATTR_SWN_REGISTRATION_ID]	= { .type = NLA_U32 },
18	[CIFS_GENL_ATTR_SWN_NET_NAME]		= { .type = NLA_STRING },
19	[CIFS_GENL_ATTR_SWN_SHARE_NAME]		= { .type = NLA_STRING },
20	[CIFS_GENL_ATTR_SWN_IP]			= { .len = sizeof(struct sockaddr_storage) },
21	[CIFS_GENL_ATTR_SWN_NET_NAME_NOTIFY]	= { .type = NLA_FLAG },
22	[CIFS_GENL_ATTR_SWN_SHARE_NAME_NOTIFY]	= { .type = NLA_FLAG },
23	[CIFS_GENL_ATTR_SWN_IP_NOTIFY]		= { .type = NLA_FLAG },
24	[CIFS_GENL_ATTR_SWN_KRB_AUTH]		= { .type = NLA_FLAG },
25	[CIFS_GENL_ATTR_SWN_USER_NAME]		= { .type = NLA_STRING },
26	[CIFS_GENL_ATTR_SWN_PASSWORD]		= { .type = NLA_STRING },
27	[CIFS_GENL_ATTR_SWN_DOMAIN_NAME]	= { .type = NLA_STRING },
28	[CIFS_GENL_ATTR_SWN_NOTIFICATION_TYPE]	= { .type = NLA_U32 },
29	[CIFS_GENL_ATTR_SWN_RESOURCE_STATE]	= { .type = NLA_U32 },
30	[CIFS_GENL_ATTR_SWN_RESOURCE_NAME]	= { .type = NLA_STRING},
31};
32
33static const struct genl_ops cifs_genl_ops[] = {
34	{
35		.cmd = CIFS_GENL_CMD_SWN_NOTIFY,
36		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
37		.doit = cifs_swn_notify,
38	},
39};
40
41static const struct genl_multicast_group cifs_genl_mcgrps[] = {
42	[CIFS_GENL_MCGRP_SWN] = { .name = CIFS_GENL_MCGRP_SWN_NAME },
43};
44
45struct genl_family cifs_genl_family = {
46	.name		= CIFS_GENL_NAME,
47	.version	= CIFS_GENL_VERSION,
48	.hdrsize	= 0,
49	.maxattr	= CIFS_GENL_ATTR_MAX,
50	.module		= THIS_MODULE,
51	.policy		= cifs_genl_policy,
52	.ops		= cifs_genl_ops,
53	.n_ops		= ARRAY_SIZE(cifs_genl_ops),
54	.resv_start_op	= CIFS_GENL_CMD_SWN_NOTIFY + 1,
55	.mcgrps		= cifs_genl_mcgrps,
56	.n_mcgrps	= ARRAY_SIZE(cifs_genl_mcgrps),
57};
58
59/**
60 * cifs_genl_init - Register generic netlink family
61 *
62 * Return zero if initialized successfully, otherwise non-zero.
63 */
64int cifs_genl_init(void)
65{
66	int ret;
67
68	ret = genl_register_family(&cifs_genl_family);
69	if (ret < 0) {
70		cifs_dbg(VFS, "%s: failed to register netlink family\n",
71				__func__);
72		return ret;
73	}
74
75	return 0;
76}
77
78/**
79 * cifs_genl_exit - Unregister generic netlink family
80 */
81void cifs_genl_exit(void)
82{
83	int ret;
84
85	ret = genl_unregister_family(&cifs_genl_family);
86	if (ret < 0) {
87		cifs_dbg(VFS, "%s: failed to unregister netlink family\n",
88				__func__);
89	}
90}
91