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