From owner-svn-src-head@FreeBSD.ORG Mon Jul 28 12:47:10 2014 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id C1B6A44B; Mon, 28 Jul 2014 12:47:10 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id A2A0E24AF; Mon, 28 Jul 2014 12:47:10 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s6SClANK034533; Mon, 28 Jul 2014 12:47:10 GMT (envelope-from mav@svn.freebsd.org) Received: (from mav@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s6SCl9kF034529; Mon, 28 Jul 2014 12:47:09 GMT (envelope-from mav@svn.freebsd.org) Message-Id: <201407281247.s6SCl9kF034529@svn.freebsd.org> From: Alexander Motin Date: Mon, 28 Jul 2014 12:47:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r269183 - head/usr.sbin/ctld X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 28 Jul 2014 12:47:10 -0000 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 #include #include +#include #include #include #include @@ -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 #ifdef ICL_KERNEL_PROXY #include -#include #endif +#include #include #include @@ -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");