acl/app/jaws/global/dns_lookup.c

270 lines
7.6 KiB
C
Raw Normal View History

2014-11-19 00:25:21 +08:00
#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__);
}
}