usr/config.h: fix comment for struct iscsi_session_timeout_config
[open-iscsi.git] / usr / discoveryd.c
blobde080ea2c2718ba43ed6d6bc6a1d53238385f0e2
1 /*
2 * iSCSI Initiator discovery daemon
4 * Copyright (C) 2010 Mike Christie
5 * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
7 * maintained by open-iscsi@googlegroups.com
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * See the file COPYING included with this distribution for more details.
21 #include <errno.h>
22 #include <stdio.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <signal.h>
26 #include <stdlib.h>
27 #include <time.h>
28 #include <sys/types.h>
29 #include <sys/wait.h>
31 #include "discovery.h"
32 #include "idbm.h"
33 #include "list.h"
34 #include "iscsi_proto.h"
35 #include "sysdeps.h"
36 #include "log.h"
37 #include "session_mgmt.h"
38 #include "iscsi_util.h"
39 #include "event_poll.h"
40 #include "iface.h"
41 #include "session_mgmt.h"
42 #include "session_info.h"
43 #include "isns-proto.h"
44 #include "isns.h"
45 #include "paths.h"
46 #include "message.h"
47 #include "iscsi_err.h"
49 #define DISC_DEF_POLL_INVL 30
51 static LIST_HEAD(iscsi_targets);
52 static int stop_discoveryd;
54 static LIST_HEAD(isns_initiators);
55 static LIST_HEAD(isns_refresh_list);
56 static char *isns_entity_id = NULL;
57 static uint32_t isns_refresh_interval;
58 static int isns_register_nodes = 1;
60 static void isns_reg_refresh_by_eid_qry(void *data);
62 typedef void (do_disc_and_login_fn)(const char *def_iname,
63 struct discovery_rec *drec, int poll_inval);
65 static int logout_session(void *data, struct list_head *list,
66 struct session_info *info)
68 struct list_head *rec_list = data;
69 struct node_rec *rec;
71 list_for_each_entry(rec, rec_list, list) {
72 if (iscsi_match_session(rec, info))
73 return iscsi_logout_portal(info, list);
75 return -1;
78 static void discoveryd_stop(void)
80 struct node_rec *rec, *tmp_rec;
81 int nr_found = 0;
83 if (list_empty(&iscsi_targets))
84 goto done;
87 * User requested to just login and exit.
89 if (!stop_discoveryd)
90 goto done;
92 iscsi_logout_portals(&iscsi_targets, &nr_found, 1, logout_session);
93 list_for_each_entry_safe(rec, tmp_rec, &iscsi_targets, list) {
94 list_del(&rec->list);
95 free(rec);
98 done:
99 exit(0);
102 static void catch_signal(int signo)
104 log_debug(1, "%d caught signal -%d...", signo, getpid());
105 switch (signo) {
106 case SIGTERM:
107 stop_discoveryd = 1;
108 break;
109 default:
110 break;
114 static void setup_signal_handler(void)
116 struct sigaction sa_old;
117 struct sigaction sa_new;
119 sa_new.sa_handler = catch_signal;
120 sigemptyset(&sa_new.sa_mask);
121 sa_new.sa_flags = 0;
122 sigaction(SIGTERM, &sa_new, &sa_old );
126 * update_sessions - login/logout sessions
127 * @new_rec_list: new target portals recs bound to ifaces
128 * @targetname: if set we only update sessions for this target
129 * @iname: if set we only update session for that initiator
131 * This will login/logout of portals. When it returns the recs on
132 * new_rec_list will be freed or put on the iscsi_targets list.
134 * FIXME: if we are hitting a per problem this may be it. With targets
135 * that do a target per lun this could get ugly.
137 static void update_sessions(struct list_head *new_rec_list,
138 const char *targetname, const char *iname)
140 struct node_rec *rec, *tmp_rec;
141 struct list_head stale_rec_list;
142 int nr_found;
144 INIT_LIST_HEAD(&stale_rec_list);
146 * Check if a target portal is no longer being sent.
147 * Note: Due to how we reread ifaces this will also detect
148 * changes in ifaces being access through portals.
150 list_for_each_entry_safe(rec, tmp_rec, &iscsi_targets, list) {
151 log_debug(7, "Trying to match %s %s to %s %s %s",
152 targetname, iname, rec->name, rec->conn[0].address,
153 rec->iface.name);
154 if (targetname && strcmp(rec->name, targetname))
155 continue;
157 if (iname) {
158 if (strlen(rec->iface.iname) &&
159 strcmp(rec->iface.iname, iname))
160 continue;
161 else if (strcmp(iname, isns_config.ic_source_name))
162 continue;
165 log_debug(5, "Matched %s %s, checking if in new targets.",
166 targetname, iname);
167 if (!idbm_find_rec_in_list(new_rec_list, rec->name,
168 rec->conn[0].address,
169 rec->conn[0].port, &rec->iface)) {
170 log_debug(5, "Not found. Marking for logout");
171 list_move_tail(&rec->list, &stale_rec_list);
175 list_for_each_entry_safe(rec, tmp_rec, new_rec_list, list) {
176 if (!iscsi_check_for_running_session(rec))
177 iscsi_login_portal_nowait(rec);
179 if (!idbm_find_rec_in_list(&iscsi_targets, rec->name,
180 rec->conn[0].address,
181 rec->conn[0].port, &rec->iface)) {
182 log_debug(5, "%s %s %s %s not on curr target list. "
183 "Adding.", rec->name, rec->conn[0].address,
184 rec->iface.name, rec->iface.iname);
185 list_move_tail(&rec->list, &iscsi_targets);
186 } else {
187 list_del(&rec->list);
188 free(rec);
192 if (!list_empty(&stale_rec_list)) {
193 iscsi_logout_portals(&stale_rec_list, &nr_found, 0,
194 logout_session);
195 list_for_each_entry_safe(rec, tmp_rec, &stale_rec_list, list) {
196 list_del(&rec->list);
197 free(rec);
202 static void fork_disc(const char *def_iname, struct discovery_rec *drec,
203 int poll_inval, do_disc_and_login_fn *do_disc_and_login)
205 pid_t pid;
207 pid = fork();
208 if (pid == 0) {
209 setup_signal_handler();
210 do_disc_and_login(def_iname, drec, poll_inval);
211 exit(0);
212 } else if (pid < 0)
213 log_error("Fork failed (err %d - %s). Will not be able "
214 "to perform discovery to %s.\n",
215 errno, strerror(errno), drec->address);
216 else {
217 shutdown_callback(pid);
218 log_debug(1, "iSCSI disc and login helper pid=%d", pid);
219 reap_inc();
223 struct isns_node_list {
224 isns_source_t *source;
225 struct list_head list;
228 /* iSNS */
229 static int isns_build_objs(isns_portal_info_t *portal_info,
230 isns_object_list_t *objs)
232 struct isns_node_list *node;
233 isns_object_t *inode, *entity;
234 unsigned int i, nportals = 1;
235 int rc = 0;
237 log_debug(7, "isns_build_objs");
239 /* we currently just use all portals */
240 if (isns_portal_is_wildcard(portal_info)) {
241 static isns_portal_info_t *iflist;
243 nportals = isns_get_nr_portals();
244 log_debug(4, "got %d portals", nportals);
245 if (!nportals)
246 return ISCSI_ERR_NO_OBJS_FOUND;
248 iflist = calloc(nportals, sizeof(isns_portal_info_t));
249 if (!iflist) {
250 log_error("Unable to allocate %d portals.", nportals);
251 return ISCSI_ERR_NOMEM;
254 nportals = isns_enumerate_portals(iflist, nportals);
255 if (nportals == 0) {
256 log_error("Unable to enumerate portals - "
257 "no usable interfaces found\n");
258 free(iflist);
259 return ISCSI_ERR_NO_OBJS_FOUND;
261 for (i = 0; i < nportals; ++i) {
262 iflist[i].addr.sin6_port = portal_info->addr.sin6_port;
263 iflist[i].proto = portal_info->proto;
265 portal_info = iflist;
268 if (!isns_entity_id) {
269 isns_entity_id = calloc(1, 256);
270 if (!isns_entity_id)
271 return ISCSI_ERR_NOMEM;
273 rc = getnameinfo((struct sockaddr *) &portal_info->addr,
274 sizeof(portal_info->addr),
275 isns_entity_id, 256, NULL, 0, 0);
276 if (rc) {
277 free(isns_entity_id);
278 isns_entity_id = NULL;
280 log_error("Could not get hostname for EID.");
281 return ISCSI_ERR;
285 entity = isns_create_entity(ISNS_ENTITY_PROTOCOL_ISCSI, isns_entity_id);
286 if (!entity) {
287 log_error("Could not create iSNS entity.");
288 return ISCSI_ERR_NOMEM;
290 isns_object_list_append(objs, entity);
292 for (i = 0; i < nportals; ++i, ++portal_info) {
293 isns_object_t *portal;
295 portal = isns_create_portal(portal_info, entity);
296 if (!portal) {
297 rc = ISCSI_ERR_NOMEM;
298 goto fail;
300 isns_object_list_append(objs, portal);
302 if (!isns_object_set_uint32(portal, ISNS_TAG_SCN_PORT,
303 isns_portal_tcpudp_port(portal_info))) {
304 rc = ISCSI_ERR_INVAL;
305 goto fail;
309 list_for_each_entry(node, &isns_initiators, list) {
310 inode = isns_create_storage_node2(node->source,
311 ISNS_ISCSI_INITIATOR_MASK,
312 NULL);
313 if (!inode) {
314 rc = ISCSI_ERR_NOMEM;
315 goto fail;
317 isns_object_list_append(objs, inode);
320 return 0;
321 fail:
322 isns_object_list_destroy(objs);
323 return rc;
326 struct isns_qry_data {
327 const char *iname;
328 const char *targetname;
331 static int isns_query_node(void *data, struct iface_rec *iface,
332 struct list_head *recs)
334 struct isns_qry_data *qry_data = data;
335 int is_def_iname = 0;
336 const char *iname;
338 if (qry_data->iname) {
339 if (!strcmp(qry_data->iname, isns_config.ic_source_name))
340 is_def_iname = 1;
342 if ((!is_def_iname || strlen(iface->iname)) &&
343 strcmp(iface->iname, qry_data->iname))
344 return 0;
346 iname = qry_data->iname;
347 } else {
348 if (strlen(iface->iname))
349 iname = iface->iname;
350 else
351 iname = isns_config.ic_source_name;
354 return discovery_isns_query(NULL, iname, qry_data->targetname, recs);
357 static int isns_disc_new_portals(const char *targetname, const char *iname)
359 struct list_head ifaces, rec_list;
360 struct iface_rec *iface, *tmp_iface;
361 struct isns_qry_data qry_data;
362 int rc;
364 INIT_LIST_HEAD(&rec_list);
365 INIT_LIST_HEAD(&ifaces);
367 qry_data.targetname = targetname;
368 qry_data.iname = iname;
370 iface_link_ifaces(&ifaces);
371 rc = idbm_bind_ifaces_to_nodes(isns_query_node, &qry_data, &ifaces,
372 &rec_list);
373 if (rc) {
374 log_error("Could not perform iSNS DevAttrQuery for node %s.",
375 targetname);
376 goto free_ifaces;
378 update_sessions(&rec_list, targetname, iname);
379 rc = 0;
381 free_ifaces:
382 list_for_each_entry_safe(iface, tmp_iface, &ifaces, list) {
383 list_del(&iface->list);
384 free(iface);
387 return rc;
390 static void isns_reg_refresh_with_disc(void *data)
392 int retries = 0, rc;
394 log_debug(1, "Refresh registration using DevAttrQuery");
397 * it is ok to block here since we are not expecting SCNs
398 * from the server.
400 do {
402 * Some servers do not support SCNs so we ping
403 * the server by doing discovery.
405 rc = isns_disc_new_portals(NULL, NULL);
406 if (rc) {
407 log_debug(4, "Registration refresh using DevAttrQuery "
408 "failed (retires %d) err %d", retries, rc);
409 sleep(1);
410 retries++;
411 continue;
413 } while (rc && retries < 3);
415 if (rc)
417 * Try to reregister from scratch.
419 isns_register_nodes = 1;
422 struct isns_refresh_data {
423 isns_client_t *clnt;
424 isns_simple_t *qry;
425 uint32_t xid;
426 uint32_t interval;
427 time_t start_time;
428 struct list_head list;
431 static void isns_free_refresh_data(struct isns_refresh_data *refresh_data)
433 list_del(&refresh_data->list);
434 if (refresh_data->qry)
435 isns_simple_free(refresh_data->qry);
436 if (refresh_data->clnt)
437 isns_client_destroy(refresh_data->clnt);
438 free(refresh_data);
441 static struct isns_refresh_data *isns_find_refresh_data(uint32_t xid)
443 struct isns_refresh_data *refresh_data;
445 list_for_each_entry(refresh_data, &isns_refresh_list, list) {
446 if (refresh_data->xid == xid)
447 return refresh_data;
449 return NULL;
452 static void isns_eid_qry_rsp(uint32_t xid, int status, isns_simple_t *rsp)
454 struct isns_refresh_data *refresh_data;
456 refresh_data = isns_find_refresh_data(xid);
457 if (!refresh_data) {
458 log_error("EID Query respond could not match xid");
459 return;
462 if (refresh_data->clnt) {
463 isns_client_destroy(refresh_data->clnt);
464 refresh_data->clnt = NULL;
467 if (!rsp || status != ISNS_SUCCESS) {
468 log_debug(1, "Registration refresh using eid qry failed: %s",
469 isns_strerror(status));
471 isns_add_oneshot_timer(2, isns_reg_refresh_by_eid_qry,
472 refresh_data);
473 return;
476 log_debug(1, "eid qry successful");
477 refresh_data->start_time = time(NULL);
478 isns_add_oneshot_timer(isns_refresh_interval,
479 isns_reg_refresh_by_eid_qry, refresh_data);
482 static void isns_reg_refresh_by_eid_qry(void *data)
484 struct isns_refresh_data *refresh_data = data;
485 isns_attr_list_t qry_key = ISNS_ATTR_LIST_INIT;
486 isns_simple_t *qry;
487 isns_client_t *clnt;
488 int status, timeout;
490 log_debug(1, "Refresh registration using eid qry");
491 if (refresh_data->start_time + refresh_data->interval <= time(NULL)) {
492 log_error("Could not refresh registration with server "
493 "before registration period. Starting new "
494 "registration.");
495 isns_free_refresh_data(refresh_data);
496 isns_register_nodes = 1;
497 return;
500 clnt = isns_create_default_client(NULL);
501 if (!clnt) {
502 log_error("iSNS registration refresh failed. Could not "
503 "connect to server.");
504 goto rearm;
506 refresh_data->clnt = clnt;
508 * if a operation has failed we will want to adjust timers
509 * and possibly reregister.
511 isns_socket_set_report_failure(clnt->ic_socket);
514 * if this is a retry or re-refresh then there will be a qry
516 qry = refresh_data->qry;
517 if (qry)
518 goto send;
520 isns_attr_list_append_string(&qry_key, ISNS_TAG_ENTITY_IDENTIFIER,
521 isns_entity_id);
522 qry = isns_create_query(clnt, &qry_key);
523 isns_attr_list_destroy(&qry_key);
524 if (!qry)
525 goto rearm;
526 isns_query_request_attr_tag(qry, ISNS_TAG_ENTITY_PROTOCOL);
527 refresh_data->qry = qry;
529 send:
530 timeout = (refresh_data->start_time + refresh_data->interval) -
531 time(NULL);
533 status = isns_simple_transmit(clnt->ic_socket, qry, NULL,
534 timeout, isns_eid_qry_rsp);
535 if (status == ISNS_SUCCESS) {
536 log_debug(7, "sent eid qry with xid %u", qry->is_xid);
538 refresh_data->xid = qry->is_xid;
539 return;
541 rearm:
542 if (refresh_data->clnt) {
543 isns_client_destroy(refresh_data->clnt);
544 refresh_data->clnt = NULL;
546 log_debug(1, "Could not send eid qry to refresh registration.");
547 isns_add_oneshot_timer(2, isns_reg_refresh_by_eid_qry, refresh_data);
550 static int isns_setup_registration_refresh(isns_simple_t *rsp, int poll_inval)
552 isns_object_list_t objs = ISNS_OBJECT_LIST_INIT;
553 struct isns_refresh_data *refresh_data;
554 int status, i, rc = 0;
555 uint32_t interval = 0;
557 status = isns_query_response_get_objects(rsp, &objs);
558 if (status) {
559 log_error("Unable to extract object list from "
560 "registration response: %s\n",
561 isns_strerror(status));
562 return ISCSI_ERR;
565 for (i = 0; i < objs.iol_count; ++i) {
566 isns_object_t *obj = objs.iol_data[i];
568 if (!isns_object_is_entity(obj))
569 continue;
571 if (isns_object_get_uint32(obj, ISNS_TAG_REGISTRATION_PERIOD,
572 &interval))
573 break;
576 if (!interval)
577 goto free_objs;
579 refresh_data = calloc(1, sizeof(*refresh_data));
580 if (!refresh_data) {
581 rc = ISCSI_ERR_NOMEM;
582 goto free_objs;
584 INIT_LIST_HEAD(&refresh_data->list);
585 list_add_tail(&refresh_data->list, &isns_refresh_list);
586 refresh_data->start_time = time(NULL);
589 * Several servers do not support SCNs properly, so for the
590 * registration period refresh we do a DevAttrQuery for all targets
591 * if the poll_inval is greater than 0.
593 * If the target does support SCNs then we just send a query
594 * for our entity's protocol.
597 /* we cut in half to give us time to handle errors */
598 isns_refresh_interval = interval / 2;
599 if (!isns_refresh_interval) {
600 log_warning("iSNS Registration Period only %d seconds.",
601 interval);
602 isns_refresh_interval = interval;
604 refresh_data->interval = interval;
606 if (poll_inval > 0) {
607 /* user wants to override server and do disc */
608 if (isns_refresh_interval > poll_inval)
609 isns_refresh_interval = poll_inval;
610 isns_add_timer(isns_refresh_interval,
611 isns_reg_refresh_with_disc,
612 refresh_data);
613 } else
615 * user wants to use server value so we just ping
616 * with a simple qry
618 isns_add_oneshot_timer(isns_refresh_interval,
619 isns_reg_refresh_by_eid_qry,
620 refresh_data);
621 log_debug(5, "Got registration period of %u "
622 "internval. Using interval of %u",
623 interval, isns_refresh_interval);
625 free_objs:
626 isns_flush_events();
627 isns_object_list_destroy(&objs);
628 return rc;
631 static void isns_cancel_refresh_timers(void)
633 isns_cancel_timer(isns_reg_refresh_with_disc, NULL);
634 isns_cancel_timer(isns_reg_refresh_by_eid_qry, NULL);
637 static int isns_register_objs(isns_client_t *clnt, isns_object_list_t *objs,
638 int poll_inval)
640 struct isns_node_list *node;
641 isns_object_t *entity = NULL;
642 isns_simple_t *reg;
643 unsigned int i;
644 int status, rc = 0;
646 log_debug(7, "isns_register_objs");
648 for (i = 0; i < objs->iol_count; ++i) {
649 if (isns_object_is_entity(objs->iol_data[i])) {
650 entity = objs->iol_data[i];
651 break;
655 reg = isns_create_registration(clnt, entity);
656 if (!reg)
657 return ISCSI_ERR_NOMEM;
659 for (i = 0; i < objs->iol_count; ++i)
660 isns_registration_add_object(reg, objs->iol_data[i]);
661 isns_registration_set_replace(reg, 1);
663 status = isns_simple_call(clnt->ic_socket, &reg);
664 if (status != ISNS_SUCCESS) {
665 log_error("Could not register with iSNS server: %s",
666 isns_strerror(status));
667 rc = ISCSI_ERR;
668 goto free_reg;
670 log_debug(4, "Registered objs");
672 if (!poll_inval)
673 goto free_reg;
675 rc = isns_setup_registration_refresh(reg, poll_inval);
676 if (rc)
677 goto free_reg;
679 list_for_each_entry(node, &isns_initiators, list) {
680 isns_simple_free(reg);
681 reg = isns_create_scn_registration2(clnt,
682 ISNS_SCN_OBJECT_UPDATED_MASK |
683 ISNS_SCN_OBJECT_ADDED_MASK |
684 ISNS_SCN_OBJECT_REMOVED_MASK |
685 ISNS_SCN_TARGET_AND_SELF_ONLY_MASK,
686 node->source);
688 if (!reg) {
689 isns_cancel_refresh_timers();
690 rc = ISCSI_ERR_NOMEM;
691 goto done;
694 status = isns_simple_call(clnt->ic_socket, &reg);
695 if (status != ISNS_SUCCESS) {
696 log_error("SCN registration for node %s failed: %s\n",
697 isns_source_name(node->source),
698 isns_strerror(status));
700 * if the user was going to poll then ignore error
701 * since user was probably using polling because SCNs
702 * were not supported by server
704 if (poll_inval < 0) {
705 isns_cancel_refresh_timers();
706 rc = ISCSI_ERR;
707 break;
710 log_debug(4, "Registered %s for SCNs",
711 isns_source_name(node->source));
714 free_reg:
715 isns_simple_free(reg);
716 done:
717 return rc;
720 static int isns_scn_register(isns_socket_t *svr_sock, int poll_inval)
722 isns_object_list_t objs = ISNS_OBJECT_LIST_INIT;
723 isns_portal_info_t portal_info;
724 isns_client_t *clnt;
725 int rc;
727 clnt = isns_create_default_client(NULL);
728 if (!clnt) {
729 log_error("iSNS setup failed. Could not connect to server.");
730 return ISCSI_ERR_TRANS;
732 isns_socket_set_disconnect_fatal(clnt->ic_socket);
734 log_debug(7, "isns_scn_register");
736 if (!isns_socket_get_portal_info(svr_sock, &portal_info)) {
737 log_error("Could not get portal info for iSNS registration.");
738 rc = ISCSI_ERR_NO_OBJS_FOUND;
739 goto destroy_clnt;
742 rc = isns_build_objs(&portal_info, &objs);
743 if (rc)
744 goto destroy_clnt;
746 rc = isns_register_objs(clnt, &objs, poll_inval);
747 isns_object_list_destroy(&objs);
748 if (!rc)
749 log_warning("iSNS: Registered network entity with EID %s with "
750 "server.", isns_entity_id);
752 destroy_clnt:
753 isns_client_destroy(clnt);
754 return rc;
757 static isns_source_t *isns_lookup_node(char *iname)
759 struct isns_node_list *node;
761 list_for_each_entry(node, &isns_initiators, list) {
762 if (!strcmp(iname, isns_source_name(node->source)))
763 return node->source;
765 return NULL;
768 static struct isns_node_list *isns_create_node(const char *iname)
770 isns_source_t *source;
771 struct isns_node_list *node;
773 source = isns_source_create_iscsi(iname);
774 if (!source)
775 return NULL;
777 node = calloc(1, sizeof(*node));
778 if (!node) {
779 isns_source_release(source);
780 return NULL;
782 INIT_LIST_HEAD(&node->list);
783 node->source = source;
784 return node;
787 static int isns_create_node_list(const char *def_iname)
789 struct iface_rec *iface, *tmp_iface;
790 struct list_head ifaces;
791 struct isns_node_list *node, *tmp_node;
792 int rc = 0;
794 INIT_LIST_HEAD(&ifaces);
795 iface_link_ifaces(&ifaces);
797 if (def_iname) {
798 node = isns_create_node(def_iname);
799 if (!node) {
800 rc = ISCSI_ERR_NOMEM;
801 goto fail;
803 list_add_tail(&node->list, &isns_initiators);
806 list_for_each_entry(iface, &ifaces, list) {
807 if (strlen(iface->iname) &&
808 !isns_lookup_node(iface->iname)) {
809 node = isns_create_node(iface->iname);
810 if (!node) {
811 rc = ISCSI_ERR_NOMEM;
812 goto fail;
814 list_add_tail(&node->list, &isns_initiators);
817 /* fix me */
818 rc = 0;
819 goto done;
820 fail:
821 list_for_each_entry_safe(node, tmp_node, &isns_initiators, list) {
822 list_del(&node->list);
823 free(node);
826 done:
827 list_for_each_entry_safe(iface, tmp_iface, &ifaces, list) {
828 list_del(&iface->list);
829 free(iface);
831 return rc;
834 static void isns_scn_callback(isns_db_t *db, uint32_t bitmap,
835 isns_object_template_t *node_type,
836 const char *node_name, const char *dst_name)
838 log_error("SCN for initiator: %s (Target: %s, Event: %s.)",
839 dst_name, node_name, isns_event_string(bitmap));
840 isns_disc_new_portals(node_name, dst_name);
843 static void isns_clear_refresh_list(void)
845 struct isns_refresh_data *refresh_data, *tmp_refresh;
847 list_for_each_entry_safe(refresh_data, tmp_refresh, &isns_refresh_list,
848 list)
849 isns_free_refresh_data(refresh_data);
852 static int isns_scn_recv(isns_server_t *svr, isns_socket_t *svr_sock,
853 int poll_inval)
855 isns_message_t *msg, *rsp;
856 struct timeval timeout = { 0, 0 };
857 time_t now, then, next_timeout;
858 unsigned int function;
859 int rc = 0;
861 log_debug(1, "isns_scn_recv");
863 while (!stop_discoveryd) {
864 /* reap disc/login procs */
865 reap_proc();
867 * timer func could force a scn registration so check timers
868 * first
870 then = isns_run_timers();
871 now = time(NULL);
872 next_timeout = now + 3600;
873 if (then && then < next_timeout)
874 next_timeout = then;
876 if (isns_register_nodes) {
877 isns_clear_refresh_list();
879 * it is ok to block here, because the server
880 * should have unregistered us or this is our
881 * first time registerting.
883 rc = isns_scn_register(svr_sock, poll_inval);
884 if (rc) {
885 sleep(5);
886 continue;
889 isns_disc_new_portals(NULL, NULL);
890 if (!poll_inval)
891 break;
892 isns_register_nodes = 0;
894 * the scn reg may have added timers or changed
895 * timeout values so recheck.
897 continue;
900 /* Determine how long we can sleep */
901 if (next_timeout <= now)
902 continue;
903 timeout.tv_sec = next_timeout - now;
905 if ((msg = isns_recv_message(&timeout)) == NULL)
906 continue;
908 function = isns_message_function(msg);
909 if (function != ISNS_STATE_CHANGE_NOTIFICATION) {
910 log_warning("Discarding unexpected %s message\n",
911 isns_function_name(function));
912 isns_message_release(msg);
913 continue;
916 if ((rsp = isns_process_message(svr, msg)) != NULL) {
917 isns_socket_t *sock = isns_message_socket(msg);
919 isns_socket_send(sock, rsp);
920 isns_message_release(rsp);
923 isns_message_release(msg);
926 log_debug(1, "isns_scn_recv done");
927 reap_proc();
928 return rc;
931 #define ISNS_EVENTD_PIDFILE ISNS_RUNDIR"/iscsid.isns.pid"
932 #define ISNS_EVENTD_CTL ISNS_RUNDIR"/iscsid.isns.isnsctl"
934 static int isns_eventd(const char *def_iname, char *disc_addr, int port,
935 int poll_inval)
937 static isns_socket_t *svr_sock;
938 isns_server_t *svr;
939 isns_db_t *db;
940 struct isns_node_list *tmp_node, *node;
941 int rc = 0;
943 isns_create_node_list(def_iname);
944 if (list_empty(&isns_initiators)) {
945 log_error("iSNS registration failed. Initiatorname not set.");
946 return ISCSI_ERR_INVAL;
949 /* use def_iname or if not set the first iface's iname for the src */
950 node = list_entry(isns_initiators.next, struct isns_node_list, list);
951 isns_assign_string(&isns_config.ic_source_name,
952 isns_source_name(node->source));
953 isns_config.ic_security = 0;
954 isns_config.ic_pidfile = ISNS_EVENTD_PIDFILE;
955 isns_config.ic_control_socket = ISNS_EVENTD_CTL;
957 if (discovery_isns_set_servername(disc_addr, port)) {
958 rc = ISCSI_ERR_NOMEM;
959 goto fail;
962 isns_write_pidfile(isns_config.ic_pidfile);
964 db = isns_db_open(NULL);
965 if (!db) {
966 log_error("iSNS setup failed. Could not create db.");
967 rc = ISCSI_ERR_NOMEM;
968 goto fail;
970 svr = isns_create_server(node->source, db, &isns_callback_service_ops);
971 if (!svr) {
972 log_error("iSNS setup failed. Could not create server.");
973 rc = ISCSI_ERR_TRANS;
974 goto fail;
976 isns_server_set_scn_callback(svr, isns_scn_callback);
978 svr_sock = isns_create_server_socket(NULL, NULL, AF_INET6, SOCK_DGRAM);
979 if (!svr_sock) {
980 log_error("iSNS setup failed. Could not create server socket.");
981 rc = ISCSI_ERR_TRANS;
982 goto fail;
985 rc = isns_scn_recv(svr, svr_sock, poll_inval);
986 isns_cancel_refresh_timers();
987 fail:
988 isns_clear_refresh_list();
990 list_for_each_entry_safe(node, tmp_node, &isns_initiators, list) {
991 list_del(&node->list);
992 free(node);
995 if (isns_entity_id)
996 free(isns_entity_id);
997 isns_entity_id = NULL;
999 discovery_isns_free_servername();
1001 if (isns_config.ic_source_name)
1002 free(isns_config.ic_source_name);
1003 isns_config.ic_source_name = NULL;
1004 return rc;
1007 static void start_isns(const char *def_iname, struct discovery_rec *drec,
1008 int poll_inval)
1010 int rc, port = drec->port;
1012 if (port < 0)
1013 port = ISNS_DEFAULT_PORT;
1015 rc = isns_eventd(def_iname, drec->address, port, poll_inval);
1016 log_debug(1, "start isns done %d.", rc);
1017 discoveryd_stop();
1020 /* SendTargets */
1021 static void __do_st_disc_and_login(struct discovery_rec *drec)
1023 struct list_head rec_list, setup_ifaces;
1024 struct iface_rec *iface, *tmp_iface;
1025 int rc;
1027 INIT_LIST_HEAD(&rec_list);
1028 INIT_LIST_HEAD(&setup_ifaces);
1031 * The disc daemon will try again in poll_interval secs
1032 * so no need to retry here
1034 drec->u.sendtargets.reopen_max = 0;
1036 iface_link_ifaces(&setup_ifaces);
1038 * disc code assumes this is not set and wants to use
1039 * the userspace IO code.
1041 ipc = NULL;
1043 rc = idbm_bind_ifaces_to_nodes(discovery_sendtargets, drec,
1044 &setup_ifaces, &rec_list);
1045 if (rc) {
1046 log_error("Could not perform SendTargets to %s:%d.",
1047 drec->address, drec->port);
1048 goto free_ifaces;
1051 update_sessions(&rec_list, NULL, NULL);
1053 free_ifaces:
1054 list_for_each_entry_safe(iface, tmp_iface, &setup_ifaces, list) {
1055 list_del(&iface->list);
1056 free(iface);
1060 static void do_st_disc_and_login(const char *def_iname,
1061 struct discovery_rec *drec, int poll_inval)
1063 if (poll_inval < 0)
1064 poll_inval = DISC_DEF_POLL_INVL;
1066 do {
1067 __do_st_disc_and_login(drec);
1068 if (!poll_inval)
1069 break;
1070 } while (!stop_discoveryd && !sleep(poll_inval));
1072 discoveryd_stop();
1075 static int st_start(void *data, struct discovery_rec *drec)
1077 log_debug(1, "st_start %s:%d %d", drec->address, drec->port,
1078 drec->u.sendtargets.use_discoveryd);
1079 if (!drec->u.sendtargets.use_discoveryd)
1080 return ISCSI_ERR_INVAL;
1082 fork_disc(NULL, drec, drec->u.sendtargets.discoveryd_poll_inval,
1083 do_st_disc_and_login);
1084 return 0;
1087 static void discoveryd_st_start(void)
1089 idbm_for_each_st_drec(NULL, st_start);
1092 static int isns_start(void *data, struct discovery_rec *drec)
1094 log_debug(1, "isns_start %s:%d %d", drec->address, drec->port,
1095 drec->u.isns.use_discoveryd);
1096 if (!drec->u.isns.use_discoveryd)
1097 return ISCSI_ERR_INVAL;
1099 fork_disc(data, drec, drec->u.isns.discoveryd_poll_inval, start_isns);
1100 return 0;
1103 static void discoveryd_isns_start(const char *def_iname)
1105 idbm_for_each_isns_drec((void *)def_iname, isns_start);
1108 void discoveryd_start(const char *def_iname)
1110 discoveryd_isns_start(def_iname);
1111 discoveryd_st_start();