implemented gmp_rsa_public_key.encrypt() method
[strongswan.git] / src / whack / whack.c
index a3b9837..4c3083b 100644 (file)
@@ -11,8 +11,6 @@
  * 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.
- *
- * RCSID $Id: whack.c,v 1.21 2006/04/20 04:42:12 as Exp $
  */
 
 #include <stdio.h>
 
 #include <freeswan.h>
 
+#include <utils/optionsfrom.h>
+
 #include "constants.h"
 #include "defs.h"
 #include "whack.h"
 
-static void
-help(void)
+static void help(void)
 {
-    fprintf(stderr
-       , "Usage:\n\n"
-       "all forms:"
-           " [--optionsfrom <filename>]"
-           " [--ctlbase <path>]"
-           " [--label <string>]"
-           "\n\n"
-       "help: whack"
-           " [--help]"
-           " [--version]"
-           "\n\n"
-       "connection: whack"
-           " --name <connection_name>"
-           " \\\n   "
-           " [--ipv4 | --ipv6]"
-           " [--tunnelipv4 | --tunnelipv6]"
-           " \\\n   "
-           " (--host <ip-address> | --id <identity>)"
-           " \\\n   "
-           " [--cert <path>]"
-           " [--ca <distinguished name>]"
-           " [--sendcert <policy>]"
-           " \\\n   "
-           " [--groups <access control groups>]"
-           " \\\n   "
-           " [--ikeport <port-number>]"
-           " [--nexthop <ip-address>]"
-           " [--srcip <ip-address>]"
-           " \\\n   "
-           " [--client <subnet> | --clientwithin <address range>]"
-           " [--clientprotoport <protocol>/<port>]"
-           " \\\n   "
-           " [--dnskeyondemand]"
-           " [--updown <updown>]"
-           " \\\n   "
-           " --to"
-           " (--host <ip-address> | --id <identity>)"
-           " \\\n   "
-           " [--cert <path>]"
-           " [--ca <distinguished name>]"
-           " [--sendcert <policy>]"
-           " \\\n   "
-           " [--ikeport <port-number>]"
-           " [--nexthop <ip-address>]"
-           " [--srcip <ip-address>]"
-           " \\\n   "
-           " [--client <subnet> | --clientwithin <address range>]"
-           " [--clientprotoport <protocol>/<port>]"
-           " \\\n   "
-           " [--dnskeyondemand]"
-           " [--updown <updown>]"
-           " [--psk]"
-           " [--rsasig]"
-           " \\\n   "
-           " [--encrypt]"
-           " [--authenticate]"
-           " [--compress]"
-           " [--tunnel]"
-           " [--pfs]"
-           " \\\n   "
-           " [--ikelifetime <seconds>]"
-           " [--ipseclifetime <seconds>]"
-           " \\\n   "
-           " [--reykeymargin <seconds>]"
-           " [--reykeyfuzz <percentage>]"
-           " \\\n   "
-           " [--keyingtries <count>]"
-           " \\\n   "
-           " [--esp <esp-algos>]"
-           " \\\n   "
-           " [--dontrekey]"
-
-            " [--dpdaction (none|clear|hold|restart)]"
-           " \\\n   "
-            " [--dpddelay <seconds> --dpdtimeout <seconds>]"
-            " \\\n   "
-           " [--initiateontraffic|--pass|--drop|--reject]"
-           " \\\n   "
-           " [--failnone|--failpass|--faildrop|--failreject]"
-           "\n\n"
-       "routing: whack"
-           " (--route | --unroute)"
-           " --name <connection_name>"
-           "\n\n"
-       "initiation:"
-           "\n "
-           " whack"
-           " (--initiate | --terminate)"
-           " --name <connection_name>"
-           " [--asynchronous]"
-           "\n\n"
-       "opportunistic initiation: whack"
-           " [--tunnelipv4 | --tunnelipv6]"
-           " \\\n   "
-           " --oppohere <ip-address>"
-           " --oppothere <ip-address>"
-           "\n\n"
-       "delete: whack"
-           " --delete"
-           " (--name <connection_name> | --caname <ca name>)"
-           "\n\n"
-       "deletestate: whack"
-           " --deletestate <state_object_number>"
-            " --crash <ip-address>"
-           "\n\n"
-       "pubkey: whack"
-           " --keyid <id>"
-           " [--addkey]"
-           " [--pubkeyrsa <key>]"
-           "\n\n"
-       "myid: whack"
-           " --myid <id>"
-           "\n\n"
-       "ca: whack"
-           " --caname <name>"
-           " --cacert <path>"
-           " \\\n   "
-           " [--ldaphost <hostname>]"
-           " [--ldapbase <base>]"
-           " \\\n   "
-           " [--crluri <uri>]"
-           " [--crluri2 <uri>]"
-           " [--ocspuri <uri>]"
-           " [--strictcrlpolicy]"
-           "\n\n"
+       fprintf(stderr
+               , "Usage:\n\n"
+               "all forms:"
+                       " [--optionsfrom <filename>]"
+                       " [--ctlbase <path>]"
+                       " [--label <string>]"
+                       "\n\n"
+               "help: whack"
+                       " [--help]"
+                       " [--version]"
+                       "\n\n"
+               "connection: whack"
+                       " --name <connection_name>"
+                       " \\\n   "
+                       " [--ipv4 | --ipv6]"
+                       " [--tunnelipv4 | --tunnelipv6]"
+                       " \\\n   "
+                       " (--host <ip-address> | --id <identity>)"
+                       " \\\n   "
+                       " [--cert <path>]"
+                       " [--ca <distinguished name>]"
+                       " [--sendcert <policy>]"
+                       " \\\n   "
+                       " [--groups <access control groups>]"
+                       " \\\n   "
+                       " [--ikeport <port-number>]"
+                       " [--nexthop <ip-address>]"
+                       " [--srcip <ip-address>]"
+                       " \\\n   "
+                       " [--client <subnet> | --clientwithin <address range>]"
+                       " [--clientprotoport <protocol>/<port>]"
+                       " \\\n   "
+                       " [--dnskeyondemand]"
+                       " [--updown <updown>]"
+                       " \\\n   "
+                       " --to"
+                       " (--host <ip-address> | --id <identity>)"
+                       " \\\n   "
+                       " [--cert <path>]"
+                       " [--ca <distinguished name>]"
+                       " [--sendcert <policy>]"
+                       " \\\n   "
+                       " [--ikeport <port-number>]"
+                       " [--nexthop <ip-address>]"
+                       " [--srcip <ip-address>]"
+                       " \\\n   "
+                       " [--client <subnet> | --clientwithin <address range>]"
+                       " [--clientprotoport <protocol>/<port>]"
+                       " \\\n   "
+                       " [--dnskeyondemand]"
+                       " [--updown <updown>]"
+                       " [--psk]"
+                       " [--rsasig]"
+                       " \\\n   "
+                       " [--encrypt]"
+                       " [--authenticate]"
+                       " [--compress]"
+                       " [--tunnel]"
+                       " [--pfs]"
+                       " \\\n   "
+                       " [--ikelifetime <seconds>]"
+                       " [--ipseclifetime <seconds>]"
+                       " \\\n   "
+                       " [--reykeymargin <seconds>]"
+                       " [--reykeyfuzz <percentage>]"
+                       " \\\n   "
+                       " [--keyingtries <count>]"
+                       " \\\n   "
+                       " [--esp <esp-algos>]"
+                       " \\\n   "
+                       " [--dontrekey]"
+
+                       " [--dpdaction (none|clear|hold|restart)]"
+                       " \\\n   "
+                       " [--dpddelay <seconds> --dpdtimeout <seconds>]"
+                       " \\\n   "
+                       " [--initiateontraffic|--pass|--drop|--reject]"
+                       " \\\n   "
+                       " [--failnone|--failpass|--faildrop|--failreject]"
+                       "\n\n"
+               "routing: whack"
+                       " (--route | --unroute)"
+                       " --name <connection_name>"
+                       "\n\n"
+               "initiation:"
+                       "\n "
+                       " whack"
+                       " (--initiate | --terminate)"
+                       " --name <connection_name>"
+                       " [--asynchronous]"
+                       "\n\n"
+               "opportunistic initiation: whack"
+                       " [--tunnelipv4 | --tunnelipv6]"
+                       " \\\n   "
+                       " --oppohere <ip-address>"
+                       " --oppothere <ip-address>"
+                       "\n\n"
+               "delete: whack"
+                       " --delete"
+                       " (--name <connection_name> | --caname <ca name>)"
+                       "\n\n"
+               "deletestate: whack"
+                       " --deletestate <state_object_number>"
+                       " --crash <ip-address>"
+                       "\n\n"
+               "pubkey: whack"
+                       " --keyid <id>"
+                       " [--addkey]"
+                       " [--pubkeyrsa <key>]"
+                       "\n\n"
+               "myid: whack"
+                       " --myid <id>"
+                       "\n\n"
+               "ca: whack"
+                       " --caname <name>"
+                       " --cacert <path>"
+                       " \\\n   "
+                       " [--ldaphost <hostname>]"
+                       " [--ldapbase <base>]"
+                       " \\\n   "
+                       " [--crluri <uri>]"
+                       " [--crluri2 <uri>]"
+                       " [--ocspuri <uri>]"
+                       " [--strictcrlpolicy]"
+                       "\n\n"
 #ifdef DEBUG
-       "debug: whack [--name <connection_name>]"
-           " \\\n   "
-           " [--debug-none]"
-           " [--debug-all]"
-           " \\\n   "
-           " [--debug-raw]"
-           " [--debug-crypt]"
-           " [--debug-parsing]"
-           " [--debug-emitting]"
-           " \\\n   "
-           " [--debug-control]"
-           " [--debug-lifecycle]"
-           " [--debug-klips]"
-           " [--debug-dns]"
-           " \\\n   "
-           " [--debug-natt]"
-           " [--debug-oppo]"
-           " [--debug-controlmore]"
-           " [--debug-private]"
-           "\n\n"
+               "debug: whack [--name <connection_name>]"
+                       " \\\n   "
+                       " [--debug-none]"
+                       " [--debug-all]"
+                       " \\\n   "
+                       " [--debug-raw]"
+                       " [--debug-crypt]"
+                       " [--debug-parsing]"
+                       " [--debug-emitting]"
+                       " \\\n   "
+                       " [--debug-control]"
+                       " [--debug-lifecycle]"
+                       " [--debug-klips]"
+                       " [--debug-dns]"
+                       " \\\n   "
+                       " [--debug-natt]"
+                       " [--debug-oppo]"
+                       " [--debug-controlmore]"
+                       " [--debug-private]"
+                       "\n\n"
 #endif
-       "listen: whack"
-           " (--listen | --unlisten)"
-           "\n\n"
-       "list: whack [--utc]"
-           " [--listalgs]"
-           " [--listpubkeys]"
-           " [--listcerts]"
-           " [--listcacerts]"
-           " \\\n   "
-           " [--listacerts]"
-           " [--listaacerts]"
-           " [--listocspcerts]"
-           " [--listgroups]"
-           " \\\n   "
-           " [--listcainfos]"
-           " [--listcrls]"
-           " [--listocsp]"
-           " [--listcards]"
-           " [--listall]"
-           "\n\n"
-       "purge: whack"
-           " [--purgeocsp]"
-           "\n\n"
-       "reread: whack"
-           " [--rereadsecrets]"
-           " [--rereadcacerts]"
-           " [--rereadaacerts]"
-           " \\\n   "
-           " [--rereadocspcerts]"
-           " [--rereadacerts]"
-           " [--rereadcrls]"
-           " [--rereadall]"
-           "\n\n"
-       "status: whack"
-           " [--name <connection_name>] --status|--statusall"
-           "\n\n"
-       "scdecrypt: whack"
-           " --scencrypt|scdecrypt <value>"
-           " [--inbase <base>]"
-           " [--outbase <base>]"
-           " [--keyid <id>]"
-           "\n\n"
-       "shutdown: whack"
-           " --shutdown"
-           "\n\n"
-       "strongSwan %s\n"
-       , ipsec_version_code());
+               "listen: whack"
+                       " (--listen | --unlisten)"
+                       "\n\n"
+               "list: whack [--utc]"
+                       " [--listalgs]"
+                       " [--listpubkeys]"
+                       " [--listcerts]"
+                       " [--listcacerts]"
+                       " \\\n   "
+                       " [--listacerts]"
+                       " [--listaacerts]"
+                       " [--listocspcerts]"
+                       " [--listgroups]"
+                       " \\\n   "
+                       " [--listcainfos]"
+                       " [--listcrls]"
+                       " [--listocsp]"
+                       " [--listcards]"
+                       " [--listall]"
+                       "\n\n"
+               "purge: whack"
+                       " [--purgeocsp]"
+                       "\n\n"
+               "reread: whack"
+                       " [--rereadsecrets]"
+                       " [--rereadcacerts]"
+                       " [--rereadaacerts]"
+                       " \\\n   "
+                       " [--rereadocspcerts]"
+                       " [--rereadacerts]"
+                       " [--rereadcrls]"
+                       " [--rereadall]"
+                       "\n\n"
+               "status: whack"
+                       " [--name <connection_name>] --status|--statusall"
+                       "\n\n"
+               "scdecrypt: whack"
+                       " --scencrypt|scdecrypt <value>"
+                       " [--inbase <base>]"
+                       " [--outbase <base>]"
+                       " [--keyid <id>]"
+                       "\n\n"
+               "shutdown: whack"
+                       " --shutdown"
+                       "\n\n"
+               "strongSwan %s\n"
+               , ipsec_version_code());
 }
 
-static const char *label = NULL;       /* --label operand, saved for diagnostics */
+static const char *label = NULL;        /* --label operand, saved for diagnostics */
 
-static const char *name = NULL;        /* --name operand, saved for diagnostics */
+static const char *name = NULL; /* --name operand, saved for diagnostics */
 
-/* print a string as a diagnostic, then exit whack unhappily */
-static void
-diag(const char *mess)
+/* options read by optionsfrom */
+options_t *options;
+
+/**
+ * exit whack after cleaning up
+ */
+static void whack_exit(int status)
 {
-    if (mess != NULL)
-    {
-       fprintf(stderr, "whack error: ");
-       if (label != NULL)
-           fprintf(stderr, "%s ", label);
-       if (name != NULL)
-           fprintf(stderr, "\"%s\" ", name);
-       fprintf(stderr, "%s\n", mess);
-    }
-
-    exit(RC_WHACK_PROBLEM);
+       options->destroy(options);
+       exit(status);
 }
 
-/* conditially calls diag; prints second arg, if non-NULL, as quoted string */
-static void
-diagq(err_t ugh, const char *this)
+/**
+ * print a string as a diagnostic, then exit whack unhappily
+ */
+static void diag(const char *mess)
 {
-    if (ugh != NULL)
-    {
-       if (this == NULL)
+       if (mess != NULL)
        {
-           diag(ugh);
+               fprintf(stderr, "whack error: ");
+               if (label != NULL)
+               {
+                       fprintf(stderr, "%s ", label);
+               }
+               if (name != NULL)
+               {
+                       fprintf(stderr, "\"%s\" ", name);
+               }
+               fprintf(stderr, "%s\n", mess);
        }
-       else
+       whack_exit(RC_WHACK_PROBLEM);
+}
+
+/* conditially calls diag; prints second arg, if non-NULL, as quoted string */
+static void diagq(err_t ugh, const char *this)
+{
+       if (ugh != NULL)
        {
-           char buf[120];      /* arbitrary limit */
+               if (this == NULL)
+               {
+                       diag(ugh);
+               }
+               else
+               {
+                       char buf[120];      /* arbitrary limit */
 
-           snprintf(buf, sizeof(buf), "%s \"%s\"", ugh, this);
-           diag(buf);
+                       snprintf(buf, sizeof(buf), "%s \"%s\"", ugh, this);
+                       diag(buf);
+               }
        }
-    }
 }
 
 /* complex combined operands return one of these enumerated values
@@ -287,181 +301,181 @@ diagq(err_t ugh, const char *this)
  * - CA_* options (CA description options)
  */
 enum {
-#   define OPT_FIRST   OPT_CTLBASE
-    OPT_CTLBASE,
-    OPT_NAME,
+#   define OPT_FIRST    OPT_CTLBASE
+       OPT_CTLBASE,
+       OPT_NAME,
 
-    OPT_CD,
+       OPT_CD,
 
-    OPT_KEYID,
-    OPT_ADDKEY,
-    OPT_PUBKEYRSA,
+       OPT_KEYID,
+       OPT_ADDKEY,
+       OPT_PUBKEYRSA,
 
-    OPT_MYID,
+       OPT_MYID,
 
-    OPT_ROUTE,
-    OPT_UNROUTE,
+       OPT_ROUTE,
+       OPT_UNROUTE,
 
-    OPT_INITIATE,
-    OPT_TERMINATE,
-    OPT_DELETE,
-    OPT_DELETESTATE,
-    OPT_LISTEN,
-    OPT_UNLISTEN,
+       OPT_INITIATE,
+       OPT_TERMINATE,
+       OPT_DELETE,
+       OPT_DELETESTATE,
+       OPT_LISTEN,
+       OPT_UNLISTEN,
 
-    OPT_PURGEOCSP,
+       OPT_PURGEOCSP,
 
-    OPT_REREADSECRETS,
-    OPT_REREADCACERTS,
-    OPT_REREADAACERTS,
-    OPT_REREADOCSPCERTS,
-    OPT_REREADACERTS,
-    OPT_REREADCRLS,
-    OPT_REREADALL,
+       OPT_REREADSECRETS,
+       OPT_REREADCACERTS,
+       OPT_REREADAACERTS,
+       OPT_REREADOCSPCERTS,
+       OPT_REREADACERTS,
+       OPT_REREADCRLS,
+       OPT_REREADALL,
 
-    OPT_STATUS,
-    OPT_STATUSALL,
-    OPT_SHUTDOWN,
+       OPT_STATUS,
+       OPT_STATUSALL,
+       OPT_SHUTDOWN,
 
-    OPT_OPPO_HERE,
-    OPT_OPPO_THERE,
+       OPT_OPPO_HERE,
+       OPT_OPPO_THERE,
 
-    OPT_ASYNC,
-    OPT_DELETECRASH,
+       OPT_ASYNC,
+       OPT_DELETECRASH,
 
-#   define OPT_LAST OPT_ASYNC  /* last "normal" option */
+#   define OPT_LAST OPT_ASYNC   /* last "normal" option */
 
 /* Smartcard options */
 
-#   define SC_FIRST SC_ENCRYPT /* first smartcard option */
+#   define SC_FIRST SC_ENCRYPT  /* first smartcard option */
 
-    SC_ENCRYPT,
-    SC_DECRYPT,
-    SC_INBASE,
-    SC_OUTBASE,
+       SC_ENCRYPT,
+       SC_DECRYPT,
+       SC_INBASE,
+       SC_OUTBASE,
 
-#   define SC_LAST SC_OUTBASE  /* last "smartcard" option */
+#   define SC_LAST SC_OUTBASE   /* last "smartcard" option */
 
 /* List options */
 
-#   define LST_FIRST LST_UTC   /* first list option */
-    LST_UTC,
-    LST_ALGS,
-    LST_PUBKEYS,
-    LST_CERTS,
-    LST_CACERTS,
-    LST_ACERTS,
-    LST_AACERTS,
-    LST_OCSPCERTS,
-    LST_GROUPS,
-    LST_CAINFOS,
-    LST_CRLS,
-    LST_OCSP,
-    LST_CARDS,
-    LST_ALL,
-
-#   define LST_LAST LST_ALL    /* last list option */
+#   define LST_FIRST LST_UTC    /* first list option */
+       LST_UTC,
+       LST_ALGS,
+       LST_PUBKEYS,
+       LST_CERTS,
+       LST_CACERTS,
+       LST_ACERTS,
+       LST_AACERTS,
+       LST_OCSPCERTS,
+       LST_GROUPS,
+       LST_CAINFOS,
+       LST_CRLS,
+       LST_OCSP,
+       LST_CARDS,
+       LST_ALL,
+
+#   define LST_LAST LST_ALL     /* last list option */
 
 /* Connection End Description options */
 
-#   define END_FIRST END_HOST  /* first end description */
-    END_HOST,
-    END_ID,
-    END_CERT,
-    END_CA,
-    END_SENDCERT,
-    END_GROUPS,
-    END_IKEPORT,
-    END_NEXTHOP,
-    END_CLIENT,
-    END_CLIENTWITHIN,
-    END_CLIENTPROTOPORT,
-    END_DNSKEYONDEMAND,
-    END_SRCIP,
-    END_HOSTACCESS,
-    END_UPDOWN,
-       
-#define END_LAST  END_UPDOWN   /* last end description*/
+#   define END_FIRST END_HOST   /* first end description */
+       END_HOST,
+       END_ID,
+       END_CERT,
+       END_CA,
+       END_SENDCERT,
+       END_GROUPS,
+       END_IKEPORT,
+       END_NEXTHOP,
+       END_CLIENT,
+       END_CLIENTWITHIN,
+       END_CLIENTPROTOPORT,
+       END_DNSKEYONDEMAND,
+       END_SRCIP,
+       END_HOSTACCESS,
+       END_UPDOWN,
+               
+#define END_LAST  END_UPDOWN    /* last end description*/
 
 /* Connection Description options -- segregated */
 
-#   define CD_FIRST CD_TO      /* first connection description */
-    CD_TO,
+#   define CD_FIRST CD_TO       /* first connection description */
+       CD_TO,
 
 #   define CD_POLICY_FIRST  CD_PSK
-    CD_PSK,    /* same order as POLICY_* */
-    CD_RSASIG, /* same order as POLICY_* */
-    CD_ENCRYPT,        /* same order as POLICY_* */
-    CD_AUTHENTICATE,   /* same order as POLICY_* */
-    CD_COMPRESS,       /* same order as POLICY_* */
-    CD_TUNNEL, /* same order as POLICY_* */
-    CD_PFS,    /* same order as POLICY_* */
-    CD_DISABLEARRIVALCHECK,    /* same order as POLICY_* */
-    CD_SHUNT0, /* same order as POLICY_* */
-    CD_SHUNT1, /* same order as POLICY_* */
-    CD_FAIL0,  /* same order as POLICY_* */
-    CD_FAIL1,  /* same order as POLICY_* */
-    CD_DONT_REKEY,     /* same order as POLICY_* */
-
-    CD_TUNNELIPV4,
-    CD_TUNNELIPV6,
-    CD_CONNIPV4,
-    CD_CONNIPV6,
-
-    CD_IKELIFETIME,
-    CD_IPSECLIFETIME,
-    CD_RKMARGIN,
-    CD_RKFUZZ,
-    CD_KTRIES,
-    CD_DPDACTION,
-    CD_DPDDELAY,
-    CD_DPDTIMEOUT,
-    CD_IKE,
-    CD_PFSGROUP,
-    CD_ESP,    
-
-#   define CD_LAST CD_ESP      /* last connection description */
+       CD_PSK,     /* same order as POLICY_* */
+       CD_RSASIG,  /* same order as POLICY_* */
+       CD_ENCRYPT, /* same order as POLICY_* */
+       CD_AUTHENTICATE,    /* same order as POLICY_* */
+       CD_COMPRESS,        /* same order as POLICY_* */
+       CD_TUNNEL,  /* same order as POLICY_* */
+       CD_PFS,     /* same order as POLICY_* */
+       CD_DISABLEARRIVALCHECK,     /* same order as POLICY_* */
+       CD_SHUNT0,  /* same order as POLICY_* */
+       CD_SHUNT1,  /* same order as POLICY_* */
+       CD_FAIL0,   /* same order as POLICY_* */
+       CD_FAIL1,   /* same order as POLICY_* */
+       CD_DONT_REKEY,      /* same order as POLICY_* */
+
+       CD_TUNNELIPV4,
+       CD_TUNNELIPV6,
+       CD_CONNIPV4,
+       CD_CONNIPV6,
+
+       CD_IKELIFETIME,
+       CD_IPSECLIFETIME,
+       CD_RKMARGIN,
+       CD_RKFUZZ,
+       CD_KTRIES,
+       CD_DPDACTION,
+       CD_DPDDELAY,
+       CD_DPDTIMEOUT,
+       CD_IKE,
+       CD_PFSGROUP,
+       CD_ESP,     
+
+#   define CD_LAST CD_ESP       /* last connection description */
 
 /* Certificate Authority (CA) description options */
 
-#   define CA_FIRST CA_NAME    /* first ca description */
+#   define CA_FIRST CA_NAME     /* first ca description */
 
-    CA_NAME,
-    CA_CERT,
-    CA_LDAPHOST,
-    CA_LDAPBASE,
-    CA_CRLURI,
-    CA_CRLURI2,
-    CA_OCSPURI,
-    CA_STRICT
+       CA_NAME,
+       CA_CERT,
+       CA_LDAPHOST,
+       CA_LDAPBASE,
+       CA_CRLURI,
+       CA_CRLURI2,
+       CA_OCSPURI,
+       CA_STRICT
 
-#   define CA_LAST CA_STRICT   /* last ca description */
+#   define CA_LAST CA_STRICT    /* last ca description */
 
-#ifdef DEBUG   /* must be last so others are less than 32 to fit in lset_t */
+#ifdef DEBUG    /* must be last so others are less than 32 to fit in lset_t */
 #   define DBGOPT_FIRST DBGOPT_NONE
-    ,
-    /* NOTE: these definitions must match DBG_* and IMPAIR_* in constants.h */
-    DBGOPT_NONE,
-    DBGOPT_ALL,
-
-    DBGOPT_RAW,                /* same order as DBG_* */
-    DBGOPT_CRYPT,      /* same order as DBG_* */
-    DBGOPT_PARSING,    /* same order as DBG_* */
-    DBGOPT_EMITTING,   /* same order as DBG_* */
-    DBGOPT_CONTROL,    /* same order as DBG_* */
-    DBGOPT_LIFECYCLE,  /* same order as DBG_* */
-    DBGOPT_KLIPS,      /* same order as DBG_* */
-    DBGOPT_DNS,                /* same order as DBG_* */
-    DBGOPT_NATT,       /* same order as DBG_* */
-    DBGOPT_OPPO,       /* same order as DBG_* */
-    DBGOPT_CONTROLMORE,        /* same order as DBG_* */
-
-    DBGOPT_PRIVATE,    /* same order as DBG_* */
-
-    DBGOPT_IMPAIR_DELAY_ADNS_KEY_ANSWER,       /* same order as IMPAIR_* */
-    DBGOPT_IMPAIR_DELAY_ADNS_TXT_ANSWER,       /* same order as IMPAIR_* */
-    DBGOPT_IMPAIR_BUST_MI2,    /* same order as IMPAIR_* */
-    DBGOPT_IMPAIR_BUST_MR2     /* same order as IMPAIR_* */
+       ,
+       /* NOTE: these definitions must match DBG_* and IMPAIR_* in constants.h */
+       DBGOPT_NONE,
+       DBGOPT_ALL,
+
+       DBGOPT_RAW,         /* same order as DBG_* */
+       DBGOPT_CRYPT,       /* same order as DBG_* */
+       DBGOPT_PARSING,     /* same order as DBG_* */
+       DBGOPT_EMITTING,    /* same order as DBG_* */
+       DBGOPT_CONTROL,     /* same order as DBG_* */
+       DBGOPT_LIFECYCLE,   /* same order as DBG_* */
+       DBGOPT_KLIPS,       /* same order as DBG_* */
+       DBGOPT_DNS,         /* same order as DBG_* */
+       DBGOPT_NATT,        /* same order as DBG_* */
+       DBGOPT_OPPO,        /* same order as DBG_* */
+       DBGOPT_CONTROLMORE, /* same order as DBG_* */
+
+       DBGOPT_PRIVATE,     /* same order as DBG_* */
+
+       DBGOPT_IMPAIR_DELAY_ADNS_KEY_ANSWER,        /* same order as IMPAIR_* */
+       DBGOPT_IMPAIR_DELAY_ADNS_TXT_ANSWER,        /* same order as IMPAIR_* */
+       DBGOPT_IMPAIR_BUST_MI2,     /* same order as IMPAIR_* */
+       DBGOPT_IMPAIR_BUST_MR2      /* same order as IMPAIR_* */
 
 #   define DBGOPT_LAST DBGOPT_IMPAIR_BUST_MR2
 #endif
@@ -473,1439 +487,1430 @@ enum {
  * Numeric arg is bit immediately left of basic value.
  *
  */
-#define OPTION_OFFSET  256     /* to get out of the way of letter options */
-#define NUMERIC_ARG (1 << 9)   /* expect a numeric argument */
-#define AUX_SHIFT   10 /* amount to shift for aux information */
+#define OPTION_OFFSET   256     /* to get out of the way of letter options */
+#define NUMERIC_ARG (1 << 9)    /* expect a numeric argument */
+#define AUX_SHIFT   10  /* amount to shift for aux information */
 
 static const struct option long_opts[] = {
-#   define OO  OPTION_OFFSET
-    /* name, has_arg, flag, val */
-
-    { "help", no_argument, NULL, 'h' },
-    { "version", no_argument, NULL, 'v' },
-    { "optionsfrom", required_argument, NULL, '+' },
-    { "label", required_argument, NULL, 'l' },
-
-    { "ctlbase", required_argument, NULL, OPT_CTLBASE + OO },
-    { "name", required_argument, NULL, OPT_NAME + OO },
-
-    { "keyid", required_argument, NULL, OPT_KEYID + OO },
-    { "addkey", no_argument, NULL, OPT_ADDKEY + OO },
-    { "pubkeyrsa", required_argument, NULL, OPT_PUBKEYRSA + OO },
-
-    { "myid", required_argument, NULL, OPT_MYID + OO },
-
-    { "route", no_argument, NULL, OPT_ROUTE + OO },
-    { "unroute", no_argument, NULL, OPT_UNROUTE + OO },
-
-    { "initiate", no_argument, NULL, OPT_INITIATE + OO },
-    { "terminate", no_argument, NULL, OPT_TERMINATE + OO },
-    { "delete", no_argument, NULL, OPT_DELETE + OO },
-    { "deletestate", required_argument, NULL, OPT_DELETESTATE + OO + NUMERIC_ARG },
-    { "crash", required_argument, NULL, OPT_DELETECRASH + OO },
-    { "listen", no_argument, NULL, OPT_LISTEN + OO },
-    { "unlisten", no_argument, NULL, OPT_UNLISTEN + OO },
-
-    { "purgeocsp", no_argument, NULL, OPT_PURGEOCSP + OO },
-
-    { "rereadsecrets", no_argument, NULL, OPT_REREADSECRETS + OO },
-    { "rereadcacerts", no_argument, NULL, OPT_REREADCACERTS + OO },
-    { "rereadaacerts", no_argument, NULL, OPT_REREADAACERTS + OO },
-    { "rereadocspcerts", no_argument, NULL, OPT_REREADOCSPCERTS + OO },
-    { "rereadacerts", no_argument, NULL, OPT_REREADACERTS + OO },
-    { "rereadcrls", no_argument, NULL, OPT_REREADCRLS + OO },
-    { "rereadall", no_argument, NULL, OPT_REREADALL + OO },
-    { "status", no_argument, NULL, OPT_STATUS + OO },
-    { "statusall", no_argument, NULL, OPT_STATUSALL + OO },
-    { "shutdown", no_argument, NULL, OPT_SHUTDOWN + OO },
-
-    { "oppohere", required_argument, NULL, OPT_OPPO_HERE + OO },
-    { "oppothere", required_argument, NULL, OPT_OPPO_THERE + OO },
-
-    { "asynchronous", no_argument, NULL, OPT_ASYNC + OO },
-
-    /* smartcard options */
-
-    { "scencrypt", required_argument, NULL, SC_ENCRYPT + OO },
-    { "scdecrypt", required_argument, NULL, SC_DECRYPT + OO },
-    { "inbase", required_argument, NULL, SC_INBASE + OO },
-    { "outbase", required_argument, NULL, SC_OUTBASE + OO },
-
-    /* list options */
-
-    { "utc", no_argument, NULL, LST_UTC + OO },
-    { "listalgs", no_argument, NULL, LST_ALGS + OO },
-    { "listpubkeys", no_argument, NULL, LST_PUBKEYS + OO },
-    { "listcerts", no_argument, NULL, LST_CERTS + OO },
-    { "listcacerts", no_argument, NULL, LST_CACERTS + OO },
-    { "listacerts", no_argument, NULL, LST_ACERTS + OO },
-    { "listaacerts", no_argument, NULL, LST_AACERTS + OO },
-    { "listocspcerts", no_argument, NULL, LST_OCSPCERTS + OO },
-    { "listgroups", no_argument, NULL, LST_GROUPS + OO },
-    { "listcainfos", no_argument, NULL, LST_CAINFOS + OO },
-    { "listcrls", no_argument, NULL, LST_CRLS + OO },
-    { "listocsp", no_argument, NULL, LST_OCSP + OO },
-    { "listcards", no_argument, NULL, LST_CARDS + OO },
-    { "listall", no_argument, NULL, LST_ALL + OO },
-
-    /* options for an end description */
-
-    { "host", required_argument, NULL, END_HOST + OO },
-    { "id", required_argument, NULL, END_ID + OO },
-    { "cert", required_argument, NULL, END_CERT + OO },
-    { "ca", required_argument, NULL, END_CA + OO },
-    { "sendcert", required_argument, NULL, END_SENDCERT + OO },
-    { "groups", required_argument, NULL, END_GROUPS + OO },
-    { "ikeport", required_argument, NULL, END_IKEPORT + OO + NUMERIC_ARG },
-    { "nexthop", required_argument, NULL, END_NEXTHOP + OO },
-    { "client", required_argument, NULL, END_CLIENT + OO },
-    { "clientwithin", required_argument, NULL, END_CLIENTWITHIN + OO },
-    { "clientprotoport", required_argument, NULL, END_CLIENTPROTOPORT + OO },
-    { "dnskeyondemand", no_argument, NULL, END_DNSKEYONDEMAND + OO },
-    { "srcip",  required_argument, NULL, END_SRCIP + OO },
-    { "hostaccess", no_argument, NULL, END_HOSTACCESS + OO },
-    { "updown", required_argument, NULL, END_UPDOWN + OO },
-
-    /* options for a connection description */
-
-    { "to", no_argument, NULL, CD_TO + OO },
-
-    { "psk", no_argument, NULL, CD_PSK + OO },
-    { "rsasig", no_argument, NULL, CD_RSASIG + OO },
-
-    { "encrypt", no_argument, NULL, CD_ENCRYPT + OO },
-    { "authenticate", no_argument, NULL, CD_AUTHENTICATE + OO },
-    { "compress", no_argument, NULL, CD_COMPRESS + OO },
-    { "tunnel", no_argument, NULL, CD_TUNNEL + OO },
-    { "tunnelipv4", no_argument, NULL, CD_TUNNELIPV4 + OO },
-    { "tunnelipv6", no_argument, NULL, CD_TUNNELIPV6 + OO },
-    { "pfs", no_argument, NULL, CD_PFS + OO },
-    { "disablearrivalcheck", no_argument, NULL, CD_DISABLEARRIVALCHECK + OO },
-    { "initiateontraffic", no_argument, NULL
-       , CD_SHUNT0 + (POLICY_SHUNT_TRAP >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO },
-    { "pass", no_argument, NULL
-       , CD_SHUNT0 + (POLICY_SHUNT_PASS >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO },
-    { "drop", no_argument, NULL
-       , CD_SHUNT0 + (POLICY_SHUNT_DROP >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO },
-    { "reject", no_argument, NULL
-       , CD_SHUNT0 + (POLICY_SHUNT_REJECT >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO },
-    { "failnone", no_argument, NULL
-       , CD_FAIL0 + (POLICY_FAIL_NONE >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO },
-    { "failpass", no_argument, NULL
-       , CD_FAIL0 + (POLICY_FAIL_PASS >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO },
-    { "faildrop", no_argument, NULL
-       , CD_FAIL0 + (POLICY_FAIL_DROP >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO },
-    { "failreject", no_argument, NULL
-       , CD_FAIL0 + (POLICY_FAIL_REJECT >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO },
-    { "dontrekey", no_argument, NULL, CD_DONT_REKEY + OO },
-    { "ipv4", no_argument, NULL, CD_CONNIPV4 + OO },
-    { "ipv6", no_argument, NULL, CD_CONNIPV6 + OO },
-
-    { "ikelifetime", required_argument, NULL, CD_IKELIFETIME + OO + NUMERIC_ARG },
-    { "ipseclifetime", required_argument, NULL, CD_IPSECLIFETIME + OO + NUMERIC_ARG },
-    { "rekeymargin", required_argument, NULL, CD_RKMARGIN + OO + NUMERIC_ARG },
-    { "rekeywindow", required_argument, NULL, CD_RKMARGIN + OO + NUMERIC_ARG },        /* OBSOLETE */
-    { "rekeyfuzz", required_argument, NULL, CD_RKFUZZ + OO + NUMERIC_ARG },
-    { "keyingtries", required_argument, NULL, CD_KTRIES + OO + NUMERIC_ARG },
-    { "dpdaction", required_argument, NULL, CD_DPDACTION + OO },
-    { "dpddelay", required_argument, NULL, CD_DPDDELAY + OO + NUMERIC_ARG },
-    { "dpdtimeout", required_argument, NULL, CD_DPDTIMEOUT + OO + NUMERIC_ARG },
-    { "ike", required_argument, NULL, CD_IKE + OO },
-    { "pfsgroup", required_argument, NULL, CD_PFSGROUP + OO },
-    { "esp", required_argument, NULL, CD_ESP + OO },
-
-    /* options for a ca description */
-
-    { "caname", required_argument, NULL, CA_NAME + OO },
-    { "cacert", required_argument, NULL, CA_CERT + OO },
-    { "ldaphost", required_argument, NULL, CA_LDAPHOST + OO },
-    { "ldapbase", required_argument, NULL, CA_LDAPBASE + OO },
-    { "crluri", required_argument, NULL, CA_CRLURI + OO },
-    { "crluri2", required_argument, NULL, CA_CRLURI2 + OO },
-    { "ocspuri", required_argument, NULL, CA_OCSPURI + OO },
-    { "strictcrlpolicy", no_argument, NULL, CA_STRICT + OO },
+#   define OO   OPTION_OFFSET
+       /* name, has_arg, flag, val */
+
+       { "help", no_argument, NULL, 'h' },
+       { "version", no_argument, NULL, 'v' },
+       { "optionsfrom", required_argument, NULL, '+' },
+       { "label", required_argument, NULL, 'l' },
+
+       { "ctlbase", required_argument, NULL, OPT_CTLBASE + OO },
+       { "name", required_argument, NULL, OPT_NAME + OO },
+
+       { "keyid", required_argument, NULL, OPT_KEYID + OO },
+       { "addkey", no_argument, NULL, OPT_ADDKEY + OO },
+       { "pubkeyrsa", required_argument, NULL, OPT_PUBKEYRSA + OO },
+
+       { "myid", required_argument, NULL, OPT_MYID + OO },
+
+       { "route", no_argument, NULL, OPT_ROUTE + OO },
+       { "unroute", no_argument, NULL, OPT_UNROUTE + OO },
+
+       { "initiate", no_argument, NULL, OPT_INITIATE + OO },
+       { "terminate", no_argument, NULL, OPT_TERMINATE + OO },
+       { "delete", no_argument, NULL, OPT_DELETE + OO },
+       { "deletestate", required_argument, NULL, OPT_DELETESTATE + OO + NUMERIC_ARG },
+       { "crash", required_argument, NULL, OPT_DELETECRASH + OO },
+       { "listen", no_argument, NULL, OPT_LISTEN + OO },
+       { "unlisten", no_argument, NULL, OPT_UNLISTEN + OO },
+
+       { "purgeocsp", no_argument, NULL, OPT_PURGEOCSP + OO },
+
+       { "rereadsecrets", no_argument, NULL, OPT_REREADSECRETS + OO },
+       { "rereadcacerts", no_argument, NULL, OPT_REREADCACERTS + OO },
+       { "rereadaacerts", no_argument, NULL, OPT_REREADAACERTS + OO },
+       { "rereadocspcerts", no_argument, NULL, OPT_REREADOCSPCERTS + OO },
+       { "rereadacerts", no_argument, NULL, OPT_REREADACERTS + OO },
+       { "rereadcrls", no_argument, NULL, OPT_REREADCRLS + OO },
+       { "rereadall", no_argument, NULL, OPT_REREADALL + OO },
+       { "status", no_argument, NULL, OPT_STATUS + OO },
+       { "statusall", no_argument, NULL, OPT_STATUSALL + OO },
+       { "shutdown", no_argument, NULL, OPT_SHUTDOWN + OO },
+
+       { "oppohere", required_argument, NULL, OPT_OPPO_HERE + OO },
+       { "oppothere", required_argument, NULL, OPT_OPPO_THERE + OO },
+
+       { "asynchronous", no_argument, NULL, OPT_ASYNC + OO },
+
+       /* smartcard options */
+
+       { "scencrypt", required_argument, NULL, SC_ENCRYPT + OO },
+       { "scdecrypt", required_argument, NULL, SC_DECRYPT + OO },
+       { "inbase", required_argument, NULL, SC_INBASE + OO },
+       { "outbase", required_argument, NULL, SC_OUTBASE + OO },
+
+       /* list options */
+
+       { "utc", no_argument, NULL, LST_UTC + OO },
+       { "listalgs", no_argument, NULL, LST_ALGS + OO },
+       { "listpubkeys", no_argument, NULL, LST_PUBKEYS + OO },
+       { "listcerts", no_argument, NULL, LST_CERTS + OO },
+       { "listcacerts", no_argument, NULL, LST_CACERTS + OO },
+       { "listacerts", no_argument, NULL, LST_ACERTS + OO },
+       { "listaacerts", no_argument, NULL, LST_AACERTS + OO },
+       { "listocspcerts", no_argument, NULL, LST_OCSPCERTS + OO },
+       { "listgroups", no_argument, NULL, LST_GROUPS + OO },
+       { "listcainfos", no_argument, NULL, LST_CAINFOS + OO },
+       { "listcrls", no_argument, NULL, LST_CRLS + OO },
+       { "listocsp", no_argument, NULL, LST_OCSP + OO },
+       { "listcards", no_argument, NULL, LST_CARDS + OO },
+       { "listall", no_argument, NULL, LST_ALL + OO },
+
+       /* options for an end description */
+
+       { "host", required_argument, NULL, END_HOST + OO },
+       { "id", required_argument, NULL, END_ID + OO },
+       { "cert", required_argument, NULL, END_CERT + OO },
+       { "ca", required_argument, NULL, END_CA + OO },
+       { "sendcert", required_argument, NULL, END_SENDCERT + OO },
+       { "groups", required_argument, NULL, END_GROUPS + OO },
+       { "ikeport", required_argument, NULL, END_IKEPORT + OO + NUMERIC_ARG },
+       { "nexthop", required_argument, NULL, END_NEXTHOP + OO },
+       { "client", required_argument, NULL, END_CLIENT + OO },
+       { "clientwithin", required_argument, NULL, END_CLIENTWITHIN + OO },
+       { "clientprotoport", required_argument, NULL, END_CLIENTPROTOPORT + OO },
+       { "dnskeyondemand", no_argument, NULL, END_DNSKEYONDEMAND + OO },
+       { "srcip",  required_argument, NULL, END_SRCIP + OO },
+       { "hostaccess", no_argument, NULL, END_HOSTACCESS + OO },
+       { "updown", required_argument, NULL, END_UPDOWN + OO },
+
+       /* options for a connection description */
+
+       { "to", no_argument, NULL, CD_TO + OO },
+
+       { "psk", no_argument, NULL, CD_PSK + OO },
+       { "rsasig", no_argument, NULL, CD_RSASIG + OO },
+
+       { "encrypt", no_argument, NULL, CD_ENCRYPT + OO },
+       { "authenticate", no_argument, NULL, CD_AUTHENTICATE + OO },
+       { "compress", no_argument, NULL, CD_COMPRESS + OO },
+       { "tunnel", no_argument, NULL, CD_TUNNEL + OO },
+       { "tunnelipv4", no_argument, NULL, CD_TUNNELIPV4 + OO },
+       { "tunnelipv6", no_argument, NULL, CD_TUNNELIPV6 + OO },
+       { "pfs", no_argument, NULL, CD_PFS + OO },
+       { "disablearrivalcheck", no_argument, NULL, CD_DISABLEARRIVALCHECK + OO },
+       { "initiateontraffic", no_argument, NULL
+               , CD_SHUNT0 + (POLICY_SHUNT_TRAP >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO },
+       { "pass", no_argument, NULL
+               , CD_SHUNT0 + (POLICY_SHUNT_PASS >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO },
+       { "drop", no_argument, NULL
+               , CD_SHUNT0 + (POLICY_SHUNT_DROP >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO },
+       { "reject", no_argument, NULL
+               , CD_SHUNT0 + (POLICY_SHUNT_REJECT >> POLICY_SHUNT_SHIFT << AUX_SHIFT) + OO },
+       { "failnone", no_argument, NULL
+               , CD_FAIL0 + (POLICY_FAIL_NONE >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO },
+       { "failpass", no_argument, NULL
+               , CD_FAIL0 + (POLICY_FAIL_PASS >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO },
+       { "faildrop", no_argument, NULL
+               , CD_FAIL0 + (POLICY_FAIL_DROP >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO },
+       { "failreject", no_argument, NULL
+               , CD_FAIL0 + (POLICY_FAIL_REJECT >> POLICY_FAIL_SHIFT << AUX_SHIFT) + OO },
+       { "dontrekey", no_argument, NULL, CD_DONT_REKEY + OO },
+       { "ipv4", no_argument, NULL, CD_CONNIPV4 + OO },
+       { "ipv6", no_argument, NULL, CD_CONNIPV6 + OO },
+
+       { "ikelifetime", required_argument, NULL, CD_IKELIFETIME + OO + NUMERIC_ARG },
+       { "ipseclifetime", required_argument, NULL, CD_IPSECLIFETIME + OO + NUMERIC_ARG },
+       { "rekeymargin", required_argument, NULL, CD_RKMARGIN + OO + NUMERIC_ARG },
+       { "rekeywindow", required_argument, NULL, CD_RKMARGIN + OO + NUMERIC_ARG }, /* OBSOLETE */
+       { "rekeyfuzz", required_argument, NULL, CD_RKFUZZ + OO + NUMERIC_ARG },
+       { "keyingtries", required_argument, NULL, CD_KTRIES + OO + NUMERIC_ARG },
+       { "dpdaction", required_argument, NULL, CD_DPDACTION + OO },
+       { "dpddelay", required_argument, NULL, CD_DPDDELAY + OO + NUMERIC_ARG },
+       { "dpdtimeout", required_argument, NULL, CD_DPDTIMEOUT + OO + NUMERIC_ARG },
+       { "ike", required_argument, NULL, CD_IKE + OO },
+       { "pfsgroup", required_argument, NULL, CD_PFSGROUP + OO },
+       { "esp", required_argument, NULL, CD_ESP + OO },
+
+       /* options for a ca description */
+
+       { "caname", required_argument, NULL, CA_NAME + OO },
+       { "cacert", required_argument, NULL, CA_CERT + OO },
+       { "ldaphost", required_argument, NULL, CA_LDAPHOST + OO },
+       { "ldapbase", required_argument, NULL, CA_LDAPBASE + OO },
+       { "crluri", required_argument, NULL, CA_CRLURI + OO },
+       { "crluri2", required_argument, NULL, CA_CRLURI2 + OO },
+       { "ocspuri", required_argument, NULL, CA_OCSPURI + OO },
+       { "strictcrlpolicy", no_argument, NULL, CA_STRICT + OO },
 
 #ifdef DEBUG
-    { "debug-none", no_argument, NULL, DBGOPT_NONE + OO },
-    { "debug-all]", no_argument, NULL, DBGOPT_ALL + OO },
-    { "debug-raw", no_argument, NULL, DBGOPT_RAW + OO },
-    { "debug-crypt", no_argument, NULL, DBGOPT_CRYPT + OO },
-    { "debug-parsing", no_argument, NULL, DBGOPT_PARSING + OO },
-    { "debug-emitting", no_argument, NULL, DBGOPT_EMITTING + OO },
-    { "debug-control", no_argument, NULL, DBGOPT_CONTROL + OO },
-    { "debug-lifecycle", no_argument, NULL, DBGOPT_LIFECYCLE + OO },
-    { "debug-klips", no_argument, NULL, DBGOPT_KLIPS + OO },
-    { "debug-dns", no_argument, NULL, DBGOPT_DNS + OO },
-    { "debug-natt", no_argument, NULL, DBGOPT_NATT + OO },
-    { "debug-oppo", no_argument, NULL, DBGOPT_OPPO + OO },
-    { "debug-controlmore", no_argument, NULL, DBGOPT_CONTROLMORE + OO },
-    { "debug-private", no_argument, NULL, DBGOPT_PRIVATE + OO },
-
-    { "impair-delay-adns-key-answer", no_argument, NULL, DBGOPT_IMPAIR_DELAY_ADNS_KEY_ANSWER + OO },
-    { "impair-delay-adns-txt-answer", no_argument, NULL, DBGOPT_IMPAIR_DELAY_ADNS_TXT_ANSWER + OO },
-    { "impair-bust-mi2", no_argument, NULL, DBGOPT_IMPAIR_BUST_MI2 + OO },
-    { "impair-bust-mr2", no_argument, NULL, DBGOPT_IMPAIR_BUST_MR2 + OO },
+       { "debug-none", no_argument, NULL, DBGOPT_NONE + OO },
+       { "debug-all]", no_argument, NULL, DBGOPT_ALL + OO },
+       { "debug-raw", no_argument, NULL, DBGOPT_RAW + OO },
+       { "debug-crypt", no_argument, NULL, DBGOPT_CRYPT + OO },
+       { "debug-parsing", no_argument, NULL, DBGOPT_PARSING + OO },
+       { "debug-emitting", no_argument, NULL, DBGOPT_EMITTING + OO },
+       { "debug-control", no_argument, NULL, DBGOPT_CONTROL + OO },
+       { "debug-lifecycle", no_argument, NULL, DBGOPT_LIFECYCLE + OO },
+       { "debug-klips", no_argument, NULL, DBGOPT_KLIPS + OO },
+       { "debug-dns", no_argument, NULL, DBGOPT_DNS + OO },
+       { "debug-natt", no_argument, NULL, DBGOPT_NATT + OO },
+       { "debug-oppo", no_argument, NULL, DBGOPT_OPPO + OO },
+       { "debug-controlmore", no_argument, NULL, DBGOPT_CONTROLMORE + OO },
+       { "debug-private", no_argument, NULL, DBGOPT_PRIVATE + OO },
+
+       { "impair-delay-adns-key-answer", no_argument, NULL, DBGOPT_IMPAIR_DELAY_ADNS_KEY_ANSWER + OO },
+       { "impair-delay-adns-txt-answer", no_argument, NULL, DBGOPT_IMPAIR_DELAY_ADNS_TXT_ANSWER + OO },
+       { "impair-bust-mi2", no_argument, NULL, DBGOPT_IMPAIR_BUST_MI2 + OO },
+       { "impair-bust-mr2", no_argument, NULL, DBGOPT_IMPAIR_BUST_MR2 + OO },
 #endif
 #   undef OO
-    { 0,0,0,0 }
+       { 0,0,0,0 }
 };
 
 struct sockaddr_un ctl_addr = { AF_UNIX, DEFAULT_CTLBASE CTL_SUFFIX };
 
 /* helper variables and function to encode strings from whack message */
 
-static char
-    *next_str,
-    *str_roof;
+static char    *next_str,*str_roof;
 
-static bool
-pack_str(char **p)
+static bool pack_str(char **p)
 {
-    const char *s = *p == NULL? "" : *p;       /* note: NULL becomes ""! */
-    size_t len = strlen(s) + 1;
-
-    if (str_roof - next_str < (ptrdiff_t)len)
-    {
-       return FALSE;   /* fishy: no end found */
-    }
-    else
-    {
-       strcpy(next_str, s);
-       next_str += len;
-       *p = NULL;      /* don't send pointers on the wire! */
-       return TRUE;
-    }
+       const char *s = *p == NULL? "" : *p;        /* note: NULL becomes ""! */
+       size_t len = strlen(s) + 1;
+
+       if (str_roof - next_str < (ptrdiff_t)len)
+       {
+               return FALSE;   /* fishy: no end found */
+       }
+       else
+       {
+               strcpy(next_str, s);
+               next_str += len;
+               *p = NULL;      /* don't send pointers on the wire! */
+               return TRUE;
+       }
 }
 
-static void
-check_life_time(time_t life, time_t limit, const char *which
-, const whack_message_t *msg)
+static void check_life_time(time_t life, time_t limit, const char *which,
+                                                       const whack_message_t *msg)
 {
-    time_t mint = msg->sa_rekey_margin * (100 + msg->sa_rekey_fuzz) / 100;
-
-    if (life > limit)
-    {
-       char buf[200];  /* arbitrary limit */
-
-       snprintf(buf, sizeof(buf)
-           , "%s [%lu seconds] must be less than %lu seconds"
-           , which, (unsigned long)life, (unsigned long)limit);
-       diag(buf);
-    }
-    if ((msg->policy & POLICY_DONT_REKEY) == LEMPTY && life <= mint)
-    {
-       char buf[200];  /* arbitrary limit */
-
-       snprintf(buf, sizeof(buf)
-           , "%s [%lu] must be greater than"
-           " rekeymargin*(100+rekeyfuzz)/100 [%lu*(100+%lu)/100 = %lu]"
-           , which
-           , (unsigned long)life
-           , (unsigned long)msg->sa_rekey_margin
-           , (unsigned long)msg->sa_rekey_fuzz
-           , (unsigned long)mint);
-       diag(buf);
-    }
+       time_t mint = msg->sa_rekey_margin * (100 + msg->sa_rekey_fuzz) / 100;
+
+       if (life > limit)
+       {
+               char buf[200];  /* arbitrary limit */
+
+               snprintf(buf, sizeof(buf)
+                       , "%s [%lu seconds] must be less than %lu seconds"
+                       , which, (unsigned long)life, (unsigned long)limit);
+               diag(buf);
+       }
+       if ((msg->policy & POLICY_DONT_REKEY) == LEMPTY && life <= mint)
+       {
+               char buf[200];  /* arbitrary limit */
+
+               snprintf(buf, sizeof(buf)
+                       , "%s [%lu] must be greater than"
+                       " rekeymargin*(100+rekeyfuzz)/100 [%lu*(100+%lu)/100 = %lu]"
+                       , which
+                       , (unsigned long)life
+                       , (unsigned long)msg->sa_rekey_margin
+                       , (unsigned long)msg->sa_rekey_fuzz
+                       , (unsigned long)mint);
+               diag(buf);
+       }
 }
 
-static void
-clear_end(whack_end_t *e)
+static void clear_end(whack_end_t *e)
 {
-    zero(e);
-    e->id = NULL;
-    e->cert = NULL;
-    e->ca = NULL;
-    e->updown = NULL;
-    e->host_port = IKE_UDP_PORT;
+       zero(e);
+       e->id = NULL;
+       e->cert = NULL;
+       e->ca = NULL;
+       e->updown = NULL;
+       e->host_port = IKE_UDP_PORT;
 }
 
-static void
-update_ports(whack_message_t *m)
+static void update_ports(whack_message_t *m)
 {
-    int port;
-
-    if (m->left.port != 0) {
-        port = htons(m->left.port);
-        setportof(port, &m->left.host_addr);
-        setportof(port, &m->left.client.addr);
-    }
-    if (m->right.port != 0) {
-        port = htons(m->right.port);
-        setportof(port, &m->right.host_addr);
-        setportof(port, &m->right.client.addr);
-    }
+       int port;
+
+       if (m->left.port != 0) {
+               port = htons(m->left.port);
+               setportof(port, &m->left.host_addr);
+               setportof(port, &m->left.client.addr);
+       }
+       if (m->right.port != 0) {
+               port = htons(m->right.port);
+               setportof(port, &m->right.host_addr);
+               setportof(port, &m->right.client.addr);
+       }
 }
 
-static void
-check_end(whack_end_t *this, whack_end_t *that
-, bool default_nexthop, sa_family_t caf, sa_family_t taf)
+static void check_end(whack_end_t *this, whack_end_t *that,
+                                         bool default_nexthop, sa_family_t caf, sa_family_t taf)
 {
-    if (caf != addrtypeof(&this->host_addr))
-       diag("address family of host inconsistent");
-
-    if (default_nexthop)
-    {
-       if (isanyaddr(&that->host_addr))
-           diag("our nexthop must be specified when other host is a %any or %opportunistic");
-       this->host_nexthop = that->host_addr;
-    }
-
-    if (caf != addrtypeof(&this->host_nexthop))
-       diag("address family of nexthop inconsistent");
-
-    if (this->has_client)
-    {
-       if (taf != subnettypeof(&this->client))
-           diag("address family of client subnet inconsistent");
-    }
-    else
-    {
-       /* fill in anyaddr-anyaddr as (missing) client subnet */
-       ip_address cn;
-
-       diagq(anyaddr(caf, &cn), NULL);
-       diagq(rangetosubnet(&cn, &cn, &this->client), NULL);
-    }
-
-    /* fill in anyaddr if source IP is not defined */
-    if (!this->has_srcip)
-       diagq(anyaddr(caf, &this->host_srcip), optarg);
+       if (caf != addrtypeof(&this->host_addr))
+               diag("address family of host inconsistent");
+
+       if (default_nexthop)
+       {
+               if (isanyaddr(&that->host_addr))
+                       diag("our nexthop must be specified when other host is a %any or %opportunistic");
+               this->host_nexthop = that->host_addr;
+       }
+
+       if (caf != addrtypeof(&this->host_nexthop))
+               diag("address family of nexthop inconsistent");
+
+       if (this->has_client)
+       {
+               if (taf != subnettypeof(&this->client))
+                       diag("address family of client subnet inconsistent");
+       }
+       else
+       {
+               /* fill in anyaddr-anyaddr as (missing) client subnet */
+               ip_address cn;
+
+               diagq(anyaddr(caf, &cn), NULL);
+               diagq(rangetosubnet(&cn, &cn, &this->client), NULL);
+       }
+
+       /* fill in anyaddr if source IP is not defined */
+       if (!this->has_srcip)
+               diagq(anyaddr(caf, &this->host_srcip), optarg);
 
    /* check protocol */
-    if (this->protocol != that->protocol)
-       diag("the protocol for leftprotoport and rightprotoport must be the same");
+       if (this->protocol != that->protocol)
+               diag("the protocol for leftprotoport and rightprotoport must be the same");
 }
 
-static void
-get_secret(int sock)
+static void get_secret(int sock)
 {
-    const char *buf, *secret;
-    int len;
-
-    fflush(stdout);
-    usleep(20000); /* give fflush time for flushing */
-    buf = getpass("Enter: ");
-    secret = (buf == NULL)? "" : buf;
-
-    /* send the secret to pluto */
-    len = strlen(secret) + 1;
-    if (write(sock, secret, len) != len)
-    {
-       int e = errno;
-
-       fprintf(stderr, "whack: write() failed (%d %s)\n", e, strerror(e));
-       exit(RC_WHACK_PROBLEM);
-    }
+       const char *buf, *secret;
+       int len;
+
+       fflush(stdout);
+       usleep(20000); /* give fflush time for flushing */
+       buf = getpass("Enter: ");
+       secret = (buf == NULL)? "" : buf;
+
+       /* send the secret to pluto */
+       len = strlen(secret) + 1;
+       if (write(sock, secret, len) != len)
+       {
+               int e = errno;
+
+               fprintf(stderr, "whack: write() failed (%d %s)\n", e, strerror(e));
+               exit(RC_WHACK_PROBLEM);
+       }
 }
 
 /* This is a hack for initiating ISAKMP exchanges. */
 
-int
-main(int argc, char **argv)
+int main(int argc, char **argv)
 {
-    whack_message_t msg;
-    char esp_buf[256]; /* uses snprintf */
-    lset_t
-       opts_seen = LEMPTY,
-       sc_seen = LEMPTY,
-       lst_seen = LEMPTY,
-       cd_seen = LEMPTY,
-       ca_seen = LEMPTY,
-       end_seen = LEMPTY,
-       end_seen_before_to = LEMPTY;
-    const char
-       *af_used_by = NULL,
-       *tunnel_af_used_by = NULL;
-
-    /* check division of numbering space */
+       whack_message_t msg;
+       char esp_buf[256];  /* uses snprintf */
+       lset_t
+               opts_seen = LEMPTY,
+               sc_seen = LEMPTY,
+               lst_seen = LEMPTY,
+               cd_seen = LEMPTY,
+               ca_seen = LEMPTY,
+               end_seen = LEMPTY,
+               end_seen_before_to = LEMPTY;
+       const char
+               *af_used_by = NULL,
+               *tunnel_af_used_by = NULL;
+
+       /* check division of numbering space */
 #ifdef DEBUG
-    assert(OPTION_OFFSET + DBGOPT_LAST < NUMERIC_ARG);
+       assert(OPTION_OFFSET + DBGOPT_LAST < NUMERIC_ARG);
 #else
-    assert(OPTION_OFFSET + CA_LAST < NUMERIC_ARG);
+       assert(OPTION_OFFSET + CA_LAST < NUMERIC_ARG);
 #endif
-    assert(OPT_LAST - OPT_FIRST < (sizeof opts_seen * BITS_PER_BYTE));
-    assert(SC_LAST  - SC_FIRST  < (sizeof sc_seen   * BITS_PER_BYTE));
-    assert(LST_LAST - LST_FIRST < (sizeof lst_seen  * BITS_PER_BYTE));
-    assert(END_LAST - END_FIRST < (sizeof end_seen  * BITS_PER_BYTE));
-    assert(CD_LAST  - CD_FIRST  < (sizeof cd_seen   * BITS_PER_BYTE));
-    assert(CA_LAST  - CA_FIRST  < (sizeof ca_seen   * BITS_PER_BYTE));
-#ifdef DEBUG   /* must be last so others are less than (sizeof cd_seen * BITS_PER_BYTE) to fit in lset_t */
-    assert(DBGOPT_LAST - DBGOPT_FIRST < (sizeof cd_seen * BITS_PER_BYTE));
+       assert(OPT_LAST - OPT_FIRST < (sizeof opts_seen * BITS_PER_BYTE));
+       assert(SC_LAST  - SC_FIRST  < (sizeof sc_seen   * BITS_PER_BYTE));
+       assert(LST_LAST - LST_FIRST < (sizeof lst_seen  * BITS_PER_BYTE));
+       assert(END_LAST - END_FIRST < (sizeof end_seen  * BITS_PER_BYTE));
+       assert(CD_LAST  - CD_FIRST  < (sizeof cd_seen   * BITS_PER_BYTE));
+       assert(CA_LAST  - CA_FIRST  < (sizeof ca_seen   * BITS_PER_BYTE));
+#ifdef DEBUG    /* must be last so others are less than (sizeof cd_seen * BITS_PER_BYTE) to fit in lset_t */
+       assert(DBGOPT_LAST - DBGOPT_FIRST < (sizeof cd_seen * BITS_PER_BYTE));
 #endif
-    /* check that POLICY bit assignment matches with CD_ */
-    assert(LELEM(CD_DONT_REKEY - CD_POLICY_FIRST) == POLICY_DONT_REKEY);
-
-    zero(&msg);
-
-    clear_end(&msg.right);     /* left set from this after --to */
-
-    msg.name = NULL;
-    msg.keyid = NULL;
-    msg.keyval.ptr = NULL;
-    msg.esp = NULL;
-    msg.ike = NULL;
-    msg.pfsgroup = NULL;
-
-    msg.sa_ike_life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT;
-    msg.sa_ipsec_life_seconds = PLUTO_SA_LIFE_DURATION_DEFAULT;
-    msg.sa_rekey_margin = SA_REPLACEMENT_MARGIN_DEFAULT;
-    msg.sa_rekey_fuzz = SA_REPLACEMENT_FUZZ_DEFAULT;
-    msg.sa_keying_tries = SA_REPLACEMENT_RETRIES_DEFAULT;
-
-    msg.addr_family = AF_INET;
-    msg.tunnel_addr_family = AF_INET;
-    
-    msg.cacert = NULL;
-    msg.ldaphost = NULL;
-    msg.ldapbase = NULL;
-    msg.crluri = NULL;
-    msg.crluri2 = NULL;
-    msg.ocspuri = NULL;
-
-    for (;;)
-    {
-       int long_index;
-       unsigned long opt_whole = 0;  /* numeric argument for some flags */
-
-       /* Note: we don't like the way short options get parsed
-        * by getopt_long, so we simply pass an empty string as
-        * the list.  It could be "hp:d:c:o:eatfs" "NARXPECK".
-        */
-       int c = getopt_long(argc, argv, "", long_opts, &long_index) - OPTION_OFFSET;
-       int aux = 0;
+       /* check that POLICY bit assignment matches with CD_ */
+       assert(LELEM(CD_DONT_REKEY - CD_POLICY_FIRST) == POLICY_DONT_REKEY);
 
-       /* decode a numeric argument, if expected */
-       if (0 <= c)
-       {
-           if (c & NUMERIC_ARG)
-           {
-               char *endptr;
-
-               c -= NUMERIC_ARG;
-               opt_whole = strtoul(optarg, &endptr, 0);
-
-               if (*endptr != '\0' || endptr == optarg)
-                   diagq("badly formed numeric argument", optarg);
-           }
-           if (c >= (1 << AUX_SHIFT))
-           {
-               aux = c >> AUX_SHIFT;
-               c -= aux << AUX_SHIFT;
-           }
-       }
+       zero(&msg);
 
-       /* per-class option processing */
-       if (0 <= c && c <= OPT_LAST)
-       {
-           /* OPT_* options get added to opts_seen.
-            * Reject repeated options (unless later code intervenes).
-            */
-           lset_t f = LELEM(c);
-
-           if (opts_seen & f)
-               diagq("duplicated flag", long_opts[long_index].name);
-           opts_seen |= f;
-       }
-       else if (SC_FIRST <= c && c <= SC_LAST)
-       {
-           /* SC_* options get added to sc_seen.
-            * Reject repeated options (unless later code intervenes).
-            */
-           lset_t f = LELEM(c - SC_FIRST);
-
-           if (sc_seen & f)
-               diagq("duplicated flag", long_opts[long_index].name);
-           sc_seen |= f;
-       }
-       else if (LST_FIRST <= c && c <= LST_LAST)
+       clear_end(&msg.right);      /* left set from this after --to */
+
+       msg.name = NULL;
+       msg.keyid = NULL;
+       msg.keyval.ptr = NULL;
+       msg.esp = NULL;
+       msg.ike = NULL;
+       msg.pfsgroup = NULL;
+
+   /* if a connection is added via whack then we assume IKEv1 */
+       msg.ikev1 = TRUE;
+
+       msg.sa_ike_life_seconds = OAKLEY_ISAKMP_SA_LIFETIME_DEFAULT;
+       msg.sa_ipsec_life_seconds = PLUTO_SA_LIFE_DURATION_DEFAULT;
+       msg.sa_rekey_margin = SA_REPLACEMENT_MARGIN_DEFAULT;
+       msg.sa_rekey_fuzz = SA_REPLACEMENT_FUZZ_DEFAULT;
+       msg.sa_keying_tries = SA_REPLACEMENT_RETRIES_DEFAULT;
+
+       msg.addr_family = AF_INET;
+       msg.tunnel_addr_family = AF_INET;
+       
+       msg.cacert = NULL;
+       msg.ldaphost = NULL;
+       msg.ldapbase = NULL;
+       msg.crluri = NULL;
+       msg.crluri2 = NULL;
+       msg.ocspuri = NULL;
+
+       options = options_create();
+
+       for (;;)
        {
-           /* LST_* options get added to lst_seen.
-            * Reject repeated options (unless later code intervenes).
-            */
-           lset_t f = LELEM(c - LST_FIRST);
-
-           if (lst_seen & f)
-               diagq("duplicated flag", long_opts[long_index].name);
-           lst_seen |= f;
-       }
+               int long_index;
+               unsigned long opt_whole = 0;  /* numeric argument for some flags */
+
+               /* Note: we don't like the way short options get parsed
+                * by getopt_long, so we simply pass an empty string as
+                * the list.  It could be "hp:d:c:o:eatfs" "NARXPECK".
+                */
+               int c = getopt_long(argc, argv, "", long_opts, &long_index) - OPTION_OFFSET;
+               int aux = 0;
+
+               /* decode a numeric argument, if expected */
+               if (0 <= c)
+               {
+                       if (c & NUMERIC_ARG)
+                       {
+                               char *endptr;
+
+                               c -= NUMERIC_ARG;
+                               opt_whole = strtoul(optarg, &endptr, 0);
+
+                               if (*endptr != '\0' || endptr == optarg)
+                                       diagq("badly formed numeric argument", optarg);
+                       }
+                       if (c >= (1 << AUX_SHIFT))
+                       {
+                               aux = c >> AUX_SHIFT;
+                               c -= aux << AUX_SHIFT;
+                       }
+               }
+
+               /* per-class option processing */
+               if (0 <= c && c <= OPT_LAST)
+               {
+                       /* OPT_* options get added to opts_seen.
+                        * Reject repeated options (unless later code intervenes).
+                        */
+                       lset_t f = LELEM(c);
+
+                       if (opts_seen & f)
+                               diagq("duplicated flag", long_opts[long_index].name);
+                       opts_seen |= f;
+               }
+               else if (SC_FIRST <= c && c <= SC_LAST)
+               {
+                       /* SC_* options get added to sc_seen.
+                        * Reject repeated options (unless later code intervenes).
+                        */
+                       lset_t f = LELEM(c - SC_FIRST);
+
+                       if (sc_seen & f)
+                               diagq("duplicated flag", long_opts[long_index].name);
+                       sc_seen |= f;
+               }
+               else if (LST_FIRST <= c && c <= LST_LAST)
+               {
+                       /* LST_* options get added to lst_seen.
+                        * Reject repeated options (unless later code intervenes).
+                        */
+                       lset_t f = LELEM(c - LST_FIRST);
+
+                       if (lst_seen & f)
+                               diagq("duplicated flag", long_opts[long_index].name);
+                       lst_seen |= f;
+               }
 #ifdef DEBUG
-       else if (DBGOPT_FIRST <= c && c <= DBGOPT_LAST)
-       {
-           msg.whack_options = TRUE;
-       }
+               else if (DBGOPT_FIRST <= c && c <= DBGOPT_LAST)
+               {
+                       msg.whack_options = TRUE;
+               }
 #endif
-       else if (END_FIRST <= c && c <= END_LAST)
-       {
-           /* END_* options are added to end_seen.
-            * Reject repeated options (unless later code intervenes).
-            */
-           lset_t f = LELEM(c - END_FIRST);
-
-           if (end_seen & f)
-               diagq("duplicated flag", long_opts[long_index].name);
-           end_seen |= f;
-           opts_seen |= LELEM(OPT_CD);
-       }
-       else if (CD_FIRST <= c && c <= CD_LAST)
-       {
-           /* CD_* options are added to cd_seen.
-            * Reject repeated options (unless later code intervenes).
-            */
-           lset_t f = LELEM(c - CD_FIRST);
-
-           if (cd_seen & f)
-               diagq("duplicated flag", long_opts[long_index].name);
-           cd_seen |= f;
-           opts_seen |= LELEM(OPT_CD);
-       }
-       else if (CA_FIRST <= c && c <= CA_LAST)
-       {
-           /* CA_* options are added to ca_seen.
-            * Reject repeated options (unless later code intervenes).
-            */
-           lset_t f = LELEM(c - CA_FIRST);
-
-           if (ca_seen & f)
-               diagq("duplicated flag", long_opts[long_index].name);
-           ca_seen |= f;
-       }
+               else if (END_FIRST <= c && c <= END_LAST)
+               {
+                       /* END_* options are added to end_seen.
+                        * Reject repeated options (unless later code intervenes).
+                        */
+                       lset_t f = LELEM(c - END_FIRST);
+
+                       if (end_seen & f)
+                               diagq("duplicated flag", long_opts[long_index].name);
+                       end_seen |= f;
+                       opts_seen |= LELEM(OPT_CD);
+               }
+               else if (CD_FIRST <= c && c <= CD_LAST)
+               {
+                       /* CD_* options are added to cd_seen.
+                        * Reject repeated options (unless later code intervenes).
+                        */
+                       lset_t f = LELEM(c - CD_FIRST);
+
+                       if (cd_seen & f)
+                               diagq("duplicated flag", long_opts[long_index].name);
+                       cd_seen |= f;
+                       opts_seen |= LELEM(OPT_CD);
+               }
+               else if (CA_FIRST <= c && c <= CA_LAST)
+               {
+                       /* CA_* options are added to ca_seen.
+                        * Reject repeated options (unless later code intervenes).
+                        */
+                       lset_t f = LELEM(c - CA_FIRST);
+
+                       if (ca_seen & f)
+                               diagq("duplicated flag", long_opts[long_index].name);
+                       ca_seen |= f;
+               }
 
-       /* Note: "break"ing from switch terminates loop.
-        * most cases should end with "continue".
-        */
-       switch (c)
-       {
-       case EOF - OPTION_OFFSET:       /* end of flags */
-           break;
-
-       case 0 - OPTION_OFFSET: /* long option already handled */
-           continue;
-
-       case ':' - OPTION_OFFSET:       /* diagnostic already printed by getopt_long */
-       case '?' - OPTION_OFFSET:       /* diagnostic already printed by getopt_long */
-           diag(NULL); /* print no additional diagnostic, but exit sadly */
-           break;      /* not actually reached */
-
-       case 'h' - OPTION_OFFSET:       /* --help */
-           help();
-           return 0;   /* GNU coding standards say to stop here */
-
-       case 'v' - OPTION_OFFSET:       /* --version */
-           {
-               const char **sp = ipsec_copyright_notice();
-
-               printf("%s\n", ipsec_version_string());
-               for (; *sp != NULL; sp++)
-                   puts(*sp);
-           }
-           return 0;   /* GNU coding standards say to stop here */
-
-       case 'l' - OPTION_OFFSET:       /* --label <string> */
-           label = optarg;     /* remember for diagnostics */
-           continue;
-
-       case '+' - OPTION_OFFSET:       /* --optionsfrom <filename> */
-           optionsfrom(optarg, &argc, &argv, optind, stderr);
-           /* does not return on error */
-           continue;
-
-       /* the rest of the options combine in complex ways */
-
-       case OPT_CTLBASE:       /* --port <ctlbase> */
-           if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path)
-           , "%s%s", optarg, CTL_SUFFIX) == -1)
-               diag("<ctlbase>" CTL_SUFFIX " must be fit in a sun_addr");
-           continue;
-
-       case OPT_NAME:  /* --name <connection-name> */
-           name = optarg;
-           msg.name = optarg;
-           continue;
-
-       case OPT_KEYID: /* --keyid <identity> */
-           msg.whack_key = !msg.whack_sc_op;
-           msg.keyid = optarg; /* decoded by Pluto */
-           continue;
-
-       case OPT_MYID:  /* --myid <identity> */
-           msg.whack_myid = TRUE;
-           msg.myid = optarg;  /* decoded by Pluto */
-           continue;
-
-       case OPT_ADDKEY:        /* --addkey */
-           msg.whack_addkey = TRUE;
-           continue;
-
-       case OPT_PUBKEYRSA:     /* --pubkeyrsa <key> */
-           {
-               static char keyspace[RSA_MAX_ENCODING_BYTES];   /* room for 8K bit key */
-               char diag_space[TTODATAV_BUF];
-               const char *ugh = ttodatav(optarg, 0, 0
-                   , keyspace, sizeof(keyspace)
-                   , &msg.keyval.len, diag_space, sizeof(diag_space)
-                   , TTODATAV_SPACECOUNTS);
-
-               if (ugh != NULL)
+               /* Note: "break"ing from switch terminates loop.
+                * most cases should end with "continue".
+                */
+               switch (c)
                {
-                   char ugh_space[80]; /* perhaps enough space */
+               case EOF - OPTION_OFFSET:       /* end of flags */
+                       break;
 
-                   snprintf(ugh_space, sizeof(ugh_space)
-                       , "RSA public-key data malformed (%s)", ugh);
-                   diagq(ugh_space, optarg);
-               }
-               msg.pubkey_alg = PUBKEY_ALG_RSA;
-               msg.keyval.ptr = keyspace;
-           }
-           continue;
-
-       case OPT_ROUTE: /* --route */
-           msg.whack_route = TRUE;
-           continue;
-
-       case OPT_UNROUTE:       /* --unroute */
-           msg.whack_unroute = TRUE;
-           continue;
-
-       case OPT_INITIATE:      /* --initiate */
-           msg.whack_initiate = TRUE;
-           continue;
-
-       case OPT_TERMINATE:     /* --terminate */
-           msg.whack_terminate = TRUE;
-           continue;
-
-       case OPT_DELETE:        /* --delete */
-           msg.whack_delete = TRUE;
-           continue;
-
-       case OPT_DELETESTATE:   /* --deletestate <state_object_number> */
-           msg.whack_deletestate = TRUE;
-           msg.whack_deletestateno = opt_whole;
-           continue;
-
-       case OPT_DELETECRASH:   /* --crash <ip-address> */
-           msg.whack_crash = TRUE;
-           tunnel_af_used_by = long_opts[long_index].name;
-           diagq(ttoaddr(optarg, 0, msg.tunnel_addr_family, &msg.whack_crash_peer), optarg);
-           if (isanyaddr(&msg.whack_crash_peer))
-               diagq("0.0.0.0 or 0::0 isn't a valid client address", optarg);
-           continue;
-
-       case OPT_LISTEN:        /* --listen */
-           msg.whack_listen = TRUE;
-           continue;
-
-       case OPT_UNLISTEN:      /* --unlisten */
-           msg.whack_unlisten = TRUE;
-           continue;
-
-       case OPT_PURGEOCSP:     /* --purgeocsp */
-           msg.whack_purgeocsp = TRUE;
-           continue;
-
-       case OPT_REREADSECRETS:   /* --rereadsecrets */
-       case OPT_REREADCACERTS:   /* --rereadcacerts */
-       case OPT_REREADAACERTS:   /* --rereadaacerts */
-       case OPT_REREADOCSPCERTS: /* --rereadocspcerts */
-       case OPT_REREADACERTS:    /* --rereadacerts */
-       case OPT_REREADCRLS:      /* --rereadcrls */
-           msg.whack_reread |= LELEM(c-OPT_REREADSECRETS);
-           continue;
-
-       case OPT_REREADALL:     /* --rereadall */
-           msg.whack_reread = REREAD_ALL;
-           continue;
-
-       case OPT_STATUSALL:     /* --statusall */
-           msg.whack_statusall = TRUE;
-
-       case OPT_STATUS:        /* --status */
-           msg.whack_status = TRUE;
-           continue;
-       
-       case OPT_SHUTDOWN:      /* --shutdown */
-           msg.whack_shutdown = TRUE;
-           continue;
-
-       case OPT_OPPO_HERE:     /* --oppohere <ip-address> */
-           tunnel_af_used_by = long_opts[long_index].name;
-           diagq(ttoaddr(optarg, 0, msg.tunnel_addr_family, &msg.oppo_my_client), optarg);
-           if (isanyaddr(&msg.oppo_my_client))
-               diagq("0.0.0.0 or 0::0 isn't a valid client address", optarg);
-           continue;
-
-       case OPT_OPPO_THERE:    /* --oppohere <ip-address> */
-           tunnel_af_used_by = long_opts[long_index].name;
-           diagq(ttoaddr(optarg, 0, msg.tunnel_addr_family, &msg.oppo_peer_client), optarg);
-           if (isanyaddr(&msg.oppo_peer_client))
-               diagq("0.0.0.0 or 0::0 isn't a valid client address", optarg);
-           continue;
-
-       case OPT_ASYNC:
-           msg.whack_async = TRUE;
-           continue;
-
-       /* Smartcard options */
-
-       case SC_ENCRYPT:        /* --scencrypt <plaintext data> */
-       case SC_DECRYPT:        /* --scdecrypt <encrypted data> */
-           msg.whack_sc_op = 1 + c - SC_ENCRYPT;
-            msg.whack_key = FALSE;
-           msg.sc_data = optarg;
-           continue;
-
-       case SC_INBASE:         /* --inform  <format> */
-       case SC_OUTBASE:        /* --outform <format> */
-          {
-               int base = 0;
-
-               if (streq(optarg, "16") || strcaseeq(optarg, "hex"))
-                   base = 16;
-               else if (streq(optarg, "64") || strcaseeq(optarg, "base64"))
-                   base = 64;
-               else if (streq(optarg, "256") || strcaseeq(optarg, "text")
-                     || strcaseeq(optarg, "ascii"))
-                   base = 256;
-               else
-                   diagq("not a valid base", optarg);
+               case 0 - OPTION_OFFSET: /* long option already handled */
+                       continue;
+
+               case ':' - OPTION_OFFSET:       /* diagnostic already printed by getopt_long */
+               case '?' - OPTION_OFFSET:       /* diagnostic already printed by getopt_long */
+                       diag(NULL); /* print no additional diagnostic, but exit sadly */
+                       break;      /* not actually reached */
+
+               case 'h' - OPTION_OFFSET:       /* --help */
+                       help();
+                       whack_exit(0);              /* GNU coding standards say to stop here */
+
+               case 'v' - OPTION_OFFSET:       /* --version */
+                       {
+                               const char **sp = ipsec_copyright_notice();
+
+                               printf("%s\n", ipsec_version_string());
+                               for (; *sp != NULL; sp++)
+                                       puts(*sp);
+                       }
+                       whack_exit(0);   /* GNU coding standards say to stop here */
+
+               case 'l' - OPTION_OFFSET:       /* --label <string> */
+                       label = optarg;             /* remember for diagnostics */
+                       continue;
+
+               case '+' - OPTION_OFFSET:       /* --optionsfrom <filename> */
+                       if (!options->from(options, optarg, &argc, &argv, optind))
+                       {
+                               fprintf(stderr, "optionsfrom failed");
+                               whack_exit(RC_WHACK_PROBLEM);                           
+                       }
+                       continue;
+
+               /* the rest of the options combine in complex ways */
+
+               case OPT_CTLBASE:       /* --port <ctlbase> */
+                       if (snprintf(ctl_addr.sun_path, sizeof(ctl_addr.sun_path)
+                       , "%s%s", optarg, CTL_SUFFIX) == -1)
+                               diag("<ctlbase>" CTL_SUFFIX " must be fit in a sun_addr");
+                       continue;
+
+               case OPT_NAME:  /* --name <connection-name> */
+                       name = optarg;
+                       msg.name = optarg;
+                       continue;
+
+               case OPT_KEYID: /* --keyid <identity> */
+                       msg.whack_key = !msg.whack_sc_op;
+                       msg.keyid = optarg; /* decoded by Pluto */
+                       continue;
+
+               case OPT_MYID:  /* --myid <identity> */
+                       msg.whack_myid = TRUE;
+                       msg.myid = optarg;  /* decoded by Pluto */
+                       continue;
+
+               case OPT_ADDKEY:        /* --addkey */
+                       msg.whack_addkey = TRUE;
+                       continue;
+
+               case OPT_PUBKEYRSA:     /* --pubkeyrsa <key> */
+                       {
+                               static char keyspace[RSA_MAX_ENCODING_BYTES];   /* room for 8K bit key */
+                               char diag_space[TTODATAV_BUF];
+                               const char *ugh = ttodatav(optarg, 0, 0
+                                       , keyspace, sizeof(keyspace)
+                                       , &msg.keyval.len, diag_space, sizeof(diag_space)
+                                       , TTODATAV_SPACECOUNTS);
+
+                               if (ugh != NULL)
+                               {
+                                       char ugh_space[80]; /* perhaps enough space */
+
+                                       snprintf(ugh_space, sizeof(ugh_space)
+                                               , "RSA public-key data malformed (%s)", ugh);
+                                       diagq(ugh_space, optarg);
+                               }
+                               msg.pubkey_alg = PUBKEY_ALG_RSA;
+                               msg.keyval.ptr = keyspace;
+                       }
+                       continue;
+
+               case OPT_ROUTE: /* --route */
+                       msg.whack_route = TRUE;
+                       continue;
+
+               case OPT_UNROUTE:       /* --unroute */
+                       msg.whack_unroute = TRUE;
+                       continue;
+
+               case OPT_INITIATE:      /* --initiate */
+                       msg.whack_initiate = TRUE;
+                       continue;
+
+               case OPT_TERMINATE:     /* --terminate */
+                       msg.whack_terminate = TRUE;
+                       continue;
+
+               case OPT_DELETE:        /* --delete */
+                       msg.whack_delete = TRUE;
+                       continue;
+
+               case OPT_DELETESTATE:   /* --deletestate <state_object_number> */
+                       msg.whack_deletestate = TRUE;
+                       msg.whack_deletestateno = opt_whole;
+                       continue;
+
+               case OPT_DELETECRASH:   /* --crash <ip-address> */
+                       msg.whack_crash = TRUE;
+                       tunnel_af_used_by = long_opts[long_index].name;
+                       diagq(ttoaddr(optarg, 0, msg.tunnel_addr_family, &msg.whack_crash_peer), optarg);
+                       if (isanyaddr(&msg.whack_crash_peer))
+                               diagq("0.0.0.0 or 0::0 isn't a valid client address", optarg);
+                       continue;
+
+               case OPT_LISTEN:        /* --listen */
+                       msg.whack_listen = TRUE;
+                       continue;
+
+               case OPT_UNLISTEN:      /* --unlisten */
+                       msg.whack_unlisten = TRUE;
+                       continue;
+
+               case OPT_PURGEOCSP:     /* --purgeocsp */
+                       msg.whack_purgeocsp = TRUE;
+                       continue;
+
+               case OPT_REREADSECRETS:   /* --rereadsecrets */
+               case OPT_REREADCACERTS:   /* --rereadcacerts */
+               case OPT_REREADAACERTS:   /* --rereadaacerts */
+               case OPT_REREADOCSPCERTS: /* --rereadocspcerts */
+               case OPT_REREADACERTS:    /* --rereadacerts */
+               case OPT_REREADCRLS:      /* --rereadcrls */
+                       msg.whack_reread |= LELEM(c-OPT_REREADSECRETS);
+                       continue;
+
+               case OPT_REREADALL:     /* --rereadall */
+                       msg.whack_reread = REREAD_ALL;
+                       continue;
+
+               case OPT_STATUSALL:     /* --statusall */
+                       msg.whack_statusall = TRUE;
+
+               case OPT_STATUS:        /* --status */
+                       msg.whack_status = TRUE;
+                       continue;
                
-               if (c == SC_INBASE)
-                   msg.inbase = base;
-               else
-                   msg.outbase = base;
-           }
-           continue;
-
-       /* List options */
-
-        case LST_UTC:          /* --utc */
-            msg.whack_utc = TRUE;
-            continue;
-
-       case LST_ALGS:          /* --listalgs */
-       case LST_PUBKEYS:       /* --listpubkeys */
-       case LST_CERTS:         /* --listcerts */
-       case LST_CACERTS:       /* --listcacerts */
-       case LST_ACERTS:        /* --listacerts */
-       case LST_AACERTS:       /* --listaacerts */
-       case LST_OCSPCERTS:     /* --listocspcerts */
-       case LST_GROUPS:        /* --listgroups */
-       case LST_CAINFOS:       /* --listcainfos */
-       case LST_CRLS:          /* --listcrls */
-       case LST_OCSP:          /* --listocsp */
-       case LST_CARDS:         /* --listcards */
-           msg.whack_list |= LELEM(c - LST_ALGS);
-           continue;
-
-       case LST_ALL:   /* --listall */
-           msg.whack_list = LIST_ALL;
-           continue;
-
-       /* Connection Description options */
-
-       case END_HOST:  /* --host <ip-address> */
-       {
-           lset_t new_policy = LEMPTY;
-
-           af_used_by = long_opts[long_index].name;
-           diagq(anyaddr(msg.addr_family, &msg.right.host_addr), optarg);
-           if (streq(optarg, "%any"))
-           {
-           }
-           else if (streq(optarg, "%opportunistic"))
-           {
-               /* always use tunnel mode; mark as opportunistic */
-               new_policy |= POLICY_TUNNEL | POLICY_OPPO;
-           }
-           else if (streq(optarg, "%group"))
-           {
-               /* always use tunnel mode; mark as group */
-               new_policy |= POLICY_TUNNEL | POLICY_GROUP;
-           }
-           else if (streq(optarg, "%opportunisticgroup"))
-           {
-               /* always use tunnel mode; mark as opportunistic */
-               new_policy |= POLICY_TUNNEL | POLICY_OPPO | POLICY_GROUP;
-           }
-           else
-           {
-               diagq(ttoaddr(optarg, 0, msg.addr_family
-                   , &msg.right.host_addr), optarg);
-           }
-
-           msg.policy |= new_policy;
-
-           if (new_policy & (POLICY_OPPO | POLICY_GROUP))
-           {
-               if (!LHAS(end_seen, END_CLIENT - END_FIRST))
+               case OPT_SHUTDOWN:      /* --shutdown */
+                       msg.whack_shutdown = TRUE;
+                       continue;
+
+               case OPT_OPPO_HERE:     /* --oppohere <ip-address> */
+                       tunnel_af_used_by = long_opts[long_index].name;
+                       diagq(ttoaddr(optarg, 0, msg.tunnel_addr_family, &msg.oppo_my_client), optarg);
+                       if (isanyaddr(&msg.oppo_my_client))
+                               diagq("0.0.0.0 or 0::0 isn't a valid client address", optarg);
+                       continue;
+
+               case OPT_OPPO_THERE:    /* --oppohere <ip-address> */
+                       tunnel_af_used_by = long_opts[long_index].name;
+                       diagq(ttoaddr(optarg, 0, msg.tunnel_addr_family, &msg.oppo_peer_client), optarg);
+                       if (isanyaddr(&msg.oppo_peer_client))
+                               diagq("0.0.0.0 or 0::0 isn't a valid client address", optarg);
+                       continue;
+
+               case OPT_ASYNC:
+                       msg.whack_async = TRUE;
+                       continue;
+
+               /* Smartcard options */
+
+               case SC_ENCRYPT:        /* --scencrypt <plaintext data> */
+               case SC_DECRYPT:        /* --scdecrypt <encrypted data> */
+                       msg.whack_sc_op = 1 + c - SC_ENCRYPT;
+                       msg.whack_key = FALSE;
+                       msg.sc_data = optarg;
+                       continue;
+
+               case SC_INBASE:         /* --inform  <format> */
+               case SC_OUTBASE:        /* --outform <format> */
+                  {
+                               int base = 0;
+
+                               if (streq(optarg, "16") || strcaseeq(optarg, "hex"))
+                                       base = 16;
+                               else if (streq(optarg, "64") || strcaseeq(optarg, "base64"))
+                                       base = 64;
+                               else if (streq(optarg, "256") || strcaseeq(optarg, "text")
+                                         || strcaseeq(optarg, "ascii"))
+                                       base = 256;
+                               else
+                                       diagq("not a valid base", optarg);
+                               
+                               if (c == SC_INBASE)
+                                       msg.inbase = base;
+                               else
+                                       msg.outbase = base;
+                       }
+                       continue;
+
+               /* List options */
+
+               case LST_UTC:           /* --utc */
+                       msg.whack_utc = TRUE;
+                       continue;
+
+               case LST_ALGS:          /* --listalgs */
+               case LST_PUBKEYS:       /* --listpubkeys */
+               case LST_CERTS:         /* --listcerts */
+               case LST_CACERTS:       /* --listcacerts */
+               case LST_ACERTS:        /* --listacerts */
+               case LST_AACERTS:       /* --listaacerts */
+               case LST_OCSPCERTS:     /* --listocspcerts */
+               case LST_GROUPS:        /* --listgroups */
+               case LST_CAINFOS:       /* --listcainfos */
+               case LST_CRLS:          /* --listcrls */
+               case LST_OCSP:          /* --listocsp */
+               case LST_CARDS:         /* --listcards */
+                       msg.whack_list |= LELEM(c - LST_ALGS);
+                       continue;
+
+               case LST_ALL:   /* --listall */
+                       msg.whack_list = LIST_ALL;
+                       continue;
+
+               /* Connection Description options */
+
+               case END_HOST:  /* --host <ip-address> */
                {
-                   /* set host to 0.0.0 and --client to 0.0.0.0/0
-                    * or IPV6 equivalent
-                    */
-                   ip_address any;
-
-                   tunnel_af_used_by = optarg;
-                   diagq(anyaddr(msg.tunnel_addr_family, &any), optarg);
-                   diagq(initsubnet(&any, 0, '0', &msg.right.client), optarg);
+                       lset_t new_policy = LEMPTY;
+
+                       af_used_by = long_opts[long_index].name;
+                       diagq(anyaddr(msg.addr_family, &msg.right.host_addr), optarg);
+                       if (streq(optarg, "%any"))
+                       {
+                       }
+                       else if (streq(optarg, "%opportunistic"))
+                       {
+                               /* always use tunnel mode; mark as opportunistic */
+                               new_policy |= POLICY_TUNNEL | POLICY_OPPO;
+                       }
+                       else if (streq(optarg, "%group"))
+                       {
+                               /* always use tunnel mode; mark as group */
+                               new_policy |= POLICY_TUNNEL | POLICY_GROUP;
+                       }
+                       else if (streq(optarg, "%opportunisticgroup"))
+                       {
+                               /* always use tunnel mode; mark as opportunistic */
+                               new_policy |= POLICY_TUNNEL | POLICY_OPPO | POLICY_GROUP;
+                       }
+                       else
+                       {
+                               diagq(ttoaddr(optarg, 0, msg.addr_family
+                                       , &msg.right.host_addr), optarg);
+                       }
+
+                       msg.policy |= new_policy;
+
+                       if (new_policy & (POLICY_OPPO | POLICY_GROUP))
+                       {
+                               if (!LHAS(end_seen, END_CLIENT - END_FIRST))
+                               {
+                                       /* set host to 0.0.0 and --client to 0.0.0.0/0
+                                        * or IPV6 equivalent
+                                        */
+                                       ip_address any;
+
+                                       tunnel_af_used_by = optarg;
+                                       diagq(anyaddr(msg.tunnel_addr_family, &any), optarg);
+                                       diagq(initsubnet(&any, 0, '0', &msg.right.client), optarg);
+                               }
+                               msg.right.has_client = TRUE;
+                       }
+                       if (new_policy & POLICY_GROUP)
+                       {
+                               /* client subnet must not be specified by user:
+                                * it will come from the group's file.
+                                */
+                               if (LHAS(end_seen, END_CLIENT - END_FIRST))
+                                       diag("--host %group clashes with --client");
+
+                               end_seen |= LELEM(END_CLIENT - END_FIRST);
+                       }
+                       if (new_policy & POLICY_OPPO)
+                               msg.right.key_from_DNS_on_demand = TRUE;
+                       continue;
                }
-               msg.right.has_client = TRUE;
-           }
-           if (new_policy & POLICY_GROUP)
-           {
-               /* client subnet must not be specified by user:
-                * it will come from the group's file.
+               case END_ID:    /* --id <identity> */
+                       msg.right.id = optarg;      /* decoded by Pluto */
+                       continue;
+
+               case END_CERT:  /* --cert <path> */
+                       msg.right.cert = optarg;    /* decoded by Pluto */
+                       continue;
+
+               case END_CA:    /* --ca <distinguished name> */
+                       msg.right.ca = optarg;      /* decoded by Pluto */
+                       continue;
+
+               case END_SENDCERT:
+                       if (streq(optarg, "yes") || streq(optarg, "always"))
+                       {
+                               msg.right.sendcert = CERT_ALWAYS_SEND;
+                       }
+                       else if (streq(optarg, "no") || streq(optarg, "never"))
+                       {
+                               msg.right.sendcert = CERT_NEVER_SEND;
+                       }
+                       else if (streq(optarg, "ifasked"))
+                       {
+                               msg.right.sendcert = CERT_SEND_IF_ASKED;
+                       }
+                       else
+                       {
+                               diagq("whack sendcert value is not legal", optarg);
+                       }
+                       continue;
+
+               case END_GROUPS:/* --groups <access control groups> */
+                       msg.right.groups = optarg;  /* decoded by Pluto */
+                       continue;
+
+               case END_IKEPORT:       /* --ikeport <port-number> */
+                       if (opt_whole<=0 || opt_whole >= 0x10000)
+                               diagq("<port-number> must be a number between 1 and 65535", optarg);
+                       msg.right.host_port = opt_whole;
+                       continue;
+
+               case END_NEXTHOP:       /* --nexthop <ip-address> */
+                       af_used_by = long_opts[long_index].name;
+                       if (streq(optarg, "%direct"))
+                               diagq(anyaddr(msg.addr_family
+                                       , &msg.right.host_nexthop), optarg);
+                       else
+                               diagq(ttoaddr(optarg, 0, msg.addr_family
+                                       , &msg.right.host_nexthop), optarg);
+                       continue;
+
+               case END_SRCIP:        /* --srcip <ip-address> */
+                       af_used_by = long_opts[long_index].name;
+                       if (streq(optarg, "%modeconfig") || streq(optarg, "%modecfg"))
+                       {
+                               msg.right.modecfg = TRUE;
+                       }
+                       else
+                       {
+                               diagq(ttoaddr(optarg, 0, msg.addr_family
+                                       , &msg.right.host_srcip), optarg);
+                               msg.right.has_srcip = TRUE;
+                       }
+                       msg.policy |= POLICY_TUNNEL;        /* srcip => tunnel */
+                       continue;
+
+               case END_CLIENT:        /* --client <subnet> */
+                       if (end_seen & LELEM(END_CLIENTWITHIN - END_FIRST))
+                               diag("--client conflicts with --clientwithin");
+                       tunnel_af_used_by = long_opts[long_index].name;
+                       if ((strlen(optarg) >= 6 && strncmp(optarg,"vhost:",6) == 0)
+                       ||  (strlen(optarg) >= 5 && strncmp(optarg,"vnet:",5) == 0))
+                       {
+                               msg.right.virt = optarg;
+                       }
+                       else
+                       {
+                               diagq(ttosubnet(optarg, 0, msg.tunnel_addr_family, &msg.right.client), optarg);
+                               msg.right.has_client = TRUE;
+                       }
+                       msg.policy |= POLICY_TUNNEL;        /* client => tunnel */
+                       continue;
+
+               case END_CLIENTWITHIN:  /* --clienwithin <address range> */
+                       if (end_seen & LELEM(END_CLIENT - END_FIRST))
+                               diag("--clientwithin conflicts with --client");
+                       tunnel_af_used_by = long_opts[long_index].name;
+                       diagq(ttosubnet(optarg, 0, msg.tunnel_addr_family, &msg.right.client), optarg);
+                       msg.right.has_client = TRUE;
+                       msg.policy |= POLICY_TUNNEL;        /* client => tunnel */
+                       msg.right.has_client_wildcard = TRUE;
+                       continue;
+
+               case END_CLIENTPROTOPORT: /* --clientprotoport <protocol>/<port> */
+                       diagq(ttoprotoport(optarg, 0, &msg.right.protocol, &msg.right.port
+                               , &msg.right.has_port_wildcard), optarg);
+                       continue;
+
+               case END_DNSKEYONDEMAND:        /* --dnskeyondemand */
+                       msg.right.key_from_DNS_on_demand = TRUE;
+                       continue;
+
+               case END_HOSTACCESS:    /* --hostaccess */
+                       msg.right.hostaccess = TRUE;
+                       continue;
+
+               case END_UPDOWN:        /* --updown <updown> */
+                       msg.right.updown = optarg;
+                       continue;
+
+               case CD_TO:             /* --to */
+                       /* process right end, move it to left, reset it */
+                       if (!LHAS(end_seen, END_HOST - END_FIRST))
+                               diag("connection missing --host before --to");
+                       msg.left = msg.right;
+                       clear_end(&msg.right);
+                       end_seen_before_to = end_seen;
+                       end_seen = LEMPTY;
+                       continue;
+
+               case CD_PSK:            /* --psk */
+               case CD_RSASIG:         /* --rsasig */
+               case CD_ENCRYPT:        /* --encrypt */
+               case CD_AUTHENTICATE:   /* --authenticate */
+               case CD_COMPRESS:       /* --compress */
+               case CD_TUNNEL:         /* --tunnel */
+               case CD_PFS:            /* --pfs */
+               case CD_DISABLEARRIVALCHECK:    /* --disablearrivalcheck */
+               case CD_DONT_REKEY:     /* --donotrekey */
+                       msg.policy |= LELEM(c - CD_POLICY_FIRST);
+                       continue;
+
+               /* --initiateontraffic
+                * --pass
+                * --drop
+                * --reject
                 */
-               if (LHAS(end_seen, END_CLIENT - END_FIRST))
-                   diag("--host %group clashes with --client");
-
-               end_seen |= LELEM(END_CLIENT - END_FIRST);
-           }
-           if (new_policy & POLICY_OPPO)
-               msg.right.key_from_DNS_on_demand = TRUE;
-           continue;
-       }
-       case END_ID:    /* --id <identity> */
-           msg.right.id = optarg;      /* decoded by Pluto */
-           continue;
-
-       case END_CERT:  /* --cert <path> */
-           msg.right.cert = optarg;    /* decoded by Pluto */
-           continue;
-
-       case END_CA:    /* --ca <distinguished name> */
-           msg.right.ca = optarg;      /* decoded by Pluto */
-           continue;
-
-       case END_SENDCERT:
-           if (streq(optarg, "yes") || streq(optarg, "always"))
-           {
-               msg.right.sendcert = CERT_ALWAYS_SEND;
-           }
-           else if (streq(optarg, "no") || streq(optarg, "never"))
-           {
-               msg.right.sendcert = CERT_NEVER_SEND;
-           }
-           else if (streq(optarg, "ifasked"))
-           {
-               msg.right.sendcert = CERT_SEND_IF_ASKED;
-           }
-           else
-           {
-               diagq("whack sendcert value is not legal", optarg);
-           }
-           continue;
-
-       case END_GROUPS:/* --groups <access control groups> */
-           msg.right.groups = optarg;  /* decoded by Pluto */
-           continue;
-
-       case END_IKEPORT:       /* --ikeport <port-number> */
-           if (opt_whole<=0 || opt_whole >= 0x10000)
-               diagq("<port-number> must be a number between 1 and 65535", optarg);
-           msg.right.host_port = opt_whole;
-           continue;
-
-       case END_NEXTHOP:       /* --nexthop <ip-address> */
-           af_used_by = long_opts[long_index].name;
-           if (streq(optarg, "%direct"))
-               diagq(anyaddr(msg.addr_family
-                   , &msg.right.host_nexthop), optarg);
-           else
-               diagq(ttoaddr(optarg, 0, msg.addr_family
-                   , &msg.right.host_nexthop), optarg);
-           continue;
-
-       case END_SRCIP:        /* --srcip <ip-address> */
-           af_used_by = long_opts[long_index].name;
-           if (streq(optarg, "%modeconfig") || streq(optarg, "%modecfg"))
-           {
-               msg.right.modecfg = TRUE;
-           }
-           else
-           {
-               diagq(ttoaddr(optarg, 0, msg.addr_family
-                   , &msg.right.host_srcip), optarg);
-               msg.right.has_srcip = TRUE;
-           }
-           msg.policy |= POLICY_TUNNEL;        /* srcip => tunnel */
-           continue;
-
-       case END_CLIENT:        /* --client <subnet> */
-           if (end_seen & LELEM(END_CLIENTWITHIN - END_FIRST))
-               diag("--client conflicts with --clientwithin");
-           tunnel_af_used_by = long_opts[long_index].name;
-#ifdef VIRTUAL_IP
-           if ((strlen(optarg) >= 6 && strncmp(optarg,"vhost:",6) == 0)
-           ||  (strlen(optarg) >= 5 && strncmp(optarg,"vnet:",5) == 0))
-           {
-               msg.right.virt = optarg;
-           }
-           else
-           {
-               diagq(ttosubnet(optarg, 0, msg.tunnel_addr_family, &msg.right.client), optarg);
-               msg.right.has_client = TRUE;
-           }
-#else
-           diagq(ttosubnet(optarg, 0, msg.tunnel_addr_family, &msg.right.client), optarg);
-           msg.right.has_client = TRUE;
-#endif
-           msg.policy |= POLICY_TUNNEL;        /* client => tunnel */
-           continue;
-
-       case END_CLIENTWITHIN:  /* --clienwithin <address range> */
-           if (end_seen & LELEM(END_CLIENT - END_FIRST))
-               diag("--clientwithin conflicts with --client");
-           tunnel_af_used_by = long_opts[long_index].name;
-           diagq(ttosubnet(optarg, 0, msg.tunnel_addr_family, &msg.right.client), optarg);
-           msg.right.has_client = TRUE;
-           msg.policy |= POLICY_TUNNEL;        /* client => tunnel */
-           msg.right.has_client_wildcard = TRUE;
-           continue;
-
-       case END_CLIENTPROTOPORT: /* --clientprotoport <protocol>/<port> */
-           diagq(ttoprotoport(optarg, 0, &msg.right.protocol, &msg.right.port
-               , &msg.right.has_port_wildcard), optarg);
-           continue;
-
-       case END_DNSKEYONDEMAND:        /* --dnskeyondemand */
-           msg.right.key_from_DNS_on_demand = TRUE;
-           continue;
-
-       case END_HOSTACCESS:    /* --hostaccess */
-           msg.right.hostaccess = TRUE;
-           continue;
-
-       case END_UPDOWN:        /* --updown <updown> */
-           msg.right.updown = optarg;
-           continue;
-
-       case CD_TO:             /* --to */
-           /* process right end, move it to left, reset it */
-           if (!LHAS(end_seen, END_HOST - END_FIRST))
-               diag("connection missing --host before --to");
-           msg.left = msg.right;
-           clear_end(&msg.right);
-           end_seen_before_to = end_seen;
-           end_seen = LEMPTY;
-           continue;
-
-       case CD_PSK:            /* --psk */
-       case CD_RSASIG:         /* --rsasig */
-       case CD_ENCRYPT:        /* --encrypt */
-       case CD_AUTHENTICATE:   /* --authenticate */
-       case CD_COMPRESS:       /* --compress */
-       case CD_TUNNEL:         /* --tunnel */
-       case CD_PFS:            /* --pfs */
-       case CD_DISABLEARRIVALCHECK:    /* --disablearrivalcheck */
-       case CD_DONT_REKEY:     /* --donotrekey */
-           msg.policy |= LELEM(c - CD_POLICY_FIRST);
-           continue;
-
-       /* --initiateontraffic
-        * --pass
-        * --drop
-        * --reject
-        */
-       case CD_SHUNT0:
-           msg.policy = (msg.policy & ~POLICY_SHUNT_MASK)
-               | ((lset_t)aux << POLICY_SHUNT_SHIFT);
-           continue;
-
-       /* --failnone
-        * --failpass
-        * --faildrop
-        * --failreject
-        */
-       case CD_FAIL0:
-           msg.policy = (msg.policy & ~POLICY_FAIL_MASK)
-               | ((lset_t)aux << POLICY_FAIL_SHIFT);
-           continue;
-
-       case CD_IKELIFETIME:    /* --ikelifetime <seconds> */
-           msg.sa_ike_life_seconds = opt_whole;
-           continue;
-
-       case CD_IPSECLIFETIME:  /* --ipseclifetime <seconds> */
-           msg.sa_ipsec_life_seconds = opt_whole;
-           continue;
-
-       case CD_RKMARGIN:       /* --rekeymargin <seconds> */
-           msg.sa_rekey_margin = opt_whole;
-           continue;
-
-       case CD_RKFUZZ: /* --rekeyfuzz <percentage> */
-           msg.sa_rekey_fuzz = opt_whole;
-           continue;
-
-       case CD_KTRIES: /* --keyingtries <count> */
-           msg.sa_keying_tries = opt_whole;
-           continue;
-
-       case CD_DPDACTION:
-           if (streq(optarg, "none"))
-               msg.dpd_action = DPD_ACTION_NONE;
-           else if (streq(optarg, "clear"))
-               msg.dpd_action = DPD_ACTION_CLEAR;
-           else if (streq(optarg, "hold"))
-               msg.dpd_action = DPD_ACTION_HOLD;
-           else if (streq(optarg, "restart"))
-               msg.dpd_action = DPD_ACTION_RESTART;
-           else
-               msg.dpd_action = DPD_ACTION_UNKNOWN;
-           continue;
-
-       case CD_DPDDELAY:
-           msg.dpd_delay = opt_whole;
-           continue;
-
-       case CD_DPDTIMEOUT:
-           msg.dpd_timeout = opt_whole;
-           continue;
-
-       case CD_IKE:    /* --ike <ike_alg1,ike_alg2,...> */
-           msg.ike = optarg;
-           continue;
-           
-       case CD_PFSGROUP:       /* --pfsgroup modpXXXX */
-           msg.pfsgroup = optarg;
-           continue;
-
-       case CD_ESP:    /* --esp <esp_alg1,esp_alg2,...> */
-           msg.esp = optarg;
-           continue;
-
-       case CD_CONNIPV4:
-           if (LHAS(cd_seen, CD_CONNIPV6 - CD_FIRST))
-               diag("--ipv4 conflicts with --ipv6");
-
-           /* Since this is the default, the flag is redundant.
-            * So we don't need to set msg.addr_family
-            * and we don't need to check af_used_by
-            * and we don't have to consider defaulting tunnel_addr_family.
-            */
-           continue;
-
-       case CD_CONNIPV6:
-           if (LHAS(cd_seen, CD_CONNIPV4 - CD_FIRST))
-               diag("--ipv6 conflicts with --ipv4");
-
-           if (af_used_by != NULL)
-               diagq("--ipv6 must precede", af_used_by);
-
-           af_used_by = long_opts[long_index].name;
-           msg.addr_family = AF_INET6;
-
-           /* Consider defaulting tunnel_addr_family to AF_INET6.
-            * Do so only if it hasn't yet been specified or used.
-            */
-           if (LDISJOINT(cd_seen, LELEM(CD_TUNNELIPV4 - CD_FIRST) | LELEM(CD_TUNNELIPV6 - CD_FIRST))
-           && tunnel_af_used_by == NULL)
-               msg.tunnel_addr_family = AF_INET6;
-           continue;
-
-       case CD_TUNNELIPV4:
-           if (LHAS(cd_seen, CD_TUNNELIPV6 - CD_FIRST))
-               diag("--tunnelipv4 conflicts with --tunnelipv6");
-
-           if (tunnel_af_used_by != NULL)
-               diagq("--tunnelipv4 must precede", af_used_by);
-
-           msg.tunnel_addr_family = AF_INET;
-           continue;
-
-       case CD_TUNNELIPV6:
-           if (LHAS(cd_seen, CD_TUNNELIPV4 - CD_FIRST))
-               diag("--tunnelipv6 conflicts with --tunnelipv4");
-
-           if (tunnel_af_used_by != NULL)
-               diagq("--tunnelipv6 must precede", af_used_by);
-
-           msg.tunnel_addr_family = AF_INET6;
-           continue;
-
-       case CA_NAME:           /* --caname <name> */
-           msg.name = optarg;
-           msg.whack_ca = TRUE;
-           continue;
-       case CA_CERT:           /* --cacert <path> */
-           msg.cacert = optarg;
-           continue;
-       case CA_LDAPHOST:       /* --ldaphost <hostname> */
-           msg.ldaphost = optarg;
-           continue;
-       case CA_LDAPBASE:       /* --ldapbase <base> */
-           msg.ldapbase = optarg;
-           continue;
-       case CA_CRLURI:         /* --crluri <uri> */
-           msg.crluri = optarg;
-           continue;
-       case CA_CRLURI2:        /* --crluri2 <uri> */
-           msg.crluri2 = optarg;
-           continue;
-       case CA_OCSPURI:        /* --ocspuri <uri> */
-           msg.ocspuri = optarg;
-           continue;
-       case CA_STRICT:         /* --strictcrlpolicy */
-           msg.whack_strict = TRUE;
-           continue;
+               case CD_SHUNT0:
+                       msg.policy = (msg.policy & ~POLICY_SHUNT_MASK)
+                               | ((lset_t)aux << POLICY_SHUNT_SHIFT);
+                       continue;
+
+               /* --failnone
+                * --failpass
+                * --faildrop
+                * --failreject
+                */
+               case CD_FAIL0:
+                       msg.policy = (msg.policy & ~POLICY_FAIL_MASK)
+                               | ((lset_t)aux << POLICY_FAIL_SHIFT);
+                       continue;
+
+               case CD_IKELIFETIME:    /* --ikelifetime <seconds> */
+                       msg.sa_ike_life_seconds = opt_whole;
+                       continue;
+
+               case CD_IPSECLIFETIME:  /* --ipseclifetime <seconds> */
+                       msg.sa_ipsec_life_seconds = opt_whole;
+                       continue;
+
+               case CD_RKMARGIN:       /* --rekeymargin <seconds> */
+                       msg.sa_rekey_margin = opt_whole;
+                       continue;
+
+               case CD_RKFUZZ: /* --rekeyfuzz <percentage> */
+                       msg.sa_rekey_fuzz = opt_whole;
+                       continue;
+
+               case CD_KTRIES: /* --keyingtries <count> */
+                       msg.sa_keying_tries = opt_whole;
+                       continue;
+
+               case CD_DPDACTION:
+                       if (streq(optarg, "none"))
+                               msg.dpd_action = DPD_ACTION_NONE;
+                       else if (streq(optarg, "clear"))
+                               msg.dpd_action = DPD_ACTION_CLEAR;
+                       else if (streq(optarg, "hold"))
+                               msg.dpd_action = DPD_ACTION_HOLD;
+                       else if (streq(optarg, "restart"))
+                               msg.dpd_action = DPD_ACTION_RESTART;
+                       else
+                               msg.dpd_action = DPD_ACTION_UNKNOWN;
+                       continue;
+
+               case CD_DPDDELAY:
+                       msg.dpd_delay = opt_whole;
+                       continue;
+
+               case CD_DPDTIMEOUT:
+                       msg.dpd_timeout = opt_whole;
+                       continue;
+
+               case CD_IKE:    /* --ike <ike_alg1,ike_alg2,...> */
+                       msg.ike = optarg;
+                       continue;
+                       
+               case CD_PFSGROUP:       /* --pfsgroup modpXXXX */
+                       msg.pfsgroup = optarg;
+                       continue;
+
+               case CD_ESP:    /* --esp <esp_alg1,esp_alg2,...> */
+                       msg.esp = optarg;
+                       continue;
+
+               case CD_CONNIPV4:
+                       if (LHAS(cd_seen, CD_CONNIPV6 - CD_FIRST))
+                               diag("--ipv4 conflicts with --ipv6");
+
+                       /* Since this is the default, the flag is redundant.
+                        * So we don't need to set msg.addr_family
+                        * and we don't need to check af_used_by
+                        * and we don't have to consider defaulting tunnel_addr_family.
+                        */
+                       continue;
+
+               case CD_CONNIPV6:
+                       if (LHAS(cd_seen, CD_CONNIPV4 - CD_FIRST))
+                               diag("--ipv6 conflicts with --ipv4");
+
+                       if (af_used_by != NULL)
+                               diagq("--ipv6 must precede", af_used_by);
+
+                       af_used_by = long_opts[long_index].name;
+                       msg.addr_family = AF_INET6;
+
+                       /* Consider defaulting tunnel_addr_family to AF_INET6.
+                        * Do so only if it hasn't yet been specified or used.
+                        */
+                       if (LDISJOINT(cd_seen, LELEM(CD_TUNNELIPV4 - CD_FIRST) | LELEM(CD_TUNNELIPV6 - CD_FIRST))
+                       && tunnel_af_used_by == NULL)
+                               msg.tunnel_addr_family = AF_INET6;
+                       continue;
+
+               case CD_TUNNELIPV4:
+                       if (LHAS(cd_seen, CD_TUNNELIPV6 - CD_FIRST))
+                               diag("--tunnelipv4 conflicts with --tunnelipv6");
+
+                       if (tunnel_af_used_by != NULL)
+                               diagq("--tunnelipv4 must precede", af_used_by);
+
+                       msg.tunnel_addr_family = AF_INET;
+                       continue;
+
+               case CD_TUNNELIPV6:
+                       if (LHAS(cd_seen, CD_TUNNELIPV4 - CD_FIRST))
+                               diag("--tunnelipv6 conflicts with --tunnelipv4");
+
+                       if (tunnel_af_used_by != NULL)
+                               diagq("--tunnelipv6 must precede", af_used_by);
+
+                       msg.tunnel_addr_family = AF_INET6;
+                       continue;
+
+               case CA_NAME:           /* --caname <name> */
+                       msg.name = optarg;
+                       msg.whack_ca = TRUE;
+                       continue;
+               case CA_CERT:           /* --cacert <path> */
+                       msg.cacert = optarg;
+                       continue;
+               case CA_LDAPHOST:       /* --ldaphost <hostname> */
+                       msg.ldaphost = optarg;
+                       continue;
+               case CA_LDAPBASE:       /* --ldapbase <base> */
+                       msg.ldapbase = optarg;
+                       continue;
+               case CA_CRLURI:         /* --crluri <uri> */
+                       msg.crluri = optarg;
+                       continue;
+               case CA_CRLURI2:        /* --crluri2 <uri> */
+                       msg.crluri2 = optarg;
+                       continue;
+               case CA_OCSPURI:        /* --ocspuri <uri> */
+                       msg.ocspuri = optarg;
+                       continue;
+               case CA_STRICT:         /* --strictcrlpolicy */
+                       msg.whack_strict = TRUE;
+                       continue;
 
 #ifdef DEBUG
-       case DBGOPT_NONE:       /* --debug-none */
-           msg.debugging = DBG_NONE;
-           continue;
-
-       case DBGOPT_ALL:        /* --debug-all */
-           msg.debugging |= DBG_ALL;   /* note: does not include PRIVATE */
-           continue;
-
-       case DBGOPT_RAW:        /* --debug-raw */
-       case DBGOPT_CRYPT:      /* --debug-crypt */
-       case DBGOPT_PARSING:    /* --debug-parsing */
-       case DBGOPT_EMITTING:   /* --debug-emitting */
-       case DBGOPT_CONTROL:    /* --debug-control */
-       case DBGOPT_LIFECYCLE:  /* --debug-lifecycle */
-       case DBGOPT_KLIPS:      /* --debug-klips */
-       case DBGOPT_DNS:        /* --debug-dns */
-       case DBGOPT_NATT:       /* --debug-natt */
-       case DBGOPT_OPPO:       /* --debug-oppo */
-       case DBGOPT_CONTROLMORE: /* --debug-controlmore */
-       case DBGOPT_PRIVATE:    /* --debug-private */
-       case DBGOPT_IMPAIR_DELAY_ADNS_KEY_ANSWER:       /* --impair-delay-adns-key-answer */
-       case DBGOPT_IMPAIR_DELAY_ADNS_TXT_ANSWER:       /* --impair-delay-adns-txt-answer */
-       case DBGOPT_IMPAIR_BUST_MI2:    /* --impair_bust_mi2 */
-       case DBGOPT_IMPAIR_BUST_MR2:    /* --impair_bust_mr2 */
-           msg.debugging |= LELEM(c-DBGOPT_RAW);
-           continue;
+               case DBGOPT_NONE:       /* --debug-none */
+                       msg.debugging = DBG_NONE;
+                       continue;
+
+               case DBGOPT_ALL:        /* --debug-all */
+                       msg.debugging |= DBG_ALL;   /* note: does not include PRIVATE */
+                       continue;
+
+               case DBGOPT_RAW:        /* --debug-raw */
+               case DBGOPT_CRYPT:      /* --debug-crypt */
+               case DBGOPT_PARSING:    /* --debug-parsing */
+               case DBGOPT_EMITTING:   /* --debug-emitting */
+               case DBGOPT_CONTROL:    /* --debug-control */
+               case DBGOPT_LIFECYCLE:  /* --debug-lifecycle */
+               case DBGOPT_KLIPS:      /* --debug-klips */
+               case DBGOPT_DNS:        /* --debug-dns */
+               case DBGOPT_NATT:       /* --debug-natt */
+               case DBGOPT_OPPO:       /* --debug-oppo */
+               case DBGOPT_CONTROLMORE: /* --debug-controlmore */
+               case DBGOPT_PRIVATE:    /* --debug-private */
+               case DBGOPT_IMPAIR_DELAY_ADNS_KEY_ANSWER:       /* --impair-delay-adns-key-answer */
+               case DBGOPT_IMPAIR_DELAY_ADNS_TXT_ANSWER:       /* --impair-delay-adns-txt-answer */
+               case DBGOPT_IMPAIR_BUST_MI2:    /* --impair_bust_mi2 */
+               case DBGOPT_IMPAIR_BUST_MR2:    /* --impair_bust_mr2 */
+                       msg.debugging |= LELEM(c-DBGOPT_RAW);
+                       continue;
 #endif
-       default:
-           assert(FALSE);      /* unknown return value */
+               default:
+                       assert(FALSE);      /* unknown return value */
+               }
+               break;
        }
-       break;
-    }
-
-    if (optind != argc)
-    {
-       /* If you see this message unexpectedly, perhaps the
-        * case for the previous option ended with "break"
-        * instead of "continue"
-        */
-       diagq("unexpected argument", argv[optind]);
-    }
-
-    /* For each possible form of the command, figure out if an argument
-     * suggests whether that form was intended, and if so, whether all
-     * required information was supplied.
-     */
-
-    /* check opportunistic initiation simulation request */
-    switch (opts_seen & (LELEM(OPT_OPPO_HERE) | LELEM(OPT_OPPO_THERE)))
-    {
-    case LELEM(OPT_OPPO_HERE):
-    case LELEM(OPT_OPPO_THERE):
-       diag("--oppohere and --oppothere must be used together");
-       /*NOTREACHED*/
-    case LELEM(OPT_OPPO_HERE) | LELEM(OPT_OPPO_THERE):
-       msg.whack_oppo_initiate = TRUE;
-       if (LIN(cd_seen, LELEM(CD_TUNNELIPV4 - CD_FIRST) | LELEM(CD_TUNNELIPV6 - CD_FIRST)))
-           opts_seen &= ~LELEM(OPT_CD);
-       break;
-    }
-
-    /* check connection description */
-    if (LHAS(opts_seen, OPT_CD))
-    {
-       if (!LHAS(cd_seen, CD_TO-CD_FIRST))
-           diag("connection description option, but no --to");
-
-       if (!LHAS(end_seen, END_HOST-END_FIRST))
-           diag("connection missing --host after --to");
-
-       if (isanyaddr(&msg.left.host_addr)
-       && isanyaddr(&msg.right.host_addr))
-           diag("hosts cannot both be 0.0.0.0 or 0::0");
-
-       if (msg.policy & POLICY_OPPO)
+
+       if (optind != argc)
        {
-           if ((msg.policy & (POLICY_PSK | POLICY_RSASIG)) != POLICY_RSASIG)
-               diag("only RSASIG is supported for opportunism");
-           if ((msg.policy & POLICY_PFS) == 0)
-               diag("PFS required for opportunism");
-           if ((msg.policy & POLICY_ENCRYPT) == 0)
-               diag("encryption required for opportunism");
+               /* If you see this message unexpectedly, perhaps the
+                * case for the previous option ended with "break"
+                * instead of "continue"
+                */
+               diagq("unexpected argument", argv[optind]);
        }
 
-       check_end(&msg.left, &msg.right, !LHAS(end_seen_before_to, END_NEXTHOP-END_FIRST)
-           , msg.addr_family, msg.tunnel_addr_family);
-
-       check_end(&msg.right, &msg.left, !LHAS(end_seen, END_NEXTHOP-END_FIRST)
-           , msg.addr_family, msg.tunnel_addr_family);
-
-       if (subnettypeof(&msg.left.client) != subnettypeof(&msg.right.client))
-           diag("endpoints clash: one is IPv4 and the other is IPv6");
+       /* For each possible form of the command, figure out if an argument
+        * suggests whether that form was intended, and if so, whether all
+        * required information was supplied.
+        */
 
-       if (NEVER_NEGOTIATE(msg.policy))
+       /* check opportunistic initiation simulation request */
+       switch (opts_seen & (LELEM(OPT_OPPO_HERE) | LELEM(OPT_OPPO_THERE)))
        {
-           /* we think this is just a shunt (because he didn't specify
-            * a host authentication method).  If he didn't specify a
-            * shunt type, he's probably gotten it wrong.
-            */
-           if ((msg.policy & POLICY_SHUNT_MASK) == POLICY_SHUNT_TRAP)
-               diag("non-shunt connection must have --psk or --rsasig or both");
+       case LELEM(OPT_OPPO_HERE):
+       case LELEM(OPT_OPPO_THERE):
+               diag("--oppohere and --oppothere must be used together");
+               /*NOTREACHED*/
+       case LELEM(OPT_OPPO_HERE) | LELEM(OPT_OPPO_THERE):
+               msg.whack_oppo_initiate = TRUE;
+               if (LIN(cd_seen, LELEM(CD_TUNNELIPV4 - CD_FIRST) | LELEM(CD_TUNNELIPV6 - CD_FIRST)))
+                       opts_seen &= ~LELEM(OPT_CD);
+               break;
        }
-       else
+
+       /* check connection description */
+       if (LHAS(opts_seen, OPT_CD))
        {
-           /* not just a shunt: a real ipsec connection */
-           if ((msg.policy & POLICY_ID_AUTH_MASK) == LEMPTY)
-               diag("must specify --rsasig or --psk for a connection");
+               if (!LHAS(cd_seen, CD_TO-CD_FIRST))
+                       diag("connection description option, but no --to");
 
-           if (!HAS_IPSEC_POLICY(msg.policy)
-           && (msg.left.has_client || msg.right.has_client))
-               diag("must not specify clients for ISAKMP-only connection");
+               if (!LHAS(end_seen, END_HOST-END_FIRST))
+                       diag("connection missing --host after --to");
+
+               if (isanyaddr(&msg.left.host_addr)
+               && isanyaddr(&msg.right.host_addr))
+                       diag("hosts cannot both be 0.0.0.0 or 0::0");
+
+               if (msg.policy & POLICY_OPPO)
+               {
+                       if ((msg.policy & (POLICY_PSK | POLICY_RSASIG)) != POLICY_RSASIG)
+                               diag("only RSASIG is supported for opportunism");
+                       if ((msg.policy & POLICY_PFS) == 0)
+                               diag("PFS required for opportunism");
+                       if ((msg.policy & POLICY_ENCRYPT) == 0)
+                               diag("encryption required for opportunism");
+               }
+
+               check_end(&msg.left, &msg.right, !LHAS(end_seen_before_to, END_NEXTHOP-END_FIRST)
+                       , msg.addr_family, msg.tunnel_addr_family);
+
+               check_end(&msg.right, &msg.left, !LHAS(end_seen, END_NEXTHOP-END_FIRST)
+                       , msg.addr_family, msg.tunnel_addr_family);
+
+               if (subnettypeof(&msg.left.client) != subnettypeof(&msg.right.client))
+                       diag("endpoints clash: one is IPv4 and the other is IPv6");
+
+               if (NEVER_NEGOTIATE(msg.policy))
+               {
+                       /* we think this is just a shunt (because he didn't specify
+                        * a host authentication method).  If he didn't specify a
+                        * shunt type, he's probably gotten it wrong.
+                        */
+                       if ((msg.policy & POLICY_SHUNT_MASK) == POLICY_SHUNT_TRAP)
+                               diag("non-shunt connection must have --psk or --rsasig or both");
+               }
+               else
+               {
+                       /* not just a shunt: a real ipsec connection */
+                       if ((msg.policy & POLICY_ID_AUTH_MASK) == LEMPTY)
+                               diag("must specify --rsasig or --psk for a connection");
+
+                       if (!HAS_IPSEC_POLICY(msg.policy)
+                       && (msg.left.has_client || msg.right.has_client))
+                               diag("must not specify clients for ISAKMP-only connection");
+               }
+
+               msg.whack_connection = TRUE;
        }
 
-       msg.whack_connection = TRUE;
-    }
-
-    /* decide whether --name is mandatory or forbidden */
-    if (!LDISJOINT(opts_seen
-    , LELEM(OPT_ROUTE) | LELEM(OPT_UNROUTE)
-    | LELEM(OPT_INITIATE) | LELEM(OPT_TERMINATE)
-    | LELEM(OPT_DELETE) | LELEM(OPT_CD)))
-    {
-       if (!LHAS(opts_seen, OPT_NAME) && !msg.whack_ca)
-           diag("missing --name <connection_name>");
-    }
-    else if (!msg.whack_options && !msg.whack_status)
-    {
-       if (LHAS(opts_seen, OPT_NAME))
-           diag("no reason for --name");
-    }
-
-    if (!LDISJOINT(opts_seen, LELEM(OPT_PUBKEYRSA) | LELEM(OPT_ADDKEY)))
-    {
-       if (!LHAS(opts_seen, OPT_KEYID))
-           diag("--addkey and --pubkeyrsa require --keyid");
-    }
-
-    if (!(msg.whack_connection || msg.whack_key || msg.whack_myid
-    || msg.whack_delete || msg.whack_deletestate
-    || msg.whack_initiate || msg.whack_oppo_initiate || msg.whack_terminate
-    || msg.whack_route || msg.whack_unroute || msg.whack_listen
-    || msg.whack_unlisten || msg.whack_list || msg.whack_purgeocsp || msg.whack_reread
-    || msg.whack_ca || msg.whack_status || msg.whack_options || msg.whack_shutdown
-    || msg.whack_sc_op))
-    {
-       diag("no action specified; try --help for hints");
-    }
-
-    update_ports(&msg);
-
-    /* tricky quick and dirty check for wild values */
-    if (msg.sa_rekey_margin != 0
-    && msg.sa_rekey_fuzz * msg.sa_rekey_margin * 4 / msg.sa_rekey_margin / 4
-     != msg.sa_rekey_fuzz)
-       diag("rekeymargin or rekeyfuzz values are so large that they cause oveflow");
-
-    check_life_time (msg.sa_ike_life_seconds, OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM
-       , "ikelifetime", &msg);
-
-    check_life_time(msg.sa_ipsec_life_seconds, SA_LIFE_DURATION_MAXIMUM
-       , "ipseclifetime", &msg);
-
-    if (msg.dpd_action == DPD_ACTION_UNKNOWN)
-       diag("dpdaction must be \"none\", \"clear\", \"hold\" or \"restart\"");
-
-    if (msg.dpd_action != DPD_ACTION_NONE)
-    {
-       if (msg.dpd_delay <= 0)
-           diag("dpddelay must be larger than zero");
-       
-       if (msg.dpd_timeout <= 0)
-           diag("dpdtimeout must be larger than zero");
-       
-       if (msg.dpd_timeout <= msg.dpd_delay)
-           diag("dpdtimeout must be larger than dpddelay");
-    }
-
-    /* pack strings for inclusion in message */
-    next_str = msg.string;
-    str_roof = &msg.string[sizeof(msg.string)];
-
-    /* build esp message as esp="<esp>;<pfsgroup>" */
-    if (msg.pfsgroup) {
-           snprintf(esp_buf, sizeof (esp_buf), "%s;%s", 
-                   msg.esp ? msg.esp : "",
-                   msg.pfsgroup ? msg.pfsgroup : "");
-           msg.esp=esp_buf;
-    }
-    if (!pack_str(&msg.name)           /* string  1 */
-    || !pack_str(&msg.left.id)         /* string  2 */
-    || !pack_str(&msg.left.cert)       /* string  3 */
-    || !pack_str(&msg.left.ca)         /* string  4 */
-    || !pack_str(&msg.left.groups)     /* string  5 */
-    || !pack_str(&msg.left.updown)     /* string  6 */
-#ifdef VIRTUAL_IP
-    || !pack_str(&msg.left.virt)
-#endif
-    || !pack_str(&msg.right.id)                /* string  7 */
-    || !pack_str(&msg.right.cert)      /* string  8 */
-    || !pack_str(&msg.right.ca)                /* string  9 */
-    || !pack_str(&msg.right.groups)    /* string 10 */
-    || !pack_str(&msg.right.updown)    /* string 11 */
-#ifdef VIRTUAL_IP
-    || !pack_str(&msg.right.virt)
-#endif
-    || !pack_str(&msg.keyid)           /* string 12 */
-    || !pack_str(&msg.myid)            /* string 13 */
-    || !pack_str(&msg.cacert)          /* string 14 */
-    || !pack_str(&msg.ldaphost)                /* string 15 */
-    || !pack_str(&msg.ldapbase)                /* string 16 */
-    || !pack_str(&msg.crluri)          /* string 17 */
-    || !pack_str(&msg.crluri2)         /* string 18 */
-    || !pack_str(&msg.ocspuri)         /* string 19 */
-    || !pack_str(&msg.ike)             /* string 20 */
-    || !pack_str(&msg.esp)             /* string 21 */
-    || !pack_str(&msg.sc_data)         /* string 22 */
-    || str_roof - next_str < (ptrdiff_t)msg.keyval.len)    /* chunk (sort of string 5) */
-       diag("too many bytes of strings to fit in message to pluto");
-
-    memcpy(next_str, msg.keyval.ptr, msg.keyval.len);
-    msg.keyval.ptr = NULL;
-    next_str += msg.keyval.len;
-
-    msg.magic = ((opts_seen & ~LELEM(OPT_SHUTDOWN))
-               | sc_seen | lst_seen | cd_seen | ca_seen) != LEMPTY
-           || msg.whack_options
-       ? WHACK_MAGIC : WHACK_BASIC_MAGIC;
-
-    /* send message to Pluto */
-    if (access(ctl_addr.sun_path, R_OK | W_OK) < 0)
-    {
-       int e = errno;
-
-       switch (e)
+       /* decide whether --name is mandatory or forbidden */
+       if (!LDISJOINT(opts_seen
+       , LELEM(OPT_ROUTE) | LELEM(OPT_UNROUTE)
+       | LELEM(OPT_INITIATE) | LELEM(OPT_TERMINATE)
+       | LELEM(OPT_DELETE) | LELEM(OPT_CD)))
        {
-       case EACCES:
-           fprintf(stderr, "whack: no right to communicate with pluto (access(\"%s\"))\n"
-               , ctl_addr.sun_path);
-           break;
-       case ENOENT:
-           fprintf(stderr, "whack: Pluto is not running (no \"%s\")\n"
-               , ctl_addr.sun_path);
-           break;
-       default:
-           fprintf(stderr, "whack: access(\"%s\") failed with %d %s\n"
-               , ctl_addr.sun_path, errno, strerror(e));
-           break;
+               if (!LHAS(opts_seen, OPT_NAME) && !msg.whack_ca)
+                       diag("missing --name <connection_name>");
        }
-       exit(RC_WHACK_PROBLEM);
-    }
-    else
-    {
-       int sock = socket(AF_UNIX, SOCK_STREAM, 0);
-       int exit_status = 0;
-       ssize_t len = next_str - (char *)&msg;
-
-       if (sock == -1)
+       else if (!msg.whack_options && !msg.whack_status)
        {
-           int e = errno;
-
-           fprintf(stderr, "whack: socket() failed (%d %s)\n", e, strerror(e));
-           exit(RC_WHACK_PROBLEM);
+               if (LHAS(opts_seen, OPT_NAME))
+                       diag("no reason for --name");
        }
 
-       if (connect(sock, (struct sockaddr *)&ctl_addr
-       , offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0)
+       if (!LDISJOINT(opts_seen, LELEM(OPT_PUBKEYRSA) | LELEM(OPT_ADDKEY)))
        {
-           int e = errno;
-
-           fprintf(stderr, "whack:%s connect() for \"%s\" failed (%d %s)\n"
-               , e == ECONNREFUSED? " is Pluto running? " : ""
-               , ctl_addr.sun_path, e, strerror(e));
-           exit(RC_WHACK_PROBLEM);
+               if (!LHAS(opts_seen, OPT_KEYID))
+                       diag("--addkey and --pubkeyrsa require --keyid");
        }
 
-       if (write(sock, &msg, len) != len)
+       if (!(msg.whack_connection || msg.whack_key || msg.whack_myid
+       || msg.whack_delete || msg.whack_deletestate
+       || msg.whack_initiate || msg.whack_oppo_initiate || msg.whack_terminate
+       || msg.whack_route || msg.whack_unroute || msg.whack_listen
+       || msg.whack_unlisten || msg.whack_list || msg.whack_purgeocsp || msg.whack_reread
+       || msg.whack_ca || msg.whack_status || msg.whack_options || msg.whack_shutdown
+       || msg.whack_sc_op))
        {
-           int e = errno;
+               diag("no action specified; try --help for hints");
+       }
+
+       update_ports(&msg);
+
+       /* tricky quick and dirty check for wild values */
+       if (msg.sa_rekey_margin != 0
+       && msg.sa_rekey_fuzz * msg.sa_rekey_margin * 4 / msg.sa_rekey_margin / 4
+        != msg.sa_rekey_fuzz)
+               diag("rekeymargin or rekeyfuzz values are so large that they cause oveflow");
 
-           fprintf(stderr, "whack: write() failed (%d %s)\n", e, strerror(e));
-           exit(RC_WHACK_PROBLEM);
+       check_life_time (msg.sa_ike_life_seconds, OAKLEY_ISAKMP_SA_LIFETIME_MAXIMUM
+               , "ikelifetime", &msg);
+
+       check_life_time(msg.sa_ipsec_life_seconds, SA_LIFE_DURATION_MAXIMUM
+               , "ipseclifetime", &msg);
+
+       if (msg.dpd_action == DPD_ACTION_UNKNOWN)
+               diag("dpdaction must be \"none\", \"clear\", \"hold\" or \"restart\"");
+
+       if (msg.dpd_action != DPD_ACTION_NONE)
+       {
+               if (msg.dpd_delay <= 0)
+                       diag("dpddelay must be larger than zero");
+               
+               if (msg.dpd_timeout <= 0)
+                       diag("dpdtimeout must be larger than zero");
+               
+               if (msg.dpd_timeout <= msg.dpd_delay)
+                       diag("dpdtimeout must be larger than dpddelay");
        }
 
-       /* for now, just copy reply back to stdout */
+       /* pack strings for inclusion in message */
+       next_str = msg.string;
+       str_roof = &msg.string[sizeof(msg.string)];
 
+       /* build esp message as esp="<esp>;<pfsgroup>" */
+       if (msg.pfsgroup) {
+                       snprintf(esp_buf, sizeof (esp_buf), "%s;%s", 
+                                       msg.esp ? msg.esp : "",
+                                       msg.pfsgroup ? msg.pfsgroup : "");
+                       msg.esp=esp_buf;
+       }
+       if (!pack_str(&msg.name)            /* string  1 */
+       || !pack_str(&msg.left.id)          /* string  2 */
+       || !pack_str(&msg.left.cert)        /* string  3 */
+       || !pack_str(&msg.left.ca)          /* string  4 */
+       || !pack_str(&msg.left.groups)      /* string  5 */
+       || !pack_str(&msg.left.updown)      /* string  6 */
+       || !pack_str(&msg.left.virt)        /* string  7 */
+       || !pack_str(&msg.right.id)         /* string  8 */
+       || !pack_str(&msg.right.cert)       /* string  9 */
+       || !pack_str(&msg.right.ca)         /* string 10 */
+       || !pack_str(&msg.right.groups)     /* string 11 */
+       || !pack_str(&msg.right.updown)     /* string 12 */
+       || !pack_str(&msg.right.virt)       /* string 13 */
+       || !pack_str(&msg.keyid)            /* string 14 */
+       || !pack_str(&msg.myid)             /* string 15 */
+       || !pack_str(&msg.cacert)           /* string 16 */
+       || !pack_str(&msg.ldaphost)         /* string 17 */
+       || !pack_str(&msg.ldapbase)         /* string 18 */
+       || !pack_str(&msg.crluri)           /* string 19 */
+       || !pack_str(&msg.crluri2)          /* string 20 */
+       || !pack_str(&msg.ocspuri)          /* string 21 */
+       || !pack_str(&msg.ike)              /* string 22 */
+       || !pack_str(&msg.esp)              /* string 23 */
+       || !pack_str(&msg.sc_data)          /* string 24 */
+       || str_roof - next_str < (ptrdiff_t)msg.keyval.len)    /* chunk (sort of string 5) */
+               diag("too many bytes of strings to fit in message to pluto");
+
+       memcpy(next_str, msg.keyval.ptr, msg.keyval.len);
+       msg.keyval.ptr = NULL;
+       next_str += msg.keyval.len;
+
+       msg.magic = ((opts_seen & ~LELEM(OPT_SHUTDOWN))
+                               | sc_seen | lst_seen | cd_seen | ca_seen) != LEMPTY
+                       || msg.whack_options
+               ? WHACK_MAGIC : WHACK_BASIC_MAGIC;
+
+       /* send message to Pluto */
+       if (access(ctl_addr.sun_path, R_OK | W_OK) < 0)
        {
-           char buf[4097];     /* arbitrary limit on log line length */
-           char *be = buf;
+               int e = errno;
 
-           for (;;)
-           {
-               char *ls = buf;
-               ssize_t rl = read(sock, be, (buf + sizeof(buf)-1) - be);
+               switch (e)
+               {
+               case EACCES:
+                       fprintf(stderr, "whack: no right to communicate with pluto (access(\"%s\"))\n"
+                               , ctl_addr.sun_path);
+                       break;
+               case ENOENT:
+                       fprintf(stderr, "whack: Pluto is not running (no \"%s\")\n"
+                               , ctl_addr.sun_path);
+                       break;
+               default:
+                       fprintf(stderr, "whack: access(\"%s\") failed with %d %s\n"
+                               , ctl_addr.sun_path, errno, strerror(e));
+                       break;
+               }
+               whack_exit(RC_WHACK_PROBLEM);
+       }
+       else
+       {
+               int sock = socket(AF_UNIX, SOCK_STREAM, 0);
+               int exit_status = 0;
+               ssize_t len = next_str - (char *)&msg;
 
-               if (rl < 0)
+               if (sock == -1)
                {
-                   int e = errno;
+                       int e = errno;
 
-                   fprintf(stderr, "whack: read() failed (%d %s)\n", e, strerror(e));
-                   exit(RC_WHACK_PROBLEM);
+                       fprintf(stderr, "whack: socket() failed (%d %s)\n", e, strerror(e));
+                       whack_exit(RC_WHACK_PROBLEM);
                }
-               if (rl == 0)
+
+               if (connect(sock, (struct sockaddr *)&ctl_addr
+               , offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0)
                {
-                   if (be != buf)
-                       fprintf(stderr, "whack: last line from pluto too long or unterminated\n");
-                   break;
-               }
+                       int e = errno;
 
-               be += rl;
-               *be = '\0';
+                       fprintf(stderr, "whack:%s connect() for \"%s\" failed (%d %s)\n"
+                               , e == ECONNREFUSED? " is Pluto running? " : ""
+                               , ctl_addr.sun_path, e, strerror(e));
+                       whack_exit(RC_WHACK_PROBLEM);
+               }
 
-               for (;;)
+               if (write(sock, &msg, len) != len)
                {
-                   char *le = strchr(ls, '\n');
+                       int e = errno;
 
-                   if (le == NULL)
-                   {
-                       /* move last, partial line to start of buffer */
-                       memmove(buf, ls, be-ls);
-                       be -= ls - buf;
-                       break;
-                   }
+                       fprintf(stderr, "whack: write() failed (%d %s)\n", e, strerror(e));
+                       whack_exit(RC_WHACK_PROBLEM);
+               }
 
-                   le++;       /* include NL in line */
-                   write(1, ls, le - ls);
+               /* for now, just copy reply back to stdout */
 
-                   /* figure out prefix number
-                    * and how it should affect our exit status
-                    */
-                   {
-                       unsigned long s = strtoul(ls, NULL, 10);
+               {
+                       char buf[4097];     /* arbitrary limit on log line length */
+                       char *be = buf;
 
-                       switch (s)
+                       for (;;)
                        {
-                       case RC_COMMENT:
-                       case RC_LOG:
-                           /* ignore */
-                           break;
-                       case RC_SUCCESS:
-                           /* be happy */
-                           exit_status = 0;
-                           break;
-                       case RC_ENTERSECRET:
-                           get_secret(sock);
-                           break;
-                       /* case RC_LOG_SERIOUS: */
-                       default:
-                           /* pass through */
-                           exit_status = s;
-                           break;
+                               char *ls = buf;
+                               ssize_t rl = read(sock, be, (buf + sizeof(buf)-1) - be);
+
+                               if (rl < 0)
+                               {
+                                       int e = errno;
+
+                                       fprintf(stderr, "whack: read() failed (%d %s)\n", e, strerror(e));
+                                       whack_exit(RC_WHACK_PROBLEM);
+                               }
+                               if (rl == 0)
+                               {
+                                       if (be != buf)
+                                               fprintf(stderr, "whack: last line from pluto too long or unterminated\n");
+                                       break;
+                               }
+
+                               be += rl;
+                               *be = '\0';
+
+                               for (;;)
+                               {
+                                       char *le = strchr(ls, '\n');
+
+                                       if (le == NULL)
+                                       {
+                                               /* move last, partial line to start of buffer */
+                                               memmove(buf, ls, be-ls);
+                                               be -= ls - buf;
+                                               break;
+                                       }
+
+                                       le++;       /* include NL in line */
+                                       ignore_result(write(1, ls, le - ls));
+
+                                       /* figure out prefix number
+                                        * and how it should affect our exit status
+                                        */
+                                       {
+                                               unsigned long s = strtoul(ls, NULL, 10);
+
+                                               switch (s)
+                                               {
+                                               case RC_COMMENT:
+                                               case RC_LOG:
+                                                       /* ignore */
+                                                       break;
+                                               case RC_SUCCESS:
+                                                       /* be happy */
+                                                       exit_status = 0;
+                                                       break;
+                                               case RC_ENTERSECRET:
+                                                       get_secret(sock);
+                                                       break;
+                                               /* case RC_LOG_SERIOUS: */
+                                               default:
+                                                       /* pass through */
+                                                       exit_status = s;
+                                                       break;
+                                               }
+                                       }
+                                       ls = le;
+                               }
                        }
-                   }
-                   ls = le;
                }
-           }
+               whack_exit(exit_status);
        }
-       return exit_status;
-    }
+       return -1; /* should never be reached */
 }