1*82974f22Smrg /* $NetBSD: iscsid_main.c,v 1.12 2019/02/04 08:21:12 mrg Exp $ */
275a17f3cSagc
375a17f3cSagc /*-
475a17f3cSagc * Copyright (c) 2005,2006,2011 The NetBSD Foundation, Inc.
575a17f3cSagc * All rights reserved.
675a17f3cSagc *
775a17f3cSagc * This code is derived from software contributed to The NetBSD Foundation
875a17f3cSagc * by Wasabi Systems, Inc.
975a17f3cSagc *
1075a17f3cSagc * Redistribution and use in source and binary forms, with or without
1175a17f3cSagc * modification, are permitted provided that the following conditions
1275a17f3cSagc * are met:
1375a17f3cSagc * 1. Redistributions of source code must retain the above copyright
1475a17f3cSagc * notice, this list of conditions and the following disclaimer.
1575a17f3cSagc * 2. Redistributions in binary form must reproduce the above copyright
1675a17f3cSagc * notice, this list of conditions and the following disclaimer in the
1775a17f3cSagc * documentation and/or other materials provided with the distribution.
1875a17f3cSagc *
1975a17f3cSagc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2075a17f3cSagc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2175a17f3cSagc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2275a17f3cSagc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2375a17f3cSagc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2475a17f3cSagc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2575a17f3cSagc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2675a17f3cSagc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2775a17f3cSagc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2875a17f3cSagc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2975a17f3cSagc * POSSIBILITY OF SUCH DAMAGE.
3075a17f3cSagc */
3175a17f3cSagc
3275a17f3cSagc #include "iscsid_globals.h"
3375a17f3cSagc
3475a17f3cSagc #include <sys/types.h>
3575a17f3cSagc #include <sys/socket.h>
3675a17f3cSagc #include <sys/un.h>
3775a17f3cSagc #include <sys/sysctl.h>
3875a17f3cSagc
3975a17f3cSagc #include <ctype.h>
40c08d1e52Sriz #include <err.h>
4175a17f3cSagc #include <fcntl.h>
426fea88c2Smlelstv #include <syslog.h>
436fea88c2Smlelstv #include <util.h>
4475a17f3cSagc
4575a17f3cSagc #define DEVICE "/dev/iscsi0"
4675a17f3cSagc
4775a17f3cSagc /* -------------------------------------------------------------------------- */
4875a17f3cSagc
4975a17f3cSagc list_head_t list[NUM_DAEMON_LISTS]; /* the lists this daemon keeps */
5075a17f3cSagc
5175a17f3cSagc pthread_mutex_t sesslist_lock; /* session list lock */
526fea88c2Smlelstv pthread_t main_thread; /* main thread handle */
5375a17f3cSagc pthread_t event_thread; /* event thread handle */
5475a17f3cSagc
5575a17f3cSagc int driver = -1; /* the driver's file desc */
5675a17f3cSagc int client_sock; /* the client communication socket */
5775a17f3cSagc
58e85ef03bSjoerg int debug_level; /* How much info to display */
596fea88c2Smlelstv int debugging;
6075a17f3cSagc
6175a17f3cSagc /*
6275a17f3cSagc To avoid memory fragmentation (and speed things up a bit), we use the
6375a17f3cSagc static bufs unless the request or response exceeds the buffer size
6475a17f3cSagc (which it normally shouldn't, assuming we don't have thousands
6575a17f3cSagc of list entries).
6675a17f3cSagc */
6738a27f5aSagc static uint8_t req_buf[REQ_BUFFER_SIZE]; /* default buffer for requests */
6838a27f5aSagc static uint8_t rsp_buf[RSP_BUFFER_SIZE]; /* default buffer for responses */
6975a17f3cSagc
7075a17f3cSagc /* -------------------------------------------------------------------------- */
7175a17f3cSagc
7268a964c3Schristos static void __dead
usage(void)7368a964c3Schristos usage(void)
7468a964c3Schristos {
75c08d1e52Sriz fprintf(stderr, "Usage: %s [-d <lvl>] [-n]\n", getprogname());
7668a964c3Schristos exit(EXIT_FAILURE);
7768a964c3Schristos }
7868a964c3Schristos
7975a17f3cSagc /*
8075a17f3cSagc * create_node_name:
8175a17f3cSagc * Create and set default node name.
8275a17f3cSagc *
8375a17f3cSagc * Returns 0 on success, else an error code.
8475a17f3cSagc */
8575a17f3cSagc
8638a27f5aSagc static int
create_node_name(void)8775a17f3cSagc create_node_name(void)
8875a17f3cSagc {
8975a17f3cSagc iscsi_set_node_name_parameters_t snp;
9075a17f3cSagc uint32_t hid = 0;
9175a17f3cSagc size_t siz;
9275a17f3cSagc int mib[2];
93*82974f22Smrg int total;
9475a17f3cSagc unsigned char *s;
9575a17f3cSagc
9675a17f3cSagc (void) memset(&snp, 0x0, sizeof(snp));
9775a17f3cSagc mib[0] = CTL_KERN;
9875a17f3cSagc mib[1] = KERN_HOSTID;
9975a17f3cSagc siz = sizeof(hid);
10075a17f3cSagc sysctl(mib, 2, &hid, &siz, NULL, 0);
10175a17f3cSagc mib[1] = KERN_HOSTNAME;
10275a17f3cSagc siz = ISCSI_STRING_LENGTH - 45;
10375a17f3cSagc sysctl(mib, 2, snp.InitiatorAlias, &siz, NULL, 0);
10475a17f3cSagc
1056fea88c2Smlelstv DEB(3, ("Host Name: <%s>, Host ID: %u", snp.InitiatorAlias, hid));
10675a17f3cSagc if (!snp.InitiatorAlias[0]) {
10775a17f3cSagc printf("Warning: iSCSI Node Name not set (No Host Name)!\n");
10875a17f3cSagc return ISCSID_STATUS_NO_INITIATOR_NAME;
10975a17f3cSagc }
11075a17f3cSagc for (s = snp.InitiatorAlias; *s; s++)
11175a17f3cSagc if (!isalnum((unsigned char) *s) && *s != '-' && *s != '.' && *s != ':')
11275a17f3cSagc *s = '-';
113*82974f22Smrg total = snprintf((char *)snp.InitiatorName, sizeof(snp.InitiatorName),
11475a17f3cSagc "iqn.1994-04.org.netbsd:iscsi.%s:%u", snp.InitiatorAlias, hid);
115*82974f22Smrg if ((size_t)total > sizeof(snp.InitiatorName)) {
116*82974f22Smrg printf("Warning: iSCSI Node InitiatorName too long to set InitiatorAlias!\n");
117*82974f22Smrg return ISCSID_STATUS_NO_INITIATOR_NAME;
118*82974f22Smrg }
11975a17f3cSagc
12075a17f3cSagc ioctl(driver, ISCSI_SET_NODE_NAME, &snp);
12175a17f3cSagc return snp.status;
12275a17f3cSagc }
12375a17f3cSagc
12475a17f3cSagc
12575a17f3cSagc /*
12675a17f3cSagc * init_daemon:
12775a17f3cSagc * Open driver, create communication socket.
12875a17f3cSagc *
12975a17f3cSagc * Returns: <0 on error
13075a17f3cSagc */
13175a17f3cSagc
13238a27f5aSagc static int
init_daemon(void)13375a17f3cSagc init_daemon(void)
13475a17f3cSagc {
13575a17f3cSagc int sock, i;
13675a17f3cSagc struct sockaddr_un name;
13775a17f3cSagc iscsid_request_t req;
13875a17f3cSagc
13975a17f3cSagc if ((driver = open(DEVICE, O_RDONLY)) < 0) {
14075a17f3cSagc perror("opening " DEVICE);
14175a17f3cSagc return -1;
14275a17f3cSagc }
14375a17f3cSagc
14475a17f3cSagc sock = socket(AF_UNIX, SOCK_DGRAM, 0);
14575a17f3cSagc if (sock < 0) {
14675a17f3cSagc perror("opening datagram socket");
14775a17f3cSagc return -1;
14875a17f3cSagc }
14975a17f3cSagc
15075a17f3cSagc name.sun_family = AF_UNIX;
15175a17f3cSagc strlcpy(name.sun_path, ISCSID_SOCK_NAME, sizeof(name.sun_path));
15275a17f3cSagc
15375a17f3cSagc req.request = ISCSID_DAEMON_TEST;
15475a17f3cSagc req.parameter_length = 0;
15575a17f3cSagc
156f7720048Schristos i = sendto(sock, &req, sizeof(req), 0, (struct sockaddr *)(void *)&name,
157f7720048Schristos (socklen_t)sizeof(struct sockaddr_un));
15875a17f3cSagc if (i == sizeof(req)) {
15975a17f3cSagc printf("Daemon already loaded!\n");
16075a17f3cSagc close(sock);
16175a17f3cSagc return -1;
16275a17f3cSagc }
16375a17f3cSagc
16475a17f3cSagc unlink(ISCSID_SOCK_NAME);
165f7720048Schristos if (bind(sock, (struct sockaddr *)(void *)&name, (socklen_t)sizeof(struct sockaddr_un))) {
16675a17f3cSagc perror("binding name to socket");
16775a17f3cSagc return -1;
16875a17f3cSagc }
16975a17f3cSagc
17075a17f3cSagc for (i = 0; i < NUM_DAEMON_LISTS; i++) {
17175a17f3cSagc TAILQ_INIT(&list[i].list);
17275a17f3cSagc list[i].num_entries = 0;
17375a17f3cSagc }
17475a17f3cSagc
1756fea88c2Smlelstv if ((i = pthread_mutex_init(&sesslist_lock, NULL)) != 0) {
17675a17f3cSagc printf("Mutex init failed (%d)\n", i);
17775a17f3cSagc close(sock);
17875a17f3cSagc return -1;
17975a17f3cSagc }
18075a17f3cSagc
18175a17f3cSagc if (!register_event_handler()) {
18275a17f3cSagc printf("Couldn't register event handler\n");
18375a17f3cSagc close(sock);
18475a17f3cSagc unlink(ISCSID_SOCK_NAME);
18575a17f3cSagc pthread_mutex_destroy(&sesslist_lock);
18675a17f3cSagc return -1;
18775a17f3cSagc }
18875a17f3cSagc
18975a17f3cSagc create_node_name();
19075a17f3cSagc
19175a17f3cSagc return sock;
19275a17f3cSagc }
19375a17f3cSagc
19475a17f3cSagc
19575a17f3cSagc /*
19675a17f3cSagc * make_rsp:
19775a17f3cSagc * Allocate a response buffer if the static buffer is insufficient, set
19875a17f3cSagc * the response parameter length.
19975a17f3cSagc *
20075a17f3cSagc * Parameter:
20175a17f3cSagc * len Response parameter size (not counting header)
20275a17f3cSagc * prsp Pointer to address of response buffer
20375a17f3cSagc * prsp_temp Will be set to TRUE if buffer was allocated, FALSE
20475a17f3cSagc * for static buffer.
20575a17f3cSagc *
20675a17f3cSagc * Returns: Pointer to response buffer, NULL if allocation failed.
20775a17f3cSagc */
20875a17f3cSagc
20975a17f3cSagc iscsid_response_t *
make_rsp(size_t len,iscsid_response_t ** prsp,int * prsp_temp)210f7720048Schristos make_rsp(size_t len, iscsid_response_t ** prsp, int *prsp_temp)
21175a17f3cSagc {
21275a17f3cSagc iscsid_response_t *rsp;
21375a17f3cSagc
21475a17f3cSagc if ((len + sizeof(iscsid_response_t)) > RSP_BUFFER_SIZE) {
21575a17f3cSagc if ((rsp = calloc(1, len)) == NULL) {
21675a17f3cSagc (*prsp)->status = ISCSID_STATUS_NO_RESOURCES;
21775a17f3cSagc return NULL;
21875a17f3cSagc }
21975a17f3cSagc *prsp_temp = TRUE;
22075a17f3cSagc *prsp = rsp;
22175a17f3cSagc } else
22275a17f3cSagc rsp = *prsp;
22375a17f3cSagc
22475a17f3cSagc memset (rsp, 0, len + sizeof(iscsid_response_t));
225f7720048Schristos rsp->parameter_length = (uint32_t)len;
22675a17f3cSagc return rsp;
22775a17f3cSagc }
22875a17f3cSagc
22975a17f3cSagc
23075a17f3cSagc /*
23175a17f3cSagc * process_message:
23275a17f3cSagc * minimal parameter check and dispatch for the daemon functions.
23375a17f3cSagc *
23475a17f3cSagc * Parameter:
23575a17f3cSagc * req The request
23675a17f3cSagc * prsp Pointer to address of response buffer
23775a17f3cSagc * prsp_temp Will be set to TRUE if buffer was allocated, FALSE
23875a17f3cSagc * for static buffer.
23975a17f3cSagc */
24075a17f3cSagc
24138a27f5aSagc static void
process_message(iscsid_request_t * req,iscsid_response_t ** prsp,int * prsp_temp)24275a17f3cSagc process_message(iscsid_request_t *req, iscsid_response_t **prsp, int *prsp_temp)
24375a17f3cSagc {
24475a17f3cSagc iscsid_response_t *rsp;
245f7720048Schristos void *p = req->parameter;
24675a17f3cSagc
24775a17f3cSagc *prsp_temp = FALSE;
248f7720048Schristos *prsp = rsp = (iscsid_response_t *)(void *)rsp_buf;
24975a17f3cSagc rsp->parameter_length = 0;
25075a17f3cSagc rsp->status = ISCSID_STATUS_SUCCESS;
25175a17f3cSagc
25275a17f3cSagc switch (req->request) {
25375a17f3cSagc case ISCSID_ADD_TARGET:
25475a17f3cSagc if (req->parameter_length < sizeof(iscsid_add_target_req_t)) {
25575a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
25675a17f3cSagc break;
25775a17f3cSagc }
258f7720048Schristos add_target((iscsid_add_target_req_t *)p, prsp, prsp_temp);
25975a17f3cSagc break;
26075a17f3cSagc
26175a17f3cSagc case ISCSID_ADD_PORTAL:
26275a17f3cSagc if (req->parameter_length != sizeof(iscsid_add_portal_req_t)) {
26375a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
26475a17f3cSagc break;
26575a17f3cSagc }
266f7720048Schristos add_portal((iscsid_add_portal_req_t *)p, prsp, prsp_temp);
26775a17f3cSagc break;
26875a17f3cSagc
26975a17f3cSagc case ISCSID_SET_TARGET_OPTIONS:
27075a17f3cSagc if (req->parameter_length != sizeof(iscsid_get_set_target_options_t)) {
27175a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
27275a17f3cSagc break;
27375a17f3cSagc }
274f7720048Schristos rsp->status = set_target_options((iscsid_get_set_target_options_t *)p);
27575a17f3cSagc break;
27675a17f3cSagc
27775a17f3cSagc case ISCSID_GET_TARGET_OPTIONS:
27875a17f3cSagc if (req->parameter_length != sizeof(iscsid_sym_id_t)) {
27975a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
28075a17f3cSagc break;
28175a17f3cSagc }
28275a17f3cSagc rsp->status = ISCSID_STATUS_NOTIMPL;
28375a17f3cSagc break;
28475a17f3cSagc
28575a17f3cSagc case ISCSID_SET_TARGET_AUTHENTICATION:
28675a17f3cSagc if (req->parameter_length !=
28775a17f3cSagc sizeof(iscsid_set_target_authentication_req_t)) {
28875a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
28975a17f3cSagc break;
29075a17f3cSagc }
291f7720048Schristos rsp->status = set_target_auth((iscsid_set_target_authentication_req_t *)p);
29275a17f3cSagc break;
29375a17f3cSagc
29475a17f3cSagc case ISCSID_SLP_FIND_TARGETS:
29575a17f3cSagc rsp->status = ISCSID_STATUS_NOTIMPL;
29675a17f3cSagc break;
29775a17f3cSagc
29875a17f3cSagc case ISCSID_REFRESH_TARGETS:
29975a17f3cSagc if (req->parameter_length < sizeof(iscsid_refresh_req_t)) {
30075a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
30175a17f3cSagc break;
30275a17f3cSagc }
303f7720048Schristos rsp->status = refresh_targets((iscsid_refresh_req_t *)p);
30475a17f3cSagc break;
30575a17f3cSagc
30675a17f3cSagc case ISCSID_REMOVE_TARGET:
30775a17f3cSagc if (req->parameter_length != sizeof(iscsid_list_id_t)) {
30875a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
30975a17f3cSagc break;
31075a17f3cSagc }
311f7720048Schristos rsp->status = remove_target((iscsid_list_id_t *)p);
31275a17f3cSagc break;
31375a17f3cSagc
31475a17f3cSagc case ISCSID_SEARCH_LIST:
31575a17f3cSagc if (req->parameter_length != sizeof(iscsid_search_list_req_t)) {
31675a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
31775a17f3cSagc break;
31875a17f3cSagc }
319f7720048Schristos search_list((iscsid_search_list_req_t *)p, prsp, prsp_temp);
32075a17f3cSagc break;
32175a17f3cSagc
32275a17f3cSagc case ISCSID_GET_LIST:
32375a17f3cSagc if (req->parameter_length != sizeof(iscsid_get_list_req_t)) {
32475a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
32575a17f3cSagc break;
32675a17f3cSagc }
327f7720048Schristos get_list((iscsid_get_list_req_t *)p, prsp, prsp_temp);
32875a17f3cSagc break;
32975a17f3cSagc
33075a17f3cSagc case ISCSID_GET_TARGET_INFO:
33175a17f3cSagc if (req->parameter_length != sizeof(iscsid_list_id_t)) {
33275a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
33375a17f3cSagc break;
33475a17f3cSagc }
335f7720048Schristos get_target_info((iscsid_list_id_t *)p, prsp, prsp_temp);
33675a17f3cSagc break;
33775a17f3cSagc
33875a17f3cSagc case ISCSID_GET_PORTAL_INFO:
33975a17f3cSagc if (req->parameter_length != sizeof(iscsid_list_id_t)) {
34075a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
34175a17f3cSagc break;
34275a17f3cSagc }
343f7720048Schristos get_portal_info((iscsid_list_id_t *)p, prsp, prsp_temp);
34475a17f3cSagc break;
34575a17f3cSagc
34675a17f3cSagc #ifndef ISCSI_MINIMAL
34775a17f3cSagc case ISCSID_ADD_ISNS_SERVER:
34875a17f3cSagc if (req->parameter_length != sizeof(iscsid_add_isns_server_req_t)) {
34975a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
35075a17f3cSagc break;
35175a17f3cSagc }
352f7720048Schristos add_isns_server((iscsid_add_isns_server_req_t *)p,
35375a17f3cSagc prsp, prsp_temp);
35475a17f3cSagc break;
35575a17f3cSagc
35675a17f3cSagc case ISCSID_GET_ISNS_SERVER:
35775a17f3cSagc if (req->parameter_length != sizeof(iscsid_sym_id_t)) {
35875a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
35975a17f3cSagc break;
36075a17f3cSagc }
361f7720048Schristos get_isns_server((iscsid_sym_id_t *)p, prsp, prsp_temp);
36275a17f3cSagc break;
36375a17f3cSagc
36475a17f3cSagc case ISCSID_SLP_FIND_ISNS_SERVERS:
36575a17f3cSagc rsp->status = ISCSID_STATUS_NOTIMPL;
36675a17f3cSagc break;
36775a17f3cSagc
36875a17f3cSagc case ISCSID_REMOVE_ISNS_SERVER:
36975a17f3cSagc if (req->parameter_length != sizeof(iscsid_sym_id_t)) {
37075a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
37175a17f3cSagc break;
37275a17f3cSagc }
373f7720048Schristos rsp->status = remove_isns_server((iscsid_sym_id_t *)p);
37475a17f3cSagc break;
37575a17f3cSagc #endif
37675a17f3cSagc
37775a17f3cSagc case ISCSID_ADD_INITIATOR_PORTAL:
37875a17f3cSagc if (req->parameter_length != sizeof(iscsid_add_initiator_req_t)) {
37975a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
38075a17f3cSagc break;
38175a17f3cSagc }
382f7720048Schristos add_initiator_portal((iscsid_add_initiator_req_t *)p,
38375a17f3cSagc prsp, prsp_temp);
38475a17f3cSagc break;
38575a17f3cSagc
38675a17f3cSagc case ISCSID_GET_INITIATOR_PORTAL:
38775a17f3cSagc if (req->parameter_length != sizeof(iscsid_sym_id_t)) {
38875a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
38975a17f3cSagc break;
39075a17f3cSagc }
391f7720048Schristos get_initiator_portal((iscsid_sym_id_t *)p, prsp, prsp_temp);
39275a17f3cSagc break;
39375a17f3cSagc
39475a17f3cSagc case ISCSID_REMOVE_INITIATOR_PORTAL:
39575a17f3cSagc if (req->parameter_length != sizeof(iscsid_sym_id_t)) {
39675a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
39775a17f3cSagc break;
39875a17f3cSagc }
399f7720048Schristos rsp->status = remove_initiator_portal((iscsid_sym_id_t *)p);
40075a17f3cSagc break;
40175a17f3cSagc
40275a17f3cSagc case ISCSID_LOGIN:
40375a17f3cSagc if (req->parameter_length != sizeof(iscsid_login_req_t)) {
40475a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
40575a17f3cSagc break;
40675a17f3cSagc }
4076fea88c2Smlelstv log_in((iscsid_login_req_t *)p, rsp);
40875a17f3cSagc break;
40975a17f3cSagc
41075a17f3cSagc case ISCSID_ADD_CONNECTION:
41175a17f3cSagc if (req->parameter_length != sizeof(iscsid_login_req_t)) {
41275a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
41375a17f3cSagc break;
41475a17f3cSagc }
415f7720048Schristos add_connection((iscsid_login_req_t *)p, rsp);
41675a17f3cSagc break;
41775a17f3cSagc
41875a17f3cSagc case ISCSID_LOGOUT:
41975a17f3cSagc if (req->parameter_length != sizeof(iscsid_sym_id_t)) {
42075a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
42175a17f3cSagc break;
42275a17f3cSagc }
4236fea88c2Smlelstv rsp->status = log_out((iscsid_sym_id_t *)p);
42475a17f3cSagc break;
42575a17f3cSagc
42675a17f3cSagc case ISCSID_REMOVE_CONNECTION:
42775a17f3cSagc if (req->parameter_length != sizeof(iscsid_remove_connection_req_t)) {
42875a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
42975a17f3cSagc break;
43075a17f3cSagc }
431f7720048Schristos rsp->status = remove_connection((iscsid_remove_connection_req_t *)p);
43275a17f3cSagc break;
43375a17f3cSagc
43475a17f3cSagc case ISCSID_GET_SESSION_LIST:
43575a17f3cSagc get_session_list(prsp, prsp_temp);
43675a17f3cSagc break;
43775a17f3cSagc
43875a17f3cSagc case ISCSID_GET_CONNECTION_LIST:
43975a17f3cSagc if (req->parameter_length != sizeof(iscsid_sym_id_t)) {
44075a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
44175a17f3cSagc break;
44275a17f3cSagc }
443f7720048Schristos get_connection_list((iscsid_sym_id_t *)p, prsp, prsp_temp);
44475a17f3cSagc break;
44575a17f3cSagc
44675a17f3cSagc case ISCSID_GET_CONNECTION_INFO:
44775a17f3cSagc if (req->parameter_length != sizeof(iscsid_get_connection_info_req_t)) {
44875a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
44975a17f3cSagc break;
45075a17f3cSagc }
451f7720048Schristos get_connection_info((iscsid_get_connection_info_req_t *)p,
45275a17f3cSagc prsp, prsp_temp);
45375a17f3cSagc break;
45475a17f3cSagc
45575a17f3cSagc case ISCSID_SET_NODE_NAME:
45675a17f3cSagc if (req->parameter_length != sizeof(iscsid_set_node_name_req_t)) {
45775a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_PARAMETER;
45875a17f3cSagc break;
45975a17f3cSagc }
460f7720048Schristos rsp->status = set_node_name((iscsid_set_node_name_req_t *)p);
46175a17f3cSagc break;
46275a17f3cSagc
46375a17f3cSagc case ISCSID_GET_VERSION:
46475a17f3cSagc get_version(prsp, prsp_temp);
46575a17f3cSagc break;
46675a17f3cSagc
46775a17f3cSagc default:
46875a17f3cSagc rsp->status = ISCSID_STATUS_INVALID_REQUEST;
46975a17f3cSagc break;
47075a17f3cSagc }
47175a17f3cSagc }
47275a17f3cSagc
4736fea88c2Smlelstv void
iscsid_log(const char * fmt,...)4746fea88c2Smlelstv iscsid_log(const char *fmt, ...)
4756fea88c2Smlelstv {
4766fea88c2Smlelstv va_list ap;
4776fea88c2Smlelstv va_start(ap, fmt);
4786fea88c2Smlelstv vsyslog(LOG_INFO, fmt, ap);
4796fea88c2Smlelstv va_end(ap);
4806fea88c2Smlelstv }
48175a17f3cSagc
48275a17f3cSagc /*
48375a17f3cSagc * exit_daemon:
48475a17f3cSagc * Deregister the event handler, deregister isns servers, then exit program.
48575a17f3cSagc */
48675a17f3cSagc
48744b25f2fSmlelstv static void __dead
exit_daemon(void)48875a17f3cSagc exit_daemon(void)
48975a17f3cSagc {
49075a17f3cSagc LOCK_SESSIONS;
49175a17f3cSagc deregister_event_handler();
49275a17f3cSagc
49375a17f3cSagc #ifndef ISCSI_MINIMAL
49475a17f3cSagc dereg_all_isns_servers();
49575a17f3cSagc #endif
49675a17f3cSagc exit(0);
49775a17f3cSagc }
49875a17f3cSagc
4996fea88c2Smlelstv static void
handler_exit(void)5006fea88c2Smlelstv handler_exit(void)
5016fea88c2Smlelstv {
5026fea88c2Smlelstv pthread_kill(main_thread, SIGINT);
5036fea88c2Smlelstv }
5046fea88c2Smlelstv
5056fea88c2Smlelstv static void
sighandler(int sig)5066fea88c2Smlelstv sighandler(int sig)
5076fea88c2Smlelstv {
5086fea88c2Smlelstv }
50975a17f3cSagc
51075a17f3cSagc /*
51175a17f3cSagc * main:
51275a17f3cSagc * init, go daemon, then loop reading requests, processing them,
51375a17f3cSagc * and sending responses.
51475a17f3cSagc * Stops on receiving a terminate message (no response to that one is sent),
51575a17f3cSagc * or when an error occurs reading or writing the socket.
51675a17f3cSagc *
51775a17f3cSagc * Parameter: argc, argv currently ignored.
51875a17f3cSagc */
51975a17f3cSagc
52075a17f3cSagc int
521f7720048Schristos /*ARGSUSED*/
main(int argc,char ** argv)52275a17f3cSagc main(int argc, char **argv)
52375a17f3cSagc {
52468a964c3Schristos int req_temp, rsp_temp, c;
525f7720048Schristos ssize_t ret;
526f7720048Schristos size_t len;
52775a17f3cSagc struct sockaddr_un from;
52875a17f3cSagc socklen_t fromlen;
52975a17f3cSagc iscsid_request_t *req;
53075a17f3cSagc iscsid_response_t *rsp;
531c08d1e52Sriz char *p;
5326fea88c2Smlelstv struct sigaction sa;
533c08d1e52Sriz
5346fea88c2Smlelstv while ((c = getopt(argc, argv, "Dd:")) != -1)
535c08d1e52Sriz switch (c) {
5366fea88c2Smlelstv case 'D':
5376fea88c2Smlelstv debugging++;
538c08d1e52Sriz break;
539c08d1e52Sriz case 'd':
540c08d1e52Sriz debug_level=(int)strtol(optarg, &p, 10);
541c08d1e52Sriz if (*p)
5426fea88c2Smlelstv errx(EXIT_FAILURE, "illegal log level -- %s",
543c08d1e52Sriz optarg);
544c08d1e52Sriz break;
545c08d1e52Sriz default:
546c08d1e52Sriz usage();
547c08d1e52Sriz }
54875a17f3cSagc
5496fea88c2Smlelstv openlog("iscsid", (debugging ? LOG_PERROR : 0) | LOG_PID, LOG_DAEMON);
5506fea88c2Smlelstv
55175a17f3cSagc client_sock = init_daemon();
55275a17f3cSagc if (client_sock < 0)
55375a17f3cSagc exit(1);
55475a17f3cSagc
5556fea88c2Smlelstv DEBOUT(("iSCSI daemon loaded"));
55675a17f3cSagc
5576fea88c2Smlelstv if (!debugging) {
5586fea88c2Smlelstv if (daemon(0, 1) < 0)
5596fea88c2Smlelstv err(EXIT_FAILURE, "daemon() failed");
5606fea88c2Smlelstv pidfile(NULL);
5616fea88c2Smlelstv }
56275a17f3cSagc
5636fea88c2Smlelstv memset(&sa, 0, sizeof(sa));
5646fea88c2Smlelstv sa.sa_handler = sighandler;
5656fea88c2Smlelstv sigaction(SIGINT, &sa, NULL);
5666fea88c2Smlelstv sigaction(SIGTERM, &sa, NULL);
5676fea88c2Smlelstv
5686fea88c2Smlelstv main_thread = pthread_self();
5696fea88c2Smlelstv ret = pthread_create(&event_thread, NULL, event_handler, handler_exit);
57075a17f3cSagc if (ret) {
571f7720048Schristos printf("Thread creation failed (%zd)\n", ret);
57275a17f3cSagc close(client_sock);
57375a17f3cSagc unlink(ISCSID_SOCK_NAME);
57475a17f3cSagc deregister_event_handler();
57575a17f3cSagc pthread_mutex_destroy(&sesslist_lock);
57675a17f3cSagc return -1;
57775a17f3cSagc }
57875a17f3cSagc
57975a17f3cSagc /* ---------------------------------------------------------------------- */
58075a17f3cSagc
58175a17f3cSagc for (;;) {
5826fea88c2Smlelstv
58375a17f3cSagc /* First, get size of request */
584f7720048Schristos req = (iscsid_request_t *)(void *)req_buf;
58575a17f3cSagc fromlen = sizeof(from);
58675a17f3cSagc len = sizeof(iscsid_request_t);
58775a17f3cSagc
58875a17f3cSagc do {
589f547f456Schristos ret = recvfrom(client_sock, req, len, MSG_PEEK |
590f547f456Schristos MSG_WAITALL, (struct sockaddr *) &from,
591f547f456Schristos &fromlen);
59275a17f3cSagc } while (ret == -1 && errno == EAGAIN);
59375a17f3cSagc
594f7720048Schristos if ((size_t)ret != len) {
5956fea88c2Smlelstv DEBOUT(("Receiving from socket: %s",strerror(errno)));
59675a17f3cSagc break;
59775a17f3cSagc }
5986fea88c2Smlelstv DEB(2, ("Request %d, parlen %d",
59975a17f3cSagc req->request, req->parameter_length));
60075a17f3cSagc
60175a17f3cSagc len += req->parameter_length;
60275a17f3cSagc
60375a17f3cSagc /* now that we know the size, get the buffer for it */
60475a17f3cSagc req_temp = (len > REQ_BUFFER_SIZE);
60575a17f3cSagc
60675a17f3cSagc if (req_temp) {
60775a17f3cSagc req = malloc(len);
60875a17f3cSagc if (!req) {
609f7720048Schristos printf("Can't alloc %zu bytes\n", len);
61075a17f3cSagc break;
61175a17f3cSagc }
61275a17f3cSagc }
61375a17f3cSagc /* read the complete request */
61475a17f3cSagc fromlen = sizeof(from);
61575a17f3cSagc ret = recvfrom(client_sock, req, len, MSG_WAITALL,
616f7720048Schristos (struct sockaddr *)(void *)&from, &fromlen);
617f7720048Schristos if ((size_t)ret != len) {
6186fea88c2Smlelstv DEB(2, ("Error receiving from socket!"));
61975a17f3cSagc if (req_temp)
62075a17f3cSagc free(req);
62175a17f3cSagc continue;
62275a17f3cSagc }
62375a17f3cSagc /* terminate? then go die. */
62475a17f3cSagc if (req->request == ISCSID_DAEMON_TERMINATE)
62575a17f3cSagc break;
62675a17f3cSagc
62775a17f3cSagc /* No reply required to test message */
62875a17f3cSagc if (req->request == ISCSID_DAEMON_TEST) {
62975a17f3cSagc if (req_temp)
63075a17f3cSagc free(req);
6316fea88c2Smlelstv DEB(2, ("Test message!"));
63275a17f3cSagc continue;
63375a17f3cSagc }
63475a17f3cSagc /* no return path? then we can't send a reply, */
63575a17f3cSagc /* so don't process the command */
63675a17f3cSagc if (!from.sun_path[0]) {
6374fa33b60Smlelstv if (req_temp)
6384fa33b60Smlelstv free(req);
6396fea88c2Smlelstv DEB(2, ("No Return Address!"));
64075a17f3cSagc continue;
64175a17f3cSagc }
64275a17f3cSagc /* process the request */
64375a17f3cSagc process_message(req, &rsp, &rsp_temp);
6444fa33b60Smlelstv if (rsp == NULL) {
6454fa33b60Smlelstv if (req_temp)
6464fa33b60Smlelstv free(req);
6476fea88c2Smlelstv DEB(2, ("Invalid message!"));
6484fa33b60Smlelstv continue;
6494fa33b60Smlelstv }
65075a17f3cSagc
6516fea88c2Smlelstv DEB(2, ("Sending reply: status %d, len %d",
65275a17f3cSagc rsp->status, rsp->parameter_length));
65375a17f3cSagc
65475a17f3cSagc /* send the response */
65575a17f3cSagc len = sizeof(iscsid_response_t) + rsp->parameter_length;
65675a17f3cSagc ret = sendto(client_sock, rsp, len, 0,
657f7720048Schristos (struct sockaddr *)(void *)&from, fromlen);
658f7720048Schristos if (len != (size_t)ret) {
6596fea88c2Smlelstv DEB(2, ("Error sending reply!"));
66075a17f3cSagc }
66175a17f3cSagc /* free temp buffers if we needed them */
66275a17f3cSagc if (req_temp)
66375a17f3cSagc free(req);
66475a17f3cSagc if (rsp_temp)
66575a17f3cSagc free(rsp);
66675a17f3cSagc }
66775a17f3cSagc
6686fea88c2Smlelstv pthread_join(event_thread, NULL);
6696fea88c2Smlelstv
6706fea88c2Smlelstv DEBOUT(("Exiting daemon"));
6716fea88c2Smlelstv
67275a17f3cSagc exit_daemon();
67375a17f3cSagc
67475a17f3cSagc /* we never get here */
67575a17f3cSagc return 0;
67675a17f3cSagc }
677