Index: head/usr.bin/iscsictl/Makefile =================================================================== --- head/usr.bin/iscsictl/Makefile (revision 281460) +++ head/usr.bin/iscsictl/Makefile (revision 281461) @@ -1,16 +1,18 @@ # $FreeBSD$ PROG= iscsictl SRCS= iscsictl.c periphs.c parse.y token.l y.tab.h CFLAGS+= -I${.CURDIR} CFLAGS+= -I${.CURDIR}/../../sys/dev/iscsi MAN= iscsi.conf.5 iscsictl.8 +LIBADD= xo + YFLAGS+= -v LFLAGS+= -i CLEANFILES= y.tab.c y.tab.h y.output WARNS= 6 NO_WMISSING_VARIABLE_DECLARATIONS= .include Index: head/usr.bin/iscsictl/iscsictl.c =================================================================== --- head/usr.bin/iscsictl/iscsictl.c (revision 281460) +++ head/usr.bin/iscsictl/iscsictl.c (revision 281461) @@ -1,865 +1,909 @@ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Edward Tomasz Napierala under sponsorship * from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include -#include #include #include #include #include #include #include #include +#include #include #include "iscsictl.h" struct conf * conf_new(void) { struct conf *conf; conf = calloc(1, sizeof(*conf)); if (conf == NULL) - err(1, "calloc"); + xo_err(1, "calloc"); TAILQ_INIT(&conf->conf_targets); return (conf); } struct target * target_find(struct conf *conf, const char *nickname) { struct target *targ; TAILQ_FOREACH(targ, &conf->conf_targets, t_next) { if (targ->t_nickname != NULL && strcasecmp(targ->t_nickname, nickname) == 0) return (targ); } return (NULL); } struct target * target_new(struct conf *conf) { struct target *targ; targ = calloc(1, sizeof(*targ)); if (targ == NULL) - err(1, "calloc"); + xo_err(1, "calloc"); targ->t_conf = conf; TAILQ_INSERT_TAIL(&conf->conf_targets, targ, t_next); return (targ); } void target_delete(struct target *targ) { TAILQ_REMOVE(&targ->t_conf->conf_targets, targ, t_next); free(targ); } static char * default_initiator_name(void) { char *name; size_t namelen; int error; namelen = _POSIX_HOST_NAME_MAX + strlen(DEFAULT_IQN); name = calloc(1, namelen + 1); if (name == NULL) - err(1, "calloc"); + xo_err(1, "calloc"); strcpy(name, DEFAULT_IQN); error = gethostname(name + strlen(DEFAULT_IQN), namelen - strlen(DEFAULT_IQN)); if (error != 0) - err(1, "gethostname"); + xo_err(1, "gethostname"); return (name); } static bool valid_hex(const char ch) { switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'a': case 'A': case 'b': case 'B': case 'c': case 'C': case 'd': case 'D': case 'e': case 'E': case 'f': case 'F': return (true); default: return (false); } } bool valid_iscsi_name(const char *name) { int i; if (strlen(name) >= MAX_NAME_LEN) { - warnx("overlong name for \"%s\"; max length allowed " + xo_warnx("overlong name for \"%s\"; max length allowed " "by iSCSI specification is %d characters", name, MAX_NAME_LEN); return (false); } /* * In the cases below, we don't return an error, just in case the admin * was right, and we're wrong. */ if (strncasecmp(name, "iqn.", strlen("iqn.")) == 0) { for (i = strlen("iqn."); name[i] != '\0'; i++) { /* * XXX: We should verify UTF-8 normalisation, as defined * by 3.2.6.2: iSCSI Name Encoding. */ if (isalnum(name[i])) continue; if (name[i] == '-' || name[i] == '.' || name[i] == ':') continue; - warnx("invalid character \"%c\" in iSCSI name " + xo_warnx("invalid character \"%c\" in iSCSI name " "\"%s\"; allowed characters are letters, digits, " "'-', '.', and ':'", name[i], name); break; } /* * XXX: Check more stuff: valid date and a valid reversed domain. */ } else if (strncasecmp(name, "eui.", strlen("eui.")) == 0) { if (strlen(name) != strlen("eui.") + 16) - warnx("invalid iSCSI name \"%s\"; the \"eui.\" " + xo_warnx("invalid iSCSI name \"%s\"; the \"eui.\" " "should be followed by exactly 16 hexadecimal " "digits", name); for (i = strlen("eui."); name[i] != '\0'; i++) { if (!valid_hex(name[i])) { - warnx("invalid character \"%c\" in iSCSI " + xo_warnx("invalid character \"%c\" in iSCSI " "name \"%s\"; allowed characters are 1-9 " "and A-F", name[i], name); break; } } } else if (strncasecmp(name, "naa.", strlen("naa.")) == 0) { if (strlen(name) > strlen("naa.") + 32) - warnx("invalid iSCSI name \"%s\"; the \"naa.\" " + xo_warnx("invalid iSCSI name \"%s\"; the \"naa.\" " "should be followed by at most 32 hexadecimal " "digits", name); for (i = strlen("naa."); name[i] != '\0'; i++) { if (!valid_hex(name[i])) { - warnx("invalid character \"%c\" in ISCSI " + xo_warnx("invalid character \"%c\" in ISCSI " "name \"%s\"; allowed characters are 1-9 " "and A-F", name[i], name); break; } } } else { - warnx("invalid iSCSI name \"%s\"; should start with " + xo_warnx("invalid iSCSI name \"%s\"; should start with " "either \".iqn\", \"eui.\", or \"naa.\"", name); } return (true); } void conf_verify(struct conf *conf) { struct target *targ; TAILQ_FOREACH(targ, &conf->conf_targets, t_next) { assert(targ->t_nickname != NULL); if (targ->t_session_type == SESSION_TYPE_UNSPECIFIED) targ->t_session_type = SESSION_TYPE_NORMAL; if (targ->t_session_type == SESSION_TYPE_NORMAL && targ->t_name == NULL) - errx(1, "missing TargetName for target \"%s\"", + xo_errx(1, "missing TargetName for target \"%s\"", targ->t_nickname); if (targ->t_session_type == SESSION_TYPE_DISCOVERY && targ->t_name != NULL) - errx(1, "cannot specify TargetName for discovery " + xo_errx(1, "cannot specify TargetName for discovery " "sessions for target \"%s\"", targ->t_nickname); if (targ->t_name != NULL) { if (valid_iscsi_name(targ->t_name) == false) - errx(1, "invalid target name \"%s\"", + xo_errx(1, "invalid target name \"%s\"", targ->t_name); } if (targ->t_protocol == PROTOCOL_UNSPECIFIED) targ->t_protocol = PROTOCOL_ISCSI; if (targ->t_address == NULL) - errx(1, "missing TargetAddress for target \"%s\"", + xo_errx(1, "missing TargetAddress for target \"%s\"", targ->t_nickname); if (targ->t_initiator_name == NULL) targ->t_initiator_name = default_initiator_name(); if (valid_iscsi_name(targ->t_initiator_name) == false) - errx(1, "invalid initiator name \"%s\"", + xo_errx(1, "invalid initiator name \"%s\"", targ->t_initiator_name); if (targ->t_header_digest == DIGEST_UNSPECIFIED) targ->t_header_digest = DIGEST_NONE; if (targ->t_data_digest == DIGEST_UNSPECIFIED) targ->t_data_digest = DIGEST_NONE; if (targ->t_auth_method == AUTH_METHOD_UNSPECIFIED) { if (targ->t_user != NULL || targ->t_secret != NULL || targ->t_mutual_user != NULL || targ->t_mutual_secret != NULL) targ->t_auth_method = AUTH_METHOD_CHAP; else targ->t_auth_method = AUTH_METHOD_NONE; } if (targ->t_auth_method == AUTH_METHOD_CHAP) { if (targ->t_user == NULL) { - errx(1, "missing chapIName for target \"%s\"", + xo_errx(1, "missing chapIName for target \"%s\"", targ->t_nickname); } if (targ->t_secret == NULL) - errx(1, "missing chapSecret for target \"%s\"", + xo_errx(1, "missing chapSecret for target \"%s\"", targ->t_nickname); if (targ->t_mutual_user != NULL || targ->t_mutual_secret != NULL) { if (targ->t_mutual_user == NULL) - errx(1, "missing tgtChapName for " + xo_errx(1, "missing tgtChapName for " "target \"%s\"", targ->t_nickname); if (targ->t_mutual_secret == NULL) - errx(1, "missing tgtChapSecret for " + xo_errx(1, "missing tgtChapSecret for " "target \"%s\"", targ->t_nickname); } } } } static void conf_from_target(struct iscsi_session_conf *conf, const struct target *targ) { memset(conf, 0, sizeof(*conf)); /* * XXX: Check bounds and return error instead of silently truncating. */ if (targ->t_initiator_name != NULL) strlcpy(conf->isc_initiator, targ->t_initiator_name, sizeof(conf->isc_initiator)); if (targ->t_initiator_address != NULL) strlcpy(conf->isc_initiator_addr, targ->t_initiator_address, sizeof(conf->isc_initiator_addr)); if (targ->t_initiator_alias != NULL) strlcpy(conf->isc_initiator_alias, targ->t_initiator_alias, sizeof(conf->isc_initiator_alias)); if (targ->t_name != NULL) strlcpy(conf->isc_target, targ->t_name, sizeof(conf->isc_target)); if (targ->t_address != NULL) strlcpy(conf->isc_target_addr, targ->t_address, sizeof(conf->isc_target_addr)); if (targ->t_user != NULL) strlcpy(conf->isc_user, targ->t_user, sizeof(conf->isc_user)); if (targ->t_secret != NULL) strlcpy(conf->isc_secret, targ->t_secret, sizeof(conf->isc_secret)); if (targ->t_mutual_user != NULL) strlcpy(conf->isc_mutual_user, targ->t_mutual_user, sizeof(conf->isc_mutual_user)); if (targ->t_mutual_secret != NULL) strlcpy(conf->isc_mutual_secret, targ->t_mutual_secret, sizeof(conf->isc_mutual_secret)); if (targ->t_session_type == SESSION_TYPE_DISCOVERY) conf->isc_discovery = 1; if (targ->t_protocol == PROTOCOL_ISER) conf->isc_iser = 1; if (targ->t_offload != NULL) strlcpy(conf->isc_offload, targ->t_offload, sizeof(conf->isc_offload)); if (targ->t_header_digest == DIGEST_CRC32C) conf->isc_header_digest = ISCSI_DIGEST_CRC32C; else conf->isc_header_digest = ISCSI_DIGEST_NONE; if (targ->t_data_digest == DIGEST_CRC32C) conf->isc_data_digest = ISCSI_DIGEST_CRC32C; else conf->isc_data_digest = ISCSI_DIGEST_NONE; } static int kernel_add(int iscsi_fd, const struct target *targ) { struct iscsi_session_add isa; int error; memset(&isa, 0, sizeof(isa)); conf_from_target(&isa.isa_conf, targ); error = ioctl(iscsi_fd, ISCSISADD, &isa); if (error != 0) - warn("ISCSISADD"); + xo_warn("ISCSISADD"); return (error); } static int kernel_modify(int iscsi_fd, unsigned int session_id, const struct target *targ) { struct iscsi_session_modify ism; int error; memset(&ism, 0, sizeof(ism)); ism.ism_session_id = session_id; conf_from_target(&ism.ism_conf, targ); error = ioctl(iscsi_fd, ISCSISMODIFY, &ism); if (error != 0) - warn("ISCSISMODIFY"); + xo_warn("ISCSISMODIFY"); return (error); } static void kernel_modify_some(int iscsi_fd, unsigned int session_id, const char *target, const char *target_addr, const char *user, const char *secret) { struct iscsi_session_state *states = NULL; struct iscsi_session_state *state; struct iscsi_session_conf *conf; struct iscsi_session_list isl; struct iscsi_session_modify ism; unsigned int i, nentries = 1; int error; for (;;) { states = realloc(states, nentries * sizeof(struct iscsi_session_state)); if (states == NULL) - err(1, "realloc"); + xo_err(1, "realloc"); memset(&isl, 0, sizeof(isl)); isl.isl_nentries = nentries; isl.isl_pstates = states; error = ioctl(iscsi_fd, ISCSISLIST, &isl); if (error != 0 && errno == EMSGSIZE) { nentries *= 4; continue; } break; } if (error != 0) - errx(1, "ISCSISLIST"); + xo_errx(1, "ISCSISLIST"); for (i = 0; i < isl.isl_nentries; i++) { state = &states[i]; if (state->iss_id == session_id) break; } if (i == isl.isl_nentries) - errx(1, "session-id %u not found", session_id); + xo_errx(1, "session-id %u not found", session_id); conf = &state->iss_conf; if (target != NULL) strlcpy(conf->isc_target, target, sizeof(conf->isc_target)); if (target_addr != NULL) strlcpy(conf->isc_target_addr, target_addr, sizeof(conf->isc_target_addr)); if (user != NULL) strlcpy(conf->isc_user, user, sizeof(conf->isc_user)); if (secret != NULL) strlcpy(conf->isc_secret, secret, sizeof(conf->isc_secret)); memset(&ism, 0, sizeof(ism)); ism.ism_session_id = session_id; memcpy(&ism.ism_conf, conf, sizeof(ism.ism_conf)); error = ioctl(iscsi_fd, ISCSISMODIFY, &ism); if (error != 0) - warn("ISCSISMODIFY"); + xo_warn("ISCSISMODIFY"); } static int kernel_remove(int iscsi_fd, const struct target *targ) { struct iscsi_session_remove isr; int error; memset(&isr, 0, sizeof(isr)); conf_from_target(&isr.isr_conf, targ); error = ioctl(iscsi_fd, ISCSISREMOVE, &isr); if (error != 0) - warn("ISCSISREMOVE"); + xo_warn("ISCSISREMOVE"); return (error); } /* * XXX: Add filtering. */ static int kernel_list(int iscsi_fd, const struct target *targ __unused, int verbose) { struct iscsi_session_state *states = NULL; const struct iscsi_session_state *state; const struct iscsi_session_conf *conf; struct iscsi_session_list isl; unsigned int i, nentries = 1; int error; for (;;) { states = realloc(states, nentries * sizeof(struct iscsi_session_state)); if (states == NULL) - err(1, "realloc"); + xo_err(1, "realloc"); memset(&isl, 0, sizeof(isl)); isl.isl_nentries = nentries; isl.isl_pstates = states; error = ioctl(iscsi_fd, ISCSISLIST, &isl); if (error != 0 && errno == EMSGSIZE) { nentries *= 4; continue; } break; } if (error != 0) { - warn("ISCSISLIST"); + xo_warn("ISCSISLIST"); return (error); } if (verbose != 0) { + xo_open_list("session"); for (i = 0; i < isl.isl_nentries; i++) { state = &states[i]; conf = &state->iss_conf; - printf("Session ID: %u\n", state->iss_id); - printf("Initiator name: %s\n", conf->isc_initiator); - printf("Initiator portal: %s\n", - conf->isc_initiator_addr); - printf("Initiator alias: %s\n", - conf->isc_initiator_alias); - printf("Target name: %s\n", conf->isc_target); - printf("Target portal: %s\n", - conf->isc_target_addr); - printf("Target alias: %s\n", - state->iss_target_alias); - printf("User: %s\n", conf->isc_user); - printf("Secret: %s\n", conf->isc_secret); - printf("Mutual user: %s\n", - conf->isc_mutual_user); - printf("Mutual secret: %s\n", - conf->isc_mutual_secret); - printf("Session type: %s\n", + xo_open_instance("session"); + + /* + * Display-only modifier as this information + * is also present within the 'session' container + */ + xo_emit("{L:/%-18s}{V:sessionId/%u}\n", + "Session ID:", state->iss_id); + + xo_open_container("initiator"); + xo_emit("{L:/%-18s}{V:name/%s}\n", + "Initiator name:", conf->isc_initiator); + xo_emit("{L:/%-18s}{V:portal/%s}\n", + "Initiator portal:", conf->isc_initiator_addr); + xo_emit("{L:/%-18s}{V:alias/%s}\n", + "Initiator alias:", conf->isc_initiator_alias); + xo_close_container("initiator"); + + xo_open_container("target"); + xo_emit("{L:/%-18s}{V:name/%s}\n", + "Target name:", conf->isc_target); + xo_emit("{L:/%-18s}{V:portal/%s}\n", + "Target portal:", conf->isc_target_addr); + xo_emit("{L:/%-18s}{V:alias/%s}\n", + "Target alias:", state->iss_target_alias); + xo_close_container("target"); + + xo_open_container("auth"); + xo_emit("{L:/%-18s}{V:user/%s}\n", + "User:", conf->isc_user); + xo_emit("{L:/%-18s}{V:secret/%s}\n", + "Secret:", conf->isc_secret); + xo_emit("{L:/%-18s}{V:mutualUser/%s}\n", + "Mutual user:", conf->isc_mutual_user); + xo_emit("{L:/%-18s}{V:mutualSecret/%s}\n", + "Mutual secret:", conf->isc_mutual_secret); + xo_close_container("auth"); + + xo_emit("{L:/%-18s}{V:type/%s}\n", + "Session type:", conf->isc_discovery ? "Discovery" : "Normal"); - printf("Session state: %s\n", - state->iss_connected ? - "Connected" : "Disconnected"); - printf("Failure reason: %s\n", state->iss_reason); - printf("Header digest: %s\n", + xo_emit("{L:/%-18s}{V:state/%s}\n", + "Session state:", + state->iss_connected ? "Connected" : "Disconnected"); + xo_emit("{L:/%-18s}{V:failureReason/%s}\n", + "Failure reason:", state->iss_reason); + xo_emit("{L:/%-18s}{V:headerDigest/%s}\n", + "Header digest:", state->iss_header_digest == ISCSI_DIGEST_CRC32C ? "CRC32C" : "None"); - printf("Data digest: %s\n", + xo_emit("{L:/%-18s}{V:dataDigest/%s}\n", + "Data digest:", state->iss_data_digest == ISCSI_DIGEST_CRC32C ? "CRC32C" : "None"); - printf("DataSegmentLen: %d\n", - state->iss_max_data_segment_length); - printf("ImmediateData: %s\n", - state->iss_immediate_data ? "Yes" : "No"); - printf("iSER (RDMA): %s\n", - conf->isc_iser ? "Yes" : "No"); - printf("Offload driver: %s\n", state->iss_offload); - printf("Device nodes: "); + xo_emit("{L:/%-18s}{V:dataSegmentLen/%d}\n", + "DataSegmentLen:", state->iss_max_data_segment_length); + xo_emit("{L:/%-18s}{V:immediateData/%s}\n", + "ImmediateData:", state->iss_immediate_data ? "Yes" : "No"); + xo_emit("{L:/%-18s}{V:iSER/%s}\n", + "iSER (RDMA):", conf->isc_iser ? "Yes" : "No"); + xo_emit("{L:/%-18s}{V:offloadDriver/%s}\n", + "Offload driver:", state->iss_offload); + xo_emit("{L:/%-18s}", + "Device nodes:"); print_periphs(state->iss_id); - printf("\n\n"); + xo_emit("\n\n"); + xo_close_instance("session"); } + xo_close_list("session"); } else { - printf("%-36s %-16s %s\n", + xo_emit("{T:/%-36s} {T:/%-16s} {T:/%s}\n", "Target name", "Target portal", "State"); + + if (isl.isl_nentries != 0) + xo_open_list("session"); for (i = 0; i < isl.isl_nentries; i++) { + state = &states[i]; conf = &state->iss_conf; - printf("%-36s %-16s ", + xo_open_instance("session"); + xo_emit("{V:name/%-36s/%s} {V:portal/%-16s/%s} ", conf->isc_target, conf->isc_target_addr); if (state->iss_reason[0] != '\0') { - printf("%s\n", state->iss_reason); + xo_emit("{V:state/%s}\n", state->iss_reason); } else { if (conf->isc_discovery) { - printf("Discovery\n"); + xo_emit("{V:state}\n", "Discovery"); } else if (state->iss_connected) { - printf("Connected: "); + xo_emit("{V:state}: ", "Connected"); print_periphs(state->iss_id); - printf("\n"); + xo_emit("\n"); } else { - printf("Disconnected\n"); + xo_emit("{V:state}\n", "Disconnected"); } } + xo_close_instance("session"); } + if (isl.isl_nentries != 0) + xo_close_list("session"); } return (0); } static void usage(void) { fprintf(stderr, "usage: iscsictl -A -p portal -t target " "[-u user -s secret]\n"); fprintf(stderr, " iscsictl -A -d discovery-host " "[-u user -s secret]\n"); fprintf(stderr, " iscsictl -A -a [-c path]\n"); fprintf(stderr, " iscsictl -A -n nickname [-c path]\n"); fprintf(stderr, " iscsictl -M -i session-id [-p portal] " "[-t target] [-u user] [-s secret]\n"); fprintf(stderr, " iscsictl -M -i session-id -n nickname " "[-c path]\n"); fprintf(stderr, " iscsictl -R [-p portal] [-t target]\n"); fprintf(stderr, " iscsictl -R -a\n"); fprintf(stderr, " iscsictl -R -n nickname [-c path]\n"); fprintf(stderr, " iscsictl -L [-v]\n"); exit(1); } char * checked_strdup(const char *s) { char *c; c = strdup(s); if (c == NULL) - err(1, "strdup"); + xo_err(1, "strdup"); return (c); } int main(int argc, char **argv) { int Aflag = 0, Mflag = 0, Rflag = 0, Lflag = 0, aflag = 0, vflag = 0; const char *conf_path = DEFAULT_CONFIG_PATH; char *nickname = NULL, *discovery_host = NULL, *portal = NULL, *target = NULL, *user = NULL, *secret = NULL; long long session_id = -1; char *end; int ch, error, iscsi_fd, retval, saved_errno; int failed = 0; struct conf *conf; struct target *targ; + argc = xo_parse_args(argc, argv); + xo_open_container("iscsictl"); + while ((ch = getopt(argc, argv, "AMRLac:d:i:n:p:t:u:s:v")) != -1) { switch (ch) { case 'A': Aflag = 1; break; case 'M': Mflag = 1; break; case 'R': Rflag = 1; break; case 'L': Lflag = 1; break; case 'a': aflag = 1; break; case 'c': conf_path = optarg; break; case 'd': discovery_host = optarg; break; case 'i': session_id = strtol(optarg, &end, 10); if ((size_t)(end - optarg) != strlen(optarg)) - errx(1, "trailing characters after session-id"); + xo_errx(1, "trailing characters after session-id"); if (session_id < 0) - errx(1, "session-id cannot be negative"); + xo_errx(1, "session-id cannot be negative"); if (session_id > UINT_MAX) - errx(1, "session-id cannot be greater than %u", + xo_errx(1, "session-id cannot be greater than %u", UINT_MAX); break; case 'n': nickname = optarg; break; case 'p': portal = optarg; break; case 't': target = optarg; break; case 'u': user = optarg; break; case 's': secret = optarg; break; case 'v': vflag = 1; break; case '?': default: usage(); } } argc -= optind; if (argc != 0) usage(); if (Aflag + Mflag + Rflag + Lflag == 0) Lflag = 1; if (Aflag + Mflag + Rflag + Lflag > 1) - errx(1, "at most one of -A, -M, -R, or -L may be specified"); + xo_errx(1, "at most one of -A, -M, -R, or -L may be specified"); /* * Note that we ignore unneccessary/inapplicable "-c" flag; so that * people can do something like "alias ISCSICTL="iscsictl -c path" * in shell scripts. */ if (Aflag != 0) { if (aflag != 0) { if (portal != NULL) - errx(1, "-a and -p and mutually exclusive"); + xo_errx(1, "-a and -p and mutually exclusive"); if (target != NULL) - errx(1, "-a and -t and mutually exclusive"); + xo_errx(1, "-a and -t and mutually exclusive"); if (user != NULL) - errx(1, "-a and -u and mutually exclusive"); + xo_errx(1, "-a and -u and mutually exclusive"); if (secret != NULL) - errx(1, "-a and -s and mutually exclusive"); + xo_errx(1, "-a and -s and mutually exclusive"); if (nickname != NULL) - errx(1, "-a and -n and mutually exclusive"); + xo_errx(1, "-a and -n and mutually exclusive"); if (discovery_host != NULL) - errx(1, "-a and -d and mutually exclusive"); + xo_errx(1, "-a and -d and mutually exclusive"); } else if (nickname != NULL) { if (portal != NULL) - errx(1, "-n and -p and mutually exclusive"); + xo_errx(1, "-n and -p and mutually exclusive"); if (target != NULL) - errx(1, "-n and -t and mutually exclusive"); + xo_errx(1, "-n and -t and mutually exclusive"); if (user != NULL) - errx(1, "-n and -u and mutually exclusive"); + xo_errx(1, "-n and -u and mutually exclusive"); if (secret != NULL) - errx(1, "-n and -s and mutually exclusive"); + xo_errx(1, "-n and -s and mutually exclusive"); if (discovery_host != NULL) - errx(1, "-n and -d and mutually exclusive"); + xo_errx(1, "-n and -d and mutually exclusive"); } else if (discovery_host != NULL) { if (portal != NULL) - errx(1, "-d and -p and mutually exclusive"); + xo_errx(1, "-d and -p and mutually exclusive"); if (target != NULL) - errx(1, "-d and -t and mutually exclusive"); + xo_errx(1, "-d and -t and mutually exclusive"); } else { if (target == NULL && portal == NULL) - errx(1, "must specify -a, -n or -t/-p"); + xo_errx(1, "must specify -a, -n or -t/-p"); if (target != NULL && portal == NULL) - errx(1, "-t must always be used with -p"); + xo_errx(1, "-t must always be used with -p"); if (portal != NULL && target == NULL) - errx(1, "-p must always be used with -t"); + xo_errx(1, "-p must always be used with -t"); } if (user != NULL && secret == NULL) - errx(1, "-u must always be used with -s"); + xo_errx(1, "-u must always be used with -s"); if (secret != NULL && user == NULL) - errx(1, "-s must always be used with -u"); + xo_errx(1, "-s must always be used with -u"); if (session_id != -1) - errx(1, "-i cannot be used with -A"); + xo_errx(1, "-i cannot be used with -A"); if (vflag != 0) - errx(1, "-v cannot be used with -A"); + xo_errx(1, "-v cannot be used with -A"); } else if (Mflag != 0) { if (session_id == -1) - errx(1, "-M requires -i"); + xo_errx(1, "-M requires -i"); if (discovery_host != NULL) - errx(1, "-M and -d are mutually exclusive"); + xo_errx(1, "-M and -d are mutually exclusive"); if (aflag != 0) - errx(1, "-M and -a are mutually exclusive"); + xo_errx(1, "-M and -a are mutually exclusive"); if (nickname != NULL) { if (portal != NULL) - errx(1, "-n and -p and mutually exclusive"); + xo_errx(1, "-n and -p and mutually exclusive"); if (target != NULL) - errx(1, "-n and -t and mutually exclusive"); + xo_errx(1, "-n and -t and mutually exclusive"); if (user != NULL) - errx(1, "-n and -u and mutually exclusive"); + xo_errx(1, "-n and -u and mutually exclusive"); if (secret != NULL) - errx(1, "-n and -s and mutually exclusive"); + xo_errx(1, "-n and -s and mutually exclusive"); } if (vflag != 0) - errx(1, "-v cannot be used with -M"); + xo_errx(1, "-v cannot be used with -M"); } else if (Rflag != 0) { if (user != NULL) - errx(1, "-R and -u are mutually exclusive"); + xo_errx(1, "-R and -u are mutually exclusive"); if (secret != NULL) - errx(1, "-R and -s are mutually exclusive"); + xo_errx(1, "-R and -s are mutually exclusive"); if (discovery_host != NULL) - errx(1, "-R and -d are mutually exclusive"); + xo_errx(1, "-R and -d are mutually exclusive"); if (aflag != 0) { if (portal != NULL) - errx(1, "-a and -p and mutually exclusive"); + xo_errx(1, "-a and -p and mutually exclusive"); if (target != NULL) - errx(1, "-a and -t and mutually exclusive"); + xo_errx(1, "-a and -t and mutually exclusive"); if (nickname != NULL) - errx(1, "-a and -n and mutually exclusive"); + xo_errx(1, "-a and -n and mutually exclusive"); } else if (nickname != NULL) { if (portal != NULL) - errx(1, "-n and -p and mutually exclusive"); + xo_errx(1, "-n and -p and mutually exclusive"); if (target != NULL) - errx(1, "-n and -t and mutually exclusive"); + xo_errx(1, "-n and -t and mutually exclusive"); } else if (target == NULL && portal == NULL) { - errx(1, "must specify either -a, -n, -t, or -p"); + xo_errx(1, "must specify either -a, -n, -t, or -p"); } if (session_id != -1) - errx(1, "-i cannot be used with -R"); + xo_errx(1, "-i cannot be used with -R"); if (vflag != 0) - errx(1, "-v cannot be used with -R"); + xo_errx(1, "-v cannot be used with -R"); } else { assert(Lflag != 0); if (portal != NULL) - errx(1, "-L and -p and mutually exclusive"); + xo_errx(1, "-L and -p and mutually exclusive"); if (target != NULL) - errx(1, "-L and -t and mutually exclusive"); + xo_errx(1, "-L and -t and mutually exclusive"); if (user != NULL) - errx(1, "-L and -u and mutually exclusive"); + xo_errx(1, "-L and -u and mutually exclusive"); if (secret != NULL) - errx(1, "-L and -s and mutually exclusive"); + xo_errx(1, "-L and -s and mutually exclusive"); if (nickname != NULL) - errx(1, "-L and -n and mutually exclusive"); + xo_errx(1, "-L and -n and mutually exclusive"); if (discovery_host != NULL) - errx(1, "-L and -d and mutually exclusive"); + xo_errx(1, "-L and -d and mutually exclusive"); if (session_id != -1) - errx(1, "-i cannot be used with -L"); + xo_errx(1, "-i cannot be used with -L"); } iscsi_fd = open(ISCSI_PATH, O_RDWR); if (iscsi_fd < 0 && errno == ENOENT) { saved_errno = errno; retval = kldload("iscsi"); if (retval != -1) iscsi_fd = open(ISCSI_PATH, O_RDWR); else errno = saved_errno; } if (iscsi_fd < 0) - err(1, "failed to open %s", ISCSI_PATH); + xo_err(1, "failed to open %s", ISCSI_PATH); if (Aflag != 0 && aflag != 0) { conf = conf_new_from_file(conf_path); TAILQ_FOREACH(targ, &conf->conf_targets, t_next) failed += kernel_add(iscsi_fd, targ); } else if (nickname != NULL) { conf = conf_new_from_file(conf_path); targ = target_find(conf, nickname); if (targ == NULL) - errx(1, "target %s not found in %s", + xo_errx(1, "target %s not found in %s", nickname, conf_path); if (Aflag != 0) failed += kernel_add(iscsi_fd, targ); else if (Mflag != 0) failed += kernel_modify(iscsi_fd, session_id, targ); else if (Rflag != 0) failed += kernel_remove(iscsi_fd, targ); else failed += kernel_list(iscsi_fd, targ, vflag); } else if (Mflag != 0) { kernel_modify_some(iscsi_fd, session_id, target, portal, user, secret); } else { if (Aflag != 0 && target != NULL) { if (valid_iscsi_name(target) == false) - errx(1, "invalid target name \"%s\"", target); + xo_errx(1, "invalid target name \"%s\"", target); } conf = conf_new(); targ = target_new(conf); targ->t_initiator_name = default_initiator_name(); targ->t_header_digest = DIGEST_NONE; targ->t_data_digest = DIGEST_NONE; targ->t_name = target; if (discovery_host != NULL) { targ->t_session_type = SESSION_TYPE_DISCOVERY; targ->t_address = discovery_host; } else { targ->t_session_type = SESSION_TYPE_NORMAL; targ->t_address = portal; } targ->t_user = user; targ->t_secret = secret; if (Aflag != 0) failed += kernel_add(iscsi_fd, targ); else if (Rflag != 0) failed += kernel_remove(iscsi_fd, targ); else failed += kernel_list(iscsi_fd, targ, vflag); } error = close(iscsi_fd); if (error != 0) - err(1, "close"); + xo_err(1, "close"); if (failed > 0) return (1); + + xo_close_container("iscsictl"); + xo_finish(); return (0); } Index: head/usr.bin/iscsictl/parse.y =================================================================== --- head/usr.bin/iscsictl/parse.y (revision 281460) +++ head/usr.bin/iscsictl/parse.y (revision 281461) @@ -1,345 +1,346 @@ %{ /*- * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * This software was developed by Edward Tomasz Napierala under sponsorship * from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include -#include #include #include #include #include +#include + #include "iscsictl.h" extern FILE *yyin; extern char *yytext; extern int lineno; static struct conf *conf; static struct target *target; extern void yyerror(const char *); extern int yylex(void); extern void yyrestart(FILE *); %} %token AUTH_METHOD HEADER_DIGEST DATA_DIGEST TARGET_NAME TARGET_ADDRESS %token INITIATOR_NAME INITIATOR_ADDRESS INITIATOR_ALIAS USER SECRET %token MUTUAL_USER MUTUAL_SECRET SEMICOLON SESSION_TYPE PROTOCOL OFFLOAD %token IGNORED EQUALS OPENING_BRACKET CLOSING_BRACKET %union { char *str; } %token STR %% targets: | targets target ; target: STR OPENING_BRACKET target_entries CLOSING_BRACKET { if (target_find(conf, $1) != NULL) - errx(1, "duplicated target %s", $1); + xo_errx(1, "duplicated target %s", $1); target->t_nickname = $1; target = target_new(conf); } ; target_entries: | target_entries target_entry | target_entries target_entry SEMICOLON ; target_entry: target_name | target_address | initiator_name | initiator_address | initiator_alias | user | secret | mutual_user | mutual_secret | auth_method | header_digest | data_digest | session_type | offload | protocol | ignored ; target_name: TARGET_NAME EQUALS STR { if (target->t_name != NULL) - errx(1, "duplicated TargetName at line %d", lineno); + xo_errx(1, "duplicated TargetName at line %d", lineno); target->t_name = $3; } ; target_address: TARGET_ADDRESS EQUALS STR { if (target->t_address != NULL) - errx(1, "duplicated TargetAddress at line %d", lineno); + xo_errx(1, "duplicated TargetAddress at line %d", lineno); target->t_address = $3; } ; initiator_name: INITIATOR_NAME EQUALS STR { if (target->t_initiator_name != NULL) - errx(1, "duplicated InitiatorName at line %d", lineno); + xo_errx(1, "duplicated InitiatorName at line %d", lineno); target->t_initiator_name = $3; } ; initiator_address: INITIATOR_ADDRESS EQUALS STR { if (target->t_initiator_address != NULL) - errx(1, "duplicated InitiatorAddress at line %d", lineno); + xo_errx(1, "duplicated InitiatorAddress at line %d", lineno); target->t_initiator_address = $3; } ; initiator_alias: INITIATOR_ALIAS EQUALS STR { if (target->t_initiator_alias != NULL) - errx(1, "duplicated InitiatorAlias at line %d", lineno); + xo_errx(1, "duplicated InitiatorAlias at line %d", lineno); target->t_initiator_alias = $3; } ; user: USER EQUALS STR { if (target->t_user != NULL) - errx(1, "duplicated chapIName at line %d", lineno); + xo_errx(1, "duplicated chapIName at line %d", lineno); target->t_user = $3; } ; secret: SECRET EQUALS STR { if (target->t_secret != NULL) - errx(1, "duplicated chapSecret at line %d", lineno); + xo_errx(1, "duplicated chapSecret at line %d", lineno); target->t_secret = $3; } ; mutual_user: MUTUAL_USER EQUALS STR { if (target->t_mutual_user != NULL) - errx(1, "duplicated tgtChapName at line %d", lineno); + xo_errx(1, "duplicated tgtChapName at line %d", lineno); target->t_mutual_user = $3; } ; mutual_secret: MUTUAL_SECRET EQUALS STR { if (target->t_mutual_secret != NULL) - errx(1, "duplicated tgtChapSecret at line %d", lineno); + xo_errx(1, "duplicated tgtChapSecret at line %d", lineno); target->t_mutual_secret = $3; } ; auth_method: AUTH_METHOD EQUALS STR { if (target->t_auth_method != AUTH_METHOD_UNSPECIFIED) - errx(1, "duplicated AuthMethod at line %d", lineno); + xo_errx(1, "duplicated AuthMethod at line %d", lineno); if (strcasecmp($3, "none") == 0) target->t_auth_method = AUTH_METHOD_NONE; else if (strcasecmp($3, "chap") == 0) target->t_auth_method = AUTH_METHOD_CHAP; else - errx(1, "invalid AuthMethod at line %d; " + xo_errx(1, "invalid AuthMethod at line %d; " "must be either \"none\" or \"CHAP\"", lineno); } ; header_digest: HEADER_DIGEST EQUALS STR { if (target->t_header_digest != DIGEST_UNSPECIFIED) - errx(1, "duplicated HeaderDigest at line %d", lineno); + xo_errx(1, "duplicated HeaderDigest at line %d", lineno); if (strcasecmp($3, "none") == 0) target->t_header_digest = DIGEST_NONE; else if (strcasecmp($3, "CRC32C") == 0) target->t_header_digest = DIGEST_CRC32C; else - errx(1, "invalid HeaderDigest at line %d; " + xo_errx(1, "invalid HeaderDigest at line %d; " "must be either \"none\" or \"CRC32C\"", lineno); } ; data_digest: DATA_DIGEST EQUALS STR { if (target->t_data_digest != DIGEST_UNSPECIFIED) - errx(1, "duplicated DataDigest at line %d", lineno); + xo_errx(1, "duplicated DataDigest at line %d", lineno); if (strcasecmp($3, "none") == 0) target->t_data_digest = DIGEST_NONE; else if (strcasecmp($3, "CRC32C") == 0) target->t_data_digest = DIGEST_CRC32C; else - errx(1, "invalid DataDigest at line %d; " + xo_errx(1, "invalid DataDigest at line %d; " "must be either \"none\" or \"CRC32C\"", lineno); } ; session_type: SESSION_TYPE EQUALS STR { if (target->t_session_type != SESSION_TYPE_UNSPECIFIED) - errx(1, "duplicated SessionType at line %d", lineno); + xo_errx(1, "duplicated SessionType at line %d", lineno); if (strcasecmp($3, "normal") == 0) target->t_session_type = SESSION_TYPE_NORMAL; else if (strcasecmp($3, "discovery") == 0) target->t_session_type = SESSION_TYPE_DISCOVERY; else - errx(1, "invalid SessionType at line %d; " + xo_errx(1, "invalid SessionType at line %d; " "must be either \"normal\" or \"discovery\"", lineno); } ; offload: OFFLOAD EQUALS STR { if (target->t_offload != NULL) - errx(1, "duplicated offload at line %d", lineno); + xo_errx(1, "duplicated offload at line %d", lineno); target->t_offload = $3; } ; protocol: PROTOCOL EQUALS STR { if (target->t_protocol != PROTOCOL_UNSPECIFIED) - errx(1, "duplicated protocol at line %d", lineno); + xo_errx(1, "duplicated protocol at line %d", lineno); if (strcasecmp($3, "iscsi") == 0) target->t_protocol = PROTOCOL_ISCSI; else if (strcasecmp($3, "iser") == 0) target->t_protocol = PROTOCOL_ISER; else - errx(1, "invalid protocol at line %d; " + xo_errx(1, "invalid protocol at line %d; " "must be either \"iscsi\" or \"iser\"", lineno); } ; ignored: IGNORED EQUALS STR { - warnx("obsolete statement ignored at line %d", lineno); + xo_warnx("obsolete statement ignored at line %d", lineno); } ; %% void yyerror(const char *str) { - errx(1, "error in configuration file at line %d near '%s': %s", + xo_errx(1, "error in configuration file at line %d near '%s': %s", lineno, yytext, str); } static void check_perms(const char *path) { struct stat sb; int error; error = stat(path, &sb); if (error != 0) { - warn("stat"); + xo_warn("stat"); return; } if (sb.st_mode & S_IWOTH) { - warnx("%s is world-writable", path); + xo_warnx("%s is world-writable", path); } else if (sb.st_mode & S_IROTH) { - warnx("%s is world-readable", path); + xo_warnx("%s is world-readable", path); } else if (sb.st_mode & S_IXOTH) { /* * Ok, this one doesn't matter, but still do it, * just for consistency. */ - warnx("%s is world-executable", path); + xo_warnx("%s is world-executable", path); } /* * XXX: Should we also check for owner != 0? */ } struct conf * conf_new_from_file(const char *path) { int error; conf = conf_new(); target = target_new(conf); yyin = fopen(path, "r"); if (yyin == NULL) - err(1, "unable to open configuration file %s", path); + xo_err(1, "unable to open configuration file %s", path); check_perms(path); lineno = 1; yyrestart(yyin); error = yyparse(); assert(error == 0); fclose(yyin); assert(target->t_nickname == NULL); target_delete(target); conf_verify(conf); return (conf); } Index: head/usr.bin/iscsictl/periphs.c =================================================================== --- head/usr.bin/iscsictl/periphs.c (revision 281460) +++ head/usr.bin/iscsictl/periphs.c (revision 281461) @@ -1,186 +1,202 @@ /* * Copyright (c) 1997-2007 Kenneth D. Merry * Copyright (c) 2012 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by Edward Tomasz Napierala * under sponsorship from the FreeBSD Foundation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include -#include #include #include #include #include #include #include #include #include #include #include +#include #include "iscsictl.h" void print_periphs(int session_id) { union ccb ccb; int bufsize, fd; unsigned int i; - int skip_bus, skip_device; + int have_path_id, skip_bus, skip_device; + path_id_t path_id; if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) { - warn("couldn't open %s", XPT_DEVICE); + xo_warn("couldn't open %s", XPT_DEVICE); return; } /* * First, iterate over the whole list to find the bus. */ bzero(&ccb, sizeof(union ccb)); ccb.ccb_h.path_id = CAM_XPT_PATH_ID; ccb.ccb_h.target_id = CAM_TARGET_WILDCARD; ccb.ccb_h.target_lun = CAM_LUN_WILDCARD; ccb.ccb_h.func_code = XPT_DEV_MATCH; bufsize = sizeof(struct dev_match_result) * 100; ccb.cdm.match_buf_len = bufsize; ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize); if (ccb.cdm.matches == NULL) { - warnx("can't malloc memory for matches"); + xo_warnx("can't malloc memory for matches"); close(fd); return; } ccb.cdm.num_matches = 0; /* * We fetch all nodes, since we display most of them in the default * case, and all in the verbose case. */ ccb.cdm.num_patterns = 0; ccb.cdm.pattern_buf_len = 0; + path_id = -1; /* Make GCC happy. */ + have_path_id = 0; skip_bus = 1; skip_device = 1; + xo_open_container("devices"); + xo_open_list("lun"); /* * We do the ioctl multiple times if necessary, in case there are * more than 100 nodes in the EDT. */ do { if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) { - warn("error sending CAMIOCOMMAND ioctl"); + xo_warn("error sending CAMIOCOMMAND ioctl"); break; } if ((ccb.ccb_h.status != CAM_REQ_CMP) || ((ccb.cdm.status != CAM_DEV_MATCH_LAST) && (ccb.cdm.status != CAM_DEV_MATCH_MORE))) { - warnx("got CAM error %#x, CDM error %d\n", + xo_warnx("got CAM error %#x, CDM error %d\n", ccb.ccb_h.status, ccb.cdm.status); break; } for (i = 0; i < ccb.cdm.num_matches; i++) { switch (ccb.cdm.matches[i].type) { case DEV_MATCH_BUS: { struct bus_match_result *bus_result; bus_result = &ccb.cdm.matches[i].result.bus_result; skip_bus = 1; if (strcmp(bus_result->dev_name, "iscsi") != 0) { //printf("not iscsi\n"); continue; } if ((int)bus_result->unit_number != session_id) { //printf("wrong unit, %d != %d\n", bus_result->unit_number, session_id); continue; } - skip_bus = 0; } case DEV_MATCH_DEVICE: { skip_device = 1; if (skip_bus != 0) continue; skip_device = 0; - break; } case DEV_MATCH_PERIPH: { struct periph_match_result *periph_result; periph_result = &ccb.cdm.matches[i].result.periph_result; if (skip_device != 0) continue; if (strcmp(periph_result->periph_name, "pass") == 0) continue; - fprintf(stdout, "%s%d ", - periph_result->periph_name, - periph_result->unit_number); + xo_open_instance("lun"); + xo_emit("{e:lun/%d}", periph_result->target_lun); + xo_emit("{Vq:device/%s%d} ", + periph_result->periph_name, + periph_result->unit_number); + xo_close_instance("lun"); + if (have_path_id == 0) { + path_id = periph_result->path_id; + have_path_id = 1; + } + break; } default: fprintf(stdout, "unknown match type\n"); break; } } } while ((ccb.ccb_h.status == CAM_REQ_CMP) && (ccb.cdm.status == CAM_DEV_MATCH_MORE)); + xo_close_list("lun"); + + xo_emit("{e:scbus/%d}{e:bus/%d}{e:target/%d}", + have_path_id ? (int)path_id : -1, 0, have_path_id ? 0 : -1); + xo_close_container("devices"); close(fd); }