4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29 /*
30 * University Copyright- Copyright (c) 1982, 1986, 1988
31 * The Regents of the University of California
32 * All Rights Reserved
33 *
34 * University Acknowledgment- Portions of this document are derived from
35 * software developed by the University of California, Berkeley, and its
36 * contributors.
37 */
38
39 /*
40 * Module to intercept old V7 and 4BSD "ioctl" calls.
41 */
42
43 #include <sys/types.h>
56 #include <sys/ttcompat.h>
57 #include <sys/ddi.h>
58 #include <sys/sunddi.h>
59 #include <sys/kmem.h>
60 #include <sys/policy.h>
61
62 /*
63 * This is the loadable module wrapper.
64 */
65 #include <sys/conf.h>
66 #include <sys/modctl.h>
67
68 /* See os/streamio.c */
69 extern int sgttyb_handling;
70
71 static struct streamtab ttcoinfo;
72
73 static struct fmodsw fsw = {
74 "ttcompat",
75 &ttcoinfo,
76 D_MTQPAIR | D_MP
77 };
78
79 /*
80 * Module linkage information for the kernel.
81 */
82
83 static struct modlstrmod modlstrmod = {
84 &mod_strmodops,
85 "alt ioctl calls",
86 &fsw
87 };
88
89 static struct modlinkage modlinkage = {
90 MODREV_1, &modlstrmod, NULL
91 };
92
93 int
94 _init(void)
95 {
96 return (mod_install(&modlinkage));
139 300,
140 200
141 };
142
143 static struct qinit ttycompatwinit = {
144 (int (*)())ttcompatwput,
145 NULL,
146 ttcompatopen,
147 ttcompatclose,
148 NULL,
149 &ttycompatmoinfo
150 };
151
152 static struct streamtab ttcoinfo = {
153 &ttycompatrinit,
154 &ttycompatwinit,
155 NULL,
156 NULL
157 };
158
159 /*
160 * This is the termios structure that is used to reset terminal settings
161 * when the underlying device is an instance of zcons. It came from
162 * cmd/init/init.c and should be kept in-sync with dflt_termios found therein.
163 */
164 static const struct termios base_termios = {
165 BRKINT|ICRNL|IXON|IMAXBEL, /* iflag */
166 OPOST|ONLCR|TAB3, /* oflag */
167 CS8|CREAD|B9600, /* cflag */
168 ISIG|ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN, /* lflag */
169 CINTR, CQUIT, CERASE, CKILL, CEOF, 0, 0, 0, 0, 0, 0, 0, /* c_cc vals */
170 0, 0, 0, 0, 0, 0, 0
171 };
172
173
174 static void ttcompat_do_ioctl(ttcompat_state_t *, queue_t *, mblk_t *);
175 static void ttcompat_ioctl_ack(queue_t *, mblk_t *);
176 static void ttcopyout(queue_t *, mblk_t *);
177 static void ttcompat_ioctl_nak(queue_t *, mblk_t *);
178 static void from_compat(compat_state_t *, struct termios *);
179 static void to_compat(struct termios *, compat_state_t *);
180
181 /*
182 * Open - get the current modes and translate them to the V7/4BSD equivalent.
183 */
184 /*ARGSUSED*/
185 static int
186 ttcompatopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
187 {
188 ttcompat_state_t *tp;
189 mblk_t *mp;
190 mblk_t *datamp;
191 struct iocblk *iocb;
192 int error;
193
194 if (q->q_ptr != NULL) {
195 tp = (ttcompat_state_t *)q->q_ptr;
196 /* fail open if TIOCEXCL was done and its not privileged */
197 if ((tp->t_new_lflags & XCLUDE) &&
198 secpolicy_excl_open(crp) != 0) {
199 return (EBUSY);
200 }
201 return (0); /* already attached */
202 }
203 tp = kmem_zalloc(sizeof (ttcompat_state_t), KM_SLEEP);
204 tp->t_iocpending = NULL;
205 tp->t_state = 0;
206 tp->t_iocid = 0;
207 tp->t_ioccmd = 0;
208 tp->t_new_lflags = 0;
209 tp->t_curstate.t_flags = 0;
210 tp->t_curstate.t_ispeed = B0;
211 tp->t_curstate.t_ospeed = B0;
212 tp->t_curstate.t_erase = '\0';
213 tp->t_curstate.t_kill = '\0';
214 tp->t_curstate.t_intrc = '\0';
215 tp->t_curstate.t_quitc = '\0';
216 tp->t_curstate.t_startc = '\0';
217 tp->t_curstate.t_stopc = '\0';
218 tp->t_curstate.t_eofc = '\0';
219 tp->t_curstate.t_brkc = '\0';
220 tp->t_curstate.t_suspc = '\0';
221 tp->t_curstate.t_dsuspc = '\0';
222 tp->t_curstate.t_rprntc = '\0';
223 tp->t_curstate.t_flushc = '\0';
224 tp->t_curstate.t_werasc = '\0';
225 tp->t_curstate.t_lnextc = '\0';
226 tp->t_curstate.t_xflags = 0;
227 tp->t_bufcallid = 0;
228 tp->t_arg = 0;
229
230 q->q_ptr = tp;
231 WR(q)->q_ptr = tp;
232 qprocson(q);
233
234 /*
235 * Determine if the underlying device is a zcons instance. If so,
236 * then issue a termios ioctl to reset the terminal settings.
237 */
238 if (getmajor(q->q_stream->sd_vnode->v_rdev) !=
239 ddi_name_to_major("zcons"))
240 return (0);
241
242 /*
243 * Create the ioctl message.
244 */
245 if ((mp = mkiocb(TCSETSF)) == NULL) {
246 error = ENOMEM;
247 goto common_error;
248 }
249 if ((datamp = allocb(sizeof (struct termios), BPRI_HI)) == NULL) {
250 freemsg(mp);
251 error = ENOMEM;
252 goto common_error;
253 }
254 iocb = (struct iocblk *)mp->b_rptr;
255 iocb->ioc_count = sizeof (struct termios);
256 bcopy(&base_termios, datamp->b_rptr, sizeof (struct termios));
257 datamp->b_wptr += sizeof (struct termios);
258 mp->b_cont = datamp;
259
260 /*
261 * Send the ioctl message on its merry way toward the driver.
262 * Set some state beforehand so we can properly wait for
263 * an acknowledgement.
264 */
265 tp->t_state |= TS_IOCWAIT | TS_TIOCNAK;
266 tp->t_iocid = iocb->ioc_id;
267 tp->t_ioccmd = TCSETSF;
268 putnext(WR(q), mp);
269
270 /*
271 * Wait for an acknowledgement. A NAK is treated as an error.
272 * The presence of the TS_TIOCNAK flag indicates that a NAK was
273 * received.
274 */
275 while (tp->t_state & TS_IOCWAIT) {
276 if (qwait_sig(q) == 0) {
277 error = EINTR;
278 goto common_error;
279 }
280 }
281 if (!(tp->t_state & TS_TIOCNAK))
282 return (0);
283 error = ENOTTY;
284
285 common_error:
286 qprocsoff(q);
287 kmem_free(tp, sizeof (ttcompat_state_t));
288 q->q_ptr = NULL;
289 WR(q)->q_ptr = NULL;
290 return (error);
291 }
292
293 /* ARGSUSED1 */
294 static int
295 ttcompatclose(queue_t *q, int flag, cred_t *crp)
296 {
297 ttcompat_state_t *tp = (ttcompat_state_t *)q->q_ptr;
298 mblk_t *mp;
299
300 /* Dump the state structure, then unlink it */
301 qprocsoff(q);
302 if (tp->t_bufcallid != 0) {
303 qunbufcall(q, tp->t_bufcallid);
304 tp->t_bufcallid = 0;
305 }
306 if ((mp = tp->t_iocpending) != NULL)
307 freemsg(mp);
308 kmem_free(tp, sizeof (ttcompat_state_t));
309 q->q_ptr = NULL;
310
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 /*
41 * Module to intercept old V7 and 4BSD "ioctl" calls.
42 */
43
44 #include <sys/types.h>
57 #include <sys/ttcompat.h>
58 #include <sys/ddi.h>
59 #include <sys/sunddi.h>
60 #include <sys/kmem.h>
61 #include <sys/policy.h>
62
63 /*
64 * This is the loadable module wrapper.
65 */
66 #include <sys/conf.h>
67 #include <sys/modctl.h>
68
69 /* See os/streamio.c */
70 extern int sgttyb_handling;
71
72 static struct streamtab ttcoinfo;
73
74 static struct fmodsw fsw = {
75 "ttcompat",
76 &ttcoinfo,
77 D_MTQPAIR | D_MP | _D_SINGLE_INSTANCE
78 };
79
80 /*
81 * Module linkage information for the kernel.
82 */
83
84 static struct modlstrmod modlstrmod = {
85 &mod_strmodops,
86 "alt ioctl calls",
87 &fsw
88 };
89
90 static struct modlinkage modlinkage = {
91 MODREV_1, &modlstrmod, NULL
92 };
93
94 int
95 _init(void)
96 {
97 return (mod_install(&modlinkage));
140 300,
141 200
142 };
143
144 static struct qinit ttycompatwinit = {
145 (int (*)())ttcompatwput,
146 NULL,
147 ttcompatopen,
148 ttcompatclose,
149 NULL,
150 &ttycompatmoinfo
151 };
152
153 static struct streamtab ttcoinfo = {
154 &ttycompatrinit,
155 &ttycompatwinit,
156 NULL,
157 NULL
158 };
159
160 static void ttcompat_do_ioctl(ttcompat_state_t *, queue_t *, mblk_t *);
161 static void ttcompat_ioctl_ack(queue_t *, mblk_t *);
162 static void ttcopyout(queue_t *, mblk_t *);
163 static void ttcompat_ioctl_nak(queue_t *, mblk_t *);
164 static void from_compat(compat_state_t *, struct termios *);
165 static void to_compat(struct termios *, compat_state_t *);
166
167 /*
168 * Open - get the current modes and translate them to the V7/4BSD equivalent.
169 */
170 /*ARGSUSED*/
171 static int
172 ttcompatopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
173 {
174 ttcompat_state_t *tp;
175
176 if (q->q_ptr != NULL) {
177 tp = (ttcompat_state_t *)q->q_ptr;
178 /* fail open if TIOCEXCL was done and its not privileged */
179 if ((tp->t_new_lflags & XCLUDE) &&
180 secpolicy_excl_open(crp) != 0) {
181 return (EBUSY);
182 }
183 return (0); /* already attached */
184 }
185 tp = kmem_zalloc(sizeof (ttcompat_state_t), KM_SLEEP);
186 q->q_ptr = tp;
187 WR(q)->q_ptr = tp;
188 qprocson(q);
189
190 return (0);
191 }
192
193 /* ARGSUSED1 */
194 static int
195 ttcompatclose(queue_t *q, int flag, cred_t *crp)
196 {
197 ttcompat_state_t *tp = (ttcompat_state_t *)q->q_ptr;
198 mblk_t *mp;
199
200 /* Dump the state structure, then unlink it */
201 qprocsoff(q);
202 if (tp->t_bufcallid != 0) {
203 qunbufcall(q, tp->t_bufcallid);
204 tp->t_bufcallid = 0;
205 }
206 if ((mp = tp->t_iocpending) != NULL)
207 freemsg(mp);
208 kmem_free(tp, sizeof (ttcompat_state_t));
209 q->q_ptr = NULL;
210
|