/** * performs the Idc initialization * we separate the globals initialization to globals "base" initialization which is actually * "general" globals initialization except for Idc not being initialized, and idc initialization. * This is needed for windows filter driver, which gets loaded prior to VBoxDrv, * thus it's not possible to make idc initialization from the driver startup routine for it. * * @returns VBox status code. * @param pGlobals Pointer to the globals. */ DECLHIDDEN(int) vboxNetAdpInitIdc(PVBOXNETADPGLOBALS pGlobals) { int rc; /* * Establish a connection to SUPDRV and register our component factory. */ rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL); if (RT_SUCCESS(rc)) { rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory); if (RT_SUCCESS(rc)) { #if 1 /** @todo REMOVE ME! */ PVBOXNETADP pTmp; rc = vboxNetAdpCreate(&pGlobals->TrunkFactory, &pTmp); if (RT_FAILURE(rc)) Log(("Failed to create vboxnet0, rc=%Rrc.\n", rc)); #endif Log(("VBoxNetAdp: pSession=%p\n", SUPR0IdcGetSession(&pGlobals->SupDrvIDC))); return rc; } /* bail out. */ LogRel(("VBoxNetAdp: Failed to register component factory, rc=%Rrc\n", rc)); SUPR0IdcClose(&pGlobals->SupDrvIDC); } return rc; }
/** * Device I/O Control entry point. * * @returns Darwin for slow IOCtls and VBox status code for the fast ones. * @param Dev The device number (major+minor). * @param iCmd The IOCtl command. * @param pData Pointer to the data (if any it's a SUPDRVIOCTLDATA (kernel copy)). * @param fFlags Flag saying we're a character device (like we didn't know already). * @param pProcess The process issuing this request. */ static int VBoxNetAdpDarwinIOCtl(dev_t Dev, u_long iCmd, caddr_t pData, int fFlags, struct proc *pProcess) { uint32_t cbReq = IOCPARM_LEN(iCmd); PVBOXNETADPREQ pReq = (PVBOXNETADPREQ)pData; int rc; Log(("VBoxNetAdpDarwinIOCtl: param len %#x; iCmd=%#lx\n", cbReq, iCmd)); switch (IOCBASECMD(iCmd)) { case IOCBASECMD(VBOXNETADP_CTL_ADD): { if ( (IOC_DIRMASK & iCmd) != IOC_INOUT || cbReq < sizeof(VBOXNETADPREQ)) return EINVAL; PVBOXNETADP pNew; Log(("VBoxNetAdpDarwinIOCtl: szName=%s\n", pReq->szName)); rc = vboxNetAdpCreate(&pNew, pReq->szName[0] && RTStrEnd(pReq->szName, RT_MIN(cbReq, sizeof(pReq->szName))) ? pReq->szName : NULL); if (RT_FAILURE(rc)) return rc == VERR_OUT_OF_RESOURCES ? ENOMEM : EINVAL; Assert(strlen(pReq->szName) < sizeof(pReq->szName)); strncpy(pReq->szName, pNew->szName, sizeof(pReq->szName) - 1); pReq->szName[sizeof(pReq->szName) - 1] = '\0'; Log(("VBoxNetAdpDarwinIOCtl: Added '%s'\n", pReq->szName)); break; } case IOCBASECMD(VBOXNETADP_CTL_REMOVE): { if (!RTStrEnd(pReq->szName, RT_MIN(cbReq, sizeof(pReq->szName)))) return EINVAL; PVBOXNETADP pAdp = vboxNetAdpFindByName(pReq->szName); if (!pAdp) return EINVAL; rc = vboxNetAdpDestroy(pAdp); if (RT_FAILURE(rc)) return EINVAL; Log(("VBoxNetAdpDarwinIOCtl: Removed %s\n", pReq->szName)); break; } default: printf("VBoxNetAdpDarwinIOCtl: unknown command %lx.\n", IOCBASECMD(iCmd)); return EINVAL; } return 0; }
/** * Device I/O Control entry point. * * @param pFilp Associated file pointer. * @param uCmd The function specified to ioctl(). * @param ulArg The argument specified to ioctl(). */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) static int VBoxNetAdpLinuxIOCtl(struct inode *pInode, struct file *pFilp, unsigned int uCmd, unsigned long ulArg) #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) */ static long VBoxNetAdpLinuxIOCtlUnlocked(struct file *pFilp, unsigned int uCmd, unsigned long ulArg) #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) */ { VBOXNETADPREQ Req; PVBOXNETADP pAdp; int rc; char *pszName = NULL; Log(("VBoxNetAdpLinuxIOCtl: param len %#x; uCmd=%#x; add=%#x\n", _IOC_SIZE(uCmd), uCmd, VBOXNETADP_CTL_ADD)); if (RT_UNLIKELY(_IOC_SIZE(uCmd) != sizeof(Req))) /* paranoia */ { Log(("VBoxNetAdpLinuxIOCtl: bad ioctl sizeof(Req)=%#x _IOC_SIZE=%#x; uCmd=%#x.\n", sizeof(Req), _IOC_SIZE(uCmd), uCmd)); return -EINVAL; } switch (uCmd) { case VBOXNETADP_CTL_ADD: Log(("VBoxNetAdpLinuxIOCtl: _IOC_DIR(uCmd)=%#x; IOC_OUT=%#x\n", _IOC_DIR(uCmd), IOC_OUT)); if (RT_UNLIKELY(copy_from_user(&Req, (void *)ulArg, sizeof(Req)))) { Log(("VBoxNetAdpLinuxIOCtl: copy_from_user(,%#lx,) failed; uCmd=%#x.\n", ulArg, uCmd)); return -EFAULT; } Log(("VBoxNetAdpLinuxIOCtl: Add %s\n", Req.szName)); if (Req.szName[0]) { pAdp = vboxNetAdpFindByName(Req.szName); if (pAdp) { Log(("VBoxNetAdpLinuxIOCtl: '%s' already exists\n", Req.szName)); return -EINVAL; } pszName = Req.szName; } rc = vboxNetAdpCreate(&pAdp, pszName); if (RT_FAILURE(rc)) { Log(("VBoxNetAdpLinuxIOCtl: vboxNetAdpCreate -> %Rrc\n", rc)); return -(rc == VERR_OUT_OF_RESOURCES ? ENOMEM : EINVAL); } Assert(strlen(pAdp->szName) < sizeof(Req.szName)); strncpy(Req.szName, pAdp->szName, sizeof(Req.szName) - 1); Req.szName[sizeof(Req.szName) - 1] = '\0'; if (RT_UNLIKELY(copy_to_user((void *)ulArg, &Req, sizeof(Req)))) { /* this is really bad! */ /** @todo remove the adapter again? */ printk(KERN_ERR "VBoxNetAdpLinuxIOCtl: copy_to_user(%#lx,,%#zx); uCmd=%#x!\n", ulArg, sizeof(Req), uCmd); return -EFAULT; } Log(("VBoxNetAdpLinuxIOCtl: Successfully added '%s'\n", Req.szName)); break; case VBOXNETADP_CTL_REMOVE: if (RT_UNLIKELY(copy_from_user(&Req, (void *)ulArg, sizeof(Req)))) { Log(("VBoxNetAdpLinuxIOCtl: copy_from_user(,%#lx,) failed; uCmd=%#x.\n", ulArg, uCmd)); return -EFAULT; } Log(("VBoxNetAdpLinuxIOCtl: Remove %s\n", Req.szName)); pAdp = vboxNetAdpFindByName(Req.szName); if (!pAdp) { Log(("VBoxNetAdpLinuxIOCtl: '%s' not found\n", Req.szName)); return -EINVAL; } rc = vboxNetAdpDestroy(pAdp); if (RT_FAILURE(rc)) { Log(("VBoxNetAdpLinuxIOCtl: vboxNetAdpDestroy('%s') -> %Rrc\n", Req.szName, rc)); return -EINVAL; } Log(("VBoxNetAdpLinuxIOCtl: Successfully removed '%s'\n", Req.szName)); break; default: printk(KERN_ERR "VBoxNetAdpLinuxIOCtl: unknown command %x.\n", uCmd); return -EINVAL; } return 0; }