1 /* 2 * Copyright (c) 2017 Mellanox Technologies Inc. All rights reserved. 3 * Copyright (c) 2010 Voltaire Inc. All rights reserved. 4 * 5 * This software is available to you under a choice of one of two 6 * licenses. You may choose to be licensed under the terms of the GNU 7 * General Public License (GPL) Version 2, available from the file 8 * COPYING in the main directory of this source tree, or the 9 * OpenIB.org BSD license below: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * - Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials 22 * provided with the distribution. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 * SOFTWARE. 32 */ 33 34 #define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__ 35 36 #include <linux/export.h> 37 #include <net/netlink.h> 38 #include <net/net_namespace.h> 39 #include <net/sock.h> 40 #include <rdma/rdma_netlink.h> 41 #include <linux/module.h> 42 #include "core_priv.h" 43 44 static DEFINE_MUTEX(rdma_nl_mutex); 45 static struct sock *nls; 46 static struct { 47 const struct rdma_nl_cbs *cb_table; 48 } rdma_nl_types[RDMA_NL_NUM_CLIENTS]; 49 50 bool rdma_nl_chk_listeners(unsigned int group) 51 { 52 return netlink_has_listeners(nls, group); 53 } 54 EXPORT_SYMBOL(rdma_nl_chk_listeners); 55 56 static bool is_nl_msg_valid(unsigned int type, unsigned int op) 57 { 58 static const unsigned int max_num_ops[RDMA_NL_NUM_CLIENTS] = { 59 [RDMA_NL_IWCM] = RDMA_NL_IWPM_NUM_OPS, 60 [RDMA_NL_LS] = RDMA_NL_LS_NUM_OPS, 61 [RDMA_NL_NLDEV] = RDMA_NLDEV_NUM_OPS, 62 }; 63 64 /* 65 * This BUILD_BUG_ON is intended to catch addition of new 66 * RDMA netlink protocol without updating the array above. 67 */ 68 BUILD_BUG_ON(RDMA_NL_NUM_CLIENTS != 6); 69 70 if (type >= RDMA_NL_NUM_CLIENTS) 71 return false; 72 73 return (op < max_num_ops[type]) ? true : false; 74 } 75 76 static bool is_nl_valid(unsigned int type, unsigned int op) 77 { 78 const struct rdma_nl_cbs *cb_table; 79 80 if (!is_nl_msg_valid(type, op)) 81 return false; 82 83 if (!rdma_nl_types[type].cb_table) { 84 mutex_unlock(&rdma_nl_mutex); 85 request_module("rdma-netlink-subsys-%d", type); 86 mutex_lock(&rdma_nl_mutex); 87 } 88 89 cb_table = rdma_nl_types[type].cb_table; 90 91 if (!cb_table || (!cb_table[op].dump && !cb_table[op].doit)) 92 return false; 93 return true; 94 } 95 96 void rdma_nl_register(unsigned int index, 97 const struct rdma_nl_cbs cb_table[]) 98 { 99 mutex_lock(&rdma_nl_mutex); 100 if (!is_nl_msg_valid(index, 0)) { 101 /* 102 * All clients are not interesting in success/failure of 103 * this call. They want to see the print to error log and 104 * continue their initialization. Print warning for them, 105 * because it is programmer's error to be here. 106 */ 107 mutex_unlock(&rdma_nl_mutex); 108 WARN(true, 109 "The not-valid %u index was supplied to RDMA netlink\n", 110 index); 111 return; 112 } 113 114 if (rdma_nl_types[index].cb_table) { 115 mutex_unlock(&rdma_nl_mutex); 116 WARN(true, 117 "The %u index is already registered in RDMA netlink\n", 118 index); 119 return; 120 } 121 122 rdma_nl_types[index].cb_table = cb_table; 123 mutex_unlock(&rdma_nl_mutex); 124 } 125 EXPORT_SYMBOL(rdma_nl_register); 126 127 void rdma_nl_unregister(unsigned int index) 128 { 129 mutex_lock(&rdma_nl_mutex); 130 rdma_nl_types[index].cb_table = NULL; 131 mutex_unlock(&rdma_nl_mutex); 132 } 133 EXPORT_SYMBOL(rdma_nl_unregister); 134 135 void *ibnl_put_msg(struct sk_buff *skb, struct nlmsghdr **nlh, int seq, 136 int len, int client, int op, int flags) 137 { 138 *nlh = nlmsg_put(skb, 0, seq, RDMA_NL_GET_TYPE(client, op), len, flags); 139 if (!*nlh) 140 return NULL; 141 return nlmsg_data(*nlh); 142 } 143 EXPORT_SYMBOL(ibnl_put_msg); 144 145 int ibnl_put_attr(struct sk_buff *skb, struct nlmsghdr *nlh, 146 int len, void *data, int type) 147 { 148 if (nla_put(skb, type, len, data)) { 149 nlmsg_cancel(skb, nlh); 150 return -EMSGSIZE; 151 } 152 return 0; 153 } 154 EXPORT_SYMBOL(ibnl_put_attr); 155 156 static int rdma_nl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, 157 struct netlink_ext_ack *extack) 158 { 159 int type = nlh->nlmsg_type; 160 unsigned int index = RDMA_NL_GET_CLIENT(type); 161 unsigned int op = RDMA_NL_GET_OP(type); 162 const struct rdma_nl_cbs *cb_table; 163 164 if (!is_nl_valid(index, op)) 165 return -EINVAL; 166 167 cb_table = rdma_nl_types[index].cb_table; 168 169 if ((cb_table[op].flags & RDMA_NL_ADMIN_PERM) && 170 !netlink_capable(skb, CAP_NET_ADMIN)) 171 return -EPERM; 172 173 /* 174 * LS responses overload the 0x100 (NLM_F_ROOT) flag. Don't 175 * mistakenly call the .dump() function. 176 */ 177 if (index == RDMA_NL_LS) { 178 if (cb_table[op].doit) 179 return cb_table[op].doit(skb, nlh, extack); 180 return -EINVAL; 181 } 182 /* FIXME: Convert IWCM to properly handle doit callbacks */ 183 if ((nlh->nlmsg_flags & NLM_F_DUMP) || index == RDMA_NL_IWCM) { 184 struct netlink_dump_control c = { 185 .dump = cb_table[op].dump, 186 }; 187 if (c.dump) 188 return netlink_dump_start(nls, skb, nlh, &c); 189 return -EINVAL; 190 } 191 192 if (cb_table[op].doit) 193 return cb_table[op].doit(skb, nlh, extack); 194 195 return 0; 196 } 197 198 /* 199 * This function is similar to netlink_rcv_skb with one exception: 200 * It calls to the callback for the netlink messages without NLM_F_REQUEST 201 * flag. These messages are intended for RDMA_NL_LS consumer, so it is allowed 202 * for that consumer only. 203 */ 204 static int rdma_nl_rcv_skb(struct sk_buff *skb, int (*cb)(struct sk_buff *, 205 struct nlmsghdr *, 206 struct netlink_ext_ack *)) 207 { 208 struct netlink_ext_ack extack = {}; 209 struct nlmsghdr *nlh; 210 int err; 211 212 while (skb->len >= nlmsg_total_size(0)) { 213 int msglen; 214 215 nlh = nlmsg_hdr(skb); 216 err = 0; 217 218 if (nlh->nlmsg_len < NLMSG_HDRLEN || skb->len < nlh->nlmsg_len) 219 return 0; 220 221 /* 222 * Generally speaking, the only requests are handled 223 * by the kernel, but RDMA_NL_LS is different, because it 224 * runs backward netlink scheme. Kernel initiates messages 225 * and waits for reply with data to keep pathrecord cache 226 * in sync. 227 */ 228 if (!(nlh->nlmsg_flags & NLM_F_REQUEST) && 229 (RDMA_NL_GET_CLIENT(nlh->nlmsg_type) != RDMA_NL_LS)) 230 goto ack; 231 232 /* Skip control messages */ 233 if (nlh->nlmsg_type < NLMSG_MIN_TYPE) 234 goto ack; 235 236 err = cb(skb, nlh, &extack); 237 if (err == -EINTR) 238 goto skip; 239 240 ack: 241 if (nlh->nlmsg_flags & NLM_F_ACK || err) 242 netlink_ack(skb, nlh, err, &extack); 243 244 skip: 245 msglen = NLMSG_ALIGN(nlh->nlmsg_len); 246 if (msglen > skb->len) 247 msglen = skb->len; 248 skb_pull(skb, msglen); 249 } 250 251 return 0; 252 } 253 254 static void rdma_nl_rcv(struct sk_buff *skb) 255 { 256 mutex_lock(&rdma_nl_mutex); 257 rdma_nl_rcv_skb(skb, &rdma_nl_rcv_msg); 258 mutex_unlock(&rdma_nl_mutex); 259 } 260 261 int rdma_nl_unicast(struct sk_buff *skb, u32 pid) 262 { 263 int err; 264 265 err = netlink_unicast(nls, skb, pid, MSG_DONTWAIT); 266 return (err < 0) ? err : 0; 267 } 268 EXPORT_SYMBOL(rdma_nl_unicast); 269 270 int rdma_nl_unicast_wait(struct sk_buff *skb, __u32 pid) 271 { 272 int err; 273 274 err = netlink_unicast(nls, skb, pid, 0); 275 return (err < 0) ? err : 0; 276 } 277 EXPORT_SYMBOL(rdma_nl_unicast_wait); 278 279 int rdma_nl_multicast(struct sk_buff *skb, unsigned int group, gfp_t flags) 280 { 281 return nlmsg_multicast(nls, skb, 0, group, flags); 282 } 283 EXPORT_SYMBOL(rdma_nl_multicast); 284 285 int __init rdma_nl_init(void) 286 { 287 struct netlink_kernel_cfg cfg = { 288 .input = rdma_nl_rcv, 289 }; 290 291 nls = netlink_kernel_create(&init_net, NETLINK_RDMA, &cfg); 292 if (!nls) 293 return -ENOMEM; 294 295 nls->sk_sndtimeo = 10 * HZ; 296 return 0; 297 } 298 299 void rdma_nl_exit(void) 300 { 301 int idx; 302 303 for (idx = 0; idx < RDMA_NL_NUM_CLIENTS; idx++) 304 rdma_nl_unregister(idx); 305 306 netlink_kernel_release(nls); 307 } 308 309 MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_RDMA); 310