2
0
Fork 0
lighttpd2/src/main/condition.c

664 lines
20 KiB
C
Raw Normal View History

#include <lighttpd/base.h>
2008-06-29 15:48:28 +00:00
static gboolean condition_parse_ip(liConditionRValue *val, const char *txt) {
2009-07-09 20:17:24 +00:00
if (li_parse_ipv4(txt, &val->ipv4.addr, NULL, NULL)) {
val->type = LI_COND_VALUE_SOCKET_IPV4;
2008-07-25 22:42:08 +00:00
val->ipv4.networkmask = 0xFFFFFFFF;
return TRUE;
}
2009-07-09 20:17:24 +00:00
if (li_parse_ipv6(txt, val->ipv6.addr, NULL, NULL)) {
val->type = LI_COND_VALUE_SOCKET_IPV6;
2008-07-25 22:42:08 +00:00
val->ipv6.network = 128;
return TRUE;
}
return FALSE;
}
static gboolean condition_parse_ip_net(liConditionRValue *val, const char *txt) {
2009-07-09 20:17:24 +00:00
if (li_parse_ipv4(txt, &val->ipv4.addr, &val->ipv4.networkmask, NULL)) {
val->type = LI_COND_VALUE_SOCKET_IPV4;
2008-07-25 22:42:08 +00:00
return TRUE;
}
2009-07-09 20:17:24 +00:00
if (li_parse_ipv6(txt, val->ipv6.addr, &val->ipv6.network, NULL)) {
val->type = LI_COND_VALUE_SOCKET_IPV6;
2008-07-25 22:42:08 +00:00
return TRUE;
}
return FALSE;
}
static gboolean condition_ip_from_socket(liConditionRValue *val, liSockAddr *addr) {
2008-07-25 22:42:08 +00:00
switch (addr->plain.sa_family) {
case AF_INET:
val->type = LI_COND_VALUE_SOCKET_IPV4;
2008-07-25 22:42:08 +00:00
val->ipv4.addr = addr->ipv4.sin_addr.s_addr;
val->ipv4.networkmask = 0xFFFFFFFF;
return TRUE;
#ifdef HAVE_IPV6
case AF_INET6:
val->type = LI_COND_VALUE_SOCKET_IPV6;
2008-07-25 22:42:08 +00:00
memcpy(val->ipv6.addr, addr->ipv6.sin6_addr.s6_addr, 16);
val->ipv6.network = 128;
return TRUE;
#endif
}
2008-07-25 22:42:08 +00:00
return FALSE;
}
2009-07-09 20:17:24 +00:00
liConditionLValue* li_condition_lvalue_new(liCondLValue type, GString *key) {
liConditionLValue *lvalue = g_slice_new0(liConditionLValue);
if (type == LI_COMP_REQUEST_HEADER || type == LI_COMP_RESPONSE_HEADER) g_string_ascii_down(key);
lvalue->type = type;
lvalue->key = key;
lvalue->refcount = 1;
return lvalue;
2008-06-29 15:48:28 +00:00
}
2009-07-09 20:17:24 +00:00
void li_condition_lvalue_acquire(liConditionLValue *lvalue) {
2008-09-09 14:41:02 +00:00
assert(g_atomic_int_get(&lvalue->refcount) > 0);
g_atomic_int_inc(&lvalue->refcount);
}
2008-06-29 15:48:28 +00:00
2009-07-09 20:17:24 +00:00
void li_condition_lvalue_release(liConditionLValue *lvalue) {
2008-08-06 18:46:42 +00:00
if (!lvalue) return;
2008-09-09 14:41:02 +00:00
assert(g_atomic_int_get(&lvalue->refcount) > 0);
if (g_atomic_int_dec_and_test(&lvalue->refcount)) {
if (lvalue->key) g_string_free(lvalue->key, TRUE);
g_slice_free(liConditionLValue, lvalue);
}
2008-06-29 15:48:28 +00:00
}
static liCondition* condition_new(liCompOperator op, liConditionLValue *lvalue) {
liCondition *c = g_slice_new0(liCondition);
2008-06-29 15:48:28 +00:00
c->refcount = 1;
c->op = op;
c->lvalue = lvalue;
2008-06-29 15:48:28 +00:00
return c;
}
2008-07-25 20:38:42 +00:00
/* only EQ and NE */
static liCondition* cond_new_string(liCompOperator op, liConditionLValue *lvalue, GString *str) {
liCondition *c;
2008-07-25 20:38:42 +00:00
c = condition_new(op, lvalue);
c->rvalue.type = LI_COND_VALUE_STRING;
2008-07-25 20:38:42 +00:00
c->rvalue.string = str;
2008-06-29 15:48:28 +00:00
return c;
}
2008-07-25 20:38:42 +00:00
/* only MATCH and NOMATCH */
static liCondition* cond_new_match(liServer *srv, liCompOperator op, liConditionLValue *lvalue, GString *str) {
liCondition *c;
GRegex *regex;
GError *err = NULL;
regex = g_regex_new(str->str, G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &err);
if (!regex || err) {
ERROR(srv, "failed to compile regex \"%s\": %s", str->str, err->message);
g_error_free(err);
return NULL;
}
c = condition_new(op, lvalue);
c->rvalue.type = LI_COND_VALUE_REGEXP;
c->rvalue.regex = regex;
g_string_free(str, TRUE);
return c;
2008-07-25 20:38:42 +00:00
}
/* only IP and NOTIP */
static liCondition* cond_new_ip(liServer *srv, liCompOperator op, liConditionLValue *lvalue, GString *str) {
liCondition *c;
2008-07-25 22:42:08 +00:00
c = condition_new(op, lvalue);
if (!condition_parse_ip_net(&c->rvalue, str->str)) {
ERROR(srv, "Invalid ip address '%s'", str->str);
2009-07-09 20:17:24 +00:00
li_condition_release(srv, c);
2008-07-25 22:42:08 +00:00
return NULL;
}
return c;
2008-06-29 15:48:28 +00:00
}
2009-07-09 20:17:24 +00:00
liCondition* li_condition_new_bool(liServer *srv, liConditionLValue *lvalue, gboolean b) {
liCondition *c;
UNUSED(srv);
c = condition_new(LI_CONFIG_COND_EQ, lvalue);
c->rvalue.type = LI_COND_VALUE_BOOL;
c->rvalue.b = b;
return c;
}
2009-07-09 20:17:24 +00:00
liCondition* li_condition_new_string(liServer *srv, liCompOperator op, liConditionLValue *lvalue, GString *str) {
2008-07-25 20:38:42 +00:00
switch (op) {
case LI_CONFIG_COND_EQ:
case LI_CONFIG_COND_NE:
case LI_CONFIG_COND_PREFIX:
case LI_CONFIG_COND_NOPREFIX:
case LI_CONFIG_COND_SUFFIX:
case LI_CONFIG_COND_NOSUFFIX:
return cond_new_string(op, lvalue, str);
case LI_CONFIG_COND_MATCH:
case LI_CONFIG_COND_NOMATCH:
2008-07-25 20:38:42 +00:00
return cond_new_match(srv, op, lvalue, str);
case LI_CONFIG_COND_IP:
case LI_CONFIG_COND_NOTIP:
2008-07-25 20:38:42 +00:00
return cond_new_ip(srv, op, lvalue, str);
case LI_CONFIG_COND_GT:
case LI_CONFIG_COND_GE:
case LI_CONFIG_COND_LT:
case LI_CONFIG_COND_LE:
2009-07-09 20:17:24 +00:00
ERROR(srv, "Cannot compare strings with '%s'", li_comp_op_to_string(op));
2008-07-25 20:38:42 +00:00
return NULL;
2008-06-29 15:48:28 +00:00
}
ERROR(srv, "Condition creation failed: %s %s '%s'",
2009-07-09 20:17:24 +00:00
li_cond_lvalue_to_string(lvalue->type), li_comp_op_to_string(op),
2008-07-25 20:38:42 +00:00
str->str);
2008-06-30 10:25:01 +00:00
return NULL;
2008-06-29 15:48:28 +00:00
}
2009-07-09 20:17:24 +00:00
liCondition* li_condition_new_int(liServer *srv, liCompOperator op, liConditionLValue *lvalue, gint64 i) {
liCondition *c;
2008-07-25 20:38:42 +00:00
switch (op) {
case LI_CONFIG_COND_PREFIX:
case LI_CONFIG_COND_NOPREFIX:
case LI_CONFIG_COND_SUFFIX:
case LI_CONFIG_COND_NOSUFFIX:
case LI_CONFIG_COND_MATCH:
case LI_CONFIG_COND_NOMATCH:
case LI_CONFIG_COND_IP:
case LI_CONFIG_COND_NOTIP:
2009-07-09 20:17:24 +00:00
ERROR(srv, "Cannot compare integers with '%s'", li_comp_op_to_string(op));
return NULL;
case LI_CONFIG_COND_EQ:
case LI_CONFIG_COND_NE:
case LI_CONFIG_COND_GT:
case LI_CONFIG_COND_GE:
case LI_CONFIG_COND_LT:
case LI_CONFIG_COND_LE:
2008-07-25 20:38:42 +00:00
c = condition_new(op, lvalue);
c->rvalue.type = LI_COND_VALUE_NUMBER;
2008-07-25 20:38:42 +00:00
c->rvalue.i = i;
return c;
}
ERROR(srv, "Condition creation failed: %s %s %"G_GINT64_FORMAT,
2009-07-09 20:17:24 +00:00
li_cond_lvalue_to_string(lvalue->type), li_comp_op_to_string(op),
2008-07-25 20:38:42 +00:00
i);
return NULL;
2008-06-29 15:48:28 +00:00
}
2008-07-25 20:38:42 +00:00
static void condition_free(liCondition *c) {
2009-07-09 20:17:24 +00:00
li_condition_lvalue_release(c->lvalue);
switch (c->rvalue.type) {
case LI_COND_VALUE_BOOL:
case LI_COND_VALUE_NUMBER:
2008-06-30 10:25:01 +00:00
/* nothing to free */
2008-06-29 15:48:28 +00:00
break;
case LI_COND_VALUE_STRING:
2008-07-25 20:38:42 +00:00
g_string_free(c->rvalue.string, TRUE);
break;
case LI_COND_VALUE_REGEXP:
g_regex_unref(c->rvalue.regex);
2008-07-25 20:38:42 +00:00
break;
case LI_COND_VALUE_SOCKET_IPV4:
case LI_COND_VALUE_SOCKET_IPV6:
2008-07-25 20:38:42 +00:00
/* nothing to free */
2008-06-29 15:48:28 +00:00
break;
}
g_slice_free(liCondition, c);
2008-06-29 15:48:28 +00:00
}
2009-07-09 20:17:24 +00:00
void li_condition_acquire(liCondition *c) {
2008-09-09 14:41:02 +00:00
assert(g_atomic_int_get(&c->refcount) > 0);
g_atomic_int_inc(&c->refcount);
}
2009-07-09 20:17:24 +00:00
void li_condition_release(liServer *srv, liCondition* c) {
UNUSED(srv);
2008-08-06 18:46:42 +00:00
if (!c) return;
2008-09-09 14:41:02 +00:00
assert(g_atomic_int_get(&c->refcount) > 0);
if (g_atomic_int_dec_and_test(&c->refcount)) {
2008-06-29 15:48:28 +00:00
condition_free(c);
}
}
2009-07-09 20:17:24 +00:00
const char* li_comp_op_to_string(liCompOperator op) {
switch (op) {
case LI_CONFIG_COND_EQ: return "==";
case LI_CONFIG_COND_NE: return "!=";
case LI_CONFIG_COND_PREFIX: return "=^";
case LI_CONFIG_COND_NOPREFIX: return "=^";
case LI_CONFIG_COND_SUFFIX: return "=$";
case LI_CONFIG_COND_NOSUFFIX: return "!$";
case LI_CONFIG_COND_MATCH: return "=~";
case LI_CONFIG_COND_NOMATCH: return "!~";
case LI_CONFIG_COND_IP: return "=/";
case LI_CONFIG_COND_NOTIP: return "!/";
case LI_CONFIG_COND_GT: return ">";
case LI_CONFIG_COND_GE: return ">=";
case LI_CONFIG_COND_LT: return "<";
case LI_CONFIG_COND_LE: return "<=";
}
2008-06-29 15:48:28 +00:00
return "<unkown>";
2008-06-29 15:48:28 +00:00
}
2009-07-09 20:17:24 +00:00
const char* li_cond_lvalue_to_string(liCondLValue t) {
switch (t) {
case LI_COMP_REQUEST_LOCALIP: return "request.localip";
case LI_COMP_REQUEST_REMOTEIP: return "request.remoteip";
case LI_COMP_REQUEST_PATH: return "request.path";
case LI_COMP_REQUEST_HOST: return "request.host";
case LI_COMP_REQUEST_SCHEME: return "request.scheme";
case LI_COMP_REQUEST_QUERY_STRING: return "request.query";
case LI_COMP_REQUEST_METHOD: return "request.method";
case LI_COMP_REQUEST_CONTENT_LENGTH: return "request.length";
2009-10-03 14:47:57 +00:00
case LI_COMP_REQUEST_IS_HANDLED: return "request.is_handled";
case LI_COMP_PHYSICAL_PATH: return "physical.path";
case LI_COMP_PHYSICAL_EXISTS: return "physical.exist";
case LI_COMP_PHYSICAL_SIZE: return "physical.size";
case LI_COMP_PHYSICAL_ISDIR: return "physical.is_dir";
case LI_COMP_PHYSICAL_ISFILE: return "physical.is_file";
case LI_COMP_RESPONSE_STATUS: return "response.status";
case LI_COMP_REQUEST_HEADER: return "request.header";
case LI_COMP_RESPONSE_HEADER: return "response.header";
case LI_COMP_UNKNOWN: return "<unknown>";
}
2008-06-29 15:48:28 +00:00
return "<unkown>";
}
2009-07-09 20:17:24 +00:00
liCondLValue li_cond_lvalue_from_string(const gchar *str, guint len) {
gchar *c = (gchar*)str;
if (g_str_has_prefix(c, "request.")) {
c += sizeof("request.")-1;
len -= sizeof("request.")-1;
if (strncmp(c, "localip", len) == 0)
return LI_COMP_REQUEST_LOCALIP;
else if (strncmp(c, "remoteip", len) == 0)
return LI_COMP_REQUEST_REMOTEIP;
else if (strncmp(c, "path", len) == 0)
return LI_COMP_REQUEST_PATH;
else if (strncmp(c, "host", len) == 0)
return LI_COMP_REQUEST_HOST;
else if (strncmp(c, "scheme", len) == 0)
return LI_COMP_REQUEST_SCHEME;
else if (strncmp(c, "query", len) == 0)
return LI_COMP_REQUEST_QUERY_STRING;
else if (strncmp(c, "method", len) == 0)
return LI_COMP_REQUEST_METHOD;
else if (strncmp(c, "length", len) == 0)
return LI_COMP_REQUEST_CONTENT_LENGTH;
else if (strncmp(c, "header", len) == 0)
return LI_COMP_REQUEST_HEADER;
2009-10-03 14:47:57 +00:00
else if (strncmp(c, "is_handled", len) == 0)
return LI_COMP_REQUEST_IS_HANDLED;
} else if (g_str_has_prefix(c, "physical.")) {
c += sizeof("physical.")-1;
len -= sizeof("physical.")-1;
if (strncmp(c, "path", len) == 0)
return LI_COMP_PHYSICAL_PATH;
else if (strncmp(c, "exists", len) == 0)
return LI_COMP_PHYSICAL_EXISTS;
else if (strncmp(c, "size", len) == 0)
return LI_COMP_PHYSICAL_SIZE;
else if (strncmp(c, "is_file", len) == 0)
return LI_COMP_PHYSICAL_ISFILE;
else if (strncmp(c, "is_dir", len) == 0)
return LI_COMP_PHYSICAL_ISDIR;
} else if (g_str_has_prefix(c, "response.")) {
c += sizeof("response.")-1;
len -= sizeof("response.")-1;
if (strncmp(c, "status", len) == 0)
return LI_COMP_RESPONSE_STATUS;
else if (strncmp(c, "header", len) == 0)
return LI_COMP_RESPONSE_HEADER;
}
return LI_COMP_UNKNOWN;
2008-06-29 15:48:28 +00:00
}
2008-06-30 10:25:01 +00:00
2009-07-09 20:17:24 +00:00
static liHandlerResult li_condition_check_eval_bool(liVRequest *vr, liCondition *cond, gboolean *res) {
liHandlerResult r;
struct stat st;
int err;
*res = !cond->rvalue.b; /* "FALSE" is "not (expected result)" */
switch (cond->lvalue->type) {
case LI_COMP_PHYSICAL_ISDIR:
case LI_COMP_PHYSICAL_ISFILE:
case LI_COMP_PHYSICAL_EXISTS:
if (vr->physical.path->len == 0) {
/* no file, return FALSE */
return LI_HANDLER_GO_ON;
}
r = li_stat_cache_get(vr, vr->physical.path, &st, &err, NULL);
if (r == LI_HANDLER_WAIT_FOR_EVENT) return r;
/* not found, return FALSE */
if (r != LI_HANDLER_GO_ON) return LI_HANDLER_GO_ON;
break;
default:
memset(&st, 0, sizeof(st));
break;
}
switch (cond->lvalue->type) {
2009-10-03 14:47:57 +00:00
case LI_COMP_REQUEST_IS_HANDLED:
*res = li_vrequest_is_handled(vr);
break;
case LI_COMP_PHYSICAL_ISDIR:
*res = S_ISDIR(st.st_mode);
break;
case LI_COMP_PHYSICAL_ISFILE:
*res = S_ISREG(st.st_mode);
break;
case LI_COMP_PHYSICAL_EXISTS:
*res = TRUE;
break;
default:
2009-07-09 20:17:24 +00:00
VR_ERROR(vr, "invalid lvalue \"%s\" for boolean comparison", li_cond_lvalue_to_string(cond->lvalue->type));
return LI_HANDLER_ERROR;
}
if (!cond->rvalue.b) *res = !*res;
return LI_HANDLER_GO_ON;
}
/* LI_COND_VALUE_STRING and LI_COND_VALUE_REGEXP only */
2009-07-09 20:17:24 +00:00
static liHandlerResult li_condition_check_eval_string(liVRequest *vr, liCondition *cond, gboolean *res) {
liActionRegexStackElement arse;
liConnection *con = vr->con;
const char *val = "";
*res = FALSE;
2008-06-30 10:25:01 +00:00
switch (cond->lvalue->type) {
case LI_COMP_REQUEST_LOCALIP:
val = con->local_addr_str->str;
break;
case LI_COMP_REQUEST_REMOTEIP:
val = con->remote_addr_str->str;
2008-06-30 10:25:01 +00:00
break;
case LI_COMP_REQUEST_PATH:
val = vr->request.uri.path->str;
2008-06-30 10:25:01 +00:00
break;
case LI_COMP_REQUEST_HOST:
val = vr->request.uri.host->str;
2008-06-30 10:25:01 +00:00
break;
case LI_COMP_REQUEST_SCHEME:
val = con->is_ssl ? "https" : "http";
2008-06-30 10:25:01 +00:00
break;
case LI_COMP_REQUEST_QUERY_STRING:
val = vr->request.uri.query->str;
2008-06-30 10:25:01 +00:00
break;
case LI_COMP_REQUEST_METHOD:
val = vr->request.http_method_str->str;
2008-06-30 10:25:01 +00:00
break;
case LI_COMP_PHYSICAL_PATH:
val = vr->physical.path->str;
2008-08-07 12:12:51 +00:00
break;
case LI_COMP_REQUEST_HEADER:
2009-09-13 15:46:02 +00:00
li_http_header_get_all(con->wrk->tmp_str, vr->request.headers, GSTR_LEN(cond->lvalue->key));
val = con->wrk->tmp_str->str;
2008-06-30 10:25:01 +00:00
break;
case LI_COMP_RESPONSE_HEADER:
VREQUEST_WAIT_FOR_RESPONSE_HEADERS(vr);
li_http_header_get_all(con->wrk->tmp_str, vr->response.headers, GSTR_LEN(cond->lvalue->key));
val = con->wrk->tmp_str->str;
break;
case LI_COMP_REQUEST_CONTENT_LENGTH:
g_string_printf(con->wrk->tmp_str, "%"L_GOFFSET_FORMAT, vr->request.content_length);
val = con->wrk->tmp_str->str;
2008-06-30 11:38:52 +00:00
break;
default:
VR_ERROR(vr, "couldn't get string value for '%s'", li_cond_lvalue_to_string(cond->lvalue->type));
return LI_HANDLER_ERROR;
2008-06-30 10:25:01 +00:00
}
2008-06-30 11:38:52 +00:00
2008-07-25 22:42:08 +00:00
switch (cond->op) {
case LI_CONFIG_COND_EQ:
*res = g_str_equal(val, cond->rvalue.string->str);
2008-06-30 12:34:37 +00:00
break;
case LI_CONFIG_COND_NE:
2008-12-09 21:38:37 +00:00
*res = !g_str_equal(val, cond->rvalue.string->str);
break;
case LI_CONFIG_COND_PREFIX:
*res = g_str_has_prefix(val, cond->rvalue.string->str);
break;
case LI_CONFIG_COND_NOPREFIX:
*res = !g_str_has_prefix(val, cond->rvalue.string->str);
break;
case LI_CONFIG_COND_SUFFIX:
*res = g_str_has_suffix(val, cond->rvalue.string->str);
2008-06-30 12:34:37 +00:00
break;
case LI_CONFIG_COND_NOSUFFIX:
*res = !g_str_has_suffix(val, cond->rvalue.string->str);
break;
case LI_CONFIG_COND_MATCH:
*res = g_regex_match(cond->rvalue.regex, val, 0, &arse.match_info);
arse.string = (*res) ? g_string_new(val) : NULL;
g_array_append_val(vr->action_stack.regex_stack, arse);
break;
case LI_CONFIG_COND_NOMATCH:
*res = !g_regex_match(cond->rvalue.regex, val, 0, &arse.match_info);
arse.string = NULL;
g_array_append_val(vr->action_stack.regex_stack, arse);
2008-06-30 12:34:37 +00:00
break;
case LI_CONFIG_COND_IP:
case LI_CONFIG_COND_NOTIP:
case LI_CONFIG_COND_GE:
case LI_CONFIG_COND_GT:
case LI_CONFIG_COND_LE:
case LI_CONFIG_COND_LT:
2009-07-09 20:17:24 +00:00
VR_ERROR(vr, "cannot compare string/regexp with '%s'", li_comp_op_to_string(cond->op));
return LI_HANDLER_ERROR;
2008-06-30 10:25:01 +00:00
}
2008-06-30 12:01:53 +00:00
return LI_HANDLER_GO_ON;
2008-06-30 10:25:01 +00:00
}
2008-06-30 11:38:52 +00:00
2009-07-09 20:17:24 +00:00
static liHandlerResult li_condition_check_eval_int(liVRequest *vr, liCondition *cond, gboolean *res) {
liHandlerResult r;
struct stat st;
int err;
gint64 val;
*res = FALSE;
2008-06-30 11:38:52 +00:00
switch (cond->lvalue->type) {
case LI_COMP_REQUEST_CONTENT_LENGTH:
val = vr->request.content_length;
break;
case LI_COMP_PHYSICAL_SIZE:
if (vr->physical.path->len == 0) {
val = -1;
break;
}
r = li_stat_cache_get(vr, vr->physical.path, &st, &err, NULL);
if (r == LI_HANDLER_WAIT_FOR_EVENT) return r;
if (r != LI_HANDLER_GO_ON) {
val = -1; /* not found -> size "-1" */
} else {
val = (gint64)st.st_size;
}
2008-06-30 12:34:37 +00:00
break;
case LI_COMP_RESPONSE_STATUS:
VREQUEST_WAIT_FOR_RESPONSE_HEADERS(vr);
val = vr->response.http_status;
break;
2008-06-30 12:34:37 +00:00
default:
2009-07-09 20:17:24 +00:00
VR_ERROR(vr, "couldn't get int value for '%s'", li_cond_lvalue_to_string(cond->lvalue->type));
return LI_HANDLER_ERROR;
2008-06-30 11:38:52 +00:00
}
switch (cond->op) {
case LI_CONFIG_COND_EQ: /** == */
*res = (val == cond->rvalue.i);
break;
case LI_CONFIG_COND_NE: /** != */
*res = (val != cond->rvalue.i);
break;
case LI_CONFIG_COND_LT: /** < */
*res = (val < cond->rvalue.i);
break;
case LI_CONFIG_COND_LE: /** <= */
*res = (val <= cond->rvalue.i);
break;
case LI_CONFIG_COND_GT: /** > */
*res = (val > cond->rvalue.i);
break;
case LI_CONFIG_COND_GE: /** >= */
*res = (val >= cond->rvalue.i);
break;
case LI_CONFIG_COND_PREFIX:
case LI_CONFIG_COND_NOPREFIX:
case LI_CONFIG_COND_SUFFIX:
case LI_CONFIG_COND_NOSUFFIX:
case LI_CONFIG_COND_MATCH:
case LI_CONFIG_COND_NOMATCH:
case LI_CONFIG_COND_IP:
case LI_CONFIG_COND_NOTIP:
2009-07-09 20:17:24 +00:00
VR_ERROR(vr, "cannot compare int with '%s'", li_comp_op_to_string(cond->op));
return LI_HANDLER_ERROR;
2008-06-30 11:38:52 +00:00
}
return LI_HANDLER_GO_ON;
2008-06-30 11:38:52 +00:00
}
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) {
2008-07-25 22:42:08 +00:00
return ipv4_in_ipv4_net(target->ipv4.addr, network->ipv4.addr, network->ipv4.networkmask);
} else if (network->type == LI_COND_VALUE_SOCKET_IPV6) {
2008-07-25 22:42:08 +00:00
return ipv4_in_ipv6_net(target->ipv4.addr, network->ipv6.addr, network->ipv6.network);
}
} else if (target->type == LI_COND_VALUE_SOCKET_IPV6) {
if (network->type == LI_COND_VALUE_SOCKET_IPV4) {
2008-07-25 22:42:08 +00:00
return ipv6_in_ipv4_net(target->ipv6.addr, network->ipv4.addr, network->ipv4.networkmask);
} else if (network->type == LI_COND_VALUE_SOCKET_IPV6) {
2008-07-25 22:42:08 +00:00
return ipv6_in_ipv6_net(target->ipv6.addr, network->ipv6.addr, network->ipv6.network);
}
}
return FALSE;
}
/* LI_CONFIG_COND_IP and LI_CONFIG_COND_NOTIP only */
2009-07-09 20:17:24 +00:00
static liHandlerResult li_condition_check_eval_ip(liVRequest *vr, liCondition *cond, gboolean *res) {
liConnection *con = vr->con;
liConditionRValue ipval;
const char *val = NULL;
*res = (cond->op == LI_CONFIG_COND_NOTIP);
2008-07-25 22:42:08 +00:00
ipval.type = LI_COND_VALUE_NUMBER;
2008-07-25 22:42:08 +00:00
switch (cond->lvalue->type) {
case LI_COMP_REQUEST_LOCALIP:
if (!condition_ip_from_socket(&ipval, con->local_addr.addr))
return LI_HANDLER_GO_ON;
2008-07-25 22:42:08 +00:00
break;
case LI_COMP_REQUEST_REMOTEIP:
if (!condition_ip_from_socket(&ipval, con->remote_addr.addr))
return LI_HANDLER_GO_ON;
2008-07-25 22:42:08 +00:00
break;
case LI_COMP_REQUEST_PATH:
VR_ERROR(vr, "%s", "Cannot parse request.path as ip");
return LI_HANDLER_ERROR;
case LI_COMP_REQUEST_HOST:
val = vr->request.uri.host->str;
2008-07-25 22:42:08 +00:00
break;
case LI_COMP_REQUEST_SCHEME:
VR_ERROR(vr, "%s", "Cannot parse request.scheme as ip");
return LI_HANDLER_ERROR;
case LI_COMP_REQUEST_QUERY_STRING:
val = vr->request.uri.query->str;
2008-07-25 22:42:08 +00:00
break;
case LI_COMP_REQUEST_METHOD:
VR_ERROR(vr, "%s", "Cannot parse request.method as ip");
return LI_HANDLER_ERROR;
2009-10-03 14:47:57 +00:00
case LI_COMP_REQUEST_IS_HANDLED:
VR_ERROR(vr, "%s", "Cannot parse request.is_handled as ip");
return LI_HANDLER_ERROR;
case LI_COMP_PHYSICAL_PATH:
case LI_COMP_PHYSICAL_EXISTS:
VR_ERROR(vr, "%s", "Cannot parse physical.path(-exists) as ip");
return LI_HANDLER_ERROR;
2008-07-25 22:42:08 +00:00
break;
case LI_COMP_REQUEST_HEADER:
2009-09-13 15:46:02 +00:00
li_http_header_get_all(con->wrk->tmp_str, vr->request.headers, GSTR_LEN(cond->lvalue->key));
val = con->wrk->tmp_str->str;
2008-07-25 22:42:08 +00:00
break;
case LI_COMP_RESPONSE_HEADER:
VREQUEST_WAIT_FOR_RESPONSE_HEADERS(vr);
li_http_header_get_all(con->wrk->tmp_str, vr->response.headers, GSTR_LEN(cond->lvalue->key));
val = con->wrk->tmp_str->str;
break;
case LI_COMP_PHYSICAL_SIZE:
case LI_COMP_REQUEST_CONTENT_LENGTH:
case LI_COMP_RESPONSE_STATUS:
VR_ERROR(vr, "%s", "Cannot parse integers as ip");
return LI_HANDLER_ERROR;
case LI_COMP_PHYSICAL_ISDIR:
case LI_COMP_PHYSICAL_ISFILE:
VR_ERROR(vr, "%s", "phys.is_dir and phys.is_file are boolean conditionals");
return LI_HANDLER_ERROR;
case LI_COMP_UNKNOWN:
VR_ERROR(vr, "%s", "Cannot parse unknown condition value");
return LI_HANDLER_ERROR;
2008-07-25 22:42:08 +00:00
}
if (ipval.type == LI_COND_VALUE_NUMBER) {
if (!val || !condition_parse_ip(&ipval, val))
return LI_HANDLER_GO_ON;
2008-07-25 22:42:08 +00:00
}
switch (cond->op) {
case LI_CONFIG_COND_IP:
*res = ip_in_net(&ipval, &cond->rvalue);
break;
case LI_CONFIG_COND_NOTIP:
*res = !ip_in_net(&ipval, &cond->rvalue);
break;
case LI_CONFIG_COND_PREFIX:
case LI_CONFIG_COND_NOPREFIX:
case LI_CONFIG_COND_SUFFIX:
case LI_CONFIG_COND_NOSUFFIX:
case LI_CONFIG_COND_EQ:
case LI_CONFIG_COND_NE:
case LI_CONFIG_COND_MATCH:
case LI_CONFIG_COND_NOMATCH:
case LI_CONFIG_COND_GE:
case LI_CONFIG_COND_GT:
case LI_CONFIG_COND_LE:
case LI_CONFIG_COND_LT:
2009-07-09 20:17:24 +00:00
VR_ERROR(vr, "cannot match ips with '%s'", li_comp_op_to_string(cond->op));
return LI_HANDLER_ERROR;
2008-07-25 22:42:08 +00:00
}
return LI_HANDLER_GO_ON;
2008-07-25 22:42:08 +00:00
}
2008-06-30 10:25:01 +00:00
2009-07-09 20:17:24 +00:00
liHandlerResult li_condition_check(liVRequest *vr, liCondition *cond, gboolean *res) {
switch (cond->rvalue.type) {
case LI_COND_VALUE_BOOL:
2009-07-09 20:17:24 +00:00
return li_condition_check_eval_bool(vr, cond, res);
case LI_COND_VALUE_STRING:
case LI_COND_VALUE_REGEXP:
2009-07-09 20:17:24 +00:00
return li_condition_check_eval_string(vr, cond, res);
case LI_COND_VALUE_NUMBER:
2009-07-09 20:17:24 +00:00
return li_condition_check_eval_int(vr, cond, res);
case LI_COND_VALUE_SOCKET_IPV4:
case LI_COND_VALUE_SOCKET_IPV6:
2009-07-09 20:17:24 +00:00
return li_condition_check_eval_ip(vr, cond, res);
2008-06-30 10:25:01 +00:00
}
VR_ERROR(vr, "Unsupported conditional type: %i", cond->rvalue.type);
return LI_HANDLER_ERROR;
2008-06-30 10:25:01 +00:00
}