mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-12-14 08:50:53 +08:00
270 lines
7.3 KiB
C
270 lines
7.3 KiB
C
|
#include "lib_acl.h"
|
|||
|
|
|||
|
#ifdef ACL_BCB_COMPILER
|
|||
|
#pragma hdrstop
|
|||
|
#endif
|
|||
|
|
|||
|
#include "dns.h"
|
|||
|
#include "dns_lookup.h"
|
|||
|
|
|||
|
#define STRNCPY ACL_SAFE_STRNCPY
|
|||
|
|
|||
|
/*----------------------------------------------------------------------------*/
|
|||
|
|
|||
|
static void inner_nslookup_error(CLIENT_ENTRY *entry)
|
|||
|
{
|
|||
|
if (entry->client == NULL)
|
|||
|
acl_msg_fatal("%s(%d): client null",
|
|||
|
__FILE__, __LINE__);
|
|||
|
|
|||
|
if (entry->dns_errmsg) {
|
|||
|
acl_aio_refer(entry->client);
|
|||
|
acl_aio_writen(entry->client, entry->dns_errmsg,
|
|||
|
(int) strlen(entry->dns_errmsg));
|
|||
|
/* <20>ָ<EFBFBD>referֵ */
|
|||
|
acl_aio_unrefer(entry->client);
|
|||
|
}
|
|||
|
|
|||
|
entry->nslookup_notify_fn(entry, NSLOOKUP_ERR);
|
|||
|
}
|
|||
|
|
|||
|
static void inner_nslookup_ok(CLIENT_ENTRY *entry, ACL_DNS_DB *dns_db)
|
|||
|
{
|
|||
|
ACL_ITER iter;
|
|||
|
int i = 0;
|
|||
|
|
|||
|
entry->ip_idx = 0;
|
|||
|
entry->dns_ctx.ip_cnt = 0;
|
|||
|
acl_foreach(iter, dns_db) {
|
|||
|
const ACL_HOST_INFO *info;
|
|||
|
|
|||
|
info = (const ACL_HOST_INFO*) iter.data;
|
|||
|
ACL_SAFE_STRNCPY(entry->dns_ctx.ip[i], info->ip,
|
|||
|
sizeof(entry->dns_ctx.ip[i]));
|
|||
|
entry->dns_ctx.port[i++] = info->hport;
|
|||
|
entry->dns_ctx.ip_cnt++;
|
|||
|
if (entry->dns_ctx.ip_cnt >= DNS_IP_MAX)
|
|||
|
break;
|
|||
|
}
|
|||
|
entry->nslookup_notify_fn(entry, NSLOOKUP_OK);
|
|||
|
}
|
|||
|
|
|||
|
static void inner_nslookup_complete(ACL_DNS_DB *dns_db, void *ctx,
|
|||
|
int errnum acl_unused)
|
|||
|
{
|
|||
|
CLIENT_ENTRY *entry = (CLIENT_ENTRY*) ctx;
|
|||
|
|
|||
|
if (dns_db != NULL)
|
|||
|
inner_nslookup_ok(entry, dns_db);
|
|||
|
else
|
|||
|
inner_nslookup_error(entry);
|
|||
|
}
|
|||
|
|
|||
|
/* <20><>ѯDNS<4E><53>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD>鷢<EFBFBD>͵ķ<CDB5>ʽ */
|
|||
|
static void inner_nslookup(SERVICE *service, CLIENT_ENTRY *entry,
|
|||
|
const char *domain, int port)
|
|||
|
{
|
|||
|
char *ptr;
|
|||
|
|
|||
|
STRNCPY(entry->dns_ctx.domain_key, domain,
|
|||
|
sizeof(entry->dns_ctx.domain_key));
|
|||
|
acl_lowercase(entry->dns_ctx.domain_key);
|
|||
|
ptr = strchr(entry->dns_ctx.domain_key, ':');
|
|||
|
if (ptr)
|
|||
|
*ptr = 0;
|
|||
|
entry->server_port = port;
|
|||
|
if (entry->server_port <= 0)
|
|||
|
entry->server_port = 80;
|
|||
|
|
|||
|
STRNCPY(entry->domain_key, entry->dns_ctx.domain_key,
|
|||
|
sizeof(entry->domain_key));
|
|||
|
acl_dns_lookup(service->dns_handle, entry->domain_key,
|
|||
|
inner_nslookup_complete, entry);
|
|||
|
}
|
|||
|
|
|||
|
/*----------------------------------------------------------------------------*/
|
|||
|
|
|||
|
/* DNS<4E><53>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD>Ļص<C4BB><D8B5><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
static void thrpool_nslookup_complete(const DNS_CTX *dns_ctx)
|
|||
|
{
|
|||
|
const char *myname = "thrpool_nslookup_complte";
|
|||
|
SERVICE *service = (SERVICE *) dns_ctx->context;
|
|||
|
DNS_RING *list;
|
|||
|
ACL_RING *ring_ptr;
|
|||
|
CLIENT_ENTRY *entry;
|
|||
|
time_t inter, now;
|
|||
|
|
|||
|
list = (DNS_RING *) acl_htable_find(service->dns_table,
|
|||
|
dns_ctx->domain_key);
|
|||
|
if (list == NULL) {
|
|||
|
acl_msg_warn(NULL, "%s: domain(%s) not found maybe handled",
|
|||
|
myname, dns_ctx->domain_key);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
time(&now);
|
|||
|
inter = now - dns_ctx->begin;
|
|||
|
|
|||
|
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯʱ<D1AF><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϣ */
|
|||
|
if (inter >= 5)
|
|||
|
acl_msg_warn("%s(%d): dns search time=%d, domain(%s)",
|
|||
|
myname, __LINE__, time(NULL) - dns_ctx->begin,
|
|||
|
dns_ctx->domain_key);
|
|||
|
|
|||
|
while (1) {
|
|||
|
ring_ptr = acl_ring_pop_head(&list->ring);
|
|||
|
if (ring_ptr == NULL)
|
|||
|
break;
|
|||
|
|
|||
|
list->nrefer--;
|
|||
|
|
|||
|
entry = ACL_RING_TO_APPL(ring_ptr, CLIENT_ENTRY, dns_entry);
|
|||
|
|
|||
|
entry->tm.dns_lookup = now - entry->tm.stamp;
|
|||
|
entry->tm.stamp = now;
|
|||
|
|
|||
|
if (dns_ctx->ip_cnt <= 0) {
|
|||
|
acl_msg_error("%s(%d): dns not found domain(%s)",
|
|||
|
myname, __LINE__, dns_ctx->domain_key);
|
|||
|
if (entry->client == NULL)
|
|||
|
acl_msg_fatal("%s(%d): client null",
|
|||
|
__FILE__, __LINE__);
|
|||
|
|
|||
|
if (entry->dns_errmsg) {
|
|||
|
/* XXX: <20><>Ϊ<EFBFBD>˴<EFBFBD><CBB4><EFBFBD><EFBFBD>ܻ<EFBFBD><DCBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ر<EFBFBD> client <20><><EFBFBD>ĵط<C4B5>:
|
|||
|
* acl_aio_writen <EFBFBD><EFBFBD> forward_complete<EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD>ֹ<EFBFBD>ظ<EFBFBD>
|
|||
|
* <EFBFBD>ر<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʷǷ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ * <EFBFBD>ڵ<EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ܹر<EFBFBD>
|
|||
|
* <EFBFBD>ĺ<EFBFBD><EFBFBD><EFBFBD>(acl_aio_writen)<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> client <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڸú<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>غ<EFBFBD><EFBFBD>ٻָ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
|
|||
|
*/
|
|||
|
|
|||
|
acl_aio_refer(entry->client);
|
|||
|
acl_aio_writen(entry->client, entry->dns_errmsg,
|
|||
|
(int) strlen(entry->dns_errmsg));
|
|||
|
/* <20>ָ<EFBFBD>referֵ */
|
|||
|
acl_aio_unrefer(entry->client);
|
|||
|
}
|
|||
|
|
|||
|
entry->nslookup_notify_fn(entry, NSLOOKUP_ERR);
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (acl_do_debug(20, 2)) {
|
|||
|
int i;
|
|||
|
|
|||
|
for (i = 0; i < dns_ctx->ip_cnt; i++)
|
|||
|
acl_msg_info("%s(%d): domain(%s), ip%d(%s)",
|
|||
|
myname, __LINE__, dns_ctx->domain_key,
|
|||
|
i, dns_ctx->ip[i]);
|
|||
|
}
|
|||
|
|
|||
|
/* <20><><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD>DNS<4E><53><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
memcpy(&entry->dns_ctx, dns_ctx, sizeof(entry->dns_ctx));
|
|||
|
|
|||
|
/* <20><><EFBFBD><EFBFBD>ע<EFBFBD>Ͳ<EFBFBD><CDB2>ֱ<EFBFBD><D6B1><EFBFBD><F2BFAAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Բ<EFBFBD><D4B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Թ<EFBFBD><D4B9><EFBFBD>:)-- zsx, 2008.2.28
|
|||
|
* strcpy(proxy_entry->dns_ctx.ip[1], proxy_entry->dns_ctx.ip[0]);
|
|||
|
* strcpy(proxy_entry->dns_ctx.ip[0], "127.0.0.1");
|
|||
|
* if (proxy_entry->dns_ctx.ip_cnt < 2)
|
|||
|
* proxy_entry->dns_ctx.ip_cnt = 2;
|
|||
|
*/
|
|||
|
entry->ip_idx = 0;
|
|||
|
entry->nslookup_notify_fn(entry, NSLOOKUP_OK);
|
|||
|
}
|
|||
|
|
|||
|
acl_htable_delete(service->dns_table, dns_ctx->domain_key, NULL);
|
|||
|
if (list->nrefer <= 0)
|
|||
|
acl_myfree(list);
|
|||
|
else
|
|||
|
acl_msg_fatal("%s(%d): list's nrefer=%d",
|
|||
|
myname, __LINE__, list->nrefer);
|
|||
|
}
|
|||
|
|
|||
|
/* <20><>ѯDNS<4E><53>Ϣ<EFBFBD><CFA2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD>ķ<EFBFBD>ʽ */
|
|||
|
static void thrpool_nslookup(SERVICE *service, CLIENT_ENTRY *entry,
|
|||
|
const char *domain, int port)
|
|||
|
{
|
|||
|
const char *myname = "thrpool_nslookup";
|
|||
|
DNS_CTX dns_ctx;
|
|||
|
DNS_RING *list;
|
|||
|
char *ptr;
|
|||
|
|
|||
|
entry->tm.stamp = time(NULL);
|
|||
|
|
|||
|
memset(&dns_ctx, 0, sizeof(dns_ctx));
|
|||
|
dns_ctx.begin = entry->tm.stamp;
|
|||
|
STRNCPY(dns_ctx.domain_key, domain, sizeof(dns_ctx.domain_key));
|
|||
|
ptr = strchr(dns_ctx.domain_key, ':');
|
|||
|
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
if (ptr)
|
|||
|
*ptr = 0;
|
|||
|
|
|||
|
entry->server_port = port;
|
|||
|
if (entry->server_port <= 0)
|
|||
|
entry->server_port = 80;
|
|||
|
|
|||
|
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>Сд<D0A1><D0B4><EFBFBD>Ա<EFBFBD><D4B1>ڽ<EFBFBD><DABD>й<EFBFBD>ϣ<EFBFBD><CFA3>ѯ */
|
|||
|
acl_lowercase(dns_ctx.domain_key);
|
|||
|
|
|||
|
dns_ctx.context = service;
|
|||
|
dns_ctx.callback = thrpool_nslookup_complete;
|
|||
|
|
|||
|
STRNCPY(entry->domain_key, dns_ctx.domain_key, sizeof(entry->domain_key));
|
|||
|
|
|||
|
/* <20>Ȳ<EFBFBD>ѯDNS<4E><53>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD> */
|
|||
|
list = (DNS_RING *) acl_htable_find(service->dns_table, dns_ctx.domain_key);
|
|||
|
if (list) {
|
|||
|
/* <20><><EFBFBD><EFBFBD><EFBFBD>ζ<EFBFBD>ͬһ<CDAC><D2BB><EFBFBD><EFBFBD><EFBFBD>IJ<EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD>ӽ<EFBFBD>ͬһ<CDAC><D2BB><EFBFBD><EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD> */
|
|||
|
acl_ring_prepend(&list->ring, &entry->dns_entry);
|
|||
|
/* <20><><EFBFBD><EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ü<EFBFBD><C3BC><EFBFBD><EFBFBD><EFBFBD>1 */
|
|||
|
list->nrefer++;
|
|||
|
/* <20><><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD>ڣ<EFBFBD>˵<EFBFBD><CBB5><EFBFBD>в<EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD>أ<EFBFBD><D8A3>䷵<EFBFBD>غ<EFBFBD><D8BA><EFBFBD>һͬ<D2BB><CDAC>
|
|||
|
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˴<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʳ<EFBFBD>ͻ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ
|
|||
|
* <EFBFBD><EFBFBD>ѯDNS<EFBFBD>Ĺ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD>̳߳ؽ<EFBFBD><EFBFBD>в<EFBFBD>ѯ<EFBFBD>ġ<EFBFBD>
|
|||
|
* (void) dns_server_lookup(proxy_entry->aio_proxy->dns_server, &dns_ctx);
|
|||
|
*/
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
/* <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>µIJ<C2B5>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><F3A3ACB2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>β<EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ò<EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD>м<EFBFBD><D0BC><EFBFBD><EFBFBD>ò<EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD> */
|
|||
|
|
|||
|
list = (DNS_RING *) acl_mycalloc(1, sizeof(DNS_RING));
|
|||
|
acl_ring_init(&list->ring);
|
|||
|
STRNCPY(list->domain_key, dns_ctx.domain_key, sizeof(list->domain_key));
|
|||
|
|
|||
|
/* <20><><EFBFBD><EFBFBD><EFBFBD>β<EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>µIJ<C2B5>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD>ҽ<EFBFBD><D2BD><EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ü<EFBFBD><C3BC><EFBFBD><EFBFBD><EFBFBD>1 */
|
|||
|
acl_ring_prepend(&list->ring, &entry->dns_entry);
|
|||
|
list->nrefer++;
|
|||
|
|
|||
|
/* <20><><EFBFBD>µIJ<C2B5>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD> */
|
|||
|
if (acl_htable_enter(service->dns_table, list->domain_key, (char *) list) == NULL)
|
|||
|
acl_msg_fatal("%s: add domain(%s) to table error", myname, list->domain_key);
|
|||
|
|
|||
|
/* <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>DNS<4E><53>ѯ<EFBFBD><D1AF><EFBFBD><EFBFBD> */
|
|||
|
(void) dns_server_lookup(service->dns_server, &dns_ctx);
|
|||
|
}
|
|||
|
|
|||
|
/*----------------------------------------------------------------------------*/
|
|||
|
|
|||
|
void dns_lookup(CLIENT_ENTRY *entry, const char *domain, int port)
|
|||
|
{
|
|||
|
const char *myname = "dns_lookup";
|
|||
|
SERVICE *service = entry->service;
|
|||
|
|
|||
|
if (acl_ipv4_valid(domain)) {
|
|||
|
entry->ip_idx = 0;
|
|||
|
ACL_SAFE_STRNCPY(entry->dns_ctx.ip[0], domain,
|
|||
|
sizeof(entry->dns_ctx.ip[0]));
|
|||
|
entry->dns_ctx.port[0] = port;
|
|||
|
entry->dns_ctx.ip_cnt = 1;
|
|||
|
entry->nslookup_notify_fn(entry, NSLOOKUP_OK);
|
|||
|
return;
|
|||
|
} else if (service->dns_handle) {
|
|||
|
inner_nslookup(service, entry, domain, port);
|
|||
|
} else if (service->dns_server) {
|
|||
|
thrpool_nslookup(service, entry, domain, port);
|
|||
|
} else {
|
|||
|
acl_msg_fatal("%s(%d): no dns lookup set", myname, __LINE__);
|
|||
|
}
|
|||
|
}
|