- Timestamp:
- May 2, 2007 4:03:55 PM (18 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/ConsoleImpl.cpp
r2396 r2453 5619 5619 * @param tapSetupApplication the name of the setup script 5620 5620 */ 5621 HRESULT Console::callTapSetupApplication(Bstr &tapDevice, Bstr &tapSetupApplication) 5621 HRESULT Console::callTapSetupApplication(bool isStatic, RTFILE tapFD, Bstr &tapDevice, 5622 Bstr &tapSetupApplication) 5622 5623 { 5623 5624 LogFlowThisFunc(("\n")); 5624 5625 #ifdef __LINUX__ 5625 5626 /* Command line to start the script with. */ 5626 const char *pszArgs; 5627 /* Buffer to read the script output to. It doesn't have to be long, as we are only 5628 interested in the first few (normally 5 or 6) bytes. */ 5629 char acBuffer[64]; 5630 /* The size of the string returned by the script. We only accept strings of 63 characters 5631 or less. */ 5632 size_t cBufSize; 5627 char szCommand[4096]; 5633 5628 /* Result code */ 5634 5629 int rc; 5635 5630 5636 5631 /* Get the script name. */ 5637 Utf8Str tapSetupApp(tapSetupApplication); 5638 pszArgs = tapSetupApp.raw(); 5632 Utf8Str tapSetupAppUtf8(tapSetupApplication), tapDeviceUtf8(tapDevice); 5633 RTStrPrintf(szCommand, sizeof(szCommand), "%s %d %s", tapSetupAppUtf8.raw(), 5634 isStatic ? tapFD : 0, isStatic ? tapDeviceUtf8.raw() : ""); 5639 5635 /* 5640 5636 * Create the process and read its output. 5641 5637 */ 5642 FILE *pfScriptHandle = popen(pszArgs, "r"); 5638 Log2(("About to start the TAP setup script with the following command line: %s\n", 5639 szCommand)); 5640 FILE *pfScriptHandle = popen(szCommand, "r"); 5643 5641 if (pfScriptHandle == 0) 5644 5642 { 5645 5643 int iErr = errno; 5646 5644 Log(("Failed to start the TAP interface setup script %s, error text: %s\n", 5647 pszArgs, strerror(iErr)));5645 szCommand, strerror(iErr))); 5648 5646 LogFlowThisFunc(("rc=E_FAIL\n")); 5649 5647 return setError(E_FAIL, tr ("Failed to run the host networking set up command %s: %s"), 5650 pszArgs, strerror(iErr)); 5651 } 5652 fgets(acBuffer, sizeof(acBuffer), pfScriptHandle); 5653 cBufSize = strlen(acBuffer); 5654 /* The script must return the name of the interface followed by a carriage return as the 5655 first line of its output. We need a null-terminated string. */ 5656 if ((cBufSize < 2) || (acBuffer[cBufSize - 1] != '\n')) 5657 { 5658 pclose(pfScriptHandle); 5659 Log(("The TAP interface setup script did not return the name of a TAP device.\n")); 5660 LogFlowThisFunc(("rc=E_FAIL\n")); 5661 return setError(E_FAIL, tr ("The host networking set up command did not supply an interface name")); 5662 } 5663 acBuffer[cBufSize - 1] = 0; 5664 tapDevice = acBuffer; 5648 szCommand, strerror(iErr)); 5649 } 5650 /* If we are using a dynamic TAP interface, we need to get the interface name. */ 5651 if (!isStatic) 5652 { 5653 /* Buffer to read the application output to. It doesn't have to be long, as we are only 5654 interested in the first few (normally 5 or 6) bytes. */ 5655 char acBuffer[64]; 5656 /* The length of the string returned by the application. We only accept strings of 63 5657 characters or less. */ 5658 size_t cBufSize; 5659 5660 /* Read the name of the device from the application. */ 5661 fgets(acBuffer, sizeof(acBuffer), pfScriptHandle); 5662 cBufSize = strlen(acBuffer); 5663 /* The script must return the name of the interface followed by a carriage return as the 5664 first line of its output. We need a null-terminated string. */ 5665 if ((cBufSize < 2) || (acBuffer[cBufSize - 1] != '\n')) 5666 { 5667 pclose(pfScriptHandle); 5668 Log(("The TAP interface setup script did not return the name of a TAP device.\n")); 5669 LogFlowThisFunc(("rc=E_FAIL\n")); 5670 return setError(E_FAIL, tr ("The host networking set up command did not supply an interface name")); 5671 } 5672 /* Overwrite the terminating newline character. */ 5673 acBuffer[cBufSize - 1] = 0; 5674 tapDevice = acBuffer; 5675 } 5665 5676 rc = pclose(pfScriptHandle); 5666 5677 if (!WIFEXITED(rc)) … … 5749 5760 * Set/obtain the tap interface. 5750 5761 */ 5762 bool isStatic = false; 5751 5763 struct ifreq IfReq; 5752 5764 memset(&IfReq, 0, sizeof(IfReq)); … … 5754 5766 Bstr tapDeviceName, tapSetupApplication; 5755 5767 rc = networkAdapter->COMGETTER(HostInterface)(tapDeviceName.asOutParam()); 5756 if (FAILED(rc) || tapDeviceName.isEmpty())5768 if (FAILED(rc)) 5757 5769 { 5758 networkAdapter->COMGETTER(TAPSetupApplication)(tapSetupApplication.asOutParam()); 5759 if (tapSetupApplication.isEmpty()) 5760 { 5761 Log(("No setup application was supplied for the TAP interface.\n")); 5762 rc = setError(E_FAIL, tr ("No setup application was supplied for the host networking interface")); 5763 } 5764 else 5765 { 5766 rc = callTapSetupApplication(tapDeviceName, tapSetupApplication); 5767 } 5770 tapDeviceName.setNull(); /* Is this necessary? */ 5768 5771 } 5769 if (SUCCEEDED(rc))5772 else if (!tapDeviceName.isEmpty()) 5770 5773 { 5774 isStatic = true; 5775 /* If we are using a static TAP device then try to open it. */ 5771 5776 Utf8Str str(tapDeviceName); 5772 5777 if (str.length() <= sizeof(IfReq.ifr_name)) … … 5776 5781 IfReq.ifr_flags = IFF_TAP | IFF_NO_PI; 5777 5782 rcVBox = ioctl(maTapFD[slot], TUNSETIFF, &IfReq); 5778 if (!rcVBox) 5783 if (rcVBox != 0) 5784 { 5785 Log(("Failed to open the host network interface %ls\n", tapDeviceName.raw())); 5786 rc = setError(E_FAIL, tr ("Failed to open the host network interface %ls"), 5787 tapDeviceName.raw()); 5788 } 5789 } 5790 if (SUCCEEDED(rc)) 5791 { 5792 networkAdapter->COMGETTER(TAPSetupApplication)(tapSetupApplication.asOutParam()); 5793 if (tapSetupApplication.isEmpty()) 5794 { 5795 if (tapDeviceName.isEmpty()) 5796 { 5797 Log(("No setup application was supplied for the TAP interface.\n")); 5798 rc = setError(E_FAIL, tr ("No setup application was supplied for the host networking interface")); 5799 } 5800 } 5801 else 5802 { 5803 rc = callTapSetupApplication(isStatic, maTapFD[slot], tapDeviceName, 5804 tapSetupApplication); 5805 } 5806 } 5807 if (SUCCEEDED(rc)) 5808 { 5809 if (!isStatic) 5810 { 5811 Utf8Str str(tapDeviceName); 5812 if (str.length() <= sizeof(IfReq.ifr_name)) 5813 strcpy(IfReq.ifr_name, str.raw()); 5814 else 5815 memcpy(IfReq.ifr_name, str.raw(), sizeof(IfReq.ifr_name) - 1); /** @todo bitch about names which are too long... */ 5816 IfReq.ifr_flags = IFF_TAP | IFF_NO_PI; 5817 rcVBox = ioctl(maTapFD[slot], TUNSETIFF, &IfReq); 5818 if (rcVBox != 0) 5819 { 5820 Log(("Failed to open the host network interface %ls returned by the setup script", tapDeviceName.raw())); 5821 rc = setError(E_FAIL, tr ("Failed to open the host network interface %ls returned by the setup script"), tapDeviceName.raw()); 5822 } 5823 } 5824 if (SUCCEEDED(rc)) 5779 5825 { 5780 5826 /* … … 5783 5829 if (fcntl(maTapFD[slot], F_SETFL, O_NONBLOCK) != -1) 5784 5830 { 5785 tapDeviceName = IfReq.ifr_name; 5786 if (tapDeviceName) 5787 { 5788 Log(("attachToHostInterface: %RTfile %ls\n", maTapFD[slot], tapDeviceName.raw())); 5789 5790 /* 5791 * Here is the right place to communicate the TAP file descriptor and 5792 * the host interface name to the server if/when it becomes really 5793 * necessary. 5794 */ 5795 maTAPDeviceName[slot] = tapDeviceName; 5796 rcVBox = VINF_SUCCESS; 5797 rc = S_OK; 5798 } 5799 else 5800 rcVBox = VERR_NO_MEMORY; 5831 Log(("attachToHostInterface: %RTfile %ls\n", maTapFD[slot], tapDeviceName.raw())); 5832 5833 /* 5834 * Here is the right place to communicate the TAP file descriptor and 5835 * the host interface name to the server if/when it becomes really 5836 * necessary. 5837 */ 5838 maTAPDeviceName[slot] = tapDeviceName; 5839 rcVBox = VINF_SUCCESS; 5801 5840 } 5802 5841 else … … 5807 5846 strerror(errno)); 5808 5847 } 5809 }5810 else5811 {5812 AssertMsgFailed(("Configuration error: Failed to configure /dev/net/tun. errno=%d\n", errno));5813 rcVBox = VERR_HOSTIF_IOCTL;5814 rc = setError(E_FAIL, tr ("Could not set up the host networking device: %s"),5815 strerror(errno));5816 5848 } 5817 5849 } … … 5883 5915 * Close the file handle. 5884 5916 */ 5885 int rcVBox = RTFileClose(maTapFD[slot]); 5886 AssertRC(rcVBox); 5917 Bstr tapDeviceName, tapTerminateApplication; 5918 bool isStatic = true; 5919 rc = networkAdapter->COMGETTER(HostInterface)(tapDeviceName.asOutParam()); 5920 if (FAILED(rc) || tapDeviceName.isEmpty()) 5921 { 5922 /* If the name is not empty, this is a dynamic TAP device, so close it now, 5923 so that the termination script can remove the interface. Otherwise we still 5924 need the FD to pass to the termination script. */ 5925 isStatic = false; 5926 int rcVBox = RTFileClose(maTapFD[slot]); 5927 AssertRC(rcVBox); 5928 maTapFD[slot] = NIL_RTFILE; 5929 } 5887 5930 /* 5888 5931 * Execute the termination command. 5889 5932 */ 5890 Bstr tapTerminateApplication;5891 5933 networkAdapter->COMGETTER(TAPTerminateApplication)(tapTerminateApplication.asOutParam()); 5892 5934 if (tapTerminateApplication) … … 5897 5939 /* Build the command line. */ 5898 5940 char szCommand[4096]; 5899 RTStrPrintf(szCommand, sizeof(szCommand), "%s % s", tapTermAppUtf8.raw(),5900 maTAPDeviceName[slot].isEmpty() ? "" :maTAPDeviceName[slot].raw());5941 RTStrPrintf(szCommand, sizeof(szCommand), "%s %d %s", tapTermAppUtf8.raw(), 5942 isStatic ? maTapFD[slot] : 0, maTAPDeviceName[slot].raw()); 5901 5943 5902 5944 /* … … 5922 5964 } 5923 5965 5966 if (isStatic) 5967 { 5968 /* If we are using a static TAP device, we close it now, after having called the 5969 termination script. */ 5970 int rcVBox = RTFileClose(maTapFD[slot]); 5971 AssertRC(rcVBox); 5972 } 5924 5973 /* the TAP device name and handle are no longer valid */ 5925 5974 maTapFD[slot] = NIL_RTFILE; -
trunk/src/VBox/Main/include/ConsoleImpl.h
r2386 r2453 340 340 HRESULT powerDown(); 341 341 342 HRESULT callTapSetupApplication(Bstr &tapDevice, Bstr &tapSetupApplication); 342 HRESULT callTapSetupApplication(bool isStatic, RTFILE tapFD, Bstr &tapDevice, 343 Bstr &tapSetupApplication); 343 344 HRESULT attachToHostInterface(INetworkAdapter *networkAdapter); 344 345 HRESULT detachFromHostInterface(INetworkAdapter *networkAdapter);
Note:
See TracChangeset
for help on using the changeset viewer.