Make allow/deny syntax consistent with that of add/delete
authorGerrit Renker <gerrit.renker@googlemail.com>
Tue, 30 Jun 2009 08:17:16 +0000 (10:17 +0200)
committerAndre Noll <maan@systemlinux.org>
Tue, 30 Jun 2009 08:17:16 +0000 (10:17 +0200)
After the changes for the add/delete commands, this patch updates
allow/deny to use the same syntax and (almost) the same code.

acl.c
command.c
net.c
net.h
send_common.c

diff --git a/acl.c b/acl.c
index 14edcf7..9bc83c2 100644 (file)
--- a/acl.c
+++ b/acl.c
@@ -136,30 +136,16 @@ char *acl_get_contents(struct list_head *acl)
  */
 void acl_init(struct list_head *acl, char * const *acl_info, int num)
 {
-       int i;
+       char    addr[16];
+       int     mask, i;
 
        INIT_LIST_HEAD(acl);
-       for (i = 0; i < num; i++) {
-               char *arg = para_strdup(acl_info[i]);
-               char *p = strchr(arg, '/');
-               int netmask;
-
-               if (!p)
-                       goto err;
-               *p = '\0';
-               if (!is_valid_ipv4_address(arg))
-                       goto err;
-               netmask = atoi(++p);
-               if (netmask < 0 || netmask > 32)
-                       goto err;
-               acl_add_entry(acl, arg, netmask);
-               goto success;
-err:
-               PARA_CRIT_LOG("syntax error: %s\n", acl_info[i]);
-success:
-               free(arg);
-               continue;
-       }
+       for (i = 0; i < num; i++)
+               if (parse_cidr(acl_info[i], addr, sizeof(addr), &mask) == NULL)
+                       PARA_CRIT_LOG("ACL syntax error: %s, ignoring\n",
+                                     acl_info[i]);
+               else
+                       acl_add_entry(acl, addr, mask);
 }
 
 /**
index 1ca54da..e3b15a5 100644 (file)
--- a/command.c
+++ b/command.c
@@ -185,17 +185,9 @@ static int check_sender_args(int argc, char * const * argv, struct sender_comman
                break;
        case SENDER_DENY:
        case SENDER_ALLOW:
-               if (argc != 4 && argc != 5)
+               if (argc != 4 || parse_cidr(argv[3], scd->host,
+                               sizeof(scd->host), &scd->netmask) == NULL)
                        return -E_COMMAND_SYNTAX;
-               if (!is_valid_ipv4_address(argv[3]))
-                       return -E_COMMAND_SYNTAX;
-               scd->netmask = 32;
-               if (argc == 5) {
-                       scd->netmask = atoi(argv[4]);
-                       if (scd->netmask < 0 || scd->netmask > 32)
-                               return -E_COMMAND_SYNTAX;
-               }
-               strncpy(scd->host, argv[3], sizeof(scd->host));
                break;
        case SENDER_ADD:
        case SENDER_DELETE:
diff --git a/net.c b/net.c
index 7207e52..ab6a989 100644 (file)
--- a/net.c
+++ b/net.c
@@ -92,6 +92,47 @@ void disable_crypt(int fd)
        crypt_data_array[fd].private_data = NULL;
 }
 
+/**
+ * Parse and validate IPv4 address/netmask string.
+ *
+ * \param cidr   Address in CIDR notation
+ * \param addr   Copy of the IPv4 address part of \a cidr
+ * \param addrlen Size of \a addr in bytes
+ * \param netmask Value of the netmask part in \a cidr or the
+ *               default of 32 if not specified.
+ *
+ * \return Pointer to \a addr if succesful, NULL on error.
+ * \sa RFC 4632
+ */
+char *parse_cidr(const char *cidr,
+                char    *addr, ssize_t addrlen,
+                int32_t *netmask)
+{
+       const char *o = cidr;
+       char *c = addr, *end = c + (addrlen - 1);
+
+       *netmask = 0x20;
+
+       if (cidr == NULL || addrlen < 1)
+               goto failed;
+
+       for (o = cidr; (*c = *o == '/'? '\0' : *o); c++, o++)
+               if (c == end)
+                       goto failed;
+
+       if (*o == '/')
+               if (para_atoi32(++o, netmask) < 0 ||
+                   *netmask < 0 || *netmask > 0x20)
+                       goto failed;
+
+       if (is_valid_ipv4_address(addr))
+               return addr;
+failed:
+       *addr = '\0';
+       return NULL;
+}
+
+
 /**
  * Match string as a candidate IPv4 address.
  *
diff --git a/net.h b/net.h
index 11b1708..8b70617 100644 (file)
--- a/net.h
+++ b/net.h
@@ -29,6 +29,8 @@
 /**
  * Functions to parse and validate (parts of) URLs.
  */
+extern char *parse_cidr(const char *cidr,
+                       char *addr, ssize_t addrlen, int32_t *netmask);
 extern char *parse_url(const char *url,
                       char *host, ssize_t hostlen, int32_t *port);
 /**
index b816007..200e59a 100644 (file)
@@ -389,8 +389,9 @@ char *generic_sender_help(void)
 {
        return make_message(
                "usage: {on|off}\n"
-               "usage: {allow|deny} IP mask\n"
-               "example: allow 127.0.0.1 32\n"
+               "usage: {allow|deny} IP[/netmask]\n"
+               "       where mask defaults to 32\n"
+               "example: allow 192.168.0.1/24\n"
        );
 }