2 * iSCSI Administration Utility
4 * Copyright (C) 2004 Dmitry Yusupov, Alex Aizman
5 * Copyright (C) 2006 Mike Christie
6 * Copyright (C) 2006 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.
31 #include "initiator.h"
32 #include "discovery.h"
36 #include "iscsi_util.h"
37 #include "transport.h"
39 #include "iscsi_sysfs.h"
41 #include "iscsi_settings.h"
42 #include "fw_context.h"
44 #include "session_info.h"
47 #include "idbm_fields.h"
48 #include "session_mgmt.h"
49 #include "iscsid_req.h"
50 #include "isns-proto.h"
51 #include "iscsi_err.h"
53 static char program_name
[] = "iscsiadm";
54 static char config_file
[TARGET_NAME_MAXLEN
];
55 extern struct iscsi_ipc
*ipc
;
73 OP_NONPERSISTENT
= 0x10
76 static struct option
const long_options
[] =
78 {"mode", required_argument
, NULL
, 'm'},
79 {"portal", required_argument
, NULL
, 'p'},
80 {"targetname", required_argument
, NULL
, 'T'},
81 {"interface", required_argument
, NULL
, 'I'},
82 {"op", required_argument
, NULL
, 'o'},
83 {"type", required_argument
, NULL
, 't'},
84 {"name", required_argument
, NULL
, 'n'},
85 {"value", required_argument
, NULL
, 'v'},
86 {"host", required_argument
, NULL
, 'H'},
87 {"sid", required_argument
, NULL
, 'r'},
88 {"rescan", no_argument
, NULL
, 'R'},
89 {"print", required_argument
, NULL
, 'P'},
90 {"discover", no_argument
, NULL
, 'D'},
91 {"login", no_argument
, NULL
, 'l'},
92 {"loginall", required_argument
, NULL
, 'L'},
93 {"logout", no_argument
, NULL
, 'u'},
94 {"logoutall", required_argument
, NULL
, 'U'},
95 {"stats", no_argument
, NULL
, 's'},
96 {"killiscsid", required_argument
, NULL
, 'k'},
97 {"debug", required_argument
, NULL
, 'd'},
98 {"show", no_argument
, NULL
, 'S'},
99 {"version", no_argument
, NULL
, 'V'},
100 {"help", no_argument
, NULL
, 'h'},
103 static char *short_options
= "RlDVhm:p:P:T:H:I:U:k:L:d:r:n:v:o:sSt:u";
105 static void usage(int status
)
108 fprintf(stderr
, "Try `%s --help' for more information.\n",
112 iscsiadm -m discoverydb [ -hV ] [ -d debug_level ] [-P printlevel] [ -t type -p ip:port -I ifaceN ... [ -Dl ] ] | [ [ -p ip:port -t type] \
113 [ -o operation ] [ -n name ] [ -v value ] [ -lD ] ] \n\
114 iscsiadm -m discovery [ -hV ] [ -d debug_level ] [-P printlevel] [ -t type -p ip:port -I ifaceN ... [ -l ] ] | [ [ -p ip:port ] [ -l | -D ] ] \n\
115 iiscsiadm -m node [ -hV ] [ -d debug_level ] [ -P printlevel ] [ -L all,manual,automatic ] [ -U all,manual,automatic ] [ -S ] [ [ -T targetname -p ip:port -I ifaceN ] [ -l | -u | -R | -s] ] \
116 [ [ -o operation ] [ -n name ] [ -v value ] ]\n\
117 iscsiadm -m session [ -hV ] [ -d debug_level ] [ -P printlevel] [ -r sessionid | sysfsdir [ -R | -u | -s ] [ -o operation ] [ -n name ] [ -v value ] ]\n\
118 iscsiadm -m iface [ -hV ] [ -d debug_level ] [ -P printlevel ] [ -I ifacename ] [ [ -o operation ] [ -n name ] [ -v value ] ]\n\
119 iscsiadm -m fw [ -l ]\n\
120 iscsiadm -m host [ -P printlevel ] [ -H hostno ]\n\
121 iscsiadm -k priority\n");
131 if (!strcmp("new", str
))
133 else if (!strcmp("delete", str
))
135 else if (!strcmp("update", str
))
137 else if (!strcmp("show", str
))
139 else if (!strcmp("nonpersistent", str
))
140 op
= OP_NONPERSISTENT
;
148 str_to_mode(char *str
)
152 if (!strcmp("discovery", str
))
153 mode
= MODE_DISCOVERY
;
154 else if (!strcmp("discoverydb", str
))
155 mode
= MODE_DISCOVERYDB
;
156 else if (!strcmp("node", str
))
158 else if (!strcmp("session", str
))
160 else if (!strcmp("iface", str
))
162 else if (!strcmp("fw", str
))
164 else if (!strcmp("host", str
))
173 str_to_type(char *str
)
177 if (!strcmp("sendtargets", str
) ||
179 type
= DISCOVERY_TYPE_SENDTARGETS
;
180 else if (!strcmp("slp", str
))
181 type
= DISCOVERY_TYPE_SLP
;
182 else if (!strcmp("isns", str
))
183 type
= DISCOVERY_TYPE_ISNS
;
184 else if (!strcmp("fw", str
))
185 type
= DISCOVERY_TYPE_FW
;
192 static void kill_iscsid(int priority
)
199 * We only support SIGTERM like stoppage of iscsid for now.
200 * In the future we can do something where we try go finish
201 * up operations like login, error handling, etc, before
202 * iscsid is stopped, and we can add different values to indicate
203 * that the user wants iscsid to log out existing sessions before
207 log_error("Invalid iscsid priority %d. Priority must be 0.",
212 memset(&req
, 0, sizeof(req
));
213 req
.command
= MGMT_IPC_IMMEDIATE_STOP
;
214 rc
= iscsid_exec_req(&req
, &rsp
, 0);
216 iscsi_err_print_msg(rc
);
217 log_error("Could not stop iscsid. Trying sending iscsid "
218 "SIGTERM or SIGKILL signals manually\n");
223 * TODO: we can display how the ifaces are related to node records.
224 * And we can add a scsi_host mode which would display how
225 * sessions are related to hosts
226 * (scsi_host and iscsi_sessions are the currently running instance of
227 * a iface or node record).
229 static int print_ifaces(struct iface_rec
*iface
, int info_level
)
231 int err
, num_found
= 0;
233 switch (info_level
) {
236 err
= iface_for_each_iface(NULL
, 0, &num_found
,
241 err
= iface_conf_read(iface
);
243 log_error("Could not read iface %s.\n",
247 iface_print_tree(NULL
, iface
);
250 err
= iface_for_each_iface(NULL
, 0, &num_found
,
254 log_error("Invalid info level %d. Try 0 - 1.", info_level
);
255 return ISCSI_ERR_INVAL
;
259 log_error("No interfaces found.");
260 err
= ISCSI_ERR_NO_OBJS_FOUND
;
266 match_startup_mode(node_rec_t
*rec
, char *mode
)
268 if ((!strcmp(mode
, "automatic") &&
269 rec
->startup
== ISCSI_STARTUP_AUTOMATIC
) ||
270 (!strcmp(mode
, "onboot") &&
271 rec
->startup
== ISCSI_STARTUP_ONBOOT
) ||
272 (!strcmp(mode
, "manual") &&
273 rec
->startup
== ISCSI_STARTUP_MANUAL
) ||
274 !strcmp(mode
, "all"))
277 /* support conn or session startup params */
278 if ((!strcmp(mode
, "automatic") &&
279 rec
->conn
[0].startup
== ISCSI_STARTUP_AUTOMATIC
) ||
280 (!strcmp(mode
, "onboot") &&
281 rec
->conn
[0].startup
== ISCSI_STARTUP_ONBOOT
) ||
282 (!strcmp(mode
, "manual") &&
283 rec
->conn
[0].startup
== ISCSI_STARTUP_MANUAL
) ||
284 !strcmp(mode
, "all"))
291 for_each_session(struct node_rec
*rec
, iscsi_sysfs_session_op_fn
*fn
)
293 int err
, num_found
= 0;
295 if (rec
&& rec
->session
.info
) {
297 err
= fn(rec
, rec
->session
.info
);
299 err
= iscsi_sysfs_for_each_session(rec
, &num_found
, fn
);
302 log_error("Could not execute operation on all sessions: %s",
303 iscsi_err_to_str(err
));
304 else if (!num_found
) {
305 log_error("No session found.");
306 err
= ISCSI_ERR_NO_OBJS_FOUND
;
312 static int link_recs(void *data
, struct node_rec
*rec
)
314 struct list_head
*list
= data
;
315 struct node_rec
*rec_copy
;
317 rec_copy
= calloc(1, sizeof(*rec_copy
));
319 return ISCSI_ERR_NOMEM
;
320 memcpy(rec_copy
, rec
, sizeof(*rec_copy
));
321 INIT_LIST_HEAD(&rec_copy
->list
);
322 list_add_tail(&rec_copy
->list
, list
);
327 __logout_by_startup(void *data
, struct list_head
*list
,
328 struct session_info
*info
)
333 memset(&rec
, 0, sizeof(node_rec_t
));
334 if (idbm_rec_read(&rec
, info
->targetname
, info
->tpgt
,
335 info
->persistent_address
,
336 info
->persistent_port
, &info
->iface
)) {
338 * this is due to a HW driver or some other driver
341 log_debug(7, "could not read data for [%s,%s.%d]\n",
342 info
->targetname
, info
->persistent_address
,
343 info
->persistent_port
);
347 /* multiple drivers could be connected to the same portal */
348 if (strcmp(rec
.iface
.transport_name
, info
->iface
.transport_name
))
351 * we always skip on boot because if the user killed this on
352 * they would not be able to do anything
354 if (rec
.startup
== ISCSI_STARTUP_ONBOOT
)
357 if (match_startup_mode(&rec
, mode
))
360 return iscsi_logout_portal(info
, list
);
364 logout_by_startup(char *mode
)
369 if (!mode
|| !(!strcmp(mode
, "automatic") || !strcmp(mode
, "all") ||
370 !strcmp(mode
,"manual"))) {
371 log_error("Invalid logoutall option %s.", mode
);
372 usage(ISCSI_ERR_INVAL
);
373 return ISCSI_ERR_INVAL
;
376 rc
= iscsi_logout_portals(mode
, &nr_found
, 1, __logout_by_startup
);
377 if (rc
== ISCSI_ERR_NO_OBJS_FOUND
)
378 log_error("No matching sessions found");
383 * TODO: merged this and logout into the common for_each_matched_rec by making
384 * the matching more generic
387 __login_by_startup(void *data
, struct list_head
*list
, struct node_rec
*rec
)
391 if (match_startup_mode(rec
, mode
))
394 return iscsi_login_portal(NULL
, list
, rec
);
398 login_by_startup(char *mode
)
400 int nr_found
= 0, err
, rc
;
401 struct list_head rec_list
;
403 if (!mode
|| !(!strcmp(mode
, "automatic") || !strcmp(mode
, "all") ||
404 !strcmp(mode
,"manual") || !strcmp(mode
, "onboot"))) {
405 log_error("Invalid loginall option %s.", mode
);
406 usage(ISCSI_ERR_INVAL
);
407 return ISCSI_ERR_INVAL
;
410 INIT_LIST_HEAD(&rec_list
);
411 err
= idbm_for_each_rec(&nr_found
, &rec_list
, link_recs
);
412 if (err
&& !list_empty(&rec_list
))
413 /* log msg and try to log into what we found */
414 log_error("Could not read all records: %s",
415 iscsi_err_to_str(err
));
416 else if (err
&& list_empty(&rec_list
)) {
417 log_error("Could not read node DB: %s.",
418 iscsi_err_to_str(err
));
420 } else if (list_empty(&rec_list
)) {
421 log_error("No records found");
422 return ISCSI_ERR_NO_OBJS_FOUND
;
426 err
= iscsi_login_portals(mode
, &nr_found
, 1, &rec_list
,
429 log_error("Could not log into all portals");
437 * iscsi_logout_matched_portal - logout of targets matching the rec info
438 * @data: record to session with
439 * @list: list to add logout rec to
440 * @info: session to match with rec
442 static int iscsi_logout_matched_portal(void *data
, struct list_head
*list
,
443 struct session_info
*info
)
445 struct node_rec
*pattern_rec
= data
;
446 struct iscsi_transport
*t
;
448 t
= iscsi_sysfs_get_transport_by_sid(info
->sid
);
452 if (!iscsi_match_session(pattern_rec
, info
))
455 /* we do not support this yet */
456 if (t
->caps
& CAP_FW_DB
) {
457 log_error("Could not logout session of [sid: %d, "
458 "target: %s, portal: %s,%d].", info
->sid
,
459 info
->targetname
, info
->persistent_address
,
461 log_error("Logout not supported for driver: %s.", t
->name
);
464 return iscsi_logout_portal(info
, list
);
467 static int rec_match_fn(void *data
, node_rec_t
*rec
)
469 struct rec_op_data
*op_data
= data
;
471 if (!__iscsi_match_session(op_data
->match_rec
, rec
->name
,
472 rec
->conn
[0].address
, rec
->conn
[0].port
,
473 &rec
->iface
, rec
->session
.sid
))
475 return op_data
->fn(op_data
->data
, rec
);
478 static int __for_each_matched_rec(int verbose
, struct node_rec
*rec
,
479 void *data
, idbm_iface_op_fn
*fn
)
481 struct rec_op_data op_data
;
482 int nr_found
= 0, rc
;
484 memset(&op_data
, 0, sizeof(struct rec_op_data
));
486 op_data
.match_rec
= rec
;
489 rc
= idbm_for_each_rec(&nr_found
, &op_data
, rec_match_fn
);
492 log_error("Could not execute operation on all "
493 "records: %s", iscsi_err_to_str(rc
));
494 } else if (!nr_found
) {
496 log_error("No records found");
497 rc
= ISCSI_ERR_NO_OBJS_FOUND
;
503 static int for_each_matched_rec(struct node_rec
*rec
, void *data
,
504 idbm_iface_op_fn
*fn
)
506 return __for_each_matched_rec(1, rec
, data
, fn
);
510 static int login_portals(struct node_rec
*pattern_rec
)
512 struct list_head rec_list
;
513 int nr_found
, rc
, err
;
515 INIT_LIST_HEAD(&rec_list
);
516 err
= for_each_matched_rec(pattern_rec
, &rec_list
, link_recs
);
517 if (err
== ISCSI_ERR_NO_OBJS_FOUND
)
519 else if (err
&& list_empty(&rec_list
))
523 /* if there is an err but some recs then try to login to what we have */
525 err
= iscsi_login_portals(pattern_rec
, &nr_found
, 1, &rec_list
,
528 log_error("Could not log into all portals");
536 static int print_nodes(int info_level
, struct node_rec
*rec
)
538 struct node_rec tmp_rec
;
541 switch (info_level
) {
544 rc
= for_each_matched_rec(rec
, NULL
, idbm_print_node_flat
);
547 memset(&tmp_rec
, 0, sizeof(node_rec_t
));
548 rc
= for_each_matched_rec(rec
, &tmp_rec
,
549 idbm_print_node_and_iface_tree
);
552 log_error("Invalid info level %d. Try 0 or 1.", info_level
);
553 rc
= ISCSI_ERR_INVAL
;
559 static char *get_config_file(void)
565 memset(&req
, 0, sizeof(req
));
566 req
.command
= MGMT_IPC_CONFIG_FILE
;
568 rc
= iscsid_exec_req(&req
, &rsp
, 1);
572 if (rsp
.u
.config
.var
[0] != '\0') {
573 strcpy(config_file
, rsp
.u
.config
.var
);
580 static int rescan_portal(void *data
, struct session_info
*info
)
584 if (!iscsi_match_session(data
, info
))
587 printf("Rescanning session [sid: %d, target: %s, portal: "
588 "%s,%d]\n", info
->sid
, info
->targetname
,
589 info
->persistent_address
, info
->port
);
591 host_no
= iscsi_sysfs_get_host_no_from_sid(info
->sid
, &err
);
593 log_error("Could not rescan session sid %d.", info
->sid
);
596 /* rescan each device to pick up size changes */
597 iscsi_sysfs_for_each_device(NULL
, host_no
, info
->sid
,
598 iscsi_sysfs_rescan_device
);
599 /* now scan for new devices */
600 iscsi_sysfs_scan_host(host_no
, 0);
605 session_stats(void *data
, struct session_info
*info
)
611 if (!iscsi_match_session(data
, info
))
614 memset(&req
, 0, sizeof(req
));
615 req
.command
= MGMT_IPC_SESSION_STATS
;
616 req
.u
.session
.sid
= info
->sid
;
618 rc
= iscsid_exec_req(&req
, &rsp
, 1);
622 printf("Stats for session [sid: %d, target: %s, portal: "
624 info
->sid
, info
->targetname
, info
->persistent_address
,
627 printf( "iSCSI SNMP:\n"
629 "\ttxdata_octets: %lld\n"
630 "\trxdata_octets: %lld\n"
633 "\tscsicmd_pdus: %u\n"
634 "\ttmfcmd_pdus: %u\n"
637 "\tdataout_pdus: %u\n"
638 "\tlogout_pdus: %u\n"
642 "\tscsirsp_pdus: %u\n"
643 "\ttmfrsp_pdus: %u\n"
644 "\ttextrsp_pdus: %u\n"
645 "\tdatain_pdus: %u\n"
646 "\tlogoutrsp_pdus: %u\n"
652 "\ttimeout_err: %u\n",
653 (unsigned long long)rsp
.u
.getstats
.stats
.txdata_octets
,
654 (unsigned long long)rsp
.u
.getstats
.stats
.rxdata_octets
,
656 rsp
.u
.getstats
.stats
.noptx_pdus
,
657 rsp
.u
.getstats
.stats
.scsicmd_pdus
,
658 rsp
.u
.getstats
.stats
.tmfcmd_pdus
,
659 rsp
.u
.getstats
.stats
.login_pdus
,
660 rsp
.u
.getstats
.stats
.text_pdus
,
661 rsp
.u
.getstats
.stats
.dataout_pdus
,
662 rsp
.u
.getstats
.stats
.logout_pdus
,
663 rsp
.u
.getstats
.stats
.snack_pdus
,
665 rsp
.u
.getstats
.stats
.noprx_pdus
,
666 rsp
.u
.getstats
.stats
.scsirsp_pdus
,
667 rsp
.u
.getstats
.stats
.tmfrsp_pdus
,
668 rsp
.u
.getstats
.stats
.textrsp_pdus
,
669 rsp
.u
.getstats
.stats
.datain_pdus
,
670 rsp
.u
.getstats
.stats
.logoutrsp_pdus
,
671 rsp
.u
.getstats
.stats
.r2t_pdus
,
672 rsp
.u
.getstats
.stats
.async_pdus
,
673 rsp
.u
.getstats
.stats
.rjt_pdus
,
675 rsp
.u
.getstats
.stats
.digest_err
,
676 rsp
.u
.getstats
.stats
.timeout_err
);
678 if (rsp
.u
.getstats
.stats
.custom_length
)
679 printf( "iSCSI Extended:\n");
681 for (i
= 0; i
< rsp
.u
.getstats
.stats
.custom_length
; i
++) {
682 printf("\t%s: %llu\n", rsp
.u
.getstats
.stats
.custom
[i
].desc
,
683 (unsigned long long)rsp
.u
.getstats
.stats
.custom
[i
].value
);
689 static int add_static_rec(int *found
, char *targetname
, int tpgt
,
690 char *ip
, int port
, struct iface_rec
*iface
)
693 discovery_rec_t
*drec
;
696 rec
= calloc(1, sizeof(*rec
));
698 log_error("Could not allocate memory for node addition");
699 rc
= ISCSI_ERR_NOMEM
;
703 drec
= calloc(1, sizeof(*drec
));
705 log_error("Could not allocate memory for node addition");
706 rc
= ISCSI_ERR_NOMEM
;
709 drec
->type
= DISCOVERY_TYPE_STATIC
;
711 idbm_node_setup_from_conf(rec
);
712 strlcpy(rec
->name
, targetname
, TARGET_NAME_MAXLEN
);
714 rec
->conn
[0].port
= port
;
715 strlcpy(rec
->conn
[0].address
, ip
, NI_MAXHOST
);
718 rc
= iface_conf_read(iface
);
720 log_error("Could not read iface %s. Error %d",
725 iface_copy(&rec
->iface
, iface
);
728 rc
= idbm_add_node(rec
, drec
, 1);
731 printf("New iSCSI node [%s:" iface_fmt
" %s,%d,%d %s] added\n",
732 rec
->iface
.transport_name
, iface_str(&rec
->iface
),
733 ip
, port
, tpgt
, targetname
);
742 static int add_static_portal(int *found
, void *data
,
743 char *targetname
, int tpgt
, char *ip
, int port
)
745 node_rec_t
*rec
= data
;
747 if (strlen(rec
->conn
[0].address
) &&
748 strcmp(rec
->conn
[0].address
, ip
))
751 if (rec
->conn
[0].port
!= -1 && rec
->conn
[0].port
!= port
)
754 return add_static_rec(found
, targetname
, tpgt
, ip
, port
,
758 static int add_static_node(int *found
, void *data
,
761 node_rec_t
*rec
= data
;
763 if (!strlen(rec
->name
))
766 if (strcmp(rec
->name
, targetname
))
769 if (!strlen(rec
->conn
[0].address
))
772 return add_static_rec(found
, targetname
, rec
->tpgt
,
773 rec
->conn
[0].address
,
774 rec
->conn
[0].port
, &rec
->iface
);
776 return idbm_for_each_portal(found
, data
, add_static_portal
,
780 static int add_static_recs(struct node_rec
*rec
)
782 int rc
, nr_found
= 0;
784 rc
= idbm_for_each_node(&nr_found
, rec
, add_static_node
);
791 /* brand new target */
792 if (strlen(rec
->name
) && strlen(rec
->conn
[0].address
)) {
793 rc
= add_static_rec(&nr_found
, rec
->name
, rec
->tpgt
,
794 rec
->conn
[0].address
, rec
->conn
[0].port
,
800 log_error("Error while adding record: %s", iscsi_err_to_str(rc
));
805 * start sendtargets discovery process based on the
809 do_offload_sendtargets(discovery_rec_t
*drec
, int host_no
, int do_login
)
811 drec
->type
= DISCOVERY_TYPE_OFFLOAD_SENDTARGETS
;
812 return discovery_offload_sendtargets(host_no
, do_login
, drec
);
815 static int delete_node(void *data
, struct node_rec
*rec
)
817 if (iscsi_check_for_running_session(rec
)) {
819 * We could log out the session for the user, but if
820 * the session is being used the user may get something
821 * they were not expecting (FS errors and a read only
824 log_error("This command will remove the record [iface: %s, "
825 "target: %s, portal: %s,%d], but a session is "
826 "using it. Logout session then rerun command to "
827 "remove record.", rec
->iface
.name
, rec
->name
,
828 rec
->conn
[0].address
, rec
->conn
[0].port
);
829 return ISCSI_ERR_SESS_EXISTS
;
832 return idbm_delete_node(rec
);
835 static int delete_stale_rec(void *data
, struct node_rec
*rec
)
837 struct list_head
*new_rec_list
= data
;
838 struct node_rec
*new_rec
;
840 list_for_each_entry(new_rec
, new_rec_list
, list
) {
842 * We could also move this to idbm.c and instead of looping
843 * over every node just loop over disc to node links.
845 if (rec
->disc_type
!= new_rec
->disc_type
||
846 rec
->disc_port
!= new_rec
->disc_port
||
847 strcmp(rec
->disc_address
, new_rec
->disc_address
))
849 * if we are not from the same discovery source
854 if (__iscsi_match_session(rec
,
856 new_rec
->conn
[0].address
,
857 new_rec
->conn
[0].port
,
859 new_rec
->session
.sid
))
862 /* if there is a error we can continue on */
863 return delete_node(NULL
, rec
);
867 exec_disc_op_on_recs(discovery_rec_t
*drec
, struct list_head
*rec_list
,
868 int info_level
, int do_login
, int op
)
870 int rc
= 0, err
, found
= 0;
871 struct node_rec
*new_rec
, tmp_rec
;
873 /* clean up node db */
875 idbm_for_each_rec(&found
, rec_list
, delete_stale_rec
);
877 if (op
& OP_NEW
|| op
& OP_UPDATE
) {
878 /* now add/update records */
879 list_for_each_entry(new_rec
, rec_list
, list
) {
880 rc
= idbm_add_node(new_rec
, drec
, op
& OP_UPDATE
);
882 log_error("Could not add/update "
883 "[%s:" iface_fmt
" %s,%d,%d %s]",
884 new_rec
->iface
.transport_name
,
885 iface_str(&new_rec
->iface
),
886 new_rec
->conn
[0].address
,
887 new_rec
->conn
[0].port
,
888 new_rec
->tpgt
, new_rec
->name
);
892 memset(&tmp_rec
, 0, sizeof(node_rec_t
));
893 list_for_each_entry(new_rec
, rec_list
, list
) {
894 switch (info_level
) {
897 idbm_print_node_flat(NULL
, new_rec
);
900 idbm_print_node_and_iface_tree(&tmp_rec
, new_rec
);
908 err
= iscsi_login_portals(NULL
, &found
, 1, rec_list
,
916 do_software_sendtargets(discovery_rec_t
*drec
, struct list_head
*ifaces
,
917 int info_level
, int do_login
, int op
, int sync_drec
)
919 struct list_head rec_list
;
920 struct node_rec
*rec
, *tmp
;
923 INIT_LIST_HEAD(&rec_list
);
925 * compat: if the user did not pass any op then we do all
929 op
= OP_NEW
| OP_DELETE
| OP_UPDATE
;
931 drec
->type
= DISCOVERY_TYPE_SENDTARGETS
;
933 * we will probably want to know how a specific iface and discovery
934 * DB lined up, but for now just put all the targets found from
935 * a discovery portal in one place
937 if ((!(op
& OP_NONPERSISTENT
)) && sync_drec
) {
938 rc
= idbm_add_discovery(drec
);
940 log_error("Could not add new discovery record.");
945 rc
= idbm_bind_ifaces_to_nodes(discovery_sendtargets
, drec
, ifaces
,
948 log_error("Could not perform SendTargets discovery: %s",
949 iscsi_err_to_str(rc
));
951 } else if (list_empty(&rec_list
)) {
952 log_error("No portals found");
953 return ISCSI_ERR_NO_OBJS_FOUND
;
956 rc
= exec_disc_op_on_recs(drec
, &rec_list
, info_level
, do_login
, op
);
958 list_for_each_entry_safe(rec
, tmp
, &rec_list
, list
) {
959 list_del(&rec
->list
);
967 do_sendtargets(discovery_rec_t
*drec
, struct list_head
*ifaces
,
968 int info_level
, int do_login
, int op
, int sync_drec
)
970 struct iface_rec
*tmp
, *iface
;
972 struct iscsi_transport
*t
;
974 if (list_empty(ifaces
)) {
979 /* we allow users to mix hw and sw iscsi so we have to sort it out */
980 list_for_each_entry_safe(iface
, tmp
, ifaces
, list
) {
981 rc
= iface_conf_read(iface
);
983 log_error("Could not read iface info for %s. "
984 "Make sure a iface config with the file "
985 "name and iface.iscsi_ifacename %s is in %s.",
986 iface
->name
, iface
->name
, IFACE_CONFIG_DIR
);
987 list_del(&iface
->list
);
992 host_no
= iscsi_sysfs_get_host_no_from_hwinfo(iface
, &rc
);
993 if (rc
|| host_no
== -1) {
994 log_debug(1, "Could not match iface" iface_fmt
" to "
995 "host.", iface_str(iface
));
996 /* try software iscsi */
1000 t
= iscsi_sysfs_get_transport_by_hba(host_no
);
1002 log_error("Could not match hostno %d to "
1003 "transport. Dropping interface %s,"
1005 host_no
, iface
->transport_name
,
1006 iface_str(iface
), iface
->ipaddress
);
1007 list_del(&iface
->list
);
1012 if (t
->caps
& CAP_SENDTARGETS_OFFLOAD
) {
1013 do_offload_sendtargets(drec
, host_no
, do_login
);
1014 list_del(&iface
->list
);
1019 if (list_empty(ifaces
))
1020 return ISCSI_ERR_NO_OBJS_FOUND
;
1023 return do_software_sendtargets(drec
, ifaces
, info_level
, do_login
,
1027 static int do_isns(discovery_rec_t
*drec
, struct list_head
*ifaces
,
1028 int info_level
, int do_login
, int op
)
1030 struct list_head rec_list
;
1031 struct node_rec
*rec
, *tmp
;
1034 INIT_LIST_HEAD(&rec_list
);
1036 * compat: if the user did not pass any op then we do all
1040 op
= OP_NEW
| OP_DELETE
| OP_UPDATE
;
1042 drec
->type
= DISCOVERY_TYPE_ISNS
;
1044 rc
= idbm_bind_ifaces_to_nodes(discovery_isns
, drec
, ifaces
,
1047 log_error("Could not perform iSNS discovery: %s",
1048 iscsi_err_to_str(rc
));
1050 } else if (list_empty(&rec_list
)) {
1051 log_error("No portals found");
1052 return ISCSI_ERR_NO_OBJS_FOUND
;
1055 rc
= exec_disc_op_on_recs(drec
, &rec_list
, info_level
, do_login
, op
);
1057 list_for_each_entry_safe(rec
, tmp
, &rec_list
, list
) {
1058 list_del(&rec
->list
);
1066 verify_mode_params(int argc
, char **argv
, char *allowed
, int skip_m
)
1073 while ((ch
= getopt_long(argc
, argv
, short_options
,
1074 long_options
, &longindex
)) >= 0) {
1075 if (!strchr(allowed
, ch
)) {
1076 if (ch
== 'm' && skip_m
)
1086 static void catch_sigint( int signo
) {
1087 log_warning("caught SIGINT, exiting...");
1091 /* TODO: merge iter helpers and clean them up, so we can use them here */
1092 static int exec_iface_op(int op
, int do_show
, int info_level
,
1093 struct iface_rec
*iface
, char *name
, char *value
)
1095 struct db_set_param set_param
;
1096 struct node_rec
*rec
= NULL
;
1102 log_error("Could not add interface. No interface "
1107 rec
= idbm_create_rec(NULL
, -1, NULL
, -1, iface
, 0);
1108 if (rec
&& iscsi_check_for_running_session(rec
)) {
1109 rc
= ISCSI_ERR_SESS_EXISTS
;
1113 iface_setup_defaults(iface
);
1114 rc
= iface_conf_write(iface
);
1117 printf("New interface %s added\n", iface
->name
);
1120 log_error("Could not create new interface %s.", iface
->name
);
1124 log_error("Could not delete interface. No interface "
1126 return ISCSI_ERR_INVAL
;
1129 rec
= idbm_create_rec(NULL
, -1, NULL
, -1, iface
, 1);
1131 rc
= ISCSI_ERR_INVAL
;
1135 /* logout and delete records using it first */
1136 rc
= __for_each_matched_rec(0, rec
, NULL
, delete_node
);
1137 if (rc
&& rc
!= ISCSI_ERR_NO_OBJS_FOUND
)
1140 rc
= iface_conf_delete(iface
);
1144 printf("%s unbound and deleted.\n", iface
->name
);
1147 log_error("Could not delete iface %s: %s", iface
->name
,
1148 iscsi_err_to_str(rc
));
1151 if (!iface
|| !name
|| !value
) {
1152 log_error("Update requires name, value, and iface.");
1153 rc
= ISCSI_ERR_INVAL
;
1157 rec
= idbm_create_rec(NULL
, -1, NULL
, -1, iface
, 1);
1159 rc
= ISCSI_ERR_INVAL
;
1163 if (iscsi_check_for_running_session(rec
))
1164 log_warning("Updating iface while iscsi sessions "
1165 "are using it. You must logout the running "
1166 "sessions then log back in for the "
1167 "new settings to take affect.");
1169 if (!strcmp(name
, IFACE_ISCSINAME
)) {
1170 log_error("Can not update "
1171 "iface.iscsi_ifacename. Delete it, "
1172 "and then create a new one.");
1173 rc
= ISCSI_ERR_INVAL
;
1177 if (iface_is_bound_by_hwaddr(&rec
->iface
) &&
1178 !strcmp(name
, IFACE_NETNAME
)) {
1179 log_error("Can not update interface binding "
1180 "from hwaddress to net_ifacename. ");
1181 log_error("You must delete the interface and "
1182 "create a new one");
1183 rc
= ISCSI_ERR_INVAL
;
1187 if (iface_is_bound_by_netdev(&rec
->iface
) &&
1188 !strcmp(name
, IFACE_HWADDR
)) {
1189 log_error("Can not update interface binding "
1190 "from net_ifacename to hwaddress. ");
1191 log_error("You must delete the interface and "
1192 "create a new one");
1193 rc
= ISCSI_ERR_INVAL
;
1196 set_param
.name
= name
;
1197 set_param
.value
= value
;
1199 /* pass rec's iface because it has the db values */
1200 rc
= iface_conf_update(&set_param
, &rec
->iface
);
1204 rc
= __for_each_matched_rec(0, rec
, &set_param
,
1205 idbm_node_set_param
);
1206 if (rc
== ISCSI_ERR_NO_OBJS_FOUND
)
1211 printf("%s updated.\n", iface
->name
);
1214 log_error("Could not update iface %s: %s",
1215 iface
->name
, iscsi_err_to_str(rc
));
1218 if (!iface
|| (iface
&& info_level
> 0)) {
1219 if (op
== OP_NOOP
|| op
== OP_SHOW
)
1220 rc
= print_ifaces(iface
, info_level
);
1222 rc
= ISCSI_ERR_INVAL
;
1224 rc
= iface_conf_read(iface
);
1226 idbm_print_iface_info(&do_show
, iface
);
1228 log_error("Could not read iface %s (%d).",
1238 /* TODO cleanup arguments */
1239 static int exec_node_op(int op
, int do_login
, int do_logout
,
1240 int do_show
, int do_rescan
, int do_stats
,
1241 int info_level
, struct node_rec
*rec
,
1242 char *name
, char *value
)
1245 struct db_set_param set_param
;
1248 log_debug(2, "%s: %s:%s node [%s,%s,%d] sid %u", __FUNCTION__
,
1249 rec
->iface
.transport_name
, rec
->iface
.name
,
1250 rec
->name
, rec
->conn
[0].address
, rec
->conn
[0].port
,
1254 rc
= add_static_recs(rec
);
1259 rc
= for_each_session(rec
, rescan_portal
);
1264 rc
= for_each_session(rec
, session_stats
);
1268 if (do_login
&& do_logout
) {
1269 log_error("Invalid parameters. Both login and logout passed in");
1270 rc
= ISCSI_ERR_INVAL
;
1274 if ((do_login
|| do_logout
) && op
> OP_NOOP
) {
1275 log_error("Invalid parameters. Login/logout and op passed in");
1276 rc
= ISCSI_ERR_INVAL
;
1280 if ((!do_login
&& !do_logout
&& op
== OP_NOOP
) &&
1281 (!strlen(rec
->name
) && !strlen(rec
->conn
[0].address
) &&
1282 !strlen(rec
->iface
.name
))) {
1283 rc
= print_nodes(info_level
, rec
);
1288 rc
= login_portals(rec
);
1295 rc
= iscsi_logout_portals(rec
, &nr_found
, 1,
1296 iscsi_logout_matched_portal
);
1297 if (rc
== ISCSI_ERR_NO_OBJS_FOUND
)
1298 log_error("No matching sessions found");
1302 if (op
== OP_NOOP
|| (!do_login
&& !do_logout
&& op
== OP_SHOW
)) {
1303 rc
= for_each_matched_rec(rec
, &do_show
, idbm_print_node_info
);
1307 if (op
== OP_UPDATE
) {
1308 if (!name
|| !value
) {
1309 log_error("update requires name and value");
1310 rc
= ISCSI_ERR_INVAL
;
1314 /* compat - old tools used node and iface transport name */
1315 if (!strncmp(name
, "iface.", 6) &&
1316 strcmp(name
, "iface.transport_name")) {
1317 log_error("Cannot modify %s. Use iface mode to update "
1318 "this value.", name
);
1319 rc
= ISCSI_ERR_INVAL
;
1323 if (!strcmp(name
, "node.transport_name"))
1324 name
= "iface.transport_name";
1326 * tmp hack - we added compat crap above for the transport,
1327 * but want to fix Doran's issue in this release too. However
1328 * his patch is too harsh on many settings and we do not have
1329 * time to update apps so we have this tmp hack until we
1330 * can settle on a good interface that distros can use
1331 * and we can mark stable.
1333 if (!strcmp(name
, "iface.transport_name")) {
1334 if (iscsi_check_for_running_session(rec
)) {
1335 log_warning("Cannot modify node/iface "
1336 "transport name while a session "
1337 "is using it. Log out the session "
1338 "then update record.");
1339 rc
= ISCSI_ERR_SESS_EXISTS
;
1344 set_param
.name
= name
;
1345 set_param
.value
= value
;
1347 rc
= for_each_matched_rec(rec
, &set_param
, idbm_node_set_param
);
1349 } else if (op
== OP_DELETE
) {
1350 rc
= for_each_matched_rec(rec
, NULL
, delete_node
);
1353 log_error("operation is not supported.");
1354 rc
= ISCSI_ERR_INVAL
;
1361 static int exec_fw_disc_op(discovery_rec_t
*drec
, struct list_head
*ifaces
,
1362 int info_level
, int do_login
, int op
)
1364 struct list_head targets
, rec_list
, new_ifaces
;
1365 struct iface_rec
*iface
, *tmp_iface
;
1366 struct node_rec
*rec
, *tmp_rec
;
1369 INIT_LIST_HEAD(&targets
);
1370 INIT_LIST_HEAD(&rec_list
);
1371 INIT_LIST_HEAD(&new_ifaces
);
1373 * compat: if the user did not pass any op then we do all
1377 op
= OP_NEW
| OP_DELETE
| OP_UPDATE
;
1380 * if a user passed in ifaces then we use them and ignore the ibft
1383 if (!list_empty(ifaces
)) {
1384 list_for_each_entry_safe(iface
, tmp_iface
, ifaces
, list
) {
1385 rc
= iface_conf_read(iface
);
1387 log_error("Could not read iface info for %s. "
1388 "Make sure a iface config with the "
1389 "file name and iface.iscsi_ifacename "
1390 "%s is in %s.", iface
->name
,
1391 iface
->name
, IFACE_CONFIG_DIR
);
1392 list_del_init(&iface
->list
);
1397 goto discover_fw_tgts
;
1401 * Next, check if we see any offload cards. If we do then
1402 * we make a iface if needed.
1404 * Note1: if there is not a offload card we do not setup
1405 * software iscsi binding with the nic used for booting,
1406 * because we do not know if that was intended.
1408 * Note2: we assume that the user probably wanted to access
1409 * all targets through all the ifaces instead of being limited
1410 * to what you can export in ibft.
1412 rc
= fw_get_targets(&targets
);
1414 log_error("Could not get list of targets from firmware. "
1418 rc
= iface_create_ifaces_from_boot_contexts(&new_ifaces
, &targets
);
1421 if (!list_empty(&new_ifaces
))
1422 ifaces
= &new_ifaces
;
1425 rc
= idbm_bind_ifaces_to_nodes(discovery_fw
, drec
,
1428 log_error("Could not perform fw discovery.\n");
1430 rc
= exec_disc_op_on_recs(drec
, &rec_list
, info_level
,
1434 fw_free_targets(&targets
);
1436 list_for_each_entry_safe(iface
, tmp_iface
, &new_ifaces
, list
) {
1437 list_del(&iface
->list
);
1441 list_for_each_entry_safe(rec
, tmp_rec
, &rec_list
, list
) {
1442 list_del(&rec
->list
);
1448 static int exec_fw_op(discovery_rec_t
*drec
, struct list_head
*ifaces
,
1449 int info_level
, int do_login
, int op
)
1451 struct boot_context
*context
;
1452 struct list_head targets
, rec_list
;
1453 struct node_rec
*rec
;
1456 INIT_LIST_HEAD(&targets
);
1457 INIT_LIST_HEAD(&rec_list
);
1460 return exec_fw_disc_op(drec
, ifaces
, info_level
, do_login
, op
);
1462 /* The following ops do not interact with the DB */
1463 rc
= fw_get_targets(&targets
);
1465 log_error("Could not get list of targets from firmware. "
1471 list_for_each_entry(context
, &targets
, list
) {
1472 rec
= idbm_create_rec_from_boot_context(context
);
1474 log_error("Could not convert firmware info to "
1476 rc
= ISCSI_ERR_NOMEM
;
1480 iscsi_login_portal(NULL
, NULL
, rec
);
1484 list_for_each_entry(context
, &targets
, list
)
1485 fw_print_entry(context
);
1488 fw_free_targets(&targets
);
1492 static void setup_drec_defaults(int type
, char *ip
, int port
,
1493 struct discovery_rec
*drec
)
1496 case DISCOVERY_TYPE_ISNS
:
1497 idbm_isns_defaults(&drec
->u
.isns
);
1499 case DISCOVERY_TYPE_SENDTARGETS
:
1500 idbm_sendtargets_defaults(&drec
->u
.sendtargets
);
1503 log_error("Invalid disc type.");
1505 strlcpy(drec
->address
, ip
, sizeof(drec
->address
));
1511 * exec_discover - prep, add, read and exec discovery on drec
1512 * @type: discovery type
1515 * @ifaces: list of ifaces to bind to
1516 * @info_level: print level
1517 * @do_login: set to 1 if discovery function should also log into portals found
1518 * @do_discover: set to 1 if discovery was requested
1519 * @op: ops passed in by user
1520 * @drec: discovery rec struct
1522 * This function determines what type of op needs to be executed
1523 * and will read and add a drec, and perform discovery if needed.
1526 * Greater than 0 - error
1527 * 0 - op/discovery completed
1530 static int exec_discover(int disc_type
, char *ip
, int port
,
1531 struct list_head
*ifaces
, int info_level
,
1532 int do_login
, int do_discover
, int op
,
1533 struct discovery_rec
*drec
)
1538 log_error("Please specify portal as <ipaddr>[:<ipport>]");
1539 return ISCSI_ERR_INVAL
;
1542 if (op
& OP_NEW
&& !do_discover
) {
1543 setup_drec_defaults(disc_type
, ip
, port
, drec
);
1545 rc
= idbm_add_discovery(drec
);
1547 log_error("Could not add new discovery record.");
1550 printf("New discovery record for [%s,%d] added.\n", ip
,
1556 rc
= idbm_discovery_read(drec
, disc_type
, ip
, port
);
1559 log_error("Discovery record [%s,%d] not found.",
1564 /* Just add default rec for user */
1565 log_debug(1, "Discovery record [%s,%d] not found!",
1567 setup_drec_defaults(disc_type
, ip
, port
, drec
);
1568 if (!(op
& OP_NONPERSISTENT
)) {
1569 rc
= idbm_add_discovery(drec
);
1571 log_error("Could not add new discovery "
1576 } else if (!do_discover
)
1580 switch (disc_type
) {
1581 case DISCOVERY_TYPE_SENDTARGETS
:
1583 * idbm_add_discovery call above handles drec syncing so
1584 * we always pass in 0 here.
1586 rc
= do_sendtargets(drec
, ifaces
, info_level
, do_login
, op
,
1589 case DISCOVERY_TYPE_ISNS
:
1590 rc
= do_isns(drec
, ifaces
, info_level
, do_login
, op
);
1593 log_error("Unsupported discovery type.");
1600 static int exec_disc2_op(int disc_type
, char *ip
, int port
,
1601 struct list_head
*ifaces
, int info_level
, int do_login
,
1602 int do_discover
, int op
, char *name
, char *value
,
1605 struct discovery_rec drec
;
1608 memset(&drec
, 0, sizeof(struct discovery_rec
));
1609 if (disc_type
!= -1)
1610 drec
.type
= disc_type
;
1612 switch (disc_type
) {
1613 case DISCOVERY_TYPE_SENDTARGETS
:
1615 port
= ISCSI_LISTEN_PORT
;
1617 rc
= exec_discover(disc_type
, ip
, port
, ifaces
, info_level
,
1618 do_login
, do_discover
, op
, &drec
);
1622 case DISCOVERY_TYPE_SLP
:
1623 log_error("SLP discovery is not fully implemented yet.");
1624 rc
= ISCSI_ERR_INVAL
;
1626 case DISCOVERY_TYPE_ISNS
:
1628 port
= ISNS_DEFAULT_PORT
;
1630 rc
= exec_discover(disc_type
, ip
, port
, ifaces
, info_level
,
1631 do_login
, do_discover
, op
, &drec
);
1635 case DISCOVERY_TYPE_FW
:
1637 log_error("Invalid command. Possibly missing "
1638 "--discover argument.");
1639 rc
= ISCSI_ERR_INVAL
;
1643 drec
.type
= DISCOVERY_TYPE_FW
;
1644 rc
= exec_fw_op(&drec
, ifaces
, info_level
, do_login
, op
);
1647 rc
= ISCSI_ERR_INVAL
;
1650 if (op
== OP_NOOP
|| op
== OP_SHOW
) {
1651 if (idbm_print_all_discovery(info_level
))
1652 /* successfully found some recs */
1655 rc
= ISCSI_ERR_NO_OBJS_FOUND
;
1657 log_error("Invalid operation. Operation not "
1660 log_error("Invalid command. Possibly missing discovery "
1663 log_error("Invalid command. Portal not needed or "
1664 "Possibly missing discovery --type.");
1671 if (op
== OP_NOOP
|| op
== OP_SHOW
) {
1672 if (!idbm_print_discovery_info(&drec
, do_show
)) {
1673 log_error("No records found");
1674 rc
= ISCSI_ERR_NO_OBJS_FOUND
;
1676 } else if (op
== OP_DELETE
) {
1677 rc
= idbm_delete_discovery(&drec
);
1679 log_error("Unable to delete record!");
1680 } else if (op
== OP_UPDATE
) {
1681 struct db_set_param set_param
;
1683 if (!name
|| !value
) {
1684 log_error("Update requires name and value.");
1685 rc
= ISCSI_ERR_INVAL
;
1688 set_param
.name
= name
;
1689 set_param
.value
= value
;
1690 rc
= idbm_discovery_set_param(&set_param
, &drec
);
1692 log_error("Operation is not supported.");
1693 rc
= ISCSI_ERR_INVAL
;
1700 static int exec_disc_op(int disc_type
, char *ip
, int port
,
1701 struct list_head
*ifaces
, int info_level
, int do_login
,
1702 int do_discover
, int op
, char *name
, char *value
,
1705 struct discovery_rec drec
;
1708 memset(&drec
, 0, sizeof(struct discovery_rec
));
1710 switch (disc_type
) {
1711 case DISCOVERY_TYPE_SENDTARGETS
:
1712 drec
.type
= DISCOVERY_TYPE_SENDTARGETS
;
1715 port
= ISCSI_LISTEN_PORT
;
1718 log_error("Please specify portal as "
1719 "<ipaddr>[:<ipport>]");
1720 rc
= ISCSI_ERR_INVAL
;
1724 idbm_sendtargets_defaults(&drec
.u
.sendtargets
);
1725 strlcpy(drec
.address
, ip
, sizeof(drec
.address
));
1728 rc
= do_sendtargets(&drec
, ifaces
, info_level
,
1733 case DISCOVERY_TYPE_SLP
:
1734 log_error("SLP discovery is not fully implemented yet.");
1735 rc
= ISCSI_ERR_INVAL
;
1737 case DISCOVERY_TYPE_ISNS
:
1739 log_error("Please specify portal as "
1740 "<ipaddr>:[<ipport>]");
1741 rc
= ISCSI_ERR_INVAL
;
1745 strlcpy(drec
.address
, ip
, sizeof(drec
.address
));
1747 drec
.port
= ISNS_DEFAULT_PORT
;
1751 rc
= do_isns(&drec
, ifaces
, info_level
, do_login
, op
);
1755 case DISCOVERY_TYPE_FW
:
1756 drec
.type
= DISCOVERY_TYPE_FW
;
1757 rc
= exec_fw_op(&drec
, ifaces
, info_level
, do_login
, op
);
1762 * We only have sendtargets disc recs in discovery
1763 * mode, so we can hardcode the port check to the
1764 * iscsi default here.
1766 * For isns or slp recs then discovery db mode
1770 port
= ISCSI_LISTEN_PORT
;
1772 if (idbm_discovery_read(&drec
,
1773 DISCOVERY_TYPE_SENDTARGETS
,
1775 log_error("Discovery record [%s,%d] "
1776 "not found!", ip
, port
);
1777 rc
= ISCSI_ERR_INVAL
;
1780 if ((do_discover
|| do_login
) &&
1781 drec
.type
== DISCOVERY_TYPE_SENDTARGETS
) {
1782 rc
= do_sendtargets(&drec
, ifaces
, info_level
,
1784 } else if (op
== OP_NOOP
|| op
== OP_SHOW
) {
1785 if (!idbm_print_discovery_info(&drec
,
1787 log_error("No records found");
1788 rc
= ISCSI_ERR_NO_OBJS_FOUND
;
1790 } else if (op
== OP_DELETE
) {
1791 rc
= idbm_delete_discovery(&drec
);
1793 log_error("Unable to delete record!");
1794 } else if (op
== OP_UPDATE
|| op
== OP_NEW
) {
1795 log_error("Operations new and update for "
1796 "discovery mode is not supported. "
1797 "Use discoverydb mode.");
1798 rc
= ISCSI_ERR_INVAL
;
1801 log_error("Invalid operation.");
1802 rc
= ISCSI_ERR_INVAL
;
1805 } else if (op
== OP_NOOP
|| op
== OP_SHOW
) {
1806 if (!idbm_print_all_discovery(info_level
))
1807 rc
= ISCSI_ERR_NO_OBJS_FOUND
;
1810 log_error("Invalid operation.");
1811 rc
= ISCSI_ERR_INVAL
;
1822 main(int argc
, char **argv
)
1824 char *ip
= NULL
, *name
= NULL
, *value
= NULL
;
1825 char *targetname
= NULL
, *group_session_mgmt_mode
= NULL
;
1826 int ch
, longindex
, mode
=-1, port
=-1, do_login
=0, do_rescan
=0;
1827 int rc
=0, sid
=-1, op
=OP_NOOP
, type
=-1, do_logout
=0, do_stats
=0;
1828 int do_login_all
=0, do_logout_all
=0, info_level
=-1, num_ifaces
= 0;
1829 int tpgt
= PORTAL_GROUP_TAG_UNKNOWN
, killiscsid
=-1, do_show
=0;
1830 int do_discover
= 0;
1831 struct sigaction sa_old
;
1832 struct sigaction sa_new
;
1833 struct list_head ifaces
;
1834 struct iface_rec
*iface
= NULL
, *tmp
;
1835 struct node_rec
*rec
= NULL
;
1836 uint32_t host_no
= -1;
1838 INIT_LIST_HEAD(&ifaces
);
1839 /* do not allow ctrl-c for now... */
1840 memset(&sa_old
, 0, sizeof(struct sigaction
));
1841 memset(&sa_new
, 0, sizeof(struct sigaction
));
1843 sa_new
.sa_handler
= catch_sigint
;
1844 sigemptyset(&sa_new
.sa_mask
);
1845 sa_new
.sa_flags
= 0;
1846 sigaction(SIGINT
, &sa_new
, &sa_old
);
1850 /* enable stdout logging */
1851 log_init(program_name
, 1024, log_do_log_std
, NULL
);
1855 while ((ch
= getopt_long(argc
, argv
, short_options
,
1856 long_options
, &longindex
)) >= 0) {
1859 killiscsid
= atoi(optarg
);
1860 if (killiscsid
< 0) {
1861 log_error("Invalid killiscsid priority %d "
1862 "Priority must be greater than or "
1863 "equal to zero.", killiscsid
);
1864 rc
= ISCSI_ERR_INVAL
;
1869 type
= str_to_type(optarg
);
1872 op
|= str_to_op(optarg
);
1873 if (op
== OP_NOOP
) {
1874 log_error("can not recognize operation: '%s'",
1876 rc
= ISCSI_ERR_INVAL
;
1888 host_no
= strtoul(optarg
, NULL
, 10);
1890 log_error("invalid host no %s. %s.",
1891 optarg
, strerror(errno
));
1892 rc
= ISCSI_ERR_INVAL
;
1897 sid
= iscsi_sysfs_get_sid_from_path(optarg
);
1899 log_error("invalid sid '%s'",
1901 rc
= ISCSI_ERR_INVAL
;
1909 info_level
= atoi(optarg
);
1922 group_session_mgmt_mode
= optarg
;
1926 group_session_mgmt_mode
= optarg
;
1935 log_level
= atoi(optarg
);
1938 mode
= str_to_mode(optarg
);
1941 targetname
= optarg
;
1944 ip
= str_to_ipport(optarg
, &port
, &tpgt
);
1947 iface
= iface_alloc(optarg
, &rc
);
1948 if (rc
== ISCSI_ERR_INVAL
) {
1949 printf("Invalid iface name %s. Must be from "
1950 "1 to %d characters.\n",
1951 optarg
, ISCSI_MAX_IFACE_LEN
- 1);
1953 } else if (!iface
|| rc
) {
1954 printf("Could not add iface %s.", optarg
);
1955 rc
= ISCSI_ERR_INVAL
;
1959 list_add_tail(&iface
->list
, &ifaces
);
1963 printf("%s version %s\n", program_name
,
1972 log_error("unrecognized character '%c'", optopt
);
1973 rc
= ISCSI_ERR_INVAL
;
1977 if (killiscsid
>= 0) {
1978 kill_iscsid(killiscsid
);
1983 usage(ISCSI_ERR_INVAL
);
1985 if (mode
== MODE_FW
) {
1986 if ((rc
= verify_mode_params(argc
, argv
, "ml", 0))) {
1987 log_error("fw mode: option '-%c' is not "
1988 "allowed/supported", rc
);
1989 rc
= ISCSI_ERR_INVAL
;
1993 rc
= exec_fw_op(NULL
, NULL
, info_level
, do_login
, op
);
1997 increase_max_files();
1998 if (idbm_init(get_config_file
)) {
1999 log_warning("exiting due to idbm configuration error");
2000 rc
= ISCSI_ERR_IDBM
;
2006 if ((rc
= verify_mode_params(argc
, argv
, "HdmP", 0))) {
2007 log_error("host mode: option '-%c' is not "
2008 "allowed/supported", rc
);
2009 rc
= ISCSI_ERR_INVAL
;
2013 rc
= host_info_print(info_level
, host_no
);
2016 iface_setup_host_bindings();
2018 if ((rc
= verify_mode_params(argc
, argv
, "IdnvmPo", 0))) {
2019 log_error("iface mode: option '-%c' is not "
2020 "allowed/supported", rc
);
2021 rc
= ISCSI_ERR_INVAL
;
2025 if (!list_empty(&ifaces
)) {
2026 iface
= list_entry(ifaces
.next
, struct iface_rec
,
2029 log_error("iface mode only accepts one "
2030 "interface. Using the first one "
2031 "%s.", iface
->name
);
2033 rc
= exec_iface_op(op
, do_show
, info_level
, iface
,
2036 case MODE_DISCOVERYDB
:
2037 if ((rc
= verify_mode_params(argc
, argv
, "DSIPdmntplov", 0))) {
2038 log_error("discovery mode: option '-%c' is not "
2039 "allowed/supported", rc
);
2040 rc
= ISCSI_ERR_INVAL
;
2044 rc
= exec_disc2_op(type
, ip
, port
, &ifaces
, info_level
,
2045 do_login
, do_discover
, op
, name
, value
,
2048 case MODE_DISCOVERY
:
2049 if ((rc
= verify_mode_params(argc
, argv
, "DSIPdmntplov", 0))) {
2050 log_error("discovery mode: option '-%c' is not "
2051 "allowed/supported", rc
);
2052 rc
= ISCSI_ERR_INVAL
;
2056 rc
= exec_disc_op(type
, ip
, port
, &ifaces
, info_level
,
2057 do_login
, do_discover
, op
, name
, value
,
2061 if ((rc
= verify_mode_params(argc
, argv
, "RsPIdmlSonvupTUL",
2063 log_error("node mode: option '-%c' is not "
2064 "allowed/supported", rc
);
2065 rc
= ISCSI_ERR_INVAL
;
2070 rc
= login_by_startup(group_session_mgmt_mode
);
2074 if (do_logout_all
) {
2075 rc
= logout_by_startup(group_session_mgmt_mode
);
2079 if (!list_empty(&ifaces
)) {
2080 iface
= list_entry(ifaces
.next
, struct iface_rec
,
2083 log_error("NODE mode only accepts one "
2084 "interface. Using the first one "
2085 "driver %s hwaddress %s ipaddress "
2086 "%s.", iface
->transport_name
,
2087 iface
->hwaddress
, iface
->ipaddress
);
2090 if (ip
&& port
== -1)
2091 port
= ISCSI_LISTEN_PORT
;
2093 rec
= idbm_create_rec(targetname
, tpgt
, ip
, port
, iface
, 1);
2095 rc
= ISCSI_ERR_NOMEM
;
2099 rc
= exec_node_op(op
, do_login
, do_logout
, do_show
,
2100 do_rescan
, do_stats
, info_level
, rec
,
2104 if ((rc
= verify_mode_params(argc
, argv
,
2105 "PiRdrmusonuSv", 1))) {
2106 log_error("session mode: option '-%c' is not "
2107 "allowed or supported", rc
);
2108 rc
= ISCSI_ERR_INVAL
;
2113 struct session_info
*info
;
2115 snprintf(session
, 63, "session%d", sid
);
2118 info
= calloc(1, sizeof(*info
));
2120 rc
= ISCSI_ERR_NOMEM
;
2124 rc
= iscsi_sysfs_get_sessioninfo_by_id(info
, session
);
2126 log_error("Could not get session info for sid "
2132 * We should be able to go on, but for now
2133 * we only support session mode ops if the module
2134 * is loaded and we support that module.
2136 if (!iscsi_sysfs_get_transport_by_sid(sid
))
2139 if (!do_logout
&& !do_rescan
&& !do_stats
&&
2140 op
== OP_NOOP
&& info_level
> 0) {
2141 rc
= session_info_print(info_level
, info
);
2145 rec
= idbm_create_rec(info
->targetname
,
2147 info
->persistent_address
,
2148 info
->persistent_port
,
2151 rc
= ISCSI_ERR_NOMEM
;
2154 rec
->session
.info
= info
;
2155 rec
->session
.sid
= sid
;
2157 /* drop down to node ops */
2158 rc
= exec_node_op(op
, do_login
, do_logout
, do_show
,
2159 do_rescan
, do_stats
, info_level
,
2165 if (do_logout
|| do_rescan
|| do_stats
) {
2166 rc
= exec_node_op(op
, do_login
, do_logout
,
2167 do_show
, do_rescan
, do_stats
,
2168 info_level
, NULL
, name
, value
);
2172 rc
= session_info_print(info_level
, NULL
);
2176 log_error("This mode is not yet supported");
2185 list_for_each_entry_safe(iface
, tmp
, &ifaces
, list
) {
2186 list_del(&iface
->list
);