Changeset 2382 in vbox for trunk/src/VBox/Main
- Timestamp:
- Apr 27, 2007 7:50:36 AM (18 years ago)
- svn:sync-xref-src-repo-rev:
- 20786
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/ConsoleImpl.cpp
r2358 r2382 26 26 # include <sys/poll.h> 27 27 # include <sys/fcntl.h> 28 # include <sys/types.h> 29 # include <sys/wait.h> 28 30 # include <net/if.h> 29 31 # include <linux/if_tun.h> 32 # include <stdio.h> 33 # include <stdlib.h> 34 # include <string.h> 30 35 #endif 31 36 … … 5558 5563 5559 5564 /** 5565 * Call the initialisation script for a dynamic TAP interface. 5566 * 5567 * The initialisation script should create a TAP interface, set it up and write its name to 5568 * standard output followed by a carriage return. Anything further written to standard 5569 * output will be ignored. If it returns a non-zero exit code, or does not write an 5570 * intelligable interface name to standard output, it will be treated as having failed. 5571 * For now, this method only works on Linux. 5572 * 5573 * @returns COM status code 5574 * @param tapDevice string to store the name of the tap device created to 5575 * @param tapSetupApplication the name of the setup script 5576 */ 5577 HRESULT Console::callTapSetupApplication(Bstr &tapDevice, Bstr &tapSetupApplication) 5578 { 5579 LogFlowThisFunc(("\n")); 5580 #ifdef __LINUX__ 5581 /* Command line to start the script with. */ 5582 const char *pszArgs; 5583 /* Buffer to read the script output to. It doesn't have to be long, as we are only 5584 interested in the first few (normally 5 or 6) bytes. */ 5585 char acBuffer[64]; 5586 /* The size of the string returned by the script. We only accept strings of 63 characters 5587 or less. */ 5588 size_t cBufSize; 5589 /* Result code */ 5590 int rc; 5591 5592 /* Get the script name. */ 5593 Utf8Str tapSetupApp(tapSetupApplication); 5594 pszArgs = tapSetupApp.raw(); 5595 /* 5596 * Create the process and read its output. 5597 */ 5598 FILE *pfScriptHandle = popen(pszArgs, "r"); 5599 if (pfScriptHandle == 0) 5600 { 5601 int iErr = errno; 5602 Log(("Failed to start the TAP interface setup script %s, error text: %s\n", 5603 pszArgs, strerror(iErr))); 5604 LogFlowThisFunc(("rc=E_FAIL\n")); 5605 return setError(E_FAIL, "Failed to start the TAP interface setup script %s, error text: %s\n", 5606 pszArgs, strerror(iErr)); 5607 } 5608 fgets(acBuffer, sizeof(acBuffer), pfScriptHandle); 5609 cBufSize = strlen(acBuffer); 5610 /* The script must return the name of the interface followed by a carriage return as the 5611 first line of its output. We need a null-terminated string. */ 5612 if ((cBufSize < 2) || (acBuffer[cBufSize - 1] != '\n')) 5613 { 5614 pclose(pfScriptHandle); 5615 Log(("The TAP interface setup script did not return the name of a TAP device.\n")); 5616 LogFlowThisFunc(("rc=E_FAIL\n")); 5617 return setError(E_FAIL, "The TAP interface setup script did not return the name of a TAP device.\n"); 5618 } 5619 acBuffer[cBufSize - 1] = 0; 5620 tapDevice = acBuffer; 5621 rc = pclose(pfScriptHandle); 5622 if (!WIFEXITED(rc)) 5623 { 5624 Log(("The TAP interface setup script terminated abnormally.\n")); 5625 LogFlowThisFunc(("rc=E_FAIL\n")); 5626 return setError(E_FAIL, "The TAP interface setup script terminated abnormally.\n"); 5627 } 5628 if (WEXITSTATUS(rc) != 0) 5629 { 5630 Log(("The TAP interface setup script returned a non-zero exit code.\n")); 5631 LogFlowThisFunc(("rc=E_FAIL\n")); 5632 return setError(E_FAIL, "The TAP interface setup script returned a non-zero exit code.\n"); 5633 } 5634 LogFlowThisFunc(("rc=S_OK\n")); 5635 return S_OK; 5636 #else /* __LINUX__ not defined */ 5637 LogFlowThisFunc(("rc=E_NOTIMPL\n")); 5638 return E_NOTIMPL; /* not yet supported */ 5639 #endif 5640 } 5641 5642 /** 5560 5643 * Helper function to handle host interface device creation and attachment. 5561 5644 * … … 5567 5650 HRESULT Console::attachToHostInterface(INetworkAdapter *networkAdapter) 5568 5651 { 5652 LogFlowThisFunc(("\n")); 5569 5653 /* sanity check */ 5570 5654 AssertReturn (isLockedOnCurrentThread(), E_FAIL); … … 5623 5707 struct ifreq IfReq; 5624 5708 memset(&IfReq, 0, sizeof(IfReq)); 5625 Bstr tapDeviceName; 5709 /* The name of the TAP interface we are using and the TAP setup script resp. */ 5710 Bstr tapDeviceName, tapSetupApplication; 5626 5711 rc = networkAdapter->COMGETTER(HostInterface)(tapDeviceName.asOutParam()); 5627 5712 if (FAILED(rc) || tapDeviceName.isEmpty()) 5628 strcpy(IfReq.ifr_name, "tap%d"); 5629 else 5713 { 5714 networkAdapter->COMGETTER(TAPSetupApplication)(tapSetupApplication.asOutParam()); 5715 if (tapSetupApplication.isEmpty()) 5716 { 5717 Log(("No setup application was supplied for the TAP interface.\n")); 5718 rc = setError(E_FAIL, "No setup application was supplied for the TAP interface.\n"); 5719 } 5720 else 5721 { 5722 rc = callTapSetupApplication(tapDeviceName, tapSetupApplication); 5723 } 5724 } 5725 if (SUCCEEDED(rc)) 5630 5726 { 5631 5727 Utf8Str str(tapDeviceName); … … 5634 5730 else 5635 5731 memcpy(IfReq.ifr_name, str.raw(), sizeof(IfReq.ifr_name) - 1); /** @todo bitch about names which are too long... */ 5636 } 5637 IfReq.ifr_flags = IFF_TAP | IFF_NO_PI; 5638 rcVBox = ioctl(maTapFD[slot], TUNSETIFF, &IfReq); 5639 if (!rcVBox) 5640 { 5641 /* 5642 * Make it pollable. 5643 */ 5644 if (fcntl(maTapFD[slot], F_SETFL, O_NONBLOCK) != -1) 5732 IfReq.ifr_flags = IFF_TAP | IFF_NO_PI; 5733 rcVBox = ioctl(maTapFD[slot], TUNSETIFF, &IfReq); 5734 if (!rcVBox) 5645 5735 { 5646 tapDeviceName = IfReq.ifr_name; 5647 if (tapDeviceName) 5736 /* 5737 * Make it pollable. 5738 */ 5739 if (fcntl(maTapFD[slot], F_SETFL, O_NONBLOCK) != -1) 5648 5740 { 5649 Log(("attachToHostInterface: %RTfile %ls\n", maTapFD[slot], tapDeviceName.raw())); 5650 5651 /* 5652 * Here is the right place to communicate the TAP file descriptor and 5653 * the host interface name to the server if/when it becomes really 5654 * necessary. 5655 */ 5656 maTAPDeviceName[slot] = tapDeviceName; 5657 rcVBox = VINF_SUCCESS; 5658 rc = S_OK; 5741 tapDeviceName = IfReq.ifr_name; 5742 if (tapDeviceName) 5743 { 5744 Log(("attachToHostInterface: %RTfile %ls\n", maTapFD[slot], tapDeviceName.raw())); 5745 5746 /* 5747 * Here is the right place to communicate the TAP file descriptor and 5748 * the host interface name to the server if/when it becomes really 5749 * necessary. 5750 */ 5751 maTAPDeviceName[slot] = tapDeviceName; 5752 rcVBox = VINF_SUCCESS; 5753 rc = S_OK; 5754 } 5755 else 5756 rcVBox = VERR_NO_MEMORY; 5659 5757 } 5660 5758 else 5661 rcVBox = VERR_NO_MEMORY; 5759 { 5760 AssertMsgFailed(("Configuration error: Failed to configure /dev/net/tun non blocking. errno=%d\n", errno)); 5761 rcVBox = VERR_HOSTIF_BLOCKING; 5762 rc = setError(E_FAIL, "Failed to set /dev/net/tun to non blocking. errno=%d\n", errno); 5763 } 5662 5764 } 5663 5765 else 5664 5766 { 5665 AssertMsgFailed(("Configuration error: Failed to configure /dev/net/tun non blocking. errno=%d\n", errno));5666 rcVBox = VERR_HOSTIF_ BLOCKING;5667 rc = setError(E_FAIL, "Failed to set /dev/net/tun to non blocking. errno=%d\n", errno);5767 AssertMsgFailed(("Configuration error: Failed to configure /dev/net/tun. errno=%d\n", errno)); 5768 rcVBox = VERR_HOSTIF_IOCTL; 5769 rc = setError(E_FAIL, "Failed to configure /dev/net/tun. errno = %d\n", errno); 5668 5770 } 5669 }5670 else5671 {5672 AssertMsgFailed(("Configuration error: Failed to configure /dev/net/tun. errno=%d\n", errno));5673 rcVBox = VERR_HOSTIF_IOCTL;5674 rc = setError(E_FAIL, "Failed to configure /dev/net/tun. errno = %d\n", errno);5675 5771 } 5676 5772 } … … 5703 5799 } 5704 5800 } 5705 #ifdef VBOX_WITH_UNIXY_TAP_NETWORKING 5706 if (SUCCEEDED(rc)) 5707 { 5708 /* 5709 * Call the initialization program. 5710 * 5711 * The initialization program is passed the device name as the first param. 5712 * The second parameter is the decimal value of the file handle of the device 5713 * which it inherits. 5714 */ 5715 Bstr tapSetupApplication; 5716 networkAdapter->COMGETTER(TAPSetupApplication)(tapSetupApplication.asOutParam()); 5717 if (tapSetupApplication) 5718 { 5719 /* 5720 * Create the argument list. 5721 */ 5722 const char *apszArgs[4]; 5723 /* 0. The program name. */ 5724 Utf8Str tapSetupApp(tapSetupApplication); 5725 apszArgs[0] = tapSetupApp.raw(); 5726 5727 /* 1. The file descriptor. */ 5728 char szFD[32]; 5729 RTStrPrintf(szFD, sizeof(szFD), "%RTfile", maTapFD[slot]); 5730 apszArgs[1] = szFD; 5731 5732 /* 2. The device name (optional). */ 5733 apszArgs[2] = maTAPDeviceName[slot].isEmpty() ? NULL : maTAPDeviceName[slot].raw(); 5734 5735 /* 3. The end. */ 5736 apszArgs[3] = NULL; 5737 5738 /* 5739 * Create the process and wait for it to complete. 5740 */ 5741 RTPROCESS Process; 5742 int rcVBox = RTProcCreate(apszArgs[0], &apszArgs[0], NULL, 0, &Process); 5743 if (VBOX_SUCCESS(rcVBox)) 5744 { 5745 /* wait for the process to exit */ 5746 RTPROCSTATUS ProcStatus; 5747 rcVBox = RTProcWait(Process, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus); 5748 AssertRC(rcVBox); 5749 if (VBOX_SUCCESS(rcVBox)) 5750 { 5751 if ( ProcStatus.enmReason == RTPROCEXITREASON_NORMAL 5752 && ProcStatus.iStatus == 0) 5753 rcVBox = VINF_SUCCESS; 5754 else 5755 rcVBox = VMSetError(mpVM, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, N_("Failed to initialize Host Interface Networking")); 5756 } 5757 } 5758 else 5759 { 5760 AssertMsgFailed(("Configuration error: Failed to start init program \"%s\", rc=%Vra\n", tapSetupApp.raw(), rcVBox)); 5761 rc = setError(E_FAIL, "Failed to start init program \"%s\", rc = %Vra\n", tapSetupApp.raw(), rcVBox); 5762 } 5763 5764 /* in case of failure, cleanup. */ 5765 if (VBOX_FAILURE(rcVBox) && SUCCEEDED(rc)) 5766 { 5767 rc = setError(E_FAIL, tr ("General failure configuring Host Interface Networking")); 5768 } 5769 } 5770 } 5771 #endif /* VBOX_WITH_UNIXY_TAP_NETWORKING */ 5801 LogFlowThisFunc(("rc=%d\n", rc)); 5772 5802 return rc; 5773 5803 } 5774 5804 5775 /** 5776 * Helper function to handle detachment from a host interface 5777 * 5778 * @param networkAdapter the network adapter which attachment should be reset 5779 * @return COM status code 5780 * 5781 * @note The caller must lock this object for writing. 5782 */ 5805 #if 0 5806 /* Old code for this function. */ 5783 5807 HRESULT Console::detachFromHostInterface(INetworkAdapter *networkAdapter) 5784 5808 { … … 5858 5882 } 5859 5883 #endif 5884 return rc; 5885 } 5886 #endif 5887 5888 /** 5889 * Helper function to handle detachment from a host interface 5890 * 5891 * @param networkAdapter the network adapter which attachment should be reset 5892 * @return COM status code 5893 * 5894 * @note The caller must lock this object for writing. 5895 */ 5896 HRESULT Console::detachFromHostInterface(INetworkAdapter *networkAdapter) 5897 { 5898 /* sanity check */ 5899 LogFlowThisFunc(("\n")); 5900 AssertReturn (isLockedOnCurrentThread(), E_FAIL); 5901 5902 HRESULT rc = S_OK; 5903 #ifdef DEBUG 5904 /* paranoia */ 5905 NetworkAttachmentType_T attachment; 5906 networkAdapter->COMGETTER(AttachmentType)(&attachment); 5907 Assert(attachment == NetworkAttachmentType_HostInterfaceNetworkAttachment); 5908 #endif /* DEBUG */ 5909 5910 #ifdef VBOX_WITH_UNIXY_TAP_NETWORKING 5911 5912 ULONG slot = 0; 5913 rc = networkAdapter->COMGETTER(Slot)(&slot); 5914 AssertComRC(rc); 5915 5916 /* is there an open TAP device? */ 5917 if (maTapFD[slot] != NIL_RTFILE) 5918 { 5919 /* 5920 * Close the file handle. 5921 */ 5922 int rcVBox = RTFileClose(maTapFD[slot]); 5923 AssertRC(rcVBox); 5924 /* 5925 * Execute the termination command. 5926 */ 5927 Bstr tapTerminateApplication; 5928 networkAdapter->COMGETTER(TAPTerminateApplication)(tapTerminateApplication.asOutParam()); 5929 if (tapTerminateApplication) 5930 { 5931 /* Get the program name. */ 5932 Utf8Str tapTermAppUtf8(tapTerminateApplication); 5933 5934 /* Build the command line. */ 5935 char szCommand[4096]; 5936 RTStrPrintf(szCommand, sizeof(szCommand), "%s %RTfile %s", tapTermAppUtf8.raw(), 5937 maTapFD[slot], 5938 maTAPDeviceName[slot].isEmpty() ? "" : maTAPDeviceName[slot].raw()); 5939 5940 /* 5941 * Create the process and wait for it to complete. 5942 */ 5943 Log(("Calling the termination command: %s\n", szCommand)); 5944 int rcCommand = system(szCommand); 5945 if (rcCommand == -1) 5946 { 5947 Log(("Failed to execute the clean up script for the TAP interface")); 5948 rc = setError(E_FAIL, tr ("Failed to execute the clean up script for the TAP interface")); 5949 } 5950 if (!WIFEXITED(rc)) 5951 { 5952 Log(("The TAP interface clean up script terminated abnormally.\n")); 5953 rc = setError(E_FAIL, "The TAP interface clean up script terminated abnormally.\n"); 5954 } 5955 if (WEXITSTATUS(rc) != 0) 5956 { 5957 Log(("The TAP interface clean up script returned a non-zero exit code.\n")); 5958 rc = setError(E_FAIL, "The TAP interface clean up script returned a non-zero exit code.\n"); 5959 } 5960 } 5961 5962 /* the TAP device name and handle are no longer valid */ 5963 maTapFD[slot] = NIL_RTFILE; 5964 maTAPDeviceName[slot] = ""; 5965 } 5966 #endif 5967 LogFlowThisFunc(("returning %d\n", rc)); 5860 5968 return rc; 5861 5969 } -
trunk/src/VBox/Main/include/ConsoleImpl.h
r2333 r2382 340 340 HRESULT powerDown(); 341 341 342 HRESULT callTapSetupApplication(Bstr &tapDevice, Bstr &tapSetupApplication); 342 343 HRESULT attachToHostInterface(INetworkAdapter *networkAdapter); 343 344 HRESULT detachFromHostInterface(INetworkAdapter *networkAdapter);
Note:
See TracChangeset
for help on using the changeset viewer.