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