/** * 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; }
int ioctl(int fd, int request, ...) { void *data; va_list args; va_start(args, request); data = (request & IOC_INOUT) ? va_arg(args, void *) : NULL; va_end(args); if(data == NULL && (request & IOC_INOUT) && IOCPARM_LEN(request) != 0) { errno = EFAULT; return -1; } fd = request != FIONBIO ? _socketGetFd(fd) : fd; if(fd == -1) return -1; switch(request) { case FIONBIO: { // See note in fcntl (below) int flags = fcntl(fd, F_GETFL, 0); if(flags == -1) return -1; flags = *(int *)data != 0 ? (flags | O_NONBLOCK) : (flags & ~O_NONBLOCK); return fcntl(fd, F_SETFL, flags); } case BIOCSETF: case BIOCSETWF: case BIOCSETFNR: { int ret; struct bpf_program *prog = (struct bpf_program *)data; if(prog->bf_len > BPF_MAXBUFSIZE) { errno = EINVAL; return -1; } struct bpf_program_serialized *prog_ser = (struct bpf_program_serialized *)malloc(sizeof(struct bpf_program_serialized)); if(prog_ser == NULL) { errno = ENOMEM; return -1; } prog_ser->bf_len = prog->bf_len; memcpy(prog_ser->bf_insns, prog->bf_insns, prog->bf_len); request = _IOC(request & IOC_DIRMASK, IOCGROUP(request), IOCBASECMD(request), sizeof(struct bpf_program_serialized)); ret = bsdIoctl(fd, request, prog_ser); free(prog_ser); return _socketParseBsdResult(NULL, ret); } default: return _socketParseBsdResult(NULL, bsdIoctl(fd, request, data)); } }
static int consolectl_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) { switch (cmd) { case CONS_GETVERS: *(int*)data = 0x200; return 0; case CONS_MOUSECTL: { mouse_info_t *mi = (mouse_info_t*)data; sysmouse_process_event(mi); return (0); } default: printf("consolectl: unknown ioctl: %c:%lx\n", (char)IOCGROUP(cmd), IOCBASECMD(cmd)); return (ENOIOCTL); } }