Changeset 5126 in vbox for trunk/src/VBox/Devices/Network
- Timestamp:
- Oct 1, 2007 2:52:32 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/DrvTAP.cpp
r5013 r5126 22 22 *******************************************************************************/ 23 23 #define LOG_GROUP LOG_GROUP_DRV_TUN 24 #include <VBox/log.h> 24 25 #include <VBox/pdmdrv.h> 25 26 … … 27 28 #include <iprt/file.h> 28 29 #include <iprt/string.h> 30 #include <iprt/path.h> 29 31 #ifdef ASYNC_NET 30 32 # include <iprt/thread.h> … … 36 38 #include <sys/poll.h> 37 39 #ifdef RT_OS_SOLARIS 40 # include <sys/stat.h> 41 # include <sys/ethernet.h> 42 # include <sys/sockio.h> 43 # include <netinet/in.h> 44 # include <netinet/in_systm.h> 45 # include <netinet/ip.h> 46 # include <netinet/ip_icmp.h> 47 # include <netinet/udp.h> 48 # include <netinet/tcp.h> 49 # include <net/if.h> 50 # include <stropts.h> 38 51 # include <fcntl.h> 52 # include <ctype.h> 53 # include <stdlib.h> 39 54 #else 40 55 # include <sys/fcntl.h> … … 75 90 /** TAP device file handle. */ 76 91 RTFILE FileDevice; 92 /** The configured TAP device name. */ 93 char *pszDeviceName; 94 #ifdef RT_OS_SOLARIS 95 /** The actual TAP device name. */ 96 char *pszDeviceNameActual; 97 #endif 98 /** TAP setup application. */ 99 char *pszSetupApplication; 100 /** TAP terminate application. */ 101 char *pszTerminateApplication; 77 102 #ifdef ASYNC_NET 78 103 /** The write end of the control pipe. */ … … 119 144 /** Converts a pointer to TAP::INetworkConnector to a PRDVTAP. */ 120 145 #define PDMINETWORKCONNECTOR_2_DRVTAP(pInterface) ( (PDRVTAP)((uintptr_t)pInterface - RT_OFFSETOF(DRVTAP, INetworkConnector)) ) 146 147 148 /******************************************************************************* 149 * Internal Functions * 150 *******************************************************************************/ 151 #ifdef RT_OS_SOLARIS 152 static DECLCALLBACK(int) SolarisTAPAttach(PPDMDRVINS pDrvIns); 153 #endif 121 154 122 155 … … 415 448 416 449 450 #if defined(RT_OS_SOLARIS) 451 /** 452 * Calls OS-specific TAP setup application/script. 453 * 454 * @returns VBox error code. 455 * @param pData The instance data. 456 */ 457 static int drvTAPSetupApplication(PDRVTAP pData) 458 { 459 char *pszArgs[3]; 460 pszArgs[0] = pData->pszSetupApplication; 461 pszArgs[1] = pData->pszDeviceNameActual; 462 pszArgs[2] = NULL; 463 464 /** @todo use RTProcCreate */ 465 466 Log2(("Starting TAP setup application: %s %s\n", pData->pszSetupApplication, pData->pszDeviceNameActual)); 467 pid_t pid = fork(); 468 if (pid < 0) 469 { 470 /* Bad. fork() failed! */ 471 LogRel(("TAP#%d: Failed to fork() process for running TAP setup application: %s\n", pDrvIns->iInstance, 472 pData->pszSetupApplication, strerror(errno))); 473 return VERR_HOSTIF_INIT_FAILED; 474 } 475 if (pid == 0) 476 { 477 /* Child process. */ 478 execv(pszArgs[0], pszArgs); 479 _exit(1); 480 } 481 482 /* Parent process. */ 483 int result; 484 while (waitpid(pid, &result, 0) < 0) 485 ; 486 if (!WIFEXITED(result) || WEXITSTATUS(result) != 0) 487 { 488 LogRel(("TAP#%d: Failed to run TAP setup application: %s\n", pDrvIns->iInstance, pData->pszSetupApplication)); 489 return VERR_HOSTIF_INIT_FAILED; 490 } 491 492 return VINF_SUCCESS; 493 } 494 495 496 /** 497 * Calls OS-specific TAP terminate application/script. 498 * 499 * @returns VBox error code. 500 * @param pData The instance data. 501 */ 502 static int drvTAPTerminateApplication(PDRVTAP pData) 503 { 504 char *pszArgs[3]; 505 pszArgs[0] = pData->pszTerminateApplication; 506 pszArgs[1] = pData->pszDeviceNameActual; 507 pszArgs[2] = NULL; 508 509 /** @todo use RTProcCreate */ 510 511 Log2(("Starting TAP terminate application: %s %s\n", pData->pszTerminateApplication, pData->pszDeviceNameActual)); 512 pid_t pid = fork(); 513 if (pid < 0) 514 { 515 /* Bad. fork() failed! */ 516 LogRel(("TAP#%d: Failed to fork() process for running TAP terminate application: %s\n", pDrvIns->iInstance, 517 pData->pszTerminateApplication, strerror(errno))); 518 return VERR_HOSTIF_TERM_FAILED; 519 } 520 if (pid == 0) 521 { 522 /* Child process. */ 523 execv(pszArgs[0], pszArgs); 524 _exit(1); 525 } 526 527 /* Parent process. */ 528 int result; 529 while (waitpid(pid, &result, 0) < 0) 530 ; 531 if (!WIFEXITED(result) || WEXITSTATUS(result) != 0) 532 { 533 LogRel(("TAP#%d: Failed to run TAP terminate application: %s\n", pDrvIns->iInstance, pData->pszSetupApplication)); 534 return VERR_HOSTIF_TERM_FAILED; 535 } 536 537 return VINF_SUCCESS; 538 } 539 540 #endif /* RT_OS_SOLARIS */ 541 542 543 #ifdef RT_OS_SOLARIS 544 /** From net/if_tun.h, installed by Universal TUN/TAP driver */ 545 # define TUNNEWPPA (('T'<<16) | 0x0001) 546 /** Whether to enable ARP for TAP. */ 547 # define VBOX_SOLARIS_TAP_ARP 1 548 549 /** 550 * Creates/Attaches TAP device to IP. 551 * 552 * @returns VBox error code. 553 * @param pDrvIns The driver instance data. 554 * @param pszDevName Pointer to device name. 555 */ 556 static DECLCALLBACK(int) SolarisTAPAttach(PPDMDRVINS pDrvIns) 557 { 558 PDRVTAP pData = PDMINS2DATA(pDrvIns, PDRVTAP); 559 LogFlow(("SolarisTapAttach: pData=%p\n", pData)); 560 561 562 /* Close previously opened file desc., if any. */ 563 static int s_IPFileDes = -1; /** @todo r=bird: what's the point of keeping this open? */ 564 if (s_IPFileDes >= 0) 565 close(s_IPFileDes); 566 567 s_IPFileDes = open("/dev/udp", O_RDWR, 0); 568 if (s_IPFileDes < 0) 569 return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_HIF_OPEN_FAILED, RT_SRC_POS, 570 N_("Failed to open /dev/udp. errno=%d"), errno); 571 572 int TapFileDes = open("/dev/tap", O_RDWR, 0); 573 if (TapFileDes < 0) 574 return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_HIF_OPEN_FAILED, RT_SRC_POS, 575 N_("Failed to open /dev/tap for TAP. errno=%d"), errno); 576 577 /* Use the PPA from the ifname if possible (e.g "tap2", then use 2 as PPA) */ 578 int iPPA = -1; 579 if (pData->pszDeviceName) 580 { 581 size_t cch = strlen(pData->pszDeviceName); 582 if (cch > 1 && isdigit(pData->pszDeviceName[cch - 1]) != 0) 583 iPPA = pData->pszDeviceName[cch - 1] - '0'; 584 } 585 586 struct strioctl ioIF; 587 ioIF.ic_cmd = TUNNEWPPA; 588 ioIF.ic_len = sizeof(iPPA); 589 ioIF.ic_dp = (char *)(&iPPA); 590 ioIF.ic_timout = 0; 591 iPPA = ioctl(TapFileDes, I_STR, &ioIF); 592 if (iPPA < 0) /** @todo r=bird: leaving at least one file descriptor open. */ 593 return PDMDrvHlpVMSetError(pDrvIns, VERR_HOSTIF_IOCTL, RT_SRC_POS, 594 N_("Failed to get new interface. errno=%d"), errno); 595 596 int InterfaceFD = open("/dev/tap", O_RDWR, 0); 597 if (!InterfaceFD) 598 return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_HIF_OPEN_FAILED, RT_SRC_POS, 599 N_("Failed to open interface /dev/tap. errno=%d"), errno); 600 601 if (ioctl(InterfaceFD, I_PUSH, "ip") == -1) 602 { 603 close(InterfaceFD); 604 return PDMDrvHlpVMSetError(pDrvIns, VERR_HOSTIF_IOCTL, RT_SRC_POS, 605 N_("Failed to push IP. errno=%d"), errno); 606 } 607 608 struct lifreq ifReq; 609 memset(&ifReq, 0, sizeof(ifReq)); 610 if (ioctl(InterfaceFD, SIOCGLIFFLAGS, &ifReq) == -1) 611 LogRel(("TAP#%d: Failed to get interface flags.\n", pDrvIns->iInstance)); 612 613 char szTmp[16]; 614 char *pszDevName = pData->pszDeviceName; 615 if (!pData->pszDeviceName || !*pData->pszDeviceName) 616 { 617 RTStrPrintf(szTmp, sizeof(szTmp), "tap%d", iPPA); 618 pszDevName = szTmp; 619 } 620 621 ifReq.lifr_ppa = iPPA; 622 RTStrPrintf (ifReq.lifr_name, sizeof(ifReq.lifr_name), pszDevName); 623 624 if (ioctl(InterfaceFD, SIOCSLIFNAME, &ifReq) == -1) 625 LogRel(("TAP#%d: Failed to set PPA. errno=%d\n", pDrvIns->iInstance, errno)); 626 627 if (ioctl(InterfaceFD, SIOCGLIFFLAGS, &ifReq) == -1) 628 LogRel(("TAP#%d: Failed to get interface flags after setting PPA. errno=%d\n", pDrvIns->iInstance, errno)); 629 630 #ifdef VBOX_SOLARIS_TAP_ARP 631 /* Interface */ 632 if (ioctl(InterfaceFD, I_PUSH, "arp") == -1) 633 LogRel(("TAP#%d: Failed to push ARP to Interface FD. errno=%d\n", pDrvIns->iInstance, errno)); 634 635 /* IP */ 636 if (ioctl(s_IPFileDes, I_POP, NULL) == -1) 637 LogRel(("TAP#%d: Failed I_POP from IP FD. errno=%d\n", pDrvIns->iInstance, errno)); 638 639 if (ioctl(s_IPFileDes, I_PUSH, "arp") == -1) 640 LogRel(("TAP#%d: Failed to push ARP to IP FD. errno=%d\n", pDrvIns->iInstance, errno)); 641 642 /* ARP */ 643 int ARPFileDes = open("/dev/tap", O_RDWR, 0); 644 if (ARPFileDes < 0) 645 LogRel(("TAP#%d: Failed to open for /dev/tap for ARP. errno=%d", pDrvIns->iInstance, errno)); 646 647 if (ioctl(ARPFileDes, I_PUSH, "arp") == -1) 648 LogRel(("TAP#%d: Failed to push ARP to ARP FD. errno=%d\n", pDrvIns->iInstance, errno)); 649 650 ioIF.ic_cmd = SIOCSLIFNAME; 651 ioIF.ic_timout = 0; 652 ioIF.ic_len = sizeof(ifReq); 653 ioIF.ic_dp = (char *)&ifReq; 654 if (ioctl(ARPFileDes, I_STR, &ioIF) == -1) 655 LogRel(("TAP#%d: Failed to set interface name to ARP.\n", pDrvIns->iInstance)); 656 #endif 657 658 /* We must use I_LINK and not I_PLINK as I_PLINK makes the link persistent. 659 * Then we would not be able unlink the interface if we reuse it. 660 * Even 'unplumb' won't work after that. 661 */ 662 int IPMuxID = ioctl(s_IPFileDes, I_LINK, InterfaceFD); 663 if (IPMuxID == -1) 664 { 665 close(InterfaceFD); 666 #ifdef VBOX_SOLARIS_TAP_ARP 667 close(ARPFileDes); 668 #endif 669 LogRel(("TAP#%d: Cannot link TAP device to IP.\n", pDrvIns->iInstance)); 670 return PDMDrvHlpVMSetError(pDrvIns, VERR_HOSTIF_IOCTL, RT_SRC_POS, 671 N_("Failed to link TAP device to IP. Check TAP interface name. errno=%d"), errno); 672 } 673 674 #ifdef VBOX_SOLARIS_TAP_ARP 675 int ARPMuxID = ioctl(s_IPFileDes, I_LINK, ARPFileDes); 676 if (ARPMuxID == -1) 677 LogRel(("TAP#%d: Failed to link TAP device to ARP\n", pDrvIns->iInstance)); 678 679 close(ARPFileDes); 680 #endif 681 close(InterfaceFD); 682 683 /* Reuse ifReq */ 684 memset(&ifReq, 0, sizeof(ifReq)); 685 RTStrPrintf (ifReq.lifr_name, sizeof(ifReq.lifr_name), pszDevName); 686 ifReq.lifr_ip_muxid = IPMuxID; 687 #ifdef VBOX_SOLARIS_TAP_ARP 688 ifReq.lifr_arp_muxid = ARPMuxID; 689 #endif 690 691 if (ioctl(s_IPFileDes, SIOCSLIFMUXID, &ifReq) == -1) 692 { 693 #ifdef VBOX_SOLARIS_TAP_ARP 694 ioctl(IPFileDes, I_PUNLINK, ARPMuxID); 695 #endif 696 ioctl(IPFileDes, I_PUNLINK, IPMuxID); 697 close(s_IPFileDes); 698 s_IPFileDes = -1; 699 LogRel(("TAP#%d: Failed to set Mux ID.\n", pDrvIns->iInstance)); 700 return PDMDrvHlpVMSetError(pDrvIns, VERR_HOSTIF_IOCTL, RT_SRC_POS, 701 N_("Failed to set Mux ID. Check TAP interface name. errno=%d"), errno); 702 } 703 704 /* what's the point? */ 705 pData->FileDevice = (RTFILE)TapFileDes; 706 pData->pszDeviceNameActual = RTStrDup(pszDevName); 707 708 return VINF_SUCCESS; 709 } 710 711 #endif /* RT_OS_SOLARIS */ 712 713 417 714 /** 418 715 * Queries an interface to the driver. … … 451 748 { 452 749 LogFlow(("drvTAPDestruct\n")); 750 PDRVTAP pData = PDMINS2DATA(pDrvIns, PDRVTAP); 751 453 752 #ifdef ASYNC_NET 454 PDRVTAP pData = PDMINS2DATA(pDrvIns, PDRVTAP);455 456 753 /* 457 754 * Terminate the Async I/O Thread. … … 487 784 } 488 785 #endif 786 787 #ifdef RT_OS_SOLARIS 788 if (pData->pszTerminateApplication) 789 drvTAPTerminateApplication(pData); 790 791 RTStrFree(pData->pszDeviceNameActual); 792 #endif 793 MMR3HeapFree(pData->pszDeviceName); 794 MMR3HeapFree(pData->pszSetupApplication); 795 MMR3HeapFree(pData->pszTerminateApplication); 489 796 } 490 797 … … 509 816 pData->pDrvIns = pDrvIns; 510 817 pData->FileDevice = NIL_RTFILE; 818 pData->pszDeviceName = NULL; 819 #ifdef RT_OS_SOLARIS 820 pData->pszDeviceNameActual = NULL; 821 #endif 822 pData->pszSetupApplication = NULL; 823 pData->pszTerminateApplication = NULL; 511 824 #ifdef ASYNC_NET 512 825 pData->Thread = NIL_RTTHREAD; … … 524 837 * Validate the config. 525 838 */ 526 if (!CFGMR3AreValuesValid(pCfgHandle, "Device\0InitProg\0TermProg\0FileHandle\0 "))839 if (!CFGMR3AreValuesValid(pCfgHandle, "Device\0InitProg\0TermProg\0FileHandle\0TAPSetupApplication\0TAPTerminateApplication")) 527 840 return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES, ""); 528 841 … … 546 859 * Read the configuration. 547 860 */ 861 #if defined(RT_OS_SOLARIS) /** @todo Other platforms' TAP code should be moved here from ConsoleImpl & VBoxBFE. */ 862 rc = CFGMR3QueryStringAlloc(pCfgHandle, "TAPSetupApplication", &pData->pszSetupApplication); 863 if (VBOX_SUCCESS(rc)) 864 { 865 if (!RTPathExists(pData->pszSetupApplication)) 866 return PDMDrvHlpVMSetError(pDrvIns, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, 867 N_("Invalid TAP setup program path: %s"), pData->pszSetupApplication); 868 } 869 else if (rc != VERR_CFGM_VALUE_NOT_FOUND) 870 return PDMDRV_SET_ERROR(pDrvIns, rc, N_("Configuration error: failed to query \"TAPTerminateApplication\"")); 871 872 rc = CFGMR3QueryStringAlloc(pCfgHandle, "TAPTerminateApplication", &pData->pszTerminateApplication); 873 if (VBOX_SUCCESS(rc)) 874 { 875 if (!RTPathExists(pData->pszTerminateApplication)) 876 return PDMDrvHlpVMSetError(pDrvIns, VERR_HOSTIF_INIT_FAILED, RT_SRC_POS, 877 N_("Invalid TAP terminate program path: %s"), pData->pszTerminateApplication); 878 } 879 else if (rc != VERR_CFGM_VALUE_NOT_FOUND) 880 return PDMDRV_SET_ERROR(pDrvIns, rc, N_("Configuration error: failed to query \"TAPTerminateApplication\"")); 881 882 883 rc = CFGMR3QueryStringAlloc(pCfgHandle, "Device", &pData->pszDeviceName); 884 if (VBOX_FAILURE(rc)) 885 return PDMDRV_SET_ERROR(pDrvIns, rc, 886 N_("Configuration error: Query for \"Device\" string failed!")); 887 888 /* 889 * Do the setup. 890 */ 891 rc = SolarisTAPAttach(pDrvIns); 892 if (VBOX_FAILURE(rc)) 893 return rc; 894 895 if (pData->pszSetupApplication) 896 { 897 rc = drvTAPSetupApplication(pData); 898 if (RT_SUCCESS(rc)) 899 return rc; 900 } 901 902 #else /* !SOLARIS */ 903 548 904 int32_t iFile; 549 905 rc = CFGMR3QueryS32(pCfgHandle, "FileHandle", &iFile); … … 555 911 return PDMDrvHlpVMSetError(pDrvIns, VERR_INVALID_HANDLE, RT_SRC_POS, 556 912 N_("The TAP file handle %RTfile is not valid!"), pData->FileDevice); 913 #endif /* !SOLARIS */ 557 914 558 915 /*
Note:
See TracChangeset
for help on using the changeset viewer.