Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 28 Jul 2014 12:47:09 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r269183 - head/usr.sbin/ctld
Message-ID:  <201407281247.s6SCl9kF034529@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Mon Jul 28 12:47:09 2014
New Revision: 269183
URL: http://svnweb.freebsd.org/changeset/base/269183

Log:
  Add netmasks support to initiator-portal option.
  
  MFC after:	2 weeks

Modified:
  head/usr.sbin/ctld/ctl.conf.5
  head/usr.sbin/ctld/ctld.c
  head/usr.sbin/ctld/ctld.h
  head/usr.sbin/ctld/login.c

Modified: head/usr.sbin/ctld/ctl.conf.5
==============================================================================
--- head/usr.sbin/ctld/ctl.conf.5	Mon Jul 28 10:17:41 2014	(r269182)
+++ head/usr.sbin/ctld/ctl.conf.5	Mon Jul 28 12:47:09 2014	(r269183)
@@ -27,7 +27,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 20, 2014
+.Dd July 28, 2014
 .Dt CTL.CONF 5
 .Os
 .Sh NAME
@@ -119,7 +119,7 @@ name.
 Otherwise, only initiators with names matching one of defined
 ones will be allowed to connect.
 .It Ic initiator-portal Ao Ar address Ac
-Specifies iSCSI initiator portal - IPv4 or IPv6 address.
+Specifies iSCSI initiator portal - IPv4 or IPv6 address or network.
 If not defined, there will be no restrictions based on initiator
 address.
 Otherwise, only initiators with addresses matching one of defined

Modified: head/usr.sbin/ctld/ctld.c
==============================================================================
--- head/usr.sbin/ctld/ctld.c	Mon Jul 28 10:17:41 2014	(r269182)
+++ head/usr.sbin/ctld/ctld.c	Mon Jul 28 12:47:09 2014	(r269183)
@@ -34,6 +34,7 @@
 #include <sys/socket.h>
 #include <sys/wait.h>
 #include <netinet/in.h>
+#include <arpa/inet.h>
 #include <assert.h>
 #include <ctype.h>
 #include <errno.h>
@@ -319,14 +320,56 @@ const struct auth_portal *
 auth_portal_new(struct auth_group *ag, const char *portal)
 {
 	struct auth_portal *ap;
+	char *net, *mask, *str, *tmp;
+	int len, dm, m;
 
 	ap = calloc(1, sizeof(*ap));
 	if (ap == NULL)
 		log_err(1, "calloc");
 	ap->ap_auth_group = ag;
 	ap->ap_initator_portal = checked_strdup(portal);
+	mask = str = checked_strdup(portal);
+	net = strsep(&mask, "/");
+	if (net[0] == '[')
+		net++;
+	len = strlen(net);
+	if (len == 0)
+		goto error;
+	if (net[len - 1] == ']')
+		net[len - 1] = 0;
+	if (strchr(net, ':') != NULL) {
+		struct sockaddr_in6 *sin6 =
+		    (struct sockaddr_in6 *)&ap->ap_sa;
+
+		sin6->sin6_len = sizeof(*sin6);
+		sin6->sin6_family = AF_INET6;
+		if (inet_pton(AF_INET6, net, &sin6->sin6_addr) <= 0)
+			goto error;
+		dm = 128;
+	} else {
+		struct sockaddr_in *sin =
+		    (struct sockaddr_in *)&ap->ap_sa;
+
+		sin->sin_len = sizeof(*sin);
+		sin->sin_family = AF_INET;
+		if (inet_pton(AF_INET, net, &sin->sin_addr) <= 0)
+			goto error;
+		dm = 32;
+	}
+	if (mask != NULL) {
+		m = strtol(mask, &tmp, 0);
+		if (m < 0 || m > dm || tmp[0] != 0)
+			goto error;
+	} else
+		m = dm;
+	ap->ap_mask = m;
+	free(str);
 	TAILQ_INSERT_TAIL(&ag->ag_portals, ap, ap_next);
 	return (ap);
+
+error:
+	log_errx(1, "Incorrect initiator portal '%s'", portal);
+	return (NULL);
 }
 
 static void
@@ -347,13 +390,34 @@ auth_portal_defined(const struct auth_gr
 }
 
 const struct auth_portal *
-auth_portal_find(const struct auth_group *ag, const char *portal)
+auth_portal_find(const struct auth_group *ag, const struct sockaddr_storage *ss)
 {
-	const struct auth_portal *auth_portal;
+	const struct auth_portal *ap;
+	uint8_t *a, *b, bmask;
+	int i;
 
-	TAILQ_FOREACH(auth_portal, &ag->ag_portals, ap_next) {
-		if (strcmp(auth_portal->ap_initator_portal, portal) == 0)
-			return (auth_portal);
+	TAILQ_FOREACH(ap, &ag->ag_portals, ap_next) {
+		if (ap->ap_sa.ss_family != ss->ss_family)
+			continue;
+		if (ss->ss_family == AF_INET) {
+			a = (uint8_t *)&((struct sockaddr_in *)ss)->sin_addr;
+			b = (uint8_t *)&((struct sockaddr_in *)&ap->ap_sa)->sin_addr;
+		} else {
+			a = (uint8_t *)&((struct sockaddr_in6 *)ss)->sin6_addr;
+			b = (uint8_t *)&((struct sockaddr_in6 *)&ap->ap_sa)->sin6_addr;
+		}
+		for (i = 0; i < ap->ap_mask / 8; i++) {
+			if (a[i] != b[i])
+				goto next;
+		}
+		if (ap->ap_mask % 8) {
+			bmask = 0xff << (8 - (ap->ap_mask % 8));
+			if ((a[i] & bmask) != (b[i] & bmask))
+				goto next;
+		}
+		return (ap);
+next:
+		;
 	}
 
 	return (NULL);
@@ -950,7 +1014,8 @@ lun_option_set(struct lun_option *lo, co
 }
 
 static struct connection *
-connection_new(struct portal *portal, int fd, const char *host)
+connection_new(struct portal *portal, int fd, const char *host,
+    const struct sockaddr *client_sa)
 {
 	struct connection *conn;
 
@@ -960,6 +1025,7 @@ connection_new(struct portal *portal, in
 	conn->conn_portal = portal;
 	conn->conn_socket = fd;
 	conn->conn_initiator_addr = checked_strdup(host);
+	memcpy(&conn->conn_initiator_sa, client_sa, client_sa->sa_len);
 
 	/*
 	 * Default values, from RFC 3720, section 12.
@@ -1586,7 +1652,7 @@ wait_for_children(bool block)
 
 static void
 handle_connection(struct portal *portal, int fd,
-    const struct sockaddr *client_sa, socklen_t client_salen, bool dont_fork)
+    const struct sockaddr *client_sa, bool dont_fork)
 {
 	struct connection *conn;
 	int error;
@@ -1621,7 +1687,7 @@ handle_connection(struct portal *portal,
 	}
 	pidfile_close(conf->conf_pidfh);
 
-	error = getnameinfo(client_sa, client_salen,
+	error = getnameinfo(client_sa, client_sa->sa_len,
 	    host, sizeof(host), NULL, 0, NI_NUMERICHOST);
 	if (error != 0)
 		log_errx(1, "getnameinfo: %s", gai_strerror(error));
@@ -1631,7 +1697,7 @@ handle_connection(struct portal *portal,
 	log_set_peer_addr(host);
 	setproctitle("%s", host);
 
-	conn = connection_new(portal, fd, host);
+	conn = connection_new(portal, fd, host, client_sa);
 	set_timeout(conf);
 	kernel_capsicate();
 	login(conn);
@@ -1687,6 +1753,9 @@ main_loop(struct conf *conf, bool dont_f
 			client_salen = sizeof(client_sa);
 			kernel_accept(&connection_id, &portal_id,
 			    (struct sockaddr *)&client_sa, &client_salen);
+			if (client_salen < client_sa.ss_len)
+				log_errx(1, "salen %u < %u",
+				    client_salen, client_sa.ss_len);
 
 			log_debugx("incoming connection, id %d, portal id %d",
 			    connection_id, portal_id);
@@ -1703,8 +1772,7 @@ main_loop(struct conf *conf, bool dont_f
 
 found:
 			handle_connection(portal, connection_id,
-			    (struct sockaddr *)&client_sa, client_salen,
-			    dont_fork);
+			    (struct sockaddr *)&client_sa, dont_fork);
 		} else {
 #endif
 			assert(proxy_mode == false);
@@ -1731,9 +1799,13 @@ found:
 					    &client_salen);
 					if (client_fd < 0)
 						log_err(1, "accept");
+					if (client_salen < client_sa.ss_len)
+						log_errx(1, "salen %u < %u",
+						    client_salen,
+						    client_sa.ss_len);
 					handle_connection(portal, client_fd,
 					    (struct sockaddr *)&client_sa,
-					    client_salen, dont_fork);
+					    dont_fork);
 					break;
 				}
 			}

Modified: head/usr.sbin/ctld/ctld.h
==============================================================================
--- head/usr.sbin/ctld/ctld.h	Mon Jul 28 10:17:41 2014	(r269182)
+++ head/usr.sbin/ctld/ctld.h	Mon Jul 28 12:47:09 2014	(r269183)
@@ -35,8 +35,8 @@
 #include <sys/queue.h>
 #ifdef ICL_KERNEL_PROXY
 #include <sys/types.h>
-#include <sys/socket.h>
 #endif
+#include <sys/socket.h>
 #include <stdbool.h>
 #include <libutil.h>
 
@@ -67,6 +67,8 @@ struct auth_portal {
 	TAILQ_ENTRY(auth_portal)	ap_next;
 	struct auth_group		*ap_auth_group;
 	char				*ap_initator_portal;
+	struct sockaddr_storage		ap_sa;
+	int				ap_mask;
 };
 
 #define	AG_TYPE_UNKNOWN			0
@@ -179,6 +181,7 @@ struct connection {
 	char			*conn_initiator_addr;
 	char			*conn_initiator_alias;
 	uint8_t			conn_initiator_isid[6];
+	struct sockaddr_storage	conn_initiator_sa;
 	uint32_t		conn_cmdsn;
 	uint32_t		conn_statsn;
 	size_t			conn_max_data_segment_length;
@@ -235,7 +238,7 @@ const struct auth_portal	*auth_portal_ne
 				    const char *initiator_portal);
 bool			auth_portal_defined(const struct auth_group *ag);
 const struct auth_portal	*auth_portal_find(const struct auth_group *ag,
-				    const char *initiator_portal);
+				    const struct sockaddr_storage *sa);
 
 struct portal_group	*portal_group_new(struct conf *conf, const char *name);
 void			portal_group_delete(struct portal_group *pg);

Modified: head/usr.sbin/ctld/login.c
==============================================================================
--- head/usr.sbin/ctld/login.c	Mon Jul 28 10:17:41 2014	(r269182)
+++ head/usr.sbin/ctld/login.c	Mon Jul 28 12:47:09 2014	(r269183)
@@ -954,7 +954,7 @@ login(struct connection *conn)
 	}
 
 	if (auth_portal_defined(ag)) {
-		if (auth_portal_find(ag, conn->conn_initiator_addr) == NULL) {
+		if (auth_portal_find(ag, &conn->conn_initiator_sa) == NULL) {
 			login_send_error(request, 0x02, 0x02);
 			log_errx(1, "initiator does not match allowed "
 			    "initiator portals");



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201407281247.s6SCl9kF034529>