cgd.c revision 1.91.2.7 1 /* $NetBSD: cgd.c,v 1.91.2.7 2017/02/05 13:40:26 skrll Exp $ */
2
3 /*-
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Roland C. Dowdeswell.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.91.2.7 2017/02/05 13:40:26 skrll Exp $");
34
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/proc.h>
39 #include <sys/errno.h>
40 #include <sys/buf.h>
41 #include <sys/bufq.h>
42 #include <sys/malloc.h>
43 #include <sys/module.h>
44 #include <sys/pool.h>
45 #include <sys/ioctl.h>
46 #include <sys/device.h>
47 #include <sys/disk.h>
48 #include <sys/disklabel.h>
49 #include <sys/fcntl.h>
50 #include <sys/namei.h> /* for pathbuf */
51 #include <sys/vnode.h>
52 #include <sys/conf.h>
53 #include <sys/syslog.h>
54
55 #include <dev/dkvar.h>
56 #include <dev/cgdvar.h>
57
58 #include <miscfs/specfs/specdev.h> /* for v_rdev */
59
60 #include "ioconf.h"
61
62 struct selftest_params {
63 const char *alg;
64 int blocksize; /* number of bytes */
65 int secsize;
66 daddr_t blkno;
67 int keylen; /* number of bits */
68 int txtlen; /* number of bytes */
69 const uint8_t *key;
70 const uint8_t *ptxt;
71 const uint8_t *ctxt;
72 };
73
74 /* Entry Point Functions */
75
76 static dev_type_open(cgdopen);
77 static dev_type_close(cgdclose);
78 static dev_type_read(cgdread);
79 static dev_type_write(cgdwrite);
80 static dev_type_ioctl(cgdioctl);
81 static dev_type_strategy(cgdstrategy);
82 static dev_type_dump(cgddump);
83 static dev_type_size(cgdsize);
84
85 const struct bdevsw cgd_bdevsw = {
86 .d_open = cgdopen,
87 .d_close = cgdclose,
88 .d_strategy = cgdstrategy,
89 .d_ioctl = cgdioctl,
90 .d_dump = cgddump,
91 .d_psize = cgdsize,
92 .d_discard = nodiscard,
93 .d_flag = D_DISK
94 };
95
96 const struct cdevsw cgd_cdevsw = {
97 .d_open = cgdopen,
98 .d_close = cgdclose,
99 .d_read = cgdread,
100 .d_write = cgdwrite,
101 .d_ioctl = cgdioctl,
102 .d_stop = nostop,
103 .d_tty = notty,
104 .d_poll = nopoll,
105 .d_mmap = nommap,
106 .d_kqfilter = nokqfilter,
107 .d_discard = nodiscard,
108 .d_flag = D_DISK
109 };
110
111 /*
112 * Vector 5 from IEEE 1619/D16 truncated to 64 bytes, blkno 1.
113 */
114 static const uint8_t selftest_aes_xts_256_ptxt[64] = {
115 0x27, 0xa7, 0x47, 0x9b, 0xef, 0xa1, 0xd4, 0x76,
116 0x48, 0x9f, 0x30, 0x8c, 0xd4, 0xcf, 0xa6, 0xe2,
117 0xa9, 0x6e, 0x4b, 0xbe, 0x32, 0x08, 0xff, 0x25,
118 0x28, 0x7d, 0xd3, 0x81, 0x96, 0x16, 0xe8, 0x9c,
119 0xc7, 0x8c, 0xf7, 0xf5, 0xe5, 0x43, 0x44, 0x5f,
120 0x83, 0x33, 0xd8, 0xfa, 0x7f, 0x56, 0x00, 0x00,
121 0x05, 0x27, 0x9f, 0xa5, 0xd8, 0xb5, 0xe4, 0xad,
122 0x40, 0xe7, 0x36, 0xdd, 0xb4, 0xd3, 0x54, 0x12,
123 };
124
125 static const uint8_t selftest_aes_xts_256_ctxt[512] = {
126 0x26, 0x4d, 0x3c, 0xa8, 0x51, 0x21, 0x94, 0xfe,
127 0xc3, 0x12, 0xc8, 0xc9, 0x89, 0x1f, 0x27, 0x9f,
128 0xef, 0xdd, 0x60, 0x8d, 0x0c, 0x02, 0x7b, 0x60,
129 0x48, 0x3a, 0x3f, 0xa8, 0x11, 0xd6, 0x5e, 0xe5,
130 0x9d, 0x52, 0xd9, 0xe4, 0x0e, 0xc5, 0x67, 0x2d,
131 0x81, 0x53, 0x2b, 0x38, 0xb6, 0xb0, 0x89, 0xce,
132 0x95, 0x1f, 0x0f, 0x9c, 0x35, 0x59, 0x0b, 0x8b,
133 0x97, 0x8d, 0x17, 0x52, 0x13, 0xf3, 0x29, 0xbb,
134 };
135
136 static const uint8_t selftest_aes_xts_256_key[33] = {
137 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
138 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
139 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
140 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95,
141 0
142 };
143
144 /*
145 * Vector 11 from IEEE 1619/D16 truncated to 64 bytes, blkno 0xffff.
146 */
147 static const uint8_t selftest_aes_xts_512_ptxt[64] = {
148 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
149 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
150 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
151 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
152 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
153 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
154 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
155 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
156 };
157
158 static const uint8_t selftest_aes_xts_512_ctxt[64] = {
159 0x77, 0xa3, 0x12, 0x51, 0x61, 0x8a, 0x15, 0xe6,
160 0xb9, 0x2d, 0x1d, 0x66, 0xdf, 0xfe, 0x7b, 0x50,
161 0xb5, 0x0b, 0xad, 0x55, 0x23, 0x05, 0xba, 0x02,
162 0x17, 0xa6, 0x10, 0x68, 0x8e, 0xff, 0x7e, 0x11,
163 0xe1, 0xd0, 0x22, 0x54, 0x38, 0xe0, 0x93, 0x24,
164 0x2d, 0x6d, 0xb2, 0x74, 0xfd, 0xe8, 0x01, 0xd4,
165 0xca, 0xe0, 0x6f, 0x20, 0x92, 0xc7, 0x28, 0xb2,
166 0x47, 0x85, 0x59, 0xdf, 0x58, 0xe8, 0x37, 0xc2,
167 };
168
169 static const uint8_t selftest_aes_xts_512_key[65] = {
170 0x27, 0x18, 0x28, 0x18, 0x28, 0x45, 0x90, 0x45,
171 0x23, 0x53, 0x60, 0x28, 0x74, 0x71, 0x35, 0x26,
172 0x62, 0x49, 0x77, 0x57, 0x24, 0x70, 0x93, 0x69,
173 0x99, 0x59, 0x57, 0x49, 0x66, 0x96, 0x76, 0x27,
174 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93,
175 0x23, 0x84, 0x62, 0x64, 0x33, 0x83, 0x27, 0x95,
176 0x02, 0x88, 0x41, 0x97, 0x16, 0x93, 0x99, 0x37,
177 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, 0x45, 0x92,
178 0
179 };
180
181 const struct selftest_params selftests[] = {
182 {
183 .alg = "aes-xts",
184 .blocksize = 16,
185 .secsize = 512,
186 .blkno = 1,
187 .keylen = 256,
188 .txtlen = sizeof(selftest_aes_xts_256_ptxt),
189 .key = selftest_aes_xts_256_key,
190 .ptxt = selftest_aes_xts_256_ptxt,
191 .ctxt = selftest_aes_xts_256_ctxt
192 },
193 {
194 .alg = "aes-xts",
195 .blocksize = 16,
196 .secsize = 512,
197 .blkno = 0xffff,
198 .keylen = 512,
199 .txtlen = sizeof(selftest_aes_xts_512_ptxt),
200 .key = selftest_aes_xts_512_key,
201 .ptxt = selftest_aes_xts_512_ptxt,
202 .ctxt = selftest_aes_xts_512_ctxt
203 }
204 };
205
206 static int cgd_match(device_t, cfdata_t, void *);
207 static void cgd_attach(device_t, device_t, void *);
208 static int cgd_detach(device_t, int);
209 static struct cgd_softc *cgd_spawn(int);
210 static int cgd_destroy(device_t);
211
212 /* Internal Functions */
213
214 static int cgd_diskstart(device_t, struct buf *);
215 static void cgdiodone(struct buf *);
216 static int cgd_dumpblocks(device_t, void *, daddr_t, int);
217
218 static int cgd_ioctl_set(struct cgd_softc *, void *, struct lwp *);
219 static int cgd_ioctl_clr(struct cgd_softc *, struct lwp *);
220 static int cgd_ioctl_get(dev_t, void *, struct lwp *);
221 static int cgdinit(struct cgd_softc *, const char *, struct vnode *,
222 struct lwp *);
223 static void cgd_cipher(struct cgd_softc *, void *, void *,
224 size_t, daddr_t, size_t, int);
225
226 static struct dkdriver cgddkdriver = {
227 .d_minphys = minphys,
228 .d_open = cgdopen,
229 .d_close = cgdclose,
230 .d_strategy = cgdstrategy,
231 .d_iosize = NULL,
232 .d_diskstart = cgd_diskstart,
233 .d_dumpblocks = cgd_dumpblocks,
234 .d_lastclose = NULL
235 };
236
237 CFATTACH_DECL3_NEW(cgd, sizeof(struct cgd_softc),
238 cgd_match, cgd_attach, cgd_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
239 extern struct cfdriver cgd_cd;
240
241 /* DIAGNOSTIC and DEBUG definitions */
242
243 #if defined(CGDDEBUG) && !defined(DEBUG)
244 #define DEBUG
245 #endif
246
247 #ifdef DEBUG
248 int cgddebug = 0;
249
250 #define CGDB_FOLLOW 0x1
251 #define CGDB_IO 0x2
252 #define CGDB_CRYPTO 0x4
253
254 #define IFDEBUG(x,y) if (cgddebug & (x)) y
255 #define DPRINTF(x,y) IFDEBUG(x, printf y)
256 #define DPRINTF_FOLLOW(y) DPRINTF(CGDB_FOLLOW, y)
257
258 static void hexprint(const char *, void *, int);
259
260 #else
261 #define IFDEBUG(x,y)
262 #define DPRINTF(x,y)
263 #define DPRINTF_FOLLOW(y)
264 #endif
265
266 #ifdef DIAGNOSTIC
267 #define DIAGPANIC(x) panic x
268 #define DIAGCONDPANIC(x,y) if (x) panic y
269 #else
270 #define DIAGPANIC(x)
271 #define DIAGCONDPANIC(x,y)
272 #endif
273
274 /* Global variables */
275
276 /* Utility Functions */
277
278 #define CGDUNIT(x) DISKUNIT(x)
279 #define GETCGD_SOFTC(_cs, x) if (!((_cs) = getcgd_softc(x))) return ENXIO
280
281 /* The code */
282
283 static struct cgd_softc *
284 getcgd_softc(dev_t dev)
285 {
286 int unit = CGDUNIT(dev);
287 struct cgd_softc *sc;
288
289 DPRINTF_FOLLOW(("getcgd_softc(0x%"PRIx64"): unit = %d\n", dev, unit));
290
291 sc = device_lookup_private(&cgd_cd, unit);
292 if (sc == NULL)
293 sc = cgd_spawn(unit);
294 return sc;
295 }
296
297 static int
298 cgd_match(device_t self, cfdata_t cfdata, void *aux)
299 {
300
301 return 1;
302 }
303
304 static void
305 cgd_attach(device_t parent, device_t self, void *aux)
306 {
307 struct cgd_softc *sc = device_private(self);
308
309 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_BIO);
310 dk_init(&sc->sc_dksc, self, DKTYPE_CGD);
311 disk_init(&sc->sc_dksc.sc_dkdev, sc->sc_dksc.sc_xname, &cgddkdriver);
312
313 if (!pmf_device_register(self, NULL, NULL))
314 aprint_error_dev(self,
315 "unable to register power management hooks\n");
316 }
317
318
319 static int
320 cgd_detach(device_t self, int flags)
321 {
322 int ret;
323 const int pmask = 1 << RAW_PART;
324 struct cgd_softc *sc = device_private(self);
325 struct dk_softc *dksc = &sc->sc_dksc;
326
327 if (DK_BUSY(dksc, pmask))
328 return EBUSY;
329
330 if (DK_ATTACHED(dksc) &&
331 (ret = cgd_ioctl_clr(sc, curlwp)) != 0)
332 return ret;
333
334 disk_destroy(&dksc->sc_dkdev);
335 mutex_destroy(&sc->sc_lock);
336
337 return 0;
338 }
339
340 void
341 cgdattach(int num)
342 {
343 int error;
344
345 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
346 if (error != 0)
347 aprint_error("%s: unable to register cfattach\n",
348 cgd_cd.cd_name);
349 }
350
351 static struct cgd_softc *
352 cgd_spawn(int unit)
353 {
354 cfdata_t cf;
355
356 cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK);
357 cf->cf_name = cgd_cd.cd_name;
358 cf->cf_atname = cgd_cd.cd_name;
359 cf->cf_unit = unit;
360 cf->cf_fstate = FSTATE_STAR;
361
362 return device_private(config_attach_pseudo(cf));
363 }
364
365 static int
366 cgd_destroy(device_t dev)
367 {
368 int error;
369 cfdata_t cf;
370
371 cf = device_cfdata(dev);
372 error = config_detach(dev, DETACH_QUIET);
373 if (error)
374 return error;
375 free(cf, M_DEVBUF);
376 return 0;
377 }
378
379 static int
380 cgdopen(dev_t dev, int flags, int fmt, struct lwp *l)
381 {
382 struct cgd_softc *cs;
383
384 DPRINTF_FOLLOW(("cgdopen(0x%"PRIx64", %d)\n", dev, flags));
385 GETCGD_SOFTC(cs, dev);
386 return dk_open(&cs->sc_dksc, dev, flags, fmt, l);
387 }
388
389 static int
390 cgdclose(dev_t dev, int flags, int fmt, struct lwp *l)
391 {
392 int error;
393 struct cgd_softc *cs;
394 struct dk_softc *dksc;
395
396 DPRINTF_FOLLOW(("cgdclose(0x%"PRIx64", %d)\n", dev, flags));
397 GETCGD_SOFTC(cs, dev);
398 dksc = &cs->sc_dksc;
399 if ((error = dk_close(dksc, dev, flags, fmt, l)) != 0)
400 return error;
401
402 if (!DK_ATTACHED(dksc)) {
403 if ((error = cgd_destroy(cs->sc_dksc.sc_dev)) != 0) {
404 aprint_error_dev(dksc->sc_dev,
405 "unable to detach instance\n");
406 return error;
407 }
408 }
409 return 0;
410 }
411
412 static void
413 cgdstrategy(struct buf *bp)
414 {
415 struct cgd_softc *cs;
416
417 DPRINTF_FOLLOW(("cgdstrategy(%p): b_bcount = %ld\n", bp,
418 (long)bp->b_bcount));
419
420 cs = getcgd_softc(bp->b_dev);
421 if (!cs) {
422 bp->b_error = ENXIO;
423 goto bail;
424 }
425
426 /*
427 * Reject unaligned writes.
428 */
429 if (((uintptr_t)bp->b_data & 3) != 0) {
430 bp->b_error = EINVAL;
431 goto bail;
432 }
433
434 dk_strategy(&cs->sc_dksc, bp);
435 return;
436
437 bail:
438 bp->b_resid = bp->b_bcount;
439 biodone(bp);
440 return;
441 }
442
443 static int
444 cgdsize(dev_t dev)
445 {
446 struct cgd_softc *cs = getcgd_softc(dev);
447
448 DPRINTF_FOLLOW(("cgdsize(0x%"PRIx64")\n", dev));
449 if (!cs)
450 return -1;
451 return dk_size(&cs->sc_dksc, dev);
452 }
453
454 /*
455 * cgd_{get,put}data are functions that deal with getting a buffer
456 * for the new encrypted data. We have a buffer per device so that
457 * we can ensure that we can always have a transaction in flight.
458 * We use this buffer first so that we have one less piece of
459 * malloc'ed data at any given point.
460 */
461
462 static void *
463 cgd_getdata(struct dk_softc *dksc, unsigned long size)
464 {
465 struct cgd_softc *cs = (struct cgd_softc *)dksc;
466 void * data = NULL;
467
468 mutex_enter(&cs->sc_lock);
469 if (cs->sc_data_used == 0) {
470 cs->sc_data_used = 1;
471 data = cs->sc_data;
472 }
473 mutex_exit(&cs->sc_lock);
474
475 if (data)
476 return data;
477
478 return malloc(size, M_DEVBUF, M_NOWAIT);
479 }
480
481 static void
482 cgd_putdata(struct dk_softc *dksc, void *data)
483 {
484 struct cgd_softc *cs = (struct cgd_softc *)dksc;
485
486 if (data == cs->sc_data) {
487 mutex_enter(&cs->sc_lock);
488 cs->sc_data_used = 0;
489 mutex_exit(&cs->sc_lock);
490 } else {
491 free(data, M_DEVBUF);
492 }
493 }
494
495 static int
496 cgd_diskstart(device_t dev, struct buf *bp)
497 {
498 struct cgd_softc *cs = device_private(dev);
499 struct dk_softc *dksc = &cs->sc_dksc;
500 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
501 struct buf *nbp;
502 void * addr;
503 void * newaddr;
504 daddr_t bn;
505 struct vnode *vp;
506
507 DPRINTF_FOLLOW(("cgd_diskstart(%p, %p)\n", dksc, bp));
508
509 bn = bp->b_rawblkno;
510
511 /*
512 * We attempt to allocate all of our resources up front, so that
513 * we can fail quickly if they are unavailable.
514 */
515 nbp = getiobuf(cs->sc_tvn, false);
516 if (nbp == NULL)
517 return EAGAIN;
518
519 /*
520 * If we are writing, then we need to encrypt the outgoing
521 * block into a new block of memory.
522 */
523 newaddr = addr = bp->b_data;
524 if ((bp->b_flags & B_READ) == 0) {
525 newaddr = cgd_getdata(dksc, bp->b_bcount);
526 if (!newaddr) {
527 putiobuf(nbp);
528 return EAGAIN;
529 }
530 cgd_cipher(cs, newaddr, addr, bp->b_bcount, bn,
531 dg->dg_secsize, CGD_CIPHER_ENCRYPT);
532 }
533
534 nbp->b_data = newaddr;
535 nbp->b_flags = bp->b_flags;
536 nbp->b_oflags = bp->b_oflags;
537 nbp->b_cflags = bp->b_cflags;
538 nbp->b_iodone = cgdiodone;
539 nbp->b_proc = bp->b_proc;
540 nbp->b_blkno = btodb(bn * dg->dg_secsize);
541 nbp->b_bcount = bp->b_bcount;
542 nbp->b_private = bp;
543
544 BIO_COPYPRIO(nbp, bp);
545
546 if ((nbp->b_flags & B_READ) == 0) {
547 vp = nbp->b_vp;
548 mutex_enter(vp->v_interlock);
549 vp->v_numoutput++;
550 mutex_exit(vp->v_interlock);
551 }
552 VOP_STRATEGY(cs->sc_tvn, nbp);
553
554 return 0;
555 }
556
557 static void
558 cgdiodone(struct buf *nbp)
559 {
560 struct buf *obp = nbp->b_private;
561 struct cgd_softc *cs = getcgd_softc(obp->b_dev);
562 struct dk_softc *dksc = &cs->sc_dksc;
563 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
564 daddr_t bn;
565
566 KDASSERT(cs);
567
568 DPRINTF_FOLLOW(("cgdiodone(%p)\n", nbp));
569 DPRINTF(CGDB_IO, ("cgdiodone: bp %p bcount %d resid %d\n",
570 obp, obp->b_bcount, obp->b_resid));
571 DPRINTF(CGDB_IO, (" dev 0x%"PRIx64", nbp %p bn %" PRId64
572 " addr %p bcnt %d\n", nbp->b_dev, nbp, nbp->b_blkno, nbp->b_data,
573 nbp->b_bcount));
574 if (nbp->b_error != 0) {
575 obp->b_error = nbp->b_error;
576 DPRINTF(CGDB_IO, ("%s: error %d\n", dksc->sc_xname,
577 obp->b_error));
578 }
579
580 /* Perform the decryption if we are reading.
581 *
582 * Note: use the blocknumber from nbp, since it is what
583 * we used to encrypt the blocks.
584 */
585
586 if (nbp->b_flags & B_READ) {
587 bn = dbtob(nbp->b_blkno) / dg->dg_secsize;
588 cgd_cipher(cs, obp->b_data, obp->b_data, obp->b_bcount,
589 bn, dg->dg_secsize, CGD_CIPHER_DECRYPT);
590 }
591
592 /* If we allocated memory, free it now... */
593 if (nbp->b_data != obp->b_data)
594 cgd_putdata(dksc, nbp->b_data);
595
596 putiobuf(nbp);
597
598 /* Request is complete for whatever reason */
599 obp->b_resid = 0;
600 if (obp->b_error != 0)
601 obp->b_resid = obp->b_bcount;
602
603 dk_done(dksc, obp);
604 dk_start(dksc, NULL);
605 }
606
607 static int
608 cgd_dumpblocks(device_t dev, void *va, daddr_t blkno, int nblk)
609 {
610 struct cgd_softc *sc = device_private(dev);
611 struct dk_softc *dksc = &sc->sc_dksc;
612 struct disk_geom *dg = &dksc->sc_dkdev.dk_geom;
613 size_t nbytes, blksize;
614 void *buf;
615 int error;
616
617 /*
618 * dk_dump gives us units of disklabel sectors. Everything
619 * else in cgd uses units of diskgeom sectors. These had
620 * better agree; otherwise we need to figure out how to convert
621 * between them.
622 */
623 KASSERTMSG((dg->dg_secsize == dksc->sc_dkdev.dk_label->d_secsize),
624 "diskgeom secsize %"PRIu32" != disklabel secsize %"PRIu32,
625 dg->dg_secsize, dksc->sc_dkdev.dk_label->d_secsize);
626 blksize = dg->dg_secsize;
627
628 /*
629 * Compute the number of bytes in this request, which dk_dump
630 * has `helpfully' converted to a number of blocks for us.
631 */
632 nbytes = nblk*blksize;
633
634 /* Try to acquire a buffer to store the ciphertext. */
635 buf = cgd_getdata(dksc, nbytes);
636 if (buf == NULL)
637 /* Out of memory: give up. */
638 return ENOMEM;
639
640 /* Encrypt the caller's data into the temporary buffer. */
641 cgd_cipher(sc, buf, va, nbytes, blkno, blksize, CGD_CIPHER_ENCRYPT);
642
643 /* Pass it on to the underlying disk device. */
644 error = bdev_dump(sc->sc_tdev, blkno, buf, nbytes);
645
646 /* Release the buffer. */
647 cgd_putdata(dksc, buf);
648
649 /* Return any error from the underlying disk device. */
650 return error;
651 }
652
653 /* XXX: we should probably put these into dksubr.c, mostly */
654 static int
655 cgdread(dev_t dev, struct uio *uio, int flags)
656 {
657 struct cgd_softc *cs;
658 struct dk_softc *dksc;
659
660 DPRINTF_FOLLOW(("cgdread(0x%llx, %p, %d)\n",
661 (unsigned long long)dev, uio, flags));
662 GETCGD_SOFTC(cs, dev);
663 dksc = &cs->sc_dksc;
664 if (!DK_ATTACHED(dksc))
665 return ENXIO;
666 return physio(cgdstrategy, NULL, dev, B_READ, minphys, uio);
667 }
668
669 /* XXX: we should probably put these into dksubr.c, mostly */
670 static int
671 cgdwrite(dev_t dev, struct uio *uio, int flags)
672 {
673 struct cgd_softc *cs;
674 struct dk_softc *dksc;
675
676 DPRINTF_FOLLOW(("cgdwrite(0x%"PRIx64", %p, %d)\n", dev, uio, flags));
677 GETCGD_SOFTC(cs, dev);
678 dksc = &cs->sc_dksc;
679 if (!DK_ATTACHED(dksc))
680 return ENXIO;
681 return physio(cgdstrategy, NULL, dev, B_WRITE, minphys, uio);
682 }
683
684 static int
685 cgdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
686 {
687 struct cgd_softc *cs;
688 struct dk_softc *dksc;
689 int part = DISKPART(dev);
690 int pmask = 1 << part;
691
692 DPRINTF_FOLLOW(("cgdioctl(0x%"PRIx64", %ld, %p, %d, %p)\n",
693 dev, cmd, data, flag, l));
694
695 switch (cmd) {
696 case CGDIOCGET:
697 return cgd_ioctl_get(dev, data, l);
698 case CGDIOCSET:
699 case CGDIOCCLR:
700 if ((flag & FWRITE) == 0)
701 return EBADF;
702 /* FALLTHROUGH */
703 default:
704 GETCGD_SOFTC(cs, dev);
705 dksc = &cs->sc_dksc;
706 break;
707 }
708
709 switch (cmd) {
710 case CGDIOCSET:
711 if (DK_ATTACHED(dksc))
712 return EBUSY;
713 return cgd_ioctl_set(cs, data, l);
714 case CGDIOCCLR:
715 if (DK_BUSY(&cs->sc_dksc, pmask))
716 return EBUSY;
717 return cgd_ioctl_clr(cs, l);
718 case DIOCCACHESYNC:
719 /*
720 * XXX Do we really need to care about having a writable
721 * file descriptor here?
722 */
723 if ((flag & FWRITE) == 0)
724 return (EBADF);
725
726 /*
727 * We pass this call down to the underlying disk.
728 */
729 return VOP_IOCTL(cs->sc_tvn, cmd, data, flag, l->l_cred);
730 case DIOCGSTRATEGY:
731 case DIOCSSTRATEGY:
732 if (!DK_ATTACHED(dksc))
733 return ENOENT;
734 /*FALLTHROUGH*/
735 default:
736 return dk_ioctl(dksc, dev, cmd, data, flag, l);
737 case CGDIOCGET:
738 KASSERT(0);
739 return EINVAL;
740 }
741 }
742
743 static int
744 cgddump(dev_t dev, daddr_t blkno, void *va, size_t size)
745 {
746 struct cgd_softc *cs;
747
748 DPRINTF_FOLLOW(("cgddump(0x%"PRIx64", %" PRId64 ", %p, %lu)\n",
749 dev, blkno, va, (unsigned long)size));
750 GETCGD_SOFTC(cs, dev);
751 return dk_dump(&cs->sc_dksc, dev, blkno, va, size);
752 }
753
754 /*
755 * XXXrcd:
756 * for now we hardcode the maximum key length.
757 */
758 #define MAX_KEYSIZE 1024
759
760 static const struct {
761 const char *n;
762 int v;
763 int d;
764 } encblkno[] = {
765 { "encblkno", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
766 { "encblkno8", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
767 { "encblkno1", CGD_CIPHER_CBC_ENCBLKNO1, 8 },
768 };
769
770 /* ARGSUSED */
771 static int
772 cgd_ioctl_set(struct cgd_softc *cs, void *data, struct lwp *l)
773 {
774 struct cgd_ioctl *ci = data;
775 struct vnode *vp;
776 int ret;
777 size_t i;
778 size_t keybytes; /* key length in bytes */
779 const char *cp;
780 struct pathbuf *pb;
781 char *inbuf;
782 struct dk_softc *dksc = &cs->sc_dksc;
783
784 cp = ci->ci_disk;
785
786 ret = pathbuf_copyin(ci->ci_disk, &pb);
787 if (ret != 0) {
788 return ret;
789 }
790 ret = dk_lookup(pb, l, &vp);
791 pathbuf_destroy(pb);
792 if (ret != 0) {
793 return ret;
794 }
795
796 inbuf = malloc(MAX_KEYSIZE, M_TEMP, M_WAITOK);
797
798 if ((ret = cgdinit(cs, cp, vp, l)) != 0)
799 goto bail;
800
801 (void)memset(inbuf, 0, MAX_KEYSIZE);
802 ret = copyinstr(ci->ci_alg, inbuf, 256, NULL);
803 if (ret)
804 goto bail;
805 cs->sc_cfuncs = cryptfuncs_find(inbuf);
806 if (!cs->sc_cfuncs) {
807 ret = EINVAL;
808 goto bail;
809 }
810
811 (void)memset(inbuf, 0, MAX_KEYSIZE);
812 ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL);
813 if (ret)
814 goto bail;
815
816 for (i = 0; i < __arraycount(encblkno); i++)
817 if (strcmp(encblkno[i].n, inbuf) == 0)
818 break;
819
820 if (i == __arraycount(encblkno)) {
821 ret = EINVAL;
822 goto bail;
823 }
824
825 keybytes = ci->ci_keylen / 8 + 1;
826 if (keybytes > MAX_KEYSIZE) {
827 ret = EINVAL;
828 goto bail;
829 }
830
831 (void)memset(inbuf, 0, MAX_KEYSIZE);
832 ret = copyin(ci->ci_key, inbuf, keybytes);
833 if (ret)
834 goto bail;
835
836 cs->sc_cdata.cf_blocksize = ci->ci_blocksize;
837 cs->sc_cdata.cf_mode = encblkno[i].v;
838 cs->sc_cdata.cf_keylen = ci->ci_keylen;
839 cs->sc_cdata.cf_priv = cs->sc_cfuncs->cf_init(ci->ci_keylen, inbuf,
840 &cs->sc_cdata.cf_blocksize);
841 if (cs->sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE) {
842 log(LOG_WARNING, "cgd: Disallowed cipher with blocksize %zu > %u\n",
843 cs->sc_cdata.cf_blocksize, CGD_MAXBLOCKSIZE);
844 cs->sc_cdata.cf_priv = NULL;
845 }
846
847 /*
848 * The blocksize is supposed to be in bytes. Unfortunately originally
849 * it was expressed in bits. For compatibility we maintain encblkno
850 * and encblkno8.
851 */
852 cs->sc_cdata.cf_blocksize /= encblkno[i].d;
853 (void)explicit_memset(inbuf, 0, MAX_KEYSIZE);
854 if (!cs->sc_cdata.cf_priv) {
855 ret = EINVAL; /* XXX is this the right error? */
856 goto bail;
857 }
858 free(inbuf, M_TEMP);
859
860 bufq_alloc(&dksc->sc_bufq, "fcfs", 0);
861
862 cs->sc_data = malloc(MAXPHYS, M_DEVBUF, M_WAITOK);
863 cs->sc_data_used = 0;
864
865 /* Attach the disk. */
866 dk_attach(dksc);
867 disk_attach(&dksc->sc_dkdev);
868
869 disk_set_info(dksc->sc_dev, &dksc->sc_dkdev, NULL);
870
871 /* Discover wedges on this disk. */
872 dkwedge_discover(&dksc->sc_dkdev);
873
874 return 0;
875
876 bail:
877 free(inbuf, M_TEMP);
878 (void)vn_close(vp, FREAD|FWRITE, l->l_cred);
879 return ret;
880 }
881
882 /* ARGSUSED */
883 static int
884 cgd_ioctl_clr(struct cgd_softc *cs, struct lwp *l)
885 {
886 struct dk_softc *dksc = &cs->sc_dksc;
887
888 if (!DK_ATTACHED(dksc))
889 return ENXIO;
890
891 /* Delete all of our wedges. */
892 dkwedge_delall(&dksc->sc_dkdev);
893
894 /* Kill off any queued buffers. */
895 dk_drain(dksc);
896 bufq_free(dksc->sc_bufq);
897
898 (void)vn_close(cs->sc_tvn, FREAD|FWRITE, l->l_cred);
899 cs->sc_cfuncs->cf_destroy(cs->sc_cdata.cf_priv);
900 free(cs->sc_tpath, M_DEVBUF);
901 free(cs->sc_data, M_DEVBUF);
902 cs->sc_data_used = 0;
903 dk_detach(dksc);
904 disk_detach(&dksc->sc_dkdev);
905
906 return 0;
907 }
908
909 static int
910 cgd_ioctl_get(dev_t dev, void *data, struct lwp *l)
911 {
912 struct cgd_softc *cs = getcgd_softc(dev);
913 struct cgd_user *cgu;
914 int unit;
915 struct dk_softc *dksc = &cs->sc_dksc;
916
917 unit = CGDUNIT(dev);
918 cgu = (struct cgd_user *)data;
919
920 DPRINTF_FOLLOW(("cgd_ioctl_get(0x%"PRIx64", %d, %p, %p)\n",
921 dev, unit, data, l));
922
923 if (cgu->cgu_unit == -1)
924 cgu->cgu_unit = unit;
925
926 if (cgu->cgu_unit < 0)
927 return EINVAL; /* XXX: should this be ENXIO? */
928
929 cs = device_lookup_private(&cgd_cd, unit);
930 if (cs == NULL || !DK_ATTACHED(dksc)) {
931 cgu->cgu_dev = 0;
932 cgu->cgu_alg[0] = '\0';
933 cgu->cgu_blocksize = 0;
934 cgu->cgu_mode = 0;
935 cgu->cgu_keylen = 0;
936 }
937 else {
938 cgu->cgu_dev = cs->sc_tdev;
939 strlcpy(cgu->cgu_alg, cs->sc_cfuncs->cf_name,
940 sizeof(cgu->cgu_alg));
941 cgu->cgu_blocksize = cs->sc_cdata.cf_blocksize;
942 cgu->cgu_mode = cs->sc_cdata.cf_mode;
943 cgu->cgu_keylen = cs->sc_cdata.cf_keylen;
944 }
945 return 0;
946 }
947
948 static int
949 cgdinit(struct cgd_softc *cs, const char *cpath, struct vnode *vp,
950 struct lwp *l)
951 {
952 struct disk_geom *dg;
953 int ret;
954 char *tmppath;
955 uint64_t psize;
956 unsigned secsize;
957 struct dk_softc *dksc = &cs->sc_dksc;
958
959 cs->sc_tvn = vp;
960 cs->sc_tpath = NULL;
961
962 tmppath = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
963 ret = copyinstr(cpath, tmppath, MAXPATHLEN, &cs->sc_tpathlen);
964 if (ret)
965 goto bail;
966 cs->sc_tpath = malloc(cs->sc_tpathlen, M_DEVBUF, M_WAITOK);
967 memcpy(cs->sc_tpath, tmppath, cs->sc_tpathlen);
968
969 cs->sc_tdev = vp->v_rdev;
970
971 if ((ret = getdisksize(vp, &psize, &secsize)) != 0)
972 goto bail;
973
974 if (psize == 0) {
975 ret = ENODEV;
976 goto bail;
977 }
978
979 /*
980 * XXX here we should probe the underlying device. If we
981 * are accessing a partition of type RAW_PART, then
982 * we should populate our initial geometry with the
983 * geometry that we discover from the device.
984 */
985 dg = &dksc->sc_dkdev.dk_geom;
986 memset(dg, 0, sizeof(*dg));
987 dg->dg_secperunit = psize;
988 dg->dg_secsize = secsize;
989 dg->dg_ntracks = 1;
990 dg->dg_nsectors = 1024 * 1024 / dg->dg_secsize;
991 dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors;
992
993 bail:
994 free(tmppath, M_TEMP);
995 if (ret && cs->sc_tpath)
996 free(cs->sc_tpath, M_DEVBUF);
997 return ret;
998 }
999
1000 /*
1001 * Our generic cipher entry point. This takes care of the
1002 * IV mode and passes off the work to the specific cipher.
1003 * We implement here the IV method ``encrypted block
1004 * number''.
1005 *
1006 * XXXrcd: for now we rely on our own crypto framework defined
1007 * in dev/cgd_crypto.c. This will change when we
1008 * get a generic kernel crypto framework.
1009 */
1010
1011 static void
1012 blkno2blkno_buf(char *sbuf, daddr_t blkno)
1013 {
1014 int i;
1015
1016 /* Set up the blkno in blkno_buf, here we do not care much
1017 * about the final layout of the information as long as we
1018 * can guarantee that each sector will have a different IV
1019 * and that the endianness of the machine will not affect
1020 * the representation that we have chosen.
1021 *
1022 * We choose this representation, because it does not rely
1023 * on the size of buf (which is the blocksize of the cipher),
1024 * but allows daddr_t to grow without breaking existing
1025 * disks.
1026 *
1027 * Note that blkno2blkno_buf does not take a size as input,
1028 * and hence must be called on a pre-zeroed buffer of length
1029 * greater than or equal to sizeof(daddr_t).
1030 */
1031 for (i=0; i < sizeof(daddr_t); i++) {
1032 *sbuf++ = blkno & 0xff;
1033 blkno >>= 8;
1034 }
1035 }
1036
1037 static void
1038 cgd_cipher(struct cgd_softc *cs, void *dstv, void *srcv,
1039 size_t len, daddr_t blkno, size_t secsize, int dir)
1040 {
1041 char *dst = dstv;
1042 char *src = srcv;
1043 cfunc_cipher_prep *ciprep = cs->sc_cfuncs->cf_cipher_prep;
1044 cfunc_cipher *cipher = cs->sc_cfuncs->cf_cipher;
1045 struct uio dstuio;
1046 struct uio srcuio;
1047 struct iovec dstiov[2];
1048 struct iovec srciov[2];
1049 size_t blocksize = cs->sc_cdata.cf_blocksize;
1050 size_t todo;
1051 char blkno_buf[CGD_MAXBLOCKSIZE], *iv;
1052
1053 DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir));
1054
1055 DIAGCONDPANIC(len % blocksize != 0,
1056 ("cgd_cipher: len %% blocksize != 0"));
1057
1058 /* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */
1059 DIAGCONDPANIC(sizeof(daddr_t) > blocksize,
1060 ("cgd_cipher: sizeof(daddr_t) > blocksize"));
1061
1062 DIAGCONDPANIC(blocksize > CGD_MAXBLOCKSIZE,
1063 ("cgd_cipher: blocksize > CGD_MAXBLOCKSIZE"));
1064
1065 dstuio.uio_iov = dstiov;
1066 dstuio.uio_iovcnt = 1;
1067
1068 srcuio.uio_iov = srciov;
1069 srcuio.uio_iovcnt = 1;
1070
1071 for (; len > 0; len -= todo) {
1072 todo = MIN(len, secsize);
1073
1074 dstiov[0].iov_base = dst;
1075 srciov[0].iov_base = src;
1076 dstiov[0].iov_len = todo;
1077 srciov[0].iov_len = todo;
1078
1079 memset(blkno_buf, 0x0, blocksize);
1080 blkno2blkno_buf(blkno_buf, blkno);
1081 IFDEBUG(CGDB_CRYPTO, hexprint("step 1: blkno_buf",
1082 blkno_buf, blocksize));
1083
1084 /*
1085 * Compute an initial IV. All ciphers
1086 * can convert blkno_buf in-place.
1087 */
1088 iv = blkno_buf;
1089 ciprep(cs->sc_cdata.cf_priv, iv, blkno_buf, blocksize, dir);
1090 IFDEBUG(CGDB_CRYPTO, hexprint("step 2: iv", iv, blocksize));
1091
1092 cipher(cs->sc_cdata.cf_priv, &dstuio, &srcuio, iv, dir);
1093
1094 dst += todo;
1095 src += todo;
1096 blkno++;
1097 }
1098 }
1099
1100 #ifdef DEBUG
1101 static void
1102 hexprint(const char *start, void *buf, int len)
1103 {
1104 char *c = buf;
1105
1106 DIAGCONDPANIC(len < 0, ("hexprint: called with len < 0"));
1107 printf("%s: len=%06d 0x", start, len);
1108 while (len--)
1109 printf("%02x", (unsigned char) *c++);
1110 }
1111 #endif
1112
1113 static void
1114 selftest(void)
1115 {
1116 struct cgd_softc cs;
1117 void *buf;
1118
1119 printf("running cgd selftest ");
1120
1121 for (size_t i = 0; i < __arraycount(selftests); i++) {
1122 const char *alg = selftests[i].alg;
1123 const uint8_t *key = selftests[i].key;
1124 int keylen = selftests[i].keylen;
1125 int txtlen = selftests[i].txtlen;
1126
1127 printf("%s-%d ", alg, keylen);
1128
1129 memset(&cs, 0, sizeof(cs));
1130
1131 cs.sc_cfuncs = cryptfuncs_find(alg);
1132 if (cs.sc_cfuncs == NULL)
1133 panic("%s not implemented", alg);
1134
1135 cs.sc_cdata.cf_blocksize = 8 * selftests[i].blocksize;
1136 cs.sc_cdata.cf_mode = CGD_CIPHER_CBC_ENCBLKNO1;
1137 cs.sc_cdata.cf_keylen = keylen;
1138
1139 cs.sc_cdata.cf_priv = cs.sc_cfuncs->cf_init(keylen,
1140 key, &cs.sc_cdata.cf_blocksize);
1141 if (cs.sc_cdata.cf_priv == NULL)
1142 panic("cf_priv is NULL");
1143 if (cs.sc_cdata.cf_blocksize > CGD_MAXBLOCKSIZE)
1144 panic("bad block size %zu", cs.sc_cdata.cf_blocksize);
1145
1146 cs.sc_cdata.cf_blocksize /= 8;
1147
1148 buf = malloc(txtlen, M_DEVBUF, M_WAITOK);
1149 memcpy(buf, selftests[i].ptxt, txtlen);
1150
1151 cgd_cipher(&cs, buf, buf, txtlen, selftests[i].blkno,
1152 selftests[i].secsize, CGD_CIPHER_ENCRYPT);
1153 if (memcmp(buf, selftests[i].ctxt, txtlen) != 0)
1154 panic("encryption is broken");
1155
1156 cgd_cipher(&cs, buf, buf, txtlen, selftests[i].blkno,
1157 selftests[i].secsize, CGD_CIPHER_DECRYPT);
1158 if (memcmp(buf, selftests[i].ptxt, txtlen) != 0)
1159 panic("decryption is broken");
1160
1161 free(buf, M_DEVBUF);
1162 cs.sc_cfuncs->cf_destroy(cs.sc_cdata.cf_priv);
1163 }
1164
1165 printf("done\n");
1166 }
1167
1168 MODULE(MODULE_CLASS_DRIVER, cgd, "blowfish,des,dk_subr");
1169
1170 #ifdef _MODULE
1171 CFDRIVER_DECL(cgd, DV_DISK, NULL);
1172
1173 devmajor_t cgd_bmajor = -1, cgd_cmajor = -1;
1174 #endif
1175
1176 static int
1177 cgd_modcmd(modcmd_t cmd, void *arg)
1178 {
1179 int error = 0;
1180
1181 switch (cmd) {
1182 case MODULE_CMD_INIT:
1183 selftest();
1184 #ifdef _MODULE
1185 error = config_cfdriver_attach(&cgd_cd);
1186 if (error)
1187 break;
1188
1189 error = config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
1190 if (error) {
1191 config_cfdriver_detach(&cgd_cd);
1192 aprint_error("%s: unable to register cfattach for"
1193 "%s, error %d\n", __func__, cgd_cd.cd_name, error);
1194 break;
1195 }
1196 /*
1197 * Attach the {b,c}devsw's
1198 */
1199 error = devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1200 &cgd_cdevsw, &cgd_cmajor);
1201
1202 /*
1203 * If devsw_attach fails, remove from autoconf database
1204 */
1205 if (error) {
1206 config_cfattach_detach(cgd_cd.cd_name, &cgd_ca);
1207 config_cfdriver_detach(&cgd_cd);
1208 aprint_error("%s: unable to attach %s devsw, "
1209 "error %d", __func__, cgd_cd.cd_name, error);
1210 break;
1211 }
1212 #endif
1213 break;
1214
1215 case MODULE_CMD_FINI:
1216 #ifdef _MODULE
1217 /*
1218 * Remove {b,c}devsw's
1219 */
1220 devsw_detach(&cgd_bdevsw, &cgd_cdevsw);
1221
1222 /*
1223 * Now remove device from autoconf database
1224 */
1225 error = config_cfattach_detach(cgd_cd.cd_name, &cgd_ca);
1226 if (error) {
1227 (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1228 &cgd_cdevsw, &cgd_cmajor);
1229 aprint_error("%s: failed to detach %s cfattach, "
1230 "error %d\n", __func__, cgd_cd.cd_name, error);
1231 break;
1232 }
1233 error = config_cfdriver_detach(&cgd_cd);
1234 if (error) {
1235 (void)config_cfattach_attach(cgd_cd.cd_name, &cgd_ca);
1236 (void)devsw_attach("cgd", &cgd_bdevsw, &cgd_bmajor,
1237 &cgd_cdevsw, &cgd_cmajor);
1238 aprint_error("%s: failed to detach %s cfdriver, "
1239 "error %d\n", __func__, cgd_cd.cd_name, error);
1240 break;
1241 }
1242 #endif
1243 break;
1244
1245 case MODULE_CMD_STAT:
1246 error = ENOTTY;
1247 break;
1248 default:
1249 error = ENOTTY;
1250 break;
1251 }
1252
1253 return error;
1254 }
1255