VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageHostonly.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.3 KB
RevLine 
[17488]1/* $Id: VBoxManageHostonly.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * VBoxManage - Implementation of hostonlyif command.
4 */
5
6/*
[98103]7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
[17488]8 *
[96407]9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
[17488]26 */
27
[57358]28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
[17488]32#include <VBox/com/com.h>
33#include <VBox/com/array.h>
34#include <VBox/com/ErrorInfo.h>
[20928]35#include <VBox/com/errorprint.h>
[17488]36#include <VBox/com/VirtualBox.h>
37
38#include <iprt/cidr.h>
39#include <iprt/param.h>
40#include <iprt/path.h>
41#include <iprt/stream.h>
42#include <iprt/string.h>
43#include <iprt/net.h>
44#include <iprt/getopt.h>
[18108]45#include <iprt/ctype.h>
[17488]46
47#include <VBox/log.h>
48
49#include "VBoxManage.h"
50
[92372]51DECLARE_TRANSLATION_CONTEXT(HostOnly);
52
[94234]53
[17488]54using namespace com;
55
[65827]56static const RTGETOPTDEF g_aHostOnlyCreateOptions[] =
57{
58 { "--machinereadable", 'M', RTGETOPT_REQ_NOTHING },
59};
60
[35317]61#if defined(VBOX_WITH_NETFLT) && !defined(RT_OS_SOLARIS)
[56118]62static RTEXITCODE handleCreate(HandlerArg *a)
[17488]63{
[56118]64 /*
65 * Parse input.
66 */
[65827]67 bool fMachineReadable = false;
[56118]68 RTGETOPTUNION ValueUnion;
69 RTGETOPTSTATE GetState;
[65827]70 RTGetOptInit(&GetState, a->argc, a->argv, g_aHostOnlyCreateOptions,
71 RT_ELEMENTS(g_aHostOnlyCreateOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
72 int c;
73 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
74 {
75 switch (c)
76 {
77 case 'M': // --machinereadable
78 fMachineReadable = true;
79 break;
[17488]80
[65827]81 default:
[94212]82 return errorGetOpt(c, &ValueUnion);
[65827]83 }
84 }
85
[56118]86 /*
87 * Do the work.
88 */
[17488]89 ComPtr<IHost> host;
[56118]90 CHECK_ERROR2I_RET(a->virtualBox, COMGETTER(Host)(host.asOutParam()), RTEXITCODE_FAILURE);
[17488]91
92 ComPtr<IHostNetworkInterface> hif;
93 ComPtr<IProgress> progress;
94
[56118]95 CHECK_ERROR2I_RET(host, CreateHostOnlyNetworkInterface(hif.asOutParam(), progress.asOutParam()), RTEXITCODE_FAILURE);
[17488]96
[65827]97 if (fMachineReadable)
98 {
[79507]99 progress->WaitForCompletion(10000); /* Ten seconds should probably be enough. */
[65827]100 CHECK_PROGRESS_ERROR_RET(progress, (""), RTEXITCODE_FAILURE);
101 }
102 else
103 {
104 /*HRESULT hrc =*/ showProgress(progress);
[92372]105 CHECK_PROGRESS_ERROR_RET(progress, (HostOnly::tr("Failed to create the host-only adapter")), RTEXITCODE_FAILURE);
[65827]106 }
[17488]107
[56118]108 Bstr bstrName;
109 CHECK_ERROR2I(hif, COMGETTER(Name)(bstrName.asOutParam()));
[17679]110
[65827]111 if (fMachineReadable)
112 RTPrintf("%ls", bstrName.raw());
113 else
[92372]114 RTPrintf(HostOnly::tr("Interface '%ls' was successfully created\n"), bstrName.raw());
[56118]115 return RTEXITCODE_SUCCESS;
[17488]116}
117
[56118]118static RTEXITCODE handleRemove(HandlerArg *a)
[17488]119{
[56118]120 /*
121 * Parse input.
122 */
123 const char *pszName = NULL;
124 int ch;
125 RTGETOPTUNION ValueUnion;
126 RTGETOPTSTATE GetState;
127 RTGetOptInit(&GetState, a->argc, a->argv, NULL, 0, 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
128 while ((ch = RTGetOpt(&GetState, &ValueUnion)) != 0)
129 switch (ch)
130 {
131 case VINF_GETOPT_NOT_OPTION:
132 if (pszName)
[94212]133 return errorSyntax(HostOnly::tr("Only one interface name can be specified"));
[56118]134 pszName = ValueUnion.psz;
135 break;
[17488]136
[56118]137 default:
[94212]138 return errorGetOpt(ch, &ValueUnion);
[56118]139 }
140 if (!pszName)
[94212]141 return errorSyntax(HostOnly::tr("No interface name was specified"));
[17488]142
[56118]143 /*
144 * Do the work.
145 */
[17488]146 ComPtr<IHost> host;
[56118]147 CHECK_ERROR2I_RET(a->virtualBox, COMGETTER(Host)(host.asOutParam()), RTEXITCODE_FAILURE);
[17488]148
149 ComPtr<IHostNetworkInterface> hif;
[56118]150 CHECK_ERROR2I_RET(host, FindHostNetworkInterfaceByName(Bstr(pszName).raw(), hif.asOutParam()), RTEXITCODE_FAILURE);
[17488]151
[19239]152 Bstr guid;
[56118]153 CHECK_ERROR2I_RET(hif, COMGETTER(Id)(guid.asOutParam()), RTEXITCODE_FAILURE);
[17488]154
155 ComPtr<IProgress> progress;
[56118]156 CHECK_ERROR2I_RET(host, RemoveHostOnlyNetworkInterface(guid.raw(), progress.asOutParam()), RTEXITCODE_FAILURE);
[17488]157
[63300]158 /*HRESULT hrc =*/ showProgress(progress);
[92372]159 CHECK_PROGRESS_ERROR_RET(progress, (HostOnly::tr("Failed to remove the host-only adapter")), RTEXITCODE_FAILURE);
[17488]160
[56118]161 return RTEXITCODE_SUCCESS;
[17488]162}
163#endif
164
[18108]165static const RTGETOPTDEF g_aHostOnlyIPOptions[]
[17488]166 = {
[18108]167 { "--dhcp", 'd', RTGETOPT_REQ_NOTHING },
168 { "-dhcp", 'd', RTGETOPT_REQ_NOTHING }, // deprecated
169 { "--ip", 'a', RTGETOPT_REQ_STRING },
170 { "-ip", 'a', RTGETOPT_REQ_STRING }, // deprecated
171 { "--netmask", 'm', RTGETOPT_REQ_STRING },
172 { "-netmask", 'm', RTGETOPT_REQ_STRING }, // deprecated
173 { "--ipv6", 'b', RTGETOPT_REQ_STRING },
174 { "-ipv6", 'b', RTGETOPT_REQ_STRING }, // deprecated
175 { "--netmasklengthv6", 'l', RTGETOPT_REQ_UINT8 },
176 { "-netmasklengthv6", 'l', RTGETOPT_REQ_UINT8 } // deprecated
[17488]177 };
178
[56118]179static RTEXITCODE handleIpConfig(HandlerArg *a)
[17488]180{
[56118]181 bool fDhcp = false;
182 bool fNetmasklengthv6 = false;
183 uint32_t uNetmasklengthv6 = UINT32_MAX;
184 const char *pszIpv6 = NULL;
185 const char *pszIp = NULL;
186 const char *pszNetmask = NULL;
187 const char *pszName = NULL;
[17488]188
189 int c;
190 RTGETOPTUNION ValueUnion;
191 RTGETOPTSTATE GetState;
[56118]192 RTGetOptInit(&GetState, a->argc, a->argv, g_aHostOnlyIPOptions, RT_ELEMENTS(g_aHostOnlyIPOptions),
193 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
194 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
[17488]195 {
196 switch (c)
197 {
[18108]198 case 'd': // --dhcp
[56118]199 fDhcp = true;
200 break;
[18108]201 case 'a': // --ip
[56118]202 if (pszIp)
[92372]203 RTMsgWarning(HostOnly::tr("The --ip option is specified more than once"));
[56118]204 pszIp = ValueUnion.psz;
205 break;
[18108]206 case 'm': // --netmask
[56118]207 if (pszNetmask)
[92372]208 RTMsgWarning(HostOnly::tr("The --netmask option is specified more than once"));
[56118]209 pszNetmask = ValueUnion.psz;
210 break;
[18108]211 case 'b': // --ipv6
[56118]212 if (pszIpv6)
[92372]213 RTMsgWarning(HostOnly::tr("The --ipv6 option is specified more than once"));
[56118]214 pszIpv6 = ValueUnion.psz;
215 break;
[18108]216 case 'l': // --netmasklengthv6
[56118]217 if (fNetmasklengthv6)
[92372]218 RTMsgWarning(HostOnly::tr("The --netmasklengthv6 option is specified more than once"));
[56118]219 fNetmasklengthv6 = true;
220 uNetmasklengthv6 = ValueUnion.u8;
221 break;
[17759]222 case VINF_GETOPT_NOT_OPTION:
[56118]223 if (pszName)
[94212]224 return errorSyntax(HostOnly::tr("Only one interface name can be specified"));
[56118]225 pszName = ValueUnion.psz;
226 break;
[17488]227 default:
[94212]228 return errorGetOpt(c, &ValueUnion);
[17488]229 }
230 }
231
[18108]232 /* parameter sanity check */
[56118]233 if (fDhcp && (fNetmasklengthv6 || pszIpv6 || pszIp || pszNetmask))
[94212]234 return errorSyntax(HostOnly::tr("You can not use --dhcp with static ip configuration parameters: --ip, --netmask, --ipv6 and --netmasklengthv6."));
[56118]235 if ((pszIp || pszNetmask) && (fNetmasklengthv6 || pszIpv6))
[94212]236 return errorSyntax(HostOnly::tr("You can not use ipv4 configuration (--ip and --netmask) with ipv6 (--ipv6 and --netmasklengthv6) simultaneously."));
[18108]237
[17488]238 ComPtr<IHost> host;
[56118]239 CHECK_ERROR2I_RET(a->virtualBox, COMGETTER(Host)(host.asOutParam()), RTEXITCODE_FAILURE);
[17488]240
241 ComPtr<IHostNetworkInterface> hif;
[56118]242 CHECK_ERROR2I_RET(host, FindHostNetworkInterfaceByName(Bstr(pszName).raw(), hif.asOutParam()), RTEXITCODE_FAILURE);
243 if (hif.isNull())
[92372]244 return errorArgument(HostOnly::tr("Could not find interface '%s'"), pszName);
[17488]245
[56118]246 if (fDhcp)
247 CHECK_ERROR2I_RET(hif, EnableDynamicIPConfig(), RTEXITCODE_FAILURE);
248 else if (pszIp)
[17488]249 {
[56118]250 if (!pszNetmask)
251 pszNetmask = "255.255.255.0"; /* ?? */
252 CHECK_ERROR2I_RET(hif, EnableStaticIPConfig(Bstr(pszIp).raw(), Bstr(pszNetmask).raw()), RTEXITCODE_FAILURE);
[17488]253 }
[56118]254 else if (pszIpv6)
[17488]255 {
[56118]256 BOOL fIpV6Supported;
257 CHECK_ERROR2I_RET(hif, COMGETTER(IPV6Supported)(&fIpV6Supported), RTEXITCODE_FAILURE);
258 if (!fIpV6Supported)
[17759]259 {
[92372]260 RTMsgError(HostOnly::tr("IPv6 setting is not supported for this adapter"));
[56118]261 return RTEXITCODE_FAILURE;
[17759]262 }
263
[56118]264 if (uNetmasklengthv6 == UINT32_MAX)
265 uNetmasklengthv6 = 64; /* ?? */
266 CHECK_ERROR2I_RET(hif, EnableStaticIPConfigV6(Bstr(pszIpv6).raw(), (ULONG)uNetmasklengthv6), RTEXITCODE_FAILURE);
[17488]267 }
268 else
[94212]269 return errorSyntax(HostOnly::tr("Neither -dhcp nor -ip nor -ipv6 was specfified"));
[17488]270
[56118]271 return RTEXITCODE_SUCCESS;
[17488]272}
273
274
[56118]275RTEXITCODE handleHostonlyIf(HandlerArg *a)
[17488]276{
277 if (a->argc < 1)
[94212]278 return errorSyntax(HostOnly::tr("No sub-command specified"));
[17488]279
[56118]280 RTEXITCODE rcExit;
281 if (!strcmp(a->argv[0], "ipconfig"))
[94212]282 {
283 setCurrentSubcommand(HELP_SCOPE_HOSTONLYIF_IPCONFIG);
[56118]284 rcExit = handleIpConfig(a);
[94212]285 }
[35317]286#if defined(VBOX_WITH_NETFLT) && !defined(RT_OS_SOLARIS)
[56118]287 else if (!strcmp(a->argv[0], "create"))
[94212]288 {
289 setCurrentSubcommand(HELP_SCOPE_HOSTONLYIF_CREATE);
[56118]290 rcExit = handleCreate(a);
[94212]291 }
[56118]292 else if (!strcmp(a->argv[0], "remove"))
[94212]293 {
294 setCurrentSubcommand(HELP_SCOPE_HOSTONLYIF_REMOVE);
[56118]295 rcExit = handleRemove(a);
[94212]296 }
[17488]297#endif
[56118]298 else
[94212]299 rcExit = errorSyntax(HostOnly::tr("Unknown sub-command '%s'"), a->argv[0]);
[56118]300 return rcExit;
[17488]301}
302
[91416]303#ifdef VBOX_WITH_VMNET
304struct HostOnlyNetworkOptions
305{
306 bool fEnable;
307 bool fDisable;
308 Bstr bstrNetworkId;
309 Bstr bstrNetworkName;
310 Bstr bstrNetworkMask;
311 Bstr bstrLowerIp;
312 Bstr bstrUpperIp;
313 /* Initialize fEnable and fDisable */
314 HostOnlyNetworkOptions() : fEnable(false), fDisable(false) {};
315};
316typedef struct HostOnlyNetworkOptions HOSTONLYNETOPT;
317
318static RTEXITCODE createUpdateHostOnlyNetworkParse(HandlerArg *a, HOSTONLYNETOPT& options)
319{
320 static const RTGETOPTDEF s_aOptions[] =
321 {
322 { "--id", 'i', RTGETOPT_REQ_STRING },
323 { "--name", 'n', RTGETOPT_REQ_STRING },
324 { "--netmask", 'm', RTGETOPT_REQ_STRING },
325 { "--lower-ip", 'l', RTGETOPT_REQ_STRING },
326 { "--lowerip", 'l', RTGETOPT_REQ_STRING },
327 { "--upper-ip", 'u', RTGETOPT_REQ_STRING },
328 { "--upperip", 'u', RTGETOPT_REQ_STRING },
329 { "--enable", 'e', RTGETOPT_REQ_NOTHING },
330 { "--disable", 'd', RTGETOPT_REQ_NOTHING },
331 };
332
333 RTGETOPTSTATE GetState;
334 RTGETOPTUNION ValueUnion;
335 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1 /* iFirst */, 0);
336 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
337
338 int c;
339 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
340 {
341 switch (c)
342 {
343 case 'i':
344 options.bstrNetworkId = ValueUnion.psz;
345 break;
346 case 'n':
347 options.bstrNetworkName = ValueUnion.psz;
348 break;
349 case 'm':
350 options.bstrNetworkMask = ValueUnion.psz;
351 break;
352 case 'l':
353 options.bstrLowerIp = ValueUnion.psz;
354 break;
355 case 'u':
356 options.bstrUpperIp = ValueUnion.psz;
357 break;
358 case 'e':
359 options.fEnable = true;
360 break;
361 case 'd':
362 options.fDisable = true;
363 break;
364 case VINF_GETOPT_NOT_OPTION:
365 return errorUnknownSubcommand(ValueUnion.psz);
366 default:
367 return errorGetOpt(c, &ValueUnion);
368 }
369 }
370 return RTEXITCODE_SUCCESS;
371}
372
373static RTEXITCODE createUpdateHostOnlyNetworkCommon(ComPtr<IHostOnlyNetwork> hostOnlyNetwork, HOSTONLYNETOPT& options)
374{
375 HRESULT hrc = S_OK;
376
377 if (options.bstrNetworkId.isNotEmpty())
378 {
379 CHECK_ERROR2_RET(hrc, hostOnlyNetwork, COMSETTER(Id)(options.bstrNetworkId.raw()), RTEXITCODE_FAILURE);
380 }
381 if (options.bstrNetworkName.isNotEmpty())
382 {
383 CHECK_ERROR2_RET(hrc, hostOnlyNetwork, COMSETTER(NetworkName)(options.bstrNetworkName.raw()), RTEXITCODE_FAILURE);
384 }
385 if (options.bstrNetworkMask.isNotEmpty())
386 {
387 CHECK_ERROR2_RET(hrc, hostOnlyNetwork, COMSETTER(NetworkMask)(options.bstrNetworkMask.raw()), RTEXITCODE_FAILURE);
388 }
389 if (options.bstrLowerIp.isNotEmpty())
390 {
391 CHECK_ERROR2_RET(hrc, hostOnlyNetwork, COMSETTER(LowerIP)(options.bstrLowerIp.raw()), RTEXITCODE_FAILURE);
392 }
393 if (options.bstrUpperIp.isNotEmpty())
394 {
395 CHECK_ERROR2_RET(hrc, hostOnlyNetwork, COMSETTER(UpperIP)(options.bstrUpperIp.raw()), RTEXITCODE_FAILURE);
396 }
397 if (options.fEnable)
398 {
399 CHECK_ERROR2_RET(hrc, hostOnlyNetwork, COMSETTER(Enabled)(TRUE), RTEXITCODE_FAILURE);
400 }
401 if (options.fDisable)
402 {
403 CHECK_ERROR2_RET(hrc, hostOnlyNetwork, COMSETTER(Enabled)(FALSE), RTEXITCODE_FAILURE);
404 }
405
406 return RTEXITCODE_SUCCESS;
407}
408
409static RTEXITCODE handleNetAdd(HandlerArg *a)
410{
411 HRESULT hrc = S_OK;
412
413 HOSTONLYNETOPT options;
414 hrc = createUpdateHostOnlyNetworkParse(a, options);
415
416 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
417 ComPtr<IHostOnlyNetwork> hostOnlyNetwork;
418
419 if (options.bstrNetworkName.isEmpty())
[92372]420 return errorArgument(HostOnly::tr("The --name parameter must be specified"));
[91416]421 if (options.bstrNetworkMask.isEmpty())
[92372]422 return errorArgument(HostOnly::tr("The --netmask parameter must be specified"));
[91416]423 if (options.bstrLowerIp.isEmpty())
[92372]424 return errorArgument(HostOnly::tr("The --lower-ip parameter must be specified"));
[91416]425 if (options.bstrUpperIp.isEmpty())
[92372]426 return errorArgument(HostOnly::tr("The --upper-ip parameter must be specified"));
[91416]427
428 CHECK_ERROR2_RET(hrc, pVirtualBox,
429 CreateHostOnlyNetwork(options.bstrNetworkName.raw(), hostOnlyNetwork.asOutParam()),
430 RTEXITCODE_FAILURE);
431 return createUpdateHostOnlyNetworkCommon(hostOnlyNetwork, options);
432}
433
434static RTEXITCODE handleNetModify(HandlerArg *a)
435{
436 HRESULT hrc = S_OK;
437
438 HOSTONLYNETOPT options;
439 hrc = createUpdateHostOnlyNetworkParse(a, options);
440
441 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
442 ComPtr<IHostOnlyNetwork> hostOnlyNetwork;
443
444 if (options.bstrNetworkName.isNotEmpty())
445 {
446 CHECK_ERROR2_RET(hrc, pVirtualBox,
447 FindHostOnlyNetworkByName(options.bstrNetworkName.raw(), hostOnlyNetwork.asOutParam()),
448 RTEXITCODE_FAILURE);
449 }
450 else if (options.bstrNetworkId.isNotEmpty())
451 {
452 CHECK_ERROR2_RET(hrc, pVirtualBox,
453 FindHostOnlyNetworkById(options.bstrNetworkId.raw(), hostOnlyNetwork.asOutParam()),
454 RTEXITCODE_FAILURE);
455 }
456 else
[92372]457 return errorArgument(HostOnly::tr("Either --name or --id parameter must be specified"));
[91416]458
459 return createUpdateHostOnlyNetworkCommon(hostOnlyNetwork, options);
460}
461
462static RTEXITCODE handleNetRemove(HandlerArg *a)
463{
464 HRESULT hrc = S_OK;
465
466 static const RTGETOPTDEF s_aOptions[] =
467 {
468 { "--id", 'i', RTGETOPT_REQ_STRING },
469 { "--name", 'n', RTGETOPT_REQ_STRING },
470 };
471
472 RTGETOPTSTATE GetState;
473 RTGETOPTUNION ValueUnion;
474 int vrc = RTGetOptInit(&GetState, a->argc, a->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1 /* iFirst */, 0);
475 AssertRCReturn(vrc, RTEXITCODE_FAILURE);
476
477 Bstr strNetworkId, strNetworkName;
478
479 int c;
480 while ((c = RTGetOpt(&GetState, &ValueUnion)) != 0)
481 {
482 switch (c)
483 {
484 case 'i':
485 strNetworkId=ValueUnion.psz;
486 break;
487 case 'n':
488 strNetworkName=ValueUnion.psz;
489 break;
490 case VINF_GETOPT_NOT_OPTION:
491 return errorUnknownSubcommand(ValueUnion.psz);
492 default:
493 return errorGetOpt(c, &ValueUnion);
494 }
495 }
496
497 ComPtr<IVirtualBox> pVirtualBox = a->virtualBox;
498 ComPtr<IHostOnlyNetwork> hostOnlyNetwork;
499
500 if (!strNetworkName.isEmpty())
501 {
502 CHECK_ERROR2_RET(hrc, pVirtualBox,
503 FindHostOnlyNetworkByName(strNetworkName.raw(), hostOnlyNetwork.asOutParam()),
504 RTEXITCODE_FAILURE);
505 }
506 else if (!strNetworkId.isEmpty())
507 {
508 CHECK_ERROR2_RET(hrc, pVirtualBox,
509 FindHostOnlyNetworkById(strNetworkId.raw(), hostOnlyNetwork.asOutParam()),
510 RTEXITCODE_FAILURE);
511 }
512 else
[92372]513 return errorArgument(HostOnly::tr("Either --name or --id parameter must be specified"));
[91416]514
515 CHECK_ERROR2_RET(hrc, pVirtualBox,
516 RemoveHostOnlyNetwork(hostOnlyNetwork),
517 RTEXITCODE_FAILURE);
518 return RTEXITCODE_SUCCESS;
519}
520
521RTEXITCODE handleHostonlyNet(HandlerArg *a)
522{
523 if (a->argc < 1)
[92372]524 return errorSyntax(HostOnly::tr("No sub-command specified"));
[91416]525
526 RTEXITCODE rcExit;
527 if (!strcmp(a->argv[0], "add"))
528 {
529 setCurrentSubcommand(HELP_SCOPE_HOSTONLYNET_ADD);
530 rcExit = handleNetAdd(a);
531 }
532 else if (!strcmp(a->argv[0], "modify"))
533 {
534 setCurrentSubcommand(HELP_SCOPE_HOSTONLYNET_MODIFY);
535 rcExit = handleNetModify(a);
536 }
537 else if (!strcmp(a->argv[0], "remove"))
538 {
539 setCurrentSubcommand(HELP_SCOPE_HOSTONLYNET_REMOVE);
540 rcExit = handleNetRemove(a);
541 }
542 else
[92372]543 rcExit = errorSyntax(HostOnly::tr("Unknown sub-command '%s'"), a->argv[0]);
[91416]544 return rcExit;
545}
546#endif /* VBOX_WITH_VMNET */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use