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 
16 static 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 
33 static 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 
41 static const struct genl_multicast_group cifs_genl_mcgrps[] = {
42 	[CIFS_GENL_MCGRP_SWN] = { .name = CIFS_GENL_MCGRP_SWN_NAME },
43 };
44 
45 struct 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 	.mcgrps		= cifs_genl_mcgrps,
55 	.n_mcgrps	= ARRAY_SIZE(cifs_genl_mcgrps),
56 };
57 
58 /**
59  * cifs_genl_init - Register generic netlink family
60  *
61  * Return zero if initialized successfully, otherwise non-zero.
62  */
cifs_genl_init(void)63 int cifs_genl_init(void)
64 {
65 	int ret;
66 
67 	ret = genl_register_family(&cifs_genl_family);
68 	if (ret < 0) {
69 		cifs_dbg(VFS, "%s: failed to register netlink family\n",
70 				__func__);
71 		return ret;
72 	}
73 
74 	return 0;
75 }
76 
77 /**
78  * cifs_genl_exit - Unregister generic netlink family
79  */
cifs_genl_exit(void)80 void cifs_genl_exit(void)
81 {
82 	int ret;
83 
84 	ret = genl_unregister_family(&cifs_genl_family);
85 	if (ret < 0) {
86 		cifs_dbg(VFS, "%s: failed to unregister netlink family\n",
87 				__func__);
88 	}
89 }
90