[Midnightbsd-cvs] src [11520] trunk/usr.bin/iscsictl: add iscsictl
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Sat Jul 7 15:22:04 EDT 2018
Revision: 11520
http://svnweb.midnightbsd.org/src/?rev=11520
Author: laffer1
Date: 2018-07-07 15:22:04 -0400 (Sat, 07 Jul 2018)
Log Message:
-----------
add iscsictl
Added Paths:
-----------
trunk/usr.bin/iscsictl/
trunk/usr.bin/iscsictl/Makefile
trunk/usr.bin/iscsictl/iscsi.conf.5
trunk/usr.bin/iscsictl/iscsictl.8
trunk/usr.bin/iscsictl/iscsictl.c
trunk/usr.bin/iscsictl/iscsictl.h
trunk/usr.bin/iscsictl/parse.y
trunk/usr.bin/iscsictl/periphs.c
trunk/usr.bin/iscsictl/token.l
Added: trunk/usr.bin/iscsictl/Makefile
===================================================================
--- trunk/usr.bin/iscsictl/Makefile (rev 0)
+++ trunk/usr.bin/iscsictl/Makefile 2018-07-07 19:22:04 UTC (rev 11520)
@@ -0,0 +1,20 @@
+# $MidnightBSD$
+# $FreeBSD: stable/10/usr.bin/iscsictl/Makefile 277173 2015-01-14 11:29:16Z trasz $
+
+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
+
+DPADD= ${LIBCAM} ${LIBUTIL}
+LDADD= -lcam -lutil
+
+YFLAGS+= -v
+LFLAGS+= -i
+CLEANFILES= y.tab.c y.tab.h y.output
+
+WARNS= 6
+NO_WMISSING_VARIABLE_DECLARATIONS=
+
+.include <bsd.prog.mk>
Property changes on: trunk/usr.bin/iscsictl/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/iscsictl/iscsi.conf.5
===================================================================
--- trunk/usr.bin/iscsictl/iscsi.conf.5 (rev 0)
+++ trunk/usr.bin/iscsictl/iscsi.conf.5 2018-07-07 19:22:04 UTC (rev 11520)
@@ -0,0 +1,189 @@
+.\" $MidnightBSD$
+.\" Copyright (c) 2007-2010 Daniel Braniss <danny at cs.huji.ac.il>
+.\" All rights reserved.
+.\"
+.\" 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: stable/10/usr.bin/iscsictl/iscsi.conf.5 277173 2015-01-14 11:29:16Z trasz $
+.\"
+.Dd December 17, 2013
+.Dt ISCSI.CONF 5
+.Os
+.Sh NAME
+.Nm iscsi.conf
+.Nd iSCSI initiator configuration file
+.Sh DESCRIPTION
+The file
+.Nm ,
+is used by the
+.Xr iscsictl 8
+and
+.Xr iscontrol 8
+utilities.
+It contains declarations and parameter/key-options.
+The syntax is very simple,
+.D1 Li variable = value;
+and they can be grouped via a
+.Em block
+declaration:
+.Bf Li
+.Bd -literal
+ # this is a comment
+ target_1 { # nickname
+ variable = value;
+ ...
+ } # this must be on a line by itself.
+.Ed
+.Ef
+.Pp
+The following are specified in the iSCSI RFC 3720,
+for a full description see sections 11/12 of the RFC.
+.Bl -tag -width MaxConnections
+.It Cm AuthMethod
+currently only supported authentication method is CHAP, with
+digest either MD5 or SHA.
+Default is none.
+.It Cm HeaderDigest
+a
+.Em digest
+is calculated on the header of all iSCSI PDUs, and
+checked.
+Only CRC32C is implemented.
+Default is none.
+.It Cm DataDigest
+same as for HeaderDigest, but on the data part of the iSCSI PDU.
+(not yet tested)
+.It Cm TargetName
+is the name by which the target is known, not to be confused with
+target address, either obtained via the target administrator, or
+from a
+.Em discovery session .
+.It Cm InitiatorName
+if not specified, defaults to
+.Sy iqn.2005-01.il.ac.huji.cs:
+.Aq hostname .
+.It Cm TargetAddress
+is of the form
+.Sy domainname[:port][,portal-group-tag]
+to quote the RFC:
+.Bd -ragged -compact
+The domainname can be specified as either a DNS host name, a
+dotted-decimal IPv4 address, or a bracketed IPv6 address as specified
+in [RFC2732].
+.Ed
+Note: portal-group-tag is unused at the moment.
+.Em not implemented yet.
+.It Cm MaxRecvDataSegmentLength
+the maximum data segment length in
+bytes it can receive in an iSCSI PDU, default is 8192.
+.It Cm MaxOutstandingR2T
+is used to calculate/negotiate the
+.Em tag opening ,
+can be overridden by the
+.Sy tag
+option.
+.It Cm SessionType
+either Discovery or Normal, default is Normal, see the
+.Fl d
+flag of
+.Cm iscontrol .
+.El
+.sp
+The following are not specified in the
+.Sy RFC 3720
+.Bl -tag -width sockbufsize
+.It Cm port
+The iSCSI port used by the iSCSI protocol, defaults to 3260.
+.It Cm tags
+Sets the
+.Em tag opening
+to the value specified.
+.It Cm maxluns
+overrides the compiled value of
+.Sy luns ,
+see
+.Xr iscsi_initiator 4 .
+This value can only be reduced.
+.It Cm sockbufsize
+sets the receiver and transmitter socket buffer size to
+.Em size ,
+in kilobytes.
+The default is 128.
+.El
+.sp
+If
+.Em AuthMethod
+is set to
+.Cm CHAP ,
+then the following must also be set:
+.Bl -tag -width chapSecret
+.It Cm chapSecret
+this
+.Em shared-secret .
+Can be either an ASCII string (e.g. hello world), a hex string (e.g
+0xababcd0987654321...), or base64 string (eg 0b...)
+.It Cm chapIName
+the chap-name, defaults to
+.Em hostname .
+.It Cm chapDigest
+can be MD5 or SHA1.
+.It Cm tgtChapName/tgtChapSecret
+name and secret used for mutual CHAP; by default, mutual CHAP
+is not used.
+.El
+.Sh FILES
+.Bl -tag -width indent
+.It Pa /etc/iscsi.conf
+.El
+.Sh EXAMPLES
+.Bd -literal
+#
+# Globals
+#
+port = 3260
+#
+myiscsi { # nickname
+ targetaddress = iscsi1
+ targetname = iqn.1900.com.com:sn.123456
+}
+chaptest {
+ targetaddress= 10.0.0.1;
+ targetname = iqn.1900.com.com:sn.123456
+ initiatorname= iqn.2005-01.il.ac.huji.cs:nobody
+ authmethod = CHAP; chapDigest = SHA1;
+ chapsecret = 0x3713c3336d9a224c2791c873d3d2b174
+ tags = 256
+}
+.Ed
+.Sh SEE ALSO
+.Xr iscsi_initiator 4 ,
+.Xr iscsictl 8 ,
+.Xr iscontrol 8
+.Sh STANDARDS
+ISCSI RFC 3720
+.\"Sh HISTORY
+.\"Sh AUTHORS
+.Sh BUGS
+Some options have not been implemented, either they were found
+to be unnecessary, or not understood, this can change in the future.
+.br
+The tags opening value is difficult to calculate, use wisely.
Property changes on: trunk/usr.bin/iscsictl/iscsi.conf.5
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/iscsictl/iscsictl.8
===================================================================
--- trunk/usr.bin/iscsictl/iscsictl.8 (rev 0)
+++ trunk/usr.bin/iscsictl/iscsictl.8 2018-07-07 19:22:04 UTC (rev 11520)
@@ -0,0 +1,197 @@
+.\" $MidnightBSD$
+.\" 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 AUTHORS 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 AUTHORS 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: stable/10/usr.bin/iscsictl/iscsictl.8 294635 2016-01-23 15:48:14Z trasz $
+.\"
+.Dd October 17, 2015
+.Dt ISCSICTL 8
+.Os
+.Sh NAME
+.Nm iscsictl
+.Nd iSCSI initiator management utility
+.Sh SYNOPSIS
+.Nm
+.Fl A
+.Fl p Ar portal Fl t Ar target
+.Op Fl u Ar user Fl s Ar secret
+.Op Fl w Ar timeout
+.Nm
+.Fl A
+.Fl d Ar discovery-host Op Fl u Ar user Fl s Ar secret
+.Nm
+.Fl A
+.Fl a Op Fl c Ar path
+.Nm
+.Fl A
+.Fl n Ar nickname Op Fl c Ar path
+.Nm
+.Fl M
+.Fl i Ar session-id
+.Op Fl p Ar portal
+.Op Fl t Ar target
+.Op Fl u Ar user
+.Op Fl s Ar secret
+.Nm
+.Fl M
+.Fl i Ar session-id
+.Op Fl n Ar nickname Op Fl c Ar path
+.Nm
+.Fl R
+.Op Fl p Ar portal
+.Op Fl t Ar target
+.Nm
+.Fl R
+.Fl a
+.Nm
+.Fl R
+.Fl n Ar nickname Op Fl c Ar path
+.Nm
+.Fl L
+.Op Fl v
+.Op Fl w Ar timeout
+.Sh DESCRIPTION
+The
+.Nm
+utility is used to configure the iSCSI initiator.
+.Pp
+The following options are available:
+.Bl -tag -width ".Fl A"
+.It Fl A
+Add session.
+.It Fl M
+Modify session.
+.It Fl R
+Remove session.
+.It Fl L
+List sessions.
+.It Fl a
+When adding, add all sessions defined in the configuration file.
+When removing, remove all currently established sessions.
+.It Fl c
+Path to the configuration file.
+The default is
+.Pa /etc/iscsi.conf .
+.It Fl d
+Target host name or address used for SendTargets discovery.
+When used, it will add a temporary discovery session.
+After discovery is done, sessions will be added for each discovered target,
+and the temporary discovery session will be removed.
+.It Fl i
+Session ID, as displayed by
+.Nm
+.Fl v .
+.It Fl n
+The "nickname" of session defined in the configuration file.
+.It Fl p
+Target portal - host name or address - for statically defined targets.
+.It Fl s
+CHAP secret.
+.It Fl t
+Target name.
+.It Fl u
+CHAP login.
+.It Fl v
+Verbose mode.
+.It Fl w
+Instead of returning immediately, wait up to
+.Ar timeout
+seconds until all configured sessions are successfully established.
+.El
+.Pp
+Certain parameters are necessary when adding a session.
+One can specify these either via command line (using the
+.Fl t ,
+.Fl p ,
+.Fl u ,
+and
+.Fl s
+options), or configuration file (using the
+.Fl a
+or
+.Fl n
+options).
+Some functionality - for example mutual CHAP - is available only
+via configuration file.
+.Pp
+Since connecting to the target is performed in background, non-zero
+exit status does not mean that the session was successfully established.
+Use either
+.Nm Fl L
+to check the connection status, or the
+.Fl w
+flag to wait for session establishment.
+.Pp
+Note that in order for the iSCSI initiator to be able to connect to a target,
+the
+.Xr iscsid 8
+daemon must be running.
+.Pp
+Also note that
+.Fx
+currently supports two different initiators: the old one,
+.Xr iscsi_initiator 4 ,
+with its control utility
+.Xr iscontrol 8 ,
+and the new one,
+.Xr iscsi 4 ,
+with
+.Nm
+and
+.Xr iscsid 8 .
+The only thing the two have in common is the configuration file,
+.Xr iscsi.conf 5 .
+.Sh FILES
+.Bl -tag -width ".Pa /etc/iscsi.conf" -compact
+.It Pa /etc/iscsi.conf
+iSCSI initiator configuration file.
+.El
+.Sh EXIT STATUS
+The
+.Nm
+utility exits 0 on success, and >0 if an error occurs.
+.Sh EXAMPLES
+Attach to target iqn.2012-06.com.example:target0, served by 192.168.1.1:
+.Dl Nm Fl A Fl t Ar iqn.2012-06.com.example:target0 Fl p Ar 192.168.1.1
+.Pp
+Disconnect all iSCSI sessions:
+.Dl Nm Fl Ra
+.Sh SEE ALSO
+.Xr iscsi 4 ,
+.Xr iscsi.conf 5 ,
+.Xr iscsid 8
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Fx 10.0 .
+.Sh AUTHORS
+The
+.Nm
+utility was developed by
+.An Edward Tomasz Napierala Aq trasz at FreeBSD.org
+under sponsorship from the FreeBSD Foundation.
Property changes on: trunk/usr.bin/iscsictl/iscsictl.8
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/iscsictl/iscsictl.c
===================================================================
--- trunk/usr.bin/iscsictl/iscsictl.c (rev 0)
+++ trunk/usr.bin/iscsictl/iscsictl.c 2018-07-07 19:22:04 UTC (rev 11520)
@@ -0,0 +1,935 @@
+/* $MidnightBSD$ */
+/*-
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/usr.bin/iscsictl/iscsictl.c 294635 2016-01-23 15:48:14Z trasz $");
+
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/linker.h>
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <iscsi_ioctl.h>
+#include "iscsictl.h"
+
+struct conf *
+conf_new(void)
+{
+ struct conf *conf;
+
+ conf = calloc(1, sizeof(*conf));
+ if (conf == NULL)
+ 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");
+ 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");
+ strcpy(name, DEFAULT_IQN);
+ error = gethostname(name + strlen(DEFAULT_IQN),
+ namelen - strlen(DEFAULT_IQN));
+ if (error != 0)
+ 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 "
+ "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 "
+ "\"%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.\" "
+ "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 "
+ "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.\" "
+ "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 "
+ "name \"%s\"; allowed characters are 1-9 "
+ "and A-F", name[i], name);
+ break;
+ }
+ }
+ } else {
+ 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\"",
+ targ->t_nickname);
+ if (targ->t_session_type == SESSION_TYPE_DISCOVERY &&
+ targ->t_name != NULL)
+ 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\"",
+ 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\"",
+ 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\"",
+ 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\"",
+ targ->t_nickname);
+ }
+ if (targ->t_secret == NULL)
+ 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 "
+ "target \"%s\"", targ->t_nickname);
+ if (targ->t_mutual_secret == NULL)
+ 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_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");
+ 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");
+ 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");
+
+ 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");
+
+ 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);
+
+ 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");
+}
+
+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");
+ 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");
+
+ 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");
+ return (error);
+ }
+
+ if (verbose != 0) {
+ 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",
+ 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",
+ state->iss_header_digest == ISCSI_DIGEST_CRC32C ?
+ "CRC32C" : "None");
+ printf("Data digest: %s\n",
+ 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("Device nodes: ");
+ print_periphs(state->iss_id);
+ printf("\n\n");
+ }
+ } else {
+ printf("%-36s %-16s %s\n",
+ "Target name", "Target portal", "State");
+ for (i = 0; i < isl.isl_nentries; i++) {
+ state = &states[i];
+ conf = &state->iss_conf;
+
+ printf("%-36s %-16s ",
+ conf->isc_target, conf->isc_target_addr);
+
+ if (state->iss_reason[0] != '\0') {
+ printf("%s\n", state->iss_reason);
+ } else {
+ if (conf->isc_discovery) {
+ printf("Discovery\n");
+ } else if (state->iss_connected) {
+ printf("Connected: ");
+ print_periphs(state->iss_id);
+ printf("\n");
+ } else {
+ printf("Disconnected\n");
+ }
+ }
+ }
+ }
+
+ return (0);
+}
+
+static int
+kernel_wait(int iscsi_fd, int timeout)
+{
+ 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;
+ bool all_connected;
+ int error;
+
+ for (;;) {
+ for (;;) {
+ states = realloc(states,
+ nentries * sizeof(struct iscsi_session_state));
+ if (states == NULL)
+ 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");
+ return (error);
+ }
+
+ all_connected = true;
+ for (i = 0; i < isl.isl_nentries; i++) {
+ state = &states[i];
+ conf = &state->iss_conf;
+
+ if (!state->iss_connected) {
+ all_connected = false;
+ break;
+ }
+ }
+
+ if (all_connected)
+ return (0);
+
+ sleep(1);
+
+ if (timeout > 0) {
+ timeout--;
+ if (timeout == 0)
+ return (1);
+ }
+ }
+}
+
+static void
+usage(void)
+{
+
+ fprintf(stderr, "usage: iscsictl -A -p portal -t target "
+ "[-u user -s secret] [-w timeout]\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] [-w timeout]\n");
+ exit(1);
+}
+
+char *
+checked_strdup(const char *s)
+{
+ char *c;
+
+ c = strdup(s);
+ if (c == NULL)
+ 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;
+ int timeout = -1;
+ long long session_id = -1;
+ char *end;
+ int ch, error, iscsi_fd, retval, saved_errno;
+ int failed = 0;
+ struct conf *conf;
+ struct target *targ;
+
+ while ((ch = getopt(argc, argv, "AMRLac:d:i:n:p:t:u:s:vw:")) != -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");
+ if (session_id < 0)
+ errx(1, "session-id cannot be negative");
+ if (session_id > UINT_MAX)
+ 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 'w':
+ timeout = strtol(optarg, &end, 10);
+ if ((size_t)(end - optarg) != strlen(optarg))
+ errx(1, "trailing characters after timeout");
+ if (timeout < 0)
+ errx(1, "timeout cannot be negative");
+ 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");
+
+ /*
+ * 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");
+ if (target != NULL)
+ errx(1, "-a and -t and mutually exclusive");
+ if (user != NULL)
+ errx(1, "-a and -u and mutually exclusive");
+ if (secret != NULL)
+ errx(1, "-a and -s and mutually exclusive");
+ if (nickname != NULL)
+ errx(1, "-a and -n and mutually exclusive");
+ if (discovery_host != NULL)
+ errx(1, "-a and -d and mutually exclusive");
+ } else if (nickname != NULL) {
+ if (portal != NULL)
+ errx(1, "-n and -p and mutually exclusive");
+ if (target != NULL)
+ errx(1, "-n and -t and mutually exclusive");
+ if (user != NULL)
+ errx(1, "-n and -u and mutually exclusive");
+ if (secret != NULL)
+ errx(1, "-n and -s and mutually exclusive");
+ if (discovery_host != NULL)
+ errx(1, "-n and -d and mutually exclusive");
+ } else if (discovery_host != NULL) {
+ if (portal != NULL)
+ errx(1, "-d and -p and mutually exclusive");
+ if (target != NULL)
+ errx(1, "-d and -t and mutually exclusive");
+ } else {
+ if (target == NULL && portal == NULL)
+ errx(1, "must specify -a, -n or -t/-p");
+
+ if (target != NULL && portal == NULL)
+ errx(1, "-t must always be used with -p");
+ if (portal != NULL && target == NULL)
+ errx(1, "-p must always be used with -t");
+ }
+
+ if (user != NULL && secret == NULL)
+ errx(1, "-u must always be used with -s");
+ if (secret != NULL && user == NULL)
+ errx(1, "-s must always be used with -u");
+
+ if (session_id != -1)
+ errx(1, "-i cannot be used with -A");
+ if (vflag != 0)
+ errx(1, "-v cannot be used with -A");
+
+ } else if (Mflag != 0) {
+ if (session_id == -1)
+ errx(1, "-M requires -i");
+
+ if (discovery_host != NULL)
+ errx(1, "-M and -d are mutually exclusive");
+ if (aflag != 0)
+ errx(1, "-M and -a are mutually exclusive");
+ if (nickname != NULL) {
+ if (portal != NULL)
+ errx(1, "-n and -p and mutually exclusive");
+ if (target != NULL)
+ errx(1, "-n and -t and mutually exclusive");
+ if (user != NULL)
+ errx(1, "-n and -u and mutually exclusive");
+ if (secret != NULL)
+ errx(1, "-n and -s and mutually exclusive");
+ }
+
+ if (vflag != 0)
+ errx(1, "-v cannot be used with -M");
+ if (timeout != -1)
+ errx(1, "-w cannot be used with -M");
+
+ } else if (Rflag != 0) {
+ if (user != NULL)
+ errx(1, "-R and -u are mutually exclusive");
+ if (secret != NULL)
+ errx(1, "-R and -s are mutually exclusive");
+ if (discovery_host != NULL)
+ errx(1, "-R and -d are mutually exclusive");
+
+ if (aflag != 0) {
+ if (portal != NULL)
+ errx(1, "-a and -p and mutually exclusive");
+ if (target != NULL)
+ errx(1, "-a and -t and mutually exclusive");
+ if (nickname != NULL)
+ errx(1, "-a and -n and mutually exclusive");
+ } else if (nickname != NULL) {
+ if (portal != NULL)
+ errx(1, "-n and -p and mutually exclusive");
+ if (target != NULL)
+ errx(1, "-n and -t and mutually exclusive");
+ } else if (target == NULL && portal == NULL) {
+ errx(1, "must specify either -a, -n, -t, or -p");
+ }
+
+ if (session_id != -1)
+ errx(1, "-i cannot be used with -R");
+ if (vflag != 0)
+ errx(1, "-v cannot be used with -R");
+ if (timeout != -1)
+ errx(1, "-w cannot be used with -R");
+
+ } else {
+ assert(Lflag != 0);
+
+ if (portal != NULL)
+ errx(1, "-L and -p and mutually exclusive");
+ if (target != NULL)
+ errx(1, "-L and -t and mutually exclusive");
+ if (user != NULL)
+ errx(1, "-L and -u and mutually exclusive");
+ if (secret != NULL)
+ errx(1, "-L and -s and mutually exclusive");
+ if (nickname != NULL)
+ errx(1, "-L and -n and mutually exclusive");
+ if (discovery_host != NULL)
+ errx(1, "-L and -d and mutually exclusive");
+
+ if (session_id != -1)
+ 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);
+
+ 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",
+ 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);
+ }
+ 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);
+ }
+
+ if (timeout != -1)
+ failed += kernel_wait(iscsi_fd, timeout);
+
+ error = close(iscsi_fd);
+ if (error != 0)
+ err(1, "close");
+
+ if (failed > 0)
+ return (1);
+ return (0);
+}
Property changes on: trunk/usr.bin/iscsictl/iscsictl.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/iscsictl/iscsictl.h
===================================================================
--- trunk/usr.bin/iscsictl/iscsictl.h (rev 0)
+++ trunk/usr.bin/iscsictl/iscsictl.h 2018-07-07 19:22:04 UTC (rev 11520)
@@ -0,0 +1,117 @@
+/* $MidnightBSD$ */
+/*-
+ * 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: stable/10/usr.bin/iscsictl/iscsictl.h 255570 2013-09-14 15:29:06Z trasz $
+ */
+
+#ifndef ISCSICTL_H
+#define ISCSICTL_H
+
+#include <sys/queue.h>
+#include <stdbool.h>
+#include <libutil.h>
+
+#define DEFAULT_CONFIG_PATH "/etc/iscsi.conf"
+#define DEFAULT_IQN "iqn.1994-09.org.freebsd:"
+
+#define MAX_NAME_LEN 223
+#define MAX_DATA_SEGMENT_LENGTH 65536
+
+#define AUTH_METHOD_UNSPECIFIED 0
+#define AUTH_METHOD_NONE 1
+#define AUTH_METHOD_CHAP 2
+
+#define DIGEST_UNSPECIFIED 0
+#define DIGEST_NONE 1
+#define DIGEST_CRC32C 2
+
+#define SESSION_TYPE_UNSPECIFIED 0
+#define SESSION_TYPE_NORMAL 1
+#define SESSION_TYPE_DISCOVERY 2
+
+#define PROTOCOL_UNSPECIFIED 0
+#define PROTOCOL_ISCSI 1
+#define PROTOCOL_ISER 2
+
+struct target {
+ TAILQ_ENTRY(target) t_next;
+ struct conf *t_conf;
+ char *t_nickname;
+ char *t_name;
+ char *t_address;
+ char *t_initiator_name;
+ char *t_initiator_address;
+ char *t_initiator_alias;
+ int t_header_digest;
+ int t_data_digest;
+ int t_auth_method;
+ int t_session_type;
+ int t_protocol;
+ char *t_user;
+ char *t_secret;
+ char *t_mutual_user;
+ char *t_mutual_secret;
+};
+
+struct conf {
+ TAILQ_HEAD(, target) conf_targets;
+};
+
+#define CONN_SESSION_TYPE_NONE 0
+#define CONN_SESSION_TYPE_DISCOVERY 1
+#define CONN_SESSION_TYPE_NORMAL 2
+
+struct connection {
+ struct target *conn_target;
+ int conn_socket;
+ int conn_session_type;
+ uint32_t conn_cmdsn;
+ uint32_t conn_statsn;
+ size_t conn_max_data_segment_length;
+ size_t conn_max_burst_length;
+ size_t conn_max_outstanding_r2t;
+ int conn_header_digest;
+ int conn_data_digest;
+};
+
+struct conf *conf_new(void);
+struct conf *conf_new_from_file(const char *path);
+void conf_delete(struct conf *conf);
+void conf_verify(struct conf *conf);
+
+struct target *target_new(struct conf *conf);
+struct target *target_find(struct conf *conf, const char *nickname);
+void target_delete(struct target *ic);
+
+void print_periphs(int session_id);
+
+char *checked_strdup(const char *);
+bool valid_iscsi_name(const char *name);
+
+#endif /* !ISCSICTL_H */
Property changes on: trunk/usr.bin/iscsictl/iscsictl.h
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/iscsictl/parse.y
===================================================================
--- trunk/usr.bin/iscsictl/parse.y (rev 0)
+++ trunk/usr.bin/iscsictl/parse.y 2018-07-07 19:22:04 UTC (rev 11520)
@@ -0,0 +1,336 @@
+/* $MidnightBSD$ */
+%{
+/*-
+ * 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: stable/10/usr.bin/iscsictl/parse.y 262841 2014-03-06 11:07:51Z trasz $
+ */
+
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <assert.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 IGNORED
+%token EQUALS OPENING_BRACKET CLOSING_BRACKET
+
+%union
+{
+ char *str;
+}
+
+%token <str> STR
+
+%%
+
+targets:
+ |
+ targets target
+ ;
+
+target: STR OPENING_BRACKET target_entries CLOSING_BRACKET
+ {
+ if (target_find(conf, $1) != NULL)
+ 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
+ |
+ protocol
+ |
+ ignored
+ ;
+
+target_name: TARGET_NAME EQUALS STR
+ {
+ if (target->t_name != NULL)
+ 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);
+ target->t_address = $3;
+ }
+ ;
+
+initiator_name: INITIATOR_NAME EQUALS STR
+ {
+ if (target->t_initiator_name != NULL)
+ 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);
+ 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);
+ target->t_initiator_alias = $3;
+ }
+ ;
+
+user: USER EQUALS STR
+ {
+ if (target->t_user != NULL)
+ 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);
+ target->t_secret = $3;
+ }
+ ;
+
+mutual_user: MUTUAL_USER EQUALS STR
+ {
+ if (target->t_mutual_user != NULL)
+ 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);
+ 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);
+ 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; "
+ "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);
+ 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; "
+ "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);
+ 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; "
+ "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);
+ 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; "
+ "must be either \"normal\" or \"discovery\"", lineno);
+ }
+ ;
+
+protocol: PROTOCOL EQUALS STR
+ {
+ if (target->t_protocol != PROTOCOL_UNSPECIFIED)
+ 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; "
+ "must be either \"iscsi\" or \"iser\"", lineno);
+ }
+ ;
+
+ignored: IGNORED EQUALS STR
+ {
+ 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",
+ lineno, yytext, str);
+}
+
+static void
+check_perms(const char *path)
+{
+ struct stat sb;
+ int error;
+
+ error = stat(path, &sb);
+ if (error != 0) {
+ warn("stat");
+ return;
+ }
+ if (sb.st_mode & S_IWOTH) {
+ warnx("%s is world-writable", path);
+ } else if (sb.st_mode & S_IROTH) {
+ 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);
+ }
+
+ /*
+ * 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);
+ 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);
+}
Property changes on: trunk/usr.bin/iscsictl/parse.y
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: trunk/usr.bin/iscsictl/periphs.c
===================================================================
--- trunk/usr.bin/iscsictl/periphs.c (rev 0)
+++ trunk/usr.bin/iscsictl/periphs.c 2018-07-07 19:22:04 UTC (rev 11520)
@@ -0,0 +1,187 @@
+/* $MidnightBSD$ */
+/*
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/usr.bin/iscsictl/periphs.c 265532 2014-05-07 08:04:41Z trasz $");
+
+#include <sys/ioctl.h>
+#include <sys/stdint.h>
+#include <sys/types.h>
+#include <sys/endian.h>
+#include <sys/sbuf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <err.h>
+
+#include <cam/cam.h>
+#include <cam/cam_debug.h>
+#include <cam/cam_ccb.h>
+#include <cam/scsi/scsi_all.h>
+#include <cam/scsi/scsi_da.h>
+#include <cam/scsi/scsi_pass.h>
+#include <cam/scsi/scsi_message.h>
+#include <cam/scsi/smp_all.h>
+#include <cam/ata/ata_all.h>
+#include <camlib.h>
+
+#include "iscsictl.h"
+
+void
+print_periphs(int session_id)
+{
+ union ccb ccb;
+ int bufsize, fd;
+ unsigned int i;
+ int skip_bus, skip_device;
+
+ if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
+ 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");
+ 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;
+
+ skip_bus = 1;
+ skip_device = 1;
+
+ /*
+ * 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");
+ 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",
+ 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);
+
+ break;
+ }
+ default:
+ fprintf(stdout, "unknown match type\n");
+ break;
+ }
+ }
+
+ } while ((ccb.ccb_h.status == CAM_REQ_CMP)
+ && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
+
+ close(fd);
+}
+
Property changes on: trunk/usr.bin/iscsictl/periphs.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/usr.bin/iscsictl/token.l
===================================================================
--- trunk/usr.bin/iscsictl/token.l (rev 0)
+++ trunk/usr.bin/iscsictl/token.l 2018-07-07 19:22:04 UTC (rev 11520)
@@ -0,0 +1,98 @@
+/* $MidnightBSD$ */
+%{
+/*-
+ * 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: stable/10/usr.bin/iscsictl/token.l 275248 2014-11-29 15:39:31Z trasz $
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "iscsictl.h"
+#include "y.tab.h"
+
+int lineno;
+
+#define YY_DECL int yylex(void)
+extern int yylex(void);
+
+%}
+
+%option noinput
+%option nounput
+%option noyywrap
+
+%%
+HeaderDigest { return HEADER_DIGEST; }
+DataDigest { return DATA_DIGEST; }
+TargetName { return TARGET_NAME; }
+TargetAddress { return TARGET_ADDRESS; }
+InitiatorName { return INITIATOR_NAME; }
+InitiatorAddress { return INITIATOR_ADDRESS; }
+InitiatorAlias { return INITIATOR_ALIAS; }
+chapIName { return USER; }
+chapSecret { return SECRET; }
+tgtChapName { return MUTUAL_USER; }
+tgtChapSecret { return MUTUAL_SECRET; }
+AuthMethod { return AUTH_METHOD; }
+SessionType { return SESSION_TYPE; }
+protocol { return PROTOCOL; }
+port { return IGNORED; }
+MaxConnections { return IGNORED; }
+TargetAlias { return IGNORED; }
+TargetPortalGroupTag { return IGNORED; }
+InitialR2T { return IGNORED; }
+ImmediateData { return IGNORED; }
+MaxRecvDataSegmentLength { return IGNORED; }
+MaxBurstLength { return IGNORED; }
+FirstBurstLength { return IGNORED; }
+DefaultTime2Wait { return IGNORED; }
+DefaultTime2Retain { return IGNORED; }
+MaxOutstandingR2T { return IGNORED; }
+DataPDUInOrder { return IGNORED; }
+DataSequenceInOrder { return IGNORED; }
+ErrorRecoveryLevel { return IGNORED; }
+tags { return IGNORED; }
+maxluns { return IGNORED; }
+sockbufsize { return IGNORED; }
+chapDigest { return IGNORED; }
+\"[^"]+\" { yylval.str = strndup(yytext + 1,
+ strlen(yytext) - 2); return STR; }
+[a-zA-Z0-9\.\-_/\:\[\]]+ { yylval.str = strdup(yytext); return STR; }
+\{ { return OPENING_BRACKET; }
+\} { return CLOSING_BRACKET; }
+= { return EQUALS; }
+; { return SEMICOLON; }
+#.*$ /* ignore comments */;
+\r\n { lineno++; }
+\n { lineno++; }
+[ \t]+ /* ignore whitespace */;
+. { yylval.str = strdup(yytext); return STR; }
+%%
Property changes on: trunk/usr.bin/iscsictl/token.l
___________________________________________________________________
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
More information about the Midnightbsd-cvs
mailing list