1 /* 2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * BSD 3 Clause License 8 * 9 * Copyright (c) 2007, The Storage Networking Industry Association. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * - Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 17 * - Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in 19 * the documentation and/or other materials provided with the 20 * distribution. 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 40 /* This file contains all the door server code */ 41 42 #include <door.h> 43 #include <alloca.h> 44 #include <errno.h> 45 #include <note.h> 46 #include <libintl.h> 47 #include <ndmpd_door.h> 48 #include "ndmpd.h" 49 50 /* static variables */ 51 static int ndmp_door_fildes = -1; 52 static mutex_t ndmp_doorsrv_mutex; 53 54 /* static routines */ 55 static void ndmp_door_server(void *cookie, char *ptr, size_t size, 56 door_desc_t *dp, uint_t n_desc); 57 58 /* 59 * Statistics used in ndmpstat command 60 */ 61 ndmp_stat_t ndstat; 62 63 int 64 ndmp_door_init(void) 65 { 66 int fd; 67 68 (void) mutex_lock(&ndmp_doorsrv_mutex); 69 70 if (ndmp_door_fildes != -1) { 71 NDMP_LOG(LOG_DEBUG, 72 "ndmp_door_init: ndmpd service is already running."); 73 (void) mutex_unlock(&ndmp_doorsrv_mutex); 74 return (0); 75 } 76 77 if ((ndmp_door_fildes = door_create(ndmp_door_server, 78 NULL, DOOR_UNREF)) < 0) { 79 NDMP_LOG(LOG_DEBUG, "ndmp_door_init: Could not create door."); 80 (void) mutex_unlock(&ndmp_doorsrv_mutex); 81 return (-1); 82 } 83 84 (void) unlink(NDMP_DOOR_SVC); 85 86 if ((fd = creat(NDMP_DOOR_SVC, 0444)) < 0) { 87 NDMP_LOG(LOG_DEBUG, "ndmp_door_init: Can't create %s: %m.", 88 NDMP_DOOR_SVC); 89 (void) door_revoke(ndmp_door_fildes); 90 ndmp_door_fildes = -1; 91 (void) mutex_unlock(&ndmp_doorsrv_mutex); 92 return (-1); 93 } 94 95 (void) close(fd); 96 (void) fdetach(NDMP_DOOR_SVC); 97 98 if (fattach(ndmp_door_fildes, NDMP_DOOR_SVC) < 0) { 99 NDMP_LOG(LOG_DEBUG, "ndmp_door_init: fattach failed %m"); 100 (void) door_revoke(ndmp_door_fildes); 101 ndmp_door_fildes = -1; 102 (void) mutex_unlock(&ndmp_doorsrv_mutex); 103 return (-1); 104 } 105 106 NDMP_LOG(LOG_DEBUG, "ndmp_door_init: Door server successfully started"); 107 (void) mutex_unlock(&ndmp_doorsrv_mutex); 108 return (0); 109 } 110 111 void 112 ndmp_door_fini(void) 113 { 114 (void) mutex_lock(&ndmp_doorsrv_mutex); 115 116 if (ndmp_door_fildes != -1) { 117 (void) fdetach(NDMP_DOOR_SVC); 118 (void) door_revoke(ndmp_door_fildes); 119 ndmp_door_fildes = -1; 120 } 121 122 (void) mutex_unlock(&ndmp_doorsrv_mutex); 123 } 124 125 boolean_t 126 ndmp_door_check(void) 127 { 128 door_info_t info; 129 int door; 130 131 if ((door = open(NDMP_DOOR_SVC, O_RDONLY)) < 0) 132 return (0); 133 134 if (door_info(door, &info) < 0) { 135 (void) close(door); 136 return (0); 137 } 138 139 if (info.di_target > 0) { 140 NDMP_LOG(LOG_ERR, 141 "Service already running: pid %ld", info.di_target); 142 (void) close(door); 143 return (1); 144 } 145 146 (void) close(door); 147 return (0); 148 } 149 150 /* door server */ 151 /*ARGSUSED*/ 152 void 153 ndmp_door_server(void *cookie, char *ptr, size_t size, 154 door_desc_t *dp, uint_t n_desc) 155 { 156 NOTE(ARGUNUSED(cookie,dp,n_desc)) 157 int req_type; 158 char *buf; 159 int buflen; 160 unsigned int used; 161 ndmp_door_ctx_t *dec_ctx; 162 ndmp_door_ctx_t *enc_ctx; 163 unsigned int dec_status; 164 unsigned int enc_status; 165 166 dec_ctx = ndmp_door_decode_start(ptr, size); 167 if (dec_ctx == 0) 168 return; 169 170 req_type = ndmp_door_get_uint32(dec_ctx); 171 buflen = NDMP_DOOR_SIZE; 172 173 if ((buf = alloca(buflen)) == NULL) { 174 NDMP_LOG(LOG_DEBUG, "Out of memory."); 175 (void) ndmp_door_decode_finish(dec_ctx); 176 return; 177 } 178 179 enc_ctx = ndmp_door_encode_start(buf, buflen); 180 if (enc_ctx == 0) { 181 (void) ndmp_door_decode_finish(dec_ctx); 182 return; 183 } 184 185 if (req_type != NDMP_GET_STAT) 186 NDMP_LOG(LOG_DEBUG, "ndmp_door_server: req_type=%d", req_type); 187 188 switch (req_type) { 189 case NDMP_GET_DOOR_STATUS: { 190 ndmp_door_put_int32(enc_ctx, NDMP_DOOR_SRV_SUCCESS); 191 break; 192 } 193 case NDMP_DEVICES_GET_INFO: { 194 ndmp_door_put_int32(enc_ctx, NDMP_DOOR_SRV_SUCCESS); 195 ndmpd_get_devs(enc_ctx); 196 break; 197 } 198 case NDMP_SHOW: { 199 ndmp_door_put_int32(enc_ctx, NDMP_DOOR_SRV_SUCCESS); 200 ndmp_connect_list_get(enc_ctx); 201 break; 202 } 203 case NDMP_TERMINATE_SESSION_ID: { 204 int status, id; 205 id = ndmp_door_get_int32(dec_ctx); 206 status = ndmpd_connect_kill_id(id); 207 if (status == -1) /* session not found */ 208 ndmp_door_put_int32(enc_ctx, 209 NDMP_DOOR_SRV_SUCCESS); 210 else 211 ndmp_door_put_int32(enc_ctx, 212 NDMP_DOOR_SRV_SUCCESS); 213 ndmp_door_put_int32(enc_ctx, status); 214 break; 215 } 216 217 case NDMP_GET_STAT: 218 ndmp_door_put_int32(enc_ctx, NDMP_DOOR_SRV_SUCCESS); 219 ndmp_door_put_uint32(enc_ctx, ndstat.ns_trun); 220 ndmp_door_put_uint32(enc_ctx, ndstat.ns_twait); 221 ndmp_door_put_uint32(enc_ctx, ndstat.ns_nbk); 222 ndmp_door_put_uint32(enc_ctx, ndstat.ns_nrs); 223 ndmp_door_put_uint32(enc_ctx, ndstat.ns_rfile); 224 ndmp_door_put_uint32(enc_ctx, ndstat.ns_wfile); 225 ndmp_door_put_uint64(enc_ctx, ndstat.ns_rdisk); 226 ndmp_door_put_uint64(enc_ctx, ndstat.ns_wdisk); 227 ndmp_door_put_uint64(enc_ctx, ndstat.ns_rtape); 228 ndmp_door_put_uint64(enc_ctx, ndstat.ns_wtape); 229 break; 230 231 default: 232 NDMP_LOG(LOG_DEBUG, 233 "ndmp_door_server: Invalid request type 0x%x", req_type); 234 goto decode_error; 235 } 236 237 if ((dec_status = ndmp_door_decode_finish(dec_ctx)) != 0) 238 goto decode_error; 239 240 if ((enc_status = ndmp_door_encode_finish(enc_ctx, &used)) != 0) 241 goto encode_error; 242 243 (void) door_return(buf, used, NULL, 0); 244 245 return; 246 247 decode_error: 248 ndmp_door_put_int32(enc_ctx, NDMP_DOOR_SRV_ERROR); 249 ndmp_door_put_uint32(enc_ctx, dec_status); 250 (void) ndmp_door_encode_finish(enc_ctx, &used); 251 (void) door_return(buf, used, NULL, 0); 252 return; 253 254 encode_error: 255 enc_ctx = ndmp_door_encode_start(buf, buflen); 256 ndmp_door_put_int32(enc_ctx, NDMP_DOOR_SRV_ERROR); 257 ndmp_door_put_uint32(enc_ctx, enc_status); 258 (void) ndmp_door_encode_finish(enc_ctx, &used); 259 (void) door_return(buf, used, NULL, 0); 260 } 261