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");
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to