diff options
| author | Peter Wemm <peter@FreeBSD.org> | 1998-05-03 04:11:49 +0000 |
|---|---|---|
| committer | Peter Wemm <peter@FreeBSD.org> | 1998-05-03 04:11:49 +0000 |
| commit | 4e0ffe0baef832be2a8161229e9e4f7cb18a586a (patch) | |
| tree | 759849259eae9f7cb0d3ddbd7a131081c6688068 /contrib/bind/bin/nsupdate | |
| parent | e2f1a81473c07cf46c3104b8dcfdd992a2fe7ca8 (diff) | |
Notes
Diffstat (limited to 'contrib/bind/bin/nsupdate')
| -rw-r--r-- | contrib/bind/bin/nsupdate/Makefile | 79 | ||||
| -rw-r--r-- | contrib/bind/bin/nsupdate/nsupdate.c | 471 |
2 files changed, 550 insertions, 0 deletions
diff --git a/contrib/bind/bin/nsupdate/Makefile b/contrib/bind/bin/nsupdate/Makefile new file mode 100644 index 000000000000..46806b6efc2c --- /dev/null +++ b/contrib/bind/bin/nsupdate/Makefile @@ -0,0 +1,79 @@ +## Copyright (c) 1996 by 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS +## ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +## OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +## CONSORTIUM 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: Makefile,v 8.18 1997/06/19 03:22:11 halley Exp $ + +DESTDIR= +CC= cc +SHELL= /bin/sh + +CDEBUG= -g + +#(net2 and its descendents) +SYSTYPE = bsdos +TOP = ../.. +INCL = ${TOP}/include +PORTINCL = ${TOP}/port/${SYSTYPE}/include +LIBBIND = ${TOP}/lib/libbind.a +A=a +O=o +LEX = lex -I +SYSLIBS = -ll -lutil +PIDDIR = /var/run +DESTBIN = /usr/local/bin +DESTSBIN = /usr/local/sbin +DESTEXEC = /usr/local/libexec +DESTMAN = /usr/share/man +DESTHELP= /usr/share/misc +STRIP=-s + +LDFLAGS= +CFLAGS= ${CDEBUG} -I${PORTINCL} -I${INCL} + +PROG= nsupdate +SRCS= ${PROG}.c +OBJS= ${PROG}.${O} + +all: ${PROG} + +${PROG}: ${OBJS} ${LIBBIND} Makefile + ${CC} ${CDEBUG} ${LDFLAGS} -o ${PROG} ${OBJS} \ + ${LIBBIND} ${SYSLIBS} + +distclean: clean + +clean: FRC + rm -f ${PROG} ${OBJS} core .depend + rm -f *.BAK *.CKP *~ *.orig + +depend: ${SRCS} + mkdep -p ${CPPFLAGS} -I${INCL} -I${PORTINCL} ${SRCS} + +${DESTDIR}${DESTBIN}: + mkdir -p ${DESTDIR}${DESTBIN} + +install: ${DESTDIR}${DESTBIN} ${PROG} + ${INSTALL} ${STRIP} -c -m 755 ${PROG} ${DESTDIR}${DESTBIN}/${PROG} + +links: FRC + @set -e; ln -s SRC/*.[ch] . + +tags: FRC + ctags *.[ch] + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. diff --git a/contrib/bind/bin/nsupdate/nsupdate.c b/contrib/bind/bin/nsupdate/nsupdate.c new file mode 100644 index 000000000000..2b3171678b3a --- /dev/null +++ b/contrib/bind/bin/nsupdate/nsupdate.c @@ -0,0 +1,471 @@ +#if !defined(lint) && !defined(SABER) +static char rcsid[] = "$Id: nsupdate.c,v 8.5 1998/02/14 20:54:48 halley Exp $"; +#endif /* not lint */ + +/* + * Copyright (c) 1996 by 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM 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. + */ + +#include "port_before.h" +#include <sys/param.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <errno.h> +#include <limits.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "port_after.h" + +/* XXX all of this stuff should come from libbind.a */ + +/* + * Map class and type names to number + */ +struct map { + char token[10]; + int val; +}; + +struct map class_strs[] = { + { "in", C_IN }, + { "chaos", C_CHAOS }, + { "hs", C_HS }, +}; +#define M_CLASS_CNT (sizeof(class_strs) / sizeof(struct map)) + +struct map type_strs[] = { + { "a", T_A }, + { "ns", T_NS }, + { "cname", T_CNAME }, + { "soa", T_SOA }, + { "mb", T_MB }, + { "mg", T_MG }, + { "mr", T_MR }, + { "null", T_NULL }, + { "wks", T_WKS }, + { "ptr", T_PTR }, + { "hinfo", T_HINFO }, + { "minfo", T_MINFO }, + { "mx", T_MX }, + { "txt", T_TXT }, + { "rp", T_RP }, + { "afsdb", T_AFSDB }, + { "x25", T_X25 }, + { "isdn", T_ISDN }, + { "rt", T_RT }, + { "nsap", T_NSAP }, + { "nsap_ptr", T_NSAP_PTR }, + { "px", T_PX }, + { "loc", T_LOC }, +}; +#define M_TYPE_CNT (sizeof(type_strs) / sizeof(struct map)) + +struct map section_strs[] = { + { "zone", S_ZONE }, + { "prereq", S_PREREQ }, + { "update", S_UPDATE }, + { "reserved", S_ADDT }, +}; +#define M_SECTION_CNT (sizeof(section_strs) / sizeof(struct map)) + +struct map opcode_strs[] = { + { "nxdomain", NXDOMAIN }, + { "yxdomain", YXDOMAIN }, + { "nxrrset", NXRRSET }, + { "yxrrset", YXRRSET }, + { "delete", DELETE }, + { "add", ADD }, +}; +#define M_OPCODE_CNT (sizeof(opcode_strs) / sizeof(struct map)) + +static char *progname; +static FILE *log; + +static void usage(void); +static int getword_str(char *, int, char **, char *); + +/* + * format of file read by nsupdate is kept the same as the log + * file generated by updates, so that the log file can be fed + * to nsupdate to reconstruct lost updates. + * + * file is read on line at a time using fgets() rather than + * one word at a time using getword() so that it is easy to + * adapt nsupdate to read piped input from other scripts + * + * overloading of class/type has to be deferred to res_update() + * because class is needed by res_update() to determined the + * zone to which a resource record belongs + */ +int +main(argc, argv) + int argc; + char **argv; +{ + FILE *fp = NULL; + char buf[BUFSIZ], buf2[BUFSIZ], hostbuf[100], filebuf[100]; + char dnbuf[MAXDNAME]; + u_char packet[PACKETSZ], answer[PACKETSZ]; + char *host = hostbuf, *batchfile = filebuf; + char *r_dname, *cp, *startp, *endp, *svstartp; + char section[15], opcode[10]; + int i, c, n, n1, inside, lineno = 0, vc = 0, + debug = 0, r_size, r_section, r_opcode, + prompt = 0, ret = 0; + int16_t r_class, r_type; + u_int32_t r_ttl; + struct map *mp; + ns_updrec *rrecp_start = NULL, *rrecp, *tmprrecp; + struct in_addr hostaddr; + extern int getopt(); + extern char *optarg; + extern int optind, opterr, optopt; + + + progname = argv[0]; + + while ((c = getopt(argc, argv, "dv")) != EOF) { + switch (c) { + case 'v': + vc = 1; + break; + case 'd': + debug = 1; + break; + default: + usage(); + } + } + + if ((argc - optind) == 0) { + /* no file specified, read from stdin */ + ret = system("tty -s"); + if (ret == 0) /* terminal */ + prompt = 1; + else /* stdin redirect from a file or a pipe */ + prompt = 0; + } else { + /* file specified, open it */ + /* XXX - currently accepts only one filename */ + if ((fp = fopen(argv[optind], "r")) == NULL) { + fprintf(stderr, "error opening file: %s\n", argv[optind]); + exit (1); + } + } + for (;;) { + + inside = 1; + if (prompt) + fprintf(stdout, "> "); + if (!fp) + cp = fgets(buf, sizeof buf, stdin); + else + cp = fgets(buf, sizeof buf, fp); + if (cp == NULL) /* EOF */ + break; + lineno++; + + /* get rid of the trailing newline */ + n = strlen(buf); + buf[--n] = '\0'; + + startp = cp; + endp = strchr(cp, ';'); + if (endp != NULL) + endp--; + else + endp = cp + n - 1; + + /* verify section name */ + if (!getword_str(section, sizeof section, &startp, endp)) { + /* empty line */ + inside = 0; + } + if (inside) { + /* inside the same update packet, + * continue accumulating records */ + r_section = -1; + n1 = strlen(section); + if (section[n1-1] == ':') + section[--n1] = '\0'; + for (mp = section_strs; mp < section_strs+M_SECTION_CNT; mp++) + if (!strcasecmp(section, mp->token)) { + r_section = mp->val; + break; + } + if (r_section == -1) { + fprintf(stderr, "incorrect section name: %s\n", section); + exit (1); + } + if (r_section == S_ZONE) { + fprintf(stderr, "section ZONE not permitted\n"); + exit (1); + } + /* read operation code */ + if (!getword_str(opcode, sizeof opcode, &startp, endp)) { + fprintf(stderr, "failed to read operation code\n"); + exit (1); + } + r_opcode = -1; + if (opcode[0] == '{') { + n1 = strlen(opcode); + for (i = 0; i < n1; i++) + opcode[i] = opcode[i+1]; + if (opcode[n1-2] == '}') + opcode[n1-2] = '\0'; + } + for (mp = opcode_strs; mp < opcode_strs+M_OPCODE_CNT; mp++) { + if (!strcasecmp(opcode, mp->token)) { + r_opcode = mp->val; + break; + } + } + if (r_opcode == -1) { + fprintf(stderr, "incorrect operation code: %s\n", opcode); + exit (1); + } + /* read owner's domain name */ + if (!getword_str(dnbuf, sizeof dnbuf, &startp, endp)) { + fprintf(stderr, "failed to read owner name\n"); + exit (1); + } + r_dname = dnbuf; + r_ttl = 0; + r_type = -1; + r_class = C_IN; /* default to IN */ + r_size = 0; + + (void) getword_str(buf2, sizeof buf2, &startp, endp); + + if (isdigit(buf2[0])) { /* ttl */ + r_ttl = strtoul(buf2, 0, 10); + if (errno == ERANGE && r_ttl == ULONG_MAX) { + fprintf(stderr, "oversized ttl: %s\n", buf2); + exit (1); + } + (void) getword_str(buf2, sizeof buf2, &startp, endp); + } + + if (buf2[0]) { /* possibly class */ + for (mp = class_strs; mp < class_strs+M_CLASS_CNT; mp++) { + if (!strcasecmp(buf2, mp->token)) { + r_class = mp->val; + (void) getword_str(buf2, sizeof buf2, &startp, endp); + break; + } + } + } + /* + * type and rdata field may or may not be required depending + * on the section and operation + */ + switch (r_section) { + case S_PREREQ: + if (r_ttl) { + fprintf(stderr, "nonzero ttl in prereq section: %ul\n", + r_ttl); + r_ttl = 0; + } + switch (r_opcode) { + case NXDOMAIN: + case YXDOMAIN: + if (buf2[0]) { + fprintf (stderr, "invalid field: %s, ignored\n", + buf2); + exit (1); + } + break; + case NXRRSET: + case YXRRSET: + if (buf2[0]) + for (mp = type_strs; mp < type_strs+M_TYPE_CNT; mp++) + if (!strcasecmp(buf2, mp->token)) { + r_type = mp->val; + break; + } + if (r_type == -1) { + fprintf (stderr, "invalid type for RRset: %s\n", + buf2); + exit (1); + } + if (r_opcode == NXRRSET) + break; + /* + * for RRset exists (value dependent) case, + * nonempty rdata field will be present. + * simply copy the whole string now and let + * res_update() interpret the various fields + * depending on type + */ + cp = startp; + while (cp <= endp && isspace(*cp)) + cp++; + r_size = endp - cp + 1; + break; + default: + fprintf (stderr, + "unknown operation in prereq section\"%s\"\n", + opcode); + exit (1); + } + break; + case S_UPDATE: + switch (r_opcode) { + case DELETE: + r_ttl = 0; + r_type = T_ANY; + /* read type, if specified */ + if (buf2[0]) + for (mp = type_strs; mp < type_strs+M_TYPE_CNT; mp++) + if (!strcasecmp(buf2, mp->token)) { + r_type = mp->val; + svstartp = startp; + (void) getword_str(buf2, sizeof buf2, + &startp, endp); + if (buf2[0]) /* unget preference */ + startp = svstartp; + break; + } + /* read rdata portion, if specified */ + cp = startp; + while (cp <= endp && isspace(*cp)) + cp++; + r_size = endp - cp + 1; + break; + case ADD: + if (r_ttl == 0) { + fprintf (stderr, + "ttl must be specified for record to be added: %s\n", buf); + exit (1); + } + /* read type */ + if (buf2[0]) + for (mp = type_strs; mp < type_strs+M_TYPE_CNT; mp++) + if (!strcasecmp(buf2, mp->token)) { + r_type = mp->val; + break; + } + if (r_type == -1) { + fprintf(stderr, + "invalid type for record to be added: %s\n", buf2); + exit (1); + } + /* read rdata portion */ + cp = startp; + while (cp < endp && isspace(*cp)) + cp++; + r_size = endp - cp + 1; + if (r_size <= 0) { + fprintf(stderr, + "nonempty rdata field needed to add the record at line %d\n", + lineno); + exit (1); + } + break; + default: + fprintf(stderr, + "unknown operation in update section\"%s\"\n", opcode); + exit (1); + } + break; + default: + fprintf(stderr, + "unknown section identifier \"%s\"\n", section); + exit (1); + } + + if ( !(rrecp = res_mkupdrec(r_section, r_dname, r_class, + r_type, r_ttl)) || + (r_size > 0 && !(rrecp->r_data = (u_char *)malloc(r_size))) ) { + fprintf(stderr, "saverrec error\n"); + exit (1); + } + rrecp->r_opcode = r_opcode; + rrecp->r_size = r_size; + (void) strncpy((char *)rrecp->r_data, cp, r_size); + /* append current record to the end of linked list of + * records seen so far */ + if (rrecp_start == NULL) + rrecp_start = rrecp; + else { + tmprrecp = rrecp_start; + while (tmprrecp->r_next != NULL) + tmprrecp = tmprrecp->r_next; + tmprrecp->r_next = rrecp; + } + } else { /* end of an update packet */ + (void) res_init(); + if (vc) + _res.options |= RES_USEVC | RES_STAYOPEN; + if (debug) + _res.options |= RES_DEBUG; + if (rrecp_start) { + if ((n = res_update(rrecp_start)) < 0) + fprintf(stderr, "failed update packet\n"); + /* free malloc'ed memory */ + while(rrecp_start) { + tmprrecp = rrecp_start; + rrecp_start = rrecp_start->r_next; + free((char *)tmprrecp->r_dname); + free((char *)tmprrecp); + } + } + } + } /* for */ + return (0); +} + +static void +usage() { + fprintf(stderr, "Usage: %s [-d] [-v] [file]\n", + progname); + exit(1); +} + +/* + * Get a whitespace delimited word from a string (not file) + * into buf. modify the start pointer to point after the + * word in the string. + */ +static int +getword_str(char *buf, int size, char **startpp, char *endp) { + char *cp; + int c; + + for (cp = buf; *startpp <= endp; ) { + c = **startpp; + if (isspace(c) || c == '\0') { + if (cp != buf) /* trailing whitespace */ + break; + else { /* leading whitespace */ + (*startpp)++; + continue; + } + } + (*startpp)++; + if (cp >= buf+size-1) + break; + *cp++ = (u_char)c; + } + *cp = '\0'; + return (cp != buf); +} |
