xref: /linux/fs/smb/client/netlink.c (revision 54665dce982689e2fd99b32e9a0dcc204fda8a51)
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 		.flags = GENL_ADMIN_PERM,
37 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
38 		.doit = cifs_swn_notify,
39 	},
40 };
41 
42 static const struct genl_multicast_group cifs_genl_mcgrps[] = {
43 	[CIFS_GENL_MCGRP_SWN] = {
44 		.name = CIFS_GENL_MCGRP_SWN_NAME,
45 		.flags = GENL_MCAST_CAP_NET_ADMIN,
46 	},
47 };
48 
49 struct genl_family cifs_genl_family = {
50 	.name		= CIFS_GENL_NAME,
51 	.version	= CIFS_GENL_VERSION,
52 	.hdrsize	= 0,
53 	.maxattr	= CIFS_GENL_ATTR_MAX,
54 	.module		= THIS_MODULE,
55 	.policy		= cifs_genl_policy,
56 	.ops		= cifs_genl_ops,
57 	.n_ops		= ARRAY_SIZE(cifs_genl_ops),
58 	.resv_start_op	= CIFS_GENL_CMD_SWN_NOTIFY + 1,
59 	.mcgrps		= cifs_genl_mcgrps,
60 	.n_mcgrps	= ARRAY_SIZE(cifs_genl_mcgrps),
61 };
62 
63 /**
64  * cifs_genl_init - Register generic netlink family
65  *
66  * Return zero if initialized successfully, otherwise non-zero.
67  */
68 int cifs_genl_init(void)
69 {
70 	int ret;
71 
72 	ret = genl_register_family(&cifs_genl_family);
73 	if (ret < 0) {
74 		cifs_dbg(VFS, "%s: failed to register netlink family\n",
75 				__func__);
76 		return ret;
77 	}
78 
79 	return 0;
80 }
81 
82 /**
83  * cifs_genl_exit - Unregister generic netlink family
84  */
85 void cifs_genl_exit(void)
86 {
87 	int ret;
88 
89 	ret = genl_unregister_family(&cifs_genl_family);
90 	if (ret < 0) {
91 		cifs_dbg(VFS, "%s: failed to unregister netlink family\n",
92 				__func__);
93 	}
94 }
95