21  *
  22  *      - Neither the name of The Storage Networking Industry Association (SNIA)
  23  *        nor the names of its contributors may be used to endorse or promote
  24  *        products derived from this software without specific prior written
  25  *        permission.
  26  *
  27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  37  * POSSIBILITY OF SUCH DAMAGE.
  38  */
  39 /* Copyright (c) 2007, The Storage Networking Industry Association. */
  40 /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
  41 
  42 #include <sys/types.h>
  43 #include <ctype.h>
  44 #include <errno.h>
  45 #include <fcntl.h>
  46 #include <stdlib.h>
  47 #include "ndmpd_common.h"
  48 #include "ndmpd.h"
  49 #include <string.h>
  50 #include <sys/scsi/impl/uscsi.h>
  51 #include <sys/scsi/scsi.h>
  52 
  53 static void scsi_open_send_reply(ndmp_connection_t *connection, int err);
  54 static void common_open(ndmp_connection_t *connection, char *devname);
  55 static void common_set_target(ndmp_connection_t *connection, char *device,
  56     ushort_t controller, ushort_t sid, ushort_t lun);
  57 
  58 
  59 /*
  60  * ************************************************************************
  61  * NDMP V2 HANDLERS
  62  * ************************************************************************
 
 
  86 /*
  87  * ndmpd_scsi_close_v2
  88  *
  89  * This handler closes the currently open SCSI device.
  90  *
  91  * Parameters:
  92  *   connection (input) - connection handle.
  93  *   body       (input) - request message body.
  94  *
  95  * Returns:
  96  *   void
  97  */
  98 /*ARGSUSED*/
  99 void
 100 ndmpd_scsi_close_v2(ndmp_connection_t *connection, void *body)
 101 {
 102         ndmp_scsi_close_reply reply;
 103         ndmpd_session_t *session = ndmp_get_client_data(connection);
 104 
 105         if (session->ns_scsi.sd_is_open == -1) {
 106                 NDMP_LOG(LOG_ERR, "SCSI device is not open.");
 107                 reply.error = NDMP_DEV_NOT_OPEN_ERR;
 108                 ndmp_send_reply(connection, (void *) &reply,
 109                     "sending scsi_close reply");
 110                 return;
 111         }
 112         (void) ndmp_open_list_del(session->ns_scsi.sd_adapter_name,
 113             session->ns_scsi.sd_sid,
 114             session->ns_scsi.sd_lun);
 115         (void) close(session->ns_scsi.sd_devid);
 116 
 117         session->ns_scsi.sd_is_open = -1;
 118         session->ns_scsi.sd_devid = -1;
 119         session->ns_scsi.sd_sid = 0;
 120         session->ns_scsi.sd_lun = 0;
 121         session->ns_scsi.sd_valid_target_set = FALSE;
 122         (void) memset(session->ns_scsi.sd_adapter_name, 0,
 123             sizeof (session->ns_scsi.sd_adapter_name));
 124 
 125         reply.error = NDMP_NO_ERR;
 126         ndmp_send_reply(connection, (void *) &reply,
 
 209  * This handler resets the currently targeted SCSI device.
 210  *
 211  * Parameters:
 212  *   connection (input) - connection handle.
 213  *   body       (input) - request message body.
 214  *
 215  * Returns:
 216  *   void
 217  */
 218 /*ARGSUSED*/
 219 void
 220 ndmpd_scsi_reset_device_v2(ndmp_connection_t *connection, void *body)
 221 {
 222         ndmp_scsi_reset_device_reply reply;
 223 
 224 
 225         ndmpd_session_t *session = ndmp_get_client_data(connection);
 226         struct uscsi_cmd  cmd;
 227 
 228         if (session->ns_scsi.sd_devid == -1) {
 229                 NDMP_LOG(LOG_ERR, "SCSI device is not open.");
 230                 reply.error = NDMP_DEV_NOT_OPEN_ERR;
 231         } else {
 232                 reply.error = NDMP_NO_ERR;
 233                 (void) memset((void*)&cmd, 0, sizeof (cmd));
 234                 cmd.uscsi_flags |= USCSI_RESET;
 235                 if (ioctl(session->ns_scsi.sd_devid, USCSICMD, &cmd) < 0) {
 236                         NDMP_LOG(LOG_ERR, "USCSI reset failed: %m.");
 237                         NDMP_LOG(LOG_DEBUG,
 238                             "ioctl(USCSICMD) USCSI_RESET failed: %m.");
 239                         reply.error = NDMP_IO_ERR;
 240                 }
 241         }
 242 
 243         ndmp_send_reply(connection, (void *) &reply,
 244             "sending scsi_reset_device reply");
 245 }
 246 
 247 
 248 /*
 249  * ndmpd_scsi_reset_bus_v2
 250  *
 251  * This handler resets the currently targeted SCSI bus.
 252  *
 253  * Request not yet supported.
 254  *
 255  * Parameters:
 256  *   connection (input) - connection handle.
 257  *   body       (input) - request message body.
 258  *
 259  * Returns:
 260  *   void
 261  */
 262 /*ARGSUSED*/
 263 void
 264 ndmpd_scsi_reset_bus_v2(ndmp_connection_t *connection, void *body)
 265 {
 266         ndmp_scsi_reset_bus_reply reply;
 267 
 268         NDMP_LOG(LOG_DEBUG, "request not supported");
 269         reply.error = NDMP_NOT_SUPPORTED_ERR;
 270 
 271         ndmp_send_reply(connection, (void *) &reply,
 272             "sending scsi_reset_bus reply");
 273 }
 274 
 275 
 276 /*
 277  * ndmpd_scsi_execute_cdb_v2
 278  *
 279  * This handler sends the CDB to the currently targeted SCSI device.
 280  *
 281  * Parameters:
 282  *   connection (input) - connection handle.
 283  *   body       (input) - request message body.
 284  *
 285  * Returns:
 286  *   void
 287  */
 288 void
 289 ndmpd_scsi_execute_cdb_v2(ndmp_connection_t *connection, void *body)
 290 {
 291         ndmp_execute_cdb_request *request = (ndmp_execute_cdb_request *) body;
 292         ndmp_execute_cdb_reply reply;
 293         ndmpd_session_t *session = ndmp_get_client_data(connection);
 294 
 295         if (session->ns_scsi.sd_is_open == -1 ||
 296             !session->ns_scsi.sd_valid_target_set) {
 297                 (void) memset((void *) &reply, 0, sizeof (reply));
 298 
 299                 NDMP_LOG(LOG_ERR, "SCSI device is not open.");
 300                 reply.error = NDMP_DEV_NOT_OPEN_ERR;
 301                 ndmp_send_reply(connection, (void *) &reply,
 302                     "sending scsi_execute_cdb reply");
 303         } else {
 304                 ndmp_execute_cdb(session, session->ns_scsi.sd_adapter_name,
 305                     session->ns_scsi.sd_sid, session->ns_scsi.sd_lun, request);
 306         }
 307 }
 308 
 309 
 310 /*
 311  * ************************************************************************
 312  * NDMP V3 HANDLERS
 313  * ************************************************************************
 314  */
 315 
 316 /*
 317  * ndmpd_scsi_open_v3
 318  *
 319  * This handler opens the specified SCSI device.
 
 399 /*
 400  * common_open
 401  *
 402  * Common SCSI open function for all NDMP versions
 403  *
 404  * Parameters:
 405  *   connection (input) - connection handle.
 406  *   devname (input) - device name to open.
 407  *
 408  * Returns:
 409  *   void
 410  */
 411 static void
 412 common_open(ndmp_connection_t *connection, char *devname)
 413 {
 414         ndmpd_session_t *session = ndmp_get_client_data(connection);
 415         char adptnm[SCSI_MAX_NAME];
 416         int sid, lun;
 417         int err;
 418         scsi_adapter_t *sa;
 419         int devid;
 420 
 421         err = NDMP_NO_ERR;
 422 
 423         if (session->ns_tape.td_fd != -1 || session->ns_scsi.sd_is_open != -1) {
 424                 NDMP_LOG(LOG_ERR,
 425                     "Session already has a tape or scsi device open.");
 426                 err = NDMP_DEVICE_OPENED_ERR;
 427         } else if ((sa = scsi_get_adapter(0)) != NULL) {
 428                 NDMP_LOG(LOG_DEBUG, "Adapter device found: %s", devname);
 429                 (void) strlcpy(adptnm, devname, SCSI_MAX_NAME-2);
 430                 adptnm[SCSI_MAX_NAME-1] = '\0';
 431                 sid = lun = -1;
 432 
 433                 scsi_find_sid_lun(sa, devname, &sid, &lun);
 434                 if (ndmp_open_list_find(devname, sid, lun) == NULL &&
 435                     (devid = open(devname, O_RDWR | O_NDELAY)) < 0) {
 436                         NDMP_LOG(LOG_ERR, "Failed to open device %s: %m.",
 437                             devname);
 438                         err = NDMP_NO_DEVICE_ERR;
 439                 }
 440         } else {
 441                 NDMP_LOG(LOG_ERR, "%s: No such SCSI adapter.", devname);
 442                 err = NDMP_NO_DEVICE_ERR;
 443         }
 444 
 445         if (err != NDMP_NO_ERR) {
 446                 scsi_open_send_reply(connection, err);
 447                 return;
 448         }
 449 
 450         switch (ndmp_open_list_add(connection, adptnm, sid, lun, devid)) {
 451         case 0:
 452                 /* OK */
 453                 break;
 454         case EBUSY:
 455                 err = NDMP_DEVICE_BUSY_ERR;
 456                 break;
 457         case ENOMEM:
 458                 err = NDMP_NO_MEM_ERR;
 459                 break;
 460         default:
 461                 err = NDMP_IO_ERR;
 
 495  *
 496  * Returns:
 497  *   0: on success
 498  *  -1: otherwise
 499  */
 500 /*ARGSUSED*/
 501 static void
 502 common_set_target(ndmp_connection_t *connection, char *device,
 503     ushort_t controller, ushort_t sid, ushort_t lun)
 504 {
 505         ndmp_scsi_set_target_reply reply;
 506         ndmpd_session_t *session = ndmp_get_client_data(connection);
 507         int type;
 508 
 509         reply.error = NDMP_NO_ERR;
 510 
 511         if (session->ns_scsi.sd_is_open == -1) {
 512                 reply.error = NDMP_DEV_NOT_OPEN_ERR;
 513         } else if (!scsi_dev_exists(session->ns_scsi.sd_adapter_name, sid,
 514             lun)) {
 515                 NDMP_LOG(LOG_ERR, "No such SCSI device: target %d lun %d.",
 516                     sid, lun);
 517                 reply.error = NDMP_NO_DEVICE_ERR;
 518         } else {
 519                 type = scsi_get_devtype(session->ns_scsi.sd_adapter_name, sid,
 520                     lun);
 521                 if (type != DTYPE_SEQUENTIAL && type != DTYPE_CHANGER) {
 522                         NDMP_LOG(LOG_ERR,
 523                             "Not a tape or robot device: target %d lun %d.",
 524                             sid, lun);
 525                         reply.error = NDMP_ILLEGAL_ARGS_ERR;
 526                 }
 527         }
 528 
 529         if (reply.error != NDMP_NO_ERR) {
 530                 ndmp_send_reply(connection, (void *) &reply,
 531                     "sending scsi_set_target reply");
 532                 return;
 533         }
 534 
 535         /*
 536          * The open_list must be updated if the SID or LUN are going to be
 537          * changed.  Close uses the same SID & LUN for removing the entry
 538          * from the open_list.
 539          */
 540         if (sid != session->ns_scsi.sd_sid || lun != session->ns_scsi.sd_lun) {
 541                 switch (ndmp_open_list_add(connection,
 542                     session->ns_scsi.sd_adapter_name, sid, lun, 0)) {
 543                 case 0:
 544                         (void) ndmp_open_list_del(session->
 545                             ns_scsi.sd_adapter_name, session->ns_scsi.sd_sid,
 546                             session->ns_scsi.sd_lun);
 547                         break;
 548                 case EBUSY:
 549                         reply.error = NDMP_DEVICE_BUSY_ERR;
 550                         break;
 551                 case ENOMEM:
 552                         reply.error = NDMP_NO_MEM_ERR;
 553                         break;
 554                 default:
 555                         reply.error = NDMP_IO_ERR;
 556                 }
 557         }
 558 
 559         if (reply.error == NDMP_NO_ERR) {
 560                 NDMP_LOG(LOG_DEBUG, "Updated sid %d lun %d", sid, lun);
 561                 session->ns_scsi.sd_sid = sid;
 562                 session->ns_scsi.sd_lun = lun;
 563                 session->ns_scsi.sd_valid_target_set = TRUE;
 564         }
 565 
 566         ndmp_send_reply(connection, (void *) &reply,
 567             "sending scsi_set_target reply");
 568 }
 569 
 570 /*
 571  * scsi_find_sid_lun
 572  *
 573  * gets the adapter, and returns the sid and lun number
 574  */
 575 void
 576 scsi_find_sid_lun(scsi_adapter_t *sa, char *devname, int *sid, int *lun)
 577 {
 578         scsi_link_t *sl;
 579         char *name;
 580 
 | 
 
 
  21  *
  22  *      - Neither the name of The Storage Networking Industry Association (SNIA)
  23  *        nor the names of its contributors may be used to endorse or promote
  24  *        products derived from this software without specific prior written
  25  *        permission.
  26  *
  27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  30  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  37  * POSSIBILITY OF SUCH DAMAGE.
  38  */
  39 /* Copyright (c) 2007, The Storage Networking Industry Association. */
  40 /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
  41 /* Copyright 2017 Nexenta Systems, Inc. All rights reserved. */
  42 
  43 #include <sys/types.h>
  44 #include <syslog.h>
  45 #include <ctype.h>
  46 #include <errno.h>
  47 #include <fcntl.h>
  48 #include <stdlib.h>
  49 #include "ndmpd_common.h"
  50 #include "ndmpd.h"
  51 #include <string.h>
  52 #include <sys/scsi/impl/uscsi.h>
  53 #include <sys/scsi/scsi.h>
  54 
  55 static void scsi_open_send_reply(ndmp_connection_t *connection, int err);
  56 static void common_open(ndmp_connection_t *connection, char *devname);
  57 static void common_set_target(ndmp_connection_t *connection, char *device,
  58     ushort_t controller, ushort_t sid, ushort_t lun);
  59 
  60 
  61 /*
  62  * ************************************************************************
  63  * NDMP V2 HANDLERS
  64  * ************************************************************************
 
 
  88 /*
  89  * ndmpd_scsi_close_v2
  90  *
  91  * This handler closes the currently open SCSI device.
  92  *
  93  * Parameters:
  94  *   connection (input) - connection handle.
  95  *   body       (input) - request message body.
  96  *
  97  * Returns:
  98  *   void
  99  */
 100 /*ARGSUSED*/
 101 void
 102 ndmpd_scsi_close_v2(ndmp_connection_t *connection, void *body)
 103 {
 104         ndmp_scsi_close_reply reply;
 105         ndmpd_session_t *session = ndmp_get_client_data(connection);
 106 
 107         if (session->ns_scsi.sd_is_open == -1) {
 108                 syslog(LOG_ERR, "SCSI device is not open.");
 109                 reply.error = NDMP_DEV_NOT_OPEN_ERR;
 110                 ndmp_send_reply(connection, (void *) &reply,
 111                     "sending scsi_close reply");
 112                 return;
 113         }
 114         (void) ndmp_open_list_del(session->ns_scsi.sd_adapter_name,
 115             session->ns_scsi.sd_sid,
 116             session->ns_scsi.sd_lun);
 117         (void) close(session->ns_scsi.sd_devid);
 118 
 119         session->ns_scsi.sd_is_open = -1;
 120         session->ns_scsi.sd_devid = -1;
 121         session->ns_scsi.sd_sid = 0;
 122         session->ns_scsi.sd_lun = 0;
 123         session->ns_scsi.sd_valid_target_set = FALSE;
 124         (void) memset(session->ns_scsi.sd_adapter_name, 0,
 125             sizeof (session->ns_scsi.sd_adapter_name));
 126 
 127         reply.error = NDMP_NO_ERR;
 128         ndmp_send_reply(connection, (void *) &reply,
 
 211  * This handler resets the currently targeted SCSI device.
 212  *
 213  * Parameters:
 214  *   connection (input) - connection handle.
 215  *   body       (input) - request message body.
 216  *
 217  * Returns:
 218  *   void
 219  */
 220 /*ARGSUSED*/
 221 void
 222 ndmpd_scsi_reset_device_v2(ndmp_connection_t *connection, void *body)
 223 {
 224         ndmp_scsi_reset_device_reply reply;
 225 
 226 
 227         ndmpd_session_t *session = ndmp_get_client_data(connection);
 228         struct uscsi_cmd  cmd;
 229 
 230         if (session->ns_scsi.sd_devid == -1) {
 231                 syslog(LOG_ERR, "SCSI device is not open.");
 232                 reply.error = NDMP_DEV_NOT_OPEN_ERR;
 233         } else {
 234                 reply.error = NDMP_NO_ERR;
 235                 (void) memset((void*)&cmd, 0, sizeof (cmd));
 236                 cmd.uscsi_flags |= USCSI_RESET;
 237                 if (ioctl(session->ns_scsi.sd_devid, USCSICMD, &cmd) < 0) {
 238                         syslog(LOG_ERR, "USCSI reset failed: %m.");
 239                         reply.error = NDMP_IO_ERR;
 240                 }
 241         }
 242 
 243         ndmp_send_reply(connection, (void *) &reply,
 244             "sending scsi_reset_device reply");
 245 }
 246 
 247 
 248 /*
 249  * ndmpd_scsi_reset_bus_v2
 250  *
 251  * This handler resets the currently targeted SCSI bus.
 252  *
 253  * Request not yet supported.
 254  *
 255  * Parameters:
 256  *   connection (input) - connection handle.
 257  *   body       (input) - request message body.
 258  *
 259  * Returns:
 260  *   void
 261  */
 262 /*ARGSUSED*/
 263 void
 264 ndmpd_scsi_reset_bus_v2(ndmp_connection_t *connection, void *body)
 265 {
 266         ndmp_scsi_reset_bus_reply reply;
 267 
 268         reply.error = NDMP_NOT_SUPPORTED_ERR;
 269 
 270         ndmp_send_reply(connection, (void *) &reply,
 271             "sending scsi_reset_bus reply");
 272 }
 273 
 274 
 275 /*
 276  * ndmpd_scsi_execute_cdb_v2
 277  *
 278  * This handler sends the CDB to the currently targeted SCSI device.
 279  *
 280  * Parameters:
 281  *   connection (input) - connection handle.
 282  *   body       (input) - request message body.
 283  *
 284  * Returns:
 285  *   void
 286  */
 287 void
 288 ndmpd_scsi_execute_cdb_v2(ndmp_connection_t *connection, void *body)
 289 {
 290         ndmp_execute_cdb_request *request = (ndmp_execute_cdb_request *) body;
 291         ndmp_execute_cdb_reply reply;
 292         ndmpd_session_t *session = ndmp_get_client_data(connection);
 293 
 294         if (session->ns_scsi.sd_is_open == -1 ||
 295             !session->ns_scsi.sd_valid_target_set) {
 296                 (void) memset((void *) &reply, 0, sizeof (reply));
 297 
 298                 reply.error = NDMP_DEV_NOT_OPEN_ERR;
 299                 ndmp_send_reply(connection, (void *) &reply,
 300                     "sending scsi_execute_cdb reply");
 301         } else {
 302                 ndmp_execute_cdb(session, session->ns_scsi.sd_adapter_name,
 303                     session->ns_scsi.sd_sid, session->ns_scsi.sd_lun, request);
 304         }
 305 }
 306 
 307 
 308 /*
 309  * ************************************************************************
 310  * NDMP V3 HANDLERS
 311  * ************************************************************************
 312  */
 313 
 314 /*
 315  * ndmpd_scsi_open_v3
 316  *
 317  * This handler opens the specified SCSI device.
 
 397 /*
 398  * common_open
 399  *
 400  * Common SCSI open function for all NDMP versions
 401  *
 402  * Parameters:
 403  *   connection (input) - connection handle.
 404  *   devname (input) - device name to open.
 405  *
 406  * Returns:
 407  *   void
 408  */
 409 static void
 410 common_open(ndmp_connection_t *connection, char *devname)
 411 {
 412         ndmpd_session_t *session = ndmp_get_client_data(connection);
 413         char adptnm[SCSI_MAX_NAME];
 414         int sid, lun;
 415         int err;
 416         scsi_adapter_t *sa;
 417         int devid = -1;
 418 
 419         err = NDMP_NO_ERR;
 420 
 421         if (session->ns_tape.td_fd != -1 || session->ns_scsi.sd_is_open != -1) {
 422                 err = NDMP_DEVICE_OPENED_ERR;
 423         } else if ((sa = scsi_get_adapter(0)) != NULL) {
 424                 (void) strlcpy(adptnm, devname, SCSI_MAX_NAME-2);
 425                 adptnm[SCSI_MAX_NAME-1] = '\0';
 426                 sid = lun = -1;
 427 
 428                 scsi_find_sid_lun(sa, devname, &sid, &lun);
 429                 if (ndmp_open_list_find(devname, sid, lun) == NULL &&
 430                     (devid = open(devname, O_RDWR | O_NDELAY)) < 0) {
 431                         syslog(LOG_ERR, "Failed to open device %s: %m.",
 432                             devname);
 433                         err = NDMP_NO_DEVICE_ERR;
 434                 }
 435         } else {
 436                 syslog(LOG_ERR, "%s: No such SCSI adapter.", devname);
 437                 err = NDMP_NO_DEVICE_ERR;
 438         }
 439 
 440         if (err != NDMP_NO_ERR) {
 441                 scsi_open_send_reply(connection, err);
 442                 return;
 443         }
 444 
 445         switch (ndmp_open_list_add(connection, adptnm, sid, lun, devid)) {
 446         case 0:
 447                 /* OK */
 448                 break;
 449         case EBUSY:
 450                 err = NDMP_DEVICE_BUSY_ERR;
 451                 break;
 452         case ENOMEM:
 453                 err = NDMP_NO_MEM_ERR;
 454                 break;
 455         default:
 456                 err = NDMP_IO_ERR;
 
 490  *
 491  * Returns:
 492  *   0: on success
 493  *  -1: otherwise
 494  */
 495 /*ARGSUSED*/
 496 static void
 497 common_set_target(ndmp_connection_t *connection, char *device,
 498     ushort_t controller, ushort_t sid, ushort_t lun)
 499 {
 500         ndmp_scsi_set_target_reply reply;
 501         ndmpd_session_t *session = ndmp_get_client_data(connection);
 502         int type;
 503 
 504         reply.error = NDMP_NO_ERR;
 505 
 506         if (session->ns_scsi.sd_is_open == -1) {
 507                 reply.error = NDMP_DEV_NOT_OPEN_ERR;
 508         } else if (!scsi_dev_exists(session->ns_scsi.sd_adapter_name, sid,
 509             lun)) {
 510                 syslog(LOG_ERR, "No such SCSI device: target %d lun %d.",
 511                     sid, lun);
 512                 reply.error = NDMP_NO_DEVICE_ERR;
 513         } else {
 514                 type = scsi_get_devtype(session->ns_scsi.sd_adapter_name, sid,
 515                     lun);
 516                 if (type != DTYPE_SEQUENTIAL && type != DTYPE_CHANGER) {
 517                         syslog(LOG_ERR,
 518                             "Not a tape or robot device: target %d lun %d.",
 519                             sid, lun);
 520                         reply.error = NDMP_ILLEGAL_ARGS_ERR;
 521                 }
 522         }
 523 
 524         if (reply.error != NDMP_NO_ERR) {
 525                 ndmp_send_reply(connection, (void *) &reply,
 526                     "sending scsi_set_target reply");
 527                 return;
 528         }
 529 
 530         /*
 531          * The open_list must be updated if the SID or LUN are going to be
 532          * changed.  Close uses the same SID & LUN for removing the entry
 533          * from the open_list.
 534          */
 535         if (sid != session->ns_scsi.sd_sid || lun != session->ns_scsi.sd_lun) {
 536                 switch (ndmp_open_list_add(connection,
 537                     session->ns_scsi.sd_adapter_name, sid, lun, 0)) {
 538                 case 0:
 539                         (void) ndmp_open_list_del(session->
 540                             ns_scsi.sd_adapter_name, session->ns_scsi.sd_sid,
 541                             session->ns_scsi.sd_lun);
 542                         break;
 543                 case EBUSY:
 544                         reply.error = NDMP_DEVICE_BUSY_ERR;
 545                         break;
 546                 case ENOMEM:
 547                         reply.error = NDMP_NO_MEM_ERR;
 548                         break;
 549                 default:
 550                         reply.error = NDMP_IO_ERR;
 551                 }
 552         }
 553 
 554         if (reply.error == NDMP_NO_ERR) {
 555                 session->ns_scsi.sd_sid = sid;
 556                 session->ns_scsi.sd_lun = lun;
 557                 session->ns_scsi.sd_valid_target_set = TRUE;
 558         }
 559 
 560         ndmp_send_reply(connection, (void *) &reply,
 561             "sending scsi_set_target reply");
 562 }
 563 
 564 /*
 565  * scsi_find_sid_lun
 566  *
 567  * gets the adapter, and returns the sid and lun number
 568  */
 569 void
 570 scsi_find_sid_lun(scsi_adapter_t *sa, char *devname, int *sid, int *lun)
 571 {
 572         scsi_link_t *sl;
 573         char *name;
 574 
 |