mirror of
https://github.com/sogou/workflow.git
synced 2026-10-26 01:30:47 +08:00
Merge branch 'master' of https://github.com/sogou/workflow into nossl
This commit is contained in:
+185
-30
@@ -37,6 +37,157 @@ static inline void __append_uint16(std::string& s, uint16_t tmp)
|
||||
s.append((const char *)&tmp, sizeof (uint16_t));
|
||||
}
|
||||
|
||||
static inline void __append_uint32(std::string& s, uint32_t tmp)
|
||||
{
|
||||
tmp = htonl(tmp);
|
||||
s.append((const char *)&tmp, sizeof (uint32_t));
|
||||
}
|
||||
|
||||
static inline int __append_name(std::string& s, const char *p)
|
||||
{
|
||||
const char *name;
|
||||
size_t len;
|
||||
|
||||
while (*p)
|
||||
{
|
||||
name = p;
|
||||
while (*p && *p != '.')
|
||||
p++;
|
||||
|
||||
len = p - name;
|
||||
if (len > DNS_LABELS_MAX || (len == 0 && *p && *(p + 1)))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
__append_uint8(s, len);
|
||||
s.append(name, len);
|
||||
}
|
||||
|
||||
if (*p == '.')
|
||||
p++;
|
||||
}
|
||||
|
||||
len = 0;
|
||||
__append_uint8(s, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int __append_record_list(std::string& s, int *count,
|
||||
dns_record_cursor_t *cursor)
|
||||
{
|
||||
int cnt = 0;
|
||||
struct dns_record *record;
|
||||
std::string record_buf;
|
||||
std::string rdata_buf;
|
||||
int ret;
|
||||
|
||||
while (dns_record_cursor_next(&record, cursor) == 0)
|
||||
{
|
||||
record_buf.clear();
|
||||
ret = __append_name(record_buf, record->name);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
__append_uint16(record_buf, record->type);
|
||||
__append_uint16(record_buf, record->rclass);
|
||||
__append_uint32(record_buf, record->ttl);
|
||||
|
||||
switch (record->type)
|
||||
{
|
||||
case DNS_TYPE_A:
|
||||
case DNS_TYPE_AAAA:
|
||||
__append_uint16(record_buf, record->rdlength);
|
||||
record_buf.append((const char *)record->rdata, record->rdlength);
|
||||
break;
|
||||
|
||||
case DNS_TYPE_NS:
|
||||
case DNS_TYPE_CNAME:
|
||||
case DNS_TYPE_PTR:
|
||||
rdata_buf.clear();
|
||||
ret = __append_name(rdata_buf, (const char *)record->rdata);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
__append_uint16(record_buf, rdata_buf.size());
|
||||
record_buf.append(rdata_buf);
|
||||
|
||||
break;
|
||||
|
||||
case DNS_TYPE_SOA:
|
||||
{
|
||||
auto *soa = (struct dns_record_soa *)record->rdata;
|
||||
|
||||
rdata_buf.clear();
|
||||
ret = __append_name(rdata_buf, soa->mname);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = __append_name(rdata_buf, soa->rname);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
__append_uint32(rdata_buf, soa->serial);
|
||||
__append_uint32(rdata_buf, soa->refresh);
|
||||
__append_uint32(rdata_buf, soa->retry);
|
||||
__append_uint32(rdata_buf, soa->expire);
|
||||
__append_uint32(rdata_buf, soa->minimum);
|
||||
|
||||
__append_uint16(record_buf, rdata_buf.size());
|
||||
record_buf.append(rdata_buf);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DNS_TYPE_SRV:
|
||||
{
|
||||
auto *srv = (struct dns_record_srv *)record->rdata;
|
||||
|
||||
rdata_buf.clear();
|
||||
__append_uint16(rdata_buf, srv->priority);
|
||||
__append_uint16(rdata_buf, srv->weight);
|
||||
__append_uint16(rdata_buf, srv->port);
|
||||
ret = __append_name(rdata_buf, srv->target);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
__append_uint16(record_buf, rdata_buf.size());
|
||||
record_buf.append(rdata_buf);
|
||||
|
||||
break;
|
||||
}
|
||||
case DNS_TYPE_MX:
|
||||
{
|
||||
auto *mx = (struct dns_record_mx *)record->rdata;
|
||||
rdata_buf.clear();
|
||||
__append_uint16(rdata_buf, mx->preference);
|
||||
ret = __append_name(rdata_buf, mx->exchange);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
__append_uint16(record_buf, rdata_buf.size());
|
||||
record_buf.append(rdata_buf);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// TODO not implement
|
||||
continue;
|
||||
}
|
||||
|
||||
cnt++;
|
||||
s.append(record_buf);
|
||||
}
|
||||
|
||||
if (count)
|
||||
*count = cnt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DnsMessage::DnsMessage(DnsMessage&& msg) :
|
||||
ProtocolMessage(std::move(msg))
|
||||
{
|
||||
@@ -70,54 +221,58 @@ DnsMessage& DnsMessage::operator = (DnsMessage&& msg)
|
||||
|
||||
int DnsMessage::encode_reply()
|
||||
{
|
||||
dns_record_cursor_t cursor;
|
||||
struct dns_header h;
|
||||
const char *name;
|
||||
std::string tmpbuf;
|
||||
const char *p;
|
||||
size_t len;
|
||||
int ancount;
|
||||
int nscount;
|
||||
int arcount;
|
||||
int ret;
|
||||
|
||||
msgbuf.clear();
|
||||
msgsize = 0;
|
||||
|
||||
// TODO encode other field
|
||||
// TODO
|
||||
// this is an incomplete and inefficient way, compress not used,
|
||||
// pointers can only be used for occurances of a domain name where
|
||||
// the format is not class specific
|
||||
dns_answer_cursor_init(&cursor, this->parser);
|
||||
ret = __append_record_list(tmpbuf, &ancount, &cursor);
|
||||
dns_record_cursor_deinit(&cursor);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dns_authority_cursor_init(&cursor, this->parser);
|
||||
ret = __append_record_list(tmpbuf, &nscount, &cursor);
|
||||
dns_record_cursor_deinit(&cursor);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dns_additional_cursor_init(&cursor, this->parser);
|
||||
ret = __append_record_list(tmpbuf, &arcount, &cursor);
|
||||
dns_record_cursor_deinit(&cursor);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
h = this->parser->header;
|
||||
h.id = htons(h.id);
|
||||
h.qdcount = htons(1);
|
||||
h.ancount = htons(0);
|
||||
h.nscount = htons(0);
|
||||
h.arcount = htons(0);
|
||||
h.ancount = htons(ancount);
|
||||
h.nscount = htons(nscount);
|
||||
h.arcount = htons(arcount);
|
||||
|
||||
msgbuf.append((const char *)&h, sizeof (struct dns_header));
|
||||
p = parser->question.qname ? parser->question.qname : ".";
|
||||
while (*p)
|
||||
{
|
||||
name = p;
|
||||
while (*p && *p != '.')
|
||||
p++;
|
||||
ret = __append_name(msgbuf, p);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
len = p - name;
|
||||
if (len > DNS_LABELS_MAX || (len == 0 && *p && *(p + 1)))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
__append_uint8(msgbuf, len);
|
||||
msgbuf.append(name, len);
|
||||
}
|
||||
|
||||
if (*p == '.')
|
||||
p++;
|
||||
}
|
||||
|
||||
len = 0;
|
||||
__append_uint8(msgbuf, len);
|
||||
__append_uint16(msgbuf, parser->question.qtype);
|
||||
__append_uint16(msgbuf, parser->question.qclass);
|
||||
|
||||
msgbuf.append(tmpbuf);
|
||||
|
||||
if (msgbuf.size() >= (1 << 16))
|
||||
{
|
||||
errno = EOVERFLOW;
|
||||
|
||||
Reference in New Issue
Block a user