/*ARGSUSED*/ void ndmpd_scsi_close_v2(ndmp_connection_t *connection, void *body) { ndmp_scsi_close_reply reply; ndmpd_session_t *session = ndmp_get_client_data(connection); if (session->ns_scsi.sd_is_open == -1) { syslog(LOG_ERR, "SCSI device is not open."); reply.error = NDMP_DEV_NOT_OPEN_ERR; ndmp_send_reply(connection, (void *) &reply, "sending scsi_close reply"); return; } (void) ndmp_open_list_del(session->ns_scsi.sd_adapter_name, session->ns_scsi.sd_sid, session->ns_scsi.sd_lun); (void) close(session->ns_scsi.sd_devid); session->ns_scsi.sd_is_open = -1; session->ns_scsi.sd_devid = -1; session->ns_scsi.sd_sid = 0; session->ns_scsi.sd_lun = 0; session->ns_scsi.sd_valid_target_set = FALSE; (void) memset(session->ns_scsi.sd_adapter_name, 0, sizeof (session->ns_scsi.sd_adapter_name)); reply.error = NDMP_NO_ERR; ndmp_send_reply(connection, (void *) &reply, "sending scsi_close reply"); }
/* * connection_handler * * NDMP connection handler. * Waits for, reads, and processes NDMP requests on a connection. * * Parameters: * connection (input) - connection handle. * * Return: * void */ void connection_handler(ndmp_connection_t *connection) { static int conn_id = 1; ndmpd_session_t session; ndmp_notify_connected_request req; int connection_fd; (void) memset(&session, 0, sizeof (session)); session.ns_connection = connection; session.ns_eof = FALSE; /* * The 'protocol_version' must be 1 at first, since the client talks * to the server in version 1 then they can move to a higher * protocol version. */ session.ns_protocol_version = ndmp_ver; session.ns_scsi.sd_is_open = -1; session.ns_scsi.sd_devid = -1; session.ns_scsi.sd_sid = 0; session.ns_scsi.sd_lun = 0; session.ns_scsi.sd_valid_target_set = 0; (void) memset(session.ns_scsi.sd_adapter_name, 0, sizeof (session.ns_scsi.sd_adapter_name)); session.ns_tape.td_fd = -1; session.ns_tape.td_sid = 0; session.ns_tape.td_lun = 0; (void) memset(session.ns_tape.td_adapter_name, 0, sizeof (session.ns_tape.td_adapter_name)); session.ns_tape.td_pos = 0; session.ns_tape.td_record_count = 0; session.ns_file_handler_list = 0; (void) ndmpd_data_init(&session); ndmpd_file_history_init(&session); if (ndmpd_mover_init(&session) < 0) return; if (ndmp_lbr_init(&session) < 0) return; /* * Setup defaults here. The init functions can not set defaults * since the init functions are called by the stop request handlers * and client set variables need to persist across data operations. */ session.ns_mover.md_record_size = MAX_RECORD_SIZE; ndmp_set_client_data(connection, (void *)&session); req.reason = NDMP_CONNECTED; req.protocol_version = ndmp_ver; req.text_reason = ""; if (ndmp_send_request_lock(connection, NDMP_NOTIFY_CONNECTION_STATUS, NDMP_NO_ERR, (void *)&req, 0) < 0) { NDMP_LOG(LOG_DEBUG, "Connection terminated"); return; } connection_fd = ndmp_get_fd(connection); NDMP_LOG(LOG_DEBUG, "connection_fd: %d", connection_fd); /* * Add the handler function for the connection to the DMA. */ if (ndmpd_add_file_handler(&session, (void *)&session, connection_fd, NDMPD_SELECT_MODE_READ, HC_CLIENT, connection_file_handler) != 0) { NDMP_LOG(LOG_DEBUG, "Could not register session handler."); return; } /* * Register the connection in the list of active connections. */ if (ndmp_connect_list_add(connection, &conn_id) != 0) { NDMP_LOG(LOG_ERR, "Could not register the session to the server."); (void) ndmpd_remove_file_handler(&session, connection_fd); return; } session.hardlink_q = hardlink_q_init(); while (session.ns_eof == FALSE) (void) ndmpd_select(&session, TRUE, HC_ALL); hardlink_q_cleanup(session.hardlink_q); NDMP_LOG(LOG_DEBUG, "Connection terminated"); (void) ndmpd_remove_file_handler(&session, connection_fd); if (session.ns_scsi.sd_is_open != -1) { NDMP_LOG(LOG_DEBUG, "scsi.is_open: %d", session.ns_scsi.sd_is_open); (void) ndmp_open_list_del(session.ns_scsi.sd_adapter_name, session.ns_scsi.sd_sid, session.ns_scsi.sd_lun); } if (session.ns_tape.td_fd != -1) { NDMP_LOG(LOG_DEBUG, "tape.fd: %d", session.ns_tape.td_fd); (void) close(session.ns_tape.td_fd); (void) ndmp_open_list_del(session.ns_tape.td_adapter_name, session.ns_tape.td_sid, session.ns_tape.td_lun); } ndmpd_mover_shut_down(&session); ndmp_lbr_cleanup(&session); ndmpd_data_cleanup(&session); ndmpd_file_history_cleanup(&session, FALSE); ndmpd_mover_cleanup(&session); (void) ndmp_connect_list_del(connection); }
/*ARGSUSED*/ static void common_set_target(ndmp_connection_t *connection, char *device, ushort_t controller, ushort_t sid, ushort_t lun) { ndmp_scsi_set_target_reply reply; ndmpd_session_t *session = ndmp_get_client_data(connection); int type; reply.error = NDMP_NO_ERR; if (session->ns_scsi.sd_is_open == -1) { reply.error = NDMP_DEV_NOT_OPEN_ERR; } else if (!scsi_dev_exists(session->ns_scsi.sd_adapter_name, sid, lun)) { syslog(LOG_ERR, "No such SCSI device: target %d lun %d.", sid, lun); reply.error = NDMP_NO_DEVICE_ERR; } else { type = scsi_get_devtype(session->ns_scsi.sd_adapter_name, sid, lun); if (type != DTYPE_SEQUENTIAL && type != DTYPE_CHANGER) { syslog(LOG_ERR, "Not a tape or robot device: target %d lun %d.", sid, lun); reply.error = NDMP_ILLEGAL_ARGS_ERR; } } if (reply.error != NDMP_NO_ERR) { ndmp_send_reply(connection, (void *) &reply, "sending scsi_set_target reply"); return; } /* * The open_list must be updated if the SID or LUN are going to be * changed. Close uses the same SID & LUN for removing the entry * from the open_list. */ if (sid != session->ns_scsi.sd_sid || lun != session->ns_scsi.sd_lun) { switch (ndmp_open_list_add(connection, session->ns_scsi.sd_adapter_name, sid, lun, 0)) { case 0: (void) ndmp_open_list_del(session-> ns_scsi.sd_adapter_name, session->ns_scsi.sd_sid, session->ns_scsi.sd_lun); break; case EBUSY: reply.error = NDMP_DEVICE_BUSY_ERR; break; case ENOMEM: reply.error = NDMP_NO_MEM_ERR; break; default: reply.error = NDMP_IO_ERR; } } if (reply.error == NDMP_NO_ERR) { syslog(LOG_DEBUG, "Updated sid %d lun %d", sid, lun); session->ns_scsi.sd_sid = sid; session->ns_scsi.sd_lun = lun; session->ns_scsi.sd_valid_target_set = TRUE; } ndmp_send_reply(connection, (void *) &reply, "sending scsi_set_target reply"); }