root/drivers/scsi/scsi_netlink.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. scsi_nl_rcv_msg
  2. scsi_netlink_init
  3. scsi_netlink_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  scsi_netlink.c  - SCSI Transport Netlink Interface
   4  *
   5  *  Copyright (C) 2006   James Smart, Emulex Corporation
   6  */
   7 #include <linux/time.h>
   8 #include <linux/jiffies.h>
   9 #include <linux/security.h>
  10 #include <linux/delay.h>
  11 #include <linux/slab.h>
  12 #include <linux/export.h>
  13 #include <net/sock.h>
  14 #include <net/netlink.h>
  15 
  16 #include <scsi/scsi_netlink.h>
  17 #include "scsi_priv.h"
  18 
  19 struct sock *scsi_nl_sock = NULL;
  20 EXPORT_SYMBOL_GPL(scsi_nl_sock);
  21 
  22 /**
  23  * scsi_nl_rcv_msg - Receive message handler.
  24  * @skb:                socket receive buffer
  25  *
  26  * Description: Extracts message from a receive buffer.
  27  *    Validates message header and calls appropriate transport message handler
  28  *
  29  *
  30  **/
  31 static void
  32 scsi_nl_rcv_msg(struct sk_buff *skb)
  33 {
  34         struct nlmsghdr *nlh;
  35         struct scsi_nl_hdr *hdr;
  36         u32 rlen;
  37         int err, tport;
  38 
  39         while (skb->len >= NLMSG_HDRLEN) {
  40                 err = 0;
  41 
  42                 nlh = nlmsg_hdr(skb);
  43                 if ((nlh->nlmsg_len < (sizeof(*nlh) + sizeof(*hdr))) ||
  44                     (skb->len < nlh->nlmsg_len)) {
  45                         printk(KERN_WARNING "%s: discarding partial skb\n",
  46                                  __func__);
  47                         return;
  48                 }
  49 
  50                 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
  51                 if (rlen > skb->len)
  52                         rlen = skb->len;
  53 
  54                 if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) {
  55                         err = -EBADMSG;
  56                         goto next_msg;
  57                 }
  58 
  59                 hdr = nlmsg_data(nlh);
  60                 if ((hdr->version != SCSI_NL_VERSION) ||
  61                     (hdr->magic != SCSI_NL_MAGIC)) {
  62                         err = -EPROTOTYPE;
  63                         goto next_msg;
  64                 }
  65 
  66                 if (!netlink_capable(skb, CAP_SYS_ADMIN)) {
  67                         err = -EPERM;
  68                         goto next_msg;
  69                 }
  70 
  71                 if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) {
  72                         printk(KERN_WARNING "%s: discarding partial message\n",
  73                                  __func__);
  74                         goto next_msg;
  75                 }
  76 
  77                 /*
  78                  * Deliver message to the appropriate transport
  79                  */
  80                 tport = hdr->transport;
  81                 if (tport == SCSI_NL_TRANSPORT) {
  82                         switch (hdr->msgtype) {
  83                         case SCSI_NL_SHOST_VENDOR:
  84                                 /* Locate the driver that corresponds to the message */
  85                                 err = -ESRCH;
  86                                 break;
  87                         default:
  88                                 err = -EBADR;
  89                                 break;
  90                         }
  91                         if (err)
  92                                 printk(KERN_WARNING "%s: Msgtype %d failed - err %d\n",
  93                                        __func__, hdr->msgtype, err);
  94                 }
  95                 else
  96                         err = -ENOENT;
  97 
  98 next_msg:
  99                 if ((err) || (nlh->nlmsg_flags & NLM_F_ACK))
 100                         netlink_ack(skb, nlh, err, NULL);
 101 
 102                 skb_pull(skb, rlen);
 103         }
 104 }
 105 
 106 /**
 107  * scsi_netlink_init - Called by SCSI subsystem to initialize
 108  *      the SCSI transport netlink interface
 109  *
 110  **/
 111 void
 112 scsi_netlink_init(void)
 113 {
 114         struct netlink_kernel_cfg cfg = {
 115                 .input  = scsi_nl_rcv_msg,
 116                 .groups = SCSI_NL_GRP_CNT,
 117         };
 118 
 119         scsi_nl_sock = netlink_kernel_create(&init_net, NETLINK_SCSITRANSPORT,
 120                                              &cfg);
 121         if (!scsi_nl_sock) {
 122                 printk(KERN_ERR "%s: register of receive handler failed\n",
 123                                 __func__);
 124                 return;
 125         }
 126 
 127         return;
 128 }
 129 
 130 
 131 /**
 132  * scsi_netlink_exit - Called by SCSI subsystem to disable the SCSI transport netlink interface
 133  *
 134  **/
 135 void
 136 scsi_netlink_exit(void)
 137 {
 138         if (scsi_nl_sock) {
 139                 netlink_kernel_release(scsi_nl_sock);
 140         }
 141 
 142         return;
 143 }
 144 

/* [<][>][^][v][top][bottom][index][help] */