1
+/*
2
+ * BSD ioctl(2) emulation
3
+ *
4
+ * Copyright (c) 2013-2015 Stacey D. Son
5
+ *
6
+ * SPDX-License-Identifier: GPL-2.0-or-later
7
+ */
8
+#include "qemu/osdep.h"
9
+
10
+#include <sys/types.h>
11
+#include <sys/param.h>
12
+#include <sys/disk.h>
13
+#include <sys/ioccom.h>
14
+#include <sys/ioctl.h>
15
+#include <sys/sockio.h>
16
+#include <sys/_termios.h>
17
+#include <sys/ttycom.h>
18
+#include <sys/filio.h>
19
+
20
+#include <crypto/cryptodev.h>
21
+
22
+#include <net/ethernet.h>
23
+#include <net/if.h>
24
+#include <net/if_var.h>
25
+#include <net/if_types.h>
26
+#include <net/route.h>
27
+#include <net/if_dl.h>
28
+#include <net/if_gif.h>
29
+#include <net/if_gre.h>
30
+#include <net/if_lagg.h>
31
+#include <net/if_media.h>
32
+#include <net/pfvar.h>
33
+#include <net/if_pfsync.h>
34
+#include <netinet/icmp6.h>
35
+#include <netinet/in.h>
36
+#include <netinet/ip_carp.h>
37
+#include <netinet6/in6_var.h>
38
+#include <netinet6/nd6.h>
39
+#include <net80211/ieee80211_ioctl.h>
40
+
41
+#include <stdio.h>
42
+
43
+#include "qemu.h"
44
+
45
+#include "syscall_defs.h"
46
+#include "bsd-ioctl.h"
47
+#include "os-ioctl-cryptodev.h"
48
+#include "os-ioctl-filio.h"
49
+#include "os-ioctl-in6_var.h"
50
+#include "os-ioctl-sockio.h"
51
+#include "os-ioctl-ttycom.h"
52
+#include "os-ioctl-disk.h"
53
+
54
+static void target_to_host_termios(void *dst, const void *src)
55
+{
56
+ struct termios *host = dst;
57
+ const struct target_termios *target = src;
58
+
59
+ host->c_iflag = target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
60
+ host->c_oflag = target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
61
+ host->c_cflag = target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
62
+ host->c_lflag = target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
63
+
64
+ memset(host->c_cc, 0, sizeof(host->c_cc));
65
+ host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
66
+ host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
67
+#ifdef VEOL2
68
+ host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
69
+#endif
70
+ host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
71
+#ifdef VWERASE
72
+ host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
73
+#endif
74
+ host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
75
+#ifdef VREPRINT
76
+ host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
77
+#endif
78
+#ifdef VERASE2
79
+ host->c_cc[VERASE2] = target->c_cc[TARGET_VERASE2];
80
+#endif
81
+ host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
82
+ host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
83
+ host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
84
+#ifdef VDSUSP
85
+ host->c_cc[VDSUSP] = target->c_cc[TARGET_VDSUSP];
86
+#endif
87
+ host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
88
+ host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
89
+#ifdef VLNEXT
90
+ host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
91
+#endif
92
+#ifdef VDISCARD
93
+ host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
94
+#endif
95
+ host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
96
+ host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
97
+#ifdef VSTATUS
98
+ host->c_cc[VSTATUS] = target->c_cc[TARGET_VSTATUS];
99
+#endif
100
+
101
+ host->c_ispeed = tswap32(target->c_ispeed);
102
+ host->c_ospeed = tswap32(target->c_ospeed);
103
+}
104
+
105
+static void host_to_target_termios(void *dst, const void *src)
106
+{
107
+ struct target_termios *target = dst;
108
+ const struct termios *host = src;
109
+
110
+ target->c_iflag = tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
111
+ target->c_oflag = tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
112
+ target->c_cflag = tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
113
+ target->c_lflag = tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
114
+
115
+ memset(target->c_cc, 0, sizeof(target->c_cc));
116
+ target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
117
+ target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
118
+#ifdef VEOL2
119
+ target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
120
+#endif
121
+ target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
122
+#ifdef VWERASE
123
+ target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
124
+#endif
125
+ target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
126
+#ifdef VREPRINT
127
+ target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
128
+#endif
129
+#ifdef VERASE2
130
+ target->c_cc[TARGET_VERASE2] = host->c_cc[VERASE2];
131
+#endif
132
+ target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
133
+ target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
134
+ target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
135
+#ifdef VDSUSP
136
+ target->c_cc[TARGET_VDSUSP] = host->c_cc[VDSUSP];
137
+#endif
138
+ target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
139
+ target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
140
+#ifdef VLNEXT
141
+ target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
142
+#endif
143
+#ifdef VDISCARD
144
+ target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
145
+#endif
146
+ target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
147
+ target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
148
+#ifdef VSTATUS
149
+ target->c_cc[TARGET_VSTATUS] = host->c_cc[VSTATUS];
150
+#endif
151
+
152
+ target->c_ispeed = tswap32(host->c_ispeed);
153
+ target->c_ospeed = tswap32(host->c_ospeed);
154
+}
155
+
156
+static const StructEntry struct_termios_def = {
157
+ .convert = { host_to_target_termios, target_to_host_termios },
158
+ .size = { sizeof(struct target_termios), sizeof(struct termios) },
159
+ .align = { __alignof__(struct target_termios),
160
+ __alignof__(struct termios) },
161
+};
162
+
163
+/* ioctl structure type definitions */
164
+#define STRUCT(name, ...) STRUCT_ ## name,
165
+#define STRUCT_SPECIAL(name) STRUCT_ ## name,
166
+enum {
167
+#include "os-ioctl-types.h"
168
+STRUCT_MAX
169
+};
170
+#undef STRUCT
171
+#undef STRUCT_SPECIAL
172
+
173
+#define STRUCT(name, ...) \
174
+ static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
175
+#define STRUCT_SPECIAL(name)
176
+#include "os-ioctl-types.h"
177
+#undef STRUCT
178
+#undef STRUCT_SPECIAL
179
+
180
+
181
+struct IOCTLEntry;
182
+
183
+typedef abi_long do_ioctl_fn(const struct IOCTLEntry *ie, uint8_t *buf_temp,
184
+ int fd, abi_long cmd, abi_long arg);
185
+
186
+struct IOCTLEntry {
187
+ unsigned int target_cmd;
188
+ unsigned int host_cmd;
189
+ const char *name;
190
+ int access;
191
+ do_ioctl_fn *do_ioctl;
192
+ const argtype arg_type[5];
193
+};
194
+typedef struct IOCTLEntry IOCTLEntry;
195
+
196
+#define MAX_STRUCT_SIZE 4096
197
+
198
+static abi_long do_ioctl_unsupported(__unused const IOCTLEntry *ie,
199
+ __unused uint8_t *buf_temp,
200
+ __unused int fd, __unused abi_long cmd,
201
+ __unused abi_long arg);
202
+
203
+static abi_long do_ioctl_in6_ifreq_sockaddr_int(const IOCTLEntry *ie,
204
+ uint8_t *buf_temp, int fd, abi_long cmd, abi_long arg);
205
+
206
+static IOCTLEntry ioctl_entries[] = {
207
+#define IOC_ 0x0000
208
+#define IOC_R 0x0001
209
+#define IOC_W 0x0002
210
+#define IOC_RW (IOC_R | IOC_W)
211
+#define IOCTL(cmd, access, ...) \
212
+ { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
213
+#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
214
+ { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
215
+#define IOCTL_SPECIAL_UNIMPL(cmd, access, dofn, ...) \
216
+ { TARGET_ ## cmd, 0, #cmd, access, dofn, { __VA_ARGS__ } },
217
+#include "os-ioctl-cmds.h"
218
+ { 0, 0 },
219
+};