Add listen mask checks to angel
parent
c82ce879bb
commit
007e5e040c
|
@ -8,10 +8,37 @@ struct liPluginCoreConfig {
|
|||
/* Load */
|
||||
liInstanceConf *load_instconf;
|
||||
gboolean load_failed;
|
||||
GPtrArray *load_listen_masks;
|
||||
|
||||
/* Running */
|
||||
liInstanceConf *instconf;
|
||||
liInstance *inst;
|
||||
GPtrArray *listen_masks;
|
||||
};
|
||||
|
||||
typedef struct liPluginCoreListenMask liPluginCoreListenMask;
|
||||
struct liPluginCoreListenMask {
|
||||
enum {
|
||||
LI_PLUGIN_CORE_LISTEN_MASK_IPV4,
|
||||
LI_PLUGIN_CORE_LISTEN_MASK_IPV6,
|
||||
LI_PLUGIN_CORE_LISTEN_MASK_UNIX
|
||||
} type;
|
||||
|
||||
union {
|
||||
struct {
|
||||
guint32 addr;
|
||||
guint32 networkmask;
|
||||
guint16 port;
|
||||
} ipv4;
|
||||
struct {
|
||||
guint8 addr[16];
|
||||
guint network;
|
||||
guint16 port;
|
||||
} ipv6;
|
||||
struct {
|
||||
GString *path;
|
||||
} unix_socket;
|
||||
} value;
|
||||
};
|
||||
|
||||
gboolean plugin_core_init(liServer *srv);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <lighttpd/settings.h>
|
||||
|
||||
/** optional parameters are set to default values (netmask all bits, port 0) */
|
||||
/** parse an IPv4 (if netmask is not NULL with optional cidr netmask, if port is not NULL with optional port) */
|
||||
LI_API gboolean li_parse_ipv4(const char *str, guint32 *ip, guint32 *netmask, guint16 *port);
|
||||
/** parse an IPv6 (if network is not NULL with optional cidr network, if port is not NULL with optional port if the ip/cidr part is in [...]) */
|
||||
|
|
|
@ -64,6 +64,11 @@ LI_API liSocketAddress li_sockaddr_local_from_socket(gint fd);
|
|||
LI_API liSocketAddress li_sockaddr_remote_from_socket(gint fd);
|
||||
LI_API void li_sockaddr_clear(liSocketAddress *saddr);
|
||||
|
||||
LI_API gboolean ipv4_in_ipv4_net(guint32 target, guint32 match, guint32 networkmask);
|
||||
LI_API gboolean ipv6_in_ipv6_net(const unsigned char *target, const guint8 *match, guint network);
|
||||
LI_API gboolean ipv6_in_ipv4_net(const unsigned char *target, guint32 match, guint32 networkmask);
|
||||
LI_API gboolean ipv4_in_ipv6_net(guint32 target, const guint8 *match, guint network);
|
||||
|
||||
LI_API void li_gstring_replace_char_with_str_len(GString *gstr, gchar c, gchar *str, guint len);
|
||||
|
||||
LI_API gboolean li_strncase_equal(GString *str, const gchar *s, guint len);
|
||||
|
|
|
@ -165,18 +165,18 @@ gboolean plugins_config_load(liServer *srv, const gchar *filename) {
|
|||
}
|
||||
}
|
||||
|
||||
ERROR(srv, "%s", "activate");
|
||||
INFO(srv, "%s", "activate");
|
||||
|
||||
/* activate new config */
|
||||
for (i = ps->load_plugins->len; i-- > 0; ) {
|
||||
liPlugin *p = g_ptr_array_index(ps->load_plugins, i);
|
||||
ERROR(srv, "activate: %s", p->name);
|
||||
INFO(srv, "activate: %s", p->name);
|
||||
if (p->handle_activate_config) {
|
||||
p->handle_activate_config(srv, p);
|
||||
}
|
||||
}
|
||||
|
||||
ERROR(srv, "%s", "done");
|
||||
INFO(srv, "%s", "done");
|
||||
|
||||
{ /* swap the arrays */
|
||||
GPtrArray *tmp = ps->load_plugins; ps->load_plugins = ps->plugins; ps->plugins = tmp;
|
||||
|
@ -205,7 +205,7 @@ void plugins_handle_item(liServer *srv, GString *itemname, liValue *hash) {
|
|||
liPlugins *ps = &srv->plugins;
|
||||
server_item *si;
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
/* debug items */
|
||||
{
|
||||
GString *tmp = li_value_to_string(hash);
|
||||
|
|
|
@ -99,22 +99,115 @@ static const liPluginItemOption core_instance_options[] = {
|
|||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static void core_listen_mask_free(liPluginCoreListenMask *mask) {
|
||||
switch (mask->type) {
|
||||
case LI_PLUGIN_CORE_LISTEN_MASK_IPV4:
|
||||
case LI_PLUGIN_CORE_LISTEN_MASK_IPV6:
|
||||
break;
|
||||
case LI_PLUGIN_CORE_LISTEN_MASK_UNIX:
|
||||
g_string_free(mask->value.unix_socket.path, TRUE);
|
||||
break;
|
||||
}
|
||||
g_slice_free(liPluginCoreListenMask, mask);
|
||||
}
|
||||
|
||||
static void core_listen_parse(liServer *srv, liPlugin *p, liValue **options) {
|
||||
liPluginCoreConfig *config = (liPluginCoreConfig*) p->data;
|
||||
gboolean have_type = FALSE;
|
||||
|
||||
liPluginCoreListenMask *mask = g_slice_new0(liPluginCoreListenMask);
|
||||
|
||||
if (options[0]) { /* ip */
|
||||
if (have_type) goto only_one_type;
|
||||
have_type = TRUE;
|
||||
if (li_parse_ipv4(options[0]->data.string->str, &mask->value.ipv4.addr, &mask->value.ipv4.networkmask, &mask->value.ipv4.port)) {
|
||||
mask->type = LI_PLUGIN_CORE_LISTEN_MASK_IPV4;
|
||||
} else if (li_parse_ipv6(options[0]->data.string->str, mask->value.ipv6.addr, &mask->value.ipv6.network, &mask->value.ipv6.port)) {
|
||||
mask->type = LI_PLUGIN_CORE_LISTEN_MASK_IPV6;
|
||||
} else {
|
||||
ERROR(srv, "couldn't parse ip/network:port in listen mask '%s'", options[0]->data.string->str);
|
||||
config->load_failed = FALSE;
|
||||
g_slice_free(liPluginCoreListenMask, mask);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (options[1]) { /* unix */
|
||||
if (have_type) goto only_one_type;
|
||||
have_type = TRUE;
|
||||
mask->type = LI_PLUGIN_CORE_LISTEN_MASK_UNIX;
|
||||
mask->value.unix_socket.path = g_string_new_len(GSTR_LEN(options[2]->data.string));
|
||||
}
|
||||
|
||||
if (!have_type) {
|
||||
ERROR(srv, "%s", "no options found in listen mask");
|
||||
config->load_failed = FALSE;
|
||||
g_slice_free(liPluginCoreListenMask, mask);
|
||||
return;
|
||||
}
|
||||
|
||||
g_ptr_array_add(config->load_listen_masks, mask);
|
||||
return;
|
||||
|
||||
only_one_type:
|
||||
ERROR(srv, "%s", "you can only use one of 'ip' and 'unix' in listen masks");
|
||||
config->load_failed = FALSE;
|
||||
g_slice_free(liPluginCoreListenMask, mask);
|
||||
return;
|
||||
}
|
||||
|
||||
static const liPluginItemOption core_listen_options[] = {
|
||||
{ "ip", LI_VALUE_STRING, 0 },
|
||||
{ "unix", LI_VALUE_STRING, 0 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
|
||||
static const liPluginItem core_items[] = {
|
||||
{ "instance", core_instance_parse, core_instance_options },
|
||||
{ "listen", core_listen_parse, core_listen_options },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static int do_listen(liServer *srv, GString *str) {
|
||||
static int do_listen(liServer *srv, liPluginCoreConfig *config, GString *str) {
|
||||
guint32 ipv4;
|
||||
#ifdef HAVE_IPV6
|
||||
guint8 ipv6[16];
|
||||
#endif
|
||||
guint16 port = 80;
|
||||
guint16 port;
|
||||
guint i;
|
||||
liPluginCoreListenMask *mask;
|
||||
|
||||
if (li_parse_ipv4(str->str, &ipv4, NULL, &port)) {
|
||||
int s, v;
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
if (!port) port = 80;
|
||||
|
||||
if (config->listen_masks->len) {
|
||||
for (i = 0; i < config->listen_masks->len; i++) {
|
||||
mask = g_ptr_array_index(config->listen_masks, i);
|
||||
switch (mask->type) {
|
||||
case LI_PLUGIN_CORE_LISTEN_MASK_IPV4:
|
||||
if (!ipv4_in_ipv4_net(ipv4, mask->value.ipv4.addr, mask->value.ipv4.networkmask)) continue;
|
||||
if ((mask->value.ipv4.port != port) && (mask->value.ipv4.port != 0 || (port != 80 && port != 443))) continue;
|
||||
break;
|
||||
case LI_PLUGIN_CORE_LISTEN_MASK_IPV6:
|
||||
if (!ipv4_in_ipv6_net(ipv4, mask->value.ipv6.addr, mask->value.ipv6.network)) continue;
|
||||
if ((mask->value.ipv6.port != port) && (mask->value.ipv6.port != 0 || (port != 80 && port != 443))) continue;
|
||||
break;
|
||||
case LI_PLUGIN_CORE_LISTEN_MASK_UNIX:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (i == config->listen_masks->len) {
|
||||
ERROR(srv, "listen to socket '%s' not allowed", str->str);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = ipv4;
|
||||
addr.sin_port = htons(port);
|
||||
|
@ -146,6 +239,30 @@ static int do_listen(liServer *srv, GString *str) {
|
|||
int s, v;
|
||||
struct sockaddr_in6 addr;
|
||||
li_ipv6_tostring(ipv6_str, ipv6);
|
||||
if (!port) port = 80;
|
||||
|
||||
if (config->listen_masks->len) {
|
||||
for (i = 0; i < config->listen_masks->len; i++) {
|
||||
mask = g_ptr_array_index(config->listen_masks, i);
|
||||
switch (mask->type) {
|
||||
case LI_PLUGIN_CORE_LISTEN_MASK_IPV4:
|
||||
if (!ipv6_in_ipv4_net(ipv6, mask->value.ipv4.addr, mask->value.ipv4.networkmask)) continue;
|
||||
if ((mask->value.ipv4.port != port) && (mask->value.ipv4.port != 0 || (port != 80 && port != 443))) continue;
|
||||
break;
|
||||
case LI_PLUGIN_CORE_LISTEN_MASK_IPV6:
|
||||
if (!ipv6_in_ipv6_net(ipv6, mask->value.ipv6.addr, mask->value.ipv6.network)) continue;
|
||||
if ((mask->value.ipv6.port != port) && (mask->value.ipv6.port != 0 || (port != 80 && port != 443))) continue;
|
||||
break;
|
||||
case LI_PLUGIN_CORE_LISTEN_MASK_UNIX:
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (i == config->listen_masks->len) {
|
||||
ERROR(srv, "listen to socket '%s' not allowed", str->str);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin6_family = AF_INET6;
|
||||
|
@ -185,6 +302,7 @@ static int do_listen(liServer *srv, GString *str) {
|
|||
g_string_free(ipv6_str, TRUE);
|
||||
return s;
|
||||
#endif
|
||||
/* TODO: listen unix socket */
|
||||
} else {
|
||||
ERROR(srv, "Invalid ip: '%s'", str->str);
|
||||
return -1;
|
||||
|
@ -195,13 +313,13 @@ static void core_listen(liServer *srv, liInstance *i, liPlugin *p, gint32 id, GS
|
|||
GError *err = NULL;
|
||||
gint fd;
|
||||
GArray *fds;
|
||||
UNUSED(p);
|
||||
liPluginCoreConfig *config = (liPluginCoreConfig*) p->data;
|
||||
|
||||
DEBUG(srv, "core_listen(%i) '%s'", id, data->str);
|
||||
|
||||
if (-1 == id) return; /* ignore simple calls */
|
||||
|
||||
fd = do_listen(srv, data);
|
||||
fd = do_listen(srv, config, data);
|
||||
|
||||
if (-1 == fd) {
|
||||
GString *error = g_string_sized_new(0);
|
||||
|
@ -242,6 +360,7 @@ static void core_reached_state(liServer *srv, liInstance *i, liPlugin *p, gint32
|
|||
static void core_clean(liServer *srv, liPlugin *p);
|
||||
static void core_free(liServer *srv, liPlugin *p) {
|
||||
liPluginCoreConfig *config = (liPluginCoreConfig*) p->data;
|
||||
guint i;
|
||||
|
||||
core_clean(srv, p);
|
||||
|
||||
|
@ -255,10 +374,19 @@ static void core_free(liServer *srv, liPlugin *p) {
|
|||
li_instance_release(config->inst);
|
||||
config->inst = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < config->listen_masks->len; i++) {
|
||||
core_listen_mask_free(g_ptr_array_index(config->listen_masks, i));
|
||||
}
|
||||
g_ptr_array_free(config->listen_masks, TRUE);
|
||||
g_ptr_array_free(config->load_listen_masks, TRUE);
|
||||
config->listen_masks = NULL;
|
||||
config->load_listen_masks = NULL;
|
||||
}
|
||||
|
||||
static void core_clean(liServer *srv, liPlugin *p) {
|
||||
liPluginCoreConfig *config = (liPluginCoreConfig*) p->data;
|
||||
guint i;
|
||||
UNUSED(srv);
|
||||
|
||||
if (config->load_instconf) {
|
||||
|
@ -266,6 +394,11 @@ static void core_clean(liServer *srv, liPlugin *p) {
|
|||
config->load_instconf = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < config->load_listen_masks->len; i++) {
|
||||
core_listen_mask_free(g_ptr_array_index(config->load_listen_masks, i));
|
||||
}
|
||||
g_ptr_array_set_size(config->load_listen_masks, 0);
|
||||
|
||||
config->load_failed = FALSE;
|
||||
}
|
||||
|
||||
|
@ -277,6 +410,8 @@ static gboolean core_check(liServer *srv, liPlugin *p) {
|
|||
|
||||
static void core_activate(liServer *srv, liPlugin *p) {
|
||||
liPluginCoreConfig *config = (liPluginCoreConfig*) p->data;
|
||||
GPtrArray *tmp_ptrarray;
|
||||
guint i;
|
||||
|
||||
if (config->instconf) {
|
||||
li_instance_conf_release(config->instconf);
|
||||
|
@ -289,19 +424,27 @@ static void core_activate(liServer *srv, liPlugin *p) {
|
|||
config->inst = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < config->listen_masks->len; i++) {
|
||||
core_listen_mask_free(g_ptr_array_index(config->listen_masks, i));
|
||||
}
|
||||
g_ptr_array_set_size(config->listen_masks, 0);
|
||||
|
||||
|
||||
config->instconf = config->load_instconf;
|
||||
config->load_instconf = NULL;
|
||||
|
||||
tmp_ptrarray = config->load_listen_masks; config->load_listen_masks = config->listen_masks; config->listen_masks = tmp_ptrarray;
|
||||
|
||||
if (config->instconf) {
|
||||
config->inst = li_server_new_instance(srv, config->instconf);
|
||||
li_instance_set_state(config->inst, LI_INSTANCE_RUNNING);
|
||||
ERROR(srv, "%s", "Starting instance");
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean core_init(liServer *srv, liPlugin *p) {
|
||||
liPluginCoreConfig *config;
|
||||
UNUSED(srv);
|
||||
p->data = g_slice_new0(liPluginCoreConfig);
|
||||
p->data = config = g_slice_new0(liPluginCoreConfig);
|
||||
p->items = core_items;
|
||||
|
||||
p->handle_free = core_free;
|
||||
|
@ -309,6 +452,9 @@ static gboolean core_init(liServer *srv, liPlugin *p) {
|
|||
p->handle_check_config = core_check;
|
||||
p->handle_activate_config = core_activate;
|
||||
|
||||
config->listen_masks = g_ptr_array_new();
|
||||
config->load_listen_masks = g_ptr_array_new();
|
||||
|
||||
g_hash_table_insert(p->angel_callbacks, "listen", (gpointer)(intptr_t)core_listen);
|
||||
g_hash_table_insert(p->angel_callbacks, "reached-state", (gpointer)(intptr_t)core_reached_state);
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ static void read_pipe(liServer *srv, liErrorPipe *epipe, gboolean flush) {
|
|||
if (ioctl(epipe->fds[0], FIONREAD, &toread) || toread == 0) {
|
||||
toread = 256;
|
||||
} else {
|
||||
if (toread > max_read) toread = max_read;
|
||||
if (toread < 0 || toread > max_read) toread = max_read;
|
||||
}
|
||||
|
||||
buf = g_string_sized_new(toread);
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
end = (space | 0) @{ cs = ipv4_parser_first_final; fbreak; };
|
||||
|
||||
ipv4 := ipv4_data end;
|
||||
ipv4_cidr := ipv4_data netmask end;
|
||||
ipv4_socket := ipv4_data port end;
|
||||
ipv4_socket_cidr := ipv4_data netmask port end;
|
||||
ipv4_cidr := ipv4_data netmask? end;
|
||||
ipv4_socket := ipv4_data port? end;
|
||||
ipv4_socket_cidr := ipv4_data netmask? port? end;
|
||||
|
||||
write data;
|
||||
}%%
|
||||
|
@ -38,6 +38,9 @@ gboolean li_parse_ipv4(const char *str, guint32 *ip, guint32 *netmask, guint16 *
|
|||
gboolean res = TRUE;
|
||||
int cs, tmpval = 0, i = 0;
|
||||
|
||||
if (netmask) *netmask = 0xffffffffu;
|
||||
if (port) *port = 0;
|
||||
|
||||
%% write init nocs;
|
||||
|
||||
cs = netmask
|
||||
|
@ -116,6 +119,9 @@ gboolean li_parse_ipv6(const char *str, guint8 *ip, guint *network, guint16 *por
|
|||
gboolean res = TRUE, compressed = FALSE;
|
||||
int cs, tmpval = 0, i = 0;
|
||||
|
||||
if (network) *network = 128;
|
||||
if (port) *port = 0;
|
||||
|
||||
%% write init nocs;
|
||||
|
||||
cs = network
|
||||
|
|
|
@ -583,7 +583,7 @@ liSocketAddress li_sockaddr_from_string(GString *str, guint tcp_default_port) {
|
|||
#ifdef HAVE_IPV6
|
||||
guint8 ipv6[16];
|
||||
#endif
|
||||
guint16 port = tcp_default_port;
|
||||
guint16 port;
|
||||
liSocketAddress saddr = { 0, NULL };
|
||||
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
|
@ -595,7 +595,7 @@ liSocketAddress li_sockaddr_from_string(GString *str, guint tcp_default_port) {
|
|||
} else
|
||||
#endif
|
||||
if (li_parse_ipv4(str->str, &ipv4, NULL, &port)) {
|
||||
if (!port) return saddr;
|
||||
if (!port) port = tcp_default_port;
|
||||
saddr.len = sizeof(struct sockaddr_in);
|
||||
saddr.addr = (liSockAddr*) g_slice_alloc0(saddr.len);
|
||||
saddr.addr->ipv4.sin_family = AF_INET;
|
||||
|
@ -604,7 +604,7 @@ liSocketAddress li_sockaddr_from_string(GString *str, guint tcp_default_port) {
|
|||
#ifdef HAVE_IPV6
|
||||
} else
|
||||
if (li_parse_ipv6(str->str, ipv6, NULL, &port)) {
|
||||
if (!port) return saddr;
|
||||
if (!port) port = tcp_default_port;
|
||||
saddr.len = sizeof(struct sockaddr_in6);
|
||||
saddr.addr = (liSockAddr*) g_slice_alloc0(saddr.len);
|
||||
saddr.addr->ipv6.sin6_family = AF_INET6;
|
||||
|
@ -653,6 +653,30 @@ void li_sockaddr_clear(liSocketAddress *saddr) {
|
|||
saddr->len = 0;
|
||||
}
|
||||
|
||||
gboolean ipv4_in_ipv4_net(guint32 target, guint32 match, guint32 networkmask) {
|
||||
return (target & networkmask) == (match & networkmask);
|
||||
}
|
||||
|
||||
gboolean ipv6_in_ipv6_net(const unsigned char *target, const guint8 *match, guint network) {
|
||||
guint8 mask = network % 8;
|
||||
if (0 != memcmp(target, match, network / 8)) return FALSE;
|
||||
if (!mask) return TRUE;
|
||||
mask = ~(((guint) 1 << (8-mask)) - 1);
|
||||
return (target[network / 8] & mask) == (match[network / 8] & mask);
|
||||
}
|
||||
|
||||
gboolean ipv6_in_ipv4_net(const unsigned char *target, guint32 match, guint32 networkmask) {
|
||||
static const guint8 ipv6match[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
|
||||
if (!ipv6_in_ipv6_net(target, ipv6match, 96)) return FALSE;
|
||||
return ipv4_in_ipv4_net(*(guint32*)(target+12), match, networkmask);
|
||||
}
|
||||
|
||||
gboolean ipv4_in_ipv6_net(guint32 target, const guint8 *match, guint network) {
|
||||
guint8 ipv6[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
|
||||
*(guint32*) (ipv6+12) = target;
|
||||
return ipv6_in_ipv6_net(ipv6, match, network);
|
||||
}
|
||||
|
||||
/* unused */
|
||||
void li_gstring_replace_char_with_str_len(GString *gstr, gchar c, gchar *str, guint len) {
|
||||
for (guint i = 0; i < gstr->len; i++) {
|
||||
|
|
|
@ -9,11 +9,13 @@ int angel_fake_listen(liServer *srv, GString *str) {
|
|||
#ifdef HAVE_IPV6
|
||||
guint8 ipv6[16];
|
||||
#endif
|
||||
guint16 port = 80;
|
||||
guint16 port;
|
||||
|
||||
if (li_parse_ipv4(str->str, &ipv4, NULL, &port)) {
|
||||
int s, v;
|
||||
struct sockaddr_in addr;
|
||||
|
||||
if (!port) port = 80;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = ipv4;
|
||||
|
@ -47,6 +49,7 @@ int angel_fake_listen(liServer *srv, GString *str) {
|
|||
struct sockaddr_in6 addr;
|
||||
li_ipv6_tostring(ipv6_str, ipv6);
|
||||
|
||||
if (!port) port = 80;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin6_family = AF_INET6;
|
||||
memcpy(&addr.sin6_addr, ipv6, 16);
|
||||
|
|
|
@ -505,30 +505,6 @@ static liHandlerResult li_condition_check_eval_int(liVRequest *vr, liCondition *
|
|||
return LI_HANDLER_GO_ON;
|
||||
}
|
||||
|
||||
static gboolean ipv4_in_ipv4_net(guint32 target, guint32 match, guint32 networkmask) {
|
||||
return (target & networkmask) == (match & networkmask);
|
||||
}
|
||||
|
||||
static gboolean ipv6_in_ipv6_net(const unsigned char *target, const guint8 *match, guint network) {
|
||||
guint8 mask = network % 8;
|
||||
if (0 != memcmp(target, match, network / 8)) return FALSE;
|
||||
if (!mask) return TRUE;
|
||||
mask = ~(((guint) 1 << (8-mask)) - 1);
|
||||
return (target[network / 8] & mask) == (match[network / 8] & mask);
|
||||
}
|
||||
|
||||
static gboolean ipv6_in_ipv4_net(const unsigned char *target, guint32 match, guint32 networkmask) {
|
||||
static const guint8 ipv6match[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
|
||||
if (!ipv6_in_ipv6_net(target, ipv6match, 96)) return FALSE;
|
||||
return ipv4_in_ipv4_net(*(guint32*)(target+12), match, networkmask);
|
||||
}
|
||||
|
||||
static gboolean ipv4_in_ipv6_net(guint32 target, const guint8 *match, guint network) {
|
||||
guint8 ipv6[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0 };
|
||||
*(guint32*) (ipv6+12) = target;
|
||||
return ipv6_in_ipv6_net(ipv6, match, network);
|
||||
}
|
||||
|
||||
static gboolean ip_in_net(liConditionRValue *target, liConditionRValue *network) {
|
||||
if (target->type == LI_COND_VALUE_SOCKET_IPV4) {
|
||||
if (network->type == LI_COND_VALUE_SOCKET_IPV4) {
|
||||
|
|
Loading…
Reference in New Issue