/* * Copyright 2007-2010, Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Hugo Santos */ #include #include #include #include #include #include #include "strace.h" #include "Syscall.h" #include "TypeHandler.h" struct ioctl_info { unsigned int index; const char *name; TypeHandler *handler; }; #define IOCTL_INFO_ENTRY(name) \ { name, #name, NULL } #define IOCTL_INFO_ENTRY_TYPE(name, type) \ { name, #name, TypeHandlerFactory::Create() } static const ioctl_info kIOCtls[] = { // IOCTL_INFO_ENTRY_TYPE(B_GET_DEVICE_SIZE, size_t *), IOCTL_INFO_ENTRY_TYPE(B_SET_DEVICE_SIZE, size_t *), IOCTL_INFO_ENTRY(B_SET_NONBLOCKING_IO), IOCTL_INFO_ENTRY(B_SET_BLOCKING_IO), IOCTL_INFO_ENTRY(B_GET_READ_STATUS), IOCTL_INFO_ENTRY(B_GET_WRITE_STATUS), IOCTL_INFO_ENTRY(B_GET_GEOMETRY), IOCTL_INFO_ENTRY(B_GET_DRIVER_FOR_DEVICE), IOCTL_INFO_ENTRY(B_GET_PARTITION_INFO), IOCTL_INFO_ENTRY(B_SET_PARTITION), IOCTL_INFO_ENTRY(B_FORMAT_DEVICE), IOCTL_INFO_ENTRY(B_EJECT_DEVICE), IOCTL_INFO_ENTRY(B_GET_ICON), IOCTL_INFO_ENTRY(B_GET_BIOS_GEOMETRY), IOCTL_INFO_ENTRY(B_GET_MEDIA_STATUS), IOCTL_INFO_ENTRY(B_LOAD_MEDIA), IOCTL_INFO_ENTRY(B_GET_BIOS_DRIVE_ID), IOCTL_INFO_ENTRY(B_SET_UNINTERRUPTABLE_IO), IOCTL_INFO_ENTRY(B_SET_INTERRUPTABLE_IO), IOCTL_INFO_ENTRY(B_FLUSH_DRIVE_CACHE), IOCTL_INFO_ENTRY(B_GET_PATH_FOR_DEVICE), IOCTL_INFO_ENTRY(B_GET_NEXT_OPEN_DEVICE), IOCTL_INFO_ENTRY(B_ADD_FIXED_DRIVER), IOCTL_INFO_ENTRY(B_REMOVE_FIXED_DRIVER), /* IOCTL_INFO_ENTRY(B_AUDIO_DRIVER_BASE), // conflicts IOCTL_INFO_ENTRY(B_MIDI_DRIVER_BASE), IOCTL_INFO_ENTRY(B_JOYSTICK_DRIVER_BASE), IOCTL_INFO_ENTRY(B_GRAPHIC_DRIVER_BASE), IOCTL_INFO_ENTRY(B_DEVICE_OP_CODES_END), */ // IOCTL_INFO_ENTRY(SIOCADDRT), IOCTL_INFO_ENTRY(SIOCDELRT), IOCTL_INFO_ENTRY_TYPE(SIOCSIFADDR, struct ifreq *), IOCTL_INFO_ENTRY_TYPE(SIOCGIFADDR, struct ifreq *), IOCTL_INFO_ENTRY_TYPE(SIOCSIFDSTADDR, struct ifreq *), IOCTL_INFO_ENTRY_TYPE(SIOCGIFDSTADDR, struct ifreq *), IOCTL_INFO_ENTRY_TYPE(SIOCSIFFLAGS, struct ifreq *), IOCTL_INFO_ENTRY_TYPE(SIOCGIFFLAGS, struct ifreq *), IOCTL_INFO_ENTRY_TYPE(SIOCGIFBRDADDR, struct ifreq *), IOCTL_INFO_ENTRY_TYPE(SIOCSIFBRDADDR, struct ifreq *), IOCTL_INFO_ENTRY_TYPE(SIOCGIFCOUNT, struct ifconf *), IOCTL_INFO_ENTRY_TYPE(SIOCGIFCONF, struct ifconf *), IOCTL_INFO_ENTRY_TYPE(SIOCGIFINDEX, struct ifreq *), IOCTL_INFO_ENTRY(SIOCGIFNAME), IOCTL_INFO_ENTRY_TYPE(SIOCGIFNETMASK, struct ifreq *), IOCTL_INFO_ENTRY_TYPE(SIOCSIFNETMASK, struct ifreq *), IOCTL_INFO_ENTRY_TYPE(SIOCGIFMETRIC, struct ifreq *), IOCTL_INFO_ENTRY_TYPE(SIOCSIFMETRIC, struct ifreq *), IOCTL_INFO_ENTRY_TYPE(SIOCDIFADDR, struct ifreq *), IOCTL_INFO_ENTRY_TYPE(SIOCAIFADDR, struct ifaliasreq *), IOCTL_INFO_ENTRY(SIOCADDMULTI), IOCTL_INFO_ENTRY(SIOCDELMULTI), IOCTL_INFO_ENTRY_TYPE(SIOCGIFMTU, struct ifreq *), IOCTL_INFO_ENTRY_TYPE(SIOCSIFMTU, struct ifreq *), IOCTL_INFO_ENTRY(SIOCSIFMEDIA), IOCTL_INFO_ENTRY(SIOCGIFMEDIA), IOCTL_INFO_ENTRY(SIOCGRTSIZE), IOCTL_INFO_ENTRY(SIOCGRTTABLE), IOCTL_INFO_ENTRY_TYPE(SIOCGIFSTATS, struct ifreq *), IOCTL_INFO_ENTRY_TYPE(SIOCGIFTYPE, struct ifreq *), IOCTL_INFO_ENTRY(SIOCSPACKETCAP), IOCTL_INFO_ENTRY(SIOCCPACKETCAP), IOCTL_INFO_ENTRY(SIOCSHIWAT), IOCTL_INFO_ENTRY(SIOCGHIWAT), IOCTL_INFO_ENTRY(SIOCSLOWAT), IOCTL_INFO_ENTRY(SIOCGLOWAT), IOCTL_INFO_ENTRY(SIOCATMARK), IOCTL_INFO_ENTRY(SIOCSPGRP), IOCTL_INFO_ENTRY_TYPE(B_SOCKET_SET_ALIAS, struct ifaliasreq *), IOCTL_INFO_ENTRY_TYPE(B_SOCKET_GET_ALIAS, struct ifaliasreq *), IOCTL_INFO_ENTRY_TYPE(B_SOCKET_COUNT_ALIASES, struct ifreq *), // termios ioctls #define TCWAITEVENT (TCGETA + 4) #define TCQUERYCONNECTED (TCGETA + 8) #define TCVTIME (TCGETA + 14) IOCTL_INFO_ENTRY(TCGETA), IOCTL_INFO_ENTRY(TCSETA), IOCTL_INFO_ENTRY(TCSETAF), IOCTL_INFO_ENTRY(TCSETAW), IOCTL_INFO_ENTRY(TCWAITEVENT), IOCTL_INFO_ENTRY(TCSBRK), IOCTL_INFO_ENTRY(TCFLSH), IOCTL_INFO_ENTRY(TCXONC), IOCTL_INFO_ENTRY(TCQUERYCONNECTED), IOCTL_INFO_ENTRY(TCGETBITS), IOCTL_INFO_ENTRY(TCSETDTR), IOCTL_INFO_ENTRY(TCSETRTS), IOCTL_INFO_ENTRY(TIOCGWINSZ), IOCTL_INFO_ENTRY(TIOCSWINSZ), IOCTL_INFO_ENTRY(TCVTIME), IOCTL_INFO_ENTRY(TIOCGPGRP), IOCTL_INFO_ENTRY(TIOCSPGRP), IOCTL_INFO_ENTRY(TIOCSCTTY), IOCTL_INFO_ENTRY(TIOCMGET), IOCTL_INFO_ENTRY(TIOCMSET), IOCTL_INFO_ENTRY(TIOCSBRK), IOCTL_INFO_ENTRY(TIOCCBRK), IOCTL_INFO_ENTRY(TIOCMBIS), IOCTL_INFO_ENTRY(TIOCMBIC), IOCTL_INFO_ENTRY(TIOCOUTQ), IOCTL_INFO_ENTRY(TIOCEXCL), IOCTL_INFO_ENTRY(TIOCNXCL), // private termios IOCTL_INFO_ENTRY(B_IOCTL_GET_TTY_INDEX), IOCTL_INFO_ENTRY(B_IOCTL_GRANT_TTY), // scsi ioctls IOCTL_INFO_ENTRY(B_SCSI_SCAN_FOR_DEVICES), IOCTL_INFO_ENTRY(B_SCSI_ENABLE_PROFILING), IOCTL_INFO_ENTRY(B_SCSI_INQUIRY), IOCTL_INFO_ENTRY(B_SCSI_EJECT), IOCTL_INFO_ENTRY(B_SCSI_PREVENT_ALLOW), IOCTL_INFO_ENTRY(B_RAW_DEVICE_COMMAND), IOCTL_INFO_ENTRY(B_SCSI_GET_TOC), IOCTL_INFO_ENTRY(B_SCSI_PLAY_TRACK), IOCTL_INFO_ENTRY(B_SCSI_PLAY_POSITION), IOCTL_INFO_ENTRY(B_SCSI_STOP_AUDIO), IOCTL_INFO_ENTRY(B_SCSI_PAUSE_AUDIO), IOCTL_INFO_ENTRY(B_SCSI_RESUME_AUDIO), IOCTL_INFO_ENTRY(B_SCSI_GET_POSITION), IOCTL_INFO_ENTRY(B_SCSI_SET_VOLUME), IOCTL_INFO_ENTRY(B_SCSI_GET_VOLUME), IOCTL_INFO_ENTRY(B_SCSI_READ_CD), IOCTL_INFO_ENTRY(B_SCSI_SCAN), IOCTL_INFO_ENTRY(B_SCSI_DATA_MODE), // socket ioctls IOCTL_INFO_ENTRY_TYPE(FIONBIO, int*), IOCTL_INFO_ENTRY_TYPE(FIONREAD, int*), IOCTL_INFO_ENTRY_TYPE(FIOSEEKDATA, off_t*), IOCTL_INFO_ENTRY_TYPE(FIOSEEKHOLE, off_t*), { 0, NULL, NULL } }; static EnumTypeHandler::EnumMap kIoctlNames; static TypeHandlerSelector::SelectMap kIoctlTypeHandlers; void patch_ioctl() { for (int i = 0; kIOCtls[i].name != NULL; i++) { kIoctlNames[kIOCtls[i].index] = kIOCtls[i].name; if (kIOCtls[i].handler != NULL) kIoctlTypeHandlers[kIOCtls[i].index] = kIOCtls[i].handler; } Syscall *ioctl = get_syscall("_kern_ioctl"); ioctl->GetParameter("cmd")->SetHandler( new EnumTypeHandler(kIoctlNames)); ioctl->GetParameter("data")->SetHandler( new TypeHandlerSelector(kIoctlTypeHandlers, 1, TypeHandlerFactory::Create())); }