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