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

📄 reply.c

📁 此dns服务器是在mydns基础上改写
💻 C
📖 第 1 页 / 共 2 页
字号:
	Returns the numeric offset of the start of this record within the reply, or -1 on error.**************************************************************************************************/static inline intreply_add_rp(TASK *t, RR *r){	char		*mbox, *txt, *dest;	char		encmbox[DNS_MAXNAMELEN+1], enctxt[DNS_MAXNAMELEN+1];	int		size, mboxlen, txtlen;	MYDNS_RR	*rr = (MYDNS_RR *)r->rr;	mbox = rr->data;	txt = rr->rp_txt;#if DEBUG_ENABLED && DEBUG_REPLY	Debug("%s: REPLY_ADD: `%s' IN RP `%s %s'", desctask(t), r->name, mbox, txt);#endif	if (reply_start_rr(t, r, r->name, DNS_QTYPE_RP, rr->ttl, "RP") < 0)		return (-1);	if ((mboxlen = name_encode(t, encmbox, mbox, CUROFFSET(t), 1)) < 0)		return rr_error(r->id, "rr %u: %s (RP %s) (mbox=\"%s\")", r->id,							 _("invalid name in \"mbox\""), _("record"), mbox);	if ((txtlen = name_encode(t, enctxt, txt, CUROFFSET(t) + mboxlen, 1)) < 0)		return rr_error(r->id, "rr %u: %s (RP %s) (txt=\"%s\")", r->id,							 _("invalid name in \"txt\""), _("record"), txt);	size = mboxlen + txtlen;	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, encmbox, mboxlen);	DNS_PUT(dest, enctxt, txtlen);	return (0);}/*--- reply_add_rp() ----------------------------------------------------------------------------*//**************************************************************************************************	REPLY_ADD_SOA	Add a SOA 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_soa(TASK *t, RR *r){	char			*dest, ns[DNS_MAXNAMELEN+1], mbox[DNS_MAXNAMELEN+1];	int			size, nslen, mboxlen;	MYDNS_SOA	*soa = (MYDNS_SOA *)r->rr;#if DEBUG_ENABLED && DEBUG_REPLY	Debug("%s: REPLY_ADD: `%s' IN SOA (mbox=[%s])", desctask(t), soa->origin, soa->mbox);#endif	if (reply_start_rr(t, r, r->name, DNS_QTYPE_SOA, soa->ttl, "SOA") < 0)		return (-1);	if ((nslen = name_encode(t, ns, soa->ns, CUROFFSET(t), 1)) < 0)		return rr_error(r->id, "rr %u: %s (SOA %s) (ns=\"%s\")", r->id,							 _("invalid name in \"ns\""), _("record"), soa->ns);	if ((mboxlen = name_encode(t, mbox, soa->mbox, CUROFFSET(t) + nslen, 1)) < 0)		return rr_error(r->id, "rr %u: %s (SOA %s) (mbox=\"%s\")", r->id,							 _("invalid name in \"mbox\""), _("record"), soa->mbox);	size = nslen + mboxlen + (SIZE32 * 5);	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, ns, nslen);	DNS_PUT(dest, mbox, mboxlen);	DNS_PUT32(dest, soa->serial);	DNS_PUT32(dest, soa->refresh);	DNS_PUT32(dest, soa->retry);	DNS_PUT32(dest, soa->expire);	DNS_PUT32(dest, soa->minimum);	return (0);}/*--- reply_add_soa() ---------------------------------------------------------------------------*//**************************************************************************************************	REPLY_ADD_SRV	Adds a SRV 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_srv(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 SRV `%u %u %u %s'",			desctask(t), r->name, (uint16_t)rr->aux, rr->srv_weight, rr->srv_port, rr->data);#endif	if (reply_start_rr(t, r, r->name, DNS_QTYPE_SRV, rr->ttl, "SRV") < 0)		return (-1);	/* RFC 2782 says that we can't use name compression on this field... */	/* Arnt Gulbrandsen advises against using compression in the SRV target, although		most clients should support it */	if ((enclen = name_encode(t, enc, rr->data, CUROFFSET(t) + SIZE16 + SIZE16 + SIZE16, 0)) < 0)		return rr_error(r->id, "rr %u: %s (SRV %s) (data=\"%s\")", r->id,							 _("invalid name in \"data\""), _("record"), rr->data);	size = SIZE16 + SIZE16 + 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_PUT16(dest, (uint16_t)rr->srv_weight);	DNS_PUT16(dest, (uint16_t)rr->srv_port);	DNS_PUT(dest, enc, enclen);	return (0);}/*--- reply_add_srv() ---------------------------------------------------------------------------*//**************************************************************************************************	REPLY_ADD_TXT	Adds a TXT 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_txt(TASK *t, RR *r){	char		*dest;	char		size;	size_t	len;	MYDNS_RR	*rr = (MYDNS_RR *)r->rr;#if DEBUG_ENABLED && DEBUG_REPLY	Debug("%s: REPLY_ADD: `%s' IN TXT", desctask(t), r->name);#endif	len = strlen(rr->data);	if (reply_start_rr(t, r, r->name, DNS_QTYPE_TXT, rr->ttl, "TXT") < 0)		return (-1);	size = len + 1;	r->length += SIZE16 + size;	if (!(dest = rdata_enlarge(t, SIZE16 + size)))		return dnserror(t, DNS_RCODE_SERVFAIL, ERR_INTERNAL);	DNS_PUT16(dest, size);	*dest++ = len;	memcpy(dest, rr->data, len);	dest += len;	return (0);}/*--- reply_add_txt() ---------------------------------------------------------------------------*//**************************************************************************************************	REPLY_PROCESS_RRLIST	Adds each resource record found in `rrlist' to the reply.**************************************************************************************************/static intreply_process_rrlist(TASK *t, RRLIST *rrlist){	register RR *r;	if (!rrlist)		return (0);	for (r = rrlist->head; r; r = r->next)	{		switch (r->rrtype)		{			case DNS_RRTYPE_SOA:				if (reply_add_soa(t, r) < 0)					return (-1);				break;			case DNS_RRTYPE_RR:				{					MYDNS_RR *rr = (MYDNS_RR *)r->rr;					if (!rr)						break;					switch (rr->type)					{						case DNS_QTYPE_A:							if (reply_add_a(t, r) < 0)								return (-1);							break;						case DNS_QTYPE_AAAA:							if (reply_add_aaaa(t, r) < 0)								return (-1);							break;						case DNS_QTYPE_CNAME:							if (reply_add_generic_rr(t, r, "CNAME") < 0)								return (-1);							break;						case DNS_QTYPE_HINFO:							if (reply_add_hinfo(t, r) < 0)								return (-1);							break;						case DNS_QTYPE_MX:							if (reply_add_mx(t, r) < 0)								return (-1);							break;						case DNS_QTYPE_NAPTR:							if (reply_add_naptr(t, r) < 0)								return (-1);							break;						case DNS_QTYPE_NS:							if (reply_add_generic_rr(t, r, "NS") < 0)								return (-1);							break;						case DNS_QTYPE_PTR:							if (reply_add_generic_rr(t, r, "PTR") < 0)								return (-1);							break;						case DNS_QTYPE_RP:							if (reply_add_rp(t, r) < 0)								return (-1);							break;						case DNS_QTYPE_SRV:							if (reply_add_srv(t, r) < 0)								return (-1);							break;						case DNS_QTYPE_TXT:							if (reply_add_txt(t, r) < 0)								return (-1);							break;						default:							Warnx("%s: %s: %s", desctask(t), mydns_qtype_str(rr->type),									_("unsupported resource record type"));					}				}				break;		}	}	return (0);}/*--- reply_process_rrlist() --------------------------------------------------------------------*//**************************************************************************************************	TRUNCATE_RRLIST	Returns new count of items in this list.	The TC flag is _not_ set if data was truncated from the ADDITIONAL section.**************************************************************************************************/static inttruncate_rrlist(TASK *t, off_t maxpkt, RRLIST *rrlist, datasection_t ds){	register RR *rr;	register int recs;#if DEBUG_ENABLED && DEBUG_REPLY	int orig_recs = rrlist->size;#endif	/* Warn about truncated packets, but only if TCP is not enabled.  Most resolvers will try		TCP if a UDP packet is truncated. */	if (!tcp_enabled)		Verbose("%s: %s", desctask(t), _("query truncated"));	recs = rrlist->size;	for (rr = rrlist->head; rr; rr = rr->next)	{		if (rr->offset + rr->length >= maxpkt)		{			recs--;			if (ds != ADDITIONAL)				t->hdr.tc = 1;		}		else			t->rdlen += rr->length;	}#if DEBUG_ENABLED && DEBUG_REPLY	Debug("%s section truncated from %d records to %d records",			reply_datasection_str[ds], orig_recs, recs);#endif	return (recs);}/*--- truncate_rrlist() -------------------------------------------------------------------------*//**************************************************************************************************	REPLY_CHECK_TRUNCATION	If this reply would be truncated, removes any RR's that won't fit and sets the truncation flag.**************************************************************************************************/static voidreply_check_truncation(TASK *t, int *ancount, int *nscount, int *arcount){	size_t maxpkt = (t->protocol == SOCK_STREAM ? DNS_MAXPACKETLEN_TCP : DNS_MAXPACKETLEN_UDP);	size_t maxrd = maxpkt - (DNS_HEADERSIZE + t->qdlen);	if (t->rdlen <= maxrd)		return;#if DEBUG_ENABLED && DEBUG_REPLY	Debug("reply_check_truncation() needs to truncate reply (%d) to fit packet max (%d)",			t->rdlen, maxrd);#endif	/* Loop through an/ns/ar sections, truncating as necessary, and updating counts */	t->rdlen = 0;	*ancount = truncate_rrlist(t, maxpkt, &t->an, ANSWER);	*nscount = truncate_rrlist(t, maxpkt, &t->ns, AUTHORITY);	*arcount = truncate_rrlist(t, maxpkt, &t->ar, ADDITIONAL);}/*--- reply_check_truncation() ------------------------------------------------------------------*//**************************************************************************************************	BUILD_CACHE_REPLY	Builds reply data from cached answer.**************************************************************************************************/voidbuild_cache_reply(TASK *t){	char *dest = t->reply;	DNS_PUT16(dest, t->id);										/* Query ID */	DNS_PUT(dest, &t->hdr, SIZE16);							/* Header */}/*--- build_cache_reply() -----------------------------------------------------------------------*//**************************************************************************************************	BUILD_REPLY	Given a task, constructs the reply data.**************************************************************************************************/voidbuild_reply(TASK *t, int want_additional){	char	*dest;	int	ancount, nscount, arcount;	/* Add data to ADDITIONAL section */	if (want_additional)	{		reply_add_additional(t, &t->an, ANSWER);		reply_add_additional(t, &t->ns, AUTHORITY);	}	/* Sort records where necessary */	if (t->an.a_records > 1)									/* ANSWER section: Sort A/AAAA records */		sort_a_recs(t, &t->an, ANSWER);	if (t->an.mx_records > 1)									/* ANSWER section: Sort MX records */		sort_mx_recs(t, &t->an, ANSWER);	if (t->an.srv_records > 1)									/* ANSWER section: Sort SRV records */		sort_srv_recs(t, &t->an, ANSWER);	if (t->ar.a_records > 1)									/* AUTHORITY section: Sort A/AAAA records */		sort_a_recs(t, &t->ar, AUTHORITY);	/* Build `rdata' containing resource records in ANSWER, AUTHORITY, and ADDITIONAL */	t->replylen = DNS_HEADERSIZE + t->qdlen + t->rdlen;	if (reply_process_rrlist(t, &t->an) || reply_process_rrlist(t, &t->ns) || reply_process_rrlist(t, &t->ar))	{		/* Empty RR lists */		rrlist_free(&t->an);		rrlist_free(&t->ns);		rrlist_free(&t->ar);		/* Make sure reply is empty */		t->replylen = 0;		t->rdlen = 0;		Free(t->rdata);	}	ancount = t->an.size;	nscount = t->ns.size;	arcount = t->ar.size;	/* Verify reply length */	reply_check_truncation(t, &ancount, &nscount, &arcount);	/* Make sure header bits are set correctly */	t->hdr.qr = 1;	t->hdr.cd = 0;	/* Construct the reply */	t->replylen = DNS_HEADERSIZE + t->qdlen + t->rdlen;	dest = t->reply = malloc(t->replylen);	if (!t->reply)		Err(_("out of memory"));	DNS_PUT16(dest, t->id);										/* Query ID */	DNS_PUT(dest, &t->hdr, SIZE16);							/* Header */	DNS_PUT16(dest, t->qdcount);								/* QUESTION count */	DNS_PUT16(dest, ancount);									/* ANSWER count */	DNS_PUT16(dest, nscount);									/* AUTHORITY count */	DNS_PUT16(dest, arcount);									/* ADDITIONAL count */	if (t->qdlen && t->qd)		DNS_PUT(dest, t->qd, t->qdlen);						/* Data for QUESTION section */	DNS_PUT(dest, t->rdata, t->rdlen);						/* Resource record data */#if DEBUG_ENABLED && DEBUG_REPLY	Debug("%s: reply:     id = %u", desctask(t), t->id);	Debug("%s: reply:     qr = %u (message is a %s)", desctask(t), t->hdr.qr, t->hdr.qr ? "response" : "query");	Debug("%s: reply: opcode = %u (%s)", desctask(t), t->hdr.opcode, mydns_opcode_str(t->hdr.opcode));	Debug("%s: reply:     aa = %u (answer %s)", desctask(t), t->hdr.aa, t->hdr.aa ? "is authoritative" : "not authoritative");	Debug("%s: reply:     tc = %u (message %s)", desctask(t), t->hdr.tc, t->hdr.tc ? "truncated" : "not truncated");	Debug("%s: reply:     rd = %u (%s)", desctask(t), t->hdr.rd, t->hdr.rd ? "recursion desired" : "no recursion");	Debug("%s: reply:     ra = %u (recursion %s)", desctask(t), t->hdr.ra, t->hdr.ra ? "available" : "unavailable");	Debug("%s: reply:  rcode = %u (%s)", desctask(t), t->hdr.rcode, mydns_rcode_str(t->hdr.rcode));	/* escdata(t->reply, t->replylen); */#endif}/*--- build_reply() -----------------------------------------------------------------------------*//* vi:set ts=3: *//* NEED_PO */

⌨️ 快捷键说明

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