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

📄 axfr.c

📁 此dns服务器是在mydns基础上改写
💻 C
字号:
/**************************************************************************************************	$Id: axfr.c,v 1.39 2005/05/06 16:06:18 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_AXFR	1#define	AXFR_TIME_LIMIT		3600		/* AXFR may not take more than this long, overall */static size_t total_records, total_octets;/**************************************************************************************************	AXFR_ERROR	Quits and outputs a warning message.**************************************************************************************************//* Stupid compiler doesn't know exit from _exit... *//* static void axfr_error(TASK *, const char *, ...) __attribute__ ((__noreturn__)); */static voidaxfr_error(TASK *t, const char *fmt, ...){	va_list	ap;	char		msg[BUFSIZ];	va_start(ap, fmt);	vsnprintf(msg, sizeof(msg), fmt, ap);	va_end(ap);	if (t)		task_output_info(t, NULL);	else		Warnx("%s", msg);	sockclose(t->fd);	_exit(EXIT_FAILURE);	/* NOTREACHED */}/*--- axfr_error() ------------------------------------------------------------------------------*//**************************************************************************************************	AXFR_TIMEOUT	Hard timeout called by SIGALRM after one hour.**************************************************************************************************/static voidaxfr_timeout(int dummy){	axfr_error(NULL, _("AXFR timed out"));}/*--- axfr_timeout() ----------------------------------------------------------------------------*//**************************************************************************************************	AXFR_WRITE_WAIT	Wait for the client to become ready to read.  Times out after `task_timeout' seconds.**************************************************************************************************/static voidaxfr_write_wait(TASK *t){	fd_set	wfd;	struct timeval tv;	int		rv;	FD_ZERO(&wfd);	FD_SET(t->fd, &wfd);	tv.tv_sec = task_timeout;	tv.tv_usec = 0;	if ((rv = select(t->fd + 1, NULL, &wfd, NULL, &tv)) < 0)		axfr_error(t, "%s: %s", _("select"), strerror(errno));	if (rv != 1 || !FD_ISSET(t->fd, &wfd))		axfr_error(t, _("write timeout"));}/*--- axfr_write_wait() -------------------------------------------------------------------------*//**************************************************************************************************	AXFR_WRITE	Writes the specified buffer, obeying task_timeout (via axfr_write_wait).**************************************************************************************************/static voidaxfr_write(TASK *t, char *buf, size_t size){	int		rv;	size_t	offset = 0;	do	{		axfr_write_wait(t);		if ((rv = write(t->fd, buf+offset, size-offset)) < 0)			axfr_error(t, "write: %s", strerror(errno));		if (!rv)			axfr_error(t, _("client closed connection"));		offset += rv;	} while (offset < size);}/*--- axfr_write() ------------------------------------------------------------------------------*//**************************************************************************************************	AXFR_REPLY	Sends one reply to the client.**************************************************************************************************/static voidaxfr_reply(TASK *t){	char len[2], *l = len;	build_reply(t, 0);	DNS_PUT16(l, t->replylen);	axfr_write(t, len, SIZE16);	axfr_write(t, t->reply, t->replylen);	total_octets += SIZE16 + t->replylen;	total_records++;	/* Reset the pertinent parts of the task reply data */	rrlist_free(&t->an);	rrlist_free(&t->ns);	rrlist_free(&t->ar);	Free(t->reply);	t->replylen = 0;	name_forget(t);	Free(t->rdata);	t->rdlen = 0;	/* Nuke question data */	t->qdcount = 0;	t->qdlen = 0;}/*--- axfr_reply() ------------------------------------------------------------------------------*//**************************************************************************************************	CHECK_XFER	If the "xfer" column exists in the soa table, it should contain a list of wildcards separated	by commas.  In order for this zone transfer to continue, one of the wildcards must match	the client's IP address.**************************************************************************************************/static voidcheck_xfer(TASK *t, MYDNS_SOA *soa){	SQL_RES	*res = NULL;	SQL_ROW	row;	char		ip[256];	char		query[512];	size_t	querylen;	int		ok = 0;	if (!mydns_soa_use_xfer)		return;	strncpy(ip, clientaddr(t), sizeof(ip)-1);	querylen = snprintf(query, sizeof(query), "SELECT xfer FROM %s WHERE id=%u%s",		mydns_soa_table_name, soa->id, mydns_rr_use_active ? " AND active=1" : "");	if (!(res = sql_query(sql, query, querylen)))		ErrSQL(sql, "%s: %s", desctask(t), _("error loading zone transfer access rules"));	if ((row = sql_getrow(res)))	{		char *wild, *r;#if DEBUG_ENABLED && DEBUG_AXFR		Debug("%s: checking AXFR access rule '%s'", desctask(t), row[0]);#endif		for (r = row[0]; !ok && (wild = strsep(&r, ",")); )		{			if (strchr(wild, '/'))			{				if (t->family == AF_INET)					ok = in_cidr(wild, t->addr4.sin_addr);			}			else if (wildcard_match(wild, ip))				ok = 1;		}	}	sql_free(res);	if (!ok)	{		dnserror(t, DNS_RCODE_REFUSED, ERR_NO_AXFR);		axfr_reply(t);		axfr_error(t, _("access denied"));	}}/*--- check_xfer() ------------------------------------------------------------------------------*//**************************************************************************************************	AXFR_ZONE	DNS-based zone transfer.**************************************************************************************************/static voidaxfr_zone(TASK *t, MYDNS_SOA *soa){#if DEBUG_ENABLED && DEBUG_AXFR	Debug("%s: Beginning zone transfer", desctask(t));#endif	/* Check optional "xfer" column and initialize reply */	check_xfer(t, soa);	reply_init(t);	/* Send opening SOA record */	rrlist_add(t, ANSWER, DNS_RRTYPE_SOA, (void *)soa, soa->origin);	axfr_reply(t);#if DEBUG_ENABLED && DEBUG_AXFR	Debug("%s: Initial SOA record sent", desctask(t));#endif	/*	**  Get all resource records for zone (if zone ID is nonzero, i.e. not manufactured)	**  and transmit each resource record.	*/	if (soa->id)	{		MYDNS_RR *ThisRR = NULL, *rr;		if (mydns_rr_load(sql, &ThisRR, soa->id, DNS_QTYPE_ANY, NULL, soa->origin, "") == 0)		{			for (rr = ThisRR; rr; rr = rr->next)			{				int len;#if DEBUG_ENABLED && DEBUG_AXFR				Debug("%s: Examining rr->name '%s'", desctask(t), rr->name);#endif				/* If 'name' doesn't end with a dot, append the origin */				len = strlen(rr->name);				if (rr->name[len-1] != '.')				{#if DEBUG_ENABLED && DEBUG_AXFR					Debug("%s: Appending origin for name '%s'", desctask(t), rr->name);#endif					if (*rr->name)						strcat(rr->name, ".");					strncat(rr->name, soa->origin, sizeof(rr->name) - len - 1);#if DEBUG_ENABLED && DEBUG_AXFR					Debug("%s: rr->name is now '%s'", desctask(t), rr->name);#endif				}#if ALIAS_ENABLED				/* If we have been compiled with alias support and the current record is an alias pass it to alias_recurse() */				if (rr->alias != 0)					alias_recurse(t, ANSWER, rr->name, soa, NULL, rr);				else#endif				rrlist_add(t, ANSWER, DNS_RRTYPE_RR, (void *)rr, rr->name);				/* Transmit this resource record */				axfr_reply(t);			}			mydns_rr_free(ThisRR);		}	}	/* Send closing SOA record */	rrlist_add(t, ANSWER, DNS_RRTYPE_SOA, (void *)soa, soa->origin);	axfr_reply(t);#if DEBUG_ENABLED && DEBUG_AXFR	Debug("%s: Closing SOA record sent", desctask(t));#endif	mydns_soa_free(soa);}/*--- axfr_zone() -------------------------------------------------------------------------------*//**************************************************************************************************	AXFR_GET_SOA	Attempt to find a SOA record.  If SOA id is 0, we made it up.**************************************************************************************************/static MYDNS_SOA *axfr_get_soa(TASK *t){	MYDNS_SOA *soa = NULL;	/*add by zyl 20080331 --begin*/   char*  myip = (char*)malloc(16);   memset(myip,0,sizeof(myip));   iplong_to_ipchs(myip, 16, t->addr4.sin_addr.s_addr);   /*add by zyl 20080331 --end*/   /*add by zyl 20080408 --begin*/   int telecom_operator = 0;   int ipint = 0;   ipchs_to_ipuint32(&ipint,myip);   if(ipint)      get_telecom_operator(&telecom_operator,ipint);   /*add by zyl 20080408 --end*/   free(myip);	/* Try to load SOA */	if (mydns_soa_load(sql, &soa, t->qname,telecom_operator) < 0)	//modi by zyl 080408		ErrSQL(sql, "%s: %s", desctask(t), _("error loading zone"));	if (soa)	{#if DEBUG_ENABLED && DEBUG_AXFR		Debug("AXFR: %s: SOA record %u", soa->origin, soa->id);#endif		return (soa);	}	/* STILL no SOA?  We aren't authoritative */	dnserror(t, DNS_RCODE_REFUSED, ERR_ZONE_NOT_FOUND);	axfr_reply(t);	axfr_error(t, _("unknown zone"));	/* NOTREACHED */	return (NULL);}/*--- axfr_get_soa() ----------------------------------------------------------------------------*//**************************************************************************************************	AXFR	DNS-based zone transfer.  Send all resource records for in QNAME's zone to the client.**************************************************************************************************/voidaxfr(TASK *t){	struct timeval start, finish;								/* Time AXFR began and ended */	MYDNS_SOA *soa;												/* SOA record for zone (may be bogus!) */	/* Do generic startup stuff; this is a child process */	signal(SIGALRM, axfr_timeout);	alarm(AXFR_TIME_LIMIT);	sql = NULL;	db_connect();	gettimeofday(&start, NULL);	total_records = total_octets = 0;	t->no_markers = 1;#if DEBUG_ENABLED && DEBUG_AXFR	Debug("%s: Starting AXFR for task ID %lu", desctask(t), t->internal_id);#endif	/* Get SOA for zone */	soa = axfr_get_soa(t);	/* Transfer that zone */	axfr_zone(t, soa);	/* Report result */	gettimeofday(&finish, NULL);#if DEBUG_ENABLED && DEBUG_AXFR	Debug("AXFR: %u records, %u octets, %.3fs", 		total_records, total_octets,		((finish.tv_sec + finish.tv_usec / 1000000.0) - (start.tv_sec + start.tv_usec / 1000000.0)));#endif	t->qdcount = 1;	t->an.size = total_records;	task_output_info(t, NULL);	sockclose(t->fd);	_exit(EXIT_SUCCESS);}/*--- axfr() ------------------------------------------------------------------------------------*//* vi:set ts=3: *//* NEED_PO */

⌨️ 快捷键说明

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