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.
28 #include <sys/types.h>
31 #include "discovery.h"
34 #include "iscsi_proto.h"
37 #include "session_mgmt.h"
38 #include "iscsi_util.h"
39 #include "event_poll.h"
41 #include "session_mgmt.h"
42 #include "session_info.h"
43 #include "isns-proto.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
;
71 list_for_each_entry(rec
, rec_list
, list
) {
72 if (iscsi_match_session(rec
, info
))
73 return iscsi_logout_portal(info
, list
);
78 static void discoveryd_stop(void)
80 struct node_rec
*rec
, *tmp_rec
;
83 if (list_empty(&iscsi_targets
))
87 * User requested to just login and exit.
92 iscsi_logout_portals(&iscsi_targets
, &nr_found
, 1, logout_session
);
93 list_for_each_entry_safe(rec
, tmp_rec
, &iscsi_targets
, list
) {
102 static void catch_signal(int signo
)
104 log_debug(1, "%d caught signal -%d...", signo
, getpid());
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
);
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
;
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
,
154 if (targetname
&& strcmp(rec
->name
, targetname
))
158 if (strlen(rec
->iface
.iname
) &&
159 strcmp(rec
->iface
.iname
, iname
))
161 else if (strcmp(iname
, isns_config
.ic_source_name
))
165 log_debug(5, "Matched %s %s, checking if in new targets.",
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
);
187 list_del(&rec
->list
);
192 if (!list_empty(&stale_rec_list
)) {
193 iscsi_logout_portals(&stale_rec_list
, &nr_found
, 0,
195 list_for_each_entry_safe(rec
, tmp_rec
, &stale_rec_list
, list
) {
196 list_del(&rec
->list
);
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
)
209 setup_signal_handler();
210 do_disc_and_login(def_iname
, drec
, poll_inval
);
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
);
217 shutdown_callback(pid
);
218 log_debug(1, "iSCSI disc and login helper pid=%d", pid
);
223 struct isns_node_list
{
224 isns_source_t
*source
;
225 struct list_head list
;
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;
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
);
246 return ISCSI_ERR_NO_OBJS_FOUND
;
248 iflist
= calloc(nportals
, sizeof(isns_portal_info_t
));
250 log_error("Unable to allocate %d portals.", nportals
);
251 return ISCSI_ERR_NOMEM
;
254 nportals
= isns_enumerate_portals(iflist
, nportals
);
256 log_error("Unable to enumerate portals - "
257 "no usable interfaces found\n");
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);
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);
277 free(isns_entity_id
);
278 isns_entity_id
= NULL
;
280 log_error("Could not get hostname for EID.");
285 entity
= isns_create_entity(ISNS_ENTITY_PROTOCOL_ISCSI
, isns_entity_id
);
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
);
297 rc
= ISCSI_ERR_NOMEM
;
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
;
309 list_for_each_entry(node
, &isns_initiators
, list
) {
310 inode
= isns_create_storage_node2(node
->source
,
311 ISNS_ISCSI_INITIATOR_MASK
,
314 rc
= ISCSI_ERR_NOMEM
;
317 isns_object_list_append(objs
, inode
);
322 isns_object_list_destroy(objs
);
326 struct isns_qry_data
{
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;
338 if (qry_data
->iname
) {
339 if (!strcmp(qry_data
->iname
, isns_config
.ic_source_name
))
342 if ((!is_def_iname
|| strlen(iface
->iname
)) &&
343 strcmp(iface
->iname
, qry_data
->iname
))
346 iname
= qry_data
->iname
;
348 if (strlen(iface
->iname
))
349 iname
= iface
->iname
;
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
;
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
,
374 log_error("Could not perform iSNS DevAttrQuery for node %s.",
378 update_sessions(&rec_list
, targetname
, iname
);
382 list_for_each_entry_safe(iface
, tmp_iface
, &ifaces
, list
) {
383 list_del(&iface
->list
);
390 static void isns_reg_refresh_with_disc(void *data
)
394 log_debug(1, "Refresh registration using DevAttrQuery");
397 * it is ok to block here since we are not expecting SCNs
402 * Some servers do not support SCNs so we ping
403 * the server by doing discovery.
405 rc
= isns_disc_new_portals(NULL
, NULL
);
407 log_debug(4, "Registration refresh using DevAttrQuery "
408 "failed (retires %d) err %d", retries
, rc
);
413 } while (rc
&& retries
< 3);
417 * Try to reregister from scratch.
419 isns_register_nodes
= 1;
422 struct isns_refresh_data
{
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
);
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
)
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
);
458 log_error("EID Query respond could not match xid");
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
,
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
;
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 "
495 isns_free_refresh_data(refresh_data
);
496 isns_register_nodes
= 1;
500 clnt
= isns_create_default_client(NULL
);
502 log_error("iSNS registration refresh failed. Could not "
503 "connect to server.");
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
;
520 isns_attr_list_append_string(&qry_key
, ISNS_TAG_ENTITY_IDENTIFIER
,
522 qry
= isns_create_query(clnt
, &qry_key
);
523 isns_attr_list_destroy(&qry_key
);
526 isns_query_request_attr_tag(qry
, ISNS_TAG_ENTITY_PROTOCOL
);
527 refresh_data
->qry
= qry
;
530 timeout
= (refresh_data
->start_time
+ refresh_data
->interval
) -
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
;
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
);
559 log_error("Unable to extract object list from "
560 "registration response: %s\n",
561 isns_strerror(status
));
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
))
571 if (isns_object_get_uint32(obj
, ISNS_TAG_REGISTRATION_PERIOD
,
579 refresh_data
= calloc(1, sizeof(*refresh_data
));
581 rc
= ISCSI_ERR_NOMEM
;
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.",
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
,
615 * user wants to use server value so we just ping
618 isns_add_oneshot_timer(isns_refresh_interval
,
619 isns_reg_refresh_by_eid_qry
,
621 log_debug(5, "Got registration period of %u "
622 "internval. Using interval of %u",
623 interval
, isns_refresh_interval
);
627 isns_object_list_destroy(&objs
);
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
,
640 struct isns_node_list
*node
;
641 isns_object_t
*entity
= NULL
;
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
];
655 reg
= isns_create_registration(clnt
, entity
);
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
, ®
);
664 if (status
!= ISNS_SUCCESS
) {
665 log_error("Could not register with iSNS server: %s",
666 isns_strerror(status
));
670 log_debug(4, "Registered objs");
675 rc
= isns_setup_registration_refresh(reg
, poll_inval
);
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
,
689 isns_cancel_refresh_timers();
690 rc
= ISCSI_ERR_NOMEM
;
694 status
= isns_simple_call(clnt
->ic_socket
, ®
);
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();
710 log_debug(4, "Registered %s for SCNs",
711 isns_source_name(node
->source
));
715 isns_simple_free(reg
);
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
;
727 clnt
= isns_create_default_client(NULL
);
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
;
742 rc
= isns_build_objs(&portal_info
, &objs
);
746 rc
= isns_register_objs(clnt
, &objs
, poll_inval
);
747 isns_object_list_destroy(&objs
);
749 log_warning("iSNS: Registered network entity with EID %s with "
750 "server.", isns_entity_id
);
753 isns_client_destroy(clnt
);
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
)))
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
);
777 node
= calloc(1, sizeof(*node
));
779 isns_source_release(source
);
782 INIT_LIST_HEAD(&node
->list
);
783 node
->source
= source
;
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
;
794 INIT_LIST_HEAD(&ifaces
);
795 iface_link_ifaces(&ifaces
);
798 node
= isns_create_node(def_iname
);
800 rc
= ISCSI_ERR_NOMEM
;
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
);
811 rc
= ISCSI_ERR_NOMEM
;
814 list_add_tail(&node
->list
, &isns_initiators
);
821 list_for_each_entry_safe(node
, tmp_node
, &isns_initiators
, list
) {
822 list_del(&node
->list
);
827 list_for_each_entry_safe(iface
, tmp_iface
, &ifaces
, list
) {
828 list_del(&iface
->list
);
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
,
849 isns_free_refresh_data(refresh_data
);
852 static int isns_scn_recv(isns_server_t
*svr
, isns_socket_t
*svr_sock
,
855 isns_message_t
*msg
, *rsp
;
856 struct timeval timeout
= { 0, 0 };
857 time_t now
, then
, next_timeout
;
858 unsigned int function
;
861 log_debug(1, "isns_scn_recv");
863 while (!stop_discoveryd
) {
864 /* reap disc/login procs */
867 * timer func could force a scn registration so check timers
870 then
= isns_run_timers();
872 next_timeout
= now
+ 3600;
873 if (then
&& then
< next_timeout
)
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
);
889 isns_disc_new_portals(NULL
, NULL
);
892 isns_register_nodes
= 0;
894 * the scn reg may have added timers or changed
895 * timeout values so recheck.
900 /* Determine how long we can sleep */
901 if (next_timeout
<= now
)
903 timeout
.tv_sec
= next_timeout
- now
;
905 if ((msg
= isns_recv_message(&timeout
)) == NULL
)
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
);
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");
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
,
937 static isns_socket_t
*svr_sock
;
940 struct isns_node_list
*tmp_node
, *node
;
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
;
962 isns_write_pidfile(isns_config
.ic_pidfile
);
964 db
= isns_db_open(NULL
);
966 log_error("iSNS setup failed. Could not create db.");
967 rc
= ISCSI_ERR_NOMEM
;
970 svr
= isns_create_server(node
->source
, db
, &isns_callback_service_ops
);
972 log_error("iSNS setup failed. Could not create server.");
973 rc
= ISCSI_ERR_TRANS
;
976 isns_server_set_scn_callback(svr
, isns_scn_callback
);
978 svr_sock
= isns_create_server_socket(NULL
, NULL
, AF_INET6
, SOCK_DGRAM
);
980 log_error("iSNS setup failed. Could not create server socket.");
981 rc
= ISCSI_ERR_TRANS
;
985 rc
= isns_scn_recv(svr
, svr_sock
, poll_inval
);
986 isns_cancel_refresh_timers();
988 isns_clear_refresh_list();
990 list_for_each_entry_safe(node
, tmp_node
, &isns_initiators
, list
) {
991 list_del(&node
->list
);
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
;
1007 static void start_isns(const char *def_iname
, struct discovery_rec
*drec
,
1010 int rc
, port
= drec
->port
;
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
);
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
;
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.
1043 rc
= idbm_bind_ifaces_to_nodes(discovery_sendtargets
, drec
,
1044 &setup_ifaces
, &rec_list
);
1046 log_error("Could not perform SendTargets to %s:%d.",
1047 drec
->address
, drec
->port
);
1051 update_sessions(&rec_list
, NULL
, NULL
);
1054 list_for_each_entry_safe(iface
, tmp_iface
, &setup_ifaces
, list
) {
1055 list_del(&iface
->list
);
1060 static void do_st_disc_and_login(const char *def_iname
,
1061 struct discovery_rec
*drec
, int poll_inval
)
1064 poll_inval
= DISC_DEF_POLL_INVL
;
1067 __do_st_disc_and_login(drec
);
1070 } while (!stop_discoveryd
&& !sleep(poll_inval
));
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
);
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
);
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();