diff options
Diffstat (limited to 'drivers/scsi/scsi_netlink.c')
| -rw-r--r-- | drivers/scsi/scsi_netlink.c | 96 |
1 files changed, 40 insertions, 56 deletions
diff --git a/drivers/scsi/scsi_netlink.c b/drivers/scsi/scsi_netlink.c index 370c78cc1cb..109802f776e 100644 --- a/drivers/scsi/scsi_netlink.c +++ b/drivers/scsi/scsi_netlink.c @@ -21,6 +21,9 @@ #include <linux/time.h> #include <linux/jiffies.h> #include <linux/security.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/export.h> #include <net/sock.h> #include <net/netlink.h> @@ -30,7 +33,6 @@ struct sock *scsi_nl_sock = NULL; EXPORT_SYMBOL_GPL(scsi_nl_sock); - /** * scsi_nl_rcv_msg - Receive message handler. * @skb: socket receive buffer @@ -45,17 +47,17 @@ scsi_nl_rcv_msg(struct sk_buff *skb) { struct nlmsghdr *nlh; struct scsi_nl_hdr *hdr; - uint32_t rlen; - int err; + u32 rlen; + int err, tport; - while (skb->len >= NLMSG_SPACE(0)) { + while (skb->len >= NLMSG_HDRLEN) { err = 0; nlh = nlmsg_hdr(skb); if ((nlh->nlmsg_len < (sizeof(*nlh) + sizeof(*hdr))) || (skb->len < nlh->nlmsg_len)) { printk(KERN_WARNING "%s: discarding partial skb\n", - __FUNCTION__); + __func__); return; } @@ -65,30 +67,47 @@ scsi_nl_rcv_msg(struct sk_buff *skb) if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) { err = -EBADMSG; - return; + goto next_msg; } - hdr = NLMSG_DATA(nlh); + hdr = nlmsg_data(nlh); if ((hdr->version != SCSI_NL_VERSION) || (hdr->magic != SCSI_NL_MAGIC)) { err = -EPROTOTYPE; goto next_msg; } - if (security_netlink_recv(skb, CAP_SYS_ADMIN)) { + if (!netlink_capable(skb, CAP_SYS_ADMIN)) { err = -EPERM; goto next_msg; } if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) { printk(KERN_WARNING "%s: discarding partial message\n", - __FUNCTION__); - return; + __func__); + goto next_msg; } /* - * We currently don't support anyone sending us a message + * Deliver message to the appropriate transport */ + tport = hdr->transport; + if (tport == SCSI_NL_TRANSPORT) { + switch (hdr->msgtype) { + case SCSI_NL_SHOST_VENDOR: + /* Locate the driver that corresponds to the message */ + err = -ESRCH; + break; + default: + err = -EBADR; + break; + } + if (err) + printk(KERN_WARNING "%s: Msgtype %d failed - err %d\n", + __func__, hdr->msgtype, err); + } + else + err = -ENOENT; next_msg: if ((err) || (nlh->nlmsg_flags & NLM_F_ACK)) @@ -98,58 +117,25 @@ next_msg: } } - /** - * scsi_nl_rcv_event - Event handler for a netlink socket. - * @this: event notifier block - * @event: event type - * @ptr: event payload - * - **/ -static int -scsi_nl_rcv_event(struct notifier_block *this, unsigned long event, void *ptr) -{ - struct netlink_notify *n = ptr; - - if (n->protocol != NETLINK_SCSITRANSPORT) - return NOTIFY_DONE; - - /* - * Currently, we are not tracking PID's, etc. There is nothing - * to handle. - */ - - return NOTIFY_DONE; -} - -static struct notifier_block scsi_netlink_notifier = { - .notifier_call = scsi_nl_rcv_event, -}; - - -/** - * scsi_netlink_init - Called by SCSI subsystem to intialize the SCSI transport netlink interface + * scsi_netlink_init - Called by SCSI subsystem to initialize + * the SCSI transport netlink interface * **/ void scsi_netlink_init(void) { - int error; - - error = netlink_register_notifier(&scsi_netlink_notifier); - if (error) { - printk(KERN_ERR "%s: register of event handler failed - %d\n", - __FUNCTION__, error); - return; - } + struct netlink_kernel_cfg cfg = { + .input = scsi_nl_rcv_msg, + .groups = SCSI_NL_GRP_CNT, + }; scsi_nl_sock = netlink_kernel_create(&init_net, NETLINK_SCSITRANSPORT, - SCSI_NL_GRP_CNT, scsi_nl_rcv_msg, NULL, - THIS_MODULE); + &cfg); if (!scsi_nl_sock) { - printk(KERN_ERR "%s: register of recieve handler failed\n", - __FUNCTION__); - netlink_unregister_notifier(&scsi_netlink_notifier); + printk(KERN_ERR "%s: register of receive handler failed\n", + __func__); + return; } return; @@ -165,10 +151,8 @@ scsi_netlink_exit(void) { if (scsi_nl_sock) { netlink_kernel_release(scsi_nl_sock); - netlink_unregister_notifier(&scsi_netlink_notifier); } return; } - |
