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 214 * messages 215 * 216 * @skb: socket receive buffer 217 * 218 **/ 219 static int 220 scsi_generic_msg_handler(struct sk_buff *skb) 221 { 222 struct nlmsghdr *nlh = nlmsg_hdr(skb); 223 struct scsi_nl_hdr *snlh = NLMSG_DATA(nlh); 224 struct scsi_nl_drvr *driver; 225 struct Scsi_Host *shost; 226 unsigned long flags; 227 int err = 0, match, pid; 228 229 pid = NETLINK_CREDS(skb)->pid; 230 231 switch (snlh->msgtype) { 232 case SCSI_NL_SHOST_VENDOR: 233 { 234 struct scsi_nl_host_vendor_msg *msg = NLMSG_DATA(nlh); 235 236 /* Locate the driver that corresponds to the message */ 237 spin_lock_irqsave(&scsi_nl_lock, flags); 238 match = 0; 239 list_for_each_entry(driver, &scsi_nl_drivers, next) { 240 if (driver->vendor_id == msg->vendor_id) { 241 match = 1; 242 break; 243 } 244 } 245 246 if ((!match) || (!driver->dmsg_handler)) { 247 spin_unlock_irqrestore(&scsi_nl_lock, flags); 248 err = -ESRCH; 249 goto rcv_exit; 250 } 251 252 if (driver->flags & HANDLER_DELETING) { 253 spin_unlock_irqrestore(&scsi_nl_lock, flags); 254 err = -ESHUTDOWN; 255 goto rcv_exit; 256 } 257 258 driver->refcnt++; 259 spin_unlock_irqrestore(&scsi_nl_lock, flags); 260 261 262 /* if successful, scsi_host_lookup takes a shost reference */ 263 shost = scsi_host_lookup(msg->host_no); 264 if (!shost) { 265 err = -ENODEV; 266 goto driver_exit; 267 } 268 269 /* is this host owned by the vendor ? */ 270 if (shost->hostt != driver->hostt) { 271 err = -EINVAL; 272 goto vendormsg_put; 273 } 274 275 /* pass message on to the driver */ 276 err = driver->dmsg_handler(shost, (void *)&msg[1], 277 msg->vmsg_datalen, pid); 278 279 vendormsg_put: 280 /* release reference by scsi_host_lookup */ 281 scsi_host_put(shost); 282 283 driver_exit: 284 /* release our own reference on the registration object */ 285 spin_lock_irqsave(&scsi_nl_lock, flags); 286 driver->refcnt--; 287 spin_unlock_irqrestore(&scsi_nl_lock, flags); 288 break; 289 } 290 291 default: 292 err = -EBADR; 293 break; 294 } 295 296 rcv_exit: 297 if (err) 298 printk(KERN_WARNING "%s: Msgtype %d failed - err %d\n", 299 __func__, snlh->msgtype, err); 300 return err; 301 } 302 303 304 /** 305 * scsi_nl_add_transport - 306 * Registers message and event handlers for a transport. Enables 307 * receipt of netlink messages and events to a transport. 308 * 309 * @tport: transport registering handlers 310 * @msg_handler: receive message handler callback 311 * @event_handler: receive event handler callback 312 **/ 313 int 314 scsi_nl_add_transport(u8 tport, 315 int (*msg_handler)(struct sk_buff *), 316 void (*event_handler)(struct notifier_block *, unsigned long, void *)) 317 { 318 unsigned long flags; 319 int err = 0; 320 321 if (tport >= SCSI_NL_MAX_TRANSPORTS) 322 return -EINVAL; 323 324 spin_lock_irqsave(&scsi_nl_lock, flags); 325 326 if (scsi_nl_state & STATE_EHANDLER_BSY) { 327 spin_unlock_irqrestore(&scsi_nl_lock, flags); 328 msleep(1); 329 spin_lock_irqsave(&scsi_nl_lock, flags); 330 } 331 332 if (transports[tport].msg_handler || transports[tport].event_handler) { 333 err = -EALREADY; 334 goto register_out; 335 } 336 337 transports[tport].msg_handler = msg_handler; 338 transports[tport].event_handler = event_handler; 339 transports[tport].flags = 0; 340 transports[tport].refcnt = 0; 341 342 register_out: 343 spin_unlock_irqrestore(&scsi_nl_lock, flags); 344 345 return err; 346 } 347 EXPORT_SYMBOL_GPL(scsi_nl_add_transport); 348 349 350 /** 351 * scsi_nl_remove_transport - 352 * Disable transport receiption of messages and events 353 * 354 * @tport: transport deregistering handlers 355 * 356 **/ 357 void 358 scsi_nl_remove_transport(u8 tport) 359 { 360 unsigned long flags; 361 362 spin_lock_irqsave(&scsi_nl_lock, flags); 363 if (scsi_nl_state & STATE_EHANDLER_BSY) { 364 spin_unlock_irqrestore(&scsi_nl_lock, flags); 365 msleep(1); 366 spin_lock_irqsave(&scsi_nl_lock, flags); 367 } 368 369 if (tport < SCSI_NL_MAX_TRANSPORTS) { 370 transports[tport].flags |= HANDLER_DELETING; 371 372 while (transports[tport].refcnt != 0) { 373 spin_unlock_irqrestore(&scsi_nl_lock, flags); 374 schedule_timeout_uninterruptible(HZ/4); 375 spin_lock_irqsave(&scsi_nl_lock, flags); 376 } 377 transports[tport].msg_handler = NULL; 378 transports[tport].event_handler = NULL; 379 transports[tport].flags = 0; 380 } 381 382 spin_unlock_irqrestore(&scsi_nl_lock, flags); 383 384 return; 385 } 386 EXPORT_SYMBOL_GPL(scsi_nl_remove_transport); 387 388 389 /** 390 * scsi_nl_add_driver - 391 * A driver is registering its interfaces for SCSI netlink messages 392 * 393 * @vendor_id: A unique identification value for the driver. 394 * @hostt: address of the driver's host template. Used 395 * to verify an shost is bound to the driver 396 * @nlmsg_handler: receive message handler callback 397 * @nlevt_handler: receive event handler callback 398 * 399 * Returns: 400 * 0 on Success 401 * error result otherwise 402 **/ 403 int 404 scsi_nl_add_driver(u64 vendor_id, struct scsi_host_template *hostt, 405 int (*nlmsg_handler)(struct Scsi_Host *shost, void *payload, 406 u32 len, u32 pid), 407 void (*nlevt_handler)(struct notifier_block *nb, 408 unsigned long event, void *notify_ptr)) 409 { 410 struct scsi_nl_drvr *driver; 411 unsigned long flags; 412 413 driver = kzalloc(sizeof(*driver), GFP_KERNEL); 414 if (unlikely(!driver)) { 415 printk(KERN_ERR "%s: allocation failure\n", __func__); 416 return -ENOMEM; 417 } 418 419 driver->dmsg_handler = nlmsg_handler; 420 driver->devt_handler = nlevt_handler; 421 driver->hostt = hostt; 422 driver->vendor_id = vendor_id; 423 424 spin_lock_irqsave(&scsi_nl_lock, flags); 425 if (scsi_nl_state & STATE_EHANDLER_BSY) { 426 spin_unlock_irqrestore(&scsi_nl_lock, flags); 427 msleep(1); 428 spin_lock_irqsave(&scsi_nl_lock, flags); 429 } 430 list_add_tail(&driver->next, &scsi_nl_drivers); 431 spin_unlock_irqrestore(&scsi_nl_lock, flags); 432 433 return 0; 434 } 435 EXPORT_SYMBOL_GPL(scsi_nl_add_driver); 436 437 438 /** 439 * scsi_nl_remove_driver - 440 * An driver is unregistering with the SCSI netlink messages 441 * 442 * @vendor_id: The unique identification value for the driver. 443 **/ 444 void 445 scsi_nl_remove_driver(u64 vendor_id) 446 { 447 struct scsi_nl_drvr *driver; 448 unsigned long flags; 449 450 spin_lock_irqsave(&scsi_nl_lock, flags); 451 if (scsi_nl_state & STATE_EHANDLER_BSY) { 452 spin_unlock_irqrestore(&scsi_nl_lock, flags); 453 msleep(1); 454 spin_lock_irqsave(&scsi_nl_lock, flags); 455 } 456 457 list_for_each_entry(driver, &scsi_nl_drivers, next) { 458 if (driver->vendor_id == vendor_id) { 459 driver->flags |= HANDLER_DELETING; 460 while (driver->refcnt != 0) { 461 spin_unlock_irqrestore(&scsi_nl_lock, flags); 462 schedule_timeout_uninterruptible(HZ/4); 463 spin_lock_irqsave(&scsi_nl_lock, flags); 464 } 465 list_del(&driver->next); 466 kfree(driver); 467 spin_unlock_irqrestore(&scsi_nl_lock, flags); 468 return; 469 } 470 } 471 472 spin_unlock_irqrestore(&scsi_nl_lock, flags); 473 474 printk(KERN_ERR "%s: removal of driver failed - vendor_id 0x%llx\n", 475 __func__, (unsigned long long)vendor_id); 476 return; 477 } 478 EXPORT_SYMBOL_GPL(scsi_nl_remove_driver); 479 480 481 /** 482 * scsi_netlink_init - Called by SCSI subsystem to intialize 483 * the SCSI transport netlink interface 484 * 485 **/ 486 void 487 scsi_netlink_init(void) 488 { 489 int error; 490 491 INIT_LIST_HEAD(&scsi_nl_drivers); 492 493 error = netlink_register_notifier(&scsi_netlink_notifier); 494 if (error) { 495 printk(KERN_ERR "%s: register of event handler failed - %d\n", 496 __func__, error); 497 return; 498 } 499 500 scsi_nl_sock = netlink_kernel_create(&init_net, NETLINK_SCSITRANSPORT, 501 SCSI_NL_GRP_CNT, scsi_nl_rcv_msg, NULL, 502 THIS_MODULE); 503 if (!scsi_nl_sock) { 504 printk(KERN_ERR "%s: register of recieve handler failed\n", 505 __func__); 506 netlink_unregister_notifier(&scsi_netlink_notifier); 507 return; 508 } 509 510 /* Register the entry points for the generic SCSI transport */ 511 error = scsi_nl_add_transport(SCSI_NL_TRANSPORT, 512 scsi_generic_msg_handler, NULL); 513 if (error) 514 printk(KERN_ERR "%s: register of GENERIC transport handler" 515 " failed - %d\n", __func__, error); 516 return; 517 } 518 519 520 /** 521 * scsi_netlink_exit - Called by SCSI subsystem to disable the SCSI transport netlink interface 522 * 523 **/ 524 void 525 scsi_netlink_exit(void) 526 { 527 scsi_nl_remove_transport(SCSI_NL_TRANSPORT); 528 529 if (scsi_nl_sock) { 530 netlink_kernel_release(scsi_nl_sock); 531 netlink_unregister_notifier(&scsi_netlink_notifier); 532 } 533 534 return; 535 } 536 537 538 /* 539 * Exported Interfaces 540 */ 541 542 /** 543 * scsi_nl_send_transport_msg - 544 * Generic function to send a single message from a SCSI transport to 545 * a single process 546 * 547 * @pid: receiving pid 548 * @hdr: message payload 549 * 550 **/ 551 void 552 scsi_nl_send_transport_msg(u32 pid, struct scsi_nl_hdr *hdr) 553 { 554 struct sk_buff *skb; 555 struct nlmsghdr *nlh; 556 const char *fn; 557 char *datab; 558 u32 len, skblen; 559 int err; 560 561 if (!scsi_nl_sock) { 562 err = -ENOENT; 563 fn = "netlink socket"; 564 goto msg_fail; 565 } 566 567 len = NLMSG_SPACE(hdr->msglen); 568 skblen = NLMSG_SPACE(len); 569 570 skb = alloc_skb(skblen, GFP_KERNEL); 571 if (!skb) { 572 err = -ENOBUFS; 573 fn = "alloc_skb"; 574 goto msg_fail; 575 } 576 577 nlh = nlmsg_put(skb, pid, 0, SCSI_TRANSPORT_MSG, len - sizeof(*nlh), 0); 578 if (!nlh) { 579 err = -ENOBUFS; 580 fn = "nlmsg_put"; 581 goto msg_fail_skb; 582 } 583 datab = NLMSG_DATA(nlh); 584 memcpy(datab, hdr, hdr->msglen); 585 586 err = nlmsg_unicast(scsi_nl_sock, skb, pid); 587 if (err < 0) { 588 fn = "nlmsg_unicast"; 589 /* nlmsg_unicast already kfree_skb'd */ 590 goto msg_fail; 591 } 592 593 return; 594 595 msg_fail_skb: 596 kfree_skb(skb); 597 msg_fail: 598 printk(KERN_WARNING 599 "%s: Dropped Message : pid %d Transport %d, msgtype x%x, " 600 "msglen %d: %s : err %d\n", 601 __func__, pid, hdr->transport, hdr->msgtype, hdr->msglen, 602 fn, err); 603 return; 604 } 605 EXPORT_SYMBOL_GPL(scsi_nl_send_transport_msg); 606 607 608 /** 609 * scsi_nl_send_vendor_msg - called to send a shost vendor unique message 610 * to a specific process id. 611 * 612 * @pid: process id of the receiver 613 * @host_no: host # sending the message 614 * @vendor_id: unique identifier for the driver's vendor 615 * @data_len: amount, in bytes, of vendor unique payload data 616 * @data_buf: pointer to vendor unique data buffer 617 * 618 * Returns: 619 * 0 on succesful return 620 * otherwise, failing error code 621 * 622 * Notes: 623 * This routine assumes no locks are held on entry. 624 */ 625 int 626 scsi_nl_send_vendor_msg(u32 pid, unsigned short host_no, u64 vendor_id, 627 char *data_buf, u32 data_len) 628 { 629 struct sk_buff *skb; 630 struct nlmsghdr *nlh; 631 struct scsi_nl_host_vendor_msg *msg; 632 u32 len, skblen; 633 int err; 634 635 if (!scsi_nl_sock) { 636 err = -ENOENT; 637 goto send_vendor_fail; 638 } 639 640 len = SCSI_NL_MSGALIGN(sizeof(*msg) + data_len); 641 skblen = NLMSG_SPACE(len); 642 643 skb = alloc_skb(skblen, GFP_KERNEL); 644 if (!skb) { 645 err = -ENOBUFS; 646 goto send_vendor_fail; 647 } 648 649 nlh = nlmsg_put(skb, 0, 0, SCSI_TRANSPORT_MSG, 650 skblen - sizeof(*nlh), 0); 651 if (!nlh) { 652 err = -ENOBUFS; 653 goto send_vendor_fail_skb; 654 } 655 msg = NLMSG_DATA(nlh); 656 657 INIT_SCSI_NL_HDR(&msg->snlh, SCSI_NL_TRANSPORT, 658 SCSI_NL_SHOST_VENDOR, len); 659 msg->vendor_id = vendor_id; 660 msg->host_no = host_no; 661 msg->vmsg_datalen = data_len; /* bytes */ 662 memcpy(&msg[1], data_buf, data_len); 663 664 err = nlmsg_unicast(scsi_nl_sock, skb, pid); 665 if (err) 666 /* nlmsg_multicast already kfree_skb'd */ 667 goto send_vendor_fail; 668 669 return 0; 670 671 send_vendor_fail_skb: 672 kfree_skb(skb); 673 send_vendor_fail: 674 printk(KERN_WARNING 675 "%s: Dropped SCSI Msg : host %d vendor_unique - err %d\n", 676 __func__, host_no, err); 677 return err; 678 } 679 EXPORT_SYMBOL(scsi_nl_send_vendor_msg); 680 681 682