mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-12-15 09:20:52 +08:00
158 lines
3.1 KiB
C++
158 lines
3.1 KiB
C++
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <getopt.h>
|
|
#include "acl_cpp/lib_acl.hpp"
|
|
#include "fiber/go_fiber.hpp"
|
|
|
|
#include "rfc1035.h"
|
|
#include "argv.h"
|
|
|
|
static RFC1035_MESSAGE* parse_request(const char* data, size_t len)
|
|
{
|
|
RFC1035_MESSAGE *request;
|
|
request = rfc1035_request_unpack(data, len);
|
|
if (request == NULL) {
|
|
logger_error("unpack request error, size=%d", (int) len);
|
|
return NULL;
|
|
}
|
|
RFC1035_QUERY *query = request->query;
|
|
if (query == NULL || query->name[0] == 0) {
|
|
rfc1035_message_destroy(request);
|
|
return NULL;
|
|
}
|
|
|
|
#if 0
|
|
printf(">>>ask name=%s, query type=%d, class=%d\n",
|
|
query->name, query->qtype, query->qclass);
|
|
#endif
|
|
|
|
switch (query->qtype) {
|
|
case RFC1035_TYPE_A:
|
|
break;
|
|
case RFC1035_TYPE_AAAA:
|
|
break;
|
|
default:
|
|
logger_error("unsport qtype=%d, qclass=%d",
|
|
query->qtype, query->qclass);
|
|
rfc1035_message_destroy(request);
|
|
return NULL;
|
|
}
|
|
|
|
return request;
|
|
}
|
|
|
|
static size_t build_reply(const RFC1035_MESSAGE* request, char* buf, size_t size)
|
|
{
|
|
ARGV* ips = argv_alloc(5);
|
|
argv_add(ips, "192.168.1.1", NULL);
|
|
argv_add(ips, "192.168.1.2", NULL);
|
|
argv_add(ips, "192.168.1.3", NULL);
|
|
|
|
RFC1035_REPLY reply;
|
|
reply.hostname = request->query->name;
|
|
|
|
#if 1
|
|
reply.domain_root = "test.com";
|
|
reply.dns_name = "ipv6-static.dns.test.com";
|
|
reply.dns_ip = "127.0.0.1";
|
|
#else
|
|
reply.domain_root = NULL;
|
|
reply.dns_name = NULL;
|
|
reply.dns_ip = NULL;
|
|
#endif
|
|
|
|
reply.ips = ips;
|
|
|
|
reply.ip_type = RFC1035_TYPE_A;
|
|
reply.ttl = 600;
|
|
reply.qid = request->id;
|
|
|
|
size_t n = rfc1035_build_reply(&reply, buf, size);
|
|
argv_free(ips);
|
|
return n;
|
|
}
|
|
|
|
static void handle_pkt(acl::socket_stream& stream, const char* data, size_t len)
|
|
{
|
|
RFC1035_MESSAGE* request = parse_request(data, len);
|
|
if (request == NULL) {
|
|
logger_error("parse request error");
|
|
return;
|
|
}
|
|
|
|
char buf[1024];
|
|
size_t ret = build_reply(request, buf, sizeof(buf));
|
|
rfc1035_message_destroy(request);
|
|
if (!ret) {
|
|
logger_error("build reply error");
|
|
return;
|
|
}
|
|
|
|
if (stream.write(buf, ret) == -1) {
|
|
logger_error("write error");
|
|
}
|
|
}
|
|
|
|
static void dns_server(acl::socket_stream& stream)
|
|
{
|
|
char buf[1024];
|
|
int ret;
|
|
|
|
while (true) {
|
|
ret = stream.read(buf, sizeof(buf), false);
|
|
if (ret == -1) {
|
|
continue;
|
|
}
|
|
buf[ret] = 0;
|
|
handle_pkt(stream, buf, ret);
|
|
}
|
|
}
|
|
|
|
static void usage(const char *procname)
|
|
{
|
|
printf("usage: %s -h [help]\r\n"
|
|
" -s addr\r\n"
|
|
, procname);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
int ch;
|
|
acl::string addr("127.0.0.1:53");
|
|
|
|
while ((ch = getopt(argc, argv, "hs:")) > 0) {
|
|
switch (ch) {
|
|
case 'h':
|
|
usage(argv[0]);
|
|
return 0;
|
|
case 's':
|
|
addr = optarg;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (addr.empty()) {
|
|
usage(argv[0]);
|
|
return 0;
|
|
}
|
|
|
|
acl::log::stdout_open(true);
|
|
acl::fiber::stdout_open(true);
|
|
|
|
acl::socket_stream stream;
|
|
if (!stream.bind_udp(addr)) {
|
|
printf("bind %s error %s\r\n", addr.c_str(), acl::last_serror());
|
|
return 1;
|
|
}
|
|
|
|
go[&] {
|
|
dns_server(stream);
|
|
};
|
|
|
|
acl::fiber::schedule();
|
|
return 0;
|
|
}
|