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

📄 lwdnsq.c

📁 This a good VPN source
💻 C
字号:
/* * DNS KEY lookup helper * Copyright (C) 2002 Michael Richardson <mcr@freeswan.org> *  * 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.  See <http://www.fsf.org/copyleft/gpl.txt>. *  * 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. */char tncfg_c_version[] = "RCSID $Id: lwdnsq.c,v 1.19 2004/12/02 06:16:19 mcr Exp $";#include <stdio.h>#include <string.h>#include <stdlib.h> #include <unistd.h> #include <errno.h>#include <getopt.h>#include <setjmp.h>#include <ctype.h>#include <signal.h>#include <time.h>#include <isc/lang.h>#include <isc/magic.h>#include <isc/types.h>#include <isc/result.h>#include <isc/mem.h>#include <isc/buffer.h>#include <isc/region.h>#include <dns/name.h>#include <dns/rdata.h>#include <dns/rdatastruct.h>#include <lwres/netdb.h>#include <lwres/async.h>#include "lwdnsq.h"FILE *cmdlog = NULL;extern int EF_DISABLE_BANNER;extern int EF_ALIGNMENT;extern int EF_PROTECT_BELOW;extern int EF_PROTECT_FREE;extern int EF_ALLOW_MALLOC_0;extern int EF_FREE_WIPES;static voidusage(char *name){		fprintf(stdout,"%s\n", name);	exit(1);}static struct option const longopts[] ={	{"prompt", 0, 0, 'i'},	{"serial", 0, 0, 's'},	{"debug",  0, 0, 'g'},	{"log",    1, 0, 'l'},	{"regress",0, 0, 'X'},	{"ignoreeof",0, 0, 'Z'},	{0, 0, 0, 0}};/* globals */jmp_buf getMeOut;static void sig_handler(int sig){  fprintf(stderr, "Caught signal %d, cleaning up and exiting\n", sig);  longjmp(getMeOut, 1);}static void cmdprompt(dnskey_glob *gs){	if(gs->prompt) {		printf("lwdnsq> ");	}	fflush(gs->cmdproto_out);}static void quitprog(dnskey_glob *gs,		     int argc UNUSED,		     char **argv UNUSED){	argc = argc;	argv = argv;	gs->done=1;}static void setdebug(dnskey_glob *gs,	      int argc,	      char **argv){	if(argc > 1) {		gs->debug=strtoul(argv[1],NULL,0);	}	printf("0 DEBUG is %d\n",gs->debug);}static int cmdparse(dnskey_glob *gs,	     char *cmdline){	char *argv[256];	int   argc;	char *arg;	static const struct cmd_entry {		const char *cmdname;		void (*cmdfunc)(dnskey_glob *, int, char **);	} cmds[]={		{"key",       lookup_key},		{"key4",      lookup_key4},		{"key6",      lookup_key6},		{"txt",       lookup_txt},		{"txt4",      lookup_txt4},		{"txt6",      lookup_txt6},		{"ipseckey",  lookup_ipseckey},		{"ipseckey4", lookup_ipseckey4},		{"ipseckey6", lookup_ipseckey6},		{"oe4",       lookup_oe4},		{"oe6",       lookup_oe6},		{"vpn4",      lookup_key4},		{"vpn6",      lookup_key6},		{"quit",      quitprog},		{"a",         lookup_a},		{"aaaa",      lookup_aaaa},		{"debug",     setdebug},		{NULL,        NULL}};	const struct cmd_entry *ce = cmds;	if(cmdlog != NULL) {		fprintf(cmdlog, "%lu|%s\n", time(NULL), cmdline);		fflush(cmdlog);	}	argc=0;		/* skip initial spaces */	while(cmdline && isspace(*cmdline)) {		cmdline++;	}	while(cmdline && *cmdline!='\0' &&	      (arg=strsep(&cmdline, " \t\n"))!=NULL) {	  if (argc < (signed)(sizeof(argv)/sizeof(*argv - 1))) {	    /* ignore arguments that would overflow.	     * XXX should generate a diagnostic.	     */	    argv[argc++]=arg;	  }	  while(cmdline && isspace(*cmdline)) {	    cmdline++;	  }	}	argv[argc]=NULL;	if(argc==0 || argv[0][0]=='\0') {	    /* ignore empty line */	} else if(strcasecmp("help", argv[0]) == 0) {	    fprintf(gs->cmdproto_out, "0 HELP\n");	    for (; ce->cmdname != NULL; ce++)		fprintf(gs->cmdproto_out, "0 HELP %s\n", ce->cmdname);	} else {	    for (;; ce++) {		if (ce->cmdname == NULL) {		    fprintf(gs->cmdproto_out, "0 FATAL unknown command \"%s\"\n", argv[0]);		    break;		}		if(strcasecmp(ce->cmdname, argv[0])==0) {		    (*ce->cmdfunc)(gs, argc, argv);		    break;		}	    }	}	if (!gs->done) {		gs->promptnow = 1;	}	return 0;}static int cmdread(dnskey_glob *gs,		   char  *buf,		   int    len){	unsigned char *nl;	int   cmdlen;	cmdlen=0;	/* 	 * have to handle partial reads and multiple commands	 * per read, since this may in fact be a file or a pipe.	 */	if((gs->cmdloc + len + 1) > sizeof(gs->cmdbuf)) {		fprintf(stderr, "command '%.*s...' is too long, discarding!\n",			40, buf);		fflush(stdout);				gs->cmdloc=0;		return 0;	}	memcpy(gs->cmdbuf+gs->cmdloc, buf, len);	gs->cmdloc+=len;	gs->cmdbuf[gs->cmdloc]='\0';	while((nl = strchr(gs->cmdbuf, '\n')) != NULL) {		/* found a newline, so turn it into a \0, and process the		 * command, and then we will pull the rest of the buffer		 * up.		 */		*nl='\0';		cmdlen= nl - gs->cmdbuf +1;		cmdparse(gs, gs->cmdbuf);		gs->cmdloc -= cmdlen;		memmove(gs->cmdbuf, gs->cmdbuf+cmdlen, gs->cmdloc);	}	return 1;}intmain(int argc, char *argv[]){	char *program_name;	dnskey_glob gs;	int c;	static int ignoreeof=0;  /* static to avoid longjmp clobber */	int ineof;	char *logfilename=NULL;	memset(&gs, 0, sizeof(dnskey_glob));#if 0	printf("PID: %d\n", getpid());	sleep(60);#endif#ifdef EFENCE	EF_DISABLE_BANNER=1;	/* EF_ALIGNMENT=4; */	EF_PROTECT_BELOW=1;	EF_PROTECT_FREE=1;	/* EF_ALLOW_MALLOC_0; */	EF_FREE_WIPES=1;#endif	{ 			FILE *newerr;			newerr = fopen("/var/tmp/lwdnsq.log", "a+");			if(newerr) {				close(2);				dup2(fileno(newerr), 2);				fclose(newerr);			}			fprintf(stderr, "stderr capture started\n");			setbuf(stderr, NULL);	}	program_name = argv[0];	gs.concurrent = 1;	if(lwres_async_init(&gs.lwctx) != ERRSET_SUCCESS) {		fprintf(stderr, "Can not initialize async context\n");		exit(3);	}	if(isc_mem_create(0,0,&gs.iscmem) != ISC_R_SUCCESS) {		fprintf(stderr, "Can not initialize isc memory allocator\n");		exit(4);	}	if(isc_buffer_allocate(gs.iscmem, &gs.iscbuf, LWDNSQ_RESULT_LEN_MAX)) {		fprintf(stderr, "Can not allocate a result buffer\n");		exit(5);	}	while((c = getopt_long_only(argc, argv, "dgl:siXZ", longopts, 0)) != EOF) {		switch(c) {		case 'd':			gs.debug+=2;			logfilename="/var/tmp/lwdns.req.log";			break;		case 'g':			gs.debug++;			break;		case 's':			gs.concurrent=0;			break;		case 'i':			gs.prompt=1;			break;		case 'X':			gs.regress++;			break;		case 'l':			logfilename=optarg;			break;		case 'Z':			ignoreeof=1;			break;		default:			usage(program_name);			break;		}	}	if(gs.debug && ignoreeof) {		fprintf(stderr, "Ignoring end of file\n");	}	if(isatty(0)) {		gs.prompt=1;	}	if(logfilename != NULL) {	  cmdlog = fopen(logfilename, "w");	  if(cmdlog == NULL) {	    fprintf(stderr, "Can not open %s: %s\n", logfilename, strerror(errno));	  }	}	/* do various bits of setup */	if(setjmp(getMeOut)!=0) {		signal(SIGINT,  SIG_DFL);		signal(SIGPIPE, SIG_IGN);				/* cleanup_crap(); */				exit(1);	}		if(signal(SIGINT, sig_handler) == SIG_ERR)		perror("Setting handler for SIGINT");		if(signal(SIGPIPE, sig_handler) == SIG_ERR)		perror("Setting handler for SIGINT");		cmdprompt(&gs);	ineof = 0;	gs.done = 0;	gs.cmdproto_out = stdout;	while(!gs.done) 	{		int    timeout;		char   buf[128];		int    n;		int    rlen, err2;		timeout = LWDNSQ_RETRANSMIT_INTERVAL * 1000;		/* 		 * do not prompt for more items, or look for HUP if		 * we are in serial mode.. We know we are working		 * if there are questions in flight. 		 */		gs.l_fds[1].events = 0;		if(gs.concurrent || gs.dns_inflight == 0) {			if(gs.promptnow && gs.prompt) {				cmdprompt(&gs);				gs.promptnow = FALSE;			}			gs.l_fds[1].events = POLLIN;			if(!ignoreeof) {				gs.l_fds[1].events |= POLLHUP;			}			gs.l_nfds = 2;		} else {			gs.l_fds[1].events = 0;			gs.l_nfds = 1;		}					gs.l_fds[1].revents = 0;		gs.l_fds[0].events = POLLIN|POLLHUP;		gs.l_fds[0].revents = 0;		gs.l_fds[0].fd = lwres_async_fd(gs.lwctx);		if(gs.debug > 1) {			fprintf(stderr, "=== invoking poll(,%d,%d)\n",				gs.l_nfds, timeout);			for(n = 0; n < gs.l_nfds; n++) {				fprintf(stderr, "=== waiting on fd#%d\n",					gs.l_fds[n].fd);			}			fprintf(stderr, "=== inflight: %d\n", gs.dns_inflight);		}		errno = 0;		n = poll(gs.l_fds, gs.l_nfds, timeout);		err2 = errno;		/* there was some activity, so look for pending retransmits		 * first, even if it wasn't due to the timeout.		 */		{			struct dnskey_lookup *dl, *dlthis;						dl = gs.dns_outstanding;						while(dl) {				/* dl could go away */				dlthis = dl;				dl = dl->next;				dns_rexmit(&gs, dlthis, 0);			}		}		if(n < 0) {			perror("poll");		}		if(gs.debug > 1) {			fprintf(stderr, "=== poll returned with %d\n", n);		}						while(n>0) {			if((gs.l_fds[0].revents & POLLERR) == POLLERR ||			   (gs.l_fds[1].revents & POLLERR) == POLLERR)			{				struct dnskey_lookup *dl, *dlthis;				if(gs.debug > 1) {					fprintf(stderr, "=== poll returned error %s\n",						strerror(err2));				}				/* on error, we force retransmit, because				 * one reasonable source of errors it because				 * the named isn't ready yet.				 */				sleep(1);							dl = gs.dns_outstanding;				while(dl) {					/* dl could go away */					dlthis = dl;					dl = dl->next;										dns_rexmit(&gs, dlthis, 1);				}				n = 0;				break;			}			/* see if there are DNS events coming back */			if((gs.l_fds[0].revents & POLLIN) == POLLIN) {				if(gs.debug > 1) {					fprintf(stderr,						"=== new responses from lwdnsd\n");				}				process_dns_reply(&gs);				fflush(stdout);				n--;			}			if(!ignoreeof &&			   (gs.l_fds[1].revents & POLLHUP) == POLLHUP)			{				break;			}			if((gs.l_fds[1].revents & POLLIN) == POLLIN) {								rlen=read(0, buf, sizeof(buf));				if(gs.debug > 1) {					if(rlen > 0) {						buf[rlen]='\0';					}					fprintf(stderr,						"=== new commands on fd 0: %d: %s\n",						rlen, buf);				}				if(rlen > 0) {					cmdread(&gs, buf, rlen);				} else if(rlen == 0) {					ineof = 1;					if(!ignoreeof) {						/* EOF, die */						gs.done=1;					}				}				n--;			} 		}		if((gs.l_fds[1].revents & POLLHUP) == POLLHUP)		{			ineof = 1;			if(!ignoreeof)			{				gs.done=1;			}		}		if(ignoreeof) {			/* if we have exhausted the input,			 * and there are none in flight,			 * then exit, finally.			 */			if(ineof) { 				if(gs.dns_inflight == 0) {					gs.done=1;				}			}		}		if(gs.debug) {			fprintf(stderr, "=== ineof: %d inflight: %d\n",				ineof, gs.dns_inflight);		}	}	signal(SIGINT,  SIG_DFL);	signal(SIGPIPE, SIG_IGN);  	exit(0);}	/* * $Log: lwdnsq.c,v $ * Revision 1.19  2004/12/02 06:16:19  mcr * 	fixed long standing bug with async resolver when there was * 	more than one outstanding request. * * Revision 1.18  2004/11/25 18:16:47  mcr * 	make sure to actually open the log file. * * Revision 1.17  2004/11/24 01:36:10  mcr * 	if debugging is on, then log all requests that are sent, * 	so that we can later replay, looking for bugs. * * Revision 1.16  2003/12/02 04:34:09  mcr * 	if lwresd does not start early enough, then the request is * 	lost and never retransmitted. This version can now deal with * 	named being slow to start, or taking along time to verify * 	DNSSEC signatures. * 	This also fixes the non-concurrent stuff. * * Revision 1.15  2003/12/02 02:55:19  mcr * 	prompting in non-concurrent mode looks right now. * 	do not ask for EOF messages from stdin if we are in ignoreeof * 	mode. * * Revision 1.14  2003/12/01 21:45:17  mcr * 	the lwctx structure needs to be properly initialized. * 	the lwdnsq program needs to have the --serial option finished, * 	and a retransmitter installed. * * Revision 1.13  2003/09/19 02:56:11  mcr * 	fixes to make lwdnsq compile with strictest compile flags. * * Revision 1.12  2003/09/16 05:01:14  mcr * 	prefix all debugging with === so that it can be easily removed. * * Revision 1.11  2003/09/10 04:43:52  mcr * 	final fixes to lwdnsq to exit only when all requests are done, * 	and we have been told to wait, *OR* if there is an EOF in stdin. * * Revision 1.10  2003/09/03 01:13:24  mcr * 	first attempt at async capable lwdnsq. * * Revision 1.9  2003/04/02 07:37:57  dhr * * lwdnsq: fix non-deterministic bug in handling batched input * * Revision 1.8  2003/02/08 04:03:06  mcr * 	renamed --single to --serial. * * Revision 1.7  2003/01/14 03:01:14  dhr * * improve diagnostics; tidy * * Revision 1.6  2002/12/19 07:29:47  dhr * * - avoid (improbable) buffer overflow * - suppress prompt after "quit" command * - add space to prompt to match aesthetics and man page * - elminate a magic number * * Revision 1.5  2002/12/19 07:08:42  dhr * * continue renaming dnskey => lwdnsq * * Revision 1.4  2002/12/12 06:03:41  mcr * 	added --regress option to force times to be regular * * Revision 1.3  2002/11/25 18:37:48  mcr * 	make sure that we exit cleanly upon EOF. * * Revision 1.2  2002/11/16 02:53:53  mcr * 	lwdnsq - with new contract added. * * Revision 1.1  2002/10/30 02:25:31  mcr * 	renamed version of files from dnskey/ * * Revision 1.3  2002/10/09 20:14:16  mcr * 	make sure to flush stdout at the right time - do it regardless * 	of whether or not we are printing prompts. * * Revision 1.2  2002/09/30 18:55:54  mcr * 	skeleton for dnskey helper program. * * Revision 1.1  2002/09/30 16:50:23  mcr * 	documentation for "dnskey" helper * * Local variables: * c-file-style: "linux" * c-basic-offset: 2 * End: * */

⌨️ 快捷键说明

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