Home | History | Annotate | Line # | Download | only in iscsid
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