1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 1996, 2013 Oracle and/or its affiliates.  All rights reserved.
5  */
6 /*
7  * Copyright (c) 1990, 1993, 1994, 1995, 1996
8  *	Keith Bostic.  All rights reserved.
9  */
10 /*
11  * Copyright (c) 1990, 1993, 1994, 1995
12  *	The Regents of the University of California.  All rights reserved.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  * $Id$
39  */
40 
41 #include "db_config.h"
42 
43 #include "db_int.h"
44 #include "dbinc/crypto.h"
45 #include "dbinc/hmac.h"
46 #include "dbinc/db_page.h"
47 #include "dbinc/db_swap.h"
48 #include "dbinc/btree.h"
49 #include "dbinc/hash.h"
50 #include "dbinc/heap.h"
51 #include "dbinc/qam.h"
52 
53 /*
54  * __db_pgin --
55  *	Primary page-swap routine.
56  *
57  * PUBLIC: int __db_pgin __P((DB_ENV *, db_pgno_t, void *, DBT *));
58  */
59 int
__db_pgin(dbenv,pg,pp,cookie)60 __db_pgin(dbenv, pg, pp, cookie)
61 	DB_ENV *dbenv;
62 	db_pgno_t pg;
63 	void *pp;
64 	DBT *cookie;
65 {
66 	DB dummydb, *dbp;
67 	DB_CIPHER *db_cipher;
68 	DB_LSN not_used;
69 	DB_PGINFO *pginfo;
70 	ENV *env;
71 	PAGE *pagep;
72 	size_t sum_len;
73 	int is_hmac, ret;
74 	u_int8_t *chksum;
75 
76 	pginfo = (DB_PGINFO *)cookie->data;
77 	env = dbenv->env;
78 	pagep = (PAGE *)pp;
79 
80 	ret = is_hmac = 0;
81 	chksum = NULL;
82 	memset(&dummydb, 0, sizeof(DB));
83 	dbp = &dummydb;
84 	dbp->dbenv = dbenv;
85 	dbp->env = env;
86 	dbp->flags = pginfo->flags;
87 	dbp->pgsize = pginfo->db_pagesize;
88 	db_cipher = env->crypto_handle;
89 	switch (pagep->type) {
90 	case P_HASHMETA:
91 	case P_HEAPMETA:
92 	case P_BTREEMETA:
93 	case P_QAMMETA:
94 		/*
95 		 * If checksumming is set on the meta-page, we must set
96 		 * it in the dbp.
97 		 */
98 		if (FLD_ISSET(((DBMETA *)pp)->metaflags, DBMETA_CHKSUM))
99 			F_SET(dbp, DB_AM_CHKSUM);
100 		else
101 			F_CLR(dbp, DB_AM_CHKSUM);
102 		if (((DBMETA *)pp)->encrypt_alg != 0 ||
103 		    F_ISSET(dbp, DB_AM_ENCRYPT))
104 			is_hmac = 1;
105 		/*
106 		 * !!!
107 		 * For all meta pages it is required that the chksum
108 		 * be at the same location.  Use BTMETA to get to it
109 		 * for any meta type.
110 		 */
111 		chksum = ((BTMETA *)pp)->chksum;
112 		sum_len = DBMETASIZE;
113 		break;
114 	case P_INVALID:
115 		/*
116 		 * We assume that we've read a file hole if we have
117 		 * a zero LSN, zero page number and P_INVALID.  Otherwise
118 		 * we have an invalid page that might contain real data.
119 		 */
120 		if (IS_ZERO_LSN(LSN(pagep)) && pagep->pgno == PGNO_INVALID) {
121 			sum_len = 0;
122 			break;
123 		}
124 		/* FALLTHROUGH */
125 	default:
126 		chksum = P_CHKSUM(dbp, pagep);
127 		sum_len = pginfo->db_pagesize;
128 		/*
129 		 * If we are reading in a non-meta page, then if we have
130 		 * a db_cipher then we are using hmac.
131 		 */
132 		is_hmac = CRYPTO_ON(env) ? 1 : 0;
133 		break;
134 	}
135 
136 	/*
137 	 * We expect a checksum error if there was a configuration problem.
138 	 * If there is no configuration problem and we don't get a match,
139 	 * it's fatal: panic the system.
140 	 */
141 	if (F_ISSET(dbp, DB_AM_CHKSUM) && sum_len != 0) {
142 		if (F_ISSET(dbp, DB_AM_SWAP) && is_hmac == 0)
143 			P_32_SWAP(chksum);
144 		switch (ret = __db_check_chksum(
145 		    env, NULL, db_cipher, chksum, pp, sum_len, is_hmac)) {
146 		case 0:
147 			break;
148 		case -1:
149 			if (DBENV_LOGGING(env))
150 				(void)__db_cksum_log(
151 				    env, NULL, &not_used, DB_FLUSH);
152 			__db_errx(env, DB_STR_A("0684",
153 	    "checksum error: page %lu: catastrophic recovery required",
154 			    "%lu"), (u_long)pg);
155 			return (__env_panic(env, DB_RUNRECOVERY));
156 		default:
157 			return (ret);
158 		}
159 	}
160 	if ((ret = __db_decrypt_pg(env, dbp, pagep)) != 0)
161 		return (ret);
162 	switch (pagep->type) {
163 	case P_INVALID:
164 		if (pginfo->type == DB_QUEUE)
165 			return (__qam_pgin_out(env, pg, pp, cookie));
166 		else if (pginfo->type == DB_HEAP)
167 			return (__heap_pgin(dbp, pg, pp, cookie));
168 		/*
169 		 * This page is either newly allocated from the end of the
170 		 * file, or from the free list, or it is an as-yet unwritten
171 		 * hash bucket page. In this last case it needs to be
172 		 * initialized, but never byte-swapped. Otherwise the header
173 		 * may need swapping. It will not be a metadata page, so the
174 		 * byte swapping code of __ham_pgin is adequate.  If hash
175 		 * is not configured fall back to btree swapping.
176 		 */
177 #ifdef HAVE_HASH
178 		return (__ham_pgin(dbp, pg, pp, cookie));
179 #else
180 		return (__bam_pgin(dbp, pg, pp, cookie));
181 #endif
182 		/* NOTREACHED. */
183 		break;
184 	case P_HASH_UNSORTED:
185 	case P_HASH:
186 	case P_HASHMETA:
187 		return (__ham_pgin(dbp, pg, pp, cookie));
188 	case P_HEAP:
189 	case P_HEAPMETA:
190 	case P_IHEAP:
191 		return (__heap_pgin(dbp, pg, pp, cookie));
192 	case P_BTREEMETA:
193 	case P_IBTREE:
194 	case P_IRECNO:
195 	case P_LBTREE:
196 	case P_LDUP:
197 	case P_LRECNO:
198 	case P_OVERFLOW:
199 		return (__bam_pgin(dbp, pg, pp, cookie));
200 	case P_QAMMETA:
201 	case P_QAMDATA:
202 		return (__qam_pgin_out(env, pg, pp, cookie));
203 	default:
204 		break;
205 	}
206 	return (__db_pgfmt(env, pg));
207 }
208 
209 /*
210  * __db_pgout --
211  *	Primary page-swap routine.
212  *
213  * PUBLIC: int __db_pgout __P((DB_ENV *, db_pgno_t, void *, DBT *));
214  */
215 int
__db_pgout(dbenv,pg,pp,cookie)216 __db_pgout(dbenv, pg, pp, cookie)
217 	DB_ENV *dbenv;
218 	db_pgno_t pg;
219 	void *pp;
220 	DBT *cookie;
221 {
222 	DB dummydb, *dbp;
223 	DB_PGINFO *pginfo;
224 	ENV *env;
225 	PAGE *pagep;
226 	int ret;
227 
228 	pginfo = (DB_PGINFO *)cookie->data;
229 	env = dbenv->env;
230 	pagep = (PAGE *)pp;
231 
232 	memset(&dummydb, 0, sizeof(DB));
233 	dbp = &dummydb;
234 	dbp->dbenv = dbenv;
235 	dbp->env = env;
236 	dbp->flags = pginfo->flags;
237 	dbp->pgsize = pginfo->db_pagesize;
238 	ret = 0;
239 	switch (pagep->type) {
240 	case P_INVALID:
241 		switch (pginfo->type) {
242 		case DB_QUEUE:
243 			ret = __qam_pgin_out(env, pg, pp, cookie);
244 			break;
245 #ifdef HAVE_HASH
246 		case DB_HASH:
247 			ret = __ham_pgout(dbp, pg, pp, cookie);
248 			break;
249 #endif
250 #ifdef HAVE_HEAP
251 		case DB_HEAP:
252 			ret = __heap_pgout(dbp, pg, pp, cookie);
253 			break;
254 #endif
255 		case DB_BTREE:
256 		case DB_RECNO:
257 			ret = __bam_pgout(dbp, pg, pp, cookie);
258 			break;
259 		default:
260 			return (__db_pgfmt(env, pg));
261 		}
262 		break;
263 	case P_HASH:
264 	case P_HASH_UNSORTED:
265 		/*
266 		 * Support pgout of unsorted hash pages - since online
267 		 * replication upgrade can cause pages of this type to be
268 		 * written out.
269 		 *
270 		 * FALLTHROUGH
271 		 */
272 	case P_HASHMETA:
273 		ret = __ham_pgout(dbp, pg, pp, cookie);
274 		break;
275 	case P_HEAP:
276 	case P_HEAPMETA:
277 	case P_IHEAP:
278 		ret = __heap_pgout(dbp, pg, pp, cookie);
279 		break;
280 	case P_BTREEMETA:
281 	case P_IBTREE:
282 	case P_IRECNO:
283 	case P_LBTREE:
284 	case P_LDUP:
285 	case P_LRECNO:
286 	case P_OVERFLOW:
287 		ret = __bam_pgout(dbp, pg, pp, cookie);
288 		break;
289 	case P_QAMMETA:
290 	case P_QAMDATA:
291 		ret = __qam_pgin_out(env, pg, pp, cookie);
292 		break;
293 	default:
294 		return (__db_pgfmt(env, pg));
295 	}
296 	if (ret)
297 		return (ret);
298 
299 	return (__db_encrypt_and_checksum_pg(env, dbp, pagep));
300 }
301 
302 /*
303  * __db_decrypt_pg --
304  *      Utility function to decrypt a db page.
305  *
306  * PUBLIC: int __db_decrypt_pg __P((ENV *, DB *, PAGE *));
307  */
308 int
__db_decrypt_pg(env,dbp,pagep)309 __db_decrypt_pg (env, dbp, pagep)
310 	ENV *env;
311 	DB *dbp;
312 	PAGE *pagep;
313 {
314 	DB_CIPHER *db_cipher;
315 	size_t pg_len, pg_off;
316 	u_int8_t *iv;
317 	int ret;
318 
319 	db_cipher = env->crypto_handle;
320 	ret = 0;
321 	iv = NULL;
322 	if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
323 		DB_ASSERT(env, db_cipher != NULL);
324 		DB_ASSERT(env, F_ISSET(dbp, DB_AM_CHKSUM));
325 
326 		pg_off = P_OVERHEAD(dbp);
327 		DB_ASSERT(env, db_cipher->adj_size(pg_off) == 0);
328 
329 		switch (pagep->type) {
330 		case P_HASHMETA:
331 		case P_HEAPMETA:
332 		case P_BTREEMETA:
333 		case P_QAMMETA:
334 			/*
335 			 * !!!
336 			 * For all meta pages it is required that the iv
337 			 * be at the same location.  Use BTMETA to get to it
338 			 * for any meta type.
339 			 */
340 			iv = ((BTMETA *)pagep)->iv;
341 			pg_len = DBMETASIZE;
342 			break;
343 		case P_INVALID:
344 			if (IS_ZERO_LSN(LSN(pagep)) &&
345 			    pagep->pgno == PGNO_INVALID) {
346 				pg_len = 0;
347 				break;
348 			}
349 			/* FALLTHROUGH */
350 		default:
351 			iv = P_IV(dbp, pagep);
352 			pg_len = dbp->pgsize;
353 			break;
354 		}
355 		if (pg_len != 0)
356 			ret = db_cipher->decrypt(env, db_cipher->data,
357 			    iv, ((u_int8_t *)pagep) + pg_off,
358 			    pg_len - pg_off);
359 	}
360 	return (ret);
361 }
362 
363 /*
364  * __db_encrypt_and_checksum_pg --
365  *	Utility function to encrypt and checksum a db page.
366  *
367  * PUBLIC: int __db_encrypt_and_checksum_pg
368  * PUBLIC:     __P((ENV *, DB *, PAGE *));
369  */
370 int
__db_encrypt_and_checksum_pg(env,dbp,pagep)371 __db_encrypt_and_checksum_pg (env, dbp, pagep)
372 	ENV *env;
373 	DB *dbp;
374 	PAGE *pagep;
375 {
376 	DB_CIPHER *db_cipher;
377 	int ret;
378 	size_t pg_off, pg_len, sum_len;
379 	u_int8_t *chksum, *iv, *key;
380 
381 	chksum = iv = key = NULL;
382 	db_cipher = env->crypto_handle;
383 
384 	if (F_ISSET(dbp, DB_AM_ENCRYPT)) {
385 		DB_ASSERT(env, db_cipher != NULL);
386 		DB_ASSERT(env, F_ISSET(dbp, DB_AM_CHKSUM));
387 
388 		pg_off = P_OVERHEAD(dbp);
389 		DB_ASSERT(env, db_cipher->adj_size(pg_off) == 0);
390 
391 		key = db_cipher->mac_key;
392 
393 		switch (pagep->type) {
394 		case P_HASHMETA:
395 		case P_HEAPMETA:
396 		case P_BTREEMETA:
397 		case P_QAMMETA:
398 			/*
399 			 * !!!
400 			 * For all meta pages it is required that the iv
401 			 * be at the same location.  Use BTMETA to get to it
402 			 * for any meta type.
403 			 */
404 			iv = ((BTMETA *)pagep)->iv;
405 			pg_len = DBMETASIZE;
406 			break;
407 		default:
408 			iv = P_IV(dbp, pagep);
409 			pg_len = dbp->pgsize;
410 			break;
411 		}
412 		if ((ret = db_cipher->encrypt(env, db_cipher->data,
413 		    iv, ((u_int8_t *)pagep) + pg_off, pg_len - pg_off)) != 0)
414 			return (ret);
415 	}
416 	if (F_ISSET(dbp, DB_AM_CHKSUM)) {
417 		switch (pagep->type) {
418 		case P_HASHMETA:
419 		case P_HEAPMETA:
420 		case P_BTREEMETA:
421 		case P_QAMMETA:
422 			/*
423 			 * !!!
424 			 * For all meta pages it is required that the chksum
425 			 * be at the same location.  Use BTMETA to get to it
426 			 * for any meta type.
427 			 */
428 			chksum = ((BTMETA *)pagep)->chksum;
429 			sum_len = DBMETASIZE;
430 			break;
431 		default:
432 			chksum = P_CHKSUM(dbp, pagep);
433 			sum_len = dbp->pgsize;
434 			break;
435 		}
436 		__db_chksum(NULL, (u_int8_t *)pagep, sum_len, key, chksum);
437 		if (F_ISSET(dbp, DB_AM_SWAP) && !F_ISSET(dbp, DB_AM_ENCRYPT))
438 			 P_32_SWAP(chksum);
439 	}
440 	return (0);
441 }
442 
443 /*
444  * __db_metaswap --
445  *	Byteswap the common part of the meta-data page.
446  *
447  * PUBLIC: void __db_metaswap __P((PAGE *));
448  */
449 void
__db_metaswap(pg)450 __db_metaswap(pg)
451 	PAGE *pg;
452 {
453 	u_int8_t *p;
454 
455 	p = (u_int8_t *)pg;
456 
457 	/* Swap the meta-data information. */
458 	SWAP32(p);	/* lsn.file */
459 	SWAP32(p);	/* lsn.offset */
460 	SWAP32(p);	/* pgno */
461 	SWAP32(p);	/* magic */
462 	SWAP32(p);	/* version */
463 	SWAP32(p);	/* pagesize */
464 	p += 4;		/* unused, page type, unused, unused */
465 	SWAP32(p);	/* free */
466 	SWAP32(p);	/* alloc_lsn part 1 */
467 	SWAP32(p);	/* alloc_lsn part 2 */
468 	SWAP32(p);	/* cached key count */
469 	SWAP32(p);	/* cached record count */
470 	SWAP32(p);	/* flags */
471 }
472 
473 /*
474  * __db_byteswap --
475  *	Byteswap an ordinary database page.
476  *
477  * PUBLIC: int __db_byteswap
478  * PUBLIC:         __P((DB *, db_pgno_t, PAGE *, size_t, int));
479  */
480 int
__db_byteswap(dbp,pg,h,pagesize,pgin)481 __db_byteswap(dbp, pg, h, pagesize, pgin)
482 	DB *dbp;
483 	db_pgno_t pg;
484 	PAGE *h;
485 	size_t pagesize;
486 	int pgin;
487 {
488 	ENV *env;
489 	BINTERNAL *bi;
490 	BKEYDATA *bk;
491 	BOVERFLOW *bo;
492 	RINTERNAL *ri;
493 	db_indx_t i, *inp, len, tmp;
494 	u_int8_t *end, *p, *pgend;
495 
496 	if (pagesize == 0)
497 		return (0);
498 
499 	if (pgin) {
500 		M_32_SWAP(h->lsn.file);
501 		M_32_SWAP(h->lsn.offset);
502 		M_32_SWAP(h->pgno);
503 		M_32_SWAP(h->prev_pgno);
504 		M_32_SWAP(h->next_pgno);
505 		M_16_SWAP(h->entries);
506 		M_16_SWAP(h->hf_offset);
507 	}
508 
509 	if (dbp == NULL)
510 		return (0);
511 	env = dbp->env;
512 
513 	pgend = (u_int8_t *)h + pagesize;
514 
515 	inp = P_INP(dbp, h);
516 	if ((u_int8_t *)inp >= pgend)
517 		goto out;
518 
519 	switch (TYPE(h)) {
520 	case P_HASH_UNSORTED:
521 	case P_HASH:
522 		for (i = 0; i < NUM_ENT(h); i++) {
523 			if (pgin)
524 				M_16_SWAP(inp[i]);
525 
526 			if (P_ENTRY(dbp, h, i) >= pgend)
527 				continue;
528 
529 			switch (HPAGE_TYPE(dbp, h, i)) {
530 			case H_KEYDATA:
531 				break;
532 			case H_DUPLICATE:
533 				len = LEN_HKEYDATA(dbp, h, pagesize, i);
534 				p = HKEYDATA_DATA(P_ENTRY(dbp, h, i));
535 				for (end = p + len; p < end;) {
536 					if (pgin) {
537 						P_16_SWAP(p);
538 						memcpy(&tmp,
539 						    p, sizeof(db_indx_t));
540 						p += sizeof(db_indx_t);
541 					} else {
542 						memcpy(&tmp,
543 						    p, sizeof(db_indx_t));
544 						SWAP16(p);
545 					}
546 					p += tmp;
547 					SWAP16(p);
548 				}
549 				break;
550 			case H_OFFDUP:
551 				p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i));
552 				SWAP32(p);			/* pgno */
553 				break;
554 			case H_OFFPAGE:
555 				p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i));
556 				SWAP32(p);			/* pgno */
557 				SWAP32(p);			/* tlen */
558 				break;
559 			default:
560 				return (__db_pgfmt(env, pg));
561 			}
562 
563 		}
564 
565 		/*
566 		 * The offsets in the inp array are used to determine
567 		 * the size of entries on a page; therefore they
568 		 * cannot be converted until we've done all the
569 		 * entries.
570 		 */
571 		if (!pgin)
572 			for (i = 0; i < NUM_ENT(h); i++)
573 				M_16_SWAP(inp[i]);
574 		break;
575 	case P_LBTREE:
576 	case P_LDUP:
577 	case P_LRECNO:
578 		for (i = 0; i < NUM_ENT(h); i++) {
579 			if (pgin)
580 				M_16_SWAP(inp[i]);
581 
582 			/*
583 			 * In the case of on-page duplicates, key information
584 			 * should only be swapped once.
585 			 */
586 			if (h->type == P_LBTREE && i > 1) {
587 				if (pgin) {
588 					if (inp[i] == inp[i - 2])
589 						continue;
590 				} else {
591 					M_16_SWAP(inp[i]);
592 					if (inp[i] == inp[i - 2])
593 						continue;
594 					M_16_SWAP(inp[i]);
595 				}
596 			}
597 
598 			bk = GET_BKEYDATA(dbp, h, i);
599 			if ((u_int8_t *)bk >= pgend)
600 				continue;
601 			switch (B_TYPE(bk->type)) {
602 			case B_KEYDATA:
603 				M_16_SWAP(bk->len);
604 				break;
605 			case B_DUPLICATE:
606 			case B_OVERFLOW:
607 				bo = (BOVERFLOW *)bk;
608 				M_32_SWAP(bo->pgno);
609 				M_32_SWAP(bo->tlen);
610 				break;
611 			default:
612 				return (__db_pgfmt(env, pg));
613 			}
614 
615 			if (!pgin)
616 				M_16_SWAP(inp[i]);
617 		}
618 		break;
619 	case P_IBTREE:
620 		for (i = 0; i < NUM_ENT(h); i++) {
621 			if (pgin)
622 				M_16_SWAP(inp[i]);
623 
624 			bi = GET_BINTERNAL(dbp, h, i);
625 			if ((u_int8_t *)bi >= pgend)
626 				continue;
627 
628 			M_16_SWAP(bi->len);
629 			M_32_SWAP(bi->pgno);
630 			M_32_SWAP(bi->nrecs);
631 
632 			switch (B_TYPE(bi->type)) {
633 			case B_KEYDATA:
634 				break;
635 			case B_DUPLICATE:
636 			case B_OVERFLOW:
637 				bo = (BOVERFLOW *)bi->data;
638 				M_32_SWAP(bo->pgno);
639 				M_32_SWAP(bo->tlen);
640 				break;
641 			default:
642 				return (__db_pgfmt(env, pg));
643 			}
644 
645 			if (!pgin)
646 				M_16_SWAP(inp[i]);
647 		}
648 		break;
649 	case P_IRECNO:
650 		for (i = 0; i < NUM_ENT(h); i++) {
651 			if (pgin)
652 				M_16_SWAP(inp[i]);
653 
654 			ri = GET_RINTERNAL(dbp, h, i);
655 			if ((u_int8_t *)ri >= pgend)
656 				continue;
657 
658 			M_32_SWAP(ri->pgno);
659 			M_32_SWAP(ri->nrecs);
660 
661 			if (!pgin)
662 				M_16_SWAP(inp[i]);
663 		}
664 		break;
665 	case P_HEAP:
666 	case P_IHEAP:
667 	case P_INVALID:
668 	case P_OVERFLOW:
669 	case P_QAMDATA:
670 		/* Nothing to do. */
671 		break;
672 	default:
673 		return (__db_pgfmt(env, pg));
674 	}
675 
676 out:	if (!pgin) {
677 		/* Swap the header information. */
678 		M_32_SWAP(h->lsn.file);
679 		M_32_SWAP(h->lsn.offset);
680 		M_32_SWAP(h->pgno);
681 		M_32_SWAP(h->prev_pgno);
682 		M_32_SWAP(h->next_pgno);
683 		M_16_SWAP(h->entries);
684 		M_16_SWAP(h->hf_offset);
685 	}
686 	return (0);
687 }
688 
689 /*
690  * __db_pageswap --
691  *	Byteswap any database page.  Normally, the page to be swapped will be
692  *	referenced by the "pp" argument and the pdata argument will be NULL.
693  *	This function is also called by automatically generated log functions,
694  *	where the page may be split into separate header and data parts.  In
695  *	that case, pdata is not NULL we reconsitute
696  *
697  * PUBLIC: int __db_pageswap
698  * PUBLIC:         __P((ENV *, DB *, void *, size_t, DBT *, int));
699  */
700 int
__db_pageswap(env,dbp,pp,len,pdata,pgin)701 __db_pageswap(env, dbp, pp, len, pdata, pgin)
702 	ENV *env;
703 	DB *dbp;
704 	void *pp;
705 	size_t len;
706 	DBT *pdata;
707 	int pgin;
708 {
709 	db_pgno_t pg;
710 	size_t pgsize;
711 	void *pgcopy;
712 	int ret;
713 	u_int16_t hoffset;
714 
715 	switch (TYPE(pp)) {
716 	case P_BTREEMETA:
717 		return (__bam_mswap(env, pp));
718 
719 	case P_HASHMETA:
720 		return (__ham_mswap(env, pp));
721 
722 	case P_QAMMETA:
723 		return (__qam_mswap(env, pp));
724 
725 	case P_INVALID:
726 	case P_OVERFLOW:
727 	case P_QAMDATA:
728 		/*
729 		 * We may have been passed an invalid page, or a queue data
730 		 * page, or an overflow page where fields like hoffset have a
731 		 * special meaning.  In that case, no swapping of the page data
732 		 * is required, just the fields in the page header.
733 		 */
734 		pdata = NULL;
735 		break;
736 
737 	default:
738 		break;
739 	}
740 
741 	if (pgin) {
742 		P_32_COPYSWAP(&PGNO(pp), &pg);
743 		P_16_COPYSWAP(&HOFFSET(pp), &hoffset);
744 	} else {
745 		pg = PGNO(pp);
746 		hoffset = HOFFSET(pp);
747 	}
748 
749 	if (pdata == NULL)
750 		ret = __db_byteswap(dbp, pg, (PAGE *)pp, len, pgin);
751 	else {
752 		pgsize = hoffset + pdata->size;
753 		if ((ret = __os_malloc(env, pgsize, &pgcopy)) != 0)
754 			return (ret);
755 		memset(pgcopy, 0, pgsize);
756 		memcpy(pgcopy, pp, len);
757 		memcpy((u_int8_t *)pgcopy + hoffset, pdata->data, pdata->size);
758 
759 		ret = __db_byteswap(dbp, pg, (PAGE *)pgcopy, pgsize, pgin);
760 		memcpy(pp, pgcopy, len);
761 
762 		/*
763 		 * If we are swapping data to be written to the log, we can't
764 		 * overwrite the buffer that was passed in: it may be a pointer
765 		 * into a page in cache.  We set DB_DBT_APPMALLOC here so that
766 		 * the calling code can free the memory we allocate here.
767 		 */
768 		if (!pgin) {
769 			if ((ret =
770 			    __os_malloc(env, pdata->size, &pdata->data)) != 0) {
771 				__os_free(env, pgcopy);
772 				return (ret);
773 			}
774 			F_SET(pdata, DB_DBT_APPMALLOC);
775 		}
776 		memcpy(pdata->data, (u_int8_t *)pgcopy + hoffset, pdata->size);
777 		__os_free(env, pgcopy);
778 	}
779 
780 	return (ret);
781 }
782 
783 /*
784  * __db_recordswap --
785  *	Byteswap any database record.
786  *
787  * PUBLIC: void __db_recordswap __P((u_int32_t,
788  * PUBLIC:     u_int32_t, void *, void *, u_int32_t));
789  */
790 void
__db_recordswap(op,size,hdr,data,pgin)791 __db_recordswap(op, size, hdr, data, pgin)
792 	u_int32_t op;
793 	u_int32_t size;
794 	void *hdr, *data;
795 	u_int32_t pgin;
796 {
797 	BKEYDATA *bk;
798 	BOVERFLOW *bo;
799 	BINTERNAL *bi;
800 	RINTERNAL *ri;
801 	db_indx_t tmp;
802 	u_int8_t *p, *end;
803 
804 	if (size == 0)
805 		return;
806 	switch (OP_PAGE_GET(op)) {
807 	case P_LDUP:
808 	case P_LBTREE:
809 	case P_LRECNO:
810 		bk = (BKEYDATA *)hdr;
811 		switch (B_TYPE(bk->type)) {
812 		case B_KEYDATA:
813 			M_16_SWAP(bk->len);
814 			break;
815 		case B_DUPLICATE:
816 		case B_OVERFLOW:
817 			bo = (BOVERFLOW *)hdr;
818 			M_32_SWAP(bo->pgno);
819 			M_32_SWAP(bo->tlen);
820 			break;
821 		default:
822 			DB_ASSERT(NULL, bk->type != bk->type);
823 		}
824 		break;
825 	case P_IBTREE:
826 		bi = (BINTERNAL *)hdr;
827 		M_16_SWAP(bi->len);
828 		M_32_SWAP(bi->pgno);
829 		M_32_SWAP(bi->nrecs);
830 		if (B_TYPE(bi->type) == B_OVERFLOW) {
831 			if (data == NULL) {
832 				DB_ASSERT(NULL,
833 				    size == BINTERNAL_SIZE(BOVERFLOW_SIZE));
834 				bo = (BOVERFLOW *)bi->data;
835 			} else
836 				bo = (BOVERFLOW *)data;
837 			M_32_SWAP(bo->pgno);
838 		}
839 		break;
840 	case P_IRECNO:
841 		ri = (RINTERNAL *)hdr;
842 		M_32_SWAP(ri->pgno);
843 		M_32_SWAP(ri->nrecs);
844 		break;
845 	case P_OVERFLOW:
846 		break;
847 	case P_HASH:
848 	case P_HASH_UNSORTED:
849 		switch (OP_MODE_GET(op)) {
850 		/* KEYDATA and DUPLICATE records do not include the header. */
851 		case H_KEYDATA:
852 			break;
853 		case H_DUPLICATE:
854 			p = (u_int8_t *)hdr;
855 			for (end = p + size; p < end;) {
856 				if (pgin) {
857 					P_16_SWAP(p);
858 					memcpy(&tmp,
859 					    p, sizeof(db_indx_t));
860 					p += sizeof(db_indx_t);
861 				} else {
862 					memcpy(&tmp,
863 					    p, sizeof(db_indx_t));
864 					SWAP16(p);
865 				}
866 				p += tmp;
867 				SWAP16(p);
868 			}
869 			break;
870 		/* These two record types include the full header. */
871 		case H_OFFDUP:
872 			p = (u_int8_t *)hdr;
873 			p += SSZ(HOFFPAGE, pgno);
874 			SWAP32(p);			/* pgno */
875 			break;
876 		case H_OFFPAGE:
877 			p = (u_int8_t *)hdr;
878 			p += SSZ(HOFFPAGE, pgno);
879 			SWAP32(p);			/* pgno */
880 			SWAP32(p);			/* tlen */
881 			break;
882 		default:
883 			DB_ASSERT(NULL, op != op);
884 		}
885 		break;
886 
887 	default:
888 		DB_ASSERT(NULL, op != op);
889 	}
890 }
891