diff options
author | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2006-05-22 05:12:18 +0000 |
---|---|---|
committer | Rene Mayrhofer <rene@mayrhofer.eu.org> | 2006-05-22 05:12:18 +0000 |
commit | aa0f5b38aec14428b4b80e06f90ff781f8bca5f1 (patch) | |
tree | 95f3d0c8cb0d59d88900dbbd72110d7ab6e15b2a /programs/lwdnsq/lwdnsq.c | |
parent | 7c383bc22113b23718be89fe18eeb251942d7356 (diff) | |
download | vyos-strongswan-aa0f5b38aec14428b4b80e06f90ff781f8bca5f1.tar.gz vyos-strongswan-aa0f5b38aec14428b4b80e06f90ff781f8bca5f1.zip |
Import initial strongswan 2.7.0 version into SVN.
Diffstat (limited to 'programs/lwdnsq/lwdnsq.c')
-rw-r--r-- | programs/lwdnsq/lwdnsq.c | 506 |
1 files changed, 506 insertions, 0 deletions
diff --git a/programs/lwdnsq/lwdnsq.c b/programs/lwdnsq/lwdnsq.c new file mode 100644 index 000000000..2684a7d45 --- /dev/null +++ b/programs/lwdnsq/lwdnsq.c @@ -0,0 +1,506 @@ +/* + * 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.1 2004/03/15 20:35:28 as Exp $"; + + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> + +#include <freeswan.h> + +#include <errno.h> +#include <getopt.h> +#include <setjmp.h> +#include <ctype.h> +#include <signal.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" + +static void +usage(char *name) +{ + fprintf(stdout,"%s --attach --virtual <virtual-device> --physical <physical-device>\n", + name); + exit(1); +} + +static struct option const longopts[] = +{ + {"prompt", 0, 0, 'i'}, + {"serial", 0, 0, 's'}, + {"debug", 0, 0, 'g'}, + {"regress",0, 0, 'X'}, + {"ignoreeof",0, 0, 'Z'}, + {0, 0, 0, 0} +}; + +/* globals */ +jmp_buf getMeOut; + +void sig_handler(int sig) +{ + fprintf(stderr, "Caught signal %d, cleaning up and exiting\n", sig); + longjmp(getMeOut, 1); +} + +void cmdprompt(dnskey_glob *gs) +{ + if(gs->prompt) { + printf("lwdnsq> "); + } + fflush(gs->cmdproto_out); +} + +void quitprog(dnskey_glob *gs, + int argc, + char **argv) +{ + gs->done=1; +} + +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); +} + + +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; + + argc=0; + + /* skip initial spaces */ + while(cmdline && isspace(*cmdline)) { + cmdline++; + } + + while(cmdline && *cmdline!='\0' && + (arg=strsep(&cmdline, " \t\n"))!=NULL) { + if (argc < 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) + cmdprompt(gs); + return 0; +} + +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; +} + +int +main(int argc, char *argv[]) +{ + char *program_name; + dnskey_glob gs; + int c; + static int ignoreeof=0; /* static to avoid longjmp clobber */ + int ineof; + + memset(&gs, 0, sizeof(dnskey_glob)); + +#if 0 + printf("PID: %d\n", getpid()); + sleep(60); +#endif + + 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, "dgsiXZ", longopts, 0)) != EOF) { + switch(c) { + case 'd': + gs.debug+=2; + break; + + case 'g': + gs.debug++; + break; + case 's': + gs.concurrent=0; + break; + case 'i': + gs.prompt=1; + break; + case 'X': + gs.regress++; + 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; + } + + /* 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) < 0) + perror("Setting handler for SIGINT"); + + if(signal(SIGPIPE, sig_handler) < 0) + perror("Setting handler for SIGINT"); + + cmdprompt(&gs); + + ineof = 0; + gs.done = 0; + gs.cmdproto_out = stdout; + gs.l_fds[0].events = POLLIN|POLLHUP; + gs.l_fds[0].fd=0; + + gs.l_fds[1].events = POLLIN|POLLHUP|POLLERR; + gs.l_fds[1].fd = lwres_async_fd(gs.lwctx); + + gs.l_nfds= 2; + + while(!gs.done) + { + int timeout; + char buf[128]; + int n; + int rlen; + + timeout=-1; + + gs.l_fds[0].revents = 0; + + gs.l_fds[1].events = POLLIN|POLLHUP|POLLERR; + gs.l_fds[1].revents = 0; + gs.l_fds[1].fd = lwres_async_fd(gs.lwctx); + + if(gs.debug > 1) { + fprintf(stderr, "=== invoking poll(,%d,) with %s\n", + gs.l_nfds, + timeout>0 ? "waittime" : "no wait"); + 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); + } + + n = poll(gs.l_fds, gs.l_nfds, timeout); + + if(n == 0) { + /* timeout! */ + } + + 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) + { + break; + } + + /* see if there are DNS events coming back */ + if((gs.l_fds[1].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[0].revents & POLLHUP) == POLLHUP) + { + break; + } + + if((gs.l_fds[0].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[0].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.1 2004/03/15 20:35:28 as + * added files from freeswan-2.04-x509-1.5.3 + * + * 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: + * + */ |