1/*
2 * Copyright 2007-2010, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Hugo Santos <hugosantos@gmail.com>
7 */
8
9
10#include <sys/ioctl.h>
11#include <sys/sockio.h>
12#include <termios.h>
13
14#include <Drivers.h>
15#include <tty.h>
16#include <scsi.h>
17
18#include "strace.h"
19#include "Syscall.h"
20#include "TypeHandler.h"
21
22
23struct ioctl_info {
24	unsigned int index;
25	const char *name;
26	TypeHandler *handler;
27};
28
29#define IOCTL_INFO_ENTRY(name) \
30	{ name, #name, NULL }
31
32#define IOCTL_INFO_ENTRY_TYPE(name, type) \
33	{ name, #name, TypeHandlerFactory<type>::Create() }
34
35static const ioctl_info kIOCtls[] = {
36	// <Drivers.h>
37	IOCTL_INFO_ENTRY_TYPE(B_GET_DEVICE_SIZE, size_t *),
38	IOCTL_INFO_ENTRY_TYPE(B_SET_DEVICE_SIZE, size_t *),
39	IOCTL_INFO_ENTRY(B_SET_NONBLOCKING_IO),
40	IOCTL_INFO_ENTRY(B_SET_BLOCKING_IO),
41	IOCTL_INFO_ENTRY(B_GET_READ_STATUS),
42	IOCTL_INFO_ENTRY(B_GET_WRITE_STATUS),
43	IOCTL_INFO_ENTRY(B_GET_GEOMETRY),
44	IOCTL_INFO_ENTRY(B_GET_DRIVER_FOR_DEVICE),
45	IOCTL_INFO_ENTRY(B_GET_PARTITION_INFO),
46	IOCTL_INFO_ENTRY(B_SET_PARTITION),
47	IOCTL_INFO_ENTRY(B_FORMAT_DEVICE),
48	IOCTL_INFO_ENTRY(B_EJECT_DEVICE),
49	IOCTL_INFO_ENTRY(B_GET_ICON),
50	IOCTL_INFO_ENTRY(B_GET_BIOS_GEOMETRY),
51	IOCTL_INFO_ENTRY(B_GET_MEDIA_STATUS),
52	IOCTL_INFO_ENTRY(B_LOAD_MEDIA),
53	IOCTL_INFO_ENTRY(B_GET_BIOS_DRIVE_ID),
54	IOCTL_INFO_ENTRY(B_SET_UNINTERRUPTABLE_IO),
55	IOCTL_INFO_ENTRY(B_SET_INTERRUPTABLE_IO),
56	IOCTL_INFO_ENTRY(B_FLUSH_DRIVE_CACHE),
57	IOCTL_INFO_ENTRY(B_GET_PATH_FOR_DEVICE),
58	IOCTL_INFO_ENTRY(B_GET_NEXT_OPEN_DEVICE),
59	IOCTL_INFO_ENTRY(B_ADD_FIXED_DRIVER),
60	IOCTL_INFO_ENTRY(B_REMOVE_FIXED_DRIVER),
61
62	/*
63	IOCTL_INFO_ENTRY(B_AUDIO_DRIVER_BASE), // conflicts
64	IOCTL_INFO_ENTRY(B_MIDI_DRIVER_BASE),
65	IOCTL_INFO_ENTRY(B_JOYSTICK_DRIVER_BASE),
66	IOCTL_INFO_ENTRY(B_GRAPHIC_DRIVER_BASE),
67	IOCTL_INFO_ENTRY(B_DEVICE_OP_CODES_END),
68	*/
69
70	// <sys/sockio.h>
71	IOCTL_INFO_ENTRY(SIOCADDRT),
72	IOCTL_INFO_ENTRY(SIOCDELRT),
73	IOCTL_INFO_ENTRY_TYPE(SIOCSIFADDR, struct ifreq *),
74	IOCTL_INFO_ENTRY_TYPE(SIOCGIFADDR, struct ifreq *),
75	IOCTL_INFO_ENTRY_TYPE(SIOCSIFDSTADDR, struct ifreq *),
76	IOCTL_INFO_ENTRY_TYPE(SIOCGIFDSTADDR, struct ifreq *),
77	IOCTL_INFO_ENTRY_TYPE(SIOCSIFFLAGS, struct ifreq *),
78	IOCTL_INFO_ENTRY_TYPE(SIOCGIFFLAGS, struct ifreq *),
79	IOCTL_INFO_ENTRY_TYPE(SIOCGIFBRDADDR, struct ifreq *),
80	IOCTL_INFO_ENTRY_TYPE(SIOCSIFBRDADDR, struct ifreq *),
81	IOCTL_INFO_ENTRY_TYPE(SIOCGIFCOUNT, struct ifconf *),
82	IOCTL_INFO_ENTRY_TYPE(SIOCGIFCONF, struct ifconf *),
83	IOCTL_INFO_ENTRY_TYPE(SIOCGIFINDEX, struct ifreq *),
84	IOCTL_INFO_ENTRY(SIOCGIFNAME),
85	IOCTL_INFO_ENTRY_TYPE(SIOCGIFNETMASK, struct ifreq *),
86	IOCTL_INFO_ENTRY_TYPE(SIOCSIFNETMASK, struct ifreq *),
87	IOCTL_INFO_ENTRY_TYPE(SIOCGIFMETRIC, struct ifreq *),
88	IOCTL_INFO_ENTRY_TYPE(SIOCSIFMETRIC, struct ifreq *),
89	IOCTL_INFO_ENTRY_TYPE(SIOCDIFADDR, struct ifreq *),
90	IOCTL_INFO_ENTRY_TYPE(SIOCAIFADDR, struct ifaliasreq *),
91	IOCTL_INFO_ENTRY(SIOCADDMULTI),
92	IOCTL_INFO_ENTRY(SIOCDELMULTI),
93	IOCTL_INFO_ENTRY_TYPE(SIOCGIFMTU, struct ifreq *),
94	IOCTL_INFO_ENTRY_TYPE(SIOCSIFMTU, struct ifreq *),
95	IOCTL_INFO_ENTRY(SIOCSIFMEDIA),
96	IOCTL_INFO_ENTRY(SIOCGIFMEDIA),
97	IOCTL_INFO_ENTRY(SIOCGRTSIZE),
98	IOCTL_INFO_ENTRY(SIOCGRTTABLE),
99	IOCTL_INFO_ENTRY_TYPE(SIOCGIFSTATS, struct ifreq *),
100	IOCTL_INFO_ENTRY_TYPE(SIOCGIFTYPE, struct ifreq *),
101	IOCTL_INFO_ENTRY(SIOCSPACKETCAP),
102	IOCTL_INFO_ENTRY(SIOCCPACKETCAP),
103	IOCTL_INFO_ENTRY(SIOCSHIWAT),
104	IOCTL_INFO_ENTRY(SIOCGHIWAT),
105	IOCTL_INFO_ENTRY(SIOCSLOWAT),
106	IOCTL_INFO_ENTRY(SIOCGLOWAT),
107	IOCTL_INFO_ENTRY(SIOCATMARK),
108	IOCTL_INFO_ENTRY(SIOCSPGRP),
109
110	IOCTL_INFO_ENTRY_TYPE(B_SOCKET_SET_ALIAS, struct ifaliasreq *),
111	IOCTL_INFO_ENTRY_TYPE(B_SOCKET_GET_ALIAS, struct ifaliasreq *),
112	IOCTL_INFO_ENTRY_TYPE(B_SOCKET_COUNT_ALIASES, struct ifreq *),
113
114	// termios ioctls
115#define TCWAITEVENT				(TCGETA + 4)
116#define TCQUERYCONNECTED		(TCGETA + 8)
117#define TCVTIME					(TCGETA + 14)
118	IOCTL_INFO_ENTRY(TCGETA),
119	IOCTL_INFO_ENTRY(TCSETA),
120	IOCTL_INFO_ENTRY(TCSETAF),
121	IOCTL_INFO_ENTRY(TCSETAW),
122	IOCTL_INFO_ENTRY(TCWAITEVENT),
123	IOCTL_INFO_ENTRY(TCSBRK),
124	IOCTL_INFO_ENTRY(TCFLSH),
125	IOCTL_INFO_ENTRY(TCXONC),
126	IOCTL_INFO_ENTRY(TCQUERYCONNECTED),
127	IOCTL_INFO_ENTRY(TCGETBITS),
128	IOCTL_INFO_ENTRY(TCSETDTR),
129	IOCTL_INFO_ENTRY(TCSETRTS),
130	IOCTL_INFO_ENTRY(TIOCGWINSZ),
131	IOCTL_INFO_ENTRY(TIOCSWINSZ),
132	IOCTL_INFO_ENTRY(TCVTIME),
133	IOCTL_INFO_ENTRY(TIOCGPGRP),
134	IOCTL_INFO_ENTRY(TIOCSPGRP),
135	IOCTL_INFO_ENTRY(TIOCSCTTY),
136	IOCTL_INFO_ENTRY(TIOCMGET),
137	IOCTL_INFO_ENTRY(TIOCMSET),
138	IOCTL_INFO_ENTRY(TIOCSBRK),
139	IOCTL_INFO_ENTRY(TIOCCBRK),
140	IOCTL_INFO_ENTRY(TIOCMBIS),
141	IOCTL_INFO_ENTRY(TIOCMBIC),
142	IOCTL_INFO_ENTRY(TIOCOUTQ),
143	IOCTL_INFO_ENTRY(TIOCEXCL),
144	IOCTL_INFO_ENTRY(TIOCNXCL),
145
146	// private termios
147	IOCTL_INFO_ENTRY(B_IOCTL_GET_TTY_INDEX),
148	IOCTL_INFO_ENTRY(B_IOCTL_GRANT_TTY),
149
150	// scsi ioctls
151	IOCTL_INFO_ENTRY(B_SCSI_SCAN_FOR_DEVICES),
152	IOCTL_INFO_ENTRY(B_SCSI_ENABLE_PROFILING),
153	IOCTL_INFO_ENTRY(B_SCSI_INQUIRY),
154	IOCTL_INFO_ENTRY(B_SCSI_EJECT),
155	IOCTL_INFO_ENTRY(B_SCSI_PREVENT_ALLOW),
156	IOCTL_INFO_ENTRY(B_RAW_DEVICE_COMMAND),
157	IOCTL_INFO_ENTRY(B_SCSI_GET_TOC),
158	IOCTL_INFO_ENTRY(B_SCSI_PLAY_TRACK),
159	IOCTL_INFO_ENTRY(B_SCSI_PLAY_POSITION),
160	IOCTL_INFO_ENTRY(B_SCSI_STOP_AUDIO),
161	IOCTL_INFO_ENTRY(B_SCSI_PAUSE_AUDIO),
162	IOCTL_INFO_ENTRY(B_SCSI_RESUME_AUDIO),
163	IOCTL_INFO_ENTRY(B_SCSI_GET_POSITION),
164	IOCTL_INFO_ENTRY(B_SCSI_SET_VOLUME),
165	IOCTL_INFO_ENTRY(B_SCSI_GET_VOLUME),
166	IOCTL_INFO_ENTRY(B_SCSI_READ_CD),
167	IOCTL_INFO_ENTRY(B_SCSI_SCAN),
168	IOCTL_INFO_ENTRY(B_SCSI_DATA_MODE),
169
170	// socket ioctls
171	IOCTL_INFO_ENTRY_TYPE(FIONBIO, int*),
172	IOCTL_INFO_ENTRY_TYPE(FIONREAD, int*),
173	IOCTL_INFO_ENTRY_TYPE(FIOSEEKDATA, off_t*),
174	IOCTL_INFO_ENTRY_TYPE(FIOSEEKHOLE, off_t*),
175
176	{ 0, NULL, NULL }
177};
178
179static EnumTypeHandler::EnumMap kIoctlNames;
180static TypeHandlerSelector::SelectMap kIoctlTypeHandlers;
181
182void
183patch_ioctl()
184{
185	for (int i = 0; kIOCtls[i].name != NULL; i++) {
186		kIoctlNames[kIOCtls[i].index] = kIOCtls[i].name;
187		if (kIOCtls[i].handler != NULL)
188			kIoctlTypeHandlers[kIOCtls[i].index] = kIOCtls[i].handler;
189	}
190
191	Syscall *ioctl = get_syscall("_kern_ioctl");
192
193	ioctl->GetParameter("cmd")->SetHandler(
194			new EnumTypeHandler(kIoctlNames));
195	ioctl->GetParameter("data")->SetHandler(
196			new TypeHandlerSelector(kIoctlTypeHandlers,
197					1, TypeHandlerFactory<void *>::Create()));
198}
199
200