/* $Id: VBoxManageHostonly.cpp 17759 2009-03-12 15:57:18Z vboxsync $ */ /** @file * VBoxManage - Implementation of hostonlyif command. */ /* * Copyright (C) 2006-2009 Sun Microsystems, Inc. * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; * you can redistribute it and/or modify it under the terms of the GNU * General Public License (GPL) as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * VirtualBox OSE distribution. VirtualBox OSE is distributed in the * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 USA or visit http://www.sun.com if you need * additional information or have any questions. */ /******************************************************************************* * Header Files * *******************************************************************************/ #ifndef VBOX_ONLY_DOCS #include #include #include #include #include #include #include #include #endif /* !VBOX_ONLY_DOCS */ #include #include #include #include #include #include #include #include #include "VBoxManage.h" #ifndef VBOX_ONLY_DOCS using namespace com; #if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT) static int handleCreate(HandlerArg *a, int iStart, int *pcProcessed) { // if (a->argc - iStart < 1) // return errorSyntax(USAGE_HOSTONLYIFS, "Not enough parameters"); int index = iStart; HRESULT rc; // Bstr name(a->argv[iStart]); // index++; ComPtr host; CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam())); ComPtr hif; ComPtr progress; CHECK_ERROR(host, CreateHostOnlyNetworkInterface (hif.asOutParam(), progress.asOutParam())); showProgress(progress); HRESULT hr; CHECK_ERROR(progress, COMGETTER(ResultCode) (&hr)); *pcProcessed = index - iStart; if(FAILED(hr)) { com::ProgressErrorInfo info(progress); if (info.isBasicAvailable()) RTPrintf("Error: failed to remove the host-only adapter. Error message: %lS\n", info.getText().raw()); else RTPrintf("Error: failed to remove the host-only adapter. No error message available, HRESULT code: 0x%x\n", hr); return 1; } Bstr name; CHECK_ERROR(hif, COMGETTER(Name) (name.asOutParam())); RTPrintf("Interface '%lS' was successfully created\n", name.raw()); return 0; } static int handleRemove(HandlerArg *a, int iStart, int *pcProcessed) { if (a->argc - iStart < 1) return errorSyntax(USAGE_HOSTONLYIFS, "Not enough parameters"); int index = iStart; HRESULT rc; Bstr name(a->argv[iStart]); index++; ComPtr host; CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam())); ComPtr hif; CHECK_ERROR(host, FindHostNetworkInterfaceByName(name, hif.asOutParam())); GUID guid; CHECK_ERROR(hif, COMGETTER(Id)(&guid)); ComPtr progress; CHECK_ERROR(host, RemoveHostOnlyNetworkInterface (guid, hif.asOutParam(),progress.asOutParam())); showProgress(progress); HRESULT hr; CHECK_ERROR(progress, COMGETTER(ResultCode) (&hr)); *pcProcessed = index - iStart; if(FAILED(hr)) { com::ProgressErrorInfo info(progress); if (info.isBasicAvailable()) RTPrintf("Error: failed to remove the host-only adapter. Error message: %lS\n", info.getText().raw()); else RTPrintf("Error: failed to remove the host-only adapter. No error message available, HRESULT code: 0x%x\n", hr); return 1; } return 0; } #endif enum enOptionCodes { DHCP = 1000, IP, NETMASK, IPV6, NETMASKLENGTHV6 }; static const RTGETOPTDEF g_aListOptions[] = { { "-dhcp", DHCP, RTGETOPT_REQ_NOTHING }, { "-ip", IP, RTGETOPT_REQ_STRING }, { "-netmask", NETMASK, RTGETOPT_REQ_STRING }, { "-ipv6", IPV6, RTGETOPT_REQ_STRING }, { "-netmasklengthv6", NETMASKLENGTHV6, RTGETOPT_REQ_UINT8 } }; static int handleIpconfig(HandlerArg *a, int iStart, int *pcProcessed) { if (a->argc - iStart < 2) return errorSyntax(USAGE_HOSTONLYIFS, "Not enough parameters"); int index = iStart; HRESULT rc; Bstr name(a->argv[iStart]); index++; bool bDhcp = false; bool bNetmasklengthv6 = false; uint32_t uNetmasklengthv6 = -1; const char *pIpv6 = NULL; const char * pIp = NULL; const char * pNetmask = NULL; int c; RTGETOPTUNION ValueUnion; RTGETOPTSTATE GetState; RTGetOptInit(&GetState, a->argc, a->argv, g_aListOptions, RT_ELEMENTS(g_aListOptions), index, 0 /* fFlags */); while ((c = RTGetOpt(&GetState, &ValueUnion))) { switch (c) { case DHCP: // -dhcp if (bDhcp) return errorSyntax(USAGE_HOSTONLYIFS, "You can only specify -dhcp once."); else if(bNetmasklengthv6 || pIpv6 || pIp || pNetmask) return errorSyntax(USAGE_HOSTONLYIFS, "You can not use -dhcp with static ip configuration parameters: -ip, -netmask, -ipv6 and -netmasklengthv6."); else bDhcp = true; break; case IP: if(pIp) return errorSyntax(USAGE_HOSTONLYIFS, "You can only specify -ip once."); else if (bDhcp) return errorSyntax(USAGE_HOSTONLYIFS, "You can not use -dhcp with static ip configuration parameters: -ip, -netmask, -ipv6 and -netmasklengthv6."); else if(bNetmasklengthv6 || pIpv6) return errorSyntax(USAGE_HOSTONLYIFS, "You can not use ipv4 configuration (-ip and -netmask) with ipv6 (-ipv6 and -netmasklengthv6) simultaneously."); else { pIp = ValueUnion.psz; } break; case NETMASK: if(pNetmask) return errorSyntax(USAGE_HOSTONLYIFS, "You can only specify -netmask once."); else if (bDhcp) return errorSyntax(USAGE_HOSTONLYIFS, "You can not use -dhcp with static ip configuration parameters: -ip, -netmask, -ipv6 and -netmasklengthv6."); else if(bNetmasklengthv6 || pIpv6) return errorSyntax(USAGE_HOSTONLYIFS, "You can not use ipv4 configuration (-ip and -netmask) with ipv6 (-ipv6 and -netmasklengthv6) simultaneously."); else { pNetmask = ValueUnion.psz; } break; case IPV6: if(pIpv6) return errorSyntax(USAGE_HOSTONLYIFS, "You can only specify -ipv6 once."); else if (bDhcp) return errorSyntax(USAGE_HOSTONLYIFS, "You can not use -dhcp with static ip configuration parameters: -ip, -netmask, -ipv6 and -netmasklengthv6."); else if(pIp || pNetmask) return errorSyntax(USAGE_HOSTONLYIFS, "You can not use ipv4 configuration (-ip and -netmask) with ipv6 (-ipv6 and -netmasklengthv6) simultaneously."); else pIpv6 = ValueUnion.psz; break; case NETMASKLENGTHV6: if(bNetmasklengthv6) return errorSyntax(USAGE_HOSTONLYIFS, "You can only specify -netmasklengthv6 once."); else if (bDhcp) return errorSyntax(USAGE_HOSTONLYIFS, "You can not use -dhcp with static ip configuration parameters: -ip, -netmask, -ipv6 and -netmasklengthv6."); else if(pIp || pNetmask) return errorSyntax(USAGE_HOSTONLYIFS, "You can not use ipv4 configuration (-ip and -netmask) with ipv6 (-ipv6 and -netmasklengthv6) simultaneously."); else { bNetmasklengthv6 = true; uNetmasklengthv6 = ValueUnion.u8; } break; case VINF_GETOPT_NOT_OPTION: case VERR_GETOPT_UNKNOWN_OPTION: return errorSyntax(USAGE_HOSTONLYIFS, "Unknown option \"%s\".", ValueUnion.psz); break; default: if (c > 0) return errorSyntax(USAGE_HOSTONLYIFS, "missing case: %c\n", c); else if (ValueUnion.pDef) return errorSyntax(USAGE_HOSTONLYIFS, "%s: %Rrs", ValueUnion.pDef->pszLong, c); else return errorSyntax(USAGE_HOSTONLYIFS, "%Rrs", c); } } ComPtr host; CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam())); ComPtr hif; CHECK_ERROR(host, FindHostNetworkInterfaceByName(name, hif.asOutParam())); if(FAILED(rc)) return errorArgument("could not find interface '%s'", a->argv[iStart]); if(bDhcp) { CHECK_ERROR(hif, EnableDynamicIpConfig ()); } else if(pIp) { if(!pNetmask) pNetmask = "255.255.255.0"; /* ?? */ CHECK_ERROR(hif, EnableStaticIpConfig (Bstr(pIp), Bstr(pNetmask))); } else if(pIpv6) { if(uNetmasklengthv6 == -1) uNetmasklengthv6 = 64; /* ?? */ BOOL bIpV6Supported; CHECK_ERROR(hif, COMGETTER(IPV6Supported) (&bIpV6Supported)); if(!bIpV6Supported) { RTPrintf("IPv6 setting is not supported for this adapter\n"); return 1; } Bstr ipv6str(pIpv6); CHECK_ERROR(hif, EnableStaticIpConfigV6 (ipv6str, (ULONG)uNetmasklengthv6)); } else { return errorSyntax(USAGE_HOSTONLYIFS, "neither -dhcp nor -ip nor -ipv6 was spcfified"); } return 0; } int handleHostonlyIf(HandlerArg *a) { int result = 0; if (a->argc < 1) return errorSyntax(USAGE_HOSTONLYIFS, "Not enough parameters"); for (int i = 0; i < a->argc; i++) { if (strcmp(a->argv[i], "ipconfig") == 0) { int cProcessed; result = handleIpconfig(a, i+1, &cProcessed); break; // if(!rc) // i+= cProcessed; // else // break; } #if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_NETFLT) else if (strcmp(a->argv[i], "create") == 0) { int cProcessed; result = handleCreate(a, i+1, &cProcessed); if(!result) i+= cProcessed; else break; } else if (strcmp(a->argv[i], "remove") == 0) { int cProcessed; result = handleRemove(a, i+1, &cProcessed); if(!result) i+= cProcessed; else break; } #endif else { result = errorSyntax(USAGE_HOSTONLYIFS, "Invalid parameter '%s'", Utf8Str(a->argv[i]).raw()); break; } } return result; } #endif /* !VBOX_ONLY_DOCS */