linux/net/wimax/op-msg.c
<<
>>
Prefs
   1/*
   2 * Linux WiMAX
   3 * Generic messaging interface between userspace and driver/device
   4 *
   5 *
   6 * Copyright (C) 2007-2008 Intel Corporation <linux-wimax@intel.com>
   7 * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License version
  11 * 2 as published by the Free Software Foundation.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  21 * 02110-1301, USA.
  22 *
  23 *
  24 * This implements a direct communication channel between user space and
  25 * the driver/device, by which free form messages can be sent back and
  26 * forth.
  27 *
  28 * This is intended for device-specific features, vendor quirks, etc.
  29 *
  30 * See include/net/wimax.h
  31 *
  32 * GENERIC NETLINK ENCODING AND CAPACITY
  33 *
  34 * A destination "pipe name" is added to each message; it is up to the
  35 * drivers to assign or use those names (if using them at all).
  36 *
  37 * Messages are encoded as a binary netlink attribute using nla_put()
  38 * using type NLA_UNSPEC (as some versions of libnl still in
  39 * deployment don't yet understand NLA_BINARY).
  40 *
  41 * The maximum capacity of this transport is PAGESIZE per message (so
  42 * the actual payload will be bit smaller depending on the
  43 * netlink/generic netlink attributes and headers).
  44 *
  45 * RECEPTION OF MESSAGES
  46 *
  47 * When a message is received from user space, it is passed verbatim
  48 * to the driver calling wimax_dev->op_msg_from_user(). The return
  49 * value from this function is passed back to user space as an ack
  50 * over the generic netlink protocol.
  51 *
  52 * The stack doesn't do any processing or interpretation of these
  53 * messages.
  54 *
  55 * SENDING MESSAGES
  56 *
  57 * Messages can be sent with wimax_msg().
  58 *
  59 * If the message delivery needs to happen on a different context to
  60 * that of its creation, wimax_msg_alloc() can be used to get a
  61 * pointer to the message that can be delivered later on with
  62 * wimax_msg_send().
  63 *
  64 * ROADMAP
  65 *
  66 * wimax_gnl_doit_msg_from_user()    Process a message from user space
  67 *   wimax_dev_get_by_genl_info()
  68 *   wimax_dev->op_msg_from_user()   Delivery of message to the driver
  69 *
  70 * wimax_msg()                       Send a message to user space
  71 *   wimax_msg_alloc()
  72 *   wimax_msg_send()
  73 */
  74#include <linux/device.h>
  75#include <linux/slab.h>
  76#include <net/genetlink.h>
  77#include <linux/netdevice.h>
  78#include <linux/wimax.h>
  79#include <linux/security.h>
  80#include <linux/export.h>
  81#include "wimax-internal.h"
  82
  83
  84#define D_SUBMODULE op_msg
  85#include "debug-levels.h"
  86
  87
  88/**
  89 * wimax_msg_alloc - Create a new skb for sending a message to userspace
  90 *
  91 * @wimax_dev: WiMAX device descriptor
  92 * @pipe_name: "named pipe" the message will be sent to
  93 * @msg: pointer to the message data to send
  94 * @size: size of the message to send (in bytes), including the header.
  95 * @gfp_flags: flags for memory allocation.
  96 *
  97 * Returns: %0 if ok, negative errno code on error
  98 *
  99 * Description:
 100 *
 101 * Allocates an skb that will contain the message to send to user
 102 * space over the messaging pipe and initializes it, copying the
 103 * payload.
 104 *
 105 * Once this call is done, you can deliver it with
 106 * wimax_msg_send().
 107 *
 108 * IMPORTANT:
 109 *
 110 * Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as
 111 * wimax_msg_send() depends on skb->data being placed at the
 112 * beginning of the user message.
 113 *
 114 * Unlike other WiMAX stack calls, this call can be used way early,
 115 * even before wimax_dev_add() is called, as long as the
 116 * wimax_dev->net_dev pointer is set to point to a proper
 117 * net_dev. This is so that drivers can use it early in case they need
 118 * to send stuff around or communicate with user space.
 119 */
 120struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev,
 121                                const char *pipe_name,
 122                                const void *msg, size_t size,
 123                                gfp_t gfp_flags)
 124{
 125        int result;
 126        struct device *dev = wimax_dev_to_dev(wimax_dev);
 127        size_t msg_size;
 128        void *genl_msg;
 129        struct sk_buff *skb;
 130
 131        msg_size = nla_total_size(size)
 132                + nla_total_size(sizeof(u32))
 133                + (pipe_name ? nla_total_size(strlen(pipe_name)) : 0);
 134        result = -ENOMEM;
 135        skb = genlmsg_new(msg_size, gfp_flags);
 136        if (skb == NULL)
 137                goto error_new;
 138        genl_msg = genlmsg_put(skb, 0, 0, &wimax_gnl_family,
 139                               0, WIMAX_GNL_OP_MSG_TO_USER);
 140        if (genl_msg == NULL) {
 141                dev_err(dev, "no memory to create generic netlink message\n");
 142                goto error_genlmsg_put;
 143        }
 144        result = nla_put_u32(skb, WIMAX_GNL_MSG_IFIDX,
 145                             wimax_dev->net_dev->ifindex);
 146        if (result < 0) {
 147                dev_err(dev, "no memory to add ifindex attribute\n");
 148                goto error_nla_put;
 149        }
 150        if (pipe_name) {
 151                result = nla_put_string(skb, WIMAX_GNL_MSG_PIPE_NAME,
 152                                        pipe_name);
 153                if (result < 0) {
 154                        dev_err(dev, "no memory to add pipe_name attribute\n");
 155                        goto error_nla_put;
 156                }
 157        }
 158        result = nla_put(skb, WIMAX_GNL_MSG_DATA, size, msg);
 159        if (result < 0) {
 160                dev_err(dev, "no memory to add payload (msg %p size %zu) in "
 161                        "attribute: %d\n", msg, size, result);
 162                goto error_nla_put;
 163        }
 164        genlmsg_end(skb, genl_msg);
 165        return skb;
 166
 167error_nla_put:
 168error_genlmsg_put:
 169error_new:
 170        nlmsg_free(skb);
 171        return ERR_PTR(result);
 172}
 173EXPORT_SYMBOL_GPL(wimax_msg_alloc);
 174
 175
 176/**
 177 * wimax_msg_data_len - Return a pointer and size of a message's payload
 178 *
 179 * @msg: Pointer to a message created with wimax_msg_alloc()
 180 * @size: Pointer to where to store the message's size
 181 *
 182 * Returns the pointer to the message data.
 183 */
 184const void *wimax_msg_data_len(struct sk_buff *msg, size_t *size)
 185{
 186        struct nlmsghdr *nlh = (void *) msg->head;
 187        struct nlattr *nla;
 188
 189        nla = nlmsg_find_attr(nlh, sizeof(struct genlmsghdr),
 190                              WIMAX_GNL_MSG_DATA);
 191        if (nla == NULL) {
 192                printk(KERN_ERR "Cannot find attribute WIMAX_GNL_MSG_DATA\n");
 193                return NULL;
 194        }
 195        *size = nla_len(nla);
 196        return nla_data(nla);
 197}
 198EXPORT_SYMBOL_GPL(wimax_msg_data_len);
 199
 200
 201/**
 202 * wimax_msg_data - Return a pointer to a message's payload
 203 *
 204 * @msg: Pointer to a message created with wimax_msg_alloc()
 205 */
 206const void *wimax_msg_data(struct sk_buff *msg)
 207{
 208        struct nlmsghdr *nlh = (void *) msg->head;
 209        struct nlattr *nla;
 210
 211        nla = nlmsg_find_attr(nlh, sizeof(struct genlmsghdr),
 212                              WIMAX_GNL_MSG_DATA);
 213        if (nla == NULL) {
 214                printk(KERN_ERR "Cannot find attribute WIMAX_GNL_MSG_DATA\n");
 215                return NULL;
 216        }
 217        return nla_data(nla);
 218}
 219EXPORT_SYMBOL_GPL(wimax_msg_data);
 220
 221
 222/**
 223 * wimax_msg_len - Return a message's payload length
 224 *
 225 * @msg: Pointer to a message created with wimax_msg_alloc()
 226 */
 227ssize_t wimax_msg_len(struct sk_buff *msg)
 228{
 229        struct nlmsghdr *nlh = (void *) msg->head;
 230        struct nlattr *nla;
 231
 232        nla = nlmsg_find_attr(nlh, sizeof(struct genlmsghdr),
 233                              WIMAX_GNL_MSG_DATA);
 234        if (nla == NULL) {
 235                printk(KERN_ERR "Cannot find attribute WIMAX_GNL_MSG_DATA\n");
 236                return -EINVAL;
 237        }
 238        return nla_len(nla);
 239}
 240EXPORT_SYMBOL_GPL(wimax_msg_len);
 241
 242
 243/**
 244 * wimax_msg_send - Send a pre-allocated message to user space
 245 *
 246 * @wimax_dev: WiMAX device descriptor
 247 *
 248 * @skb: &struct sk_buff returned by wimax_msg_alloc(). Note the
 249 *     ownership of @skb is transferred to this function.
 250 *
 251 * Returns: 0 if ok, < 0 errno code on error
 252 *
 253 * Description:
 254 *
 255 * Sends a free-form message that was preallocated with
 256 * wimax_msg_alloc() and filled up.
 257 *
 258 * Assumes that once you pass an skb to this function for sending, it
 259 * owns it and will release it when done (on success).
 260 *
 261 * IMPORTANT:
 262 *
 263 * Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as
 264 * wimax_msg_send() depends on skb->data being placed at the
 265 * beginning of the user message.
 266 *
 267 * Unlike other WiMAX stack calls, this call can be used way early,
 268 * even before wimax_dev_add() is called, as long as the
 269 * wimax_dev->net_dev pointer is set to point to a proper
 270 * net_dev. This is so that drivers can use it early in case they need
 271 * to send stuff around or communicate with user space.
 272 */
 273int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb)
 274{
 275        struct device *dev = wimax_dev_to_dev(wimax_dev);
 276        void *msg = skb->data;
 277        size_t size = skb->len;
 278        might_sleep();
 279
 280        d_printf(1, dev, "CTX: wimax msg, %zu bytes\n", size);
 281        d_dump(2, dev, msg, size);
 282        genlmsg_multicast(skb, 0, wimax_gnl_mcg.id, GFP_KERNEL);
 283        d_printf(1, dev, "CTX: genl multicast done\n");
 284        return 0;
 285}
 286EXPORT_SYMBOL_GPL(wimax_msg_send);
 287
 288
 289/**
 290 * wimax_msg - Send a message to user space
 291 *
 292 * @wimax_dev: WiMAX device descriptor (properly referenced)
 293 * @pipe_name: "named pipe" the message will be sent to
 294 * @buf: pointer to the message to send.
 295 * @size: size of the buffer pointed to by @buf (in bytes).
 296 * @gfp_flags: flags for memory allocation.
 297 *
 298 * Returns: %0 if ok, negative errno code on error.
 299 *
 300 * Description:
 301 *
 302 * Sends a free-form message to user space on the device @wimax_dev.
 303 *
 304 * NOTES:
 305 *
 306 * Once the @skb is given to this function, who will own it and will
 307 * release it when done (unless it returns error).
 308 */
 309int wimax_msg(struct wimax_dev *wimax_dev, const char *pipe_name,
 310              const void *buf, size_t size, gfp_t gfp_flags)
 311{
 312        int result = -ENOMEM;
 313        struct sk_buff *skb;
 314
 315        skb = wimax_msg_alloc(wimax_dev, pipe_name, buf, size, gfp_flags);
 316        if (IS_ERR(skb))
 317                result = PTR_ERR(skb);
 318        else
 319                result = wimax_msg_send(wimax_dev, skb);
 320        return result;
 321}
 322EXPORT_SYMBOL_GPL(wimax_msg);
 323
 324
 325static const struct nla_policy wimax_gnl_msg_policy[WIMAX_GNL_ATTR_MAX + 1] = {
 326        [WIMAX_GNL_MSG_IFIDX] = {
 327                .type = NLA_U32,
 328        },
 329        [WIMAX_GNL_MSG_DATA] = {
 330                .type = NLA_UNSPEC,     /* libnl doesn't grok BINARY yet */
 331        },
 332};
 333
 334
 335/*
 336 * Relays a message from user space to the driver
 337 *
 338 * The skb is passed to the driver-specific function with the netlink
 339 * and generic netlink headers already stripped.
 340 *
 341 * This call will block while handling/relaying the message.
 342 */
 343static
 344int wimax_gnl_doit_msg_from_user(struct sk_buff *skb, struct genl_info *info)
 345{
 346        int result, ifindex;
 347        struct wimax_dev *wimax_dev;
 348        struct device *dev;
 349        struct nlmsghdr *nlh = info->nlhdr;
 350        char *pipe_name;
 351        void *msg_buf;
 352        size_t msg_len;
 353
 354        might_sleep();
 355        d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info);
 356        result = -ENODEV;
 357        if (info->attrs[WIMAX_GNL_MSG_IFIDX] == NULL) {
 358                printk(KERN_ERR "WIMAX_GNL_MSG_FROM_USER: can't find IFIDX "
 359                       "attribute\n");
 360                goto error_no_wimax_dev;
 361        }
 362        ifindex = nla_get_u32(info->attrs[WIMAX_GNL_MSG_IFIDX]);
 363        wimax_dev = wimax_dev_get_by_genl_info(info, ifindex);
 364        if (wimax_dev == NULL)
 365                goto error_no_wimax_dev;
 366        dev = wimax_dev_to_dev(wimax_dev);
 367
 368        /* Unpack arguments */
 369        result = -EINVAL;
 370        if (info->attrs[WIMAX_GNL_MSG_DATA] == NULL) {
 371                dev_err(dev, "WIMAX_GNL_MSG_FROM_USER: can't find MSG_DATA "
 372                        "attribute\n");
 373                goto error_no_data;
 374        }
 375        msg_buf = nla_data(info->attrs[WIMAX_GNL_MSG_DATA]);
 376        msg_len = nla_len(info->attrs[WIMAX_GNL_MSG_DATA]);
 377
 378        if (info->attrs[WIMAX_GNL_MSG_PIPE_NAME] == NULL)
 379                pipe_name = NULL;
 380        else {
 381                struct nlattr *attr = info->attrs[WIMAX_GNL_MSG_PIPE_NAME];
 382                size_t attr_len = nla_len(attr);
 383                /* libnl-1.1 does not yet support NLA_NUL_STRING */
 384                result = -ENOMEM;
 385                pipe_name = kstrndup(nla_data(attr), attr_len + 1, GFP_KERNEL);
 386                if (pipe_name == NULL)
 387                        goto error_alloc;
 388                pipe_name[attr_len] = 0;
 389        }
 390        mutex_lock(&wimax_dev->mutex);
 391        result = wimax_dev_is_ready(wimax_dev);
 392        if (result == -ENOMEDIUM)
 393                result = 0;
 394        if (result < 0)
 395                goto error_not_ready;
 396        result = -ENOSYS;
 397        if (wimax_dev->op_msg_from_user == NULL)
 398                goto error_noop;
 399
 400        d_printf(1, dev,
 401                 "CRX: nlmsghdr len %u type %u flags 0x%04x seq 0x%x pid %u\n",
 402                 nlh->nlmsg_len, nlh->nlmsg_type, nlh->nlmsg_flags,
 403                 nlh->nlmsg_seq, nlh->nlmsg_pid);
 404        d_printf(1, dev, "CRX: wimax message %zu bytes\n", msg_len);
 405        d_dump(2, dev, msg_buf, msg_len);
 406
 407        result = wimax_dev->op_msg_from_user(wimax_dev, pipe_name,
 408                                             msg_buf, msg_len, info);
 409error_noop:
 410error_not_ready:
 411        mutex_unlock(&wimax_dev->mutex);
 412error_alloc:
 413        kfree(pipe_name);
 414error_no_data:
 415        dev_put(wimax_dev->net_dev);
 416error_no_wimax_dev:
 417        d_fnend(3, NULL, "(skb %p info %p) = %d\n", skb, info, result);
 418        return result;
 419}
 420
 421
 422/*
 423 * Generic Netlink glue
 424 */
 425
 426struct genl_ops wimax_gnl_msg_from_user = {
 427        .cmd = WIMAX_GNL_OP_MSG_FROM_USER,
 428        .flags = GENL_ADMIN_PERM,
 429        .policy = wimax_gnl_msg_policy,
 430        .doit = wimax_gnl_doit_msg_from_user,
 431        .dumpit = NULL,
 432};
 433
 434
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.