From 67cc35ade9fd02420f55a6789b0990f6486dffb6 Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Fri, 15 May 2009 14:00:50 +0000 Subject: [PATCH] Finish hostonly networks support in vbox * src/vbox/vbox_driver.c src/vbox/vbox_tmpl.c: last patch for hostonly networks support in vbox driver, patch by Pritesh Kothari daniel --- ChangeLog | 5 + src/vbox/vbox_driver.c | 8 + src/vbox/vbox_tmpl.c | 1039 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1052 insertions(+) diff --git a/ChangeLog b/ChangeLog index 113f52ec19..920913d2fa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Fri May 15 15:59:08 CEST 2009 Daniel Veillard + + * src/vbox/vbox_driver.c src/vbox/vbox_tmpl.c: last patch for + hostonly networks support in vbox driver, patch by Pritesh Kothari + Fri May 15 15:44:01 CEST 2009 Daniel Veillard * src/vbox/vbox_tmpl.c: implement vbox vrdp/sdl/gui support, diff --git a/src/vbox/vbox_driver.c b/src/vbox/vbox_driver.c index 76632e71a4..a3d54287c6 100644 --- a/src/vbox/vbox_driver.c +++ b/src/vbox/vbox_driver.c @@ -40,8 +40,10 @@ extern virDriver vbox22Driver; +extern virNetworkDriver vbox22NetworkDriver; #if 0 extern virDriver vbox25Driver; +extern virNetworkDriver vbox25NetworkDriver; #endif static virDriver vboxDriverDummy; @@ -54,6 +56,7 @@ static virDriver vboxDriverDummy; int vboxRegister(void) { virDriverPtr driver; + virNetworkDriverPtr networkDriver; uint32_t uVersion; /* @@ -63,6 +66,7 @@ int vboxRegister(void) { * never work */ driver = &vboxDriverDummy; + networkDriver = &vbox22NetworkDriver; /* Init the glue and get the API version. */ if (VBoxCGlueInit() == 0) { @@ -80,10 +84,12 @@ int vboxRegister(void) { if (uVersion >= 2001052 && uVersion < 2002051) { DEBUG0("VirtualBox API version: 2.2"); driver = &vbox22Driver; + networkDriver = &vbox22NetworkDriver; #if 0 } else if (uVersion >= 2002051 && uVersion < 2005051) { DEBUG0("VirtualBox API version: 2.5"); driver = &vbox25Driver; + networkDriver = &vbox25NetworkDriver; #endif } else { DEBUG0("Unsupport VirtualBox API version"); @@ -95,6 +101,8 @@ int vboxRegister(void) { if (virRegisterDriver(driver) < 0) return -1; + if (virRegisterNetworkDriver(networkDriver) < 0) + return -1; return 0; } diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c index 5514a1bfa9..67bb19ce41 100644 --- a/src/vbox/vbox_tmpl.c +++ b/src/vbox/vbox_tmpl.c @@ -3881,6 +3881,1024 @@ cleanup: return ret; } +/** + * The Network Functions here on + */ +static virDrvOpenStatus vboxNetworkOpen(virConnectPtr conn, + virConnectAuthPtr auth ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED) { + vboxGlobalData *data = conn->privateData; + + if (STRNEQ(conn->driver->name, "VBOX")) + goto cleanup; + + if ((data->pFuncs == NULL) || + (data->vboxObj == NULL) || + (data->vboxSession == NULL)) + goto cleanup; + + DEBUG0("network intialized"); + /* conn->networkPrivateData = some network specific data */ + return VIR_DRV_OPEN_SUCCESS; + +cleanup: + return VIR_DRV_OPEN_DECLINED; +} + +static int vboxNetworkClose(virConnectPtr conn) { + DEBUG0("network unintialized"); + conn->networkPrivateData = NULL; + return 0; +} + +static int vboxNumOfNetworks(virConnectPtr conn) { + vboxGlobalData *data = conn->privateData; + int numActive = 0; + + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + int i = 0; + PRUint32 networkInterfacesSize = 0; + IHostNetworkInterface **networkInterfaces = NULL; + + host->vtbl->GetNetworkInterfaces(host, &networkInterfacesSize, &networkInterfaces); + + for (i = 0; i < networkInterfacesSize; i++) { + if (networkInterfaces[i]) { + PRUint32 interfaceType = 0; + + networkInterfaces[i]->vtbl->GetInterfaceType(networkInterfaces[i], &interfaceType); + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + PRUint32 status = HostNetworkInterfaceStatus_Unknown; + + networkInterfaces[i]->vtbl->GetStatus(networkInterfaces[i], &status); + + if (status == HostNetworkInterfaceStatus_Up) { + numActive++; + } + } + + networkInterfaces[i]->vtbl->nsisupports.Release((nsISupports *) networkInterfaces[i]); + } + } + + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + + DEBUG("numActive: %d", numActive); + return numActive; +} + +static int vboxListNetworks(virConnectPtr conn, char **const names, int nnames) { + vboxGlobalData *data = conn->privateData; + int numActive = 0; + + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + int i = 0; + PRUint32 networkInterfacesSize = 0; + IHostNetworkInterface **networkInterfaces = NULL; + + host->vtbl->GetNetworkInterfaces(host, &networkInterfacesSize, &networkInterfaces); + + for (i = 0; (numActive < nnames) && (i < networkInterfacesSize); i++) { + if (networkInterfaces[i]) { + PRUint32 interfaceType = 0; + + networkInterfaces[i]->vtbl->GetInterfaceType(networkInterfaces[i], &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + PRUint32 status = HostNetworkInterfaceStatus_Unknown; + + networkInterfaces[i]->vtbl->GetStatus(networkInterfaces[i], &status); + + if (status == HostNetworkInterfaceStatus_Up) { + char *nameUtf8 = NULL; + PRUnichar *nameUtf16 = NULL; + + networkInterfaces[i]->vtbl->GetName(networkInterfaces[i], &nameUtf16); + data->pFuncs->pfnUtf16ToUtf8(nameUtf16, &nameUtf8); + + DEBUG("nnames[%d]: %s", numActive, nameUtf8); + names[numActive] = strdup(nameUtf8); + if (names[numActive] == NULL) { + vboxError(conn, VIR_ERR_SYSTEM_ERROR, "%s", "strdup failed"); + } else { + numActive++; + } + + data->pFuncs->pfnUtf8Free(nameUtf8); + data->pFuncs->pfnUtf16Free(nameUtf16); + } + } + } + } + + for (i = 0; i < networkInterfacesSize; i++) { + if (networkInterfaces[i]) { + networkInterfaces[i]->vtbl->nsisupports.Release((nsISupports *) networkInterfaces[i]); + } + } + + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + + return numActive; +} + +static int vboxNumOfDefinedNetworks(virConnectPtr conn) { + vboxGlobalData *data = conn->privateData; + int numActive = 0; + + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + int i = 0; + PRUint32 networkInterfacesSize = 0; + IHostNetworkInterface **networkInterfaces = NULL; + + host->vtbl->GetNetworkInterfaces(host, &networkInterfacesSize, &networkInterfaces); + + for (i = 0; i < networkInterfacesSize; i++) { + if (networkInterfaces[i]) { + PRUint32 interfaceType = 0; + + networkInterfaces[i]->vtbl->GetInterfaceType(networkInterfaces[i], &interfaceType); + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + PRUint32 status = HostNetworkInterfaceStatus_Unknown; + + networkInterfaces[i]->vtbl->GetStatus(networkInterfaces[i], &status); + + if (status == HostNetworkInterfaceStatus_Down) { + numActive++; + } + } + + networkInterfaces[i]->vtbl->nsisupports.Release((nsISupports *) networkInterfaces[i]); + } + } + + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + + DEBUG("numActive: %d", numActive); + return numActive; +} + +static int vboxListDefinedNetworks(virConnectPtr conn, char **const names, int nnames) { + vboxGlobalData *data = conn->privateData; + int numActive = 0; + + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + int i = 0; + PRUint32 networkInterfacesSize = 0; + IHostNetworkInterface **networkInterfaces = NULL; + + host->vtbl->GetNetworkInterfaces(host, &networkInterfacesSize, &networkInterfaces); + + for (i = 0; (numActive < nnames) && (i < networkInterfacesSize); i++) { + if (networkInterfaces[i]) { + PRUint32 interfaceType = 0; + + networkInterfaces[i]->vtbl->GetInterfaceType(networkInterfaces[i], &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + PRUint32 status = HostNetworkInterfaceStatus_Unknown; + + networkInterfaces[i]->vtbl->GetStatus(networkInterfaces[i], &status); + + if (status == HostNetworkInterfaceStatus_Down) { + char *nameUtf8 = NULL; + PRUnichar *nameUtf16 = NULL; + + networkInterfaces[i]->vtbl->GetName(networkInterfaces[i], &nameUtf16); + data->pFuncs->pfnUtf16ToUtf8(nameUtf16, &nameUtf8); + + DEBUG("nnames[%d]: %s", numActive, nameUtf8); + names[numActive] = strdup(nameUtf8); + if (names[numActive] == NULL) { + vboxError(conn, VIR_ERR_SYSTEM_ERROR, "%s", "strdup failed"); + } else { + numActive++; + } + + data->pFuncs->pfnUtf8Free(nameUtf8); + data->pFuncs->pfnUtf16Free(nameUtf16); + } + } + } + } + + for (i = 0; i < networkInterfacesSize; i++) { + if (networkInterfaces[i]) { + networkInterfaces[i]->vtbl->nsisupports.Release((nsISupports *) networkInterfaces[i]); + } + } + + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + + return numActive; +} + +static virNetworkPtr vboxNetworkLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { + vboxGlobalData *data = conn->privateData; + virNetworkPtr ret = NULL; + nsID *iid = NULL; + + if (VIR_ALLOC(iid) < 0) { + virReportOOMError(conn); + goto cleanup; + } + + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + IHostNetworkInterface *networkInterface = NULL; + + nsIDFromChar(iid, uuid); + host->vtbl->FindHostNetworkInterfaceById(host, iid, &networkInterface); + if (networkInterface) { + PRUint32 interfaceType = 0; + + networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + char *nameUtf8 = NULL; + PRUnichar *nameUtf16 = NULL; + + networkInterface->vtbl->GetName(networkInterface, &nameUtf16); + data->pFuncs->pfnUtf16ToUtf8(nameUtf16, &nameUtf8); + + ret = virGetNetwork(conn, nameUtf8, uuid); + + DEBUG("Network Name: %s", nameUtf8); + DEBUG("Network UUID: " + "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + (unsigned)iid->m0, (unsigned)iid->m1, + (unsigned)iid->m2, (unsigned)iid->m3[0], + (unsigned)iid->m3[1], (unsigned)iid->m3[2], + (unsigned)iid->m3[3], (unsigned)iid->m3[4], + (unsigned)iid->m3[5], (unsigned)iid->m3[6], + (unsigned)iid->m3[7]); + + data->pFuncs->pfnUtf8Free(nameUtf8); + data->pFuncs->pfnUtf16Free(nameUtf16); + } + + networkInterface->vtbl->nsisupports.Release((nsISupports *) networkInterface); + } + + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + +cleanup: + VIR_FREE(iid); + return ret; +} + +static virNetworkPtr vboxNetworkLookupByName(virConnectPtr conn, const char *name) { + vboxGlobalData *data = conn->privateData; + virNetworkPtr ret = NULL; + + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + PRUnichar *nameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; + + data->pFuncs->pfnUtf8ToUtf16(name, &nameUtf16); + + host->vtbl->FindHostNetworkInterfaceByName(host, nameUtf16, &networkInterface); + + if (networkInterface) { + PRUint32 interfaceType = 0; + + networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + unsigned char uuid[VIR_UUID_BUFLEN]; + nsID *iid = NULL; + + networkInterface->vtbl->GetId(networkInterface, &iid); + + nsIDtoChar(uuid, iid); + + ret = virGetNetwork(conn, name, uuid); + + DEBUG("Network Name: %s", name); + DEBUG("Network UUID: " + "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + (unsigned)iid->m0, (unsigned)iid->m1, + (unsigned)iid->m2, (unsigned)iid->m3[0], + (unsigned)iid->m3[1], (unsigned)iid->m3[2], + (unsigned)iid->m3[3], (unsigned)iid->m3[4], + (unsigned)iid->m3[5], (unsigned)iid->m3[6], + (unsigned)iid->m3[7]); + + data->pFuncs->pfnComUnallocMem(iid); + } + + networkInterface->vtbl->nsisupports.Release((nsISupports *) networkInterface); + } + + data->pFuncs->pfnUtf16Free(nameUtf16); + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + + return ret; +} + +static virNetworkPtr vboxNetworkCreateXML(virConnectPtr conn, const char *xml) { + vboxGlobalData *data = conn->privateData; + virNetworkDefPtr def = NULL; + virNetworkPtr ret = NULL; + nsID *iid = NULL; + char *networkNameUtf8 = NULL; + + if ((def = virNetworkDefParseString(conn, xml)) == NULL) + goto cleanup; + + if (VIR_ALLOC(iid) < 0) { + virReportOOMError(conn); + goto cleanup; + } + + if (virAsprintf(&networkNameUtf8, "HostInterfaceNetworking-%s", def->name) < 0) { + virReportOOMError(conn); + goto cleanup; + } + + nsIDFromChar(iid, def->uuid); + + DEBUG("Network Name: %s", def->name); + DEBUG("Network UUID: " + "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + (unsigned)iid->m0, (unsigned)iid->m1, + (unsigned)iid->m2, (unsigned)iid->m3[0], + (unsigned)iid->m3[1], (unsigned)iid->m3[2], + (unsigned)iid->m3[3], (unsigned)iid->m3[4], + (unsigned)iid->m3[5], (unsigned)iid->m3[6], + (unsigned)iid->m3[7]); + + if ((data->vboxObj) && (def->forwardType == VIR_NETWORK_FORWARD_NONE)) { + /* VirtualBox version 2.2.* has only one "hostonly" + * network called "vboxnet0" for linux + */ + if (STREQ(def->name, "vboxnet0")) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + PRUnichar *networkInterfaceNameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; + + data->pFuncs->pfnUtf8ToUtf16(def->name, &networkInterfaceNameUtf16); + + host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface); + + if (networkInterface) { + PRUint32 interfaceType = 0; + + networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + unsigned char uuid[VIR_UUID_BUFLEN]; + nsID *vboxnet0IID = NULL; + PRUnichar *networkNameUtf16 = NULL; + + data->pFuncs->pfnUtf8ToUtf16(networkNameUtf8 , &networkNameUtf16); + + networkInterface->vtbl->GetId(networkInterface, &vboxnet0IID); + + nsIDtoChar(uuid, vboxnet0IID); + + /* Currently support only one dhcp server per network + * with contigious address space from start to end + */ + if ((def->nranges >= 1) && + (def->ranges[0].start) && + (def->ranges[0].end)) { + IDHCPServer *dhcpServer = NULL; + + data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj, + networkNameUtf16, + &dhcpServer); + if (!dhcpServer) { + /* create a dhcp server */ + data->vboxObj->vtbl->CreateDHCPServer(data->vboxObj, + networkNameUtf16, + &dhcpServer); + DEBUG0("couldn't find dhcp server so creating one"); + } + if (dhcpServer) { + PRUnichar *ipAddressUtf16 = NULL; + PRUnichar *networkMaskUtf16 = NULL; + PRUnichar *fromIPAddressUtf16 = NULL; + PRUnichar *toIPAddressUtf16 = NULL; + PRUnichar *trunkTypeUtf16 = NULL; + + + data->pFuncs->pfnUtf8ToUtf16(def->ipAddress, &ipAddressUtf16); + data->pFuncs->pfnUtf8ToUtf16(def->netmask, &networkMaskUtf16); + data->pFuncs->pfnUtf8ToUtf16(def->ranges[0].start, &fromIPAddressUtf16); + data->pFuncs->pfnUtf8ToUtf16(def->ranges[0].end, &toIPAddressUtf16); + data->pFuncs->pfnUtf8ToUtf16("netflt", &trunkTypeUtf16); + + dhcpServer->vtbl->SetEnabled(dhcpServer, PR_TRUE); + + dhcpServer->vtbl->SetConfiguration(dhcpServer, + ipAddressUtf16, + networkMaskUtf16, + fromIPAddressUtf16, + toIPAddressUtf16); + + dhcpServer->vtbl->Start(dhcpServer, + networkNameUtf16, + networkInterfaceNameUtf16, + trunkTypeUtf16); + + data->pFuncs->pfnUtf16Free(ipAddressUtf16); + data->pFuncs->pfnUtf16Free(networkMaskUtf16); + data->pFuncs->pfnUtf16Free(fromIPAddressUtf16); + data->pFuncs->pfnUtf16Free(toIPAddressUtf16); + data->pFuncs->pfnUtf16Free(trunkTypeUtf16); + dhcpServer->vtbl->nsisupports.Release((nsISupports *) dhcpServer); + } + } + + ret = virGetNetwork(conn, def->name, uuid); + + DEBUG("Real Network UUID: " + "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + (unsigned)vboxnet0IID->m0, (unsigned)vboxnet0IID->m1, + (unsigned)vboxnet0IID->m2, (unsigned)vboxnet0IID->m3[0], + (unsigned)vboxnet0IID->m3[1], (unsigned)vboxnet0IID->m3[2], + (unsigned)vboxnet0IID->m3[3], (unsigned)vboxnet0IID->m3[4], + (unsigned)vboxnet0IID->m3[5], (unsigned)vboxnet0IID->m3[6], + (unsigned)vboxnet0IID->m3[7]); + + data->pFuncs->pfnComUnallocMem(vboxnet0IID); + data->pFuncs->pfnUtf16Free(networkNameUtf16); + } + + networkInterface->vtbl->nsisupports.Release((nsISupports *) networkInterface); + } + + data->pFuncs->pfnUtf16Free(networkInterfaceNameUtf16); + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + } + +cleanup: + VIR_FREE(iid); + VIR_FREE(networkNameUtf8); + virNetworkDefFree(def); + return ret; +} + +static virNetworkPtr vboxNetworkDefineXML(virConnectPtr conn, const char *xml) { + vboxGlobalData *data = conn->privateData; + virNetworkDefPtr def = NULL; + virNetworkPtr ret = NULL; + nsID *iid = NULL; + char *networkNameUtf8 = NULL; + + /* vboxNetworkDefineXML() is not exactly "network definition" + * as the network is up and running, only the DHCP server is off, + * so you can always assign static IP and get the network running. + */ + if ((def = virNetworkDefParseString(conn, xml)) == NULL) + goto cleanup; + + if (VIR_ALLOC(iid) < 0) { + virReportOOMError(conn); + goto cleanup; + } + + if (virAsprintf(&networkNameUtf8, "HostInterfaceNetworking-%s", def->name) < 0) { + virReportOOMError(conn); + goto cleanup; + } + + nsIDFromChar(iid, def->uuid); + + DEBUG("Network Name: %s", def->name); + DEBUG("Network UUID: " + "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + (unsigned)iid->m0, (unsigned)iid->m1, + (unsigned)iid->m2, (unsigned)iid->m3[0], + (unsigned)iid->m3[1], (unsigned)iid->m3[2], + (unsigned)iid->m3[3], (unsigned)iid->m3[4], + (unsigned)iid->m3[5], (unsigned)iid->m3[6], + (unsigned)iid->m3[7]); + + if ((data->vboxObj) && (def->forwardType == VIR_NETWORK_FORWARD_NONE)) { + /* VirtualBox version 2.2.* has only one "hostonly" + * network called "vboxnet0" for linux + */ + if (STREQ(def->name, "vboxnet0")) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + PRUnichar *networkInterfaceNameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; + + data->pFuncs->pfnUtf8ToUtf16(def->name, &networkInterfaceNameUtf16); + + host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface); + + if (networkInterface) { + PRUint32 interfaceType = 0; + + networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + unsigned char uuid[VIR_UUID_BUFLEN]; + nsID *vboxnet0IID = NULL; + PRUnichar *networkNameUtf16 = NULL; + + data->pFuncs->pfnUtf8ToUtf16(networkNameUtf8 , &networkNameUtf16); + + networkInterface->vtbl->GetId(networkInterface, &vboxnet0IID); + + nsIDtoChar(uuid, vboxnet0IID); + + /* Currently support only one dhcp server per network + * with contigious address space from start to end + */ + if ((def->nranges >= 1) && + (def->ranges[0].start) && + (def->ranges[0].end)) { + IDHCPServer *dhcpServer = NULL; + + data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj, + networkNameUtf16, + &dhcpServer); + if (!dhcpServer) { + /* create a dhcp server */ + data->vboxObj->vtbl->CreateDHCPServer(data->vboxObj, + networkNameUtf16, + &dhcpServer); + DEBUG0("couldn't find dhcp server so creating one"); + } + if (dhcpServer) { + PRUnichar *ipAddressUtf16 = NULL; + PRUnichar *networkMaskUtf16 = NULL; + PRUnichar *fromIPAddressUtf16 = NULL; + PRUnichar *toIPAddressUtf16 = NULL; + + + data->pFuncs->pfnUtf8ToUtf16(def->ipAddress, &ipAddressUtf16); + data->pFuncs->pfnUtf8ToUtf16(def->netmask, &networkMaskUtf16); + data->pFuncs->pfnUtf8ToUtf16(def->ranges[0].start, &fromIPAddressUtf16); + data->pFuncs->pfnUtf8ToUtf16(def->ranges[0].end, &toIPAddressUtf16); + + dhcpServer->vtbl->SetEnabled(dhcpServer, PR_FALSE); + + dhcpServer->vtbl->SetConfiguration(dhcpServer, + ipAddressUtf16, + networkMaskUtf16, + fromIPAddressUtf16, + toIPAddressUtf16); + + data->pFuncs->pfnUtf16Free(ipAddressUtf16); + data->pFuncs->pfnUtf16Free(networkMaskUtf16); + data->pFuncs->pfnUtf16Free(fromIPAddressUtf16); + data->pFuncs->pfnUtf16Free(toIPAddressUtf16); + dhcpServer->vtbl->nsisupports.Release((nsISupports *) dhcpServer); + } + } + + ret = virGetNetwork(conn, def->name, uuid); + + DEBUG("Real Network UUID: " + "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + (unsigned)vboxnet0IID->m0, (unsigned)vboxnet0IID->m1, + (unsigned)vboxnet0IID->m2, (unsigned)vboxnet0IID->m3[0], + (unsigned)vboxnet0IID->m3[1], (unsigned)vboxnet0IID->m3[2], + (unsigned)vboxnet0IID->m3[3], (unsigned)vboxnet0IID->m3[4], + (unsigned)vboxnet0IID->m3[5], (unsigned)vboxnet0IID->m3[6], + (unsigned)vboxnet0IID->m3[7]); + + data->pFuncs->pfnComUnallocMem(vboxnet0IID); + data->pFuncs->pfnUtf16Free(networkNameUtf16); + } + + networkInterface->vtbl->nsisupports.Release((nsISupports *) networkInterface); + } + + data->pFuncs->pfnUtf16Free(networkInterfaceNameUtf16); + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + } + +cleanup: + VIR_FREE(iid); + VIR_FREE(networkNameUtf8); + virNetworkDefFree(def); + return ret; +} + +static int vboxNetworkUndefine(virNetworkPtr network) { + vboxGlobalData *data = network->conn->privateData; + char *networkNameUtf8 = NULL; + int ret = -1; + + /* Current limitation of the function for VirtualBox 2.2.* is + * that you can't delete the default hostonly adaptor namely: + * vboxnet0 and thus all this functions does is remove the + * dhcp server configuration, but the network can still be used + * by giving the machine static IP and also it will still + * show up in the net-list in virsh + */ + + if (virAsprintf(&networkNameUtf8, "HostInterfaceNetworking-%s", network->name) < 0) { + virReportOOMError(network->conn); + goto cleanup; + } + + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + PRUnichar *networkInterfaceNameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; + + data->pFuncs->pfnUtf8ToUtf16(network->name, &networkInterfaceNameUtf16); + + host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface); + + if (networkInterface) { + PRUint32 interfaceType = 0; + + networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + PRUnichar *networkNameUtf16 = NULL; + IDHCPServer *dhcpServer = NULL; + + data->pFuncs->pfnUtf8ToUtf16(networkNameUtf8 , &networkNameUtf16); + + data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj, + networkNameUtf16, + &dhcpServer); + if (dhcpServer) { + data->vboxObj->vtbl->RemoveDHCPServer(data->vboxObj, dhcpServer); + dhcpServer->vtbl->nsisupports.Release((nsISupports *) dhcpServer); + } + + data->pFuncs->pfnUtf16Free(networkNameUtf16); + } + + networkInterface->vtbl->nsisupports.Release((nsISupports *) networkInterface); + } + + data->pFuncs->pfnUtf16Free(networkInterfaceNameUtf16); + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + + ret = 0; + +cleanup: + VIR_FREE(networkNameUtf8); + return ret; +} + +static int vboxNetworkCreate(virNetworkPtr network) { + vboxGlobalData *data = network->conn->privateData; + char *networkNameUtf8 = NULL; + int ret = -1; + + /* Current limitation of the function for VirtualBox 2.2.* is + * that the default hostonly network "vboxnet0" is always active + * and thus all this functions does is start the dhcp server, + * but the network can still be used without starting the dhcp + * server by giving the machine static IP + */ + + if (virAsprintf(&networkNameUtf8, "HostInterfaceNetworking-%s", network->name) < 0) { + virReportOOMError(network->conn); + goto cleanup; + } + + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + PRUnichar *networkInterfaceNameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; + + data->pFuncs->pfnUtf8ToUtf16(network->name, &networkInterfaceNameUtf16); + + host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface); + + if (networkInterface) { + PRUint32 interfaceType = 0; + + networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + PRUnichar *networkNameUtf16 = NULL; + IDHCPServer *dhcpServer = NULL; + + + data->pFuncs->pfnUtf8ToUtf16(networkNameUtf8 , &networkNameUtf16); + + data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj, + networkNameUtf16, + &dhcpServer); + if (dhcpServer) { + PRUnichar *trunkTypeUtf16 = NULL; + + dhcpServer->vtbl->SetEnabled(dhcpServer, PR_TRUE); + + data->pFuncs->pfnUtf8ToUtf16("netflt", &trunkTypeUtf16); + + dhcpServer->vtbl->Start(dhcpServer, + networkNameUtf16, + networkInterfaceNameUtf16, + trunkTypeUtf16); + + data->pFuncs->pfnUtf16Free(trunkTypeUtf16); + dhcpServer->vtbl->nsisupports.Release((nsISupports *) dhcpServer); + } + + data->pFuncs->pfnUtf16Free(networkNameUtf16); + } + + networkInterface->vtbl->nsisupports.Release((nsISupports *) networkInterface); + } + + data->pFuncs->pfnUtf16Free(networkInterfaceNameUtf16); + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + + ret = 0; + +cleanup: + VIR_FREE(networkNameUtf8); + return ret; +} + +static int vboxNetworkDestroy(virNetworkPtr network) { + vboxGlobalData *data = network->conn->privateData; + char *networkNameUtf8 = NULL; + int ret = -1; + + /* Current limitation of the function for VirtualBox 2.2.* is + * that the default hostonly network "vboxnet0" is always active + * and thus all this functions does is stop the dhcp server, + * but the network can still be used without the dhcp server + * by giving the machine static IP + */ + + if (virAsprintf(&networkNameUtf8, "HostInterfaceNetworking-%s", network->name) < 0) { + virReportOOMError(network->conn); + goto cleanup; + } + + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + PRUnichar *networkInterfaceNameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; + + data->pFuncs->pfnUtf8ToUtf16(network->name, &networkInterfaceNameUtf16); + + host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface); + + if (networkInterface) { + PRUint32 interfaceType = 0; + + networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + PRUnichar *networkNameUtf16 = NULL; + IDHCPServer *dhcpServer = NULL; + + + data->pFuncs->pfnUtf8ToUtf16(networkNameUtf8 , &networkNameUtf16); + + data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj, + networkNameUtf16, + &dhcpServer); + if (dhcpServer) { + + dhcpServer->vtbl->SetEnabled(dhcpServer, PR_FALSE); + + dhcpServer->vtbl->Stop(dhcpServer); + + dhcpServer->vtbl->nsisupports.Release((nsISupports *) dhcpServer); + } + + data->pFuncs->pfnUtf16Free(networkNameUtf16); + } + + networkInterface->vtbl->nsisupports.Release((nsISupports *) networkInterface); + } + + data->pFuncs->pfnUtf16Free(networkInterfaceNameUtf16); + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + + ret = 0; + +cleanup: + VIR_FREE(networkNameUtf8); + return ret; +} + +static char *vboxNetworkDumpXML(virNetworkPtr network, int flags ATTRIBUTE_UNUSED) { + vboxGlobalData *data = network->conn->privateData; + virNetworkDefPtr def = NULL; + char *ret = NULL; + char *networkNameUtf8 = NULL; + + if (VIR_ALLOC(def) < 0) { + virReportOOMError(network->conn); + goto cleanup; + } + + if (virAsprintf(&networkNameUtf8, "HostInterfaceNetworking-%s", network->name) < 0) { + virReportOOMError(network->conn); + goto cleanup; + } + + if (data->vboxObj) { + IHost *host = NULL; + + data->vboxObj->vtbl->GetHost(data->vboxObj, &host); + if (host) { + PRUnichar *networkInterfaceNameUtf16 = NULL; + IHostNetworkInterface *networkInterface = NULL; + + data->pFuncs->pfnUtf8ToUtf16(network->name, &networkInterfaceNameUtf16); + + host->vtbl->FindHostNetworkInterfaceByName(host, networkInterfaceNameUtf16, &networkInterface); + + if (networkInterface) { + PRUint32 interfaceType = 0; + + networkInterface->vtbl->GetInterfaceType(networkInterface, &interfaceType); + + if (interfaceType == HostNetworkInterfaceType_HostOnly) { + def->name = strdup(network->name); + if (def->name != NULL) { + nsID *vboxnet0IID = NULL; + PRUnichar *networkNameUtf16 = NULL; + IDHCPServer *dhcpServer = NULL; + + data->pFuncs->pfnUtf8ToUtf16(networkNameUtf8 , &networkNameUtf16); + + networkInterface->vtbl->GetId(networkInterface, &vboxnet0IID); + + nsIDtoChar(def->uuid, vboxnet0IID); + + def->forwardType = VIR_NETWORK_FORWARD_NONE; + + data->vboxObj->vtbl->FindDHCPServerByNetworkName(data->vboxObj, + networkNameUtf16, + &dhcpServer); + if (dhcpServer) { + def->nranges = 1; + if (VIR_ALLOC_N(def->ranges, def->nranges) >=0 ) { + PRUnichar *ipAddressUtf16 = NULL; + PRUnichar *networkMaskUtf16 = NULL; + PRUnichar *fromIPAddressUtf16 = NULL; + PRUnichar *toIPAddressUtf16 = NULL; + + dhcpServer->vtbl->GetIPAddress(dhcpServer, &ipAddressUtf16); + dhcpServer->vtbl->GetNetworkMask(dhcpServer, &networkMaskUtf16); + dhcpServer->vtbl->GetLowerIP(dhcpServer, &fromIPAddressUtf16); + dhcpServer->vtbl->GetUpperIP(dhcpServer, &toIPAddressUtf16); + /* Currently virtualbox supports only one dhcp server per network + * with contigious address space from start to end + */ + data->pFuncs->pfnUtf16ToUtf8(ipAddressUtf16, &def->ipAddress); + data->pFuncs->pfnUtf16ToUtf8(networkMaskUtf16, &def->netmask); + data->pFuncs->pfnUtf16ToUtf8(fromIPAddressUtf16, &def->ranges[0].start); + data->pFuncs->pfnUtf16ToUtf8(toIPAddressUtf16, &def->ranges[0].end); + + data->pFuncs->pfnUtf16Free(ipAddressUtf16); + data->pFuncs->pfnUtf16Free(networkMaskUtf16); + data->pFuncs->pfnUtf16Free(fromIPAddressUtf16); + data->pFuncs->pfnUtf16Free(toIPAddressUtf16); + } else { + def->nranges = 0; + } + + def->nhosts = 1; + if (VIR_ALLOC_N(def->hosts, def->nhosts) >=0 ) { + def->hosts[0].name = strdup(network->name); + if (def->hosts[0].name == NULL) { + VIR_FREE(def->hosts); + def->nhosts = 0; + vboxError(network->conn, + VIR_ERR_SYSTEM_ERROR, + "%s", "strdup failed"); + } else { + PRUnichar *macAddressUtf16 = NULL; + PRUnichar *ipAddressUtf16 = NULL; + + networkInterface->vtbl->GetHardwareAddress(networkInterface, &macAddressUtf16); + networkInterface->vtbl->GetIPAddress(networkInterface, &ipAddressUtf16); + + data->pFuncs->pfnUtf16ToUtf8(macAddressUtf16, &def->hosts[0].mac); + data->pFuncs->pfnUtf16ToUtf8(ipAddressUtf16, &def->hosts[0].ip); + + data->pFuncs->pfnUtf16Free(macAddressUtf16); + data->pFuncs->pfnUtf16Free(ipAddressUtf16); + } + } else { + def->nhosts = 0; + } + + dhcpServer->vtbl->nsisupports.Release((nsISupports *) dhcpServer); + } else { + PRUnichar *networkMaskUtf16 = NULL; + PRUnichar *ipAddressUtf16 = NULL; + + networkInterface->vtbl->GetNetworkMask(networkInterface, &networkMaskUtf16); + networkInterface->vtbl->GetIPAddress(networkInterface, &ipAddressUtf16); + + data->pFuncs->pfnUtf16ToUtf8(networkMaskUtf16, &def->netmask); + data->pFuncs->pfnUtf16ToUtf8(ipAddressUtf16, &def->ipAddress); + + data->pFuncs->pfnUtf16Free(networkMaskUtf16); + data->pFuncs->pfnUtf16Free(ipAddressUtf16); + } + + + DEBUG("Network UUID: " + "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + (unsigned)vboxnet0IID->m0, (unsigned)vboxnet0IID->m1, + (unsigned)vboxnet0IID->m2, (unsigned)vboxnet0IID->m3[0], + (unsigned)vboxnet0IID->m3[1], (unsigned)vboxnet0IID->m3[2], + (unsigned)vboxnet0IID->m3[3], (unsigned)vboxnet0IID->m3[4], + (unsigned)vboxnet0IID->m3[5], (unsigned)vboxnet0IID->m3[6], + (unsigned)vboxnet0IID->m3[7]); + + data->pFuncs->pfnComUnallocMem(vboxnet0IID); + data->pFuncs->pfnUtf16Free(networkNameUtf16); + } else { + vboxError(network->conn, VIR_ERR_SYSTEM_ERROR, + "%s", "strdup failed"); + } + } + + networkInterface->vtbl->nsisupports.Release((nsISupports *) networkInterface); + } + + data->pFuncs->pfnUtf16Free(networkInterfaceNameUtf16); + host->vtbl->nsisupports.Release((nsISupports *) host); + } + } + + ret = virNetworkDefFormat(network->conn, def); + +cleanup: + VIR_FREE(networkNameUtf8); + return ret; +} + + +/** + * Function Tables + */ + virDriver NAME(Driver) = { VIR_DRV_VBOX, "VBOX", @@ -3943,3 +4961,24 @@ virDriver NAME(Driver) = { .domainMigratePrepare2 = NULL, .domainMigrateFinish2 = NULL, }; + +virNetworkDriver NAME(NetworkDriver) = { + "VBOX", + .open = vboxNetworkOpen, + .close = vboxNetworkClose, + .numOfNetworks = vboxNumOfNetworks, + .listNetworks = vboxListNetworks, + .numOfDefinedNetworks = vboxNumOfDefinedNetworks, + .listDefinedNetworks = vboxListDefinedNetworks, + .networkLookupByUUID = vboxNetworkLookupByUUID, + .networkLookupByName = vboxNetworkLookupByName, + .networkCreateXML = vboxNetworkCreateXML, + .networkDefineXML = vboxNetworkDefineXML, + .networkUndefine = vboxNetworkUndefine, + .networkCreate = vboxNetworkCreate, + .networkDestroy = vboxNetworkDestroy, + .networkDumpXML = vboxNetworkDumpXML, + .networkGetBridgeName = NULL, + .networkGetAutostart = NULL, + .networkSetAutostart = NULL +};