the "www.example.*" wildcard hash support
This commit is contained in:
parent
86364a7ca5
commit
5fb6ed90af
9 changed files with 471 additions and 298 deletions
|
@ -53,7 +53,7 @@ ngx_hash_find(ngx_hash_t *hash, ngx_uint_t key, u_char *name, size_t len)
|
||||||
|
|
||||||
|
|
||||||
void *
|
void *
|
||||||
ngx_hash_find_wildcard(ngx_hash_wildcard_t *hwc, u_char *name, size_t len)
|
ngx_hash_find_wc_head(ngx_hash_wildcard_t *hwc, u_char *name, size_t len)
|
||||||
{
|
{
|
||||||
void *value;
|
void *value;
|
||||||
ngx_uint_t i, n, key;
|
ngx_uint_t i, n, key;
|
||||||
|
@ -63,7 +63,7 @@ ngx_hash_find_wildcard(ngx_hash_wildcard_t *hwc, u_char *name, size_t len)
|
||||||
|
|
||||||
line.len = len;
|
line.len = len;
|
||||||
line.data = name;
|
line.data = name;
|
||||||
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "wc:\"%V\"", &line);
|
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "wch:\"%V\"", &line);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
n = len;
|
n = len;
|
||||||
|
@ -112,7 +112,7 @@ ngx_hash_find_wildcard(ngx_hash_wildcard_t *hwc, u_char *name, size_t len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
value = ngx_hash_find_wildcard(hwc, name, n - 1);
|
value = ngx_hash_find_wc_head(hwc, name, n - 1);
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
return value;
|
return value;
|
||||||
|
@ -128,6 +128,104 @@ ngx_hash_find_wildcard(ngx_hash_wildcard_t *hwc, u_char *name, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
ngx_hash_find_wc_tail(ngx_hash_wildcard_t *hwc, u_char *name, size_t len)
|
||||||
|
{
|
||||||
|
void *value;
|
||||||
|
ngx_uint_t i, key;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
ngx_str_t line;
|
||||||
|
|
||||||
|
line.len = len;
|
||||||
|
line.data = name;
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "wct:\"%V\"", &line);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
key = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (name[i] == '.') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = ngx_hash(key, name[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == len) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "key:\"%ui\"", key);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
value = ngx_hash_find(&hwc->hash, key, name, i);
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the 2 low bits of value have the special meaning:
|
||||||
|
* 00 - value is data pointer,
|
||||||
|
* 01 - value is pointer to wildcard hash allowing "example.*".
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((uintptr_t) value & 1) {
|
||||||
|
|
||||||
|
i++;
|
||||||
|
|
||||||
|
hwc = (ngx_hash_wildcard_t *) ((uintptr_t) value & (uintptr_t) ~3);
|
||||||
|
|
||||||
|
value = ngx_hash_find_wc_tail(hwc, &name[i], len - i);
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hwc->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hwc->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
ngx_hash_find_combined(ngx_hash_combined_t *hash, ngx_uint_t key, u_char *name,
|
||||||
|
size_t len)
|
||||||
|
{
|
||||||
|
void *value;
|
||||||
|
|
||||||
|
if (hash->hash.buckets) {
|
||||||
|
value = ngx_hash_find(&hash->hash, key, name, len);
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash->wc_head && hash->wc_head->hash.buckets) {
|
||||||
|
value = ngx_hash_find_wc_head(hash->wc_head, name, len);
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hash->wc_tail && hash->wc_tail->hash.buckets) {
|
||||||
|
value = ngx_hash_find_wc_tail(hash->wc_tail, name, len);
|
||||||
|
|
||||||
|
if (value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define NGX_HASH_ELT_SIZE(name) \
|
#define NGX_HASH_ELT_SIZE(name) \
|
||||||
(sizeof(void *) + ngx_align((name)->key.len + 1, sizeof(void *)))
|
(sizeof(void *) + ngx_align((name)->key.len + 1, sizeof(void *)))
|
||||||
|
|
||||||
|
@ -544,7 +642,14 @@ ngx_hash_keys_array_init(ngx_hash_keys_arrays_t *ha, ngx_uint_t type)
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_array_init(&ha->dns_wildcards, ha->temp_pool, asize,
|
if (ngx_array_init(&ha->dns_wc_head, ha->temp_pool, asize,
|
||||||
|
sizeof(ngx_hash_key_t))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_array_init(&ha->dns_wc_tail, ha->temp_pool, asize,
|
||||||
sizeof(ngx_hash_key_t))
|
sizeof(ngx_hash_key_t))
|
||||||
!= NGX_OK)
|
!= NGX_OK)
|
||||||
{
|
{
|
||||||
|
@ -556,9 +661,15 @@ ngx_hash_keys_array_init(ngx_hash_keys_arrays_t *ha, ngx_uint_t type)
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ha->dns_wildcards_hash = ngx_pcalloc(ha->temp_pool,
|
ha->dns_wc_head_hash = ngx_pcalloc(ha->temp_pool,
|
||||||
sizeof(ngx_array_t) * ha->hsize);
|
sizeof(ngx_array_t) * ha->hsize);
|
||||||
if (ha->dns_wildcards_hash == NULL) {
|
if (ha->dns_wc_head_hash == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ha->dns_wc_tail_hash = ngx_pcalloc(ha->temp_pool,
|
||||||
|
sizeof(ngx_array_t) * ha->hsize);
|
||||||
|
if (ha->dns_wc_tail_hash == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,37 +682,144 @@ ngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key, void *value,
|
||||||
ngx_uint_t flags)
|
ngx_uint_t flags)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
u_char *reverse;
|
u_char *p;
|
||||||
ngx_str_t *name;
|
ngx_str_t *name;
|
||||||
ngx_uint_t i, k, n, skip;
|
ngx_uint_t i, k, n, skip, last;
|
||||||
|
ngx_array_t *keys, *hwc;
|
||||||
ngx_hash_key_t *hk;
|
ngx_hash_key_t *hk;
|
||||||
|
|
||||||
if (!(flags & NGX_HASH_WILDCARD_KEY)) {
|
last = key->len;
|
||||||
|
|
||||||
/* exact hash */
|
if (flags & NGX_HASH_WILDCARD_KEY) {
|
||||||
|
|
||||||
k = 0;
|
/*
|
||||||
|
* supported wildcards:
|
||||||
|
* "*.example.com", ".example.com", and "www.example.*"
|
||||||
|
*/
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
|
||||||
for (i = 0; i < key->len; i++) {
|
for (i = 0; i < key->len; i++) {
|
||||||
if (!(flags & NGX_HASH_READONLY_KEY)) {
|
|
||||||
key->data[i] = ngx_tolower(key->data[i]);
|
if (key->data[i] == '*') {
|
||||||
|
if (++n > 1) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key->data[i] == '.' && key->data[i + 1] == '.') {
|
||||||
|
return NGX_DECLINED;
|
||||||
}
|
}
|
||||||
k = ngx_hash(k, key->data[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
k %= ha->hsize;
|
if (key->len > 1 && key->data[0] == '.') {
|
||||||
|
skip = 1;
|
||||||
|
goto wildcard;
|
||||||
|
}
|
||||||
|
|
||||||
/* check conflicts in exact hash */
|
if (key->len > 2) {
|
||||||
|
|
||||||
|
if (key->data[0] == '*' && key->data[1] == '.') {
|
||||||
|
skip = 2;
|
||||||
|
goto wildcard;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key->data[i - 2] == '.' && key->data[i - 1] == '*') {
|
||||||
|
skip = 0;
|
||||||
|
last -= 2;
|
||||||
|
goto wildcard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n) {
|
||||||
|
return NGX_DECLINED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* exact hash */
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < last; i++) {
|
||||||
|
if (!(flags & NGX_HASH_READONLY_KEY)) {
|
||||||
|
key->data[i] = ngx_tolower(key->data[i]);
|
||||||
|
}
|
||||||
|
k = ngx_hash(k, key->data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
k %= ha->hsize;
|
||||||
|
|
||||||
|
/* check conflicts in exact hash */
|
||||||
|
|
||||||
|
name = ha->keys_hash[k].elts;
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
for (i = 0; i < ha->keys_hash[k].nelts; i++) {
|
||||||
|
if (last != name[i].len) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_strncmp(key->data, name[i].data, last) == 0) {
|
||||||
|
return NGX_BUSY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4,
|
||||||
|
sizeof(ngx_str_t))
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
name = ngx_array_push(&ha->keys_hash[k]);
|
||||||
|
if (name == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*name = *key;
|
||||||
|
|
||||||
|
hk = ngx_array_push(&ha->keys);
|
||||||
|
if (hk == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
hk->key = *key;
|
||||||
|
hk->key_hash = ngx_hash_key(key->data, last);
|
||||||
|
hk->value = value;
|
||||||
|
|
||||||
|
return NGX_OK;
|
||||||
|
|
||||||
|
|
||||||
|
wildcard:
|
||||||
|
|
||||||
|
/* wildcard hash */
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
|
||||||
|
for (i = skip; i < last; i++) {
|
||||||
|
key->data[i] = ngx_tolower(key->data[i]);
|
||||||
|
k = ngx_hash(k, key->data[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
k %= ha->hsize;
|
||||||
|
|
||||||
|
if (skip == 1) {
|
||||||
|
|
||||||
|
/* check conflicts in exact hash for ".example.com" */
|
||||||
|
|
||||||
name = ha->keys_hash[k].elts;
|
name = ha->keys_hash[k].elts;
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
|
len = last - skip;
|
||||||
|
|
||||||
for (i = 0; i < ha->keys_hash[k].nelts; i++) {
|
for (i = 0; i < ha->keys_hash[k].nelts; i++) {
|
||||||
if (key->len != name[i].len) {
|
if (len != name[i].len) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ngx_strncmp(key->data, name[i].data, key->len) == 0) {
|
if (ngx_strncmp(&key->data[1], name[i].data, len) == 0) {
|
||||||
return NGX_BUSY;
|
return NGX_BUSY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -620,92 +838,36 @@ ngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key, void *value,
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
*name = *key;
|
name->len = last - 1;
|
||||||
|
name->data = ngx_palloc(ha->temp_pool, name->len);
|
||||||
hk = ngx_array_push(&ha->keys);
|
if (name->data == NULL) {
|
||||||
if (hk == NULL) {
|
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
hk->key = *key;
|
ngx_memcpy(name->data, &key->data[1], name->len);
|
||||||
hk->key_hash = ngx_hash_key(key->data, key->len);
|
}
|
||||||
hk->value = value;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
/* wildcard hash */
|
|
||||||
|
|
||||||
skip = (key->data[0] == '*') ? 2 : 1;
|
|
||||||
k = 0;
|
|
||||||
|
|
||||||
for (i = skip; i < key->len; i++) {
|
|
||||||
key->data[i] = ngx_tolower(key->data[i]);
|
|
||||||
k = ngx_hash(k, key->data[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
k %= ha->hsize;
|
|
||||||
|
|
||||||
if (skip == 1) {
|
|
||||||
|
|
||||||
/* check conflicts in exact hash for ".example.com" */
|
|
||||||
|
|
||||||
name = ha->keys_hash[k].elts;
|
|
||||||
|
|
||||||
if (name) {
|
|
||||||
len = key->len - skip;
|
|
||||||
|
|
||||||
for (i = 0; i < ha->keys_hash[k].nelts; i++) {
|
|
||||||
if (len != name[i].len) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ngx_strncmp(&key->data[1], name[i].data, len) == 0) {
|
|
||||||
return NGX_BUSY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4,
|
|
||||||
sizeof(ngx_str_t))
|
|
||||||
!= NGX_OK)
|
|
||||||
{
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
name = ngx_array_push(&ha->keys_hash[k]);
|
|
||||||
if (name == NULL) {
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
name->len = key->len - 1;
|
|
||||||
name->data = ngx_palloc(ha->temp_pool, name->len);
|
|
||||||
if (name->data == NULL) {
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_memcpy(name->data, &key->data[1], name->len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (skip) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* convert "*.example.com" to "com.example.\0"
|
* convert "*.example.com" to "com.example.\0"
|
||||||
* and ".example.com" to "com.example\0"
|
* and ".example.com" to "com.example\0"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
reverse = ngx_palloc(ha->temp_pool, key->len);
|
p = ngx_palloc(ha->temp_pool, last);
|
||||||
if (reverse == NULL) {
|
if (p == NULL) {
|
||||||
return NGX_ERROR;
|
return NGX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
n = 0;
|
n = 0;
|
||||||
|
|
||||||
for (i = key->len - 1; i; i--) {
|
for (i = last - 1; i; i--) {
|
||||||
if (key->data[i] == '.') {
|
if (key->data[i] == '.') {
|
||||||
ngx_memcpy(&reverse[n], &key->data[i + 1], len);
|
ngx_memcpy(&p[n], &key->data[i + 1], len);
|
||||||
n += len;
|
n += len;
|
||||||
reverse[n++] = '.';
|
p[n++] = '.';
|
||||||
len = 0;
|
len = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -714,63 +876,75 @@ ngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key, void *value,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len) {
|
if (len) {
|
||||||
ngx_memcpy(&reverse[n], &key->data[1], len);
|
ngx_memcpy(&p[n], &key->data[1], len);
|
||||||
n += len;
|
n += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
reverse[n] = '\0';
|
p[n] = '\0';
|
||||||
|
|
||||||
|
hwc = &ha->dns_wc_head;
|
||||||
|
keys = &ha->dns_wc_head_hash[k];
|
||||||
|
|
||||||
hk = ngx_array_push(&ha->dns_wildcards);
|
} else {
|
||||||
if (hk == NULL) {
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
hk->key.len = key->len - 1;
|
/* convert "www.example.*" to "www.example\0" */
|
||||||
hk->key.data = reverse;
|
|
||||||
hk->key_hash = 0;
|
|
||||||
hk->value = value;
|
|
||||||
|
|
||||||
|
p = key->data;
|
||||||
|
key->data[last] = '\0';
|
||||||
|
last++;
|
||||||
|
|
||||||
/* check conflicts in wildcard hash */
|
hwc = &ha->dns_wc_tail;
|
||||||
|
keys = &ha->dns_wc_tail_hash[k];
|
||||||
name = ha->dns_wildcards_hash[k].elts;
|
|
||||||
|
|
||||||
if (name) {
|
|
||||||
len = key->len - skip;
|
|
||||||
|
|
||||||
for (i = 0; i < ha->dns_wildcards_hash[k].nelts; i++) {
|
|
||||||
if (len != name[i].len) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ngx_strncmp(key->data + skip, name[i].data, len) == 0) {
|
|
||||||
return NGX_BUSY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (ngx_array_init(&ha->dns_wildcards_hash[k], ha->temp_pool, 4,
|
|
||||||
sizeof(ngx_str_t))
|
|
||||||
!= NGX_OK)
|
|
||||||
{
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
name = ngx_array_push(&ha->dns_wildcards_hash[k]);
|
|
||||||
if (name == NULL) {
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
name->len = key->len - skip;
|
|
||||||
name->data = ngx_palloc(ha->temp_pool, name->len);
|
|
||||||
if (name->data == NULL) {
|
|
||||||
return NGX_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ngx_memcpy(name->data, key->data + skip, name->len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
hk = ngx_array_push(hwc);
|
||||||
|
if (hk == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
hk->key.len = last - 1;
|
||||||
|
hk->key.data = p;
|
||||||
|
hk->key_hash = 0;
|
||||||
|
hk->value = value;
|
||||||
|
|
||||||
|
|
||||||
|
/* check conflicts in wildcard hash */
|
||||||
|
|
||||||
|
name = keys->elts;
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
len = last - skip;
|
||||||
|
|
||||||
|
for (i = 0; i < keys->nelts; i++) {
|
||||||
|
if (len != name[i].len) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ngx_strncmp(key->data + skip, name[i].data, len) == 0) {
|
||||||
|
return NGX_BUSY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (ngx_array_init(keys, ha->temp_pool, 4, sizeof(ngx_str_t)) != NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
name = ngx_array_push(keys);
|
||||||
|
if (name == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
name->len = last - skip;
|
||||||
|
name->data = ngx_palloc(ha->temp_pool, name->len);
|
||||||
|
if (name->data == NULL) {
|
||||||
|
return NGX_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngx_memcpy(name->data, key->data + skip, name->len);
|
||||||
|
|
||||||
return NGX_OK;
|
return NGX_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,13 @@ typedef struct {
|
||||||
typedef ngx_uint_t (*ngx_hash_key_pt) (u_char *data, size_t len);
|
typedef ngx_uint_t (*ngx_hash_key_pt) (u_char *data, size_t len);
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ngx_hash_t hash;
|
||||||
|
ngx_hash_wildcard_t *wc_head;
|
||||||
|
ngx_hash_wildcard_t *wc_tail;
|
||||||
|
} ngx_hash_combined_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_hash_t *hash;
|
ngx_hash_t *hash;
|
||||||
ngx_hash_key_pt key;
|
ngx_hash_key_pt key;
|
||||||
|
@ -73,8 +80,11 @@ typedef struct {
|
||||||
ngx_array_t keys;
|
ngx_array_t keys;
|
||||||
ngx_array_t *keys_hash;
|
ngx_array_t *keys_hash;
|
||||||
|
|
||||||
ngx_array_t dns_wildcards;
|
ngx_array_t dns_wc_head;
|
||||||
ngx_array_t *dns_wildcards_hash;
|
ngx_array_t *dns_wc_head_hash;
|
||||||
|
|
||||||
|
ngx_array_t dns_wc_tail;
|
||||||
|
ngx_array_t *dns_wc_tail_hash;
|
||||||
} ngx_hash_keys_arrays_t;
|
} ngx_hash_keys_arrays_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,8 +97,10 @@ typedef struct {
|
||||||
|
|
||||||
|
|
||||||
void *ngx_hash_find(ngx_hash_t *hash, ngx_uint_t key, u_char *name, size_t len);
|
void *ngx_hash_find(ngx_hash_t *hash, ngx_uint_t key, u_char *name, size_t len);
|
||||||
void *ngx_hash_find_wildcard(ngx_hash_wildcard_t *hwc, u_char *name,
|
void *ngx_hash_find_wc_head(ngx_hash_wildcard_t *hwc, u_char *name, size_t len);
|
||||||
size_t len);
|
void *ngx_hash_find_wc_tail(ngx_hash_wildcard_t *hwc, u_char *name, size_t len);
|
||||||
|
void *ngx_hash_find_combined(ngx_hash_combined_t *hash, ngx_uint_t key,
|
||||||
|
u_char *name, size_t len);
|
||||||
|
|
||||||
ngx_int_t ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
|
ngx_int_t ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
|
||||||
ngx_uint_t nelts);
|
ngx_uint_t nelts);
|
||||||
|
|
|
@ -26,8 +26,7 @@ typedef struct {
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_hash_t hash;
|
ngx_hash_combined_t hash;
|
||||||
ngx_hash_wildcard_t *dns_wildcards;
|
|
||||||
ngx_int_t index;
|
ngx_int_t index;
|
||||||
ngx_http_variable_value_t *default_value;
|
ngx_http_variable_value_t *default_value;
|
||||||
ngx_uint_t hostnames; /* unsigned hostnames:1 */
|
ngx_uint_t hostnames; /* unsigned hostnames:1 */
|
||||||
|
@ -142,28 +141,13 @@ ngx_http_map_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
||||||
key = ngx_hash(key, name[i]);
|
key = ngx_hash(key, name[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
value = NULL;
|
value = ngx_hash_find_combined(&map->hash, key, name, len);
|
||||||
|
|
||||||
if (map->hash.buckets) {
|
|
||||||
value = ngx_hash_find(&map->hash, key, name, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
*v = *value;
|
*v = *value;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (map->dns_wildcards && map->dns_wildcards->hash.buckets) {
|
*v = *map->default_value;
|
||||||
value = ngx_hash_find_wildcard(map->dns_wildcards, name, len);
|
|
||||||
if (value) {
|
|
||||||
*v = *value;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
*v = *map->default_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
*v = *map->default_value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||||
|
@ -282,6 +266,9 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
map->default_value = ctx.default_value ? ctx.default_value:
|
||||||
|
&ngx_http_variable_null_value;
|
||||||
|
|
||||||
hash.key = ngx_hash_key_lc;
|
hash.key = ngx_hash_key_lc;
|
||||||
hash.max_size = mcf->hash_max_size;
|
hash.max_size = mcf->hash_max_size;
|
||||||
hash.bucket_size = mcf->hash_bucket_size;
|
hash.bucket_size = mcf->hash_bucket_size;
|
||||||
|
@ -289,7 +276,7 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
hash.pool = cf->pool;
|
hash.pool = cf->pool;
|
||||||
|
|
||||||
if (ctx.keys.keys.nelts) {
|
if (ctx.keys.keys.nelts) {
|
||||||
hash.hash = &map->hash;
|
hash.hash = &map->hash.hash;
|
||||||
hash.temp_pool = NULL;
|
hash.temp_pool = NULL;
|
||||||
|
|
||||||
if (ngx_hash_init(&hash, ctx.keys.keys.elts, ctx.keys.keys.nelts)
|
if (ngx_hash_init(&hash, ctx.keys.keys.elts, ctx.keys.keys.nelts)
|
||||||
|
@ -300,27 +287,44 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
map->default_value = ctx.default_value ? ctx.default_value:
|
if (ctx.keys.dns_wc_head.nelts) {
|
||||||
&ngx_http_variable_null_value;
|
|
||||||
|
|
||||||
if (ctx.keys.dns_wildcards.nelts) {
|
ngx_qsort(ctx.keys.dns_wc_head.elts,
|
||||||
|
(size_t) ctx.keys.dns_wc_head.nelts,
|
||||||
ngx_qsort(ctx.keys.dns_wildcards.elts,
|
|
||||||
(size_t) ctx.keys.dns_wildcards.nelts,
|
|
||||||
sizeof(ngx_hash_key_t), ngx_http_map_cmp_dns_wildcards);
|
sizeof(ngx_hash_key_t), ngx_http_map_cmp_dns_wildcards);
|
||||||
|
|
||||||
hash.hash = NULL;
|
hash.hash = NULL;
|
||||||
hash.temp_pool = pool;
|
hash.temp_pool = pool;
|
||||||
|
|
||||||
if (ngx_hash_wildcard_init(&hash, ctx.keys.dns_wildcards.elts,
|
if (ngx_hash_wildcard_init(&hash, ctx.keys.dns_wc_head.elts,
|
||||||
ctx.keys.dns_wildcards.nelts)
|
ctx.keys.dns_wc_head.nelts)
|
||||||
!= NGX_OK)
|
!= NGX_OK)
|
||||||
{
|
{
|
||||||
ngx_destroy_pool(pool);
|
ngx_destroy_pool(pool);
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
map->dns_wildcards = (ngx_hash_wildcard_t *) hash.hash;
|
map->hash.wc_head = (ngx_hash_wildcard_t *) hash.hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx.keys.dns_wc_tail.nelts) {
|
||||||
|
|
||||||
|
ngx_qsort(ctx.keys.dns_wc_tail.elts,
|
||||||
|
(size_t) ctx.keys.dns_wc_tail.nelts,
|
||||||
|
sizeof(ngx_hash_key_t), ngx_http_map_cmp_dns_wildcards);
|
||||||
|
|
||||||
|
hash.hash = NULL;
|
||||||
|
hash.temp_pool = pool;
|
||||||
|
|
||||||
|
if (ngx_hash_wildcard_init(&hash, ctx.keys.dns_wc_tail.elts,
|
||||||
|
ctx.keys.dns_wc_tail.nelts)
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
ngx_destroy_pool(pool);
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
map->hash.wc_tail = (ngx_hash_wildcard_t *) hash.hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_destroy_pool(pool);
|
ngx_destroy_pool(pool);
|
||||||
|
@ -344,10 +348,9 @@ ngx_http_map_cmp_dns_wildcards(const void *one, const void *two)
|
||||||
static char *
|
static char *
|
||||||
ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
|
ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
|
||||||
{
|
{
|
||||||
u_char ch;
|
|
||||||
ngx_int_t rc;
|
ngx_int_t rc;
|
||||||
ngx_str_t *value, file;
|
ngx_str_t *value, file;
|
||||||
ngx_uint_t i, key, flags;
|
ngx_uint_t i, key;
|
||||||
ngx_http_map_conf_ctx_t *ctx;
|
ngx_http_map_conf_ctx_t *ctx;
|
||||||
ngx_http_variable_value_t *var, **vp;
|
ngx_http_variable_value_t *var, **vp;
|
||||||
|
|
||||||
|
@ -439,50 +442,36 @@ ngx_http_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
|
||||||
|
|
||||||
found:
|
found:
|
||||||
|
|
||||||
ch = value[0].data[0];
|
if (ngx_strcmp(value[0].data, "default") == 0) {
|
||||||
|
|
||||||
if ((ch != '*' && ch != '.') || ctx->hostnames == 0) {
|
if (ctx->default_value) {
|
||||||
|
|
||||||
if (ngx_strcmp(value[0].data, "default") == 0) {
|
|
||||||
|
|
||||||
if (ctx->default_value) {
|
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
|
||||||
"duplicate default map parameter");
|
|
||||||
return NGX_CONF_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx->default_value = var;
|
|
||||||
|
|
||||||
return NGX_CONF_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value[0].len && ch == '!') {
|
|
||||||
value[0].len--;
|
|
||||||
value[0].data++;
|
|
||||||
}
|
|
||||||
|
|
||||||
flags = 0;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if ((ch == '*' && (value[0].len < 3 || value[0].data[1] != '.'))
|
|
||||||
|| (ch == '.' && value[0].len < 2))
|
|
||||||
{
|
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"invalid DNS wildcard \"%V\"", &value[0]);
|
"duplicate default map parameter");
|
||||||
|
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
flags = NGX_HASH_WILDCARD_KEY;
|
ctx->default_value = var;
|
||||||
|
|
||||||
|
return NGX_CONF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ngx_hash_add_key(&ctx->keys, &value[0], var, flags);
|
if (value[0].len && value[0].data[0] == '!') {
|
||||||
|
value[0].len--;
|
||||||
|
value[0].data++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = ngx_hash_add_key(&ctx->keys, &value[0], var,
|
||||||
|
(ctx->hostnames) ? NGX_HASH_WILDCARD_KEY : 0);
|
||||||
|
|
||||||
if (rc == NGX_OK) {
|
if (rc == NGX_OK) {
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_DECLINED) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"invalid hostname or wildcard \"%V\"", &value[0]);
|
||||||
|
}
|
||||||
|
|
||||||
if (rc == NGX_BUSY) {
|
if (rc == NGX_BUSY) {
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"conflicting parameter \"%V\"", &value[0]);
|
"conflicting parameter \"%V\"", &value[0]);
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
#define NGX_HTTP_REFERER_NO_URI_PART ((void *) 4)
|
#define NGX_HTTP_REFERER_NO_URI_PART ((void *) 4)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_hash_t hash;
|
ngx_hash_combined_t hash;
|
||||||
ngx_hash_wildcard_t *dns_wildcards;
|
|
||||||
|
|
||||||
ngx_flag_t no_referer;
|
ngx_flag_t no_referer;
|
||||||
ngx_flag_t blocked_referer;
|
ngx_flag_t blocked_referer;
|
||||||
|
@ -90,7 +89,10 @@ ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
||||||
|
|
||||||
rlcf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module);
|
rlcf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module);
|
||||||
|
|
||||||
if (rlcf->hash.buckets == NULL && rlcf->dns_wildcards == NULL) {
|
if (rlcf->hash.hash.buckets == NULL
|
||||||
|
&& rlcf->hash.wc_head == NULL
|
||||||
|
&& rlcf->hash.wc_tail == NULL)
|
||||||
|
{
|
||||||
goto valid;
|
goto valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,18 +137,10 @@ ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
|
||||||
|
|
||||||
len = p - ref;
|
len = p - ref;
|
||||||
|
|
||||||
if (rlcf->hash.buckets) {
|
uri = ngx_hash_find_combined(&rlcf->hash, key, buf, len);
|
||||||
uri = ngx_hash_find(&rlcf->hash, key, buf, len);
|
|
||||||
if (uri) {
|
|
||||||
goto uri;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rlcf->dns_wildcards) {
|
if (uri) {
|
||||||
uri = ngx_hash_find_wildcard(rlcf->dns_wildcards, buf, len);
|
goto uri;
|
||||||
if (uri) {
|
|
||||||
goto uri;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
invalid:
|
invalid:
|
||||||
|
@ -208,7 +202,6 @@ ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||||
|
|
||||||
if (conf->keys == NULL) {
|
if (conf->keys == NULL) {
|
||||||
conf->hash = prev->hash;
|
conf->hash = prev->hash;
|
||||||
conf->dns_wildcards = prev->dns_wildcards;
|
|
||||||
|
|
||||||
ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0);
|
ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0);
|
||||||
ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0);
|
ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0);
|
||||||
|
@ -217,7 +210,9 @@ ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((conf->no_referer == 1 || conf->blocked_referer == 1)
|
if ((conf->no_referer == 1 || conf->blocked_referer == 1)
|
||||||
&& conf->keys->keys.nelts == 0 && conf->keys->dns_wildcards.nelts == 0)
|
&& conf->keys->keys.nelts == 0
|
||||||
|
&& conf->keys->dns_wc_head.nelts == 0
|
||||||
|
&& conf->keys->dns_wc_tail.nelts == 0)
|
||||||
{
|
{
|
||||||
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||||
"the \"none\" or \"blocked\" referers are specified "
|
"the \"none\" or \"blocked\" referers are specified "
|
||||||
|
@ -233,7 +228,7 @@ ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||||
hash.pool = cf->pool;
|
hash.pool = cf->pool;
|
||||||
|
|
||||||
if (conf->keys->keys.nelts) {
|
if (conf->keys->keys.nelts) {
|
||||||
hash.hash = &conf->hash;
|
hash.hash = &conf->hash.hash;
|
||||||
hash.temp_pool = NULL;
|
hash.temp_pool = NULL;
|
||||||
|
|
||||||
if (ngx_hash_init(&hash, conf->keys->keys.elts, conf->keys->keys.nelts)
|
if (ngx_hash_init(&hash, conf->keys->keys.elts, conf->keys->keys.nelts)
|
||||||
|
@ -243,24 +238,44 @@ ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf->keys->dns_wildcards.nelts) {
|
if (conf->keys->dns_wc_head.nelts) {
|
||||||
|
|
||||||
ngx_qsort(conf->keys->dns_wildcards.elts,
|
ngx_qsort(conf->keys->dns_wc_head.elts,
|
||||||
(size_t) conf->keys->dns_wildcards.nelts,
|
(size_t) conf->keys->dns_wc_head.nelts,
|
||||||
sizeof(ngx_hash_key_t),
|
sizeof(ngx_hash_key_t),
|
||||||
ngx_http_cmp_referer_wildcards);
|
ngx_http_cmp_referer_wildcards);
|
||||||
|
|
||||||
hash.hash = NULL;
|
hash.hash = NULL;
|
||||||
hash.temp_pool = cf->temp_pool;
|
hash.temp_pool = cf->temp_pool;
|
||||||
|
|
||||||
if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wildcards.elts,
|
if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wc_head.elts,
|
||||||
conf->keys->dns_wildcards.nelts)
|
conf->keys->dns_wc_head.nelts)
|
||||||
!= NGX_OK)
|
!= NGX_OK)
|
||||||
{
|
{
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
conf->dns_wildcards = (ngx_hash_wildcard_t *) hash.hash;
|
conf->hash.wc_head = (ngx_hash_wildcard_t *) hash.hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conf->keys->dns_wc_tail.nelts) {
|
||||||
|
|
||||||
|
ngx_qsort(conf->keys->dns_wc_tail.elts,
|
||||||
|
(size_t) conf->keys->dns_wc_tail.nelts,
|
||||||
|
sizeof(ngx_hash_key_t),
|
||||||
|
ngx_http_cmp_referer_wildcards);
|
||||||
|
|
||||||
|
hash.hash = NULL;
|
||||||
|
hash.temp_pool = cf->temp_pool;
|
||||||
|
|
||||||
|
if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wc_tail.elts,
|
||||||
|
conf->keys->dns_wc_tail.nelts)
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
conf->hash.wc_tail = (ngx_hash_wildcard_t *) hash.hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conf->no_referer == NGX_CONF_UNSET) {
|
if (conf->no_referer == NGX_CONF_UNSET) {
|
||||||
|
@ -373,23 +388,8 @@ static char *
|
||||||
ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys,
|
ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys,
|
||||||
ngx_str_t *value, ngx_str_t *uri)
|
ngx_str_t *value, ngx_str_t *uri)
|
||||||
{
|
{
|
||||||
u_char ch;
|
ngx_int_t rc;
|
||||||
ngx_int_t rc;
|
ngx_str_t *u;
|
||||||
ngx_str_t *u;
|
|
||||||
ngx_uint_t flags;
|
|
||||||
|
|
||||||
ch = value->data[0];
|
|
||||||
|
|
||||||
if ((ch == '*' && (value->len < 3 || value->data[1] != '.'))
|
|
||||||
|| (ch == '.' && value->len < 2))
|
|
||||||
{
|
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
|
||||||
"invalid DNS wildcard \"%V\"", value);
|
|
||||||
|
|
||||||
return NGX_CONF_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
flags = (ch == '*' || ch == '.') ? NGX_HASH_WILDCARD_KEY : 0;
|
|
||||||
|
|
||||||
if (uri->len == 0) {
|
if (uri->len == 0) {
|
||||||
u = NGX_HTTP_REFERER_NO_URI_PART;
|
u = NGX_HTTP_REFERER_NO_URI_PART;
|
||||||
|
@ -403,12 +403,17 @@ ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys,
|
||||||
*u = *uri;
|
*u = *uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = ngx_hash_add_key(keys, value, u, flags);
|
rc = ngx_hash_add_key(keys, value, u, NGX_HASH_WILDCARD_KEY);
|
||||||
|
|
||||||
if (rc == NGX_OK) {
|
if (rc == NGX_OK) {
|
||||||
return NGX_CONF_OK;
|
return NGX_CONF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_DECLINED) {
|
||||||
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
|
"invalid hostname or wildcard \"%V\"", value);
|
||||||
|
}
|
||||||
|
|
||||||
if (rc == NGX_BUSY) {
|
if (rc == NGX_BUSY) {
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"conflicting parameter \"%V\"", value);
|
"conflicting parameter \"%V\"", value);
|
||||||
|
|
|
@ -73,7 +73,6 @@ static char *
|
||||||
ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
{
|
{
|
||||||
char *rv;
|
char *rv;
|
||||||
u_char ch;
|
|
||||||
ngx_int_t rc, j;
|
ngx_int_t rc, j;
|
||||||
ngx_uint_t mi, m, s, l, p, a, i, n;
|
ngx_uint_t mi, m, s, l, p, a, i, n;
|
||||||
ngx_uint_t find_config_index, use_rewrite, use_access;
|
ngx_uint_t find_config_index, use_rewrite, use_access;
|
||||||
|
@ -648,36 +647,9 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
}
|
}
|
||||||
|
|
||||||
name = in_addr[a].names.elts;
|
name = in_addr[a].names.elts;
|
||||||
for (s = 0; s < in_addr[a].names.nelts; s++) {
|
|
||||||
|
|
||||||
ch = name[s].name.data[0];
|
|
||||||
|
|
||||||
if (ch == '*' || ch == '.') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
|
|
||||||
0);
|
|
||||||
|
|
||||||
if (rc == NGX_ERROR) {
|
|
||||||
return NGX_CONF_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc == NGX_BUSY) {
|
|
||||||
ngx_log_error(NGX_LOG_WARN, cf->log, 0,
|
|
||||||
"conflicting server name \"%V\" on %s, ignored",
|
|
||||||
&name[s].name, in_addr[a].listen_conf->addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (s = 0; s < in_addr[a].names.nelts; s++) {
|
for (s = 0; s < in_addr[a].names.nelts; s++) {
|
||||||
|
|
||||||
ch = name[s].name.data[0];
|
|
||||||
|
|
||||||
if (ch != '*' && ch != '.') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
|
rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
|
||||||
NGX_HASH_WILDCARD_KEY);
|
NGX_HASH_WILDCARD_KEY);
|
||||||
|
|
||||||
|
@ -685,6 +657,13 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc == NGX_DECLINED) {
|
||||||
|
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
|
||||||
|
"invalid server name or wildcard \"%V\" on %s",
|
||||||
|
&name[s].name, in_addr[a].listen_conf->addr);
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (rc == NGX_BUSY) {
|
if (rc == NGX_BUSY) {
|
||||||
ngx_log_error(NGX_LOG_WARN, cf->log, 0,
|
ngx_log_error(NGX_LOG_WARN, cf->log, 0,
|
||||||
"conflicting server name \"%V\" on %s, ignored",
|
"conflicting server name \"%V\" on %s, ignored",
|
||||||
|
@ -709,25 +688,46 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ha.dns_wildcards.nelts) {
|
if (ha.dns_wc_head.nelts) {
|
||||||
|
|
||||||
ngx_qsort(ha.dns_wildcards.elts,
|
ngx_qsort(ha.dns_wc_head.elts,
|
||||||
(size_t) ha.dns_wildcards.nelts,
|
(size_t) ha.dns_wc_head.nelts,
|
||||||
sizeof(ngx_hash_key_t),
|
sizeof(ngx_hash_key_t),
|
||||||
ngx_http_cmp_dns_wildcards);
|
ngx_http_cmp_dns_wildcards);
|
||||||
|
|
||||||
hash.hash = NULL;
|
hash.hash = NULL;
|
||||||
hash.temp_pool = ha.temp_pool;
|
hash.temp_pool = ha.temp_pool;
|
||||||
|
|
||||||
if (ngx_hash_wildcard_init(&hash, ha.dns_wildcards.elts,
|
if (ngx_hash_wildcard_init(&hash, ha.dns_wc_head.elts,
|
||||||
ha.dns_wildcards.nelts)
|
ha.dns_wc_head.nelts)
|
||||||
!= NGX_OK)
|
!= NGX_OK)
|
||||||
{
|
{
|
||||||
ngx_destroy_pool(ha.temp_pool);
|
ngx_destroy_pool(ha.temp_pool);
|
||||||
return NGX_CONF_ERROR;
|
return NGX_CONF_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
in_addr[a].dns_wildcards = (ngx_hash_wildcard_t *) hash.hash;
|
in_addr[a].wc_head = (ngx_hash_wildcard_t *) hash.hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ha.dns_wc_tail.nelts) {
|
||||||
|
|
||||||
|
ngx_qsort(ha.dns_wc_tail.elts,
|
||||||
|
(size_t) ha.dns_wc_tail.nelts,
|
||||||
|
sizeof(ngx_hash_key_t),
|
||||||
|
ngx_http_cmp_dns_wildcards);
|
||||||
|
|
||||||
|
hash.hash = NULL;
|
||||||
|
hash.temp_pool = ha.temp_pool;
|
||||||
|
|
||||||
|
if (ngx_hash_wildcard_init(&hash, ha.dns_wc_tail.elts,
|
||||||
|
ha.dns_wc_tail.nelts)
|
||||||
|
!= NGX_OK)
|
||||||
|
{
|
||||||
|
ngx_destroy_pool(ha.temp_pool);
|
||||||
|
return NGX_CONF_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
in_addr[a].wc_tail = (ngx_hash_wildcard_t *) hash.hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngx_destroy_pool(ha.temp_pool);
|
ngx_destroy_pool(ha.temp_pool);
|
||||||
|
@ -848,8 +848,10 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
hip->addrs[i].core_srv_conf = in_addr[i].core_srv_conf;
|
hip->addrs[i].core_srv_conf = in_addr[i].core_srv_conf;
|
||||||
|
|
||||||
if (in_addr[i].hash.buckets == NULL
|
if (in_addr[i].hash.buckets == NULL
|
||||||
&& (in_addr[i].dns_wildcards == NULL
|
&& (in_addr[i].wc_head == NULL
|
||||||
|| in_addr[i].dns_wildcards->hash.buckets == NULL))
|
|| in_addr[i].wc_head->hash.buckets == NULL)
|
||||||
|
&& (in_addr[i].wc_head == NULL
|
||||||
|
|| in_addr[i].wc_head->hash.buckets == NULL))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -861,7 +863,8 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
hip->addrs[i].virtual_names = vn;
|
hip->addrs[i].virtual_names = vn;
|
||||||
|
|
||||||
vn->hash = in_addr[i].hash;
|
vn->hash = in_addr[i].hash;
|
||||||
vn->dns_wildcards = in_addr[i].dns_wildcards;
|
vn->wc_head = in_addr[i].wc_head;
|
||||||
|
vn->wc_tail = in_addr[i].wc_tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (done) {
|
if (done) {
|
||||||
|
@ -934,7 +937,8 @@ ngx_http_add_address(ngx_conf_t *cf, ngx_http_conf_in_port_t *in_port,
|
||||||
in_addr->addr = lscf->addr;
|
in_addr->addr = lscf->addr;
|
||||||
in_addr->hash.buckets = NULL;
|
in_addr->hash.buckets = NULL;
|
||||||
in_addr->hash.size = 0;
|
in_addr->hash.size = 0;
|
||||||
in_addr->dns_wildcards = NULL;
|
in_addr->wc_head = NULL;
|
||||||
|
in_addr->wc_tail = NULL;
|
||||||
in_addr->names.elts = NULL;
|
in_addr->names.elts = NULL;
|
||||||
in_addr->core_srv_conf = cscf;
|
in_addr->core_srv_conf = cscf;
|
||||||
in_addr->default_server = lscf->conf.default_server;
|
in_addr->default_server = lscf->conf.default_server;
|
||||||
|
|
|
@ -2618,7 +2618,7 @@ ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
|
||||||
ch = value[1].data[0];
|
ch = value[1].data[0];
|
||||||
|
|
||||||
if (cscf->server_name.data == NULL && value[1].len) {
|
if (cscf->server_name.data == NULL && value[1].len) {
|
||||||
if (ch == '*') {
|
if (ngx_strchr(value[1].data, '*')) {
|
||||||
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"first server name \"%V\" must not be wildcard",
|
"first server name \"%V\" must not be wildcard",
|
||||||
&value[1]);
|
&value[1]);
|
||||||
|
|
|
@ -173,7 +173,8 @@ typedef struct {
|
||||||
in_addr_t addr;
|
in_addr_t addr;
|
||||||
|
|
||||||
ngx_hash_t hash;
|
ngx_hash_t hash;
|
||||||
ngx_hash_wildcard_t *dns_wildcards;
|
ngx_hash_wildcard_t *wc_head;
|
||||||
|
ngx_hash_wildcard_t *wc_tail;
|
||||||
|
|
||||||
ngx_array_t names; /* array of ngx_http_server_name_t */
|
ngx_array_t names; /* array of ngx_http_server_name_t */
|
||||||
|
|
||||||
|
|
|
@ -1459,19 +1459,10 @@ ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len,
|
||||||
|
|
||||||
vn = r->virtual_names;
|
vn = r->virtual_names;
|
||||||
|
|
||||||
if (vn->hash.buckets) {
|
cscf = ngx_hash_find_combined(vn, hash, host, len);
|
||||||
cscf = ngx_hash_find(&vn->hash, hash, host, len);
|
|
||||||
if (cscf) {
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vn->dns_wildcards && vn->dns_wildcards->hash.buckets) {
|
if (cscf) {
|
||||||
cscf = ngx_hash_find_wildcard(vn->dns_wildcards, host, len);
|
goto found;
|
||||||
|
|
||||||
if (cscf) {
|
|
||||||
goto found;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
|
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
|
||||||
|
|
|
@ -275,10 +275,7 @@ typedef struct {
|
||||||
} ngx_http_connection_t;
|
} ngx_http_connection_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef ngx_hash_combined_t ngx_http_virtual_names_t;
|
||||||
ngx_hash_t hash;
|
|
||||||
ngx_hash_wildcard_t *dns_wildcards;
|
|
||||||
} ngx_http_virtual_names_t;
|
|
||||||
|
|
||||||
|
|
||||||
typedef void (*ngx_http_cleanup_pt)(void *data);
|
typedef void (*ngx_http_cleanup_pt)(void *data);
|
||||||
|
|
Loading…
Reference in a new issue