[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