]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
dnssec-keygen: Move keygen function above main
authorMatthijs Mekking <matthijs@isc.org>
Wed, 11 Sep 2019 08:53:53 +0000 (10:53 +0200)
committerMatthijs Mekking <matthijs@isc.org>
Wed, 6 Nov 2019 21:31:44 +0000 (22:31 +0100)
This is done in a separate commit to make diff easier.

bin/dnssec/dnssec-keygen.c

index cb2aa3804c7639520814a4c9c73a991b086658cb..54ba5dce653d7e23dfad1a832f1e8a9faed4ff05 100644 (file)
@@ -119,8 +119,6 @@ struct keygen_ctx {
 
 typedef struct keygen_ctx keygen_ctx_t;
 
-static void keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv);
-
 static void
 usage(void) {
        fprintf(stderr, "Usage:\n");
@@ -231,402 +229,85 @@ progress(int p)
        (void) fflush(stderr);
 }
 
-int
-main(int argc, char **argv) {
-       char            *algname = NULL, *freeit = NULL;
-       char            *classname = NULL;
-       char            *endp;
-       isc_mem_t       *mctx = NULL;
-       isc_result_t    ret;
-       isc_textregion_t r;
-       isc_log_t       *log = NULL;
-       const char      *engine = NULL;
-       unsigned char   c;
-       int             ch;
-
-       keygen_ctx_t ctx = {
-               .options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC,
-               .prepub = -1,
-               .protocol = -1,
-               .size = -1,
-       };
+static void
+keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv)
+{
+       char filename[255];
+       char algstr[DNS_SECALG_FORMATSIZE];
+       uint16_t flags = 0;
+       int param = 0;
+       bool null_key = false;
+       bool conflict = false;
+       bool show_progress = false;
+       isc_buffer_t buf;
+       dns_name_t *name;
+       dns_fixedname_t fname;
+       isc_result_t ret;
+       dst_key_t* key = NULL;
+       dst_key_t* prevkey = NULL;
 
-       if (argc == 1) {
-               usage();
-       }
+       UNUSED(argc);
 
-#if USE_PKCS11
-       pk11_result_register();
-#endif
-       dns_result_register();
+       dns_secalg_format(ctx->alg, algstr, sizeof(algstr));
 
-       isc_commandline_errprint = false;
+       if (ctx->predecessor == NULL) {
+               if (ctx->prepub == -1)
+                       ctx->prepub = 0;
 
-       /*
-        * Process memory debugging argument first.
-        */
-#define CMDLINE_FLAGS "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:L:m:n:P:p:qR:r:S:s:T:t:" \
-                     "v:V"
-       while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
-               switch (ch) {
-               case 'm':
-                       if (strcasecmp(isc_commandline_argument, "record") == 0)
-                               isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
-                       if (strcasecmp(isc_commandline_argument, "trace") == 0)
-                               isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
-                       if (strcasecmp(isc_commandline_argument, "usage") == 0)
-                               isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
-                       if (strcasecmp(isc_commandline_argument, "size") == 0)
-                               isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
-                       if (strcasecmp(isc_commandline_argument, "mctx") == 0)
-                               isc_mem_debugging |= ISC_MEM_DEBUGCTX;
-                       break;
-               default:
-                       break;
+               name = dns_fixedname_initname(&fname);
+               isc_buffer_init(&buf, argv[isc_commandline_index],
+                               strlen(argv[isc_commandline_index]));
+               isc_buffer_add(&buf, strlen(argv[isc_commandline_index]));
+               ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL);
+               if (ret != ISC_R_SUCCESS) {
+                       fatal("invalid key name %s: %s",
+                             argv[isc_commandline_index],
+                             isc_result_totext(ret));
                }
-       }
-       isc_commandline_reset = true;
-
-       isc_mem_create(&mctx);
 
-       isc_stdtime_get(&ctx.now);
+               if (!dst_algorithm_supported(ctx->alg)) {
+                       fatal("unsupported algorithm: %s", algstr);
+               }
 
-       while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
-           switch (ch) {
-               case '3':
-                       ctx.use_nsec3 = true;
-                       break;
-               case 'a':
-                       algname = isc_commandline_argument;
-                       break;
-               case 'b':
-                       ctx.size = strtol(isc_commandline_argument, &endp, 10);
-                       if (*endp != '\0' || ctx.size < 0)
-                               fatal("-b requires a non-negative number");
-                       break;
-               case 'C':
-                       ctx.oldstyle = true;
-                       break;
-               case 'c':
-                       classname = isc_commandline_argument;
-                       break;
-               case 'd':
-                       ctx.dbits = strtol(isc_commandline_argument, &endp, 10);
-                       if (*endp != '\0' || ctx.dbits < 0)
-                               fatal("-d requires a non-negative number");
-                       break;
-               case 'E':
-                       engine = isc_commandline_argument;
-                       break;
-               case 'e':
-                       fprintf(stderr,
-                               "phased-out option -e "
-                               "(was 'use (RSA) large exponent')\n");
-                       break;
-               case 'f':
-                       c = (unsigned char)(isc_commandline_argument[0]);
-                       if (toupper(c) == 'K')
-                               ctx.kskflag = DNS_KEYFLAG_KSK;
-                       else if (toupper(c) == 'R')
-                               ctx.revflag = DNS_KEYFLAG_REVOKE;
-                       else
-                               fatal("unknown flag '%s'",
-                                     isc_commandline_argument);
-                       break;
-               case 'g':
-                       ctx.generator = strtol(isc_commandline_argument,
-                                          &endp, 10);
-                       if (*endp != '\0' || ctx.generator <= 0)
-                               fatal("-g requires a positive number");
-                       break;
-               case 'K':
-                       ctx.directory = isc_commandline_argument;
-                       ret = try_dir(ctx.directory);
-                       if (ret != ISC_R_SUCCESS)
-                               fatal("cannot open directory %s: %s",
-                                     ctx.directory, isc_result_totext(ret));
-                       break;
-               case 'L':
-                       ctx.ttl = strtottl(isc_commandline_argument);
-                       ctx.setttl = true;
-                       break;
-                       break;
-               case 'n':
-                       ctx.nametype = isc_commandline_argument;
-                       break;
-               case 'm':
-                       break;
-               case 'p':
-                       ctx.protocol = strtol(isc_commandline_argument, &endp,
-                                             10);
-                       if (*endp != '\0' || ctx.protocol < 0 ||
-                           ctx.protocol > 255)
-                       {
-                               fatal("-p must be followed by a number "
-                                     "[0..255]");
-                       }
-                       break;
-               case 'q':
-                       ctx.quiet = true;
-                       break;
-               case 'r':
-                       fatal("The -r option has been deprecated.\n"
-                             "System random data is always used.\n");
-                       break;
-               case 's':
-                       ctx.signatory = strtol(isc_commandline_argument,
-                                              &endp, 10);
-                       if (*endp != '\0' || ctx.signatory < 0 ||
-                           ctx.signatory > 15)
-                       {
-                               fatal("-s must be followed by a number "
-                                     "[0..15]");
-                       }
-                       break;
-               case 'T':
-                       if (strcasecmp(isc_commandline_argument, "KEY") == 0)
-                               ctx.options |= DST_TYPE_KEY;
-                       else if (strcasecmp(isc_commandline_argument,
-                                "DNSKEY") == 0)
-                               /* default behavior */
-                               ;
-                       else
-                               fatal("unknown type '%s'",
-                                     isc_commandline_argument);
-                       break;
-               case 't':
-                       ctx.type = isc_commandline_argument;
-                       break;
-               case 'v':
-                       endp = NULL;
-                       verbose = strtol(isc_commandline_argument, &endp, 0);
-                       if (*endp != '\0')
-                               fatal("-v must be followed by a number");
-                       break;
-               case 'G':
-                       ctx.genonly = true;
-                       break;
-               case 'P':
-                       /* -Psync ? */
-                       if (isoptarg("sync", argv, usage)) {
-                               if (ctx.setsyncadd)
-                                       fatal("-P sync specified more than "
-                                             "once");
+               if (ctx->alg == DST_ALG_DH) {
+                       ctx->options |= DST_TYPE_KEY;
+               }
 
-                               ctx.syncadd = strtotime(
-                                                      isc_commandline_argument,
-                                                      ctx.now, ctx.now,
-                                                      &ctx.setsyncadd);
+               if (ctx->use_nsec3) {
+                       switch (ctx->alg) {
+                       case DST_ALG_RSASHA1:
+                               ctx->alg = DST_ALG_NSEC3RSASHA1;
+                               break;
+                       case DST_ALG_NSEC3RSASHA1:
+                       case DST_ALG_RSASHA256:
+                       case DST_ALG_RSASHA512:
+                       case DST_ALG_ECDSA256:
+                       case DST_ALG_ECDSA384:
+                       case DST_ALG_ED25519:
+                       case DST_ALG_ED448:
                                break;
+                       default:
+                               fatal("algorithm %s is incompatible with NSEC3"
+                                     ", do not use the -3 option", algstr);
                        }
-                       (void)isoptarg("dnskey", argv, usage);
-                       if (ctx.setpub || ctx.unsetpub)
-                               fatal("-P specified more than once");
+               }
 
-                       ctx.publish = strtotime(isc_commandline_argument,
-                                               ctx.now, ctx.now, &ctx.setpub);
-                       ctx.unsetpub = !ctx.setpub;
-                       break;
-               case 'A':
-                       if (ctx.setact || ctx.unsetact)
-                               fatal("-A specified more than once");
-
-                       ctx.activate = strtotime(isc_commandline_argument,
-                                                ctx.now, ctx.now, &ctx.setact);
-                       ctx.unsetact = !ctx.setact;
-                       break;
-               case 'R':
-                       if (ctx.setrev || ctx.unsetrev)
-                               fatal("-R specified more than once");
-
-                       ctx.revokekey = strtotime(isc_commandline_argument,
-                                                ctx.now, ctx.now, &ctx.setrev);
-                       ctx.unsetrev = !ctx.setrev;
-                       break;
-               case 'I':
-                       if (ctx.setinact || ctx.unsetinact)
-                               fatal("-I specified more than once");
-
-                       ctx.inactive = strtotime(isc_commandline_argument,
-                                              ctx.now, ctx.now, &ctx.setinact);
-                       ctx.unsetinact = !ctx.setinact;
-                       break;
-               case 'D':
-                       /* -Dsync ? */
-                       if (isoptarg("sync", argv, usage)) {
-                               if (ctx.setsyncdel)
-                                       fatal("-D sync specified more than "
-                                             "once");
-
-                               ctx.syncdel = strtotime(
-                                                      isc_commandline_argument,
-                                                      ctx.now, ctx.now,
-                                                      &ctx.setsyncdel);
-                               break;
-                       }
-                       (void)isoptarg("dnskey", argv, usage);
-                       if (ctx.setdel || ctx.unsetdel)
-                               fatal("-D specified more than once");
-
-                       ctx.deltime = strtotime(isc_commandline_argument,
-                                               ctx.now, ctx.now, &ctx.setdel);
-                       ctx.unsetdel = !ctx.setdel;
-                       break;
-               case 'S':
-                       ctx.predecessor = isc_commandline_argument;
-                       break;
-               case 'i':
-                       ctx.prepub = strtottl(isc_commandline_argument);
-                       break;
-               case 'F':
-                       /* Reserved for FIPS mode */
-                       /* FALLTHROUGH */
-               case '?':
-                       if (isc_commandline_option != '?')
-                               fprintf(stderr, "%s: invalid argument -%c\n",
-                                       program, isc_commandline_option);
-                       /* FALLTHROUGH */
-               case 'h':
-                       /* Does not return. */
-                       usage();
-
-               case 'V':
-                       /* Does not return. */
-                       version(program);
-
-               default:
-                       fprintf(stderr, "%s: unhandled option -%c\n",
-                               program, isc_commandline_option);
-                       exit(1);
-               }
-       }
-
-       if (!isatty(0))
-               ctx.quiet = true;
-
-       ret = dst_lib_init(mctx, engine);
-       if (ret != ISC_R_SUCCESS)
-               fatal("could not initialize dst: %s",
-                     isc_result_totext(ret));
-
-       setup_logging(mctx, &log);
-
-       ctx.rdclass = strtoclass(classname);
-
-       if (ctx.predecessor == NULL) {
-               if (argc < isc_commandline_index + 1)
-                       fatal("the key name was not specified");
-               if (argc > isc_commandline_index + 1)
-                       fatal("extraneous arguments");
-
-               if (algname == NULL)
-                       fatal("no algorithm specified");
-
-               r.base = algname;
-               r.length = strlen(algname);
-               ret = dns_secalg_fromtext(&ctx.alg, &r);
-               if (ret != ISC_R_SUCCESS) {
-                       fatal("unknown algorithm %s", algname);
-               }
-               if (!dst_algorithm_supported(ctx.alg)) {
-                       fatal("unsupported algorithm: %s", algname);
-               }
-       }
-
-       keygen(&ctx, mctx, argc, argv);
-
-       cleanup_logging(&log);
-       dst_lib_destroy();
-       dns_name_destroy();
-       if (verbose > 10)
-               isc_mem_stats(mctx, stdout);
-       isc_mem_destroy(&mctx);
-
-       if (freeit != NULL)
-               free(freeit);
-
-       return (0);
-}
-
-static void
-keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv)
-{
-       char filename[255];
-       char algstr[DNS_SECALG_FORMATSIZE];
-       uint16_t flags = 0;
-       int param = 0;
-       bool null_key = false;
-       bool conflict = false;
-       bool show_progress = false;
-       isc_buffer_t buf;
-       dns_name_t *name;
-       dns_fixedname_t fname;
-       isc_result_t ret;
-       dst_key_t* key = NULL;
-       dst_key_t* prevkey = NULL;
-
-       UNUSED(argc);
-
-       dns_secalg_format(ctx->alg, algstr, sizeof(algstr));
-
-       if (ctx->predecessor == NULL) {
-               if (ctx->prepub == -1)
-                       ctx->prepub = 0;
-
-               name = dns_fixedname_initname(&fname);
-               isc_buffer_init(&buf, argv[isc_commandline_index],
-                               strlen(argv[isc_commandline_index]));
-               isc_buffer_add(&buf, strlen(argv[isc_commandline_index]));
-               ret = dns_name_fromtext(name, &buf, dns_rootname, 0, NULL);
-               if (ret != ISC_R_SUCCESS) {
-                       fatal("invalid key name %s: %s",
-                             argv[isc_commandline_index],
-                             isc_result_totext(ret));
-               }
-
-               if (!dst_algorithm_supported(ctx->alg)) {
-                       fatal("unsupported algorithm: %s", algstr);
-               }
-
-               if (ctx->alg == DST_ALG_DH) {
-                       ctx->options |= DST_TYPE_KEY;
-               }
-
-               if (ctx->use_nsec3) {
-                       switch (ctx->alg) {
-                       case DST_ALG_RSASHA1:
-                               ctx->alg = DST_ALG_NSEC3RSASHA1;
-                               break;
-                       case DST_ALG_NSEC3RSASHA1:
-                       case DST_ALG_RSASHA256:
-                       case DST_ALG_RSASHA512:
-                       case DST_ALG_ECDSA256:
-                       case DST_ALG_ECDSA384:
-                       case DST_ALG_ED25519:
-                       case DST_ALG_ED448:
-                               break;
-                       default:
-                               fatal("algorithm %s is incompatible with NSEC3"
-                                     ", do not use the -3 option", algstr);
-                       }
-               }
-
-               if (ctx->type != NULL && (ctx->options & DST_TYPE_KEY) != 0) {
-                       if (strcasecmp(ctx->type, "NOAUTH") == 0) {
-                               flags |= DNS_KEYTYPE_NOAUTH;
-                       } else if (strcasecmp(ctx->type, "NOCONF") == 0) {
-                               flags |= DNS_KEYTYPE_NOCONF;
-                       } else if (strcasecmp(ctx->type, "NOAUTHCONF") == 0) {
-                               flags |= (DNS_KEYTYPE_NOAUTH |
-                                         DNS_KEYTYPE_NOCONF);
-                               if (ctx->size < 0)
-                                       ctx->size = 0;
-                       } else if (strcasecmp(ctx->type, "AUTHCONF") == 0) {
-                               /* nothing */;
-                       } else {
-                               fatal("invalid type %s", ctx->type);
-                       }
-               }
+               if (ctx->type != NULL && (ctx->options & DST_TYPE_KEY) != 0) {
+                       if (strcasecmp(ctx->type, "NOAUTH") == 0) {
+                               flags |= DNS_KEYTYPE_NOAUTH;
+                       } else if (strcasecmp(ctx->type, "NOCONF") == 0) {
+                               flags |= DNS_KEYTYPE_NOCONF;
+                       } else if (strcasecmp(ctx->type, "NOAUTHCONF") == 0) {
+                               flags |= (DNS_KEYTYPE_NOAUTH |
+                                         DNS_KEYTYPE_NOCONF);
+                               if (ctx->size < 0)
+                                       ctx->size = 0;
+                       } else if (strcasecmp(ctx->type, "AUTHCONF") == 0) {
+                               /* nothing */;
+                       } else {
+                               fatal("invalid type %s", ctx->type);
+                       }
+               }
 
                if (ctx->size < 0) {
                        switch (ctx->alg) {
@@ -912,7 +593,7 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv)
 
                        if (ctx->setpub)
                                dst_key_settime(key, DST_TIME_PUBLISH,
-                                               ctx->publish);
+                                               ctx->publish);
                        else if (ctx->setact && !ctx->unsetpub)
                                dst_key_settime(key, DST_TIME_PUBLISH,
                                                ctx->activate - ctx->prepub);
@@ -963,7 +644,6 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv)
                        if (ctx->setsyncdel)
                                dst_key_settime(key, DST_TIME_SYNCDELETE,
                                                ctx->syncdel);
-
                } else {
                        if (ctx->setpub || ctx->setact || ctx->setrev ||
                            ctx->setinact || ctx->setdel || ctx->unsetpub ||
@@ -1033,8 +713,325 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv)
                fatal("dst_key_buildfilename returned: %s\n",
                      isc_result_totext(ret));
        printf("%s\n", filename);
+
        dst_key_free(&key);
        if (prevkey != NULL) {
                dst_key_free(&prevkey);
        }
 }
+
+int
+main(int argc, char **argv) {
+       char            *algname = NULL, *freeit = NULL;
+       char            *classname = NULL;
+       char            *endp;
+       isc_mem_t       *mctx = NULL;
+       isc_result_t    ret;
+       isc_textregion_t r;
+       isc_log_t       *log = NULL;
+       const char      *engine = NULL;
+       unsigned char   c;
+       int             ch;
+
+       keygen_ctx_t ctx = {
+               .options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC,
+               .prepub = -1,
+               .protocol = -1,
+               .size = -1,
+       };
+
+       if (argc == 1) {
+               usage();
+       }
+
+#if USE_PKCS11
+       pk11_result_register();
+#endif
+       dns_result_register();
+
+       isc_commandline_errprint = false;
+
+       /*
+        * Process memory debugging argument first.
+        */
+#define CMDLINE_FLAGS "3A:a:b:Cc:D:d:E:eFf:Gg:hI:i:K:L:m:n:P:p:qR:r:S:s:T:t:" \
+                     "v:V"
+       while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+               switch (ch) {
+               case 'm':
+                       if (strcasecmp(isc_commandline_argument, "record") == 0)
+                               isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+                       if (strcasecmp(isc_commandline_argument, "trace") == 0)
+                               isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
+                       if (strcasecmp(isc_commandline_argument, "usage") == 0)
+                               isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
+                       if (strcasecmp(isc_commandline_argument, "size") == 0)
+                               isc_mem_debugging |= ISC_MEM_DEBUGSIZE;
+                       if (strcasecmp(isc_commandline_argument, "mctx") == 0)
+                               isc_mem_debugging |= ISC_MEM_DEBUGCTX;
+                       break;
+               default:
+                       break;
+               }
+       }
+       isc_commandline_reset = true;
+
+       isc_mem_create(&mctx);
+       isc_stdtime_get(&ctx.now);
+
+       while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
+           switch (ch) {
+               case '3':
+                       ctx.use_nsec3 = true;
+                       break;
+               case 'a':
+                       algname = isc_commandline_argument;
+                       break;
+               case 'b':
+                       ctx.size = strtol(isc_commandline_argument, &endp, 10);
+                       if (*endp != '\0' || ctx.size < 0)
+                               fatal("-b requires a non-negative number");
+                       break;
+               case 'C':
+                       ctx.oldstyle = true;
+                       break;
+               case 'c':
+                       classname = isc_commandline_argument;
+                       break;
+               case 'd':
+                       ctx.dbits = strtol(isc_commandline_argument, &endp, 10);
+                       if (*endp != '\0' || ctx.dbits < 0)
+                               fatal("-d requires a non-negative number");
+                       break;
+               case 'E':
+                       engine = isc_commandline_argument;
+                       break;
+               case 'e':
+                       fprintf(stderr,
+                               "phased-out option -e "
+                               "(was 'use (RSA) large exponent')\n");
+                       break;
+               case 'f':
+                       c = (unsigned char)(isc_commandline_argument[0]);
+                       if (toupper(c) == 'K')
+                               ctx.kskflag = DNS_KEYFLAG_KSK;
+                       else if (toupper(c) == 'R')
+                               ctx.revflag = DNS_KEYFLAG_REVOKE;
+                       else
+                               fatal("unknown flag '%s'",
+                                     isc_commandline_argument);
+                       break;
+               case 'g':
+                       ctx.generator = strtol(isc_commandline_argument,
+                                          &endp, 10);
+                       if (*endp != '\0' || ctx.generator <= 0)
+                               fatal("-g requires a positive number");
+                       break;
+               case 'K':
+                       ctx.directory = isc_commandline_argument;
+                       ret = try_dir(ctx.directory);
+                       if (ret != ISC_R_SUCCESS)
+                               fatal("cannot open directory %s: %s",
+                                     ctx.directory, isc_result_totext(ret));
+                       break;
+               case 'L':
+                       ctx.ttl = strtottl(isc_commandline_argument);
+                       ctx.setttl = true;
+                       break;
+                       break;
+               case 'n':
+                       ctx.nametype = isc_commandline_argument;
+                       break;
+               case 'm':
+                       break;
+               case 'p':
+                       ctx.protocol = strtol(isc_commandline_argument, &endp,
+                                             10);
+                       if (*endp != '\0' || ctx.protocol < 0 ||
+                           ctx.protocol > 255)
+                       {
+                               fatal("-p must be followed by a number "
+                                     "[0..255]");
+                       }
+                       break;
+               case 'q':
+                       ctx.quiet = true;
+                       break;
+               case 'r':
+                       fatal("The -r option has been deprecated.\n"
+                             "System random data is always used.\n");
+                       break;
+               case 's':
+                       ctx.signatory = strtol(isc_commandline_argument,
+                                              &endp, 10);
+                       if (*endp != '\0' || ctx.signatory < 0 ||
+                           ctx.signatory > 15)
+                       {
+                               fatal("-s must be followed by a number "
+                                     "[0..15]");
+                       }
+                       break;
+               case 'T':
+                       if (strcasecmp(isc_commandline_argument, "KEY") == 0)
+                               ctx.options |= DST_TYPE_KEY;
+                       else if (strcasecmp(isc_commandline_argument,
+                                "DNSKEY") == 0)
+                               /* default behavior */
+                               ;
+                       else
+                               fatal("unknown type '%s'",
+                                     isc_commandline_argument);
+                       break;
+               case 't':
+                       ctx.type = isc_commandline_argument;
+                       break;
+               case 'v':
+                       endp = NULL;
+                       verbose = strtol(isc_commandline_argument, &endp, 0);
+                       if (*endp != '\0')
+                               fatal("-v must be followed by a number");
+                       break;
+               case 'G':
+                       ctx.genonly = true;
+                       break;
+               case 'P':
+                       /* -Psync ? */
+                       if (isoptarg("sync", argv, usage)) {
+                               if (ctx.setsyncadd)
+                                       fatal("-P sync specified more than "
+                                             "once");
+
+                               ctx.syncadd = strtotime(
+                                                      isc_commandline_argument,
+                                                      ctx.now, ctx.now,
+                                                      &ctx.setsyncadd);
+                               break;
+                       }
+                       (void)isoptarg("dnskey", argv, usage);
+                       if (ctx.setpub || ctx.unsetpub)
+                               fatal("-P specified more than once");
+
+                       ctx.publish = strtotime(isc_commandline_argument,
+                                               ctx.now, ctx.now, &ctx.setpub);
+                       ctx.unsetpub = !ctx.setpub;
+                       break;
+               case 'A':
+                       if (ctx.setact || ctx.unsetact)
+                               fatal("-A specified more than once");
+
+                       ctx.activate = strtotime(isc_commandline_argument,
+                                                ctx.now, ctx.now, &ctx.setact);
+                       ctx.unsetact = !ctx.setact;
+                       break;
+               case 'R':
+                       if (ctx.setrev || ctx.unsetrev)
+                               fatal("-R specified more than once");
+
+                       ctx.revokekey = strtotime(isc_commandline_argument,
+                                                ctx.now, ctx.now, &ctx.setrev);
+                       ctx.unsetrev = !ctx.setrev;
+                       break;
+               case 'I':
+                       if (ctx.setinact || ctx.unsetinact)
+                               fatal("-I specified more than once");
+
+                       ctx.inactive = strtotime(isc_commandline_argument,
+                                              ctx.now, ctx.now, &ctx.setinact);
+                       ctx.unsetinact = !ctx.setinact;
+                       break;
+               case 'D':
+                       /* -Dsync ? */
+                       if (isoptarg("sync", argv, usage)) {
+                               if (ctx.setsyncdel)
+                                       fatal("-D sync specified more than "
+                                             "once");
+
+                               ctx.syncdel = strtotime(
+                                                      isc_commandline_argument,
+                                                      ctx.now, ctx.now,
+                                                      &ctx.setsyncdel);
+                               break;
+                       }
+                       (void)isoptarg("dnskey", argv, usage);
+                       if (ctx.setdel || ctx.unsetdel)
+                               fatal("-D specified more than once");
+
+                       ctx.deltime = strtotime(isc_commandline_argument,
+                                               ctx.now, ctx.now, &ctx.setdel);
+                       ctx.unsetdel = !ctx.setdel;
+                       break;
+               case 'S':
+                       ctx.predecessor = isc_commandline_argument;
+                       break;
+               case 'i':
+                       ctx.prepub = strtottl(isc_commandline_argument);
+                       break;
+               case 'F':
+                       /* Reserved for FIPS mode */
+                       /* FALLTHROUGH */
+               case '?':
+                       if (isc_commandline_option != '?')
+                               fprintf(stderr, "%s: invalid argument -%c\n",
+                                       program, isc_commandline_option);
+                       /* FALLTHROUGH */
+               case 'h':
+                       /* Does not return. */
+                       usage();
+
+               case 'V':
+                       /* Does not return. */
+                       version(program);
+
+               default:
+                       fprintf(stderr, "%s: unhandled option -%c\n",
+                               program, isc_commandline_option);
+                       exit(1);
+               }
+       }
+
+       if (!isatty(0))
+               ctx.quiet = true;
+
+       ret = dst_lib_init(mctx, engine);
+       if (ret != ISC_R_SUCCESS)
+               fatal("could not initialize dst: %s",
+                     isc_result_totext(ret));
+
+       setup_logging(mctx, &log);
+
+       ctx.rdclass = strtoclass(classname);
+
+       if (ctx.predecessor == NULL) {
+               if (argc < isc_commandline_index + 1)
+                       fatal("the key name was not specified");
+               if (argc > isc_commandline_index + 1)
+                       fatal("extraneous arguments");
+
+               if (algname == NULL)
+                       fatal("no algorithm specified");
+
+               r.base = algname;
+               r.length = strlen(algname);
+               ret = dns_secalg_fromtext(&ctx.alg, &r);
+               if (ret != ISC_R_SUCCESS) {
+                       fatal("unknown algorithm %s", algname);
+               }
+               if (!dst_algorithm_supported(ctx.alg)) {
+                       fatal("unsupported algorithm: %s", algname);
+               }
+       }
+
+       keygen(&ctx, mctx, argc, argv);
+
+       cleanup_logging(&log);
+       dst_lib_destroy();
+       dns_name_destroy();
+       if (verbose > 10)
+               isc_mem_stats(mctx, stdout);
+       isc_mem_destroy(&mctx);
+
+       if (freeit != NULL)
+               free(freeit);
+
+       return (0);
+}