📄 nsupdate.c
字号:
/* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. *//* $Id: nsupdate.c,v 1.103.2.15.2.16 2004/06/17 01:00:38 sra Exp $ */#include <config.h>#include <ctype.h>#include <errno.h>#include <limits.h>#include <stdlib.h>#include <unistd.h>#include <isc/app.h>#include <isc/base64.h>#include <isc/buffer.h>#include <isc/commandline.h>#include <isc/entropy.h>#include <isc/event.h>#include <isc/hash.h>#include <isc/lex.h>#include <isc/mem.h>#include <isc/parseint.h>#include <isc/region.h>#include <isc/sockaddr.h>#include <isc/socket.h>#include <isc/stdio.h>#include <isc/string.h>#include <isc/task.h>#include <isc/timer.h>#include <isc/types.h>#include <isc/util.h>#include <dns/callbacks.h>#include <dns/dispatch.h>#include <dns/dnssec.h>#include <dns/events.h>#include <dns/fixedname.h>#include <dns/masterdump.h>#include <dns/message.h>#include <dns/name.h>#include <dns/rcode.h>#include <dns/rdata.h>#include <dns/rdataclass.h>#include <dns/rdatalist.h>#include <dns/rdataset.h>#include <dns/rdatastruct.h>#include <dns/rdatatype.h>#include <dns/request.h>#include <dns/result.h>#include <dns/tsig.h>#include <dst/dst.h>#include <lwres/lwres.h>#include <lwres/net.h>#include <bind9/getaddresses.h>#ifdef HAVE_ADDRINFO#ifdef HAVE_GETADDRINFO#ifdef HAVE_GAISTRERROR#define USE_GETADDRINFO#endif#endif#endif#ifndef USE_GETADDRINFO#ifndef ISC_PLATFORM_NONSTDHERRNOextern int h_errno;#endif#endif#define MAXCMD (4 * 1024)#define MAXWIRE (64 * 1024)#define PACKETSIZE ((64 * 1024) - 1)#define INITTEXT (2 * 1024)#define MAXTEXT (128 * 1024)#define FIND_TIMEOUT 5#define TTL_MAX 2147483647U /* Maximum signed 32 bit integer. */#define DNSDEFAULTPORT 53#ifndef RESOLV_CONF#define RESOLV_CONF "/etc/resolv.conf"#endifstatic isc_boolean_t debugging = ISC_FALSE, ddebugging = ISC_FALSE;static isc_boolean_t memdebugging = ISC_FALSE;static isc_boolean_t have_ipv4 = ISC_FALSE;static isc_boolean_t have_ipv6 = ISC_FALSE;static isc_boolean_t is_dst_up = ISC_FALSE;static isc_boolean_t usevc = ISC_FALSE;static isc_taskmgr_t *taskmgr = NULL;static isc_task_t *global_task = NULL;static isc_event_t *global_event = NULL;static isc_mem_t *mctx = NULL;static dns_dispatchmgr_t *dispatchmgr = NULL;static dns_requestmgr_t *requestmgr = NULL;static isc_socketmgr_t *socketmgr = NULL;static isc_timermgr_t *timermgr = NULL;static dns_dispatch_t *dispatchv4 = NULL;static dns_dispatch_t *dispatchv6 = NULL;static dns_message_t *updatemsg = NULL;static dns_fixedname_t fuserzone;static dns_name_t *userzone = NULL;static dns_tsigkey_t *tsigkey = NULL;static dst_key_t *sig0key;static lwres_context_t *lwctx = NULL;static lwres_conf_t *lwconf;static isc_sockaddr_t *servers;static int ns_inuse = 0;static int ns_total = 0;static isc_sockaddr_t *userserver = NULL;static isc_sockaddr_t *localaddr = NULL;static char *keystr = NULL, *keyfile = NULL;static isc_entropy_t *entp = NULL;static isc_boolean_t shuttingdown = ISC_FALSE;static FILE *input;static isc_boolean_t interactive = ISC_TRUE;static isc_boolean_t seenerror = ISC_FALSE;static const dns_master_style_t *style;static int requests = 0;static unsigned int timeout = 300;static unsigned int udp_timeout = 3;static unsigned int udp_retries = 3;static dns_rdataclass_t defaultclass = dns_rdataclass_in;static dns_rdataclass_t zoneclass = dns_rdataclass_none;static dns_message_t *answer = NULL;typedef struct nsu_requestinfo { dns_message_t *msg; isc_sockaddr_t *addr;} nsu_requestinfo_t;static voidsendrequest(isc_sockaddr_t *srcaddr, isc_sockaddr_t *destaddr, dns_message_t *msg, dns_request_t **request);static voidfatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);static voiddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);static voidddebug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);#define STATUS_MORE (isc_uint16_t)0#define STATUS_SEND (isc_uint16_t)1#define STATUS_QUIT (isc_uint16_t)2#define STATUS_SYNTAX (isc_uint16_t)3static dns_rdataclass_tgetzoneclass(void) { if (zoneclass == dns_rdataclass_none) zoneclass = defaultclass; return (zoneclass);}static isc_boolean_tsetzoneclass(dns_rdataclass_t rdclass) { if (zoneclass == dns_rdataclass_none || rdclass == dns_rdataclass_none) zoneclass = rdclass; if (zoneclass != rdclass) return (ISC_FALSE); return (ISC_TRUE);}static voidfatal(const char *format, ...) { va_list args; va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); exit(1);}static voiddebug(const char *format, ...) { va_list args; if (debugging) { va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); }}static voidddebug(const char *format, ...) { va_list args; if (ddebugging) { va_start(args, format); vfprintf(stderr, format, args); va_end(args); fprintf(stderr, "\n"); }}static inline voidcheck_result(isc_result_t result, const char *msg) { if (result != ISC_R_SUCCESS) fatal("%s: %s", msg, isc_result_totext(result));}static void *mem_alloc(void *arg, size_t size) { return (isc_mem_get(arg, size));}static voidmem_free(void *arg, void *mem, size_t size) { isc_mem_put(arg, mem, size);}static char *nsu_strsep(char **stringp, const char *delim) { char *string = *stringp; char *s; const char *d; char sc, dc; if (string == NULL) return (NULL); for (; *string != '\0'; string++) { sc = *string; for (d = delim; (dc = *d) != '\0'; d++) { if (sc == dc) break; } if (dc == 0) break; } for (s = string; *s != '\0'; s++) { sc = *s; for (d = delim; (dc = *d) != '\0'; d++) { if (sc == dc) { *s++ = '\0'; *stringp = s; return (string); } } } *stringp = NULL; return (string);}static voidreset_system(void) { isc_result_t result; ddebug("reset_system()"); /* If the update message is still around, destroy it */ if (updatemsg != NULL) dns_message_reset(updatemsg, DNS_MESSAGE_INTENTRENDER); else { result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &updatemsg); check_result(result, "dns_message_create"); } updatemsg->opcode = dns_opcode_update;}static voidsetup_keystr(void) { unsigned char *secret = NULL; int secretlen; isc_buffer_t secretbuf; isc_result_t result; isc_buffer_t keynamesrc; char *secretstr; char *s; dns_fixedname_t fkeyname; dns_name_t *keyname; dns_fixedname_init(&fkeyname); keyname = dns_fixedname_name(&fkeyname); debug("Creating key..."); s = strchr(keystr, ':'); if (s == NULL || s == keystr || *s == 0) fatal("key option must specify keyname:secret"); secretstr = s + 1; isc_buffer_init(&keynamesrc, keystr, s - keystr); isc_buffer_add(&keynamesrc, s - keystr); debug("namefromtext"); result = dns_name_fromtext(keyname, &keynamesrc, dns_rootname, ISC_FALSE, NULL); check_result(result, "dns_name_fromtext"); secretlen = strlen(secretstr) * 3 / 4; secret = isc_mem_allocate(mctx, secretlen); if (secret == NULL) fatal("out of memory"); isc_buffer_init(&secretbuf, secret, secretlen); result = isc_base64_decodestring(secretstr, &secretbuf); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not create key from %s: %s\n", keystr, isc_result_totext(result)); goto failure; } secretlen = isc_buffer_usedlength(&secretbuf); debug("keycreate"); result = dns_tsigkey_create(keyname, dns_tsig_hmacmd5_name, secret, secretlen, ISC_TRUE, NULL, 0, 0, mctx, NULL, &tsigkey); if (result != ISC_R_SUCCESS) fprintf(stderr, "could not create key from %s: %s\n", keystr, dns_result_totext(result)); failure: if (secret != NULL) isc_mem_free(mctx, secret);}static voidsetup_keyfile(void) { dst_key_t *dstkey = NULL; isc_result_t result; debug("Creating key..."); result = dst_key_fromnamedfile(keyfile, DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx, &dstkey); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not read key from %s: %s\n", keyfile, isc_result_totext(result)); return; } if (dst_key_alg(dstkey) == DST_ALG_HMACMD5) { result = dns_tsigkey_createfromkey(dst_key_name(dstkey), dns_tsig_hmacmd5_name, dstkey, ISC_FALSE, NULL, 0, 0, mctx, NULL, &tsigkey); if (result != ISC_R_SUCCESS) { fprintf(stderr, "could not create key from %s: %s\n", keyfile, isc_result_totext(result)); dst_key_free(&dstkey); return; } } else sig0key = dstkey;}static voiddoshutdown(void) { isc_task_detach(&global_task); if (userserver != NULL) isc_mem_put(mctx, userserver, sizeof(isc_sockaddr_t)); if (localaddr != NULL) isc_mem_put(mctx, localaddr, sizeof(isc_sockaddr_t)); if (tsigkey != NULL) { ddebug("Freeing TSIG key"); dns_tsigkey_detach(&tsigkey); } if (sig0key != NULL) { ddebug("Freeing SIG(0) key"); dst_key_free(&sig0key); } if (updatemsg != NULL) dns_message_destroy(&updatemsg); if (is_dst_up) { ddebug("Destroy DST lib"); dst_lib_destroy(); is_dst_up = ISC_FALSE; } if (entp != NULL) { ddebug("Detach from entropy"); isc_entropy_detach(&entp); } lwres_conf_clear(lwctx); lwres_context_destroy(&lwctx); isc_mem_put(mctx, servers, ns_total * sizeof(isc_sockaddr_t)); ddebug("Destroying request manager"); dns_requestmgr_detach(&requestmgr); ddebug("Freeing the dispatchers"); if (have_ipv4) dns_dispatch_detach(&dispatchv4); if (have_ipv6) dns_dispatch_detach(&dispatchv6); ddebug("Shutting down dispatch manager"); dns_dispatchmgr_destroy(&dispatchmgr);}static voidmaybeshutdown(void) { ddebug("Shutting down request manager"); dns_requestmgr_shutdown(requestmgr); if (requests != 0) return; doshutdown();}static voidshutdown_program(isc_task_t *task, isc_event_t *event) { REQUIRE(task == global_task); UNUSED(task); ddebug("shutdown_program()"); isc_event_free(&event); shuttingdown = ISC_TRUE; maybeshutdown();}static voidsetup_system(void) { isc_result_t result; isc_sockaddr_t bind_any, bind_any6; lwres_result_t lwresult; unsigned int attrs, attrmask; int i; ddebug("setup_system()"); dns_result_register(); result = isc_net_probeipv4(); if (result == ISC_R_SUCCESS) have_ipv4 = ISC_TRUE; result = isc_net_probeipv6(); if (result == ISC_R_SUCCESS) have_ipv6 = ISC_TRUE; if (!have_ipv4 && !have_ipv6) fatal("could not find either IPv4 or IPv6"); result = isc_mem_create(0, 0, &mctx); check_result(result, "isc_mem_create"); lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1); if (lwresult != LWRES_R_SUCCESS) fatal("lwres_context_create failed"); (void)lwres_conf_parse(lwctx, RESOLV_CONF); lwconf = lwres_conf_get(lwctx); ns_total = lwconf->nsnext; if (ns_total <= 0) { /* No name servers in resolv.conf; default to loopback. */ struct in_addr localhost; ns_total = 1; servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t)); if (servers == NULL) fatal("out of memory"); localhost.s_addr = htonl(INADDR_LOOPBACK); isc_sockaddr_fromin(&servers[0], &localhost, DNSDEFAULTPORT); } else { servers = isc_mem_get(mctx, ns_total * sizeof(isc_sockaddr_t)); if (servers == NULL) fatal("out of memory"); for (i = 0; i < ns_total; i++) { if (lwconf->nameservers[i].family == LWRES_ADDRTYPE_V4) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -