Home | History | Annotate | Line # | Download | only in dev
cgd.c revision 1.53.4.2.4.1
      1  1.53.4.2.4.1      matt /* $NetBSD: cgd.c,v 1.53.4.2.4.1 2010/04/21 00:27:32 matt Exp $ */
      2           1.1     elric 
      3           1.1     elric /*-
      4           1.1     elric  * Copyright (c) 2002 The NetBSD Foundation, Inc.
      5           1.1     elric  * All rights reserved.
      6           1.1     elric  *
      7           1.1     elric  * This code is derived from software contributed to The NetBSD Foundation
      8           1.1     elric  * by Roland C. Dowdeswell.
      9           1.1     elric  *
     10           1.1     elric  * Redistribution and use in source and binary forms, with or without
     11           1.1     elric  * modification, are permitted provided that the following conditions
     12           1.1     elric  * are met:
     13           1.1     elric  * 1. Redistributions of source code must retain the above copyright
     14           1.1     elric  *    notice, this list of conditions and the following disclaimer.
     15           1.1     elric  * 2. Redistributions in binary form must reproduce the above copyright
     16           1.1     elric  *    notice, this list of conditions and the following disclaimer in the
     17           1.1     elric  *    documentation and/or other materials provided with the distribution.
     18           1.1     elric  *
     19           1.1     elric  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20           1.1     elric  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21           1.1     elric  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22           1.1     elric  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23           1.1     elric  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24           1.1     elric  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25           1.1     elric  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26           1.1     elric  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27           1.1     elric  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28           1.1     elric  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29           1.1     elric  * POSSIBILITY OF SUCH DAMAGE.
     30           1.1     elric  */
     31           1.1     elric 
     32           1.1     elric #include <sys/cdefs.h>
     33  1.53.4.2.4.1      matt __KERNEL_RCSID(0, "$NetBSD: cgd.c,v 1.53.4.2.4.1 2010/04/21 00:27:32 matt Exp $");
     34           1.1     elric 
     35           1.1     elric #include <sys/types.h>
     36           1.1     elric #include <sys/param.h>
     37           1.1     elric #include <sys/systm.h>
     38           1.1     elric #include <sys/proc.h>
     39           1.1     elric #include <sys/errno.h>
     40           1.1     elric #include <sys/buf.h>
     41          1.21      yamt #include <sys/bufq.h>
     42           1.1     elric #include <sys/malloc.h>
     43           1.1     elric #include <sys/pool.h>
     44           1.1     elric #include <sys/ioctl.h>
     45           1.1     elric #include <sys/device.h>
     46           1.1     elric #include <sys/disk.h>
     47           1.1     elric #include <sys/disklabel.h>
     48           1.1     elric #include <sys/fcntl.h>
     49           1.1     elric #include <sys/vnode.h>
     50           1.1     elric #include <sys/conf.h>
     51           1.1     elric 
     52           1.1     elric #include <dev/dkvar.h>
     53           1.1     elric #include <dev/cgdvar.h>
     54           1.1     elric 
     55           1.1     elric /* Entry Point Functions */
     56           1.1     elric 
     57           1.1     elric void	cgdattach(int);
     58           1.1     elric 
     59          1.18   thorpej static dev_type_open(cgdopen);
     60          1.18   thorpej static dev_type_close(cgdclose);
     61          1.18   thorpej static dev_type_read(cgdread);
     62          1.18   thorpej static dev_type_write(cgdwrite);
     63          1.18   thorpej static dev_type_ioctl(cgdioctl);
     64          1.18   thorpej static dev_type_strategy(cgdstrategy);
     65          1.18   thorpej static dev_type_dump(cgddump);
     66          1.18   thorpej static dev_type_size(cgdsize);
     67           1.1     elric 
     68           1.1     elric const struct bdevsw cgd_bdevsw = {
     69           1.1     elric 	cgdopen, cgdclose, cgdstrategy, cgdioctl,
     70           1.1     elric 	cgddump, cgdsize, D_DISK
     71           1.1     elric };
     72           1.1     elric 
     73           1.1     elric const struct cdevsw cgd_cdevsw = {
     74           1.1     elric 	cgdopen, cgdclose, cgdread, cgdwrite, cgdioctl,
     75           1.4  jdolecek 	nostop, notty, nopoll, nommap, nokqfilter, D_DISK
     76           1.1     elric };
     77           1.1     elric 
     78           1.1     elric /* Internal Functions */
     79           1.1     elric 
     80          1.16     elric static int	cgdstart(struct dk_softc *, struct buf *);
     81           1.1     elric static void	cgdiodone(struct buf *);
     82           1.1     elric 
     83          1.32  christos static int	cgd_ioctl_set(struct cgd_softc *, void *, struct lwp *);
     84          1.32  christos static int	cgd_ioctl_clr(struct cgd_softc *, void *, struct lwp *);
     85          1.27  drochner static int	cgdinit(struct cgd_softc *, const char *, struct vnode *,
     86          1.32  christos 			struct lwp *);
     87          1.44  christos static void	cgd_cipher(struct cgd_softc *, void *, void *,
     88           1.1     elric 			   size_t, daddr_t, size_t, int);
     89           1.1     elric 
     90           1.1     elric /* Pseudo-disk Interface */
     91           1.1     elric 
     92           1.1     elric static struct dk_intf the_dkintf = {
     93           1.1     elric 	DTYPE_CGD,
     94           1.1     elric 	"cgd",
     95           1.1     elric 	cgdopen,
     96           1.1     elric 	cgdclose,
     97           1.1     elric 	cgdstrategy,
     98           1.1     elric 	cgdstart,
     99           1.1     elric };
    100           1.1     elric static struct dk_intf *di = &the_dkintf;
    101           1.1     elric 
    102          1.29      yamt static struct dkdriver cgddkdriver = {
    103          1.29      yamt 	.d_strategy = cgdstrategy,
    104          1.29      yamt 	.d_minphys = minphys,
    105          1.29      yamt };
    106          1.29      yamt 
    107           1.1     elric /* DIAGNOSTIC and DEBUG definitions */
    108           1.1     elric 
    109           1.1     elric #if defined(CGDDEBUG) && !defined(DEBUG)
    110           1.1     elric #define DEBUG
    111           1.1     elric #endif
    112           1.1     elric 
    113           1.1     elric #ifdef DEBUG
    114           1.1     elric int cgddebug = 0;
    115           1.1     elric 
    116           1.1     elric #define CGDB_FOLLOW	0x1
    117           1.1     elric #define CGDB_IO	0x2
    118           1.1     elric #define CGDB_CRYPTO	0x4
    119           1.1     elric 
    120           1.1     elric #define IFDEBUG(x,y)		if (cgddebug & (x)) y
    121           1.1     elric #define DPRINTF(x,y)		IFDEBUG(x, printf y)
    122           1.1     elric #define DPRINTF_FOLLOW(y)	DPRINTF(CGDB_FOLLOW, y)
    123           1.1     elric 
    124          1.26  drochner static void	hexprint(const char *, void *, int);
    125           1.1     elric 
    126           1.1     elric #else
    127           1.1     elric #define IFDEBUG(x,y)
    128           1.1     elric #define DPRINTF(x,y)
    129           1.1     elric #define DPRINTF_FOLLOW(y)
    130           1.1     elric #endif
    131           1.1     elric 
    132           1.1     elric #ifdef DIAGNOSTIC
    133          1.22     perry #define DIAGPANIC(x)		panic x
    134           1.1     elric #define DIAGCONDPANIC(x,y)	if (x) panic y
    135           1.1     elric #else
    136           1.1     elric #define DIAGPANIC(x)
    137           1.1     elric #define DIAGCONDPANIC(x,y)
    138           1.1     elric #endif
    139           1.1     elric 
    140           1.1     elric /* Global variables */
    141           1.1     elric 
    142           1.1     elric struct	cgd_softc *cgd_softc;
    143           1.1     elric int	numcgd = 0;
    144           1.1     elric 
    145           1.1     elric /* Utility Functions */
    146           1.1     elric 
    147           1.1     elric #define CGDUNIT(x)		DISKUNIT(x)
    148           1.1     elric #define GETCGD_SOFTC(_cs, x)	if (!((_cs) = getcgd_softc(x))) return ENXIO
    149           1.1     elric 
    150           1.1     elric static struct cgd_softc *
    151           1.1     elric getcgd_softc(dev_t dev)
    152           1.1     elric {
    153           1.1     elric 	int	unit = CGDUNIT(dev);
    154           1.1     elric 
    155           1.1     elric 	DPRINTF_FOLLOW(("getcgd_softc(0x%x): unit = %d\n", dev, unit));
    156           1.1     elric 	if (unit >= numcgd)
    157           1.1     elric 		return NULL;
    158           1.1     elric 	return &cgd_softc[unit];
    159           1.1     elric }
    160           1.1     elric 
    161           1.1     elric /* The code */
    162           1.1     elric 
    163           1.1     elric static void
    164           1.1     elric cgdsoftc_init(struct cgd_softc *cs, int num)
    165           1.1     elric {
    166          1.25   xtraeme 	char	sbuf[DK_XNAME_SIZE];
    167           1.1     elric 
    168           1.1     elric 	memset(cs, 0x0, sizeof(*cs));
    169          1.25   xtraeme 	snprintf(sbuf, DK_XNAME_SIZE, "cgd%d", num);
    170          1.16     elric 	simple_lock_init(&cs->sc_slock);
    171          1.25   xtraeme 	dk_sc_init(&cs->sc_dksc, cs, sbuf);
    172          1.47        ad 	disk_init(&cs->sc_dksc.sc_dkdev, cs->sc_dksc.sc_xname, &cgddkdriver);
    173           1.1     elric }
    174           1.1     elric 
    175           1.1     elric void
    176           1.1     elric cgdattach(int num)
    177           1.1     elric {
    178           1.1     elric 	int	i;
    179           1.1     elric 
    180           1.1     elric 	DPRINTF_FOLLOW(("cgdattach(%d)\n", num));
    181           1.1     elric 	if (num <= 0) {
    182           1.1     elric 		DIAGPANIC(("cgdattach: count <= 0"));
    183           1.1     elric 		return;
    184           1.1     elric 	}
    185           1.1     elric 
    186          1.10       agc 	cgd_softc = (void *)malloc(num * sizeof(*cgd_softc), M_DEVBUF, M_NOWAIT);
    187          1.10       agc 	if (!cgd_softc) {
    188           1.1     elric 		printf("WARNING: unable to malloc(9) memory for crypt disks\n");
    189           1.1     elric 		DIAGPANIC(("cgdattach: cannot malloc(9) enough memory"));
    190           1.1     elric 		return;
    191           1.1     elric 	}
    192           1.1     elric 
    193           1.1     elric 	numcgd = num;
    194           1.1     elric 	for (i=0; i<num; i++)
    195           1.1     elric 		cgdsoftc_init(&cgd_softc[i], i);
    196           1.1     elric }
    197           1.1     elric 
    198          1.18   thorpej static int
    199          1.32  christos cgdopen(dev_t dev, int flags, int fmt, struct lwp *l)
    200           1.1     elric {
    201           1.1     elric 	struct	cgd_softc *cs;
    202           1.1     elric 
    203           1.1     elric 	DPRINTF_FOLLOW(("cgdopen(%d, %d)\n", dev, flags));
    204           1.1     elric 	GETCGD_SOFTC(cs, dev);
    205          1.32  christos 	return dk_open(di, &cs->sc_dksc, dev, flags, fmt, l);
    206           1.1     elric }
    207           1.1     elric 
    208          1.18   thorpej static int
    209          1.32  christos cgdclose(dev_t dev, int flags, int fmt, struct lwp *l)
    210           1.1     elric {
    211           1.1     elric 	struct	cgd_softc *cs;
    212           1.1     elric 
    213           1.1     elric 	DPRINTF_FOLLOW(("cgdclose(%d, %d)\n", dev, flags));
    214           1.1     elric 	GETCGD_SOFTC(cs, dev);
    215          1.32  christos 	return dk_close(di, &cs->sc_dksc, dev, flags, fmt, l);
    216           1.1     elric }
    217           1.1     elric 
    218          1.18   thorpej static void
    219           1.1     elric cgdstrategy(struct buf *bp)
    220           1.1     elric {
    221           1.1     elric 	struct	cgd_softc *cs = getcgd_softc(bp->b_dev);
    222           1.1     elric 
    223           1.1     elric 	DPRINTF_FOLLOW(("cgdstrategy(%p): b_bcount = %ld\n", bp,
    224           1.1     elric 	    (long)bp->b_bcount));
    225           1.1     elric 	/* XXXrcd: Should we test for (cs != NULL)? */
    226           1.1     elric 	dk_strategy(di, &cs->sc_dksc, bp);
    227           1.1     elric 	return;
    228           1.1     elric }
    229           1.1     elric 
    230          1.18   thorpej static int
    231           1.1     elric cgdsize(dev_t dev)
    232           1.1     elric {
    233           1.1     elric 	struct cgd_softc *cs = getcgd_softc(dev);
    234           1.1     elric 
    235           1.1     elric 	DPRINTF_FOLLOW(("cgdsize(%d)\n", dev));
    236           1.1     elric 	if (!cs)
    237           1.1     elric 		return -1;
    238           1.1     elric 	return dk_size(di, &cs->sc_dksc, dev);
    239           1.1     elric }
    240           1.1     elric 
    241          1.16     elric /*
    242          1.16     elric  * cgd_{get,put}data are functions that deal with getting a buffer
    243          1.16     elric  * for the new encrypted data.  We have a buffer per device so that
    244          1.16     elric  * we can ensure that we can always have a transaction in flight.
    245          1.16     elric  * We use this buffer first so that we have one less piece of
    246          1.16     elric  * malloc'ed data at any given point.
    247          1.16     elric  */
    248          1.16     elric 
    249          1.16     elric static void *
    250          1.16     elric cgd_getdata(struct dk_softc *dksc, unsigned long size)
    251          1.16     elric {
    252          1.16     elric 	struct	cgd_softc *cs =dksc->sc_osc;
    253          1.44  christos 	void *	data = NULL;
    254          1.16     elric 
    255          1.16     elric 	simple_lock(&cs->sc_slock);
    256          1.16     elric 	if (cs->sc_data_used == 0) {
    257          1.16     elric 		cs->sc_data_used = 1;
    258          1.16     elric 		data = cs->sc_data;
    259          1.16     elric 	}
    260          1.16     elric 	simple_unlock(&cs->sc_slock);
    261          1.16     elric 
    262          1.16     elric 	if (data)
    263          1.16     elric 		return data;
    264          1.16     elric 
    265          1.16     elric 	return malloc(size, M_DEVBUF, M_NOWAIT);
    266          1.16     elric }
    267          1.16     elric 
    268           1.1     elric static void
    269          1.44  christos cgd_putdata(struct dk_softc *dksc, void *data)
    270          1.16     elric {
    271          1.16     elric 	struct	cgd_softc *cs =dksc->sc_osc;
    272          1.16     elric 
    273          1.16     elric 	if (data == cs->sc_data) {
    274          1.16     elric 		simple_lock(&cs->sc_slock);
    275          1.16     elric 		cs->sc_data_used = 0;
    276          1.16     elric 		simple_unlock(&cs->sc_slock);
    277          1.16     elric 	} else {
    278          1.16     elric 		free(data, M_DEVBUF);
    279          1.16     elric 	}
    280          1.16     elric }
    281          1.16     elric 
    282          1.16     elric static int
    283           1.1     elric cgdstart(struct dk_softc *dksc, struct buf *bp)
    284           1.1     elric {
    285           1.1     elric 	struct	cgd_softc *cs = dksc->sc_osc;
    286          1.17       dbj 	struct	buf *nbp;
    287          1.44  christos 	void *	addr;
    288          1.44  christos 	void *	newaddr;
    289           1.1     elric 	daddr_t	bn;
    290          1.49        ad 	struct	vnode *vp;
    291           1.1     elric 
    292           1.1     elric 	DPRINTF_FOLLOW(("cgdstart(%p, %p)\n", dksc, bp));
    293           1.1     elric 	disk_busy(&dksc->sc_dkdev); /* XXX: put in dksubr.c */
    294           1.1     elric 
    295          1.31      yamt 	bn = bp->b_rawblkno;
    296           1.1     elric 
    297           1.1     elric 	/*
    298          1.16     elric 	 * We attempt to allocate all of our resources up front, so that
    299          1.16     elric 	 * we can fail quickly if they are unavailable.
    300          1.16     elric 	 */
    301          1.22     perry 
    302          1.49        ad 	nbp = getiobuf(cs->sc_tvn, false);
    303          1.17       dbj 	if (nbp == NULL) {
    304          1.16     elric 		disk_unbusy(&dksc->sc_dkdev, 0, (bp->b_flags & B_READ));
    305          1.16     elric 		return -1;
    306          1.16     elric 	}
    307          1.16     elric 
    308          1.16     elric 	/*
    309           1.1     elric 	 * If we are writing, then we need to encrypt the outgoing
    310          1.16     elric 	 * block into a new block of memory.  If we fail, then we
    311          1.16     elric 	 * return an error and let the dksubr framework deal with it.
    312           1.1     elric 	 */
    313           1.1     elric 	newaddr = addr = bp->b_data;
    314           1.1     elric 	if ((bp->b_flags & B_READ) == 0) {
    315          1.16     elric 		newaddr = cgd_getdata(dksc, bp->b_bcount);
    316          1.16     elric 		if (!newaddr) {
    317          1.33      yamt 			putiobuf(nbp);
    318          1.16     elric 			disk_unbusy(&dksc->sc_dkdev, 0, (bp->b_flags & B_READ));
    319          1.16     elric 			return -1;
    320          1.16     elric 		}
    321           1.1     elric 		cgd_cipher(cs, newaddr, addr, bp->b_bcount, bn,
    322           1.1     elric 		    DEV_BSIZE, CGD_CIPHER_ENCRYPT);
    323           1.1     elric 	}
    324           1.1     elric 
    325          1.17       dbj 	nbp->b_data = newaddr;
    326          1.49        ad 	nbp->b_flags = bp->b_flags;
    327          1.49        ad 	nbp->b_oflags = bp->b_oflags;
    328          1.49        ad 	nbp->b_cflags = bp->b_cflags;
    329          1.17       dbj 	nbp->b_iodone = cgdiodone;
    330          1.17       dbj 	nbp->b_proc = bp->b_proc;
    331          1.17       dbj 	nbp->b_blkno = bn;
    332          1.17       dbj 	nbp->b_bcount = bp->b_bcount;
    333          1.17       dbj 	nbp->b_private = bp;
    334          1.17       dbj 
    335          1.17       dbj 	BIO_COPYPRIO(nbp, bp);
    336          1.17       dbj 
    337          1.17       dbj 	if ((nbp->b_flags & B_READ) == 0) {
    338          1.49        ad 		vp = nbp->b_vp;
    339          1.49        ad 		mutex_enter(&vp->v_interlock);
    340          1.49        ad 		vp->v_numoutput++;
    341          1.49        ad 		mutex_exit(&vp->v_interlock);
    342          1.17       dbj 	}
    343          1.17       dbj 	VOP_STRATEGY(cs->sc_tvn, nbp);
    344          1.16     elric 	return 0;
    345           1.1     elric }
    346           1.1     elric 
    347          1.18   thorpej static void
    348          1.17       dbj cgdiodone(struct buf *nbp)
    349           1.1     elric {
    350          1.17       dbj 	struct	buf *obp = nbp->b_private;
    351          1.17       dbj 	struct	cgd_softc *cs = getcgd_softc(obp->b_dev);
    352           1.1     elric 	struct	dk_softc *dksc = &cs->sc_dksc;
    353  1.53.4.2.4.1      matt 	int s;
    354          1.22     perry 
    355          1.17       dbj 	KDASSERT(cs);
    356           1.1     elric 
    357          1.17       dbj 	DPRINTF_FOLLOW(("cgdiodone(%p)\n", nbp));
    358          1.20      yamt 	DPRINTF(CGDB_IO, ("cgdiodone: bp %p bcount %d resid %d\n",
    359           1.1     elric 	    obp, obp->b_bcount, obp->b_resid));
    360          1.20      yamt 	DPRINTF(CGDB_IO, (" dev 0x%x, nbp %p bn %" PRId64 " addr %p bcnt %d\n",
    361          1.17       dbj 	    nbp->b_dev, nbp, nbp->b_blkno, nbp->b_data,
    362          1.17       dbj 	    nbp->b_bcount));
    363          1.46        ad 	if (nbp->b_error != 0) {
    364          1.46        ad 		obp->b_error = nbp->b_error;
    365           1.1     elric 		printf("%s: error %d\n", dksc->sc_xname, obp->b_error);
    366           1.1     elric 	}
    367           1.1     elric 
    368          1.16     elric 	/* Perform the decryption if we are reading.
    369           1.1     elric 	 *
    370           1.1     elric 	 * Note: use the blocknumber from nbp, since it is what
    371           1.1     elric 	 *       we used to encrypt the blocks.
    372           1.1     elric 	 */
    373           1.1     elric 
    374          1.16     elric 	if (nbp->b_flags & B_READ)
    375           1.1     elric 		cgd_cipher(cs, obp->b_data, obp->b_data, obp->b_bcount,
    376           1.1     elric 		    nbp->b_blkno, DEV_BSIZE, CGD_CIPHER_DECRYPT);
    377           1.1     elric 
    378          1.16     elric 	/* If we allocated memory, free it now... */
    379           1.1     elric 	if (nbp->b_data != obp->b_data)
    380          1.16     elric 		cgd_putdata(dksc, nbp->b_data);
    381           1.1     elric 
    382          1.33      yamt 	putiobuf(nbp);
    383           1.1     elric 
    384           1.1     elric 	/* Request is complete for whatever reason */
    385           1.1     elric 	obp->b_resid = 0;
    386          1.46        ad 	if (obp->b_error != 0)
    387           1.1     elric 		obp->b_resid = obp->b_bcount;
    388  1.53.4.2.4.1      matt 	s = splbio();
    389           1.5       mrg 	disk_unbusy(&dksc->sc_dkdev, obp->b_bcount - obp->b_resid,
    390           1.5       mrg 	    (obp->b_flags & B_READ));
    391           1.1     elric 	biodone(obp);
    392          1.16     elric 	dk_iodone(di, dksc);
    393  1.53.4.2.4.1      matt 	splx(s);
    394           1.1     elric }
    395           1.1     elric 
    396           1.1     elric /* XXX: we should probably put these into dksubr.c, mostly */
    397          1.18   thorpej static int
    398          1.40  christos cgdread(dev_t dev, struct uio *uio, int flags)
    399           1.1     elric {
    400           1.1     elric 	struct	cgd_softc *cs;
    401           1.1     elric 	struct	dk_softc *dksc;
    402           1.1     elric 
    403           1.1     elric 	DPRINTF_FOLLOW(("cgdread(%d, %p, %d)\n", dev, uio, flags));
    404           1.1     elric 	GETCGD_SOFTC(cs, dev);
    405           1.1     elric 	dksc = &cs->sc_dksc;
    406           1.1     elric 	if ((dksc->sc_flags & DKF_INITED) == 0)
    407           1.1     elric 		return ENXIO;
    408           1.1     elric 	return physio(cgdstrategy, NULL, dev, B_READ, minphys, uio);
    409           1.1     elric }
    410           1.1     elric 
    411           1.1     elric /* XXX: we should probably put these into dksubr.c, mostly */
    412          1.18   thorpej static int
    413          1.40  christos cgdwrite(dev_t dev, struct uio *uio, int flags)
    414           1.1     elric {
    415           1.1     elric 	struct	cgd_softc *cs;
    416           1.1     elric 	struct	dk_softc *dksc;
    417           1.1     elric 
    418           1.1     elric 	DPRINTF_FOLLOW(("cgdwrite(%d, %p, %d)\n", dev, uio, flags));
    419           1.1     elric 	GETCGD_SOFTC(cs, dev);
    420           1.1     elric 	dksc = &cs->sc_dksc;
    421           1.1     elric 	if ((dksc->sc_flags & DKF_INITED) == 0)
    422           1.1     elric 		return ENXIO;
    423           1.1     elric 	return physio(cgdstrategy, NULL, dev, B_WRITE, minphys, uio);
    424           1.1     elric }
    425           1.1     elric 
    426          1.18   thorpej static int
    427          1.44  christos cgdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
    428           1.1     elric {
    429           1.1     elric 	struct	cgd_softc *cs;
    430           1.1     elric 	struct	dk_softc *dksc;
    431          1.29      yamt 	struct	disk *dk;
    432           1.1     elric 	int	ret;
    433           1.1     elric 	int	part = DISKPART(dev);
    434           1.1     elric 	int	pmask = 1 << part;
    435           1.1     elric 
    436           1.1     elric 	DPRINTF_FOLLOW(("cgdioctl(%d, %ld, %p, %d, %p)\n",
    437          1.32  christos 	    dev, cmd, data, flag, l));
    438           1.1     elric 	GETCGD_SOFTC(cs, dev);
    439           1.1     elric 	dksc = &cs->sc_dksc;
    440          1.29      yamt 	dk = &dksc->sc_dkdev;
    441           1.1     elric 	switch (cmd) {
    442           1.1     elric 	case CGDIOCSET:
    443           1.1     elric 	case CGDIOCCLR:
    444           1.1     elric 		if ((flag & FWRITE) == 0)
    445           1.1     elric 			return EBADF;
    446           1.1     elric 	}
    447           1.1     elric 
    448           1.1     elric 	switch (cmd) {
    449           1.1     elric 	case CGDIOCSET:
    450           1.1     elric 		if (dksc->sc_flags & DKF_INITED)
    451           1.1     elric 			ret = EBUSY;
    452           1.1     elric 		else
    453          1.32  christos 			ret = cgd_ioctl_set(cs, data, l);
    454           1.1     elric 		break;
    455           1.1     elric 	case CGDIOCCLR:
    456           1.1     elric 		if (!(dksc->sc_flags & DKF_INITED)) {
    457           1.1     elric 			ret = ENXIO;
    458           1.1     elric 			break;
    459           1.1     elric 		}
    460           1.1     elric 		if (DK_BUSY(&cs->sc_dksc, pmask)) {
    461           1.1     elric 			ret = EBUSY;
    462           1.1     elric 			break;
    463           1.1     elric 		}
    464          1.32  christos 		ret = cgd_ioctl_clr(cs, data, l);
    465           1.1     elric 		break;
    466      1.53.4.2       snj 
    467      1.53.4.2       snj 	case DIOCCACHESYNC:
    468      1.53.4.2       snj 		/*
    469      1.53.4.2       snj 		 * XXX Do we really need to care about having a writable
    470      1.53.4.2       snj 		 * file descriptor here?
    471      1.53.4.2       snj 		 */
    472      1.53.4.2       snj 		if ((flag & FWRITE) == 0)
    473      1.53.4.2       snj 			return (EBADF);
    474      1.53.4.2       snj 
    475      1.53.4.2       snj 		/*
    476      1.53.4.2       snj 		 * We pass this call down to the underlying disk.
    477      1.53.4.2       snj 		 */
    478      1.53.4.2       snj 		ret = VOP_IOCTL(cs->sc_tvn, cmd, data, flag, l->l_cred);
    479      1.53.4.2       snj 		break;
    480      1.53.4.2       snj 
    481           1.1     elric 	default:
    482          1.32  christos 		ret = dk_ioctl(di, dksc, dev, cmd, data, flag, l);
    483           1.1     elric 		break;
    484           1.1     elric 	}
    485           1.1     elric 
    486           1.1     elric 	return ret;
    487           1.1     elric }
    488           1.1     elric 
    489          1.18   thorpej static int
    490          1.44  christos cgddump(dev_t dev, daddr_t blkno, void *va, size_t size)
    491           1.1     elric {
    492           1.1     elric 	struct	cgd_softc *cs;
    493           1.1     elric 
    494           1.6    bouyer 	DPRINTF_FOLLOW(("cgddump(%d, %" PRId64 ", %p, %lu)\n", dev, blkno, va,
    495           1.2     elric 	    (unsigned long)size));
    496           1.1     elric 	GETCGD_SOFTC(cs, dev);
    497           1.1     elric 	return dk_dump(di, &cs->sc_dksc, dev, blkno, va, size);
    498           1.1     elric }
    499           1.1     elric 
    500           1.1     elric /*
    501           1.1     elric  * XXXrcd:
    502           1.1     elric  *  for now we hardcode the maximum key length.
    503           1.1     elric  */
    504           1.1     elric #define MAX_KEYSIZE	1024
    505           1.1     elric 
    506          1.53  christos static const struct {
    507          1.53  christos 	const char *n;
    508          1.53  christos 	int v;
    509          1.53  christos 	int d;
    510          1.53  christos } encblkno[] = {
    511          1.53  christos 	{ "encblkno",  CGD_CIPHER_CBC_ENCBLKNO8, 1 },
    512          1.53  christos 	{ "encblkno8", CGD_CIPHER_CBC_ENCBLKNO8, 1 },
    513          1.53  christos 	{ "encblkno1", CGD_CIPHER_CBC_ENCBLKNO1, 8 },
    514          1.53  christos };
    515          1.53  christos 
    516           1.1     elric /* ARGSUSED */
    517           1.1     elric static int
    518          1.32  christos cgd_ioctl_set(struct cgd_softc *cs, void *data, struct lwp *l)
    519           1.1     elric {
    520           1.1     elric 	struct	 cgd_ioctl *ci = data;
    521           1.1     elric 	struct	 vnode *vp;
    522           1.1     elric 	int	 ret;
    523          1.53  christos 	size_t	 i;
    524          1.43    cbiere 	size_t	 keybytes;			/* key length in bytes */
    525          1.27  drochner 	const char *cp;
    526          1.36  christos 	char	 *inbuf;
    527           1.1     elric 
    528           1.1     elric 	cp = ci->ci_disk;
    529          1.45      cube 	if ((ret = dk_lookup(cp, l, &vp, UIO_USERSPACE)) != 0)
    530           1.1     elric 		return ret;
    531           1.1     elric 
    532          1.36  christos 	inbuf = malloc(MAX_KEYSIZE, M_TEMP, M_WAITOK);
    533          1.36  christos 
    534          1.32  christos 	if ((ret = cgdinit(cs, cp, vp, l)) != 0)
    535           1.1     elric 		goto bail;
    536           1.1     elric 
    537          1.36  christos 	(void)memset(inbuf, 0, MAX_KEYSIZE);
    538           1.1     elric 	ret = copyinstr(ci->ci_alg, inbuf, 256, NULL);
    539           1.1     elric 	if (ret)
    540           1.1     elric 		goto bail;
    541           1.1     elric 	cs->sc_cfuncs = cryptfuncs_find(inbuf);
    542           1.1     elric 	if (!cs->sc_cfuncs) {
    543           1.1     elric 		ret = EINVAL;
    544           1.1     elric 		goto bail;
    545           1.1     elric 	}
    546           1.1     elric 
    547          1.43    cbiere 	(void)memset(inbuf, 0, MAX_KEYSIZE);
    548          1.36  christos 	ret = copyinstr(ci->ci_ivmethod, inbuf, MAX_KEYSIZE, NULL);
    549           1.1     elric 	if (ret)
    550           1.1     elric 		goto bail;
    551          1.53  christos 
    552          1.53  christos 	for (i = 0; i < __arraycount(encblkno); i++)
    553          1.53  christos 		if (strcmp(encblkno[i].n, inbuf) == 0)
    554          1.53  christos 			break;
    555          1.53  christos 
    556          1.53  christos 	if (i == __arraycount(encblkno)) {
    557           1.1     elric 		ret = EINVAL;
    558           1.1     elric 		goto bail;
    559           1.1     elric 	}
    560           1.1     elric 
    561          1.15       dan 	keybytes = ci->ci_keylen / 8 + 1;
    562          1.15       dan 	if (keybytes > MAX_KEYSIZE) {
    563           1.1     elric 		ret = EINVAL;
    564           1.1     elric 		goto bail;
    565           1.1     elric 	}
    566          1.53  christos 
    567          1.36  christos 	(void)memset(inbuf, 0, MAX_KEYSIZE);
    568          1.15       dan 	ret = copyin(ci->ci_key, inbuf, keybytes);
    569           1.1     elric 	if (ret)
    570           1.1     elric 		goto bail;
    571           1.1     elric 
    572           1.1     elric 	cs->sc_cdata.cf_blocksize = ci->ci_blocksize;
    573          1.53  christos 	cs->sc_cdata.cf_mode = encblkno[i].v;
    574           1.1     elric 	cs->sc_cdata.cf_priv = cs->sc_cfuncs->cf_init(ci->ci_keylen, inbuf,
    575           1.1     elric 	    &cs->sc_cdata.cf_blocksize);
    576          1.53  christos 	/*
    577          1.53  christos 	 * The blocksize is supposed to be in bytes. Unfortunately originally
    578          1.53  christos 	 * it was expressed in bits. For compatibility we maintain encblkno
    579          1.53  christos 	 * and encblkno8.
    580          1.53  christos 	 */
    581          1.53  christos 	cs->sc_cdata.cf_blocksize /= encblkno[i].d;
    582          1.36  christos 	(void)memset(inbuf, 0, MAX_KEYSIZE);
    583           1.1     elric 	if (!cs->sc_cdata.cf_priv) {
    584           1.1     elric 		printf("cgd: unable to initialize cipher\n");
    585           1.1     elric 		ret = EINVAL;		/* XXX is this the right error? */
    586           1.1     elric 		goto bail;
    587           1.1     elric 	}
    588          1.36  christos 	free(inbuf, M_TEMP);
    589           1.1     elric 
    590          1.30      yamt 	bufq_alloc(&cs->sc_dksc.sc_bufq, "fcfs", 0);
    591          1.16     elric 
    592          1.16     elric 	cs->sc_data = malloc(MAXPHYS, M_DEVBUF, M_WAITOK);
    593          1.16     elric 	cs->sc_data_used = 0;
    594          1.16     elric 
    595           1.1     elric 	cs->sc_dksc.sc_flags |= DKF_INITED;
    596           1.1     elric 
    597           1.1     elric 	/* Attach the disk. */
    598          1.47        ad 	disk_attach(&cs->sc_dksc.sc_dkdev);
    599           1.1     elric 
    600           1.1     elric 	/* Try and read the disklabel. */
    601           1.1     elric 	dk_getdisklabel(di, &cs->sc_dksc, 0 /* XXX ? */);
    602           1.1     elric 
    603          1.29      yamt 	/* Discover wedges on this disk. */
    604          1.29      yamt 	dkwedge_discover(&cs->sc_dksc.sc_dkdev);
    605          1.29      yamt 
    606           1.1     elric 	return 0;
    607           1.1     elric 
    608           1.1     elric bail:
    609          1.36  christos 	free(inbuf, M_TEMP);
    610          1.51        ad 	(void)vn_close(vp, FREAD|FWRITE, l->l_cred);
    611           1.1     elric 	return ret;
    612           1.1     elric }
    613           1.1     elric 
    614           1.1     elric /* ARGSUSED */
    615           1.1     elric static int
    616          1.40  christos cgd_ioctl_clr(struct cgd_softc *cs, void *data, struct lwp *l)
    617           1.1     elric {
    618          1.16     elric 	int	s;
    619          1.16     elric 
    620          1.29      yamt 	/* Delete all of our wedges. */
    621          1.29      yamt 	dkwedge_delall(&cs->sc_dksc.sc_dkdev);
    622          1.29      yamt 
    623          1.16     elric 	/* Kill off any queued buffers. */
    624          1.16     elric 	s = splbio();
    625          1.30      yamt 	bufq_drain(cs->sc_dksc.sc_bufq);
    626          1.16     elric 	splx(s);
    627          1.30      yamt 	bufq_free(cs->sc_dksc.sc_bufq);
    628           1.1     elric 
    629          1.51        ad 	(void)vn_close(cs->sc_tvn, FREAD|FWRITE, l->l_cred);
    630           1.1     elric 	cs->sc_cfuncs->cf_destroy(cs->sc_cdata.cf_priv);
    631           1.1     elric 	free(cs->sc_tpath, M_DEVBUF);
    632          1.16     elric 	free(cs->sc_data, M_DEVBUF);
    633          1.16     elric 	cs->sc_data_used = 0;
    634           1.1     elric 	cs->sc_dksc.sc_flags &= ~DKF_INITED;
    635          1.47        ad 	disk_detach(&cs->sc_dksc.sc_dkdev);
    636           1.1     elric 
    637           1.1     elric 	return 0;
    638           1.1     elric }
    639           1.1     elric 
    640           1.1     elric static int
    641      1.53.4.1       riz getsize(struct lwp *l, struct vnode *vp, size_t *size)
    642      1.53.4.1       riz {
    643      1.53.4.1       riz 	struct partinfo dpart;
    644      1.53.4.1       riz 	struct dkwedge_info dkw;
    645      1.53.4.1       riz 	int ret;
    646      1.53.4.1       riz 
    647      1.53.4.1       riz 	if ((ret = VOP_IOCTL(vp, DIOCGWEDGEINFO, &dkw, FREAD,
    648      1.53.4.1       riz 	    l->l_cred)) == 0) {
    649      1.53.4.1       riz 		*size = dkw.dkw_size;
    650      1.53.4.1       riz 		return 0;
    651      1.53.4.1       riz 	}
    652      1.53.4.1       riz 
    653      1.53.4.1       riz 	if ((ret = VOP_IOCTL(vp, DIOCGPART, &dpart, FREAD, l->l_cred)) == 0) {
    654      1.53.4.1       riz 		*size = dpart.part->p_size;
    655      1.53.4.1       riz 		return 0;
    656      1.53.4.1       riz 	}
    657      1.53.4.1       riz 
    658      1.53.4.1       riz 	return ret;
    659      1.53.4.1       riz }
    660      1.53.4.1       riz 
    661      1.53.4.1       riz 
    662      1.53.4.1       riz static int
    663          1.27  drochner cgdinit(struct cgd_softc *cs, const char *cpath, struct vnode *vp,
    664          1.32  christos 	struct lwp *l)
    665           1.1     elric {
    666           1.1     elric 	struct	dk_geom *pdg;
    667           1.1     elric 	struct	vattr va;
    668           1.1     elric 	size_t	size;
    669           1.1     elric 	int	ret;
    670          1.36  christos 	char	*tmppath;
    671           1.1     elric 
    672           1.1     elric 	cs->sc_dksc.sc_size = 0;
    673           1.1     elric 	cs->sc_tvn = vp;
    674          1.36  christos 	cs->sc_tpath = NULL;
    675           1.1     elric 
    676          1.36  christos 	tmppath = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
    677           1.1     elric 	ret = copyinstr(cpath, tmppath, MAXPATHLEN, &cs->sc_tpathlen);
    678           1.1     elric 	if (ret)
    679           1.1     elric 		goto bail;
    680           1.1     elric 	cs->sc_tpath = malloc(cs->sc_tpathlen, M_DEVBUF, M_WAITOK);
    681           1.1     elric 	memcpy(cs->sc_tpath, tmppath, cs->sc_tpathlen);
    682           1.1     elric 
    683          1.48     pooka 	if ((ret = VOP_GETATTR(vp, &va, l->l_cred)) != 0)
    684           1.1     elric 		goto bail;
    685           1.1     elric 
    686           1.1     elric 	cs->sc_tdev = va.va_rdev;
    687           1.1     elric 
    688      1.53.4.1       riz 	if ((ret = getsize(l, vp, &size)) != 0)
    689           1.1     elric 		goto bail;
    690           1.1     elric 
    691           1.1     elric 	if (!size) {
    692           1.1     elric 		ret = ENODEV;
    693           1.1     elric 		goto bail;
    694           1.1     elric 	}
    695           1.1     elric 
    696           1.1     elric 	cs->sc_dksc.sc_size = size;
    697           1.1     elric 
    698           1.1     elric 	/*
    699           1.1     elric 	 * XXX here we should probe the underlying device.  If we
    700           1.1     elric 	 *     are accessing a partition of type RAW_PART, then
    701           1.1     elric 	 *     we should populate our initial geometry with the
    702           1.1     elric 	 *     geometry that we discover from the device.
    703           1.1     elric 	 */
    704           1.1     elric 	pdg = &cs->sc_dksc.sc_geom;
    705           1.1     elric 	pdg->pdg_secsize = DEV_BSIZE;
    706           1.1     elric 	pdg->pdg_ntracks = 1;
    707           1.1     elric 	pdg->pdg_nsectors = 1024 * (1024 / pdg->pdg_secsize);
    708           1.1     elric 	pdg->pdg_ncylinders = cs->sc_dksc.sc_size / pdg->pdg_nsectors;
    709           1.1     elric 
    710           1.1     elric bail:
    711          1.36  christos 	free(tmppath, M_TEMP);
    712           1.1     elric 	if (ret && cs->sc_tpath)
    713           1.1     elric 		free(cs->sc_tpath, M_DEVBUF);
    714           1.1     elric 	return ret;
    715           1.1     elric }
    716           1.1     elric 
    717           1.1     elric /*
    718           1.1     elric  * Our generic cipher entry point.  This takes care of the
    719           1.1     elric  * IV mode and passes off the work to the specific cipher.
    720           1.1     elric  * We implement here the IV method ``encrypted block
    721           1.1     elric  * number''.
    722          1.22     perry  *
    723           1.1     elric  * For the encryption case, we accomplish this by setting
    724           1.1     elric  * up a struct uio where the first iovec of the source is
    725           1.1     elric  * the blocknumber and the first iovec of the dest is a
    726           1.1     elric  * sink.  We then call the cipher with an IV of zero, and
    727           1.1     elric  * the right thing happens.
    728          1.22     perry  *
    729           1.1     elric  * For the decryption case, we use the same basic mechanism
    730           1.1     elric  * for symmetry, but we encrypt the block number in the
    731           1.1     elric  * first iovec.
    732           1.1     elric  *
    733           1.1     elric  * We mainly do this to avoid requiring the definition of
    734           1.1     elric  * an ECB mode.
    735           1.1     elric  *
    736           1.1     elric  * XXXrcd: for now we rely on our own crypto framework defined
    737           1.1     elric  *         in dev/cgd_crypto.c.  This will change when we
    738           1.1     elric  *         get a generic kernel crypto framework.
    739           1.1     elric  */
    740           1.1     elric 
    741           1.1     elric static void
    742          1.25   xtraeme blkno2blkno_buf(char *sbuf, daddr_t blkno)
    743           1.1     elric {
    744           1.1     elric 	int	i;
    745           1.1     elric 
    746           1.1     elric 	/* Set up the blkno in blkno_buf, here we do not care much
    747           1.1     elric 	 * about the final layout of the information as long as we
    748           1.1     elric 	 * can guarantee that each sector will have a different IV
    749           1.1     elric 	 * and that the endianness of the machine will not affect
    750           1.1     elric 	 * the representation that we have chosen.
    751           1.1     elric 	 *
    752           1.1     elric 	 * We choose this representation, because it does not rely
    753           1.1     elric 	 * on the size of buf (which is the blocksize of the cipher),
    754           1.1     elric 	 * but allows daddr_t to grow without breaking existing
    755           1.1     elric 	 * disks.
    756           1.1     elric 	 *
    757           1.1     elric 	 * Note that blkno2blkno_buf does not take a size as input,
    758           1.1     elric 	 * and hence must be called on a pre-zeroed buffer of length
    759           1.1     elric 	 * greater than or equal to sizeof(daddr_t).
    760           1.1     elric 	 */
    761           1.1     elric 	for (i=0; i < sizeof(daddr_t); i++) {
    762          1.25   xtraeme 		*sbuf++ = blkno & 0xff;
    763           1.1     elric 		blkno >>= 8;
    764           1.1     elric 	}
    765           1.1     elric }
    766           1.1     elric 
    767           1.1     elric static void
    768          1.44  christos cgd_cipher(struct cgd_softc *cs, void *dstv, void *srcv,
    769          1.44  christos     size_t len, daddr_t blkno, size_t secsize, int dir)
    770           1.1     elric {
    771          1.44  christos 	char		*dst = dstv;
    772          1.44  christos 	char 		*src = srcv;
    773           1.1     elric 	cfunc_cipher	*cipher = cs->sc_cfuncs->cf_cipher;
    774           1.1     elric 	struct uio	dstuio;
    775           1.1     elric 	struct uio	srcuio;
    776           1.1     elric 	struct iovec	dstiov[2];
    777           1.1     elric 	struct iovec	srciov[2];
    778          1.42  christos 	size_t		blocksize = cs->sc_cdata.cf_blocksize;
    779           1.1     elric 	char		sink[blocksize];
    780           1.1     elric 	char		zero_iv[blocksize];
    781           1.1     elric 	char		blkno_buf[blocksize];
    782           1.1     elric 
    783           1.1     elric 	DPRINTF_FOLLOW(("cgd_cipher() dir=%d\n", dir));
    784           1.1     elric 
    785          1.22     perry 	DIAGCONDPANIC(len % blocksize != 0,
    786           1.1     elric 	    ("cgd_cipher: len %% blocksize != 0"));
    787           1.1     elric 
    788           1.1     elric 	/* ensure that sizeof(daddr_t) <= blocksize (for encblkno IVing) */
    789           1.1     elric 	DIAGCONDPANIC(sizeof(daddr_t) > blocksize,
    790           1.1     elric 	    ("cgd_cipher: sizeof(daddr_t) > blocksize"));
    791           1.1     elric 
    792           1.1     elric 	memset(zero_iv, 0x0, sizeof(zero_iv));
    793           1.1     elric 
    794           1.1     elric 	dstuio.uio_iov = dstiov;
    795           1.1     elric 	dstuio.uio_iovcnt = 2;
    796           1.1     elric 
    797           1.1     elric 	srcuio.uio_iov = srciov;
    798           1.1     elric 	srcuio.uio_iovcnt = 2;
    799           1.1     elric 
    800           1.1     elric 	dstiov[0].iov_base = sink;
    801           1.1     elric 	dstiov[0].iov_len  = blocksize;
    802           1.1     elric 	srciov[0].iov_base = blkno_buf;
    803           1.1     elric 	srciov[0].iov_len  = blocksize;
    804           1.1     elric 	dstiov[1].iov_len  = secsize;
    805           1.1     elric 	srciov[1].iov_len  = secsize;
    806           1.1     elric 
    807           1.1     elric 	for (; len > 0; len -= secsize) {
    808           1.1     elric 		dstiov[1].iov_base = dst;
    809           1.1     elric 		srciov[1].iov_base = src;
    810           1.1     elric 
    811           1.1     elric 		memset(blkno_buf, 0x0, sizeof(blkno_buf));
    812           1.1     elric 		blkno2blkno_buf(blkno_buf, blkno);
    813           1.1     elric 		if (dir == CGD_CIPHER_DECRYPT) {
    814           1.1     elric 			dstuio.uio_iovcnt = 1;
    815           1.1     elric 			srcuio.uio_iovcnt = 1;
    816           1.1     elric 			IFDEBUG(CGDB_CRYPTO, hexprint("step 0: blkno_buf",
    817           1.1     elric 			    blkno_buf, sizeof(blkno_buf)));
    818           1.1     elric 			cipher(cs->sc_cdata.cf_priv, &dstuio, &srcuio,
    819           1.1     elric 			    zero_iv, CGD_CIPHER_ENCRYPT);
    820           1.1     elric 			memcpy(blkno_buf, sink, blocksize);
    821           1.1     elric 			dstuio.uio_iovcnt = 2;
    822           1.1     elric 			srcuio.uio_iovcnt = 2;
    823           1.1     elric 		}
    824           1.1     elric 
    825           1.1     elric 		IFDEBUG(CGDB_CRYPTO, hexprint("step 1: blkno_buf",
    826           1.1     elric 		    blkno_buf, sizeof(blkno_buf)));
    827           1.1     elric 		cipher(cs->sc_cdata.cf_priv, &dstuio, &srcuio, zero_iv, dir);
    828           1.1     elric 		IFDEBUG(CGDB_CRYPTO, hexprint("step 2: sink",
    829           1.1     elric 		    sink, sizeof(sink)));
    830           1.1     elric 
    831           1.1     elric 		dst += secsize;
    832           1.1     elric 		src += secsize;
    833           1.1     elric 		blkno++;
    834           1.1     elric 	}
    835           1.1     elric }
    836           1.1     elric 
    837           1.1     elric #ifdef DEBUG
    838           1.1     elric static void
    839          1.26  drochner hexprint(const char *start, void *buf, int len)
    840           1.1     elric {
    841           1.1     elric 	char	*c = buf;
    842           1.1     elric 
    843           1.1     elric 	DIAGCONDPANIC(len < 0, ("hexprint: called with len < 0"));
    844           1.1     elric 	printf("%s: len=%06d 0x", start, len);
    845           1.1     elric 	while (len--)
    846          1.43    cbiere 		printf("%02x", (unsigned char) *c++);
    847           1.1     elric }
    848           1.1     elric #endif
    849