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