Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  *  scsi_netlink.c  - SCSI Transport Netlink Interface
  3  *
  4  *  Copyright (C) 2006   James Smart, Emulex Corporation
  5  *
  6  *  This program is free software; you can redistribute it and/or modify
  7  *  it under the terms of the GNU General Public License as published by
  8  *  the Free Software Foundation; either version 2 of the License, or
  9  *  (at your option) any later version.
 10  *
 11  *  This program is distributed in the hope that it will be useful,
 12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14  *  GNU General Public License for more details.
 15  *
 16  *  You should have received a copy of the GNU General Public License
 17  *  along with this program; if not, write to the Free Software
 18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 19  *
 20  */
 21 #include <linux/time.h>
 22 #include <linux/jiffies.h>
 23 #include <linux/security.h>
 24 #include <net/sock.h>
 25 #include <net/netlink.h>
 26 
 27 #include <scsi/scsi_netlink.h>
 28 #include "scsi_priv.h"
 29 
 30 struct sock *scsi_nl_sock = NULL;
 31 EXPORT_SYMBOL_GPL(scsi_nl_sock);
 32 
 33 
 34 /**
 35  * scsi_nl_rcv_msg - Receive message handler.
 36  * @skb:                socket receive buffer
 37  *
 38  * Description: Extracts message from a receive buffer.
 39  *    Validates message header and calls appropriate transport message handler
 40  *
 41  *
 42  **/
 43 static void
 44 scsi_nl_rcv_msg(struct sk_buff *skb)
 45 {
 46         struct nlmsghdr *nlh;
 47         struct scsi_nl_hdr *hdr;
 48         uint32_t rlen;
 49         int err;
 50 
 51         while (skb->len >= NLMSG_SPACE(0)) {
 52                 err = 0;
 53 
 54                 nlh = nlmsg_hdr(skb);
 55                 if ((nlh->nlmsg_len < (sizeof(*nlh) + sizeof(*hdr))) ||
 56                     (skb->len < nlh->nlmsg_len)) {
 57                         printk(KERN_WARNING "%s: discarding partial skb\n",
 58                                  __FUNCTION__);
 59                         return;
 60                 }
 61 
 62                 rlen = NLMSG_ALIGN(nlh->nlmsg_len);
 63                 if (rlen > skb->len)
 64                         rlen = skb->len;
 65 
 66                 if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) {
 67                         err = -EBADMSG;
 68                         return;
 69                 }
 70 
 71                 hdr = NLMSG_DATA(nlh);
 72                 if ((hdr->version != SCSI_NL_VERSION) ||
 73                     (hdr->magic != SCSI_NL_MAGIC)) {
 74                         err = -EPROTOTYPE;
 75                         goto next_msg;
 76                 }
 77 
 78                 if (security_netlink_recv(skb, CAP_SYS_ADMIN)) {
 79                         err = -EPERM;
 80                         goto next_msg;
 81                 }
 82 
 83                 if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) {
 84                         printk(KERN_WARNING "%s: discarding partial message\n",
 85                                  __FUNCTION__);
 86                         return;
 87                 }
 88 
 89                 /*
 90                  * We currently don't support anyone sending us a message
 91                  */
 92 
 93 next_msg:
 94                 if ((err) || (nlh->nlmsg_flags & NLM_F_ACK))
 95                         netlink_ack(skb, nlh, err);
 96 
 97                 skb_pull(skb, rlen);
 98         }
 99 }
100 
101 
102 /**
103  * scsi_nl_rcv_event - Event handler for a netlink socket.
104  * @this:               event notifier block
105  * @event:              event type
106  * @ptr:                event payload
107  *
108  **/
109 static int
110 scsi_nl_rcv_event(struct notifier_block *this, unsigned long event, void *ptr)
111 {
112         struct netlink_notify *n = ptr;
113 
114         if (n->protocol != NETLINK_SCSITRANSPORT)
115                 return NOTIFY_DONE;
116 
117         /*
118          * Currently, we are not tracking PID's, etc. There is nothing
119          * to handle.
120          */
121 
122         return NOTIFY_DONE;
123 }
124 
125 static struct notifier_block scsi_netlink_notifier = {
126         .notifier_call  = scsi_nl_rcv_event,
127 };
128 
129 
130 /**
131  * scsi_netlink_init - Called by SCSI subsystem to intialize the SCSI transport netlink interface
132  *
133  **/
134 void
135 scsi_netlink_init(void)
136 {
137         int error;
138 
139         error = netlink_register_notifier(&scsi_netlink_notifier);
140         if (error) {
141                 printk(KERN_ERR "%s: register of event handler failed - %d\n",
142                                 __FUNCTION__, error);
143                 return;
144         }
145 
146         scsi_nl_sock = netlink_kernel_create(&init_net, NETLINK_SCSITRANSPORT,
147                                 SCSI_NL_GRP_CNT, scsi_nl_rcv_msg, NULL,
148                                 THIS_MODULE);
149         if (!scsi_nl_sock) {
150                 printk(KERN_ERR "%s: register of recieve handler failed\n",
151                                 __FUNCTION__);
152                 netlink_unregister_notifier(&scsi_netlink_notifier);
153         }
154 
155         return;
156 }
157 
158 
159 /**
160  * scsi_netlink_exit - Called by SCSI subsystem to disable the SCSI transport netlink interface
161  *
162  **/
163 void
164 scsi_netlink_exit(void)
165 {
166         if (scsi_nl_sock) {
167                 netlink_kernel_release(scsi_nl_sock);
168                 netlink_unregister_notifier(&scsi_netlink_notifier);
169         }
170 
171         return;
172 }
173 
174 
175 
  This page was automatically generated by the LXR engine.