iscsid_main.c revision 1.1 1 1.1 agc /* $NetBSD: iscsid_main.c,v 1.1 2011/10/23 21:11:23 agc Exp $ */
2 1.1 agc
3 1.1 agc /*-
4 1.1 agc * Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc.
5 1.1 agc * All rights reserved.
6 1.1 agc *
7 1.1 agc * This code is derived from software contributed to The NetBSD Foundation
8 1.1 agc * by Wasabi Systems, Inc.
9 1.1 agc *
10 1.1 agc * Redistribution and use in source and binary forms, with or without
11 1.1 agc * modification, are permitted provided that the following conditions
12 1.1 agc * are met:
13 1.1 agc * 1. Redistributions of source code must retain the above copyright
14 1.1 agc * notice, this list of conditions and the following disclaimer.
15 1.1 agc * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 agc * notice, this list of conditions and the following disclaimer in the
17 1.1 agc * documentation and/or other materials provided with the distribution.
18 1.1 agc *
19 1.1 agc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 agc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 agc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 agc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 agc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 agc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 agc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 agc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 agc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 agc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 agc * POSSIBILITY OF SUCH DAMAGE.
30 1.1 agc */
31 1.1 agc
32 1.1 agc #include "iscsid_globals.h"
33 1.1 agc
34 1.1 agc #include <sys/types.h>
35 1.1 agc #include <sys/socket.h>
36 1.1 agc #include <sys/un.h>
37 1.1 agc #include <sys/sysctl.h>
38 1.1 agc
39 1.1 agc #include <ctype.h>
40 1.1 agc #include <fcntl.h>
41 1.1 agc
42 1.1 agc #define DEVICE "/dev/iscsi0"
43 1.1 agc
44 1.1 agc /* -------------------------------------------------------------------------- */
45 1.1 agc
46 1.1 agc list_head_t list[NUM_DAEMON_LISTS]; /* the lists this daemon keeps */
47 1.1 agc
48 1.1 agc #ifndef ISCSI_NOTHREAD
49 1.1 agc pthread_mutex_t sesslist_lock; /* session list lock */
50 1.1 agc pthread_t event_thread; /* event thread handle */
51 1.1 agc #endif
52 1.1 agc
53 1.1 agc int driver = -1; /* the driver's file desc */
54 1.1 agc int client_sock; /* the client communication socket */
55 1.1 agc
56 1.1 agc #ifdef ISCSI_DEBUG
57 1.1 agc int debug_level = ISCSI_DEBUG; /* How much info to display */
58 1.1 agc #endif
59 1.1 agc
60 1.1 agc /*
61 1.1 agc To avoid memory fragmentation (and speed things up a bit), we use the
62 1.1 agc static bufs unless the request or response exceeds the buffer size
63 1.1 agc (which it normally shouldn't, assuming we don't have thousands
64 1.1 agc of list entries).
65 1.1 agc */
66 1.1 agc STATIC uint8_t req_buf[REQ_BUFFER_SIZE]; /* default buffer for requests */
67 1.1 agc STATIC uint8_t rsp_buf[RSP_BUFFER_SIZE]; /* default buffer for responses */
68 1.1 agc
69 1.1 agc /* -------------------------------------------------------------------------- */
70 1.1 agc
71 1.1 agc
72 1.1 agc /*
73 1.1 agc * create_node_name:
74 1.1 agc * Create and set default node name.
75 1.1 agc *
76 1.1 agc * Returns 0 on success, else an error code.
77 1.1 agc */
78 1.1 agc
79 1.1 agc STATIC int
80 1.1 agc create_node_name(void)
81 1.1 agc {
82 1.1 agc iscsi_set_node_name_parameters_t snp;
83 1.1 agc uint32_t hid = 0;
84 1.1 agc size_t siz;
85 1.1 agc int mib[2];
86 1.1 agc unsigned char *s;
87 1.1 agc
88 1.1 agc (void) memset(&snp, 0x0, sizeof(snp));
89 1.1 agc mib[0] = CTL_KERN;
90 1.1 agc mib[1] = KERN_HOSTID;
91 1.1 agc siz = sizeof(hid);
92 1.1 agc sysctl(mib, 2, &hid, &siz, NULL, 0);
93 1.1 agc mib[1] = KERN_HOSTNAME;
94 1.1 agc siz = ISCSI_STRING_LENGTH - 45;
95 1.1 agc sysctl(mib, 2, snp.InitiatorAlias, &siz, NULL, 0);
96 1.1 agc
97 1.1 agc DEB(1, ("Host Name: <%s>, Host ID: %u\n", snp.InitiatorAlias, hid));
98 1.1 agc if (!snp.InitiatorAlias[0]) {
99 1.1 agc printf("Warning: iSCSI Node Name not set (No Host Name)!\n");
100 1.1 agc return ISCSID_STATUS_NO_INITIATOR_NAME;
101 1.1 agc }
102 1.1 agc for (s = snp.InitiatorAlias; *s; s++)
103 1.1 agc if (!isalnum((unsigned char) *s) && *s != '-' && *s != '.' && *s != ':')
104 1.1 agc *s = '-';
105 1.1 agc snprintf((char *)snp.InitiatorName, sizeof(snp.InitiatorName),
106 1.1 agc "iqn.1994-04.org.netbsd:iscsi.%s:%u", snp.InitiatorAlias, hid);
107 1.1 agc
108 1.1 agc ioctl(driver, ISCSI_SET_NODE_NAME, &snp);
109 1.1 agc return snp.status;
110 1.1 agc }
111 1.1 agc
112 1.1 agc
113 1.1 agc /*
114 1.1 agc * init_daemon:
115 1.1 agc * Open driver, create communication socket.
116 1.1 agc *
117 1.1 agc * Returns: <0 on error
118 1.1 agc */
119 1.1 agc
120 1.1 agc STATIC int
121 1.1 agc init_daemon(void)
122 1.1 agc {
123 1.1 agc int sock, i;
124 1.1 agc struct sockaddr_un name;
125 1.1 agc iscsid_request_t req;
126 1.1 agc
127 1.1 agc if ((driver = open(DEVICE, O_RDONLY)) < 0) {
128 1.1 agc perror("opening " DEVICE);
129 1.1 agc #ifndef ISCSI_DEBUG /* DEBUG ONLY: Allow daemon to operate w/o driver */
130 1.1 agc return -1;
131 1.1 agc #endif
132 1.1 agc }
133 1.1 agc
134 1.1 agc sock = socket(AF_UNIX, SOCK_DGRAM, 0);
135 1.1 agc if (sock < 0) {
136 1.1 agc perror("opening datagram socket");
137 1.1 agc return -1;
138 1.1 agc }
139 1.1 agc
140 1.1 agc name.sun_family = AF_UNIX;
141 1.1 agc strlcpy(name.sun_path, ISCSID_SOCK_NAME, sizeof(name.sun_path));
142 1.1 agc
143 1.1 agc req.request = ISCSID_DAEMON_TEST;
144 1.1 agc req.parameter_length = 0;
145 1.1 agc
146 1.1 agc i = sendto(sock, &req, sizeof(req), 0, (struct sockaddr *) &name,
147 1.1 agc sizeof(struct sockaddr_un));
148 1.1 agc if (i == sizeof(req)) {
149 1.1 agc printf("Daemon already loaded!\n");
150 1.1 agc close(sock);
151 1.1 agc return -1;
152 1.1 agc }
153 1.1 agc
154 1.1 agc unlink(ISCSID_SOCK_NAME);
155 1.1 agc if (bind(sock, (struct sockaddr *) &name, sizeof(struct sockaddr_un))) {
156 1.1 agc perror("binding name to socket");
157 1.1 agc return -1;
158 1.1 agc }
159 1.1 agc
160 1.1 agc for (i = 0; i < NUM_DAEMON_LISTS; i++) {
161 1.1 agc TAILQ_INIT(&list[i].list);
162 1.1 agc list[i].num_entries = 0;
163 1.1 agc }
164 1.1 agc
165 1.1 agc #ifndef ISCSI_NOTHREAD
166 1.1 agc if ((i = pthread_mutex_init(&sesslist_lock, NULL)) != 0) {
167 1.1 agc printf("Mutex init failed (%d)\n", i);
168 1.1 agc close(sock);
169 1.1 agc return -1;
170 1.1 agc }
171 1.1 agc #endif
172 1.1 agc
173 1.1 agc if (!register_event_handler()) {
174 1.1 agc printf("Couldn't register event handler\n");
175 1.1 agc close(sock);
176 1.1 agc unlink(ISCSID_SOCK_NAME);
177 1.1 agc #ifndef ISCSI_NOTHREAD
178 1.1 agc pthread_mutex_destroy(&sesslist_lock);
179 1.1 agc #endif
180 1.1 agc return -1;
181 1.1 agc }
182 1.1 agc
183 1.1 agc create_node_name();
184 1.1 agc
185 1.1 agc return sock;
186 1.1 agc }
187 1.1 agc
188 1.1 agc
189 1.1 agc /*
190 1.1 agc * make_rsp:
191 1.1 agc * Allocate a response buffer if the static buffer is insufficient, set
192 1.1 agc * the response parameter length.
193 1.1 agc *
194 1.1 agc * Parameter:
195 1.1 agc * len Response parameter size (not counting header)
196 1.1 agc * prsp Pointer to address of response buffer
197 1.1 agc * prsp_temp Will be set to TRUE if buffer was allocated, FALSE
198 1.1 agc * for static buffer.
199 1.1 agc *
200 1.1 agc * Returns: Pointer to response buffer, NULL if allocation failed.
201 1.1 agc */
202 1.1 agc
203 1.1 agc iscsid_response_t *
204 1.1 agc make_rsp(int len, iscsid_response_t ** prsp, int *prsp_temp)
205 1.1 agc {
206 1.1 agc iscsid_response_t *rsp;
207 1.1 agc
208 1.1 agc if ((len + sizeof(iscsid_response_t)) > RSP_BUFFER_SIZE) {
209 1.1 agc if ((rsp = calloc(1, len)) == NULL) {
210 1.1 agc (*prsp)->status = ISCSID_STATUS_NO_RESOURCES;
211 1.1 agc return NULL;
212 1.1 agc }
213 1.1 agc *prsp_temp = TRUE;
214 1.1 agc *prsp = rsp;
215 1.1 agc } else
216 1.1 agc rsp = *prsp;
217 1.1 agc
218 1.1 agc memset (rsp, 0, len + sizeof(iscsid_response_t));
219 1.1 agc rsp->parameter_length = len;
220 1.1 agc return rsp;
221 1.1 agc }
222 1.1 agc
223 1.1 agc
224 1.1 agc /*
225 1.1 agc * process_message:
226 1.1 agc * minimal parameter check and dispatch for the daemon functions.
227 1.1 agc *
228 1.1 agc * Parameter:
229 1.1 agc * req The request
230 1.1 agc * prsp Pointer to address of response buffer
231 1.1 agc * prsp_temp Will be set to TRUE if buffer was allocated, FALSE
232 1.1 agc * for static buffer.
233 1.1 agc */
234 1.1 agc
235 1.1 agc STATIC void
236 1.1 agc process_message(iscsid_request_t *req, iscsid_response_t **prsp, int *prsp_temp)
237 1.1 agc {
238 1.1 agc iscsid_response_t *rsp;
239 1.1 agc
240 1.1 agc *prsp_temp = FALSE;
241 1.1 agc *prsp = rsp = (iscsid_response_t *) rsp_buf;
242 1.1 agc rsp->parameter_length = 0;
243 1.1 agc rsp->status = ISCSID_STATUS_SUCCESS;
244 1.1 agc
245 1.1 agc switch (req->request) {
246 1.1 agc case ISCSID_ADD_TARGET:
247 1.1 agc if (req->parameter_length < sizeof(iscsid_add_target_req_t)) {
248 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
249 1.1 agc break;
250 1.1 agc }
251 1.1 agc add_target((iscsid_add_target_req_t *) req->parameter, prsp, prsp_temp);
252 1.1 agc break;
253 1.1 agc
254 1.1 agc case ISCSID_ADD_PORTAL:
255 1.1 agc if (req->parameter_length != sizeof(iscsid_add_portal_req_t)) {
256 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
257 1.1 agc break;
258 1.1 agc }
259 1.1 agc add_portal((iscsid_add_portal_req_t *) req->parameter, prsp, prsp_temp);
260 1.1 agc break;
261 1.1 agc
262 1.1 agc case ISCSID_SET_TARGET_OPTIONS:
263 1.1 agc if (req->parameter_length != sizeof(iscsid_get_set_target_options_t)) {
264 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
265 1.1 agc break;
266 1.1 agc }
267 1.1 agc rsp->status = set_target_options((iscsid_get_set_target_options_t *)
268 1.1 agc req->parameter);
269 1.1 agc break;
270 1.1 agc
271 1.1 agc case ISCSID_GET_TARGET_OPTIONS:
272 1.1 agc if (req->parameter_length != sizeof(iscsid_sym_id_t)) {
273 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
274 1.1 agc break;
275 1.1 agc }
276 1.1 agc rsp->status = ISCSID_STATUS_NOTIMPL;
277 1.1 agc break;
278 1.1 agc
279 1.1 agc case ISCSID_SET_TARGET_AUTHENTICATION:
280 1.1 agc if (req->parameter_length !=
281 1.1 agc sizeof(iscsid_set_target_authentication_req_t)) {
282 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
283 1.1 agc break;
284 1.1 agc }
285 1.1 agc rsp->status = set_target_auth((iscsid_set_target_authentication_req_t *)
286 1.1 agc req->parameter);
287 1.1 agc break;
288 1.1 agc
289 1.1 agc case ISCSID_SLP_FIND_TARGETS:
290 1.1 agc rsp->status = ISCSID_STATUS_NOTIMPL;
291 1.1 agc break;
292 1.1 agc
293 1.1 agc case ISCSID_REFRESH_TARGETS:
294 1.1 agc if (req->parameter_length < sizeof(iscsid_refresh_req_t)) {
295 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
296 1.1 agc break;
297 1.1 agc }
298 1.1 agc rsp->status = refresh_targets((iscsid_refresh_req_t *) req->parameter);
299 1.1 agc break;
300 1.1 agc
301 1.1 agc case ISCSID_REMOVE_TARGET:
302 1.1 agc if (req->parameter_length != sizeof(iscsid_list_id_t)) {
303 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
304 1.1 agc break;
305 1.1 agc }
306 1.1 agc rsp->status = remove_target((iscsid_list_id_t *) req->parameter);
307 1.1 agc break;
308 1.1 agc
309 1.1 agc case ISCSID_SEARCH_LIST:
310 1.1 agc if (req->parameter_length != sizeof(iscsid_search_list_req_t)) {
311 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
312 1.1 agc break;
313 1.1 agc }
314 1.1 agc search_list((iscsid_search_list_req_t *) req->parameter,
315 1.1 agc prsp, prsp_temp);
316 1.1 agc break;
317 1.1 agc
318 1.1 agc case ISCSID_GET_LIST:
319 1.1 agc if (req->parameter_length != sizeof(iscsid_get_list_req_t)) {
320 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
321 1.1 agc break;
322 1.1 agc }
323 1.1 agc get_list((iscsid_get_list_req_t *) req->parameter, prsp, prsp_temp);
324 1.1 agc break;
325 1.1 agc
326 1.1 agc case ISCSID_GET_TARGET_INFO:
327 1.1 agc if (req->parameter_length != sizeof(iscsid_list_id_t)) {
328 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
329 1.1 agc break;
330 1.1 agc }
331 1.1 agc get_target_info((iscsid_list_id_t *) req->parameter, prsp, prsp_temp);
332 1.1 agc break;
333 1.1 agc
334 1.1 agc case ISCSID_GET_PORTAL_INFO:
335 1.1 agc if (req->parameter_length != sizeof(iscsid_list_id_t)) {
336 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
337 1.1 agc break;
338 1.1 agc }
339 1.1 agc get_portal_info((iscsid_list_id_t *) req->parameter, prsp, prsp_temp);
340 1.1 agc break;
341 1.1 agc
342 1.1 agc #ifndef ISCSI_MINIMAL
343 1.1 agc case ISCSID_ADD_ISNS_SERVER:
344 1.1 agc if (req->parameter_length != sizeof(iscsid_add_isns_server_req_t)) {
345 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
346 1.1 agc break;
347 1.1 agc }
348 1.1 agc add_isns_server((iscsid_add_isns_server_req_t *) req->parameter,
349 1.1 agc prsp, prsp_temp);
350 1.1 agc break;
351 1.1 agc
352 1.1 agc case ISCSID_GET_ISNS_SERVER:
353 1.1 agc if (req->parameter_length != sizeof(iscsid_sym_id_t)) {
354 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
355 1.1 agc break;
356 1.1 agc }
357 1.1 agc get_isns_server((iscsid_sym_id_t *) req->parameter, prsp, prsp_temp);
358 1.1 agc break;
359 1.1 agc
360 1.1 agc case ISCSID_SLP_FIND_ISNS_SERVERS:
361 1.1 agc rsp->status = ISCSID_STATUS_NOTIMPL;
362 1.1 agc break;
363 1.1 agc
364 1.1 agc case ISCSID_REMOVE_ISNS_SERVER:
365 1.1 agc if (req->parameter_length != sizeof(iscsid_sym_id_t)) {
366 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
367 1.1 agc break;
368 1.1 agc }
369 1.1 agc rsp->status = remove_isns_server((iscsid_sym_id_t *) req->parameter);
370 1.1 agc break;
371 1.1 agc #endif
372 1.1 agc
373 1.1 agc case ISCSID_ADD_INITIATOR_PORTAL:
374 1.1 agc if (req->parameter_length != sizeof(iscsid_add_initiator_req_t)) {
375 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
376 1.1 agc break;
377 1.1 agc }
378 1.1 agc add_initiator_portal((iscsid_add_initiator_req_t *) req->parameter,
379 1.1 agc prsp, prsp_temp);
380 1.1 agc break;
381 1.1 agc
382 1.1 agc case ISCSID_GET_INITIATOR_PORTAL:
383 1.1 agc if (req->parameter_length != sizeof(iscsid_sym_id_t)) {
384 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
385 1.1 agc break;
386 1.1 agc }
387 1.1 agc get_initiator_portal((iscsid_sym_id_t *) req->parameter,
388 1.1 agc prsp, prsp_temp);
389 1.1 agc break;
390 1.1 agc
391 1.1 agc case ISCSID_REMOVE_INITIATOR_PORTAL:
392 1.1 agc if (req->parameter_length != sizeof(iscsid_sym_id_t)) {
393 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
394 1.1 agc break;
395 1.1 agc }
396 1.1 agc rsp->status = remove_initiator_portal((iscsid_sym_id_t *)
397 1.1 agc req->parameter);
398 1.1 agc break;
399 1.1 agc
400 1.1 agc case ISCSID_LOGIN:
401 1.1 agc if (req->parameter_length != sizeof(iscsid_login_req_t)) {
402 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
403 1.1 agc break;
404 1.1 agc }
405 1.1 agc login((iscsid_login_req_t *) req->parameter, rsp);
406 1.1 agc break;
407 1.1 agc
408 1.1 agc case ISCSID_ADD_CONNECTION:
409 1.1 agc if (req->parameter_length != sizeof(iscsid_login_req_t)) {
410 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
411 1.1 agc break;
412 1.1 agc }
413 1.1 agc add_connection((iscsid_login_req_t *) req->parameter, rsp);
414 1.1 agc break;
415 1.1 agc
416 1.1 agc case ISCSID_LOGOUT:
417 1.1 agc if (req->parameter_length != sizeof(iscsid_sym_id_t)) {
418 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
419 1.1 agc break;
420 1.1 agc }
421 1.1 agc rsp->status = logout((iscsid_sym_id_t *) req->parameter);
422 1.1 agc break;
423 1.1 agc
424 1.1 agc case ISCSID_REMOVE_CONNECTION:
425 1.1 agc if (req->parameter_length != sizeof(iscsid_remove_connection_req_t)) {
426 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
427 1.1 agc break;
428 1.1 agc }
429 1.1 agc rsp->status = remove_connection((iscsid_remove_connection_req_t *)
430 1.1 agc req->parameter);
431 1.1 agc break;
432 1.1 agc
433 1.1 agc case ISCSID_GET_SESSION_LIST:
434 1.1 agc get_session_list(prsp, prsp_temp);
435 1.1 agc break;
436 1.1 agc
437 1.1 agc case ISCSID_GET_CONNECTION_LIST:
438 1.1 agc if (req->parameter_length != sizeof(iscsid_sym_id_t)) {
439 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
440 1.1 agc break;
441 1.1 agc }
442 1.1 agc get_connection_list((iscsid_sym_id_t *) req->parameter,
443 1.1 agc prsp, prsp_temp);
444 1.1 agc break;
445 1.1 agc
446 1.1 agc case ISCSID_GET_CONNECTION_INFO:
447 1.1 agc if (req->parameter_length != sizeof(iscsid_get_connection_info_req_t)) {
448 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
449 1.1 agc break;
450 1.1 agc }
451 1.1 agc get_connection_info((iscsid_get_connection_info_req_t *) req->parameter,
452 1.1 agc prsp, prsp_temp);
453 1.1 agc break;
454 1.1 agc
455 1.1 agc case ISCSID_SET_NODE_NAME:
456 1.1 agc if (req->parameter_length != sizeof(iscsid_set_node_name_req_t)) {
457 1.1 agc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
458 1.1 agc break;
459 1.1 agc }
460 1.1 agc rsp->status = set_node_name((iscsid_set_node_name_req_t *)
461 1.1 agc req->parameter);
462 1.1 agc break;
463 1.1 agc
464 1.1 agc case ISCSID_GET_VERSION:
465 1.1 agc get_version(prsp, prsp_temp);
466 1.1 agc break;
467 1.1 agc
468 1.1 agc default:
469 1.1 agc rsp->status = ISCSID_STATUS_INVALID_REQUEST;
470 1.1 agc break;
471 1.1 agc }
472 1.1 agc }
473 1.1 agc
474 1.1 agc
475 1.1 agc /*
476 1.1 agc * exit_daemon:
477 1.1 agc * Deregister the event handler, deregister isns servers, then exit program.
478 1.1 agc */
479 1.1 agc
480 1.1 agc void
481 1.1 agc exit_daemon(void)
482 1.1 agc {
483 1.1 agc #ifndef ISCSI_NOTHREAD
484 1.1 agc LOCK_SESSIONS;
485 1.1 agc #endif
486 1.1 agc deregister_event_handler();
487 1.1 agc
488 1.1 agc #ifndef ISCSI_MINIMAL
489 1.1 agc dereg_all_isns_servers();
490 1.1 agc #endif
491 1.1 agc
492 1.1 agc printf("iSCSI Daemon Exits\n");
493 1.1 agc exit(0);
494 1.1 agc }
495 1.1 agc
496 1.1 agc
497 1.1 agc /*
498 1.1 agc * main:
499 1.1 agc * init, go daemon, then loop reading requests, processing them,
500 1.1 agc * and sending responses.
501 1.1 agc * Stops on receiving a terminate message (no response to that one is sent),
502 1.1 agc * or when an error occurs reading or writing the socket.
503 1.1 agc *
504 1.1 agc * Parameter: argc, argv currently ignored.
505 1.1 agc */
506 1.1 agc
507 1.1 agc int
508 1.1 agc main(int argc, char **argv)
509 1.1 agc {
510 1.1 agc int req_temp, rsp_temp;
511 1.1 agc int ret, len;
512 1.1 agc struct sockaddr_un from;
513 1.1 agc socklen_t fromlen;
514 1.1 agc iscsid_request_t *req;
515 1.1 agc iscsid_response_t *rsp;
516 1.1 agc #ifdef ISCSI_NOTHREAD
517 1.1 agc struct timeval seltout = { 2, 0 }; /* 2 second poll interval */
518 1.1 agc #endif
519 1.1 agc
520 1.1 agc client_sock = init_daemon();
521 1.1 agc if (client_sock < 0)
522 1.1 agc exit(1);
523 1.1 agc
524 1.1 agc printf("iSCSI Daemon loaded\n");
525 1.1 agc
526 1.1 agc daemon(0, 1);
527 1.1 agc
528 1.1 agc #ifndef ISCSI_NOTHREAD
529 1.1 agc ret = pthread_create(&event_thread, NULL, event_handler, NULL);
530 1.1 agc if (ret) {
531 1.1 agc printf("Thread creation failed (%d)\n", ret);
532 1.1 agc close(client_sock);
533 1.1 agc unlink(ISCSID_SOCK_NAME);
534 1.1 agc deregister_event_handler();
535 1.1 agc pthread_mutex_destroy(&sesslist_lock);
536 1.1 agc return -1;
537 1.1 agc }
538 1.1 agc #else
539 1.1 agc setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO, &seltout, sizeof(seltout));
540 1.1 agc #endif
541 1.1 agc
542 1.1 agc /* ---------------------------------------------------------------------- */
543 1.1 agc
544 1.1 agc for (;;) {
545 1.1 agc /* First, get size of request */
546 1.1 agc req = (iscsid_request_t *) req_buf;
547 1.1 agc fromlen = sizeof(from);
548 1.1 agc len = sizeof(iscsid_request_t);
549 1.1 agc
550 1.1 agc #ifdef ISCSI_NOTHREAD
551 1.1 agc do {
552 1.1 agc ret = recvfrom(client_sock, req, len, MSG_PEEK | MSG_WAITALL,
553 1.1 agc (struct sockaddr *) &from, &fromlen);
554 1.1 agc if (ret == -1)
555 1.1 agc event_handler(NULL);
556 1.1 agc } while (ret == -1 && errno == EAGAIN);
557 1.1 agc #else
558 1.1 agc ret = recvfrom(client_sock, req, len, MSG_PEEK | MSG_WAITALL,
559 1.1 agc (struct sockaddr *) &from, &fromlen);
560 1.1 agc #endif
561 1.1 agc
562 1.1 agc if (ret != len) {
563 1.1 agc perror("Receiving from socket");
564 1.1 agc break;
565 1.1 agc }
566 1.1 agc DEB(99, ("Request %d, parlen %d\n",
567 1.1 agc req->request, req->parameter_length));
568 1.1 agc
569 1.1 agc len += req->parameter_length;
570 1.1 agc
571 1.1 agc /* now that we know the size, get the buffer for it */
572 1.1 agc req_temp = (len > REQ_BUFFER_SIZE);
573 1.1 agc
574 1.1 agc if (req_temp) {
575 1.1 agc req = malloc(len);
576 1.1 agc if (!req) {
577 1.1 agc printf("Can't alloc %d bytes\n", len);
578 1.1 agc break;
579 1.1 agc }
580 1.1 agc }
581 1.1 agc /* read the complete request */
582 1.1 agc fromlen = sizeof(from);
583 1.1 agc ret = recvfrom(client_sock, req, len, MSG_WAITALL,
584 1.1 agc (struct sockaddr *) &from, &fromlen);
585 1.1 agc if (ret != len) {
586 1.1 agc DEBOUT(("Error receiving from socket!\n"));
587 1.1 agc if (req_temp)
588 1.1 agc free(req);
589 1.1 agc continue;
590 1.1 agc }
591 1.1 agc /* terminate? then go die. */
592 1.1 agc if (req->request == ISCSID_DAEMON_TERMINATE)
593 1.1 agc break;
594 1.1 agc
595 1.1 agc /* No reply required to test message */
596 1.1 agc if (req->request == ISCSID_DAEMON_TEST) {
597 1.1 agc if (req_temp)
598 1.1 agc free(req);
599 1.1 agc continue;
600 1.1 agc }
601 1.1 agc /* no return path? then we can't send a reply, */
602 1.1 agc /* so don't process the command */
603 1.1 agc if (!from.sun_path[0]) {
604 1.1 agc DEBOUT(("No Return Address!\n"));
605 1.1 agc continue;
606 1.1 agc }
607 1.1 agc /* process the request */
608 1.1 agc process_message(req, &rsp, &rsp_temp);
609 1.1 agc if (rsp == NULL)
610 1.1 agc break;
611 1.1 agc
612 1.1 agc DEB(99, ("Sending reply: status %d, len %d\n",
613 1.1 agc rsp->status, rsp->parameter_length));
614 1.1 agc
615 1.1 agc /* send the response */
616 1.1 agc len = sizeof(iscsid_response_t) + rsp->parameter_length;
617 1.1 agc ret = sendto(client_sock, rsp, len, 0,
618 1.1 agc (struct sockaddr *) &from, fromlen);
619 1.1 agc if (len != ret) {
620 1.1 agc DEBOUT(("Error sending reply!\n"));
621 1.1 agc }
622 1.1 agc /* free temp buffers if we needed them */
623 1.1 agc if (req_temp)
624 1.1 agc free(req);
625 1.1 agc if (rsp_temp)
626 1.1 agc free(rsp);
627 1.1 agc }
628 1.1 agc
629 1.1 agc exit_daemon();
630 1.1 agc
631 1.1 agc /* we never get here */
632 1.1 agc return 0;
633 1.1 agc }
634