⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reply.c

📁 此dns服务器是在mydns基础上改写
💻 C
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************************************	$Id: reply.c,v 1.65 2006/01/18 20:46:47 bboy Exp $	Copyright (C) 2002-2005  Don Moore <bboy@bboy.net>	This program is free software; you can redistribute it and/or modify	it under the terms of the GNU General Public License as published by	the Free Software Foundation; either version 2 of the License, or	(at Your option) any later version.	This program is distributed in the hope that it will be useful,	but WITHOUT ANY WARRANTY; without even the implied warranty of	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the	GNU General Public License for more details.	You should have received a copy of the GNU General Public License	along with this program; if not, write to the Free Software	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA**************************************************************************************************/#include "named.h"/* Make this nonzero to enable debugging for this source file */#define	DEBUG_REPLY	1#if DEBUG_ENABLED && DEBUG_REPLY/* Strings describing the datasections */char *reply_datasection_str[] = { "QUESTION", "ANSWER", "AUTHORITY", "ADDITIONAL" };#endif/**************************************************************************************************	REPLY_INIT	Examines the question data, storing the name offsets (from DNS_HEADERSIZE) for compression.**************************************************************************************************/intreply_init(TASK *t){	register char *c;												/* Current character in name */	/* Examine question data, save labels found therein. The question data should begin with		the name we've already parsed into t->qname.  I believe it is safe to assume that no		compression will be possible in the question. */	for (c = t->qname; *c; c++)		if ((c == t->qname || *c == '.') && c[1])			if (name_remember(t, (c == t->qname) ? c : (c+1),					(((c == t->qname) ? c : (c+1)) - t->qname) + DNS_HEADERSIZE) < -1)				return (-1);	return (0);}/*--- reply_init() ------------------------------------------------------------------------------*//**************************************************************************************************	REPLY_ADD_ADDITIONAL	Add ADDITIONAL for each item in the provided list.**************************************************************************************************/static voidreply_add_additional(TASK *t, RRLIST *rrlist, datasection_t section){	register RR *p;	if (!rrlist)		return;	/* Examine each RR in the rrlist */	for (p = rrlist->head; p; p = p->next)	{		if (p->rrtype == DNS_RRTYPE_RR)		{			MYDNS_RR *rr = (MYDNS_RR *)p->rr;			if (rr->type == DNS_QTYPE_NS || rr->type == DNS_QTYPE_MX || rr->type == DNS_QTYPE_SRV)			{#if DEBUG_ENABLED && DEBUG_REPLY				Debug("%s: resolving `%s' (A) for ADDITIONAL data", desctask(t), rr->data);#endif				(void)resolve(t, ADDITIONAL, DNS_QTYPE_A, rr->data, 0);			}			else if (rr->type == DNS_QTYPE_CNAME)			{#if DEBUG_ENABLED && DEBUG_REPLY				Debug("%s: resolving `%s' (CNAME) for ADDITIONAL data", desctask(t), rr->data);#endif				/* Don't do this */				(void)resolve(t, ADDITIONAL, DNS_QTYPE_CNAME, rr->data, 0);			}		}		t->sort_level++;	}}/*--- reply_add_additional() --------------------------------------------------------------------*//**************************************************************************************************	RDATA_ENLARGE	Expands t->rdata by `size' bytes.  Returns a pointer to the destination.**************************************************************************************************/static inline char *rdata_enlarge(TASK *t, size_t size){	if (!size)		return (NULL);	t->rdlen += size;	if (!t->rdata)	{		if (!(t->rdata = malloc(t->rdlen)))			Err(_("out of memory"));	}	else	{		if (!(t->rdata = realloc(t->rdata, t->rdlen)))			Err(_("out of memory"));	}	return (t->rdata + t->rdlen - size);}/*--- rdata_enlarge() ---------------------------------------------------------------------------*//**************************************************************************************************	REPLY_START_RR	Begins an RR.  Appends to t->rdata all the header fields prior to rdlength.	Returns the numeric offset of the start of this record within the reply, or -1 on error.**************************************************************************************************/static inline intreply_start_rr(TASK *t, RR *r, char *name, dns_qtype_t type, uint32_t ttl, char *desc){	char	enc[DNS_MAXNAMELEN+1];	char	*dest;	int	enclen;	/* name_encode returns dnserror() */	if ((enclen = name_encode(t, enc, name, t->replylen + t->rdlen, 1)) < 0)		return rr_error(r->id, "rr %u: %s (%s %s) (name=\"%s\")", r->id,							 _("invalid name in \"name\""), desc, _("record"), name);	r->length = enclen + SIZE16 + SIZE16 + SIZE32;	if (!(dest = rdata_enlarge(t, r->length)))		return dnserror(t, DNS_RCODE_SERVFAIL, ERR_INTERNAL);	r->offset = dest - t->rdata + DNS_HEADERSIZE + t->qdlen;	DNS_PUT(dest, enc, enclen);	DNS_PUT16(dest, type);#if STATUS_ENABLED	if (r->rrtype == DNS_RRTYPE_RR && r->rr)		DNS_PUT16(dest, ((MYDNS_RR *)(r->rr))->class)	else#endif		DNS_PUT16(dest, DNS_CLASS_IN);	DNS_PUT32(dest, ttl);	return (0);}/*--- reply_start_rr() --------------------------------------------------------------------------*//**************************************************************************************************	REPLY_ADD_GENERIC_RR	Adds a generic resource record whose sole piece of data is a domain-name,	or a 16-bit value plus a domain-name.	Returns the numeric offset of the start of this record within the reply, or -1 on error.**************************************************************************************************/static inline intreply_add_generic_rr(TASK *t, RR *r, char *desc){	char		enc[DNS_MAXNAMELEN+1], *dest;	int		size, enclen;	MYDNS_RR	*rr = (MYDNS_RR *)r->rr;#if DEBUG_ENABLED && DEBUG_REPLY	Debug("%s: REPLY_ADD: `%s' IN %s `%s'", desctask(t), r->name, mydns_qtype_str(rr->type), rr->data);#endif	if (reply_start_rr(t, r, r->name, rr->type, rr->ttl, desc) < 0)		return (-1);	if ((enclen = name_encode(t, enc, rr->data, CUROFFSET(t), 1)) < 0)		return rr_error(r->id, "rr %u: %s (%s) (data=\"%s\")", r->id,							 _("invalid name in \"data\""), desc, rr->data);	size = enclen;	r->length += SIZE16 + size;	if (!(dest = rdata_enlarge(t, SIZE16 + size)))		return dnserror(t, DNS_RCODE_SERVFAIL, ERR_INTERNAL);	DNS_PUT16(dest, size);	DNS_PUT(dest, enc, enclen);	return (0);}/*--- reply_add_generic_rr() --------------------------------------------------------------------*//**************************************************************************************************	REPLY_ADD_A	Adds an A record to the reply.	Returns the numeric offset of the start of this record within the reply, or -1 on error.**************************************************************************************************/static inline intreply_add_a(TASK *t, RR *r){	char		*dest;	int		size;	MYDNS_RR	*rr = (MYDNS_RR *)r->rr;	struct in_addr addr;	uint32_t	ip;	if (inet_pton(AF_INET, rr->data, (void *)&addr) <= 0)	{		dnserror(t, DNS_RCODE_SERVFAIL, ERR_INVALID_ADDRESS);		return rr_error(r->id, "rr %u: %s (A %s) (address=\"%s\")", r->id,							 _("invalid address in \"data\""), _("record"), rr->data);	}	ip = ntohl(addr.s_addr);#if DEBUG_ENABLED && DEBUG_REPLY	Debug("%s: REPLY_ADD: `%s' IN A %s", desctask(t), r->name, inet_ntoa(addr));#endif	if (reply_start_rr(t, r, r->name, DNS_QTYPE_A, rr->ttl, "A") < 0)		return (-1);	size = SIZE32;	r->length += SIZE16 + size;	if (!(dest = rdata_enlarge(t, SIZE16 + size)))		return dnserror(t, DNS_RCODE_SERVFAIL, ERR_INTERNAL);	DNS_PUT16(dest, size);	DNS_PUT32(dest, ip);	return (0);}/*--- reply_add_a() -----------------------------------------------------------------------------*//**************************************************************************************************	REPLY_ADD_AAAA	Adds an AAAA record to the reply.	Returns the numeric offset of the start of this record within the reply, or -1 on error.**************************************************************************************************/static inline intreply_add_aaaa(TASK *t, RR *r){	char		*dest;	int		size;	MYDNS_RR	*rr = (MYDNS_RR *)r->rr;	uint8_t	addr[16];#if DEBUG_ENABLED && DEBUG_REPLY	Debug("%s: REPLY_ADD: `%s' IN AAAA %s", desctask(t), r->name, rr->data);#endif	if (inet_pton(AF_INET6, rr->data, (void *)&addr) <= 0)	{		dnserror(t, DNS_RCODE_SERVFAIL, ERR_INVALID_ADDRESS);		return rr_error(r->id, "rr %u: %s (AAAA %s) (address=\"%s\")", r->id,							 _("invalid address in \"data\""), _("record"), rr->data);	}	if (reply_start_rr(t, r, r->name, DNS_QTYPE_AAAA, rr->ttl, "AAAA") < 0)		return (-1);	size = sizeof(uint8_t) * 16;	r->length += SIZE16 + size;	if (!(dest = rdata_enlarge(t, SIZE16 + size)))		return dnserror(t, DNS_RCODE_SERVFAIL, ERR_INTERNAL);	DNS_PUT16(dest, size);	memcpy(dest, &addr, size);	dest += size;	return (0);}/*--- reply_add_aaaa() --------------------------------------------------------------------------*//**************************************************************************************************	REPLY_ADD_HINFO	Adds an HINFO record to the reply.	Returns the numeric offset of the start of this record within the reply, or -1 on error.**************************************************************************************************/static inline intreply_add_hinfo(TASK *t, RR *r){	char		*dest;	size_t	oslen, cpulen;	MYDNS_RR	*rr = (MYDNS_RR *)r->rr;	char		os[DNS_MAXNAMELEN + 1] = "", cpu[DNS_MAXNAMELEN + 1] = "";	if (hinfo_parse(rr->data, cpu, os, DNS_MAXNAMELEN) < 0)	{		dnserror(t, DNS_RCODE_SERVFAIL, ERR_RR_NAME_TOO_LONG);		return rr_error(r->id, "rr %u: %s (HINFO %s) (data=\"%s\")", r->id,							 _("name too long in \"data\""), _("record"), rr->data);	}#if DEBUG_ENABLED && DEBUG_REPLY	Debug("%s: REPLY_ADD: `%s' IN HINFO `%s %s'", desctask(t), r->name, cpu, os);#endif	cpulen = strlen(cpu);	oslen = strlen(os);	if (reply_start_rr(t, r, r->name, DNS_QTYPE_HINFO, rr->ttl, "HINFO") < 0)		return (-1);	r->length += SIZE16 + cpulen + oslen + 2;	if (!(dest = rdata_enlarge(t, SIZE16 + cpulen + SIZE16 + oslen)))		return dnserror(t, DNS_RCODE_SERVFAIL, ERR_INTERNAL);	DNS_PUT16(dest, cpulen + oslen + 2);	*dest++ = cpulen;	memcpy(dest, cpu, cpulen);	dest += cpulen;	*dest++ = oslen;	memcpy(dest, os, oslen);	dest += oslen;	return (0);}/*--- reply_add_hinfo() -------------------------------------------------------------------------*//**************************************************************************************************	REPLY_ADD_MX	Adds an MX record to the reply.	Returns the numeric offset of the start of this record within the reply, or -1 on error.**************************************************************************************************/static inline intreply_add_mx(TASK *t, RR *r){	char		enc[DNS_MAXNAMELEN+1], *dest;	int		size, enclen;	MYDNS_RR	*rr = (MYDNS_RR *)r->rr;#if DEBUG_ENABLED && DEBUG_REPLY	Debug("%s: REPLY_ADD: `%s' IN MX `%u %s'", desctask(t), r->name, (uint16_t)rr->aux, rr->data);#endif	if (reply_start_rr(t, r, r->name, DNS_QTYPE_MX, rr->ttl, "MX") < 0)		return (-1);	if ((enclen = name_encode(t, enc, rr->data, CUROFFSET(t) + SIZE16, 1)) < 0)		return rr_error(r->id, "rr %u: %s (MX %s) (data=\"%s\")", r->id,							 _("invalid name in \"data\""), _("record"), rr->data);	size = SIZE16 + enclen;	r->length += SIZE16 + size;	if (!(dest = rdata_enlarge(t, SIZE16 + size)))		return dnserror(t, DNS_RCODE_SERVFAIL, ERR_INTERNAL);	DNS_PUT16(dest, size);	DNS_PUT16(dest, (uint16_t)rr->aux);	DNS_PUT(dest, enc, enclen);	return (0);}/*--- reply_add_mx() ----------------------------------------------------------------------------*//**************************************************************************************************	REPLY_ADD_NAPTR	Adds an NAPTR record to the reply.	Returns the numeric offset of the start of this record within the reply, or -1 on error.**************************************************************************************************/static inline intreply_add_naptr(TASK *t, RR *r){	MYDNS_RR	*rr = (MYDNS_RR *)r->rr;	size_t	flags_len, service_len, regex_len;	char		enc[DNS_MAXNAMELEN+1], *dest;	int		size, enclen, offset;#if DEBUG_ENABLED && DEBUG_REPLY	Debug("%s: REPLY_ADD: `%s' IN NAPTR `%u %u \"%s\" \"%s\" \"%s\" \"%s\"'", desctask(t),			r->name, rr->naptr_order, rr->naptr_pref, rr->naptr_flags, rr->naptr_service,			rr->naptr_regex, rr->naptr_replacement);#endif	flags_len = strlen(rr->naptr_flags);	service_len = strlen(rr->naptr_service);	regex_len = strlen(rr->naptr_regex);	if (reply_start_rr(t, r, r->name, DNS_QTYPE_NAPTR, rr->ttl, "NAPTR") < 0)		return (-1);	/* We are going to write "something else" and then a name, just like an MX record or something.		In this case, though, the "something else" is lots of data.  Calculate the size of		"something else" in 'offset' */	offset = SIZE16 + SIZE16 + 1 + flags_len + 1 + service_len + 1 + regex_len;	/* Encode the name at the offset */	if ((enclen = name_encode(t, enc, rr->naptr_replacement, CUROFFSET(t) + offset, 1)) < 0)		return rr_error(r->id, "rr %u: %s (NAPTR %s) (%s=\"%s\")", r->id,							 _("invalid name in \"replacement\""), _("record"), _("replacement"),							 rr->naptr_replacement);	size = offset + enclen;	r->length += SIZE16 + size;	if (!(dest = rdata_enlarge(t, SIZE16 + size)))		return dnserror(t, DNS_RCODE_SERVFAIL, ERR_INTERNAL);	DNS_PUT16(dest, size);	DNS_PUT16(dest, (uint16_t)rr->naptr_order);	DNS_PUT16(dest, (uint16_t)rr->naptr_pref);	*dest++ = flags_len;	memcpy(dest, rr->naptr_flags, flags_len);	dest += flags_len;	*dest++ = service_len;	memcpy(dest, rr->naptr_service, service_len);	dest += service_len;	*dest++ = regex_len;	memcpy(dest, rr->naptr_regex, regex_len);	dest += regex_len;	DNS_PUT(dest, enc, enclen);	return (0);}/*--- reply_add_naptr() -------------------------------------------------------------------------*//**************************************************************************************************	REPLY_ADD_RP	Adds an RP record to the reply.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -