sunos_ioctl.c revision 1.10 1 /*
2 * Copyright (c) 1993 Markus Wild.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. The name of the author may not be used to endorse or promote products
11 * derived from this software without specific prior written permission
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * loosely from: Header: sun_ioctl.c,v 1.7 93/05/28 04:40:43 torek Exp
25 * $Id: sunos_ioctl.c,v 1.10 1994/05/21 08:22:08 deraadt Exp $
26 */
27
28 #include <sys/param.h>
29 #include <sys/proc.h>
30 #include <sys/file.h>
31 #include <sys/filedesc.h>
32 #include <sys/ioctl.h>
33 #include <sys/termios.h>
34 #include <sys/tty.h>
35 #include <sys/socket.h>
36 #include <sys/ioctl.h>
37 #include <net/if.h>
38
39 /*
40 * SunOS ioctl calls.
41 * This file is something of a hodge-podge.
42 * Support gets added as things turn up....
43 */
44
45 struct sun_ttysize {
46 int ts_row;
47 int ts_col;
48 };
49
50 struct sun_termio {
51 u_short c_iflag;
52 u_short c_oflag;
53 u_short c_cflag;
54 u_short c_lflag;
55 char c_line;
56 unsigned char c_cc[8];
57 };
58 #define SUN_TCGETA _IOR('T', 1, struct sun_termio)
59 #define SUN_TCSETA _IOW('T', 2, struct sun_termio)
60 #define SUN_TCSETAW _IOW('T', 3, struct sun_termio)
61 #define SUN_TCSETAF _IOW('T', 4, struct sun_termio)
62 #define SUN_TCSBRK _IO('T', 5)
63
64 struct sun_termios {
65 u_long c_iflag;
66 u_long c_oflag;
67 u_long c_cflag;
68 u_long c_lflag;
69 char c_line;
70 u_char c_cc[17];
71 };
72 #define SUN_TCXONC _IO('T', 6)
73 #define SUN_TCFLSH _IO('T', 7)
74 #define SUN_TCGETS _IOR('T', 8, struct sun_termios)
75 #define SUN_TCSETS _IOW('T', 9, struct sun_termios)
76 #define SUN_TCSETSW _IOW('T', 10, struct sun_termios)
77 #define SUN_TCSETSF _IOW('T', 11, struct sun_termios)
78 #define SUN_TCSNDBRK _IO('T', 12)
79 #define SUN_TCDRAIN _IO('T', 13)
80
81 static struct speedtab sptab[] = {
82 { 0, 0 },
83 { 50, 1 },
84 { 75, 2 },
85 { 110, 3 },
86 { 134, 4 },
87 { 135, 4 },
88 { 150, 5 },
89 { 200, 6 },
90 { 300, 7 },
91 { 600, 8 },
92 { 1200, 9 },
93 { 1800, 10 },
94 { 2400, 11 },
95 { 4800, 12 },
96 { 9600, 13 },
97 { 19200, 14 },
98 { 38400, 15 },
99 { -1, -1 }
100 };
101
102 static u_long s2btab[] = {
103 0,
104 50,
105 75,
106 110,
107 134,
108 150,
109 200,
110 300,
111 600,
112 1200,
113 1800,
114 2400,
115 4800,
116 9600,
117 19200,
118 38400,
119 };
120
121 /*
122 * these two conversion functions have mostly been done
123 * with some perl cut&paste, then handedited to comment
124 * out what doesn't exist under NetBSD.
125 * A note from Markus's code:
126 * (l & BITMASK1) / BITMASK1 * BITMASK2 is translated
127 * optimally by gcc m68k, much better than any ?: stuff.
128 * Code may vary with different architectures of course.
129 *
130 * I don't know what optimizer you used, but seeing divu's and
131 * bfextu's in the m68k assembly output did not encourage me...
132 * as well, gcc on the sparc definately generates much better
133 * code with ?:.
134 */
135
136 static void
137 stios2btios(st, bt)
138 struct sun_termios *st;
139 struct termios *bt;
140 {
141 register u_long l, r;
142
143 l = st->c_iflag;
144 r = ((l & 0x00000001) ? IGNBRK : 0);
145 r |= ((l & 0x00000002) ? BRKINT : 0);
146 r |= ((l & 0x00000004) ? IGNPAR : 0);
147 r |= ((l & 0x00000008) ? PARMRK : 0);
148 r |= ((l & 0x00000010) ? INPCK : 0);
149 r |= ((l & 0x00000020) ? ISTRIP : 0);
150 r |= ((l & 0x00000040) ? INLCR : 0);
151 r |= ((l & 0x00000080) ? IGNCR : 0);
152 r |= ((l & 0x00000100) ? ICRNL : 0);
153 /* ((l & 0x00000200) ? IUCLC : 0) */
154 r |= ((l & 0x00000400) ? IXON : 0);
155 r |= ((l & 0x00000800) ? IXANY : 0);
156 r |= ((l & 0x00001000) ? IXOFF : 0);
157 r |= ((l & 0x00002000) ? IMAXBEL : 0);
158 bt->c_iflag = r;
159
160 l = st->c_oflag;
161 r = ((l & 0x00000001) ? OPOST : 0);
162 /* ((l & 0x00000002) ? OLCUC : 0) */
163 r |= ((l & 0x00000004) ? ONLCR : 0);
164 /* ((l & 0x00000008) ? OCRNL : 0) */
165 /* ((l & 0x00000010) ? ONOCR : 0) */
166 /* ((l & 0x00000020) ? ONLRET : 0) */
167 /* ((l & 0x00000040) ? OFILL : 0) */
168 /* ((l & 0x00000080) ? OFDEL : 0) */
169 /* ((l & 0x00000100) ? NLDLY : 0) */
170 /* ((l & 0x00000100) ? NL1 : 0) */
171 /* ((l & 0x00000600) ? CRDLY : 0) */
172 /* ((l & 0x00000200) ? CR1 : 0) */
173 /* ((l & 0x00000400) ? CR2 : 0) */
174 /* ((l & 0x00000600) ? CR3 : 0) */
175 /* ((l & 0x00001800) ? TABDLY : 0) */
176 /* ((l & 0x00000800) ? TAB1 : 0) */
177 /* ((l & 0x00001000) ? TAB2 : 0) */
178 r |= ((l & 0x00001800) ? OXTABS : 0);
179 /* ((l & 0x00002000) ? BSDLY : 0) */
180 /* ((l & 0x00002000) ? BS1 : 0) */
181 /* ((l & 0x00004000) ? VTDLY : 0) */
182 /* ((l & 0x00004000) ? VT1 : 0) */
183 /* ((l & 0x00008000) ? FFDLY : 0) */
184 /* ((l & 0x00008000) ? FF1 : 0) */
185 /* ((l & 0x00010000) ? PAGEOUT : 0) */
186 /* ((l & 0x00020000) ? WRAP : 0) */
187 bt->c_oflag = r;
188
189 l = st->c_cflag;
190 r = ((l & 0x00000010) ? CS6 : 0);
191 r |= ((l & 0x00000020) ? CS7 : 0);
192 r |= ((l & 0x00000030) ? CS8 : 0);
193 r |= ((l & 0x00000040) ? CSTOPB : 0);
194 r |= ((l & 0x00000080) ? CREAD : 0);
195 r |= ((l & 0x00000100) ? PARENB : 0);
196 r |= ((l & 0x00000200) ? PARODD : 0);
197 r |= ((l & 0x00000400) ? HUPCL : 0);
198 r |= ((l & 0x00000800) ? CLOCAL : 0);
199 /* ((l & 0x00001000) ? LOBLK : 0) */
200 r |= ((l & 0x80000000) ? (CRTS_IFLOW|CCTS_OFLOW) : 0);
201 bt->c_cflag = r;
202
203 bt->c_ispeed = bt->c_ospeed = s2btab[l & 0x0000000f];
204
205 l = st->c_lflag;
206 r = ((l & 0x00000001) ? ISIG : 0);
207 r |= ((l & 0x00000002) ? ICANON : 0);
208 /* ((l & 0x00000004) ? XCASE : 0) */
209 r |= ((l & 0x00000008) ? ECHO : 0);
210 r |= ((l & 0x00000010) ? ECHOE : 0);
211 r |= ((l & 0x00000020) ? ECHOK : 0);
212 r |= ((l & 0x00000040) ? ECHONL : 0);
213 r |= ((l & 0x00000080) ? NOFLSH : 0);
214 r |= ((l & 0x00000100) ? TOSTOP : 0);
215 r |= ((l & 0x00000200) ? ECHOCTL : 0);
216 r |= ((l & 0x00000400) ? ECHOPRT : 0);
217 r |= ((l & 0x00000800) ? ECHOKE : 0);
218 /* ((l & 0x00001000) ? DEFECHO : 0) */
219 r |= ((l & 0x00002000) ? FLUSHO : 0);
220 r |= ((l & 0x00004000) ? PENDIN : 0);
221 bt->c_lflag = r;
222
223 bt->c_cc[VINTR] = st->c_cc[0] ? st->c_cc[0] : _POSIX_VDISABLE;
224 bt->c_cc[VQUIT] = st->c_cc[1] ? st->c_cc[1] : _POSIX_VDISABLE;
225 bt->c_cc[VERASE] = st->c_cc[2] ? st->c_cc[2] : _POSIX_VDISABLE;
226 bt->c_cc[VKILL] = st->c_cc[3] ? st->c_cc[3] : _POSIX_VDISABLE;
227 bt->c_cc[VEOF] = st->c_cc[4] ? st->c_cc[4] : _POSIX_VDISABLE;
228 bt->c_cc[VEOL] = st->c_cc[5] ? st->c_cc[5] : _POSIX_VDISABLE;
229 bt->c_cc[VEOL2] = st->c_cc[6] ? st->c_cc[6] : _POSIX_VDISABLE;
230 /* bt->c_cc[VSWTCH] = st->c_cc[7] ? st->c_cc[7] : _POSIX_VDISABLE; */
231 bt->c_cc[VSTART] = st->c_cc[8] ? st->c_cc[8] : _POSIX_VDISABLE;
232 bt->c_cc[VSTOP] = st->c_cc[9] ? st->c_cc[9] : _POSIX_VDISABLE;
233 bt->c_cc[VSUSP] = st->c_cc[10] ? st->c_cc[10] : _POSIX_VDISABLE;
234 bt->c_cc[VDSUSP] = st->c_cc[11] ? st->c_cc[11] : _POSIX_VDISABLE;
235 bt->c_cc[VREPRINT] = st->c_cc[12] ? st->c_cc[12] : _POSIX_VDISABLE;
236 bt->c_cc[VDISCARD] = st->c_cc[13] ? st->c_cc[13] : _POSIX_VDISABLE;
237 bt->c_cc[VWERASE] = st->c_cc[14] ? st->c_cc[14] : _POSIX_VDISABLE;
238 bt->c_cc[VLNEXT] = st->c_cc[15] ? st->c_cc[15] : _POSIX_VDISABLE;
239 bt->c_cc[VSTATUS] = st->c_cc[16] ? st->c_cc[16] : _POSIX_VDISABLE;
240 }
241
242
243 static void
244 btios2stios(bt, st)
245 struct termios *bt;
246 struct sun_termios *st;
247 {
248 register u_long l, r;
249
250 l = bt->c_iflag;
251 r = ((l & IGNBRK) ? 0x00000001 : 0);
252 r |= ((l & BRKINT) ? 0x00000002 : 0);
253 r |= ((l & IGNPAR) ? 0x00000004 : 0);
254 r |= ((l & PARMRK) ? 0x00000008 : 0);
255 r |= ((l & INPCK) ? 0x00000010 : 0);
256 r |= ((l & ISTRIP) ? 0x00000020 : 0);
257 r |= ((l & INLCR) ? 0x00000040 : 0);
258 r |= ((l & IGNCR) ? 0x00000080 : 0);
259 r |= ((l & ICRNL) ? 0x00000100 : 0);
260 /* ((l & IUCLC) ? 0x00000200 : 0) */
261 r |= ((l & IXON) ? 0x00000400 : 0);
262 r |= ((l & IXANY) ? 0x00000800 : 0);
263 r |= ((l & IXOFF) ? 0x00001000 : 0);
264 r |= ((l & IMAXBEL) ? 0x00002000 : 0);
265 st->c_iflag = r;
266
267 l = bt->c_oflag;
268 r = ((l & OPOST) ? 0x00000001 : 0);
269 /* ((l & OLCUC) ? 0x00000002 : 0) */
270 r |= ((l & ONLCR) ? 0x00000004 : 0);
271 /* ((l & OCRNL) ? 0x00000008 : 0) */
272 /* ((l & ONOCR) ? 0x00000010 : 0) */
273 /* ((l & ONLRET) ? 0x00000020 : 0) */
274 /* ((l & OFILL) ? 0x00000040 : 0) */
275 /* ((l & OFDEL) ? 0x00000080 : 0) */
276 /* ((l & NLDLY) ? 0x00000100 : 0) */
277 /* ((l & NL1) ? 0x00000100 : 0) */
278 /* ((l & CRDLY) ? 0x00000600 : 0) */
279 /* ((l & CR1) ? 0x00000200 : 0) */
280 /* ((l & CR2) ? 0x00000400 : 0) */
281 /* ((l & CR3) ? 0x00000600 : 0) */
282 /* ((l & TABDLY) ? 0x00001800 : 0) */
283 /* ((l & TAB1) ? 0x00000800 : 0) */
284 /* ((l & TAB2) ? 0x00001000 : 0) */
285 r |= ((l & OXTABS) ? 0x00001800 : 0);
286 /* ((l & BSDLY) ? 0x00002000 : 0) */
287 /* ((l & BS1) ? 0x00002000 : 0) */
288 /* ((l & VTDLY) ? 0x00004000 : 0) */
289 /* ((l & VT1) ? 0x00004000 : 0) */
290 /* ((l & FFDLY) ? 0x00008000 : 0) */
291 /* ((l & FF1) ? 0x00008000 : 0) */
292 /* ((l & PAGEOUT) ? 0x00010000 : 0) */
293 /* ((l & WRAP) ? 0x00020000 : 0) */
294 st->c_oflag = r;
295
296 l = bt->c_cflag;
297 r = ((l & CS6) ? 0x00000010 : 0);
298 r |= ((l & CS7) ? 0x00000020 : 0);
299 r |= ((l & CS8) ? 0x00000030 : 0);
300 r |= ((l & CSTOPB) ? 0x00000040 : 0);
301 r |= ((l & CREAD) ? 0x00000080 : 0);
302 r |= ((l & PARENB) ? 0x00000100 : 0);
303 r |= ((l & PARODD) ? 0x00000200 : 0);
304 r |= ((l & HUPCL) ? 0x00000400 : 0);
305 r |= ((l & CLOCAL) ? 0x00000800 : 0);
306 /* ((l & LOBLK) ? 0x00001000 : 0) */
307 r |= ((l & (CRTS_IFLOW|CCTS_OFLOW)) ? 0x80000000 : 0);
308 st->c_cflag = r;
309
310 l = bt->c_lflag;
311 r = ((l & ISIG) ? 0x00000001 : 0);
312 r |= ((l & ICANON) ? 0x00000002 : 0);
313 /* ((l & XCASE) ? 0x00000004 : 0) */
314 r |= ((l & ECHO) ? 0x00000008 : 0);
315 r |= ((l & ECHOE) ? 0x00000010 : 0);
316 r |= ((l & ECHOK) ? 0x00000020 : 0);
317 r |= ((l & ECHONL) ? 0x00000040 : 0);
318 r |= ((l & NOFLSH) ? 0x00000080 : 0);
319 r |= ((l & TOSTOP) ? 0x00000100 : 0);
320 r |= ((l & ECHOCTL) ? 0x00000200 : 0);
321 r |= ((l & ECHOPRT) ? 0x00000400 : 0);
322 r |= ((l & ECHOKE) ? 0x00000800 : 0);
323 /* ((l & DEFECHO) ? 0x00001000 : 0) */
324 r |= ((l & FLUSHO) ? 0x00002000 : 0);
325 r |= ((l & PENDIN) ? 0x00004000 : 0);
326 st->c_lflag = r;
327
328 l = ttspeedtab(bt->c_ospeed, sptab);
329 if (l >= 0)
330 st->c_cflag |= l;
331
332 st->c_cc[0] = bt->c_cc[VINTR] != _POSIX_VDISABLE? bt->c_cc[VINTR]:0;
333 st->c_cc[1] = bt->c_cc[VQUIT] != _POSIX_VDISABLE? bt->c_cc[VQUIT]:0;
334 st->c_cc[2] = bt->c_cc[VERASE] != _POSIX_VDISABLE? bt->c_cc[VERASE]:0;
335 st->c_cc[3] = bt->c_cc[VKILL] != _POSIX_VDISABLE? bt->c_cc[VKILL]:0;
336 st->c_cc[4] = bt->c_cc[VEOF] != _POSIX_VDISABLE? bt->c_cc[VEOF]:0;
337 st->c_cc[5] = bt->c_cc[VEOL] != _POSIX_VDISABLE? bt->c_cc[VEOL]:0;
338 st->c_cc[6] = bt->c_cc[VEOL2] != _POSIX_VDISABLE? bt->c_cc[VEOL2]:0;
339 st->c_cc[7] = 0;
340 /* bt->c_cc[VSWTCH] != _POSIX_VDISABLE? bt->c_cc[VSWTCH]: */
341 st->c_cc[8] = bt->c_cc[VSTART] != _POSIX_VDISABLE? bt->c_cc[VSTART]:0;
342 st->c_cc[9] = bt->c_cc[VSTOP] != _POSIX_VDISABLE? bt->c_cc[VSTOP]:0;
343 st->c_cc[10]= bt->c_cc[VSUSP] != _POSIX_VDISABLE? bt->c_cc[VSUSP]:0;
344 st->c_cc[11]= bt->c_cc[VDSUSP] != _POSIX_VDISABLE? bt->c_cc[VDSUSP]:0;
345 st->c_cc[12]= bt->c_cc[VREPRINT]!= _POSIX_VDISABLE? bt->c_cc[VREPRINT]:0;
346 st->c_cc[13]= bt->c_cc[VDISCARD]!= _POSIX_VDISABLE? bt->c_cc[VDISCARD]:0;
347 st->c_cc[14]= bt->c_cc[VWERASE] != _POSIX_VDISABLE? bt->c_cc[VWERASE]:0;
348 st->c_cc[15]= bt->c_cc[VLNEXT] != _POSIX_VDISABLE? bt->c_cc[VLNEXT]:0;
349 st->c_cc[16]= bt->c_cc[VSTATUS] != _POSIX_VDISABLE? bt->c_cc[VSTATUS]:0;
350
351 st->c_line = 0;
352 }
353
354 static void
355 stios2stio(ts, t)
356 struct sun_termios *ts;
357 struct sun_termio *t;
358 {
359 t->c_iflag = ts->c_iflag;
360 t->c_oflag = ts->c_oflag;
361 t->c_cflag = ts->c_cflag;
362 t->c_lflag = ts->c_lflag;
363 t->c_line = ts->c_line;
364 bcopy(ts->c_cc, t->c_cc, 8);
365 }
366
367 static void
368 stio2stios(t, ts)
369 struct sun_termio *t;
370 struct sun_termios *ts;
371 {
372 ts->c_iflag = t->c_iflag;
373 ts->c_oflag = t->c_oflag;
374 ts->c_cflag = t->c_cflag;
375 ts->c_lflag = t->c_lflag;
376 ts->c_line = t->c_line;
377 bcopy(t->c_cc, ts->c_cc, 8); /* don't touch the upper fields! */
378 }
379
380 struct sun_ioctl_args {
381 int fd;
382 int cmd;
383 caddr_t data;
384 };
385
386 int
387 sun_ioctl(p, uap, retval)
388 register struct proc *p;
389 register struct sun_ioctl_args *uap;
390 int *retval;
391 {
392 register struct filedesc *fdp = p->p_fd;
393 register struct file *fp;
394 register int (*ctl)();
395 int error;
396
397 if ( (unsigned)uap->fd >= fdp->fd_nfiles ||
398 (fp = fdp->fd_ofiles[uap->fd]) == NULL)
399 return EBADF;
400
401 if ((fp->f_flag & (FREAD|FWRITE)) == 0)
402 return EBADF;
403
404 ctl = fp->f_ops->fo_ioctl;
405
406 switch (uap->cmd) {
407 case _IOR('t', 0, int):
408 uap->cmd = TIOCGETD;
409 break;
410 case _IOW('t', 1, int):
411 {
412 int disc;
413
414 if ((error = copyin(uap->data, (caddr_t)&disc,
415 sizeof disc)) != 0)
416 return error;
417
418 /* map SunOS NTTYDISC into our termios discipline */
419 if (disc == 2)
420 disc = 0;
421 /* all other disciplines are not supported by NetBSD */
422 if (disc)
423 return ENXIO;
424
425 return (*ctl)(fp, TIOCSETD, (caddr_t)&disc, p);
426 }
427 case _IOW('t', 101, int): /* sun SUN_TIOCSSOFTCAR */
428 {
429 int x; /* unused */
430
431 return copyin((caddr_t)&x, uap->data, sizeof x);
432 }
433 case _IOR('t', 100, int): /* sun SUN_TIOCSSOFTCAR */
434 {
435 int x = 0;
436
437 return copyout((caddr_t)&x, uap->data, sizeof x);
438 }
439 case _IO('t', 36): /* sun TIOCCONS, no parameters */
440 {
441 int on = 1;
442 return (*ctl)(fp, TIOCCONS, (caddr_t)&on, p);
443 }
444 case _IOW('t', 37, struct sun_ttysize):
445 {
446 struct winsize ws;
447 struct sun_ttysize ss;
448
449 if ((error = (*ctl)(fp, TIOCGWINSZ, (caddr_t)&ws, p)) != 0)
450 return (error);
451
452 if ((error = copyin (uap->data, &ss, sizeof (ss))) != 0)
453 return error;
454
455 ws.ws_row = ss.ts_row;
456 ws.ws_col = ss.ts_col;
457
458 return ((*ctl)(fp, TIOCSWINSZ, (caddr_t)&ws, p));
459 }
460 case _IOW('t', 38, struct sun_ttysize):
461 {
462 struct winsize ws;
463 struct sun_ttysize ss;
464
465 if ((error = (*ctl)(fp, TIOCGWINSZ, (caddr_t)&ws, p)) != 0)
466 return (error);
467
468 ss.ts_row = ws.ws_row;
469 ss.ts_col = ws.ws_col;
470
471 return copyout ((caddr_t)&ss, uap->data, sizeof (ss));
472 }
473 case _IOW('t', 130, int):
474 uap->cmd = TIOCSPGRP;
475 break;
476 case _IOR('t', 131, int):
477 uap->cmd = TIOCGPGRP;
478 break;
479 case _IO('t', 132):
480 uap->cmd = TIOCSCTTY;
481 break;
482 case SUN_TCGETA:
483 case SUN_TCGETS:
484 {
485 struct termios bts;
486 struct sun_termios sts;
487 struct sun_termio st;
488
489 if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0)
490 return error;
491
492 btios2stios (&bts, &sts);
493 if (uap->cmd == SUN_TCGETA) {
494 stios2stio (&sts, &st);
495 return copyout((caddr_t)&st, uap->data, sizeof (st));
496 } else
497 return copyout((caddr_t)&sts, uap->data, sizeof (sts));
498 /*NOTREACHED*/
499 }
500 case SUN_TCSETA:
501 case SUN_TCSETAW:
502 case SUN_TCSETAF:
503 {
504 struct termios bts;
505 struct sun_termios sts;
506 struct sun_termio st;
507
508 if ((error = copyin(uap->data, (caddr_t)&st,
509 sizeof (st))) != 0)
510 return error;
511
512 /* get full BSD termios so we don't lose information */
513 if ((error = (*ctl)(fp, TIOCGETA, (caddr_t)&bts, p)) != 0)
514 return error;
515
516 /*
517 * convert to sun termios, copy in information from
518 * termio, and convert back, then set new values.
519 */
520 btios2stios(&bts, &sts);
521 stio2stios(&st, &sts);
522 stios2btios(&sts, &bts);
523
524 return (*ctl)(fp, uap->cmd - SUN_TCSETA + TIOCSETA,
525 (caddr_t)&bts, p);
526 }
527 case SUN_TCSETS:
528 case SUN_TCSETSW:
529 case SUN_TCSETSF:
530 {
531 struct termios bts;
532 struct sun_termios sts;
533
534 if ((error = copyin (uap->data, (caddr_t)&sts,
535 sizeof (sts))) != 0)
536 return error;
537 stios2btios (&sts, &bts);
538 return (*ctl)(fp, uap->cmd - SUN_TCSETS + TIOCSETA,
539 (caddr_t)&bts, p);
540 }
541 /*
542 * Pseudo-tty ioctl translations.
543 */
544 case _IOW('t', 32, int): { /* TIOCTCNTL */
545 int error, on;
546
547 if (error = copyin (uap->data, (caddr_t)&on, sizeof (on)))
548 return error;
549 return (*ctl)(fp, TIOCUCNTL, (caddr_t)&on, p);
550 }
551 case _IOW('t', 33, int): { /* TIOCSIGNAL */
552 int error, sig;
553
554 if (error = copyin (uap->data, (caddr_t)&sig, sizeof (sig)))
555 return error;
556 return (*ctl)(fp, TIOCSIG, (caddr_t)&sig, p);
557 }
558
559 /*
560 * Socket ioctl translations.
561 */
562 #define IFREQ_IN(a) { \
563 struct ifreq ifreq; \
564 if (error = copyin (uap->data, (caddr_t)&ifreq, sizeof (ifreq))) \
565 return error; \
566 return (*ctl)(fp, a, (caddr_t)&ifreq, p); \
567 }
568 #define IFREQ_INOUT(a) { \
569 struct ifreq ifreq; \
570 if (error = copyin (uap->data, (caddr_t)&ifreq, sizeof (ifreq))) \
571 return error; \
572 if (error = (*ctl)(fp, a, (caddr_t)&ifreq, p)) \
573 return error; \
574 return copyout ((caddr_t)&ifreq, uap->data, sizeof (ifreq)); \
575 }
576
577 case _IOW('i', 12, struct ifreq):
578 /* SIOCSIFADDR */
579 break;
580
581 case _IOWR('i', 13, struct ifreq):
582 IFREQ_INOUT(OSIOCGIFADDR);
583
584 case _IOW('i', 14, struct ifreq):
585 /* SIOCSIFDSTADDR */
586 break;
587
588 case _IOWR('i', 15, struct ifreq):
589 IFREQ_INOUT(OSIOCGIFDSTADDR);
590
591 case _IOW('i', 16, struct ifreq):
592 /* SIOCSIFFLAGS */
593 break;
594
595 case _IOWR('i', 17, struct ifreq):
596 /* SIOCGIFFLAGS */
597 break;
598
599 case _IOW('i', 21, struct ifreq):
600 IFREQ_IN(SIOCSIFMTU);
601
602 case _IOWR('i', 22, struct ifreq):
603 IFREQ_INOUT(SIOCGIFMTU);
604
605 case _IOWR('i', 23, struct ifreq):
606 IFREQ_INOUT(SIOCGIFBRDADDR);
607
608 case _IOW('i', 24, struct ifreq):
609 IFREQ_IN(SIOCSIFBRDADDR);
610
611 case _IOWR('i', 25, struct ifreq):
612 IFREQ_INOUT(OSIOCGIFNETMASK);
613
614 case _IOW('i', 26, struct ifreq):
615 IFREQ_IN(SIOCSIFNETMASK);
616
617 case _IOWR('i', 27, struct ifreq):
618 IFREQ_INOUT(SIOCGIFMETRIC);
619
620 case _IOWR('i', 28, struct ifreq):
621 IFREQ_IN(SIOCSIFMETRIC);
622
623 case _IOW('i', 30, struct arpreq):
624 /* SIOCSARP */
625 break;
626
627 case _IOWR('i', 31, struct arpreq):
628 /* SIOCGARP */
629 break;
630
631 case _IOW('i', 32, struct arpreq):
632 /* SIOCDARP */
633 break;
634
635 case _IOW('i', 18, struct ifreq): /* SIOCSIFMEM */
636 case _IOWR('i', 19, struct ifreq): /* SIOCGIFMEM */
637 case _IOW('i', 40, struct ifreq): /* SIOCUPPER */
638 case _IOW('i', 41, struct ifreq): /* SIOCLOWER */
639 case _IOW('i', 44, struct ifreq): /* SIOCSETSYNC */
640 case _IOWR('i', 45, struct ifreq): /* SIOCGETSYNC */
641 case _IOWR('i', 46, struct ifreq): /* SIOCSDSTATS */
642 case _IOWR('i', 47, struct ifreq): /* SIOCSESTATS */
643 case _IOW('i', 48, int): /* SIOCSPROMISC */
644 case _IOW('i', 49, struct ifreq): /* SIOCADDMULTI */
645 case _IOW('i', 50, struct ifreq): /* SIOCDELMULTI */
646 return EOPNOTSUPP;
647
648 case _IOWR('i', 20, struct ifconf): /* SIOCGIFCONF */
649 {
650 struct ifconf ifconf;
651
652 /*
653 * XXX: two more problems
654 * 1. our sockaddr's are variable length, not always sizeof(sockaddr)
655 * 2. this returns a name per protocol, ie. it returns two "lo0"'s
656 */
657 if (error = copyin (uap->data, (caddr_t)&ifconf, sizeof (ifconf)))
658 return error;
659 if (error = (*ctl)(fp, OSIOCGIFCONF, (caddr_t)&ifconf, p))
660 return error;
661 return copyout ((caddr_t)&ifconf, uap->data, sizeof (ifconf));
662 }
663 }
664 return (ioctl(p, uap, retval));
665 }
666