linux/drivers/infiniband/core/iwpm_msg.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2014 Intel Corporation. All rights reserved.
   3 * Copyright (c) 2014 Chelsio, 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#include "iwpm_util.h"
  35
  36static const char iwpm_ulib_name[IWPM_ULIBNAME_SIZE] = "iWarpPortMapperUser";
  37u16 iwpm_ulib_version = IWPM_UABI_VERSION_MIN;
  38static int iwpm_user_pid = IWPM_PID_UNDEFINED;
  39static atomic_t echo_nlmsg_seq;
  40
  41/**
  42 * iwpm_valid_pid - Check if the userspace iwarp port mapper pid is valid
  43 *
  44 * Returns true if the pid is greater than zero, otherwise returns false
  45 */
  46int iwpm_valid_pid(void)
  47{
  48        return iwpm_user_pid > 0;
  49}
  50
  51/**
  52 * iwpm_register_pid - Send a netlink query to userspace
  53 *                     to get the iwarp port mapper pid
  54 * @pm_msg: Contains driver info to send to the userspace port mapper
  55 * @nl_client: The index of the netlink client
  56 *
  57 * nlmsg attributes:
  58 *      [IWPM_NLA_REG_PID_SEQ]
  59 *      [IWPM_NLA_REG_IF_NAME]
  60 *      [IWPM_NLA_REG_IBDEV_NAME]
  61 *      [IWPM_NLA_REG_ULIB_NAME]
  62 */
  63int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client)
  64{
  65        struct sk_buff *skb = NULL;
  66        struct iwpm_nlmsg_request *nlmsg_request = NULL;
  67        struct nlmsghdr *nlh;
  68        u32 msg_seq;
  69        const char *err_str = "";
  70        int ret = -EINVAL;
  71
  72        if (!iwpm_valid_client(nl_client)) {
  73                err_str = "Invalid port mapper client";
  74                goto pid_query_error;
  75        }
  76        if (iwpm_check_registration(nl_client, IWPM_REG_VALID) ||
  77                        iwpm_user_pid == IWPM_PID_UNAVAILABLE)
  78                return 0;
  79        skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REG_PID, &nlh, nl_client);
  80        if (!skb) {
  81                err_str = "Unable to create a nlmsg";
  82                goto pid_query_error;
  83        }
  84        nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
  85        nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq, nl_client, GFP_KERNEL);
  86        if (!nlmsg_request) {
  87                err_str = "Unable to allocate netlink request";
  88                goto pid_query_error;
  89        }
  90        msg_seq = atomic_read(&echo_nlmsg_seq);
  91
  92        /* fill in the pid request message */
  93        err_str = "Unable to put attribute of the nlmsg";
  94        ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq, IWPM_NLA_REG_PID_SEQ);
  95        if (ret)
  96                goto pid_query_error;
  97        ret = ibnl_put_attr(skb, nlh, IFNAMSIZ,
  98                            pm_msg->if_name, IWPM_NLA_REG_IF_NAME);
  99        if (ret)
 100                goto pid_query_error;
 101        ret = ibnl_put_attr(skb, nlh, IWPM_DEVNAME_SIZE,
 102                                pm_msg->dev_name, IWPM_NLA_REG_IBDEV_NAME);
 103        if (ret)
 104                goto pid_query_error;
 105        ret = ibnl_put_attr(skb, nlh, IWPM_ULIBNAME_SIZE,
 106                                (char *)iwpm_ulib_name, IWPM_NLA_REG_ULIB_NAME);
 107        if (ret)
 108                goto pid_query_error;
 109
 110        nlmsg_end(skb, nlh);
 111
 112        pr_debug("%s: Multicasting a nlmsg (dev = %s ifname = %s iwpm = %s)\n",
 113                __func__, pm_msg->dev_name, pm_msg->if_name, iwpm_ulib_name);
 114
 115        ret = rdma_nl_multicast(skb, RDMA_NL_GROUP_IWPM, GFP_KERNEL);
 116        if (ret) {
 117                skb = NULL; /* skb is freed in the netlink send-op handling */
 118                iwpm_user_pid = IWPM_PID_UNAVAILABLE;
 119                err_str = "Unable to send a nlmsg";
 120                goto pid_query_error;
 121        }
 122        nlmsg_request->req_buffer = pm_msg;
 123        ret = iwpm_wait_complete_req(nlmsg_request);
 124        return ret;
 125pid_query_error:
 126        pr_info("%s: %s (client = %d)\n", __func__, err_str, nl_client);
 127        if (skb)
 128                dev_kfree_skb(skb);
 129        if (nlmsg_request)
 130                iwpm_free_nlmsg_request(&nlmsg_request->kref);
 131        return ret;
 132}
 133
 134/**
 135 * iwpm_add_mapping - Send a netlink add mapping request to
 136 *                    the userspace port mapper
 137 * @pm_msg: Contains the local ip/tcp address info to send
 138 * @nl_client: The index of the netlink client
 139 *
 140 * nlmsg attributes:
 141 *      [IWPM_NLA_MANAGE_MAPPING_SEQ]
 142 *      [IWPM_NLA_MANAGE_ADDR]
 143 *      [IWPM_NLA_MANAGE_FLAGS]
 144 *
 145 * If the request is successful, the pm_msg stores
 146 * the port mapper response (mapped address info)
 147 */
 148int iwpm_add_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
 149{
 150        struct sk_buff *skb = NULL;
 151        struct iwpm_nlmsg_request *nlmsg_request = NULL;
 152        struct nlmsghdr *nlh;
 153        u32 msg_seq;
 154        const char *err_str = "";
 155        int ret = -EINVAL;
 156
 157        if (!iwpm_valid_client(nl_client)) {
 158                err_str = "Invalid port mapper client";
 159                goto add_mapping_error;
 160        }
 161        if (!iwpm_valid_pid())
 162                return 0;
 163        if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) {
 164                err_str = "Unregistered port mapper client";
 165                goto add_mapping_error;
 166        }
 167        skb = iwpm_create_nlmsg(RDMA_NL_IWPM_ADD_MAPPING, &nlh, nl_client);
 168        if (!skb) {
 169                err_str = "Unable to create a nlmsg";
 170                goto add_mapping_error;
 171        }
 172        nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
 173        nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq, nl_client, GFP_KERNEL);
 174        if (!nlmsg_request) {
 175                err_str = "Unable to allocate netlink request";
 176                goto add_mapping_error;
 177        }
 178        msg_seq = atomic_read(&echo_nlmsg_seq);
 179        /* fill in the add mapping message */
 180        err_str = "Unable to put attribute of the nlmsg";
 181        ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,
 182                                IWPM_NLA_MANAGE_MAPPING_SEQ);
 183        if (ret)
 184                goto add_mapping_error;
 185        ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
 186                                &pm_msg->loc_addr, IWPM_NLA_MANAGE_ADDR);
 187        if (ret)
 188                goto add_mapping_error;
 189
 190        /* If flags are required and we're not V4, then return a quiet error */
 191        if (pm_msg->flags && iwpm_ulib_version == IWPM_UABI_VERSION_MIN) {
 192                ret = -EINVAL;
 193                goto add_mapping_error_nowarn;
 194        }
 195        if (iwpm_ulib_version > IWPM_UABI_VERSION_MIN) {
 196                ret = ibnl_put_attr(skb, nlh, sizeof(u32), &pm_msg->flags,
 197                                IWPM_NLA_MANAGE_FLAGS);
 198                if (ret)
 199                        goto add_mapping_error;
 200        }
 201
 202        nlmsg_end(skb, nlh);
 203        nlmsg_request->req_buffer = pm_msg;
 204
 205        ret = rdma_nl_unicast_wait(skb, iwpm_user_pid);
 206        if (ret) {
 207                skb = NULL; /* skb is freed in the netlink send-op handling */
 208                iwpm_user_pid = IWPM_PID_UNDEFINED;
 209                err_str = "Unable to send a nlmsg";
 210                goto add_mapping_error;
 211        }
 212        ret = iwpm_wait_complete_req(nlmsg_request);
 213        return ret;
 214add_mapping_error:
 215        pr_info("%s: %s (client = %d)\n", __func__, err_str, nl_client);
 216add_mapping_error_nowarn:
 217        if (skb)
 218                dev_kfree_skb(skb);
 219        if (nlmsg_request)
 220                iwpm_free_nlmsg_request(&nlmsg_request->kref);
 221        return ret;
 222}
 223
 224/**
 225 * iwpm_add_and_query_mapping - Process the port mapper response to
 226 *                              iwpm_add_and_query_mapping request
 227 * @pm_msg: Contains the local ip/tcp address info to send
 228 * @nl_client: The index of the netlink client
 229 *
 230 * nlmsg attributes:
 231 *      [IWPM_NLA_QUERY_MAPPING_SEQ]
 232 *      [IWPM_NLA_QUERY_LOCAL_ADDR]
 233 *      [IWPM_NLA_QUERY_REMOTE_ADDR]
 234 *      [IWPM_NLA_QUERY_FLAGS]
 235 */
 236int iwpm_add_and_query_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client)
 237{
 238        struct sk_buff *skb = NULL;
 239        struct iwpm_nlmsg_request *nlmsg_request = NULL;
 240        struct nlmsghdr *nlh;
 241        u32 msg_seq;
 242        const char *err_str = "";
 243        int ret = -EINVAL;
 244
 245        if (!iwpm_valid_client(nl_client)) {
 246                err_str = "Invalid port mapper client";
 247                goto query_mapping_error;
 248        }
 249        if (!iwpm_valid_pid())
 250                return 0;
 251        if (!iwpm_check_registration(nl_client, IWPM_REG_VALID)) {
 252                err_str = "Unregistered port mapper client";
 253                goto query_mapping_error;
 254        }
 255        ret = -ENOMEM;
 256        skb = iwpm_create_nlmsg(RDMA_NL_IWPM_QUERY_MAPPING, &nlh, nl_client);
 257        if (!skb) {
 258                err_str = "Unable to create a nlmsg";
 259                goto query_mapping_error;
 260        }
 261        nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
 262        nlmsg_request = iwpm_get_nlmsg_request(nlh->nlmsg_seq,
 263                                nl_client, GFP_KERNEL);
 264        if (!nlmsg_request) {
 265                err_str = "Unable to allocate netlink request";
 266                goto query_mapping_error;
 267        }
 268        msg_seq = atomic_read(&echo_nlmsg_seq);
 269
 270        /* fill in the query message */
 271        err_str = "Unable to put attribute of the nlmsg";
 272        ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,
 273                                IWPM_NLA_QUERY_MAPPING_SEQ);
 274        if (ret)
 275                goto query_mapping_error;
 276        ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
 277                                &pm_msg->loc_addr, IWPM_NLA_QUERY_LOCAL_ADDR);
 278        if (ret)
 279                goto query_mapping_error;
 280        ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
 281                                &pm_msg->rem_addr, IWPM_NLA_QUERY_REMOTE_ADDR);
 282        if (ret)
 283                goto query_mapping_error;
 284
 285        /* If flags are required and we're not V4, then return a quite error */
 286        if (pm_msg->flags && iwpm_ulib_version == IWPM_UABI_VERSION_MIN) {
 287                ret = -EINVAL;
 288                goto query_mapping_error_nowarn;
 289        }
 290        if (iwpm_ulib_version > IWPM_UABI_VERSION_MIN) {
 291                ret = ibnl_put_attr(skb, nlh, sizeof(u32), &pm_msg->flags,
 292                                IWPM_NLA_QUERY_FLAGS);
 293                if (ret)
 294                        goto query_mapping_error;
 295        }
 296
 297        nlmsg_end(skb, nlh);
 298        nlmsg_request->req_buffer = pm_msg;
 299
 300        ret = rdma_nl_unicast_wait(skb, iwpm_user_pid);
 301        if (ret) {
 302                skb = NULL; /* skb is freed in the netlink send-op handling */
 303                err_str = "Unable to send a nlmsg";
 304                goto query_mapping_error;
 305        }
 306        ret = iwpm_wait_complete_req(nlmsg_request);
 307        return ret;
 308query_mapping_error:
 309        pr_info("%s: %s (client = %d)\n", __func__, err_str, nl_client);
 310query_mapping_error_nowarn:
 311        if (skb)
 312                dev_kfree_skb(skb);
 313        if (nlmsg_request)
 314                iwpm_free_nlmsg_request(&nlmsg_request->kref);
 315        return ret;
 316}
 317
 318/**
 319 * iwpm_remove_mapping - Send a netlink remove mapping request
 320 *                       to the userspace port mapper
 321 *
 322 * @local_addr: Local ip/tcp address to remove
 323 * @nl_client: The index of the netlink client
 324 *
 325 * nlmsg attributes:
 326 *      [IWPM_NLA_MANAGE_MAPPING_SEQ]
 327 *      [IWPM_NLA_MANAGE_ADDR]
 328 */
 329int iwpm_remove_mapping(struct sockaddr_storage *local_addr, u8 nl_client)
 330{
 331        struct sk_buff *skb = NULL;
 332        struct nlmsghdr *nlh;
 333        u32 msg_seq;
 334        const char *err_str = "";
 335        int ret = -EINVAL;
 336
 337        if (!iwpm_valid_client(nl_client)) {
 338                err_str = "Invalid port mapper client";
 339                goto remove_mapping_error;
 340        }
 341        if (!iwpm_valid_pid())
 342                return 0;
 343        if (iwpm_check_registration(nl_client, IWPM_REG_UNDEF)) {
 344                err_str = "Unregistered port mapper client";
 345                goto remove_mapping_error;
 346        }
 347        skb = iwpm_create_nlmsg(RDMA_NL_IWPM_REMOVE_MAPPING, &nlh, nl_client);
 348        if (!skb) {
 349                ret = -ENOMEM;
 350                err_str = "Unable to create a nlmsg";
 351                goto remove_mapping_error;
 352        }
 353        msg_seq = atomic_read(&echo_nlmsg_seq);
 354        nlh->nlmsg_seq = iwpm_get_nlmsg_seq();
 355        err_str = "Unable to put attribute of the nlmsg";
 356        ret = ibnl_put_attr(skb, nlh, sizeof(u32), &msg_seq,
 357                                IWPM_NLA_MANAGE_MAPPING_SEQ);
 358        if (ret)
 359                goto remove_mapping_error;
 360        ret = ibnl_put_attr(skb, nlh, sizeof(struct sockaddr_storage),
 361                                local_addr, IWPM_NLA_MANAGE_ADDR);
 362        if (ret)
 363                goto remove_mapping_error;
 364
 365        nlmsg_end(skb, nlh);
 366
 367        ret = rdma_nl_unicast_wait(skb, iwpm_user_pid);
 368        if (ret) {
 369                skb = NULL; /* skb is freed in the netlink send-op handling */
 370                iwpm_user_pid = IWPM_PID_UNDEFINED;
 371                err_str = "Unable to send a nlmsg";
 372                goto remove_mapping_error;
 373        }
 374        iwpm_print_sockaddr(local_addr,
 375                        "remove_mapping: Local sockaddr:");
 376        return 0;
 377remove_mapping_error:
 378        pr_info("%s: %s (client = %d)\n", __func__, err_str, nl_client);
 379        if (skb)
 380                dev_kfree_skb_any(skb);
 381        return ret;
 382}
 383
 384/* netlink attribute policy for the received response to register pid request */
 385static const struct nla_policy resp_reg_policy[IWPM_NLA_RREG_PID_MAX] = {
 386        [IWPM_NLA_RREG_PID_SEQ]     = { .type = NLA_U32 },
 387        [IWPM_NLA_RREG_IBDEV_NAME]  = { .type = NLA_STRING,
 388                                        .len = IWPM_DEVNAME_SIZE - 1 },
 389        [IWPM_NLA_RREG_ULIB_NAME]   = { .type = NLA_STRING,
 390                                        .len = IWPM_ULIBNAME_SIZE - 1 },
 391        [IWPM_NLA_RREG_ULIB_VER]    = { .type = NLA_U16 },
 392        [IWPM_NLA_RREG_PID_ERR]     = { .type = NLA_U16 }
 393};
 394
 395/**
 396 * iwpm_register_pid_cb - Process the port mapper response to
 397 *                        iwpm_register_pid query
 398 * @skb:
 399 * @cb: Contains the received message (payload and netlink header)
 400 *
 401 * If successful, the function receives the userspace port mapper pid
 402 * which is used in future communication with the port mapper
 403 */
 404int iwpm_register_pid_cb(struct sk_buff *skb, struct netlink_callback *cb)
 405{
 406        struct iwpm_nlmsg_request *nlmsg_request = NULL;
 407        struct nlattr *nltb[IWPM_NLA_RREG_PID_MAX];
 408        struct iwpm_dev_data *pm_msg;
 409        char *dev_name, *iwpm_name;
 410        u32 msg_seq;
 411        u8 nl_client;
 412        u16 iwpm_version;
 413        const char *msg_type = "Register Pid response";
 414
 415        if (iwpm_parse_nlmsg(cb, IWPM_NLA_RREG_PID_MAX,
 416                                resp_reg_policy, nltb, msg_type))
 417                return -EINVAL;
 418
 419        msg_seq = nla_get_u32(nltb[IWPM_NLA_RREG_PID_SEQ]);
 420        nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
 421        if (!nlmsg_request) {
 422                pr_info("%s: Could not find a matching request (seq = %u)\n",
 423                                 __func__, msg_seq);
 424                return -EINVAL;
 425        }
 426        pm_msg = nlmsg_request->req_buffer;
 427        nl_client = nlmsg_request->nl_client;
 428        dev_name = (char *)nla_data(nltb[IWPM_NLA_RREG_IBDEV_NAME]);
 429        iwpm_name = (char *)nla_data(nltb[IWPM_NLA_RREG_ULIB_NAME]);
 430        iwpm_version = nla_get_u16(nltb[IWPM_NLA_RREG_ULIB_VER]);
 431
 432        /* check device name, ulib name and version */
 433        if (strcmp(pm_msg->dev_name, dev_name) ||
 434                        strcmp(iwpm_ulib_name, iwpm_name) ||
 435                        iwpm_version < IWPM_UABI_VERSION_MIN) {
 436
 437                pr_info("%s: Incorrect info (dev = %s name = %s version = %d)\n",
 438                                __func__, dev_name, iwpm_name, iwpm_version);
 439                nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
 440                goto register_pid_response_exit;
 441        }
 442        iwpm_user_pid = cb->nlh->nlmsg_pid;
 443        iwpm_ulib_version = iwpm_version;
 444        if (iwpm_ulib_version < IWPM_UABI_VERSION)
 445                pr_warn_once("%s: Down level iwpmd/pid %u.  Continuing...",
 446                        __func__, iwpm_user_pid);
 447        atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
 448        pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
 449                        __func__, iwpm_user_pid);
 450        if (iwpm_valid_client(nl_client))
 451                iwpm_set_registration(nl_client, IWPM_REG_VALID);
 452register_pid_response_exit:
 453        nlmsg_request->request_done = 1;
 454        /* always for found nlmsg_request */
 455        kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
 456        barrier();
 457        up(&nlmsg_request->sem);
 458        return 0;
 459}
 460
 461/* netlink attribute policy for the received response to add mapping request */
 462static const struct nla_policy resp_add_policy[IWPM_NLA_RMANAGE_MAPPING_MAX] = {
 463        [IWPM_NLA_RMANAGE_MAPPING_SEQ]     = { .type = NLA_U32 },
 464        [IWPM_NLA_RMANAGE_ADDR]            = {
 465                                .len = sizeof(struct sockaddr_storage) },
 466        [IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR] = {
 467                                .len = sizeof(struct sockaddr_storage) },
 468        [IWPM_NLA_RMANAGE_MAPPING_ERR]     = { .type = NLA_U16 }
 469};
 470
 471/**
 472 * iwpm_add_mapping_cb - Process the port mapper response to
 473 *                       iwpm_add_mapping request
 474 * @skb:
 475 * @cb: Contains the received message (payload and netlink header)
 476 */
 477int iwpm_add_mapping_cb(struct sk_buff *skb, struct netlink_callback *cb)
 478{
 479        struct iwpm_sa_data *pm_msg;
 480        struct iwpm_nlmsg_request *nlmsg_request = NULL;
 481        struct nlattr *nltb[IWPM_NLA_RMANAGE_MAPPING_MAX];
 482        struct sockaddr_storage *local_sockaddr;
 483        struct sockaddr_storage *mapped_sockaddr;
 484        const char *msg_type;
 485        u32 msg_seq;
 486
 487        msg_type = "Add Mapping response";
 488        if (iwpm_parse_nlmsg(cb, IWPM_NLA_RMANAGE_MAPPING_MAX,
 489                                resp_add_policy, nltb, msg_type))
 490                return -EINVAL;
 491
 492        atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
 493
 494        msg_seq = nla_get_u32(nltb[IWPM_NLA_RMANAGE_MAPPING_SEQ]);
 495        nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
 496        if (!nlmsg_request) {
 497                pr_info("%s: Could not find a matching request (seq = %u)\n",
 498                                 __func__, msg_seq);
 499                return -EINVAL;
 500        }
 501        pm_msg = nlmsg_request->req_buffer;
 502        local_sockaddr = (struct sockaddr_storage *)
 503                        nla_data(nltb[IWPM_NLA_RMANAGE_ADDR]);
 504        mapped_sockaddr = (struct sockaddr_storage *)
 505                        nla_data(nltb[IWPM_NLA_RMANAGE_MAPPED_LOC_ADDR]);
 506
 507        if (iwpm_compare_sockaddr(local_sockaddr, &pm_msg->loc_addr)) {
 508                nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
 509                goto add_mapping_response_exit;
 510        }
 511        if (mapped_sockaddr->ss_family != local_sockaddr->ss_family) {
 512                pr_info("%s: Sockaddr family doesn't match the requested one\n",
 513                                __func__);
 514                nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
 515                goto add_mapping_response_exit;
 516        }
 517        memcpy(&pm_msg->mapped_loc_addr, mapped_sockaddr,
 518                        sizeof(*mapped_sockaddr));
 519        iwpm_print_sockaddr(&pm_msg->loc_addr,
 520                        "add_mapping: Local sockaddr:");
 521        iwpm_print_sockaddr(&pm_msg->mapped_loc_addr,
 522                        "add_mapping: Mapped local sockaddr:");
 523
 524add_mapping_response_exit:
 525        nlmsg_request->request_done = 1;
 526        /* always for found request */
 527        kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
 528        barrier();
 529        up(&nlmsg_request->sem);
 530        return 0;
 531}
 532
 533/* netlink attribute policy for the response to add and query mapping request
 534 * and response with remote address info */
 535static const struct nla_policy resp_query_policy[IWPM_NLA_RQUERY_MAPPING_MAX] = {
 536        [IWPM_NLA_RQUERY_MAPPING_SEQ]     = { .type = NLA_U32 },
 537        [IWPM_NLA_RQUERY_LOCAL_ADDR]      = {
 538                                .len = sizeof(struct sockaddr_storage) },
 539        [IWPM_NLA_RQUERY_REMOTE_ADDR]     = {
 540                                .len = sizeof(struct sockaddr_storage) },
 541        [IWPM_NLA_RQUERY_MAPPED_LOC_ADDR] = {
 542                                .len = sizeof(struct sockaddr_storage) },
 543        [IWPM_NLA_RQUERY_MAPPED_REM_ADDR] = {
 544                                .len = sizeof(struct sockaddr_storage) },
 545        [IWPM_NLA_RQUERY_MAPPING_ERR]     = { .type = NLA_U16 }
 546};
 547
 548/**
 549 * iwpm_add_and_query_mapping_cb - Process the port mapper response to
 550 *                                 iwpm_add_and_query_mapping request
 551 * @skb:
 552 * @cb: Contains the received message (payload and netlink header)
 553 */
 554int iwpm_add_and_query_mapping_cb(struct sk_buff *skb,
 555                                struct netlink_callback *cb)
 556{
 557        struct iwpm_sa_data *pm_msg;
 558        struct iwpm_nlmsg_request *nlmsg_request = NULL;
 559        struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX];
 560        struct sockaddr_storage *local_sockaddr, *remote_sockaddr;
 561        struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr;
 562        const char *msg_type;
 563        u32 msg_seq;
 564        u16 err_code;
 565
 566        msg_type = "Query Mapping response";
 567        if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX,
 568                                resp_query_policy, nltb, msg_type))
 569                return -EINVAL;
 570        atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
 571
 572        msg_seq = nla_get_u32(nltb[IWPM_NLA_RQUERY_MAPPING_SEQ]);
 573        nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
 574        if (!nlmsg_request) {
 575                pr_info("%s: Could not find a matching request (seq = %u)\n",
 576                                 __func__, msg_seq);
 577                return -EINVAL;
 578        }
 579        pm_msg = nlmsg_request->req_buffer;
 580        local_sockaddr = (struct sockaddr_storage *)
 581                        nla_data(nltb[IWPM_NLA_RQUERY_LOCAL_ADDR]);
 582        remote_sockaddr = (struct sockaddr_storage *)
 583                        nla_data(nltb[IWPM_NLA_RQUERY_REMOTE_ADDR]);
 584        mapped_loc_sockaddr = (struct sockaddr_storage *)
 585                        nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]);
 586        mapped_rem_sockaddr = (struct sockaddr_storage *)
 587                        nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]);
 588
 589        err_code = nla_get_u16(nltb[IWPM_NLA_RQUERY_MAPPING_ERR]);
 590        if (err_code == IWPM_REMOTE_QUERY_REJECT) {
 591                pr_info("%s: Received a Reject (pid = %u, echo seq = %u)\n",
 592                        __func__, cb->nlh->nlmsg_pid, msg_seq);
 593                nlmsg_request->err_code = IWPM_REMOTE_QUERY_REJECT;
 594        }
 595        if (iwpm_compare_sockaddr(local_sockaddr, &pm_msg->loc_addr) ||
 596                iwpm_compare_sockaddr(remote_sockaddr, &pm_msg->rem_addr)) {
 597                pr_info("%s: Incorrect local sockaddr\n", __func__);
 598                nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
 599                goto query_mapping_response_exit;
 600        }
 601        if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family ||
 602                mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) {
 603                pr_info("%s: Sockaddr family doesn't match the requested one\n",
 604                                __func__);
 605                nlmsg_request->err_code = IWPM_USER_LIB_INFO_ERR;
 606                goto query_mapping_response_exit;
 607        }
 608        memcpy(&pm_msg->mapped_loc_addr, mapped_loc_sockaddr,
 609                        sizeof(*mapped_loc_sockaddr));
 610        memcpy(&pm_msg->mapped_rem_addr, mapped_rem_sockaddr,
 611                        sizeof(*mapped_rem_sockaddr));
 612
 613        iwpm_print_sockaddr(&pm_msg->loc_addr,
 614                        "query_mapping: Local sockaddr:");
 615        iwpm_print_sockaddr(&pm_msg->mapped_loc_addr,
 616                        "query_mapping: Mapped local sockaddr:");
 617        iwpm_print_sockaddr(&pm_msg->rem_addr,
 618                        "query_mapping: Remote sockaddr:");
 619        iwpm_print_sockaddr(&pm_msg->mapped_rem_addr,
 620                        "query_mapping: Mapped remote sockaddr:");
 621query_mapping_response_exit:
 622        nlmsg_request->request_done = 1;
 623        /* always for found request */
 624        kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
 625        barrier();
 626        up(&nlmsg_request->sem);
 627        return 0;
 628}
 629
 630/**
 631 * iwpm_remote_info_cb - Process remote connecting peer address info, which
 632 *                       the port mapper has received from the connecting peer
 633 * @skb:
 634 * @cb: Contains the received message (payload and netlink header)
 635 *
 636 * Stores the IPv4/IPv6 address info in a hash table
 637 */
 638int iwpm_remote_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
 639{
 640        struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX];
 641        struct sockaddr_storage *local_sockaddr, *remote_sockaddr;
 642        struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr;
 643        struct iwpm_remote_info *rem_info;
 644        const char *msg_type;
 645        u8 nl_client;
 646        int ret = -EINVAL;
 647
 648        msg_type = "Remote Mapping info";
 649        if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX,
 650                                resp_query_policy, nltb, msg_type))
 651                return ret;
 652
 653        nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
 654        if (!iwpm_valid_client(nl_client)) {
 655                pr_info("%s: Invalid port mapper client = %d\n",
 656                                __func__, nl_client);
 657                return ret;
 658        }
 659        atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
 660
 661        local_sockaddr = (struct sockaddr_storage *)
 662                        nla_data(nltb[IWPM_NLA_RQUERY_LOCAL_ADDR]);
 663        remote_sockaddr = (struct sockaddr_storage *)
 664                        nla_data(nltb[IWPM_NLA_RQUERY_REMOTE_ADDR]);
 665        mapped_loc_sockaddr = (struct sockaddr_storage *)
 666                        nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]);
 667        mapped_rem_sockaddr = (struct sockaddr_storage *)
 668                        nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]);
 669
 670        if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family ||
 671                mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) {
 672                pr_info("%s: Sockaddr family doesn't match the requested one\n",
 673                                __func__);
 674                return ret;
 675        }
 676        rem_info = kzalloc(sizeof(struct iwpm_remote_info), GFP_ATOMIC);
 677        if (!rem_info) {
 678                ret = -ENOMEM;
 679                return ret;
 680        }
 681        memcpy(&rem_info->mapped_loc_sockaddr, mapped_loc_sockaddr,
 682               sizeof(struct sockaddr_storage));
 683        memcpy(&rem_info->remote_sockaddr, remote_sockaddr,
 684               sizeof(struct sockaddr_storage));
 685        memcpy(&rem_info->mapped_rem_sockaddr, mapped_rem_sockaddr,
 686               sizeof(struct sockaddr_storage));
 687        rem_info->nl_client = nl_client;
 688
 689        iwpm_add_remote_info(rem_info);
 690
 691        iwpm_print_sockaddr(local_sockaddr,
 692                        "remote_info: Local sockaddr:");
 693        iwpm_print_sockaddr(mapped_loc_sockaddr,
 694                        "remote_info: Mapped local sockaddr:");
 695        iwpm_print_sockaddr(remote_sockaddr,
 696                        "remote_info: Remote sockaddr:");
 697        iwpm_print_sockaddr(mapped_rem_sockaddr,
 698                        "remote_info: Mapped remote sockaddr:");
 699        return ret;
 700}
 701
 702/* netlink attribute policy for the received request for mapping info */
 703static const struct nla_policy resp_mapinfo_policy[IWPM_NLA_MAPINFO_REQ_MAX] = {
 704        [IWPM_NLA_MAPINFO_ULIB_NAME] = { .type = NLA_STRING,
 705                                        .len = IWPM_ULIBNAME_SIZE - 1 },
 706        [IWPM_NLA_MAPINFO_ULIB_VER]  = { .type = NLA_U16 }
 707};
 708
 709/**
 710 * iwpm_mapping_info_cb - Process a notification that the userspace
 711 *                        port mapper daemon is started
 712 * @skb:
 713 * @cb: Contains the received message (payload and netlink header)
 714 *
 715 * Using the received port mapper pid, send all the local mapping
 716 * info records to the userspace port mapper
 717 */
 718int iwpm_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
 719{
 720        struct nlattr *nltb[IWPM_NLA_MAPINFO_REQ_MAX];
 721        const char *msg_type = "Mapping Info response";
 722        u8 nl_client;
 723        char *iwpm_name;
 724        u16 iwpm_version;
 725        int ret = -EINVAL;
 726
 727        if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_REQ_MAX,
 728                                resp_mapinfo_policy, nltb, msg_type)) {
 729                pr_info("%s: Unable to parse nlmsg\n", __func__);
 730                return ret;
 731        }
 732        iwpm_name = (char *)nla_data(nltb[IWPM_NLA_MAPINFO_ULIB_NAME]);
 733        iwpm_version = nla_get_u16(nltb[IWPM_NLA_MAPINFO_ULIB_VER]);
 734        if (strcmp(iwpm_ulib_name, iwpm_name) ||
 735                        iwpm_version < IWPM_UABI_VERSION_MIN) {
 736                pr_info("%s: Invalid port mapper name = %s version = %d\n",
 737                                __func__, iwpm_name, iwpm_version);
 738                return ret;
 739        }
 740        nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
 741        if (!iwpm_valid_client(nl_client)) {
 742                pr_info("%s: Invalid port mapper client = %d\n",
 743                                __func__, nl_client);
 744                return ret;
 745        }
 746        iwpm_set_registration(nl_client, IWPM_REG_INCOMPL);
 747        atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
 748        iwpm_user_pid = cb->nlh->nlmsg_pid;
 749
 750        if (iwpm_ulib_version < IWPM_UABI_VERSION)
 751                pr_warn_once("%s: Down level iwpmd/pid %u.  Continuing...",
 752                        __func__, iwpm_user_pid);
 753
 754        if (!iwpm_mapinfo_available())
 755                return 0;
 756        pr_debug("%s: iWarp Port Mapper (pid = %d) is available!\n",
 757                 __func__, iwpm_user_pid);
 758        ret = iwpm_send_mapinfo(nl_client, iwpm_user_pid);
 759        return ret;
 760}
 761
 762/* netlink attribute policy for the received mapping info ack */
 763static const struct nla_policy ack_mapinfo_policy[IWPM_NLA_MAPINFO_NUM_MAX] = {
 764        [IWPM_NLA_MAPINFO_SEQ]    =   { .type = NLA_U32 },
 765        [IWPM_NLA_MAPINFO_SEND_NUM] = { .type = NLA_U32 },
 766        [IWPM_NLA_MAPINFO_ACK_NUM] =  { .type = NLA_U32 }
 767};
 768
 769/**
 770 * iwpm_ack_mapping_info_cb - Process the port mapper ack for
 771 *                            the provided local mapping info records
 772 * @skb:
 773 * @cb: Contains the received message (payload and netlink header)
 774 */
 775int iwpm_ack_mapping_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
 776{
 777        struct nlattr *nltb[IWPM_NLA_MAPINFO_NUM_MAX];
 778        u32 mapinfo_send, mapinfo_ack;
 779        const char *msg_type = "Mapping Info Ack";
 780
 781        if (iwpm_parse_nlmsg(cb, IWPM_NLA_MAPINFO_NUM_MAX,
 782                                ack_mapinfo_policy, nltb, msg_type))
 783                return -EINVAL;
 784        mapinfo_send = nla_get_u32(nltb[IWPM_NLA_MAPINFO_SEND_NUM]);
 785        mapinfo_ack = nla_get_u32(nltb[IWPM_NLA_MAPINFO_ACK_NUM]);
 786        if (mapinfo_ack != mapinfo_send)
 787                pr_info("%s: Invalid mapinfo number (sent = %u ack-ed = %u)\n",
 788                        __func__, mapinfo_send, mapinfo_ack);
 789        atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
 790        return 0;
 791}
 792
 793/* netlink attribute policy for the received port mapper error message */
 794static const struct nla_policy map_error_policy[IWPM_NLA_ERR_MAX] = {
 795        [IWPM_NLA_ERR_SEQ]        = { .type = NLA_U32 },
 796        [IWPM_NLA_ERR_CODE]       = { .type = NLA_U16 },
 797};
 798
 799/**
 800 * iwpm_mapping_error_cb - Process port mapper notification for error
 801 *
 802 * @skb:
 803 * @cb: Contains the received message (payload and netlink header)
 804 */
 805int iwpm_mapping_error_cb(struct sk_buff *skb, struct netlink_callback *cb)
 806{
 807        struct iwpm_nlmsg_request *nlmsg_request = NULL;
 808        int nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
 809        struct nlattr *nltb[IWPM_NLA_ERR_MAX];
 810        u32 msg_seq;
 811        u16 err_code;
 812        const char *msg_type = "Mapping Error Msg";
 813
 814        if (iwpm_parse_nlmsg(cb, IWPM_NLA_ERR_MAX,
 815                                map_error_policy, nltb, msg_type))
 816                return -EINVAL;
 817
 818        msg_seq = nla_get_u32(nltb[IWPM_NLA_ERR_SEQ]);
 819        err_code = nla_get_u16(nltb[IWPM_NLA_ERR_CODE]);
 820        pr_info("%s: Received msg seq = %u err code = %u client = %d\n",
 821                                __func__, msg_seq, err_code, nl_client);
 822        /* look for nlmsg_request */
 823        nlmsg_request = iwpm_find_nlmsg_request(msg_seq);
 824        if (!nlmsg_request) {
 825                /* not all errors have associated requests */
 826                pr_debug("Could not find matching req (seq = %u)\n", msg_seq);
 827                return 0;
 828        }
 829        atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
 830        nlmsg_request->err_code = err_code;
 831        nlmsg_request->request_done = 1;
 832        /* always for found request */
 833        kref_put(&nlmsg_request->kref, iwpm_free_nlmsg_request);
 834        barrier();
 835        up(&nlmsg_request->sem);
 836        return 0;
 837}
 838
 839/* netlink attribute policy for the received hello request */
 840static const struct nla_policy hello_policy[IWPM_NLA_HELLO_MAX] = {
 841        [IWPM_NLA_HELLO_ABI_VERSION]     = { .type = NLA_U16 }
 842};
 843
 844/**
 845 * iwpm_hello_cb - Process a hello message from iwpmd
 846 *
 847 * @skb:
 848 * @cb: Contains the received message (payload and netlink header)
 849 *
 850 * Using the received port mapper pid, send the kernel's abi_version
 851 * after adjusting it to support the iwpmd version.
 852 */
 853int iwpm_hello_cb(struct sk_buff *skb, struct netlink_callback *cb)
 854{
 855        struct nlattr *nltb[IWPM_NLA_HELLO_MAX];
 856        const char *msg_type = "Hello request";
 857        u8 nl_client;
 858        u16 abi_version;
 859        int ret = -EINVAL;
 860
 861        if (iwpm_parse_nlmsg(cb, IWPM_NLA_HELLO_MAX, hello_policy, nltb,
 862                             msg_type)) {
 863                pr_info("%s: Unable to parse nlmsg\n", __func__);
 864                return ret;
 865        }
 866        abi_version = nla_get_u16(nltb[IWPM_NLA_HELLO_ABI_VERSION]);
 867        nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
 868        if (!iwpm_valid_client(nl_client)) {
 869                pr_info("%s: Invalid port mapper client = %d\n",
 870                                __func__, nl_client);
 871                return ret;
 872        }
 873        iwpm_set_registration(nl_client, IWPM_REG_INCOMPL);
 874        atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
 875        iwpm_ulib_version = min_t(u16, IWPM_UABI_VERSION, abi_version);
 876        pr_debug("Using ABI version %u\n", iwpm_ulib_version);
 877        iwpm_user_pid = cb->nlh->nlmsg_pid;
 878        ret = iwpm_send_hello(nl_client, iwpm_user_pid, iwpm_ulib_version);
 879        return ret;
 880}
 881