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
ndmp_door_init(void)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
ndmp_door_fini(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
ndmp_door_check(void)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
ndmp_door_server(void * cookie,char * ptr,size_t size,door_desc_t * dp,uint_t n_desc)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