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