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 "wimax-internal.h"
  81
  82
  83#define D_SUBMODULE op_msg
  84#include "debug-levels.h"
  85
  86
  87/**
  88 * wimax_msg_alloc - Create a new skb for sending a message to userspace
  89 *
  90 * @wimax_dev: WiMAX device descriptor
  91 * @pipe_name: "named pipe" the message will be sent to
  92 * @msg: pointer to the message data to send
  93 * @size: size of the message to send (in bytes), including the header.
  94 * @gfp_flags: flags for memory allocation.
  95 *
  96 * Returns: %0 if ok, negative errno code on error
  97 *
  98 * Description:
  99 *
 100 * Allocates an skb that will contain the message to send to user
 101 * space over the messaging pipe and initializes it, copying the
 102 * payload.
 103 *
 104 * Once this call is done, you can deliver it with
 105 * wimax_msg_send().
 106 *
 107 * IMPORTANT:
 108 *
 109 * Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as
 110 * wimax_msg_send() depends on skb->data being placed at the
 111 * beginning of the user message.
 112 *
 113 * Unlike other WiMAX stack calls, this call can be used way early,
 114 * even before wimax_dev_add() is called, as long as the
 115 * wimax_dev->net_dev pointer is set to point to a proper
 116 * net_dev. This is so that drivers can use it early in case they need
 117 * to send stuff around or communicate with user space.
 118 */
 119struct sk_buff *wimax_msg_alloc(struct wimax_dev *wimax_dev,
 120                                const char *pipe_name,
 121                                const void *msg, size_t size,
 122                                gfp_t gfp_flags)
 123{
 124        int result;
 125        struct device *dev = wimax_dev_to_dev(wimax_dev);
 126        size_t msg_size;
 127        void *genl_msg;
 128        struct sk_buff *skb;
 129
 130        msg_size = nla_total_size(size)
 131                + nla_total_size(sizeof(u32))
 132                + (pipe_name ? nla_total_size(strlen(pipe_name)) : 0);
 133        result = -ENOMEM;
 134        skb = genlmsg_new(msg_size, gfp_flags);
 135        if (skb == NULL)
 136                goto error_new;
 137        genl_msg = genlmsg_put(skb, 0, 0, &wimax_gnl_family,
 138                               0, WIMAX_GNL_OP_MSG_TO_USER);
 139        if (genl_msg == NULL) {
 140                dev_err(dev, "no memory to create generic netlink message\n");
 141                goto error_genlmsg_put;
 142        }
 143        result = nla_put_u32(skb, WIMAX_GNL_MSG_IFIDX,
 144                             wimax_dev->net_dev->ifindex);
 145        if (result < 0) {
 146                dev_err(dev, "no memory to add ifindex attribute\n");
 147                goto error_nla_put;
 148        }
 149        if (pipe_name) {
 150                result = nla_put_string(skb, WIMAX_GNL_MSG_PIPE_NAME,
 151                                        pipe_name);
 152                if (result < 0) {
 153                        dev_err(dev, "no memory to add pipe_name attribute\n");
 154                        goto error_nla_put;
 155                }
 156        }
 157        result = nla_put(skb, WIMAX_GNL_MSG_DATA, size, msg);
 158        if (result < 0) {
 159                dev_err(dev, "no memory to add payload (msg %p size %zu) in "
 160                        "attribute: %d\n", msg, size, result);
 161                goto error_nla_put;
 162        }
 163        genlmsg_end(skb, genl_msg);
 164        return skb;
 165
 166error_nla_put:
 167error_genlmsg_put:
 168error_new:
 169        nlmsg_free(skb);
 170        return ERR_PTR(result);
 171}
 172EXPORT_SYMBOL_GPL(wimax_msg_alloc);
 173
 174
 175/**
 176 * wimax_msg_data_len - Return a pointer and size of a message's payload
 177 *
 178 * @msg: Pointer to a message created with wimax_msg_alloc()
 179 * @size: Pointer to where to store the message's size
 180 *
 181 * Returns the pointer to the message data.
 182 */
 183const void *wimax_msg_data_len(struct sk_buff *msg, size_t *size)
 184{
 185        struct nlmsghdr *nlh = (void *) msg->head;
 186        struct nlattr *nla;
 187
 188        nla = nlmsg_find_attr(nlh, sizeof(struct genlmsghdr),
 189                              WIMAX_GNL_MSG_DATA);
 190        if (nla == NULL) {
 191                printk(KERN_ERR "Cannot find attribute WIMAX_GNL_MSG_DATA\n");
 192                return NULL;
 193        }
 194        *size = nla_len(nla);
 195        return nla_data(nla);
 196}
 197EXPORT_SYMBOL_GPL(wimax_msg_data_len);
 198
 199
 200/**
 201 * wimax_msg_data - Return a pointer to a message's payload
 202 *
 203 * @msg: Pointer to a message created with wimax_msg_alloc()
 204 */
 205const void *wimax_msg_data(struct sk_buff *msg)
 206{
 207        struct nlmsghdr *nlh = (void *) msg->head;
 208        struct nlattr *nla;
 209
 210        nla = nlmsg_find_attr(nlh, sizeof(struct genlmsghdr),
 211                              WIMAX_GNL_MSG_DATA);
 212        if (nla == NULL) {
 213                printk(KERN_ERR "Cannot find attribute WIMAX_GNL_MSG_DATA\n");
 214                return NULL;
 215        }
 216        return nla_data(nla);
 217}
 218EXPORT_SYMBOL_GPL(wimax_msg_data);
 219
 220
 221/**
 222 * wimax_msg_len - Return a message's payload length
 223 *
 224 * @msg: Pointer to a message created with wimax_msg_alloc()
 225 */
 226ssize_t wimax_msg_len(struct sk_buff *msg)
 227{
 228        struct nlmsghdr *nlh = (void *) msg->head;
 229        struct nlattr *nla;
 230
 231        nla = nlmsg_find_attr(nlh, sizeof(struct genlmsghdr),
 232                              WIMAX_GNL_MSG_DATA);
 233        if (nla == NULL) {
 234                printk(KERN_ERR "Cannot find attribute WIMAX_GNL_MSG_DATA\n");
 235                return -EINVAL;
 236        }
 237        return nla_len(nla);
 238}
 239EXPORT_SYMBOL_GPL(wimax_msg_len);
 240
 241
 242/**
 243 * wimax_msg_send - Send a pre-allocated message to user space
 244 *
 245 * @wimax_dev: WiMAX device descriptor
 246 *
 247 * @skb: &struct sk_buff returned by wimax_msg_alloc(). Note the
 248 *     ownership of @skb is transferred to this function.
 249 *
 250 * Returns: 0 if ok, < 0 errno code on error
 251 *
 252 * Description:
 253 *
 254 * Sends a free-form message that was preallocated with
 255 * wimax_msg_alloc() and filled up.
 256 *
 257 * Assumes that once you pass an skb to this function for sending, it
 258 * owns it and will release it when done (on success).
 259 *
 260 * IMPORTANT:
 261 *
 262 * Don't use skb_push()/skb_pull()/skb_reserve() on the skb, as
 263 * wimax_msg_send() depends on skb->data being placed at the
 264 * beginning of the user message.
 265 *
 266 * Unlike other WiMAX stack calls, this call can be used way early,
 267 * even before wimax_dev_add() is called, as long as the
 268 * wimax_dev->net_dev pointer is set to point to a proper
 269 * net_dev. This is so that drivers can use it early in case they need
 270 * to send stuff around or communicate with user space.
 271 */
 272int wimax_msg_send(struct wimax_dev *wimax_dev, struct sk_buff *skb)
 273{
 274        struct device *dev = wimax_dev_to_dev(wimax_dev);
 275        void *msg = skb->data;
 276        size_t size = skb->len;
 277        might_sleep();
 278
 279        d_printf(1, dev, "CTX: wimax msg, %zu bytes\n", size);
 280        d_dump(2, dev, msg, size);
 281        genlmsg_multicast(skb, 0, wimax_gnl_mcg.id, GFP_KERNEL);
 282        d_printf(1, dev, "CTX: genl multicast done\n");
 283        return 0;
 284}
 285EXPORT_SYMBOL_GPL(wimax_msg_send);
 286
 287
 288/**
 289 * wimax_msg - Send a message to user space
 290 *
 291 * @wimax_dev: WiMAX device descriptor (properly referenced)
 292 * @pipe_name: "named pipe" the message will be sent to
 293 * @buf: pointer to the message to send.
 294 * @size: size of the buffer pointed to by @buf (in bytes).
 295 * @gfp_flags: flags for memory allocation.
 296 *
 297 * Returns: %0 if ok, negative errno code on error.
 298 *
 299 * Description:
 300 *
 301 * Sends a free-form message to user space on the device @wimax_dev.
 302 *
 303 * NOTES:
 304 *
 305 * Once the @skb is given to this function, who will own it and will
 306 * release it when done (unless it returns error).
 307 */
 308int wimax_msg(struct wimax_dev *wimax_dev, const char *pipe_name,
 309              const void *buf, size_t size, gfp_t gfp_flags)
 310{
 311        int result = -ENOMEM;
 312        struct sk_buff *skb;
 313
 314        skb = wimax_msg_alloc(wimax_dev, pipe_name, buf, size, gfp_flags);
 315        if (IS_ERR(skb))
 316                result = PTR_ERR(skb);
 317        else
 318                result = wimax_msg_send(wimax_dev, skb);
 319        return result;
 320}
 321EXPORT_SYMBOL_GPL(wimax_msg);
 322
 323
 324static const struct nla_policy wimax_gnl_msg_policy[WIMAX_GNL_ATTR_MAX + 1] = {
 325        [WIMAX_GNL_MSG_IFIDX] = {
 326                .type = NLA_U32,
 327        },
 328        [WIMAX_GNL_MSG_DATA] = {
 329                .type = NLA_UNSPEC,     /* libnl doesn't grok BINARY yet */
 330        },
 331};
 332
 333
 334/*
 335 * Relays a message from user space to the driver
 336 *
 337 * The skb is passed to the driver-specific function with the netlink
 338 * and generic netlink headers already stripped.
 339 *
 340 * This call will block while handling/relaying the message.
 341 */
 342static
 343int wimax_gnl_doit_msg_from_user(struct sk_buff *skb, struct genl_info *info)
 344{
 345        int result, ifindex;
 346        struct wimax_dev *wimax_dev;
 347        struct device *dev;
 348        struct nlmsghdr *nlh = info->nlhdr;
 349        char *pipe_name;
 350        void *msg_buf;
 351        size_t msg_len;
 352
 353        might_sleep();
 354        d_fnstart(3, NULL, "(skb %p info %p)\n", skb, info);
 355        result = -ENODEV;
 356        if (info->attrs[WIMAX_GNL_MSG_IFIDX] == NULL) {
 357                printk(KERN_ERR "WIMAX_GNL_MSG_FROM_USER: can't find IFIDX "
 358                       "attribute\n");
 359                goto error_no_wimax_dev;
 360        }
 361        ifindex = nla_get_u32(info->attrs[WIMAX_GNL_MSG_IFIDX]);
 362        wimax_dev = wimax_dev_get_by_genl_info(info, ifindex);
 363        if (wimax_dev == NULL)
 364                goto error_no_wimax_dev;
 365        dev = wimax_dev_to_dev(wimax_dev);
 366
 367        /* Unpack arguments */
 368        result = -EINVAL;
 369        if (info->attrs[WIMAX_GNL_MSG_DATA] == NULL) {
 370                dev_err(dev, "WIMAX_GNL_MSG_FROM_USER: can't find MSG_DATA "
 371                        "attribute\n");
 372                goto error_no_data;
 373        }
 374        msg_buf = nla_data(info->attrs[WIMAX_GNL_MSG_DATA]);
 375        msg_len = nla_len(info->attrs[WIMAX_GNL_MSG_DATA]);
 376
 377        if (info->attrs[WIMAX_GNL_MSG_PIPE_NAME] == NULL)
 378                pipe_name = NULL;
 379        else {
 380                struct nlattr *attr = info->attrs[WIMAX_GNL_MSG_PIPE_NAME];
 381                size_t attr_len = nla_len(attr);
 382                /* libnl-1.1 does not yet support NLA_NUL_STRING */
 383                result = -ENOMEM;
 384                pipe_name = kstrndup(nla_data(attr), attr_len + 1, GFP_KERNEL);
 385                if (pipe_name == NULL)
 386                        goto error_alloc;
 387                pipe_name[attr_len] = 0;
 388        }
 389        mutex_lock(&wimax_dev->mutex);
 390        result = wimax_dev_is_ready(wimax_dev);
 391        if (result == -ENOMEDIUM)
 392                result = 0;
 393        if (result < 0)
 394                goto error_not_ready;
 395        result = -ENOSYS;
 396        if (wimax_dev->op_msg_from_user == NULL)
 397                goto error_noop;
 398
 399        d_printf(1, dev,
 400                 "CRX: nlmsghdr len %u type %u flags 0x%04x seq 0x%x pid %u\n",
 401                 nlh->nlmsg_len, nlh->nlmsg_type, nlh->nlmsg_flags,
 402                 nlh->nlmsg_seq, nlh->nlmsg_pid);
 403        d_printf(1, dev, "CRX: wimax message %zu bytes\n", msg_len);
 404        d_dump(2, dev, msg_buf, msg_len);
 405
 406        result = wimax_dev->op_msg_from_user(wimax_dev, pipe_name,
 407                                             msg_buf, msg_len, info);
 408error_noop:
 409error_not_ready:
 410        mutex_unlock(&wimax_dev->mutex);
 411error_alloc:
 412        kfree(pipe_name);
 413error_no_data:
 414        dev_put(wimax_dev->net_dev);
 415error_no_wimax_dev:
 416        d_fnend(3, NULL, "(skb %p info %p) = %d\n", skb, info, result);
 417        return result;
 418}
 419
 420
 421/*
 422 * Generic Netlink glue
 423 */
 424
 425struct genl_ops wimax_gnl_msg_from_user = {
 426        .cmd = WIMAX_GNL_OP_MSG_FROM_USER,
 427        .flags = GENL_ADMIN_PERM,
 428        .policy = wimax_gnl_msg_policy,
 429        .doit = wimax_gnl_doit_msg_from_user,
 430        .dumpit = NULL,
 431};
 432
 433