Index: /trunk/doc/manual/Config.kmk
===================================================================
--- /trunk/doc/manual/Config.kmk	(revision 79610)
+++ /trunk/doc/manual/Config.kmk	(revision 79611)
@@ -39,4 +39,5 @@
 	man_VBoxManage-clonevm.xml \
 	man_VBoxManage-mediumio.xml \
+	man_VBoxManage-dhcpserver.xml \
 	man_VBoxManage-debugvm.xml \
 	man_VBoxManage-extpack.xml \
Index: /trunk/doc/manual/en_US/man_VBoxManage-dhcpserver.xml
===================================================================
--- /trunk/doc/manual/en_US/man_VBoxManage-dhcpserver.xml	(revision 79611)
+++ /trunk/doc/manual/en_US/man_VBoxManage-dhcpserver.xml	(revision 79611)
@@ -0,0 +1,258 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    manpage, user manual, usage: VBoxManage dhcpserver
+
+    Copyright (C) 2006-2015 Oracle Corporation
+
+    This file is part of VirtualBox Open Source Edition (OSE), as
+    available from http://www.virtualbox.org. This file is free software;
+    you can redistribute it and/or modify it under the terms of the GNU
+    General Public License (GPL) as published by the Free Software
+    Foundation, in version 2 as it comes in the "COPYING" file of the
+    VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+    hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ -->
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<refentry id="vboxmanage-dhcpserver" lang="en">
+
+  <refentryinfo>
+    <pubdate>$Date$</pubdate>
+    <title>VBoxManage dhcpserver</title>
+  </refentryinfo>
+
+  <refmeta>
+    <refentrytitle>VBoxManage-dhcpserver</refentrytitle>
+    <manvolnum>1</manvolnum>
+  </refmeta>
+
+  <refnamediv>
+    <refname>VBoxManage-dhcpserver</refname>
+    <refpurpose>DHCP server management</refpurpose>
+    <refclass>Oracle VM VirtualBox</refclass>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <cmdsynopsis id="synopsis-vboxmanage-dhcpserver-add">
+      <command>VBoxManage dhcpserver add</command>
+      <group choice="req">
+        <arg choice="plain">--network=<replaceable>netname</replaceable></arg>
+        <arg choice="plain">--interface=<replaceable>ifname</replaceable></arg>
+      </group>
+      <arg choice="req">--ip=<replaceable>dhcpd-address</replaceable></arg>
+      <arg choice="req">--netmask=<replaceable>mask</replaceable></arg>
+      <arg choice="req">--lower-ip=<replaceable>address</replaceable></arg>
+      <arg choice="req">--upper-ip=<replaceable>address</replaceable></arg>
+      <group choice="req">
+        <arg choice="plain">--enable</arg>
+        <arg choice="plain">--disable</arg>
+      </group>
+      <sbr/>
+      <arg choice="opt" rep="repeat">
+        <arg choice="opt">--global</arg>
+        <arg choice="opt" rep="repeat">--add-opt=<replaceable>dhcp-opt-no hex-string</replaceable></arg>
+      </arg>
+      <sbr/>
+      <arg choice="opt" rep="repeat">
+        <arg choice="req">--vm=<replaceable>name|uuid</replaceable></arg>
+        <arg choice="opt">--nic=<replaceable>1-N</replaceable></arg>
+        <arg choice="opt" rep="repeat">--add-opt=<replaceable>dhcp-opt-no hex-string</replaceable></arg>
+      </arg>
+    </cmdsynopsis>
+    <cmdsynopsis id="synopsis-vboxmanage-dhcpserver-modify">
+      <command>VBoxManage dhcpserver modify</command>
+      <group choice="req">
+        <arg choice="plain">--network=<replaceable>netname</replaceable></arg>
+        <arg choice="plain">--interface=<replaceable>ifname</replaceable></arg>
+      </group>
+      <arg choice="opt">--ip=<replaceable>dhcpd-address</replaceable></arg>
+      <arg choice="opt">--netmask=<replaceable>mask</replaceable></arg>
+      <arg choice="opt">--lower-ip=<replaceable>address</replaceable></arg>
+      <arg choice="opt">--upper-ip=<replaceable>address</replaceable></arg>
+      <group choice="opt">
+        <arg choice="plain">--enable</arg>
+        <arg choice="plain">--disable</arg>
+      </group>
+      <sbr/>
+      <arg choice="opt" rep="repeat">
+        <arg choice="opt">--global</arg>
+        <arg choice="plain">--del-opt=<replaceable>dhcp-opt-no</replaceable></arg>
+        <arg choice="plain">--add-opt=<replaceable>dhcp-opt-no hex-string</replaceable></arg>
+      </arg>
+      <sbr/>
+      <arg choice="opt" rep="repeat">
+        <arg choice="req">--vm=<replaceable>name|uuid</replaceable></arg>
+        <arg choice="opt">--nic=<replaceable>1-N</replaceable></arg>
+        <arg choice="opt" rep="repeat">--del-opt=<replaceable>dhcp-opt-no</replaceable></arg>
+        <arg choice="opt" rep="repeat">--add-opt=<replaceable>dhcp-opt-no hex-string</replaceable></arg>
+      </arg>
+    </cmdsynopsis>
+    <cmdsynopsis id="synopsis-vboxmanage-dhcpserver-remove">
+      <command>VBoxManage dhcpserver remove</command>
+      <group choice="req">
+        <arg choice="plain">--network=<replaceable>netname</replaceable></arg>
+        <arg choice="plain">--interface=<replaceable>ifname</replaceable></arg>
+      </group>
+    </cmdsynopsis>
+    <cmdsynopsis id="synopsis-vboxmanage-dhcpserver-restart">
+      <command>VBoxManage dhcpserver restart</command>
+      <group choice="req">
+        <arg choice="plain">--network=<replaceable>netname</replaceable></arg>
+        <arg choice="plain">--interface=<replaceable>ifname</replaceable></arg>
+      </group>
+    </cmdsynopsis>
+    <cmdsynopsis id="synopsis-vboxmanage-dhcpserver-findlease">
+      <command>VBoxManage dhcpserver findlease</command>
+      <group choice="req">
+        <arg choice="plain">--network=<replaceable>netname</replaceable></arg>
+        <arg choice="plain">--interface=<replaceable>ifname</replaceable></arg>
+      </group>
+      <arg choice="req">--mac-address=<replaceable>mac</replaceable></arg>
+    </cmdsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>
+      The <command>dhcpserver</command> commands enable you to control the DHCP
+       server that is built into VirtualBox.  You may find this useful when
+       using internal or host-only networking.  Theoretically, you can also
+       enable it for a bridged network, but that may cause conflicts with other
+       DHCP servers in your physical network.
+    </para>
+
+    <refsect2 id="vboxmanage-dhcpserver-common-options">
+      <title>Common options</title>
+      <remark role="help-scope" condition="GLOBAL"/>
+      <para>The subcommands of <command>dhcpserver</command> all operate on an
+        internal network that can be identified via its name or in the host-only
+        case via the host-only interface name:</para>
+      <variablelist>
+        <varlistentry>
+          <term>--network=<replaceable>netname</replaceable></term>
+          <listitem><para>The internal network name.  This is the same as you
+            would use as value to the <command>VBoxManage modifyvm --intnet</command>
+            option when configuring a VM for internal networking.  Or you see as
+            VBoxNetworkName in the output from
+            <command>VBoxManage list intnets</command>,
+            <command>VBoxManage list natnets</command>, or
+            <command>VBoxManage list hostonlyifs</command>.
+          </para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term>--interface=<replaceable>ifname</replaceable></term>
+          <listitem><para>The host only interface name.  This would be same value
+            as you would use for the <command>VBoxManage modifyvm --hostonlyadapter</command>
+            option when configuring a VM to use a host-only network.  The value
+            can also be found in the Name row in <command>VBoxManage list hostonlyifs</command>.
+          </para></listitem>
+        </varlistentry>
+      </variablelist>
+    </refsect2>
+
+    <refsect2 id="vboxmanage-dhcpserver-add">
+      <title>dhcpserver add</title>
+      <remark role="help-copy-synopsis"/>
+      <para>
+        Adds a new DHCP server to a network or host-only interface.
+      </para>
+      <variablelist>
+        <varlistentry>
+          <term><option>--ip=<replaceable>dhcpd-address</replaceable></option></term>
+          <listitem><para>The IP address the DHCP server should use.</para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><option>--netmask=<replaceable>mask</replaceable></option></term>
+          <listitem><para>The network mask.  Typically 255.255.255.0.</para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><option>--lower-ip=<replaceable>address</replaceable></option>, <option>--upper-ip=<replaceable>address</replaceable></option></term>
+          <listitem><para>The IP address range for the DHCP server to manage.  This
+            should not include the address of the DHCP server itself, but it must be
+            in the same network as it is.  The boundraries are inclusive, so both the
+            lower and upper addresses will be handed out to clients.</para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><option>--enable</option>, --disable</term>
+          <listitem><para>Whether to enable the DHCP server or disable it.  If not specified,
+            the server will be created in disabled state and no IP addresses handed out.</para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><option>--global</option></term>
+          <listitem><para>Set the option scope to global.  Any subsequent <option>--add-opt</option>
+            options will be apply to all the DHCP clients.</para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><option>--vm=<replaceable>vmname|uuid</replaceable></option></term>
+          <listitem><para>Set the option scope to the first NIC of the specified VM.  Any
+            subsequent <option>-add-opt</option> options will apply just to that interface,
+            nothing else.</para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><option>--nic=<replaceable>1-N</replaceable></option></term>
+          <listitem><para>Set the option scope to a NIC other than first of the VM specified
+            the in <option>--vm</option>.</para></listitem>
+        </varlistentry>
+        <varlistentry>
+          <term><option>--add-opt=<replaceable>dhcp-opt-no hex-string</replaceable></option></term>
+          <listitem><para>Adds the specified DHCP option number (0-255) and value.  The scope of
+            the option is decided by the <option>--vm</option> and <option>global</option> options.
+          </para></listitem>
+        </varlistentry>
+      </variablelist>
+    </refsect2>
+
+    <refsect2 id="vboxmanage-dhcpserver-modify">
+      <title>dhcpserver modify</title>
+      <remark role="help-copy-synopsis"/>
+      <para>
+        This modifies an existing DHCP server configuration.  It takes the same
+        options as the <command>add</command> command with the addition of:
+      </para>
+      <variablelist>
+        <varlistentry>
+          <term><option>--del-opt=<replaceable>dhcp-opt-no</replaceable></option></term>
+          <listitem><para>Counterpart to <option>--add-opt</option> that will cause the specified
+            DHCP option number (0-255) to be deleted from the server settings.  Like with
+            <option>--add-opt</option> the scope of the deletion is governed by the
+            <option>--vm</option> and <option>global</option> options.
+          </para></listitem>
+        </varlistentry>
+      </variablelist>
+    </refsect2>
+
+    <refsect2 id="vboxmanage-dhcpserver-remove">
+      <title>dhcpserver remove</title>
+      <remark role="help-copy-synopsis"/>
+      <para>
+        Removes the specified DHCP server.
+      </para>
+    </refsect2>
+
+    <refsect2 id="vboxmanage-dhcpserver-restart">
+      <title>dhcpserver restart</title>
+      <remark role="help-copy-synopsis"/>
+      <para>
+        Restarts the specified DHCP server.  The DHCP server must be running.
+      </para>
+    </refsect2>
+
+    <refsect2 id="vboxmanage-dhcpserver-findlease">
+      <title>dhcpserver findlease</title>
+      <remark role="help-copy-synopsis"/>
+      <para>
+        Performs a lease database lookup.  This is mainly for getting the IP
+        address of a running VM.
+      </para>
+      <variablelist>
+        <varlistentry>
+          <term><option>--mac-address=<replaceable>mac</replaceable></option></term>
+          <listitem><para>The MAC address to lookup in the lease database.</para></listitem>
+        </varlistentry>
+      </variablelist>
+    </refsect2>
+
+  </refsect1>
+
+</refentry>
+
Index: /trunk/doc/manual/en_US/user_VBoxManage.xml
===================================================================
--- /trunk/doc/manual/en_US/user_VBoxManage.xml	(revision 79610)
+++ /trunk/doc/manual/en_US/user_VBoxManage.xml	(revision 79611)
@@ -8790,139 +8790,4 @@
   </sect1>
 
-  <sect1 id="vboxmanage-dhcpserver">
-
-    <title>VBoxManage dhcpserver</title>
-
-    <para>
-      The <command>dhcpserver</command> commands enable you to control
-      the DHCP server that is built into &product-name;. You may find
-      this useful when using internal or host-only networking.
-      Theoretically, you can also enable it for a bridged network, but
-      that may cause conflicts with other DHCP servers in your physical
-      network.
-    </para>
-
-    <para>
-      Use the following command line options:
-    </para>
-
-    <itemizedlist>
-
-      <listitem>
-        <para>
-          If you use internal networking for a virtual network adapter
-          of a virtual machine, use <computeroutput>VBoxManage
-          dhcpserver add --netname
-          &lt;network_name&gt;</computeroutput>, where
-          <computeroutput>&lt;network_name&gt;</computeroutput> is the
-          same network name you used with <computeroutput>VBoxManage
-          modifyvm &lt;vmname&gt; --intnet&lt;X&gt;
-          &lt;network_name&gt;</computeroutput>.
-        </para>
-      </listitem>
-
-      <listitem>
-        <para>
-          If you use host-only networking for a virtual network adapter
-          of a virtual machine, use <computeroutput>VBoxManage
-          dhcpserver add --ifname
-          &lt;hostonly_if_name&gt;</computeroutput> instead, where
-          <computeroutput>&lt;hostonly_if_name&gt;</computeroutput> is
-          the same host-only interface name you used with
-          <computeroutput>VBoxManage modifyvm &lt;vmname&gt;
-          --hostonlyadapter&lt;X&gt;
-          &lt;hostonly_if_name&gt;</computeroutput>.
-        </para>
-
-        <para>
-          Alternatively, you can also use the <option>--netname</option>
-          option as with internal networks if you know the host-only
-          network's name. You can see the names with <command>VBoxManage
-          list hostonlyifs</command>. See
-          <xref linkend="vboxmanage-list" />.
-        </para>
-      </listitem>
-
-    </itemizedlist>
-
-    <para>
-      The following additional parameters are required when first adding
-      a DHCP server:
-    </para>
-
-    <itemizedlist>
-
-      <listitem>
-        <para>
-          With <computeroutput>--ip</computeroutput>, specify the IP
-          address of the DHCP server.
-        </para>
-      </listitem>
-
-      <listitem>
-        <para>
-          With <computeroutput>--netmask</computeroutput>, specify the
-          netmask of the network.
-        </para>
-      </listitem>
-
-      <listitem>
-        <para>
-          With <computeroutput>--lowerip</computeroutput> and
-          <computeroutput>--upperip</computeroutput>, you can specify
-          the lowest and highest IP address that the DHCP server will
-          assign to clients.
-        </para>
-      </listitem>
-
-    </itemizedlist>
-
-    <para>
-      You can specify additional DHCP options with the
-      <computeroutput>--options</computeroutput> command option. Use
-      <computeroutput>--id</computeroutput> and
-      <computeroutput>--value</computeroutput> to configure a number and
-      string pair corresponding to the DHCP option. Use
-      <computeroutput>--remove</computeroutput> to remove a DHCP option.
-    </para>
-
-    <para>
-      The <computeroutput>--vm</computeroutput> and
-      <computeroutput>--nic</computeroutput> settings enable you to
-      configure DHCP options for a specific network adapter used by the
-      named VM.
-    </para>
-
-    <para>
-      Finally, you must specify
-      <computeroutput>--enable</computeroutput> or the DHCP server will
-      be created in the disabled state and will not be running.
-    </para>
-
-    <para>
-      After this, &product-name; will automatically start the DHCP
-      server for the specified internal network or host-only network as
-      soon as the first virtual machine which uses that network is
-      started.
-    </para>
-
-    <para>
-      Use <command>VBoxManage dhcpserver remove</command> with the given
-      <computeroutput>--netname &lt;network_name&gt;</computeroutput> or
-      <computeroutput>--ifname &lt;hostonly_if_name&gt;</computeroutput>
-      to remove the DHCP server for the specified internal network or
-      host-only network.
-    </para>
-
-    <para>
-      To modify the settings of a DHCP server created using
-      <command>VBoxManage dhcpserver add</command>, you can use
-      <command>VBoxManage dhcpserver modify</command> for a given
-      network or host-only interface name. This has the same parameters
-      as <command>VBoxManage dhcpserver add</command>.
-    </para>
-
-  </sect1>
-
   <sect1 id="vboxmanage-usbdevsource">
 
@@ -9008,4 +8873,5 @@
   <xi:include href="user_man_VBoxManage-clonevm.xml"        xpointer="element(/1)" xmlns:xi="http://www.w3.org/2001/XInclude" />
   <xi:include href="user_man_VBoxManage-extpack.xml"        xpointer="element(/1)" xmlns:xi="http://www.w3.org/2001/XInclude" />
+  <xi:include href="user_man_VBoxManage-dhcpserver.xml"     xpointer="element(/1)" xmlns:xi="http://www.w3.org/2001/XInclude" />
   <xi:include href="user_man_VBoxManage-cloudprofile.xml"   xpointer="element(/1)" xmlns:xi="http://www.w3.org/2001/XInclude" />
   <xi:include href="user_man_VBoxManage-cloudlist.xml"      xpointer="element(/1)" xmlns:xi="http://www.w3.org/2001/XInclude" />
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp	(revision 79610)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp	(revision 79611)
@@ -150,5 +150,5 @@
     { "hostonlyif",         USAGE_HOSTONLYIFS,      VBMG_CMD_TODO, handleHostonlyIf,           0 },
 #endif
-    { "dhcpserver",         USAGE_DHCPSERVER,       VBMG_CMD_TODO, handleDHCPServer,           0 },
+    { "dhcpserver",         USAGE_S_NEWCMD,   HELP_CMD_DHCPSERVER, handleDHCPServer,           0 },
 #ifdef VBOX_WITH_NAT_SERVICE
     { "natnetwork",         USAGE_NATNETWORK,       VBMG_CMD_TODO, handleNATNetwork,           0 },
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h	(revision 79610)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h	(revision 79611)
@@ -92,5 +92,4 @@
     USAGE_EXPORTAPPLIANCE,
     USAGE_HOSTONLYIFS,
-    USAGE_DHCPSERVER,
     USAGE_I_DUMPHDINFO,
     USAGE_STORAGEATTACH,
@@ -209,4 +208,5 @@
 RTEXITCODE  errorTooManyParameters(char **papszArgs);
 RTEXITCODE  errorGetOpt(int rcGetOpt, union RTGETOPTUNION const *pValueUnion);
+RTEXITCODE  errorFetchValue(int iValueNo, const char *pszOption, int rcGetOptFetchValue, union RTGETOPTUNION const *pValueUnion);
 RTEXITCODE  errorSyntax(const char *pszFormat, ...);
 
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageDHCPServer.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageDHCPServer.cpp	(revision 79610)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageDHCPServer.cpp	(revision 79611)
@@ -45,6 +45,75 @@
 #include <map>
 
-#ifndef VBOX_ONLY_DOCS
 using namespace com;
+
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+#define DHCPD_CMD_COMMON_OPT_NETWORK          999 /**< The --network / --netname option number. */
+#define DHCPD_CMD_COMMON_OPT_INTERFACE        998 /**< The --interface / --ifname option number. */
+/** Common option definitions. */
+#define DHCPD_CMD_COMMON_OPTION_DEFS() \
+        { "--network",              DHCPD_CMD_COMMON_OPT_NETWORK,       RTGETOPT_REQ_STRING  }, \
+        { "--netname",              DHCPD_CMD_COMMON_OPT_NETWORK,       RTGETOPT_REQ_STRING  }, /* legacy */ \
+        { "--interface",            DHCPD_CMD_COMMON_OPT_INTERFACE,     RTGETOPT_REQ_STRING  }, \
+        { "--ifname",               DHCPD_CMD_COMMON_OPT_INTERFACE,     RTGETOPT_REQ_STRING  }  /* legacy
+
+/** Handles common options in the typical option parsing switch. */
+#define DHCPD_CMD_COMMON_OPTION_CASES(a_pCtx, a_ch, a_pValueUnion) \
+        case DHCPD_CMD_COMMON_OPT_NETWORK: \
+            if ((a_pCtx)->pszInterface != NULL) \
+                return errorSyntax("Either --network or --interface, not both"); \
+            (a_pCtx)->pszNetwork = ValueUnion.psz; \
+            break; \
+        case DHCPD_CMD_COMMON_OPT_INTERFACE: \
+            if ((a_pCtx)->pszNetwork != NULL) \
+                return errorSyntax("Either --interface or --network, not both"); \
+            (a_pCtx)->pszInterface = ValueUnion.psz; \
+            break
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+/**
+ * Definition of a dhcpserver command, with handler and various flags.
+ */
+typedef struct DHCPDCMDDEF
+{
+    /** The command name. */
+    const char *pszName;
+
+    /**
+     * Actual command handler callback.
+     *
+     * @param   pCtx            Pointer to command context to use.
+     */
+    DECLR3CALLBACKMEMBER(RTEXITCODE, pfnHandler, (struct DHCPDCMDCTX *pCtx, int argc, char **argv));
+
+    /** The sub-command scope flags. */
+    uint64_t    fSubcommandScope;
+} DHCPDCMDDEF;
+/** Pointer to a const dhcpserver command definition. */
+typedef DHCPDCMDDEF const *PCDHCPDCMDDEF;
+
+/**
+ * dhcpserver command context (mainly for carrying common options and such).
+ */
+typedef struct DHCPDCMDCTX
+{
+    /** The handler arguments from the main() function. */
+    HandlerArg     *pArg;
+    /** Pointer to the command definition. */
+    PCDHCPDCMDDEF   pCmdDef;
+    /** The network name. */
+    const char     *pszNetwork;
+    /** The (trunk) interface name. */
+    const char     *pszInterface;
+} DHCPDCMDCTX;
+/** Pointer to a dhcpserver command context. */
+typedef DHCPDCMDCTX *PDHCPDCMDCTX;
+
+
 
 typedef enum enMainOpCodes
@@ -91,57 +160,55 @@
 typedef std::vector<VmNameSlotKey> VmConfigs;
 
-static const RTGETOPTDEF g_aDHCPIPOptions[] =
-{
-    { "--netname",          't', RTGETOPT_REQ_STRING },  /* we use 't' instead of 'n' to avoid
-                                                          * 1. the misspelled "-enable" long option to be treated as 'e' (for -enable) + 'n' (for -netname) + "<the_rest_opt>" (for net name)
-                                                          * 2. the misspelled "-netmask" to be treated as 'n' (for -netname) + "<the_rest_opt>" (for net name)
-                                                          */
-    { "-netname",           't', RTGETOPT_REQ_STRING },     // deprecated (if removed check below)
-    { "--ifname",           'f', RTGETOPT_REQ_STRING },  /* we use 'f' instead of 'i' to avoid
-                                                          * 1. the misspelled "-disable" long option to be treated as 'd' (for -disable) + 'i' (for -ifname) + "<the_rest_opt>" (for if name)
-                                                          */
-    { "-ifname",            'f', RTGETOPT_REQ_STRING },     // deprecated
-    { "--ip",               'a', RTGETOPT_REQ_STRING },
-    { "-ip",                'a', RTGETOPT_REQ_STRING },     // deprecated
-    { "--netmask",          'm', RTGETOPT_REQ_STRING },
-    { "-netmask",           'm', RTGETOPT_REQ_STRING },     // deprecated
-    { "--lowerip",          'l', RTGETOPT_REQ_STRING },
-    { "-lowerip",           'l', RTGETOPT_REQ_STRING },     // deprecated
-    { "--upperip",          'u', RTGETOPT_REQ_STRING },
-    { "-upperip",           'u', RTGETOPT_REQ_STRING },     // deprecated
-    { "--enable",           'e', RTGETOPT_REQ_NOTHING },
-    { "-enable",            'e', RTGETOPT_REQ_NOTHING },    // deprecated
-    { "--disable",          'd', RTGETOPT_REQ_NOTHING },
-    { "-disable",           'd', RTGETOPT_REQ_NOTHING },     // deprecated
-    { "--options",          'o', RTGETOPT_REQ_NOTHING },
-    { "--vm",               'M', RTGETOPT_REQ_STRING}, /* only with -o */
-    { "--nic",              'n', RTGETOPT_REQ_UINT8}, /* only with -o and -M */
-    { "--id",               'i', RTGETOPT_REQ_UINT8}, /* only with -o */
-    { "--value",            'p', RTGETOPT_REQ_STRING}, /* only with -i */
-    { "--remove",           'r', RTGETOPT_REQ_NOTHING} /* only with -i */
-};
-
-static RTEXITCODE handleOp(HandlerArg *a, OPCODE enmCode, int iStart)
-{
-    if (a->argc - iStart < 2)
-        return errorSyntax(USAGE_DHCPSERVER, "Not enough parameters");
-
-    int index = iStart;
-    HRESULT rc;
-    bool fOptionsRead = false;
-    bool fVmOptionRead = false;
-
-    const char *pszVmName = NULL;
-    const char *pNetName = NULL;
-    const char *pIfName = NULL;
-    const char * pIp = NULL;
-    const char * pNetmask = NULL;
-    const char * pLowerIp = NULL;
-    const char * pUpperIp = NULL;
-
-    uint8_t u8OptId = (uint8_t)~0;
-    uint8_t u8Slot = (uint8_t)~0;
-
-    int enable = -1;
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+
+
+
+static RTEXITCODE dhcpdHandleTooManyCmds(PDHCPDCMDCTX pCtx, int argc, char **argv)
+{
+    // glue - start
+    HandlerArg *a       = pCtx->pArg;
+    OPCODE      enmCode = pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD ? OP_ADD
+                        : pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_MODIFY ? OP_MODIFY
+                        : pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_REMOVE ? OP_REMOVE : OP_RESTART;
+    RT_NOREF(argc, argv);
+    // glue - end
+
+    static const RTGETOPTDEF s_aDHCPIPOptions[] =
+    {
+        DHCPD_CMD_COMMON_OPTION_DEFS(),
+        { "--ip",               'a', RTGETOPT_REQ_STRING  },
+        { "-ip",                'a', RTGETOPT_REQ_STRING  },    // deprecated
+        { "--netmask",          'm', RTGETOPT_REQ_STRING  },
+        { "-netmask",           'm', RTGETOPT_REQ_STRING  },    // deprecated
+        { "--lowerip",          'l', RTGETOPT_REQ_STRING  },
+        { "-lowerip",           'l', RTGETOPT_REQ_STRING  },    // deprecated
+        { "--upperip",          'u', RTGETOPT_REQ_STRING  },
+        { "-upperip",           'u', RTGETOPT_REQ_STRING  },    // deprecated
+        { "--enable",           'e', RTGETOPT_REQ_NOTHING },
+        { "-enable",            'e', RTGETOPT_REQ_NOTHING },    // deprecated
+        { "--disable",          'd', RTGETOPT_REQ_NOTHING },
+        { "-disable",           'd', RTGETOPT_REQ_NOTHING },    // deprecated
+        { "--global",           'g', RTGETOPT_REQ_NOTHING },
+        { "--vm",               'M', RTGETOPT_REQ_STRING  },
+        { "--nic",              'n', RTGETOPT_REQ_UINT8   },
+        { "--add-opt",          'A', RTGETOPT_REQ_STRING  },
+        { "--del-opt",          'D', RTGETOPT_REQ_STRING  },
+        { "--id",               'i', RTGETOPT_REQ_UINT8   },    // obsolete, backwards compatibility only.
+        { "--value",            'p', RTGETOPT_REQ_STRING  },    // obsolete, backwards compatibility only.
+        { "--remove",           'r', RTGETOPT_REQ_NOTHING },    // obsolete, backwards compatibility only.
+        { "--options",          'o', RTGETOPT_REQ_NOTHING },    // obsolete legacy, ignored
+
+    };
+
+    bool fNeedValueOrRemove = false; /* Only used with --id; remove in 6.1+ */
+
+    const char *pszDhcpdIp = NULL;
+    const char *pszNetmask = NULL;
+    const char *pszLowerIp = NULL;
+    const char *pszUpperIp = NULL;
+    int         fEnabled   = -1;
 
     DhcpOpts          GlobalDhcpOptions;
@@ -149,5 +216,11 @@
     VmSlot2OptionsM   VmSlot2Options;
     VmSlot2OptionIdsM VmSlot2Options2Delete;
-    VmConfigs         VmConfigs2Delete;
+    /// @todo what was  this for: VmConfigs         VmConfigs2Delete;
+
+    const char       *pszVmName             = NULL;
+    uint8_t           u8OptId               = 0;
+    uint8_t           u8Slot                = 0;
+    DhcpOpts         *pScopeOptions         = &GlobalDhcpOptions;
+    DhcpOptIds       *pScopeOptions2Delete  = &GlobalDhcpOptions2Delete;
 
     int c;
@@ -157,223 +230,145 @@
                  a->argc,
                  a->argv,
-                 g_aDHCPIPOptions,
-                 enmCode != OP_REMOVE ? RT_ELEMENTS(g_aDHCPIPOptions) : 4, /* we use only --netname and --ifname for remove*/
-                 index,
-                 RTGETOPTINIT_FLAGS_NO_STD_OPTS);
+                 s_aDHCPIPOptions,
+                 enmCode != OP_REMOVE ? RT_ELEMENTS(s_aDHCPIPOptions) : 4, /* we use only --netname and --ifname for remove*/
+                 1,
+                 0);
     while ((c = RTGetOpt(&GetState, &ValueUnion)))
     {
         switch (c)
         {
-            case 't':   // --netname
-                if(pNetName)
-                    return errorSyntax(USAGE_DHCPSERVER, "You can only specify --netname once.");
-                else if (pIfName)
-                    return errorSyntax(USAGE_DHCPSERVER, "You can either use a --netname or --ifname for identifying the DHCP server.");
-                else
-                {
-                    pNetName = ValueUnion.psz;
-                }
-            break;
-            case 'f':   // --ifname
-                if(pIfName)
-                    return errorSyntax(USAGE_DHCPSERVER, "You can only specify --ifname once.");
-                else if (pNetName)
-                    return errorSyntax(USAGE_DHCPSERVER, "You can either use a --netname or --ipname for identifying the DHCP server.");
-                else
-                {
-                    pIfName = ValueUnion.psz;
-                }
-            break;
+            DHCPD_CMD_COMMON_OPTION_CASES(pCtx, c, &ValueUnion);
             case 'a':   // -ip
-                if(pIp)
-                    return errorSyntax(USAGE_DHCPSERVER, "You can only specify --ip once.");
-                else
-                {
-                    pIp = ValueUnion.psz;
-                }
-            break;
+                pszDhcpdIp = ValueUnion.psz;
+                break;
             case 'm':   // --netmask
-                if(pNetmask)
-                    return errorSyntax(USAGE_DHCPSERVER, "You can only specify --netmask once.");
-                else
-                {
-                    pNetmask = ValueUnion.psz;
-                }
-            break;
+                pszNetmask = ValueUnion.psz;
+                break;
             case 'l':   // --lowerip
-                if(pLowerIp)
-                    return errorSyntax(USAGE_DHCPSERVER, "You can only specify --lowerip once.");
-                else
-                {
-                    pLowerIp = ValueUnion.psz;
-                }
-            break;
+                pszLowerIp = ValueUnion.psz;
+                break;
             case 'u':   // --upperip
-                if(pUpperIp)
-                    return errorSyntax(USAGE_DHCPSERVER, "You can only specify --upperip once.");
-                else
-                {
-                    pUpperIp = ValueUnion.psz;
-                }
-            break;
+                pszUpperIp = ValueUnion.psz;
+                break;
             case 'e':   // --enable
-                if(enable >= 0)
-                    return errorSyntax(USAGE_DHCPSERVER, "You can specify either --enable or --disable once.");
-                else
-                {
-                    enable = 1;
-                }
-            break;
+                fEnabled = 1;
+                break;
             case 'd':   // --disable
-                if(enable >= 0)
-                    return errorSyntax(USAGE_DHCPSERVER, "You can specify either --enable or --disable once.");
-                else
-                {
-                    enable = 0;
-                }
-            break;
-            case VINF_GETOPT_NOT_OPTION:
-                return errorSyntax(USAGE_DHCPSERVER, "unhandled parameter: %s", ValueUnion.psz);
-            break;
-
-            case 'o': // --options
-                {
-        // {"--vm",                'n', RTGETOPT_REQ_STRING}, /* only with -o */
-        // {"--nic",               'c', RTGETOPT_REQ_UINT8}, /* only with -o and -n*/
-        // {"--id",                'i', RTGETOPT_REQ_UINT8}, /* only with -o */
-        // {"--value",             'p', RTGETOPT_REQ_STRING} /* only with -i */
-                    if (fOptionsRead)
-                        return errorSyntax(USAGE_DHCPSERVER,
-                                           "previos option edition  wasn't finished");
-                    fOptionsRead = true;
-                    fVmOptionRead = false; /* we want specify new global or vm option*/
-                    u8Slot = (uint8_t)~0;
-                    u8OptId = (uint8_t)~0;
-                    pszVmName = NULL;
-                } /* end of --options  */
-                break;
-
-            case 'M': // --vm
-                {
-                    if (fVmOptionRead)
-                        return errorSyntax(USAGE_DHCPSERVER,
-                                           "previous vm option edition wasn't finished");
-                    else
-                        fVmOptionRead = true;
-                    u8Slot = (uint8_t)~0; /* clear slot */
-                    pszVmName = RTStrDup(ValueUnion.psz);
-                }
-                break; /* end of --vm */
-
-            case 'n': // --nic
-                {
-                    if (!fVmOptionRead)
-                        return errorSyntax(USAGE_DHCPSERVER,
-                                           "vm name wasn't specified");
-
-                    u8Slot = ValueUnion.u8;
-
-                    if (u8Slot < 1)
-                        return errorSyntax(USAGE_DHCPSERVER,
-                                           "invalid NIC number: %u", u8Slot);
-                    --u8Slot;
-                }
-                break; /* end of --nic */
-
-            case 'i': // --id
-                {
-                    if (!fOptionsRead)
-                        return errorSyntax(USAGE_DHCPSERVER,
-                                           "-o wasn't found");
-
-                    u8OptId = ValueUnion.u8;
-                }
-                break; /* end of --id */
-
-            case 'p': // --value
-                {
-                    if (!fOptionsRead)
-                        return errorSyntax(USAGE_DHCPSERVER,
-                                           "-o wasn't found");
-
-                    if (u8OptId == (uint8_t)~0)
-                        return errorSyntax(USAGE_DHCPSERVER,
-                                           "--id wasn't found");
-                    if (   fVmOptionRead
-                        && u8Slot == (uint8_t)~0)
-                        return errorSyntax(USAGE_DHCPSERVER,
-                                           "--nic wasn't found");
-
-                    DhcpOpts &opts = fVmOptionRead ? VmSlot2Options[VmNameSlotKey(pszVmName, u8Slot)]
-                                                    : GlobalDhcpOptions;
-                    std::string strVal = ValueUnion.psz;
-                    opts.push_back(DhcpOptSpec((DhcpOpt_T)u8OptId, strVal));
-
-                }
-                break; // --end of value
-
-            case 'r': /* --remove */
-                {
-                    if (!fOptionsRead)
-                        return errorSyntax(USAGE_DHCPSERVER,
-                                           "-o wasn't found");
-
-                    if (u8OptId == (uint8_t)~0)
-                        return errorSyntax(USAGE_DHCPSERVER,
-                                           "--id wasn't found");
-                    if (   fVmOptionRead
-                        && u8Slot == (uint8_t)~0)
-                        return errorSyntax(USAGE_DHCPSERVER,
-                                           "--nic wasn't found");
-
-                    DhcpOptIds &optIds = fVmOptionRead ? VmSlot2Options2Delete[VmNameSlotKey(pszVmName, u8Slot)]
-                                                       : GlobalDhcpOptions2Delete;
-                    optIds.push_back((DhcpOpt_T)u8OptId);
-                }
-                break; /* --end of remove */
+                fEnabled = 0;
+                break;
+
+            case 'g':   // --global     Sets the option scope to 'global'.
+                if (fNeedValueOrRemove)
+                    return errorSyntax("Incomplete option sequence preseeding '--global'");
+                pScopeOptions         = &GlobalDhcpOptions;
+                pScopeOptions2Delete  = &GlobalDhcpOptions2Delete;
+                break;
+
+            case 'M':   // --vm         Sets the option scope to ValueUnion.psz + 0.
+                if (fNeedValueOrRemove)
+                    return errorSyntax("Incomplete option sequence preseeding '--vm'");
+                pszVmName = ValueUnion.psz;
+                u8Slot    = 0;
+                pScopeOptions        = &VmSlot2Options[VmNameSlotKey(pszVmName, u8Slot)];
+                pScopeOptions2Delete = &VmSlot2Options2Delete[VmNameSlotKey(pszVmName, u8Slot)];
+                break;
+
+            case 'n':   // --nic        Sets the option scope to pszVmName + (ValueUnion.u8 - 1).
+                if (!pszVmName)
+                    return errorSyntax("--nic option requires a --vm preceeding selecting the VM it should apply to");
+                if (fNeedValueOrRemove)
+                    return errorSyntax("Incomplete option sequence preseeding '--nic=%u", ValueUnion.u8);
+                u8Slot = ValueUnion.u8;
+                if (u8Slot < 1)
+                    return errorSyntax("invalid NIC number: %u", u8Slot);
+                --u8Slot;
+                pScopeOptions        = &VmSlot2Options[VmNameSlotKey(pszVmName, u8Slot)];
+                pScopeOptions2Delete = &VmSlot2Options2Delete[VmNameSlotKey(pszVmName, u8Slot)];
+                break;
+
+            case 'A':   // --add-opt num hexvalue
+            {
+                uint8_t const idAddOpt = ValueUnion.u8;
+                c = RTGetOptFetchValue(&GetState, &ValueUnion, RTGETOPT_REQ_STRING);
+                if (RT_FAILURE(c))
+                    return errorFetchValue(1, "--add-opt", c, &ValueUnion);
+                pScopeOptions->push_back(DhcpOptSpec((DhcpOpt_T)idAddOpt, std::string(ValueUnion.psz)));
+                break;
+            }
+
+            case 'D':   // --del-opt num
+                if (enmCode == OP_ADD)
+                    return errorSyntax("--del-opt does not apply to the 'add' subcommand");
+                pScopeOptions2Delete->push_back((DhcpOpt_T)ValueUnion.u8);
+                break;
+
+            /*
+             * For backwards compatibility. Remove in 6.1 or later.
+             */
+
+            case 'o':   // --options - obsolete, ignored.
+                break;
+
+            case 'i':   // --id
+                if (fNeedValueOrRemove)
+                    return errorSyntax("Incomplete option sequence preseeding '--id=%u", ValueUnion.u8);
+                u8OptId = ValueUnion.u8;
+                fNeedValueOrRemove = true;
+                break;
+
+            case 'p':   // --value
+                if (!fNeedValueOrRemove)
+                    return errorSyntax("--value without --id=dhcp-opt-no");
+                pScopeOptions->push_back(DhcpOptSpec((DhcpOpt_T)u8OptId, std::string(ValueUnion.psz)));
+                fNeedValueOrRemove = false;
+                break;
+
+            case 'r':   // --remove
+                if (enmCode == OP_ADD)
+                    return errorSyntax("--remove does not apply to the 'add' subcommand");
+                if (!fNeedValueOrRemove)
+                    return errorSyntax("--remove without --id=dhcp-opt-no");
+                pScopeOptions2Delete->push_back((DhcpOpt_T)u8OptId);
+                /** @todo remove from pScopeOptions */
+                fNeedValueOrRemove = false;
+                break;
 
             default:
-                if (c > 0)
-                {
-                    if (RT_C_IS_GRAPH(c))
-                        return errorSyntax(USAGE_DHCPSERVER, "unhandled option: -%c", c);
-                    return errorSyntax(USAGE_DHCPSERVER, "unhandled option: %i", c);
-                }
-                if (c == VERR_GETOPT_UNKNOWN_OPTION)
-                    return errorSyntax(USAGE_DHCPSERVER, "unknown option: %s", ValueUnion.psz);
-                if (ValueUnion.pDef)
-                    return errorSyntax(USAGE_DHCPSERVER, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
-                return errorSyntax(USAGE_DHCPSERVER, "%Rrs", c);
+                return errorGetOpt(c, &ValueUnion);
         }
     }
 
-    if(! pNetName && !pIfName)
-        return errorSyntax(USAGE_DHCPSERVER, "You need to specify either --netname or --ifname to identify the DHCP server");
-
-    if(   enmCode != OP_REMOVE
-       && enmCode != OP_RESTART
-       && GlobalDhcpOptions.empty()
-       && VmSlot2Options.empty()
-       && GlobalDhcpOptions2Delete.empty()
-       && VmSlot2Options2Delete.empty())
-    {
-        if(enable < 0 || pIp || pNetmask || pLowerIp || pUpperIp)
+    if (!pCtx->pszNetwork && !pCtx->pszInterface)
+        return errorSyntax("You need to specify either --network or --interface to identify the DHCP server");
+
+    if (   enmCode != OP_REMOVE
+        && enmCode != OP_RESTART
+        && GlobalDhcpOptions.empty()
+        && VmSlot2Options.empty()
+        && GlobalDhcpOptions2Delete.empty()
+        && VmSlot2Options2Delete.empty())
+    {
+        /** @todo For the 'modify' subcmd, missing configuration parameters could be
+         * retrieved from the current config.  All are only required for 'add'!
+         * The 'fEnabled' attribute does not come into play here.  */
+        if (fEnabled < 0 || pszDhcpdIp || pszNetmask || pszLowerIp || pszUpperIp)
         {
-            if(!pIp)
-                return errorSyntax(USAGE_DHCPSERVER, "You need to specify --ip option");
-
-            if(!pNetmask)
-                return errorSyntax(USAGE_DHCPSERVER, "You need to specify --netmask option");
-
-            if(!pLowerIp)
-                return errorSyntax(USAGE_DHCPSERVER, "You need to specify --lowerip option");
-
-            if(!pUpperIp)
-                return errorSyntax(USAGE_DHCPSERVER, "You need to specify --upperip option");
+            RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
+            if (!pszDhcpdIp)
+                rcExit = errorSyntax("Missing required option: --ip");
+            if (!pszNetmask)
+                rcExit = errorSyntax("Missing required option: --netmask");
+            if (!pszLowerIp)
+                rcExit = errorSyntax("Missing required option: --lowerip");
+            if (!pszUpperIp)
+                rcExit = errorSyntax("Missing required option: --upperip");
+            if (rcExit != RTEXITCODE_SUCCESS)
+                return rcExit;
         }
     }
 
+    HRESULT rc;
     Bstr NetName;
-    if(!pNetName)
+    if (!pCtx->pszNetwork)
     {
         ComPtr<IHost> host;
@@ -381,15 +376,15 @@
 
         ComPtr<IHostNetworkInterface> hif;
-        CHECK_ERROR(host, FindHostNetworkInterfaceByName(Bstr(pIfName).mutableRaw(), hif.asOutParam()));
+        CHECK_ERROR(host, FindHostNetworkInterfaceByName(Bstr(pCtx->pszInterface).mutableRaw(), hif.asOutParam()));
         if (FAILED(rc))
-            return errorArgument("Could not find interface '%s'", pIfName);
+            return errorArgument("Could not find interface '%s'", pCtx->pszInterface);
 
         CHECK_ERROR(hif, COMGETTER(NetworkName) (NetName.asOutParam()));
         if (FAILED(rc))
-            return errorArgument("Could not get network name for the interface '%s'", pIfName);
+            return errorArgument("Could not get network name for the interface '%s'", pCtx->pszInterface);
     }
     else
     {
-        NetName = Bstr(pNetName);
+        NetName = Bstr(pCtx->pszNetwork);
     }
 
@@ -424,76 +419,36 @@
     else
     {
-        if (pIp || pNetmask || pLowerIp || pUpperIp)
+        if (pszDhcpdIp || pszNetmask || pszLowerIp || pszUpperIp)
         {
-            CHECK_ERROR(svr, SetConfiguration (
-                          Bstr(pIp).mutableRaw(),
-                          Bstr(pNetmask).mutableRaw(),
-                          Bstr(pLowerIp).mutableRaw(),
-                          Bstr(pUpperIp).mutableRaw()));
-            if(FAILED(rc))
+            CHECK_ERROR(svr, SetConfiguration(Bstr(pszDhcpdIp).mutableRaw(),
+                                              Bstr(pszNetmask).mutableRaw(),
+                                              Bstr(pszLowerIp).mutableRaw(),
+                                              Bstr(pszUpperIp).mutableRaw()));
+            if (FAILED(rc))
                 return errorArgument("Failed to set configuration");
         }
 
-        if(enable >= 0)
-        {
-            CHECK_ERROR(svr, COMSETTER(Enabled) ((BOOL)enable));
-        }
-
-        /* remove specified options */
-        DhcpOptIdIterator itOptId;
-        for (itOptId = GlobalDhcpOptions2Delete.begin();
-             itOptId != GlobalDhcpOptions2Delete.end();
-             ++itOptId)
-        {
+        if (fEnabled >= 0)
+            CHECK_ERROR(svr, COMSETTER(Enabled)((BOOL)fEnabled));
+
+        /* Remove options: */
+        for (DhcpOptIdIterator itOptId = GlobalDhcpOptions2Delete.begin(); itOptId != GlobalDhcpOptions2Delete.end(); ++itOptId)
             CHECK_ERROR(svr, RemoveGlobalOption(*itOptId));
-        }
-        VmSlot2OptionIdsIterator itIdVector;
-        for (itIdVector = VmSlot2Options2Delete.begin();
-             itIdVector != VmSlot2Options2Delete.end();
-             ++itIdVector)
-        {
-            for(itOptId = itIdVector->second.begin();
-                itOptId != itIdVector->second.end();
-                ++itOptId)
-            {
-                CHECK_ERROR(svr,
-                            RemoveVmSlotOption(Bstr(itIdVector->first.VmName.c_str()).raw(),
-                                               itIdVector->first.u8Slot,
-                                               *itOptId));
-            }
-        }
-
-        /* option processing */
-        DhcpOptIterator itOpt;
-        VmSlot2OptionsIterator it;
+
+        for (VmSlot2OptionIdsIterator itIdVector = VmSlot2Options2Delete.begin();
+             itIdVector != VmSlot2Options2Delete.end(); ++itIdVector)
+            for (DhcpOptIdIterator itOptId = itIdVector->second.begin(); itOptId != itIdVector->second.end(); ++itOptId)
+                CHECK_ERROR(svr, RemoveVmSlotOption(Bstr(itIdVector->first.VmName.c_str()).raw(),
+                                                    itIdVector->first.u8Slot, *itOptId));
 
         /* Global Options */
-        for(itOpt = GlobalDhcpOptions.begin();
-            itOpt != GlobalDhcpOptions.end();
-            ++itOpt)
-        {
-            CHECK_ERROR(svr,
-                        AddGlobalOption(
-                          itOpt->first,
-                          com::Bstr(itOpt->second.c_str()).raw()));
-        }
-
-        /* heh, vm slot options. */
-
-        for (it = VmSlot2Options.begin();
-             it != VmSlot2Options.end();
-             ++it)
-        {
-            for(itOpt = it->second.begin();
-                itOpt != it->second.end();
-                ++itOpt)
-            {
-                CHECK_ERROR(svr,
-                            AddVmSlotOption(Bstr(it->first.VmName.c_str()).raw(),
-                                            it->first.u8Slot,
-                                            itOpt->first,
-                                            com::Bstr(itOpt->second.c_str()).raw()));
-            }
-        }
+        for (DhcpOptIterator itOpt = GlobalDhcpOptions.begin(); itOpt != GlobalDhcpOptions.end(); ++itOpt)
+            CHECK_ERROR(svr, AddGlobalOption(itOpt->first, com::Bstr(itOpt->second.c_str()).raw()));
+
+        /* VM slot options. */
+        for (VmSlot2OptionsIterator it = VmSlot2Options.begin(); it != VmSlot2Options.end(); ++it)
+            for (DhcpOptIterator itOpt = it->second.begin(); itOpt != it->second.end(); ++itOpt)
+                CHECK_ERROR(svr, AddVmSlotOption(Bstr(it->first.VmName.c_str()).raw(), it->first.u8Slot, itOpt->first,
+                                                 com::Bstr(itOpt->second.c_str()).raw()));
     }
 
@@ -502,24 +457,197 @@
 
 
-RTEXITCODE handleDHCPServer(HandlerArg *a)
-{
-    if (a->argc < 1)
-        return errorSyntax(USAGE_DHCPSERVER, "Not enough parameters");
-
-    RTEXITCODE rcExit;
-    if (strcmp(a->argv[0], "modify") == 0)
-        rcExit = handleOp(a, OP_MODIFY, 1);
-    else if (strcmp(a->argv[0], "add") == 0)
-        rcExit = handleOp(a, OP_ADD, 1);
-    else if (strcmp(a->argv[0], "remove") == 0)
-        rcExit = handleOp(a, OP_REMOVE, 1);
-    else if (strcmp(a->argv[0], "restart") == 0)
-        rcExit = handleOp(a, OP_RESTART, 1);
+/**
+ * Helper that find the DHCP server instance.
+ *
+ * @returns The DHCP server instance. NULL if failed (complaining done).
+ * @param   pCtx                The DHCP server command context.
+ */
+static ComPtr<IDHCPServer> dhcpdFindServer(PDHCPDCMDCTX pCtx)
+{
+    ComPtr<IDHCPServer> ptrRet;
+    if (pCtx->pszNetwork || pCtx->pszInterface)
+    {
+        Assert(pCtx->pszNetwork == NULL || pCtx->pszInterface == NULL);
+
+        /*
+         * We need a network name to find the DHCP server.  So, if interface is
+         * given we have to look it up.
+         */
+        HRESULT hrc;
+        Bstr bstrNetName(pCtx->pszNetwork);
+        if (!pCtx->pszNetwork)
+        {
+            ComPtr<IHost> ptrIHost;
+            CHECK_ERROR2_RET(hrc, pCtx->pArg->virtualBox, COMGETTER(Host)(ptrIHost.asOutParam()), ptrRet);
+
+            Bstr bstrInterface(pCtx->pszInterface);
+            ComPtr<IHostNetworkInterface> ptrIHostIf;
+            CHECK_ERROR2(hrc, ptrIHost, FindHostNetworkInterfaceByName(bstrInterface.raw(), ptrIHostIf.asOutParam()));
+            if (FAILED(hrc))
+            {
+                errorArgument("Failed to locate host-only interface '%s'", pCtx->pszInterface);
+                return ptrRet;
+            }
+
+            CHECK_ERROR2_RET(hrc, ptrIHostIf, COMGETTER(NetworkName)(bstrNetName.asOutParam()), ptrRet);
+        }
+
+        /*
+         * Now, try locate the server
+         */
+        hrc = pCtx->pArg->virtualBox->FindDHCPServerByNetworkName(bstrNetName.raw(), ptrRet.asOutParam());
+        if (SUCCEEDED(hrc))
+            return ptrRet;
+        if (pCtx->pszNetwork)
+            errorArgument("Failed to find DHCP server for network '%s'", pCtx->pszNetwork);
+        else
+            errorArgument("Failed to find DHCP server for host-only interface '%s' (network '%ls')",
+                          pCtx->pszInterface, bstrNetName.raw());
+    }
     else
-        rcExit = errorSyntax(USAGE_DHCPSERVER, "Invalid parameter '%s'", Utf8Str(a->argv[0]).c_str());
-
-    return rcExit;
+        errorSyntax("You need to specify either --network or --interface to identify the DHCP server");
+    return ptrRet;
 }
 
-#endif /* !VBOX_ONLY_DOCS */
-
+
+static RTEXITCODE dhcpdHandleFindLease(PDHCPDCMDCTX pCtx, int argc, char **argv)
+{
+    /*
+     * Parse the command line.
+     */
+    static const RTGETOPTDEF s_aOptions[] =
+    {
+        DHCPD_CMD_COMMON_OPTION_DEFS(),
+        { "--mac-address",      'm', RTGETOPT_REQ_MACADDR  },
+
+    };
+
+    bool            fHaveMacAddress   = false;
+    RTMAC           MacAddress        = { 0, 0, 0, 0, 0, 0 };
+
+    RTGETOPTSTATE   GetState;
+    int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
+    AssertRCReturn(vrc, RTEXITCODE_FAILURE);
+
+    RTGETOPTUNION   ValueUnion;
+    while ((vrc = RTGetOpt(&GetState, &ValueUnion)))
+    {
+        switch (vrc)
+        {
+            DHCPD_CMD_COMMON_OPTION_CASES(pCtx, vrc, &ValueUnion);
+
+            case 'm':   // --mac-address
+                fHaveMacAddress = true;
+                MacAddress = ValueUnion.MacAddr;
+                break;
+
+            default:
+                return errorGetOpt(vrc, &ValueUnion);
+        }
+    }
+
+    if (!fHaveMacAddress)
+        return errorSyntax("You need to specify a MAC address too look for");
+
+    /*
+     * Locate the server and perform the requested operation.
+     */
+    ComPtr<IDHCPServer> ptrDHCPServer = dhcpdFindServer(pCtx);
+    if (ptrDHCPServer.isNull())
+        return RTEXITCODE_FAILURE;
+
+    char    szMac[32];
+    RTStrPrintf(szMac, sizeof(szMac), "%RTmac", &MacAddress);
+    Bstr    bstrAddress;
+    Bstr    bstrState;
+    LONG64  secIssued = 0;
+    LONG64  secExpire = 0;
+    HRESULT hrc;
+    CHECK_ERROR2(hrc, ptrDHCPServer, FindLeaseByMAC(Bstr(szMac).raw(), 0 /*type*/,
+                                                    bstrAddress.asOutParam(), bstrState.asOutParam(), &secIssued, &secExpire));
+    if (SUCCEEDED(hrc))
+    {
+        RTTIMESPEC  TimeSpec;
+        int64_t     cSecLeftToLive = secExpire - RTTimeSpecGetSeconds(RTTimeNow(&TimeSpec));
+        RTTIME      Time;
+        char        szIssued[RTTIME_STR_LEN];
+        RTTimeToStringEx(RTTimeExplode(&Time, RTTimeSpecSetSeconds(&TimeSpec, secIssued)), szIssued, sizeof(szIssued), 0);
+        char        szExpire[RTTIME_STR_LEN];
+        RTTimeToStringEx(RTTimeExplode(&Time, RTTimeSpecSetSeconds(&TimeSpec, secExpire)), szExpire, sizeof(szExpire), 0);
+
+        RTPrintf("IP Address:  %ls\n"
+                 "MAC Address: %RTmac\n"
+                 "State:       %ls\n"
+                 "Issued:      %s (%RU64)\n"
+                 "Expire:      %s (%RU64)\n"
+                 "TTL:         %RU64 sec, currently %RU64 sec left\n",
+                 bstrAddress.raw(),
+                 &MacAddress,
+                 bstrState.raw(),
+                 szIssued, secIssued,
+                 szExpire, secExpire,
+                 secExpire >= secIssued ? secExpire - secIssued : 0, cSecLeftToLive > 0  ? cSecLeftToLive : 0);
+        return RTEXITCODE_SUCCESS;
+    }
+    return RTEXITCODE_FAILURE;
+}
+
+
+RTEXITCODE handleDHCPServer(HandlerArg *pArg)
+{
+    /*
+     * Command definitions.
+     */
+    static const DHCPDCMDDEF s_aCmdDefs[] =
+    {
+        { "add",            dhcpdHandleTooManyCmds,     HELP_SCOPE_DHCPSERVER_ADD },
+        { "modify",         dhcpdHandleTooManyCmds,     HELP_SCOPE_DHCPSERVER_MODIFY },
+        { "remove",         dhcpdHandleTooManyCmds,     HELP_SCOPE_DHCPSERVER_REMOVE },
+        { "restart",        dhcpdHandleTooManyCmds,     HELP_SCOPE_DHCPSERVER_RESTART },
+        { "findlease",      dhcpdHandleFindLease,       HELP_SCOPE_DHCPSERVER_FINDLEASE },
+    };
+
+    /*
+     * VBoxManage dhcpserver [common-options] subcommand ...
+     */
+    DHCPDCMDCTX CmdCtx;
+    CmdCtx.pArg         = pArg;
+    CmdCtx.pCmdDef      = NULL;
+    CmdCtx.pszInterface = NULL;
+    CmdCtx.pszNetwork   = NULL;
+
+    static const RTGETOPTDEF s_CommonOptions[] = { DHCPD_CMD_COMMON_OPTION_DEFS() };
+
+    int ch;
+    RTGETOPTUNION ValueUnion;
+    RTGETOPTSTATE GetState;
+    RTGetOptInit(&GetState, pArg->argc, pArg->argv, s_CommonOptions, RT_ELEMENTS(s_CommonOptions), 0, 0 /* No sorting! */);
+
+    while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0)
+    {
+        switch (ch)
+        {
+            DHCPD_CMD_COMMON_OPTION_CASES(&CmdCtx, ch, &ValueUnion);
+
+            case VINF_GETOPT_NOT_OPTION:
+            {
+                const char *pszCmd = ValueUnion.psz;
+                uint32_t    iCmd;
+                for (iCmd = 0; iCmd < RT_ELEMENTS(s_aCmdDefs); iCmd++)
+                    if (strcmp(s_aCmdDefs[iCmd].pszName, pszCmd) == 0)
+                    {
+                        CmdCtx.pCmdDef = &s_aCmdDefs[iCmd];
+                        setCurrentSubcommand(s_aCmdDefs[iCmd].fSubcommandScope);
+                        return s_aCmdDefs[iCmd].pfnHandler(&CmdCtx, pArg->argc - GetState.iNext + 1,
+                                                           &pArg->argv[GetState.iNext - 1]);
+                    }
+                return errorUnknownSubcommand(pszCmd);
+            }
+
+            default:
+                return errorGetOpt(ch, &ValueUnion);
+        }
+    }
+    return errorNoSubcommand();
+}
+
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp	(revision 79610)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp	(revision 79611)
@@ -297,4 +297,29 @@
     else
         RTMsgError("%Rrs", rcGetOpt);
+}
+
+
+/**
+ * For use to deal with RTGetOptFetchValue failures.
+ *
+ * @retval  RTEXITCODE_SYNTAX
+ * @param   iValueNo            The value number being fetched, counting the
+ *                              RTGetOpt value as zero and the first
+ *                              RTGetOptFetchValue call as one.
+ * @param   pszOption           The option being parsed.
+ * @param   rcGetOptFetchValue  The status returned by RTGetOptFetchValue.
+ * @param   pValueUnion         The value union returned by the fetch.
+ */
+RTEXITCODE errorFetchValue(int iValueNo, const char *pszOption, int rcGetOptFetchValue, union RTGETOPTUNION const *pValueUnion)
+{
+    Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID);
+    showLogo(g_pStdErr);
+    if (rcGetOptFetchValue == VERR_GETOPT_REQUIRED_ARGUMENT_MISSING)
+        RTMsgError("Missing the %u%s value for option %s",
+                   iValueNo, iValueNo == 1 ? "st" : iValueNo == 2 ? "nd" : iValueNo == 3 ? "rd" : "th",  pszOption);
+    else
+        errorGetOptWorker(rcGetOptFetchValue, pValueUnion);
+    return RTEXITCODE_SYNTAX;
+
 }
 
@@ -1201,26 +1226,4 @@
 #endif
 
-    if (enmCommand == USAGE_DHCPSERVER || enmCommand == USAGE_S_ALL)
-    {
-        RTStrmPrintf(pStrm,
-                           "%s dhcpserver %s      add|modify --netname <network_name> |\n"
-#if defined(VBOX_WITH_NETFLT)
-                     "                                       --ifname <hostonly_if_name>\n"
-#endif
-                     "                            [--ip <ip_address>\n"
-                     "                            --netmask <network_mask>\n"
-                     "                            --lowerip <lower_ip>\n"
-                     "                            --upperip <upper_ip>]\n"
-                     "                            [--enable | --disable]\n"
-                     "                            [--options [--vm <name> --nic <1-N>]\n"
-                     "                             --id <number> [--value <string> | --remove]]\n"
-                     "                             (multiple options allowed after --options)\n\n"
-                           "%s dhcpserver %s      remove --netname <network_name> |\n"
-#if defined(VBOX_WITH_NETFLT)
-                     "                                   --ifname <hostonly_if_name>\n"
-#endif
-                     "\n", SEP, SEP);
-    }
-
     if (enmCommand == USAGE_USBDEVSOURCE || enmCommand == USAGE_S_ALL)
     {
