xref: /illumos-gate/usr/src/cmd/ndmpd/ndmp/ndmpd_door.c (revision 674cb4b09c0706bc1cb658e79f39997d43bad8a0)
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