VirtualBox

Changeset 79611 in vbox


Ignore:
Timestamp:
Jul 8, 2019 11:33:59 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
131913
Message:

VBoxManage,manual: Added the dhcpserver subcommand findlease for testing IDHCPServer::FindLeaseByMAC(). Wrote a man page for the dhcpserver command and converted the help to the new style. Also took a shot at simplifying the option handling of the existing dhcpserver subcommands while retaining a somewhat more flexible compatibility with the old syntax (not advertised) - not really tested. bugref:9288 bugref:9151

Location:
trunk
Files:
6 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/doc/manual/Config.kmk

    r78734 r79611  
    3939        man_VBoxManage-clonevm.xml \
    4040        man_VBoxManage-mediumio.xml \
     41        man_VBoxManage-dhcpserver.xml \
    4142        man_VBoxManage-debugvm.xml \
    4243        man_VBoxManage-extpack.xml \
  • trunk/doc/manual/en_US/man_VBoxManage-dhcpserver.xml

    r79528 r79611  
    11<?xml version="1.0" encoding="UTF-8"?>
    22<!--
    3     manpage, user manual, usage: VBoxManage extpack
     3    manpage, user manual, usage: VBoxManage dhcpserver
    44
    55    Copyright (C) 2006-2015 Oracle Corporation
     
    1414 -->
    1515<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
    16 <refentry id="vboxmanage-extpack" lang="en">
     16<refentry id="vboxmanage-dhcpserver" lang="en">
    1717
    1818  <refentryinfo>
    1919    <pubdate>$Date$</pubdate>
    20     <title>VBoxManage extpack</title>
     20    <title>VBoxManage dhcpserver</title>
    2121  </refentryinfo>
    2222
    2323  <refmeta>
    24     <refentrytitle>VBoxManage-extpack</refentrytitle>
     24    <refentrytitle>VBoxManage-dhcpserver</refentrytitle>
    2525    <manvolnum>1</manvolnum>
    2626  </refmeta>
    2727
    2828  <refnamediv>
    29     <refname>VBoxManage-extpack</refname>
    30     <refpurpose>extension package management</refpurpose>
     29    <refname>VBoxManage-dhcpserver</refname>
     30    <refpurpose>DHCP server management</refpurpose>
    3131    <refclass>Oracle VM VirtualBox</refclass>
    3232  </refnamediv>
    3333
    3434  <refsynopsisdiv>
    35     <cmdsynopsis id="synopsis-vboxmanage-extpack-install"> <!-- The 'id' is mandatory and must start with 'synopsis-'. -->
    36       <command>VBoxManage extpack install</command>
    37       <arg>--replace</arg>
    38       <arg choice="req"><replaceable>tarball</replaceable></arg>
    39     </cmdsynopsis>
    40     <cmdsynopsis id="synopsis-vboxmanage-extpack-uninstall">
    41       <command>VBoxManage extpack uninstall</command>
    42       <arg>--force</arg>
    43       <arg choice="req"><replaceable>name</replaceable></arg>
    44     </cmdsynopsis>
    45     <cmdsynopsis id="synopsis-vboxmanage-extpack-cleanup">
    46       <command>VBoxManage extpack cleanup</command>
     35    <cmdsynopsis id="synopsis-vboxmanage-dhcpserver-add">
     36      <command>VBoxManage dhcpserver add</command>
     37      <group choice="req">
     38        <arg choice="plain">--network=<replaceable>netname</replaceable></arg>
     39        <arg choice="plain">--interface=<replaceable>ifname</replaceable></arg>
     40      </group>
     41      <arg choice="req">--ip=<replaceable>dhcpd-address</replaceable></arg>
     42      <arg choice="req">--netmask=<replaceable>mask</replaceable></arg>
     43      <arg choice="req">--lower-ip=<replaceable>address</replaceable></arg>
     44      <arg choice="req">--upper-ip=<replaceable>address</replaceable></arg>
     45      <group choice="req">
     46        <arg choice="plain">--enable</arg>
     47        <arg choice="plain">--disable</arg>
     48      </group>
     49      <sbr/>
     50      <arg choice="opt" rep="repeat">
     51        <arg choice="opt">--global</arg>
     52        <arg choice="opt" rep="repeat">--add-opt=<replaceable>dhcp-opt-no hex-string</replaceable></arg>
     53      </arg>
     54      <sbr/>
     55      <arg choice="opt" rep="repeat">
     56        <arg choice="req">--vm=<replaceable>name|uuid</replaceable></arg>
     57        <arg choice="opt">--nic=<replaceable>1-N</replaceable></arg>
     58        <arg choice="opt" rep="repeat">--add-opt=<replaceable>dhcp-opt-no hex-string</replaceable></arg>
     59      </arg>
     60    </cmdsynopsis>
     61    <cmdsynopsis id="synopsis-vboxmanage-dhcpserver-modify">
     62      <command>VBoxManage dhcpserver modify</command>
     63      <group choice="req">
     64        <arg choice="plain">--network=<replaceable>netname</replaceable></arg>
     65        <arg choice="plain">--interface=<replaceable>ifname</replaceable></arg>
     66      </group>
     67      <arg choice="opt">--ip=<replaceable>dhcpd-address</replaceable></arg>
     68      <arg choice="opt">--netmask=<replaceable>mask</replaceable></arg>
     69      <arg choice="opt">--lower-ip=<replaceable>address</replaceable></arg>
     70      <arg choice="opt">--upper-ip=<replaceable>address</replaceable></arg>
     71      <group choice="opt">
     72        <arg choice="plain">--enable</arg>
     73        <arg choice="plain">--disable</arg>
     74      </group>
     75      <sbr/>
     76      <arg choice="opt" rep="repeat">
     77        <arg choice="opt">--global</arg>
     78        <arg choice="plain">--del-opt=<replaceable>dhcp-opt-no</replaceable></arg>
     79        <arg choice="plain">--add-opt=<replaceable>dhcp-opt-no hex-string</replaceable></arg>
     80      </arg>
     81      <sbr/>
     82      <arg choice="opt" rep="repeat">
     83        <arg choice="req">--vm=<replaceable>name|uuid</replaceable></arg>
     84        <arg choice="opt">--nic=<replaceable>1-N</replaceable></arg>
     85        <arg choice="opt" rep="repeat">--del-opt=<replaceable>dhcp-opt-no</replaceable></arg>
     86        <arg choice="opt" rep="repeat">--add-opt=<replaceable>dhcp-opt-no hex-string</replaceable></arg>
     87      </arg>
     88    </cmdsynopsis>
     89    <cmdsynopsis id="synopsis-vboxmanage-dhcpserver-remove">
     90      <command>VBoxManage dhcpserver remove</command>
     91      <group choice="req">
     92        <arg choice="plain">--network=<replaceable>netname</replaceable></arg>
     93        <arg choice="plain">--interface=<replaceable>ifname</replaceable></arg>
     94      </group>
     95    </cmdsynopsis>
     96    <cmdsynopsis id="synopsis-vboxmanage-dhcpserver-restart">
     97      <command>VBoxManage dhcpserver restart</command>
     98      <group choice="req">
     99        <arg choice="plain">--network=<replaceable>netname</replaceable></arg>
     100        <arg choice="plain">--interface=<replaceable>ifname</replaceable></arg>
     101      </group>
     102    </cmdsynopsis>
     103    <cmdsynopsis id="synopsis-vboxmanage-dhcpserver-findlease">
     104      <command>VBoxManage dhcpserver findlease</command>
     105      <group choice="req">
     106        <arg choice="plain">--network=<replaceable>netname</replaceable></arg>
     107        <arg choice="plain">--interface=<replaceable>ifname</replaceable></arg>
     108      </group>
     109      <arg choice="req">--mac-address=<replaceable>mac</replaceable></arg>
    47110    </cmdsynopsis>
    48111  </refsynopsisdiv>
     
    51114    <title>Description</title>
    52115
    53     <refsect2 id="vboxmanage-extpack-install">
    54       <title>extpack install</title>
    55       <remark role="help-copy-synopsis"/>
    56       <para>
    57         Installs a new extension pack on the system.  This command will fail if an older
    58         version of the same extension pack is already installed.  The
    59         <option>--replace</option> option can be used to uninstall any
    60         old package before the new one is installed.
    61       </para>
    62       <variablelist>
    63         <varlistentry>
    64           <term><option>--replace</option></term><listitem><para>Uninstall existing extension pack version.</para></listitem>
    65         </varlistentry>
    66         <varlistentry>
    67           <term><replaceable>tarball</replaceable></term>
    68           <listitem>
    69             <para>The file containing the extension pack to be installed.</para>
    70           </listitem>
    71         </varlistentry>
    72       </variablelist>
    73     </refsect2>
    74 
    75     <refsect2 id="vboxmanage-extpack-uninstall">
    76       <title>extpack uninstall</title>
    77       <remark role="help-copy-synopsis"/>
    78       <para>
    79         Uninstalls an extension pack from the system.  The subcommand will also succeed
    80         in the case where the specified extension pack is not present on the system.
    81         You can use <computeroutput>VBoxManage list extpacks</computeroutput> to show
    82         the names of the extension packs which are currently installed.
    83       </para>
    84       <variablelist>
    85         <varlistentry>
    86           <term><option>--force</option></term>
    87           <listitem>
    88             <para>Overrides most refusals to uninstall an extension pack</para>
    89           </listitem>
    90         </varlistentry>
    91         <varlistentry>
    92           <term><replaceable>name</replaceable></term>
    93           <listitem>
    94             <para>The name of the extension pack to be uninstalled.</para>
    95           </listitem>
    96         </varlistentry>
    97       </variablelist>
    98     </refsect2>
    99 
    100     <refsect2 id="vboxmanage-extpack-cleanup">
    101       <title>extpack cleanup</title>
    102       <remark role="help-copy-synopsis"/>
    103       <para>
    104         Used to remove temporary files and directories that may have been left behind
    105         if a previous install or uninstall command failed.
    106       </para>
     116    <para>
     117      The <command>dhcpserver</command> commands enable you to control the DHCP
     118       server that is built into VirtualBox.  You may find this useful when
     119       using internal or host-only networking.  Theoretically, you can also
     120       enable it for a bridged network, but that may cause conflicts with other
     121       DHCP servers in your physical network.
     122    </para>
     123
     124    <refsect2 id="vboxmanage-dhcpserver-common-options">
     125      <title>Common options</title>
     126      <remark role="help-scope" condition="GLOBAL"/>
     127      <para>The subcommands of <command>dhcpserver</command> all operate on an
     128        internal network that can be identified via its name or in the host-only
     129        case via the host-only interface name:</para>
     130      <variablelist>
     131        <varlistentry>
     132          <term>--network=<replaceable>netname</replaceable></term>
     133          <listitem><para>The internal network name.  This is the same as you
     134            would use as value to the <command>VBoxManage modifyvm --intnet</command>
     135            option when configuring a VM for internal networking.  Or you see as
     136            VBoxNetworkName in the output from
     137            <command>VBoxManage list intnets</command>,
     138            <command>VBoxManage list natnets</command>, or
     139            <command>VBoxManage list hostonlyifs</command>.
     140          </para></listitem>
     141        </varlistentry>
     142        <varlistentry>
     143          <term>--interface=<replaceable>ifname</replaceable></term>
     144          <listitem><para>The host only interface name.  This would be same value
     145            as you would use for the <command>VBoxManage modifyvm --hostonlyadapter</command>
     146            option when configuring a VM to use a host-only network.  The value
     147            can also be found in the Name row in <command>VBoxManage list hostonlyifs</command>.
     148          </para></listitem>
     149        </varlistentry>
     150      </variablelist>
     151    </refsect2>
     152
     153    <refsect2 id="vboxmanage-dhcpserver-add">
     154      <title>dhcpserver add</title>
     155      <remark role="help-copy-synopsis"/>
     156      <para>
     157        Adds a new DHCP server to a network or host-only interface.
     158      </para>
     159      <variablelist>
     160        <varlistentry>
     161          <term><option>--ip=<replaceable>dhcpd-address</replaceable></option></term>
     162          <listitem><para>The IP address the DHCP server should use.</para></listitem>
     163        </varlistentry>
     164        <varlistentry>
     165          <term><option>--netmask=<replaceable>mask</replaceable></option></term>
     166          <listitem><para>The network mask.  Typically 255.255.255.0.</para></listitem>
     167        </varlistentry>
     168        <varlistentry>
     169          <term><option>--lower-ip=<replaceable>address</replaceable></option>, <option>--upper-ip=<replaceable>address</replaceable></option></term>
     170          <listitem><para>The IP address range for the DHCP server to manage.  This
     171            should not include the address of the DHCP server itself, but it must be
     172            in the same network as it is.  The boundraries are inclusive, so both the
     173            lower and upper addresses will be handed out to clients.</para></listitem>
     174        </varlistentry>
     175        <varlistentry>
     176          <term><option>--enable</option>, --disable</term>
     177          <listitem><para>Whether to enable the DHCP server or disable it.  If not specified,
     178            the server will be created in disabled state and no IP addresses handed out.</para></listitem>
     179        </varlistentry>
     180        <varlistentry>
     181          <term><option>--global</option></term>
     182          <listitem><para>Set the option scope to global.  Any subsequent <option>--add-opt</option>
     183            options will be apply to all the DHCP clients.</para></listitem>
     184        </varlistentry>
     185        <varlistentry>
     186          <term><option>--vm=<replaceable>vmname|uuid</replaceable></option></term>
     187          <listitem><para>Set the option scope to the first NIC of the specified VM.  Any
     188            subsequent <option>-add-opt</option> options will apply just to that interface,
     189            nothing else.</para></listitem>
     190        </varlistentry>
     191        <varlistentry>
     192          <term><option>--nic=<replaceable>1-N</replaceable></option></term>
     193          <listitem><para>Set the option scope to a NIC other than first of the VM specified
     194            the in <option>--vm</option>.</para></listitem>
     195        </varlistentry>
     196        <varlistentry>
     197          <term><option>--add-opt=<replaceable>dhcp-opt-no hex-string</replaceable></option></term>
     198          <listitem><para>Adds the specified DHCP option number (0-255) and value.  The scope of
     199            the option is decided by the <option>--vm</option> and <option>global</option> options.
     200          </para></listitem>
     201        </varlistentry>
     202      </variablelist>
     203    </refsect2>
     204
     205    <refsect2 id="vboxmanage-dhcpserver-modify">
     206      <title>dhcpserver modify</title>
     207      <remark role="help-copy-synopsis"/>
     208      <para>
     209        This modifies an existing DHCP server configuration.  It takes the same
     210        options as the <command>add</command> command with the addition of:
     211      </para>
     212      <variablelist>
     213        <varlistentry>
     214          <term><option>--del-opt=<replaceable>dhcp-opt-no</replaceable></option></term>
     215          <listitem><para>Counterpart to <option>--add-opt</option> that will cause the specified
     216            DHCP option number (0-255) to be deleted from the server settings.  Like with
     217            <option>--add-opt</option> the scope of the deletion is governed by the
     218            <option>--vm</option> and <option>global</option> options.
     219          </para></listitem>
     220        </varlistentry>
     221      </variablelist>
     222    </refsect2>
     223
     224    <refsect2 id="vboxmanage-dhcpserver-remove">
     225      <title>dhcpserver remove</title>
     226      <remark role="help-copy-synopsis"/>
     227      <para>
     228        Removes the specified DHCP server.
     229      </para>
     230    </refsect2>
     231
     232    <refsect2 id="vboxmanage-dhcpserver-restart">
     233      <title>dhcpserver restart</title>
     234      <remark role="help-copy-synopsis"/>
     235      <para>
     236        Restarts the specified DHCP server.  The DHCP server must be running.
     237      </para>
     238    </refsect2>
     239
     240    <refsect2 id="vboxmanage-dhcpserver-findlease">
     241      <title>dhcpserver findlease</title>
     242      <remark role="help-copy-synopsis"/>
     243      <para>
     244        Performs a lease database lookup.  This is mainly for getting the IP
     245        address of a running VM.
     246      </para>
     247      <variablelist>
     248        <varlistentry>
     249          <term><option>--mac-address=<replaceable>mac</replaceable></option></term>
     250          <listitem><para>The MAC address to lookup in the lease database.</para></listitem>
     251        </varlistentry>
     252      </variablelist>
    107253    </refsect2>
    108254
    109255  </refsect1>
    110256
    111   <refsect1>
    112     <title>Examples</title>
    113     <remark role="help-scope" condition="EXTPACK_UNINSTALL,EXTPACK"/>
    114     <para>
    115           How to list extension packs:
    116 <screen>$ VBoxManage list extpacks
    117 Extension Packs: 1
    118 Pack no. 0:   Oracle VM VirtualBox Extension Pack
    119 Version:      4.1.12
    120 Revision:     77218
    121 Edition:
    122 Description:  USB 2.0 Host Controller, VirtualBox RDP, PXE ROM with E1000 support.
    123 VRDE Module:  VBoxVRDP
    124 Usable:       true
    125 Why unusable:</screen></para>
    126 
    127     <para>How to remove an extension pack:
    128 <screen>$ VBoxManage extpack uninstall "Oracle VM VirtualBox Extension Pack"
    129 0%...10%...20%...30%...40%...50%...60%...70%...80%...90%...100%
    130 Successfully uninstalled "Oracle VM VirtualBox Extension Pack".</screen></para>
    131   </refsect1>
    132 
    133257</refentry>
    134258
  • trunk/doc/manual/en_US/user_VBoxManage.xml

    r78734 r79611  
    87908790  </sect1>
    87918791
    8792   <sect1 id="vboxmanage-dhcpserver">
    8793 
    8794     <title>VBoxManage dhcpserver</title>
    8795 
    8796     <para>
    8797       The <command>dhcpserver</command> commands enable you to control
    8798       the DHCP server that is built into &product-name;. You may find
    8799       this useful when using internal or host-only networking.
    8800       Theoretically, you can also enable it for a bridged network, but
    8801       that may cause conflicts with other DHCP servers in your physical
    8802       network.
    8803     </para>
    8804 
    8805     <para>
    8806       Use the following command line options:
    8807     </para>
    8808 
    8809     <itemizedlist>
    8810 
    8811       <listitem>
    8812         <para>
    8813           If you use internal networking for a virtual network adapter
    8814           of a virtual machine, use <computeroutput>VBoxManage
    8815           dhcpserver add --netname
    8816           &lt;network_name&gt;</computeroutput>, where
    8817           <computeroutput>&lt;network_name&gt;</computeroutput> is the
    8818           same network name you used with <computeroutput>VBoxManage
    8819           modifyvm &lt;vmname&gt; --intnet&lt;X&gt;
    8820           &lt;network_name&gt;</computeroutput>.
    8821         </para>
    8822       </listitem>
    8823 
    8824       <listitem>
    8825         <para>
    8826           If you use host-only networking for a virtual network adapter
    8827           of a virtual machine, use <computeroutput>VBoxManage
    8828           dhcpserver add --ifname
    8829           &lt;hostonly_if_name&gt;</computeroutput> instead, where
    8830           <computeroutput>&lt;hostonly_if_name&gt;</computeroutput> is
    8831           the same host-only interface name you used with
    8832           <computeroutput>VBoxManage modifyvm &lt;vmname&gt;
    8833           --hostonlyadapter&lt;X&gt;
    8834           &lt;hostonly_if_name&gt;</computeroutput>.
    8835         </para>
    8836 
    8837         <para>
    8838           Alternatively, you can also use the <option>--netname</option>
    8839           option as with internal networks if you know the host-only
    8840           network's name. You can see the names with <command>VBoxManage
    8841           list hostonlyifs</command>. See
    8842           <xref linkend="vboxmanage-list" />.
    8843         </para>
    8844       </listitem>
    8845 
    8846     </itemizedlist>
    8847 
    8848     <para>
    8849       The following additional parameters are required when first adding
    8850       a DHCP server:
    8851     </para>
    8852 
    8853     <itemizedlist>
    8854 
    8855       <listitem>
    8856         <para>
    8857           With <computeroutput>--ip</computeroutput>, specify the IP
    8858           address of the DHCP server.
    8859         </para>
    8860       </listitem>
    8861 
    8862       <listitem>
    8863         <para>
    8864           With <computeroutput>--netmask</computeroutput>, specify the
    8865           netmask of the network.
    8866         </para>
    8867       </listitem>
    8868 
    8869       <listitem>
    8870         <para>
    8871           With <computeroutput>--lowerip</computeroutput> and
    8872           <computeroutput>--upperip</computeroutput>, you can specify
    8873           the lowest and highest IP address that the DHCP server will
    8874           assign to clients.
    8875         </para>
    8876       </listitem>
    8877 
    8878     </itemizedlist>
    8879 
    8880     <para>
    8881       You can specify additional DHCP options with the
    8882       <computeroutput>--options</computeroutput> command option. Use
    8883       <computeroutput>--id</computeroutput> and
    8884       <computeroutput>--value</computeroutput> to configure a number and
    8885       string pair corresponding to the DHCP option. Use
    8886       <computeroutput>--remove</computeroutput> to remove a DHCP option.
    8887     </para>
    8888 
    8889     <para>
    8890       The <computeroutput>--vm</computeroutput> and
    8891       <computeroutput>--nic</computeroutput> settings enable you to
    8892       configure DHCP options for a specific network adapter used by the
    8893       named VM.
    8894     </para>
    8895 
    8896     <para>
    8897       Finally, you must specify
    8898       <computeroutput>--enable</computeroutput> or the DHCP server will
    8899       be created in the disabled state and will not be running.
    8900     </para>
    8901 
    8902     <para>
    8903       After this, &product-name; will automatically start the DHCP
    8904       server for the specified internal network or host-only network as
    8905       soon as the first virtual machine which uses that network is
    8906       started.
    8907     </para>
    8908 
    8909     <para>
    8910       Use <command>VBoxManage dhcpserver remove</command> with the given
    8911       <computeroutput>--netname &lt;network_name&gt;</computeroutput> or
    8912       <computeroutput>--ifname &lt;hostonly_if_name&gt;</computeroutput>
    8913       to remove the DHCP server for the specified internal network or
    8914       host-only network.
    8915     </para>
    8916 
    8917     <para>
    8918       To modify the settings of a DHCP server created using
    8919       <command>VBoxManage dhcpserver add</command>, you can use
    8920       <command>VBoxManage dhcpserver modify</command> for a given
    8921       network or host-only interface name. This has the same parameters
    8922       as <command>VBoxManage dhcpserver add</command>.
    8923     </para>
    8924 
    8925   </sect1>
    8926 
    89278792  <sect1 id="vboxmanage-usbdevsource">
    89288793
     
    90088873  <xi:include href="user_man_VBoxManage-clonevm.xml"        xpointer="element(/1)" xmlns:xi="http://www.w3.org/2001/XInclude" />
    90098874  <xi:include href="user_man_VBoxManage-extpack.xml"        xpointer="element(/1)" xmlns:xi="http://www.w3.org/2001/XInclude" />
     8875  <xi:include href="user_man_VBoxManage-dhcpserver.xml"     xpointer="element(/1)" xmlns:xi="http://www.w3.org/2001/XInclude" />
    90108876  <xi:include href="user_man_VBoxManage-cloudprofile.xml"   xpointer="element(/1)" xmlns:xi="http://www.w3.org/2001/XInclude" />
    90118877  <xi:include href="user_man_VBoxManage-cloudlist.xml"      xpointer="element(/1)" xmlns:xi="http://www.w3.org/2001/XInclude" />
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.cpp

    r78126 r79611  
    150150    { "hostonlyif",         USAGE_HOSTONLYIFS,      VBMG_CMD_TODO, handleHostonlyIf,           0 },
    151151#endif
    152     { "dhcpserver",         USAGE_DHCPSERVER,       VBMG_CMD_TODO, handleDHCPServer,           0 },
     152    { "dhcpserver",         USAGE_S_NEWCMD,   HELP_CMD_DHCPSERVER, handleDHCPServer,           0 },
    153153#ifdef VBOX_WITH_NAT_SERVICE
    154154    { "natnetwork",         USAGE_NATNETWORK,       VBMG_CMD_TODO, handleNATNetwork,           0 },
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManage.h

    r77887 r79611  
    9292    USAGE_EXPORTAPPLIANCE,
    9393    USAGE_HOSTONLYIFS,
    94     USAGE_DHCPSERVER,
    9594    USAGE_I_DUMPHDINFO,
    9695    USAGE_STORAGEATTACH,
     
    209208RTEXITCODE  errorTooManyParameters(char **papszArgs);
    210209RTEXITCODE  errorGetOpt(int rcGetOpt, union RTGETOPTUNION const *pValueUnion);
     210RTEXITCODE  errorFetchValue(int iValueNo, const char *pszOption, int rcGetOptFetchValue, union RTGETOPTUNION const *pValueUnion);
    211211RTEXITCODE  errorSyntax(const char *pszFormat, ...);
    212212
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageDHCPServer.cpp

    r77595 r79611  
    4545#include <map>
    4646
    47 #ifndef VBOX_ONLY_DOCS
    4847using namespace com;
     48
     49
     50/*********************************************************************************************************************************
     51*   Defined Constants And Macros                                                                                                 *
     52*********************************************************************************************************************************/
     53#define DHCPD_CMD_COMMON_OPT_NETWORK          999 /**< The --network / --netname option number. */
     54#define DHCPD_CMD_COMMON_OPT_INTERFACE        998 /**< The --interface / --ifname option number. */
     55/** Common option definitions. */
     56#define DHCPD_CMD_COMMON_OPTION_DEFS() \
     57        { "--network",              DHCPD_CMD_COMMON_OPT_NETWORK,       RTGETOPT_REQ_STRING  }, \
     58        { "--netname",              DHCPD_CMD_COMMON_OPT_NETWORK,       RTGETOPT_REQ_STRING  }, /* legacy */ \
     59        { "--interface",            DHCPD_CMD_COMMON_OPT_INTERFACE,     RTGETOPT_REQ_STRING  }, \
     60        { "--ifname",               DHCPD_CMD_COMMON_OPT_INTERFACE,     RTGETOPT_REQ_STRING  }  /* legacy
     61
     62/** Handles common options in the typical option parsing switch. */
     63#define DHCPD_CMD_COMMON_OPTION_CASES(a_pCtx, a_ch, a_pValueUnion) \
     64        case DHCPD_CMD_COMMON_OPT_NETWORK: \
     65            if ((a_pCtx)->pszInterface != NULL) \
     66                return errorSyntax("Either --network or --interface, not both"); \
     67            (a_pCtx)->pszNetwork = ValueUnion.psz; \
     68            break; \
     69        case DHCPD_CMD_COMMON_OPT_INTERFACE: \
     70            if ((a_pCtx)->pszNetwork != NULL) \
     71                return errorSyntax("Either --interface or --network, not both"); \
     72            (a_pCtx)->pszInterface = ValueUnion.psz; \
     73            break
     74
     75
     76/*********************************************************************************************************************************
     77*   Structures and Typedefs                                                                                                      *
     78*********************************************************************************************************************************/
     79/**
     80 * Definition of a dhcpserver command, with handler and various flags.
     81 */
     82typedef struct DHCPDCMDDEF
     83{
     84    /** The command name. */
     85    const char *pszName;
     86
     87    /**
     88     * Actual command handler callback.
     89     *
     90     * @param   pCtx            Pointer to command context to use.
     91     */
     92    DECLR3CALLBACKMEMBER(RTEXITCODE, pfnHandler, (struct DHCPDCMDCTX *pCtx, int argc, char **argv));
     93
     94    /** The sub-command scope flags. */
     95    uint64_t    fSubcommandScope;
     96} DHCPDCMDDEF;
     97/** Pointer to a const dhcpserver command definition. */
     98typedef DHCPDCMDDEF const *PCDHCPDCMDDEF;
     99
     100/**
     101 * dhcpserver command context (mainly for carrying common options and such).
     102 */
     103typedef struct DHCPDCMDCTX
     104{
     105    /** The handler arguments from the main() function. */
     106    HandlerArg     *pArg;
     107    /** Pointer to the command definition. */
     108    PCDHCPDCMDDEF   pCmdDef;
     109    /** The network name. */
     110    const char     *pszNetwork;
     111    /** The (trunk) interface name. */
     112    const char     *pszInterface;
     113} DHCPDCMDCTX;
     114/** Pointer to a dhcpserver command context. */
     115typedef DHCPDCMDCTX *PDHCPDCMDCTX;
     116
     117
    49118
    50119typedef enum enMainOpCodes
     
    91160typedef std::vector<VmNameSlotKey> VmConfigs;
    92161
    93 static const RTGETOPTDEF g_aDHCPIPOptions[] =
    94 {
    95     { "--netname",          't', RTGETOPT_REQ_STRING },  /* we use 't' instead of 'n' to avoid
    96                                                           * 1. the misspelled "-enable" long option to be treated as 'e' (for -enable) + 'n' (for -netname) + "<the_rest_opt>" (for net name)
    97                                                           * 2. the misspelled "-netmask" to be treated as 'n' (for -netname) + "<the_rest_opt>" (for net name)
    98                                                           */
    99     { "-netname",           't', RTGETOPT_REQ_STRING },     // deprecated (if removed check below)
    100     { "--ifname",           'f', RTGETOPT_REQ_STRING },  /* we use 'f' instead of 'i' to avoid
    101                                                           * 1. the misspelled "-disable" long option to be treated as 'd' (for -disable) + 'i' (for -ifname) + "<the_rest_opt>" (for if name)
    102                                                           */
    103     { "-ifname",            'f', RTGETOPT_REQ_STRING },     // deprecated
    104     { "--ip",               'a', RTGETOPT_REQ_STRING },
    105     { "-ip",                'a', RTGETOPT_REQ_STRING },     // deprecated
    106     { "--netmask",          'm', RTGETOPT_REQ_STRING },
    107     { "-netmask",           'm', RTGETOPT_REQ_STRING },     // deprecated
    108     { "--lowerip",          'l', RTGETOPT_REQ_STRING },
    109     { "-lowerip",           'l', RTGETOPT_REQ_STRING },     // deprecated
    110     { "--upperip",          'u', RTGETOPT_REQ_STRING },
    111     { "-upperip",           'u', RTGETOPT_REQ_STRING },     // deprecated
    112     { "--enable",           'e', RTGETOPT_REQ_NOTHING },
    113     { "-enable",            'e', RTGETOPT_REQ_NOTHING },    // deprecated
    114     { "--disable",          'd', RTGETOPT_REQ_NOTHING },
    115     { "-disable",           'd', RTGETOPT_REQ_NOTHING },     // deprecated
    116     { "--options",          'o', RTGETOPT_REQ_NOTHING },
    117     { "--vm",               'M', RTGETOPT_REQ_STRING}, /* only with -o */
    118     { "--nic",              'n', RTGETOPT_REQ_UINT8}, /* only with -o and -M */
    119     { "--id",               'i', RTGETOPT_REQ_UINT8}, /* only with -o */
    120     { "--value",            'p', RTGETOPT_REQ_STRING}, /* only with -i */
    121     { "--remove",           'r', RTGETOPT_REQ_NOTHING} /* only with -i */
    122 };
    123 
    124 static RTEXITCODE handleOp(HandlerArg *a, OPCODE enmCode, int iStart)
    125 {
    126     if (a->argc - iStart < 2)
    127         return errorSyntax(USAGE_DHCPSERVER, "Not enough parameters");
    128 
    129     int index = iStart;
    130     HRESULT rc;
    131     bool fOptionsRead = false;
    132     bool fVmOptionRead = false;
    133 
    134     const char *pszVmName = NULL;
    135     const char *pNetName = NULL;
    136     const char *pIfName = NULL;
    137     const char * pIp = NULL;
    138     const char * pNetmask = NULL;
    139     const char * pLowerIp = NULL;
    140     const char * pUpperIp = NULL;
    141 
    142     uint8_t u8OptId = (uint8_t)~0;
    143     uint8_t u8Slot = (uint8_t)~0;
    144 
    145     int enable = -1;
     162
     163/*********************************************************************************************************************************
     164*   Global Variables                                                                                                             *
     165*********************************************************************************************************************************/
     166
     167
     168
     169static RTEXITCODE dhcpdHandleTooManyCmds(PDHCPDCMDCTX pCtx, int argc, char **argv)
     170{
     171    // glue - start
     172    HandlerArg *a       = pCtx->pArg;
     173    OPCODE      enmCode = pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_ADD ? OP_ADD
     174                        : pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_MODIFY ? OP_MODIFY
     175                        : pCtx->pCmdDef->fSubcommandScope == HELP_SCOPE_DHCPSERVER_REMOVE ? OP_REMOVE : OP_RESTART;
     176    RT_NOREF(argc, argv);
     177    // glue - end
     178
     179    static const RTGETOPTDEF s_aDHCPIPOptions[] =
     180    {
     181        DHCPD_CMD_COMMON_OPTION_DEFS(),
     182        { "--ip",               'a', RTGETOPT_REQ_STRING  },
     183        { "-ip",                'a', RTGETOPT_REQ_STRING  },    // deprecated
     184        { "--netmask",          'm', RTGETOPT_REQ_STRING  },
     185        { "-netmask",           'm', RTGETOPT_REQ_STRING  },    // deprecated
     186        { "--lowerip",          'l', RTGETOPT_REQ_STRING  },
     187        { "-lowerip",           'l', RTGETOPT_REQ_STRING  },    // deprecated
     188        { "--upperip",          'u', RTGETOPT_REQ_STRING  },
     189        { "-upperip",           'u', RTGETOPT_REQ_STRING  },    // deprecated
     190        { "--enable",           'e', RTGETOPT_REQ_NOTHING },
     191        { "-enable",            'e', RTGETOPT_REQ_NOTHING },    // deprecated
     192        { "--disable",          'd', RTGETOPT_REQ_NOTHING },
     193        { "-disable",           'd', RTGETOPT_REQ_NOTHING },    // deprecated
     194        { "--global",           'g', RTGETOPT_REQ_NOTHING },
     195        { "--vm",               'M', RTGETOPT_REQ_STRING  },
     196        { "--nic",              'n', RTGETOPT_REQ_UINT8   },
     197        { "--add-opt",          'A', RTGETOPT_REQ_STRING  },
     198        { "--del-opt",          'D', RTGETOPT_REQ_STRING  },
     199        { "--id",               'i', RTGETOPT_REQ_UINT8   },    // obsolete, backwards compatibility only.
     200        { "--value",            'p', RTGETOPT_REQ_STRING  },    // obsolete, backwards compatibility only.
     201        { "--remove",           'r', RTGETOPT_REQ_NOTHING },    // obsolete, backwards compatibility only.
     202        { "--options",          'o', RTGETOPT_REQ_NOTHING },    // obsolete legacy, ignored
     203
     204    };
     205
     206    bool fNeedValueOrRemove = false; /* Only used with --id; remove in 6.1+ */
     207
     208    const char *pszDhcpdIp = NULL;
     209    const char *pszNetmask = NULL;
     210    const char *pszLowerIp = NULL;
     211    const char *pszUpperIp = NULL;
     212    int         fEnabled   = -1;
    146213
    147214    DhcpOpts          GlobalDhcpOptions;
     
    149216    VmSlot2OptionsM   VmSlot2Options;
    150217    VmSlot2OptionIdsM VmSlot2Options2Delete;
    151     VmConfigs         VmConfigs2Delete;
     218    /// @todo what was  this for: VmConfigs         VmConfigs2Delete;
     219
     220    const char       *pszVmName             = NULL;
     221    uint8_t           u8OptId               = 0;
     222    uint8_t           u8Slot                = 0;
     223    DhcpOpts         *pScopeOptions         = &GlobalDhcpOptions;
     224    DhcpOptIds       *pScopeOptions2Delete  = &GlobalDhcpOptions2Delete;
    152225
    153226    int c;
     
    157230                 a->argc,
    158231                 a->argv,
    159                  g_aDHCPIPOptions,
    160                  enmCode != OP_REMOVE ? RT_ELEMENTS(g_aDHCPIPOptions) : 4, /* we use only --netname and --ifname for remove*/
    161                  index,
    162                  RTGETOPTINIT_FLAGS_NO_STD_OPTS);
     232                 s_aDHCPIPOptions,
     233                 enmCode != OP_REMOVE ? RT_ELEMENTS(s_aDHCPIPOptions) : 4, /* we use only --netname and --ifname for remove*/
     234                 1,
     235                 0);
    163236    while ((c = RTGetOpt(&GetState, &ValueUnion)))
    164237    {
    165238        switch (c)
    166239        {
    167             case 't':   // --netname
    168                 if(pNetName)
    169                     return errorSyntax(USAGE_DHCPSERVER, "You can only specify --netname once.");
    170                 else if (pIfName)
    171                     return errorSyntax(USAGE_DHCPSERVER, "You can either use a --netname or --ifname for identifying the DHCP server.");
    172                 else
    173                 {
    174                     pNetName = ValueUnion.psz;
    175                 }
    176             break;
    177             case 'f':   // --ifname
    178                 if(pIfName)
    179                     return errorSyntax(USAGE_DHCPSERVER, "You can only specify --ifname once.");
    180                 else if (pNetName)
    181                     return errorSyntax(USAGE_DHCPSERVER, "You can either use a --netname or --ipname for identifying the DHCP server.");
    182                 else
    183                 {
    184                     pIfName = ValueUnion.psz;
    185                 }
    186             break;
     240            DHCPD_CMD_COMMON_OPTION_CASES(pCtx, c, &ValueUnion);
    187241            case 'a':   // -ip
    188                 if(pIp)
    189                     return errorSyntax(USAGE_DHCPSERVER, "You can only specify --ip once.");
    190                 else
    191                 {
    192                     pIp = ValueUnion.psz;
    193                 }
    194             break;
     242                pszDhcpdIp = ValueUnion.psz;
     243                break;
    195244            case 'm':   // --netmask
    196                 if(pNetmask)
    197                     return errorSyntax(USAGE_DHCPSERVER, "You can only specify --netmask once.");
    198                 else
    199                 {
    200                     pNetmask = ValueUnion.psz;
    201                 }
    202             break;
     245                pszNetmask = ValueUnion.psz;
     246                break;
    203247            case 'l':   // --lowerip
    204                 if(pLowerIp)
    205                     return errorSyntax(USAGE_DHCPSERVER, "You can only specify --lowerip once.");
    206                 else
    207                 {
    208                     pLowerIp = ValueUnion.psz;
    209                 }
    210             break;
     248                pszLowerIp = ValueUnion.psz;
     249                break;
    211250            case 'u':   // --upperip
    212                 if(pUpperIp)
    213                     return errorSyntax(USAGE_DHCPSERVER, "You can only specify --upperip once.");
    214                 else
    215                 {
    216                     pUpperIp = ValueUnion.psz;
    217                 }
    218             break;
     251                pszUpperIp = ValueUnion.psz;
     252                break;
    219253            case 'e':   // --enable
    220                 if(enable >= 0)
    221                     return errorSyntax(USAGE_DHCPSERVER, "You can specify either --enable or --disable once.");
    222                 else
    223                 {
    224                     enable = 1;
    225                 }
    226             break;
     254                fEnabled = 1;
     255                break;
    227256            case 'd':   // --disable
    228                 if(enable >= 0)
    229                     return errorSyntax(USAGE_DHCPSERVER, "You can specify either --enable or --disable once.");
    230                 else
    231                 {
    232                     enable = 0;
    233                 }
    234             break;
    235             case VINF_GETOPT_NOT_OPTION:
    236                 return errorSyntax(USAGE_DHCPSERVER, "unhandled parameter: %s", ValueUnion.psz);
    237             break;
    238 
    239             case 'o': // --options
    240                 {
    241         // {"--vm",                'n', RTGETOPT_REQ_STRING}, /* only with -o */
    242         // {"--nic",               'c', RTGETOPT_REQ_UINT8}, /* only with -o and -n*/
    243         // {"--id",                'i', RTGETOPT_REQ_UINT8}, /* only with -o */
    244         // {"--value",             'p', RTGETOPT_REQ_STRING} /* only with -i */
    245                     if (fOptionsRead)
    246                         return errorSyntax(USAGE_DHCPSERVER,
    247                                            "previos option edition  wasn't finished");
    248                     fOptionsRead = true;
    249                     fVmOptionRead = false; /* we want specify new global or vm option*/
    250                     u8Slot = (uint8_t)~0;
    251                     u8OptId = (uint8_t)~0;
    252                     pszVmName = NULL;
    253                 } /* end of --options  */
    254                 break;
    255 
    256             case 'M': // --vm
    257                 {
    258                     if (fVmOptionRead)
    259                         return errorSyntax(USAGE_DHCPSERVER,
    260                                            "previous vm option edition wasn't finished");
    261                     else
    262                         fVmOptionRead = true;
    263                     u8Slot = (uint8_t)~0; /* clear slot */
    264                     pszVmName = RTStrDup(ValueUnion.psz);
    265                 }
    266                 break; /* end of --vm */
    267 
    268             case 'n': // --nic
    269                 {
    270                     if (!fVmOptionRead)
    271                         return errorSyntax(USAGE_DHCPSERVER,
    272                                            "vm name wasn't specified");
    273 
    274                     u8Slot = ValueUnion.u8;
    275 
    276                     if (u8Slot < 1)
    277                         return errorSyntax(USAGE_DHCPSERVER,
    278                                            "invalid NIC number: %u", u8Slot);
    279                     --u8Slot;
    280                 }
    281                 break; /* end of --nic */
    282 
    283             case 'i': // --id
    284                 {
    285                     if (!fOptionsRead)
    286                         return errorSyntax(USAGE_DHCPSERVER,
    287                                            "-o wasn't found");
    288 
    289                     u8OptId = ValueUnion.u8;
    290                 }
    291                 break; /* end of --id */
    292 
    293             case 'p': // --value
    294                 {
    295                     if (!fOptionsRead)
    296                         return errorSyntax(USAGE_DHCPSERVER,
    297                                            "-o wasn't found");
    298 
    299                     if (u8OptId == (uint8_t)~0)
    300                         return errorSyntax(USAGE_DHCPSERVER,
    301                                            "--id wasn't found");
    302                     if (   fVmOptionRead
    303                         && u8Slot == (uint8_t)~0)
    304                         return errorSyntax(USAGE_DHCPSERVER,
    305                                            "--nic wasn't found");
    306 
    307                     DhcpOpts &opts = fVmOptionRead ? VmSlot2Options[VmNameSlotKey(pszVmName, u8Slot)]
    308                                                     : GlobalDhcpOptions;
    309                     std::string strVal = ValueUnion.psz;
    310                     opts.push_back(DhcpOptSpec((DhcpOpt_T)u8OptId, strVal));
    311 
    312                 }
    313                 break; // --end of value
    314 
    315             case 'r': /* --remove */
    316                 {
    317                     if (!fOptionsRead)
    318                         return errorSyntax(USAGE_DHCPSERVER,
    319                                            "-o wasn't found");
    320 
    321                     if (u8OptId == (uint8_t)~0)
    322                         return errorSyntax(USAGE_DHCPSERVER,
    323                                            "--id wasn't found");
    324                     if (   fVmOptionRead
    325                         && u8Slot == (uint8_t)~0)
    326                         return errorSyntax(USAGE_DHCPSERVER,
    327                                            "--nic wasn't found");
    328 
    329                     DhcpOptIds &optIds = fVmOptionRead ? VmSlot2Options2Delete[VmNameSlotKey(pszVmName, u8Slot)]
    330                                                        : GlobalDhcpOptions2Delete;
    331                     optIds.push_back((DhcpOpt_T)u8OptId);
    332                 }
    333                 break; /* --end of remove */
     257                fEnabled = 0;
     258                break;
     259
     260            case 'g':   // --global     Sets the option scope to 'global'.
     261                if (fNeedValueOrRemove)
     262                    return errorSyntax("Incomplete option sequence preseeding '--global'");
     263                pScopeOptions         = &GlobalDhcpOptions;
     264                pScopeOptions2Delete  = &GlobalDhcpOptions2Delete;
     265                break;
     266
     267            case 'M':   // --vm         Sets the option scope to ValueUnion.psz + 0.
     268                if (fNeedValueOrRemove)
     269                    return errorSyntax("Incomplete option sequence preseeding '--vm'");
     270                pszVmName = ValueUnion.psz;
     271                u8Slot    = 0;
     272                pScopeOptions        = &VmSlot2Options[VmNameSlotKey(pszVmName, u8Slot)];
     273                pScopeOptions2Delete = &VmSlot2Options2Delete[VmNameSlotKey(pszVmName, u8Slot)];
     274                break;
     275
     276            case 'n':   // --nic        Sets the option scope to pszVmName + (ValueUnion.u8 - 1).
     277                if (!pszVmName)
     278                    return errorSyntax("--nic option requires a --vm preceeding selecting the VM it should apply to");
     279                if (fNeedValueOrRemove)
     280                    return errorSyntax("Incomplete option sequence preseeding '--nic=%u", ValueUnion.u8);
     281                u8Slot = ValueUnion.u8;
     282                if (u8Slot < 1)
     283                    return errorSyntax("invalid NIC number: %u", u8Slot);
     284                --u8Slot;
     285                pScopeOptions        = &VmSlot2Options[VmNameSlotKey(pszVmName, u8Slot)];
     286                pScopeOptions2Delete = &VmSlot2Options2Delete[VmNameSlotKey(pszVmName, u8Slot)];
     287                break;
     288
     289            case 'A':   // --add-opt num hexvalue
     290            {
     291                uint8_t const idAddOpt = ValueUnion.u8;
     292                c = RTGetOptFetchValue(&GetState, &ValueUnion, RTGETOPT_REQ_STRING);
     293                if (RT_FAILURE(c))
     294                    return errorFetchValue(1, "--add-opt", c, &ValueUnion);
     295                pScopeOptions->push_back(DhcpOptSpec((DhcpOpt_T)idAddOpt, std::string(ValueUnion.psz)));
     296                break;
     297            }
     298
     299            case 'D':   // --del-opt num
     300                if (enmCode == OP_ADD)
     301                    return errorSyntax("--del-opt does not apply to the 'add' subcommand");
     302                pScopeOptions2Delete->push_back((DhcpOpt_T)ValueUnion.u8);
     303                break;
     304
     305            /*
     306             * For backwards compatibility. Remove in 6.1 or later.
     307             */
     308
     309            case 'o':   // --options - obsolete, ignored.
     310                break;
     311
     312            case 'i':   // --id
     313                if (fNeedValueOrRemove)
     314                    return errorSyntax("Incomplete option sequence preseeding '--id=%u", ValueUnion.u8);
     315                u8OptId = ValueUnion.u8;
     316                fNeedValueOrRemove = true;
     317                break;
     318
     319            case 'p':   // --value
     320                if (!fNeedValueOrRemove)
     321                    return errorSyntax("--value without --id=dhcp-opt-no");
     322                pScopeOptions->push_back(DhcpOptSpec((DhcpOpt_T)u8OptId, std::string(ValueUnion.psz)));
     323                fNeedValueOrRemove = false;
     324                break;
     325
     326            case 'r':   // --remove
     327                if (enmCode == OP_ADD)
     328                    return errorSyntax("--remove does not apply to the 'add' subcommand");
     329                if (!fNeedValueOrRemove)
     330                    return errorSyntax("--remove without --id=dhcp-opt-no");
     331                pScopeOptions2Delete->push_back((DhcpOpt_T)u8OptId);
     332                /** @todo remove from pScopeOptions */
     333                fNeedValueOrRemove = false;
     334                break;
    334335
    335336            default:
    336                 if (c > 0)
    337                 {
    338                     if (RT_C_IS_GRAPH(c))
    339                         return errorSyntax(USAGE_DHCPSERVER, "unhandled option: -%c", c);
    340                     return errorSyntax(USAGE_DHCPSERVER, "unhandled option: %i", c);
    341                 }
    342                 if (c == VERR_GETOPT_UNKNOWN_OPTION)
    343                     return errorSyntax(USAGE_DHCPSERVER, "unknown option: %s", ValueUnion.psz);
    344                 if (ValueUnion.pDef)
    345                     return errorSyntax(USAGE_DHCPSERVER, "%s: %Rrs", ValueUnion.pDef->pszLong, c);
    346                 return errorSyntax(USAGE_DHCPSERVER, "%Rrs", c);
     337                return errorGetOpt(c, &ValueUnion);
    347338        }
    348339    }
    349340
    350     if(! pNetName && !pIfName)
    351         return errorSyntax(USAGE_DHCPSERVER, "You need to specify either --netname or --ifname to identify the DHCP server");
    352 
    353     if(   enmCode != OP_REMOVE
    354        && enmCode != OP_RESTART
    355        && GlobalDhcpOptions.empty()
    356        && VmSlot2Options.empty()
    357        && GlobalDhcpOptions2Delete.empty()
    358        && VmSlot2Options2Delete.empty())
    359     {
    360         if(enable < 0 || pIp || pNetmask || pLowerIp || pUpperIp)
     341    if (!pCtx->pszNetwork && !pCtx->pszInterface)
     342        return errorSyntax("You need to specify either --network or --interface to identify the DHCP server");
     343
     344    if (   enmCode != OP_REMOVE
     345        && enmCode != OP_RESTART
     346        && GlobalDhcpOptions.empty()
     347        && VmSlot2Options.empty()
     348        && GlobalDhcpOptions2Delete.empty()
     349        && VmSlot2Options2Delete.empty())
     350    {
     351        /** @todo For the 'modify' subcmd, missing configuration parameters could be
     352         * retrieved from the current config.  All are only required for 'add'!
     353         * The 'fEnabled' attribute does not come into play here.  */
     354        if (fEnabled < 0 || pszDhcpdIp || pszNetmask || pszLowerIp || pszUpperIp)
    361355        {
    362             if(!pIp)
    363                 return errorSyntax(USAGE_DHCPSERVER, "You need to specify --ip option");
    364 
    365             if(!pNetmask)
    366                 return errorSyntax(USAGE_DHCPSERVER, "You need to specify --netmask option");
    367 
    368             if(!pLowerIp)
    369                 return errorSyntax(USAGE_DHCPSERVER, "You need to specify --lowerip option");
    370 
    371             if(!pUpperIp)
    372                 return errorSyntax(USAGE_DHCPSERVER, "You need to specify --upperip option");
     356            RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
     357            if (!pszDhcpdIp)
     358                rcExit = errorSyntax("Missing required option: --ip");
     359            if (!pszNetmask)
     360                rcExit = errorSyntax("Missing required option: --netmask");
     361            if (!pszLowerIp)
     362                rcExit = errorSyntax("Missing required option: --lowerip");
     363            if (!pszUpperIp)
     364                rcExit = errorSyntax("Missing required option: --upperip");
     365            if (rcExit != RTEXITCODE_SUCCESS)
     366                return rcExit;
    373367        }
    374368    }
    375369
     370    HRESULT rc;
    376371    Bstr NetName;
    377     if(!pNetName)
     372    if (!pCtx->pszNetwork)
    378373    {
    379374        ComPtr<IHost> host;
     
    381376
    382377        ComPtr<IHostNetworkInterface> hif;
    383         CHECK_ERROR(host, FindHostNetworkInterfaceByName(Bstr(pIfName).mutableRaw(), hif.asOutParam()));
     378        CHECK_ERROR(host, FindHostNetworkInterfaceByName(Bstr(pCtx->pszInterface).mutableRaw(), hif.asOutParam()));
    384379        if (FAILED(rc))
    385             return errorArgument("Could not find interface '%s'", pIfName);
     380            return errorArgument("Could not find interface '%s'", pCtx->pszInterface);
    386381
    387382        CHECK_ERROR(hif, COMGETTER(NetworkName) (NetName.asOutParam()));
    388383        if (FAILED(rc))
    389             return errorArgument("Could not get network name for the interface '%s'", pIfName);
     384            return errorArgument("Could not get network name for the interface '%s'", pCtx->pszInterface);
    390385    }
    391386    else
    392387    {
    393         NetName = Bstr(pNetName);
     388        NetName = Bstr(pCtx->pszNetwork);
    394389    }
    395390
     
    424419    else
    425420    {
    426         if (pIp || pNetmask || pLowerIp || pUpperIp)
     421        if (pszDhcpdIp || pszNetmask || pszLowerIp || pszUpperIp)
    427422        {
    428             CHECK_ERROR(svr, SetConfiguration (
    429                           Bstr(pIp).mutableRaw(),
    430                           Bstr(pNetmask).mutableRaw(),
    431                           Bstr(pLowerIp).mutableRaw(),
    432                           Bstr(pUpperIp).mutableRaw()));
    433             if(FAILED(rc))
     423            CHECK_ERROR(svr, SetConfiguration(Bstr(pszDhcpdIp).mutableRaw(),
     424                                              Bstr(pszNetmask).mutableRaw(),
     425                                              Bstr(pszLowerIp).mutableRaw(),
     426                                              Bstr(pszUpperIp).mutableRaw()));
     427            if (FAILED(rc))
    434428                return errorArgument("Failed to set configuration");
    435429        }
    436430
    437         if(enable >= 0)
    438         {
    439             CHECK_ERROR(svr, COMSETTER(Enabled) ((BOOL)enable));
    440         }
    441 
    442         /* remove specified options */
    443         DhcpOptIdIterator itOptId;
    444         for (itOptId = GlobalDhcpOptions2Delete.begin();
    445              itOptId != GlobalDhcpOptions2Delete.end();
    446              ++itOptId)
    447         {
     431        if (fEnabled >= 0)
     432            CHECK_ERROR(svr, COMSETTER(Enabled)((BOOL)fEnabled));
     433
     434        /* Remove options: */
     435        for (DhcpOptIdIterator itOptId = GlobalDhcpOptions2Delete.begin(); itOptId != GlobalDhcpOptions2Delete.end(); ++itOptId)
    448436            CHECK_ERROR(svr, RemoveGlobalOption(*itOptId));
    449         }
    450         VmSlot2OptionIdsIterator itIdVector;
    451         for (itIdVector = VmSlot2Options2Delete.begin();
    452              itIdVector != VmSlot2Options2Delete.end();
    453              ++itIdVector)
    454         {
    455             for(itOptId = itIdVector->second.begin();
    456                 itOptId != itIdVector->second.end();
    457                 ++itOptId)
    458             {
    459                 CHECK_ERROR(svr,
    460                             RemoveVmSlotOption(Bstr(itIdVector->first.VmName.c_str()).raw(),
    461                                                itIdVector->first.u8Slot,
    462                                                *itOptId));
    463             }
    464         }
    465 
    466         /* option processing */
    467         DhcpOptIterator itOpt;
    468         VmSlot2OptionsIterator it;
     437
     438        for (VmSlot2OptionIdsIterator itIdVector = VmSlot2Options2Delete.begin();
     439             itIdVector != VmSlot2Options2Delete.end(); ++itIdVector)
     440            for (DhcpOptIdIterator itOptId = itIdVector->second.begin(); itOptId != itIdVector->second.end(); ++itOptId)
     441                CHECK_ERROR(svr, RemoveVmSlotOption(Bstr(itIdVector->first.VmName.c_str()).raw(),
     442                                                    itIdVector->first.u8Slot, *itOptId));
    469443
    470444        /* Global Options */
    471         for(itOpt = GlobalDhcpOptions.begin();
    472             itOpt != GlobalDhcpOptions.end();
    473             ++itOpt)
    474         {
    475             CHECK_ERROR(svr,
    476                         AddGlobalOption(
    477                           itOpt->first,
    478                           com::Bstr(itOpt->second.c_str()).raw()));
    479         }
    480 
    481         /* heh, vm slot options. */
    482 
    483         for (it = VmSlot2Options.begin();
    484              it != VmSlot2Options.end();
    485              ++it)
    486         {
    487             for(itOpt = it->second.begin();
    488                 itOpt != it->second.end();
    489                 ++itOpt)
    490             {
    491                 CHECK_ERROR(svr,
    492                             AddVmSlotOption(Bstr(it->first.VmName.c_str()).raw(),
    493                                             it->first.u8Slot,
    494                                             itOpt->first,
    495                                             com::Bstr(itOpt->second.c_str()).raw()));
    496             }
    497         }
     445        for (DhcpOptIterator itOpt = GlobalDhcpOptions.begin(); itOpt != GlobalDhcpOptions.end(); ++itOpt)
     446            CHECK_ERROR(svr, AddGlobalOption(itOpt->first, com::Bstr(itOpt->second.c_str()).raw()));
     447
     448        /* VM slot options. */
     449        for (VmSlot2OptionsIterator it = VmSlot2Options.begin(); it != VmSlot2Options.end(); ++it)
     450            for (DhcpOptIterator itOpt = it->second.begin(); itOpt != it->second.end(); ++itOpt)
     451                CHECK_ERROR(svr, AddVmSlotOption(Bstr(it->first.VmName.c_str()).raw(), it->first.u8Slot, itOpt->first,
     452                                                 com::Bstr(itOpt->second.c_str()).raw()));
    498453    }
    499454
     
    502457
    503458
    504 RTEXITCODE handleDHCPServer(HandlerArg *a)
    505 {
    506     if (a->argc < 1)
    507         return errorSyntax(USAGE_DHCPSERVER, "Not enough parameters");
    508 
    509     RTEXITCODE rcExit;
    510     if (strcmp(a->argv[0], "modify") == 0)
    511         rcExit = handleOp(a, OP_MODIFY, 1);
    512     else if (strcmp(a->argv[0], "add") == 0)
    513         rcExit = handleOp(a, OP_ADD, 1);
    514     else if (strcmp(a->argv[0], "remove") == 0)
    515         rcExit = handleOp(a, OP_REMOVE, 1);
    516     else if (strcmp(a->argv[0], "restart") == 0)
    517         rcExit = handleOp(a, OP_RESTART, 1);
     459/**
     460 * Helper that find the DHCP server instance.
     461 *
     462 * @returns The DHCP server instance. NULL if failed (complaining done).
     463 * @param   pCtx                The DHCP server command context.
     464 */
     465static ComPtr<IDHCPServer> dhcpdFindServer(PDHCPDCMDCTX pCtx)
     466{
     467    ComPtr<IDHCPServer> ptrRet;
     468    if (pCtx->pszNetwork || pCtx->pszInterface)
     469    {
     470        Assert(pCtx->pszNetwork == NULL || pCtx->pszInterface == NULL);
     471
     472        /*
     473         * We need a network name to find the DHCP server.  So, if interface is
     474         * given we have to look it up.
     475         */
     476        HRESULT hrc;
     477        Bstr bstrNetName(pCtx->pszNetwork);
     478        if (!pCtx->pszNetwork)
     479        {
     480            ComPtr<IHost> ptrIHost;
     481            CHECK_ERROR2_RET(hrc, pCtx->pArg->virtualBox, COMGETTER(Host)(ptrIHost.asOutParam()), ptrRet);
     482
     483            Bstr bstrInterface(pCtx->pszInterface);
     484            ComPtr<IHostNetworkInterface> ptrIHostIf;
     485            CHECK_ERROR2(hrc, ptrIHost, FindHostNetworkInterfaceByName(bstrInterface.raw(), ptrIHostIf.asOutParam()));
     486            if (FAILED(hrc))
     487            {
     488                errorArgument("Failed to locate host-only interface '%s'", pCtx->pszInterface);
     489                return ptrRet;
     490            }
     491
     492            CHECK_ERROR2_RET(hrc, ptrIHostIf, COMGETTER(NetworkName)(bstrNetName.asOutParam()), ptrRet);
     493        }
     494
     495        /*
     496         * Now, try locate the server
     497         */
     498        hrc = pCtx->pArg->virtualBox->FindDHCPServerByNetworkName(bstrNetName.raw(), ptrRet.asOutParam());
     499        if (SUCCEEDED(hrc))
     500            return ptrRet;
     501        if (pCtx->pszNetwork)
     502            errorArgument("Failed to find DHCP server for network '%s'", pCtx->pszNetwork);
     503        else
     504            errorArgument("Failed to find DHCP server for host-only interface '%s' (network '%ls')",
     505                          pCtx->pszInterface, bstrNetName.raw());
     506    }
    518507    else
    519         rcExit = errorSyntax(USAGE_DHCPSERVER, "Invalid parameter '%s'", Utf8Str(a->argv[0]).c_str());
    520 
    521     return rcExit;
     508        errorSyntax("You need to specify either --network or --interface to identify the DHCP server");
     509    return ptrRet;
    522510}
    523511
    524 #endif /* !VBOX_ONLY_DOCS */
    525 
     512
     513static RTEXITCODE dhcpdHandleFindLease(PDHCPDCMDCTX pCtx, int argc, char **argv)
     514{
     515    /*
     516     * Parse the command line.
     517     */
     518    static const RTGETOPTDEF s_aOptions[] =
     519    {
     520        DHCPD_CMD_COMMON_OPTION_DEFS(),
     521        { "--mac-address",      'm', RTGETOPT_REQ_MACADDR  },
     522
     523    };
     524
     525    bool            fHaveMacAddress   = false;
     526    RTMAC           MacAddress        = { 0, 0, 0, 0, 0, 0 };
     527
     528    RTGETOPTSTATE   GetState;
     529    int vrc = RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
     530    AssertRCReturn(vrc, RTEXITCODE_FAILURE);
     531
     532    RTGETOPTUNION   ValueUnion;
     533    while ((vrc = RTGetOpt(&GetState, &ValueUnion)))
     534    {
     535        switch (vrc)
     536        {
     537            DHCPD_CMD_COMMON_OPTION_CASES(pCtx, vrc, &ValueUnion);
     538
     539            case 'm':   // --mac-address
     540                fHaveMacAddress = true;
     541                MacAddress = ValueUnion.MacAddr;
     542                break;
     543
     544            default:
     545                return errorGetOpt(vrc, &ValueUnion);
     546        }
     547    }
     548
     549    if (!fHaveMacAddress)
     550        return errorSyntax("You need to specify a MAC address too look for");
     551
     552    /*
     553     * Locate the server and perform the requested operation.
     554     */
     555    ComPtr<IDHCPServer> ptrDHCPServer = dhcpdFindServer(pCtx);
     556    if (ptrDHCPServer.isNull())
     557        return RTEXITCODE_FAILURE;
     558
     559    char    szMac[32];
     560    RTStrPrintf(szMac, sizeof(szMac), "%RTmac", &MacAddress);
     561    Bstr    bstrAddress;
     562    Bstr    bstrState;
     563    LONG64  secIssued = 0;
     564    LONG64  secExpire = 0;
     565    HRESULT hrc;
     566    CHECK_ERROR2(hrc, ptrDHCPServer, FindLeaseByMAC(Bstr(szMac).raw(), 0 /*type*/,
     567                                                    bstrAddress.asOutParam(), bstrState.asOutParam(), &secIssued, &secExpire));
     568    if (SUCCEEDED(hrc))
     569    {
     570        RTTIMESPEC  TimeSpec;
     571        int64_t     cSecLeftToLive = secExpire - RTTimeSpecGetSeconds(RTTimeNow(&TimeSpec));
     572        RTTIME      Time;
     573        char        szIssued[RTTIME_STR_LEN];
     574        RTTimeToStringEx(RTTimeExplode(&Time, RTTimeSpecSetSeconds(&TimeSpec, secIssued)), szIssued, sizeof(szIssued), 0);
     575        char        szExpire[RTTIME_STR_LEN];
     576        RTTimeToStringEx(RTTimeExplode(&Time, RTTimeSpecSetSeconds(&TimeSpec, secExpire)), szExpire, sizeof(szExpire), 0);
     577
     578        RTPrintf("IP Address:  %ls\n"
     579                 "MAC Address: %RTmac\n"
     580                 "State:       %ls\n"
     581                 "Issued:      %s (%RU64)\n"
     582                 "Expire:      %s (%RU64)\n"
     583                 "TTL:         %RU64 sec, currently %RU64 sec left\n",
     584                 bstrAddress.raw(),
     585                 &MacAddress,
     586                 bstrState.raw(),
     587                 szIssued, secIssued,
     588                 szExpire, secExpire,
     589                 secExpire >= secIssued ? secExpire - secIssued : 0, cSecLeftToLive > 0  ? cSecLeftToLive : 0);
     590        return RTEXITCODE_SUCCESS;
     591    }
     592    return RTEXITCODE_FAILURE;
     593}
     594
     595
     596RTEXITCODE handleDHCPServer(HandlerArg *pArg)
     597{
     598    /*
     599     * Command definitions.
     600     */
     601    static const DHCPDCMDDEF s_aCmdDefs[] =
     602    {
     603        { "add",            dhcpdHandleTooManyCmds,     HELP_SCOPE_DHCPSERVER_ADD },
     604        { "modify",         dhcpdHandleTooManyCmds,     HELP_SCOPE_DHCPSERVER_MODIFY },
     605        { "remove",         dhcpdHandleTooManyCmds,     HELP_SCOPE_DHCPSERVER_REMOVE },
     606        { "restart",        dhcpdHandleTooManyCmds,     HELP_SCOPE_DHCPSERVER_RESTART },
     607        { "findlease",      dhcpdHandleFindLease,       HELP_SCOPE_DHCPSERVER_FINDLEASE },
     608    };
     609
     610    /*
     611     * VBoxManage dhcpserver [common-options] subcommand ...
     612     */
     613    DHCPDCMDCTX CmdCtx;
     614    CmdCtx.pArg         = pArg;
     615    CmdCtx.pCmdDef      = NULL;
     616    CmdCtx.pszInterface = NULL;
     617    CmdCtx.pszNetwork   = NULL;
     618
     619    static const RTGETOPTDEF s_CommonOptions[] = { DHCPD_CMD_COMMON_OPTION_DEFS() };
     620
     621    int ch;
     622    RTGETOPTUNION ValueUnion;
     623    RTGETOPTSTATE GetState;
     624    RTGetOptInit(&GetState, pArg->argc, pArg->argv, s_CommonOptions, RT_ELEMENTS(s_CommonOptions), 0, 0 /* No sorting! */);
     625
     626    while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0)
     627    {
     628        switch (ch)
     629        {
     630            DHCPD_CMD_COMMON_OPTION_CASES(&CmdCtx, ch, &ValueUnion);
     631
     632            case VINF_GETOPT_NOT_OPTION:
     633            {
     634                const char *pszCmd = ValueUnion.psz;
     635                uint32_t    iCmd;
     636                for (iCmd = 0; iCmd < RT_ELEMENTS(s_aCmdDefs); iCmd++)
     637                    if (strcmp(s_aCmdDefs[iCmd].pszName, pszCmd) == 0)
     638                    {
     639                        CmdCtx.pCmdDef = &s_aCmdDefs[iCmd];
     640                        setCurrentSubcommand(s_aCmdDefs[iCmd].fSubcommandScope);
     641                        return s_aCmdDefs[iCmd].pfnHandler(&CmdCtx, pArg->argc - GetState.iNext + 1,
     642                                                           &pArg->argv[GetState.iNext - 1]);
     643                    }
     644                return errorUnknownSubcommand(pszCmd);
     645            }
     646
     647            default:
     648                return errorGetOpt(ch, &ValueUnion);
     649        }
     650    }
     651    return errorNoSubcommand();
     652}
     653
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp

    r78632 r79611  
    297297    else
    298298        RTMsgError("%Rrs", rcGetOpt);
     299}
     300
     301
     302/**
     303 * For use to deal with RTGetOptFetchValue failures.
     304 *
     305 * @retval  RTEXITCODE_SYNTAX
     306 * @param   iValueNo            The value number being fetched, counting the
     307 *                              RTGetOpt value as zero and the first
     308 *                              RTGetOptFetchValue call as one.
     309 * @param   pszOption           The option being parsed.
     310 * @param   rcGetOptFetchValue  The status returned by RTGetOptFetchValue.
     311 * @param   pValueUnion         The value union returned by the fetch.
     312 */
     313RTEXITCODE errorFetchValue(int iValueNo, const char *pszOption, int rcGetOptFetchValue, union RTGETOPTUNION const *pValueUnion)
     314{
     315    Assert(g_enmCurCommand != HELP_CMD_VBOXMANAGE_INVALID);
     316    showLogo(g_pStdErr);
     317    if (rcGetOptFetchValue == VERR_GETOPT_REQUIRED_ARGUMENT_MISSING)
     318        RTMsgError("Missing the %u%s value for option %s",
     319                   iValueNo, iValueNo == 1 ? "st" : iValueNo == 2 ? "nd" : iValueNo == 3 ? "rd" : "th",  pszOption);
     320    else
     321        errorGetOptWorker(rcGetOptFetchValue, pValueUnion);
     322    return RTEXITCODE_SYNTAX;
     323
    299324}
    300325
     
    12011226#endif
    12021227
    1203     if (enmCommand == USAGE_DHCPSERVER || enmCommand == USAGE_S_ALL)
    1204     {
    1205         RTStrmPrintf(pStrm,
    1206                            "%s dhcpserver %s      add|modify --netname <network_name> |\n"
    1207 #if defined(VBOX_WITH_NETFLT)
    1208                      "                                       --ifname <hostonly_if_name>\n"
    1209 #endif
    1210                      "                            [--ip <ip_address>\n"
    1211                      "                            --netmask <network_mask>\n"
    1212                      "                            --lowerip <lower_ip>\n"
    1213                      "                            --upperip <upper_ip>]\n"
    1214                      "                            [--enable | --disable]\n"
    1215                      "                            [--options [--vm <name> --nic <1-N>]\n"
    1216                      "                             --id <number> [--value <string> | --remove]]\n"
    1217                      "                             (multiple options allowed after --options)\n\n"
    1218                            "%s dhcpserver %s      remove --netname <network_name> |\n"
    1219 #if defined(VBOX_WITH_NETFLT)
    1220                      "                                   --ifname <hostonly_if_name>\n"
    1221 #endif
    1222                      "\n", SEP, SEP);
    1223     }
    1224 
    12251228    if (enmCommand == USAGE_USBDEVSOURCE || enmCommand == USAGE_S_ALL)
    12261229    {
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette