0001
0002
0003
0004
0005
0006
0007 #include <linux/time.h>
0008 #include <linux/jiffies.h>
0009 #include <linux/security.h>
0010 #include <linux/delay.h>
0011 #include <linux/slab.h>
0012 #include <linux/export.h>
0013 #include <net/sock.h>
0014 #include <net/netlink.h>
0015
0016 #include <scsi/scsi_netlink.h>
0017 #include "scsi_priv.h"
0018
0019 struct sock *scsi_nl_sock = NULL;
0020 EXPORT_SYMBOL_GPL(scsi_nl_sock);
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 static void
0032 scsi_nl_rcv_msg(struct sk_buff *skb)
0033 {
0034 struct nlmsghdr *nlh;
0035 struct scsi_nl_hdr *hdr;
0036 u32 rlen;
0037 int err, tport;
0038
0039 while (skb->len >= NLMSG_HDRLEN) {
0040 err = 0;
0041
0042 nlh = nlmsg_hdr(skb);
0043 if ((nlh->nlmsg_len < (sizeof(*nlh) + sizeof(*hdr))) ||
0044 (skb->len < nlh->nlmsg_len)) {
0045 printk(KERN_WARNING "%s: discarding partial skb\n",
0046 __func__);
0047 return;
0048 }
0049
0050 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
0051 if (rlen > skb->len)
0052 rlen = skb->len;
0053
0054 if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) {
0055 err = -EBADMSG;
0056 goto next_msg;
0057 }
0058
0059 hdr = nlmsg_data(nlh);
0060 if ((hdr->version != SCSI_NL_VERSION) ||
0061 (hdr->magic != SCSI_NL_MAGIC)) {
0062 err = -EPROTOTYPE;
0063 goto next_msg;
0064 }
0065
0066 if (!netlink_capable(skb, CAP_SYS_ADMIN)) {
0067 err = -EPERM;
0068 goto next_msg;
0069 }
0070
0071 if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) {
0072 printk(KERN_WARNING "%s: discarding partial message\n",
0073 __func__);
0074 goto next_msg;
0075 }
0076
0077
0078
0079
0080 tport = hdr->transport;
0081 if (tport == SCSI_NL_TRANSPORT) {
0082 switch (hdr->msgtype) {
0083 case SCSI_NL_SHOST_VENDOR:
0084
0085 err = -ESRCH;
0086 break;
0087 default:
0088 err = -EBADR;
0089 break;
0090 }
0091 if (err)
0092 printk(KERN_WARNING "%s: Msgtype %d failed - err %d\n",
0093 __func__, hdr->msgtype, err);
0094 }
0095 else
0096 err = -ENOENT;
0097
0098 next_msg:
0099 if ((err) || (nlh->nlmsg_flags & NLM_F_ACK))
0100 netlink_ack(skb, nlh, err, NULL);
0101
0102 skb_pull(skb, rlen);
0103 }
0104 }
0105
0106
0107
0108
0109
0110
0111 void
0112 scsi_netlink_init(void)
0113 {
0114 struct netlink_kernel_cfg cfg = {
0115 .input = scsi_nl_rcv_msg,
0116 .groups = SCSI_NL_GRP_CNT,
0117 };
0118
0119 scsi_nl_sock = netlink_kernel_create(&init_net, NETLINK_SCSITRANSPORT,
0120 &cfg);
0121 if (!scsi_nl_sock) {
0122 printk(KERN_ERR "%s: register of receive handler failed\n",
0123 __func__);
0124 return;
0125 }
0126
0127 return;
0128 }
0129
0130
0131
0132
0133
0134
0135 void
0136 scsi_netlink_exit(void)
0137 {
0138 if (scsi_nl_sock) {
0139 netlink_kernel_release(scsi_nl_sock);
0140 }
0141
0142 return;
0143 }
0144