xref: /src/sys/compat/linux/linux_ioctl.c (revision 26740e8f80da17c78bee6fa322e6bb1f2669be5c)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 1994-1995 Søren Schmidt
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/capsicum.h>
31 #include <sys/cdio.h>
32 #include <sys/consio.h>
33 #include <sys/disk.h>
34 #include <sys/dvdio.h>
35 #include <sys/fcntl.h>
36 #include <sys/filio.h>
37 #include <sys/jail.h>
38 #include <sys/kbio.h>
39 #include <sys/kcov.h>
40 #include <sys/kernel.h>
41 #include <sys/linker_set.h>
42 #include <sys/lock.h>
43 #include <sys/malloc.h>
44 #include <sys/mman.h>
45 #include <sys/proc.h>
46 #include <sys/vnode.h>
47 #include <sys/sbuf.h>
48 #include <sys/sockio.h>
49 #include <sys/soundcard.h>
50 #include <sys/syscallsubr.h>
51 #include <sys/sysctl.h>
52 #include <sys/sysproto.h>
53 #include <sys/sx.h>
54 #include <sys/tty.h>
55 
56 #include <net/if.h>
57 #include <net/if_var.h>
58 #include <net/if_dl.h>
59 #include <net/if_types.h>
60 
61 #include <dev/evdev/input.h>
62 #include <dev/hid/hidraw.h>
63 #include <dev/iicbus/iic.h>
64 #include <dev/usb/usb_ioctl.h>
65 
66 #ifdef COMPAT_LINUX32
67 #include <machine/../linux32/linux.h>
68 #include <machine/../linux32/linux32_proto.h>
69 #else
70 #include <machine/../linux/linux.h>
71 #include <machine/../linux/linux_proto.h>
72 #endif
73 
74 #include <compat/linux/linux_common.h>
75 #include <compat/linux/linux_ioctl.h>
76 #include <compat/linux/linux_mib.h>
77 #include <compat/linux/linux_socket.h>
78 #include <compat/linux/linux_time.h>
79 #include <compat/linux/linux_util.h>
80 
81 #include <contrib/v4l/videodev.h>
82 #include <compat/linux/linux_videodev_compat.h>
83 
84 #include <contrib/v4l/videodev2.h>
85 #include <compat/linux/linux_videodev2_compat.h>
86 
87 #include <cam/scsi/scsi_sg.h>
88 
89 #include <dev/nvme/nvme_linux.h>
90 
91 #define	DEFINE_LINUX_IOCTL_SET(shortname, SHORTNAME)		\
92 static linux_ioctl_function_t linux_ioctl_ ## shortname;	\
93 static struct linux_ioctl_handler shortname ## _handler = {	\
94 	.func = linux_ioctl_ ## shortname,			\
95 	.low = LINUX_IOCTL_ ## SHORTNAME ## _MIN,		\
96 	.high = LINUX_IOCTL_ ## SHORTNAME ## _MAX,		\
97 };								\
98 DATA_SET(linux_ioctl_handler_set, shortname ## _handler)
99 
100 DEFINE_LINUX_IOCTL_SET(cdrom, CDROM);
101 DEFINE_LINUX_IOCTL_SET(vfat, VFAT);
102 DEFINE_LINUX_IOCTL_SET(console, CONSOLE);
103 DEFINE_LINUX_IOCTL_SET(hdio, HDIO);
104 DEFINE_LINUX_IOCTL_SET(disk, DISK);
105 DEFINE_LINUX_IOCTL_SET(i2c, I2C);
106 DEFINE_LINUX_IOCTL_SET(socket, SOCKET);
107 DEFINE_LINUX_IOCTL_SET(sound, SOUND);
108 DEFINE_LINUX_IOCTL_SET(termio, TERMIO);
109 DEFINE_LINUX_IOCTL_SET(private, PRIVATE);
110 DEFINE_LINUX_IOCTL_SET(drm, DRM);
111 DEFINE_LINUX_IOCTL_SET(sg, SG);
112 DEFINE_LINUX_IOCTL_SET(v4l, VIDEO);
113 DEFINE_LINUX_IOCTL_SET(v4l2, VIDEO2);
114 DEFINE_LINUX_IOCTL_SET(fbsd_usb, FBSD_LUSB);
115 DEFINE_LINUX_IOCTL_SET(evdev, EVDEV);
116 DEFINE_LINUX_IOCTL_SET(kcov, KCOV);
117 #ifndef COMPAT_LINUX32
118 DEFINE_LINUX_IOCTL_SET(nvme, NVME);
119 #endif
120 DEFINE_LINUX_IOCTL_SET(hidraw, HIDRAW);
121 
122 #undef DEFINE_LINUX_IOCTL_SET
123 
124 static int linux_ioctl_special(struct thread *, struct linux_ioctl_args *);
125 
126 /*
127  * Keep sorted by low.
128  */
129 static struct linux_ioctl_handler linux_ioctls[] = {
130 	{ .func = linux_ioctl_termio, .low = LINUX_IOCTL_TERMIO_MIN,
131 	    .high = LINUX_IOCTL_TERMIO_MAX },
132 };
133 
134 #ifdef __i386__
135 static TAILQ_HEAD(, linux_ioctl_handler_element) linux_ioctl_handlers =
136     TAILQ_HEAD_INITIALIZER(linux_ioctl_handlers);
137 static struct sx linux_ioctl_sx;
138 SX_SYSINIT(linux_ioctl, &linux_ioctl_sx, "Linux ioctl handlers");
139 #else
140 extern TAILQ_HEAD(, linux_ioctl_handler_element) linux_ioctl_handlers;
141 extern struct sx linux_ioctl_sx;
142 #endif
143 #ifdef COMPAT_LINUX32
144 static TAILQ_HEAD(, linux_ioctl_handler_element) linux32_ioctl_handlers =
145     TAILQ_HEAD_INITIALIZER(linux32_ioctl_handlers);
146 #endif
147 
148 /*
149  * hdio related ioctls for VMWare support
150  */
151 
152 struct linux_hd_geometry {
153 	uint8_t		heads;
154 	uint8_t		sectors;
155 	uint16_t	cylinders;
156 	uint32_t	start;
157 };
158 
159 struct linux_hd_big_geometry {
160 	uint8_t		heads;
161 	uint8_t		sectors;
162 	uint32_t	cylinders;
163 	uint32_t	start;
164 };
165 
166 struct linux_i2c_msg {
167 	uint16_t	addr;
168 	uint16_t	flags;
169 	uint16_t	len;
170 	l_uintptr_t	buf;
171 };
172 
173 struct linux_i2c_rdwr_data {
174 	l_uintptr_t	msgs;
175 	l_uint		nmsgs;
176 };
177 
178 static int
linux_ioctl_hdio(struct thread * td,struct linux_ioctl_args * args)179 linux_ioctl_hdio(struct thread *td, struct linux_ioctl_args *args)
180 {
181 	struct file *fp;
182 	int error;
183 	u_int sectorsize, fwcylinders, fwheads, fwsectors;
184 	off_t mediasize, bytespercyl;
185 
186 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
187 	if (error != 0)
188 		return (error);
189 	switch (args->cmd & 0xffff) {
190 	case LINUX_HDIO_GET_GEO:
191 	case LINUX_HDIO_GET_GEO_BIG:
192 		error = fo_ioctl(fp, DIOCGMEDIASIZE,
193 			(caddr_t)&mediasize, td->td_ucred, td);
194 		if (!error)
195 			error = fo_ioctl(fp, DIOCGSECTORSIZE,
196 				(caddr_t)&sectorsize, td->td_ucred, td);
197 		if (!error)
198 			error = fo_ioctl(fp, DIOCGFWHEADS,
199 				(caddr_t)&fwheads, td->td_ucred, td);
200 		if (!error)
201 			error = fo_ioctl(fp, DIOCGFWSECTORS,
202 				(caddr_t)&fwsectors, td->td_ucred, td);
203 		/*
204 		 * XXX: DIOCGFIRSTOFFSET is not yet implemented, so
205 		 * so pretend that GEOM always says 0. This is NOT VALID
206 		 * for slices or partitions, only the per-disk raw devices.
207 		 */
208 
209 		fdrop(fp, td);
210 		if (error)
211 			return (error);
212 		/*
213 		 * 1. Calculate the number of bytes in a cylinder,
214 		 *    given the firmware's notion of heads and sectors
215 		 *    per cylinder.
216 		 * 2. Calculate the number of cylinders, given the total
217 		 *    size of the media.
218 		 * All internal calculations should have 64-bit precision.
219 		 */
220 		bytespercyl = (off_t) sectorsize * fwheads * fwsectors;
221 		fwcylinders = mediasize / bytespercyl;
222 
223 		if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO) {
224 			struct linux_hd_geometry hdg;
225 
226 			hdg.cylinders = fwcylinders;
227 			hdg.heads = fwheads;
228 			hdg.sectors = fwsectors;
229 			hdg.start = 0;
230 			error = copyout(&hdg, (void *)args->arg, sizeof(hdg));
231 		} else if ((args->cmd & 0xffff) == LINUX_HDIO_GET_GEO_BIG) {
232 			struct linux_hd_big_geometry hdbg;
233 
234 			memset(&hdbg, 0, sizeof(hdbg));
235 			hdbg.cylinders = fwcylinders;
236 			hdbg.heads = fwheads;
237 			hdbg.sectors = fwsectors;
238 			hdbg.start = 0;
239 			error = copyout(&hdbg, (void *)args->arg, sizeof(hdbg));
240 		}
241 		return (error);
242 		break;
243 	default:
244 		/* XXX */
245 		linux_msg(td,
246 			"%s fd=%d, cmd=0x%x ('%c',%d) is not implemented",
247 			__func__, args->fd, args->cmd,
248 			(int)(args->cmd & 0xff00) >> 8,
249 			(int)(args->cmd & 0xff));
250 		break;
251 	}
252 	fdrop(fp, td);
253 	return (ENOIOCTL);
254 }
255 
256 static int
linux_ioctl_disk(struct thread * td,struct linux_ioctl_args * args)257 linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args)
258 {
259 	struct file *fp;
260 	int error;
261 	u_int sectorsize, psectorsize;
262 	uint64_t blksize64;
263 	off_t mediasize, stripesize;
264 
265 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
266 	if (error != 0)
267 		return (error);
268 	switch (args->cmd & 0xffff) {
269 	case LINUX_BLKGETSIZE:
270 		error = fo_ioctl(fp, DIOCGSECTORSIZE,
271 		    (caddr_t)&sectorsize, td->td_ucred, td);
272 		if (!error)
273 			error = fo_ioctl(fp, DIOCGMEDIASIZE,
274 			    (caddr_t)&mediasize, td->td_ucred, td);
275 		fdrop(fp, td);
276 		if (error)
277 			return (error);
278 		sectorsize = mediasize / sectorsize;
279 		/*
280 		 * XXX: How do we know we return the right size of integer ?
281 		 */
282 		return (copyout(&sectorsize, (void *)args->arg,
283 		    sizeof(sectorsize)));
284 		break;
285 	case LINUX_BLKGETSIZE64:
286 		error = fo_ioctl(fp, DIOCGMEDIASIZE,
287 		    (caddr_t)&mediasize, td->td_ucred, td);
288 		fdrop(fp, td);
289 		if (error)
290 			return (error);
291 		blksize64 = mediasize;
292 		return (copyout(&blksize64, (void *)args->arg,
293 		    sizeof(blksize64)));
294 	case LINUX_BLKSSZGET:
295 		error = fo_ioctl(fp, DIOCGSECTORSIZE,
296 		    (caddr_t)&sectorsize, td->td_ucred, td);
297 		fdrop(fp, td);
298 		if (error)
299 			return (error);
300 		return (copyout(&sectorsize, (void *)args->arg,
301 		    sizeof(sectorsize)));
302 		break;
303 	case LINUX_BLKPBSZGET:
304 		error = fo_ioctl(fp, DIOCGSTRIPESIZE,
305 		    (caddr_t)&stripesize, td->td_ucred, td);
306 		if (error != 0) {
307 			fdrop(fp, td);
308 			return (error);
309 		}
310 		if (stripesize > 0 && stripesize <= 4096) {
311 			psectorsize = stripesize;
312 		} else  {
313 			error = fo_ioctl(fp, DIOCGSECTORSIZE,
314 			    (caddr_t)&sectorsize, td->td_ucred, td);
315 			if (error != 0) {
316 				fdrop(fp, td);
317 				return (error);
318 			}
319 			psectorsize = sectorsize;
320 		}
321 		fdrop(fp, td);
322 		return (copyout(&psectorsize, (void *)args->arg,
323 		    sizeof(psectorsize)));
324 	}
325 	fdrop(fp, td);
326 	return (ENOIOCTL);
327 }
328 
329 /*
330  * termio related ioctls
331  */
332 
333 struct linux_termio {
334 	unsigned short c_iflag;
335 	unsigned short c_oflag;
336 	unsigned short c_cflag;
337 	unsigned short c_lflag;
338 	unsigned char c_line;
339 	unsigned char c_cc[LINUX_NCC];
340 };
341 
342 struct linux_termios {
343 	unsigned int c_iflag;
344 	unsigned int c_oflag;
345 	unsigned int c_cflag;
346 	unsigned int c_lflag;
347 	unsigned char c_line;
348 	unsigned char c_cc[LINUX_NCCS];
349 };
350 
351 struct linux_termios2 {
352 	unsigned int c_iflag;
353 	unsigned int c_oflag;
354 	unsigned int c_cflag;
355 	unsigned int c_lflag;
356 	unsigned char c_line;
357 	unsigned char c_cc[LINUX_NCCS];
358 	unsigned int c_ispeed;
359 	unsigned int c_ospeed;
360 };
361 
362 struct linux_winsize {
363 	unsigned short ws_row, ws_col;
364 	unsigned short ws_xpixel, ws_ypixel;
365 };
366 
367 struct speedtab {
368 	int sp_speed;			/* Speed. */
369 	int sp_code;			/* Code. */
370 };
371 
372 static struct speedtab sptab[] = {
373 	{ B0, LINUX_B0 }, { B50, LINUX_B50 },
374 	{ B75, LINUX_B75 }, { B110, LINUX_B110 },
375 	{ B134, LINUX_B134 }, { B150, LINUX_B150 },
376 	{ B200, LINUX_B200 }, { B300, LINUX_B300 },
377 	{ B600, LINUX_B600 }, { B1200, LINUX_B1200 },
378 	{ B1800, LINUX_B1800 }, { B2400, LINUX_B2400 },
379 	{ B4800, LINUX_B4800 }, { B9600, LINUX_B9600 },
380 	{ B19200, LINUX_B19200 }, { B38400, LINUX_B38400 },
381 	{ B57600, LINUX_B57600 }, { B115200, LINUX_B115200 },
382 	{-1, -1 }
383 };
384 
385 struct linux_serial_struct {
386 	int	type;
387 	int	line;
388 	int	port;
389 	int	irq;
390 	int	flags;
391 	int	xmit_fifo_size;
392 	int	custom_divisor;
393 	int	baud_base;
394 	unsigned short close_delay;
395 	char	reserved_char[2];
396 	int	hub6;
397 	unsigned short closing_wait;
398 	unsigned short closing_wait2;
399 	int	reserved[4];
400 };
401 
402 static int
linux_to_bsd_speed(int code,struct speedtab * table)403 linux_to_bsd_speed(int code, struct speedtab *table)
404 {
405 	for ( ; table->sp_code != -1; table++)
406 		if (table->sp_code == code)
407 			return (table->sp_speed);
408 	return (-1);
409 }
410 
411 static int
bsd_to_linux_speed(int speed,struct speedtab * table)412 bsd_to_linux_speed(int speed, struct speedtab *table)
413 {
414 	for ( ; table->sp_speed != -1; table++)
415 		if (table->sp_speed == speed)
416 			return (table->sp_code);
417 	return (LINUX_BOTHER);
418 }
419 
420 static void
bsd_to_linux_termios(struct termios * bios,struct linux_termios * lios)421 bsd_to_linux_termios(struct termios *bios, struct linux_termios *lios)
422 {
423 	int i;
424 
425 	lios->c_iflag = 0;
426 	if (bios->c_iflag & IGNBRK)
427 		lios->c_iflag |= LINUX_IGNBRK;
428 	if (bios->c_iflag & BRKINT)
429 		lios->c_iflag |= LINUX_BRKINT;
430 	if (bios->c_iflag & IGNPAR)
431 		lios->c_iflag |= LINUX_IGNPAR;
432 	if (bios->c_iflag & PARMRK)
433 		lios->c_iflag |= LINUX_PARMRK;
434 	if (bios->c_iflag & INPCK)
435 		lios->c_iflag |= LINUX_INPCK;
436 	if (bios->c_iflag & ISTRIP)
437 		lios->c_iflag |= LINUX_ISTRIP;
438 	if (bios->c_iflag & INLCR)
439 		lios->c_iflag |= LINUX_INLCR;
440 	if (bios->c_iflag & IGNCR)
441 		lios->c_iflag |= LINUX_IGNCR;
442 	if (bios->c_iflag & ICRNL)
443 		lios->c_iflag |= LINUX_ICRNL;
444 	if (bios->c_iflag & IXON)
445 		lios->c_iflag |= LINUX_IXON;
446 	if (bios->c_iflag & IXANY)
447 		lios->c_iflag |= LINUX_IXANY;
448 	if (bios->c_iflag & IXOFF)
449 		lios->c_iflag |= LINUX_IXOFF;
450 	if (bios->c_iflag & IMAXBEL)
451 		lios->c_iflag |= LINUX_IMAXBEL;
452 	if (bios->c_iflag & IUTF8)
453 		lios->c_iflag |= LINUX_IUTF8;
454 
455 	lios->c_oflag = 0;
456 	if (bios->c_oflag & OPOST)
457 		lios->c_oflag |= LINUX_OPOST;
458 	if (bios->c_oflag & ONLCR)
459 		lios->c_oflag |= LINUX_ONLCR;
460 	if (bios->c_oflag & TAB3)
461 		lios->c_oflag |= LINUX_XTABS;
462 
463 	lios->c_cflag = bsd_to_linux_speed(bios->c_ispeed, sptab);
464 	lios->c_cflag |= (bios->c_cflag & CSIZE) >> 4;
465 	if (bios->c_cflag & CSTOPB)
466 		lios->c_cflag |= LINUX_CSTOPB;
467 	if (bios->c_cflag & CREAD)
468 		lios->c_cflag |= LINUX_CREAD;
469 	if (bios->c_cflag & PARENB)
470 		lios->c_cflag |= LINUX_PARENB;
471 	if (bios->c_cflag & PARODD)
472 		lios->c_cflag |= LINUX_PARODD;
473 	if (bios->c_cflag & HUPCL)
474 		lios->c_cflag |= LINUX_HUPCL;
475 	if (bios->c_cflag & CLOCAL)
476 		lios->c_cflag |= LINUX_CLOCAL;
477 	if (bios->c_cflag & CRTSCTS)
478 		lios->c_cflag |= LINUX_CRTSCTS;
479 
480 	lios->c_lflag = 0;
481 	if (bios->c_lflag & ISIG)
482 		lios->c_lflag |= LINUX_ISIG;
483 	if (bios->c_lflag & ICANON)
484 		lios->c_lflag |= LINUX_ICANON;
485 	if (bios->c_lflag & ECHO)
486 		lios->c_lflag |= LINUX_ECHO;
487 	if (bios->c_lflag & ECHOE)
488 		lios->c_lflag |= LINUX_ECHOE;
489 	if (bios->c_lflag & ECHOK)
490 		lios->c_lflag |= LINUX_ECHOK;
491 	if (bios->c_lflag & ECHONL)
492 		lios->c_lflag |= LINUX_ECHONL;
493 	if (bios->c_lflag & NOFLSH)
494 		lios->c_lflag |= LINUX_NOFLSH;
495 	if (bios->c_lflag & TOSTOP)
496 		lios->c_lflag |= LINUX_TOSTOP;
497 	if (bios->c_lflag & ECHOCTL)
498 		lios->c_lflag |= LINUX_ECHOCTL;
499 	if (bios->c_lflag & ECHOPRT)
500 		lios->c_lflag |= LINUX_ECHOPRT;
501 	if (bios->c_lflag & ECHOKE)
502 		lios->c_lflag |= LINUX_ECHOKE;
503 	if (bios->c_lflag & FLUSHO)
504 		lios->c_lflag |= LINUX_FLUSHO;
505 	if (bios->c_lflag & PENDIN)
506 		lios->c_lflag |= LINUX_PENDIN;
507 	if (bios->c_lflag & IEXTEN)
508 		lios->c_lflag |= LINUX_IEXTEN;
509 
510 	for (i=0; i<LINUX_NCCS; i++)
511 		lios->c_cc[i] = LINUX_POSIX_VDISABLE;
512 	lios->c_cc[LINUX_VINTR] = bios->c_cc[VINTR];
513 	lios->c_cc[LINUX_VQUIT] = bios->c_cc[VQUIT];
514 	lios->c_cc[LINUX_VERASE] = bios->c_cc[VERASE];
515 	lios->c_cc[LINUX_VKILL] = bios->c_cc[VKILL];
516 	lios->c_cc[LINUX_VEOF] = bios->c_cc[VEOF];
517 	lios->c_cc[LINUX_VEOL] = bios->c_cc[VEOL];
518 	lios->c_cc[LINUX_VMIN] = bios->c_cc[VMIN];
519 	lios->c_cc[LINUX_VTIME] = bios->c_cc[VTIME];
520 	lios->c_cc[LINUX_VEOL2] = bios->c_cc[VEOL2];
521 	lios->c_cc[LINUX_VSUSP] = bios->c_cc[VSUSP];
522 	lios->c_cc[LINUX_VSTART] = bios->c_cc[VSTART];
523 	lios->c_cc[LINUX_VSTOP] = bios->c_cc[VSTOP];
524 	lios->c_cc[LINUX_VREPRINT] = bios->c_cc[VREPRINT];
525 	lios->c_cc[LINUX_VDISCARD] = bios->c_cc[VDISCARD];
526 	lios->c_cc[LINUX_VWERASE] = bios->c_cc[VWERASE];
527 	lios->c_cc[LINUX_VLNEXT] = bios->c_cc[VLNEXT];
528 	if (linux_preserve_vstatus)
529 		lios->c_cc[LINUX_VSTATUS] = bios->c_cc[VSTATUS];
530 
531 	for (i=0; i<LINUX_NCCS; i++) {
532 		if (i != LINUX_VMIN && i != LINUX_VTIME &&
533 		    lios->c_cc[i] == _POSIX_VDISABLE)
534 			lios->c_cc[i] = LINUX_POSIX_VDISABLE;
535 	}
536 	lios->c_line = 0;
537 }
538 
539 static void
bsd_to_linux_termios2(struct termios * bios,struct linux_termios2 * lios2)540 bsd_to_linux_termios2(struct termios *bios, struct linux_termios2 *lios2)
541 {
542 	bsd_to_linux_termios(bios, (struct linux_termios *)lios2);
543 	lios2->c_ospeed = bios->c_ospeed;
544 	lios2->c_ispeed = bios->c_ispeed;
545 }
546 
547 static void
linux_to_bsd_termios(struct linux_termios * lios,struct termios * bios)548 linux_to_bsd_termios(struct linux_termios *lios, struct termios *bios)
549 {
550 	int i;
551 
552 	bios->c_iflag = 0;
553 	if (lios->c_iflag & LINUX_IGNBRK)
554 		bios->c_iflag |= IGNBRK;
555 	if (lios->c_iflag & LINUX_BRKINT)
556 		bios->c_iflag |= BRKINT;
557 	if (lios->c_iflag & LINUX_IGNPAR)
558 		bios->c_iflag |= IGNPAR;
559 	if (lios->c_iflag & LINUX_PARMRK)
560 		bios->c_iflag |= PARMRK;
561 	if (lios->c_iflag & LINUX_INPCK)
562 		bios->c_iflag |= INPCK;
563 	if (lios->c_iflag & LINUX_ISTRIP)
564 		bios->c_iflag |= ISTRIP;
565 	if (lios->c_iflag & LINUX_INLCR)
566 		bios->c_iflag |= INLCR;
567 	if (lios->c_iflag & LINUX_IGNCR)
568 		bios->c_iflag |= IGNCR;
569 	if (lios->c_iflag & LINUX_ICRNL)
570 		bios->c_iflag |= ICRNL;
571 	if (lios->c_iflag & LINUX_IXON)
572 		bios->c_iflag |= IXON;
573 	if (lios->c_iflag & LINUX_IXANY)
574 		bios->c_iflag |= IXANY;
575 	if (lios->c_iflag & LINUX_IXOFF)
576 		bios->c_iflag |= IXOFF;
577 	if (lios->c_iflag & LINUX_IMAXBEL)
578 		bios->c_iflag |= IMAXBEL;
579 	if (lios->c_iflag & LINUX_IUTF8)
580 		bios->c_iflag |= IUTF8;
581 
582 	bios->c_oflag = 0;
583 	if (lios->c_oflag & LINUX_OPOST)
584 		bios->c_oflag |= OPOST;
585 	if (lios->c_oflag & LINUX_ONLCR)
586 		bios->c_oflag |= ONLCR;
587 	if (lios->c_oflag & LINUX_XTABS)
588 		bios->c_oflag |= TAB3;
589 
590 	bios->c_cflag = (lios->c_cflag & LINUX_CSIZE) << 4;
591 	if (lios->c_cflag & LINUX_CSTOPB)
592 		bios->c_cflag |= CSTOPB;
593 	if (lios->c_cflag & LINUX_CREAD)
594 		bios->c_cflag |= CREAD;
595 	if (lios->c_cflag & LINUX_PARENB)
596 		bios->c_cflag |= PARENB;
597 	if (lios->c_cflag & LINUX_PARODD)
598 		bios->c_cflag |= PARODD;
599 	if (lios->c_cflag & LINUX_HUPCL)
600 		bios->c_cflag |= HUPCL;
601 	if (lios->c_cflag & LINUX_CLOCAL)
602 		bios->c_cflag |= CLOCAL;
603 	if (lios->c_cflag & LINUX_CRTSCTS)
604 		bios->c_cflag |= CRTSCTS;
605 
606 	bios->c_lflag = 0;
607 	if (lios->c_lflag & LINUX_ISIG)
608 		bios->c_lflag |= ISIG;
609 	if (lios->c_lflag & LINUX_ICANON)
610 		bios->c_lflag |= ICANON;
611 	if (lios->c_lflag & LINUX_ECHO)
612 		bios->c_lflag |= ECHO;
613 	if (lios->c_lflag & LINUX_ECHOE)
614 		bios->c_lflag |= ECHOE;
615 	if (lios->c_lflag & LINUX_ECHOK)
616 		bios->c_lflag |= ECHOK;
617 	if (lios->c_lflag & LINUX_ECHONL)
618 		bios->c_lflag |= ECHONL;
619 	if (lios->c_lflag & LINUX_NOFLSH)
620 		bios->c_lflag |= NOFLSH;
621 	if (lios->c_lflag & LINUX_TOSTOP)
622 		bios->c_lflag |= TOSTOP;
623 	if (lios->c_lflag & LINUX_ECHOCTL)
624 		bios->c_lflag |= ECHOCTL;
625 	if (lios->c_lflag & LINUX_ECHOPRT)
626 		bios->c_lflag |= ECHOPRT;
627 	if (lios->c_lflag & LINUX_ECHOKE)
628 		bios->c_lflag |= ECHOKE;
629 	if (lios->c_lflag & LINUX_FLUSHO)
630 		bios->c_lflag |= FLUSHO;
631 	if (lios->c_lflag & LINUX_PENDIN)
632 		bios->c_lflag |= PENDIN;
633 	if (lios->c_lflag & LINUX_IEXTEN)
634 		bios->c_lflag |= IEXTEN;
635 
636 	for (i=0; i<NCCS; i++)
637 		bios->c_cc[i] = _POSIX_VDISABLE;
638 	bios->c_cc[VINTR] = lios->c_cc[LINUX_VINTR];
639 	bios->c_cc[VQUIT] = lios->c_cc[LINUX_VQUIT];
640 	bios->c_cc[VERASE] = lios->c_cc[LINUX_VERASE];
641 	bios->c_cc[VKILL] = lios->c_cc[LINUX_VKILL];
642 	bios->c_cc[VEOF] = lios->c_cc[LINUX_VEOF];
643 	bios->c_cc[VEOL] = lios->c_cc[LINUX_VEOL];
644 	bios->c_cc[VMIN] = lios->c_cc[LINUX_VMIN];
645 	bios->c_cc[VTIME] = lios->c_cc[LINUX_VTIME];
646 	bios->c_cc[VEOL2] = lios->c_cc[LINUX_VEOL2];
647 	bios->c_cc[VSUSP] = lios->c_cc[LINUX_VSUSP];
648 	bios->c_cc[VSTART] = lios->c_cc[LINUX_VSTART];
649 	bios->c_cc[VSTOP] = lios->c_cc[LINUX_VSTOP];
650 	bios->c_cc[VREPRINT] = lios->c_cc[LINUX_VREPRINT];
651 	bios->c_cc[VDISCARD] = lios->c_cc[LINUX_VDISCARD];
652 	bios->c_cc[VWERASE] = lios->c_cc[LINUX_VWERASE];
653 	bios->c_cc[VLNEXT] = lios->c_cc[LINUX_VLNEXT];
654 	if (linux_preserve_vstatus)
655 		bios->c_cc[VSTATUS] = lios->c_cc[LINUX_VSTATUS];
656 
657 	for (i=0; i<NCCS; i++) {
658 		if (i != VMIN && i != VTIME &&
659 		    bios->c_cc[i] == LINUX_POSIX_VDISABLE)
660 			bios->c_cc[i] = _POSIX_VDISABLE;
661 	}
662 
663 	bios->c_ispeed = bios->c_ospeed =
664 	    linux_to_bsd_speed(lios->c_cflag & LINUX_CBAUD, sptab);
665 }
666 
667 static void
linux_to_bsd_termios2(struct linux_termios2 * lios2,struct termios * bios)668 linux_to_bsd_termios2(struct linux_termios2 *lios2, struct termios *bios)
669 {
670 	linux_to_bsd_termios((struct linux_termios *)lios2, bios);
671 	if ((lios2->c_cflag & LINUX_CBAUD) == LINUX_BOTHER)
672 		bios->c_ospeed = lios2->c_ospeed;
673 	if ((lios2->c_cflag & LINUX_CIBAUD) == LINUX_BOTHER << LINUX_IBSHIFT)
674 		bios->c_ispeed = lios2->c_ispeed;
675 }
676 
677 static void
bsd_to_linux_termio(struct termios * bios,struct linux_termio * lio)678 bsd_to_linux_termio(struct termios *bios, struct linux_termio *lio)
679 {
680 	struct linux_termios lios;
681 
682 	memset(lio, 0, sizeof(*lio));
683 	bsd_to_linux_termios(bios, &lios);
684 	lio->c_iflag = lios.c_iflag;
685 	lio->c_oflag = lios.c_oflag;
686 	lio->c_cflag = lios.c_cflag;
687 	lio->c_lflag = lios.c_lflag;
688 	lio->c_line  = lios.c_line;
689 	memcpy(lio->c_cc, lios.c_cc, LINUX_NCC);
690 }
691 
692 static void
linux_to_bsd_termio(struct linux_termio * lio,struct termios * bios)693 linux_to_bsd_termio(struct linux_termio *lio, struct termios *bios)
694 {
695 	struct linux_termios lios;
696 	int i;
697 
698 	lios.c_iflag = lio->c_iflag;
699 	lios.c_oflag = lio->c_oflag;
700 	lios.c_cflag = lio->c_cflag;
701 	lios.c_lflag = lio->c_lflag;
702 	for (i=LINUX_NCC; i<LINUX_NCCS; i++)
703 		lios.c_cc[i] = LINUX_POSIX_VDISABLE;
704 	memcpy(lios.c_cc, lio->c_cc, LINUX_NCC);
705 	linux_to_bsd_termios(&lios, bios);
706 }
707 
708 static int
linux_ioctl_termio(struct thread * td,struct linux_ioctl_args * args)709 linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args)
710 {
711 	struct termios bios;
712 	struct linux_termios lios;
713 	struct linux_termios2 lios2;
714 	struct linux_termio lio;
715 	struct file *fp;
716 	int error;
717 
718 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
719 	if (error != 0)
720 		return (error);
721 
722 	switch (args->cmd & 0xffff) {
723 	case LINUX_TCGETS:
724 		error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
725 		    td);
726 		if (error)
727 			break;
728 		bsd_to_linux_termios(&bios, &lios);
729 		error = copyout(&lios, (void *)args->arg, sizeof(lios));
730 		break;
731 
732 	case LINUX_TCSETS:
733 		error = copyin((void *)args->arg, &lios, sizeof(lios));
734 		if (error)
735 			break;
736 		linux_to_bsd_termios(&lios, &bios);
737 		error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
738 		    td));
739 		break;
740 
741 	case LINUX_TCSETSW:
742 		error = copyin((void *)args->arg, &lios, sizeof(lios));
743 		if (error)
744 			break;
745 		linux_to_bsd_termios(&lios, &bios);
746 		error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
747 		    td));
748 		break;
749 
750 	case LINUX_TCSETSF:
751 		error = copyin((void *)args->arg, &lios, sizeof(lios));
752 		if (error)
753 			break;
754 		linux_to_bsd_termios(&lios, &bios);
755 		error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
756 		    td));
757 		break;
758 
759 	case LINUX_TCGETA:
760 		error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
761 		    td);
762 		if (error)
763 			break;
764 		bsd_to_linux_termio(&bios, &lio);
765 		error = (copyout(&lio, (void *)args->arg, sizeof(lio)));
766 		break;
767 
768 	case LINUX_TCSETA:
769 		error = copyin((void *)args->arg, &lio, sizeof(lio));
770 		if (error)
771 			break;
772 		linux_to_bsd_termio(&lio, &bios);
773 		error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
774 		    td));
775 		break;
776 
777 	case LINUX_TCSETAW:
778 		error = copyin((void *)args->arg, &lio, sizeof(lio));
779 		if (error)
780 			break;
781 		linux_to_bsd_termio(&lio, &bios);
782 		error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
783 		    td));
784 		break;
785 
786 	case LINUX_TCSETAF:
787 		error = copyin((void *)args->arg, &lio, sizeof(lio));
788 		if (error)
789 			break;
790 		linux_to_bsd_termio(&lio, &bios);
791 		error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
792 		    td));
793 		break;
794 
795 	case LINUX_TCSBRK:
796 		if (args->arg != 0) {
797 			error = (fo_ioctl(fp, TIOCDRAIN, (caddr_t)&bios, td->td_ucred,
798 			    td));
799 		} else {
800 			linux_msg(td, "ioctl TCSBRK arg 0 not implemented");
801 			error = ENOIOCTL;
802 		}
803 		break;
804 
805 	case LINUX_TCXONC: {
806 		switch (args->arg) {
807 		case LINUX_TCOOFF:
808 			args->cmd = TIOCSTOP;
809 			break;
810 		case LINUX_TCOON:
811 			args->cmd = TIOCSTART;
812 			break;
813 		case LINUX_TCIOFF:
814 		case LINUX_TCION: {
815 			int c;
816 			struct write_args wr;
817 			error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios,
818 			    td->td_ucred, td);
819 			if (error)
820 				break;
821 			fdrop(fp, td);
822 			c = (args->arg == LINUX_TCIOFF) ? VSTOP : VSTART;
823 			c = bios.c_cc[c];
824 			if (c != _POSIX_VDISABLE) {
825 				wr.fd = args->fd;
826 				wr.buf = &c;
827 				wr.nbyte = sizeof(c);
828 				return (sys_write(td, &wr));
829 			} else
830 				return (0);
831 		}
832 		default:
833 			fdrop(fp, td);
834 			return (EINVAL);
835 		}
836 		args->arg = 0;
837 		error = (sys_ioctl(td, (struct ioctl_args *)args));
838 		break;
839 	}
840 
841 	case LINUX_TCFLSH: {
842 		int val;
843 		switch (args->arg) {
844 		case LINUX_TCIFLUSH:
845 			val = FREAD;
846 			break;
847 		case LINUX_TCOFLUSH:
848 			val = FWRITE;
849 			break;
850 		case LINUX_TCIOFLUSH:
851 			val = FREAD | FWRITE;
852 			break;
853 		default:
854 			fdrop(fp, td);
855 			return (EINVAL);
856 		}
857 		error = (fo_ioctl(fp,TIOCFLUSH,(caddr_t)&val,td->td_ucred,td));
858 		break;
859 	}
860 
861 	case LINUX_TIOCEXCL:
862 		args->cmd = TIOCEXCL;
863 		error = (sys_ioctl(td, (struct ioctl_args *)args));
864 		break;
865 
866 	case LINUX_TIOCNXCL:
867 		args->cmd = TIOCNXCL;
868 		error = (sys_ioctl(td, (struct ioctl_args *)args));
869 		break;
870 
871 	case LINUX_TIOCSCTTY:
872 		args->cmd = TIOCSCTTY;
873 		error = (sys_ioctl(td, (struct ioctl_args *)args));
874 		break;
875 
876 	case LINUX_TIOCGPGRP:
877 		args->cmd = TIOCGPGRP;
878 		error = (sys_ioctl(td, (struct ioctl_args *)args));
879 		break;
880 
881 	case LINUX_TIOCSPGRP:
882 		args->cmd = TIOCSPGRP;
883 		error = (sys_ioctl(td, (struct ioctl_args *)args));
884 		break;
885 
886 	/* LINUX_TIOCOUTQ */
887 	/* LINUX_TIOCSTI */
888 
889 	case LINUX_TIOCGWINSZ:
890 		args->cmd = TIOCGWINSZ;
891 		error = (sys_ioctl(td, (struct ioctl_args *)args));
892 		break;
893 
894 	case LINUX_TIOCSWINSZ:
895 		args->cmd = TIOCSWINSZ;
896 		error = (sys_ioctl(td, (struct ioctl_args *)args));
897 		break;
898 
899 	case LINUX_TIOCMGET:
900 		args->cmd = TIOCMGET;
901 		error = (sys_ioctl(td, (struct ioctl_args *)args));
902 		break;
903 
904 	case LINUX_TIOCMBIS:
905 		args->cmd = TIOCMBIS;
906 		error = (sys_ioctl(td, (struct ioctl_args *)args));
907 		break;
908 
909 	case LINUX_TIOCMBIC:
910 		args->cmd = TIOCMBIC;
911 		error = (sys_ioctl(td, (struct ioctl_args *)args));
912 		break;
913 
914 	case LINUX_TIOCMSET:
915 		args->cmd = TIOCMSET;
916 		error = (sys_ioctl(td, (struct ioctl_args *)args));
917 		break;
918 
919 	/* TIOCGSOFTCAR */
920 	/* TIOCSSOFTCAR */
921 
922 	case LINUX_FIONREAD: /* LINUX_TIOCINQ */
923 		args->cmd = FIONREAD;
924 		error = (sys_ioctl(td, (struct ioctl_args *)args));
925 		break;
926 
927 	/* LINUX_TIOCLINUX */
928 
929 	case LINUX_TIOCCONS:
930 		args->cmd = TIOCCONS;
931 		error = (sys_ioctl(td, (struct ioctl_args *)args));
932 		break;
933 
934 	case LINUX_TIOCGSERIAL: {
935 		struct linux_serial_struct lss;
936 
937 		bzero(&lss, sizeof(lss));
938 		lss.type = LINUX_PORT_16550A;
939 		lss.flags = 0;
940 		lss.close_delay = 0;
941 		error = copyout(&lss, (void *)args->arg, sizeof(lss));
942 		break;
943 	}
944 
945 	case LINUX_TIOCSSERIAL: {
946 		struct linux_serial_struct lss;
947 		error = copyin((void *)args->arg, &lss, sizeof(lss));
948 		if (error)
949 			break;
950 		/* XXX - It really helps to have an implementation that
951 		 * does nothing. NOT!
952 		 */
953 		error = 0;
954 		break;
955 	}
956 
957 	case LINUX_TIOCPKT:
958 		args->cmd = TIOCPKT;
959 		error = (sys_ioctl(td, (struct ioctl_args *)args));
960 		break;
961 
962 	case LINUX_FIONBIO:
963 		args->cmd = FIONBIO;
964 		error = (sys_ioctl(td, (struct ioctl_args *)args));
965 		break;
966 
967 	case LINUX_TIOCNOTTY:
968 		args->cmd = TIOCNOTTY;
969 		error = (sys_ioctl(td, (struct ioctl_args *)args));
970 		break;
971 
972 	case LINUX_TIOCSETD: {
973 		int line;
974 		switch (args->arg) {
975 		case LINUX_N_TTY:
976 			line = TTYDISC;
977 			break;
978 		case LINUX_N_SLIP:
979 			line = SLIPDISC;
980 			break;
981 		case LINUX_N_PPP:
982 			line = PPPDISC;
983 			break;
984 		default:
985 			fdrop(fp, td);
986 			return (EINVAL);
987 		}
988 		error = (fo_ioctl(fp, TIOCSETD, (caddr_t)&line, td->td_ucred,
989 		    td));
990 		break;
991 	}
992 
993 	case LINUX_TIOCGETD: {
994 		int linux_line;
995 		int bsd_line = TTYDISC;
996 		error = fo_ioctl(fp, TIOCGETD, (caddr_t)&bsd_line,
997 		    td->td_ucred, td);
998 		if (error)
999 			break;
1000 		switch (bsd_line) {
1001 		case TTYDISC:
1002 			linux_line = LINUX_N_TTY;
1003 			break;
1004 		case SLIPDISC:
1005 			linux_line = LINUX_N_SLIP;
1006 			break;
1007 		case PPPDISC:
1008 			linux_line = LINUX_N_PPP;
1009 			break;
1010 		default:
1011 			fdrop(fp, td);
1012 			return (EINVAL);
1013 		}
1014 		error = (copyout(&linux_line, (void *)args->arg, sizeof(int)));
1015 		break;
1016 	}
1017 
1018 	/* LINUX_TCSBRKP */
1019 	/* LINUX_TIOCTTYGSTRUCT */
1020 
1021 	case LINUX_FIONCLEX:
1022 		args->cmd = FIONCLEX;
1023 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1024 		break;
1025 
1026 	case LINUX_FIOCLEX:
1027 		args->cmd = FIOCLEX;
1028 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1029 		break;
1030 
1031 	case LINUX_FIOASYNC:
1032 		args->cmd = FIOASYNC;
1033 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1034 		break;
1035 
1036 	/* LINUX_TIOCSERCONFIG */
1037 	/* LINUX_TIOCSERGWILD */
1038 	/* LINUX_TIOCSERSWILD */
1039 	/* LINUX_TIOCGLCKTRMIOS */
1040 	/* LINUX_TIOCSLCKTRMIOS */
1041 
1042 	case LINUX_TIOCSBRK:
1043 		args->cmd = TIOCSBRK;
1044 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1045 		break;
1046 
1047 	case LINUX_TIOCCBRK:
1048 		args->cmd = TIOCCBRK;
1049 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1050 		break;
1051 
1052 	case LINUX_TCGETS2:
1053 		error = fo_ioctl(fp, TIOCGETA, (caddr_t)&bios, td->td_ucred,
1054 		    td);
1055 		if (error)
1056 			break;
1057 		bsd_to_linux_termios2(&bios, &lios2);
1058 		error = copyout(&lios2, (void *)args->arg, sizeof(lios2));
1059 		break;
1060 
1061 	case LINUX_TCSETS2:
1062 		error = copyin((void *)args->arg, &lios2, sizeof(lios2));
1063 		if (error)
1064 			break;
1065 		linux_to_bsd_termios2(&lios2, &bios);
1066 		error = (fo_ioctl(fp, TIOCSETA, (caddr_t)&bios, td->td_ucred,
1067 		    td));
1068 		break;
1069 
1070 	case LINUX_TCSETSW2:
1071 		error = copyin((void *)args->arg, &lios2, sizeof(lios2));
1072 		if (error)
1073 			break;
1074 		linux_to_bsd_termios2(&lios2, &bios);
1075 		error = (fo_ioctl(fp, TIOCSETAW, (caddr_t)&bios, td->td_ucred,
1076 		    td));
1077 		break;
1078 
1079 	case LINUX_TCSETSF2:
1080 		error = copyin((void *)args->arg, &lios2, sizeof(lios2));
1081 		if (error)
1082 			break;
1083 		linux_to_bsd_termios2(&lios2, &bios);
1084 		error = (fo_ioctl(fp, TIOCSETAF, (caddr_t)&bios, td->td_ucred,
1085 		    td));
1086 		break;
1087 
1088 	case LINUX_TIOCGPTN: {
1089 		int nb;
1090 
1091 		error = fo_ioctl(fp, TIOCGPTN, (caddr_t)&nb, td->td_ucred, td);
1092 		if (!error)
1093 			error = copyout(&nb, (void *)args->arg,
1094 			    sizeof(int));
1095 		break;
1096 	}
1097 	case LINUX_TIOCGPTPEER:
1098 		linux_msg(td, "unsupported ioctl TIOCGPTPEER");
1099 		error = ENOIOCTL;
1100 		break;
1101 	case LINUX_TIOCSPTLCK:
1102 		/*
1103 		 * Our unlockpt() does nothing. Check that fd refers
1104 		 * to a pseudo-terminal master device.
1105 		 */
1106 		args->cmd = TIOCPTMASTER;
1107 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1108 		break;
1109 	default:
1110 		error = ENOIOCTL;
1111 		break;
1112 	}
1113 
1114 	fdrop(fp, td);
1115 	return (error);
1116 }
1117 
1118 /*
1119  * CDROM related ioctls
1120  */
1121 
1122 struct linux_cdrom_msf
1123 {
1124 	u_char	cdmsf_min0;
1125 	u_char	cdmsf_sec0;
1126 	u_char	cdmsf_frame0;
1127 	u_char	cdmsf_min1;
1128 	u_char	cdmsf_sec1;
1129 	u_char	cdmsf_frame1;
1130 };
1131 
1132 struct linux_cdrom_tochdr
1133 {
1134 	u_char	cdth_trk0;
1135 	u_char	cdth_trk1;
1136 };
1137 
1138 union linux_cdrom_addr
1139 {
1140 	struct {
1141 		u_char	minute;
1142 		u_char	second;
1143 		u_char	frame;
1144 	} msf;
1145 	int	lba;
1146 };
1147 
1148 struct linux_cdrom_tocentry
1149 {
1150 	u_char	cdte_track;
1151 	u_char	cdte_adr:4;
1152 	u_char	cdte_ctrl:4;
1153 	u_char	cdte_format;
1154 	union linux_cdrom_addr cdte_addr;
1155 	u_char	cdte_datamode;
1156 };
1157 
1158 struct linux_cdrom_subchnl
1159 {
1160 	u_char	cdsc_format;
1161 	u_char	cdsc_audiostatus;
1162 	u_char	cdsc_adr:4;
1163 	u_char	cdsc_ctrl:4;
1164 	u_char	cdsc_trk;
1165 	u_char	cdsc_ind;
1166 	union linux_cdrom_addr cdsc_absaddr;
1167 	union linux_cdrom_addr cdsc_reladdr;
1168 };
1169 
1170 struct l_cdrom_read_audio {
1171 	union linux_cdrom_addr addr;
1172 	u_char		addr_format;
1173 	l_int		nframes;
1174 	u_char		*buf;
1175 };
1176 
1177 struct l_dvd_layer {
1178 	u_char		book_version:4;
1179 	u_char		book_type:4;
1180 	u_char		min_rate:4;
1181 	u_char		disc_size:4;
1182 	u_char		layer_type:4;
1183 	u_char		track_path:1;
1184 	u_char		nlayers:2;
1185 	u_char		track_density:4;
1186 	u_char		linear_density:4;
1187 	u_char		bca:1;
1188 	uint32_t	start_sector;
1189 	uint32_t	end_sector;
1190 	uint32_t	end_sector_l0;
1191 };
1192 
1193 struct l_dvd_physical {
1194 	u_char		type;
1195 	u_char		layer_num;
1196 	struct l_dvd_layer layer[4];
1197 };
1198 
1199 struct l_dvd_copyright {
1200 	u_char		type;
1201 	u_char		layer_num;
1202 	u_char		cpst;
1203 	u_char		rmi;
1204 };
1205 
1206 struct l_dvd_disckey {
1207 	u_char		type;
1208 	l_uint		agid:2;
1209 	u_char		value[2048];
1210 };
1211 
1212 struct l_dvd_bca {
1213 	u_char		type;
1214 	l_int		len;
1215 	u_char		value[188];
1216 };
1217 
1218 struct l_dvd_manufact {
1219 	u_char		type;
1220 	u_char		layer_num;
1221 	l_int		len;
1222 	u_char		value[2048];
1223 };
1224 
1225 typedef union {
1226 	u_char			type;
1227 	struct l_dvd_physical	physical;
1228 	struct l_dvd_copyright	copyright;
1229 	struct l_dvd_disckey	disckey;
1230 	struct l_dvd_bca	bca;
1231 	struct l_dvd_manufact	manufact;
1232 } l_dvd_struct;
1233 
1234 typedef u_char l_dvd_key[5];
1235 typedef u_char l_dvd_challenge[10];
1236 
1237 struct l_dvd_lu_send_agid {
1238 	u_char		type;
1239 	l_uint		agid:2;
1240 };
1241 
1242 struct l_dvd_host_send_challenge {
1243 	u_char		type;
1244 	l_uint		agid:2;
1245 	l_dvd_challenge	chal;
1246 };
1247 
1248 struct l_dvd_send_key {
1249 	u_char		type;
1250 	l_uint		agid:2;
1251 	l_dvd_key	key;
1252 };
1253 
1254 struct l_dvd_lu_send_challenge {
1255 	u_char		type;
1256 	l_uint		agid:2;
1257 	l_dvd_challenge	chal;
1258 };
1259 
1260 struct l_dvd_lu_send_title_key {
1261 	u_char		type;
1262 	l_uint		agid:2;
1263 	l_dvd_key	title_key;
1264 	l_int		lba;
1265 	l_uint		cpm:1;
1266 	l_uint		cp_sec:1;
1267 	l_uint		cgms:2;
1268 };
1269 
1270 struct l_dvd_lu_send_asf {
1271 	u_char		type;
1272 	l_uint		agid:2;
1273 	l_uint		asf:1;
1274 };
1275 
1276 struct l_dvd_host_send_rpcstate {
1277 	u_char		type;
1278 	u_char		pdrc;
1279 };
1280 
1281 struct l_dvd_lu_send_rpcstate {
1282 	u_char		type:2;
1283 	u_char		vra:3;
1284 	u_char		ucca:3;
1285 	u_char		region_mask;
1286 	u_char		rpc_scheme;
1287 };
1288 
1289 typedef union {
1290 	u_char				type;
1291 	struct l_dvd_lu_send_agid	lsa;
1292 	struct l_dvd_host_send_challenge hsc;
1293 	struct l_dvd_send_key		lsk;
1294 	struct l_dvd_lu_send_challenge	lsc;
1295 	struct l_dvd_send_key		hsk;
1296 	struct l_dvd_lu_send_title_key	lstk;
1297 	struct l_dvd_lu_send_asf	lsasf;
1298 	struct l_dvd_host_send_rpcstate	hrpcs;
1299 	struct l_dvd_lu_send_rpcstate	lrpcs;
1300 } l_dvd_authinfo;
1301 
1302 static void
bsd_to_linux_msf_lba(u_char af,union msf_lba * bp,union linux_cdrom_addr * lp)1303 bsd_to_linux_msf_lba(u_char af, union msf_lba *bp, union linux_cdrom_addr *lp)
1304 {
1305 	if (af == CD_LBA_FORMAT)
1306 		lp->lba = bp->lba;
1307 	else {
1308 		lp->msf.minute = bp->msf.minute;
1309 		lp->msf.second = bp->msf.second;
1310 		lp->msf.frame = bp->msf.frame;
1311 	}
1312 }
1313 
1314 static void
set_linux_cdrom_addr(union linux_cdrom_addr * addr,int format,int lba)1315 set_linux_cdrom_addr(union linux_cdrom_addr *addr, int format, int lba)
1316 {
1317 	if (format == LINUX_CDROM_MSF) {
1318 		addr->msf.frame = lba % 75;
1319 		lba /= 75;
1320 		lba += 2;
1321 		addr->msf.second = lba % 60;
1322 		addr->msf.minute = lba / 60;
1323 	} else
1324 		addr->lba = lba;
1325 }
1326 
1327 static int
linux_to_bsd_dvd_struct(l_dvd_struct * lp,struct dvd_struct * bp)1328 linux_to_bsd_dvd_struct(l_dvd_struct *lp, struct dvd_struct *bp)
1329 {
1330 	bp->format = lp->type;
1331 	switch (bp->format) {
1332 	case DVD_STRUCT_PHYSICAL:
1333 		if (bp->layer_num >= 4)
1334 			return (EINVAL);
1335 		bp->layer_num = lp->physical.layer_num;
1336 		break;
1337 	case DVD_STRUCT_COPYRIGHT:
1338 		bp->layer_num = lp->copyright.layer_num;
1339 		break;
1340 	case DVD_STRUCT_DISCKEY:
1341 		bp->agid = lp->disckey.agid;
1342 		break;
1343 	case DVD_STRUCT_BCA:
1344 	case DVD_STRUCT_MANUFACT:
1345 		break;
1346 	default:
1347 		return (EINVAL);
1348 	}
1349 	return (0);
1350 }
1351 
1352 static int
bsd_to_linux_dvd_struct(struct dvd_struct * bp,l_dvd_struct * lp)1353 bsd_to_linux_dvd_struct(struct dvd_struct *bp, l_dvd_struct *lp)
1354 {
1355 	switch (bp->format) {
1356 	case DVD_STRUCT_PHYSICAL: {
1357 		struct dvd_layer *blp = (struct dvd_layer *)bp->data;
1358 		struct l_dvd_layer *llp = &lp->physical.layer[bp->layer_num];
1359 		memset(llp, 0, sizeof(*llp));
1360 		llp->book_version = blp->book_version;
1361 		llp->book_type = blp->book_type;
1362 		llp->min_rate = blp->max_rate;
1363 		llp->disc_size = blp->disc_size;
1364 		llp->layer_type = blp->layer_type;
1365 		llp->track_path = blp->track_path;
1366 		llp->nlayers = blp->nlayers;
1367 		llp->track_density = blp->track_density;
1368 		llp->linear_density = blp->linear_density;
1369 		llp->bca = blp->bca;
1370 		llp->start_sector = blp->start_sector;
1371 		llp->end_sector = blp->end_sector;
1372 		llp->end_sector_l0 = blp->end_sector_l0;
1373 		break;
1374 	}
1375 	case DVD_STRUCT_COPYRIGHT:
1376 		lp->copyright.cpst = bp->cpst;
1377 		lp->copyright.rmi = bp->rmi;
1378 		break;
1379 	case DVD_STRUCT_DISCKEY:
1380 		memcpy(lp->disckey.value, bp->data, sizeof(lp->disckey.value));
1381 		break;
1382 	case DVD_STRUCT_BCA:
1383 		lp->bca.len = bp->length;
1384 		memcpy(lp->bca.value, bp->data, sizeof(lp->bca.value));
1385 		break;
1386 	case DVD_STRUCT_MANUFACT:
1387 		lp->manufact.len = bp->length;
1388 		memcpy(lp->manufact.value, bp->data,
1389 		    sizeof(lp->manufact.value));
1390 		/* lp->manufact.layer_num is unused in Linux (redhat 7.0). */
1391 		break;
1392 	default:
1393 		return (EINVAL);
1394 	}
1395 	return (0);
1396 }
1397 
1398 static int
linux_to_bsd_dvd_authinfo(l_dvd_authinfo * lp,int * bcode,struct dvd_authinfo * bp)1399 linux_to_bsd_dvd_authinfo(l_dvd_authinfo *lp, int *bcode,
1400     struct dvd_authinfo *bp)
1401 {
1402 	switch (lp->type) {
1403 	case LINUX_DVD_LU_SEND_AGID:
1404 		*bcode = DVDIOCREPORTKEY;
1405 		bp->format = DVD_REPORT_AGID;
1406 		bp->agid = lp->lsa.agid;
1407 		break;
1408 	case LINUX_DVD_HOST_SEND_CHALLENGE:
1409 		*bcode = DVDIOCSENDKEY;
1410 		bp->format = DVD_SEND_CHALLENGE;
1411 		bp->agid = lp->hsc.agid;
1412 		memcpy(bp->keychal, lp->hsc.chal, 10);
1413 		break;
1414 	case LINUX_DVD_LU_SEND_KEY1:
1415 		*bcode = DVDIOCREPORTKEY;
1416 		bp->format = DVD_REPORT_KEY1;
1417 		bp->agid = lp->lsk.agid;
1418 		break;
1419 	case LINUX_DVD_LU_SEND_CHALLENGE:
1420 		*bcode = DVDIOCREPORTKEY;
1421 		bp->format = DVD_REPORT_CHALLENGE;
1422 		bp->agid = lp->lsc.agid;
1423 		break;
1424 	case LINUX_DVD_HOST_SEND_KEY2:
1425 		*bcode = DVDIOCSENDKEY;
1426 		bp->format = DVD_SEND_KEY2;
1427 		bp->agid = lp->hsk.agid;
1428 		memcpy(bp->keychal, lp->hsk.key, 5);
1429 		break;
1430 	case LINUX_DVD_LU_SEND_TITLE_KEY:
1431 		*bcode = DVDIOCREPORTKEY;
1432 		bp->format = DVD_REPORT_TITLE_KEY;
1433 		bp->agid = lp->lstk.agid;
1434 		bp->lba = lp->lstk.lba;
1435 		break;
1436 	case LINUX_DVD_LU_SEND_ASF:
1437 		*bcode = DVDIOCREPORTKEY;
1438 		bp->format = DVD_REPORT_ASF;
1439 		bp->agid = lp->lsasf.agid;
1440 		break;
1441 	case LINUX_DVD_INVALIDATE_AGID:
1442 		*bcode = DVDIOCREPORTKEY;
1443 		bp->format = DVD_INVALIDATE_AGID;
1444 		bp->agid = lp->lsa.agid;
1445 		break;
1446 	case LINUX_DVD_LU_SEND_RPC_STATE:
1447 		*bcode = DVDIOCREPORTKEY;
1448 		bp->format = DVD_REPORT_RPC;
1449 		break;
1450 	case LINUX_DVD_HOST_SEND_RPC_STATE:
1451 		*bcode = DVDIOCSENDKEY;
1452 		bp->format = DVD_SEND_RPC;
1453 		bp->region = lp->hrpcs.pdrc;
1454 		break;
1455 	default:
1456 		return (EINVAL);
1457 	}
1458 	return (0);
1459 }
1460 
1461 static int
bsd_to_linux_dvd_authinfo(struct dvd_authinfo * bp,l_dvd_authinfo * lp)1462 bsd_to_linux_dvd_authinfo(struct dvd_authinfo *bp, l_dvd_authinfo *lp)
1463 {
1464 	switch (lp->type) {
1465 	case LINUX_DVD_LU_SEND_AGID:
1466 		lp->lsa.agid = bp->agid;
1467 		break;
1468 	case LINUX_DVD_HOST_SEND_CHALLENGE:
1469 		lp->type = LINUX_DVD_LU_SEND_KEY1;
1470 		break;
1471 	case LINUX_DVD_LU_SEND_KEY1:
1472 		memcpy(lp->lsk.key, bp->keychal, sizeof(lp->lsk.key));
1473 		break;
1474 	case LINUX_DVD_LU_SEND_CHALLENGE:
1475 		memcpy(lp->lsc.chal, bp->keychal, sizeof(lp->lsc.chal));
1476 		break;
1477 	case LINUX_DVD_HOST_SEND_KEY2:
1478 		lp->type = LINUX_DVD_AUTH_ESTABLISHED;
1479 		break;
1480 	case LINUX_DVD_LU_SEND_TITLE_KEY:
1481 		memcpy(lp->lstk.title_key, bp->keychal,
1482 		    sizeof(lp->lstk.title_key));
1483 		lp->lstk.cpm = bp->cpm;
1484 		lp->lstk.cp_sec = bp->cp_sec;
1485 		lp->lstk.cgms = bp->cgms;
1486 		break;
1487 	case LINUX_DVD_LU_SEND_ASF:
1488 		lp->lsasf.asf = bp->asf;
1489 		break;
1490 	case LINUX_DVD_INVALIDATE_AGID:
1491 		break;
1492 	case LINUX_DVD_LU_SEND_RPC_STATE:
1493 		lp->lrpcs.type = bp->reg_type;
1494 		lp->lrpcs.vra = bp->vend_rsts;
1495 		lp->lrpcs.ucca = bp->user_rsts;
1496 		lp->lrpcs.region_mask = bp->region;
1497 		lp->lrpcs.rpc_scheme = bp->rpc_scheme;
1498 		break;
1499 	case LINUX_DVD_HOST_SEND_RPC_STATE:
1500 		break;
1501 	default:
1502 		return (EINVAL);
1503 	}
1504 	return (0);
1505 }
1506 
1507 static int
linux_ioctl_cdrom(struct thread * td,struct linux_ioctl_args * args)1508 linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args)
1509 {
1510 	struct file *fp;
1511 	int error;
1512 
1513 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
1514 	if (error != 0)
1515 		return (error);
1516 	switch (args->cmd & 0xffff) {
1517 	case LINUX_CDROMPAUSE:
1518 		args->cmd = CDIOCPAUSE;
1519 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1520 		break;
1521 
1522 	case LINUX_CDROMRESUME:
1523 		args->cmd = CDIOCRESUME;
1524 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1525 		break;
1526 
1527 	case LINUX_CDROMPLAYMSF:
1528 		args->cmd = CDIOCPLAYMSF;
1529 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1530 		break;
1531 
1532 	case LINUX_CDROMPLAYTRKIND:
1533 		args->cmd = CDIOCPLAYTRACKS;
1534 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1535 		break;
1536 
1537 	case LINUX_CDROMREADTOCHDR: {
1538 		struct ioc_toc_header th;
1539 		struct linux_cdrom_tochdr lth;
1540 		error = fo_ioctl(fp, CDIOREADTOCHEADER, (caddr_t)&th,
1541 		    td->td_ucred, td);
1542 		if (!error) {
1543 			lth.cdth_trk0 = th.starting_track;
1544 			lth.cdth_trk1 = th.ending_track;
1545 			error = copyout(&lth, (void *)args->arg, sizeof(lth));
1546 		}
1547 		break;
1548 	}
1549 
1550 	case LINUX_CDROMREADTOCENTRY: {
1551 		struct linux_cdrom_tocentry lte;
1552 		struct ioc_read_toc_single_entry irtse;
1553 
1554 		error = copyin((void *)args->arg, &lte, sizeof(lte));
1555 		if (error)
1556 			break;
1557 		irtse.address_format = lte.cdte_format;
1558 		irtse.track = lte.cdte_track;
1559 		error = fo_ioctl(fp, CDIOREADTOCENTRY, (caddr_t)&irtse,
1560 		    td->td_ucred, td);
1561 		if (!error) {
1562 			lte.cdte_ctrl = irtse.entry.control;
1563 			lte.cdte_adr = irtse.entry.addr_type;
1564 			bsd_to_linux_msf_lba(irtse.address_format,
1565 			    &irtse.entry.addr, &lte.cdte_addr);
1566 			error = copyout(&lte, (void *)args->arg, sizeof(lte));
1567 		}
1568 		break;
1569 	}
1570 
1571 	case LINUX_CDROMSTOP:
1572 		args->cmd = CDIOCSTOP;
1573 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1574 		break;
1575 
1576 	case LINUX_CDROMSTART:
1577 		args->cmd = CDIOCSTART;
1578 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1579 		break;
1580 
1581 	case LINUX_CDROMEJECT:
1582 		args->cmd = CDIOCEJECT;
1583 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1584 		break;
1585 
1586 	/* LINUX_CDROMVOLCTRL */
1587 
1588 	case LINUX_CDROMSUBCHNL: {
1589 		struct linux_cdrom_subchnl sc;
1590 		struct ioc_read_subchannel bsdsc;
1591 		struct cd_sub_channel_info bsdinfo;
1592 
1593 		error = copyin((void *)args->arg, &sc, sizeof(sc));
1594 		if (error)
1595 			break;
1596 
1597 		/*
1598 		 * Invoke the native ioctl and bounce the returned data through
1599 		 * the userspace buffer.  This works because the Linux structure
1600 		 * is the same size as our structures for the subchannel header
1601 		 * and position data.
1602 		 */
1603 		bsdsc.address_format = CD_LBA_FORMAT;
1604 		bsdsc.data_format = CD_CURRENT_POSITION;
1605 		bsdsc.track = 0;
1606 		bsdsc.data_len = sizeof(sc);
1607 		bsdsc.data = (void *)args->arg;
1608 		error = fo_ioctl(fp, CDIOCREADSUBCHANNEL, (caddr_t)&bsdsc,
1609 		    td->td_ucred, td);
1610 		if (error)
1611 			break;
1612 		error = copyin((void *)args->arg, &bsdinfo, sizeof(bsdinfo));
1613 		if (error)
1614 			break;
1615 		sc.cdsc_audiostatus = bsdinfo.header.audio_status;
1616 		sc.cdsc_adr = bsdinfo.what.position.addr_type;
1617 		sc.cdsc_ctrl = bsdinfo.what.position.control;
1618 		sc.cdsc_trk = bsdinfo.what.position.track_number;
1619 		sc.cdsc_ind = bsdinfo.what.position.index_number;
1620 		set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format,
1621 		    bsdinfo.what.position.absaddr.lba);
1622 		set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format,
1623 		    bsdinfo.what.position.reladdr.lba);
1624 		error = copyout(&sc, (void *)args->arg, sizeof(sc));
1625 		break;
1626 	}
1627 
1628 	/* LINUX_CDROMREADMODE2 */
1629 	/* LINUX_CDROMREADMODE1 */
1630 	/* LINUX_CDROMREADAUDIO */
1631 	/* LINUX_CDROMEJECT_SW */
1632 	/* LINUX_CDROMMULTISESSION */
1633 	/* LINUX_CDROM_GET_UPC */
1634 
1635 	case LINUX_CDROMRESET:
1636 		args->cmd = CDIOCRESET;
1637 		error = (sys_ioctl(td, (struct ioctl_args *)args));
1638 		break;
1639 
1640 	/* LINUX_CDROMVOLREAD */
1641 	/* LINUX_CDROMREADRAW */
1642 	/* LINUX_CDROMREADCOOKED */
1643 	/* LINUX_CDROMSEEK */
1644 	/* LINUX_CDROMPLAYBLK */
1645 	/* LINUX_CDROMREADALL */
1646 	/* LINUX_CDROMCLOSETRAY */
1647 	/* LINUX_CDROMLOADFROMSLOT */
1648 	/* LINUX_CDROMGETSPINDOWN */
1649 	/* LINUX_CDROMSETSPINDOWN */
1650 	/* LINUX_CDROM_SET_OPTIONS */
1651 	/* LINUX_CDROM_CLEAR_OPTIONS */
1652 	/* LINUX_CDROM_SELECT_SPEED */
1653 	/* LINUX_CDROM_SELECT_DISC */
1654 	/* LINUX_CDROM_MEDIA_CHANGED */
1655 	/* LINUX_CDROM_DRIVE_STATUS */
1656 	/* LINUX_CDROM_DISC_STATUS */
1657 	/* LINUX_CDROM_CHANGER_NSLOTS */
1658 	/* LINUX_CDROM_LOCKDOOR */
1659 	/* LINUX_CDROM_DEBUG */
1660 	/* LINUX_CDROM_GET_CAPABILITY */
1661 	/* LINUX_CDROMAUDIOBUFSIZ */
1662 
1663 	case LINUX_DVD_READ_STRUCT: {
1664 		l_dvd_struct *lds;
1665 		struct dvd_struct *bds;
1666 
1667 		lds = malloc(sizeof(*lds), M_LINUX, M_WAITOK);
1668 		bds = malloc(sizeof(*bds), M_LINUX, M_WAITOK);
1669 		error = copyin((void *)args->arg, lds, sizeof(*lds));
1670 		if (error)
1671 			goto out;
1672 		error = linux_to_bsd_dvd_struct(lds, bds);
1673 		if (error)
1674 			goto out;
1675 		error = fo_ioctl(fp, DVDIOCREADSTRUCTURE, (caddr_t)bds,
1676 		    td->td_ucred, td);
1677 		if (error)
1678 			goto out;
1679 		error = bsd_to_linux_dvd_struct(bds, lds);
1680 		if (error)
1681 			goto out;
1682 		error = copyout(lds, (void *)args->arg, sizeof(*lds));
1683 	out:
1684 		free(bds, M_LINUX);
1685 		free(lds, M_LINUX);
1686 		break;
1687 	}
1688 
1689 	/* LINUX_DVD_WRITE_STRUCT */
1690 
1691 	case LINUX_DVD_AUTH: {
1692 		l_dvd_authinfo lda;
1693 		struct dvd_authinfo bda;
1694 		int bcode;
1695 
1696 		error = copyin((void *)args->arg, &lda, sizeof(lda));
1697 		if (error)
1698 			break;
1699 		error = linux_to_bsd_dvd_authinfo(&lda, &bcode, &bda);
1700 		if (error)
1701 			break;
1702 		error = fo_ioctl(fp, bcode, (caddr_t)&bda, td->td_ucred,
1703 		    td);
1704 		if (error) {
1705 			if (lda.type == LINUX_DVD_HOST_SEND_KEY2) {
1706 				lda.type = LINUX_DVD_AUTH_FAILURE;
1707 				(void)copyout(&lda, (void *)args->arg,
1708 				    sizeof(lda));
1709 			}
1710 			break;
1711 		}
1712 		error = bsd_to_linux_dvd_authinfo(&bda, &lda);
1713 		if (error)
1714 			break;
1715 		error = copyout(&lda, (void *)args->arg, sizeof(lda));
1716 		break;
1717 	}
1718 
1719 	case LINUX_SCSI_GET_BUS_NUMBER:
1720 	{
1721 		struct sg_scsi_id id;
1722 
1723 		error = fo_ioctl(fp, SG_GET_SCSI_ID, (caddr_t)&id,
1724 		    td->td_ucred, td);
1725 		if (error)
1726 			break;
1727 		error = copyout(&id.channel, (void *)args->arg, sizeof(int));
1728 		break;
1729 	}
1730 
1731 	case LINUX_SCSI_GET_IDLUN:
1732 	{
1733 		struct sg_scsi_id id;
1734 		struct scsi_idlun idl;
1735 
1736 		error = fo_ioctl(fp, SG_GET_SCSI_ID, (caddr_t)&id,
1737 		    td->td_ucred, td);
1738 		if (error)
1739 			break;
1740 		idl.dev_id = (id.scsi_id & 0xff) + ((id.lun & 0xff) << 8) +
1741 		    ((id.channel & 0xff) << 16) + ((id.host_no & 0xff) << 24);
1742 		idl.host_unique_id = id.host_no;
1743 		error = copyout(&idl, (void *)args->arg, sizeof(idl));
1744 		break;
1745 	}
1746 
1747 	/* LINUX_CDROM_SEND_PACKET */
1748 	/* LINUX_CDROM_NEXT_WRITABLE */
1749 	/* LINUX_CDROM_LAST_WRITTEN */
1750 
1751 	default:
1752 		error = ENOIOCTL;
1753 		break;
1754 	}
1755 
1756 	fdrop(fp, td);
1757 	return (error);
1758 }
1759 
1760 static int
linux_ioctl_vfat(struct thread * td,struct linux_ioctl_args * args)1761 linux_ioctl_vfat(struct thread *td, struct linux_ioctl_args *args)
1762 {
1763 
1764 	return (ENOTTY);
1765 }
1766 
1767 /*
1768  * Sound related ioctls
1769  */
1770 
1771 struct linux_old_mixer_info {
1772 	char	id[16];
1773 	char	name[32];
1774 };
1775 
1776 static uint32_t dirbits[4] = { IOC_VOID, IOC_IN, IOC_OUT, IOC_INOUT };
1777 
1778 #define	SETDIR(c)	(((c) & ~IOC_DIRMASK) | dirbits[args->cmd >> 30])
1779 
1780 static int
linux_ioctl_sound(struct thread * td,struct linux_ioctl_args * args)1781 linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args)
1782 {
1783 
1784 	switch (args->cmd & 0xffff) {
1785 	case LINUX_SOUND_MIXER_WRITE_VOLUME:
1786 		args->cmd = SETDIR(SOUND_MIXER_WRITE_VOLUME);
1787 		return (sys_ioctl(td, (struct ioctl_args *)args));
1788 
1789 	case LINUX_SOUND_MIXER_WRITE_BASS:
1790 		args->cmd = SETDIR(SOUND_MIXER_WRITE_BASS);
1791 		return (sys_ioctl(td, (struct ioctl_args *)args));
1792 
1793 	case LINUX_SOUND_MIXER_WRITE_TREBLE:
1794 		args->cmd = SETDIR(SOUND_MIXER_WRITE_TREBLE);
1795 		return (sys_ioctl(td, (struct ioctl_args *)args));
1796 
1797 	case LINUX_SOUND_MIXER_WRITE_SYNTH:
1798 		args->cmd = SETDIR(SOUND_MIXER_WRITE_SYNTH);
1799 		return (sys_ioctl(td, (struct ioctl_args *)args));
1800 
1801 	case LINUX_SOUND_MIXER_WRITE_PCM:
1802 		args->cmd = SETDIR(SOUND_MIXER_WRITE_PCM);
1803 		return (sys_ioctl(td, (struct ioctl_args *)args));
1804 
1805 	case LINUX_SOUND_MIXER_WRITE_SPEAKER:
1806 		args->cmd = SETDIR(SOUND_MIXER_WRITE_SPEAKER);
1807 		return (sys_ioctl(td, (struct ioctl_args *)args));
1808 
1809 	case LINUX_SOUND_MIXER_WRITE_LINE:
1810 		args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE);
1811 		return (sys_ioctl(td, (struct ioctl_args *)args));
1812 
1813 	case LINUX_SOUND_MIXER_WRITE_MIC:
1814 		args->cmd = SETDIR(SOUND_MIXER_WRITE_MIC);
1815 		return (sys_ioctl(td, (struct ioctl_args *)args));
1816 
1817 	case LINUX_SOUND_MIXER_WRITE_CD:
1818 		args->cmd = SETDIR(SOUND_MIXER_WRITE_CD);
1819 		return (sys_ioctl(td, (struct ioctl_args *)args));
1820 
1821 	case LINUX_SOUND_MIXER_WRITE_IMIX:
1822 		args->cmd = SETDIR(SOUND_MIXER_WRITE_IMIX);
1823 		return (sys_ioctl(td, (struct ioctl_args *)args));
1824 
1825 	case LINUX_SOUND_MIXER_WRITE_ALTPCM:
1826 		args->cmd = SETDIR(SOUND_MIXER_WRITE_ALTPCM);
1827 		return (sys_ioctl(td, (struct ioctl_args *)args));
1828 
1829 	case LINUX_SOUND_MIXER_WRITE_RECLEV:
1830 		args->cmd = SETDIR(SOUND_MIXER_WRITE_RECLEV);
1831 		return (sys_ioctl(td, (struct ioctl_args *)args));
1832 
1833 	case LINUX_SOUND_MIXER_WRITE_IGAIN:
1834 		args->cmd = SETDIR(SOUND_MIXER_WRITE_IGAIN);
1835 		return (sys_ioctl(td, (struct ioctl_args *)args));
1836 
1837 	case LINUX_SOUND_MIXER_WRITE_OGAIN:
1838 		args->cmd = SETDIR(SOUND_MIXER_WRITE_OGAIN);
1839 		return (sys_ioctl(td, (struct ioctl_args *)args));
1840 
1841 	case LINUX_SOUND_MIXER_WRITE_LINE1:
1842 		args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE1);
1843 		return (sys_ioctl(td, (struct ioctl_args *)args));
1844 
1845 	case LINUX_SOUND_MIXER_WRITE_LINE2:
1846 		args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE2);
1847 		return (sys_ioctl(td, (struct ioctl_args *)args));
1848 
1849 	case LINUX_SOUND_MIXER_WRITE_LINE3:
1850 		args->cmd = SETDIR(SOUND_MIXER_WRITE_LINE3);
1851 		return (sys_ioctl(td, (struct ioctl_args *)args));
1852 
1853 	case LINUX_SOUND_MIXER_WRITE_MONITOR:
1854 		args->cmd = SETDIR(SOUND_MIXER_WRITE_MONITOR);
1855 		return (sys_ioctl(td, (struct ioctl_args *)args));
1856 
1857 	case LINUX_SOUND_MIXER_INFO: {
1858 		/* Key on encoded length */
1859 		switch ((args->cmd >> 16) & 0x1fff) {
1860 		case 0x005c: {	/* SOUND_MIXER_INFO */
1861 			args->cmd = SOUND_MIXER_INFO;
1862 			return (sys_ioctl(td, (struct ioctl_args *)args));
1863 		}
1864 		case 0x0030: {	/* SOUND_OLD_MIXER_INFO */
1865 			struct linux_old_mixer_info info;
1866 			bzero(&info, sizeof(info));
1867 			strncpy(info.id, "OSS", sizeof(info.id) - 1);
1868 			strncpy(info.name, "FreeBSD OSS Mixer",
1869 			    sizeof(info.name) - 1);
1870 			return (copyout(&info, (void *)args->arg,
1871 			    sizeof(info)));
1872 		}
1873 		default:
1874 			return (ENOIOCTL);
1875 		}
1876 		break;
1877 	}
1878 
1879 	case LINUX_OSS_GETVERSION: {
1880 		int version = linux_get_oss_version(td);
1881 		return (copyout(&version, (void *)args->arg, sizeof(int)));
1882 	}
1883 
1884 	case LINUX_SOUND_MIXER_READ_STEREODEVS:
1885 		args->cmd = SOUND_MIXER_READ_STEREODEVS;
1886 		return (sys_ioctl(td, (struct ioctl_args *)args));
1887 
1888 	case LINUX_SOUND_MIXER_READ_CAPS:
1889 		args->cmd = SOUND_MIXER_READ_CAPS;
1890 		return (sys_ioctl(td, (struct ioctl_args *)args));
1891 
1892 	case LINUX_SOUND_MIXER_READ_RECMASK:
1893 		args->cmd = SOUND_MIXER_READ_RECMASK;
1894 		return (sys_ioctl(td, (struct ioctl_args *)args));
1895 
1896 	case LINUX_SOUND_MIXER_READ_DEVMASK:
1897 		args->cmd = SOUND_MIXER_READ_DEVMASK;
1898 		return (sys_ioctl(td, (struct ioctl_args *)args));
1899 
1900 	case LINUX_SOUND_MIXER_WRITE_RECSRC:
1901 		args->cmd = SETDIR(SOUND_MIXER_WRITE_RECSRC);
1902 		return (sys_ioctl(td, (struct ioctl_args *)args));
1903 
1904 	case LINUX_SNDCTL_DSP_RESET:
1905 		args->cmd = SNDCTL_DSP_RESET;
1906 		return (sys_ioctl(td, (struct ioctl_args *)args));
1907 
1908 	case LINUX_SNDCTL_DSP_SYNC:
1909 		args->cmd = SNDCTL_DSP_SYNC;
1910 		return (sys_ioctl(td, (struct ioctl_args *)args));
1911 
1912 	case LINUX_SNDCTL_DSP_SPEED:
1913 		args->cmd = SNDCTL_DSP_SPEED;
1914 		return (sys_ioctl(td, (struct ioctl_args *)args));
1915 
1916 	case LINUX_SNDCTL_DSP_STEREO:
1917 		args->cmd = SNDCTL_DSP_STEREO;
1918 		return (sys_ioctl(td, (struct ioctl_args *)args));
1919 
1920 	case LINUX_SNDCTL_DSP_GETBLKSIZE: /* LINUX_SNDCTL_DSP_SETBLKSIZE */
1921 		args->cmd = SNDCTL_DSP_GETBLKSIZE;
1922 		return (sys_ioctl(td, (struct ioctl_args *)args));
1923 
1924 	case LINUX_SNDCTL_DSP_SETFMT:
1925 		args->cmd = SNDCTL_DSP_SETFMT;
1926 		return (sys_ioctl(td, (struct ioctl_args *)args));
1927 
1928 	case LINUX_SOUND_PCM_WRITE_CHANNELS:
1929 		args->cmd = SOUND_PCM_WRITE_CHANNELS;
1930 		return (sys_ioctl(td, (struct ioctl_args *)args));
1931 
1932 	case LINUX_SOUND_PCM_WRITE_FILTER:
1933 		args->cmd = SOUND_PCM_WRITE_FILTER;
1934 		return (sys_ioctl(td, (struct ioctl_args *)args));
1935 
1936 	case LINUX_SNDCTL_DSP_POST:
1937 		args->cmd = SNDCTL_DSP_POST;
1938 		return (sys_ioctl(td, (struct ioctl_args *)args));
1939 
1940 	case LINUX_SNDCTL_DSP_SUBDIVIDE:
1941 		args->cmd = SNDCTL_DSP_SUBDIVIDE;
1942 		return (sys_ioctl(td, (struct ioctl_args *)args));
1943 
1944 	case LINUX_SNDCTL_DSP_SETFRAGMENT:
1945 		args->cmd = SNDCTL_DSP_SETFRAGMENT;
1946 		return (sys_ioctl(td, (struct ioctl_args *)args));
1947 
1948 	case LINUX_SNDCTL_DSP_GETFMTS:
1949 		args->cmd = SNDCTL_DSP_GETFMTS;
1950 		return (sys_ioctl(td, (struct ioctl_args *)args));
1951 
1952 	case LINUX_SNDCTL_DSP_GETOSPACE:
1953 		args->cmd = SNDCTL_DSP_GETOSPACE;
1954 		return (sys_ioctl(td, (struct ioctl_args *)args));
1955 
1956 	case LINUX_SNDCTL_DSP_GETISPACE:
1957 		args->cmd = SNDCTL_DSP_GETISPACE;
1958 		return (sys_ioctl(td, (struct ioctl_args *)args));
1959 
1960 	case LINUX_SNDCTL_DSP_NONBLOCK:
1961 		args->cmd = SNDCTL_DSP_NONBLOCK;
1962 		return (sys_ioctl(td, (struct ioctl_args *)args));
1963 
1964 	case LINUX_SNDCTL_DSP_GETCAPS:
1965 		args->cmd = SNDCTL_DSP_GETCAPS;
1966 		return (sys_ioctl(td, (struct ioctl_args *)args));
1967 
1968 	case LINUX_SNDCTL_DSP_SETTRIGGER: /* LINUX_SNDCTL_GETTRIGGER */
1969 		args->cmd = SNDCTL_DSP_SETTRIGGER;
1970 		return (sys_ioctl(td, (struct ioctl_args *)args));
1971 
1972 	case LINUX_SNDCTL_DSP_GETIPTR:
1973 		args->cmd = SNDCTL_DSP_GETIPTR;
1974 		return (sys_ioctl(td, (struct ioctl_args *)args));
1975 
1976 	case LINUX_SNDCTL_DSP_GETOPTR:
1977 		args->cmd = SNDCTL_DSP_GETOPTR;
1978 		return (sys_ioctl(td, (struct ioctl_args *)args));
1979 
1980 	case LINUX_SNDCTL_DSP_SETDUPLEX:
1981 		args->cmd = SNDCTL_DSP_SETDUPLEX;
1982 		return (sys_ioctl(td, (struct ioctl_args *)args));
1983 
1984 	case LINUX_SNDCTL_DSP_GETODELAY:
1985 		args->cmd = SNDCTL_DSP_GETODELAY;
1986 		return (sys_ioctl(td, (struct ioctl_args *)args));
1987 
1988 	case LINUX_SNDCTL_SEQ_RESET:
1989 		args->cmd = SNDCTL_SEQ_RESET;
1990 		return (sys_ioctl(td, (struct ioctl_args *)args));
1991 
1992 	case LINUX_SNDCTL_SEQ_SYNC:
1993 		args->cmd = SNDCTL_SEQ_SYNC;
1994 		return (sys_ioctl(td, (struct ioctl_args *)args));
1995 
1996 	case LINUX_SNDCTL_SYNTH_INFO:
1997 		args->cmd = SNDCTL_SYNTH_INFO;
1998 		return (sys_ioctl(td, (struct ioctl_args *)args));
1999 
2000 	case LINUX_SNDCTL_SEQ_CTRLRATE:
2001 		args->cmd = SNDCTL_SEQ_CTRLRATE;
2002 		return (sys_ioctl(td, (struct ioctl_args *)args));
2003 
2004 	case LINUX_SNDCTL_SEQ_GETOUTCOUNT:
2005 		args->cmd = SNDCTL_SEQ_GETOUTCOUNT;
2006 		return (sys_ioctl(td, (struct ioctl_args *)args));
2007 
2008 	case LINUX_SNDCTL_SEQ_GETINCOUNT:
2009 		args->cmd = SNDCTL_SEQ_GETINCOUNT;
2010 		return (sys_ioctl(td, (struct ioctl_args *)args));
2011 
2012 	case LINUX_SNDCTL_SEQ_PERCMODE:
2013 		args->cmd = SNDCTL_SEQ_PERCMODE;
2014 		return (sys_ioctl(td, (struct ioctl_args *)args));
2015 
2016 	case LINUX_SNDCTL_FM_LOAD_INSTR:
2017 		args->cmd = SNDCTL_FM_LOAD_INSTR;
2018 		return (sys_ioctl(td, (struct ioctl_args *)args));
2019 
2020 	case LINUX_SNDCTL_SEQ_TESTMIDI:
2021 		args->cmd = SNDCTL_SEQ_TESTMIDI;
2022 		return (sys_ioctl(td, (struct ioctl_args *)args));
2023 
2024 	case LINUX_SNDCTL_SEQ_RESETSAMPLES:
2025 		args->cmd = SNDCTL_SEQ_RESETSAMPLES;
2026 		return (sys_ioctl(td, (struct ioctl_args *)args));
2027 
2028 	case LINUX_SNDCTL_SEQ_NRSYNTHS:
2029 		args->cmd = SNDCTL_SEQ_NRSYNTHS;
2030 		return (sys_ioctl(td, (struct ioctl_args *)args));
2031 
2032 	case LINUX_SNDCTL_SEQ_NRMIDIS:
2033 		args->cmd = SNDCTL_SEQ_NRMIDIS;
2034 		return (sys_ioctl(td, (struct ioctl_args *)args));
2035 
2036 	case LINUX_SNDCTL_MIDI_INFO:
2037 		args->cmd = SNDCTL_MIDI_INFO;
2038 		return (sys_ioctl(td, (struct ioctl_args *)args));
2039 
2040 	case LINUX_SNDCTL_SEQ_TRESHOLD:
2041 		args->cmd = SNDCTL_SEQ_TRESHOLD;
2042 		return (sys_ioctl(td, (struct ioctl_args *)args));
2043 
2044 	case LINUX_SNDCTL_SYNTH_MEMAVL:
2045 		args->cmd = SNDCTL_SYNTH_MEMAVL;
2046 		return (sys_ioctl(td, (struct ioctl_args *)args));
2047 	}
2048 
2049 	return (ENOIOCTL);
2050 }
2051 
2052 /*
2053  * Console related ioctls
2054  */
2055 
2056 static int
linux_ioctl_console(struct thread * td,struct linux_ioctl_args * args)2057 linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args)
2058 {
2059 	struct file *fp;
2060 	int error;
2061 
2062 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
2063 	if (error != 0)
2064 		return (error);
2065 	switch (args->cmd & 0xffff) {
2066 	case LINUX_KIOCSOUND:
2067 		args->cmd = KIOCSOUND;
2068 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2069 		break;
2070 
2071 	case LINUX_KDMKTONE:
2072 		args->cmd = KDMKTONE;
2073 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2074 		break;
2075 
2076 	case LINUX_KDGETLED:
2077 		args->cmd = KDGETLED;
2078 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2079 		break;
2080 
2081 	case LINUX_KDSETLED:
2082 		args->cmd = KDSETLED;
2083 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2084 		break;
2085 
2086 	case LINUX_KDSETMODE:
2087 		args->cmd = KDSETMODE;
2088 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2089 		break;
2090 
2091 	case LINUX_KDGETMODE:
2092 		args->cmd = KDGETMODE;
2093 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2094 		break;
2095 
2096 	case LINUX_KDGKBMODE:
2097 		args->cmd = KDGKBMODE;
2098 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2099 		break;
2100 
2101 	case LINUX_KDSKBMODE: {
2102 		int kbdmode;
2103 		switch (args->arg) {
2104 		case LINUX_KBD_RAW:
2105 			kbdmode = K_RAW;
2106 			break;
2107 		case LINUX_KBD_XLATE:
2108 			kbdmode = K_XLATE;
2109 			break;
2110 		case LINUX_KBD_MEDIUMRAW:
2111 			kbdmode = K_RAW;
2112 			break;
2113 		default:
2114 			fdrop(fp, td);
2115 			return (EINVAL);
2116 		}
2117 		error = (fo_ioctl(fp, KDSKBMODE, (caddr_t)&kbdmode,
2118 		    td->td_ucred, td));
2119 		break;
2120 	}
2121 
2122 	case LINUX_VT_OPENQRY:
2123 		args->cmd = VT_OPENQRY;
2124 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2125 		break;
2126 
2127 	case LINUX_VT_GETMODE:
2128 		args->cmd = VT_GETMODE;
2129 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2130 		break;
2131 
2132 	case LINUX_VT_SETMODE: {
2133 		struct vt_mode mode;
2134 		if ((error = copyin((void *)args->arg, &mode, sizeof(mode))))
2135 			break;
2136 		if (LINUX_SIG_VALID(mode.relsig))
2137 			mode.relsig = linux_to_bsd_signal(mode.relsig);
2138 		else
2139 			mode.relsig = 0;
2140 		if (LINUX_SIG_VALID(mode.acqsig))
2141 			mode.acqsig = linux_to_bsd_signal(mode.acqsig);
2142 		else
2143 			mode.acqsig = 0;
2144 		/* XXX. Linux ignores frsig and set it to 0. */
2145 		mode.frsig = 0;
2146 		if ((error = copyout(&mode, (void *)args->arg, sizeof(mode))))
2147 			break;
2148 		args->cmd = VT_SETMODE;
2149 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2150 		break;
2151 	}
2152 
2153 	case LINUX_VT_GETSTATE:
2154 		args->cmd = VT_GETACTIVE;
2155 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2156 		break;
2157 
2158 	case LINUX_VT_RELDISP:
2159 		args->cmd = VT_RELDISP;
2160 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2161 		break;
2162 
2163 	case LINUX_VT_ACTIVATE:
2164 		args->cmd = VT_ACTIVATE;
2165 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2166 		break;
2167 
2168 	case LINUX_VT_WAITACTIVE:
2169 		args->cmd = VT_WAITACTIVE;
2170 		error = (sys_ioctl(td, (struct ioctl_args *)args));
2171 		break;
2172 
2173 	default:
2174 		error = ENOIOCTL;
2175 		break;
2176 	}
2177 
2178 	fdrop(fp, td);
2179 	return (error);
2180 }
2181 
2182 /*
2183  * Implement the SIOCGIFNAME ioctl
2184  */
2185 
2186 static int
linux_ioctl_ifname(struct thread * td,struct l_ifreq * uifr)2187 linux_ioctl_ifname(struct thread *td, struct l_ifreq *uifr)
2188 {
2189 	struct l_ifreq ifr;
2190 	int error, ret;
2191 
2192 	error = copyin(uifr, &ifr, sizeof(ifr));
2193 	if (error != 0)
2194 		return (error);
2195 	ret = ifname_bsd_to_linux_idx(ifr.ifr_index, ifr.ifr_name,
2196 	    LINUX_IFNAMSIZ);
2197 	if (ret > 0)
2198 		return (copyout(&ifr, uifr, sizeof(ifr)));
2199 	else
2200 		return (ENODEV);
2201 }
2202 
2203 /*
2204  * Implement the SIOCGIFCONF ioctl
2205  */
2206 static u_int
linux_ifconf_ifaddr_cb(void * arg,struct ifaddr * ifa,u_int count)2207 linux_ifconf_ifaddr_cb(void *arg, struct ifaddr *ifa, u_int count)
2208 {
2209 #ifdef COMPAT_LINUX32
2210 	struct l_ifconf *ifc;
2211 #else
2212 	struct ifconf *ifc;
2213 #endif
2214 
2215 	ifc = arg;
2216 	ifc->ifc_len += sizeof(struct l_ifreq);
2217 	return (1);
2218 }
2219 
2220 static int
linux_ifconf_ifnet_cb(if_t ifp,void * arg)2221 linux_ifconf_ifnet_cb(if_t ifp, void *arg)
2222 {
2223 
2224 	if_foreach_addr_type(ifp, AF_INET, linux_ifconf_ifaddr_cb, arg);
2225 	return (0);
2226 }
2227 
2228 struct linux_ifconfig_ifaddr_cb2_s {
2229 	struct l_ifreq ifr;
2230 	struct sbuf *sb;
2231 	size_t max_len;
2232 	size_t valid_len;
2233 };
2234 
2235 static u_int
linux_ifconf_ifaddr_cb2(void * arg,struct ifaddr * ifa,u_int len)2236 linux_ifconf_ifaddr_cb2(void *arg, struct ifaddr *ifa, u_int len)
2237 {
2238 	struct linux_ifconfig_ifaddr_cb2_s *cbs = arg;
2239 	struct sockaddr *sa = ifa->ifa_addr;
2240 
2241 	cbs->ifr.ifr_addr.sa_family = LINUX_AF_INET;
2242 	memcpy(cbs->ifr.ifr_addr.sa_data, sa->sa_data,
2243 	    sizeof(cbs->ifr.ifr_addr.sa_data));
2244 	sbuf_bcat(cbs->sb, &cbs->ifr, sizeof(cbs->ifr));
2245 	cbs->max_len += sizeof(cbs->ifr);
2246 
2247 	if (sbuf_error(cbs->sb) == 0)
2248 		cbs->valid_len = sbuf_len(cbs->sb);
2249 	return (1);
2250 }
2251 
2252 static int
linux_ifconf_ifnet_cb2(if_t ifp,void * arg)2253 linux_ifconf_ifnet_cb2(if_t ifp, void *arg)
2254 {
2255 	struct linux_ifconfig_ifaddr_cb2_s *cbs = arg;
2256 
2257 	bzero(&cbs->ifr, sizeof(cbs->ifr));
2258 	ifname_bsd_to_linux_ifp(ifp, cbs->ifr.ifr_name,
2259 	    sizeof(cbs->ifr.ifr_name));
2260 
2261 	/* Walk the address list */
2262 	if_foreach_addr_type(ifp, AF_INET, linux_ifconf_ifaddr_cb2, cbs);
2263 	return (0);
2264 }
2265 
2266 static int
linux_ifconf(struct thread * td,struct ifconf * uifc)2267 linux_ifconf(struct thread *td, struct ifconf *uifc)
2268 {
2269 	struct linux_ifconfig_ifaddr_cb2_s cbs;
2270 	struct epoch_tracker et;
2271 #ifdef COMPAT_LINUX32
2272 	struct l_ifconf ifc;
2273 #else
2274 	struct ifconf ifc;
2275 #endif
2276 	struct sbuf *sb;
2277 	int error, full;
2278 
2279 	error = copyin(uifc, &ifc, sizeof(ifc));
2280 	if (error != 0)
2281 		return (error);
2282 
2283 	/* handle the 'request buffer size' case */
2284 	if (PTRIN(ifc.ifc_buf) == NULL) {
2285 		ifc.ifc_len = 0;
2286 		NET_EPOCH_ENTER(et);
2287 		if_foreach(linux_ifconf_ifnet_cb, &ifc);
2288 		NET_EPOCH_EXIT(et);
2289 		return (copyout(&ifc, uifc, sizeof(ifc)));
2290 	}
2291 	if (ifc.ifc_len <= 0)
2292 		return (EINVAL);
2293 
2294 	full = 0;
2295 	cbs.max_len = maxphys - 1;
2296 
2297 again:
2298 	if (ifc.ifc_len <= cbs.max_len) {
2299 		cbs.max_len = ifc.ifc_len;
2300 		full = 1;
2301 	}
2302 	cbs.sb = sb = sbuf_new(NULL, NULL, cbs.max_len + 1, SBUF_FIXEDLEN);
2303 	cbs.max_len = 0;
2304 	cbs.valid_len = 0;
2305 
2306 	/* Return all AF_INET addresses of all interfaces */
2307 	NET_EPOCH_ENTER(et);
2308 	if_foreach(linux_ifconf_ifnet_cb2, &cbs);
2309 	NET_EPOCH_EXIT(et);
2310 
2311 	if (cbs.valid_len != cbs.max_len && !full) {
2312 		sbuf_delete(sb);
2313 		goto again;
2314 	}
2315 
2316 	ifc.ifc_len = cbs.valid_len;
2317 	sbuf_finish(sb);
2318 	error = copyout(sbuf_data(sb), PTRIN(ifc.ifc_buf), ifc.ifc_len);
2319 	if (error == 0)
2320 		error = copyout(&ifc, uifc, sizeof(ifc));
2321 	sbuf_delete(sb);
2322 
2323 	return (error);
2324 }
2325 
2326 static int
linux_ioctl_socket_ifreq(struct thread * td,int fd,u_int cmd,struct l_ifreq * uifr)2327 linux_ioctl_socket_ifreq(struct thread *td, int fd, u_int cmd,
2328     struct l_ifreq *uifr)
2329 {
2330 	struct l_ifreq lifr;
2331 	struct ifreq bifr;
2332 	size_t ifrusiz;
2333 	int error, temp_flags;
2334 
2335 	switch (cmd) {
2336 	case LINUX_SIOCGIFINDEX:
2337 		cmd = SIOCGIFINDEX;
2338 		break;
2339 	case LINUX_SIOCGIFFLAGS:
2340 		cmd = SIOCGIFFLAGS;
2341 		break;
2342 	case LINUX_SIOCGIFADDR:
2343 		cmd = SIOCGIFADDR;
2344 		break;
2345 	case LINUX_SIOCSIFADDR:
2346 		cmd = SIOCSIFADDR;
2347 		break;
2348 	case LINUX_SIOCGIFDSTADDR:
2349 		cmd = SIOCGIFDSTADDR;
2350 		break;
2351 	case LINUX_SIOCGIFBRDADDR:
2352 		cmd = SIOCGIFBRDADDR;
2353 		break;
2354 	case LINUX_SIOCGIFNETMASK:
2355 		cmd = SIOCGIFNETMASK;
2356 		break;
2357 	case LINUX_SIOCSIFNETMASK:
2358 		cmd = SIOCSIFNETMASK;
2359 		break;
2360 	case LINUX_SIOCGIFMTU:
2361 		cmd = SIOCGIFMTU;
2362 		break;
2363 	case LINUX_SIOCSIFMTU:
2364 		cmd = SIOCSIFMTU;
2365 		break;
2366 	case LINUX_SIOCGIFHWADDR:
2367 		cmd = SIOCGHWADDR;
2368 		break;
2369 	case LINUX_SIOCGIFMETRIC:
2370 		cmd = SIOCGIFMETRIC;
2371 		break;
2372 	case LINUX_SIOCSIFMETRIC:
2373 		cmd = SIOCSIFMETRIC;
2374 		break;
2375 	/*
2376 	 * XXX This is slightly bogus, but these ioctls are currently
2377 	 * XXX only used by the aironet (if_an) network driver.
2378 	 */
2379 	case LINUX_SIOCDEVPRIVATE:
2380 		cmd = SIOCGPRIVATE_0;
2381 		break;
2382 	case LINUX_SIOCDEVPRIVATE+1:
2383 		cmd = SIOCGPRIVATE_1;
2384 		break;
2385 	default:
2386 		LINUX_RATELIMIT_MSG_OPT2(
2387 		    "ioctl_socket_ifreq fd=%d, cmd=0x%x is not implemented",
2388 		    fd, cmd);
2389 		return (ENOIOCTL);
2390 	}
2391 
2392 	error = copyin(uifr, &lifr, sizeof(lifr));
2393 	if (error != 0)
2394 		return (error);
2395 	bzero(&bifr, sizeof(bifr));
2396 
2397 	/*
2398 	 * The size of Linux enum ifr_ifru is bigger than
2399 	 * the FreeBSD size due to the struct ifmap.
2400 	 */
2401 	ifrusiz = (sizeof(lifr) > sizeof(bifr) ? sizeof(bifr) :
2402 	    sizeof(lifr)) - offsetof(struct l_ifreq, ifr_ifru);
2403 	bcopy(&lifr.ifr_ifru, &bifr.ifr_ifru, ifrusiz);
2404 
2405 	error = ifname_linux_to_bsd(td, lifr.ifr_name, bifr.ifr_name);
2406 	if (error != 0)
2407 		return (error);
2408 
2409 	/* Translate in values. */
2410 	switch (cmd) {
2411 	case SIOCGIFINDEX:
2412 		bifr.ifr_index = lifr.ifr_index;
2413 		break;
2414 	case SIOCSIFADDR:
2415 	case SIOCSIFNETMASK:
2416 		bifr.ifr_addr.sa_len = sizeof(struct sockaddr);
2417 		bifr.ifr_addr.sa_family =
2418 		    linux_to_bsd_domain(lifr.ifr_addr.sa_family);
2419 		break;
2420 	default:
2421 		break;
2422 	}
2423 
2424 	error = kern_ioctl(td, fd, cmd, (caddr_t)&bifr);
2425 	if (error != 0)
2426 		return (error);
2427 	bzero(&lifr.ifr_ifru, sizeof(lifr.ifr_ifru));
2428 
2429 	/* Translate out values. */
2430  	switch (cmd) {
2431 	case SIOCGIFINDEX:
2432 		lifr.ifr_index = bifr.ifr_index;
2433 		break;
2434 	case SIOCGIFFLAGS:
2435 		temp_flags = bifr.ifr_flags | (bifr.ifr_flagshigh << 16);
2436 		lifr.ifr_flags = bsd_to_linux_ifflags(temp_flags);
2437 		break;
2438 	case SIOCGIFADDR:
2439 	case SIOCSIFADDR:
2440 	case SIOCGIFDSTADDR:
2441 	case SIOCGIFBRDADDR:
2442 	case SIOCGIFNETMASK:
2443 		bcopy(&bifr.ifr_addr, &lifr.ifr_addr, sizeof(bifr.ifr_addr));
2444 		lifr.ifr_addr.sa_family =
2445 		    bsd_to_linux_domain(bifr.ifr_addr.sa_family);
2446 		break;
2447 	case SIOCGHWADDR:
2448 		bcopy(&bifr.ifr_addr, &lifr.ifr_hwaddr, sizeof(bifr.ifr_addr));
2449 		lifr.ifr_hwaddr.sa_family = LINUX_ARPHRD_ETHER;
2450 		break;
2451 	default:
2452 		bcopy(&bifr.ifr_ifru, &lifr.ifr_ifru, ifrusiz);
2453 		break;
2454 	}
2455 
2456 	return (copyout(&lifr, uifr, sizeof(lifr)));
2457 }
2458 
2459 /*
2460  * Socket related ioctls
2461  */
2462 
2463 static int
linux_ioctl_socket(struct thread * td,struct linux_ioctl_args * args)2464 linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args)
2465 {
2466 	struct file *fp;
2467 	int error, type;
2468 
2469 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
2470 	if (error != 0)
2471 		return (error);
2472 	type = fp->f_type;
2473 	fdrop(fp, td);
2474 
2475 	CURVNET_SET(TD_TO_VNET(td));
2476 
2477 	if (type != DTYPE_SOCKET) {
2478 		/* not a socket - probably a tap / vmnet device */
2479 		switch (args->cmd) {
2480 		case LINUX_SIOCGIFADDR:
2481 		case LINUX_SIOCSIFADDR:
2482 		case LINUX_SIOCGIFFLAGS:
2483 			error = linux_ioctl_special(td, args);
2484 			break;
2485 		default:
2486 			error = ENOIOCTL;
2487 			break;
2488 		}
2489 		CURVNET_RESTORE();
2490 		return (error);
2491 	}
2492 
2493 	switch (args->cmd) {
2494 	case LINUX_FIOSETOWN:
2495 		args->cmd = FIOSETOWN;
2496 		error = sys_ioctl(td, (struct ioctl_args *)args);
2497 		break;
2498 
2499 	case LINUX_SIOCSPGRP:
2500 		args->cmd = SIOCSPGRP;
2501 		error = sys_ioctl(td, (struct ioctl_args *)args);
2502 		break;
2503 
2504 	case LINUX_FIOGETOWN:
2505 		args->cmd = FIOGETOWN;
2506 		error = sys_ioctl(td, (struct ioctl_args *)args);
2507 		break;
2508 
2509 	case LINUX_SIOCGPGRP:
2510 		args->cmd = SIOCGPGRP;
2511 		error = sys_ioctl(td, (struct ioctl_args *)args);
2512 		break;
2513 
2514 	case LINUX_SIOCATMARK:
2515 		args->cmd = SIOCATMARK;
2516 		error = sys_ioctl(td, (struct ioctl_args *)args);
2517 		break;
2518 
2519 	/* LINUX_SIOCGSTAMP */
2520 
2521 	case LINUX_SIOCGIFNAME:
2522 		error = linux_ioctl_ifname(td, (struct l_ifreq *)args->arg);
2523 		break;
2524 
2525 	case LINUX_SIOCGIFCONF:
2526 		error = linux_ifconf(td, (struct ifconf *)args->arg);
2527 		break;
2528 
2529 	case LINUX_SIOCADDMULTI:
2530 		args->cmd = SIOCADDMULTI;
2531 		error = sys_ioctl(td, (struct ioctl_args *)args);
2532 		break;
2533 
2534 	case LINUX_SIOCDELMULTI:
2535 		args->cmd = SIOCDELMULTI;
2536 		error = sys_ioctl(td, (struct ioctl_args *)args);
2537 		break;
2538 
2539 	case LINUX_SIOCGIFCOUNT:
2540 		error = 0;
2541 		break;
2542 
2543 	default:
2544 		error = linux_ioctl_socket_ifreq(td, args->fd, args->cmd,
2545 		    PTRIN(args->arg));
2546 		break;
2547 	}
2548 
2549 	CURVNET_RESTORE();
2550 	return (error);
2551 }
2552 
2553 /*
2554  * Device private ioctl handler
2555  */
2556 static int
linux_ioctl_private(struct thread * td,struct linux_ioctl_args * args)2557 linux_ioctl_private(struct thread *td, struct linux_ioctl_args *args)
2558 {
2559 	struct file *fp;
2560 	int error, type;
2561 
2562 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
2563 	if (error != 0)
2564 		return (error);
2565 	type = fp->f_type;
2566 	fdrop(fp, td);
2567 	if (type == DTYPE_SOCKET)
2568 		return (linux_ioctl_socket(td, args));
2569 	return (ENOIOCTL);
2570 }
2571 
2572 /*
2573  * DRM ioctl handler (sys/dev/drm)
2574  */
2575 static int
linux_ioctl_drm(struct thread * td,struct linux_ioctl_args * args)2576 linux_ioctl_drm(struct thread *td, struct linux_ioctl_args *args)
2577 {
2578 	args->cmd = SETDIR(args->cmd);
2579 	return (sys_ioctl(td, (struct ioctl_args *)args));
2580 }
2581 
2582 #ifdef COMPAT_LINUX32
2583 static int
linux_ioctl_sg_io(struct thread * td,struct linux_ioctl_args * args)2584 linux_ioctl_sg_io(struct thread *td, struct linux_ioctl_args *args)
2585 {
2586 	struct sg_io_hdr io;
2587 	struct sg_io_hdr32 io32;
2588 	struct file *fp;
2589 	int error;
2590 
2591 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
2592 	if (error != 0) {
2593 		printf("sg_linux_ioctl: fget returned %d\n", error);
2594 		return (error);
2595 	}
2596 
2597 	if ((error = copyin((void *)args->arg, &io32, sizeof(io32))) != 0)
2598 		goto out;
2599 
2600 	CP(io32, io, interface_id);
2601 	CP(io32, io, dxfer_direction);
2602 	CP(io32, io, cmd_len);
2603 	CP(io32, io, mx_sb_len);
2604 	CP(io32, io, iovec_count);
2605 	CP(io32, io, dxfer_len);
2606 	PTRIN_CP(io32, io, dxferp);
2607 	PTRIN_CP(io32, io, cmdp);
2608 	PTRIN_CP(io32, io, sbp);
2609 	CP(io32, io, timeout);
2610 	CP(io32, io, flags);
2611 	CP(io32, io, pack_id);
2612 	PTRIN_CP(io32, io, usr_ptr);
2613 	CP(io32, io, status);
2614 	CP(io32, io, masked_status);
2615 	CP(io32, io, msg_status);
2616 	CP(io32, io, sb_len_wr);
2617 	CP(io32, io, host_status);
2618 	CP(io32, io, driver_status);
2619 	CP(io32, io, resid);
2620 	CP(io32, io, duration);
2621 	CP(io32, io, info);
2622 
2623 	if ((error = fo_ioctl(fp, SG_IO, (caddr_t)&io, td->td_ucred, td)) != 0)
2624 		goto out;
2625 
2626 	CP(io, io32, interface_id);
2627 	CP(io, io32, dxfer_direction);
2628 	CP(io, io32, cmd_len);
2629 	CP(io, io32, mx_sb_len);
2630 	CP(io, io32, iovec_count);
2631 	CP(io, io32, dxfer_len);
2632 	PTROUT_CP(io, io32, dxferp);
2633 	PTROUT_CP(io, io32, cmdp);
2634 	PTROUT_CP(io, io32, sbp);
2635 	CP(io, io32, timeout);
2636 	CP(io, io32, flags);
2637 	CP(io, io32, pack_id);
2638 	PTROUT_CP(io, io32, usr_ptr);
2639 	CP(io, io32, status);
2640 	CP(io, io32, masked_status);
2641 	CP(io, io32, msg_status);
2642 	CP(io, io32, sb_len_wr);
2643 	CP(io, io32, host_status);
2644 	CP(io, io32, driver_status);
2645 	CP(io, io32, resid);
2646 	CP(io, io32, duration);
2647 	CP(io, io32, info);
2648 
2649 	error = copyout(&io32, (void *)args->arg, sizeof(io32));
2650 
2651 out:
2652 	fdrop(fp, td);
2653 	return (error);
2654 }
2655 #endif
2656 
2657 static int
linux_ioctl_sg(struct thread * td,struct linux_ioctl_args * args)2658 linux_ioctl_sg(struct thread *td, struct linux_ioctl_args *args)
2659 {
2660 
2661 	switch (args->cmd) {
2662 	case LINUX_SG_GET_VERSION_NUM:
2663 		args->cmd = SG_GET_VERSION_NUM;
2664 		break;
2665 	case LINUX_SG_SET_TIMEOUT:
2666 		args->cmd = SG_SET_TIMEOUT;
2667 		break;
2668 	case LINUX_SG_GET_TIMEOUT:
2669 		args->cmd = SG_GET_TIMEOUT;
2670 		break;
2671 	case LINUX_SG_IO:
2672 		args->cmd = SG_IO;
2673 #ifdef COMPAT_LINUX32
2674 		return (linux_ioctl_sg_io(td, args));
2675 #endif
2676 		break;
2677 	case LINUX_SG_GET_RESERVED_SIZE:
2678 		args->cmd = SG_GET_RESERVED_SIZE;
2679 		break;
2680 	case LINUX_SG_GET_SCSI_ID:
2681 		args->cmd = SG_GET_SCSI_ID;
2682 		break;
2683 	case LINUX_SG_GET_SG_TABLESIZE:
2684 		args->cmd = SG_GET_SG_TABLESIZE;
2685 		break;
2686 	default:
2687 		return (ENODEV);
2688 	}
2689 	return (sys_ioctl(td, (struct ioctl_args *)args));
2690 }
2691 
2692 /*
2693  * Video4Linux (V4L) ioctl handler
2694  */
2695 static int
linux_to_bsd_v4l_tuner(struct l_video_tuner * lvt,struct video_tuner * vt)2696 linux_to_bsd_v4l_tuner(struct l_video_tuner *lvt, struct video_tuner *vt)
2697 {
2698 	vt->tuner = lvt->tuner;
2699 	strlcpy(vt->name, lvt->name, LINUX_VIDEO_TUNER_NAME_SIZE);
2700 	vt->rangelow = lvt->rangelow;	/* possible long size conversion */
2701 	vt->rangehigh = lvt->rangehigh;	/* possible long size conversion */
2702 	vt->flags = lvt->flags;
2703 	vt->mode = lvt->mode;
2704 	vt->signal = lvt->signal;
2705 	return (0);
2706 }
2707 
2708 static int
bsd_to_linux_v4l_tuner(struct video_tuner * vt,struct l_video_tuner * lvt)2709 bsd_to_linux_v4l_tuner(struct video_tuner *vt, struct l_video_tuner *lvt)
2710 {
2711 	lvt->tuner = vt->tuner;
2712 	strlcpy(lvt->name, vt->name, LINUX_VIDEO_TUNER_NAME_SIZE);
2713 	lvt->rangelow = vt->rangelow;	/* possible long size conversion */
2714 	lvt->rangehigh = vt->rangehigh;	/* possible long size conversion */
2715 	lvt->flags = vt->flags;
2716 	lvt->mode = vt->mode;
2717 	lvt->signal = vt->signal;
2718 	return (0);
2719 }
2720 
2721 #ifdef COMPAT_LINUX_V4L_CLIPLIST
2722 static int
linux_to_bsd_v4l_clip(struct l_video_clip * lvc,struct video_clip * vc)2723 linux_to_bsd_v4l_clip(struct l_video_clip *lvc, struct video_clip *vc)
2724 {
2725 	vc->x = lvc->x;
2726 	vc->y = lvc->y;
2727 	vc->width = lvc->width;
2728 	vc->height = lvc->height;
2729 	vc->next = PTRIN(lvc->next);	/* possible pointer size conversion */
2730 	return (0);
2731 }
2732 #endif
2733 
2734 static int
linux_to_bsd_v4l_window(struct l_video_window * lvw,struct video_window * vw)2735 linux_to_bsd_v4l_window(struct l_video_window *lvw, struct video_window *vw)
2736 {
2737 	vw->x = lvw->x;
2738 	vw->y = lvw->y;
2739 	vw->width = lvw->width;
2740 	vw->height = lvw->height;
2741 	vw->chromakey = lvw->chromakey;
2742 	vw->flags = lvw->flags;
2743 	vw->clips = PTRIN(lvw->clips);	/* possible pointer size conversion */
2744 	vw->clipcount = lvw->clipcount;
2745 	return (0);
2746 }
2747 
2748 static int
bsd_to_linux_v4l_window(struct video_window * vw,struct l_video_window * lvw)2749 bsd_to_linux_v4l_window(struct video_window *vw, struct l_video_window *lvw)
2750 {
2751 	memset(lvw, 0, sizeof(*lvw));
2752 
2753 	lvw->x = vw->x;
2754 	lvw->y = vw->y;
2755 	lvw->width = vw->width;
2756 	lvw->height = vw->height;
2757 	lvw->chromakey = vw->chromakey;
2758 	lvw->flags = vw->flags;
2759 	lvw->clips = PTROUT(vw->clips);	/* possible pointer size conversion */
2760 	lvw->clipcount = vw->clipcount;
2761 	return (0);
2762 }
2763 
2764 static int
linux_to_bsd_v4l_buffer(struct l_video_buffer * lvb,struct video_buffer * vb)2765 linux_to_bsd_v4l_buffer(struct l_video_buffer *lvb, struct video_buffer *vb)
2766 {
2767 	vb->base = PTRIN(lvb->base);	/* possible pointer size conversion */
2768 	vb->height = lvb->height;
2769 	vb->width = lvb->width;
2770 	vb->depth = lvb->depth;
2771 	vb->bytesperline = lvb->bytesperline;
2772 	return (0);
2773 }
2774 
2775 static int
bsd_to_linux_v4l_buffer(struct video_buffer * vb,struct l_video_buffer * lvb)2776 bsd_to_linux_v4l_buffer(struct video_buffer *vb, struct l_video_buffer *lvb)
2777 {
2778 	lvb->base = PTROUT(vb->base);	/* possible pointer size conversion */
2779 	lvb->height = vb->height;
2780 	lvb->width = vb->width;
2781 	lvb->depth = vb->depth;
2782 	lvb->bytesperline = vb->bytesperline;
2783 	return (0);
2784 }
2785 
2786 static int
linux_to_bsd_v4l_code(struct l_video_code * lvc,struct video_code * vc)2787 linux_to_bsd_v4l_code(struct l_video_code *lvc, struct video_code *vc)
2788 {
2789 	strlcpy(vc->loadwhat, lvc->loadwhat, LINUX_VIDEO_CODE_LOADWHAT_SIZE);
2790 	vc->datasize = lvc->datasize;
2791 	vc->data = PTRIN(lvc->data);	/* possible pointer size conversion */
2792 	return (0);
2793 }
2794 
2795 #ifdef COMPAT_LINUX_V4L_CLIPLIST
2796 static int
linux_v4l_clip_copy(void * lvc,struct video_clip ** ppvc)2797 linux_v4l_clip_copy(void *lvc, struct video_clip **ppvc)
2798 {
2799 	int error;
2800 	struct video_clip vclip;
2801 	struct l_video_clip l_vclip;
2802 
2803 	error = copyin(lvc, &l_vclip, sizeof(l_vclip));
2804 	if (error) return (error);
2805 	linux_to_bsd_v4l_clip(&l_vclip, &vclip);
2806 	/* XXX: If there can be no concurrency: s/M_NOWAIT/M_WAITOK/ */
2807 	if ((*ppvc = malloc(sizeof(**ppvc), M_LINUX, M_NOWAIT)) == NULL)
2808 		return (ENOMEM);    /* XXX: Linux has no ENOMEM here. */
2809 	memcpy(*ppvc, &vclip, sizeof(vclip));
2810 	(*ppvc)->next = NULL;
2811 	return (0);
2812 }
2813 
2814 static int
linux_v4l_cliplist_free(struct video_window * vw)2815 linux_v4l_cliplist_free(struct video_window *vw)
2816 {
2817 	struct video_clip **ppvc;
2818 	struct video_clip **ppvc_next;
2819 
2820 	for (ppvc = &(vw->clips); *ppvc != NULL; ppvc = ppvc_next) {
2821 		ppvc_next = &((*ppvc)->next);
2822 		free(*ppvc, M_LINUX);
2823 	}
2824 	vw->clips = NULL;
2825 
2826 	return (0);
2827 }
2828 
2829 static int
linux_v4l_cliplist_copy(struct l_video_window * lvw,struct video_window * vw)2830 linux_v4l_cliplist_copy(struct l_video_window *lvw, struct video_window *vw)
2831 {
2832 	int error;
2833 	int clipcount;
2834 	void *plvc;
2835 	struct video_clip **ppvc;
2836 
2837 	/*
2838 	 * XXX: The cliplist is used to pass in a list of clipping
2839 	 *	rectangles or, if clipcount == VIDEO_CLIP_BITMAP, a
2840 	 *	clipping bitmap.  Some Linux apps, however, appear to
2841 	 *	leave cliplist and clips uninitialized.  In any case,
2842 	 *	the cliplist is not used by pwc(4), at the time of
2843 	 *	writing, FreeBSD's only V4L driver.  When a driver
2844 	 *	that uses the cliplist is developed, this code may
2845 	 *	need re-examiniation.
2846 	 */
2847 	error = 0;
2848 	clipcount = vw->clipcount;
2849 	if (clipcount == VIDEO_CLIP_BITMAP) {
2850 		/*
2851 		 * In this case, the pointer (clips) is overloaded
2852 		 * to be a "void *" to a bitmap, therefore there
2853 		 * is no struct video_clip to copy now.
2854 		 */
2855 	} else if (clipcount > 0 && clipcount <= 16384) {
2856 		/*
2857 		 * Clips points to list of clip rectangles, so
2858 		 * copy the list.
2859 		 *
2860 		 * XXX: Upper limit of 16384 was used here to try to
2861 		 *	avoid cases when clipcount and clips pointer
2862 		 *	are uninitialized and therefore have high random
2863 		 *	values, as is the case in the Linux Skype
2864 		 *	application.  The value 16384 was chosen as that
2865 		 *	is what is used in the Linux stradis(4) MPEG
2866 		 *	decoder driver, the only place we found an
2867 		 *	example of cliplist use.
2868 		 */
2869 		plvc = PTRIN(lvw->clips);
2870 		vw->clips = NULL;
2871 		ppvc = &(vw->clips);
2872 		while (clipcount-- > 0) {
2873 			if (plvc == NULL) {
2874 				error = EFAULT;
2875 				break;
2876 			} else {
2877 				error = linux_v4l_clip_copy(plvc, ppvc);
2878 				if (error) {
2879 					linux_v4l_cliplist_free(vw);
2880 					break;
2881 				}
2882 			}
2883 			ppvc = &((*ppvc)->next);
2884 			plvc = PTRIN(((struct l_video_clip *) plvc)->next);
2885 		}
2886 	} else {
2887 		/*
2888 		 * clipcount == 0 or negative (but not VIDEO_CLIP_BITMAP)
2889 		 * Force cliplist to null.
2890 		 */
2891 		vw->clipcount = 0;
2892 		vw->clips = NULL;
2893 	}
2894 	return (error);
2895 }
2896 #endif
2897 
2898 static int
linux_ioctl_v4l(struct thread * td,struct linux_ioctl_args * args)2899 linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
2900 {
2901 	struct file *fp;
2902 	int error;
2903 	struct video_tuner vtun;
2904 	struct video_window vwin;
2905 	struct video_buffer vbuf;
2906 	struct video_code vcode;
2907 	struct l_video_tuner l_vtun;
2908 	struct l_video_window l_vwin;
2909 	struct l_video_buffer l_vbuf;
2910 	struct l_video_code l_vcode;
2911 
2912 	switch (args->cmd & 0xffff) {
2913 	case LINUX_VIDIOCGCAP:		args->cmd = VIDIOCGCAP; break;
2914 	case LINUX_VIDIOCGCHAN:		args->cmd = VIDIOCGCHAN; break;
2915 	case LINUX_VIDIOCSCHAN:		args->cmd = VIDIOCSCHAN; break;
2916 
2917 	case LINUX_VIDIOCGTUNER:
2918 		error = fget(td, args->fd,
2919 		    &cap_ioctl_rights, &fp);
2920 		if (error != 0)
2921 			return (error);
2922 		error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun));
2923 		if (error) {
2924 			fdrop(fp, td);
2925 			return (error);
2926 		}
2927 		linux_to_bsd_v4l_tuner(&l_vtun, &vtun);
2928 		error = fo_ioctl(fp, VIDIOCGTUNER, &vtun, td->td_ucred, td);
2929 		if (!error) {
2930 			bsd_to_linux_v4l_tuner(&vtun, &l_vtun);
2931 			error = copyout(&l_vtun, (void *) args->arg,
2932 			    sizeof(l_vtun));
2933 		}
2934 		fdrop(fp, td);
2935 		return (error);
2936 
2937 	case LINUX_VIDIOCSTUNER:
2938 		error = fget(td, args->fd,
2939 		    &cap_ioctl_rights, &fp);
2940 		if (error != 0)
2941 			return (error);
2942 		error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun));
2943 		if (error) {
2944 			fdrop(fp, td);
2945 			return (error);
2946 		}
2947 		linux_to_bsd_v4l_tuner(&l_vtun, &vtun);
2948 		error = fo_ioctl(fp, VIDIOCSTUNER, &vtun, td->td_ucred, td);
2949 		fdrop(fp, td);
2950 		return (error);
2951 
2952 	case LINUX_VIDIOCGPICT:		args->cmd = VIDIOCGPICT; break;
2953 	case LINUX_VIDIOCSPICT:		args->cmd = VIDIOCSPICT; break;
2954 	case LINUX_VIDIOCCAPTURE:	args->cmd = VIDIOCCAPTURE; break;
2955 
2956 	case LINUX_VIDIOCGWIN:
2957 		error = fget(td, args->fd,
2958 		    &cap_ioctl_rights, &fp);
2959 		if (error != 0)
2960 			return (error);
2961 		error = fo_ioctl(fp, VIDIOCGWIN, &vwin, td->td_ucred, td);
2962 		if (!error) {
2963 			bsd_to_linux_v4l_window(&vwin, &l_vwin);
2964 			error = copyout(&l_vwin, (void *) args->arg,
2965 			    sizeof(l_vwin));
2966 		}
2967 		fdrop(fp, td);
2968 		return (error);
2969 
2970 	case LINUX_VIDIOCSWIN:
2971 		error = fget(td, args->fd,
2972 		    &cap_ioctl_rights, &fp);
2973 		if (error != 0)
2974 			return (error);
2975 		error = copyin((void *) args->arg, &l_vwin, sizeof(l_vwin));
2976 		if (error) {
2977 			fdrop(fp, td);
2978 			return (error);
2979 		}
2980 		linux_to_bsd_v4l_window(&l_vwin, &vwin);
2981 #ifdef COMPAT_LINUX_V4L_CLIPLIST
2982 		error = linux_v4l_cliplist_copy(&l_vwin, &vwin);
2983 		if (error) {
2984 			fdrop(fp, td);
2985 			return (error);
2986 		}
2987 #endif
2988 		error = fo_ioctl(fp, VIDIOCSWIN, &vwin, td->td_ucred, td);
2989 		fdrop(fp, td);
2990 #ifdef COMPAT_LINUX_V4L_CLIPLIST
2991 		linux_v4l_cliplist_free(&vwin);
2992 #endif
2993 		return (error);
2994 
2995 	case LINUX_VIDIOCGFBUF:
2996 		error = fget(td, args->fd,
2997 		    &cap_ioctl_rights, &fp);
2998 		if (error != 0)
2999 			return (error);
3000 		error = fo_ioctl(fp, VIDIOCGFBUF, &vbuf, td->td_ucred, td);
3001 		if (!error) {
3002 			bsd_to_linux_v4l_buffer(&vbuf, &l_vbuf);
3003 			error = copyout(&l_vbuf, (void *) args->arg,
3004 			    sizeof(l_vbuf));
3005 		}
3006 		fdrop(fp, td);
3007 		return (error);
3008 
3009 	case LINUX_VIDIOCSFBUF:
3010 		error = fget(td, args->fd,
3011 		    &cap_ioctl_rights, &fp);
3012 		if (error != 0)
3013 			return (error);
3014 		error = copyin((void *) args->arg, &l_vbuf, sizeof(l_vbuf));
3015 		if (error) {
3016 			fdrop(fp, td);
3017 			return (error);
3018 		}
3019 		linux_to_bsd_v4l_buffer(&l_vbuf, &vbuf);
3020 		error = fo_ioctl(fp, VIDIOCSFBUF, &vbuf, td->td_ucred, td);
3021 		fdrop(fp, td);
3022 		return (error);
3023 
3024 	case LINUX_VIDIOCKEY:		args->cmd = VIDIOCKEY; break;
3025 	case LINUX_VIDIOCGFREQ:		args->cmd = VIDIOCGFREQ; break;
3026 	case LINUX_VIDIOCSFREQ:		args->cmd = VIDIOCSFREQ; break;
3027 	case LINUX_VIDIOCGAUDIO:	args->cmd = VIDIOCGAUDIO; break;
3028 	case LINUX_VIDIOCSAUDIO:	args->cmd = VIDIOCSAUDIO; break;
3029 	case LINUX_VIDIOCSYNC:		args->cmd = VIDIOCSYNC; break;
3030 	case LINUX_VIDIOCMCAPTURE:	args->cmd = VIDIOCMCAPTURE; break;
3031 	case LINUX_VIDIOCGMBUF:		args->cmd = VIDIOCGMBUF; break;
3032 	case LINUX_VIDIOCGUNIT:		args->cmd = VIDIOCGUNIT; break;
3033 	case LINUX_VIDIOCGCAPTURE:	args->cmd = VIDIOCGCAPTURE; break;
3034 	case LINUX_VIDIOCSCAPTURE:	args->cmd = VIDIOCSCAPTURE; break;
3035 	case LINUX_VIDIOCSPLAYMODE:	args->cmd = VIDIOCSPLAYMODE; break;
3036 	case LINUX_VIDIOCSWRITEMODE:	args->cmd = VIDIOCSWRITEMODE; break;
3037 	case LINUX_VIDIOCGPLAYINFO:	args->cmd = VIDIOCGPLAYINFO; break;
3038 
3039 	case LINUX_VIDIOCSMICROCODE:
3040 		error = fget(td, args->fd,
3041 		    &cap_ioctl_rights, &fp);
3042 		if (error != 0)
3043 			return (error);
3044 		error = copyin((void *) args->arg, &l_vcode, sizeof(l_vcode));
3045 		if (error) {
3046 			fdrop(fp, td);
3047 			return (error);
3048 		}
3049 		linux_to_bsd_v4l_code(&l_vcode, &vcode);
3050 		error = fo_ioctl(fp, VIDIOCSMICROCODE, &vcode, td->td_ucred, td);
3051 		fdrop(fp, td);
3052 		return (error);
3053 
3054 	case LINUX_VIDIOCGVBIFMT:	args->cmd = VIDIOCGVBIFMT; break;
3055 	case LINUX_VIDIOCSVBIFMT:	args->cmd = VIDIOCSVBIFMT; break;
3056 	default:			return (ENOIOCTL);
3057 	}
3058 
3059 	error = sys_ioctl(td, (struct ioctl_args *)args);
3060 	return (error);
3061 }
3062 
3063 /*
3064  * Special ioctl handler
3065  */
3066 static int
linux_ioctl_special(struct thread * td,struct linux_ioctl_args * args)3067 linux_ioctl_special(struct thread *td, struct linux_ioctl_args *args)
3068 {
3069 	int error;
3070 
3071 	switch (args->cmd) {
3072 	case LINUX_SIOCGIFADDR:
3073 		args->cmd = SIOCGIFADDR;
3074 		error = sys_ioctl(td, (struct ioctl_args *)args);
3075 		break;
3076 	case LINUX_SIOCSIFADDR:
3077 		args->cmd = SIOCSIFADDR;
3078 		error = sys_ioctl(td, (struct ioctl_args *)args);
3079 		break;
3080 	case LINUX_SIOCGIFFLAGS:
3081 		args->cmd = SIOCGIFFLAGS;
3082 		error = sys_ioctl(td, (struct ioctl_args *)args);
3083 		break;
3084 	default:
3085 		error = ENOIOCTL;
3086 	}
3087 
3088 	return (error);
3089 }
3090 
3091 static int
linux_to_bsd_v4l2_standard(struct l_v4l2_standard * lvstd,struct v4l2_standard * vstd)3092 linux_to_bsd_v4l2_standard(struct l_v4l2_standard *lvstd, struct v4l2_standard *vstd)
3093 {
3094 	vstd->index = lvstd->index;
3095 	vstd->id = lvstd->id;
3096 	CTASSERT(sizeof(vstd->name) == sizeof(lvstd->name));
3097 	memcpy(vstd->name, lvstd->name, sizeof(vstd->name));
3098 	vstd->frameperiod = lvstd->frameperiod;
3099 	vstd->framelines = lvstd->framelines;
3100 	CTASSERT(sizeof(vstd->reserved) == sizeof(lvstd->reserved));
3101 	memcpy(vstd->reserved, lvstd->reserved, sizeof(vstd->reserved));
3102 	return (0);
3103 }
3104 
3105 static int
bsd_to_linux_v4l2_standard(struct v4l2_standard * vstd,struct l_v4l2_standard * lvstd)3106 bsd_to_linux_v4l2_standard(struct v4l2_standard *vstd, struct l_v4l2_standard *lvstd)
3107 {
3108 	lvstd->index = vstd->index;
3109 	lvstd->id = vstd->id;
3110 	CTASSERT(sizeof(vstd->name) == sizeof(lvstd->name));
3111 	memcpy(lvstd->name, vstd->name, sizeof(lvstd->name));
3112 	lvstd->frameperiod = vstd->frameperiod;
3113 	lvstd->framelines = vstd->framelines;
3114 	CTASSERT(sizeof(vstd->reserved) == sizeof(lvstd->reserved));
3115 	memcpy(lvstd->reserved, vstd->reserved, sizeof(lvstd->reserved));
3116 	return (0);
3117 }
3118 
3119 static int
linux_to_bsd_v4l2_buffer(struct l_v4l2_buffer * lvb,struct v4l2_buffer * vb)3120 linux_to_bsd_v4l2_buffer(struct l_v4l2_buffer *lvb, struct v4l2_buffer *vb)
3121 {
3122 	vb->index = lvb->index;
3123 	vb->type = lvb->type;
3124 	vb->bytesused = lvb->bytesused;
3125 	vb->flags = lvb->flags;
3126 	vb->field = lvb->field;
3127 	vb->timestamp.tv_sec = lvb->timestamp.tv_sec;
3128 	vb->timestamp.tv_usec = lvb->timestamp.tv_usec;
3129 	memcpy(&vb->timecode, &lvb->timecode, sizeof (lvb->timecode));
3130 	vb->sequence = lvb->sequence;
3131 	vb->memory = lvb->memory;
3132 	if (lvb->memory == V4L2_MEMORY_USERPTR)
3133 		/* possible pointer size conversion */
3134 		vb->m.userptr = (unsigned long)PTRIN(lvb->m.userptr);
3135 	else
3136 		vb->m.offset = lvb->m.offset;
3137 	vb->length = lvb->length;
3138 	vb->input = lvb->input;
3139 	vb->reserved = lvb->reserved;
3140 	return (0);
3141 }
3142 
3143 static int
bsd_to_linux_v4l2_buffer(struct v4l2_buffer * vb,struct l_v4l2_buffer * lvb)3144 bsd_to_linux_v4l2_buffer(struct v4l2_buffer *vb, struct l_v4l2_buffer *lvb)
3145 {
3146 	lvb->index = vb->index;
3147 	lvb->type = vb->type;
3148 	lvb->bytesused = vb->bytesused;
3149 	lvb->flags = vb->flags;
3150 	lvb->field = vb->field;
3151 	lvb->timestamp.tv_sec = vb->timestamp.tv_sec;
3152 	lvb->timestamp.tv_usec = vb->timestamp.tv_usec;
3153 	memcpy(&lvb->timecode, &vb->timecode, sizeof (vb->timecode));
3154 	lvb->sequence = vb->sequence;
3155 	lvb->memory = vb->memory;
3156 	if (vb->memory == V4L2_MEMORY_USERPTR)
3157 		/* possible pointer size conversion */
3158 		lvb->m.userptr = PTROUT(vb->m.userptr);
3159 	else
3160 		lvb->m.offset = vb->m.offset;
3161 	lvb->length = vb->length;
3162 	lvb->input = vb->input;
3163 	lvb->reserved = vb->reserved;
3164 	return (0);
3165 }
3166 
3167 static int
linux_to_bsd_v4l2_format(struct l_v4l2_format * lvf,struct v4l2_format * vf)3168 linux_to_bsd_v4l2_format(struct l_v4l2_format *lvf, struct v4l2_format *vf)
3169 {
3170 	vf->type = lvf->type;
3171 	if (lvf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY
3172 #ifdef V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
3173 	    || lvf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
3174 #endif
3175 	    )
3176 		/*
3177 		 * XXX TODO - needs 32 -> 64 bit conversion:
3178 		 * (unused by webcams?)
3179 		 */
3180 		return (EINVAL);
3181 	memcpy(&vf->fmt, &lvf->fmt, sizeof(vf->fmt));
3182 	return (0);
3183 }
3184 
3185 static int
bsd_to_linux_v4l2_format(struct v4l2_format * vf,struct l_v4l2_format * lvf)3186 bsd_to_linux_v4l2_format(struct v4l2_format *vf, struct l_v4l2_format *lvf)
3187 {
3188 	lvf->type = vf->type;
3189 	if (vf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY
3190 #ifdef V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
3191 	    || vf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
3192 #endif
3193 	    )
3194 		/*
3195 		 * XXX TODO - needs 32 -> 64 bit conversion:
3196 		 * (unused by webcams?)
3197 		 */
3198 		return (EINVAL);
3199 	memcpy(&lvf->fmt, &vf->fmt, sizeof(vf->fmt));
3200 	return (0);
3201 }
3202 static int
linux_ioctl_v4l2(struct thread * td,struct linux_ioctl_args * args)3203 linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args)
3204 {
3205 	struct file *fp;
3206 	int error;
3207 	struct v4l2_format vformat;
3208 	struct l_v4l2_format l_vformat;
3209 	struct v4l2_standard vstd;
3210 	struct l_v4l2_standard l_vstd;
3211 	struct l_v4l2_buffer l_vbuf;
3212 	struct v4l2_buffer vbuf;
3213 	struct v4l2_input vinp;
3214 
3215 	switch (args->cmd & 0xffff) {
3216 	case LINUX_VIDIOC_RESERVED:
3217 	case LINUX_VIDIOC_LOG_STATUS:
3218 		if ((args->cmd & IOC_DIRMASK) != LINUX_IOC_VOID)
3219 			return (ENOIOCTL);
3220 		args->cmd = (args->cmd & 0xffff) | IOC_VOID;
3221 		break;
3222 
3223 	case LINUX_VIDIOC_OVERLAY:
3224 	case LINUX_VIDIOC_STREAMON:
3225 	case LINUX_VIDIOC_STREAMOFF:
3226 	case LINUX_VIDIOC_S_STD:
3227 	case LINUX_VIDIOC_S_TUNER:
3228 	case LINUX_VIDIOC_S_AUDIO:
3229 	case LINUX_VIDIOC_S_AUDOUT:
3230 	case LINUX_VIDIOC_S_MODULATOR:
3231 	case LINUX_VIDIOC_S_FREQUENCY:
3232 	case LINUX_VIDIOC_S_CROP:
3233 	case LINUX_VIDIOC_S_JPEGCOMP:
3234 	case LINUX_VIDIOC_S_PRIORITY:
3235 	case LINUX_VIDIOC_DBG_S_REGISTER:
3236 	case LINUX_VIDIOC_S_HW_FREQ_SEEK:
3237 	case LINUX_VIDIOC_SUBSCRIBE_EVENT:
3238 	case LINUX_VIDIOC_UNSUBSCRIBE_EVENT:
3239 		args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_IN;
3240 		break;
3241 
3242 	case LINUX_VIDIOC_QUERYCAP:
3243 	case LINUX_VIDIOC_G_STD:
3244 	case LINUX_VIDIOC_G_AUDIO:
3245 	case LINUX_VIDIOC_G_INPUT:
3246 	case LINUX_VIDIOC_G_OUTPUT:
3247 	case LINUX_VIDIOC_G_AUDOUT:
3248 	case LINUX_VIDIOC_G_JPEGCOMP:
3249 	case LINUX_VIDIOC_QUERYSTD:
3250 	case LINUX_VIDIOC_G_PRIORITY:
3251 	case LINUX_VIDIOC_QUERY_DV_PRESET:
3252 		args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_OUT;
3253 		break;
3254 
3255 	case LINUX_VIDIOC_ENUM_FMT:
3256 	case LINUX_VIDIOC_REQBUFS:
3257 	case LINUX_VIDIOC_G_PARM:
3258 	case LINUX_VIDIOC_S_PARM:
3259 	case LINUX_VIDIOC_G_CTRL:
3260 	case LINUX_VIDIOC_S_CTRL:
3261 	case LINUX_VIDIOC_G_TUNER:
3262 	case LINUX_VIDIOC_QUERYCTRL:
3263 	case LINUX_VIDIOC_QUERYMENU:
3264 	case LINUX_VIDIOC_S_INPUT:
3265 	case LINUX_VIDIOC_S_OUTPUT:
3266 	case LINUX_VIDIOC_ENUMOUTPUT:
3267 	case LINUX_VIDIOC_G_MODULATOR:
3268 	case LINUX_VIDIOC_G_FREQUENCY:
3269 	case LINUX_VIDIOC_CROPCAP:
3270 	case LINUX_VIDIOC_G_CROP:
3271 	case LINUX_VIDIOC_ENUMAUDIO:
3272 	case LINUX_VIDIOC_ENUMAUDOUT:
3273 	case LINUX_VIDIOC_G_SLICED_VBI_CAP:
3274 #ifdef VIDIOC_ENUM_FRAMESIZES
3275 	case LINUX_VIDIOC_ENUM_FRAMESIZES:
3276 	case LINUX_VIDIOC_ENUM_FRAMEINTERVALS:
3277 	case LINUX_VIDIOC_ENCODER_CMD:
3278 	case LINUX_VIDIOC_TRY_ENCODER_CMD:
3279 #endif
3280 	case LINUX_VIDIOC_DBG_G_REGISTER:
3281 	case LINUX_VIDIOC_DBG_G_CHIP_IDENT:
3282 	case LINUX_VIDIOC_ENUM_DV_PRESETS:
3283 	case LINUX_VIDIOC_S_DV_PRESET:
3284 	case LINUX_VIDIOC_G_DV_PRESET:
3285 	case LINUX_VIDIOC_S_DV_TIMINGS:
3286 	case LINUX_VIDIOC_G_DV_TIMINGS:
3287 		args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_INOUT;
3288 		break;
3289 
3290 	case LINUX_VIDIOC_G_FMT:
3291 	case LINUX_VIDIOC_S_FMT:
3292 	case LINUX_VIDIOC_TRY_FMT:
3293 		error = copyin((void *)args->arg, &l_vformat, sizeof(l_vformat));
3294 		if (error)
3295 			return (error);
3296 		error = fget(td, args->fd,
3297 		    &cap_ioctl_rights, &fp);
3298 		if (error)
3299 			return (error);
3300 		if (linux_to_bsd_v4l2_format(&l_vformat, &vformat) != 0)
3301 			error = EINVAL;
3302 		else if ((args->cmd & 0xffff) == LINUX_VIDIOC_G_FMT)
3303 			error = fo_ioctl(fp, VIDIOC_G_FMT, &vformat,
3304 			    td->td_ucred, td);
3305 		else if ((args->cmd & 0xffff) == LINUX_VIDIOC_S_FMT)
3306 			error = fo_ioctl(fp, VIDIOC_S_FMT, &vformat,
3307 			    td->td_ucred, td);
3308 		else
3309 			error = fo_ioctl(fp, VIDIOC_TRY_FMT, &vformat,
3310 			    td->td_ucred, td);
3311 		bsd_to_linux_v4l2_format(&vformat, &l_vformat);
3312 		if (error == 0)
3313 			error = copyout(&l_vformat, (void *)args->arg,
3314 			    sizeof(l_vformat));
3315 		fdrop(fp, td);
3316 		return (error);
3317 
3318 	case LINUX_VIDIOC_ENUMSTD:
3319 		error = copyin((void *)args->arg, &l_vstd, sizeof(l_vstd));
3320 		if (error)
3321 			return (error);
3322 		linux_to_bsd_v4l2_standard(&l_vstd, &vstd);
3323 		error = fget(td, args->fd,
3324 		    &cap_ioctl_rights, &fp);
3325 		if (error)
3326 			return (error);
3327 		error = fo_ioctl(fp, VIDIOC_ENUMSTD, (caddr_t)&vstd,
3328 		    td->td_ucred, td);
3329 		if (error) {
3330 			fdrop(fp, td);
3331 			return (error);
3332 		}
3333 		bsd_to_linux_v4l2_standard(&vstd, &l_vstd);
3334 		error = copyout(&l_vstd, (void *)args->arg, sizeof(l_vstd));
3335 		fdrop(fp, td);
3336 		return (error);
3337 
3338 	case LINUX_VIDIOC_ENUMINPUT:
3339 		/*
3340 		 * The Linux struct l_v4l2_input differs only in size,
3341 		 * it has no padding at the end.
3342 		 */
3343 		error = copyin((void *)args->arg, &vinp,
3344 				sizeof(struct l_v4l2_input));
3345 		if (error != 0)
3346 			return (error);
3347 		error = fget(td, args->fd,
3348 		    &cap_ioctl_rights, &fp);
3349 		if (error != 0)
3350 			return (error);
3351 		error = fo_ioctl(fp, VIDIOC_ENUMINPUT, (caddr_t)&vinp,
3352 		    td->td_ucred, td);
3353 		if (error) {
3354 			fdrop(fp, td);
3355 			return (error);
3356 		}
3357 		error = copyout(&vinp, (void *)args->arg,
3358 				sizeof(struct l_v4l2_input));
3359 		fdrop(fp, td);
3360 		return (error);
3361 
3362 	case LINUX_VIDIOC_QUERYBUF:
3363 	case LINUX_VIDIOC_QBUF:
3364 	case LINUX_VIDIOC_DQBUF:
3365 		error = copyin((void *)args->arg, &l_vbuf, sizeof(l_vbuf));
3366 		if (error)
3367 			return (error);
3368 		error = fget(td, args->fd,
3369 		    &cap_ioctl_rights, &fp);
3370 		if (error)
3371 			return (error);
3372 		linux_to_bsd_v4l2_buffer(&l_vbuf, &vbuf);
3373 		if ((args->cmd & 0xffff) == LINUX_VIDIOC_QUERYBUF)
3374 			error = fo_ioctl(fp, VIDIOC_QUERYBUF, &vbuf,
3375 			    td->td_ucred, td);
3376 		else if ((args->cmd & 0xffff) == LINUX_VIDIOC_QBUF)
3377 			error = fo_ioctl(fp, VIDIOC_QBUF, &vbuf,
3378 			    td->td_ucred, td);
3379 		else
3380 			error = fo_ioctl(fp, VIDIOC_DQBUF, &vbuf,
3381 			    td->td_ucred, td);
3382 		bsd_to_linux_v4l2_buffer(&vbuf, &l_vbuf);
3383 		if (error == 0)
3384 			error = copyout(&l_vbuf, (void *)args->arg,
3385 			    sizeof(l_vbuf));
3386 		fdrop(fp, td);
3387 		return (error);
3388 
3389 	/*
3390 	 * XXX TODO - these need 32 -> 64 bit conversion:
3391 	 * (are any of them needed for webcams?)
3392 	 */
3393 	case LINUX_VIDIOC_G_FBUF:
3394 	case LINUX_VIDIOC_S_FBUF:
3395 
3396 	case LINUX_VIDIOC_G_EXT_CTRLS:
3397 	case LINUX_VIDIOC_S_EXT_CTRLS:
3398 	case LINUX_VIDIOC_TRY_EXT_CTRLS:
3399 
3400 	case LINUX_VIDIOC_DQEVENT:
3401 
3402 	default:			return (ENOIOCTL);
3403 	}
3404 
3405 	error = sys_ioctl(td, (struct ioctl_args *)args);
3406 	return (error);
3407 }
3408 
3409 /*
3410  * Support for emulators/linux-libusb. This port uses FBSD_LUSB* macros
3411  * instead of USB* ones. This lets us to provide correct values for cmd.
3412  * 0xffffffe0 -- 0xffffffff range seemed to be the least collision-prone.
3413  */
3414 static int
linux_ioctl_fbsd_usb(struct thread * td,struct linux_ioctl_args * args)3415 linux_ioctl_fbsd_usb(struct thread *td, struct linux_ioctl_args *args)
3416 {
3417 	int error;
3418 
3419 	error = 0;
3420 	switch (args->cmd) {
3421 	case FBSD_LUSB_DEVICEENUMERATE:
3422 		args->cmd = USB_DEVICEENUMERATE;
3423 		break;
3424 	case FBSD_LUSB_DEV_QUIRK_ADD:
3425 		args->cmd = USB_DEV_QUIRK_ADD;
3426 		break;
3427 	case FBSD_LUSB_DEV_QUIRK_GET:
3428 		args->cmd = USB_DEV_QUIRK_GET;
3429 		break;
3430 	case FBSD_LUSB_DEV_QUIRK_REMOVE:
3431 		args->cmd = USB_DEV_QUIRK_REMOVE;
3432 		break;
3433 	case FBSD_LUSB_DO_REQUEST:
3434 		args->cmd = USB_DO_REQUEST;
3435 		break;
3436 	case FBSD_LUSB_FS_CLEAR_STALL_SYNC:
3437 		args->cmd = USB_FS_CLEAR_STALL_SYNC;
3438 		break;
3439 	case FBSD_LUSB_FS_CLOSE:
3440 		args->cmd = USB_FS_CLOSE;
3441 		break;
3442 	case FBSD_LUSB_FS_COMPLETE:
3443 		args->cmd = USB_FS_COMPLETE;
3444 		break;
3445 	case FBSD_LUSB_FS_INIT:
3446 		args->cmd = USB_FS_INIT;
3447 		break;
3448 	case FBSD_LUSB_FS_OPEN:
3449 		args->cmd = USB_FS_OPEN;
3450 		break;
3451 	case FBSD_LUSB_FS_START:
3452 		args->cmd = USB_FS_START;
3453 		break;
3454 	case FBSD_LUSB_FS_STOP:
3455 		args->cmd = USB_FS_STOP;
3456 		break;
3457 	case FBSD_LUSB_FS_UNINIT:
3458 		args->cmd = USB_FS_UNINIT;
3459 		break;
3460 	case FBSD_LUSB_GET_CONFIG:
3461 		args->cmd = USB_GET_CONFIG;
3462 		break;
3463 	case FBSD_LUSB_GET_DEVICEINFO:
3464 		args->cmd = USB_GET_DEVICEINFO;
3465 		break;
3466 	case FBSD_LUSB_GET_DEVICE_DESC:
3467 		args->cmd = USB_GET_DEVICE_DESC;
3468 		break;
3469 	case FBSD_LUSB_GET_FULL_DESC:
3470 		args->cmd = USB_GET_FULL_DESC;
3471 		break;
3472 	case FBSD_LUSB_GET_IFACE_DRIVER:
3473 		args->cmd = USB_GET_IFACE_DRIVER;
3474 		break;
3475 	case FBSD_LUSB_GET_PLUGTIME:
3476 		args->cmd = USB_GET_PLUGTIME;
3477 		break;
3478 	case FBSD_LUSB_GET_POWER_MODE:
3479 		args->cmd = USB_GET_POWER_MODE;
3480 		break;
3481 	case FBSD_LUSB_GET_REPORT_DESC:
3482 		args->cmd = USB_GET_REPORT_DESC;
3483 		break;
3484 	case FBSD_LUSB_GET_REPORT_ID:
3485 		args->cmd = USB_GET_REPORT_ID;
3486 		break;
3487 	case FBSD_LUSB_GET_TEMPLATE:
3488 		args->cmd = USB_GET_TEMPLATE;
3489 		break;
3490 	case FBSD_LUSB_IFACE_DRIVER_ACTIVE:
3491 		args->cmd = USB_IFACE_DRIVER_ACTIVE;
3492 		break;
3493 	case FBSD_LUSB_IFACE_DRIVER_DETACH:
3494 		args->cmd = USB_IFACE_DRIVER_DETACH;
3495 		break;
3496 	case FBSD_LUSB_QUIRK_NAME_GET:
3497 		args->cmd = USB_QUIRK_NAME_GET;
3498 		break;
3499 	case FBSD_LUSB_READ_DIR:
3500 		args->cmd = USB_READ_DIR;
3501 		break;
3502 	case FBSD_LUSB_SET_ALTINTERFACE:
3503 		args->cmd = USB_SET_ALTINTERFACE;
3504 		break;
3505 	case FBSD_LUSB_SET_CONFIG:
3506 		args->cmd = USB_SET_CONFIG;
3507 		break;
3508 	case FBSD_LUSB_SET_IMMED:
3509 		args->cmd = USB_SET_IMMED;
3510 		break;
3511 	case FBSD_LUSB_SET_POWER_MODE:
3512 		args->cmd = USB_SET_POWER_MODE;
3513 		break;
3514 	case FBSD_LUSB_SET_TEMPLATE:
3515 		args->cmd = USB_SET_TEMPLATE;
3516 		break;
3517 	case FBSD_LUSB_FS_OPEN_STREAM:
3518 		args->cmd = USB_FS_OPEN_STREAM;
3519 		break;
3520 	case FBSD_LUSB_GET_DEV_PORT_PATH:
3521 		args->cmd = USB_GET_DEV_PORT_PATH;
3522 		break;
3523 	case FBSD_LUSB_GET_POWER_USAGE:
3524 		args->cmd = USB_GET_POWER_USAGE;
3525 		break;
3526 	case FBSD_LUSB_DEVICESTATS:
3527 		args->cmd = USB_DEVICESTATS;
3528 		break;
3529 	default:
3530 		error = ENOIOCTL;
3531 	}
3532 	if (error != ENOIOCTL)
3533 		error = sys_ioctl(td, (struct ioctl_args *)args);
3534 	return (error);
3535 }
3536 
3537 /*
3538  * Some evdev ioctls must be translated.
3539  *  - EVIOCGMTSLOTS is a IOC_READ ioctl on Linux although it has input data
3540  *    (must be IOC_INOUT on FreeBSD).
3541  *  - On Linux, EVIOCGRAB, EVIOCREVOKE and EVIOCRMFF are defined as _IOW with
3542  *    an int argument. You don't pass an int pointer to the ioctl(), however,
3543  *    but just the int directly. On FreeBSD, they are defined as _IOWINT for
3544  *    this to work.
3545  */
3546 static int
linux_ioctl_evdev(struct thread * td,struct linux_ioctl_args * args)3547 linux_ioctl_evdev(struct thread *td, struct linux_ioctl_args *args)
3548 {
3549 	struct file *fp;
3550 	clockid_t clock;
3551 	int error;
3552 
3553 	args->cmd = SETDIR(args->cmd);
3554 
3555 	switch (args->cmd) {
3556 	case (EVIOCGRAB & ~IOC_DIRMASK) | IOC_IN:
3557 		args->cmd = EVIOCGRAB;
3558 		break;
3559 	case (EVIOCREVOKE & ~IOC_DIRMASK) | IOC_IN:
3560 		args->cmd = EVIOCREVOKE;
3561 		break;
3562 	case (EVIOCRMFF & ~IOC_DIRMASK) | IOC_IN:
3563 		args->cmd = EVIOCRMFF;
3564 		break;
3565 	case EVIOCSCLOCKID: {
3566 		error = copyin(PTRIN(args->arg), &clock, sizeof(clock));
3567 		if (error != 0)
3568 			return (error);
3569 		if (clock & ~(LINUX_IOCTL_EVDEV_CLK))
3570 			return (EINVAL);
3571 		error = linux_to_native_clockid(&clock, clock);
3572 		if (error != 0)
3573 			return (error);
3574 
3575 		error = fget(td, args->fd,
3576 		    &cap_ioctl_rights, &fp);
3577 		if (error != 0)
3578 			return (error);
3579 
3580 		error = fo_ioctl(fp, EVIOCSCLOCKID, &clock, td->td_ucred, td);
3581 		fdrop(fp, td);
3582 		return (error);
3583 	}
3584 	default:
3585 		break;
3586 	}
3587 
3588 	if (IOCBASECMD(args->cmd) ==
3589 	    ((EVIOCGMTSLOTS(0) & ~IOC_DIRMASK) | IOC_OUT))
3590 		args->cmd = (args->cmd & ~IOC_DIRMASK) | IOC_INOUT;
3591 
3592 	return (sys_ioctl(td, (struct ioctl_args *)args));
3593 }
3594 
3595 static int
linux_ioctl_kcov(struct thread * td,struct linux_ioctl_args * args)3596 linux_ioctl_kcov(struct thread *td, struct linux_ioctl_args *args)
3597 {
3598 	int error;
3599 
3600 	error = 0;
3601 	switch (args->cmd & 0xffff) {
3602 	case LINUX_KCOV_INIT_TRACE:
3603 		args->cmd = KIOSETBUFSIZE;
3604 		break;
3605 	case LINUX_KCOV_ENABLE:
3606 		args->cmd = KIOENABLE;
3607 		if (args->arg == 0)
3608 			args->arg = KCOV_MODE_TRACE_PC;
3609 		else if (args->arg == 1)
3610 			args->arg = KCOV_MODE_TRACE_CMP;
3611 		else
3612 			error = EINVAL;
3613 		break;
3614 	case LINUX_KCOV_DISABLE:
3615 		args->cmd = KIODISABLE;
3616 		break;
3617 	default:
3618 		error = ENOTTY;
3619 		break;
3620 	}
3621 
3622 	if (error == 0)
3623 		error = sys_ioctl(td, (struct ioctl_args *)args);
3624 	return (error);
3625 }
3626 
3627 #ifndef COMPAT_LINUX32
3628 static int
linux_ioctl_nvme(struct thread * td,struct linux_ioctl_args * args)3629 linux_ioctl_nvme(struct thread *td, struct linux_ioctl_args *args)
3630 {
3631 
3632 	/*
3633 	 * The NVMe drivers for namespace and controller implement these
3634 	 * commands using their native format. All the others are not
3635 	 * implemented yet.
3636 	 */
3637 	switch (args->cmd & 0xffff) {
3638 	case LINUX_NVME_IOCTL_ID:
3639 		args->cmd = NVME_IOCTL_ID;
3640 		break;
3641 	case LINUX_NVME_IOCTL_RESET:
3642 		args->cmd = NVME_IOCTL_RESET;
3643 		break;
3644 	case LINUX_NVME_IOCTL_ADMIN_CMD:
3645 		args->cmd = NVME_IOCTL_ADMIN_CMD;
3646 		break;
3647 	case LINUX_NVME_IOCTL_IO_CMD:
3648 		args->cmd = NVME_IOCTL_IO_CMD;
3649 		break;
3650 	default:
3651 		return (ENODEV);
3652 	}
3653 	return (sys_ioctl(td, (struct ioctl_args *)args));
3654 }
3655 #endif
3656 
3657 static int
linux_ioctl_i2c(struct thread * td,struct linux_ioctl_args * args)3658 linux_ioctl_i2c(struct thread *td, struct linux_ioctl_args *args)
3659 {
3660 	struct linux_i2c_rdwr_data lrdwr;
3661 	struct linux_i2c_msg *lmsgs = NULL;
3662 	struct iic_rdwr_data rdwr;
3663 	struct iic_msg *msgs = NULL;
3664 	struct file *fp;
3665 	iic_linux_rdwr_t *linux_rdwr;
3666 	l_ulong funcs;
3667 	uint16_t lflags;
3668 	uint8_t addr;
3669 	int error;
3670 	l_uint i;
3671 
3672 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
3673 	if (error != 0)
3674 		return (error);
3675 
3676 	linux_rdwr = NULL;
3677 	if (fp->f_type == DTYPE_VNODE && fp->f_vnode != NULL &&
3678 	    fp->f_vnode->v_rdev != NULL)
3679 		linux_rdwr = (iic_linux_rdwr_t *)fp->f_vnode->v_rdev->si_drv2;
3680 
3681 	switch (args->cmd & 0xffff) {
3682 	case LINUX_I2C_RETRIES:
3683 	case LINUX_I2C_TIMEOUT:
3684 	case LINUX_I2C_PEC:
3685 		error = 0;
3686 		break;
3687 	case LINUX_I2C_TENBIT:
3688 		error = (args->arg == 0) ? 0 : ENOTSUP;
3689 		break;
3690 	case LINUX_I2C_FUNCS:
3691 		funcs = LINUX_I2C_FUNC_I2C | LINUX_I2C_FUNC_NOSTART;
3692 		error = copyout(&funcs, (void *)args->arg, sizeof(funcs));
3693 		break;
3694 	case LINUX_I2C_SLAVE:
3695 	case LINUX_I2C_SLAVE_FORCE:
3696 		if (args->arg > 0x7f) {
3697 			error = EINVAL;
3698 			break;
3699 		}
3700 		addr = (uint8_t)(args->arg << 1);
3701 		error = fo_ioctl(fp, I2CSADDR, (caddr_t)&addr, td->td_ucred, td);
3702 		break;
3703 	case LINUX_I2C_RDWR:
3704 		error = copyin((void *)args->arg, &lrdwr, sizeof(lrdwr));
3705 		if (error != 0)
3706 			break;
3707 		if (lrdwr.nmsgs > IIC_RDRW_MAX_MSGS) {
3708 			error = EINVAL;
3709 			break;
3710 		}
3711 		lmsgs = malloc(sizeof(*lmsgs) * lrdwr.nmsgs, M_TEMP, M_WAITOK);
3712 		msgs = malloc(sizeof(*msgs) * lrdwr.nmsgs, M_TEMP, M_WAITOK);
3713 		error = copyin((void *)(uintptr_t)lrdwr.msgs, lmsgs,
3714 		    sizeof(*lmsgs) * lrdwr.nmsgs);
3715 		if (error != 0)
3716 			break;
3717 		for (i = 0; i < lrdwr.nmsgs; i++) {
3718 			lflags = lmsgs[i].flags;
3719 			if (lmsgs[i].addr > 0x7f || (lflags & LINUX_I2C_M_TEN) != 0) {
3720 				error = ENOTSUP;
3721 				break;
3722 			}
3723 			if ((lflags & ~(LINUX_I2C_M_RD | LINUX_I2C_M_NOSTART)) != 0) {
3724 				error = ENOTSUP;
3725 				break;
3726 			}
3727 			msgs[i].slave = lmsgs[i].addr << 1;
3728 			msgs[i].flags = (lflags & LINUX_I2C_M_RD) ? IIC_M_RD : IIC_M_WR;
3729 			if ((lflags & LINUX_I2C_M_NOSTART) != 0)
3730 				msgs[i].flags |= IIC_M_NOSTART;
3731 			msgs[i].len = lmsgs[i].len;
3732 			msgs[i].buf = (uint8_t *)(uintptr_t)lmsgs[i].buf;
3733 		}
3734 		if (error == 0) {
3735 			if (linux_rdwr == NULL) {
3736 				error = ENOTTY;
3737 			} else {
3738 				rdwr.msgs = msgs;
3739 				rdwr.nmsgs = lrdwr.nmsgs;
3740 				error = linux_rdwr(fp, &rdwr, fp->f_flag, td);
3741 				if (error == 0)
3742 					td->td_retval[0] = lrdwr.nmsgs;
3743 			}
3744 		}
3745 		break;
3746 	case LINUX_I2C_SMBUS:
3747 	default:
3748 		error = ENOTSUP;
3749 		break;
3750 	}
3751 	free(msgs, M_TEMP);
3752 	free(lmsgs, M_TEMP);
3753 	fdrop(fp, td);
3754 	return (error);
3755 }
3756 
3757 static int
linux_ioctl_hidraw(struct thread * td,struct linux_ioctl_args * args)3758 linux_ioctl_hidraw(struct thread *td, struct linux_ioctl_args *args)
3759 {
3760 	int len = (args->cmd & 0x3fff0000) >> 16;
3761 	if (len > 8192)
3762 		return (EINVAL);
3763 
3764 	switch (args->cmd & 0xffff) {
3765 	case LINUX_HIDIOCGRDESCSIZE:
3766 		args->cmd = HIDIOCGRDESCSIZE;
3767 		break;
3768 	case LINUX_HIDIOCGRDESC:
3769 		args->cmd = HIDIOCGRDESC;
3770 		break;
3771 	case LINUX_HIDIOCGRAWINFO:
3772 		args->cmd = HIDIOCGRAWINFO;
3773 		break;
3774 	case LINUX_HIDIOCGRAWNAME:
3775 		args->cmd = HIDIOCGRAWNAME(len);
3776 		break;
3777 	case LINUX_HIDIOCGRAWPHYS:
3778 		args->cmd = HIDIOCGRAWPHYS(len);
3779 		break;
3780 	case LINUX_HIDIOCSFEATURE:
3781 		args->cmd = HIDIOCSFEATURE(len);
3782 		break;
3783 	case LINUX_HIDIOCGFEATURE:
3784 		args->cmd = HIDIOCGFEATURE(len);
3785 		break;
3786 	case LINUX_HIDIOCGRAWUNIQ:
3787 		args->cmd = HIDIOCGRAWUNIQ(len);
3788 		break;
3789 	case LINUX_HIDIOCSINPUT:
3790 		args->cmd = HIDIOCSINPUT(len);
3791 		break;
3792 	case LINUX_HIDIOCGINPUT:
3793 		args->cmd = HIDIOCGINPUT(len);
3794 		break;
3795 	case LINUX_HIDIOCSOUTPUT:
3796 		args->cmd = HIDIOCSOUTPUT(len);
3797 		break;
3798 	case LINUX_HIDIOCGOUTPUT:
3799 		args->cmd = HIDIOCGOUTPUT(len);
3800 		break;
3801 	}
3802 
3803 	return (sys_ioctl(td, (struct ioctl_args *)args));
3804 }
3805 
3806 /*
3807  * main ioctl syscall function
3808  */
3809 
3810 static int
linux_ioctl_fallback(struct thread * td,struct linux_ioctl_args * args)3811 linux_ioctl_fallback(struct thread *td, struct linux_ioctl_args *args)
3812 {
3813 	struct file *fp;
3814 	struct linux_ioctl_handler_element *he;
3815 	int error, cmd;
3816 
3817 	error = fget(td, args->fd, &cap_ioctl_rights, &fp);
3818 	if (error != 0)
3819 		return (error);
3820 	if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
3821 		fdrop(fp, td);
3822 		return (EBADF);
3823 	}
3824 
3825 	/* Iterate over the ioctl handlers */
3826 	cmd = args->cmd & 0xffff;
3827 	sx_slock(&linux_ioctl_sx);
3828 	mtx_lock(&Giant);
3829 #ifdef COMPAT_LINUX32
3830 	TAILQ_FOREACH(he, &linux32_ioctl_handlers, list) {
3831 		if (cmd >= he->low && cmd <= he->high) {
3832 			error = (*he->func)(td, args);
3833 			if (error != ENOIOCTL) {
3834 				mtx_unlock(&Giant);
3835 				sx_sunlock(&linux_ioctl_sx);
3836 				fdrop(fp, td);
3837 				return (error);
3838 			}
3839 		}
3840 	}
3841 #endif
3842 	TAILQ_FOREACH(he, &linux_ioctl_handlers, list) {
3843 		if (cmd >= he->low && cmd <= he->high) {
3844 			error = (*he->func)(td, args);
3845 			if (error != ENOIOCTL) {
3846 				mtx_unlock(&Giant);
3847 				sx_sunlock(&linux_ioctl_sx);
3848 				fdrop(fp, td);
3849 				return (error);
3850 			}
3851 		}
3852 	}
3853 	mtx_unlock(&Giant);
3854 	sx_sunlock(&linux_ioctl_sx);
3855 	fdrop(fp, td);
3856 
3857 	switch (args->cmd & 0xffff) {
3858 	case LINUX_BTRFS_IOC_CLONE:
3859 	case LINUX_F2FS_IOC_GET_FEATURES:
3860 	case LINUX_FS_IOC_FIEMAP:
3861 		return (ENOTSUP);
3862 
3863 	default:
3864 		linux_msg(td, "%s fd=%d, cmd=0x%x ('%c',%d) is not implemented",
3865 		    __func__, args->fd, args->cmd,
3866 		    (int)(args->cmd & 0xff00) >> 8, (int)(args->cmd & 0xff));
3867 		break;
3868 	}
3869 
3870 	return (EINVAL);
3871 }
3872 
3873 int
linux_ioctl(struct thread * td,struct linux_ioctl_args * args)3874 linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
3875 {
3876 	struct linux_ioctl_handler *handler;
3877 	int error, cmd, i;
3878 
3879 	cmd = args->cmd & 0xffff;
3880 
3881 	/*
3882 	 * array of ioctls known at compilation time. Elides a lot of work on
3883 	 * each call compared to the list variant. Everything frequently used
3884 	 * should be moved here.
3885 	 *
3886 	 * Arguably the magic creating the list should create an array instead.
3887 	 *
3888 	 * For now just a linear scan.
3889 	 */
3890 	for (i = 0; i < nitems(linux_ioctls); i++) {
3891 		handler = &linux_ioctls[i];
3892 		if (cmd >= handler->low && cmd <= handler->high) {
3893 			error = (*handler->func)(td, args);
3894 			if (error != ENOIOCTL) {
3895 				return (error);
3896 			}
3897 		}
3898 	}
3899 	return (linux_ioctl_fallback(td, args));
3900 }
3901 
3902 int
linux_ioctl_register_handler(struct linux_ioctl_handler * h)3903 linux_ioctl_register_handler(struct linux_ioctl_handler *h)
3904 {
3905 	struct linux_ioctl_handler_element *he, *cur;
3906 
3907 	if (h == NULL || h->func == NULL)
3908 		return (EINVAL);
3909 
3910 	/*
3911 	 * Reuse the element if the handler is already on the list, otherwise
3912 	 * create a new element.
3913 	 */
3914 	sx_xlock(&linux_ioctl_sx);
3915 	TAILQ_FOREACH(he, &linux_ioctl_handlers, list) {
3916 		if (he->func == h->func)
3917 			break;
3918 	}
3919 	if (he == NULL) {
3920 		he = malloc(sizeof(*he),
3921 		    M_LINUX, M_WAITOK);
3922 		he->func = h->func;
3923 	} else
3924 		TAILQ_REMOVE(&linux_ioctl_handlers, he, list);
3925 
3926 	/* Initialize range information. */
3927 	he->low = h->low;
3928 	he->high = h->high;
3929 	he->span = h->high - h->low + 1;
3930 
3931 	/* Add the element to the list, sorted on span. */
3932 	TAILQ_FOREACH(cur, &linux_ioctl_handlers, list) {
3933 		if (cur->span > he->span) {
3934 			TAILQ_INSERT_BEFORE(cur, he, list);
3935 			sx_xunlock(&linux_ioctl_sx);
3936 			return (0);
3937 		}
3938 	}
3939 	TAILQ_INSERT_TAIL(&linux_ioctl_handlers, he, list);
3940 	sx_xunlock(&linux_ioctl_sx);
3941 
3942 	return (0);
3943 }
3944 
3945 int
linux_ioctl_unregister_handler(struct linux_ioctl_handler * h)3946 linux_ioctl_unregister_handler(struct linux_ioctl_handler *h)
3947 {
3948 	struct linux_ioctl_handler_element *he;
3949 
3950 	if (h == NULL || h->func == NULL)
3951 		return (EINVAL);
3952 
3953 	sx_xlock(&linux_ioctl_sx);
3954 	TAILQ_FOREACH(he, &linux_ioctl_handlers, list) {
3955 		if (he->func == h->func) {
3956 			TAILQ_REMOVE(&linux_ioctl_handlers, he, list);
3957 			sx_xunlock(&linux_ioctl_sx);
3958 			free(he, M_LINUX);
3959 			return (0);
3960 		}
3961 	}
3962 	sx_xunlock(&linux_ioctl_sx);
3963 
3964 	return (EINVAL);
3965 }
3966 
3967 #ifdef COMPAT_LINUX32
3968 int
linux32_ioctl_register_handler(struct linux_ioctl_handler * h)3969 linux32_ioctl_register_handler(struct linux_ioctl_handler *h)
3970 {
3971 	struct linux_ioctl_handler_element *he, *cur;
3972 
3973 	if (h == NULL || h->func == NULL)
3974 		return (EINVAL);
3975 
3976 	/*
3977 	 * Reuse the element if the handler is already on the list, otherwise
3978 	 * create a new element.
3979 	 */
3980 	sx_xlock(&linux_ioctl_sx);
3981 	TAILQ_FOREACH(he, &linux32_ioctl_handlers, list) {
3982 		if (he->func == h->func)
3983 			break;
3984 	}
3985 	if (he == NULL) {
3986 		he = malloc(sizeof(*he), M_LINUX, M_WAITOK);
3987 		he->func = h->func;
3988 	} else
3989 		TAILQ_REMOVE(&linux32_ioctl_handlers, he, list);
3990 
3991 	/* Initialize range information. */
3992 	he->low = h->low;
3993 	he->high = h->high;
3994 	he->span = h->high - h->low + 1;
3995 
3996 	/* Add the element to the list, sorted on span. */
3997 	TAILQ_FOREACH(cur, &linux32_ioctl_handlers, list) {
3998 		if (cur->span > he->span) {
3999 			TAILQ_INSERT_BEFORE(cur, he, list);
4000 			sx_xunlock(&linux_ioctl_sx);
4001 			return (0);
4002 		}
4003 	}
4004 	TAILQ_INSERT_TAIL(&linux32_ioctl_handlers, he, list);
4005 	sx_xunlock(&linux_ioctl_sx);
4006 
4007 	return (0);
4008 }
4009 
4010 int
linux32_ioctl_unregister_handler(struct linux_ioctl_handler * h)4011 linux32_ioctl_unregister_handler(struct linux_ioctl_handler *h)
4012 {
4013 	struct linux_ioctl_handler_element *he;
4014 
4015 	if (h == NULL || h->func == NULL)
4016 		return (EINVAL);
4017 
4018 	sx_xlock(&linux_ioctl_sx);
4019 	TAILQ_FOREACH(he, &linux32_ioctl_handlers, list) {
4020 		if (he->func == h->func) {
4021 			TAILQ_REMOVE(&linux32_ioctl_handlers, he, list);
4022 			sx_xunlock(&linux_ioctl_sx);
4023 			free(he, M_LINUX);
4024 			return (0);
4025 		}
4026 	}
4027 	sx_xunlock(&linux_ioctl_sx);
4028 
4029 	return (EINVAL);
4030 }
4031 #endif
4032