libks_la_SOURCES += src/dht/ks_dht_bucket.c
libks_la_SOURCES += crypt/aeskey.c crypt/aestab.c crypt/sha2.c crypt/twofish.c crypt/aes_modes.c crypt/aescrypt.c crypt/twofish_cfb.c
#aes.h aescpp.h brg_endian.h aesopt.h aestab.h brg_types.h sha2.h twofish.h
+libks_la_SOURCES += src/ks_acl.c
libks_la_CFLAGS = $(AM_CFLAGS)
libks_la_CPPFLAGS = -DPOSIX
library_include_HEADERS += src/include/ks_dso.h src/include/ks_platform.h src/include/ks_types.h # src/include/ks_rng.h src/include/ks_dht.h
library_include_HEADERS += src/include/ks_printf.h src/include/ks_hash.h src/include/ks_ssl.h src/include/kws.h
library_include_HEADERS += src/utp/utp_internal.h src/utp/utp.h src/utp/utp_types.h src/utp/utp_callbacks.h src/utp/utp_templates.h
-library_include_HEADERS += src/utp/utp_hash.h src/utp/utp_packedsockaddr.h src/utp/utp_utils.h src/include/ks_utp.h
+library_include_HEADERS += src/utp/utp_hash.h src/utp/utp_packedsockaddr.h src/utp/utp_utils.h src/include/ks_utp.h src/include/ks_acl.h
tests: libks.la
$(MAKE) -C test tests
KS_DECLARE(int) ks_tolower(int c);
KS_DECLARE(char *) ks_copy_string(char *from_str, const char *to_str, ks_size_t from_str_len);
KS_DECLARE(int) ks_snprintf(char *buffer, size_t count, const char *fmt, ...);
-KS_DECLARE(unsigned int) ks_separate_string(char *buf, const char *delim, char **array, unsigned int arraylen);
+KS_DECLARE(unsigned int) ks_separate_string_string(char *buf, const char *delim, char **array, unsigned int arraylen);
+KS_DECLARE(unsigned int) ks_separate_string(char *buf, char delim, char **array, unsigned int arraylen);
+
+#define ks_inet_pton inet_pton
+
KS_DECLARE(int) ks_cpu_count(void);
static __inline__ int ks_safe_strcasecmp(const char *s1, const char *s2) {
if (!(s1 && s2)) {
KS_DECLARE(void) ks_random_string(char *buf, uint16_t len, char *set);
+#define ks_str_nil(s) (s ? s : "")
+
#include "ks_pool.h"
#include "ks_printf.h"
#include "ks_json.h"
#include "kws.h"
#include "ks_bencode.h"
#include "ks_rng.h"
+#include "ks_acl.h"
KS_END_EXTERN_C
--- /dev/null
+/*
+ * Copyright (c) 2007-2014, Anthony Minessale II
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * 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.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER
+ * 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.
+ */
+
+
+#ifndef _KS_ACL_H_
+#define _KS_ACL_H_
+
+KS_BEGIN_EXTERN_C
+
+typedef union{
+ uint32_t v4;
+ struct in6_addr v6;
+} ks_ip_t;
+
+
+#define switch_network_list_validate_ip(_list, _ip) switch_network_list_validate_ip_token(_list, _ip, NULL);
+
+#define switch_test_subnet(_ip, _net, _mask) (_mask ? ((_net & _mask) == (_ip & _mask)) : _net ? _net == _ip : 1)
+
+
+KS_DECLARE(int) ks_parse_cidr(const char *string, ks_ip_t *ip, ks_ip_t *mask, uint32_t *bitp);
+KS_DECLARE(ks_status_t) ks_network_list_create(ks_network_list_t **list, const char *name, ks_bool_t default_type,
+ ks_pool_t *pool);
+KS_DECLARE(ks_status_t) ks_network_list_add_cidr_token(ks_network_list_t *list, const char *cidr_str, ks_bool_t ok, const char *token);
+#define ks_network_list_add_cidr(_list, _cidr_str, _ok) ks_network_list_add_cidr_token(_list, _cidr_str, _ok, NULL)
+
+KS_DECLARE(char *) ks_network_ipv4_mapped_ipv6_addr(const char* ip_str);
+KS_DECLARE(ks_status_t) ks_network_list_add_host_mask(ks_network_list_t *list, const char *host, const char *mask_str, ks_bool_t ok);
+KS_DECLARE(ks_bool_t) ks_network_list_validate_ip_token(ks_network_list_t *list, uint32_t ip, const char **token);
+KS_DECLARE(ks_bool_t) ks_network_list_validate_ip6_token(ks_network_list_t *list, ks_ip_t ip, const char **token);
+
+#define ks_network_list_validate_ip(_list, _ip) ks_network_list_validate_ip_token(_list, _ip, NULL);
+
+#define ks_test_subnet(_ip, _net, _mask) (_mask ? ((_net & _mask) == (_ip & _mask)) : _net ? _net == _ip : 1)
+
+KS_DECLARE(ks_bool_t) ks_check_network_list_ip_cidr(const char *ip_str, const char *cidr_str);
+KS_DECLARE(ks_bool_t) ks_check_network_list_ip_token(const char *ip_str, ks_network_list_t *list, const char **token);
+#define ks_check_network_list_ip(_i, _l) ks_check_network_list_ip_token(_i, _l, NULL)
+
+KS_END_EXTERN_C
+#endif /* defined(_KS_ACL_H_) */
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
+
KS_DECLARE(char *) ks_pstrmemdup(ks_pool_t *pool, const char *str, size_t len);
KS_DECLARE(void *) ks_pmemdup(ks_pool_t *pool, const void *buf, size_t len);
KS_DECLARE(char *) ks_pstrcat(ks_pool_t *pool, ...);
+KS_DECLARE(char *) ks_psprintf(ks_pool_t *pool, const char *fmt, ...);
KS_END_EXTERN_C
typedef struct ks_thread_pool_s ks_thread_pool_t;
+struct ks_network_list;
+typedef struct ks_network_list ks_network_list_t;
+
+
KS_END_EXTERN_C
#endif /* defined(_KS_TYPES_H_) */
--- /dev/null
+/*
+ * Copyright (c) 2007-2014, Anthony Minessale II
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * 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.
+ *
+ * * Neither the name of the original author; nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER
+ * 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 <ks.h>
+
+
+struct ks_network_node {
+ ks_ip_t ip;
+ ks_ip_t mask;
+ uint32_t bits;
+ int family;
+ ks_bool_t ok;
+ char *token;
+ char *str;
+ struct ks_network_node *next;
+};
+typedef struct ks_network_node ks_network_node_t;
+
+struct ks_network_list {
+ struct ks_network_node *node_head;
+ ks_bool_t default_type;
+ ks_pool_t *pool;
+ char *name;
+};
+
+
+KS_DECLARE(ks_status_t) ks_network_list_create(ks_network_list_t **list, const char *name, ks_bool_t default_type,
+ ks_pool_t *pool)
+{
+ ks_network_list_t *new_list;
+
+ if (!pool) {
+ ks_pool_open(&pool);
+ }
+
+ new_list = ks_pool_alloc(pool, sizeof(**list));
+ new_list->pool = pool;
+ new_list->default_type = default_type;
+ new_list->name = ks_pstrdup(new_list->pool, name);
+
+ *list = new_list;
+
+ return KS_STATUS_SUCCESS;
+}
+
+#define IN6_AND_MASK(result, ip, mask) \
+ ((uint32_t *) (result))[0] =((const uint32_t *) (ip))[0] & ((const uint32_t *)(mask))[0]; \
+ ((uint32_t *) (result))[1] =((const uint32_t *) (ip))[1] & ((const uint32_t *)(mask))[1]; \
+ ((uint32_t *) (result))[2] =((const uint32_t *) (ip))[2] & ((const uint32_t *)(mask))[2]; \
+ ((uint32_t *) (result))[3] =((const uint32_t *) (ip))[3] & ((const uint32_t *)(mask))[3];
+KS_DECLARE(ks_bool_t) ks_testv6_subnet(ks_ip_t _ip, ks_ip_t _net, ks_ip_t _mask) {
+ if (!IN6_IS_ADDR_UNSPECIFIED(&_mask.v6)) {
+ struct in6_addr a, b;
+ IN6_AND_MASK(&a, &_net, &_mask);
+ IN6_AND_MASK(&b, &_ip, &_mask);
+ return !memcmp(&a,&b, sizeof(struct in6_addr));
+ } else {
+ if (!IN6_IS_ADDR_UNSPECIFIED(&_net.v6)) {
+ return !memcmp(&_net,&_ip,sizeof(struct in6_addr));
+ }
+ else return KS_TRUE;
+ }
+}
+KS_DECLARE(ks_bool_t) ks_network_list_validate_ip6_token(ks_network_list_t *list, ks_ip_t ip, const char **token)
+{
+ ks_network_node_t *node;
+ ks_bool_t ok = list->default_type;
+ uint32_t bits = 0;
+
+ for (node = list->node_head; node; node = node->next) {
+ if (node->family == AF_INET) continue;
+
+ if (node->bits >= bits && ks_testv6_subnet(ip, node->ip, node->mask)) {
+ if (node->ok) {
+ ok = KS_TRUE;
+ } else {
+ ok = KS_FALSE;
+ }
+
+ bits = node->bits;
+
+ if (token) {
+ *token = node->token;
+ }
+ }
+ }
+
+ return ok;
+}
+
+KS_DECLARE(ks_bool_t) ks_network_list_validate_ip_token(ks_network_list_t *list, uint32_t ip, const char **token)
+{
+ ks_network_node_t *node;
+ ks_bool_t ok = list->default_type;
+ uint32_t bits = 0;
+
+ for (node = list->node_head; node; node = node->next) {
+ if (node->family == AF_INET6) continue; /* want AF_INET */
+ if (node->bits >= bits && ks_test_subnet(ip, node->ip.v4, node->mask.v4)) {
+ if (node->ok) {
+ ok = KS_TRUE;
+ } else {
+ ok = KS_FALSE;
+ }
+
+ bits = node->bits;
+
+ if (token) {
+ *token = node->token;
+ }
+ }
+ }
+
+ return ok;
+}
+
+KS_DECLARE(char *) ks_network_ipv4_mapped_ipv6_addr(const char* ip_str)
+{
+ /* ipv4 mapped ipv6 address */
+
+ if (strncasecmp(ip_str, "::ffff:", 7)) {
+ return NULL;
+ }
+
+ return strdup(ip_str + 7);
+}
+
+
+KS_DECLARE(int) ks_parse_cidr(const char *string, ks_ip_t *ip, ks_ip_t *mask, uint32_t *bitp)
+{
+ char host[128];
+ char *bit_str;
+ int32_t bits;
+ const char *ipv6;
+ ks_ip_t *maskv = mask;
+ ks_ip_t *ipv = ip;
+
+ ks_copy_string(host, string, sizeof(host)-1);
+ bit_str = strchr(host, '/');
+
+ if (!bit_str) {
+ return -1;
+ }
+
+ *bit_str++ = '\0';
+ bits = atoi(bit_str);
+ ipv6 = strchr(string, ':');
+ if (ipv6) {
+ int i,n;
+ if (bits < 0 || bits > 128) {
+ return -2;
+ }
+ bits = atoi(bit_str);
+ ks_inet_pton(AF_INET6, host, (unsigned char *)ip);
+ for (n=bits,i=0 ;i < 16; i++){
+ if (n >= 8) {
+ maskv->v6.s6_addr[i] = 0xFF;
+ n -= 8;
+ } else if (n < 8) {
+ maskv->v6.s6_addr[i] = 0xFF & ~(0xFF >> n);
+ n -= n;
+ } else if (n == 0) {
+ maskv->v6.s6_addr[i] = 0x00;
+ }
+ }
+ } else {
+ if (bits < 0 || bits > 32) {
+ return -2;
+ }
+
+ bits = atoi(bit_str);
+ ks_inet_pton(AF_INET, host, (unsigned char *)ip);
+ ipv->v4 = htonl(ipv->v4);
+
+ maskv->v4 = 0xFFFFFFFF & ~(0xFFFFFFFF >> bits);
+ }
+ *bitp = bits;
+
+ return 0;
+}
+
+
+
+
+KS_DECLARE(ks_status_t) ks_network_list_perform_add_cidr_token(ks_network_list_t *list, const char *cidr_str, ks_bool_t ok,
+ const char *token)
+{
+ ks_ip_t ip, mask;
+ uint32_t bits;
+ ks_network_node_t *node;
+ char *ipv4 = NULL;
+
+ if ((ipv4 = ks_network_ipv4_mapped_ipv6_addr(cidr_str))) {
+ cidr_str = ipv4;
+ }
+
+ if (ks_parse_cidr(cidr_str, &ip, &mask, &bits)) {
+ ks_log(KS_LOG_ERROR, "Error Adding %s (%s) [%s] to list %s\n",
+ cidr_str, ok ? "allow" : "deny", ks_str_nil(token), list->name);
+ ks_safe_free(ipv4);
+ return KS_STATUS_GENERR;
+ }
+
+ node = ks_pool_alloc(list->pool, sizeof(*node));
+
+ node->ip = ip;
+ node->mask = mask;
+ node->ok = ok;
+ node->bits = bits;
+ node->str = ks_pstrdup(list->pool, cidr_str);
+
+ if (strchr(cidr_str,':')) {
+ node->family = AF_INET6;
+ } else {
+ node->family = AF_INET;
+ }
+
+ if (!zstr(token)) {
+ node->token = ks_pstrdup(list->pool, token);
+ }
+
+ node->next = list->node_head;
+ list->node_head = node;
+
+ ks_log(KS_LOG_NOTICE, "Adding %s (%s) [%s] to list %s\n",
+ cidr_str, ok ? "allow" : "deny", ks_str_nil(token), list->name);
+
+ ks_safe_free(ipv4);
+ return KS_STATUS_SUCCESS;
+}
+
+KS_DECLARE(ks_status_t) ks_network_list_add_cidr_token(ks_network_list_t *list, const char *cidr_str, ks_bool_t ok, const char *token)
+{
+ char *cidr_str_dup = NULL;
+ ks_status_t status = KS_STATUS_SUCCESS;
+
+ if (strchr(cidr_str, ',')) {
+ char *argv[32] = { 0 };
+ int i, argc;
+ cidr_str_dup = strdup(cidr_str);
+
+ ks_assert(cidr_str_dup);
+ if ((argc = ks_separate_string(cidr_str_dup, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) {
+ for (i = 0; i < argc; i++) {
+ ks_status_t this_status;
+ if ((this_status = ks_network_list_perform_add_cidr_token(list, argv[i], ok, token)) != KS_STATUS_SUCCESS) {
+ status = this_status;
+ }
+ }
+ }
+ } else {
+ status = ks_network_list_perform_add_cidr_token(list, cidr_str, ok, token);
+ }
+
+ ks_safe_free(cidr_str_dup);
+ return status;
+}
+
+KS_DECLARE(ks_status_t) ks_network_list_add_host_mask(ks_network_list_t *list, const char *host, const char *mask_str, ks_bool_t ok)
+{
+ ks_ip_t ip, mask;
+ ks_network_node_t *node;
+
+ ks_inet_pton(AF_INET, host, &ip);
+ ks_inet_pton(AF_INET, mask_str, &mask);
+
+ node = ks_pool_alloc(list->pool, sizeof(*node));
+
+ node->ip.v4 = ntohl(ip.v4);
+ node->mask.v4 = ntohl(mask.v4);
+ node->ok = ok;
+
+ /* http://graphics.stanford.edu/~seander/bithacks.html */
+ mask.v4 = mask.v4 - ((mask.v4 >> 1) & 0x55555555);
+ mask.v4 = (mask.v4 & 0x33333333) + ((mask.v4 >> 2) & 0x33333333);
+ node->bits = (((mask.v4 + (mask.v4 >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24;
+
+ node->str = ks_psprintf(list->pool, "%s:%s", host, mask_str);
+
+ node->next = list->node_head;
+ list->node_head = node;
+
+ return KS_STATUS_SUCCESS;
+}
+
+KS_DECLARE(ks_bool_t) ks_check_network_list_ip_cidr(const char *ip_str, const char *cidr_str)
+{
+ ks_ip_t ip, mask, net;
+ uint32_t bits;
+ char *ipv6 = strchr(ip_str,':');
+ ks_bool_t ok = KS_FALSE;
+ char *ipv4 = NULL;
+
+ if ((ipv4 = ks_network_ipv4_mapped_ipv6_addr(ip_str))) {
+ ip_str = ipv4;
+ ipv6 = NULL;
+ }
+
+ if (ipv6) {
+ ks_inet_pton(AF_INET6, ip_str, &ip);
+ } else {
+ ks_inet_pton(AF_INET, ip_str, &ip);
+ ip.v4 = htonl(ip.v4);
+ }
+
+ ks_parse_cidr(cidr_str, &net, &mask, &bits);
+
+ if (ipv6) {
+ ok = ks_testv6_subnet(ip, net, mask);
+ } else {
+ ok = ks_test_subnet(ip.v4, net.v4, mask.v4);
+ }
+
+ ks_safe_free(ipv4);
+
+ return ok;
+}
+
+KS_DECLARE(ks_bool_t) ks_check_network_list_ip_token(const char *ip_str, ks_network_list_t *list, const char **token)
+{
+ ks_ip_t ip;
+ char *ipv6 = strchr(ip_str,':');
+ ks_bool_t ok = KS_FALSE;
+ char *ipv4 = NULL;
+
+ if ((ipv4 = ks_network_ipv4_mapped_ipv6_addr(ip_str))) {
+ ip_str = ipv4;
+ ipv6 = NULL;
+ }
+
+ if (ipv6) {
+ ks_inet_pton(AF_INET6, ip_str, &ip);
+ } else {
+ ks_inet_pton(AF_INET, ip_str, &ip);
+ ip.v4 = htonl(ip.v4);
+ }
+
+
+ if (ipv6) {
+ ok = ks_network_list_validate_ip6_token(list, ip, token);
+ } else {
+ ok = ks_network_list_validate_ip_token(list, ip.v4, token);
+ }
+
+ ks_safe_free(ipv4);
+
+ return ok;
+}
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
+ */
return result;
}
+KS_DECLARE(char *) ks_psprintf(ks_pool_t *pool, const char *fmt, ...)
+{
+ va_list ap;
+ char *result;
+ va_start(ap, fmt);
+ result = ks_vpprintf(pool, fmt, ap);
+ va_end(ap);
+
+ return result;
+}
+
+
+
/* For Emacs:
* Local Variables:
* mode:c
#include <ks.h>
+#define ESCAPE_META '\\'
+
/* Written by Marc Espie, public domain */
#define KS_CTYPE_NUM_CHARS 256
}
-KS_DECLARE(unsigned int) ks_separate_string(char *buf, const char *delim, char **array, unsigned int arraylen)
+/* Helper function used when separating strings to unescape a character. The
+ supported characters are:
+
+ \n linefeed
+ \r carriage return
+ \t tab
+ \s space
+
+ Any other character is returned as it was received. */
+static char unescape_char(char escaped)
+{
+ char unescaped;
+
+ switch (escaped) {
+ case 'n':
+ unescaped = '\n';
+ break;
+ case 'r':
+ unescaped = '\r';
+ break;
+ case 't':
+ unescaped = '\t';
+ break;
+ case 's':
+ unescaped = ' ';
+ break;
+ default:
+ unescaped = escaped;
+ }
+ return unescaped;
+}
+
+
+/* Helper function used when separating strings to remove quotes, leading /
+ trailing spaces, and to convert escaped characters. */
+static char *cleanup_separated_string(char *str, char delim)
+{
+ char *ptr;
+ char *dest;
+ char *start;
+ char *end = NULL;
+ int inside_quotes = 0;
+
+ /* Skip initial whitespace */
+ for (ptr = str; *ptr == ' '; ++ptr) {
+ }
+
+ for (start = dest = ptr; *ptr; ++ptr) {
+ char e;
+ int esc = 0;
+
+ if (*ptr == ESCAPE_META) {
+ e = *(ptr + 1);
+ if (e == '\'' || e == '"' || (delim && e == delim) || e == ESCAPE_META || (e = unescape_char(*(ptr + 1))) != *(ptr + 1)) {
+ ++ptr;
+ *dest++ = e;
+ end = dest;
+ esc++;
+ }
+ }
+ if (!esc) {
+ if (*ptr == '\'' && (inside_quotes || ((ptr+1) && strchr(ptr+1, '\'')))) {
+ if ((inside_quotes = (1 - inside_quotes))) {
+ end = dest;
+ }
+ } else {
+ *dest++ = *ptr;
+ if (*ptr != ' ' || inside_quotes) {
+ end = dest;
+ }
+ }
+ }
+ }
+ if (end) {
+ *end = '\0';
+ }
+
+ return start;
+}
+
+KS_DECLARE(unsigned int) ks_separate_string_string(char *buf, const char *delim, char **array, unsigned int arraylen)
{
unsigned int count = 0;
char *d;
return p;
}
+
+
+/* Separate a string using a delimiter that is not a space */
+static unsigned int separate_string_char_delim(char *buf, char delim, char **array, unsigned int arraylen)
+{
+ enum tokenizer_state {
+ START,
+ FIND_DELIM
+ } state = START;
+
+ unsigned int count = 0;
+ char *ptr = buf;
+ int inside_quotes = 0;
+ unsigned int i;
+
+ while (*ptr && count < arraylen) {
+ switch (state) {
+ case START:
+ array[count++] = ptr;
+ state = FIND_DELIM;
+ break;
+
+ case FIND_DELIM:
+ /* escaped characters are copied verbatim to the destination string */
+ if (*ptr == ESCAPE_META) {
+ ++ptr;
+ } else if (*ptr == '\'' && (inside_quotes || ((ptr+1) && strchr(ptr+1, '\'')))) {
+ inside_quotes = (1 - inside_quotes);
+ } else if (*ptr == delim && !inside_quotes) {
+ *ptr = '\0';
+ state = START;
+ }
+ ++ptr;
+ break;
+ }
+ }
+ /* strip quotes, escaped chars and leading / trailing spaces */
+
+ for (i = 0; i < count; ++i) {
+ array[i] = cleanup_separated_string(array[i], delim);
+ }
+
+ return count;
+}
+
+/* Separate a string using a delimiter that is a space */
+static unsigned int separate_string_blank_delim(char *buf, char **array, unsigned int arraylen)
+{
+ enum tokenizer_state {
+ START,
+ SKIP_INITIAL_SPACE,
+ FIND_DELIM,
+ SKIP_ENDING_SPACE
+ } state = START;
+
+ unsigned int count = 0;
+ char *ptr = buf;
+ int inside_quotes = 0;
+ unsigned int i;
+
+ while (*ptr && count < arraylen) {
+ switch (state) {
+ case START:
+ array[count++] = ptr;
+ state = SKIP_INITIAL_SPACE;
+ break;
+
+ case SKIP_INITIAL_SPACE:
+ if (*ptr == ' ') {
+ ++ptr;
+ } else {
+ state = FIND_DELIM;
+ }
+ break;
+
+ case FIND_DELIM:
+ if (*ptr == ESCAPE_META) {
+ ++ptr;
+ } else if (*ptr == '\'') {
+ inside_quotes = (1 - inside_quotes);
+ } else if (*ptr == ' ' && !inside_quotes) {
+ *ptr = '\0';
+ state = SKIP_ENDING_SPACE;
+ }
+ ++ptr;
+ break;
+
+ case SKIP_ENDING_SPACE:
+ if (*ptr == ' ') {
+ ++ptr;
+ } else {
+ state = START;
+ }
+ break;
+ }
+ }
+ /* strip quotes, escaped chars and leading / trailing spaces */
+
+ for (i = 0; i < count; ++i) {
+ array[i] = cleanup_separated_string(array[i], 0);
+ }
+
+ return count;
+}
+
+KS_DECLARE(unsigned int) ks_separate_string(char *buf, char delim, char **array, unsigned int arraylen)
+{
+ if (!buf || !array || !arraylen) {
+ return 0;
+ }
+
+
+ if (*buf == '^' && *(buf+1) == '^') {
+ char *p = buf + 2;
+
+ if (p && *p && *(p+1)) {
+ buf = p;
+ delim = *buf++;
+ }
+ }
+
+
+ memset(array, 0, arraylen * sizeof(*array));
+
+ return (delim == ' ' ? separate_string_blank_delim(buf, array, arraylen) : separate_string_char_delim(buf, delim, array, arraylen));
+}
testpools_CFLAGS = $(AM_CFLAGS)
testpools_LDADD = $(TEST_LDADD)
+check_PROGRAMS += testacl
+testacl_SOURCES = testacl.c tap.c
+testacl_CFLAGS = $(AM_CFLAGS)
+testacl_LDADD = $(TEST_LDADD)
+
check_PROGRAMS += test_thread_pools
test_thread_pools_SOURCES = test_thread_pools.c tap.c
test_thread_pools_CFLAGS = $(AM_CFLAGS)
--- /dev/null
+#include "ks.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "tap.h"
+
+int main(int argc, char **argv)
+{
+ ks_pool_t *pool;
+ ks_network_list_t *list = NULL;
+ ks_bool_t match;
+
+ ks_init();
+
+ plan(8);
+
+ ks_pool_open(&pool);
+
+ ks_network_list_create(&list, "test", KS_FALSE, pool);
+
+
+ ks_network_list_add_cidr(list, "10.0.0.0/8", KS_TRUE);
+ ks_network_list_add_cidr(list, "172.16.0.0/12", KS_TRUE);
+ ks_network_list_add_cidr(list, "192.168.0.0/16", KS_TRUE);
+ ks_network_list_add_cidr(list, "fe80::/10", KS_TRUE);
+
+
+ match = ks_check_network_list_ip("192.168.1.1", list);
+ ok(match);
+
+ match = ks_check_network_list_ip("208.34.128.7", list);
+ ok (!match);
+
+ match = ks_check_network_list_ip_cidr("192.168.1.1", "192.168.0.0/16");
+ ok(match);
+
+ match = ks_check_network_list_ip_cidr("208.34.128.7", "192.168.0.0/16");
+ ok (!match);
+
+
+ ks_pool_free(pool, &list);
+
+
+ ks_network_list_create(&list, "test", KS_TRUE, pool);
+
+ ks_network_list_add_cidr(list, "0.0.0.0/0", KS_FALSE);
+ ks_network_list_add_cidr(list, "fe80::/10", KS_FALSE);
+
+
+ match = ks_check_network_list_ip("2637:f368:1281::10", list);
+ ok(match);
+
+ match = ks_check_network_list_ip("fe80::18b7:53b3:51d8:f5cf", list);
+ ok(!match);
+
+ match = ks_check_network_list_ip_cidr("fe80::18b7:53b3:51d8:f5cf", "fe80::/10");
+ ok(match);
+
+ match = ks_check_network_list_ip_cidr("2637:f368:1281::10", "fe80::/10");
+ ok(!match);
+
+ ks_pool_free(pool, &list);
+
+ ks_pool_close(&pool);
+
+ ks_shutdown();
+
+ done_testing();
+}