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 <linux/delay.h> 25 #include <net/sock.h> 26 #include <net/netlink.h> 27 28 #include <scsi/scsi_netlink.h> 29 #include "scsi_priv.h" 30 31 struct sock *scsi_nl_sock = NULL; 32 EXPORT_SYMBOL_GPL(scsi_nl_sock); 33 34 static DEFINE_SPINLOCK(scsi_nl_lock); 35 static struct list_head scsi_nl_drivers; 36 37 static u32 scsi_nl_state; 38 #define STATE_EHANDLER_BSY 0x00000001 39 40 struct scsi_nl_transport { 41 int (*msg_handler)(struct sk_buff *); 42 void (*event_handler)(struct notifier_block *, unsigned long, void *); 43 unsigned int refcnt; 44 int flags; 45 }; 46 47 /* flags values (bit flags) */ 48 #define HANDLER_DELETING 0x1 49 50 static struct scsi_nl_transport transports[SCSI_NL_MAX_TRANSPORTS] = 51 { {NULL, }, }; 52 53 54 struct scsi_nl_drvr { 55 struct list_head next; 56 int (*dmsg_handler)(struct Scsi_Host *shost, void *payload, 57 u32 len, u32 pid); 58 void (*devt_handler)(struct notifier_block *nb, 59 unsigned long event, void *notify_ptr); 60 struct scsi_host_template *hostt; 61 u64 vendor_id; 62 unsigned int refcnt; 63 int flags; 64 }; 65 66 67 68 /** 69 * scsi_nl_rcv_msg - Receive message handler. 70 * @skb: socket receive buffer 71 * 72 * Description: Extracts message from a receive buffer. 73 * Validates message header and calls appropriate transport message handler 74 * 75 * 76 **/ 77 static void 78 scsi_nl_rcv_msg(struct sk_buff *skb) 79 { 80 struct nlmsghdr *nlh; 81 struct scsi_nl_hdr *hdr; 82 unsigned long flags; 83 u32 rlen; 84 int err, tport; 85 86 while (skb->len >= NLMSG_SPACE(0)) { 87 err = 0; 88 89 nlh = nlmsg_hdr(skb); 90 if ((nlh->nlmsg_len < (sizeof(*nlh) + sizeof(*hdr))) || 91 (skb->len < nlh->nlmsg_len)) { 92 printk(KERN_WARNING "%s: discarding partial skb\n", 93 __func__); 94 return; 95 } 96 97 rlen = NLMSG_ALIGN(nlh->nlmsg_len); 98 if (rlen > skb->len) 99 rlen = skb->len; 100 101 if (nlh->nlmsg_type != SCSI_TRANSPORT_MSG) { 102 err = -EBADMSG; 103 goto next_msg; 104 } 105 106 hdr = NLMSG_DATA(nlh); 107 if ((hdr->version != SCSI_NL_VERSION) || 108 (hdr->magic != SCSI_NL_MAGIC)) { 109 err = -EPROTOTYPE; 110 goto next_msg; 111 } 112 113 if (security_netlink_recv(skb, CAP_SYS_ADMIN)) { 114 err = -EPERM; 115 goto next_msg; 116 } 117 118 if (nlh->nlmsg_len < (sizeof(*nlh) + hdr->msglen)) { 119 printk(KERN_WARNING "%s: discarding partial message\n", 120 __func__); 121 goto next_msg; 122 } 123 124 /* 125 * Deliver message to the appropriate transport 126 */ 127 spin_lock_irqsave(&scsi_nl_lock, flags); 128 129 tport = hdr->transport; 130 if ((tport < SCSI_NL_MAX_TRANSPORTS) && 131 !(transports[tport].flags & HANDLER_DELETING) && 132 (transports[tport].msg_handler)) { 133 transports[tport].refcnt++; 134 spin_unlock_irqrestore(&scsi_nl_lock, flags); 135 err = transports[tport].msg_handler(skb); 136 spin_lock_irqsave(&scsi_nl_lock, flags); 137 transports[tport].refcnt--; 138 } else 139 err = -ENOENT; 140 141 spin_unlock_irqrestore(&scsi_nl_lock, flags); 142 143 next_msg: 144 if ((err) || (nlh->nlmsg_flags & NLM_F_ACK)) 145 netlink_ack(skb, nlh, err); 146 147 skb_pull(skb, rlen); 148 } 149 } 150 151 152 /** 153 * scsi_nl_rcv_event - Event handler for a netlink socket. 154 * @this: event notifier block 155 * @event: event type 156 * @ptr: event payload 157 * 158 **/ 159 static int 160 scsi_nl_rcv_event(struct notifier_block *this, unsigned long event, void *ptr) 161 { 162 struct netlink_notify *n = ptr; 163 struct scsi_nl_drvr *driver; 164 unsigned long flags; 165 int tport; 166 167 if (n->protocol != NETLINK_SCSITRANSPORT) 168 return NOTIFY_DONE; 169 170 spin_lock_irqsave(&scsi_nl_lock, flags); 171 scsi_nl_state |= STATE_EHANDLER_BSY; 172 173 /* 174 * Pass event on to any transports that may be listening 175 */ 176 for (tport = 0; tport < SCSI_NL_MAX_TRANSPORTS; tport++) { 177 if (!(transports[tport].flags & HANDLER_DELETING) && 178 (transports[tport].event_handler)) { 179 spin_unlock_irqrestore(&scsi_nl_lock, flags); 180 transports[tport].event_handler(this, event, ptr); 181 spin_lock_irqsave(&scsi_nl_lock, flags); 182 } 183 } 184 185 /* 186 * Pass event on to any drivers that may be listening 187 */ 188 list_for_each_entry(driver, &scsi_nl_drivers, next) { 189 if (!(driver->flags & HANDLER_DELETING) && 190 (driver->devt_handler)) { 191 spin_unlock_irqrestore(&scsi_nl_lock, flags); 192 driver->devt_handler(this, event, ptr); 193 spin_lock_irqsave(&scsi_nl_lock, flags); 194 } 195 } 196 197 scsi_nl_state &= ~STATE_EHANDLER_BSY; 198 spin_unlock_irqrestore(&scsi_nl_lock, flags); 199 200 return NOTIFY_DONE; 201 } 202 203 static struct notifier_block scsi_netlink_notifier = { 204 .notifier_call = scsi_nl_rcv_event, 205 }; 206 207 208 /* 209 * GENERIC SCSI transport receive and event handlers 210 */ 211 212 /** 213 * scsi_generic_msg_handler - receive message handler for GENERIC transport messages 214 * @skb: socket receive buffer 215 **/ 216 static int 217 scsi_generic_msg_handler(struct sk_buff *skb) 218 { 219 struct nlmsghdr *nlh = nlmsg_hdr(skb); 220 struct scsi_nl_hdr *snlh = NLMSG_DATA(nlh); 221 struct scsi_nl_drvr *driver; 222 struct Scsi_Host *shost; 223 unsigned long flags; 224 int err = 0, match, pid; 225 226 pid = NETLINK_CREDS(skb)->pid; 227 228 switch (snlh->msgtype) { 229 case SCSI_NL_SHOST_VENDOR: 230 { 231 struct scsi_nl_host_vendor_msg *msg = NLMSG_DATA(nlh); 232 233 /* Locate the driver that corresponds to the message */ 234 spin_lock_irqsave(&scsi_nl_lock, flags); 235 match = 0; 236 list_for_each_entry(driver, &scsi_nl_drivers, next) { 237 if (driver->vendor_id == msg->vendor_id) { 238 match = 1; 239 break; 240 } 241 } 242 243 if ((!match) || (!driver->dmsg_handler)) { 244 spin_unlock_irqrestore(&scsi_nl_lock, flags); 245 err = -ESRCH; 246 goto rcv_exit; 247 } 248 249 if (driver->flags & HANDLER_DELETING) { 250 spin_unlock_irqrestore(&scsi_nl_lock, flags); 251 err = -ESHUTDOWN; 252 goto rcv_exit; 253 } 254 255 driver->refcnt++; 256 spin_unlock_irqrestore(&scsi_nl_lock, flags); 257 258 259 /* if successful, scsi_host_lookup takes a shost reference */ 260 shost = scsi_host_lookup(msg->host_no); 261 if (!shost) { 262 err = -ENODEV; 263 goto driver_exit; 264 } 265 266 /* is this host owned by the vendor ? */ 267 if (shost->hostt != driver->hostt) { 268 err = -EINVAL; 269 goto vendormsg_put; 270 } 271 272 /* pass message on to the driver */ 273 err = driver->dmsg_handler(shost, (void *)&msg[1], 274 msg->vmsg_datalen, pid); 275 276 vendormsg_put: 277 /* release reference by scsi_host_lookup */ 278 scsi_host_put(shost); 279 280 driver_exit: 281 /* release our own reference on the registration object */ 282 spin_lock_irqsave(&scsi_nl_lock, flags); 283 driver->refcnt--; 284 spin_unlock_irqrestore(&scsi_nl_lock, flags); 285 break; 286 } 287 288 default: 289 err = -EBADR; 290 break; 291 } 292 293 rcv_exit: 294 if (err) 295 printk(KERN_WARNING "%s: Msgtype %d failed - err %d\n", 296 __func__, snlh->msgtype, err); 297 return err; 298 } 299 300 301 /** 302 * scsi_nl_add_transport - 303 * Registers message and event handlers for a transport. Enables 304 * receipt of netlink messages and events to a transport. 305 * 306 * @tport: transport registering handlers 307 * @msg_handler: receive message handler callback 308 * @event_handler: receive event handler callback 309 **/ 310 int 311 scsi_nl_add_transport(u8 tport, 312 int (*msg_handler)(struct sk_buff *), 313 void (*event_handler)(struct notifier_block *, unsigned long, void *)) 314 { 315 unsigned long flags; 316 int err = 0; 317 318 if (tport >= SCSI_NL_MAX_TRANSPORTS) 319 return -EINVAL; 320 321 spin_lock_irqsave(&scsi_nl_lock, flags); 322 323 if (scsi_nl_state & STATE_EHANDLER_BSY) { 324 spin_unlock_irqrestore(&scsi_nl_lock, flags); 325 msleep(1); 326 spin_lock_irqsave(&scsi_nl_lock, flags); 327 } 328 329 if (transports[tport].msg_handler || transports[tport].event_handler) { 330 err = -EALREADY; 331 goto register_out; 332 } 333 334 transports[tport].msg_handler = msg_handler; 335 transports[tport].event_handler = event_handler; 336 transports[tport].flags = 0; 337 transports[tport].refcnt = 0; 338 339 register_out: 340 spin_unlock_irqrestore(&scsi_nl_lock, flags); 341 342 return err; 343 } 344 EXPORT_SYMBOL_GPL(scsi_nl_add_transport); 345 346 347 /** 348 * scsi_nl_remove_transport - 349 * Disable transport receiption of messages and events 350 * 351 * @tport: transport deregistering handlers 352 * 353 **/ 354 void 355 scsi_nl_remove_transport(u8 tport) 356 { 357 unsigned long flags; 358 359 spin_lock_irqsave(&scsi_nl_lock, flags); 360 if (scsi_nl_state & STATE_EHANDLER_BSY) { 361 spin_unlock_irqrestore(&scsi_nl_lock, flags); 362 msleep(1); 363 spin_lock_irqsave(&scsi_nl_lock, flags); 364 } 365 366 if (tport < SCSI_NL_MAX_TRANSPORTS) { 367 transports[tport].flags |= HANDLER_DELETING; 368 369 while (transports[tport].refcnt != 0) { 370 spin_unlock_irqrestore(&scsi_nl_lock, flags); 371 schedule_timeout_uninterruptible(HZ/4); 372 spin_lock_irqsave(&scsi_nl_lock, flags); 373 } 374 transports[tport].msg_handler = NULL; 375 transports[tport].event_handler = NULL; 376 transports[tport].flags = 0; 377 } 378 379 spin_unlock_irqrestore(&scsi_nl_lock, flags); 380 381 return; 382 } 383 EXPORT_SYMBOL_GPL(scsi_nl_remove_transport); 384 385 386 /** 387 * scsi_nl_add_driver - 388 * A driver is registering its interfaces for SCSI netlink messages 389 * 390 * @vendor_id: A unique identification value for the driver. 391 * @hostt: address of the driver's host template. Used 392 * to verify an shost is bound to the driver 393 * @nlmsg_handler: receive message handler callback 394 * @nlevt_handler: receive event handler callback 395 * 396 * Returns: 397 * 0 on Success 398 * error result otherwise 399 **/ 400 int 401 scsi_nl_add_driver(u64 vendor_id, struct scsi_host_template *hostt, 402 int (*nlmsg_handler)(struct Scsi_Host *shost, void *payload, 403 u32 len, u32 pid), 404 void (*nlevt_handler)(struct notifier_block *nb, 405 unsigned long event, void *notify_ptr)) 406 { 407 struct scsi_nl_drvr *driver; 408 unsigned long flags; 409 410 driver = kzalloc(sizeof(*driver), GFP_KERNEL); 411 if (unlikely(!driver)) { 412 printk(KERN_ERR "%s: allocation failure\n", __func__); 413 return -ENOMEM; 414 } 415 416 driver->dmsg_handler = nlmsg_handler; 417 driver->devt_handler = nlevt_handler; 418 driver->hostt = hostt; 419 driver->vendor_id = vendor_id; 420 421 spin_lock_irqsave(&scsi_nl_lock, flags); 422 if (scsi_nl_state & STATE_EHANDLER_BSY) { 423 spin_unlock_irqrestore(&scsi_nl_lock, flags); 424 msleep(1); 425 spin_lock_irqsave(&scsi_nl_lock, flags); 426 } 427 list_add_tail(&driver->next, &scsi_nl_drivers); 428 spin_unlock_irqrestore(&scsi_nl_lock, flags); 429 430 return 0; 431 } 432 EXPORT_SYMBOL_GPL(scsi_nl_add_driver); 433 434 435 /** 436 * scsi_nl_remove_driver - 437 * An driver is unregistering with the SCSI netlink messages 438 * 439 * @vendor_id: The unique identification value for the driver. 440 **/ 441 void 442 scsi_nl_remove_driver(u64 vendor_id) 443 { 444 struct scsi_nl_drvr *driver; 445 unsigned long flags; 446 447 spin_lock_irqsave(&scsi_nl_lock, flags); 448 if (scsi_nl_state & STATE_EHANDLER_BSY) { 449 spin_unlock_irqrestore(&scsi_nl_lock, flags); 450 msleep(1); 451 spin_lock_irqsave(&scsi_nl_lock, flags); 452 } 453 454 list_for_each_entry(driver, &scsi_nl_drivers, next) { 455 if (driver->vendor_id == vendor_id) { 456 driver->flags |= HANDLER_DELETING; 457 while (driver->refcnt != 0) { 458 spin_unlock_irqrestore(&scsi_nl_lock, flags); 459 schedule_timeout_uninterruptible(HZ/4); 460 spin_lock_irqsave(&scsi_nl_lock, flags); 461 } 462 list_del(&driver->next); 463 kfree(driver); 464 spin_unlock_irqrestore(&scsi_nl_lock, flags); 465 return; 466 } 467 } 468 469 spin_unlock_irqrestore(&scsi_nl_lock, flags); 470 471 printk(KERN_ERR "%s: removal of driver failed - vendor_id 0x%llx\n", 472 __func__, (unsigned long long)vendor_id); 473 return; 474 } 475 EXPORT_SYMBOL_GPL(scsi_nl_remove_driver); 476 477 478 /** 479 * scsi_netlink_init - Called by SCSI subsystem to intialize 480 * the SCSI transport netlink interface 481 * 482 **/ 483 void 484 scsi_netlink_init(void) 485 { 486 int error; 487 488 INIT_LIST_HEAD(&scsi_nl_drivers); 489 490 error = netlink_register_notifier(&scsi_netlink_notifier); 491 if (error) { 492 printk(KERN_ERR "%s: register of event handler failed - %d\n", 493 __func__, error); 494 return; 495 } 496 497 scsi_nl_sock = netlink_kernel_create(&init_net, NETLINK_SCSITRANSPORT, 498 SCSI_NL_GRP_CNT, scsi_nl_rcv_msg, NULL, 499 THIS_MODULE); 500 if (!scsi_nl_sock) { 501 printk(KERN_ERR "%s: register of recieve handler failed\n", 502 __func__); 503 netlink_unregister_notifier(&scsi_netlink_notifier); 504 return; 505 } 506 507 /* Register the entry points for the generic SCSI transport */ 508 error = scsi_nl_add_transport(SCSI_NL_TRANSPORT, 509 scsi_generic_msg_handler, NULL); 510 if (error) 511 printk(KERN_ERR "%s: register of GENERIC transport handler" 512 " failed - %d\n", __func__, error); 513 return; 514 } 515 516 517 /** 518 * scsi_netlink_exit - Called by SCSI subsystem to disable the SCSI transport netlink interface 519 * 520 **/ 521 void 522 scsi_netlink_exit(void) 523 { 524 scsi_nl_remove_transport(SCSI_NL_TRANSPORT); 525 526 if (scsi_nl_sock) { 527 netlink_kernel_release(scsi_nl_sock); 528 netlink_unregister_notifier(&scsi_netlink_notifier); 529 } 530 531 return; 532 } 533 534 535 /* 536 * Exported Interfaces 537 */ 538 539 /** 540 * scsi_nl_send_transport_msg - 541 * Generic function to send a single message from a SCSI transport to 542 * a single process 543 * 544 * @pid: receiving pid 545 * @hdr: message payload 546 * 547 **/ 548 void 549 scsi_nl_send_transport_msg(u32 pid, struct scsi_nl_hdr *hdr) 550 { 551 struct sk_buff *skb; 552 struct nlmsghdr *nlh; 553 const char *fn; 554 char *datab; 555 u32 len, skblen; 556 int err; 557 558 if (!scsi_nl_sock) { 559 err = -ENOENT; 560 fn = "netlink socket"; 561 goto msg_fail; 562 } 563 564 len = NLMSG_SPACE(hdr->msglen); 565 skblen = NLMSG_SPACE(len); 566 567 skb = alloc_skb(skblen, GFP_KERNEL); 568 if (!skb) { 569 err = -ENOBUFS; 570 fn = "alloc_skb"; 571 goto msg_fail; 572 } 573 574 nlh = nlmsg_put(skb, pid, 0, SCSI_TRANSPORT_MSG, len - sizeof(*nlh), 0); 575 if (!nlh) { 576 err = -ENOBUFS; 577 fn = "nlmsg_put"; 578 goto msg_fail_skb; 579 } 580 datab = NLMSG_DATA(nlh); 581 memcpy(datab, hdr, hdr->msglen); 582 583 err = nlmsg_unicast(scsi_nl_sock, skb, pid); 584 if (err < 0) { 585 fn = "nlmsg_unicast"; 586 /* nlmsg_unicast already kfree_skb'd */ 587 goto msg_fail; 588 } 589 590 return; 591 592 msg_fail_skb: 593 kfree_skb(skb); 594 msg_fail: 595 printk(KERN_WARNING 596 "%s: Dropped Message : pid %d Transport %d, msgtype x%x, " 597 "msglen %d: %s : err %d\n", 598 __func__, pid, hdr->transport, hdr->msgtype, hdr->msglen, 599 fn, err); 600 return; 601 } 602 EXPORT_SYMBOL_GPL(scsi_nl_send_transport_msg); 603 604 605 /** 606 * scsi_nl_send_vendor_msg - called to send a shost vendor unique message 607 * to a specific process id. 608 * 609 * @pid: process id of the receiver 610 * @host_no: host # sending the message 611 * @vendor_id: unique identifier for the driver's vendor 612 * @data_len: amount, in bytes, of vendor unique payload data 613 * @data_buf: pointer to vendor unique data buffer 614 * 615 * Returns: 616 * 0 on succesful return 617 * otherwise, failing error code 618 * 619 * Notes: 620 * This routine assumes no locks are held on entry. 621 */ 622 int 623 scsi_nl_send_vendor_msg(u32 pid, unsigned short host_no, u64 vendor_id, 624 char *data_buf, u32 data_len) 625 { 626 struct sk_buff *skb; 627 struct nlmsghdr *nlh; 628 struct scsi_nl_host_vendor_msg *msg; 629 u32 len, skblen; 630 int err; 631 632 if (!scsi_nl_sock) { 633 err = -ENOENT; 634 goto send_vendor_fail; 635 } 636 637 len = SCSI_NL_MSGALIGN(sizeof(*msg) + data_len); 638 skblen = NLMSG_SPACE(len); 639 640 skb = alloc_skb(skblen, GFP_KERNEL); 641 if (!skb) { 642 err = -ENOBUFS; 643 goto send_vendor_fail; 644 } 645 646 nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, 647 skblen - sizeof(*nlh), 0); 648 if (!nlh) { 649 err = -ENOBUFS; 650 goto send_vendor_fail_skb; 651 } 652 msg = NLMSG_DATA(nlh); 653 654 INIT_SCSI_NL_HDR(&msg->snlh, SCSI_NL_TRANSPORT, 655 SCSI_NL_SHOST_VENDOR, len); 656 msg->vendor_id = vendor_id; 657 msg->host_no = host_no; 658 msg->vmsg_datalen = data_len; /* bytes */ 659 memcpy(&msg[1], data_buf, data_len); 660 661 err = nlmsg_unicast(scsi_nl_sock, skb, pid); 662 if (err) 663 /* nlmsg_multicast already kfree_skb'd */ 664 goto send_vendor_fail; 665 666 return 0; 667 668 send_vendor_fail_skb: 669 kfree_skb(skb); 670 send_vendor_fail: 671 printk(KERN_WARNING 672 "%s: Dropped SCSI Msg : host %d vendor_unique - err %d\n", 673 __func__, host_no, err); 674 return err; 675 } 676 EXPORT_SYMBOL(scsi_nl_send_vendor_msg); 677 678 679