From 2a1b27122957ed49e0243f383563a369ae3c910c Mon Sep 17 00:00:00 2001
From: Darwin
Date: Wed, 29 Jul 2020 21:28:34 +0000
Subject: [PATCH] xnu-6153.141.1
Imported from https://opensource.apple.com/tarballs/xnu/xnu-6153.141.1.tar.gz
---
bsd/kern/kern_aio.c | 397 +-
bsd/kern/kern_exec.c | 8 +
bsd/kern/kern_exit.c | 29 +
bsd/kern/kern_proc.c | 13 +
bsd/kern/kern_sysctl.c | 2 +-
bsd/kern/mach_loader.c | 9 +-
bsd/kern/uipc_usrreq.c | 5 +
bsd/net/content_filter.c | 4 +-
bsd/net/if.c | 4 +-
bsd/net/if_gif.c | 10 +-
bsd/net/if_stf.c | 5 +-
bsd/net/kpi_interface.c | 1 +
bsd/net/necp.c | 177 +-
bsd/net/necp.h | 2 +
bsd/netinet/flow_divert.c | 26 +-
bsd/netinet/in.c | 29 +-
bsd/netinet/ip_input.c | 488 ++-
bsd/netinet/ip_var.h | 4 +-
bsd/netinet/kpi_ipfilter.c | 4 +-
bsd/netinet6/ah_input.c | 23 +-
bsd/netinet6/dest6.c | 36 +-
bsd/netinet6/esp_input.c | 2 +
bsd/netinet6/frag6.c | 41 +-
bsd/netinet6/icmp6.c | 27 +-
bsd/netinet6/in6.c | 327 +-
bsd/netinet6/in6_ifattach.c | 63 +-
bsd/netinet6/in6_pcb.c | 6 +-
bsd/netinet6/in6_src.c | 4 +-
bsd/netinet6/in6_var.h | 35 +-
bsd/netinet6/ip6_input.c | 524 ++-
bsd/netinet6/ip6_output.c | 4 +-
bsd/netinet6/ip6_var.h | 6 +-
bsd/netinet6/mld6.c | 13 +-
bsd/netinet6/nd6.c | 67 +-
bsd/netinet6/nd6_nbr.c | 21 +-
bsd/netinet6/nd6_rtr.c | 8 +-
bsd/netinet6/route6.c | 13 +-
bsd/netkey/key.c | 219 +-
bsd/nfs/nfs_socket.c | 26 +-
bsd/sys/proc.h | 1 +
bsd/sys/reason.h | 3 +-
bsd/sys/vnode.h | 18 +
bsd/sys/vnode_internal.h | 2 +-
bsd/vfs/vfs_cache.c | 18 +-
bsd/vfs/vfs_subr.c | 44 +-
config/IOKit.exports | 3 +
config/MasterVersion | 2 +-
config/Private.exports | 1 +
iokit/DriverKit/IODMACommand.iig | 191 +
iokit/DriverKit/IOInterruptDispatchSource.iig | 21 +
iokit/IOKit/IODMACommand.h | 3 +-
iokit/IOKit/IOKitKeys.h | 3 +
iokit/IOKit/IOService.h | 1 +
iokit/Kernel/IOService.cpp | 2 +
iokit/Kernel/IOUserServer.cpp | 281 +-
iokit/conf/files | 1 +
osfmk/arm/pmap.c | 13 +-
osfmk/arm/status.c | 4 +
osfmk/arm64/cswitch.s | 17 +-
osfmk/arm64/exception_asm.h | 13 +-
osfmk/arm64/locore.s | 118 +-
osfmk/arm64/pcb.c | 15 +-
osfmk/arm64/proc_reg.h | 14 +
osfmk/arm64/sleh.c | 76 +-
osfmk/arm64/status.c | 10 +-
osfmk/i386/acpi.c | 4 +-
osfmk/i386/bsd_i386.c | 44 +-
osfmk/i386/cpuid.c | 4 +
osfmk/i386/cpuid.h | 1 +
osfmk/i386/fpu.c | 76 +-
osfmk/i386/i386_init.c | 4 +-
osfmk/i386/proc_reg.h | 2 +-
osfmk/i386/ucode.c | 5 +-
osfmk/i386/ucode.h | 2 +-
osfmk/ipc/ipc_importance.c | 4 +-
osfmk/ipc/ipc_kmsg.c | 61 +-
osfmk/ipc/ipc_mqueue.c | 2 +-
osfmk/ipc/mach_msg.c | 2 +-
osfmk/kern/exception.c | 33 +
osfmk/kern/task.c | 39 +-
osfmk/kern/task.h | 14 +-
osfmk/kern/thread.h | 2 +-
osfmk/kern/zalloc.c | 224 +-
osfmk/kern/zalloc.h | 6 +-
osfmk/mach/arm/exception.h | 6 +
osfmk/mach/message.h | 22 +
osfmk/vm/vm_fault.c | 7 +-
osfmk/vm/vm_map.c | 70 +-
osfmk/vm/vm_map.h | 4 +
osfmk/vm/vm_user.c | 32 +-
tests/IP6_EXTHDR_CHECK_61873584.c | 83 +
tests/Makefile | 2 +
tests/ioc_str.h | 154 +
tests/macho_size_63133398.c | 3223 +++++++++++++++++
tests/pfkey.c | 1778 +++++++++
tests/proc_info.c | 6 +-
tests/sioc-if-addr-bounds.c | 662 ++++
tests/unp_connect_thread_uaf.c | 149 +
tools/lldbmacros/sysreg.py | 2 +-
tools/lldbmacros/zonetriage.py | 2 +-
100 files changed, 9063 insertions(+), 1225 deletions(-)
create mode 100644 iokit/DriverKit/IODMACommand.iig
create mode 100644 tests/IP6_EXTHDR_CHECK_61873584.c
create mode 100644 tests/ioc_str.h
create mode 100644 tests/macho_size_63133398.c
create mode 100644 tests/pfkey.c
create mode 100644 tests/sioc-if-addr-bounds.c
create mode 100644 tests/unp_connect_thread_uaf.c
diff --git a/bsd/kern/kern_aio.c b/bsd/kern/kern_aio.c
index 3ad8a516d..4a07657cb 100644
--- a/bsd/kern/kern_aio.c
+++ b/bsd/kern/kern_aio.c
@@ -106,11 +106,6 @@
#define AIO_suspend_sleep 111
#define AIO_worker_thread 120
-#if 0
-#undef KERNEL_DEBUG
-#define KERNEL_DEBUG KERNEL_DEBUG_CONSTANT
-#endif
-
/*
* aio requests queue up on the aio_async_workq or lio_sync_workq (for
* lio_listio LIO_WAIT). Requests then move to the per process aio_activeq
@@ -502,11 +497,11 @@ aio_workq_mutex(aio_workq_t wq)
int
aio_cancel(proc_t p, struct aio_cancel_args *uap, int *retval )
{
- struct user_aiocb my_aiocb;
- int result;
+ struct user_aiocb my_aiocb;
+ int result;
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_cancel)) | DBG_FUNC_START,
- (int)p, (int)uap->aiocbp, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_cancel) | DBG_FUNC_START,
+ VM_KERNEL_ADDRPERM(p), uap->uaiocbp, 0, 0, 0);
/* quick check to see if there are any async IO requests queued up */
if (aio_get_all_queues_count() < 1) {
@@ -562,8 +557,8 @@ aio_cancel(proc_t p, struct aio_cancel_args *uap, int *retval )
result = EBADF;
ExitRoutine:
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_cancel)) | DBG_FUNC_END,
- (int)p, (int)uap->aiocbp, result, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_cancel) | DBG_FUNC_END,
+ VM_KERNEL_ADDRPERM(p), uap->uaiocbp, result, 0, 0);
return result;
} /* aio_cancel */
@@ -577,15 +572,15 @@ aio_cancel(proc_t p, struct aio_cancel_args *uap, int *retval )
__private_extern__ void
_aio_close(proc_t p, int fd )
{
- int error;
+ int error;
/* quick check to see if there are any async IO requests queued up */
if (aio_get_all_queues_count() < 1) {
return;
}
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_close)) | DBG_FUNC_START,
- (int)p, fd, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_close) | DBG_FUNC_START,
+ VM_KERNEL_ADDRPERM(p), fd, 0, 0, 0);
/* cancel all async IO requests on our todo queues for this file descriptor */
aio_proc_lock(p);
@@ -601,8 +596,8 @@ _aio_close(proc_t p, int fd )
* when we must wait for all active aio requests.
*/
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_close_sleep)) | DBG_FUNC_NONE,
- (int)p, fd, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_close_sleep) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), fd, 0, 0, 0);
while (aio_proc_active_requests_for_file(p, fd) > 0) {
msleep(&p->AIO_CLEANUP_SLEEP_CHAN, aio_proc_mutex(p), PRIBIO, "aio_close", 0 );
@@ -611,8 +606,8 @@ _aio_close(proc_t p, int fd )
aio_proc_unlock(p);
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_close)) | DBG_FUNC_END,
- (int)p, fd, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_close) | DBG_FUNC_END,
+ VM_KERNEL_ADDRPERM(p), fd, 0, 0, 0);
return;
} /* _aio_close */
@@ -627,11 +622,11 @@ _aio_close(proc_t p, int fd )
int
aio_error(proc_t p, struct aio_error_args *uap, int *retval )
{
- aio_workq_entry *entryp;
- int error;
+ aio_workq_entry *entryp;
+ int error;
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_error)) | DBG_FUNC_START,
- (int)p, (int)uap->aiocbp, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_error) | DBG_FUNC_START,
+ VM_KERNEL_ADDRPERM(p), uap->uaiocbp, 0, 0, 0);
/* see if there are any aios to check */
if (aio_get_all_queues_count() < 1) {
@@ -649,8 +644,8 @@ aio_error(proc_t p, struct aio_error_args *uap, int *retval )
*retval = entryp->errorval;
error = 0;
aio_entry_unlock(entryp);
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_error_val)) | DBG_FUNC_NONE,
- (int)p, (int)uap->aiocbp, *retval, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_error_val) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), uap->uaiocbp, *retval, 0, 0);
goto ExitRoutine;
}
}
@@ -661,8 +656,8 @@ aio_error(proc_t p, struct aio_error_args *uap, int *retval )
ASSERT_AIO_FROM_PROC(entryp, p);
*retval = EINPROGRESS;
error = 0;
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_error_activeq)) | DBG_FUNC_NONE,
- (int)p, (int)uap->aiocbp, *retval, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_error_activeq) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), uap->uaiocbp, *retval, 0, 0);
goto ExitRoutine;
}
}
@@ -670,8 +665,8 @@ aio_error(proc_t p, struct aio_error_args *uap, int *retval )
error = EINVAL;
ExitRoutine:
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_error)) | DBG_FUNC_END,
- (int)p, (int)uap->aiocbp, error, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_error) | DBG_FUNC_END,
+ VM_KERNEL_ADDRPERM(p), uap->uaiocbp, error, 0, 0);
aio_proc_unlock(p);
return error;
@@ -688,11 +683,11 @@ aio_error(proc_t p, struct aio_error_args *uap, int *retval )
int
aio_fsync(proc_t p, struct aio_fsync_args *uap, int *retval )
{
- int error;
- int fsync_kind;
+ int error;
+ int fsync_kind;
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_fsync)) | DBG_FUNC_START,
- (int)p, (int)uap->aiocbp, uap->op, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_fsync) | DBG_FUNC_START,
+ VM_KERNEL_ADDRPERM(p), uap->uaiocbp, uap->op, 0, 0);
*retval = 0;
/* 0 := O_SYNC for binary backward compatibility with Panther */
@@ -712,8 +707,8 @@ aio_fsync(proc_t p, struct aio_fsync_args *uap, int *retval )
}
ExitRoutine:
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_fsync)) | DBG_FUNC_END,
- (int)p, (int)uap->aiocbp, error, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_fsync) | DBG_FUNC_END,
+ VM_KERNEL_ADDRPERM(p), uap->uaiocbp, error, 0, 0);
return error;
} /* aio_fsync */
@@ -726,10 +721,10 @@ aio_fsync(proc_t p, struct aio_fsync_args *uap, int *retval )
int
aio_read(proc_t p, struct aio_read_args *uap, int *retval )
{
- int error;
+ int error;
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_read)) | DBG_FUNC_START,
- (int)p, (int)uap->aiocbp, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_read) | DBG_FUNC_START,
+ VM_KERNEL_ADDRPERM(p), uap->uaiocbp, 0, 0, 0);
*retval = 0;
@@ -738,8 +733,8 @@ aio_read(proc_t p, struct aio_read_args *uap, int *retval )
*retval = -1;
}
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_read)) | DBG_FUNC_END,
- (int)p, (int)uap->aiocbp, error, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_read) | DBG_FUNC_END,
+ VM_KERNEL_ADDRPERM(p), uap->uaiocbp, error, 0, 0);
return error;
} /* aio_read */
@@ -755,12 +750,12 @@ aio_read(proc_t p, struct aio_read_args *uap, int *retval )
int
aio_return(proc_t p, struct aio_return_args *uap, user_ssize_t *retval )
{
- aio_workq_entry *entryp;
- int error;
- boolean_t proc_lock_held = FALSE;
+ aio_workq_entry *entryp;
+ int error;
+ boolean_t proc_lock_held = FALSE;
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_return)) | DBG_FUNC_START,
- (int)p, (int)uap->aiocbp, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_return) | DBG_FUNC_START,
+ VM_KERNEL_ADDRPERM(p), uap->uaiocbp, 0, 0, 0);
/* See if there are any entries to check */
if (aio_get_all_queues_count() < 1) {
@@ -798,8 +793,8 @@ aio_return(proc_t p, struct aio_return_args *uap, user_ssize_t *retval )
}
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_return_val)) | DBG_FUNC_NONE,
- (int)p, (int)uap->aiocbp, *retval, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_return_val) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), uap->uaiocbp, *retval, 0, 0);
goto ExitRoutine;
}
}
@@ -809,8 +804,8 @@ aio_return(proc_t p, struct aio_return_args *uap, user_ssize_t *retval )
ASSERT_AIO_FROM_PROC(entryp, p);
if (entryp->uaiocbp == uap->aiocbp) {
error = EINPROGRESS;
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_return_activeq)) | DBG_FUNC_NONE,
- (int)p, (int)uap->aiocbp, *retval, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_return_activeq) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), uap->uaiocbp, *retval, 0, 0);
goto ExitRoutine;
}
}
@@ -821,8 +816,8 @@ aio_return(proc_t p, struct aio_return_args *uap, user_ssize_t *retval )
if (proc_lock_held) {
aio_proc_unlock(p);
}
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_return)) | DBG_FUNC_END,
- (int)p, (int)uap->aiocbp, error, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_return) | DBG_FUNC_END,
+ VM_KERNEL_ADDRPERM(p), uap->uaiocbp, error, 0, 0);
return error;
} /* aio_return */
@@ -838,15 +833,13 @@ aio_return(proc_t p, struct aio_return_args *uap, user_ssize_t *retval )
__private_extern__ void
_aio_exec(proc_t p )
{
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_exec)) | DBG_FUNC_START,
- (int)p, 0, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_exec) | DBG_FUNC_START,
+ VM_KERNEL_ADDRPERM(p), 0, 0, 0, 0);
_aio_exit( p );
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_exec)) | DBG_FUNC_END,
- (int)p, 0, 0, 0, 0 );
-
- return;
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_exec) | DBG_FUNC_END,
+ VM_KERNEL_ADDRPERM(p), 0, 0, 0, 0);
} /* _aio_exec */
@@ -859,8 +852,8 @@ _aio_exec(proc_t p )
__private_extern__ void
_aio_exit(proc_t p )
{
- int error;
- aio_workq_entry *entryp;
+ int error;
+ aio_workq_entry *entryp;
/* quick check to see if there are any async IO requests queued up */
@@ -868,8 +861,8 @@ _aio_exit(proc_t p )
return;
}
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_exit)) | DBG_FUNC_START,
- (int)p, 0, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_exit) | DBG_FUNC_START,
+ VM_KERNEL_ADDRPERM(p), 0, 0, 0, 0);
aio_proc_lock(p);
@@ -889,8 +882,8 @@ _aio_exit(proc_t p )
* active aio requests.
*/
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_exit_sleep)) | DBG_FUNC_NONE,
- (int)p, 0, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_exit_sleep) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), 0, 0, 0, 0);
while (p->p_aio_active_count != 0) {
msleep(&p->AIO_CLEANUP_SLEEP_CHAN, aio_proc_mutex(p), PRIBIO, "aio_exit", 0 );
@@ -933,9 +926,8 @@ _aio_exit(proc_t p )
aio_proc_unlock(p);
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_exit)) | DBG_FUNC_END,
- (int)p, 0, 0, 0, 0 );
- return;
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_exit) | DBG_FUNC_END,
+ VM_KERNEL_ADDRPERM(p), 0, 0, 0, 0);
} /* _aio_exit */
@@ -1001,8 +993,9 @@ do_aio_cancel_locked(proc_t p, int fd, user_addr_t aiocbp,
/* Now it's officially cancelled. Do the completion */
result = AIO_CANCELED;
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_cancel_async_workq)) | DBG_FUNC_NONE,
- (int)entryp->procp, (int)entryp->uaiocbp, fd, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_cancel_async_workq) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), VM_KERNEL_ADDRPERM(entryp->uaiocbp),
+ fd, 0, 0);
do_aio_completion(entryp);
/* This will free if the aio_return() has already happened ... */
@@ -1032,8 +1025,9 @@ do_aio_cancel_locked(proc_t p, int fd, user_addr_t aiocbp,
*/
result = AIO_NOTCANCELED;
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_cancel_activeq)) | DBG_FUNC_NONE,
- (int)entryp->procp, (int)entryp->uaiocbp, fd, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_cancel_activeq) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), VM_KERNEL_ADDRPERM(entryp->uaiocbp),
+ fd, 0, 0);
/* Mark for waiting and such; will not take a ref if "cancelled" arg is FALSE */
aio_entry_update_for_cancel(entryp, FALSE, wait_for_completion, disable_notification);
@@ -1057,8 +1051,9 @@ do_aio_cancel_locked(proc_t p, int fd, user_addr_t aiocbp,
ASSERT_AIO_FROM_PROC(entryp, p);
if (should_cancel(entryp, aiocbp, fd)) {
result = AIO_ALLDONE;
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_cancel_doneq)) | DBG_FUNC_NONE,
- (int)entryp->procp, (int)entryp->uaiocbp, fd, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_cancel_doneq) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), VM_KERNEL_ADDRPERM(entryp->uaiocbp),
+ fd, 0, 0);
if (aiocbp != USER_ADDR_NULL) {
return result;
@@ -1092,15 +1087,15 @@ aio_suspend(proc_t p, struct aio_suspend_args *uap, int *retval )
int
aio_suspend_nocancel(proc_t p, struct aio_suspend_nocancel_args *uap, int *retval )
{
- int error;
- int i, count;
- uint64_t abstime;
- struct user_timespec ts;
- aio_workq_entry *entryp;
- user_addr_t *aiocbpp;
+ int error;
+ int i, count;
+ uint64_t abstime;
+ struct user_timespec ts;
+ aio_workq_entry *entryp;
+ user_addr_t *aiocbpp;
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_suspend)) | DBG_FUNC_START,
- (int)p, uap->nent, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_suspend) | DBG_FUNC_START,
+ VM_KERNEL_ADDRPERM(p), uap->nent, 0, 0, 0);
*retval = -1;
abstime = 0;
@@ -1178,8 +1173,8 @@ aio_suspend_nocancel(proc_t p, struct aio_suspend_nocancel_args *uap, int *retva
}
} /* for ( ; i < uap->nent; ) */
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_suspend_sleep)) | DBG_FUNC_NONE,
- (int)p, uap->nent, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_suspend_sleep) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), uap->nent, 0, 0, 0);
/*
* wait for an async IO to complete or a signal fires or timeout expires.
@@ -1212,8 +1207,8 @@ aio_suspend_nocancel(proc_t p, struct aio_suspend_nocancel_args *uap, int *retva
FREE( aiocbpp, M_TEMP );
}
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_suspend)) | DBG_FUNC_END,
- (int)p, uap->nent, error, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_suspend) | DBG_FUNC_END,
+ VM_KERNEL_ADDRPERM(p), uap->nent, error, 0, 0);
return error;
} /* aio_suspend */
@@ -1225,22 +1220,17 @@ aio_suspend_nocancel(proc_t p, struct aio_suspend_nocancel_args *uap, int *retva
*/
int
-aio_write(proc_t p, struct aio_write_args *uap, int *retval )
+aio_write(proc_t p, struct aio_write_args *uap, int *retval __unused)
{
- int error;
-
- *retval = 0;
+ int error;
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_write)) | DBG_FUNC_START,
- (int)p, (int)uap->aiocbp, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_write) | DBG_FUNC_START,
+ VM_KERNEL_ADDRPERM(p), uap->uaiocbp, 0, 0, 0);
error = aio_queue_async_request( p, uap->aiocbp, AIO_WRITE );
- if (error != 0) {
- *retval = -1;
- }
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_write)) | DBG_FUNC_END,
- (int)p, (int)uap->aiocbp, error, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_write) | DBG_FUNC_END,
+ VM_KERNEL_ADDRPERM(p), uap->uaiocbp, error, 0, 0);
return error;
} /* aio_write */
@@ -1424,6 +1414,13 @@ aio_enqueue_work( proc_t procp, aio_workq_entry *entryp, int proc_locked)
THREAD_AWAKENED, WAITQ_ALL_PRIORITIES);
aio_workq_unlock(queue);
+
+ KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_AIO, AIO_work_queued) | DBG_FUNC_START,
+ VM_KERNEL_ADDRPERM(procp), VM_KERNEL_ADDRPERM(entryp->uaiocbp),
+ entryp->flags, entryp->aiocb.aio_fildes, 0 );
+ KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_AIO, AIO_work_queued) | DBG_FUNC_END,
+ entryp->aiocb.aio_offset, 0, entryp->aiocb.aio_nbytes, 0, 0);
+
if (proc_locked == 0) {
aio_proc_unlock(procp);
}
@@ -1485,20 +1482,18 @@ aio_enqueue_work( proc_t procp, aio_workq_entry *entryp, int proc_locked)
int
lio_listio(proc_t p, struct lio_listio_args *uap, int *retval )
{
- int i;
- int call_result;
- int result;
- int old_count;
- aio_workq_entry **entryp_listp;
- user_addr_t *aiocbpp;
- struct user_sigevent aiosigev;
+ int i;
+ int call_result;
+ int result;
+ int old_count;
+ aio_workq_entry **entryp_listp;
+ user_addr_t *aiocbpp;
+ struct user_sigevent aiosigev;
aio_lio_context *lio_context;
- boolean_t free_context = FALSE;
- uint32_t *paio_offset;
- uint32_t *paio_nbytes;
+ boolean_t free_context = FALSE;
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_listio)) | DBG_FUNC_START,
- (int)p, uap->nent, uap->mode, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_listio) | DBG_FUNC_START,
+ VM_KERNEL_ADDRPERM(p), uap->nent, uap->mode, 0, 0);
entryp_listp = NULL;
lio_context = NULL;
@@ -1525,6 +1520,23 @@ lio_listio(proc_t p, struct lio_listio_args *uap, int *retval )
goto ExitRoutine;
}
+ /*
+ * lio_context ownership rules go as follow:
+ *
+ * - when the mode is LIO_WAIT, and that the AIOs aren't cancelled,
+ * this function will perform the deallocation.
+ *
+ * - when the mode is LIO_WAIT but AIOs are cancelled, then io_waiter is
+ * forced to '0' (pretending the mode is LIO_NOWAIT) and the ownership is
+ * handed over to the async path.
+ *
+ * - when the mode is LIO_NOWAIT, then the aio thread is responsible for
+ * cleaning up the context.
+ *
+ * However, there is a last case, which is when none of the commands pass
+ * preflight and no submission is done, in this case this function is
+ * responsible for cleanup.
+ */
MALLOC( lio_context, aio_lio_context*, sizeof(aio_lio_context), M_TEMP, M_WAITOK );
if (lio_context == NULL) {
call_result = EAGAIN;
@@ -1575,7 +1587,10 @@ lio_listio(proc_t p, struct lio_listio_args *uap, int *retval )
/* NULL elements are legal so check for 'em */
if (my_aiocbp == USER_ADDR_NULL) {
aio_proc_lock_spin(p);
- lio_context->io_issued--;
+ if (--lio_context->io_issued == 0) {
+ /* no submission made, needs cleanup */
+ free_context = TRUE;
+ }
aio_proc_unlock(p);
continue;
}
@@ -1598,7 +1613,10 @@ lio_listio(proc_t p, struct lio_listio_args *uap, int *retval )
entryp = *(entryp_listp + i);
if (entryp == NULL) {
aio_proc_lock_spin(p);
- lio_context->io_issued--;
+ if (--lio_context->io_issued == 0) {
+ /* no submission made, needs cleanup */
+ free_context = TRUE;
+ }
aio_proc_unlock(p);
continue;
}
@@ -1618,7 +1636,10 @@ lio_listio(proc_t p, struct lio_listio_args *uap, int *retval )
if (old_count >= aio_max_requests ||
aio_get_process_count( entryp->procp ) >= aio_max_requests_per_process ||
is_already_queued( entryp->procp, entryp->uaiocbp ) == TRUE) {
- lio_context->io_issued--;
+ if (--lio_context->io_issued == 0) {
+ /* no submission made, needs cleanup */
+ free_context = TRUE;
+ }
aio_proc_unlock(p);
aio_decrement_total_count();
@@ -1634,46 +1655,37 @@ lio_listio(proc_t p, struct lio_listio_args *uap, int *retval )
lck_mtx_convert_spin(aio_proc_mutex(p));
aio_enqueue_work(p, entryp, 1);
aio_proc_unlock(p);
+ }
- KERNEL_DEBUG_CONSTANT((BSDDBG_CODE(DBG_BSD_AIO, AIO_work_queued)) | DBG_FUNC_START,
- (int)p, (int)entryp->uaiocbp, entryp->flags, entryp->aiocb.aio_fildes, 0 );
- paio_offset = (uint32_t*) &entryp->aiocb.aio_offset;
- paio_nbytes = (uint32_t*) &entryp->aiocb.aio_nbytes;
- KERNEL_DEBUG_CONSTANT((BSDDBG_CODE(DBG_BSD_AIO, AIO_work_queued)) | DBG_FUNC_END,
- paio_offset[0], (sizeof(entryp->aiocb.aio_offset) == sizeof(uint64_t) ? paio_offset[1] : 0),
- paio_nbytes[0], (sizeof(entryp->aiocb.aio_nbytes) == sizeof(uint64_t) ? paio_nbytes[1] : 0),
- 0 );
+ if (free_context) {
+ /* no submission was made, just exit */
+ goto ExitRoutine;
}
- aio_proc_lock_spin(p);
- switch (uap->mode) {
- case LIO_WAIT:
+ if (uap->mode == LIO_WAIT) {
+ aio_proc_lock_spin(p);
+
while (lio_context->io_completed < lio_context->io_issued) {
result = msleep(lio_context, aio_proc_mutex(p), PCATCH | PRIBIO | PSPIN, "lio_listio", 0);
/* If we were interrupted, fail out (even if all finished) */
if (result != 0) {
call_result = EINTR;
- lio_context->io_waiter = 0;
break;
}
}
- /* If all IOs have finished must free it */
if (lio_context->io_completed == lio_context->io_issued) {
+ /* If all IOs have finished must free it */
free_context = TRUE;
+ } else {
+ /* handoff to the async codepath for clean up */
+ assert(call_result == EINTR);
+ lio_context->io_waiter = 0;
}
- break;
-
- case LIO_NOWAIT:
- /* If no IOs were issued must free it (rdar://problem/45717887) */
- if (lio_context->io_issued == 0) {
- free_context = TRUE;
- }
- break;
+ aio_proc_unlock(p);
}
- aio_proc_unlock(p);
/* call_result == -1 means we had no trouble queueing up requests */
if (call_result == -1) {
@@ -1692,8 +1704,8 @@ lio_listio(proc_t p, struct lio_listio_args *uap, int *retval )
free_lio_context(lio_context);
}
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_listio)) | DBG_FUNC_END,
- (int)p, call_result, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_listio) | DBG_FUNC_END,
+ VM_KERNEL_ADDRPERM(p), call_result, 0, 0, 0);
return call_result;
} /* lio_listio */
@@ -1708,11 +1720,11 @@ __attribute__((noreturn))
static void
aio_work_thread(void)
{
- aio_workq_entry *entryp;
- int error;
- vm_map_t currentmap;
- vm_map_t oldmap = VM_MAP_NULL;
- task_t oldaiotask = TASK_NULL;
+ aio_workq_entry *entryp;
+ int error;
+ vm_map_t currentmap;
+ vm_map_t oldmap = VM_MAP_NULL;
+ task_t oldaiotask = TASK_NULL;
struct uthread *uthreadp = NULL;
for (;;) {
@@ -1722,8 +1734,9 @@ aio_work_thread(void)
*/
entryp = aio_get_some_work();
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_worker_thread)) | DBG_FUNC_START,
- (int)entryp->procp, (int)entryp->uaiocbp, entryp->flags, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_worker_thread) | DBG_FUNC_START,
+ VM_KERNEL_ADDRPERM(p), VM_KERNEL_ADDRPERM(entryp->uaiocbp),
+ entryp->flags, 0, 0);
/*
* Assume the target's address space identity for the duration
@@ -1756,9 +1769,9 @@ aio_work_thread(void)
uthreadp->uu_aio_task = oldaiotask;
}
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_worker_thread)) | DBG_FUNC_END,
- (int)entryp->procp, (int)entryp->uaiocbp, entryp->errorval,
- entryp->returnval, 0 );
+ KERNEL_DEBUG(SDDBG_CODE(DBG_BSD_AIO, AIO_worker_thread) | DBG_FUNC_END,
+ VM_KERNEL_ADDRPERM(p), VM_KERNEL_ADDRPERM(entryp->uaiocbp),
+ entryp->errorval, entryp->returnval, 0);
/* XXX COUNTS */
@@ -1803,8 +1816,8 @@ aio_work_thread(void)
static aio_workq_entry *
aio_get_some_work( void )
{
- aio_workq_entry *entryp = NULL;
- aio_workq_t queue = NULL;
+ aio_workq_entry *entryp = NULL;
+ aio_workq_t queue = NULL;
/* Just one queue for the moment. In the future there will be many. */
queue = &aio_anchor.aio_async_workqs[0];
@@ -1850,8 +1863,9 @@ aio_get_some_work( void )
aio_proc_lock_spin(entryp->procp);
if (aio_delay_fsync_request( entryp )) {
/* It needs to be delayed. Put it back on the end of the work queue */
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_fsync_delay)) | DBG_FUNC_NONE,
- (int)entryp->procp, (int)entryp->uaiocbp, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_fsync_delay) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), VM_KERNEL_ADDRPERM(entryp->uaiocbp),
+ 0, 0, 0);
aio_proc_unlock(entryp->procp);
@@ -1888,6 +1902,14 @@ aio_get_some_work( void )
static boolean_t
aio_delay_fsync_request( aio_workq_entry *entryp )
{
+ if (proc_in_teardown(entryp->procp)) {
+ /*
+ * we can't delay FSYNCS when in teardown as it will confuse _aio_exit,
+ * if it was dequeued, then we must now commit to it
+ */
+ return FALSE;
+ }
+
if (entryp == TAILQ_FIRST(&entryp->procp->p_aio_activeq)) {
return FALSE;
}
@@ -1979,8 +2001,6 @@ aio_queue_async_request(proc_t procp, user_addr_t aiocbp, int kindOfIO )
aio_workq_entry *entryp;
int result;
int old_count;
- uint32_t *paio_offset;
- uint32_t *paio_nbytes;
old_count = aio_increment_total_count();
if (old_count >= aio_max_requests) {
@@ -2014,16 +2034,6 @@ aio_queue_async_request(proc_t procp, user_addr_t aiocbp, int kindOfIO )
aio_enqueue_work(procp, entryp, 1);
aio_proc_unlock(procp);
-
- paio_offset = (uint32_t*) &entryp->aiocb.aio_offset;
- paio_nbytes = (uint32_t*) &entryp->aiocb.aio_nbytes;
- KERNEL_DEBUG_CONSTANT((BSDDBG_CODE(DBG_BSD_AIO, AIO_work_queued)) | DBG_FUNC_START,
- (int)procp, (int)aiocbp, entryp->flags, entryp->aiocb.aio_fildes, 0 );
- KERNEL_DEBUG_CONSTANT((BSDDBG_CODE(DBG_BSD_AIO, AIO_work_queued)) | DBG_FUNC_END,
- paio_offset[0], (sizeof(entryp->aiocb.aio_offset) == sizeof(uint64_t) ? paio_offset[1] : 0),
- paio_nbytes[0], (sizeof(entryp->aiocb.aio_nbytes) == sizeof(uint64_t) ? paio_nbytes[1] : 0),
- 0 );
-
return 0;
error_exit:
@@ -2143,9 +2153,9 @@ aio_free_request(aio_workq_entry *entryp)
static int
aio_validate( aio_workq_entry *entryp )
{
- struct fileproc *fp;
- int flag;
- int result;
+ struct fileproc *fp;
+ int flag;
+ int result;
result = 0;
@@ -2207,13 +2217,13 @@ aio_validate( aio_workq_entry *entryp )
} /* aio_validate */
static int
-aio_increment_total_count()
+aio_increment_total_count(void)
{
return OSIncrementAtomic(&aio_anchor.aio_total_count);
}
static int
-aio_decrement_total_count()
+aio_decrement_total_count(void)
{
int old = OSDecrementAtomic(&aio_anchor.aio_total_count);
if (old <= 0) {
@@ -2224,7 +2234,7 @@ aio_decrement_total_count()
}
static int
-aio_get_process_count(proc_t procp )
+aio_get_process_count(proc_t procp)
{
return procp->p_aio_total_count;
} /* aio_get_process_count */
@@ -2242,9 +2252,9 @@ aio_get_all_queues_count( void )
static void
do_aio_completion( aio_workq_entry *entryp )
{
- boolean_t lastLioCompleted = FALSE;
+ boolean_t lastLioCompleted = FALSE;
aio_lio_context *lio_context = NULL;
- int waiter = 0;
+ int waiter = 0;
lio_context = (aio_lio_context *)entryp->group_tag;
@@ -2284,9 +2294,9 @@ do_aio_completion( aio_workq_entry *entryp )
}
if (performSignal) {
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_completion_sig)) | DBG_FUNC_NONE,
- (int)entryp->procp, (int)entryp->uaiocbp,
- entryp->aiocb.aio_sigevent.sigev_signo, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_completion_sig) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), VM_KERNEL_ADDRPERM(entryp->uaiocbp),
+ entryp->aiocb.aio_sigevent.sigev_signo, 0, 0);
psignal( entryp->procp, entryp->aiocb.aio_sigevent.sigev_signo );
}
@@ -2312,8 +2322,9 @@ do_aio_completion( aio_workq_entry *entryp )
if ((entryp->flags & AIO_EXIT_WAIT) != 0) {
int active_requests;
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_completion_cleanup_wait)) | DBG_FUNC_NONE,
- (int)entryp->procp, (int)entryp->uaiocbp, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_completion_cleanup_wait) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), VM_KERNEL_ADDRPERM(entryp->uaiocbp),
+ 0, 0, 0);
aio_proc_lock_spin(entryp->procp);
active_requests = aio_active_requests_for_process( entryp->procp );
@@ -2325,8 +2336,9 @@ do_aio_completion( aio_workq_entry *entryp )
wakeup_one((caddr_t)&entryp->procp->AIO_CLEANUP_SLEEP_CHAN);
aio_proc_unlock(entryp->procp);
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_completion_cleanup_wake)) | DBG_FUNC_NONE,
- (int)entryp->procp, (int)entryp->uaiocbp, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_completion_cleanup_wake) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), VM_KERNEL_ADDRPERM(entryp->uaiocbp),
+ 0, 0, 0);
} else {
aio_proc_unlock(entryp->procp);
}
@@ -2335,8 +2347,9 @@ do_aio_completion( aio_workq_entry *entryp )
if ((entryp->flags & AIO_CLOSE_WAIT) != 0) {
int active_requests;
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_completion_cleanup_wait)) | DBG_FUNC_NONE,
- (int)entryp->procp, (int)entryp->uaiocbp, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_completion_cleanup_wait) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), VM_KERNEL_ADDRPERM(entryp->uaiocbp),
+ 0, 0, 0);
aio_proc_lock_spin(entryp->procp);
active_requests = aio_proc_active_requests_for_file( entryp->procp, entryp->aiocb.aio_fildes);
@@ -2345,8 +2358,9 @@ do_aio_completion( aio_workq_entry *entryp )
wakeup(&entryp->procp->AIO_CLEANUP_SLEEP_CHAN);
aio_proc_unlock(entryp->procp);
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_completion_cleanup_wake)) | DBG_FUNC_NONE,
- (int)entryp->procp, (int)entryp->uaiocbp, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_completion_cleanup_wake) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), VM_KERNEL_ADDRPERM(entryp->uaiocbp),
+ 0, 0, 0);
} else {
aio_proc_unlock(entryp->procp);
}
@@ -2359,8 +2373,8 @@ do_aio_completion( aio_workq_entry *entryp )
* can do our wakeup without holding the lock.
*/
wakeup((caddr_t) &entryp->procp->AIO_SUSPEND_SLEEP_CHAN );
- KERNEL_DEBUG((BSDDBG_CODE(DBG_BSD_AIO, AIO_completion_suspend_wake)) | DBG_FUNC_NONE,
- (int)entryp->procp, (int)entryp->uaiocbp, 0, 0, 0 );
+ KERNEL_DEBUG(BSDDBG_CODE(DBG_BSD_AIO, AIO_completion_suspend_wake) | DBG_FUNC_NONE,
+ VM_KERNEL_ADDRPERM(p), VM_KERNEL_ADDRPERM(entryp->uaiocbp), 0, 0, 0);
/*
* free the LIO context if the last lio completed and no thread is
@@ -2378,8 +2392,8 @@ do_aio_completion( aio_workq_entry *entryp )
static int
do_aio_read( aio_workq_entry *entryp )
{
- struct fileproc *fp;
- int error;
+ struct fileproc *fp;
+ int error;
struct vfs_context context;
if ((error = fp_lookup(entryp->procp, entryp->aiocb.aio_fildes, &fp, 0))) {
@@ -2410,9 +2424,9 @@ do_aio_read( aio_workq_entry *entryp )
static int
do_aio_write( aio_workq_entry *entryp )
{
- struct fileproc *fp;
- int error, flags;
- struct vfs_context context;
+ struct fileproc *fp;
+ int error, flags;
+ struct vfs_context context;
if ((error = fp_lookup(entryp->procp, entryp->aiocb.aio_fildes, &fp, 0))) {
return error;
@@ -2454,7 +2468,7 @@ do_aio_write( aio_workq_entry *entryp )
* requests for the given process.
*/
static int
-aio_active_requests_for_process(proc_t procp )
+aio_active_requests_for_process(proc_t procp)
{
return procp->p_aio_active_count;
} /* aio_active_requests_for_process */
@@ -2542,11 +2556,10 @@ do_aio_fsync( aio_workq_entry *entryp )
* Called with proc aio lock held (can be held spin)
*/
static boolean_t
-is_already_queued(proc_t procp,
- user_addr_t aiocbp )
+is_already_queued(proc_t procp, user_addr_t aiocbp)
{
- aio_workq_entry *entryp;
- boolean_t result;
+ aio_workq_entry *entryp;
+ boolean_t result;
result = FALSE;
@@ -2588,7 +2601,7 @@ free_lio_context(aio_lio_context* context)
__private_extern__ void
aio_init( void )
{
- int i;
+ int i;
aio_lock_grp_attr = lck_grp_attr_alloc_init();
aio_proc_lock_grp = lck_grp_alloc_init("aio_proc", aio_lock_grp_attr);;
@@ -2622,7 +2635,7 @@ aio_init( void )
__private_extern__ void
_aio_create_worker_threads( int num )
{
- int i;
+ int i;
/* create some worker threads to handle the async IO requests */
for (i = 0; i < num; i++) {
diff --git a/bsd/kern/kern_exec.c b/bsd/kern/kern_exec.c
index afa0cb820..a5704a7f2 100644
--- a/bsd/kern/kern_exec.c
+++ b/bsd/kern/kern_exec.c
@@ -3622,6 +3622,10 @@ posix_spawn(proc_t ap, struct posix_spawn_args *uap, int32_t *retval)
proc_legacy_footprint_entitled(p, new_task, __FUNCTION__);
proc_ios13extended_footprint_entitled(p, new_task, __FUNCTION__);
#endif /* __arm64__ */
+
+#if __has_feature(ptrauth_calls)
+ task_set_pac_exception_fatal_flag(new_task);
+#endif /* __has_feature(ptrauth_calls) */
}
/* Inherit task role from old task to new task for exec */
@@ -4311,6 +4315,10 @@ __mac_execve(proc_t p, struct __mac_execve_args *uap, int32_t *retval)
task_set_main_thread_qos(new_task, main_thread);
+#if __has_feature(ptrauth_calls)
+ task_set_pac_exception_fatal_flag(new_task);
+#endif /* __has_feature(ptrauth_calls) */
+
#if CONFIG_ARCADE
/*
* Check to see if we need to trigger an arcade upcall AST now
diff --git a/bsd/kern/kern_exit.c b/bsd/kern/kern_exit.c
index 825508bf3..7349f618f 100644
--- a/bsd/kern/kern_exit.c
+++ b/bsd/kern/kern_exit.c
@@ -192,6 +192,12 @@ kern_return_t task_violated_guard(mach_exception_code_t, mach_exception_subcode_
void delay(int);
void gather_rusage_info(proc_t p, rusage_info_current *ru, int flavor);
+#if __has_feature(ptrauth_calls)
+int exit_with_pac_exception(proc_t p, exception_type_t exception, mach_exception_code_t code,
+ mach_exception_subcode_t subcode);
+#endif /* __has_feature(ptrauth_calls) */
+
+
/*
* NOTE: Source and target may *NOT* overlap!
* XXX Should share code with bsd/dev/ppc/unix_signal.c
@@ -2907,3 +2913,26 @@ kdp_wait4_find_process(thread_t thread, __unused event64_t wait_event, thread_wa
// See man wait4 for other valid wait4 arguments.
waitinfo->owner = args->pid;
}
+
+#if __has_feature(ptrauth_calls)
+int
+exit_with_pac_exception(proc_t p, exception_type_t exception, mach_exception_code_t code,
+ mach_exception_subcode_t subcode)
+{
+ thread_t self = current_thread();
+ struct uthread *ut = get_bsdthread_info(self);
+
+ os_reason_t exception_reason = os_reason_create(OS_REASON_PAC_EXCEPTION, (uint64_t)code);
+ if (exception_reason == OS_REASON_NULL) {
+ printf("exit_with_pac_exception: failed to allocate exit reason\n");
+ } else {
+ exception_reason->osr_flags |= OS_REASON_FLAG_GENERATE_CRASH_REPORT;
+ ut->uu_exception = exception;
+ ut->uu_code = code;
+ ut->uu_subcode = subcode;
+ }
+
+ return exit_with_reason(p, W_EXITCODE(0, SIGKILL), (int *)NULL, TRUE, FALSE,
+ 0, exception_reason);
+}
+#endif /* __has_feature(ptrauth_calls) */
diff --git a/bsd/kern/kern_proc.c b/bsd/kern/kern_proc.c
index 1a11358be..01f548e79 100644
--- a/bsd/kern/kern_proc.c
+++ b/bsd/kern/kern_proc.c
@@ -3863,6 +3863,19 @@ proc_set_syscall_filter_mask(proc_t p, int which, unsigned char *maskptr, size_t
return KERN_SUCCESS;
}
+bool
+proc_is_traced(proc_t p)
+{
+ bool ret = FALSE;
+ assert(p != PROC_NULL);
+ proc_lock(p);
+ if (p->p_lflag & P_LTRACED) {
+ ret = TRUE;
+ }
+ proc_unlock(p);
+ return ret;
+}
+
#ifdef CONFIG_32BIT_TELEMETRY
void
proc_log_32bit_telemetry(proc_t p)
diff --git a/bsd/kern/kern_sysctl.c b/bsd/kern/kern_sysctl.c
index edf8d8d22..a6702441c 100644
--- a/bsd/kern/kern_sysctl.c
+++ b/bsd/kern/kern_sysctl.c
@@ -1465,7 +1465,7 @@ sysctl_procargsx(int *name, u_int namelen, user_addr_t where,
if (vm_map_copy_overwrite(kernel_map,
(vm_map_address_t)copy_start,
- tmp, FALSE) != KERN_SUCCESS) {
+ tmp, (vm_map_size_t) arg_size, FALSE) != KERN_SUCCESS) {
kmem_free(kernel_map, copy_start,
round_page(arg_size));
vm_map_copy_discard(tmp);
diff --git a/bsd/kern/mach_loader.c b/bsd/kern/mach_loader.c
index d51e05c70..0d91fdd48 100644
--- a/bsd/kern/mach_loader.c
+++ b/bsd/kern/mach_loader.c
@@ -353,6 +353,7 @@ load_machfile(
struct vnode *vp = imgp->ip_vp;
off_t file_offset = imgp->ip_arch_offset;
off_t macho_size = imgp->ip_arch_size;
+ off_t total_size = 0;
off_t file_size = imgp->ip_vattr->va_data_size;
pmap_t pmap = 0; /* protected by create_map */
vm_map_t map;
@@ -368,7 +369,8 @@ load_machfile(
kern_return_t kret;
unsigned int pmap_flags = 0;
- if (macho_size > file_size) {
+ if (os_add_overflow(file_offset, macho_size, &total_size) ||
+ total_size > file_size) {
return LOAD_BADMACHO;
}
@@ -2579,6 +2581,10 @@ load_threadstack(
int flavor;
uint32_t stack_size;
+ if (total_size == 0) {
+ return LOAD_BADMACHO;
+ }
+
while (total_size > 0) {
flavor = *ts++;
size = *ts++;
@@ -2896,6 +2902,7 @@ load_code_signature(
&blob)) {
if (addr) {
ubc_cs_blob_deallocate(addr, blob_size);
+ addr = 0;
}
ret = LOAD_FAILURE;
goto out;
diff --git a/bsd/kern/uipc_usrreq.c b/bsd/kern/uipc_usrreq.c
index 2c4434dc2..b08bbbee7 100644
--- a/bsd/kern/uipc_usrreq.c
+++ b/bsd/kern/uipc_usrreq.c
@@ -468,6 +468,7 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
}
error = unp_connect(so, nam, p);
if (error) {
+ so->so_state &= ~SS_ISCONNECTING;
break;
}
} else {
@@ -529,6 +530,7 @@ uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
if (nam) {
error = unp_connect(so, nam, p);
if (error) {
+ so->so_state &= ~SS_ISCONNECTING;
break; /* XXX */
}
} else {
@@ -1180,6 +1182,9 @@ unp_connect(struct socket *so, struct sockaddr *nam, __unused proc_t p)
if (len >= SOCK_MAXADDRLEN) {
return EINVAL;
}
+
+ soisconnecting(so);
+
bcopy(soun->sun_path, buf, len);
buf[len] = 0;
diff --git a/bsd/net/content_filter.c b/bsd/net/content_filter.c
index 11b248d0c..68422f880 100644
--- a/bsd/net/content_filter.c
+++ b/bsd/net/content_filter.c
@@ -2891,10 +2891,10 @@ cfil_sock_attach(struct socket *so, struct sockaddr *local, struct sockaddr *rem
* Save passed addresses for attach event msg (in case resend
* is needed.
*/
- if (remote != NULL) {
+ if (remote != NULL && (remote->sa_len <= sizeof(union sockaddr_in_4_6))) {
memcpy(&so->so_cfil->cfi_so_attach_faddr, remote, remote->sa_len);
}
- if (local != NULL) {
+ if (local != NULL && (local->sa_len <= sizeof(union sockaddr_in_4_6))) {
memcpy(&so->so_cfil->cfi_so_attach_laddr, local, local->sa_len);
}
diff --git a/bsd/net/if.c b/bsd/net/if.c
index dcb728807..308c04b54 100644
--- a/bsd/net/if.c
+++ b/bsd/net/if.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -890,7 +890,7 @@ ifa_foraddr6_scoped(struct in6_addr *addr6, unsigned int scope)
struct in6_ifaddr *ia = NULL;
lck_rw_lock_shared(&in6_ifaddr_rwlock);
- for (ia = in6_ifaddrs; ia; ia = ia->ia_next) {
+ TAILQ_FOREACH(ia, IN6ADDR_HASH(addr6), ia6_hash) {
IFA_LOCK(&ia->ia_ifa);
if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, addr6) &&
(scope == IFSCOPE_NONE || ia->ia_ifp->if_index == scope)) {
diff --git a/bsd/net/if_gif.c b/bsd/net/if_gif.c
index 0ada425b6..9f9e6c574 100644
--- a/bsd/net/if_gif.c
+++ b/bsd/net/if_gif.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2018 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -618,6 +618,12 @@ gif_output(
/* XXX should we check if our outer source is legal? */
+ /*
+ * Save the length as m may be free by the output functions
+ * as they call m_pullup
+ */
+ u_int32_t bytes_out = m->m_pkthdr.len;
+
/* dispatch to output logic based on outer AF */
switch (sc->gif_psrc->sa_family) {
#if INET
@@ -641,7 +647,7 @@ gif_output(
/* the mbuf was freed either by in_gif_output or in here */
ifnet_stat_increment_out(ifp, 0, 0, 1);
} else {
- ifnet_stat_increment_out(ifp, 1, m->m_pkthdr.len, 0);
+ ifnet_stat_increment_out(ifp, 1, bytes_out, 0);
}
if (error == 0) {
error = EJUSTRETURN; /* if no error, packet got sent already */
diff --git a/bsd/net/if_stf.c b/bsd/net/if_stf.c
index 05e6087ab..5ceab5438 100644
--- a/bsd/net/if_stf.c
+++ b/bsd/net/if_stf.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2018 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -571,6 +571,7 @@ stf_pre_output(
IFA_REMREF(&ia6->ia_ifa);
return ENOBUFS;
}
+ *m0 = m;
}
ip6 = mtod(m, struct ip6_hdr *);
tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
@@ -604,6 +605,8 @@ stf_pre_output(
IFA_REMREF(&ia6->ia_ifa);
return ENOBUFS;
}
+
+ *m0 = m;
ip = mtod(m, struct ip *);
bzero(ip, sizeof(*ip));
diff --git a/bsd/net/kpi_interface.c b/bsd/net/kpi_interface.c
index 2d5c6454b..41fb91f69 100644
--- a/bsd/net/kpi_interface.c
+++ b/bsd/net/kpi_interface.c
@@ -641,6 +641,7 @@ ifnet_set_eflags(ifnet_t interface, u_int32_t new_flags, u_int32_t mask)
*/
if ((((new_flags & mask) & IFEF_ADV_REPORT) != 0) &&
((interface->if_eflags & IFEF_SKYWALK_NATIVE) == 0)) {
+ ifnet_lock_done(interface);
return EINVAL;
}
oeflags = interface->if_eflags;
diff --git a/bsd/net/necp.c b/bsd/net/necp.c
index c73dadf89..0c014f0be 100644
--- a/bsd/net/necp.c
+++ b/bsd/net/necp.c
@@ -227,6 +227,7 @@ u_int32_t necp_session_count = 0;
#define NECP_KERNEL_CONDITION_LOCAL_EMPTY 0x1000000
#define NECP_KERNEL_CONDITION_REMOTE_EMPTY 0x2000000
#define NECP_KERNEL_CONDITION_PLATFORM_BINARY 0x4000000
+#define NECP_KERNEL_CONDITION_SIGNING_IDENTIFIER 0x8000000
#define NECP_MAX_POLICY_RESULT_SIZE 512
#define NECP_MAX_ROUTE_RULES_ARRAY_SIZE 1024
@@ -378,7 +379,7 @@ static bool necp_policy_mark_all_for_deletion(struct necp_session *session);
static bool necp_policy_delete(struct necp_session *session, struct necp_session_policy *policy);
static void necp_policy_apply_all(struct necp_session *session);
-static necp_kernel_policy_id necp_kernel_socket_policy_add(necp_policy_order order, u_int32_t session_order, int session_pid, u_int32_t condition_mask, u_int32_t condition_negated_mask, necp_app_id cond_app_id, necp_app_id cond_real_app_id, char *cond_custom_entitlement, u_int32_t cond_account_id, char *domain, pid_t cond_pid, uid_t cond_uid, ifnet_t cond_bound_interface, struct necp_policy_condition_tc_range cond_traffic_class, u_int16_t cond_protocol, union necp_sockaddr_union *cond_local_start, union necp_sockaddr_union *cond_local_end, u_int8_t cond_local_prefix, union necp_sockaddr_union *cond_remote_start, union necp_sockaddr_union *cond_remote_end, u_int8_t cond_remote_prefix, struct necp_policy_condition_agent_type *cond_agent_type, u_int32_t cond_client_flags, necp_kernel_policy_result result, necp_kernel_policy_result_parameter result_parameter);
+static necp_kernel_policy_id necp_kernel_socket_policy_add(necp_policy_order order, u_int32_t session_order, int session_pid, u_int32_t condition_mask, u_int32_t condition_negated_mask, necp_app_id cond_app_id, necp_app_id cond_real_app_id, char *cond_custom_entitlement, u_int32_t cond_account_id, char *domain, pid_t cond_pid, uid_t cond_uid, ifnet_t cond_bound_interface, struct necp_policy_condition_tc_range cond_traffic_class, u_int16_t cond_protocol, union necp_sockaddr_union *cond_local_start, union necp_sockaddr_union *cond_local_end, u_int8_t cond_local_prefix, union necp_sockaddr_union *cond_remote_start, union necp_sockaddr_union *cond_remote_end, u_int8_t cond_remote_prefix, struct necp_policy_condition_agent_type *cond_agent_type, u_int32_t cond_client_flags, char *cond_signing_identifier, necp_kernel_policy_result result, necp_kernel_policy_result_parameter result_parameter);
static bool necp_kernel_socket_policy_delete(necp_kernel_policy_id policy_id);
static bool necp_kernel_socket_policies_reprocess(void);
static bool necp_kernel_socket_policies_update_uuid_table(void);
@@ -1934,7 +1935,8 @@ necp_policy_condition_is_valid(u_int8_t *buffer, u_int32_t length, u_int8_t poli
}
case NECP_POLICY_CONDITION_DOMAIN:
case NECP_POLICY_CONDITION_ACCOUNT:
- case NECP_POLICY_CONDITION_BOUND_INTERFACE: {
+ case NECP_POLICY_CONDITION_BOUND_INTERFACE:
+ case NECP_POLICY_CONDITION_SIGNING_IDENTIFIER: {
if (condition_length > 0) {
validated = TRUE;
}
@@ -2682,6 +2684,11 @@ necp_handle_policy_dump_all(user_addr_t out_buffer, size_t out_buffer_length)
if (condition_mask & NECP_KERNEL_CONDITION_REMOTE_EMPTY) {
num_conditions++;
}
+ if (condition_mask & NECP_KERNEL_CONDITION_SIGNING_IDENTIFIER) {
+ u_int32_t identifier_len = strlen(policy->cond_signing_identifier) + 1;
+ condition_tlv_length += identifier_len;
+ num_conditions++;
+ }
}
condition_tlv_length += num_conditions * (sizeof(u_int8_t) + sizeof(u_int32_t)); // These are for the condition TLVs. The space for "value" is already accounted for above.
@@ -2829,6 +2836,10 @@ necp_handle_policy_dump_all(user_addr_t out_buffer, size_t out_buffer_length)
if (condition_mask & NECP_KERNEL_CONDITION_REMOTE_EMPTY) {
cond_buf_cursor = necp_buffer_write_tlv(cond_buf_cursor, NECP_POLICY_CONDITION_FLOW_REMOTE_ADDR_EMPTY, 0, "", cond_buf, condition_tlv_length);
}
+ if (condition_mask & NECP_KERNEL_CONDITION_SIGNING_IDENTIFIER) {
+ cond_buf_cursor = necp_buffer_write_tlv(cond_buf_cursor, NECP_POLICY_CONDITION_SIGNING_IDENTIFIER, strlen(policy->cond_signing_identifier) + 1, policy->cond_signing_identifier,
+ cond_buf, condition_tlv_length);
+ }
}
cursor = necp_buffer_write_tlv(cursor, NECP_TLV_POLICY_CONDITION, cond_buf_cursor - cond_buf, cond_buf, tlv_buffer, total_allocated_bytes);
@@ -3152,6 +3163,7 @@ necp_policy_apply(struct necp_session *session, struct necp_session_policy *poli
u_int32_t cond_account_id = 0;
char *cond_domain = NULL;
char *cond_custom_entitlement = NULL;
+ char *cond_signing_identifier = NULL;
pid_t cond_pid = 0;
uid_t cond_uid = 0;
necp_app_id cond_app_id = 0;
@@ -3501,6 +3513,21 @@ necp_policy_apply(struct necp_session *session, struct necp_session_policy *poli
socket_only_conditions = TRUE;
break;
}
+ case NECP_POLICY_CONDITION_SIGNING_IDENTIFIER: {
+ if (condition_length > 0) {
+ if (cond_signing_identifier == NULL) {
+ cond_signing_identifier = necp_copy_string((char *)condition_value, condition_length);
+ if (cond_signing_identifier != NULL) {
+ master_condition_mask |= NECP_KERNEL_CONDITION_SIGNING_IDENTIFIER;
+ socket_only_conditions = TRUE;
+ if (condition_is_negative) {
+ master_condition_negated_mask |= NECP_KERNEL_CONDITION_SIGNING_IDENTIFIER;
+ }
+ }
+ }
+ }
+ break;
+ }
default: {
break;
}
@@ -3681,7 +3708,7 @@ necp_policy_apply(struct necp_session *session, struct necp_session_policy *poli
}
if (socket_layer_non_id_conditions) {
- necp_kernel_policy_id policy_id = necp_kernel_socket_policy_add(policy->order, session->session_order, session->proc_pid, master_condition_mask, master_condition_negated_mask, cond_app_id, cond_real_app_id, cond_custom_entitlement, cond_account_id, cond_domain, cond_pid, cond_uid, cond_bound_interface, cond_traffic_class, cond_protocol, &cond_local_start, &cond_local_end, cond_local_prefix, &cond_remote_start, &cond_remote_end, cond_remote_prefix, &cond_agent_type, cond_client_flags, ultimate_result, ultimate_result_parameter);
+ necp_kernel_policy_id policy_id = necp_kernel_socket_policy_add(policy->order, session->session_order, session->proc_pid, master_condition_mask, master_condition_negated_mask, cond_app_id, cond_real_app_id, cond_custom_entitlement, cond_account_id, cond_domain, cond_pid, cond_uid, cond_bound_interface, cond_traffic_class, cond_protocol, &cond_local_start, &cond_local_end, cond_local_prefix, &cond_remote_start, &cond_remote_end, cond_remote_prefix, &cond_agent_type, cond_client_flags, cond_signing_identifier, ultimate_result, ultimate_result_parameter);
if (policy_id == 0) {
NECPLOG0(LOG_DEBUG, "Error applying socket kernel policy");
@@ -3850,10 +3877,10 @@ necp_kernel_policy_get_new_id(bool socket_level)
return newid;
}
-#define NECP_KERNEL_VALID_SOCKET_CONDITIONS (NECP_KERNEL_CONDITION_APP_ID | NECP_KERNEL_CONDITION_REAL_APP_ID | NECP_KERNEL_CONDITION_DOMAIN | NECP_KERNEL_CONDITION_ACCOUNT_ID | NECP_KERNEL_CONDITION_PID | NECP_KERNEL_CONDITION_UID | NECP_KERNEL_CONDITION_ALL_INTERFACES | NECP_KERNEL_CONDITION_BOUND_INTERFACE | NECP_KERNEL_CONDITION_TRAFFIC_CLASS | NECP_KERNEL_CONDITION_PROTOCOL | NECP_KERNEL_CONDITION_LOCAL_START | NECP_KERNEL_CONDITION_LOCAL_END | NECP_KERNEL_CONDITION_LOCAL_PREFIX | NECP_KERNEL_CONDITION_REMOTE_START | NECP_KERNEL_CONDITION_REMOTE_END | NECP_KERNEL_CONDITION_REMOTE_PREFIX | NECP_KERNEL_CONDITION_ENTITLEMENT | NECP_KERNEL_CONDITION_CUSTOM_ENTITLEMENT | NECP_KERNEL_CONDITION_AGENT_TYPE | NECP_KERNEL_CONDITION_HAS_CLIENT | NECP_KERNEL_CONDITION_LOCAL_NETWORKS | NECP_KERNEL_CONDITION_CLIENT_FLAGS | NECP_KERNEL_CONDITION_LOCAL_EMPTY | NECP_KERNEL_CONDITION_REMOTE_EMPTY | NECP_KERNEL_CONDITION_PLATFORM_BINARY)
+#define NECP_KERNEL_VALID_SOCKET_CONDITIONS (NECP_KERNEL_CONDITION_APP_ID | NECP_KERNEL_CONDITION_REAL_APP_ID | NECP_KERNEL_CONDITION_DOMAIN | NECP_KERNEL_CONDITION_ACCOUNT_ID | NECP_KERNEL_CONDITION_PID | NECP_KERNEL_CONDITION_UID | NECP_KERNEL_CONDITION_ALL_INTERFACES | NECP_KERNEL_CONDITION_BOUND_INTERFACE | NECP_KERNEL_CONDITION_TRAFFIC_CLASS | NECP_KERNEL_CONDITION_PROTOCOL | NECP_KERNEL_CONDITION_LOCAL_START | NECP_KERNEL_CONDITION_LOCAL_END | NECP_KERNEL_CONDITION_LOCAL_PREFIX | NECP_KERNEL_CONDITION_REMOTE_START | NECP_KERNEL_CONDITION_REMOTE_END | NECP_KERNEL_CONDITION_REMOTE_PREFIX | NECP_KERNEL_CONDITION_ENTITLEMENT | NECP_KERNEL_CONDITION_CUSTOM_ENTITLEMENT | NECP_KERNEL_CONDITION_AGENT_TYPE | NECP_KERNEL_CONDITION_HAS_CLIENT | NECP_KERNEL_CONDITION_LOCAL_NETWORKS | NECP_KERNEL_CONDITION_CLIENT_FLAGS | NECP_KERNEL_CONDITION_LOCAL_EMPTY | NECP_KERNEL_CONDITION_REMOTE_EMPTY | NECP_KERNEL_CONDITION_PLATFORM_BINARY | NECP_KERNEL_CONDITION_SIGNING_IDENTIFIER)
static necp_kernel_policy_id
-necp_kernel_socket_policy_add(necp_policy_order order, u_int32_t session_order, int session_pid, u_int32_t condition_mask, u_int32_t condition_negated_mask, necp_app_id cond_app_id, necp_app_id cond_real_app_id, char *cond_custom_entitlement, u_int32_t cond_account_id, char *cond_domain, pid_t cond_pid, uid_t cond_uid, ifnet_t cond_bound_interface, struct necp_policy_condition_tc_range cond_traffic_class, u_int16_t cond_protocol, union necp_sockaddr_union *cond_local_start, union necp_sockaddr_union *cond_local_end, u_int8_t cond_local_prefix, union necp_sockaddr_union *cond_remote_start, union necp_sockaddr_union *cond_remote_end, u_int8_t cond_remote_prefix, struct necp_policy_condition_agent_type *cond_agent_type, u_int32_t cond_client_flags, necp_kernel_policy_result result, necp_kernel_policy_result_parameter result_parameter)
+necp_kernel_socket_policy_add(necp_policy_order order, u_int32_t session_order, int session_pid, u_int32_t condition_mask, u_int32_t condition_negated_mask, necp_app_id cond_app_id, necp_app_id cond_real_app_id, char *cond_custom_entitlement, u_int32_t cond_account_id, char *cond_domain, pid_t cond_pid, uid_t cond_uid, ifnet_t cond_bound_interface, struct necp_policy_condition_tc_range cond_traffic_class, u_int16_t cond_protocol, union necp_sockaddr_union *cond_local_start, union necp_sockaddr_union *cond_local_end, u_int8_t cond_local_prefix, union necp_sockaddr_union *cond_remote_start, union necp_sockaddr_union *cond_remote_end, u_int8_t cond_remote_prefix, struct necp_policy_condition_agent_type *cond_agent_type, u_int32_t cond_client_flags, char *cond_signing_identifier, necp_kernel_policy_result result, necp_kernel_policy_result_parameter result_parameter)
{
struct necp_kernel_socket_policy *new_kernel_policy = NULL;
struct necp_kernel_socket_policy *tmp_kernel_policy = NULL;
@@ -3954,6 +3981,9 @@ necp_kernel_socket_policy_add(necp_policy_order order, u_int32_t session_order,
if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_CLIENT_FLAGS) {
new_kernel_policy->cond_client_flags = cond_client_flags;
}
+ if (new_kernel_policy->condition_mask & NECP_KERNEL_CONDITION_SIGNING_IDENTIFIER) {
+ new_kernel_policy->cond_signing_identifier = cond_signing_identifier;
+ }
new_kernel_policy->result = result;
memcpy(&new_kernel_policy->result_parameter, &result_parameter, sizeof(result_parameter));
@@ -4011,6 +4041,11 @@ necp_kernel_socket_policy_delete(necp_kernel_policy_id policy_id)
policy->cond_custom_entitlement = NULL;
}
+ if (policy->cond_signing_identifier) {
+ FREE(policy->cond_signing_identifier, M_NECP);
+ policy->cond_signing_identifier = NULL;
+ }
+
FREE_ZONE(policy, sizeof(*policy), M_NECP_SOCKET_POLICY);
return TRUE;
}
@@ -5940,7 +5975,7 @@ necp_get_parent_cred_result(proc_t proc, struct necp_socket_info *info)
#define NECP_KERNEL_ADDRESS_TYPE_CONDITIONS (NECP_KERNEL_CONDITION_LOCAL_START | NECP_KERNEL_CONDITION_LOCAL_END | NECP_KERNEL_CONDITION_LOCAL_PREFIX | NECP_KERNEL_CONDITION_REMOTE_START | NECP_KERNEL_CONDITION_REMOTE_END | NECP_KERNEL_CONDITION_REMOTE_PREFIX | NECP_KERNEL_CONDITION_LOCAL_EMPTY | NECP_KERNEL_CONDITION_REMOTE_EMPTY | NECP_KERNEL_CONDITION_LOCAL_NETWORKS)
static void
-necp_application_fillout_info_locked(uuid_t application_uuid, uuid_t real_application_uuid, uuid_t responsible_application_uuid, char *account, char *domain, pid_t pid, uid_t uid, u_int16_t protocol, u_int32_t bound_interface_index, u_int32_t traffic_class, union necp_sockaddr_union *local_addr, union necp_sockaddr_union *remote_addr, u_int16_t local_port, u_int16_t remote_port, bool has_client, proc_t proc, u_int32_t drop_order, u_int32_t client_flags, struct necp_socket_info *info)
+necp_application_fillout_info_locked(uuid_t application_uuid, uuid_t real_application_uuid, uuid_t responsible_application_uuid, char *account, char *domain, pid_t pid, uid_t uid, u_int16_t protocol, u_int32_t bound_interface_index, u_int32_t traffic_class, union necp_sockaddr_union *local_addr, union necp_sockaddr_union *remote_addr, u_int16_t local_port, u_int16_t remote_port, bool has_client, proc_t proc, proc_t responsible_proc, u_int32_t drop_order, u_int32_t client_flags, struct necp_socket_info *info)
{
memset(info, 0, sizeof(struct necp_socket_info));
@@ -5953,18 +5988,6 @@ necp_application_fillout_info_locked(uuid_t application_uuid, uuid_t real_applic
info->drop_order = drop_order;
info->client_flags = client_flags;
- if (necp_kernel_application_policies_condition_mask & NECP_KERNEL_CONDITION_ENTITLEMENT && proc != NULL) {
- info->cred_result = priv_check_cred(proc_ucred(proc), PRIV_NET_PRIVILEGED_NECP_MATCH, 0);
- if (info->cred_result != 0) {
- // Process does not have entitlement, check the parent process
- necp_get_parent_cred_result(proc, info);
- }
- }
-
- if (necp_kernel_application_policies_condition_mask & NECP_KERNEL_CONDITION_PLATFORM_BINARY && proc != NULL) {
- info->is_platform_binary = csproc_get_platform_binary(proc) ? true : false;
- }
-
if (necp_kernel_application_policies_condition_mask & NECP_KERNEL_CONDITION_APP_ID && !uuid_is_null(application_uuid)) {
struct necp_uuid_id_mapping *existing_mapping = necp_uuid_lookup_app_id_locked(application_uuid);
if (existing_mapping) {
@@ -5992,6 +6015,22 @@ necp_application_fillout_info_locked(uuid_t application_uuid, uuid_t real_applic
}
}
+ if (info->used_responsible_pid) {
+ proc = responsible_proc;
+ }
+
+ if (necp_kernel_application_policies_condition_mask & NECP_KERNEL_CONDITION_ENTITLEMENT && proc != NULL) {
+ info->cred_result = priv_check_cred(proc_ucred(proc), PRIV_NET_PRIVILEGED_NECP_MATCH, 0);
+ if (info->cred_result != 0) {
+ // Process does not have entitlement, check the parent process
+ necp_get_parent_cred_result(proc, info);
+ }
+ }
+
+ if (necp_kernel_application_policies_condition_mask & NECP_KERNEL_CONDITION_PLATFORM_BINARY && proc != NULL) {
+ info->is_platform_binary = csproc_get_platform_binary(proc) ? true : false;
+ }
+
if (necp_kernel_application_policies_condition_mask & NECP_KERNEL_CONDITION_ACCOUNT_ID && account != NULL) {
struct necp_string_id_mapping *existing_mapping = necp_lookup_string_to_id_locked(&necp_account_id_list, account);
if (existing_mapping) {
@@ -6132,10 +6171,9 @@ necp_application_find_policy_match_internal(proc_t proc,
bool has_checked_delegation_entitlement = FALSE;
bool has_delegation_entitlement = FALSE;
-#if defined(XNU_TARGET_OS_OSX)
+ proc_t responsible_proc = PROC_NULL;
proc_t effective_proc = proc;
bool release_eproc = false;
-#endif /* defined(XNU_TARGET_OS_OSX) */
if (returned_result == NULL) {
return EINVAL;
@@ -6364,7 +6402,6 @@ necp_application_find_policy_match_internal(proc_t proc,
return 0;
}
-#if defined(XNU_TARGET_OS_OSX)
if (proc_pid(effective_proc) != pid) {
proc_t found_proc = proc_find(pid);
if (found_proc != PROC_NULL) {
@@ -6372,16 +6409,13 @@ necp_application_find_policy_match_internal(proc_t proc,
release_eproc = true;
}
}
+#if defined(XNU_TARGET_OS_OSX)
if (effective_proc->p_responsible_pid > 0 && effective_proc->p_responsible_pid != pid) {
- proc_t responsible_proc = proc_find(effective_proc->p_responsible_pid);
+ responsible_proc = proc_find(effective_proc->p_responsible_pid);
if (responsible_proc != PROC_NULL) {
proc_getexecutableuuid(responsible_proc, responsible_application_uuid, sizeof(responsible_application_uuid));
- proc_rele(responsible_proc);
}
}
- if (release_eproc && effective_proc != PROC_NULL) {
- proc_rele(effective_proc);
- }
#endif /* defined(XNU_TARGET_OS_OSX) */
// Lock
@@ -6389,8 +6423,8 @@ necp_application_find_policy_match_internal(proc_t proc,
u_int32_t route_rule_id_array[MAX_AGGREGATE_ROUTE_RULES];
size_t route_rule_id_array_count = 0;
- necp_application_fillout_info_locked(application_uuid, real_application_uuid, responsible_application_uuid, account, domain, pid, uid, protocol, bound_interface_index, traffic_class, &local_addr, &remote_addr, local_port, remote_port, has_client, proc, drop_order, client_flags, &info);
- matched_policy = necp_socket_find_policy_match_with_info_locked(necp_kernel_socket_policies_app_layer_map, &info, &filter_control_unit, route_rule_id_array, &route_rule_id_array_count, MAX_AGGREGATE_ROUTE_RULES, &service_action, &service, netagent_ids, netagent_use_flags, NECP_MAX_NETAGENTS, required_agent_types, num_required_agent_types, proc, NULL, NULL, &drop_dest_policy_result, &drop_all_bypass);
+ necp_application_fillout_info_locked(application_uuid, real_application_uuid, responsible_application_uuid, account, domain, pid, uid, protocol, bound_interface_index, traffic_class, &local_addr, &remote_addr, local_port, remote_port, has_client, effective_proc, responsible_proc, drop_order, client_flags, &info);
+ matched_policy = necp_socket_find_policy_match_with_info_locked(necp_kernel_socket_policies_app_layer_map, &info, &filter_control_unit, route_rule_id_array, &route_rule_id_array_count, MAX_AGGREGATE_ROUTE_RULES, &service_action, &service, netagent_ids, netagent_use_flags, NECP_MAX_NETAGENTS, required_agent_types, num_required_agent_types, info.used_responsible_pid ? responsible_proc : effective_proc, NULL, NULL, &drop_dest_policy_result, &drop_all_bypass);
if (matched_policy) {
returned_result->policy_id = matched_policy->id;
returned_result->routing_result = matched_policy->result;
@@ -6809,6 +6843,15 @@ necp_application_find_policy_match_internal(proc_t proc,
// Unlock
lck_rw_done(&necp_kernel_policy_lock);
+ if (release_eproc && effective_proc != PROC_NULL) {
+ proc_rele(effective_proc);
+ }
+#if defined(XNU_TARGET_OS_OSX)
+ if (responsible_proc != PROC_NULL) {
+ proc_rele(responsible_proc);
+ }
+#endif
+
return error;
}
@@ -6904,6 +6947,30 @@ necp_socket_check_policy(struct necp_kernel_socket_policy *kernel_policy, necp_a
return FALSE;
}
}
+
+ // Check signing identifier only after APP ID matched
+ if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_SIGNING_IDENTIFIER ||
+ kernel_policy->condition_mask & NECP_KERNEL_CONDITION_SIGNING_IDENTIFIER) {
+ u_int8_t matched = necp_boolean_state_false;
+ const char *signing_id = cs_identity_get(proc ? proc : current_proc());
+
+ if (signing_id != NULL) {
+ size_t signing_id_size = strlen(signing_id) + 1;
+ if (memcmp(signing_id, kernel_policy->cond_signing_identifier, signing_id_size) == 0) {
+ matched = necp_boolean_state_true;
+ }
+ }
+
+ if (kernel_policy->condition_negated_mask & NECP_KERNEL_CONDITION_SIGNING_IDENTIFIER) {
+ if (matched == necp_boolean_state_true) {
+ return FALSE;
+ }
+ } else {
+ if (matched != necp_boolean_state_true) {
+ return FALSE;
+ }
+ }
+ }
}
if (kernel_policy->condition_mask & NECP_KERNEL_CONDITION_REAL_APP_ID) {
@@ -7185,9 +7252,11 @@ necp_socket_calc_flowhash_locked(struct necp_socket_info *info)
}
static void
-necp_socket_fillout_info_locked(struct inpcb *inp, struct sockaddr *override_local_addr, struct sockaddr *override_remote_addr, u_int32_t override_bound_interface, u_int32_t drop_order, struct necp_socket_info *info)
+necp_socket_fillout_info_locked(struct inpcb *inp, struct sockaddr *override_local_addr, struct sockaddr *override_remote_addr, u_int32_t override_bound_interface, u_int32_t drop_order, proc_t *socket_proc, struct necp_socket_info *info)
{
struct socket *so = NULL;
+ proc_t sock_proc = NULL;
+ proc_t curr_proc = current_proc();
memset(info, 0, sizeof(struct necp_socket_info));
@@ -7278,8 +7347,20 @@ necp_socket_fillout_info_locked(struct inpcb *inp, struct sockaddr *override_loc
}
}
+ pid_t socket_pid =
+#if defined(XNU_TARGET_OS_OSX)
+ info->used_responsible_pid ? so->so_rpid :
+#endif
+ ((so->so_flags & SOF_DELEGATED) ? so->e_pid : so->last_pid);
+ if (socket_pid && (socket_pid != proc_pid(curr_proc))) {
+ sock_proc = proc_find(socket_pid);
+ if (socket_proc) {
+ *socket_proc = sock_proc;
+ }
+ }
+
if (necp_kernel_socket_policies_condition_mask & NECP_KERNEL_CONDITION_PLATFORM_BINARY) {
- info->is_platform_binary = csproc_get_platform_binary(current_proc()) ? true : false;
+ info->is_platform_binary = csproc_get_platform_binary(sock_proc ? sock_proc : curr_proc) ? true : false;
}
if (necp_kernel_socket_policies_condition_mask & NECP_KERNEL_CONDITION_ACCOUNT_ID && inp->inp_necp_attributes.inp_account != NULL) {
@@ -7612,6 +7693,7 @@ necp_socket_find_policy_match(struct inpcb *inp, struct sockaddr *override_local
necp_kernel_policy_service service = { 0, 0 };
u_int32_t drop_dest_policy_result = NECP_KERNEL_POLICY_RESULT_NONE;
necp_drop_all_bypass_check_result_t drop_all_bypass = NECP_DROP_ALL_BYPASS_CHECK_RESULT_NONE;
+ proc_t socket_proc = NULL;
u_int32_t netagent_ids[NECP_MAX_NETAGENTS];
memset(&netagent_ids, 0, sizeof(netagent_ids));
@@ -7679,7 +7761,7 @@ necp_socket_find_policy_match(struct inpcb *inp, struct sockaddr *override_local
// Lock
lck_rw_lock_shared(&necp_kernel_policy_lock);
- necp_socket_fillout_info_locked(inp, override_local_addr, override_remote_addr, override_bound_interface, drop_order, &info);
+ necp_socket_fillout_info_locked(inp, override_local_addr, override_remote_addr, override_bound_interface, drop_order, &socket_proc, &info);
// Check info
u_int32_t flowhash = necp_socket_calc_flowhash_locked(&info);
@@ -7691,6 +7773,10 @@ necp_socket_find_policy_match(struct inpcb *inp, struct sockaddr *override_local
// Unlock
lck_rw_done(&necp_kernel_policy_lock);
+ if (socket_proc) {
+ proc_rele(socket_proc);
+ }
+
return inp->inp_policyresult.policy_id;
}
@@ -7700,7 +7786,7 @@ necp_socket_find_policy_match(struct inpcb *inp, struct sockaddr *override_local
necp_kernel_policy_id skip_policy_id = NECP_KERNEL_POLICY_ID_NONE;
u_int32_t route_rule_id_array[MAX_AGGREGATE_ROUTE_RULES];
size_t route_rule_id_array_count = 0;
- matched_policy = necp_socket_find_policy_match_with_info_locked(necp_kernel_socket_policies_map[NECP_SOCKET_MAP_APP_ID_TO_BUCKET(info.application_id)], &info, &filter_control_unit, route_rule_id_array, &route_rule_id_array_count, MAX_AGGREGATE_ROUTE_RULES, &service_action, &service, netagent_ids, NULL, NECP_MAX_NETAGENTS, NULL, 0, current_proc(), &skip_policy_id, inp->inp_route.ro_rt, &drop_dest_policy_result, &drop_all_bypass);
+ matched_policy = necp_socket_find_policy_match_with_info_locked(necp_kernel_socket_policies_map[NECP_SOCKET_MAP_APP_ID_TO_BUCKET(info.application_id)], &info, &filter_control_unit, route_rule_id_array, &route_rule_id_array_count, MAX_AGGREGATE_ROUTE_RULES, &service_action, &service, netagent_ids, NULL, NECP_MAX_NETAGENTS, NULL, 0, socket_proc ? socket_proc : current_proc(), &skip_policy_id, inp->inp_route.ro_rt, &drop_dest_policy_result, &drop_all_bypass);
// If the socket matched a scoped service policy, mark as Drop if not registered.
// This covers the cases in which a service is required (on demand) but hasn't started yet.
@@ -7732,6 +7818,11 @@ necp_socket_find_policy_match(struct inpcb *inp, struct sockaddr *override_local
// Unlock
lck_rw_done(&necp_kernel_policy_lock);
+
+ if (socket_proc) {
+ proc_rele(socket_proc);
+ }
+
return NECP_KERNEL_POLICY_ID_NONE;
}
}
@@ -7773,6 +7864,11 @@ necp_socket_find_policy_match(struct inpcb *inp, struct sockaddr *override_local
// Unlock
lck_rw_done(&necp_kernel_policy_lock);
+
+ if (socket_proc) {
+ proc_rele(socket_proc);
+ }
+
return NECP_KERNEL_POLICY_ID_NONE;
}
}
@@ -7825,7 +7921,7 @@ necp_socket_find_policy_match(struct inpcb *inp, struct sockaddr *override_local
// Mark socket as a drop if set
drop_all = true;
if (drop_all_bypass == NECP_DROP_ALL_BYPASS_CHECK_RESULT_NONE) {
- drop_all_bypass = necp_check_drop_all_bypass_result(NULL);
+ drop_all_bypass = necp_check_drop_all_bypass_result(socket_proc ? socket_proc : current_proc());
}
}
if (drop_all && drop_all_bypass == NECP_DROP_ALL_BYPASS_CHECK_RESULT_FALSE) {
@@ -7856,6 +7952,10 @@ necp_socket_find_policy_match(struct inpcb *inp, struct sockaddr *override_local
tcp_mtudisc(inp, 0);
}
+ if (socket_proc) {
+ proc_rele(socket_proc);
+ }
+
return matched_policy_id;
}
@@ -9051,6 +9151,7 @@ necp_socket_is_allowed_to_send_recv_internal(struct inpcb *inp, struct sockaddr
necp_drop_all_bypass_check_result_t drop_all_bypass = NECP_DROP_ALL_BYPASS_CHECK_RESULT_NONE;
u_int32_t netagent_ids[NECP_MAX_NETAGENTS];
memset(&netagent_ids, 0, sizeof(netagent_ids));
+ proc_t socket_proc = NULL;
if (return_policy_id) {
*return_policy_id = NECP_KERNEL_POLICY_ID_NONE;
@@ -9132,7 +9233,7 @@ necp_socket_is_allowed_to_send_recv_internal(struct inpcb *inp, struct sockaddr
// Actually calculate policy result
lck_rw_lock_shared(&necp_kernel_policy_lock);
- necp_socket_fillout_info_locked(inp, override_local_addr, override_remote_addr, 0, drop_order, &info);
+ necp_socket_fillout_info_locked(inp, override_local_addr, override_remote_addr, 0, drop_order, &socket_proc, &info);
flowhash = necp_socket_calc_flowhash_locked(&info);
if (inp->inp_policyresult.policy_id != NECP_KERNEL_POLICY_ID_NONE &&
@@ -9162,7 +9263,7 @@ necp_socket_is_allowed_to_send_recv_internal(struct inpcb *inp, struct sockaddr
u_int32_t route_rule_id_array[MAX_AGGREGATE_ROUTE_RULES];
size_t route_rule_id_array_count = 0;
- struct necp_kernel_socket_policy *matched_policy = necp_socket_find_policy_match_with_info_locked(necp_kernel_socket_policies_map[NECP_SOCKET_MAP_APP_ID_TO_BUCKET(info.application_id)], &info, NULL, route_rule_id_array, &route_rule_id_array_count, MAX_AGGREGATE_ROUTE_RULES, &service_action, &service, netagent_ids, NULL, NECP_MAX_NETAGENTS, NULL, 0, current_proc(), return_skip_policy_id, inp->inp_route.ro_rt, &drop_dest_policy_result, &drop_all_bypass);
+ struct necp_kernel_socket_policy *matched_policy = necp_socket_find_policy_match_with_info_locked(necp_kernel_socket_policies_map[NECP_SOCKET_MAP_APP_ID_TO_BUCKET(info.application_id)], &info, NULL, route_rule_id_array, &route_rule_id_array_count, MAX_AGGREGATE_ROUTE_RULES, &service_action, &service, netagent_ids, NULL, NECP_MAX_NETAGENTS, NULL, 0, socket_proc ? socket_proc : current_proc(), return_skip_policy_id, inp->inp_route.ro_rt, &drop_dest_policy_result, &drop_all_bypass);
if (route_rule_id_array_count == 1) {
route_rule_id = route_rule_id_array[0];
@@ -9201,7 +9302,7 @@ necp_socket_is_allowed_to_send_recv_internal(struct inpcb *inp, struct sockaddr
if (necp_drop_all_order > 0 || info.drop_order > 0 || drop_dest_policy_result == NECP_KERNEL_POLICY_RESULT_DROP) {
drop_all = true;
if (drop_all_bypass == NECP_DROP_ALL_BYPASS_CHECK_RESULT_NONE) {
- drop_all_bypass = necp_check_drop_all_bypass_result(NULL);
+ drop_all_bypass = necp_check_drop_all_bypass_result(socket_proc ? socket_proc : current_proc());
}
}
if (drop_all && drop_all_bypass == NECP_DROP_ALL_BYPASS_CHECK_RESULT_FALSE) {
@@ -9223,6 +9324,10 @@ necp_socket_is_allowed_to_send_recv_internal(struct inpcb *inp, struct sockaddr
soevent(inp->inp_socket, (SO_FILT_HINT_LOCKED | SO_FILT_HINT_IFDENIED));
}
+ if (socket_proc) {
+ proc_rele(socket_proc);
+ }
+
return allowed_to_receive;
}
diff --git a/bsd/net/necp.h b/bsd/net/necp.h
index f658ad1ed..1da29404a 100644
--- a/bsd/net/necp.h
+++ b/bsd/net/necp.h
@@ -149,6 +149,7 @@ struct necp_packet_header {
#define NECP_POLICY_CONDITION_FLOW_LOCAL_ADDR_EMPTY 25 // N/A
#define NECP_POLICY_CONDITION_FLOW_REMOTE_ADDR_EMPTY 26 // N/A
#define NECP_POLICY_CONDITION_PLATFORM_BINARY 27 // N/A
+#define NECP_POLICY_CONDITION_SIGNING_IDENTIFIER 28 // String
/*
* Results
@@ -991,6 +992,7 @@ struct necp_kernel_socket_policy {
union necp_sockaddr_union cond_remote_end; // Matches IP address range
u_int8_t cond_remote_prefix; // Defines subnet
struct necp_policy_condition_agent_type cond_agent_type;
+ char *cond_signing_identifier; // String
necp_kernel_policy_result result;
necp_kernel_policy_result_parameter result_parameter;
diff --git a/bsd/netinet/flow_divert.c b/bsd/netinet/flow_divert.c
index 83d34f1a7..a35ed9ab2 100644
--- a/bsd/netinet/flow_divert.c
+++ b/bsd/netinet/flow_divert.c
@@ -1458,21 +1458,21 @@ flow_divert_send_close_if_needed(struct flow_divert_pcb *fd_cb)
static errno_t
flow_divert_send_data_packet(struct flow_divert_pcb *fd_cb, mbuf_t data, size_t data_len, struct sockaddr *toaddr, Boolean force)
{
- mbuf_t packet;
- mbuf_t last;
+ mbuf_t packet = NULL;
+ mbuf_t last = NULL;
int error = 0;
error = flow_divert_packet_init(fd_cb, FLOW_DIVERT_PKT_DATA, &packet);
- if (error) {
+ if (error || packet == NULL) {
FDLOG(LOG_ERR, fd_cb, "flow_divert_packet_init failed: %d", error);
- return error;
+ goto done;
}
if (toaddr != NULL) {
error = flow_divert_append_target_endpoint_tlv(packet, toaddr);
if (error) {
FDLOG(LOG_ERR, fd_cb, "flow_divert_append_target_endpoint_tlv() failed: %d", error);
- return error;
+ goto done;
}
}
@@ -1482,15 +1482,21 @@ flow_divert_send_data_packet(struct flow_divert_pcb *fd_cb, mbuf_t data, size_t
mbuf_pkthdr_adjustlen(packet, data_len);
}
error = flow_divert_send_packet(fd_cb, packet, force);
-
- if (error) {
- mbuf_setnext(last, NULL);
- mbuf_freem(packet);
- } else {
+ if (error == 0 && data_len > 0) {
fd_cb->bytes_sent += data_len;
flow_divert_add_data_statistics(fd_cb, data_len, TRUE);
}
+done:
+ if (error) {
+ if (last != NULL) {
+ mbuf_setnext(last, NULL);
+ }
+ if (packet != NULL) {
+ mbuf_freem(packet);
+ }
+ }
+
return error;
}
diff --git a/bsd/netinet/in.c b/bsd/netinet/in.c
index f51b22b4e..1e8a63778 100644
--- a/bsd/netinet/in.c
+++ b/bsd/netinet/in.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -695,7 +695,7 @@ inctl_ifaddr(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
hostIsNew = 0;
}
}
- if (mask.sin_len) {
+ if (mask.sin_len != 0) {
IFA_UNLOCK(&ia->ia_ifa);
in_ifscrub(ifp, ia, 0);
IFA_LOCK(&ia->ia_ifa);
@@ -710,7 +710,10 @@ inctl_ifaddr(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
in_ifscrub(ifp, ia, 0);
IFA_LOCK(&ia->ia_ifa);
ia->ia_dstaddr = broadaddr;
+ ia->ia_dstaddr.sin_family = AF_INET;
ia->ia_dstaddr.sin_len = sizeof(struct sockaddr_in);
+ ia->ia_dstaddr.sin_port = 0;
+ bzero(&ia->ia_dstaddr.sin_zero, sizeof(ia->ia_dstaddr.sin_zero));
maskIsNew = 1; /* We lie; but the effect's the same */
}
if (addr.sin_family == AF_INET && (hostIsNew || maskIsNew)) {
@@ -725,7 +728,11 @@ inctl_ifaddr(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
IFA_LOCK(&ia->ia_ifa);
if ((ifp->if_flags & IFF_BROADCAST) &&
(broadaddr.sin_family == AF_INET)) {
- ia->ia_broadaddr = broadaddr;
+ ia->ia_broadaddr.sin_family = AF_INET;
+ ia->ia_broadaddr.sin_len = sizeof(struct sockaddr_in);
+ ia->ia_broadaddr.sin_port = 0;
+ ia->ia_broadaddr.sin_addr = broadaddr.sin_addr;
+ bzero(&ia->ia_broadaddr.sin_zero, sizeof(ia->ia_broadaddr.sin_zero));
}
/*
@@ -940,10 +947,13 @@ inctl_ifdstaddr(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
VERIFY(ia != NULL);
IFA_LOCK(&ia->ia_ifa);
dstaddr = ia->ia_dstaddr;
+
bcopy(&ifr->ifr_dstaddr, &ia->ia_dstaddr, sizeof(dstaddr));
- if (ia->ia_dstaddr.sin_family == AF_INET) {
- ia->ia_dstaddr.sin_len = sizeof(struct sockaddr_in);
- }
+ ia->ia_dstaddr.sin_family = AF_INET;
+ ia->ia_dstaddr.sin_len = sizeof(struct sockaddr_in);
+ ia->ia_dstaddr.sin_port = 0;
+ bzero(&ia->ia_dstaddr.sin_zero, sizeof(ia->ia_dstaddr.sin_zero));
+
IFA_UNLOCK(&ia->ia_ifa);
/*
* NOTE: SIOCSIFDSTADDR is defined with struct ifreq
@@ -1061,6 +1071,11 @@ inctl_ifbrdaddr(struct ifnet *ifp, struct in_ifaddr *ia, u_long cmd,
bcopy(&ifr->ifr_broadaddr, &ia->ia_broadaddr,
sizeof(struct sockaddr_in));
+ ia->ia_broadaddr.sin_family = AF_INET;
+ ia->ia_broadaddr.sin_len = sizeof(struct sockaddr_in);
+ ia->ia_broadaddr.sin_port = 0;
+ bzero(&ia->ia_broadaddr.sin_zero, sizeof(ia->ia_broadaddr.sin_zero));
+
ev_msg.vendor_code = KEV_VENDOR_APPLE;
ev_msg.kev_class = KEV_NETWORK_CLASS;
ev_msg.kev_subclass = KEV_INET_SUBCLASS;
@@ -1491,7 +1506,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
- ia->ia_sockmask.sin_len = 8;
+ ia->ia_sockmask.sin_len = offsetof(struct sockaddr_in, sin_zero);
if (ifp->if_flags & IFF_BROADCAST) {
ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
ia->ia_broadaddr.sin_family = AF_INET;
diff --git a/bsd/netinet/ip_input.c b/bsd/netinet/ip_input.c
index 1cdd96aff..1c162bf8c 100644
--- a/bsd/netinet/ip_input.c
+++ b/bsd/netinet/ip_input.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -137,6 +137,8 @@
#include
#endif /* IPSEC */
+#include
+
#define DBG_LAYER_BEG NETDBG_CODE(DBG_NETIP, 0)
#define DBG_LAYER_END NETDBG_CODE(DBG_NETIP, 2)
#define DBG_FNC_IP_INPUT NETDBG_CODE(DBG_NETIP, (2 << 8))
@@ -246,21 +248,57 @@ SYSCTL_UINT(_net_inet_ip, OID_AUTO, adj_partial_sum,
"Perform partial sum adjustment of trailing bytes at IP layer");
/*
- * XXX - Setting ip_checkinterface mostly implements the receive side of
- * the Strong ES model described in RFC 1122, but since the routing table
- * and transmit implementation do not implement the Strong ES model,
- * setting this to 1 results in an odd hybrid.
+ * ip_checkinterface controls the receive side of the models for multihoming
+ * that are discussed in RFC 1122.
+ *
+ * ip_checkinterface values are:
+ * IP_CHECKINTERFACE_WEAK_ES:
+ * This corresponds to the Weak End-System model where incoming packets from
+ * any interface are accepted provided the destination address of the incoming packet
+ * is assigned to some interface.
+ *
+ * IP_CHECKINTERFACE_HYBRID_ES:
+ * The Hybrid End-System model use the Strong End-System for tunnel interfaces
+ * (ipsec and utun) and the weak End-System model for other interfaces families.
+ * This prevents a rogue middle box to probe for signs of TCP connections
+ * that use the tunnel interface.
+ *
+ * IP_CHECKINTERFACE_STRONG_ES:
+ * The Strong model model requires the packet arrived on an interface that
+ * is assigned the destination address of the packet.
*
- * XXX - ip_checkinterface currently must be disabled if you use ipnat
+ * Since the routing table and transmit implementation do not implement the Strong ES model,
+ * setting this to a value different from IP_CHECKINTERFACE_WEAK_ES may lead to unexpected results.
+ *
+ * When forwarding is enabled, the system reverts to the Weak ES model as a router
+ * is expected by design to receive packets from several interfaces to the same address.
+ *
+ * XXX - ip_checkinterface currently must be set to IP_CHECKINTERFACE_WEAK_ES if you use ipnat
* to translate the destination address to another local interface.
*
- * XXX - ip_checkinterface must be disabled if you add IP aliases
+ * XXX - ip_checkinterface must be set to IP_CHECKINTERFACE_WEAK_ES if you add IP aliases
* to the loopback interface instead of the interface where the
* packets for those addresses are received.
*/
-static int ip_checkinterface = 0;
-SYSCTL_INT(_net_inet_ip, OID_AUTO, check_interface, CTLFLAG_RW | CTLFLAG_LOCKED,
- &ip_checkinterface, 0, "Verify packet arrives on correct interface");
+#define IP_CHECKINTERFACE_WEAK_ES 0
+#define IP_CHECKINTERFACE_HYBRID_ES 1
+#define IP_CHECKINTERFACE_STRONG_ES 2
+
+static int ip_checkinterface = IP_CHECKINTERFACE_HYBRID_ES;
+
+static int sysctl_ip_checkinterface SYSCTL_HANDLER_ARGS;
+SYSCTL_PROC(_net_inet_ip, OID_AUTO, check_interface,
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
+ 0, 0, sysctl_ip_checkinterface, "I", "Verify packet arrives on correct interface");
+
+#if (DEBUG || DEVELOPMENT)
+#define IP_CHECK_IF_DEBUG 1
+#else
+#define IP_CHECK_IF_DEBUG 0
+#endif /* (DEBUG || DEVELOPMENT) */
+static int ip_checkinterface_debug = IP_CHECK_IF_DEBUG;
+SYSCTL_INT(_net_inet_ip, OID_AUTO, checkinterface_debug, CTLFLAG_RW | CTLFLAG_LOCKED,
+ &ip_checkinterface_debug, IP_CHECK_IF_DEBUG, "");
static int ip_chaining = 1;
SYSCTL_INT(_net_inet_ip, OID_AUTO, rx_chaining, CTLFLAG_RW | CTLFLAG_LOCKED,
@@ -425,6 +463,16 @@ SYSCTL_INT(_net_inet_ip, OID_AUTO, random_id, CTLFLAG_RW | CTLFLAG_LOCKED,
} while (0)
#endif /* !__i386__ && !__x86_64__ */
+
+typedef enum ip_check_if_result {
+ IP_CHECK_IF_NONE = 0,
+ IP_CHECK_IF_OURS = 1,
+ IP_CHECK_IF_DROP = 2,
+ IP_CHECK_IF_FORWARD = 3
+} ip_check_if_result_t;
+
+static ip_check_if_result_t ip_input_check_interface(struct mbuf **, struct ip *, struct ifnet *);
+
/*
* GRE input handler function, settable via ip_gre_register_input() for PPTP.
*/
@@ -542,6 +590,17 @@ ip_init(struct protosw *pp, struct domain *dp)
ipf_init();
+ PE_parse_boot_argn("ip_checkinterface", &i, sizeof(i));
+ switch (i) {
+ case IP_CHECKINTERFACE_WEAK_ES:
+ case IP_CHECKINTERFACE_HYBRID_ES:
+ case IP_CHECKINTERFACE_STRONG_ES:
+ ip_checkinterface = i;
+ break;
+ default:
+ break;
+ }
+
#if IPSEC
sadb_stat_mutex_grp_attr = lck_grp_attr_alloc_init();
sadb_stat_mutex_grp = lck_grp_alloc_init("sadb_stat",
@@ -681,11 +740,6 @@ ip_proto_dispatch_in(struct mbuf *m, int hlen, u_int8_t proto,
/* Perform IP header alignment fixup (post-filters), if needed */
IP_HDR_ALIGNMENT_FIXUP(m, m->m_pkthdr.rcvif, return );
- /*
- * If there isn't a specific lock for the protocol
- * we're about to call, use the generic lock for AF_INET.
- * otherwise let the protocol deal with its own locking
- */
ip = mtod(m, struct ip *);
if (changed_header) {
@@ -693,6 +747,11 @@ ip_proto_dispatch_in(struct mbuf *m, int hlen, u_int8_t proto,
ip->ip_off = ntohs(ip->ip_off);
}
+ /*
+ * If there isn't a specific lock for the protocol
+ * we're about to call, use the generic lock for AF_INET.
+ * otherwise let the protocol deal with its own locking
+ */
if ((pr_input = ip_protox[ip->ip_p]->pr_input) == NULL) {
m_freem(m);
} else if (!(ip_protox[ip->ip_p]->pr_flags & PR_PROTOLOCK)) {
@@ -837,7 +896,7 @@ ip_input_dispatch_chain(struct mbuf *m)
ip = mtod(tmp_mbuf, struct ip *);
hlen = IP_VHL_HL(ip->ip_vhl) << 2;
- while (tmp_mbuf) {
+ while (tmp_mbuf != NULL) {
nxt_mbuf = mbuf_nextpkt(tmp_mbuf);
mbuf_setnextpkt(tmp_mbuf, NULL);
@@ -862,7 +921,7 @@ ip_input_setdst_chain(struct mbuf *m, uint32_t ifindex, struct in_ifaddr *ia)
{
struct mbuf *tmp_mbuf = m;
- while (tmp_mbuf) {
+ while (tmp_mbuf != NULL) {
ip_setdstifaddr_info(tmp_mbuf, ifindex, ia);
tmp_mbuf = mbuf_nextpkt(tmp_mbuf);
}
@@ -1411,14 +1470,175 @@ ip_input_first_pass(struct mbuf *m, u_int32_t *div_info,
#endif
}
+/*
+ * Because the call to m_pullup() may freem the mbuf, the function frees the mbuf packet
+ * chain before it return IP_CHECK_IF_DROP
+ */
+static ip_check_if_result_t
+ip_input_check_interface(struct mbuf **mp, struct ip *ip, struct ifnet *inifp)
+{
+ struct mbuf *m = *mp;
+ struct in_ifaddr *ia = NULL;
+ struct in_ifaddr *best_ia = NULL;
+ struct ifnet *match_ifp = NULL;
+ ip_check_if_result_t result = IP_CHECK_IF_NONE;
+
+ /*
+ * Host broadcast and all network broadcast addresses are always a match
+ */
+ if (ip->ip_dst.s_addr == (u_int32_t)INADDR_BROADCAST ||
+ ip->ip_dst.s_addr == INADDR_ANY) {
+ ip_input_setdst_chain(m, inifp->if_index, NULL);
+ return IP_CHECK_IF_OURS;
+ }
+
+ /*
+ * Check for a match in the hash bucket.
+ */
+ lck_rw_lock_shared(in_ifaddr_rwlock);
+ TAILQ_FOREACH(ia, INADDR_HASH(ip->ip_dst.s_addr), ia_hash) {
+ if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr) {
+ best_ia = ia;
+ match_ifp = best_ia->ia_ifp;
+
+ if (ia->ia_ifp == inifp || (inifp->if_flags & IFF_LOOPBACK) ||
+ (m->m_pkthdr.pkt_flags & PKTF_LOOP)) {
+ /*
+ * A locally originated packet or packet from the loopback
+ * interface is always an exact interface address match
+ */
+ match_ifp = inifp;
+ break;
+ }
+ /*
+ * Continue the loop in case there's a exact match with another
+ * interface
+ */
+ }
+ }
+ if (best_ia != NULL) {
+ if (match_ifp != inifp && ipforwarding == 0 &&
+ ((ip_checkinterface == IP_CHECKINTERFACE_HYBRID_ES &&
+ (match_ifp->if_family == IFNET_FAMILY_IPSEC ||
+ match_ifp->if_family == IFNET_FAMILY_UTUN)) ||
+ ip_checkinterface == IP_CHECKINTERFACE_STRONG_ES)) {
+ /*
+ * Drop when interface address check is strict and forwarding
+ * is disabled
+ */
+ result = IP_CHECK_IF_DROP;
+ } else {
+ result = IP_CHECK_IF_OURS;
+ ip_input_setdst_chain(m, 0, best_ia);
+ }
+ }
+ lck_rw_done(in_ifaddr_rwlock);
+
+ if (result == IP_CHECK_IF_NONE && (inifp->if_flags & IFF_BROADCAST)) {
+ /*
+ * Check for broadcast addresses.
+ *
+ * Only accept broadcast packets that arrive via the matching
+ * interface. Reception of forwarded directed broadcasts would be
+ * handled via ip_forward() and ether_frameout() with the loopback
+ * into the stack for SIMPLEX interfaces handled by ether_frameout().
+ */
+ struct ifaddr *ifa;
+
+ ifnet_lock_shared(inifp);
+ TAILQ_FOREACH(ifa, &inifp->if_addrhead, ifa_link) {
+ if (ifa->ifa_addr->sa_family != AF_INET) {
+ continue;
+ }
+ ia = ifatoia(ifa);
+ if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == ip->ip_dst.s_addr ||
+ ia->ia_netbroadcast.s_addr == ip->ip_dst.s_addr) {
+ ip_input_setdst_chain(m, 0, ia);
+ result = IP_CHECK_IF_OURS;
+ match_ifp = inifp;
+ break;
+ }
+ }
+ ifnet_lock_done(inifp);
+ }
+
+ /* Allow DHCP/BootP responses through */
+ if (result == IP_CHECK_IF_NONE && (inifp->if_eflags & IFEF_AUTOCONFIGURING) &&
+ ip->ip_p == IPPROTO_UDP && (IP_VHL_HL(ip->ip_vhl) << 2) == sizeof(struct ip)) {
+ struct udpiphdr *ui;
+
+ if (m->m_len < sizeof(struct udpiphdr)) {
+ if ((m = m_pullup(m, sizeof(struct udpiphdr))) == NULL) {
+ OSAddAtomic(1, &udpstat.udps_hdrops);
+ *mp = NULL;
+ return IP_CHECK_IF_DROP;
+ }
+ /*
+ * m_pullup can return a different mbuf
+ */
+ *mp = m;
+ ip = mtod(m, struct ip *);
+ }
+ ui = mtod(m, struct udpiphdr *);
+ if (ntohs(ui->ui_dport) == IPPORT_BOOTPC) {
+ ASSERT(m->m_nextpkt == NULL);
+ ip_setdstifaddr_info(m, inifp->if_index, NULL);
+ result = IP_CHECK_IF_OURS;
+ match_ifp = inifp;
+ }
+ }
+
+ if (result == IP_CHECK_IF_NONE) {
+ if (ipforwarding == 0) {
+ result = IP_CHECK_IF_DROP;
+ } else {
+ result = IP_CHECK_IF_FORWARD;
+ ip_input_setdst_chain(m, inifp->if_index, NULL);
+ }
+ }
+
+ if (result == IP_CHECK_IF_OURS && match_ifp != inifp) {
+ ipstat.ips_rcv_if_weak_match++;
+
+ /* Logging is too noisy when forwarding is enabled */
+ if (ip_checkinterface_debug != 0 && ipforwarding == 0) {
+ char src_str[MAX_IPv4_STR_LEN];
+ char dst_str[MAX_IPv4_STR_LEN];
+
+ inet_ntop(AF_INET, &ip->ip_src, src_str, sizeof(src_str));
+ inet_ntop(AF_INET, &ip->ip_dst, dst_str, sizeof(dst_str));
+ os_log_info(OS_LOG_DEFAULT,
+ "%s: weak ES interface match to %s for packet from %s to %s proto %u received via %s",
+ __func__, best_ia->ia_ifp->if_xname, src_str, dst_str, ip->ip_p, inifp->if_xname);
+ }
+ } else if (result == IP_CHECK_IF_DROP) {
+ if (ip_checkinterface_debug > 0) {
+ char src_str[MAX_IPv4_STR_LEN];
+ char dst_str[MAX_IPv4_STR_LEN];
+
+ inet_ntop(AF_INET, &ip->ip_src, src_str, sizeof(src_str));
+ inet_ntop(AF_INET, &ip->ip_dst, dst_str, sizeof(dst_str));
+ os_log_info(OS_LOG_DEFAULT,
+ "%s: no interface match for packet from %s to %s proto %u received via %s",
+ __func__, src_str, dst_str, ip->ip_p, inifp->if_xname);
+ }
+ struct mbuf *tmp_mbuf = m;
+ while (tmp_mbuf != NULL) {
+ ipstat.ips_rcv_if_no_match++;
+ tmp_mbuf = tmp_mbuf->m_nextpkt;
+ }
+ m_freem_list(m);
+ *mp = NULL;
+ }
+
+ return result;
+}
+
static void
ip_input_second_pass(struct mbuf *m, struct ifnet *inifp, u_int32_t div_info,
int npkts_in_chain, int bytes_in_chain, struct ip_fw_in_args *args, int ours)
{
- unsigned int checkif;
struct mbuf *tmp_mbuf = NULL;
- struct in_ifaddr *ia = NULL;
- struct in_addr pkt_dst;
unsigned int hlen;
#if !IPFIREWALL
@@ -1460,7 +1680,7 @@ ip_input_second_pass(struct mbuf *m, struct ifnet *inifp, u_int32_t div_info,
*/
tmp_mbuf = m;
if (TAILQ_EMPTY(&in_ifaddrhead)) {
- while (tmp_mbuf) {
+ while (tmp_mbuf != NULL) {
if (!(tmp_mbuf->m_flags & (M_MCAST | M_BCAST))) {
ip_setdstifaddr_info(tmp_mbuf, inifp->if_index,
NULL);
@@ -1469,16 +1689,6 @@ ip_input_second_pass(struct mbuf *m, struct ifnet *inifp, u_int32_t div_info,
}
goto ours;
}
- /*
- * Cache the destination address of the packet; this may be
- * changed by use of 'ipfw fwd'.
- */
-#if IPFIREWALL
- pkt_dst = args->fwai_next_hop == NULL ?
- ip->ip_dst : args->fwai_next_hop->sin_addr;
-#else /* !IPFIREWALL */
- pkt_dst = ip->ip_dst;
-#endif /* !IPFIREWALL */
/*
* Enable a consistency check between the destination address
@@ -1494,63 +1704,17 @@ ip_input_second_pass(struct mbuf *m, struct ifnet *inifp, u_int32_t div_info,
* to the loopback interface instead of the interface where
* the packets are received.
*/
- checkif = ip_checkinterface && (ipforwarding == 0) &&
- !(inifp->if_flags & IFF_LOOPBACK) &&
- !(m->m_pkthdr.pkt_flags & PKTF_LOOP)
-#if IPFIREWALL
- && (args->fwai_next_hop == NULL);
-#else /* !IPFIREWALL */
- ;
-#endif /* !IPFIREWALL */
+ if (!IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
+ ip_check_if_result_t ip_check_if_result = IP_CHECK_IF_NONE;
- /*
- * Check for exact addresses in the hash bucket.
- */
- lck_rw_lock_shared(in_ifaddr_rwlock);
- TAILQ_FOREACH(ia, INADDR_HASH(pkt_dst.s_addr), ia_hash) {
- /*
- * If the address matches, verify that the packet
- * arrived via the correct interface if checking is
- * enabled.
- */
- if (IA_SIN(ia)->sin_addr.s_addr == pkt_dst.s_addr &&
- (!checkif || ia->ia_ifp == inifp)) {
- ip_input_setdst_chain(m, 0, ia);
- lck_rw_done(in_ifaddr_rwlock);
+ ip_check_if_result = ip_input_check_interface(&m, ip, inifp);
+ ASSERT(ip_check_if_result != IP_CHECK_IF_NONE);
+ if (ip_check_if_result == IP_CHECK_IF_OURS) {
goto ours;
+ } else if (ip_check_if_result == IP_CHECK_IF_DROP) {
+ return;
}
- }
- lck_rw_done(in_ifaddr_rwlock);
-
- /*
- * Check for broadcast addresses.
- *
- * Only accept broadcast packets that arrive via the matching
- * interface. Reception of forwarded directed broadcasts would be
- * handled via ip_forward() and ether_frameout() with the loopback
- * into the stack for SIMPLEX interfaces handled by ether_frameout().
- */
- if (inifp->if_flags & IFF_BROADCAST) {
- struct ifaddr *ifa;
-
- ifnet_lock_shared(inifp);
- TAILQ_FOREACH(ifa, &inifp->if_addrhead, ifa_link) {
- if (ifa->ifa_addr->sa_family != AF_INET) {
- continue;
- }
- ia = ifatoia(ifa);
- if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==
- pkt_dst.s_addr || ia->ia_netbroadcast.s_addr ==
- pkt_dst.s_addr) {
- ip_input_setdst_chain(m, 0, ia);
- ifnet_lock_done(inifp);
- goto ours;
- }
- }
- ifnet_lock_done(inifp);
- }
-
- if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
+ } else {
struct in_multi *inm;
/*
* See if we belong to the destination multicast group on the
@@ -1570,23 +1734,9 @@ ip_input_second_pass(struct mbuf *m, struct ifnet *inifp, u_int32_t div_info,
goto ours;
}
- if (ip->ip_dst.s_addr == (u_int32_t)INADDR_BROADCAST ||
- ip->ip_dst.s_addr == INADDR_ANY) {
- ip_input_setdst_chain(m, inifp->if_index, NULL);
- goto ours;
- }
-
- if (ip->ip_p == IPPROTO_UDP) {
- struct udpiphdr *ui;
- ui = mtod(m, struct udpiphdr *);
- if (ntohs(ui->ui_dport) == IPPORT_BOOTPC) {
- goto ours;
- }
- }
-
tmp_mbuf = m;
struct mbuf *nxt_mbuf = NULL;
- while (tmp_mbuf) {
+ while (tmp_mbuf != NULL) {
nxt_mbuf = mbuf_nextpkt(tmp_mbuf);
/*
* Not for us; forward if possible and desirable.
@@ -1607,6 +1757,7 @@ ip_input_second_pass(struct mbuf *m, struct ifnet *inifp, u_int32_t div_info,
KERNEL_DEBUG(DBG_LAYER_END, 0, 0, 0, 0, 0);
return;
ours:
+ ip = mtod(m, struct ip *); /* in case it changed */
/*
* If offset or IP_MF are set, must reassemble.
*/
@@ -1872,15 +2023,9 @@ void
ip_input(struct mbuf *m)
{
struct ip *ip;
- struct in_ifaddr *ia = NULL;
- unsigned int hlen, checkif;
+ unsigned int hlen;
u_short sum = 0;
- struct in_addr pkt_dst;
-#if IPFIREWALL
- int i;
- u_int32_t div_info = 0; /* packet divert/tee info */
-#endif
-#if IPFIREWALL || DUMMYNET
+#if DUMMYNET
struct ip_fw_args args;
struct m_tag *tag;
#endif
@@ -1945,7 +2090,7 @@ ip_input(struct mbuf *m)
m_tag_delete(m, tag);
}
-#if DIAGNOSTIC
+#if DIAGNOSTIC
if (m == NULL || !(m->m_flags & M_PKTHDR)) {
panic("ip_input no HDR");
}
@@ -2242,17 +2387,6 @@ ip_input(struct mbuf *m)
goto ours;
}
- /*
- * Cache the destination address of the packet; this may be
- * changed by use of 'ipfw fwd'.
- */
-#if IPFIREWALL
- pkt_dst = args.fwa_next_hop == NULL ?
- ip->ip_dst : args.fwa_next_hop->sin_addr;
-#else /* !IPFIREWALL */
- pkt_dst = ip->ip_dst;
-#endif /* !IPFIREWALL */
-
/*
* Enable a consistency check between the destination address
* and the arrival interface for a unicast packet (the RFC 1122
@@ -2267,63 +2401,17 @@ ip_input(struct mbuf *m)
* to the loopback interface instead of the interface where
* the packets are received.
*/
- checkif = ip_checkinterface && (ipforwarding == 0) &&
- !(inifp->if_flags & IFF_LOOPBACK) &&
- !(m->m_pkthdr.pkt_flags & PKTF_LOOP)
-#if IPFIREWALL
- && (args.fwa_next_hop == NULL);
-#else /* !IPFIREWALL */
- ;
-#endif /* !IPFIREWALL */
+ if (!IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
+ ip_check_if_result_t check_if_result = IP_CHECK_IF_NONE;
- /*
- * Check for exact addresses in the hash bucket.
- */
- lck_rw_lock_shared(in_ifaddr_rwlock);
- TAILQ_FOREACH(ia, INADDR_HASH(pkt_dst.s_addr), ia_hash) {
- /*
- * If the address matches, verify that the packet
- * arrived via the correct interface if checking is
- * enabled.
- */
- if (IA_SIN(ia)->sin_addr.s_addr == pkt_dst.s_addr &&
- (!checkif || ia->ia_ifp == inifp)) {
- ip_setdstifaddr_info(m, 0, ia);
- lck_rw_done(in_ifaddr_rwlock);
+ check_if_result = ip_input_check_interface(&m, ip, inifp);
+ ASSERT(check_if_result != IP_CHECK_IF_NONE);
+ if (check_if_result == IP_CHECK_IF_OURS) {
goto ours;
+ } else if (check_if_result == IP_CHECK_IF_DROP) {
+ return;
}
- }
- lck_rw_done(in_ifaddr_rwlock);
-
- /*
- * Check for broadcast addresses.
- *
- * Only accept broadcast packets that arrive via the matching
- * interface. Reception of forwarded directed broadcasts would be
- * handled via ip_forward() and ether_frameout() with the loopback
- * into the stack for SIMPLEX interfaces handled by ether_frameout().
- */
- if (inifp->if_flags & IFF_BROADCAST) {
- struct ifaddr *ifa;
-
- ifnet_lock_shared(inifp);
- TAILQ_FOREACH(ifa, &inifp->if_addrhead, ifa_link) {
- if (ifa->ifa_addr->sa_family != AF_INET) {
- continue;
- }
- ia = ifatoia(ifa);
- if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr ==
- pkt_dst.s_addr || ia->ia_netbroadcast.s_addr ==
- pkt_dst.s_addr) {
- ip_setdstifaddr_info(m, 0, ia);
- ifnet_lock_done(inifp);
- goto ours;
- }
- }
- ifnet_lock_done(inifp);
- }
-
- if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
+ } else {
struct in_multi *inm;
/*
* See if we belong to the destination multicast group on the
@@ -2341,29 +2429,6 @@ ip_input(struct mbuf *m)
INM_REMREF(inm);
goto ours;
}
- if (ip->ip_dst.s_addr == (u_int32_t)INADDR_BROADCAST ||
- ip->ip_dst.s_addr == INADDR_ANY) {
- ip_setdstifaddr_info(m, inifp->if_index, NULL);
- goto ours;
- }
-
- /* Allow DHCP/BootP responses through */
- if ((inifp->if_eflags & IFEF_AUTOCONFIGURING) &&
- hlen == sizeof(struct ip) && ip->ip_p == IPPROTO_UDP) {
- struct udpiphdr *ui;
-
- if (m->m_len < sizeof(struct udpiphdr) &&
- (m = m_pullup(m, sizeof(struct udpiphdr))) == NULL) {
- OSAddAtomic(1, &udpstat.udps_hdrops);
- return;
- }
- ui = mtod(m, struct udpiphdr *);
- if (ntohs(ui->ui_dport) == IPPORT_BOOTPC) {
- ip_setdstifaddr_info(m, inifp->if_index, NULL);
- goto ours;
- }
- ip = mtod(m, struct ip *); /* in case it changed */
- }
/*
* Not for us; forward if possible and desirable.
@@ -4671,3 +4736,32 @@ sysctl_ip_input_getperf SYSCTL_HANDLER_ARGS
return SYSCTL_OUT(req, &net_perf, MIN(sizeof(net_perf), req->oldlen));
}
#endif /* (DEBUG || DEVELOPMENT) */
+
+static int
+sysctl_ip_checkinterface SYSCTL_HANDLER_ARGS
+{
+#pragma unused(arg1, arg2)
+ int error, i;
+
+ i = ip_checkinterface;
+ error = sysctl_handle_int(oidp, &i, 0, req);
+ if (error != 0 || req->newptr == USER_ADDR_NULL) {
+ return error;
+ }
+
+ switch (i) {
+ case IP_CHECKINTERFACE_WEAK_ES:
+ case IP_CHECKINTERFACE_HYBRID_ES:
+ case IP_CHECKINTERFACE_STRONG_ES:
+ if (ip_checkinterface != i) {
+ ip_checkinterface = i;
+ os_log(OS_LOG_DEFAULT, "%s: ip_checkinterface is now %d\n",
+ __func__, ip_checkinterface);
+ }
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ return error;
+}
diff --git a/bsd/netinet/ip_var.h b/bsd/netinet/ip_var.h
index a9ecaa856..ab4d5336d 100644
--- a/bsd/netinet/ip_var.h
+++ b/bsd/netinet/ip_var.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2017 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -229,6 +229,8 @@ struct ipstat {
u_int32_t ips_rxc_notlist; /* count of pkts through ip_input */
u_int32_t ips_raw_sappend_fail; /* sock append failed */
u_int32_t ips_necp_policy_drop; /* NECP policy related drop */
+ u_int32_t ips_rcv_if_weak_match; /* packets whose receive interface that passed the Weak ES address check */
+ u_int32_t ips_rcv_if_no_match; /* packets whose receive interface did not pass the address check */
};
struct ip_linklocal_stat {
diff --git a/bsd/netinet/kpi_ipfilter.c b/bsd/netinet/kpi_ipfilter.c
index b783eb214..a47c52b4a 100644
--- a/bsd/netinet/kpi_ipfilter.c
+++ b/bsd/netinet/kpi_ipfilter.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004-2018 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -329,7 +329,7 @@ ipf_inject_input(
ip6 = mtod(m, struct ip6_hdr *);
pkt_dst6.sin6_addr = ip6->ip6_dst;
lck_rw_lock_shared(&in6_ifaddr_rwlock);
- for (ia6 = in6_ifaddrs; ia6 != NULL; ia6 = ia6->ia_next) {
+ TAILQ_FOREACH(ia6, IN6ADDR_HASH(&pkt_dst6.sin6_addr), ia6_hash) {
if (IN6_ARE_ADDR_EQUAL(&ia6->ia_addr.sin6_addr, &pkt_dst6.sin6_addr)) {
m->m_pkthdr.rcvif = ia6->ia_ifp;
break;
diff --git a/bsd/netinet6/ah_input.c b/bsd/netinet6/ah_input.c
index 67a664ec6..a2620405f 100644
--- a/bsd/netinet6/ah_input.c
+++ b/bsd/netinet6/ah_input.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -631,17 +631,17 @@ ah6_input(struct mbuf **mp, int *offp, int proto)
#pragma unused(proto)
struct mbuf *m = *mp;
int off = *offp;
- struct ip6_hdr *ip6;
- struct ah *ah;
- u_int32_t spi;
- const struct ah_algorithm *algo;
- size_t siz;
- size_t siz1;
- u_char *cksum;
+ struct ip6_hdr *ip6 = NULL;
+ struct ah *ah = NULL;
+ u_int32_t spi = 0;
+ const struct ah_algorithm *algo = NULL;
+ size_t siz = 0;
+ size_t siz1 = 0;
+ u_char *cksum = NULL;
struct secasvar *sav = NULL;
- u_int16_t nxt;
+ u_int16_t nxt = IPPROTO_DONE;
size_t stripsiz = 0;
- sa_family_t ifamily;
+ sa_family_t ifamily = AF_UNSPEC;
IP6_EXTHDR_CHECK(m, off, sizeof(struct ah), {return IPPROTO_DONE;});
ah = (struct ah *)(void *)(mtod(m, caddr_t) + off);
@@ -724,6 +724,8 @@ ah6_input(struct mbuf **mp, int *offp, int proto)
}
IP6_EXTHDR_CHECK(m, off, sizeof(struct ah) + sizoff + siz1,
{return IPPROTO_DONE;});
+ ip6 = mtod(m, struct ip6_hdr *);
+ ah = (struct ah *)(void *)(mtod(m, caddr_t) + off);
}
/*
@@ -1026,6 +1028,7 @@ ah6_input(struct mbuf **mp, int *offp, int proto)
}
if (m) {
m_freem(m);
+ *mp = NULL;
}
return IPPROTO_DONE;
}
diff --git a/bsd/netinet6/dest6.c b/bsd/netinet6/dest6.c
index ef80246c9..48dc59cf1 100644
--- a/bsd/netinet6/dest6.c
+++ b/bsd/netinet6/dest6.c
@@ -1,3 +1,30 @@
+/*
+ * Copyright (c) 2020 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
/* $FreeBSD: src/sys/netinet6/dest6.c,v 1.1.2.3 2001/07/03 11:01:49 ume Exp $ */
/* $KAME: dest6.c,v 1.27 2001/03/29 05:34:30 itojun Exp $ */
@@ -58,9 +85,9 @@ dest6_input(struct mbuf **mp, int *offp, int proto)
{
#pragma unused(proto)
struct mbuf *m = *mp;
- int off = *offp, dstoptlen, optlen;
- struct ip6_dest *dstopts;
- u_int8_t *opt;
+ int off = *offp, dstoptlen = 0, optlen = 0;
+ struct ip6_dest *dstopts = NULL;
+ u_int8_t *opt = NULL;
/* validation of the length of the header */
IP6_EXTHDR_CHECK(m, off, sizeof(*dstopts), return IPPROTO_DONE);
@@ -99,11 +126,12 @@ dest6_input(struct mbuf **mp, int *offp, int proto)
break;
}
}
-
+ *mp = m;
*offp = off;
return dstopts->ip6d_nxt;
bad:
+ *mp = NULL;
m_freem(m);
return IPPROTO_DONE;
}
diff --git a/bsd/netinet6/esp_input.c b/bsd/netinet6/esp_input.c
index 8e99b3eb7..849dc02af 100644
--- a/bsd/netinet6/esp_input.c
+++ b/bsd/netinet6/esp_input.c
@@ -529,6 +529,7 @@ esp4_input_extended(struct mbuf *m, int off, ifnet_t interface)
IPSEC_STAT_INCREMENT(ipsecstat.in_inval);
goto bad;
}
+ ip = mtod(m, struct ip *);
}
// check the UDP encap header to detect changes in the source port, and then strip the header
@@ -1199,6 +1200,7 @@ esp6_input_extended(struct mbuf **mp, int *offp, int proto, ifnet_t interface)
IPSEC_STAT_INCREMENT(ipsec6stat.in_inval);
goto bad;
}
+ ip6 = mtod(m, struct ip6_hdr *);
}
// check the UDP encap header to detect changes in the source port, and then strip the header
diff --git a/bsd/netinet6/frag6.c b/bsd/netinet6/frag6.c
index 9357d5e99..001cd1f12 100644
--- a/bsd/netinet6/frag6.c
+++ b/bsd/netinet6/frag6.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -277,18 +277,18 @@ int
frag6_input(struct mbuf **mp, int *offp, int proto)
{
#pragma unused(proto)
- struct mbuf *m = *mp, *t;
- struct ip6_hdr *ip6;
- struct ip6_frag *ip6f;
- struct ip6q *q6;
- struct ip6asfrag *af6, *ip6af, *af6dwn;
- int offset = *offp, nxt, i, next;
+ struct mbuf *m = *mp, *t = NULL;
+ struct ip6_hdr *ip6 = NULL;
+ struct ip6_frag *ip6f = NULL;
+ struct ip6q *q6 = NULL;
+ struct ip6asfrag *af6 = NULL, *ip6af = NULL, *af6dwn = NULL;
+ int offset = *offp, nxt = 0, i = 0, next = 0;
int first_frag = 0;
- int fragoff, frgpartlen; /* must be larger than u_int16_t */
+ int fragoff = 0, frgpartlen = 0; /* must be larger than u_int16_t */
struct ifnet *dstifp = NULL;
- u_int8_t ecn, ecn0;
- uint32_t csum, csum_flags;
- struct fq6_head diq6;
+ u_int8_t ecn = 0, ecn0 = 0;
+ uint32_t csum = 0, csum_flags = 0;
+ struct fq6_head diq6 = {};
int locked = 0;
VERIFY(m->m_flags & M_PKTHDR);
@@ -298,8 +298,8 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
/* Expect 32-bit aligned data pointer on strict-align platforms */
MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
- ip6 = mtod(m, struct ip6_hdr *);
IP6_EXTHDR_CHECK(m, offset, sizeof(struct ip6_frag), goto done);
+ ip6 = mtod(m, struct ip6_hdr *);
ip6f = (struct ip6_frag *)((caddr_t)ip6 + offset);
#ifdef IN6_IFSTAT_STRICT
@@ -375,6 +375,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
m->m_pkthdr.pkt_flags |= PKTF_REASSEMBLED;
ip6stat.ip6s_atmfrag_rcvd++;
in6_ifstat_inc(dstifp, ifs6_atmfrag_rcvd);
+ *mp = m;
*offp = offset;
return ip6f->ip6f_nxt;
}
@@ -539,6 +540,20 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
* fragment already stored in the reassembly queue.
*/
if (fragoff == 0) {
+ /*
+ * https://tools.ietf.org/html/rfc8200#page-20
+ * If the first fragment does not include all headers through an
+ * Upper-Layer header, then that fragment should be discarded and
+ * an ICMP Parameter Problem, Code 3, message should be sent to
+ * the source of the fragment, with the Pointer field set to zero.
+ */
+ if (!ip6_pkt_has_ulp(m)) {
+ lck_mtx_unlock(&ip6qlock);
+ locked = 0;
+ icmp6_error(m, ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, 0);
+ m = NULL;
+ goto done;
+ }
for (af6 = q6->ip6q_down; af6 != (struct ip6asfrag *)q6;
af6 = af6dwn) {
af6dwn = af6->ip6af_down;
@@ -862,6 +877,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
done:
VERIFY(m == NULL);
+ *mp = m;
if (!locked) {
if (frag6_nfragpackets == 0) {
frag6_icmp6_paramprob_error(&diq6);
@@ -884,6 +900,7 @@ frag6_input(struct mbuf **mp, int *offp, int proto)
lck_mtx_unlock(&ip6qlock);
in6_ifstat_inc(dstifp, ifs6_reass_fail);
m_freem(m);
+ *mp = NULL;
frag6_icmp6_paramprob_error(&diq6);
VERIFY(MBUFQ_EMPTY(&diq6));
return IPPROTO_DONE;
diff --git a/bsd/netinet6/icmp6.c b/bsd/netinet6/icmp6.c
index 042244b83..b6f48a666 100644
--- a/bsd/netinet6/icmp6.c
+++ b/bsd/netinet6/icmp6.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -2334,7 +2334,7 @@ icmp6_reflect(struct mbuf *m, size_t off)
* to search in the ifaddr list.
*/
lck_rw_lock_shared(&in6_ifaddr_rwlock);
- for (ia = in6_ifaddrs; ia; ia = ia->ia_next) {
+ TAILQ_FOREACH(ia, IN6ADDR_HASH(&t), ia6_hash) {
IFA_LOCK(&ia->ia_ifa);
if (IN6_ARE_ADDR_EQUAL(&t, &ia->ia_addr.sin6_addr) &&
(ia->ia6_flags & (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY | IN6_IFF_CLAT46)) == 0) {
@@ -2469,12 +2469,12 @@ icmp6_redirect_input(struct mbuf *m, int off)
u_char *redirhdr = NULL;
int redirhdrlen = 0;
struct rtentry *rt = NULL;
- int is_router;
- int is_onlink;
- struct in6_addr src6;
- struct in6_addr redtgt6;
- struct in6_addr reddst6;
- union nd_opts ndopts;
+ int is_router = 0;
+ int is_onlink = 0;
+ struct in6_addr src6 = {};
+ struct in6_addr redtgt6 = {};
+ struct in6_addr reddst6 = {};
+ union nd_opts ndopts = {};
if (m == NULL) {
return;
@@ -2485,10 +2485,6 @@ icmp6_redirect_input(struct mbuf *m, int off)
goto freeit;
}
- ip6 = mtod(m, struct ip6_hdr *);
- icmp6len = ntohs(ip6->ip6_plen);
- src6 = ip6->ip6_src;
-
/*
* If we are an advertising router on this interface,
* don't update route by icmp6 redirect.
@@ -2500,9 +2496,12 @@ icmp6_redirect_input(struct mbuf *m, int off)
goto freeit;
}
+ ip6 = mtod(m, struct ip6_hdr *);
+ icmp6len = ntohs(ip6->ip6_plen);
+ src6 = ip6->ip6_src;
#ifndef PULLDOWN_TEST
IP6_EXTHDR_CHECK(m, off, icmp6len, return );
- nd_rd = (struct nd_redirect *)((caddr_t)ip6 + off);
+ nd_rd = (struct nd_redirect *)(mtod(m, caddr_t) + off);
#else
IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len);
if (nd_rd == NULL) {
@@ -2510,6 +2509,8 @@ icmp6_redirect_input(struct mbuf *m, int off)
goto freeit;
}
#endif
+ ip6 = mtod(m, struct ip6_hdr *);
+
redtgt6 = nd_rd->nd_rd_target;
reddst6 = nd_rd->nd_rd_dst;
diff --git a/bsd/netinet6/in6.c b/bsd/netinet6/in6.c
index 5ed976827..176bd11cc 100644
--- a/bsd/netinet6/in6.c
+++ b/bsd/netinet6/in6.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -223,6 +223,19 @@ static int in6_getconnids(struct socket *, sae_associd_t, uint32_t *,
static void in6_if_up_dad_start(struct ifnet *);
+#define IA6_HASH_INIT(ia) { \
+ (ia)->ia6_hash.tqe_next = (void *)(uintptr_t)-1; \
+ (ia)->ia6_hash.tqe_prev = (void *)(uintptr_t)-1; \
+}
+
+#define IA6_IS_HASHED(ia) \
+ (!((ia)->ia6_hash.tqe_next == (void *)(uintptr_t)-1 || \
+ (ia)->ia6_hash.tqe_prev == (void *)(uintptr_t)-1))
+
+static void in6_iahash_remove(struct in6_ifaddr *);
+static void in6_iahash_insert(struct in6_ifaddr *);
+static void in6_iahash_insert_ptp(struct in6_ifaddr *);
+
extern lck_mtx_t *nd6_mutex;
#define IN6IFA_TRACE_HIST_SIZE 32 /* size of trace history */
@@ -399,7 +412,7 @@ in6_ifremloop(struct ifaddr *ifa)
* XXX: we should avoid such a configuration in IPv6...
*/
lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
- for (ia = in6_ifaddrs; ia; ia = ia->ia_next) {
+ TAILQ_FOREACH(ia, IN6ADDR_HASH(IFA_IN6(ifa)), ia6_hash) {
IFA_LOCK(&ia->ia_ifa);
if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ia->ia_addr.sin6_addr)) {
ia_count++;
@@ -788,31 +801,32 @@ in6ctl_llstop(struct ifnet *ifp)
/* Remove link local addresses from interface */
lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
- ia = in6_ifaddrs;
- while (ia != NULL) {
- if (ia->ia_ifa.ifa_ifp != ifp) {
- ia = ia->ia_next;
- continue;
- }
- IFA_LOCK(&ia->ia_ifa);
- if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr)) {
- IFA_ADDREF_LOCKED(&ia->ia_ifa); /* for us */
+ boolean_t from_begining = TRUE;
+ while (from_begining) {
+ from_begining = FALSE;
+ TAILQ_FOREACH(ia, &in6_ifaddrhead, ia6_link) {
+ if (ia->ia_ifa.ifa_ifp != ifp) {
+ continue;
+ }
+ IFA_LOCK(&ia->ia_ifa);
+ if (IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr)) {
+ IFA_ADDREF_LOCKED(&ia->ia_ifa); /* for us */
+ IFA_UNLOCK(&ia->ia_ifa);
+ lck_rw_done(&in6_ifaddr_rwlock);
+ in6_purgeaddr(&ia->ia_ifa);
+ IFA_REMREF(&ia->ia_ifa); /* for us */
+ lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
+ /*
+ * Purging the address caused in6_ifaddr_rwlock
+ * to be dropped and reacquired;
+ * therefore search again from the beginning
+ * of in6_ifaddrs list.
+ */
+ from_begining = TRUE;
+ break;
+ }
IFA_UNLOCK(&ia->ia_ifa);
- lck_rw_done(&in6_ifaddr_rwlock);
- in6_purgeaddr(&ia->ia_ifa);
- IFA_REMREF(&ia->ia_ifa); /* for us */
- lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
- /*
- * Purging the address caused in6_ifaddr_rwlock
- * to be dropped and reacquired;
- * therefore search again from the beginning
- * of in6_ifaddrs list.
- */
- ia = in6_ifaddrs;
- continue;
}
- IFA_UNLOCK(&ia->ia_ifa);
- ia = ia->ia_next;
}
lck_rw_done(&in6_ifaddr_rwlock);
@@ -1856,31 +1870,32 @@ in6_autoconf(struct ifnet *ifp, int enable)
/* Remove autoconfigured address from interface */
lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
- ia = in6_ifaddrs;
- while (ia != NULL) {
- if (ia->ia_ifa.ifa_ifp != ifp) {
- ia = ia->ia_next;
- continue;
- }
- IFA_LOCK(&ia->ia_ifa);
- if (ia->ia6_flags & IN6_IFF_AUTOCONF) {
- IFA_ADDREF_LOCKED(&ia->ia_ifa); /* for us */
+ boolean_t from_begining = TRUE;
+ while (from_begining) {
+ from_begining = FALSE;
+ TAILQ_FOREACH(ia, &in6_ifaddrhead, ia6_link) {
+ if (ia->ia_ifa.ifa_ifp != ifp) {
+ continue;
+ }
+ IFA_LOCK(&ia->ia_ifa);
+ if (ia->ia6_flags & IN6_IFF_AUTOCONF) {
+ IFA_ADDREF_LOCKED(&ia->ia_ifa); /* for us */
+ IFA_UNLOCK(&ia->ia_ifa);
+ lck_rw_done(&in6_ifaddr_rwlock);
+ in6_purgeaddr(&ia->ia_ifa);
+ IFA_REMREF(&ia->ia_ifa); /* for us */
+ lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
+ /*
+ * Purging the address caused in6_ifaddr_rwlock
+ * to be dropped and reacquired;
+ * therefore search again from the beginning
+ * of in6_ifaddrs list.
+ */
+ from_begining = TRUE;
+ break;
+ }
IFA_UNLOCK(&ia->ia_ifa);
- lck_rw_done(&in6_ifaddr_rwlock);
- in6_purgeaddr(&ia->ia_ifa);
- IFA_REMREF(&ia->ia_ifa); /* for us */
- lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
- /*
- * Purging the address caused in6_ifaddr_rwlock
- * to be dropped and reacquired;
- * therefore search again from the beginning
- * of in6_ifaddrs list.
- */
- ia = in6_ifaddrs;
- continue;
}
- IFA_UNLOCK(&ia->ia_ifa);
- ia = ia->ia_next;
}
lck_rw_done(&in6_ifaddr_rwlock);
}
@@ -2414,6 +2429,7 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra, int ifaupflags,
* Please enjoy the dancing sea turtle.
*/
IFA_ADDREF(ifa); /* for this and optionally for caller */
+ IA6_HASH_INIT(ia);
ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
if (ifra->ifra_dstaddr.sin6_family == AF_INET6 ||
(ifp->if_flags & (IFF_POINTOPOINT | IFF_LOOPBACK)) != 0) {
@@ -2462,16 +2478,7 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra, int ifaupflags,
ifnet_lock_done(ifp);
lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
- if (in6_ifaddrs != NULL) {
- struct in6_ifaddr *iac;
- for (iac = in6_ifaddrs; iac->ia_next != NULL;
- iac = iac->ia_next) {
- continue;
- }
- iac->ia_next = ia;
- } else {
- in6_ifaddrs = ia;
- }
+ TAILQ_INSERT_TAIL(&in6_ifaddrhead, ia, ia6_link);
IFA_ADDREF(ifa); /* hold for in6_ifaddrs link */
lck_rw_done(&in6_ifaddr_rwlock);
} else {
@@ -2610,7 +2617,7 @@ in6_purgeaddr(struct ifaddr *ifa)
static void
in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
{
- struct in6_ifaddr *oia;
+ struct in6_ifaddr *nia;
struct ifaddr *ifa;
int unlinked;
@@ -2627,21 +2634,18 @@ in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
IFA_UNLOCK(ifa);
ifnet_lock_done(ifp);
- unlinked = 1;
+ unlinked = 0;
lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
- oia = ia;
- if (oia == (ia = in6_ifaddrs)) {
- in6_ifaddrs = ia->ia_next;
- } else {
- while (ia->ia_next && (ia->ia_next != oia)) {
- ia = ia->ia_next;
- }
- if (ia->ia_next) {
- ia->ia_next = oia->ia_next;
- } else {
- /* search failed */
- log(LOG_NOTICE, "%s: search failed.\n", __func__);
- unlinked = 0;
+ TAILQ_FOREACH(nia, &in6_ifaddrhead, ia6_link) {
+ if (ia == nia) {
+ TAILQ_REMOVE(&in6_ifaddrhead, ia, ia6_link);
+ IFA_LOCK(ifa);
+ if (IA6_IS_HASHED(ia)) {
+ in6_iahash_remove(ia);
+ }
+ IFA_UNLOCK(ifa);
+ unlinked = 1;
+ break;
}
}
@@ -2652,7 +2656,6 @@ in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
* of other (detached) addresses, call
* pfxlist_onlink_check().
*/
- ifa = &oia->ia_ifa;
IFA_LOCK(ifa);
/*
* Only log the below message for addresses other than
@@ -2666,19 +2669,19 @@ in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
*
* For now quiece down the log message for LLAs.
*/
- if (!IN6_IS_ADDR_LINKLOCAL(&oia->ia_addr.sin6_addr)) {
- if (oia->ia6_ndpr == NULL) {
+ if (!IN6_IS_ADDR_LINKLOCAL(&ia->ia_addr.sin6_addr)) {
+ if (ia->ia6_ndpr == NULL) {
log(LOG_NOTICE, "in6_unlink_ifa: IPv6 address "
"0x%llx has no prefix\n",
- (uint64_t)VM_KERNEL_ADDRPERM(oia));
+ (uint64_t)VM_KERNEL_ADDRPERM(ia));
} else {
- struct nd_prefix *pr = oia->ia6_ndpr;
- oia->ia6_flags &= ~IN6_IFF_AUTOCONF;
- oia->ia6_ndpr = NULL;
+ struct nd_prefix *pr = ia->ia6_ndpr;
+ ia->ia6_flags &= ~IN6_IFF_AUTOCONF;
+ ia->ia6_ndpr = NULL;
NDPR_LOCK(pr);
VERIFY(pr->ndpr_addrcnt != 0);
pr->ndpr_addrcnt--;
- if (oia->ia6_flags & IN6_IFF_CLAT46) {
+ if (ia->ia6_flags & IN6_IFF_CLAT46) {
pr->ndpr_stateflags &= ~NDPRF_CLAT46;
}
NDPR_UNLOCK(pr);
@@ -2688,7 +2691,7 @@ in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp)
IFA_UNLOCK(ifa);
lck_rw_done(&in6_ifaddr_rwlock);
- if ((oia->ia6_flags & IN6_IFF_AUTOCONF) != 0) {
+ if ((ia->ia6_flags & IN6_IFF_AUTOCONF) != 0) {
lck_mtx_lock(nd6_mutex);
pfxlist_onlink_check();
lck_mtx_unlock(nd6_mutex);
@@ -2721,24 +2724,27 @@ in6_purgeif(struct ifnet *ifp)
LCK_MTX_ASSERT(nd6_mutex, LCK_MTX_ASSERT_NOTOWNED);
lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
- ia = in6_ifaddrs;
- while (ia != NULL) {
- if (ia->ia_ifa.ifa_ifp != ifp) {
- ia = ia->ia_next;
- continue;
+ boolean_t from_begining = TRUE;
+ while (from_begining) {
+ from_begining = FALSE;
+ TAILQ_FOREACH(ia, &in6_ifaddrhead, ia6_link) {
+ if (ia->ia_ifa.ifa_ifp != ifp) {
+ continue;
+ }
+ IFA_ADDREF(&ia->ia_ifa); /* for us */
+ lck_rw_done(&in6_ifaddr_rwlock);
+ in6_purgeaddr(&ia->ia_ifa);
+ IFA_REMREF(&ia->ia_ifa); /* for us */
+ lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
+ /*
+ * Purging the address would have caused
+ * in6_ifaddr_rwlock to be dropped and reacquired;
+ * therefore search again from the beginning
+ * of in6_ifaddrs list.
+ */
+ from_begining = TRUE;
+ break;
}
- IFA_ADDREF(&ia->ia_ifa); /* for us */
- lck_rw_done(&in6_ifaddr_rwlock);
- in6_purgeaddr(&ia->ia_ifa);
- IFA_REMREF(&ia->ia_ifa); /* for us */
- lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
- /*
- * Purging the address would have caused
- * in6_ifaddr_rwlock to be dropped and reacquired;
- * therefore search again from the beginning
- * of in6_ifaddrs list.
- */
- ia = in6_ifaddrs;
}
lck_rw_done(&in6_ifaddr_rwlock);
@@ -2757,6 +2763,19 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia, int ifaupflags)
error = 0;
ifa = &ia->ia_ifa;
+ lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
+ IFA_LOCK(&ia->ia_ifa);
+ if (IA6_IS_HASHED(ia)) {
+ in6_iahash_remove(ia);
+ }
+ if ((ifp->if_flags & IFF_POINTOPOINT)) {
+ in6_iahash_insert_ptp(ia);
+ } else {
+ in6_iahash_insert(ia);
+ }
+ IFA_UNLOCK(&ia->ia_ifa);
+ lck_rw_done(&in6_ifaddr_rwlock);
+
/*
* NOTE: SIOCSIFADDR is defined with struct ifreq as parameter,
* but here we are sending it down to the interface with a pointer
@@ -2766,7 +2785,7 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia, int ifaupflags)
error = ifnet_ioctl(ifp, PF_INET6, SIOCSIFADDR, ia);
if (error != 0) {
if (error != EOPNOTSUPP) {
- return error;
+ goto failed;
}
error = 0;
}
@@ -2785,7 +2804,7 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia, int ifaupflags)
IFA_UNLOCK(ifa);
error = rtinit(ifa, RTM_ADD, RTF_UP | RTF_HOST);
if (error != 0) {
- return error;
+ goto failed;
}
IFA_LOCK(ifa);
ia->ia_flags |= IFA_ROUTE;
@@ -2810,6 +2829,17 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia, int ifaupflags)
VERIFY(error == 0);
return 0;
+failed:
+ VERIFY(error != 0);
+ lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
+ IFA_LOCK(&ia->ia_ifa);
+ if (IA6_IS_HASHED(ia)) {
+ in6_iahash_remove(ia);
+ }
+ IFA_UNLOCK(&ia->ia_ifa);
+ lck_rw_done(&in6_ifaddr_rwlock);
+
+ return error;
}
void
@@ -2910,7 +2940,7 @@ in6ifa_prproxyaddr(struct in6_addr *addr)
struct in6_ifaddr *ia;
lck_rw_lock_shared(&in6_ifaddr_rwlock);
- for (ia = in6_ifaddrs; ia; ia = ia->ia_next) {
+ TAILQ_FOREACH(ia, IN6ADDR_HASH(addr), ia6_hash) {
IFA_LOCK(&ia->ia_ifa);
if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(&ia->ia_ifa))) {
IFA_ADDREF_LOCKED(&ia->ia_ifa); /* for caller */
@@ -3103,7 +3133,7 @@ in6_localaddr(struct in6_addr *in6)
}
lck_rw_lock_shared(&in6_ifaddr_rwlock);
- for (ia = in6_ifaddrs; ia; ia = ia->ia_next) {
+ TAILQ_FOREACH(ia, &in6_ifaddrhead, ia6_link) {
IFA_LOCK_SPIN(&ia->ia_ifa);
if (IN6_ARE_MASKED_ADDR_EQUAL(in6, &ia->ia_addr.sin6_addr,
&ia->ia_prefixmask.sin6_addr)) {
@@ -4883,3 +4913,94 @@ in6_event_enqueue_nwk_wq_entry(in6_evhdlr_code_t in6_event_code,
nwk_wq_enqueue((struct nwk_wq_entry*)p_in6_ev);
}
+
+/*
+ * Caller must hold in6_ifaddr_rwlock as writer.
+ */
+static void
+in6_iahash_remove(struct in6_ifaddr *ia)
+{
+ LCK_RW_ASSERT(&in6_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
+ IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
+
+ if (!IA6_IS_HASHED(ia)) {
+ panic("%s: attempt to remove wrong ia %p from ipv6 hash table\n", __func__, ia);
+ /* NOTREACHED */
+ }
+ TAILQ_REMOVE(IN6ADDR_HASH(&ia->ia_addr.sin6_addr), ia, ia6_hash);
+ IA6_HASH_INIT(ia);
+ if (IFA_REMREF_LOCKED(&ia->ia_ifa) == NULL) {
+ panic("%s: unexpected (missing) refcnt ifa=%p", __func__,
+ &ia->ia_ifa);
+ /* NOTREACHED */
+ }
+}
+
+/*
+ * Caller must hold in6_ifaddr_rwlock as writer.
+ */
+static void
+in6_iahash_insert(struct in6_ifaddr *ia)
+{
+ LCK_RW_ASSERT(&in6_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
+ IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
+
+ if (ia->ia_addr.sin6_family != AF_INET6) {
+ panic("%s: attempt to insert wrong ia %p into hash table\n", __func__, ia);
+ /* NOTREACHED */
+ } else if (IA6_IS_HASHED(ia)) {
+ panic("%s: attempt to double-insert ia %p into hash table\n", __func__, ia);
+ /* NOTREACHED */
+ }
+ TAILQ_INSERT_HEAD(IN6ADDR_HASH(&ia->ia_addr.sin6_addr),
+ ia, ia6_hash);
+ IFA_ADDREF_LOCKED(&ia->ia_ifa);
+}
+
+/*
+ * Some point to point interfaces that are tunnels borrow the address from
+ * an underlying interface (e.g. VPN server). In order for source address
+ * selection logic to find the underlying interface first, we add the address
+ * of borrowing point to point interfaces at the end of the list.
+ * (see rdar://6733789)
+ *
+ * Caller must hold in6_ifaddr_rwlock as writer.
+ */
+static void
+in6_iahash_insert_ptp(struct in6_ifaddr *ia)
+{
+ struct in6_ifaddr *tmp_ifa;
+ struct ifnet *tmp_ifp;
+
+ LCK_RW_ASSERT(&in6_ifaddr_rwlock, LCK_RW_ASSERT_EXCLUSIVE);
+ IFA_LOCK_ASSERT_HELD(&ia->ia_ifa);
+
+ if (ia->ia_addr.sin6_family != AF_INET6) {
+ panic("%s: attempt to insert wrong ia %p into hash table\n", __func__, ia);
+ /* NOTREACHED */
+ } else if (IA6_IS_HASHED(ia)) {
+ panic("%s: attempt to double-insert ia %p into hash table\n", __func__, ia);
+ /* NOTREACHED */
+ }
+ IFA_UNLOCK(&ia->ia_ifa);
+ TAILQ_FOREACH(tmp_ifa, IN6ADDR_HASH(&ia->ia_addr.sin6_addr), ia6_hash) {
+ IFA_LOCK(&tmp_ifa->ia_ifa);
+ /* ia->ia_addr won't change, so check without lock */
+ if (IN6_ARE_ADDR_EQUAL(&tmp_ifa->ia_addr.sin6_addr, &ia->ia_addr.sin6_addr)) {
+ IFA_UNLOCK(&tmp_ifa->ia_ifa);
+ break;
+ }
+ IFA_UNLOCK(&tmp_ifa->ia_ifa);
+ }
+ tmp_ifp = (tmp_ifa == NULL) ? NULL : tmp_ifa->ia_ifp;
+
+ IFA_LOCK(&ia->ia_ifa);
+ if (tmp_ifp == NULL) {
+ TAILQ_INSERT_HEAD(IN6ADDR_HASH(&ia->ia_addr.sin6_addr),
+ ia, ia6_hash);
+ } else {
+ TAILQ_INSERT_TAIL(IN6ADDR_HASH(&ia->ia_addr.sin6_addr),
+ ia, ia6_hash);
+ }
+ IFA_ADDREF_LOCKED(&ia->ia_ifa);
+}
diff --git a/bsd/netinet6/in6_ifattach.c b/bsd/netinet6/in6_ifattach.c
index bd4ad95c0..194e996e1 100644
--- a/bsd/netinet6/in6_ifattach.c
+++ b/bsd/netinet6/in6_ifattach.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -1032,7 +1032,7 @@ in6_ifattach_llcgareq(struct ifnet *ifp, struct in6_cgareq *llcgasr)
void
in6_ifdetach(struct ifnet *ifp)
{
- struct in6_ifaddr *ia, *oia;
+ struct in6_ifaddr *ia, *nia;
struct ifaddr *ifa;
struct rtentry *rt;
struct sockaddr_in6 sin6;
@@ -1050,24 +1050,27 @@ in6_ifdetach(struct ifnet *ifp)
/* nuke any of IPv6 addresses we have */
lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
- ia = in6_ifaddrs;
- while (ia != NULL) {
- if (ia->ia_ifa.ifa_ifp != ifp) {
- ia = ia->ia_next;
- continue;
+ boolean_t from_begining = TRUE;
+ while (from_begining) {
+ from_begining = FALSE;
+ TAILQ_FOREACH(ia, &in6_ifaddrhead, ia6_link) {
+ if (ia->ia_ifa.ifa_ifp != ifp) {
+ continue;
+ }
+ IFA_ADDREF(&ia->ia_ifa); /* for us */
+ lck_rw_done(&in6_ifaddr_rwlock);
+ in6_purgeaddr(&ia->ia_ifa);
+ IFA_REMREF(&ia->ia_ifa); /* for us */
+ lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
+ /*
+ * Purging the address caused in6_ifaddr_rwlock
+ * to be dropped and reacquired;
+ * therefore search again from the beginning
+ * of in6_ifaddrs list.
+ */
+ from_begining = TRUE;
+ break;
}
- IFA_ADDREF(&ia->ia_ifa); /* for us */
- lck_rw_done(&in6_ifaddr_rwlock);
- in6_purgeaddr(&ia->ia_ifa);
- IFA_REMREF(&ia->ia_ifa); /* for us */
- lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
- /*
- * Purging the address caused in6_ifaddr_rwlock
- * to be dropped and reacquired;
- * therefore search again from the beginning
- * of in6_ifaddrs list.
- */
- ia = in6_ifaddrs;
}
lck_rw_done(&in6_ifaddr_rwlock);
@@ -1135,27 +1138,17 @@ in6_ifdetach(struct ifnet *ifp)
}
/* also remove from the IPv6 address chain(itojun&jinmei) */
- unlinked = 1;
- oia = ia;
+ unlinked = 0;
lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
- if (oia == (ia = in6_ifaddrs)) {
- in6_ifaddrs = ia->ia_next;
- } else {
- while (ia->ia_next && (ia->ia_next != oia)) {
- ia = ia->ia_next;
- }
- if (ia->ia_next) {
- ia->ia_next = oia->ia_next;
- } else {
- nd6log(error,
- "%s: didn't unlink in6ifaddr from "
- "list\n", if_name(ifp));
- unlinked = 0;
+ TAILQ_FOREACH(nia, &in6_ifaddrhead, ia6_link) {
+ if (ia == nia) {
+ TAILQ_REMOVE(&in6_ifaddrhead, ia, ia6_link);
+ unlinked = 1;
+ break;
}
}
lck_rw_done(&in6_ifaddr_rwlock);
- ifa = &oia->ia_ifa;
/*
* release another refcnt for the link from in6_ifaddrs.
* Do this only if it's not already unlinked in the event
diff --git a/bsd/netinet6/in6_pcb.c b/bsd/netinet6/in6_pcb.c
index c1d2ff08e..1af6aa583 100644
--- a/bsd/netinet6/in6_pcb.c
+++ b/bsd/netinet6/in6_pcb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -200,7 +200,7 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr *nam, struct proc *p)
kauth_cred_t cred;
#endif /* !CONFIG_EMBEDDED */
- if (!in6_ifaddrs) { /* XXX broken! */
+ if (TAILQ_EMPTY(&in6_ifaddrhead)) { /* XXX broken! */
return EADDRNOTAVAIL;
}
if (!(so->so_options & (SO_REUSEADDR | SO_REUSEPORT))) {
@@ -489,7 +489,7 @@ in6_pcbladdr(struct inpcb *inp, struct sockaddr *nam,
return EINVAL;
}
- if (in6_ifaddrs) {
+ if (!TAILQ_EMPTY(&in6_ifaddrhead)) {
/*
* If the destination address is UNSPECIFIED addr,
* use the loopback addr, e.g ::1.
diff --git a/bsd/netinet6/in6_src.c b/bsd/netinet6/in6_src.c
index f018e5111..4af6fed4a 100644
--- a/bsd/netinet6/in6_src.c
+++ b/bsd/netinet6/in6_src.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -318,7 +318,7 @@ in6_selectsrc_core(struct sockaddr_in6 *dstsock, uint32_t hint_mask,
}
lck_rw_lock_shared(&in6_ifaddr_rwlock);
- for (ia = in6_ifaddrs; ia; ia = ia->ia_next) {
+ TAILQ_FOREACH(ia, &in6_ifaddrhead, ia6_link) {
int new_scope = -1, new_matchlen = -1;
struct in6_addrpolicy *new_policy = NULL;
u_int32_t srczone = 0, osrczone, dstzone;
diff --git a/bsd/netinet6/in6_var.h b/bsd/netinet6/in6_var.h
index b7c080352..bd1a424ae 100644
--- a/bsd/netinet6/in6_var.h
+++ b/bsd/netinet6/in6_var.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2018 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -161,7 +161,8 @@ struct in6_ifaddr {
struct sockaddr_in6 ia_dstaddr; /* space for destination addr */
struct sockaddr_in6 ia_prefixmask; /* prefix mask */
u_int32_t ia_plen; /* prefix length */
- struct in6_ifaddr *ia_next; /* next in6 list of IP6 addresses */
+ TAILQ_ENTRY(in6_ifaddr) ia6_link; /* next in6 list of IP6 addresses */
+ TAILQ_ENTRY(in6_ifaddr) ia6_hash; /* hash bucket entry */
int ia6_flags;
struct in6_addrlifetime_i ia6_lifetime;
@@ -180,6 +181,34 @@ struct in6_ifaddr {
};
#define ifatoia6(ifa) ((struct in6_ifaddr *)(void *)(ifa))
+
+extern TAILQ_HEAD(in6_ifaddrhead, in6_ifaddr) in6_ifaddrhead;
+extern TAILQ_HEAD(in6_ifaddrhashhead, in6_ifaddr) * in6_ifaddrhashtbl;
+extern uint32_t in6addr_nhash; /* hash table size */
+extern uint32_t in6addr_hashp; /* next largest prime */
+
+static __inline uint32_t
+in6addr_hashval(const struct in6_addr *in6)
+{
+ /*
+ * The hash index is the computed prime times the key modulo
+ * the hash size, as documented in "Introduction to Algorithms"
+ * (Cormen, Leiserson, Rivest).
+ */
+ if (in6addr_nhash > 1) {
+ uint32_t x;
+
+ x = in6->s6_addr32[0] ^ in6->s6_addr32[1] ^ in6->s6_addr32[2] ^
+ in6->s6_addr32[3];
+
+ return (x * in6addr_hashp) % in6addr_nhash;
+ } else {
+ return 0;
+ }
+}
+
+#define IN6ADDR_HASH(x) (&in6_ifaddrhashtbl[in6addr_hashval(x)])
+
#endif /* BSD_KERNEL_PRIVATE */
/* control structure to manage address selection policy */
@@ -775,8 +804,6 @@ void in6_post_msg(struct ifnet *, u_int32_t, struct in6_ifaddr *, uint8_t *mac);
#endif /* KERNEL */
#ifdef BSD_KERNEL_PRIVATE
-extern struct in6_ifaddr *in6_ifaddrs;
-
extern struct icmp6stat icmp6stat;
extern lck_rw_t in6_ifaddr_rwlock;
extern lck_mtx_t proxy6_lock;
diff --git a/bsd/netinet6/ip6_input.c b/bsd/netinet6/ip6_input.c
index 8d9241fc1..0a9a2d13a 100644
--- a/bsd/netinet6/ip6_input.c
+++ b/bsd/netinet6/ip6_input.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -131,6 +131,7 @@
#endif /* INET */
#include
#include
+#include
#include
#include
#include
@@ -158,6 +159,8 @@ extern int ipsec_bypass;
#include
#endif /* PF */
+#include
+
struct ip6protosw *ip6_protox[IPPROTO_MAX];
static lck_grp_attr_t *in6_ifaddr_rwlock_grp_attr;
@@ -166,7 +169,14 @@ static lck_attr_t *in6_ifaddr_rwlock_attr;
decl_lck_rw_data(, in6_ifaddr_rwlock);
/* Protected by in6_ifaddr_rwlock */
-struct in6_ifaddr *in6_ifaddrs = NULL;
+struct in6_ifaddrhead in6_ifaddrhead;
+struct in6_ifaddrhashhead * in6_ifaddrhashtbl;
+uint32_t in6_ifaddrhmask;
+
+#define IN6ADDR_NHASH 61
+u_int32_t in6addr_nhash = 0; /* hash table size */
+u_int32_t in6addr_hashp = 0; /* next largest prime */
+
#define IN6_IFSTAT_REQUIRE_ALIGNED_64(f) \
_CASSERT(!(offsetof(struct in6_ifstat, f) % sizeof (uint64_t)))
@@ -200,6 +210,8 @@ static int sysctl_ip6_input_getperf SYSCTL_HANDLER_ARGS;
static void ip6_init_delayed(void);
static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
+static void in6_ifaddrhashtbl_init(void);
+
#if NSTF
extern void stfattach(void);
#endif /* NSTF */
@@ -233,6 +245,61 @@ SYSCTL_PROC(_net_inet6_ip6, OID_AUTO, input_perf_data,
0, 0, sysctl_ip6_input_getperf, "S,net_perf",
"IP6 input performance data (struct net_perf, net/net_perf.h)");
+/*
+ * ip6_checkinterface controls the receive side of the models for multihoming
+ * that are discussed in RFC 1122.
+ *
+ * sysctl_ip6_checkinterface values are:
+ * IP6_CHECKINTERFACE_WEAK_ES:
+ * This corresponds to the Weak End-System model where incoming packets from
+ * any interface are accepted provided the destination address of the incoming packet
+ * is assigned to some interface.
+ *
+ * IP6_CHECKINTERFACE_HYBRID_ES:
+ * The Hybrid End-System model use the Strong End-System for tunnel interfaces
+ * (ipsec and utun) and the weak End-System model for other interfaces families.
+ * This prevents a rogue middle box to probe for signs of TCP connections
+ * that use the tunnel interface.
+ *
+ * IP6_CHECKINTERFACE_STRONG_ES:
+ * The Strong model model requires the packet arrived on an interface that
+ * is assigned the destination address of the packet.
+ *
+ * Since the routing table and transmit implementation do not implement the Strong ES model,
+ * setting this to a value different from IP6_CHECKINTERFACE_WEAK_ES may lead to unexpected results.
+ *
+ * When forwarding is enabled, the system reverts to the Weak ES model as a router
+ * is expected by design to receive packets from several interfaces to the same address.
+ */
+#define IP6_CHECKINTERFACE_WEAK_ES 0
+#define IP6_CHECKINTERFACE_HYBRID_ES 1
+#define IP6_CHECKINTERFACE_STRONG_ES 2
+
+static int ip6_checkinterface = IP6_CHECKINTERFACE_HYBRID_ES;
+
+static int sysctl_ip6_checkinterface SYSCTL_HANDLER_ARGS;
+SYSCTL_PROC(_net_inet6_ip6, OID_AUTO, check_interface,
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
+ 0, 0, sysctl_ip6_checkinterface, "I", "Verify packet arrives on correct interface");
+
+#if (DEBUG || DEVELOPMENT)
+#define IP6_CHECK_IFDEBUG 1
+#else
+#define IP6_CHECK_IFDEBUG 0
+#endif /* (DEBUG || DEVELOPMENT) */
+static int ip6_checkinterface_debug = IP6_CHECK_IFDEBUG;
+SYSCTL_INT(_net_inet6_ip6, OID_AUTO, checkinterface_debug, CTLFLAG_RW | CTLFLAG_LOCKED,
+ &ip6_checkinterface_debug, IP6_CHECK_IFDEBUG, "");
+
+typedef enum ip6_check_if_result {
+ IP6_CHECK_IF_NONE = 0,
+ IP6_CHECK_IF_OURS = 1,
+ IP6_CHECK_IF_DROP = 2,
+ IP6_CHECK_IF_FORWARD = 3
+} ip6_check_if_result_t;
+
+static ip6_check_if_result_t ip6_input_check_interface(struct mbuf *, struct ip6_hdr *, struct ifnet *, struct route_in6 *rin6, struct ifnet **);
+
/*
* On platforms which require strict alignment (currently for anything but
* i386 or x86_64), check if the IP header pointer is 32-bit aligned; if not,
@@ -376,6 +443,9 @@ ip6_init(struct ip6protosw *pp, struct domain *dp)
lck_rw_init(&in6_ifaddr_rwlock, in6_ifaddr_rwlock_grp,
in6_ifaddr_rwlock_attr);
+ TAILQ_INIT(&in6_ifaddrhead);
+ in6_ifaddrhashtbl_init();
+
IN6_IFSTAT_REQUIRE_ALIGNED_64(ifs6_in_receive);
IN6_IFSTAT_REQUIRE_ALIGNED_64(ifs6_in_hdrerr);
IN6_IFSTAT_REQUIRE_ALIGNED_64(ifs6_in_toobig);
@@ -437,6 +507,17 @@ ip6_init(struct ip6protosw *pp, struct domain *dp)
ip6_desync_factor =
(RandomULong() ^ tv.tv_usec) % MAX_TEMP_DESYNC_FACTOR;
+ PE_parse_boot_argn("ip6_checkinterface", &i, sizeof(i));
+ switch (i) {
+ case IP6_CHECKINTERFACE_WEAK_ES:
+ case IP6_CHECKINTERFACE_HYBRID_ES:
+ case IP6_CHECKINTERFACE_STRONG_ES:
+ ip6_checkinterface = i;
+ break;
+ default:
+ break;
+ }
+
in6_ifaddr_init();
ip6_moptions_init();
nd6_init();
@@ -547,6 +628,171 @@ ip6_input_adjust(struct mbuf *m, struct ip6_hdr *ip6, uint32_t plen,
}
}
}
+static ip6_check_if_result_t
+ip6_input_check_interface(struct mbuf *m, struct ip6_hdr *ip6, struct ifnet *inifp, struct route_in6 *rin6, struct ifnet **deliverifp)
+{
+ struct in6_ifaddr *ia6 = NULL;
+ struct in6_addr tmp_dst = ip6->ip6_dst; /* copy to avoid unaligned access */
+ struct in6_ifaddr *best_ia6 = NULL;
+ ip6_check_if_result_t result = IP6_CHECK_IF_NONE;
+
+ *deliverifp = NULL;
+
+ /*
+ * Check for exact addresses in the hash bucket.
+ */
+ lck_rw_lock_shared(&in6_ifaddr_rwlock);
+ TAILQ_FOREACH(ia6, IN6ADDR_HASH(&tmp_dst), ia6_hash) {
+ /*
+ * TODO: should we accept loopbacl
+ */
+ if (IN6_ARE_ADDR_EQUAL(&ia6->ia_addr.sin6_addr, &tmp_dst)) {
+ if ((ia6->ia6_flags & (IN6_IFF_NOTREADY | IN6_IFF_CLAT46))) {
+ continue;
+ }
+ best_ia6 = ia6;
+ if (ia6->ia_ifp == inifp) {
+ /*
+ * TODO: should we also accept locally originated packets
+ * or from loopback ???
+ */
+ break;
+ }
+ /*
+ * Continue the loop in case there's a exact match with another
+ * interface
+ */
+ }
+ }
+ if (best_ia6 != NULL) {
+ if (best_ia6->ia_ifp != inifp && ip6_forwarding == 0 &&
+ ((ip6_checkinterface == IP6_CHECKINTERFACE_HYBRID_ES &&
+ (best_ia6->ia_ifp->if_family == IFNET_FAMILY_IPSEC ||
+ best_ia6->ia_ifp->if_family == IFNET_FAMILY_UTUN)) ||
+ ip6_checkinterface == IP6_CHECKINTERFACE_STRONG_ES)) {
+ /*
+ * Drop when interface address check is strict and forwarding
+ * is disabled
+ */
+ result = IP6_CHECK_IF_DROP;
+ } else {
+ result = IP6_CHECK_IF_OURS;
+ *deliverifp = best_ia6->ia_ifp;
+ ip6_setdstifaddr_info(m, 0, best_ia6);
+ }
+ }
+ lck_rw_done(&in6_ifaddr_rwlock);
+
+ if (result == IP6_CHECK_IF_NONE) {
+ /*
+ * Slow path: route lookup.
+ */
+ struct sockaddr_in6 *dst6;
+
+ dst6 = SIN6(&rin6->ro_dst);
+ dst6->sin6_len = sizeof(struct sockaddr_in6);
+ dst6->sin6_family = AF_INET6;
+ dst6->sin6_addr = ip6->ip6_dst;
+
+ rtalloc_scoped_ign((struct route *)rin6,
+ RTF_PRCLONING, IFSCOPE_NONE);
+ if (rin6->ro_rt != NULL) {
+ RT_LOCK_SPIN(rin6->ro_rt);
+ }
+
+#define rt6_key(r) (SIN6((r)->rt_nodes->rn_key))
+
+ /*
+ * Accept the packet if the forwarding interface to the destination
+ * according to the routing table is the loopback interface,
+ * unless the associated route has a gateway.
+ * Note that this approach causes to accept a packet if there is a
+ * route to the loopback interface for the destination of the packet.
+ * But we think it's even useful in some situations, e.g. when using
+ * a special daemon which wants to intercept the packet.
+ *
+ * XXX: some OSes automatically make a cloned route for the destination
+ * of an outgoing packet. If the outgoing interface of the packet
+ * is a loopback one, the kernel would consider the packet to be
+ * accepted, even if we have no such address assinged on the interface.
+ * We check the cloned flag of the route entry to reject such cases,
+ * assuming that route entries for our own addresses are not made by
+ * cloning (it should be true because in6_addloop explicitly installs
+ * the host route). However, we might have to do an explicit check
+ * while it would be less efficient. Or, should we rather install a
+ * reject route for such a case?
+ */
+ if (rin6->ro_rt != NULL &&
+ (rin6->ro_rt->rt_flags & (RTF_HOST | RTF_GATEWAY)) == RTF_HOST &&
+#if RTF_WASCLONED
+ !(rin6->ro_rt->rt_flags & RTF_WASCLONED) &&
+#endif
+ rin6->ro_rt->rt_ifp->if_type == IFT_LOOP) {
+ ia6 = (struct in6_ifaddr *)rin6->ro_rt->rt_ifa;
+ /*
+ * Packets to a tentative, duplicated, or somehow invalid
+ * address must not be accepted.
+ *
+ * For performance, test without acquiring the address lock;
+ * a lot of things in the address are set once and never
+ * changed (e.g. ia_ifp.)
+ */
+ if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
+ /* this address is ready */
+ result = IP6_CHECK_IF_OURS;
+ *deliverifp = ia6->ia_ifp; /* correct? */
+ /*
+ * record dst address information into mbuf.
+ */
+ (void) ip6_setdstifaddr_info(m, 0, ia6);
+ }
+ }
+
+ if (rin6->ro_rt != NULL) {
+ RT_UNLOCK(rin6->ro_rt);
+ }
+ }
+
+ if (result == IP6_CHECK_IF_NONE) {
+ if (ip6_forwarding == 0) {
+ result = IP6_CHECK_IF_DROP;
+ } else {
+ result = IP6_CHECK_IF_FORWARD;
+ ip6_setdstifaddr_info(m, inifp->if_index, NULL);
+ }
+ }
+
+ if (result == IP6_CHECK_IF_OURS && *deliverifp != inifp) {
+ ASSERT(*deliverifp != NULL);
+ ip6stat.ip6s_rcv_if_weak_match++;
+
+ /* Logging is too noisy when forwarding is enabled */
+ if (ip6_checkinterface_debug != IP6_CHECKINTERFACE_WEAK_ES && ip6_forwarding != 0) {
+ char src_str[MAX_IPv6_STR_LEN];
+ char dst_str[MAX_IPv6_STR_LEN];
+
+ inet_ntop(AF_INET6, &ip6->ip6_src, src_str, sizeof(src_str));
+ inet_ntop(AF_INET6, &ip6->ip6_dst, dst_str, sizeof(dst_str));
+ os_log_info(OS_LOG_DEFAULT,
+ "%s: weak ES interface match to %s for packet from %s to %s proto %u received via %s",
+ __func__, (*deliverifp)->if_xname, src_str, dst_str, ip6->ip6_nxt, inifp->if_xname);
+ }
+ } else if (result == IP6_CHECK_IF_DROP) {
+ ip6stat.ip6s_rcv_if_no_match++;
+ if (ip6_checkinterface_debug > 0) {
+ char src_str[MAX_IPv6_STR_LEN];
+ char dst_str[MAX_IPv6_STR_LEN];
+
+ inet_ntop(AF_INET6, &ip6->ip6_src, src_str, sizeof(src_str));
+ inet_ntop(AF_INET6, &ip6->ip6_dst, dst_str, sizeof(dst_str));
+ os_log_info(OS_LOG_DEFAULT,
+ "%s: no interface match for packet from %s to %s proto %u received via %s",
+ __func__, src_str, dst_str, ip6->ip6_nxt, inifp->if_xname);
+ }
+ }
+
+ return result;
+}
void
ip6_input(struct mbuf *m)
@@ -559,22 +805,11 @@ ip6_input(struct mbuf *m)
struct ifnet *inifp, *deliverifp = NULL;
ipfilter_t inject_ipfref = NULL;
int seen = 1;
- struct in6_ifaddr *ia6 = NULL;
- struct sockaddr_in6 *dst6;
#if DUMMYNET
struct m_tag *tag;
+ struct ip_fw_args args = {};
#endif /* DUMMYNET */
- struct {
- struct route_in6 rin6;
-#if DUMMYNET
- struct ip_fw_args args;
-#endif /* DUMMYNET */
- } ip6ibz;
-#define rin6 ip6ibz.rin6
-#define args ip6ibz.args
-
- /* zero out {rin6, args} */
- bzero(&ip6ibz, sizeof(ip6ibz));
+ struct route_in6 rin6 = {};
/*
* Check if the packet we received is valid after interface filter
@@ -885,126 +1120,36 @@ ip6_input(struct mbuf *m)
goto bad;
}
deliverifp = inifp;
- VERIFY(ia6 == NULL);
- goto hbhcheck;
- }
-
- /*
- * Unicast check
- *
- * Fast path: see if the target is ourselves.
- */
- lck_rw_lock_shared(&in6_ifaddr_rwlock);
- for (ia6 = in6_ifaddrs; ia6 != NULL; ia6 = ia6->ia_next) {
/*
- * No reference is held on the address, as we just need
- * to test for a few things while holding the RW lock.
+ * record dst address information into mbuf, if we don't have one yet.
+ * note that we are unable to record it, if the address is not listed
+ * as our interface address (e.g. multicast addresses, etc.)
*/
- if (IN6_ARE_ADDR_EQUAL(&ia6->ia_addr.sin6_addr, &ip6->ip6_dst)) {
- break;
- }
- }
+ if (deliverifp != NULL) {
+ struct in6_ifaddr *ia6 = NULL;
- if (ia6 != NULL) {
- /*
- * For performance, test without acquiring the address lock;
- * a lot of things in the address are set once and never
- * changed (e.g. ia_ifp.)
- */
- if (!(ia6->ia6_flags & (IN6_IFF_NOTREADY | IN6_IFF_CLAT46))) {
- /* this address is ready */
- ours = 1;
- deliverifp = ia6->ia_ifp;
- /*
- * record dst address information into mbuf.
- */
- (void) ip6_setdstifaddr_info(m, 0, ia6);
- lck_rw_done(&in6_ifaddr_rwlock);
- goto hbhcheck;
+ ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
+ if (ia6 != NULL) {
+ (void) ip6_setdstifaddr_info(m, 0, ia6);
+ IFA_REMREF(&ia6->ia_ifa);
+ } else {
+ (void) ip6_setdstifaddr_info(m, inifp->if_index, NULL);
+ }
}
- lck_rw_done(&in6_ifaddr_rwlock);
- ia6 = NULL;
- /* address is not ready, so discard the packet. */
- nd6log(info, "%s: packet to an unready address %s->%s\n",
- __func__, ip6_sprintf(&ip6->ip6_src),
- ip6_sprintf(&ip6->ip6_dst));
- goto bad;
- }
- lck_rw_done(&in6_ifaddr_rwlock);
-
- /*
- * Slow path: route lookup.
- */
- dst6 = SIN6(&rin6.ro_dst);
- dst6->sin6_len = sizeof(struct sockaddr_in6);
- dst6->sin6_family = AF_INET6;
- dst6->sin6_addr = ip6->ip6_dst;
-
- rtalloc_scoped_ign((struct route *)&rin6,
- RTF_PRCLONING, IFSCOPE_NONE);
- if (rin6.ro_rt != NULL) {
- RT_LOCK_SPIN(rin6.ro_rt);
- }
-
-#define rt6_key(r) (SIN6((r)->rt_nodes->rn_key))
-
- /*
- * Accept the packet if the forwarding interface to the destination
- * according to the routing table is the loopback interface,
- * unless the associated route has a gateway.
- * Note that this approach causes to accept a packet if there is a
- * route to the loopback interface for the destination of the packet.
- * But we think it's even useful in some situations, e.g. when using
- * a special daemon which wants to intercept the packet.
- *
- * XXX: some OSes automatically make a cloned route for the destination
- * of an outgoing packet. If the outgoing interface of the packet
- * is a loopback one, the kernel would consider the packet to be
- * accepted, even if we have no such address assinged on the interface.
- * We check the cloned flag of the route entry to reject such cases,
- * assuming that route entries for our own addresses are not made by
- * cloning (it should be true because in6_addloop explicitly installs
- * the host route). However, we might have to do an explicit check
- * while it would be less efficient. Or, should we rather install a
- * reject route for such a case?
- */
- if (rin6.ro_rt != NULL &&
- (rin6.ro_rt->rt_flags & (RTF_HOST | RTF_GATEWAY)) == RTF_HOST &&
-#if RTF_WASCLONED
- !(rin6.ro_rt->rt_flags & RTF_WASCLONED) &&
-#endif
- rin6.ro_rt->rt_ifp->if_type == IFT_LOOP) {
- ia6 = (struct in6_ifaddr *)rin6.ro_rt->rt_ifa;
+ goto hbhcheck;
+ } else {
/*
- * Packets to a tentative, duplicated, or somehow invalid
- * address must not be accepted.
- *
- * For performance, test without acquiring the address lock;
- * a lot of things in the address are set once and never
- * changed (e.g. ia_ifp.)
+ * Unicast check
*/
- if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) {
- /* this address is ready */
+ ip6_check_if_result_t check_if_result = IP6_CHECK_IF_NONE;
+ check_if_result = ip6_input_check_interface(m, ip6, inifp, &rin6, &deliverifp);
+ ASSERT(check_if_result != IP6_CHECK_IF_NONE);
+ if (check_if_result == IP6_CHECK_IF_OURS) {
ours = 1;
- deliverifp = ia6->ia_ifp; /* correct? */
- /*
- * record dst address information into mbuf.
- */
- (void) ip6_setdstifaddr_info(m, 0, ia6);
- RT_UNLOCK(rin6.ro_rt);
goto hbhcheck;
+ } else if (check_if_result == IP6_CHECK_IF_DROP) {
+ goto bad;
}
- RT_UNLOCK(rin6.ro_rt);
- ia6 = NULL;
- /* address is not ready, so discard the packet. */
- nd6log(error, "%s: packet to an unready address %s->%s\n",
- __func__, ip6_sprintf(&ip6->ip6_src),
- ip6_sprintf(&ip6->ip6_dst));
- goto bad;
- }
-
- if (rin6.ro_rt != NULL) {
- RT_UNLOCK(rin6.ro_rt);
}
/*
@@ -1027,19 +1172,6 @@ ip6_input(struct mbuf *m)
}
hbhcheck:
- /*
- * record dst address information into mbuf, if we don't have one yet.
- * note that we are unable to record it, if the address is not listed
- * as our interface address (e.g. multicast addresses, etc.)
- */
- if (deliverifp != NULL && ia6 == NULL) {
- ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst);
- if (ia6 != NULL) {
- (void) ip6_setdstifaddr_info(m, 0, ia6);
- IFA_REMREF(&ia6->ia_ifa);
- }
- }
-
/*
* Process Hop-by-Hop options header if it's contained.
* m may be modified in ip6_hopopts_input().
@@ -2120,6 +2252,44 @@ ip6_lasthdr(struct mbuf *m, int off, int proto, int *nxtp)
}
}
+boolean_t
+ip6_pkt_has_ulp(struct mbuf *m)
+{
+ int off = 0, nxt = IPPROTO_NONE;
+
+ off = ip6_lasthdr(m, 0, IPPROTO_IPV6, &nxt);
+ if (off < 0 || m->m_pkthdr.len < off) {
+ return FALSE;
+ }
+
+ switch (nxt) {
+ case IPPROTO_TCP:
+ if (off + sizeof(struct tcphdr) > m->m_pkthdr.len) {
+ return FALSE;
+ }
+ break;
+ case IPPROTO_UDP:
+ if (off + sizeof(struct udphdr) > m->m_pkthdr.len) {
+ return FALSE;
+ }
+ break;
+ case IPPROTO_ICMPV6:
+ if (off + sizeof(uint32_t) > m->m_pkthdr.len) {
+ return FALSE;
+ }
+ break;
+ case IPPROTO_NONE:
+ return TRUE;
+ case IPPROTO_ESP:
+ return TRUE;
+ case IPPROTO_IPCOMP:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+ return TRUE;
+}
+
struct ip6aux *
ip6_addaux(struct mbuf *m)
{
@@ -2240,8 +2410,82 @@ sysctl_ip6_input_getperf SYSCTL_HANDLER_ARGS
{
#pragma unused(oidp, arg1, arg2)
if (req->oldptr == USER_ADDR_NULL) {
- req->oldlen = (size_t)sizeof(struct ipstat);
+ req->oldlen = (size_t)sizeof(struct net_perf);
}
return SYSCTL_OUT(req, &net_perf, MIN(sizeof(net_perf), req->oldlen));
}
+
+
+/*
+ * Initialize IPv6 source address hash table.
+ */
+static void
+in6_ifaddrhashtbl_init(void)
+{
+ int i, k, p;
+
+ if (in6_ifaddrhashtbl != NULL) {
+ return;
+ }
+
+ PE_parse_boot_argn("ina6ddr_nhash", &in6addr_nhash,
+ sizeof(in6addr_nhash));
+ if (in6addr_nhash == 0) {
+ in6addr_nhash = IN6ADDR_NHASH;
+ }
+
+ MALLOC(in6_ifaddrhashtbl, struct in6_ifaddrhashhead *,
+ in6addr_nhash * sizeof(*in6_ifaddrhashtbl),
+ M_IFADDR, M_WAITOK | M_ZERO);
+ if (in6_ifaddrhashtbl == NULL) {
+ panic("in6_ifaddrhashtbl allocation failed");
+ }
+
+ /*
+ * Generate the next largest prime greater than in6addr_nhash.
+ */
+ k = (in6addr_nhash % 2 == 0) ? in6addr_nhash + 1 : in6addr_nhash + 2;
+ for (;;) {
+ p = 1;
+ for (i = 3; i * i <= k; i += 2) {
+ if (k % i == 0) {
+ p = 0;
+ }
+ }
+ if (p == 1) {
+ break;
+ }
+ k += 2;
+ }
+ in6addr_hashp = k;
+}
+
+static int
+sysctl_ip6_checkinterface SYSCTL_HANDLER_ARGS
+{
+#pragma unused(arg1, arg2)
+ int error, i;
+
+ i = ip6_checkinterface;
+ error = sysctl_handle_int(oidp, &i, 0, req);
+ if (error || req->newptr == USER_ADDR_NULL) {
+ return error;
+ }
+
+ switch (i) {
+ case IP6_CHECKINTERFACE_WEAK_ES:
+ case IP6_CHECKINTERFACE_HYBRID_ES:
+ case IP6_CHECKINTERFACE_STRONG_ES:
+ if (ip6_checkinterface != i) {
+ ip6_checkinterface = i;
+ os_log(OS_LOG_DEFAULT, "%s: ip6_checkinterface is now %d\n",
+ __func__, ip6_checkinterface);
+ }
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ return error;
+}
diff --git a/bsd/netinet6/ip6_output.c b/bsd/netinet6/ip6_output.c
index 1d2f1a9a4..ccb9a37d0 100644
--- a/bsd/netinet6/ip6_output.c
+++ b/bsd/netinet6/ip6_output.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -4143,7 +4143,7 @@ ip6_mloopback(struct ifnet *srcifp, struct ifnet *origifp, struct mbuf *m,
struct in6_ifaddr *ia;
lck_rw_lock_shared(&in6_ifaddr_rwlock);
- for (ia = in6_ifaddrs; ia != NULL; ia = ia->ia_next) {
+ TAILQ_FOREACH(ia, IN6ADDR_HASH(&src), ia6_hash) {
IFA_LOCK_SPIN(&ia->ia_ifa);
/* compare against src addr with embedded scope */
if (IN6_ARE_ADDR_EQUAL(&ia->ia_addr.sin6_addr, &src)) {
diff --git a/bsd/netinet6/ip6_var.h b/bsd/netinet6/ip6_var.h
index 3dca8411e..a9b9cab15 100644
--- a/bsd/netinet6/ip6_var.h
+++ b/bsd/netinet6/ip6_var.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -365,6 +365,9 @@ struct ip6stat {
u_quad_t ip6s_clat464_v6addr_conffail;
u_quad_t ip6s_clat464_plat64_pfx_setfail;
u_quad_t ip6s_clat464_plat64_pfx_getfail;
+
+ u_quad_t ip6s_rcv_if_weak_match;
+ u_quad_t ip6s_rcv_if_no_match;
};
enum ip6s_sources_rule_index {
@@ -525,6 +528,7 @@ extern int ip6_unknown_opt(u_int8_t *, struct mbuf *, int);
extern char *ip6_get_prevhdr(struct mbuf *, int);
extern int ip6_nexthdr(struct mbuf *, int, int, int *);
extern int ip6_lasthdr(struct mbuf *, int, int, int *);
+extern boolean_t ip6_pkt_has_ulp(struct mbuf *m);
extern void ip6_moptions_init(void);
extern struct ip6_moptions *ip6_allocmoptions(int);
diff --git a/bsd/netinet6/mld6.c b/bsd/netinet6/mld6.c
index ba2daacdc..9f5d020bf 100644
--- a/bsd/netinet6/mld6.c
+++ b/bsd/netinet6/mld6.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -1512,18 +1512,16 @@ mld_v1_input_report(struct ifnet *ifp, struct mbuf *m,
int
mld_input(struct mbuf *m, int off, int icmp6len)
{
- struct ifnet *ifp;
- struct ip6_hdr *ip6;
- struct mld_hdr *mld;
- int mldlen;
+ struct ifnet *ifp = NULL;
+ struct ip6_hdr *ip6 = NULL;
+ struct mld_hdr *mld = NULL;
+ int mldlen = 0;
MLD_PRINTF(("%s: called w/mbuf (0x%llx,%d)\n", __func__,
(uint64_t)VM_KERNEL_ADDRPERM(m), off));
ifp = m->m_pkthdr.rcvif;
- ip6 = mtod(m, struct ip6_hdr *);
-
/* Pullup to appropriate size. */
mld = (struct mld_hdr *)(mtod(m, uint8_t *) + off);
if (mld->mld_type == MLD_LISTENER_QUERY &&
@@ -1539,6 +1537,7 @@ mld_input(struct mbuf *m, int off, int icmp6len)
icmp6stat.icp6s_badlen++;
return IPPROTO_DONE;
}
+ ip6 = mtod(m, struct ip6_hdr *);
/*
* Userland needs to see all of this traffic for implementing
diff --git a/bsd/netinet6/nd6.c b/bsd/netinet6/nd6.c
index 0af74cc8d..e55d05571 100644
--- a/bsd/netinet6/nd6.c
+++ b/bsd/netinet6/nd6.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -1267,10 +1267,10 @@ nd6_service(void *arg)
*/
addrloop:
lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
- for (ia6 = in6_ifaddrs; ia6; ia6 = nia6) {
+
+ TAILQ_FOREACH_SAFE(ia6, &in6_ifaddrhead, ia6_link, nia6) {
int oldflags = ia6->ia6_flags;
ap->found++;
- nia6 = ia6->ia_next;
IFA_LOCK(&ia6->ia_ifa);
/*
* Extra reference for ourselves; it's no-op if
@@ -2991,39 +2991,40 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
NDPR_ADDREF_LOCKED(pr);
NDPR_UNLOCK(pr);
lck_rw_lock_exclusive(&in6_ifaddr_rwlock);
- ia = in6_ifaddrs;
- while (ia != NULL) {
- IFA_LOCK(&ia->ia_ifa);
- if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0) {
- IFA_UNLOCK(&ia->ia_ifa);
- ia = ia->ia_next;
- continue;
- }
+ bool from_begining = true;
+ while (from_begining) {
+ from_begining = false;
+ TAILQ_FOREACH(ia, &in6_ifaddrhead, ia6_link) {
+ IFA_LOCK(&ia->ia_ifa);
+ if ((ia->ia6_flags & IN6_IFF_AUTOCONF) == 0) {
+ IFA_UNLOCK(&ia->ia_ifa);
+ continue;
+ }
- if (ia->ia6_ndpr == pr) {
- IFA_ADDREF_LOCKED(&ia->ia_ifa);
+ if (ia->ia6_ndpr == pr) {
+ IFA_ADDREF_LOCKED(&ia->ia_ifa);
+ IFA_UNLOCK(&ia->ia_ifa);
+ lck_rw_done(&in6_ifaddr_rwlock);
+ lck_mtx_unlock(nd6_mutex);
+ in6_purgeaddr(&ia->ia_ifa);
+ IFA_REMREF(&ia->ia_ifa);
+ lck_mtx_lock(nd6_mutex);
+ lck_rw_lock_exclusive(
+ &in6_ifaddr_rwlock);
+ /*
+ * Purging the address caused
+ * in6_ifaddr_rwlock to be
+ * dropped and
+ * reacquired; therefore search again
+ * from the beginning of in6_ifaddrs.
+ * The same applies for the prefix list.
+ */
+ iterate_pfxlist_again = true;
+ from_begining = true;
+ break;
+ }
IFA_UNLOCK(&ia->ia_ifa);
- lck_rw_done(&in6_ifaddr_rwlock);
- lck_mtx_unlock(nd6_mutex);
- in6_purgeaddr(&ia->ia_ifa);
- IFA_REMREF(&ia->ia_ifa);
- lck_mtx_lock(nd6_mutex);
- lck_rw_lock_exclusive(
- &in6_ifaddr_rwlock);
- /*
- * Purging the address caused
- * in6_ifaddr_rwlock to be
- * dropped and
- * reacquired; therefore search again
- * from the beginning of in6_ifaddrs.
- * The same applies for the prefix list.
- */
- ia = in6_ifaddrs;
- iterate_pfxlist_again = true;
- continue;
}
- IFA_UNLOCK(&ia->ia_ifa);
- ia = ia->ia_next;
}
lck_rw_done(&in6_ifaddr_rwlock);
NDPR_LOCK(pr);
diff --git a/bsd/netinet6/nd6_nbr.c b/bsd/netinet6/nd6_nbr.c
index ae3e33e53..5b57e6387 100644
--- a/bsd/netinet6/nd6_nbr.c
+++ b/bsd/netinet6/nd6_nbr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -259,30 +259,30 @@ nd6_ns_input(
{
struct ifnet *ifp = m->m_pkthdr.rcvif;
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
- struct nd_neighbor_solicit *nd_ns;
+ struct nd_neighbor_solicit *nd_ns = NULL;
struct in6_addr saddr6 = ip6->ip6_src;
struct in6_addr daddr6 = ip6->ip6_dst;
- struct in6_addr taddr6;
- struct in6_addr myaddr6;
+ struct in6_addr taddr6 = {};
+ struct in6_addr myaddr6 = {};
char *lladdr = NULL;
struct ifaddr *ifa = NULL;
int lladdrlen = 0;
int anycast = 0, proxy = 0, dadprogress = 0;
- int tlladdr;
- union nd_opts ndopts;
- struct sockaddr_dl proxydl;
- boolean_t advrouter;
- boolean_t is_dad_probe;
+ int tlladdr = 0;
+ union nd_opts ndopts = {};
+ struct sockaddr_dl proxydl = {};
+ boolean_t advrouter = FALSE;
+ boolean_t is_dad_probe = FALSE;
int oflgclr = 0;
/* Expect 32-bit aligned data pointer on strict-align platforms */
MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
IP6_EXTHDR_CHECK(m, off, icmp6len, return );
+ ip6 = mtod(m, struct ip6_hdr *);
nd_ns = (struct nd_neighbor_solicit *)((caddr_t)ip6 + off);
m->m_pkthdr.pkt_flags |= PKTF_INET6_RESOLVE;
- ip6 = mtod(m, struct ip6_hdr *); /* adjust pointer for safety */
taddr6 = nd_ns->nd_ns_target;
if (in6_setscope(&taddr6, ifp, NULL) != 0) {
goto bad;
@@ -923,6 +923,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
}
IP6_EXTHDR_CHECK(m, off, icmp6len, return );
+ ip6 = mtod(m, struct ip6_hdr *);
nd_na = (struct nd_neighbor_advert *)((caddr_t)ip6 + off);
m->m_pkthdr.pkt_flags |= PKTF_INET6_RESOLVE;
diff --git a/bsd/netinet6/nd6_rtr.c b/bsd/netinet6/nd6_rtr.c
index e0c8b4864..e47f614ba 100644
--- a/bsd/netinet6/nd6_rtr.c
+++ b/bsd/netinet6/nd6_rtr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003-2018 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -270,11 +270,11 @@ nd6_rs_input(
{
struct ifnet *ifp = m->m_pkthdr.rcvif;
struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
- struct nd_router_solicit *nd_rs;
+ struct nd_router_solicit *nd_rs = NULL;
struct in6_addr saddr6 = ip6->ip6_src;
char *lladdr = NULL;
int lladdrlen = 0;
- union nd_opts ndopts;
+ union nd_opts ndopts = {};
/* Expect 32-bit aligned data pointer on strict-align platforms */
MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
@@ -315,6 +315,7 @@ nd6_rs_input(
}
IP6_EXTHDR_CHECK(m, off, icmp6len, return );
+ ip6 = mtod(m, struct ip6_hdr *);
nd_rs = (struct nd_router_solicit *)((caddr_t)ip6 + off);
icmp6len -= sizeof(*nd_rs);
nd6_option_init(nd_rs + 1, icmp6len, &ndopts);
@@ -425,6 +426,7 @@ nd6_ra_input(
}
IP6_EXTHDR_CHECK(m, off, icmp6len, return );
+ ip6 = mtod(m, struct ip6_hdr *);
nd_ra = (struct nd_router_advert *)((caddr_t)ip6 + off);
icmp6len -= sizeof(*nd_ra);
diff --git a/bsd/netinet6/route6.c b/bsd/netinet6/route6.c
index cc0886d44..87af9c753 100644
--- a/bsd/netinet6/route6.c
+++ b/bsd/netinet6/route6.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -77,22 +77,24 @@ int
route6_input(struct mbuf **mp, int *offp, int proto)
{
#pragma unused(proto)
- struct ip6_hdr *ip6;
+ struct ip6_hdr *ip6 = NULL;
struct mbuf *m = *mp;
- struct ip6_rthdr *rh;
- int off = *offp, rhlen;
+ struct ip6_rthdr *rh = NULL;
+ int off = *offp, rhlen = 0;
#ifdef notyet
- struct ip6aux *ip6a;
+ struct ip6aux *ip6a = NULL;
ip6a = ip6_findaux(m);
if (ip6a) {
/* XXX reject home-address option before rthdr */
if (ip6a->ip6a_flags & IP6A_SWAP) {
ip6stat.ip6s_badoptions++;
+ *mp = NULL;
m_freem(m);
return IPPROTO_DONE;
}
}
+ ip6a = NULL;
#endif /* notyet */
IP6_EXTHDR_CHECK(m, off, sizeof(*rh), return IPPROTO_DONE);
@@ -116,6 +118,7 @@ route6_input(struct mbuf **mp, int *offp, int proto)
return IPPROTO_DONE;
}
+ *mp = m;
*offp += rhlen;
return rh->ip6r_nxt;
}
diff --git a/bsd/netkey/key.c b/bsd/netkey/key.c
index 87d880897..2639379d1 100644
--- a/bsd/netkey/key.c
+++ b/bsd/netkey/key.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008-2016 Apple Inc. All rights reserved.
+ * Copyright (c) 2008-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
@@ -163,8 +163,8 @@ static int key_blockacq_count = 10; /* counter for blocking SADB_ACQUIRE.*/
static int key_blockacq_lifetime = 20; /* lifetime for blocking SADB_ACQUIRE.*/
static int key_preferred_oldsa = 0; /* preferred old sa rather than new sa.*/
__private_extern__ int natt_keepalive_interval = 20; /* interval between natt keepalives.*/
-__private_extern__ int ipsec_policy_count = 0;
-static int ipsec_sav_count = 0;
+static u_int32_t ipsec_policy_count = 0;
+static u_int32_t ipsec_sav_count = 0;
static u_int32_t acq_seq = 0;
static int key_tick_init_random = 0;
@@ -369,9 +369,9 @@ ipseclog((LOG_DEBUG, "%s: direction mismatched (TREE=%d SP=%d), " \
#if 1
#define KMALLOC_WAIT(p, t, n) \
-((p) = (t) _MALLOC((u_int32_t)(n), M_SECA, M_WAITOK))
+((p) = (t) _MALLOC((n), M_SECA, M_WAITOK))
#define KMALLOC_NOWAIT(p, t, n) \
-((p) = (t) _MALLOC((u_int32_t)(n), M_SECA, M_NOWAIT))
+((p) = (t) _MALLOC((n), M_SECA, M_NOWAIT))
#define KFREE(p) \
_FREE((caddr_t)(p), M_SECA);
#else
@@ -527,9 +527,6 @@ static int key_getspi(struct socket *, struct mbuf *,
static u_int32_t key_do_getnewspi(struct sadb_spirange *, struct secasindex *);
static int key_update(struct socket *, struct mbuf *,
const struct sadb_msghdr *);
-#if IPSEC_DOSEQCHECK
-static struct secasvar *key_getsavbyseq(struct secashead *, u_int32_t);
-#endif
static int key_add(struct socket *, struct mbuf *, const struct sadb_msghdr *);
static int key_setident(struct secashead *, struct mbuf *,
const struct sadb_msghdr *);
@@ -3127,6 +3124,7 @@ key_spdenable(
}
sp->disabled = 0;
+ key_freesp(sp, KEY_SADB_LOCKED);
lck_mtx_unlock(sadb_mutex);
{
@@ -3190,6 +3188,7 @@ key_spddisable(
}
sp->disabled = 1;
+ key_freesp(sp, KEY_SADB_LOCKED);
lck_mtx_unlock(sadb_mutex);
{
@@ -3265,6 +3264,7 @@ key_spdget(
}
lck_mtx_unlock(sadb_mutex);
n = key_setdumpsp(sp, SADB_X_SPDGET, 0, mhp->msg->sadb_msg_pid);
+ key_freesp(sp, KEY_SADB_UNLOCKED);
if (n != NULL) {
m_freem(m);
return key_sendup_mbuf(so, n, KEY_SENDUP_ONE);
@@ -3432,7 +3432,8 @@ key_spddump(
const struct sadb_msghdr *mhp)
{
struct secpolicy *sp, **spbuf = NULL, **sp_ptr;
- int cnt = 0, bufcount;
+ u_int32_t cnt = 0, bufcount = 0;
+ size_t total_req_size = 0;
u_int dir;
struct mbuf *n;
int error = 0;
@@ -3446,8 +3447,17 @@ key_spddump(
error = ENOENT;
goto end;
}
- bufcount += 256; /* extra */
- KMALLOC_WAIT(spbuf, struct secpolicy**, bufcount * sizeof(struct secpolicy*));
+
+ if (os_add_overflow(bufcount, 256, &bufcount)) {
+ ipseclog((LOG_DEBUG, "key_spddump: bufcount overflow, ipsec policy count %u.\n", ipsec_policy_count));
+ bufcount = ipsec_policy_count;
+ }
+
+ if (os_mul_overflow(bufcount, sizeof(struct secpolicy *), &total_req_size)) {
+ panic("key_spddump spbuf requested memory overflow %u\n", bufcount);
+ }
+
+ KMALLOC_WAIT(spbuf, struct secpolicy**, total_req_size);
if (spbuf == NULL) {
ipseclog((LOG_DEBUG, "key_spddump: No more memory.\n"));
error = ENOMEM;
@@ -3992,14 +4002,6 @@ key_newsav(
switch (mhp->msg->sadb_msg_type) {
case SADB_GETSPI:
key_setspi(newsav, 0);
-
-#if IPSEC_DOSEQCHECK
- /* sync sequence number */
- if (mhp->msg->sadb_msg_seq == 0) {
- newsav->seq =
- (acq_seq = (acq_seq == ~0 ? 1 : ++acq_seq));
- } else
-#endif
newsav->seq = mhp->msg->sadb_msg_seq;
break;
@@ -4156,12 +4158,6 @@ key_newsav2(struct secashead *sah,
}
bzero((caddr_t)newsav, sizeof(struct secasvar));
-#if IPSEC_DOSEQCHECK
- /* sync sequence number */
- if (seq == 0) {
- newsav->seq = (acq_seq = (acq_seq == ~0 ? 1 : ++acq_seq));
- } else
-#endif
newsav->seq = seq;
key_setspi(newsav, spi);
@@ -5834,7 +5830,7 @@ key_ismyaddr6(
struct in6_multi *in6m;
lck_rw_lock_shared(&in6_ifaddr_rwlock);
- for (ia = in6_ifaddrs; ia; ia = ia->ia_next) {
+ TAILQ_FOREACH(ia, &in6_ifaddrhead, ia6_link) {
IFA_LOCK(&ia->ia_ifa);
if (key_sockaddrcmp((struct sockaddr *)&sin6,
(struct sockaddr *)&ia->ia_addr, 0) == 0) {
@@ -6358,7 +6354,8 @@ key_timehandler(void)
struct secpolicy **spbuf = NULL, **spptr = NULL;
struct secasvar **savexbuf = NULL, **savexptr = NULL;
struct secasvar **savkabuf = NULL, **savkaptr = NULL;
- int spbufcount = 0, savbufcount = 0, spcount = 0, savexcount = 0, savkacount = 0, cnt;
+ u_int64_t total_req_size = 0;
+ u_int32_t spbufcount = 0, savbufcount = 0, spcount = 0, savexcount = 0, savkacount = 0, cnt;
int stop_handler = 1; /* stop the timehandler */
microtime(&tv);
@@ -6366,19 +6363,32 @@ key_timehandler(void)
/* pre-allocate buffers before taking the lock */
/* if allocation failures occur - portions of the processing will be skipped */
if ((spbufcount = ipsec_policy_count) != 0) {
- spbufcount += 256;
- KMALLOC_WAIT(spbuf, struct secpolicy **, spbufcount * sizeof(struct secpolicy *));
+ if (os_add_overflow(spbufcount, 256, &spbufcount)) {
+ ipseclog((LOG_DEBUG, "key_timehandler: spbufcount overflow, ipsec policy count %u.\n", ipsec_policy_count));
+ spbufcount = ipsec_policy_count;
+ }
+
+ if (os_mul_overflow(spbufcount, sizeof(struct secpolicy *), &total_req_size)) {
+ panic("key_timehandler spbuf requested memory overflow %u\n", spbufcount);
+ }
+ KMALLOC_WAIT(spbuf, struct secpolicy **, total_req_size);
if (spbuf) {
spptr = spbuf;
}
}
if ((savbufcount = ipsec_sav_count) != 0) {
- savbufcount += 512;
- KMALLOC_WAIT(savexbuf, struct secasvar **, savbufcount * sizeof(struct secasvar *));
+ if (os_add_overflow(savbufcount, 512, &savbufcount)) {
+ ipseclog((LOG_DEBUG, "key_timehandler: savbufcount overflow, ipsec sa count %u.\n", ipsec_sav_count));
+ savbufcount = ipsec_sav_count;
+ }
+ if (os_mul_overflow(savbufcount, sizeof(struct secasvar *), &total_req_size)) {
+ panic("key_timehandler savexbuf requested memory overflow %u\n", savbufcount);
+ }
+ KMALLOC_WAIT(savexbuf, struct secasvar **, total_req_size);
if (savexbuf) {
savexptr = savexbuf;
}
- KMALLOC_WAIT(savkabuf, struct secasvar **, savbufcount * sizeof(struct secasvar *));
+ KMALLOC_WAIT(savkabuf, struct secasvar **, total_req_size);
if (savkabuf) {
savkaptr = savkabuf;
}
@@ -6600,26 +6610,6 @@ key_timehandler(void)
sav = NULL;
}
}
-#if 0 /* XXX Should we keep to send expire message until HARD lifetime ? */
- else if (savbuf && savexcount < savbufcount
- && sav->lft_s != NULL
- && sav->lft_s->sadb_lifetime_addtime != 0
- && tv.tv_sec - sav->created > sav->lft_s->sadb_lifetime_addtime) {
- /*
- * XXX: should be checked to be
- * installed the valid SA.
- */
-
- /*
- * If there is no SA then sending
- * expire message.
- */
- //key_expire(sav);
- sav->refcnt++;
- *savexptr++ = sav;
- savexcount++;
- }
-#endif
/* check HARD lifetime by bytes */
else if (sav->lft_h->sadb_lifetime_bytes != 0
&& sav->lft_h->sadb_lifetime_bytes < sav->lft_c->sadb_lifetime_bytes) {
@@ -6741,13 +6731,13 @@ key_timehandler(void)
}
if (savkabuf && savkacount > 0) {
struct secasvar **savkaptr_sav = savkaptr;
- int cnt_send = savkacount;
+ u_int32_t cnt_send = savkacount;
while (cnt_send--) {
if (ipsec_send_natt_keepalive(*(--savkaptr))) {
// iterate (all over again) and update timestamps
struct secasvar **savkaptr_update = savkaptr_sav;
- int cnt_update = savkacount;
+ u_int32_t cnt_update = savkacount;
while (cnt_update--) {
key_update_natt_keepalive_timestamp(*savkaptr,
*(--savkaptr_update));
@@ -7126,6 +7116,7 @@ key_getspi(
off += PFKEY_ALIGN8(sizeof(struct sadb_msg));
m_sa = (struct sadb_sa *)(void *)(mtod(n, caddr_t) + off);
+ memset(m_sa, 0, PFKEY_ALIGN8(sizeof(struct sadb_sa)));
m_sa->sadb_sa_len = PFKEY_UNIT64(sizeof(struct sadb_sa));
m_sa->sadb_sa_exttype = SADB_EXT_SA;
m_sa->sadb_sa_spi = htonl(spi);
@@ -7394,17 +7385,6 @@ key_update(
return key_senderror(so, m, error);
}
- /* find a SA with sequence number. */
-#if IPSEC_DOSEQCHECK
- if (mhp->msg->sadb_msg_seq != 0
- && (sav = key_getsavbyseq(sah, mhp->msg->sadb_msg_seq)) == NULL) {
- lck_mtx_unlock(sadb_mutex);
- ipseclog((LOG_DEBUG,
- "key_update: no larval SA with sequence %u exists.\n",
- mhp->msg->sadb_msg_seq));
- return key_senderror(so, m, ENOENT);
- }
-#else
if ((sav = key_getsavbyspi(sah, sa0->sadb_sa_spi)) == NULL) {
lck_mtx_unlock(sadb_mutex);
ipseclog((LOG_DEBUG,
@@ -7412,38 +7392,27 @@ key_update(
(u_int32_t)ntohl(sa0->sadb_sa_spi)));
return key_senderror(so, m, EINVAL);
}
-#endif
/* validity check */
if (sav->sah->saidx.proto != proto) {
- lck_mtx_unlock(sadb_mutex);
ipseclog((LOG_DEBUG,
"key_update: protocol mismatched (DB=%u param=%u)\n",
sav->sah->saidx.proto, proto));
- return key_senderror(so, m, EINVAL);
- }
-#if IPSEC_DOSEQCHECK
- if (sav->spi != sa0->sadb_sa_spi) {
lck_mtx_unlock(sadb_mutex);
- ipseclog((LOG_DEBUG,
- "key_update: SPI mismatched (DB:%u param:%u)\n",
- (u_int32_t)ntohl(sav->spi),
- (u_int32_t)ntohl(sa0->sadb_sa_spi)));
return key_senderror(so, m, EINVAL);
}
-#endif
+
if (sav->pid != mhp->msg->sadb_msg_pid) {
- lck_mtx_unlock(sadb_mutex);
ipseclog((LOG_DEBUG,
"key_update: pid mismatched (DB:%u param:%u)\n",
sav->pid, mhp->msg->sadb_msg_pid));
+ lck_mtx_unlock(sadb_mutex);
return key_senderror(so, m, EINVAL);
}
/* copy sav values */
error = key_setsaval(sav, m, mhp);
if (error) {
- key_freesav(sav, KEY_SADB_LOCKED);
lck_mtx_unlock(sadb_mutex);
return key_senderror(so, m, error);
}
@@ -7465,7 +7434,6 @@ key_update(
/* check SA values to be mature. */
if ((error = key_mature(sav)) != 0) {
- key_freesav(sav, KEY_SADB_LOCKED);
lck_mtx_unlock(sadb_mutex);
return key_senderror(so, m, error);
}
@@ -7648,44 +7616,6 @@ key_migrate(struct socket *so,
}
}
-/*
- * search SAD with sequence for a SA which state is SADB_SASTATE_LARVAL.
- * only called by key_update().
- * OUT:
- * NULL : not found
- * others : found, pointer to a SA.
- */
-#if IPSEC_DOSEQCHECK
-static struct secasvar *
-key_getsavbyseq(
- struct secashead *sah,
- u_int32_t seq)
-{
- struct secasvar *sav;
- u_int state;
-
- LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);
-
- state = SADB_SASTATE_LARVAL;
-
- /* search SAD with sequence number ? */
- LIST_FOREACH(sav, &sah->savtree[state], chain) {
- KEY_CHKSASTATE(state, sav->state, "key_getsabyseq");
-
- if (sav->seq == seq) {
- sav->refcnt++;
- KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
- printf("DP key_getsavbyseq cause "
- "refcnt++:%d SA:0x%llx\n", sav->refcnt,
- (uint64_t)VM_KERNEL_ADDRPERM(sav)));
- return sav;
- }
- }
-
- return NULL;
-}
-#endif
-
/*
* SADB_ADD processing
* add a entry to SA database, when received
@@ -9564,11 +9494,12 @@ key_dump(
struct secashead *sah;
struct secasvar *sav;
struct sav_dump_elem *savbuf = NULL, *elem_ptr;
+ size_t total_req_size = 0;
+ u_int32_t bufcount = 0, cnt = 0, cnt2 = 0;
u_int16_t proto;
u_int stateidx;
u_int8_t satype;
u_int8_t state;
- int cnt = 0, cnt2, bufcount;
struct mbuf *n;
int error = 0;
@@ -9585,12 +9516,21 @@ key_dump(
return key_senderror(so, m, EINVAL);
}
- if ((bufcount = ipsec_sav_count) <= 0) {
+ if ((bufcount = ipsec_sav_count) == 0) {
error = ENOENT;
goto end;
}
- bufcount += 512; /* extra */
- KMALLOC_WAIT(savbuf, struct sav_dump_elem*, bufcount * sizeof(struct sav_dump_elem));
+
+ if (os_add_overflow(bufcount, 512, &bufcount)) {
+ ipseclog((LOG_DEBUG, "key_dump: bufcount overflow, ipsec sa count %u.\n", ipsec_sav_count));
+ bufcount = ipsec_sav_count;
+ }
+
+ if (os_mul_overflow(bufcount, sizeof(struct sav_dump_elem), &total_req_size)) {
+ panic("key_dump savbuf requested memory overflow %u\n", bufcount);
+ }
+
+ KMALLOC_WAIT(savbuf, struct sav_dump_elem*, total_req_size);
if (savbuf == NULL) {
ipseclog((LOG_DEBUG, "key_dump: No more memory.\n"));
error = ENOMEM;
@@ -10111,6 +10051,16 @@ key_parse(
}
}
+ void *migrate_src = mh.ext[SADB_EXT_MIGRATE_ADDRESS_SRC];
+ void *migrate_dst = mh.ext[SADB_EXT_MIGRATE_ADDRESS_DST];
+ if (migrate_src != NULL && migrate_dst != NULL) {
+ error = key_validate_address_pair((struct sadb_address *)(migrate_src),
+ (struct sadb_address *)(migrate_dst));
+ if (error != 0) {
+ goto senderror;
+ }
+ }
+
if (msg->sadb_msg_type >= sizeof(key_typesw) / sizeof(key_typesw[0]) ||
key_typesw[msg->sadb_msg_type] == NULL) {
PFKEY_STAT_INCREMENT(pfkeystat.out_invmsgtype);
@@ -10247,6 +10197,16 @@ key_align(
}
extlen = PFKEY_UNUNIT64(ext->sadb_ext_len);
+ if (off + extlen > end) {
+ ipseclog((LOG_DEBUG,
+ "key_align: ext type %u invalid ext length %d "
+ "offset %zu sadb message total len %zu is passed.\n",
+ ext->sadb_ext_type, extlen, off, end));
+ bzero_mbuf(m);
+ m_freem(m);
+ PFKEY_STAT_INCREMENT(pfkeystat.out_invlen);
+ return EINVAL;
+ }
if (key_validate_ext(ext, extlen)) {
bzero_mbuf(m);
@@ -10606,7 +10566,8 @@ key_getsastat(struct socket *so,
const struct sadb_msghdr *mhp)
{
struct sadb_session_id *session_id;
- u_int32_t bufsize, arg_count, res_count;
+ u_int64_t bufsize = 0;
+ u_int32_t arg_count, res_count;
struct sadb_sastat *sa_stats_arg;
struct sastat *sa_stats_sav = NULL;
struct mbuf *n;
@@ -10637,12 +10598,15 @@ key_getsastat(struct socket *so,
LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED);
// exit early if there are no active SAs
- if (ipsec_sav_count <= 0) {
+ if (ipsec_sav_count == 0) {
printf("%s: No active SAs.\n", __FUNCTION__);
error = ENOENT;
goto end;
}
- bufsize = (ipsec_sav_count + 1) * sizeof(*sa_stats_sav);
+
+ if (os_mul_overflow(ipsec_sav_count + 1, sizeof(*sa_stats_sav), &bufsize)) {
+ panic("key_getsastat bufsize requested memory overflow %u\n", ipsec_sav_count);
+ }
KMALLOC_WAIT(sa_stats_sav, __typeof__(sa_stats_sav), bufsize);
if (sa_stats_sav == NULL) {
@@ -10661,6 +10625,13 @@ key_getsastat(struct socket *so,
error = ENOENT;
goto end;
}
+ if (PFKEY_UNUNIT64(sa_stats_arg->sadb_sastat_len) < (sizeof(*sa_stats_arg) +
+ (arg_count * sizeof(struct sastat)))) {
+ printf("%s: invalid message is passed. sa stat extlen shorter than requested stat length.\n", __FUNCTION__);
+ error = EINVAL;
+ goto end;
+ }
+
res_count = 0;
if (key_getsastatbyspi((struct sastat *)(sa_stats_arg + 1),
diff --git a/bsd/nfs/nfs_socket.c b/bsd/nfs/nfs_socket.c
index e5c2a590e..b0fad27f1 100644
--- a/bsd/nfs/nfs_socket.c
+++ b/bsd/nfs/nfs_socket.c
@@ -1799,23 +1799,21 @@ nfs_connect(struct nfsmount *nmp, int verbose, int timeo)
if (!NFS_BITMAP_ISSET(nmp->nm_mattrs, NFS_MATTR_SOCKET_TYPE)) {
nmp->nm_sotype = 0;
}
- if (!NFS_BITMAP_ISSET(nmp->nm_mattrs, NFS_MATTR_NFS_VERSION)) {
#if CONFIG_NFS4
- if (nmp->nm_vers >= NFS_VER4) {
- if (!NFS_BITMAP_ISSET(nmp->nm_mattrs, NFS_MATTR_NFS_PORT)) {
- nmp->nm_nfsport = 0;
- }
- if (nmp->nm_cbid) {
- nfs4_mount_callback_shutdown(nmp);
- }
- if (IS_VALID_CRED(nmp->nm_mcred)) {
- kauth_cred_unref(&nmp->nm_mcred);
- }
- bzero(&nmp->nm_un, sizeof(nmp->nm_un));
+ if (nmp->nm_vers >= NFS_VER4) {
+ if (!NFS_BITMAP_ISSET(nmp->nm_mattrs, NFS_MATTR_NFS_PORT)) {
+ nmp->nm_nfsport = 0;
}
-#endif
- nmp->nm_vers = 0;
+ if (nmp->nm_cbid) {
+ nfs4_mount_callback_shutdown(nmp);
+ }
+ if (IS_VALID_CRED(nmp->nm_mcred)) {
+ kauth_cred_unref(&nmp->nm_mcred);
+ }
+ bzero(&nmp->nm_un, sizeof(nmp->nm_un));
}
+#endif
+ nmp->nm_vers = 0;
}
lck_mtx_unlock(&nmp->nm_lock);
nmp->nm_nso = NULL;
diff --git a/bsd/sys/proc.h b/bsd/sys/proc.h
index e427f2ebe..65ab9901a 100644
--- a/bsd/sys/proc.h
+++ b/bsd/sys/proc.h
@@ -414,6 +414,7 @@ extern int proc_pidoriginatoruuid(uuid_t uuid_buf, uint32_t buffersize);
extern uint64_t proc_was_throttled(proc_t);
extern uint64_t proc_did_throttle(proc_t);
+extern bool proc_is_traced(proc_t p);
extern void proc_coalitionids(proc_t, uint64_t[COALITION_NUM_TYPES]);
diff --git a/bsd/sys/reason.h b/bsd/sys/reason.h
index 355b59ae9..516521f9f 100644
--- a/bsd/sys/reason.h
+++ b/bsd/sys/reason.h
@@ -113,11 +113,12 @@ void os_reason_set_description_data(os_reason_t cur_reason, uint32_t type, void
#define OS_REASON_SANDBOX 25
#define OS_REASON_SECURITY 26
#define OS_REASON_ENDPOINTSECURITY 27
+#define OS_REASON_PAC_EXCEPTION 28
/*
* Update whenever new OS_REASON namespaces are added.
*/
-#define OS_REASON_MAX_VALID_NAMESPACE OS_REASON_ENDPOINTSECURITY
+#define OS_REASON_MAX_VALID_NAMESPACE OS_REASON_PAC_EXCEPTION
#define OS_REASON_BUFFER_MAX_SIZE 5120
diff --git a/bsd/sys/vnode.h b/bsd/sys/vnode.h
index 7dfb01ef2..3a727171c 100644
--- a/bsd/sys/vnode.h
+++ b/bsd/sys/vnode.h
@@ -1769,6 +1769,24 @@ int vn_getpath_fsenter_with_parent(struct vnode *dvp, struct vnode *vp, char
*/
int vn_getpath_ext(struct vnode *vp, struct vnode *dvp, char *pathbuf, int *len, int flags);
+/*!
+ * @function vn_getpath_ext_with_mntlen
+ * @abstract Attempt to get a vnode's path without rentering filesystem (unless passed an option to allow)
+ * @discussion Paths to vnodes are not always straightforward: a file with multiple hard-links will have multiple pathnames,
+ * and it is sometimes impossible to determine a vnode's full path. vn_getpath_fsenter() may enter the filesystem
+ * to try to construct a path, so filesystems should be wary of calling it.
+ * @param vp Vnode whose path to get
+ * @param dvp parent vnode of vnode whose path to get, can be NULL if not available.
+ * @param pathbuf Buffer in which to store path.
+ * @param len Destination for length of resulting path string. Result will include NULL-terminator in count--that is, "len"
+ * will be strlen(pathbuf) + 1.
+ * @param mntlen Destination for length of path that is the mount point for the returned path. Will always be less than or equal to len.
+ * will be strlen(pathbuf) + 1.
+ * @param flags flags for controlling behavior.
+ * @return 0 for success or an error.
+ */
+int vn_getpath_ext_with_mntlen(struct vnode *vp, struct vnode *dvp, char *pathbuf, size_t *len, size_t *mntlen, int flags);
+
/* supported flags for vn_getpath_ext */
#define VN_GETPATH_FSENTER 0x0001 /* Can re-enter filesystem */
#define VN_GETPATH_NO_FIRMLINK 0x0002
diff --git a/bsd/sys/vnode_internal.h b/bsd/sys/vnode_internal.h
index 29d6d9f72..0bc52b141 100644
--- a/bsd/sys/vnode_internal.h
+++ b/bsd/sys/vnode_internal.h
@@ -604,7 +604,7 @@ void vnode_trigger_rearm(vnode_t, vfs_context_t);
void vfs_nested_trigger_unmounts(mount_t, int, vfs_context_t);
#endif /* CONFIG_TRIGGERS */
-int build_path_with_parent(vnode_t, vnode_t /* parent */, char *, int, int *, int, vfs_context_t);
+int build_path_with_parent(vnode_t, vnode_t /* parent */, char *, int, int *, size_t *, int, vfs_context_t);
void nspace_resolver_init(void);
void nspace_resolver_exited(struct proc *);
diff --git a/bsd/vfs/vfs_cache.c b/bsd/vfs/vfs_cache.c
index b027e9535..e6a802323 100644
--- a/bsd/vfs/vfs_cache.c
+++ b/bsd/vfs/vfs_cache.c
@@ -428,12 +428,14 @@ vnode_issubdir(vnode_t vp, vnode_t dvp, int *is_subdir, vfs_context_t ctx)
*
*/
int
-build_path_with_parent(vnode_t first_vp, vnode_t parent_vp, char *buff, int buflen, int *outlen, int flags, vfs_context_t ctx)
+build_path_with_parent(vnode_t first_vp, vnode_t parent_vp, char *buff, int buflen,
+ int *outlen, size_t *mntpt_outlen, int flags, vfs_context_t ctx)
{
vnode_t vp, tvp;
vnode_t vp_with_iocount;
vnode_t proc_root_dir_vp;
char *end;
+ char *mntpt_end;
const char *str;
int len;
int ret = 0;
@@ -462,6 +464,7 @@ build_path_with_parent(vnode_t first_vp, vnode_t parent_vp, char *buff, int bufl
end = &buff[buflen - 1];
*end = '\0';
+ mntpt_end = NULL;
/*
* holding the NAME_CACHE_LOCK in shared mode is
@@ -520,6 +523,9 @@ build_path_with_parent(vnode_t first_vp, vnode_t parent_vp, char *buff, int bufl
goto out_unlock;
} else {
vp = vp->v_mount->mnt_vnodecovered;
+ if (!mntpt_end && vp) {
+ mntpt_end = end;
+ }
}
}
}
@@ -761,6 +767,9 @@ build_path_with_parent(vnode_t first_vp, vnode_t parent_vp, char *buff, int bufl
tvp = NULL;
} else {
tvp = tvp->v_mount->mnt_vnodecovered;
+ if (!mntpt_end && tvp) {
+ mntpt_end = end;
+ }
}
}
if (tvp == NULLVP) {
@@ -782,7 +791,10 @@ build_path_with_parent(vnode_t first_vp, vnode_t parent_vp, char *buff, int bufl
/*
* length includes the trailing zero byte
*/
- *outlen = &buff[buflen] - end;
+ *outlen = (int)(&buff[buflen] - end);
+ if (mntpt_outlen && mntpt_end) {
+ *mntpt_outlen = (size_t)*outlen - (size_t)(&buff[buflen] - mntpt_end);
+ }
/* One of the parents was moved during path reconstruction.
* The caller is interested in knowing whether any of the
@@ -798,7 +810,7 @@ build_path_with_parent(vnode_t first_vp, vnode_t parent_vp, char *buff, int bufl
int
build_path(vnode_t first_vp, char *buff, int buflen, int *outlen, int flags, vfs_context_t ctx)
{
- return build_path_with_parent(first_vp, NULL, buff, buflen, outlen, flags, ctx);
+ return build_path_with_parent(first_vp, NULL, buff, buflen, outlen, NULL, flags, ctx);
}
/*
diff --git a/bsd/vfs/vfs_subr.c b/bsd/vfs/vfs_subr.c
index 0d44e828b..08459f529 100644
--- a/bsd/vfs/vfs_subr.c
+++ b/bsd/vfs/vfs_subr.c
@@ -2890,7 +2890,7 @@ vn_getpath_fsenter(struct vnode *vp, char *pathbuf, int *len)
int
vn_getpath_fsenter_with_parent(struct vnode *dvp, struct vnode *vp, char *pathbuf, int *len)
{
- return build_path_with_parent(vp, dvp, pathbuf, *len, len, 0, vfs_context_current());
+ return build_path_with_parent(vp, dvp, pathbuf, *len, len, NULL, 0, vfs_context_current());
}
int
@@ -2910,7 +2910,7 @@ vn_getpath_ext(struct vnode *vp, struct vnode *dvp, char *pathbuf, int *len, int
}
}
- return build_path_with_parent(vp, dvp, pathbuf, *len, len, bpflags, vfs_context_current());
+ return build_path_with_parent(vp, dvp, pathbuf, *len, len, NULL, bpflags, vfs_context_current());
}
int
@@ -2919,6 +2919,40 @@ vn_getpath_no_firmlink(struct vnode *vp, char *pathbuf, int *len)
return vn_getpath_ext(vp, NULLVP, pathbuf, len, VN_GETPATH_NO_FIRMLINK);
}
+int
+vn_getpath_ext_with_mntlen(struct vnode *vp, struct vnode *dvp, char *pathbuf, size_t *len, size_t *mntlen, int flags)
+{
+ int bpflags = (flags & VN_GETPATH_FSENTER) ? 0 : BUILDPATH_NO_FS_ENTER;
+ int local_len;
+ int error;
+
+ if (*len > INT_MAX) {
+ return EINVAL;
+ }
+
+ local_len = *len;
+
+ if (flags && (flags != VN_GETPATH_FSENTER)) {
+ if (flags & VN_GETPATH_NO_FIRMLINK) {
+ bpflags |= BUILDPATH_NO_FIRMLINK;;
+ }
+ if (flags & VN_GETPATH_VOLUME_RELATIVE) {
+ bpflags |= (BUILDPATH_VOLUME_RELATIVE | BUILDPATH_NO_FIRMLINK);
+ }
+ if (flags & VN_GETPATH_NO_PROCROOT) {
+ bpflags |= BUILDPATH_NO_PROCROOT;
+ }
+ }
+
+ error = build_path_with_parent(vp, dvp, pathbuf, local_len, &local_len, mntlen, bpflags, vfs_context_current());
+
+ if (local_len >= 0 && local_len <= (int)*len) {
+ *len = (size_t)local_len;
+ }
+
+ return error;
+}
+
int
vn_getcdhash(struct vnode *vp, off_t offset, unsigned char *cdhash)
{
@@ -3899,6 +3933,12 @@ sysctl_vfs_ctlbyfsid(__unused struct sysctl_oid *oidp, void *arg1, int arg2,
error = safedounmount(mp, flags, ctx);
break;
case VFS_CTL_STATFS:
+#if CONFIG_MACF
+ error = mac_mount_check_stat(ctx, mp);
+ if (error != 0) {
+ break;
+ }
+#endif
req->newidx = 0;
if (is_64_bit) {
req->newptr = vc.vc64.vc_ptr;
diff --git a/config/IOKit.exports b/config/IOKit.exports
index d29f1f01c..86f00a27d 100644
--- a/config/IOKit.exports
+++ b/config/IOKit.exports
@@ -8,6 +8,9 @@ __ZN22IOInterruptEventSource27getPimaryInterruptTimestampEv
__ZN22IOInterruptEventSource31enablePrimaryInterruptTimestampEb
__ZN14IOPMrootDomain11setWakeTimeEy
+
+__ZN12IODMACommand8DispatchE5IORPC
+
_IOAlignmentToSize
_IOBSDNameMatching
_IOBSDRegistryEntryForDeviceTree
diff --git a/config/MasterVersion b/config/MasterVersion
index 9259dc79e..3686593d5 100644
--- a/config/MasterVersion
+++ b/config/MasterVersion
@@ -1,4 +1,4 @@
-19.5.0
+19.6.0
# The first line of this file contains the master version number for the kernel.
# All other instances of the kernel version in xnu are derived from this file.
diff --git a/config/Private.exports b/config/Private.exports
index 0436ff54f..2a8547757 100644
--- a/config/Private.exports
+++ b/config/Private.exports
@@ -507,6 +507,7 @@ _vm_map_trunc_page_mask
_vm_map_wire_and_extract:_vm_map_wire_and_extract_external
_vm_page_wire_count
_vn_getpath_ext
+_vn_getpath_ext_with_mntlen
_vn_getpath_fsenter
_vn_getpath_fsenter_with_parent
_vn_getpath_no_firmlink
diff --git a/iokit/DriverKit/IODMACommand.iig b/iokit/DriverKit/IODMACommand.iig
new file mode 100644
index 000000000..de4dd6d3d
--- /dev/null
+++ b/iokit/DriverKit/IODMACommand.iig
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2020 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#if !__IIG
+#if KERNEL
+#include
+#endif
+#endif
+
+#ifndef _IOKIT_UIODMACOMMMAND_H
+#define _IOKIT_UIODMACOMMMAND_H
+
+#include
+#include
+
+// IODMACommand Create options
+enum {
+ kIODMACommandCreateNoOptions = 0,
+};
+
+// IODMACommand PrepareForDMA options
+enum {
+ kIODMACommandPrepareForDMANoOptions = 0,
+};
+
+// IODMACommand CompleteDMA options
+enum {
+ kIODMACommandCompleteDMANoOptions = 0,
+};
+
+// IODMACommand PerformOperation options
+enum {
+ kIODMACommandPerformOperationOptionRead = 0x00000001,
+ kIODMACommandPerformOperationOptionWrite = 0x00000002,
+ kIODMACommandPerformOperationOptionZero = 0x00000004,
+};
+
+// IODMACommandSpecification options
+enum {
+ kIODMACommandSpecificationNoOptions = 0,
+};
+
+struct IODMACommandSpecification {
+ uint64_t options;
+ uint64_t maxAddressBits;
+ uint64_t _resv[16];
+};
+
+/*!
+ * @class IODMACommand
+ *
+ * @abstract
+ * IODMACommand allows a mapping for DMA to be created from an IOMemoryDescriptor.
+ *
+ * @discussion
+ * IODMACommand allows a mapping for DMA to be created from an IOMemoryDescriptor.
+ * The IODMACommand instance represents the mapping and should be kept prepared for the
+ * duration of the I/O, and completed when the I/O is finished.
+ * IODMACommand does not perform bounce buffering but allows access to the mapping with
+ * the PerformOperation method so that data can moved into and out of the mapping, eg.
+ * to/from a driver allocated bounce buffer.
+ *
+*/
+
+class KERNEL IODMACommand : public OSObject
+{
+public:
+
+ virtual bool
+ init() override;
+
+ virtual void
+ free() override;
+
+ /*!
+ * @brief Create an IODMACommand instance.
+ * @param device The device (typically an IOPCIDevice instance that will be
+ * generating the I/O.
+ * @param options
+ * kIODMACommandCreateNoOptions No options needed
+ * @param specification A caller initialized structure describing
+ * the hardware's DMA capaibilities
+ * @param command Returned IODMACommand object with +1 retain count.
+ * It should be retained until the map is no longer required.
+ * @return kIOReturnSuccess on success. See IOReturn.h for error codes.
+ */
+ static kern_return_t
+ Create(
+ IOService * device,
+ uint64_t options,
+ const IODMACommandSpecification * specification,
+ IODMACommand ** command);
+
+ /*!
+ * @brief Create a DMA mapping for memory.
+ * @param options
+ * kIODMACommandPrepareForDMANoOptions No options needed.
+ * @param memory IOMemoryDescriptor for memory.
+ * @param offset Start offset of the DMA operation in the descriptor.
+ * @param length Pass zero to map the entire memory, or a value <= the length of the descriptor.
+ * @param flags Returned bit mask of flags
+ kIOMemoryDirectionOut the memory is readable
+ kIOMemoryDirectionIn the memory is writable
+ * @param segmentsCount Returned count of segements returned in segments
+ * @param segments Returned DMA physical address and length segments covering the DMA
+ * @return kIOReturnSuccess on success. See IOReturn.h for error codes.
+ */
+ virtual kern_return_t
+ PrepareForDMA(
+ uint64_t options,
+ IOMemoryDescriptor * memory,
+ uint64_t offset,
+ uint64_t length,
+ uint64_t * flags,
+ uint32_t * segmentsCount,
+ IOAddressSegment segments[32]);
+
+ /*!
+ * @brief Release a DMA mapping for memory.
+ * @param options
+ * kIODMACommandCompleteDMANoOptions No options needed.
+ * @return kIOReturnSuccess on success. See IOReturn.h for error codes.
+ */
+ virtual kern_return_t
+ CompleteDMA(
+ uint64_t options);
+
+ /*!
+ * @brief Obtain the parameters of a DMA preparation.
+ * @param offset Returned starting offset of the preparation.
+ * @param length Returned length of the preparation.
+ * @param memory Returned IOMemoryDescriptor of the preparation. This should be
+ * released by the caller.
+ * @return kIOReturnSuccess on success. See IOReturn.h for error codes.
+ */
+ virtual kern_return_t
+ GetPreparation(
+ uint64_t * offset,
+ uint64_t * length,
+ IOMemoryDescriptor ** memory);
+
+ /*!
+ * @brief Perform CPU access to the DMA mapping.
+ * @param options Flags for the operation to be performed
+ kIODMACommandPerformOperationOptionRead read from the DMA mapping to
+ the memory specified with the data param
+ kIODMACommandPerformOperationOptionWrite write to the DMA mapping from
+ the memory specified with the data param
+ kIODMACommandPerformOperationOptionZero zero the DMA mapping
+ * @param dmaOffset Offset into the DMA mapping for the operation to begin.
+ * @param length Length of the operation.
+ * @param dataffset Offset into the memory specified with the data param
+ * @param data Callers buffer to read into or write from. Pass NULL when
+ * using kIODMACommandPerformOperationOptionZero.
+ * @return kIOReturnSuccess on success. See IOReturn.h for error codes.
+ */
+ virtual kern_return_t
+ PerformOperation(
+ uint64_t options,
+ uint64_t dmaOffset,
+ uint64_t length,
+ uint64_t dataOffset,
+ IOMemoryDescriptor * data);
+};
+
+#endif /* ! _IOKIT_UIODMACOMMMAND_H */
diff --git a/iokit/DriverKit/IOInterruptDispatchSource.iig b/iokit/DriverKit/IOInterruptDispatchSource.iig
index ecd4b5c80..855d6beb1 100644
--- a/iokit/DriverKit/IOInterruptDispatchSource.iig
+++ b/iokit/DriverKit/IOInterruptDispatchSource.iig
@@ -37,6 +37,11 @@ struct IOInterruptDispatchSourcePayload {
uint64_t count;
};
+enum {
+ kIOInterruptDispatchSourceTypeEdge = 0x00000000,
+ kIOInterruptDispatchSourceTypeLevel = 0x00000001
+};
+
/*!
* @class IOInterruptDispatchSource
*
@@ -67,6 +72,22 @@ public:
IODispatchQueue * queue,
IOInterruptDispatchSource ** source) LOCAL;
+ /*!
+ * @brief Returns the type of interrupt used for a device supplying hardware interrupts, by index from an IOService provider.
+ * @param provider The IOService object representing the HW device producing the interrupt.
+ * @param index Index for the interrupt.
+ * @param interruptType The interrupt type for the interrupt source will be stored here.
+ * kIOInterruptTypeEdge will be returned for edge-trigggered sources.
+ * kIOInterruptTypeLevel will be returned for level-trigggered sources.
+ * Other flags may be returned depending on the provider, for example PCI flags for messaged interrupts.
+ * @return kIOReturnSuccess on success. See IOReturn.h for error codes.
+ */
+
+ static kern_return_t
+ GetInterruptType(IOService * provider,
+ uint32_t index,
+ uint64_t * interruptType);
+
virtual bool
init() override;
diff --git a/iokit/IOKit/IODMACommand.h b/iokit/IOKit/IODMACommand.h
index adaaf4cd0..2188f9577 100644
--- a/iokit/IOKit/IODMACommand.h
+++ b/iokit/IOKit/IODMACommand.h
@@ -30,6 +30,7 @@
#include
#include
+#include
class IOMapper;
class IOBufferMemoryDescriptor;
@@ -61,7 +62,7 @@ enum{
class IODMACommand : public IOCommand
{
- OSDeclareDefaultStructors(IODMACommand);
+ OSDeclareDefaultStructorsWithDispatch(IODMACommand);
friend class IODMAEventSource;
diff --git a/iokit/IOKit/IOKitKeys.h b/iokit/IOKit/IOKitKeys.h
index 34da31735..2e1a2fe04 100644
--- a/iokit/IOKit/IOKitKeys.h
+++ b/iokit/IOKit/IOKitKeys.h
@@ -110,6 +110,9 @@
// Property is an array of strings containing CFBundleIdentifiers of service being opened
#define kIODriverKitUserClientEntitlementsKey "com.apple.developer.driverkit.userclient-access"
+// Entitlement of a dext that allows any task to open one of its IOUserClients
+#define kIODriverKitUserClientEntitlementAllowAnyKey "com.apple.developer.driverkit.allow-any-userclient-access"
+
// Other DriverKit entitlements
#define kIODriverKitUSBTransportEntitlementKey "com.apple.developer.driverkit.transport.usb"
#define kIODriverKitHIDTransportEntitlementKey "com.apple.developer.driverkit.transport.hid"
diff --git a/iokit/IOKit/IOService.h b/iokit/IOKit/IOService.h
index 28c99e74c..b99bf60b0 100644
--- a/iokit/IOKit/IOService.h
+++ b/iokit/IOKit/IOService.h
@@ -174,6 +174,7 @@ extern const OSSymbol * gIOBSDUnitKey;
extern const OSSymbol * gIODriverKitEntitlementKey;
extern const OSSymbol * gIOServiceDEXTEntitlementsKey;
extern const OSSymbol * gIODriverKitUserClientEntitlementsKey;
+extern const OSSymbol * gIODriverKitUserClientEntitlementAllowAnyKey;
extern const OSSymbol * gIOMatchDeferKey;
extern SInt32 IOServiceOrdering( const OSMetaClassBase * inObj1, const OSMetaClassBase * inObj2, void * ref );
diff --git a/iokit/Kernel/IOService.cpp b/iokit/Kernel/IOService.cpp
index a8387bf2a..3189e590c 100644
--- a/iokit/Kernel/IOService.cpp
+++ b/iokit/Kernel/IOService.cpp
@@ -185,6 +185,7 @@ const OSSymbol * gIOWillTerminateNotification;
const OSSymbol * gIOServiceDEXTEntitlementsKey;
const OSSymbol * gIODriverKitEntitlementKey;
const OSSymbol * gIODriverKitUserClientEntitlementsKey;
+const OSSymbol * gIODriverKitUserClientEntitlementAllowAnyKey;
const OSSymbol * gIOMatchDeferKey;
const OSSymbol * gIOGeneralInterest;
@@ -485,6 +486,7 @@ IOService::initialize( void )
gIOServiceDEXTEntitlementsKey = OSSymbol::withCStringNoCopy( kIOServiceDEXTEntitlementsKey );
gIODriverKitEntitlementKey = OSSymbol::withCStringNoCopy( kIODriverKitEntitlementKey );
gIODriverKitUserClientEntitlementsKey = OSSymbol::withCStringNoCopy( kIODriverKitUserClientEntitlementsKey );
+ gIODriverKitUserClientEntitlementAllowAnyKey = OSSymbol::withCStringNoCopy( kIODriverKitUserClientEntitlementAllowAnyKey );
gIOMatchDeferKey = OSSymbol::withCStringNoCopy( kIOMatchDeferKey );
gIOPlatformFunctionHandlerSet = OSSymbol::withCStringNoCopy(kIOPlatformFunctionHandlerSet);
diff --git a/iokit/Kernel/IOUserServer.cpp b/iokit/Kernel/IOUserServer.cpp
index 52508a761..df4172f3c 100644
--- a/iokit/Kernel/IOUserServer.cpp
+++ b/iokit/Kernel/IOUserServer.cpp
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -502,6 +503,233 @@ IMPL(IOBufferMemoryDescriptor, SetLength)
return kIOReturnSuccess;
}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+kern_return_t
+IMPL(IODMACommand, Create)
+{
+ IOReturn ret;
+ IODMACommand * dma;
+ IODMACommand::SegmentOptions segmentOptions;
+ IOMapper * mapper;
+
+ if (options & ~((uint64_t) kIODMACommandCreateNoOptions)) {
+ // no other options currently defined
+ return kIOReturnBadArgument;
+ }
+
+ if (os_convert_overflow(specification->maxAddressBits, &segmentOptions.fNumAddressBits)) {
+ return kIOReturnBadArgument;
+ }
+ segmentOptions.fMaxSegmentSize = 0;
+ segmentOptions.fMaxTransferSize = 0;
+ segmentOptions.fAlignment = 1;
+ segmentOptions.fAlignmentLength = 1;
+ segmentOptions.fAlignmentInternalSegments = 1;
+ segmentOptions.fStructSize = sizeof(segmentOptions);
+
+ mapper = IOMapper::copyMapperForDevice(device);
+
+ dma = IODMACommand::withSpecification(
+ kIODMACommandOutputHost64,
+ &segmentOptions,
+ kIODMAMapOptionMapped,
+ mapper,
+ NULL);
+
+ OSSafeReleaseNULL(mapper);
+ *command = dma;
+
+ if (!dma) {
+ return kIOReturnNoMemory;
+ }
+ ret = kIOReturnSuccess;
+
+ return ret;
+}
+
+kern_return_t
+IMPL(IODMACommand, PrepareForDMA)
+{
+ IOReturn ret;
+ uint64_t lflags, mdFlags;
+ UInt32 numSegments;
+ UInt64 genOffset;
+
+ if (options & ~((uint64_t) kIODMACommandPrepareForDMANoOptions)) {
+ // no other options currently defined
+ return kIOReturnBadArgument;
+ }
+
+ ret = setMemoryDescriptor(memory, false);
+ if (kIOReturnSuccess != ret) {
+ return ret;
+ }
+
+ ret = prepare(offset, length);
+ if (kIOReturnSuccess != ret) {
+ clearMemoryDescriptor(false);
+ return ret;
+ }
+
+ static_assert(sizeof(IODMACommand::Segment64) == sizeof(IOAddressSegment));
+
+ numSegments = *segmentsCount;
+ genOffset = offset;
+ ret = genIOVMSegments(&genOffset, segments, &numSegments);
+
+ if (kIOReturnSuccess == ret) {
+ IOMemoryDescriptor * mem;
+ mem = __IODEQUALIFY(IOMemoryDescriptor *, fMemory);
+ mdFlags = mem->getFlags();
+ lflags = 0;
+ if (kIODirectionOut & mdFlags) {
+ lflags |= kIOMemoryDirectionOut;
+ }
+ if (kIODirectionIn & mdFlags) {
+ lflags |= kIOMemoryDirectionIn;
+ }
+ *flags = lflags;
+ *segmentsCount = numSegments;
+ }
+
+ return ret;
+}
+
+kern_return_t
+IMPL(IODMACommand, CompleteDMA)
+{
+ IOReturn ret;
+
+ if (options & ~((uint64_t) kIODMACommandCompleteDMANoOptions)) {
+ // no other options currently defined
+ return kIOReturnBadArgument;
+ }
+
+ ret = clearMemoryDescriptor(true);
+
+ return ret;
+}
+
+kern_return_t
+IMPL(IODMACommand, GetPreparation)
+{
+ IOReturn ret;
+ IOMemoryDescriptor * md;
+
+ if (!fActive) {
+ return kIOReturnNotReady;
+ }
+
+ ret = getPreparedOffsetAndLength(offset, length);
+ if (kIOReturnSuccess != ret) {
+ return ret;
+ }
+
+ if (memory) {
+ md = __DECONST(IOMemoryDescriptor *, fMemory);
+ *memory = md;
+ if (!md) {
+ ret = kIOReturnNotReady;
+ } else {
+ md->retain();
+ }
+ }
+ return ret;
+}
+
+kern_return_t
+IMPL(IODMACommand, PerformOperation)
+{
+ IOReturn ret;
+ void * buffer;
+ UInt64 copiedDMA;
+ IOByteCount mdOffset, mdLength, copied;
+
+ if (options & ~((uint64_t)
+ (kIODMACommandPerformOperationOptionRead
+ | kIODMACommandPerformOperationOptionWrite
+ | kIODMACommandPerformOperationOptionZero))) {
+ // no other options currently defined
+ return kIOReturnBadArgument;
+ }
+
+ if (!fActive) {
+ return kIOReturnNotReady;
+ }
+ if (os_convert_overflow(dataOffset, &mdOffset)) {
+ return kIOReturnBadArgument;
+ }
+ if (os_convert_overflow(length, &mdLength)) {
+ return kIOReturnBadArgument;
+ }
+ if (length > fMemory->getLength()) {
+ return kIOReturnBadArgument;
+ }
+ buffer = IONew(uint8_t, length);
+ if (NULL == buffer) {
+ return kIOReturnNoMemory;
+ }
+
+ switch (options) {
+ case kIODMACommandPerformOperationOptionZero:
+ bzero(buffer, length);
+ copiedDMA = writeBytes(dmaOffset, buffer, length);
+ if (copiedDMA != length) {
+ ret = kIOReturnUnderrun;
+ break;
+ }
+ ret = kIOReturnSuccess;
+ break;
+
+ case kIODMACommandPerformOperationOptionRead:
+ case kIODMACommandPerformOperationOptionWrite:
+
+ if (!data) {
+ ret = kIOReturnBadArgument;
+ break;
+ }
+ if (length > data->getLength()) {
+ ret = kIOReturnBadArgument;
+ break;
+ }
+ if (kIODMACommandPerformOperationOptionWrite == options) {
+ copied = data->readBytes(mdOffset, buffer, mdLength);
+ if (copied != mdLength) {
+ ret = kIOReturnUnderrun;
+ break;
+ }
+ copiedDMA = writeBytes(dmaOffset, buffer, length);
+ if (copiedDMA != length) {
+ ret = kIOReturnUnderrun;
+ break;
+ }
+ } else { /* kIODMACommandPerformOperationOptionRead */
+ copiedDMA = readBytes(dmaOffset, buffer, length);
+ if (copiedDMA != length) {
+ ret = kIOReturnUnderrun;
+ break;
+ }
+ copied = data->writeBytes(mdOffset, buffer, mdLength);
+ if (copied != mdLength) {
+ ret = kIOReturnUnderrun;
+ break;
+ }
+ }
+ ret = kIOReturnSuccess;
+ break;
+ default:
+ ret = kIOReturnBadArgument;
+ break;
+ }
+
+ IODelete(buffer, uint8_t, length);
+
+ return ret;
+}
+
+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
kern_return_t
@@ -667,6 +895,21 @@ IMPL(IOInterruptDispatchSource, Create)
return ret;
}
+kern_return_t
+IMPL(IOInterruptDispatchSource, GetInterruptType)
+{
+ IOReturn ret;
+ int type;
+
+ *interruptType = 0;
+ ret = provider->getInterruptType(index, &type);
+ if (kIOReturnSuccess == ret) {
+ *interruptType = type;
+ }
+
+ return ret;
+}
+
bool
IOInterruptDispatchSource::init()
{
@@ -2199,9 +2442,11 @@ IOUserServerUEXTTrap(OSObject * object, void * p1, void * p2, void * p3, void *
} else {
objectArg1 = NULL;
if (refs > 1) {
- objectArg1 = iokit_lookup_uext_ref_current_task(objectName1);
- if (!objectArg1) {
- return kIOReturnIPCError;
+ if (objectName1) {
+ objectArg1 = iokit_lookup_uext_ref_current_task(objectName1);
+ if (!objectArg1) {
+ return kIOReturnIPCError;
+ }
}
message->objects[1] = (OSObjectRef) objectArg1;
}
@@ -3123,18 +3368,24 @@ IOUserServer::serviceNewUserClient(IOService * service, task_t owningTask, void
userUC->setTask(owningTask);
if (!(kIODKDisableEntitlementChecking & gIODKDebug)) {
- entitlements = IOUserClient::copyClientEntitlements(owningTask);
- bundleID = service->copyProperty(gIOModuleIdentifierKey);
- ok = (entitlements
- && bundleID
- && (prop = entitlements->getObject(gIODriverKitUserClientEntitlementsKey)));
- if (ok) {
- bool found __block = false;
- ok = prop->iterateObjects(^bool (OSObject * object) {
- found = object->isEqualTo(bundleID);
- return found;
- });
- ok = found;
+ bundleID = NULL;
+ entitlements = NULL;
+ if (fEntitlements && fEntitlements->getObject(gIODriverKitUserClientEntitlementAllowAnyKey)) {
+ ok = true;
+ } else {
+ entitlements = IOUserClient::copyClientEntitlements(owningTask);
+ bundleID = service->copyProperty(gIOModuleIdentifierKey);
+ ok = (entitlements
+ && bundleID
+ && (prop = entitlements->getObject(gIODriverKitUserClientEntitlementsKey)));
+ if (ok) {
+ bool found __block = false;
+ ok = prop->iterateObjects(^bool (OSObject * object) {
+ found = object->isEqualTo(bundleID);
+ return found;
+ });
+ ok = found;
+ }
}
if (ok) {
prop = userUC->copyProperty(gIOServiceDEXTEntitlementsKey);
diff --git a/iokit/conf/files b/iokit/conf/files
index 77b47578c..48db7bedf 100644
--- a/iokit/conf/files
+++ b/iokit/conf/files
@@ -23,6 +23,7 @@ OPTIONS/mach_assert optional mach_assert
./DriverKit/IODataQueueDispatchSource.iig.cpp optional iokitcpp
./DriverKit/IOServiceNotificationDispatchSource.iig.cpp optional iokitcpp
./DriverKit/IOUserServer.iig.cpp optional iokitcpp
+./DriverKit/IODMACommand.iig.cpp optional iokitcpp
# libIOKit
diff --git a/osfmk/arm/pmap.c b/osfmk/arm/pmap.c
index cd07ccaba..2d082d60d 100644
--- a/osfmk/arm/pmap.c
+++ b/osfmk/arm/pmap.c
@@ -2543,7 +2543,7 @@ pmap_pages_reclaim(
&& ((*tte_p & ARM_TTE_TYPE_MASK) == ARM_TTE_TYPE_TABLE)) {
pte_p = (pt_entry_t *) ttetokv(*tte_p);
bpte = &pte_p[pte_index(pmap, pt_attr, va)];
- epte = bpte + PAGE_SIZE / sizeof(pt_entry_t);
+ epte = bpte + pt_attr_leaf_size(pt_attr) / sizeof(pt_entry_t);
/*
* Use PMAP_OPTIONS_REMOVE to clear any
* "compressed" markers and update the
@@ -6164,6 +6164,13 @@ pmap_remove_range_options(
PMAP_ASSERT_LOCKED(pmap);
+ const pt_attr_t * const pt_attr = pmap_get_pt_attr(pmap);
+ uint64_t pmap_page_size = pt_attr_leaf_size(pt_attr);
+
+ if (__improbable((uintptr_t)epte > (((uintptr_t)bpte + pmap_page_size) & ~(pmap_page_size - 1)))) {
+ panic("%s: PTE range [%p, %p) in pmap %p crosses page table boundary", __func__, bpte, epte, pmap);
+ }
+
num_removed = 0;
num_unwired = 0;
num_pte_changed = 0;
@@ -7114,8 +7121,8 @@ pmap_protect_options_internal(
boolean_t should_have_removed = FALSE;
bool need_strong_sync = false;
- if (__improbable(end < start)) {
- panic("%s called with bogus range: %p, %p", __func__, (void*)start, (void*)end);
+ if (__improbable((end < start) || (end > ((start + pt_attr_twig_size(pt_attr)) & ~pt_attr_twig_offmask(pt_attr))))) {
+ panic("%s: invalid address range %p, %p", __func__, (void*)start, (void*)end);
}
#if DEVELOPMENT || DEBUG
diff --git a/osfmk/arm/status.c b/osfmk/arm/status.c
index 2f35514a3..40c1f5e1d 100644
--- a/osfmk/arm/status.c
+++ b/osfmk/arm/status.c
@@ -773,6 +773,10 @@ thread_entrypoint(
{
struct arm_thread_state *state;
+ if (count != ARM_THREAD_STATE_COUNT) {
+ return KERN_INVALID_ARGUMENT;
+ }
+
state = (struct arm_thread_state *) tstate;
/*
diff --git a/osfmk/arm64/cswitch.s b/osfmk/arm64/cswitch.s
index c9b1893a1..d691acc1a 100644
--- a/osfmk/arm64/cswitch.s
+++ b/osfmk/arm64/cswitch.s
@@ -52,6 +52,9 @@
stp x25, x26, [$0, SS64_X25]
stp x27, x28, [$0, SS64_X27]
stp fp, lr, [$0, SS64_FP]
+ str xzr, [$0, SS64_PC]
+ MOV32 w$1, PSR64_KERNEL_POISON
+ str w$1, [$0, SS64_CPSR]
#ifdef HAS_APPLE_PAC
stp x0, x1, [sp, #-16]!
stp x2, x3, [sp, #-16]!
@@ -64,8 +67,8 @@
* Arg3: LR to sign
*/
mov x0, $0
- ldr x1, [x0, SS64_PC]
- ldr w2, [x0, SS64_CPSR]
+ mov x1, #0
+ mov w2, w$1
mov x3, lr
mov x4, x16
mov x5, x17
@@ -76,8 +79,8 @@
ldp x0, x1, [sp], #16
ldp fp, lr, [$0, SS64_FP]
#endif /* defined(HAS_APPLE_PAC) */
- mov $1, sp
- str $1, [$0, SS64_SP]
+ mov x$1, sp
+ str x$1, [$0, SS64_SP]
/* AAPCS-64 Page 14
*
@@ -265,7 +268,7 @@ LEXT(Call_continuation)
LEXT(Switch_context)
cbnz x1, Lswitch_threads // Skip saving old state if blocking on continuation
ldr x3, [x0, TH_KSTACKPTR] // Get the old kernel stack top
- save_general_registers x3, x4
+ save_general_registers x3, 4
Lswitch_threads:
set_thread_registers x2, x3, x4
ldr x3, [x2, TH_KSTACKPTR]
@@ -286,7 +289,7 @@ Lswitch_threads:
LEXT(Shutdown_context)
mrs x10, TPIDR_EL1 // Get thread pointer
ldr x11, [x10, TH_KSTACKPTR] // Get the top of the kernel stack
- save_general_registers x11, x12
+ save_general_registers x11, 12
msr DAIFSet, #(DAIFSC_FIQF | DAIFSC_IRQF) // Disable interrupts
ldr x11, [x10, ACT_CPUDATAP] // Get current cpu
ldr x12, [x11, CPU_ISTACKPTR] // Switch to interrupt stack
@@ -304,7 +307,7 @@ LEXT(Shutdown_context)
LEXT(Idle_context)
mrs x0, TPIDR_EL1 // Get thread pointer
ldr x1, [x0, TH_KSTACKPTR] // Get the top of the kernel stack
- save_general_registers x1, x2
+ save_general_registers x1, 2
ldr x1, [x0, ACT_CPUDATAP] // Get current cpu
ldr x2, [x1, CPU_ISTACKPTR] // Switch to interrupt stack
mov sp, x2
diff --git a/osfmk/arm64/exception_asm.h b/osfmk/arm64/exception_asm.h
index 60aa8b83f..8234158e9 100644
--- a/osfmk/arm64/exception_asm.h
+++ b/osfmk/arm64/exception_asm.h
@@ -117,7 +117,7 @@ str $1, [$0, NS_COUNT]
/*
* SPILL_REGISTERS
*
- * Spills the current set of registers (excluding x0, x1, sp, fp) to the specified
+ * Spills the current set of registers (excluding x0, x1, sp) to the specified
* save area.
* x0 - Address of the save area
*/
@@ -136,7 +136,8 @@ stp x20, x21, [x0, SS64_X20]
stp x22, x23, [x0, SS64_X22]
stp x24, x25, [x0, SS64_X24]
stp x26, x27, [x0, SS64_X26]
-str x28, [x0, SS64_X28]
+stp x28, fp, [x0, SS64_X28]
+str lr, [x0, SS64_LR]
/* Save arm_neon_saved_state64 */
@@ -157,7 +158,7 @@ stp q26, q27, [x0, NS64_Q26]
stp q28, q29, [x0, NS64_Q28]
stp q30, q31, [x0, NS64_Q30]
-mrs lr, ELR_EL1 // Get exception link register
+mrs x22, ELR_EL1 // Get exception link register
mrs x23, SPSR_EL1 // Load CPSR into var reg x23
mrs x24, FPSR
mrs x25, FPCR
@@ -177,9 +178,9 @@ mov x20, lr
* Arg4: The X16 value to sign
* Arg5: The X17 value to sign
*/
-mov x1, lr
+mov x1, x22
mov w2, w23
-ldr x3, [x0, SS64_LR]
+mov x3, x20
mov x4, x16
mov x5, x17
bl _ml_sign_thread_state
@@ -188,7 +189,7 @@ mov lr, x20
mov x1, x21
#endif /* defined(HAS_APPLE_PAC) */
-str lr, [x0, SS64_PC] // Save ELR to PCB
+str x22, [x0, SS64_PC] // Save ELR to PCB
str w23, [x0, SS64_CPSR] // Save CPSR to PCB
str w24, [x0, NS64_FPSR]
str w25, [x0, NS64_FPCR]
diff --git a/osfmk/arm64/locore.s b/osfmk/arm64/locore.s
index 1efc217f9..75b314e83 100644
--- a/osfmk/arm64/locore.s
+++ b/osfmk/arm64/locore.s
@@ -183,7 +183,6 @@
/* Save the context that was interrupted. */
ldp x2, x3, [x3, SS64_X2]
- stp fp, lr, [x0, SS64_FP]
SPILL_REGISTERS KERNEL_MODE
/*
@@ -296,6 +295,59 @@
#endif /* __ARM_KERNEL_PROTECT__ */
.endmacro
+/*
+ * CHECK_KERNEL_STACK
+ *
+ * Verifies that the kernel stack is aligned and mapped within an expected
+ * stack address range. Note: happens before saving registers (in case we can't
+ * save to kernel stack).
+ *
+ * Expects:
+ * {x0, x1, sp} - saved
+ * x0 - SP_EL0
+ * x1 - Exception syndrome
+ * sp - Saved state
+ *
+ * Seems like we need an unused argument to the macro for the \@ syntax to work
+ *
+ */
+.macro CHECK_KERNEL_STACK unused
+ stp x2, x3, [sp, SS64_X2] // Save {x2-x3}
+ and x1, x1, #ESR_EC_MASK // Mask the exception class
+ mov x2, #(ESR_EC_SP_ALIGN << ESR_EC_SHIFT)
+ cmp x1, x2 // If we have a stack alignment exception
+ b.eq Lcorrupt_stack_\@ // ...the stack is definitely corrupted
+ mov x2, #(ESR_EC_DABORT_EL1 << ESR_EC_SHIFT)
+ cmp x1, x2 // If we have a data abort, we need to
+ b.ne Lvalid_stack_\@ // ...validate the stack pointer
+ mrs x1, TPIDR_EL1 // Get thread pointer
+Ltest_kstack_\@:
+ ldr x2, [x1, TH_KSTACKPTR] // Get top of kernel stack
+ sub x3, x2, KERNEL_STACK_SIZE // Find bottom of kernel stack
+ cmp x0, x2 // if (SP_EL0 >= kstack top)
+ b.ge Ltest_istack_\@ // jump to istack test
+ cmp x0, x3 // if (SP_EL0 > kstack bottom)
+ b.gt Lvalid_stack_\@ // stack pointer valid
+Ltest_istack_\@:
+ ldr x1, [x1, ACT_CPUDATAP] // Load the cpu data ptr
+ ldr x2, [x1, CPU_INTSTACK_TOP] // Get top of istack
+ sub x3, x2, INTSTACK_SIZE_NUM // Find bottom of istack
+ cmp x0, x2 // if (SP_EL0 >= istack top)
+ b.ge Lcorrupt_stack_\@ // corrupt stack pointer
+ cmp x0, x3 // if (SP_EL0 > istack bottom)
+ b.gt Lvalid_stack_\@ // stack pointer valid
+Lcorrupt_stack_\@:
+ INIT_SAVED_STATE_FLAVORS sp, w0, w1
+ mov x0, sp // Copy exception frame pointer to x0
+ adrp x1, fleh_invalid_stack@page // Load address for fleh
+ add x1, x1, fleh_invalid_stack@pageoff // fleh_dispatch64 will save register state before we get there
+ ldp x2, x3, [sp, SS64_X2] // Restore {x2-x3}
+ b fleh_dispatch64
+Lvalid_stack_\@:
+ ldp x2, x3, [sp, SS64_X2] // Restore {x2-x3}
+.endmacro
+
+
#if __ARM_KERNEL_PROTECT__
.text
.align 3
@@ -407,7 +459,6 @@ Lel0_serror_vector_64:
stp x0, x1, [sp, SS64_X0] // Save x0, x1 to exception frame
add x0, sp, ARM_CONTEXT_SIZE // Calculate the original stack pointer
str x0, [sp, SS64_SP] // Save stack pointer to exception frame
- stp fp, lr, [sp, SS64_FP] // Save fp and lr to exception frame
INIT_SAVED_STATE_FLAVORS sp, w0, w1
mov x0, sp // Copy saved state pointer to x0
.endmacro
@@ -430,10 +481,8 @@ Lel1_sp0_synchronous_vector_kernel:
*/
tbz x1, #(5 + ESR_EC_SHIFT), Lkernel_stack_valid
mrs x0, SP_EL0 // Get SP_EL0
- stp fp, lr, [sp, SS64_FP] // Save fp, lr to the stack
str x0, [sp, SS64_SP] // Save sp to the stack
- bl check_kernel_stack
- ldp fp, lr, [sp, SS64_FP] // Restore fp, lr
+ CHECK_KERNEL_STACK
Lkernel_stack_valid:
ldp x0, x1, [sp, SS64_X0] // Restore x0, x1
add sp, sp, ARM_CONTEXT_SIZE // Restore SP1
@@ -487,7 +536,6 @@ Lel1_sp0_serror_vector_kernel:
add x0, sp, ARM_CONTEXT_SIZE // Calculate the original stack pointer
str x0, [sp, SS64_SP] // Save stack pointer to exception frame
INIT_SAVED_STATE_FLAVORS sp, w0, w1
- stp fp, lr, [sp, SS64_FP] // Save fp and lr to exception frame
mov x0, sp // Copy saved state pointer to x0
.endmacro
@@ -566,9 +614,6 @@ el1_sp1_serror_vector_long:
ldp x0, x1, [sp], #16 // Restore x0 and x1 from the exception stack
msr SPSel, #0 // Switch to SP0
stp x0, x1, [sp, SS64_X0] // Save x0, x1 to the user PCB
- stp fp, lr, [sp, SS64_FP] // Save fp and lr to the user PCB
- mov fp, #0 // Clear the fp and lr for the
- mov lr, #0 // debugger stack frame
mov x0, sp // Copy the user PCB pointer to x0
.endmacro
@@ -643,56 +688,6 @@ Lvalid_exception_stack:
mov x18, #0
b Lel1_sp1_synchronous_valid_stack
-/*
- * check_kernel_stack
- *
- * Verifies that the kernel stack is aligned and mapped within an expected
- * stack address range. Note: happens before saving registers (in case we can't
- * save to kernel stack).
- *
- * Expects:
- * {x0, x1, sp} - saved
- * x0 - SP_EL0
- * x1 - Exception syndrome
- * sp - Saved state
- */
- .text
- .align 2
-check_kernel_stack:
- stp x2, x3, [sp, SS64_X2] // Save {x2-x3}
- and x1, x1, #ESR_EC_MASK // Mask the exception class
- mov x2, #(ESR_EC_SP_ALIGN << ESR_EC_SHIFT)
- cmp x1, x2 // If we have a stack alignment exception
- b.eq Lcorrupt_stack // ...the stack is definitely corrupted
- mov x2, #(ESR_EC_DABORT_EL1 << ESR_EC_SHIFT)
- cmp x1, x2 // If we have a data abort, we need to
- b.ne Lvalid_stack // ...validate the stack pointer
- mrs x1, TPIDR_EL1 // Get thread pointer
-Ltest_kstack:
- ldr x2, [x1, TH_KSTACKPTR] // Get top of kernel stack
- sub x3, x2, KERNEL_STACK_SIZE // Find bottom of kernel stack
- cmp x0, x2 // if (SP_EL0 >= kstack top)
- b.ge Ltest_istack // jump to istack test
- cmp x0, x3 // if (SP_EL0 > kstack bottom)
- b.gt Lvalid_stack // stack pointer valid
-Ltest_istack:
- ldr x1, [x1, ACT_CPUDATAP] // Load the cpu data ptr
- ldr x2, [x1, CPU_INTSTACK_TOP] // Get top of istack
- sub x3, x2, INTSTACK_SIZE_NUM // Find bottom of istack
- cmp x0, x2 // if (SP_EL0 >= istack top)
- b.ge Lcorrupt_stack // corrupt stack pointer
- cmp x0, x3 // if (SP_EL0 > istack bottom)
- b.gt Lvalid_stack // stack pointer valid
-Lcorrupt_stack:
- INIT_SAVED_STATE_FLAVORS sp, w0, w1
- mov x0, sp // Copy exception frame pointer to x0
- adrp x1, fleh_invalid_stack@page // Load address for fleh
- add x1, x1, fleh_invalid_stack@pageoff // fleh_dispatch64 will save register state before we get there
- ldp x2, x3, [sp, SS64_X2] // Restore {x2-x3}
- b fleh_dispatch64
-Lvalid_stack:
- ldp x2, x3, [sp, SS64_X2] // Restore {x2-x3}
- ret
#if defined(KERNEL_INTEGRITY_KTRR)
.text
@@ -731,7 +726,7 @@ check_ktrr_sctlr_trap:
/* 64-bit first level exception handler dispatcher.
* Completes register context saving and branches to FLEH.
* Expects:
- * {x0, x1, fp, lr, sp} - saved
+ * {x0, x1, sp} - saved
* x0 - arm_context_t
* x1 - address of FLEH
* fp - previous stack frame if EL1
@@ -777,7 +772,8 @@ fleh_dispatch64:
#endif
mov x27, #0
mov x28, #0
- /* fp/lr already cleared by EL0_64_VECTOR */
+ mov fp, #0
+ mov lr, #0
1:
mov x21, x0 // Copy arm_context_t pointer to x21
diff --git a/osfmk/arm64/pcb.c b/osfmk/arm64/pcb.c
index 29f2b7185..9b2b057b1 100644
--- a/osfmk/arm64/pcb.c
+++ b/osfmk/arm64/pcb.c
@@ -340,9 +340,17 @@ machine_stack_attach(thread_t thread,
savestate = saved_state64(&context->ss);
savestate->fp = 0;
savestate->sp = thread->machine.kstackptr;
+
+ /*
+ * The PC and CPSR of the kernel stack saved state are never used by context switch
+ * code, and should never be used on exception return either. We're going to poison
+ * these values to ensure they never get copied to the exception frame and used to
+ * hijack control flow or privilege level on exception return.
+ */
+
+ const uint32_t default_cpsr = PSR64_KERNEL_POISON;
#if defined(HAS_APPLE_PAC)
/* Sign the initial kernel stack saved state */
- const uint32_t default_cpsr = PSR64_KERNEL_DEFAULT & ~PSR64_MODE_EL_MASK;
boolean_t intr = ml_set_interrupts_enabled(FALSE);
asm volatile (
"mov x0, %[ss]" "\n"
@@ -352,8 +360,6 @@ machine_stack_attach(thread_t thread,
"mov x2, %[default_cpsr_lo]" "\n"
"movk x2, %[default_cpsr_hi], lsl #16" "\n"
- "mrs x3, CurrentEL" "\n"
- "orr w2, w2, w3" "\n"
"str w2, [x0, %[SS64_CPSR]]" "\n"
"adrp x3, _thread_continue@page" "\n"
@@ -380,7 +386,8 @@ machine_stack_attach(thread_t thread,
ml_set_interrupts_enabled(intr);
#else
savestate->lr = (uintptr_t)thread_continue;
- savestate->cpsr = (PSR64_KERNEL_DEFAULT & ~PSR64_MODE_EL_MASK) | current_el;
+ savestate->cpsr = default_cpsr;
+ savestate->pc = 0;
#endif /* defined(HAS_APPLE_PAC) */
machine_stack_attach_kprintf("thread = %p pc = %llx, sp = %llx\n", thread, savestate->lr, savestate->sp);
}
diff --git a/osfmk/arm64/proc_reg.h b/osfmk/arm64/proc_reg.h
index 69533e29e..7226338ad 100644
--- a/osfmk/arm64/proc_reg.h
+++ b/osfmk/arm64/proc_reg.h
@@ -203,6 +203,7 @@
#else
#define PSR64_KERNEL_DEFAULT PSR64_KERNEL_STANDARD
#endif
+#define PSR64_KERNEL_POISON (PSR64_IL | PSR64_MODE_EL1)
#define PSR64_IS_KERNEL(x) ((x & PSR64_MODE_EL_MASK) > PSR64_MODE_EL0)
#define PSR64_IS_USER(x) ((x & PSR64_MODE_EL_MASK) == PSR64_MODE_EL0)
@@ -1496,6 +1497,19 @@ typedef enum {
#define ISS_FP_IOF_SHIFT 0
#define ISS_FP_IOF (0x1 << ISS_FP_IOF_SHIFT)
+/*
+ * Breakpoint Exception ISS (EL1)
+ * 24 16 0
+ * +---------+---------+
+ * |000000000| Comment |
+ * +---------+---------+
+ *
+ * where:
+ * Comment: Instruction Comment Field Value
+ */
+#define ISS_BRK_COMMENT_MASK 0xFFFF
+#define ISS_BRK_COMMENT(x) (x & ISS_BRK_COMMENT_MASK)
+
/*
* Physical Address Register (EL1)
diff --git a/osfmk/arm64/sleh.c b/osfmk/arm64/sleh.c
index b6a1f10ae..87891018b 100644
--- a/osfmk/arm64/sleh.c
+++ b/osfmk/arm64/sleh.c
@@ -114,7 +114,7 @@ static void handle_msr_trap(arm_saved_state_t *state, uint32_t iss);
extern kern_return_t arm_fast_fault(pmap_t, vm_map_address_t, vm_prot_t, bool, bool);
static void handle_uncategorized(arm_saved_state_t *);
-static void handle_breakpoint(arm_saved_state_t *) __dead2;
+static void handle_breakpoint(arm_saved_state_t *, uint32_t) __dead2;
typedef void (*abort_inspector_t)(uint32_t, fault_status_t *, vm_prot_t *);
static void inspect_instruction_abort(uint32_t, fault_status_t *, vm_prot_t *);
@@ -547,20 +547,20 @@ sleh_synchronous(arm_context_t *context, uint32_t esr, vm_offset_t far)
__builtin_unreachable();
case ESR_EC_BKPT_AARCH32:
- handle_breakpoint(state);
+ handle_breakpoint(state, esr);
__builtin_unreachable();
case ESR_EC_BRK_AARCH64:
if (PSR64_IS_KERNEL(get_saved_state_cpsr(state))) {
panic_with_thread_kernel_state("Break instruction exception from kernel. Panic (by design)", state);
} else {
- handle_breakpoint(state);
+ handle_breakpoint(state, esr);
}
__builtin_unreachable();
case ESR_EC_BKPT_REG_MATCH_EL0:
if (FSC_DEBUG_FAULT == ISS_SSDE_FSC(esr)) {
- handle_breakpoint(state);
+ handle_breakpoint(state, esr);
}
panic("Unsupported Class %u event code. state=%p class=%u esr=%u far=%p",
class, state, class, esr, (void *)far);
@@ -750,13 +750,31 @@ handle_uncategorized(arm_saved_state_t *state)
__builtin_unreachable();
}
+#if __has_feature(ptrauth_calls)
+static const uint16_t ptrauth_brk_comment_base = 0xc470;
+
+static inline bool
+brk_comment_is_ptrauth(uint16_t comment)
+{
+ return comment >= ptrauth_brk_comment_base &&
+ comment <= ptrauth_brk_comment_base + ptrauth_key_asdb;
+}
+#endif /* __has_feature(ptrauth_calls) */
+
static void
-handle_breakpoint(arm_saved_state_t *state)
+handle_breakpoint(arm_saved_state_t *state, uint32_t esr __unused)
{
exception_type_t exception = EXC_BREAKPOINT;
mach_exception_data_type_t codes[2] = {EXC_ARM_BREAKPOINT};
mach_msg_type_number_t numcodes = 2;
+#if __has_feature(ptrauth_calls)
+ if (ESR_EC(esr) == ESR_EC_BRK_AARCH64 &&
+ brk_comment_is_ptrauth(ISS_BRK_COMMENT(esr))) {
+ exception |= EXC_PTRAUTH_BIT;
+ }
+#endif /* __has_feature(ptrauth_calls) */
+
codes[1] = get_saved_state_pc(state);
exception_triage(exception, codes, numcodes);
__builtin_unreachable();
@@ -807,6 +825,36 @@ inspect_data_abort(uint32_t iss, fault_status_t *fault_code, vm_prot_t *fault_ty
}
}
+#if __has_feature(ptrauth_calls)
+static inline bool
+fault_addr_bit(vm_offset_t fault_addr, unsigned int bit)
+{
+ return (bool)((fault_addr >> bit) & 1);
+}
+
+/**
+ * Determines whether a fault address taken at EL0 contains a PAC error code
+ * corresponding to the specified kind of ptrauth key.
+ */
+static bool
+user_fault_addr_matches_pac_error_code(vm_offset_t fault_addr, bool data_key)
+{
+ bool instruction_tbi = !(get_tcr() & TCR_TBID0_TBI_DATA_ONLY);
+ bool tbi = data_key || __improbable(instruction_tbi);
+ unsigned int poison_shift;
+ if (tbi) {
+ poison_shift = 53;
+ } else {
+ poison_shift = 61;
+ }
+
+ /* PAC error codes are always in the form key_number:NOT(key_number) */
+ bool poison_bit_1 = fault_addr_bit(fault_addr, poison_shift);
+ bool poison_bit_2 = fault_addr_bit(fault_addr, poison_shift + 1);
+ return poison_bit_1 != poison_bit_2;
+}
+#endif /* __has_feature(ptrauth_calls) */
+
static void
handle_pc_align(arm_saved_state_t *ss)
{
@@ -819,6 +867,12 @@ handle_pc_align(arm_saved_state_t *ss)
}
exc = EXC_BAD_ACCESS;
+#if __has_feature(ptrauth_calls)
+ if (user_fault_addr_matches_pac_error_code(get_saved_state_pc(ss), false)) {
+ exc |= EXC_PTRAUTH_BIT;
+ }
+#endif /* __has_feature(ptrauth_calls) */
+
codes[0] = EXC_ARM_DA_ALIGN;
codes[1] = get_saved_state_pc(ss);
@@ -838,6 +892,12 @@ handle_sp_align(arm_saved_state_t *ss)
}
exc = EXC_BAD_ACCESS;
+#if __has_feature(ptrauth_calls)
+ if (user_fault_addr_matches_pac_error_code(get_saved_state_sp(ss), true)) {
+ exc |= EXC_PTRAUTH_BIT;
+ }
+#endif /* __has_feature(ptrauth_calls) */
+
codes[0] = EXC_ARM_SP_ALIGN;
codes[1] = get_saved_state_sp(ss);
@@ -1132,6 +1192,12 @@ handle_user_abort(arm_saved_state_t *state, uint32_t esr, vm_offset_t fault_addr
}
codes[1] = fault_addr;
+#if __has_feature(ptrauth_calls)
+ bool is_data_abort = (ESR_EC(esr) == ESR_EC_DABORT_EL0);
+ if (user_fault_addr_matches_pac_error_code(fault_addr, is_data_abort)) {
+ exc |= EXC_PTRAUTH_BIT;
+ }
+#endif /* __has_feature(ptrauth_calls) */
exception_triage(exc, codes, numcodes);
__builtin_unreachable();
}
diff --git a/osfmk/arm64/status.c b/osfmk/arm64/status.c
index a9f1eec26..0d8b7c7c9 100644
--- a/osfmk/arm64/status.c
+++ b/osfmk/arm64/status.c
@@ -1582,7 +1582,7 @@ kern_return_t
thread_entrypoint(__unused thread_t thread,
int flavor,
thread_state_t tstate,
- unsigned int count __unused,
+ unsigned int count,
mach_vm_offset_t * entry_point
)
{
@@ -1591,6 +1591,10 @@ thread_entrypoint(__unused thread_t thread,
{
struct arm_thread_state *state;
+ if (count != ARM_THREAD_STATE_COUNT) {
+ return KERN_INVALID_ARGUMENT;
+ }
+
state = (struct arm_thread_state *) tstate;
/*
@@ -1608,6 +1612,10 @@ thread_entrypoint(__unused thread_t thread,
{
struct arm_thread_state64 *state;
+ if (count != ARM_THREAD_STATE64_COUNT) {
+ return KERN_INVALID_ARGUMENT;
+ }
+
state = (struct arm_thread_state64*) tstate;
/*
diff --git a/osfmk/i386/acpi.c b/osfmk/i386/acpi.c
index ee93c2eb8..ecd26bfae 100644
--- a/osfmk/i386/acpi.c
+++ b/osfmk/i386/acpi.c
@@ -286,8 +286,8 @@ acpi_sleep_kernel(acpi_sleep_callback func, void *refcon)
mtrr_update_cpu();
#endif
- /* update CPU microcode */
- ucode_update_wake();
+ /* update CPU microcode and apply CPU workarounds */
+ ucode_update_wake_and_apply_cpu_was();
#if CONFIG_MTRR
/* set up PAT following boot processor power up */
diff --git a/osfmk/i386/bsd_i386.c b/osfmk/i386/bsd_i386.c
index 039a31bb6..ee93e5b10 100644
--- a/osfmk/i386/bsd_i386.c
+++ b/osfmk/i386/bsd_i386.c
@@ -92,7 +92,7 @@ thread_userstack(
__unused thread_t thread,
int flavor,
thread_state_t tstate,
- __unused unsigned int count,
+ unsigned int count,
mach_vm_offset_t *user_stack,
int *customstack,
__unused boolean_t is64bit
@@ -107,6 +107,10 @@ thread_userstack(
{
x86_thread_state32_t *state25;
+ if (__improbable(count != x86_THREAD_STATE32_COUNT)) {
+ return KERN_INVALID_ARGUMENT;
+ }
+
state25 = (x86_thread_state32_t *) tstate;
if (state25->esp) {
@@ -124,11 +128,37 @@ thread_userstack(
}
case x86_THREAD_FULL_STATE64:
- /* FALL THROUGH */
+ {
+ x86_thread_full_state64_t *state25;
+
+ if (__improbable(count != x86_THREAD_FULL_STATE64_COUNT)) {
+ return KERN_INVALID_ARGUMENT;
+ }
+
+ state25 = (x86_thread_full_state64_t *) tstate;
+
+ if (state25->ss64.rsp) {
+ *user_stack = state25->ss64.rsp;
+ if (customstack) {
+ *customstack = 1;
+ }
+ } else {
+ *user_stack = VM_USRSTACK64;
+ if (customstack) {
+ *customstack = 0;
+ }
+ }
+ break;
+ }
+
case x86_THREAD_STATE64:
{
x86_thread_state64_t *state25;
+ if (__improbable(count != x86_THREAD_STATE64_COUNT)) {
+ return KERN_INVALID_ARGUMENT;
+ }
+
state25 = (x86_thread_state64_t *) tstate;
if (state25->rsp) {
@@ -176,7 +206,7 @@ thread_entrypoint(
__unused thread_t thread,
int flavor,
thread_state_t tstate,
- __unused unsigned int count,
+ unsigned int count,
mach_vm_offset_t *entry_point
)
{
@@ -192,6 +222,10 @@ thread_entrypoint(
{
x86_thread_state32_t *state25;
+ if (count != x86_THREAD_STATE32_COUNT) {
+ return KERN_INVALID_ARGUMENT;
+ }
+
state25 = (i386_thread_state_t *) tstate;
*entry_point = state25->eip ? state25->eip : VM_MIN_ADDRESS;
break;
@@ -201,6 +235,10 @@ thread_entrypoint(
{
x86_thread_state64_t *state25;
+ if (count != x86_THREAD_STATE64_COUNT) {
+ return KERN_INVALID_ARGUMENT;
+ }
+
state25 = (x86_thread_state64_t *) tstate;
*entry_point = state25->rip ? state25->rip : VM_MIN_ADDRESS64;
break;
diff --git a/osfmk/i386/cpuid.c b/osfmk/i386/cpuid.c
index ff6c8c1fc..2187c5938 100644
--- a/osfmk/i386/cpuid.c
+++ b/osfmk/i386/cpuid.c
@@ -212,6 +212,7 @@ static cpuid_cache_descriptor_t intel_cpuid_leaf2_descriptor_table[] = {
#define INTEL_LEAF2_DESC_NUM (sizeof(intel_cpuid_leaf2_descriptor_table) / \
sizeof(cpuid_cache_descriptor_t))
+
static void do_cwas(i386_cpu_info_t *cpuinfo, boolean_t on_slave);
static void cpuid_do_precpuid_was(void);
@@ -251,6 +252,7 @@ static void
do_cwas(i386_cpu_info_t *cpuinfo, boolean_t on_slave)
{
extern int force_thread_policy_tecs;
+ cwa_classifier_e wa_reqd;
/*
* Workaround for reclaiming perf counter 3 due to TSX memory ordering erratum.
@@ -263,6 +265,7 @@ do_cwas(i386_cpu_info_t *cpuinfo, boolean_t on_slave)
rdmsr64(MSR_IA32_TSX_FORCE_ABORT) | MSR_IA32_TSXFA_RTM_FORCE_ABORT);
}
+
if (on_slave) {
return;
}
@@ -1432,6 +1435,7 @@ cpuid_wa_required(cpu_wa_e wa)
}
break;
+
default:
break;
}
diff --git a/osfmk/i386/cpuid.h b/osfmk/i386/cpuid.h
index 146e77b15..b63bd71bb 100644
--- a/osfmk/i386/cpuid.h
+++ b/osfmk/i386/cpuid.h
@@ -183,6 +183,7 @@
#define CPUID_LEAF7_EXTFEATURE_AVX5124VNNIW _Bit(2) /* AVX512_4VNNIW */
#define CPUID_LEAF7_EXTFEATURE_AVX5124FMAPS _Bit(3) /* AVX512_4FMAPS */
#define CPUID_LEAF7_EXTFEATURE_FSREPMOV _Bit(4) /* Fast Short REP MOV */
+#define CPUID_LEAF7_EXTFEATURE_SRBDS_CTRL _Bit(9) /* SRBDS MSR Presence and Mitigation Control */
#define CPUID_LEAF7_EXTFEATURE_MDCLEAR _Bit(10) /* Overloaded VERW / L1D_FLUSH */
#define CPUID_LEAF7_EXTFEATURE_TSXFA _Bit(13) /* TSX RTM_FORCE_ABORT MSR */
#define CPUID_LEAF7_EXTFEATURE_IBRS _Bit(26) /* IBRS / IBPB */
diff --git a/osfmk/i386/fpu.c b/osfmk/i386/fpu.c
index 1d7475429..2e90ed752 100644
--- a/osfmk/i386/fpu.c
+++ b/osfmk/i386/fpu.c
@@ -80,6 +80,9 @@ xstate_t fpu_capability = UNDEFINED; /* extended state capability */
xstate_t fpu_default = UNDEFINED; /* default extended state */
#define ALIGNED(addr, size) (((uintptr_t)(addr)&((size)-1))==0)
+#define VERIFY_SAVEAREA_ALIGNED(p, a) \
+ assertf(!(((uintptr_t)(p)) & ((a) - 1)), \
+ "FP save area component @ 0x%lx not 8-byte aligned", ((uintptr_t)(p)))
/* Forward */
@@ -535,6 +538,19 @@ clear_fpu(void)
set_ts();
}
+static boolean_t
+fpu_allzeroes(uint64_t * __attribute((aligned(8)))ptr, uint32_t size)
+{
+ VERIFY_SAVEAREA_ALIGNED(ptr, sizeof(uint64_t));
+ assertf((size & (sizeof(uint64_t) - 1)) == 0, "FP save area component not a multiple of 8 bytes");
+
+ for (uint32_t count = 0; count < (size / sizeof(uint64_t)); count++) {
+ if (ptr[count] != 0) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
static void
fpu_load_registers(void *fstate)
@@ -730,13 +746,19 @@ fpu_free(thread_t thread, void *fps)
}
/*
- * Set the floating-point state for a thread based
- * on the FXSave formatted data. This is basically
- * the same as fpu_set_state except it uses the
- * expanded data structure.
- * If the thread is not the current thread, it is
- * not running (held). Locking needed against
- * concurrent fpu_set_state or fpu_get_state.
+ * Set the floating-point state for a thread based on the FXSave formatted data.
+ * This is basically the same as fpu_set_state except it uses the expanded data
+ * structure.
+ * If the thread is not the current thread, it is not running (held). Locking
+ * needed against concurrent fpu_set_state or fpu_get_state.
+ *
+ * While translating between XNU FP state structures and the CPU-native XSAVE area,
+ * if we detect state components that are all zeroes, we clear the corresponding
+ * xstate_bv bit in the XSAVE area, because that allows the corresponding state to
+ * be initialized to a "clean" state. That's most important when clearing the YMM
+ * bit, since an initialized "upper clean" state results in a massive performance
+ * improvement due to elimination of false dependencies between the XMMs and the
+ * upper bits of the YMMs.
*/
kern_return_t
fpu_set_fxstate(
@@ -860,10 +882,20 @@ fpu_set_fxstate(
iavx->_xh.xstate_bv = AVX_XMASK;
iavx->_xh.xcomp_bv = 0;
+ /*
+ * See the block comment at the top of the function for a description of why we're clearing
+ * xstate_bv bits.
+ */
if (f == x86_AVX_STATE32) {
__nochk_bcopy(&xs->fpu_ymmh0, iavx->x_YMM_Hi128, 8 * sizeof(_STRUCT_XMM_REG));
+ if (fpu_allzeroes((uint64_t *)(void *)iavx->x_YMM_Hi128, 8 * sizeof(_STRUCT_XMM_REG)) == TRUE) {
+ iavx->_xh.xstate_bv &= ~XFEM_YMM;
+ }
} else if (f == x86_AVX_STATE64) {
__nochk_bcopy(&xs->fpu_ymmh0, iavx->x_YMM_Hi128, 16 * sizeof(_STRUCT_XMM_REG));
+ if (fpu_allzeroes((uint64_t *)(void *)iavx->x_YMM_Hi128, 16 * sizeof(_STRUCT_XMM_REG)) == TRUE) {
+ iavx->_xh.xstate_bv &= ~XFEM_YMM;
+ }
} else {
iavx->_xh.xstate_bv = (XFEM_SSE | XFEM_X87);
}
@@ -884,25 +916,55 @@ fpu_set_fxstate(
iavx->_xh.xstate_bv = AVX512_XMASK;
iavx->_xh.xcomp_bv = 0;
+ /*
+ * See the block comment at the top of the function for a description of why we're clearing
+ * xstate_bv bits.
+ */
switch (f) {
case x86_AVX512_STATE32:
__nochk_bcopy(&xs.s32->fpu_k0, iavx->x_Opmask, 8 * sizeof(_STRUCT_OPMASK_REG));
__nochk_bcopy(&xs.s32->fpu_zmmh0, iavx->x_ZMM_Hi256, 8 * sizeof(_STRUCT_YMM_REG));
+ if (fpu_allzeroes((uint64_t *)(void *)iavx->x_ZMM_Hi256, 8 * sizeof(_STRUCT_YMM_REG)) == TRUE) {
+ iavx->_xh.xstate_bv &= ~XFEM_ZMM;
+ }
__nochk_bcopy(&xs.s32->fpu_ymmh0, iavx->x_YMM_Hi128, 8 * sizeof(_STRUCT_XMM_REG));
+ if (fpu_allzeroes((uint64_t *)(void *)iavx->x_YMM_Hi128, 8 * sizeof(_STRUCT_XMM_REG)) == TRUE) {
+ iavx->_xh.xstate_bv &= ~XFEM_YMM;
+ }
+
DBG_AVX512_STATE(iavx);
break;
case x86_AVX_STATE32:
__nochk_bcopy(&xs.s32->fpu_ymmh0, iavx->x_YMM_Hi128, 8 * sizeof(_STRUCT_XMM_REG));
+ if (fpu_allzeroes((uint64_t *)(void *)iavx->x_YMM_Hi128, 8 * sizeof(_STRUCT_XMM_REG)) == TRUE) {
+ iavx->_xh.xstate_bv &= ~XFEM_YMM;
+ }
break;
case x86_AVX512_STATE64:
__nochk_bcopy(&xs.s64->fpu_k0, iavx->x_Opmask, 8 * sizeof(_STRUCT_OPMASK_REG));
__nochk_bcopy(&xs.s64->fpu_zmm16, iavx->x_Hi16_ZMM, 16 * sizeof(_STRUCT_ZMM_REG));
__nochk_bcopy(&xs.s64->fpu_zmmh0, iavx->x_ZMM_Hi256, 16 * sizeof(_STRUCT_YMM_REG));
+ /*
+ * Note that it is valid to have XFEM_ZMM set but XFEM_YMM cleared. In that case,
+ * the upper bits of the YMMs would be cleared and would result in a clean-upper
+ * state, allowing SSE instruction to avoid false dependencies.
+ */
+ if (fpu_allzeroes((uint64_t *)(void *)iavx->x_Hi16_ZMM, 16 * sizeof(_STRUCT_ZMM_REG)) == TRUE &&
+ fpu_allzeroes((uint64_t *)(void *)iavx->x_ZMM_Hi256, 16 * sizeof(_STRUCT_YMM_REG)) == TRUE) {
+ iavx->_xh.xstate_bv &= ~XFEM_ZMM;
+ }
+
__nochk_bcopy(&xs.s64->fpu_ymmh0, iavx->x_YMM_Hi128, 16 * sizeof(_STRUCT_XMM_REG));
+ if (fpu_allzeroes((uint64_t *)(void *)iavx->x_YMM_Hi128, 16 * sizeof(_STRUCT_XMM_REG)) == TRUE) {
+ iavx->_xh.xstate_bv &= ~XFEM_YMM;
+ }
DBG_AVX512_STATE(iavx);
break;
case x86_AVX_STATE64:
__nochk_bcopy(&xs.s64->fpu_ymmh0, iavx->x_YMM_Hi128, 16 * sizeof(_STRUCT_XMM_REG));
+ if (fpu_allzeroes((uint64_t *)(void *)iavx->x_YMM_Hi128, 16 * sizeof(_STRUCT_XMM_REG)) == TRUE) {
+ iavx->_xh.xstate_bv &= ~XFEM_YMM;
+ }
break;
}
break;
diff --git a/osfmk/i386/i386_init.c b/osfmk/i386/i386_init.c
index 70fa633d7..8c1662eea 100644
--- a/osfmk/i386/i386_init.c
+++ b/osfmk/i386/i386_init.c
@@ -871,8 +871,8 @@ do_init_slave(boolean_t fast_restart)
#if CONFIG_MTRR
mtrr_update_cpu();
#endif
- /* update CPU microcode */
- ucode_update_wake();
+ /* update CPU microcode and apply CPU workarounds */
+ ucode_update_wake_and_apply_cpu_was();
} else {
init_param = FAST_SLAVE_INIT;
}
diff --git a/osfmk/i386/proc_reg.h b/osfmk/i386/proc_reg.h
index 4ff579713..c6b8f0be9 100644
--- a/osfmk/i386/proc_reg.h
+++ b/osfmk/i386/proc_reg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000-2019 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2020 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
diff --git a/osfmk/i386/ucode.c b/osfmk/i386/ucode.c
index 139250617..9c10adb4d 100644
--- a/osfmk/i386/ucode.c
+++ b/osfmk/i386/ucode.c
@@ -190,13 +190,14 @@ cpu_update(__unused void *arg)
* by sleeping.
*/
void
-ucode_update_wake()
+ucode_update_wake_and_apply_cpu_was()
{
if (global_update) {
kprintf("ucode: Re-applying update after wake (CPU #%d)\n", cpu_number());
cpu_update(NULL);
-#if DEBUG
} else {
+ cpuid_do_was();
+#if DEBUG
kprintf("ucode: No update to apply (CPU #%d)\n", cpu_number());
#endif
}
diff --git a/osfmk/i386/ucode.h b/osfmk/i386/ucode.h
index e36380ba9..9c42e0ca4 100644
--- a/osfmk/i386/ucode.h
+++ b/osfmk/i386/ucode.h
@@ -54,4 +54,4 @@ struct intel_ucupdate {
};
extern int ucode_interface(uint64_t addr);
-extern void ucode_update_wake(void);
+extern void ucode_update_wake_and_apply_cpu_was(void);
diff --git a/osfmk/ipc/ipc_importance.c b/osfmk/ipc/ipc_importance.c
index c403b9f46..2b7391cd6 100644
--- a/osfmk/ipc/ipc_importance.c
+++ b/osfmk/ipc/ipc_importance.c
@@ -2659,7 +2659,7 @@ ipc_importance_send(
#if IMPORTANCE_TRACE
if (kdebug_enable) {
mach_msg_max_trailer_t *dbgtrailer = (mach_msg_max_trailer_t *)
- ((vm_offset_t)kmsg->ikm_header + round_msg(kmsg->ikm_header->msgh_size));
+ ((vm_offset_t)kmsg->ikm_header + mach_round_msg(kmsg->ikm_header->msgh_size));
unsigned int sender_pid = dbgtrailer->msgh_audit.val[5];
mach_msg_id_t imp_msgh_id = kmsg->ikm_header->msgh_id;
KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, (IMPORTANCE_CODE(IMP_MSG, IMP_MSG_SEND)) | DBG_FUNC_START,
@@ -3174,7 +3174,7 @@ ipc_importance_receive(
task_t task_self = current_task();
unsigned int sender_pid = ((mach_msg_max_trailer_t *)
((vm_offset_t)kmsg->ikm_header +
- round_msg(kmsg->ikm_header->msgh_size)))->msgh_audit.val[5];
+ mach_round_msg(kmsg->ikm_header->msgh_size)))->msgh_audit.val[5];
#endif
/* convert to a voucher with an inherit importance attribute? */
diff --git a/osfmk/ipc/ipc_kmsg.c b/osfmk/ipc/ipc_kmsg.c
index 3a40a39ff..95ff1fb29 100644
--- a/osfmk/ipc/ipc_kmsg.c
+++ b/osfmk/ipc/ipc_kmsg.c
@@ -832,7 +832,7 @@ ipc_kmsg_trace_send(ipc_kmsg_t kmsg,
* Trailer contents
*/
trailer = (mach_msg_trailer_t *)((vm_offset_t)msg +
- round_msg((vm_offset_t)msg->msgh_size));
+ (vm_offset_t)mach_round_msg(msg->msgh_size));
if (trailer->msgh_trailer_size <= sizeof(mach_msg_security_trailer_t)) {
extern const security_token_t KERNEL_SECURITY_TOKEN;
mach_msg_security_trailer_t *strailer;
@@ -4627,6 +4627,7 @@ ipc_kmsg_copyout_ool_descriptor(mach_msg_ool_descriptor_t *dsc, mach_msg_descrip
mach_msg_copy_options_t copy_options;
vm_map_size_t size;
mach_msg_descriptor_type_t dsc_type;
+ boolean_t misaligned = FALSE;
//SKIP_PORT_DESCRIPTORS(saddr, sdsc_count);
@@ -4644,7 +4645,59 @@ ipc_kmsg_copyout_ool_descriptor(mach_msg_ool_descriptor_t *dsc, mach_msg_descrip
panic("Inconsistent OOL/copyout size on %p: expected %d, got %lld @%p",
dsc, dsc->size, (unsigned long long)copy->size, copy);
}
- kr = vm_map_copyout_size(map, &rcv_addr, copy, size);
+
+ if ((copy->type == VM_MAP_COPY_ENTRY_LIST) &&
+ (trunc_page(copy->offset) != copy->offset ||
+ round_page(dsc->size) != dsc->size)) {
+ misaligned = TRUE;
+ }
+
+ if (misaligned) {
+ vm_map_address_t rounded_addr;
+ vm_map_size_t rounded_size;
+ vm_map_offset_t effective_page_mask, effective_page_size;
+
+ effective_page_mask = VM_MAP_PAGE_MASK(map);
+ effective_page_size = effective_page_mask + 1;
+
+ rounded_size = vm_map_round_page(copy->offset + size, effective_page_mask) - vm_map_trunc_page(copy->offset, effective_page_mask);
+
+ kr = vm_allocate_kernel(map, (vm_offset_t*)&rounded_addr, rounded_size, VM_FLAGS_ANYWHERE, 0);
+
+ if (kr == KERN_SUCCESS) {
+ /*
+ * vm_map_copy_overwrite does a full copy
+ * if size is too small to optimize.
+ * So we tried skipping the offset adjustment
+ * if we fail the 'size' test.
+ *
+ * if (size >= VM_MAP_COPY_OVERWRITE_OPTIMIZATION_THRESHOLD_PAGES * effective_page_size) {
+ *
+ * This resulted in leaked memory especially on the
+ * older watches (16k user - 4k kernel) because we
+ * would do a physical copy into the start of this
+ * rounded range but could leak part of it
+ * on deallocation if the 'size' being deallocated
+ * does not cover the full range. So instead we do
+ * the misalignment adjustment always so that on
+ * deallocation we will remove the full range.
+ */
+ if ((rounded_addr & effective_page_mask) !=
+ (copy->offset & effective_page_mask)) {
+ /*
+ * Need similar mis-alignment of source and destination...
+ */
+ rounded_addr += (copy->offset & effective_page_mask);
+
+ assert((rounded_addr & effective_page_mask) == (copy->offset & effective_page_mask));
+ }
+ rcv_addr = rounded_addr;
+
+ kr = vm_map_copy_overwrite(map, rcv_addr, copy, size, FALSE);
+ }
+ } else {
+ kr = vm_map_copyout_size(map, &rcv_addr, copy, size);
+ }
if (kr != KERN_SUCCESS) {
if (kr == KERN_RESOURCE_SHORTAGE) {
*mr |= MACH_MSG_VM_KERNEL;
@@ -5532,7 +5585,7 @@ ipc_kmsg_add_trailer(ipc_kmsg_t kmsg, ipc_space_t space __unused,
mach_msg_max_trailer_t tmp_trailer; /* This accommodates U64, and we'll munge */
void *real_trailer_out = (void*)(mach_msg_max_trailer_t *)
((vm_offset_t)kmsg->ikm_header +
- round_msg(kmsg->ikm_header->msgh_size));
+ mach_round_msg(kmsg->ikm_header->msgh_size));
/*
* Populate scratch with initial values set up at message allocation time.
@@ -5545,7 +5598,7 @@ ipc_kmsg_add_trailer(ipc_kmsg_t kmsg, ipc_space_t space __unused,
(void)thread;
trailer = (mach_msg_max_trailer_t *)
((vm_offset_t)kmsg->ikm_header +
- round_msg(kmsg->ikm_header->msgh_size));
+ mach_round_msg(kmsg->ikm_header->msgh_size));
#endif /* __arm64__ */
if (!(option & MACH_RCV_TRAILER_MASK)) {
diff --git a/osfmk/ipc/ipc_mqueue.c b/osfmk/ipc/ipc_mqueue.c
index 360879748..7626a1ad2 100644
--- a/osfmk/ipc/ipc_mqueue.c
+++ b/osfmk/ipc/ipc_mqueue.c
@@ -1424,7 +1424,7 @@ ipc_mqueue_peek_locked(ipc_mqueue_t mq,
if (msg_trailerp != NULL) {
memcpy(msg_trailerp,
(mach_msg_max_trailer_t *)((vm_offset_t)kmsg->ikm_header +
- round_msg(kmsg->ikm_header->msgh_size)),
+ mach_round_msg(kmsg->ikm_header->msgh_size)),
sizeof(mach_msg_max_trailer_t));
}
if (kmsgp != NULL) {
diff --git a/osfmk/ipc/mach_msg.c b/osfmk/ipc/mach_msg.c
index f367c8e00..01a5531cf 100644
--- a/osfmk/ipc/mach_msg.c
+++ b/osfmk/ipc/mach_msg.c
@@ -762,7 +762,7 @@ msg_receive_error(
*/
trailer = (mach_msg_max_trailer_t *)
((vm_offset_t)kmsg->ikm_header +
- round_msg(sizeof(mach_msg_header_t)));
+ mach_round_msg(sizeof(mach_msg_header_t)));
kmsg->ikm_header->msgh_size = sizeof(mach_msg_header_t);
bcopy((char *)&trailer_template,
(char *)trailer,
diff --git a/osfmk/kern/exception.c b/osfmk/kern/exception.c
index c059f1c50..4cbd102c1 100644
--- a/osfmk/kern/exception.c
+++ b/osfmk/kern/exception.c
@@ -123,6 +123,16 @@ kern_return_t bsd_exception(
mach_msg_type_number_t codeCnt);
#endif /* MACH_BSD */
+#if __has_feature(ptrauth_calls)
+extern int exit_with_pac_exception(
+ void *proc,
+ exception_type_t exception,
+ mach_exception_code_t code,
+ mach_exception_subcode_t subcode);
+
+extern bool proc_is_traced(void *p);
+#endif /* __has_feature(ptrauth_calls) */
+
/*
* Routine: exception_init
* Purpose:
@@ -525,6 +535,29 @@ exception_triage(
mach_msg_type_number_t codeCnt)
{
thread_t thread = current_thread();
+#if __has_feature(ptrauth_calls)
+ /*
+ * If it is a ptrauth violation, then check if the task has the TF_PAC_EXC_FATAL
+ * flag set and isn't being ptraced. If so, terminate the task via exit_with_reason
+ */
+ if (exception & EXC_PTRAUTH_BIT) {
+ exception &= ~EXC_PTRAUTH_BIT;
+
+ boolean_t traced_flag = FALSE;
+ task_t task = thread->task;
+ void *proc = task->bsd_info;
+
+ if (task->bsd_info) {
+ traced_flag = proc_is_traced(proc);
+ }
+
+ if (task_is_pac_exception_fatal(current_task()) && !traced_flag) {
+ exit_with_pac_exception(proc, exception, code[0], code[1]);
+ thread_exception_return();
+ /* NOT_REACHABLE */
+ }
+ }
+#endif /* __has_feature(ptrauth_calls) */
return exception_triage_thread(exception, code, codeCnt, thread);
}
diff --git a/osfmk/kern/task.c b/osfmk/kern/task.c
index df259cf29..6c1d1aa80 100644
--- a/osfmk/kern/task.c
+++ b/osfmk/kern/task.c
@@ -177,12 +177,14 @@
#include
#endif
+#include
+
#if KPERF
extern int kpc_force_all_ctrs(task_t, int);
#endif
-task_t kernel_task;
-zone_t task_zone;
+SECURITY_READ_ONLY_LATE(task_t) kernel_task;
+SECURITY_READ_ONLY_LATE(zone_t) task_zone;
lck_attr_t task_lck_attr;
lck_grp_t task_lck_grp;
lck_grp_attr_t task_lck_grp_attr;
@@ -750,6 +752,7 @@ task_reference_internal(task_t task)
void * bt[TASK_REF_BTDEPTH];
int numsaved = 0;
+ zone_require(task, task_zone);
os_ref_retain(&task->ref_count);
numsaved = OSBacktrace(bt, TASK_REF_BTDEPTH);
@@ -7492,3 +7495,35 @@ task_copy_vmobjects(task_t task, vm_object_query_t query, int len, int64_t* num)
*num = i;
}
+
+#if __has_feature(ptrauth_calls)
+
+#define PAC_EXCEPTION_ENTITLEMENT "com.apple.private.pac.exception"
+
+void
+task_set_pac_exception_fatal_flag(
+ task_t task)
+{
+ assert(task != TASK_NULL);
+
+ if (!IOTaskHasEntitlement(task, PAC_EXCEPTION_ENTITLEMENT)) {
+ return;
+ }
+
+ task_lock(task);
+ task->t_flags |= TF_PAC_EXC_FATAL;
+ task_unlock(task);
+}
+
+bool
+task_is_pac_exception_fatal(
+ task_t task)
+{
+ uint32_t flags = 0;
+
+ assert(task != TASK_NULL);
+
+ flags = os_atomic_load(&task->t_flags, relaxed);
+ return (bool)(flags & TF_PAC_EXC_FATAL);
+}
+#endif /* __has_feature(ptrauth_calls) */
diff --git a/osfmk/kern/task.h b/osfmk/kern/task.h
index 1c7ec758b..df8c779dd 100644
--- a/osfmk/kern/task.h
+++ b/osfmk/kern/task.h
@@ -271,6 +271,7 @@ struct task {
#define TF_CA_CLIENT_WI 0x00000800 /* task has CA_CLIENT work interval */
#define TF_DARKWAKE_MODE 0x00001000 /* task is in darkwake mode */
#define TF_NO_SMT 0x00002000 /* task threads must not be paired with SMT threads */
+#define TF_PAC_EXC_FATAL 0x00004000 /* task is marked a corpse if a PAC exception occurs */
/*
* Task is running within a 64-bit address space.
@@ -500,11 +501,17 @@ extern kern_return_t
#define TASK_REFERENCE_LEAK_DEBUG 0
+extern zone_t task_zone;
+
#if TASK_REFERENCE_LEAK_DEBUG
extern void task_reference_internal(task_t task);
extern os_ref_count_t task_deallocate_internal(task_t task);
#else
-#define task_reference_internal(task) os_ref_retain(&(task)->ref_count)
+#define task_reference_internal(task) \
+MACRO_BEGIN \
+ zone_require(task, task_zone); \
+ os_ref_retain(&(task)->ref_count); \
+MACRO_END
#define task_deallocate_internal(task) os_ref_release(&(task)->ref_count)
#endif
@@ -956,6 +963,11 @@ extern void task_copy_fields_for_exec(task_t dst_task, task_t src_task);
extern void task_copy_vmobjects(task_t task, vm_object_query_t query, int len, int64_t* num);
+#if __has_feature(ptrauth_calls)
+extern bool task_is_pac_exception_fatal(task_t task);
+extern void task_set_pac_exception_fatal_flag(task_t task);
+#endif /*__has_feature(ptrauth_calls)*/
+
#endif /* XNU_KERNEL_PRIVATE */
#ifdef KERNEL_PRIVATE
diff --git a/osfmk/kern/thread.h b/osfmk/kern/thread.h
index f5b7cf612..380c3ad40 100644
--- a/osfmk/kern/thread.h
+++ b/osfmk/kern/thread.h
@@ -214,7 +214,7 @@ struct thread {
#define TH_OPT_SCHED_VM_GROUP 0x0200 /* Thread belongs to special scheduler VM group */
#define TH_OPT_HONOR_QLIMIT 0x0400 /* Thread will honor qlimit while sending mach_msg, regardless of MACH_SEND_ALWAYS */
#define TH_OPT_SEND_IMPORTANCE 0x0800 /* Thread will allow importance donation from kernel rpc */
-#define TH_OPT_ZONE_GC 0x1000 /* zone_gc() called on this thread */
+#define TH_OPT_ZONE_PRIV 0x1000 /* Thread may use the zone replenish reserve */
bool wake_active; /* wake event on stop */
bool at_safe_point; /* thread_abort_safely allowed */
diff --git a/osfmk/kern/zalloc.c b/osfmk/kern/zalloc.c
index f25e40407..3ee2ae14f 100644
--- a/osfmk/kern/zalloc.c
+++ b/osfmk/kern/zalloc.c
@@ -120,8 +120,9 @@ lck_grp_attr_t zone_locks_grp_attr;
*/
#define from_zone_map(addr, size) \
- ((vm_offset_t)(addr) >= zone_map_min_address && \
- ((vm_offset_t)(addr) + size - 1) < zone_map_max_address )
+ ((vm_offset_t)(addr) >= zone_map_min_address && \
+ ((vm_offset_t)(addr) + size) >= zone_map_min_address && \
+ ((vm_offset_t)(addr) + size) <= zone_map_max_address )
/*
* Zone Corruption Debugging
@@ -646,16 +647,19 @@ get_zone_page(struct zone_page_metadata *page_meta)
void
zone_require(void *addr, zone_t expected_zone)
{
- struct zone *src_zone = NULL;
- struct zone_page_metadata *page_meta = get_zone_page_metadata((struct zone_free_element *)addr, FALSE);
+ struct zone_page_metadata *page_meta;
- src_zone = PAGE_METADATA_GET_ZONE(page_meta);
- if (__improbable(src_zone == NULL)) {
- panic("Address not in a zone for zone_require check (addr: %p)", addr);
+ if (!from_zone_map(addr, expected_zone->elem_size)) {
+ panic("Address not in a zone map for zone_require check (addr: %p)", addr);
}
- if (__improbable(src_zone != expected_zone)) {
- panic("Address not in expected zone for zone_require check (addr: %p, zone: %s)", addr, src_zone->zone_name);
+ page_meta = PAGE_METADATA_FOR_ELEMENT(addr);
+ if (PAGE_METADATA_GET_ZINDEX(page_meta) == MULTIPAGE_METADATA_MAGIC) {
+ page_meta = page_metadata_get_realmeta(page_meta);
+ }
+ if (PAGE_METADATA_GET_ZINDEX(page_meta) != expected_zone->index) {
+ panic("Address not in expected zone for zone_require check (addr: %p, zone: %s)",
+ addr, expected_zone->zone_name);
}
}
@@ -2401,7 +2405,7 @@ zinit(
z->gzalloc_exempt = FALSE;
z->alignment_required = FALSE;
z->zone_replenishing = FALSE;
- z->prio_refill_watermark = 0;
+ z->prio_refill_count = 0;
z->zone_replenish_thread = NULL;
z->zp_count = 0;
z->kasan_quarantine = TRUE;
@@ -2565,7 +2569,52 @@ zinit(
return z;
}
-unsigned zone_replenish_loops, zone_replenish_wakeups, zone_replenish_wakeups_initiated, zone_replenish_throttle_count;
+
+/*
+ * Dealing with zone allocations from the mach VM code.
+ *
+ * The implementation of the mach VM itself uses the zone allocator
+ * for things like the vm_map_entry data structure. In order to prevent
+ * an infinite recursion problem when adding more pages to a zone, zalloc
+ * uses a replenish thread to refill the VM layer's zones before they have
+ * too few remaining free entries. The reserved remaining free entries
+ * guarantee that the VM routines can get entries from already mapped pages.
+ *
+ * In order for that to work, the amount of allocations in the nested
+ * case have to be bounded. There are currently 2 replenish zones, and
+ * if each needs 1 element of each zone to add a new page to itself, that
+ * gives us a minumum reserve of 2 elements.
+ *
+ * There is also a deadlock issue with the zone garbage collection thread,
+ * or any thread that is trying to free zone pages. While holding
+ * the kernel's map lock they may need to allocate new VM map entries, hence
+ * we need enough reserve to allow them to get past the point of holding the
+ * map lock. After freeing that page, the GC thread will wait in drop_free_elements()
+ * until the replenish threads can finish. Since there's only 1 GC thread at a time,
+ * that adds a minimum of 1 to the reserve size.
+ *
+ * Since the minumum amount you can add to a zone is 1 page, we'll use 16K (from ARM)
+ * as the refill size on all platforms.
+ *
+ * When a refill zone drops to half that available, i.e. REFILL_SIZE / 2,
+ * zalloc_internal() will wake the replenish thread. The replenish thread runs
+ * until at least REFILL_SIZE worth of free elements exist, before sleeping again.
+ * In the meantime threads may continue to use the reserve until there are only REFILL_SIZE / 4
+ * elements left. Below that point only the replenish threads themselves and the GC
+ * thread may continue to use from the reserve.
+ */
+static unsigned zone_replenish_loops;
+static unsigned zone_replenish_wakeups;
+static unsigned zone_replenish_wakeups_initiated;
+static unsigned zone_replenish_throttle_count;
+
+#define ZONE_REPLENISH_TARGET (16 * 1024)
+static unsigned int zone_replenish_active = 0; /* count of zones currently replenishing */
+static unsigned int zone_replenish_max_threads = 0;
+static lck_spin_t zone_replenish_lock;
+static lck_attr_t zone_replenish_lock_attr;
+static lck_grp_t zone_replenish_lock_grp;
+static lck_grp_attr_t zone_replenish_lock_grp_attr;
static void zone_replenish_thread(zone_t);
@@ -2576,15 +2625,14 @@ __dead2
static void
zone_replenish_thread(zone_t z)
{
- vm_size_t free_size;
- current_thread()->options |= TH_OPT_VMPRIV;
+ current_thread()->options |= (TH_OPT_VMPRIV | TH_OPT_ZONE_PRIV);
for (;;) {
lock_zone(z);
assert(z->zone_valid);
- z->zone_replenishing = TRUE;
- assert(z->prio_refill_watermark != 0);
- while ((free_size = (z->cur_size - (z->count * z->elem_size))) < (z->prio_refill_watermark * z->elem_size)) {
+ assert(z->zone_replenishing);
+ assert(z->prio_refill_count != 0);
+ while ((z->cur_size / z->elem_size) - z->count < z->prio_refill_count) {
assert(z->doing_alloc_without_vm_priv == FALSE);
assert(z->doing_alloc_with_vm_priv == FALSE);
assert(z->async_prio_refill == TRUE);
@@ -2634,13 +2682,23 @@ zone_replenish_thread(zone_t z)
zone_replenish_loops++;
}
- z->zone_replenishing = FALSE;
- /* Signal any potential throttled consumers, terminating
- * their timer-bounded waits.
- */
+ /* Wakeup any potentially throttled allocations. */
thread_wakeup(z);
assert_wait(&z->zone_replenish_thread, THREAD_UNINT);
+
+ /*
+ * We finished refilling the zone, so decrement the active count
+ * and wake up any waiting GC threads.
+ */
+ lck_spin_lock(&zone_replenish_lock);
+ assert(zone_replenish_active > 0);
+ if (--zone_replenish_active == 0) {
+ thread_wakeup((event_t)&zone_replenish_active);
+ }
+ lck_spin_unlock(&zone_replenish_lock);
+
+ z->zone_replenishing = FALSE;
unlock_zone(z);
thread_block(THREAD_CONTINUE_NULL);
zone_replenish_wakeups++;
@@ -2648,11 +2706,16 @@ zone_replenish_thread(zone_t z)
}
void
-zone_prio_refill_configure(zone_t z, vm_size_t low_water_mark)
+zone_prio_refill_configure(zone_t z)
{
- z->prio_refill_watermark = low_water_mark;
+ z->prio_refill_count = ZONE_REPLENISH_TARGET / z->elem_size;
z->async_prio_refill = TRUE;
+ z->zone_replenishing = TRUE;
+ lck_spin_lock(&zone_replenish_lock);
+ ++zone_replenish_max_threads;
+ ++zone_replenish_active;
+ lck_spin_unlock(&zone_replenish_lock);
OSMemoryBarrier();
kern_return_t tres = kernel_thread_start_priority((thread_continue_t)zone_replenish_thread, z, MAXPRI_KERNEL, &z->zone_replenish_thread);
@@ -3005,6 +3068,11 @@ zone_bootstrap(void)
lck_attr_setdefault(&zone_metadata_lock_attr);
lck_mtx_init_ext(&zone_metadata_region_lck, &zone_metadata_region_lck_ext, &zone_locks_grp, &zone_metadata_lock_attr);
+ lck_grp_attr_setdefault(&zone_replenish_lock_grp_attr);
+ lck_grp_init(&zone_replenish_lock_grp, "zone_replenish_lock", &zone_replenish_lock_grp_attr);
+ lck_attr_setdefault(&zone_replenish_lock_attr);
+ lck_spin_init(&zone_replenish_lock, &zone_replenish_lock_grp, &zone_replenish_lock_attr);
+
#if CONFIG_ZCACHE
/* zcc_enable_for_zone_name=: enable per-cpu zone caching for . */
if (PE_parse_boot_arg_str("zcc_enable_for_zone_name", cache_zone_name, sizeof(cache_zone_name))) {
@@ -3246,18 +3314,6 @@ zalloc_poison_element(boolean_t check_poison, zone_t zone, vm_offset_t addr)
}
}
-/*
- * When deleting page mappings from the kernel map, it might be necessary to split
- * apart an existing vm_map_entry. That means that a "free" operation, will need to
- * *allocate* new vm_map_entry structures before it can free a page.
- *
- * This reserve here is the number of elements which are held back from everyone except
- * the zone_gc thread. This is done so the zone_gc thread should never have to wait for
- * the zone replenish thread for vm_map_entry structs. If it did, it could wind up
- * in a deadlock.
- */
-#define VM_MAP_ENTRY_RESERVE_CNT 8
-
/*
* zalloc returns an element from the specified zone.
*/
@@ -3280,6 +3336,9 @@ zalloc_internal(
thread_t thr = current_thread();
boolean_t check_poison = FALSE;
boolean_t set_doing_alloc_with_vm_priv = FALSE;
+ vm_size_t curr_free;
+ vm_size_t min_free;
+ vm_size_t resv_free;
#if CONFIG_ZLEAKS
uint32_t zleak_tracedepth = 0; /* log this allocation if nonzero */
@@ -3357,47 +3416,56 @@ zalloc_internal(
assert(zone->zone_valid);
/*
- * Check if we need another thread to replenish the zone.
+ * Check if we need another thread to replenish the zone or
+ * if we have to wait for a replenish thread to finish.
* This is used for elements, like vm_map_entry, which are
* needed themselves to implement zalloc().
*/
- if (zone->async_prio_refill && zone->zone_replenish_thread) {
- vm_size_t curr_free;
- vm_size_t refill_level;
- const vm_size_t reserved_min = VM_MAP_ENTRY_RESERVE_CNT * zone->elem_size;
-
+ if (addr == 0 && zone->async_prio_refill && zone->zone_replenish_thread) {
+ min_free = (zone->prio_refill_count * zone->elem_size) / 2;
+ resv_free = min_free / 2;
for (;;) {
- curr_free = (zone->cur_size - (zone->count * zone->elem_size));
- refill_level = zone->prio_refill_watermark * zone->elem_size;
+ curr_free = zone->cur_size - (zone->count * zone->elem_size);
/*
* Nothing to do if there are plenty of elements.
*/
- if (curr_free > refill_level) {
+ if (curr_free > min_free) {
break;
}
/*
- * Wakeup the replenish thread.
+ * Wakeup the replenish thread if not running.
*/
- zone_replenish_wakeups_initiated++;
- thread_wakeup(&zone->zone_replenish_thread);
+ if (!zone->zone_replenishing) {
+ lck_spin_lock(&zone_replenish_lock);
+ assert(zone_replenish_active < zone_replenish_max_threads);
+ ++zone_replenish_active;
+ lck_spin_unlock(&zone_replenish_lock);
+ zone->zone_replenishing = TRUE;
+ zone_replenish_wakeups_initiated++;
+ thread_wakeup(&zone->zone_replenish_thread);
+ }
/*
- * If we:
- * - still have head room, more than half the refill amount, or
- * - this is a VMPRIV thread and we're still above reserved, or
- * - this is the zone garbage collection thread which may use the reserve
- * then we don't have to wait for the replenish thread.
+ * We'll let VM_PRIV threads to continue to allocate until the
+ * reserve drops to 25%. After that only TH_OPT_ZONE_PRIV threads
+ * may continue.
*
- * The reserve for the garbage collection thread is to avoid a deadlock
- * on the zone_map_lock between the replenish thread and GC thread.
+ * TH_OPT_ZONE_PRIV threads are the GC thread and a replenish thread itself.
+ * Replenish threads *need* to use the reserve. GC threads need to
+ * get through the current allocation, but then will wait at a higher
+ * level after they've dropped any locks which would deadlock the
+ * replenish thread.
*/
- if (curr_free > refill_level / 2 ||
- ((thr->options & TH_OPT_VMPRIV) && curr_free > reserved_min) ||
- (thr->options & TH_OPT_ZONE_GC)) {
+ if ((curr_free > resv_free && (thr->options & TH_OPT_VMPRIV)) ||
+ (thr->options & TH_OPT_ZONE_PRIV)) {
break;
}
+
+ /*
+ * Wait for the replenish threads to add more elements for us to allocate from.
+ */
zone_replenish_throttle_count++;
unlock_zone(zone);
assert_wait_timeout(zone, THREAD_UNINT, 1, NSEC_PER_MSEC);
@@ -3412,17 +3480,17 @@ zalloc_internal(
addr = try_alloc_from_zone(zone, tag, &check_poison);
}
- /* If we're here because of zone_gc(), we didn't wait for zone_replenish_thread to finish.
- * So we need to ensure that we did successfully grab an element. And we only need to assert
- * this for zones that have a replenish thread configured (in this case, the Reserved VM map
- * entries zone). The value of reserved_min in the previous bit of code should have given us
- * headroom even though the GC thread didn't wait.
+ /*
+ * If we didn't wait for zone_replenish_thread to finish, ensure that we did successfully grab
+ * an element. Obviously we only need to assert this for zones that have a replenish thread configured.
+ * The value of (refill_level / 2) in the previous bit of code should have given us
+ * headroom even though this thread didn't wait.
*/
- if ((thr->options & TH_OPT_ZONE_GC) && zone->async_prio_refill) {
+ if ((thr->options & TH_OPT_ZONE_PRIV) && zone->async_prio_refill) {
assert(addr != 0);
}
- while ((addr == 0) && canblock) {
+ while (addr == 0 && canblock) {
/*
* zone is empty, try to expand it
*
@@ -4107,11 +4175,30 @@ drop_free_elements(zone_t z)
vm_address_t free_page_address;
vm_size_t size_to_free;
+ current_thread()->options |= TH_OPT_ZONE_PRIV;
lock_zone(z);
elt_size = z->elem_size;
while (!queue_empty(&z->pages.all_free)) {
+ /*
+ * If any replenishment threads are running, defer to them, so that we don't deplete reserved zones.
+ * The timing of the check isn't super important, as there are enough reserves to allow freeing an
+ * extra page_meta. Hence, we can check without grabbing the lock every time through the loop.
+ * We do need the lock however to avoid missing a wakeup when we decide to block.
+ */
+ if (zone_replenish_active > 0) {
+ lck_spin_lock(&zone_replenish_lock);
+ if (zone_replenish_active > 0) {
+ assert_wait(&zone_replenish_active, THREAD_UNINT);
+ lck_spin_unlock(&zone_replenish_lock);
+ unlock_zone(z);
+ thread_block(THREAD_CONTINUE_NULL);
+ lock_zone(z);
+ continue;
+ }
+ lck_spin_unlock(&zone_replenish_lock);
+ }
page_meta = (struct zone_page_metadata *)queue_first(&z->pages.all_free);
assert(from_zone_map((vm_address_t)page_meta, sizeof(*page_meta))); /* foreign elements should be in any_free_foreign */
/*
@@ -4120,7 +4207,7 @@ drop_free_elements(zone_t z)
*/
if (!z->zone_destruction &&
z->async_prio_refill && z->zone_replenish_thread &&
- (vm_size_t)(page_meta->free_count - z->countfree) < z->prio_refill_watermark) {
+ (vm_size_t)(page_meta->free_count - z->countfree) < z->prio_refill_count) {
break;
}
@@ -4151,9 +4238,7 @@ drop_free_elements(zone_t z)
}
#endif /* VM_MAX_TAG_ZONES */
kmem_free(zone_map, free_page_address, size_to_free);
- if (current_thread()->options & TH_OPT_ZONE_GC) {
- thread_yield_to_preemption();
- }
+ thread_yield_to_preemption();
lock_zone(z);
}
if (z->zone_destruction) {
@@ -4161,6 +4246,7 @@ drop_free_elements(zone_t z)
assert(z->count_all_free_pages == 0);
}
unlock_zone(z);
+ current_thread()->options &= ~TH_OPT_ZONE_PRIV;
#if DEBUG || DEVELOPMENT
@@ -4198,8 +4284,6 @@ zone_gc(boolean_t consider_jetsams)
lck_mtx_lock(&zone_gc_lock);
- current_thread()->options |= TH_OPT_ZONE_GC;
-
simple_lock(&all_zones_lock, &zone_locks_grp);
max_zones = num_zones;
simple_unlock(&all_zones_lock);
@@ -4229,8 +4313,6 @@ zone_gc(boolean_t consider_jetsams)
drop_free_elements(z);
}
- current_thread()->options &= ~TH_OPT_ZONE_GC;
-
lck_mtx_unlock(&zone_gc_lock);
}
diff --git a/osfmk/kern/zalloc.h b/osfmk/kern/zalloc.h
index c5f356ff9..5e3caa6de 100644
--- a/osfmk/kern/zalloc.h
+++ b/osfmk/kern/zalloc.h
@@ -166,8 +166,8 @@ struct zone {
uint32_t zleak_capture; /* per-zone counter for capturing every N allocations */
#endif /* CONFIG_ZLEAKS */
uint32_t zp_count; /* counter for poisoning every N frees */
- vm_size_t prio_refill_watermark;
- thread_t zone_replenish_thread;
+ uint32_t prio_refill_count; /* if async_prio_refill, refill to this count */
+ thread_t zone_replenish_thread;
#if CONFIG_GZALLOC
gzalloc_data_t gz;
#endif /* CONFIG_GZALLOC */
@@ -325,7 +325,7 @@ extern int zfill(
zone_t zone,
int nelem);
-extern void zone_prio_refill_configure(zone_t, vm_size_t);
+extern void zone_prio_refill_configure(zone_t);
/* See above/top of file. Z_* definitions moved so they would be usable by kexts */
diff --git a/osfmk/mach/arm/exception.h b/osfmk/mach/arm/exception.h
index 06658bc1e..42a802824 100644
--- a/osfmk/mach/arm/exception.h
+++ b/osfmk/mach/arm/exception.h
@@ -35,6 +35,12 @@
#define EXCEPTION_CODE_MAX 2 /* code and subcode */
+#if XNU_KERNEL_PRIVATE
+#if __has_feature(ptrauth_calls)
+#define EXC_PTRAUTH_BIT 0x200 /* bit set if exception could have been caused by ptrauth failure */
+#endif /* __has_feature(ptrauth_calls) */
+#endif /* XNU_KERNEL_PRIVATE */
+
/*
* Trap numbers as defined by the hardware exception vectors.
*/
diff --git a/osfmk/mach/message.h b/osfmk/mach/message.h
index a1a3a0325..cb789b57b 100644
--- a/osfmk/mach/message.h
+++ b/osfmk/mach/message.h
@@ -654,6 +654,28 @@ typedef union{
#define round_msg(x) (((mach_msg_size_t)(x) + sizeof (natural_t) - 1) & \
~(sizeof (natural_t) - 1))
+#ifdef XNU_KERNEL_PRIVATE
+
+#include
+#include
+#include
+
+#define round_msg_overflow(in, out) __os_warn_unused(({ \
+ bool __ovr = os_add_overflow(in, (__typeof__(*out))(sizeof(natural_t) - 1), out); \
+ *out &= ~((__typeof__(*out))(sizeof(natural_t) - 1)); \
+ __ovr; \
+ }))
+
+static inline mach_msg_size_t
+mach_round_msg(mach_msg_size_t x)
+{
+ if (round_msg_overflow(x, &x)) {
+ panic("round msg overflow");
+ }
+ return x;
+}
+#endif /* XNU_KERNEL_PRIVATE */
+
/*
* There is no fixed upper bound to the size of Mach messages.
*/
diff --git a/osfmk/vm/vm_fault.c b/osfmk/vm/vm_fault.c
index 0cfa66169..e558508d7 100644
--- a/osfmk/vm/vm_fault.c
+++ b/osfmk/vm/vm_fault.c
@@ -2580,7 +2580,12 @@ vm_fault_enter(vm_page_t m,
* from the current map. We do that below right before we do the
* PMAP_ENTER.
*/
- cs_enforcement_enabled = cs_process_enforcement(NULL);
+ if (pmap == kernel_pmap) {
+ /* kernel fault: cs_process_enforcement() does not apply */
+ cs_enforcement_enabled = 0;
+ } else {
+ cs_enforcement_enabled = cs_process_enforcement(NULL);
+ }
if (cs_enforcement_enabled && map_is_switched &&
map_is_switch_protected && page_immutable(m, prot) &&
diff --git a/osfmk/vm/vm_map.c b/osfmk/vm/vm_map.c
index ab0d87614..9aa1eb9b5 100644
--- a/osfmk/vm/vm_map.c
+++ b/osfmk/vm/vm_map.c
@@ -552,11 +552,11 @@ override_nx(vm_map_t map, uint32_t user_tag) /* map unused on arm */
* vm_object_copy_strategically() in vm_object.c.
*/
-static zone_t vm_map_zone; /* zone for vm_map structures */
-zone_t vm_map_entry_zone; /* zone for vm_map_entry structures */
-static zone_t vm_map_entry_reserved_zone; /* zone with reserve for non-blocking allocations */
-static zone_t vm_map_copy_zone; /* zone for vm_map_copy structures */
-zone_t vm_map_holes_zone; /* zone for vm map holes (vm_map_links) structures */
+static zone_t vm_map_zone; /* zone for vm_map structures */
+zone_t vm_map_entry_zone; /* zone for vm_map_entry structures */
+static zone_t vm_map_entry_reserved_zone; /* zone with reserve for non-blocking allocations */
+static SECURITY_READ_ONLY_LATE(zone_t) vm_map_copy_zone; /* zone for vm_map_copy structures */
+zone_t vm_map_holes_zone; /* zone for vm map holes (vm_map_links) structures */
/*
@@ -1072,12 +1072,12 @@ boolean_t vm_map_supports_hole_optimization = FALSE;
void
vm_kernel_reserved_entry_init(void)
{
- zone_prio_refill_configure(vm_map_entry_reserved_zone, (6 * PAGE_SIZE) / sizeof(struct vm_map_entry));
+ zone_prio_refill_configure(vm_map_entry_reserved_zone);
/*
* Once we have our replenish thread set up, we can start using the vm_map_holes zone.
*/
- zone_prio_refill_configure(vm_map_holes_zone, (6 * PAGE_SIZE) / sizeof(struct vm_map_links));
+ zone_prio_refill_configure(vm_map_holes_zone);
vm_map_supports_hole_optimization = TRUE;
}
@@ -4185,6 +4185,7 @@ vm_map_enter_mem_object_helper(
copy_map = named_entry->backing.copy;
assert(copy_map->type == VM_MAP_COPY_ENTRY_LIST);
+ zone_require(copy_map, vm_map_copy_zone);
if (copy_map->type != VM_MAP_COPY_ENTRY_LIST) {
/* unsupported type; should not happen */
printf("vm_map_enter_mem_object: "
@@ -6681,7 +6682,7 @@ vm_map_wire_nested(
if ((entry->protection & VM_PROT_EXECUTE)
#if !CONFIG_EMBEDDED
&&
- map != kernel_map &&
+ map->pmap != kernel_pmap &&
cs_process_enforcement(NULL)
#endif /* !CONFIG_EMBEDDED */
) {
@@ -8446,6 +8447,7 @@ vm_map_copy_discard(
switch (copy->type) {
case VM_MAP_COPY_ENTRY_LIST:
+ zone_require(copy, vm_map_copy_zone);
while (vm_map_copy_first_entry(copy) !=
vm_map_copy_to_entry(copy)) {
vm_map_entry_t entry = vm_map_copy_first_entry(copy);
@@ -8460,6 +8462,7 @@ vm_map_copy_discard(
}
break;
case VM_MAP_COPY_OBJECT:
+ zone_require(copy, vm_map_copy_zone);
vm_object_deallocate(copy->cpy_object);
break;
case VM_MAP_COPY_KERNEL_BUFFER:
@@ -8515,6 +8518,7 @@ vm_map_copy_copy(
*new_copy = *copy;
if (copy->type == VM_MAP_COPY_ENTRY_LIST) {
+ zone_require(copy, vm_map_copy_zone);
/*
* The links in the entry chain must be
* changed to point to the new copy object.
@@ -8783,6 +8787,7 @@ vm_map_copy_overwrite_nested(
*/
assert(copy->type == VM_MAP_COPY_ENTRY_LIST);
+ zone_require(copy, vm_map_copy_zone);
if (copy->size == 0) {
if (discard_on_success) {
@@ -9359,6 +9364,7 @@ vm_map_copy_overwrite(
vm_map_t dst_map,
vm_map_offset_t dst_addr,
vm_map_copy_t copy,
+ vm_map_size_t copy_size,
boolean_t interruptible)
{
vm_map_size_t head_size, tail_size;
@@ -9396,7 +9402,7 @@ vm_map_copy_overwrite(
effective_page_mask);
effective_page_size = effective_page_mask + 1;
- if (copy->size < 3 * effective_page_size) {
+ if (copy_size < VM_MAP_COPY_OVERWRITE_OPTIMIZATION_THRESHOLD_PAGES * effective_page_size) {
/*
* Too small to bother with optimizing...
*/
@@ -9420,24 +9426,24 @@ vm_map_copy_overwrite(
head_addr = dst_addr;
head_size = (effective_page_size -
(copy->offset & effective_page_mask));
- head_size = MIN(head_size, copy->size);
+ head_size = MIN(head_size, copy_size);
}
- if (!vm_map_page_aligned(copy->offset + copy->size,
+ if (!vm_map_page_aligned(copy->offset + copy_size,
effective_page_mask)) {
/*
* Mis-alignment at the end.
* Do an aligned copy up to the last page and
* then an unaligned copy for the remaining bytes.
*/
- tail_size = ((copy->offset + copy->size) &
+ tail_size = ((copy->offset + copy_size) &
effective_page_mask);
- tail_size = MIN(tail_size, copy->size);
- tail_addr = dst_addr + copy->size - tail_size;
+ tail_size = MIN(tail_size, copy_size);
+ tail_addr = dst_addr + copy_size - tail_size;
assert(tail_addr >= head_addr + head_size);
}
- assert(head_size + tail_size <= copy->size);
+ assert(head_size + tail_size <= copy_size);
- if (head_size + tail_size == copy->size) {
+ if (head_size + tail_size == copy_size) {
/*
* It's all unaligned, no optimization possible...
*/
@@ -9457,7 +9463,7 @@ vm_map_copy_overwrite(
}
for (;
(entry != vm_map_copy_to_entry(copy) &&
- entry->vme_start < dst_addr + copy->size);
+ entry->vme_start < dst_addr + copy_size);
entry = entry->vme_next) {
if (entry->is_sub_map) {
vm_map_unlock_read(dst_map);
@@ -9490,6 +9496,8 @@ vm_map_copy_overwrite(
head_copy->size = head_size;
copy->offset += head_size;
copy->size -= head_size;
+ copy_size -= head_size;
+ assert(copy_size > 0);
vm_map_copy_clip_end(copy, entry, copy->offset);
vm_map_copy_entry_unlink(copy, entry);
@@ -9521,10 +9529,12 @@ vm_map_copy_overwrite(
copy->cpy_hdr.entries_pageable;
vm_map_store_init(&tail_copy->cpy_hdr);
- tail_copy->offset = copy->offset + copy->size - tail_size;
+ tail_copy->offset = copy->offset + copy_size - tail_size;
tail_copy->size = tail_size;
copy->size -= tail_size;
+ copy_size -= tail_size;
+ assert(copy_size > 0);
entry = vm_map_copy_last_entry(copy);
vm_map_copy_clip_start(copy, entry, tail_copy->offset);
@@ -9535,6 +9545,24 @@ vm_map_copy_overwrite(
entry);
}
+ /*
+ * If we are here from ipc_kmsg_copyout_ool_descriptor(),
+ * we want to avoid TOCTOU issues w.r.t copy->size but
+ * we don't need to change vm_map_copy_overwrite_nested()
+ * and all other vm_map_copy_overwrite variants.
+ *
+ * So we assign the original copy_size that was passed into
+ * this routine back to copy.
+ *
+ * This use of local 'copy_size' passed into this routine is
+ * to try and protect against TOCTOU attacks where the kernel
+ * has been exploited. We don't expect this to be an issue
+ * during normal system operation.
+ */
+ assertf(copy->size == copy_size,
+ "Mismatch of copy sizes. Expected 0x%llx, Got 0x%llx\n", (uint64_t) copy_size, (uint64_t) copy->size);
+ copy->size = copy_size;
+
/*
* Copy most (or possibly all) of the data.
*/
@@ -9559,6 +9587,7 @@ vm_map_copy_overwrite(
done:
assert(copy->type == VM_MAP_COPY_ENTRY_LIST);
+ zone_require(copy, vm_map_copy_zone);
if (kr == KERN_SUCCESS) {
/*
* Discard all the copy maps.
@@ -10539,6 +10568,7 @@ vm_map_copy_validate_size(
vm_map_size_t sz = *size;
switch (copy->type) {
case VM_MAP_COPY_OBJECT:
+ zone_require(copy, vm_map_copy_zone);
case VM_MAP_COPY_KERNEL_BUFFER:
if (sz == copy_sz) {
return TRUE;
@@ -10550,6 +10580,7 @@ vm_map_copy_validate_size(
* validating this flavor of vm_map_copy, but we can at least
* assert that it's within a range.
*/
+ zone_require(copy, vm_map_copy_zone);
if (copy_sz >= sz &&
copy_sz <= vm_map_round_page(sz, VM_MAP_PAGE_MASK(dst_map))) {
*size = copy_sz;
@@ -10649,6 +10680,7 @@ vm_map_copyout_internal(
*/
if (copy->type == VM_MAP_COPY_OBJECT) {
+ zone_require(copy, vm_map_copy_zone);
vm_object_t object = copy->cpy_object;
kern_return_t kr;
vm_object_offset_t offset;
@@ -10688,7 +10720,7 @@ vm_map_copyout_internal(
consume_on_success);
}
-
+ zone_require(copy, vm_map_copy_zone);
/*
* Find space for the data
*/
diff --git a/osfmk/vm/vm_map.h b/osfmk/vm/vm_map.h
index e49170c5d..f56606f8f 100644
--- a/osfmk/vm/vm_map.h
+++ b/osfmk/vm/vm_map.h
@@ -1377,8 +1377,12 @@ extern kern_return_t vm_map_copy_overwrite(
vm_map_t dst_map,
vm_map_address_t dst_addr,
vm_map_copy_t copy,
+ vm_map_size_t copy_size,
boolean_t interruptible);
+#define VM_MAP_COPY_OVERWRITE_OPTIMIZATION_THRESHOLD_PAGES (3)
+
+
/* returns TRUE if size of vm_map_copy == size parameter FALSE otherwise */
extern boolean_t vm_map_copy_validate_size(
vm_map_t dst_map,
diff --git a/osfmk/vm/vm_user.c b/osfmk/vm/vm_user.c
index 027d0c992..2dc0be56b 100644
--- a/osfmk/vm/vm_user.c
+++ b/osfmk/vm/vm_user.c
@@ -800,9 +800,13 @@ mach_vm_read_overwrite(
(vm_map_size_t)size, FALSE, ©);
if (KERN_SUCCESS == error) {
+ if (copy) {
+ assertf(copy->size == (vm_map_size_t) size, "Req size: 0x%llx, Copy size: 0x%llx\n", (uint64_t) size, (uint64_t) copy->size);
+ }
+
error = vm_map_copy_overwrite(current_thread()->map,
(vm_map_address_t)data,
- copy, FALSE);
+ copy, (vm_map_size_t) size, FALSE);
if (KERN_SUCCESS == error) {
*data_size = size;
return error;
@@ -843,9 +847,13 @@ vm_read_overwrite(
(vm_map_size_t)size, FALSE, ©);
if (KERN_SUCCESS == error) {
+ if (copy) {
+ assertf(copy->size == (vm_map_size_t) size, "Req size: 0x%llx, Copy size: 0x%llx\n", (uint64_t) size, (uint64_t) copy->size);
+ }
+
error = vm_map_copy_overwrite(current_thread()->map,
(vm_map_address_t)data,
- copy, FALSE);
+ copy, (vm_map_size_t) size, FALSE);
if (KERN_SUCCESS == error) {
*data_size = size;
return error;
@@ -866,14 +874,14 @@ mach_vm_write(
vm_map_t map,
mach_vm_address_t address,
pointer_t data,
- __unused mach_msg_type_number_t size)
+ mach_msg_type_number_t size)
{
if (map == VM_MAP_NULL) {
return KERN_INVALID_ARGUMENT;
}
return vm_map_copy_overwrite(map, (vm_map_address_t)address,
- (vm_map_copy_t) data, FALSE /* interruptible XXX */);
+ (vm_map_copy_t) data, size, FALSE /* interruptible XXX */);
}
/*
@@ -891,14 +899,14 @@ vm_write(
vm_map_t map,
vm_address_t address,
pointer_t data,
- __unused mach_msg_type_number_t size)
+ mach_msg_type_number_t size)
{
if (map == VM_MAP_NULL) {
return KERN_INVALID_ARGUMENT;
}
return vm_map_copy_overwrite(map, (vm_map_address_t)address,
- (vm_map_copy_t) data, FALSE /* interruptible XXX */);
+ (vm_map_copy_t) data, size, FALSE /* interruptible XXX */);
}
/*
@@ -925,9 +933,13 @@ mach_vm_copy(
(vm_map_size_t)size, FALSE, ©);
if (KERN_SUCCESS == kr) {
+ if (copy) {
+ assertf(copy->size == (vm_map_size_t) size, "Req size: 0x%llx, Copy size: 0x%llx\n", (uint64_t) size, (uint64_t) copy->size);
+ }
+
kr = vm_map_copy_overwrite(map,
(vm_map_address_t)dest_address,
- copy, FALSE /* interruptible XXX */);
+ copy, (vm_map_size_t) size, FALSE /* interruptible XXX */);
if (KERN_SUCCESS != kr) {
vm_map_copy_discard(copy);
@@ -954,9 +966,13 @@ vm_copy(
(vm_map_size_t)size, FALSE, ©);
if (KERN_SUCCESS == kr) {
+ if (copy) {
+ assertf(copy->size == (vm_map_size_t) size, "Req size: 0x%llx, Copy size: 0x%llx\n", (uint64_t) size, (uint64_t) copy->size);
+ }
+
kr = vm_map_copy_overwrite(map,
(vm_map_address_t)dest_address,
- copy, FALSE /* interruptible XXX */);
+ copy, (vm_map_size_t) size, FALSE /* interruptible XXX */);
if (KERN_SUCCESS != kr) {
vm_map_copy_discard(copy);
diff --git a/tests/IP6_EXTHDR_CHECK_61873584.c b/tests/IP6_EXTHDR_CHECK_61873584.c
new file mode 100644
index 000000000..3569cde58
--- /dev/null
+++ b/tests/IP6_EXTHDR_CHECK_61873584.c
@@ -0,0 +1,83 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+struct packet1 {
+ struct ip6_hbh hbh;
+ struct ip6_opt hbh_opt;
+ uint8_t hbh_pad[4];
+ struct ip6_frag frag;
+ struct ip6_dest dest;
+ struct ip6_opt dest_opt;
+ uint8_t dest_pad[4];
+};
+
+struct packet2 {
+ struct ip6_hbh hbh;
+ struct ip6_opt hbh_opt;
+ uint8_t hbh_pad[4];
+ struct ip6_frag frag;
+ struct ip6_opt dest_opt;
+ uint8_t dest_pad[6];
+ uint8_t payload[16];
+};
+
+T_DECL(IP6_EXTHDR_CHECK_ICMPV6_61873584, "ICMPv6 test for IP6_EXTHDR_CHECK stale mbuf pointer vulnerability", T_META("as_root", "true"))
+{
+ struct sockaddr_in6 daddr;
+ struct packet1 packet1;
+ struct packet2 packet2;
+ int s, id, res;
+
+ srand(time(NULL));
+ id = rand();
+
+ T_SETUPBEGIN;
+ T_ASSERT_POSIX_SUCCESS(s = socket(AF_INET6, SOCK_RAW, IPPROTO_HOPOPTS), NULL);
+ T_SETUPEND;
+
+ memset(&daddr, 0, sizeof(daddr));
+ daddr.sin6_family = AF_INET6;
+ daddr.sin6_port = 0;
+ inet_pton(AF_INET6, "::1", &daddr.sin6_addr);
+
+ memset(&packet1, 'A', sizeof(struct packet1));
+ packet1.hbh.ip6h_nxt = IPPROTO_FRAGMENT;
+ packet1.hbh.ip6h_len = 0;
+ packet1.hbh_opt.ip6o_type = IP6OPT_PADN;
+ packet1.hbh_opt.ip6o_len = 4;
+ packet1.frag.ip6f_nxt = IPPROTO_DSTOPTS;
+ packet1.frag.ip6f_reserved = 0;
+ packet1.frag.ip6f_offlg = htons(0) | IP6F_MORE_FRAG;
+ packet1.frag.ip6f_ident = id;
+ // Use IPPROTO_RAW for "assertion failed: m->m_flags & M_PKTHDR" panic
+ // Use IPPROTO_ICMPV6 for "m_free: freeing an already freed mbuf" panic
+ packet1.dest.ip6d_nxt = IPPROTO_RAW;
+ packet1.dest.ip6d_len = 1;
+ packet1.dest_opt.ip6o_type = IP6OPT_PADN;
+ packet1.dest_opt.ip6o_len = 4;
+
+ memset(&packet2, 'B', sizeof(struct packet2));
+ packet2.hbh.ip6h_nxt = IPPROTO_FRAGMENT;
+ packet2.hbh.ip6h_len = 0;
+ packet2.hbh_opt.ip6o_type = IP6OPT_PADN;
+ packet2.hbh_opt.ip6o_len = 4;
+ packet2.frag.ip6f_nxt = IPPROTO_DSTOPTS;
+ packet2.frag.ip6f_reserved = 0;
+ packet2.frag.ip6f_offlg = htons(8);
+ packet2.frag.ip6f_ident = id;
+ packet2.dest_opt.ip6o_type = IP6OPT_PADN;
+ packet2.dest_opt.ip6o_len = 6;
+
+ T_ASSERT_POSIX_SUCCESS(res = sendto(s, (char *)&packet1, sizeof(packet1), 0,
+ (struct sockaddr *)&daddr, (socklen_t)sizeof(daddr)), NULL);
+ T_ASSERT_POSIX_SUCCESS(res = sendto(s, (char *)&packet2, sizeof(packet2), 0,
+ (struct sockaddr *)&daddr, (socklen_t)sizeof(daddr)), NULL);
+ T_ASSERT_POSIX_SUCCESS(res = close(s), NULL);
+}
diff --git a/tests/Makefile b/tests/Makefile
index 790dc11c1..5fef05882 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -277,6 +277,8 @@ task_vm_info_decompressions: INVALID_ARCHS = x86_64 i386
socket_bind_35243417: CODE_SIGN_ENTITLEMENTS = network_entitlements.plist
socket_bind_35685803: CODE_SIGN_ENTITLEMENTS = network_entitlements.plist
+sioc-if-addr-bounds: sioc-if-addr-bounds.c
+
net_tuntests: CODE_SIGN_ENTITLEMENTS = network_entitlements.plist
net_bridge: OTHER_CFLAGS += bpflib.c in_cksum.c
diff --git a/tests/ioc_str.h b/tests/ioc_str.h
new file mode 100644
index 000000000..f1794bf61
--- /dev/null
+++ b/tests/ioc_str.h
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2020 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#ifndef ioc_str_h
+#define ioc_str_h
+
+#include
+#include
+#include
+
+#include
+
+#include
+
+#include
+#include
+
+#define SIOC_LIST \
+ X(SIOCSIFADDR_IN6) \
+ X(SIOCGIFADDR_IN6) \
+ X(SIOCSIFDSTADDR_IN6) \
+ X(SIOCSIFNETMASK_IN6) \
+ X(SIOCGIFDSTADDR_IN6) \
+ X(SIOCGIFNETMASK_IN6) \
+ X(SIOCDIFADDR_IN6) \
+ X(SIOCAIFADDR_IN6) \
+ X(SIOCSIFPHYADDR_IN6) \
+ X(SIOCGIFPSRCADDR_IN6) \
+ X(SIOCGIFPDSTADDR_IN6) \
+ X(SIOCGIFAFLAG_IN6) \
+ X(SIOCGDRLST_IN6) \
+ X(SIOCGPRLST_IN6) \
+ X(SIOCGIFINFO_IN6) \
+ X(SIOCSNDFLUSH_IN6) \
+ X(SIOCGNBRINFO_IN6) \
+ X(SIOCSPFXFLUSH_IN6) \
+ X(SIOCSRTRFLUSH_IN6) \
+ X(SIOCGIFALIFETIME_IN6) \
+ X(SIOCSIFALIFETIME_IN6) \
+ X(SIOCGIFSTAT_IN6) \
+ X(SIOCGIFSTAT_ICMP6) \
+ X(SIOCSDEFIFACE_IN6) \
+ X(SIOCGDEFIFACE_IN6) \
+ X(SIOCSIFINFO_FLAGS) \
+ X(SIOCSSCOPE6) \
+ X(SIOCGSCOPE6) \
+ X(SIOCGSCOPE6DEF) \
+ X(SIOCSIFPREFIX_IN6) \
+ X(SIOCGIFPREFIX_IN6) \
+ X(SIOCDIFPREFIX_IN6) \
+ X(SIOCAIFPREFIX_IN6) \
+ X(SIOCCIFPREFIX_IN6) \
+ X(SIOCSGIFPREFIX_IN6) \
+ X(SIOCAADDRCTL_POLICY) \
+ X(SIOCDADDRCTL_POLICY) \
+ X(SIOCSHIWAT) \
+ X(SIOCGHIWAT) \
+ X(SIOCSLOWAT) \
+ X(SIOCGLOWAT) \
+ X(SIOCATMARK) \
+ X(SIOCSPGRP) \
+ X(SIOCGPGRP) \
+ X(SIOCSIFADDR) \
+ X(SIOCSIFDSTADDR) \
+ X(SIOCSIFFLAGS) \
+ X(SIOCGIFFLAGS) \
+ X(SIOCSIFBRDADDR) \
+ X(SIOCSIFNETMASK) \
+ X(SIOCGIFMETRIC) \
+ X(SIOCSIFMETRIC) \
+ X(SIOCDIFADDR) \
+ X(SIOCAIFADDR) \
+ X(SIOCGIFADDR) \
+ X(SIOCGIFDSTADDR) \
+ X(SIOCGIFBRDADDR) \
+ X(SIOCGIFCONF) \
+ X(SIOCGIFNETMASK) \
+ X(SIOCAUTOADDR) \
+ X(SIOCAUTONETMASK) \
+ X(SIOCARPIPLL) \
+ X(SIOCADDMULTI) \
+ X(SIOCDELMULTI) \
+ X(SIOCGIFMTU) \
+ X(SIOCSIFMTU) \
+ X(SIOCGIFPHYS) \
+ X(SIOCSIFPHYS) \
+ X(SIOCSIFMEDIA) \
+ X(SIOCGIFMEDIA) \
+ X(SIOCSIFGENERIC) \
+ X(SIOCGIFGENERIC) \
+ X(SIOCRSLVMULTI) \
+ X(SIOCSIFLLADDR) \
+ X(SIOCGIFSTATUS) \
+ X(SIOCSIFPHYADDR) \
+ X(SIOCGIFPSRCADDR) \
+ X(SIOCGIFPDSTADDR) \
+ X(SIOCDIFPHYADDR) \
+ X(SIOCGIFDEVMTU) \
+ X(SIOCSIFALTMTU) \
+ X(SIOCGIFALTMTU) \
+ X(SIOCSIFBOND) \
+ X(SIOCGIFBOND) \
+ X(SIOCGIFXMEDIA) \
+ X(SIOCSIFCAP) \
+ X(SIOCGIFCAP) \
+ X(SIOCIFCREATE) \
+ X(SIOCIFDESTROY) \
+ X(SIOCIFCREATE2) \
+ X(SIOCSDRVSPEC) \
+ X(SIOCGDRVSPEC) \
+ X(SIOCSIFVLAN) \
+ X(SIOCGIFVLAN) \
+ X(SIOCIFGCLONERS) \
+ X(SIOCGIFASYNCMAP) \
+ X(SIOCSIFASYNCMAP) \
+ X(SIOCGIFMAC) \
+ X(SIOCSIFMAC) \
+ X(SIOCSIFKPI) \
+ X(SIOCGIFKPI) \
+ X(SIOCGIFWAKEFLAGS) \
+ X(SIOCGIFFUNCTIONALTYPE) \
+ X(SIOCSIF6LOWPAN) \
+ X(SIOCGIF6LOWPAN) \
+ X(SIOCGKEVID) \
+ X(SIOCSKEVFILT) \
+ X(SIOCGKEVFILT) \
+ X(SIOCGKEVVENDOR)
+
+#endif /* ioc_str_h */
diff --git a/tests/macho_size_63133398.c b/tests/macho_size_63133398.c
new file mode 100644
index 000000000..7266fb0cf
--- /dev/null
+++ b/tests/macho_size_63133398.c
@@ -0,0 +1,3223 @@
+/*
+ * rdar://63133398 (XNU: load_machfile improperly validates macho_size)
+ *
+ * Chris J-D
+ * SEAR Red Team / 2020-May-18
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#define ADJUSTMENT_SIZE (1337 * PAGE_SIZE)
+
+/*
+ * The hexdumps below are for a minimal Mach-O:
+ *
+ * int main(int argc, char *argv[]) { return 0; }
+ *
+ * We need a well-formed Mach-O to wrap inside a malicious fat binary. The
+ * steps required to make the malicious fat binary are included programmatically
+ * to make it clear what we're testing for (slice size should take into account
+ * the file offset). See the line labelled "<-- bug".
+ */
+#if __x86_64__
+static const unsigned char macho[] = {
+ 0xcf, 0xfa, 0xed, 0xfe, 0x07, 0x00, 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xe8, 0x02, 0x00, 0x00,
+ 0x85, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x5a, 0x45,
+ 0x52, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
+ 0xe8, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x74, 0x65,
+ 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xb0, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x0f, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x75, 0x6e, 0x77, 0x69, 0x6e, 0x64,
+ 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x54, 0x45,
+ 0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xb8, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xb8, 0x0f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x19, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x4c, 0x49,
+ 0x4e, 0x4b, 0x45, 0x44, 0x49, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x22, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x38, 0x10, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x68, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x2f, 0x75, 0x73, 0x72,
+ 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x64, 0x79, 0x6c, 0x64, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0xa3, 0xc0, 0xb5, 0x19, 0x06, 0x4a, 0x31, 0xb0, 0xa9, 0x65, 0x0f, 0xd5,
+ 0x2f, 0xf4, 0x7e, 0x1b, 0x32, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0a, 0x00, 0x00, 0x10, 0x0a, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x58, 0x02,
+ 0x2a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x80, 0x18, 0x00, 0x00, 0x00,
+ 0xb0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05,
+ 0x00, 0x00, 0x01, 0x00, 0x2f, 0x75, 0x73, 0x72, 0x2f, 0x6c, 0x69, 0x62,
+ 0x2f, 0x6c, 0x69, 0x62, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x42,
+ 0x2e, 0x64, 0x79, 0x6c, 0x69, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x26, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x48, 0x89, 0xe5,
+ 0x31, 0xc0, 0x5d, 0xc3, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xb0, 0x0f, 0x00, 0x00,
+ 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xb9, 0x0f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x0c, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x5f, 0x00, 0x05, 0x00, 0x02, 0x5f,
+ 0x6d, 0x68, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x5f, 0x68,
+ 0x65, 0x61, 0x64, 0x65, 0x72, 0x00, 0x21, 0x6d, 0x61, 0x69, 0x6e, 0x00,
+ 0x25, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0xb0, 0x1f, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xb0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0f, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x0f, 0x01, 0x00, 0x00,
+ 0xb0, 0x0f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x5f, 0x5f, 0x6d, 0x68, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75,
+ 0x74, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x00, 0x5f, 0x6d,
+ 0x61, 0x69, 0x6e, 0x00, 0x64, 0x79, 0x6c, 0x64, 0x5f, 0x73, 0x74, 0x75,
+ 0x62, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x00, 0x00, 0x00, 0x00
+};
+static const size_t macho_size = 4248;
+#elif __arm64__
+static const unsigned char macho[] = {
+ 0xcf, 0xfa, 0xed, 0xfe, 0x0c, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00,
+ 0x85, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
+ 0x48, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x5a, 0x45,
+ 0x52, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00,
+ 0xe8, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x74, 0x65,
+ 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x5f, 0x5f, 0x54, 0x45, 0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xb0, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x7f, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x75, 0x6e, 0x77, 0x69, 0x6e, 0x64,
+ 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x54, 0x45,
+ 0x58, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xb8, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xb8, 0x7f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x19, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x5f, 0x5f, 0x4c, 0x49,
+ 0x4e, 0x4b, 0x45, 0x44, 0x49, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x22, 0x00, 0x00, 0x80, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x38, 0x80, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x68, 0x80, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+ 0x0b, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x2f, 0x75, 0x73, 0x72,
+ 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x64, 0x79, 0x6c, 0x64, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x24, 0xa7, 0x74, 0x0c, 0x30, 0x84, 0x32, 0x71, 0xa3, 0xb2, 0x38, 0xab,
+ 0xd5, 0x63, 0x33, 0x71, 0x32, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x5b, 0x02,
+ 0x2a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x80, 0x18, 0x00, 0x00, 0x00,
+ 0xb0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x05,
+ 0x00, 0x00, 0x01, 0x00, 0x2f, 0x75, 0x73, 0x72, 0x2f, 0x6c, 0x69, 0x62,
+ 0x2f, 0x6c, 0x69, 0x62, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x42,
+ 0x2e, 0x64, 0x79, 0x6c, 0x69, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x26, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x80, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+ 0x38, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x52, 0xc0, 0x03, 0x5f, 0xd6, 0x01, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0xb0, 0x7f, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0xb9, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x10, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x5f, 0x00,
+ 0x05, 0x00, 0x02, 0x5f, 0x6d, 0x68, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75,
+ 0x74, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x00, 0x21, 0x6d,
+ 0x61, 0x69, 0x6e, 0x00, 0x25, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0xb0,
+ 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xff, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x01, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+ 0x0f, 0x01, 0x00, 0x00, 0xb0, 0x7f, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x5f, 0x5f, 0x6d, 0x68, 0x5f, 0x65,
+ 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x65,
+ 0x72, 0x00, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x64, 0x79, 0x6c, 0x64,
+ 0x5f, 0x73, 0x74, 0x75, 0x62, 0x5f, 0x62, 0x69, 0x6e, 0x64, 0x65, 0x72,
+ 0x00, 0x00, 0x00, 0x00
+};
+static const size_t macho_size = 32920;
+#endif
+
+#if defined(__x86_64__) || defined(__arm64__)
+static char bin_path[128];
+
+static void
+cleanup_bin(void)
+{
+ unlink(bin_path);
+ bin_path[0] = '\0';
+}
+#endif
+
+T_DECL(macho_size_63133398, "load_machfile improperly validates macho_size")
+{
+#if defined(__x86_64__) || defined(__arm64__)
+ char * const av[] = { bin_path, NULL };
+ char * const ev[] = { NULL };
+ int fd;
+ void *dst_buf;
+ struct fat_header *fat_header;
+ struct fat_arch *fat_arch;
+ struct mach_header *mach_header;
+ const size_t dst_size = macho_size + ADJUSTMENT_SIZE;
+ pid_t child;
+ int status = 0;
+
+ T_SETUPBEGIN;
+
+ /* prepare the temp file: */
+ strcpy(bin_path, "/tmp/macho_size.XXXXXX");
+ T_ASSERT_POSIX_SUCCESS(fd = mkstemp(bin_path), NULL);
+ atexit(cleanup_bin);
+
+ /* size accordingly and map it in: */
+ T_ASSERT_POSIX_SUCCESS(ftruncate(fd, (off_t)dst_size), NULL);
+
+ dst_buf = mmap(NULL, (dst_size + PAGE_SIZE - 1) & ~PAGE_MASK, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 0);
+ T_ASSERT_NE(MAP_FAILED, dst_buf, NULL);
+
+ /* put the mach-o in: */
+ mach_header = (struct mach_header *)(void *)((char *)dst_buf + ADJUSTMENT_SIZE);
+ memcpy(mach_header, macho, macho_size);
+
+ /* fat binary with a single entry matching our mach-o: */
+ fat_header = (struct fat_header *)(void *)dst_buf;
+ fat_header->magic = htonl(FAT_MAGIC);
+ fat_header->nfat_arch = htonl(1);
+
+ fat_arch = (struct fat_arch *)(fat_header + 1);
+ fat_arch->cputype = (cpu_type_t)htonl(mach_header->cputype);
+ fat_arch->cpusubtype = (cpu_subtype_t)htonl(mach_header->cpusubtype);
+ fat_arch->offset = htonl(ADJUSTMENT_SIZE);
+ fat_arch->size = htonl(dst_size); /* <-- bug */
+
+ /* make it executable: */
+ T_ASSERT_POSIX_SUCCESS(fchmod(fd, 0755), NULL);
+
+ /* clear up anything we don't need: */
+ T_ASSERT_POSIX_SUCCESS(close(fd), NULL);
+ T_ASSERT_POSIX_SUCCESS(munmap(dst_buf, (dst_size + PAGE_SIZE - 1) & ~PAGE_MASK), NULL);
+
+ T_SETUPEND;
+
+ /* and let's give it a try: */
+ T_ASSERT_NE(-1, child = fork(), NULL);
+ if (0 == child) {
+ execve(av[0], av, ev);
+ T_ASSERT_FAIL("execve failed");
+ }
+
+ T_ASSERT_POSIX_SUCCESS(waitpid(child, &status, 0), NULL);
+ T_ASSERT_EQ(SIGKILL, status, NULL);
+#else
+ T_PASS("Architecture not supported by this test; passing.");
+#endif
+}
diff --git a/tests/pfkey.c b/tests/pfkey.c
new file mode 100644
index 000000000..cebd5a74b
--- /dev/null
+++ b/tests/pfkey.c
@@ -0,0 +1,1778 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+T_GLOBAL_META(
+ T_META_NAMESPACE("xnu.pfkey"),
+ T_META_ASROOT(true),
+ T_META_CHECK_LEAKS(false));
+
+#define MAX_SPD_CHECK 100
+#define TEST_SRC_ADDRESS_IPv4 "192.168.2.2"
+#define TEST_DST_ADDRESS_IPv4 "192.168.2.3"
+#define TEST_SRC_ADDRESS_IPv6 "fd04:5c6b:8df7:7092:0000:0000:0000:0002"
+#define TEST_DST_ADDRESS_IPv6 "fd04:5c6b:8df7:7092:0000:0000:0000:0003"
+#define TEST_MIGRATE_SRC_ADDRESS_IPv4 "192.168.2.10"
+#define TEST_MIGRATE_DST_ADDRESS_IPv4 "192.168.2.11"
+#define TEST_MIGRATE_SRC_ADDRESS_IPv6 "fd04:5c6b:8df7:7092:0000:0000:0002:0000"
+#define TEST_MIGRATE_DST_ADDRESS_IPv6 "fd04:5c6b:8df7:7092:0000:0000:0003:0000"
+
+typedef enum {
+ TEST_INVALID = 0,
+ TEST_SADB_X_GET_OVERFLOW_60822136 = 1,
+ TEST_SADB_X_SPDENABLE_OVERFLOW_60822924 = 2,
+ TEST_SADB_X_SPDDISABLE_OVERFLOW_60822956 = 3,
+ TEST_SADB_UPDATE_USE_AFTER_FREE_60679513 = 4,
+ TEST_SADB_DUMP_HEAP_OVERFLOW_60768729 = 5,
+ TEST_SADB_POLICY_DUMP_HEAP_OVERFLOW_60769680 = 6,
+ TEST_SADB_GETSASTAT_OOB_READ_60822823 = 7,
+ TEST_SADB_GETSASTAT_OOB_READ_SUCCESS = 8,
+ TEST_SADB_EXT_MIGRATE_ADDRESS_IPv4 = 9,
+ TEST_SADB_EXT_MIGRATE_ADDRESS_IPv6 = 10,
+ TEST_SADB_EXT_MIGRATE_BAD_ADDRESS = 11,
+} test_identifier;
+
+static test_identifier test_id = TEST_INVALID;
+static dispatch_source_t pfkey_source = NULL;
+
+static void pfkey_cleanup(void);
+
+static void pfkey_process_message_test_60822136(uint8_t **mhp, int pfkey_socket);
+static void pfkey_process_message_test_60822924(uint8_t **mhp, int pfkey_socket);
+static void pfkey_process_message_test_60822956(uint8_t **mhp, int pfkey_socket);
+static void pfkey_process_message_test_60679513(uint8_t **mhp, int pfkey_socket);
+static void pfkey_process_message_test_60768729(uint8_t **mhp, int pfkey_socket);
+static void pfkey_process_message_test_60769680(uint8_t **mhp, int pfkey_socket);
+static void pfkey_process_message_test_60822823(uint8_t **mhp, int pfkey_socket);
+static void pfkey_process_message_test_60822823_1(uint8_t **mhp, int pfkey_socket);
+static void pfkey_process_message_test_60687183(uint8_t **mhp, int pfkey_socket);
+static void pfkey_process_message_test_60687183_1(uint8_t **mhp, int pfkey_socket);
+static void pfkey_process_message_test_60687183_2(uint8_t **mhp, int pfkey_socket);
+
+static void(*const process_pfkey_message_tests[])(uint8_t * *mhp, int pfkey_socket) =
+{
+ NULL,
+ pfkey_process_message_test_60822136, // TEST_SADB_X_GET_OVERFLOW_60822136
+ pfkey_process_message_test_60822924, // TEST_SADB_X_SPDENABLE_OVERFLOW_60822924
+ pfkey_process_message_test_60822956, // TEST_SADB_X_SPDDISABLE_OVERFLOW_60822956
+ pfkey_process_message_test_60679513, // TEST_SADB_UPDATE_USE_AFTER_FREE_60679513
+ pfkey_process_message_test_60768729, // TEST_SADB_DUMP_HEAP_OVERFLOW_60768729
+ pfkey_process_message_test_60769680, // TEST_SADB_POLICY_DUMP_HEAP_OVERFLOW_60769680
+ pfkey_process_message_test_60822823, // TEST_SADB_GETSASTAT_OOB_READ_60822823
+ pfkey_process_message_test_60822823_1, // TEST_SADB_GETSASTAT_OOB_READ_SUCCESS
+ pfkey_process_message_test_60687183, // TEST_SADB_EXT_MIGRATE_ADDRESS_IPv4
+ pfkey_process_message_test_60687183_1, // TEST_SADB_EXT_MIGRATE_ADDRESS_IPv6
+ pfkey_process_message_test_60687183_2, // TEST_SADB_EXT_MIGRATE_BAD_ADDRESS
+};
+
+static void
+pfkey_align(struct sadb_msg *msg, uint8_t **mhp)
+{
+ struct sadb_ext *ext;
+ int i;
+ uint8_t *p;
+ uint8_t *ep; /* XXX should be passed from upper layer */
+
+ /* validity check */
+ T_QUIET; T_ASSERT_NOTNULL(msg, "pfkey align msg");
+ T_QUIET; T_ASSERT_NOTNULL(mhp, "pfkey align mhp");
+
+ /* initialize */
+ for (i = 0; i < SADB_EXT_MAX + 1; i++) {
+ mhp[i] = NULL;
+ }
+
+ mhp[0] = (void *)msg;
+
+ /* initialize */
+ p = (void *) msg;
+ ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len);
+
+ /* skip base header */
+ p += sizeof(struct sadb_msg);
+
+ while (p < ep) {
+ ext = (void *)p;
+ T_QUIET; T_ASSERT_GE_PTR((void *)ep, (void *)(p + sizeof(*ext)), "pfkey extension header beyond end of buffer");
+ T_QUIET; T_ASSERT_GE_ULONG((unsigned long)PFKEY_EXTLEN(ext), sizeof(*ext), "pfkey extension shorter than extension header");
+ T_QUIET; T_ASSERT_GE_PTR((void *)ep, (void *)(p + PFKEY_EXTLEN(ext)), "pfkey extension length beyond end of buffer");
+
+ T_QUIET; T_EXPECT_NULL(mhp[ext->sadb_ext_type], "duplicate extension type %u payload", ext->sadb_ext_type);
+
+ /* set pointer */
+ switch (ext->sadb_ext_type) {
+ case SADB_EXT_SA:
+ case SADB_EXT_LIFETIME_CURRENT:
+ case SADB_EXT_LIFETIME_HARD:
+ case SADB_EXT_LIFETIME_SOFT:
+ case SADB_EXT_ADDRESS_SRC:
+ case SADB_EXT_ADDRESS_DST:
+ case SADB_EXT_ADDRESS_PROXY:
+ case SADB_EXT_KEY_AUTH:
+ /* XXX should to be check weak keys. */
+ case SADB_EXT_KEY_ENCRYPT:
+ /* XXX should to be check weak keys. */
+ case SADB_EXT_IDENTITY_SRC:
+ case SADB_EXT_IDENTITY_DST:
+ case SADB_EXT_SENSITIVITY:
+ case SADB_EXT_PROPOSAL:
+ case SADB_EXT_SUPPORTED_AUTH:
+ case SADB_EXT_SUPPORTED_ENCRYPT:
+ case SADB_EXT_SPIRANGE:
+ case SADB_X_EXT_POLICY:
+ case SADB_X_EXT_SA2:
+ case SADB_EXT_SESSION_ID:
+ case SADB_EXT_SASTAT:
+#ifdef SADB_X_EXT_NAT_T_TYPE
+ case SADB_X_EXT_NAT_T_TYPE:
+ case SADB_X_EXT_NAT_T_SPORT:
+ case SADB_X_EXT_NAT_T_DPORT:
+ case SADB_X_EXT_NAT_T_OA:
+#endif
+#ifdef SADB_X_EXT_TAG
+ case SADB_X_EXT_TAG:
+#endif
+#ifdef SADB_X_EXT_PACKET
+ case SADB_X_EXT_PACKET:
+#endif
+ case SADB_X_EXT_IPSECIF:
+ case SADB_X_EXT_ADDR_RANGE_SRC_START:
+ case SADB_X_EXT_ADDR_RANGE_SRC_END:
+ case SADB_X_EXT_ADDR_RANGE_DST_START:
+ case SADB_X_EXT_ADDR_RANGE_DST_END:
+#ifdef SADB_MIGRATE
+ case SADB_EXT_MIGRATE_ADDRESS_SRC:
+ case SADB_EXT_MIGRATE_ADDRESS_DST:
+ case SADB_X_EXT_MIGRATE_IPSECIF:
+#endif
+ mhp[ext->sadb_ext_type] = (void *)ext;
+ break;
+ default:
+ T_FAIL("bad extension type %u", ext->sadb_ext_type);
+ T_END;
+ }
+
+ p += PFKEY_EXTLEN(ext);
+ }
+
+ T_QUIET; T_EXPECT_EQ_PTR((void *)ep, (void *)p, "invalid pfkey message length");
+ return;
+}
+
+
+static void
+recv_pfkey_message(int pfkey_socket)
+{
+ uint8_t buffer[8192] __attribute__((aligned(4)));
+ struct iovec iovecs[1] = {
+ { buffer, sizeof(buffer) },
+ };
+ struct msghdr msg = {
+ NULL,
+ 0,
+ iovecs,
+ sizeof(iovecs) / sizeof(iovecs[0]),
+ NULL,
+ 0,
+ 0,
+ };
+
+ do {
+ ssize_t result = -1;
+ memset(buffer, 0, sizeof(buffer));
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(result = recvmsg(pfkey_socket, &msg, 0), NULL);
+
+ if (result > 0) {
+ T_QUIET; T_ASSERT_GE_ULONG((size_t)result, sizeof(struct sadb_msg), "Invalid PFKey message size: %zu", result);
+ struct sadb_msg *hdr = (struct sadb_msg *)buffer;
+ uint8_t *mhp[SADB_EXT_MAX + 1];
+ pfkey_align(hdr, mhp);
+ (*process_pfkey_message_tests[test_id])(mhp, pfkey_socket);
+ } else if (result == 0) {
+ T_LOG("PFKey socket received EOF");
+ break;
+ }
+ } while (1);
+}
+
+static void
+send_pfkey_spd_add_message(int pfkey_socket, uint8_t proto)
+{
+ uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
+ bzero(payload, sizeof(payload));
+ uint16_t tlen = 0;
+
+ struct sadb_msg *msg_payload = (struct sadb_msg *)payload;
+ msg_payload->sadb_msg_version = PF_KEY_V2;
+ msg_payload->sadb_msg_type = SADB_X_SPDADD;
+ msg_payload->sadb_msg_errno = 0;
+ msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC;
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ msg_payload->sadb_msg_reserved = 0;
+ msg_payload->sadb_msg_seq = 0;
+ msg_payload->sadb_msg_pid = (u_int32_t)getpid();
+ tlen += sizeof(*msg_payload);
+
+ struct sadb_address *src_address_payload = (struct sadb_address *)(void *)(payload + tlen);
+ src_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_SRC & 0xffff;
+ src_address_payload->sadb_address_proto = proto & 0xff;
+ src_address_payload->sadb_address_prefixlen = (sizeof(struct in_addr) << 3);
+ src_address_payload->sadb_address_reserved = 0;
+ tlen += sizeof(*src_address_payload);
+
+ struct sockaddr_in *src = (struct sockaddr_in *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, TEST_SRC_ADDRESS_IPv4, &src->sin_addr), 1, "src address fail");
+ src->sin_family = AF_INET;
+ src->sin_len = sizeof(*src);
+ uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src->sin_len);
+ src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(src->sin_len);
+
+ struct sadb_address *dst_address_payload = (struct sadb_address *)(void *)(payload + tlen);
+ dst_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_DST & 0xffff;
+ dst_address_payload->sadb_address_proto = proto & 0xff;
+ dst_address_payload->sadb_address_prefixlen = (sizeof(struct in_addr) << 3);
+ dst_address_payload->sadb_address_reserved = 0;
+ tlen += sizeof(*dst_address_payload);
+
+ struct sockaddr_in *dst = (struct sockaddr_in *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, TEST_DST_ADDRESS_IPv4, &dst->sin_addr), 1, "dst address fail");
+ dst->sin_family = AF_INET;
+ dst->sin_len = sizeof(*dst);
+ len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst->sin_len);
+ dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(dst->sin_len);
+
+ struct sadb_lifetime *lifetime_payload = (struct sadb_lifetime *)(void *)(payload + tlen);
+ lifetime_payload->sadb_lifetime_len = PFKEY_UNIT64(sizeof(*lifetime_payload));
+ lifetime_payload->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
+ tlen += sizeof(*lifetime_payload);
+
+ struct sadb_x_policy *policy_payload = (struct sadb_x_policy *)(void *)(payload + tlen);
+ policy_payload->sadb_x_policy_len = PFKEY_UNIT64(sizeof(*policy_payload));
+ policy_payload->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ policy_payload->sadb_x_policy_type = IPSEC_POLICY_DISCARD;
+ policy_payload->sadb_x_policy_dir = IPSEC_DIR_OUTBOUND;
+ tlen += sizeof(*policy_payload);
+
+ // Update the total length
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send spd add");
+}
+
+static void
+send_pfkey_spd_get_message(int pfkey_socket, uint32_t policy_id)
+{
+ uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
+ bzero(payload, sizeof(payload));
+ uint16_t tlen = 0;
+
+ struct sadb_msg *msg_payload = (struct sadb_msg *)(void *)payload;
+ msg_payload->sadb_msg_version = PF_KEY_V2;
+ msg_payload->sadb_msg_type = SADB_X_SPDGET;
+ msg_payload->sadb_msg_errno = 0;
+ msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC;
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ msg_payload->sadb_msg_reserved = 0;
+ msg_payload->sadb_msg_seq = 0;
+ msg_payload->sadb_msg_pid = (uint32_t)getpid();
+ tlen += sizeof(*msg_payload);
+
+ struct sadb_x_policy *policy_payload = (struct sadb_x_policy *)(void *)(payload + tlen);
+ policy_payload->sadb_x_policy_len = PFKEY_UNIT64(sizeof(*policy_payload));
+ policy_payload->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ policy_payload->sadb_x_policy_id = policy_id;
+ tlen += sizeof(*policy_payload);
+
+ // Update the total length
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send spd get failed");
+}
+
+static void
+send_pfkey_spd_enable_message(int pfkey_socket, uint32_t policy_id)
+{
+ uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
+ bzero(payload, sizeof(payload));
+ uint16_t tlen = 0;
+
+ struct sadb_msg *msg_payload = (struct sadb_msg *)(void *)payload;
+ msg_payload->sadb_msg_version = PF_KEY_V2;
+ msg_payload->sadb_msg_type = SADB_X_SPDENABLE;
+ msg_payload->sadb_msg_errno = 0;
+ msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC;
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ msg_payload->sadb_msg_reserved = 0;
+ msg_payload->sadb_msg_seq = 0;
+ msg_payload->sadb_msg_pid = (uint32_t)getpid();
+ tlen += sizeof(*msg_payload);
+
+ struct sadb_x_policy *policy_payload = (struct sadb_x_policy *)(void *)(payload + tlen);
+ policy_payload->sadb_x_policy_len = PFKEY_UNIT64(sizeof(*policy_payload));
+ policy_payload->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ policy_payload->sadb_x_policy_id = policy_id;
+ tlen += sizeof(*policy_payload);
+
+ // Update the total length
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send spd enable failed");
+}
+
+static void
+send_pfkey_spd_disable_message(int pfkey_socket, uint32_t policy_id)
+{
+ uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
+ bzero(payload, sizeof(payload));
+ uint16_t tlen = 0;
+
+ struct sadb_msg *msg_payload = (struct sadb_msg *)(void *)payload;
+ msg_payload->sadb_msg_version = PF_KEY_V2;
+ msg_payload->sadb_msg_type = SADB_X_SPDDISABLE;
+ msg_payload->sadb_msg_errno = 0;
+ msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC;
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ msg_payload->sadb_msg_reserved = 0;
+ msg_payload->sadb_msg_seq = 0;
+ msg_payload->sadb_msg_pid = (uint32_t)getpid();
+ tlen += sizeof(*msg_payload);
+
+ struct sadb_x_policy *policy_payload = (struct sadb_x_policy *)(void *)(payload + tlen);
+ policy_payload->sadb_x_policy_len = PFKEY_UNIT64(sizeof(*policy_payload));
+ policy_payload->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ policy_payload->sadb_x_policy_id = policy_id;
+ tlen += sizeof(*policy_payload);
+
+ // Update the total length
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send spd disable failed");
+}
+
+static void
+send_pfkey_spd_delete_message(int pfkey_socket, uint32_t policy_id)
+{
+ uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
+ bzero(payload, sizeof(payload));
+ uint16_t tlen = 0;
+
+ struct sadb_msg *msg_payload = (struct sadb_msg *)payload;
+ msg_payload->sadb_msg_version = PF_KEY_V2;
+ msg_payload->sadb_msg_type = SADB_X_SPDDELETE2;
+ msg_payload->sadb_msg_errno = 0;
+ msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC;
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ msg_payload->sadb_msg_reserved = 0;
+ msg_payload->sadb_msg_seq = 0;
+ msg_payload->sadb_msg_pid = (uint32_t)getpid();
+ tlen += sizeof(*msg_payload);
+
+ struct sadb_x_policy *policy_payload = (struct sadb_x_policy *)(void *)(payload + tlen);
+ policy_payload->sadb_x_policy_len = PFKEY_UNIT64(sizeof(*policy_payload));
+ policy_payload->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ policy_payload->sadb_x_policy_id = policy_id;
+ tlen += sizeof(*policy_payload);
+
+ // Update the total length
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send spd delete failed");
+}
+
+static void
+send_pfkey_spd_dump_message(int pfkey_socket)
+{
+ uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
+ bzero(payload, sizeof(payload));
+ uint16_t tlen = 0;
+
+ struct sadb_msg *msg_payload = (struct sadb_msg *)(void *)payload;
+ msg_payload->sadb_msg_version = PF_KEY_V2;
+ msg_payload->sadb_msg_type = SADB_X_SPDDUMP;
+ msg_payload->sadb_msg_errno = 0;
+ msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC;
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ msg_payload->sadb_msg_reserved = 0;
+ msg_payload->sadb_msg_seq = 0;
+ msg_payload->sadb_msg_pid = (uint32_t)getpid();
+ tlen += sizeof(*msg_payload);
+
+ // Update the total length
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send spd dump failed");
+}
+
+static void
+send_pfkey_flush_sp(int pfkey_socket)
+{
+ uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
+ bzero(payload, sizeof(payload));
+ uint16_t tlen = 0;
+
+ struct sadb_msg *msg_payload = (struct sadb_msg *)payload;
+ msg_payload->sadb_msg_version = PF_KEY_V2;
+ msg_payload->sadb_msg_type = SADB_X_SPDFLUSH;
+ msg_payload->sadb_msg_errno = 0;
+ msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC;
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ msg_payload->sadb_msg_reserved = 0;
+ msg_payload->sadb_msg_seq = 0;
+ msg_payload->sadb_msg_pid = (u_int32_t)getpid();
+ tlen += sizeof(*msg_payload);
+
+ // Update the total length
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey flush security policies");
+}
+
+static void
+send_pkey_get_spi(int pfkey_socket)
+{
+ uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
+ bzero(payload, sizeof(payload));
+ uint16_t tlen = 0;
+
+ struct sadb_msg *msg_payload = (struct sadb_msg *)payload;
+ msg_payload->sadb_msg_version = PF_KEY_V2;
+ msg_payload->sadb_msg_type = SADB_GETSPI;
+ msg_payload->sadb_msg_errno = 0;
+ msg_payload->sadb_msg_satype = SADB_SATYPE_ESP;
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ msg_payload->sadb_msg_reserved = 0;
+ msg_payload->sadb_msg_seq = 0;
+ msg_payload->sadb_msg_pid = (u_int32_t)getpid();
+ tlen += sizeof(*msg_payload);
+
+ struct sadb_x_sa2 *sa2_payload = (struct sadb_x_sa2 *)(void *)(payload + tlen);
+ sa2_payload->sadb_x_sa2_len = PFKEY_UNIT64(sizeof(*sa2_payload));
+ sa2_payload->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
+ sa2_payload->sadb_x_sa2_mode = IPSEC_MODE_TRANSPORT;
+ sa2_payload->sadb_x_sa2_reqid = 0;
+ tlen += sizeof(*sa2_payload);
+
+ struct sadb_address *src_address_payload = (struct sadb_address *)(void *)(payload + tlen);
+ src_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_SRC & 0xffff;
+ src_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
+ src_address_payload->sadb_address_prefixlen = (sizeof(struct in_addr) << 3);
+ src_address_payload->sadb_address_reserved = 0;
+ tlen += sizeof(*src_address_payload);
+
+ struct sockaddr_in *src = (struct sockaddr_in *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, TEST_SRC_ADDRESS_IPv4, &src->sin_addr), 1, "src address fail");
+ src->sin_family = AF_INET;
+ src->sin_len = sizeof(*src);
+ uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src->sin_len);
+ src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(src->sin_len);
+
+ struct sadb_address *dst_address_payload = (struct sadb_address *)(void *)(payload + tlen);
+ dst_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_DST & 0xffff;
+ dst_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
+ dst_address_payload->sadb_address_prefixlen = (sizeof(struct in_addr) << 3);
+ dst_address_payload->sadb_address_reserved = 0;
+ tlen += sizeof(*dst_address_payload);
+
+ struct sockaddr_in *dst = (struct sockaddr_in *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, TEST_DST_ADDRESS_IPv4, &dst->sin_addr), 1, "dst address fail");
+ dst->sin_family = AF_INET;
+ dst->sin_len = sizeof(*dst);
+ len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst->sin_len);
+ dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(dst->sin_len);
+
+ // Update the total length
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send get spi");
+}
+
+static void
+send_pkey_add_sa(int pfkey_socket, uint32_t spi, const char *src, const char *dst, int family)
+{
+ uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
+ bzero(payload, sizeof(payload));
+ uint16_t tlen = 0;
+
+ struct sadb_msg *msg_payload = (struct sadb_msg *)payload;
+ msg_payload->sadb_msg_version = PF_KEY_V2;
+ msg_payload->sadb_msg_type = SADB_ADD;
+ msg_payload->sadb_msg_errno = 0;
+ msg_payload->sadb_msg_satype = SADB_SATYPE_ESP;
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ msg_payload->sadb_msg_reserved = 0;
+ msg_payload->sadb_msg_seq = 0;
+ msg_payload->sadb_msg_pid = (u_int32_t)getpid();
+ tlen += sizeof(*msg_payload);
+
+ struct sadb_sa_2 *sa2_payload = (struct sadb_sa_2 *)(void *)(payload + tlen);
+ sa2_payload->sa.sadb_sa_len = PFKEY_UNIT64(sizeof(*sa2_payload));
+ sa2_payload->sa.sadb_sa_exttype = SADB_EXT_SA;
+ sa2_payload->sa.sadb_sa_spi = htonl(spi);
+ sa2_payload->sa.sadb_sa_replay = 4;
+ sa2_payload->sa.sadb_sa_state = SADB_SASTATE_LARVAL;
+ sa2_payload->sa.sadb_sa_auth = SADB_X_AALG_SHA2_256;
+ sa2_payload->sa.sadb_sa_encrypt = SADB_X_EALG_AESCBC;
+ sa2_payload->sa.sadb_sa_flags |= (SADB_X_EXT_NATT | SADB_X_EXT_NATT_KEEPALIVE);
+ sa2_payload->sadb_sa_natt_src_port = htons(4500);
+ sa2_payload->sadb_sa_natt_port = 4500;
+ sa2_payload->sadb_sa_natt_interval = 20;
+ sa2_payload->sadb_sa_natt_offload_interval = 0;
+ tlen += sizeof(*sa2_payload);
+
+ struct sadb_x_sa2 *sa2_x_payload = (struct sadb_x_sa2 *)(void *)(payload + tlen);
+ sa2_x_payload->sadb_x_sa2_len = PFKEY_UNIT64(sizeof(*sa2_x_payload));
+ sa2_x_payload->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
+ sa2_x_payload->sadb_x_sa2_mode = IPSEC_MODE_TRANSPORT;
+ sa2_x_payload->sadb_x_sa2_reqid = 0;
+ tlen += sizeof(*sa2_x_payload);
+
+ uint8_t prefixlen = (family == AF_INET) ? (sizeof(struct in_addr) << 3) : (sizeof(struct in6_addr) << 3);
+
+ struct sadb_address *src_address_payload = (struct sadb_address *)(void *)(payload + tlen);
+ src_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_SRC & 0xffff;
+ src_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
+ src_address_payload->sadb_address_prefixlen = prefixlen;
+ src_address_payload->sadb_address_reserved = 0;
+ tlen += sizeof(*src_address_payload);
+
+ if (family == AF_INET) {
+ struct sockaddr_in *src4 = (struct sockaddr_in *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, src, &src4->sin_addr), 1, "src address fail");
+ src4->sin_family = AF_INET;
+ src4->sin_len = sizeof(*src4);
+ uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src4->sin_len);
+ src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(src4->sin_len);
+ } else {
+ struct sockaddr_in6 *src6 = (struct sockaddr_in6 *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, src, &src6->sin6_addr), 1, "src address fail");
+ src6->sin6_family = AF_INET6;
+ src6->sin6_len = sizeof(*src6);
+ uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src6->sin6_len);
+ src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(src6->sin6_len);
+ }
+
+ struct sadb_address *dst_address_payload = (struct sadb_address *)(void *)(payload + tlen);
+ dst_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_DST & 0xffff;
+ dst_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
+ dst_address_payload->sadb_address_prefixlen = prefixlen;
+ dst_address_payload->sadb_address_reserved = 0;
+ tlen += sizeof(*dst_address_payload);
+
+ if (family == AF_INET) {
+ struct sockaddr_in *dst4 = (struct sockaddr_in *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, dst, &dst4->sin_addr), 1, "dst address fail");
+ dst4->sin_family = AF_INET;
+ dst4->sin_len = sizeof(*dst4);
+ uint16_t len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst4->sin_len);
+ dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(dst4->sin_len);
+ } else {
+ struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, dst, &dst6->sin6_addr), 1, "dst address fail");
+ dst6->sin6_family = AF_INET6;
+ dst6->sin6_len = sizeof(*dst6);
+ uint16_t len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst6->sin6_len);
+ dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(dst6->sin6_len);
+ }
+
+ struct sadb_key *encrypt_key_payload = (struct sadb_key *)(void *)(payload + tlen);
+ uint16_t len = sizeof(*encrypt_key_payload) + PFKEY_ALIGN8(32);
+ encrypt_key_payload->sadb_key_len = PFKEY_UNIT64(len);
+ encrypt_key_payload->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
+ encrypt_key_payload->sadb_key_bits = (uint16_t)(32 << 3);
+ encrypt_key_payload->sadb_key_reserved = 0;
+ tlen += sizeof(*encrypt_key_payload);
+ arc4random_buf(payload + tlen, 32);
+ tlen += PFKEY_ALIGN8(32);
+
+ struct sadb_key *auth_key_payload = (struct sadb_key *)(void *)(payload + tlen);
+ len = sizeof(*auth_key_payload) + PFKEY_ALIGN8(32);
+ auth_key_payload->sadb_key_len = PFKEY_UNIT64(len);
+ auth_key_payload->sadb_key_exttype = SADB_EXT_KEY_AUTH;
+ auth_key_payload->sadb_key_bits = (uint16_t)(32 << 3);
+ auth_key_payload->sadb_key_reserved = 0;
+ tlen += sizeof(*auth_key_payload);
+ arc4random_buf(payload + tlen, 32);
+ tlen += PFKEY_ALIGN8(32);
+
+ struct sadb_lifetime *hard_lifetime_payload = (struct sadb_lifetime *)(void *)(payload + tlen);
+ hard_lifetime_payload->sadb_lifetime_len = PFKEY_UNIT64(sizeof(*hard_lifetime_payload));
+ hard_lifetime_payload->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
+ tlen += sizeof(*hard_lifetime_payload);
+
+ struct sadb_lifetime *soft_lifetime_payload = (struct sadb_lifetime *)(void *)(payload + tlen);
+ soft_lifetime_payload->sadb_lifetime_len = PFKEY_UNIT64(sizeof(*soft_lifetime_payload));
+ soft_lifetime_payload->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
+ tlen += sizeof(*soft_lifetime_payload);
+
+ // Update the total length
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send update sa");
+}
+
+static void
+send_pkey_update_sa(int pfkey_socket, uint32_t spi)
+{
+ uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
+ bzero(payload, sizeof(payload));
+ uint16_t tlen = 0;
+
+ struct sadb_msg *msg_payload = (struct sadb_msg *)payload;
+ msg_payload->sadb_msg_version = PF_KEY_V2;
+ msg_payload->sadb_msg_type = SADB_UPDATE;
+ msg_payload->sadb_msg_errno = 0;
+ msg_payload->sadb_msg_satype = SADB_SATYPE_ESP;
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ msg_payload->sadb_msg_reserved = 0;
+ msg_payload->sadb_msg_seq = 0;
+ msg_payload->sadb_msg_pid = (u_int32_t)getpid();
+ tlen += sizeof(*msg_payload);
+
+ struct sadb_sa_2 *sa2_payload = (struct sadb_sa_2 *)(void *)(payload + tlen);
+ sa2_payload->sa.sadb_sa_len = PFKEY_UNIT64(sizeof(*sa2_payload));
+ sa2_payload->sa.sadb_sa_exttype = SADB_EXT_SA;
+ sa2_payload->sa.sadb_sa_spi = htonl(spi);
+ sa2_payload->sa.sadb_sa_replay = 4;
+ sa2_payload->sa.sadb_sa_state = SADB_SASTATE_LARVAL;
+ sa2_payload->sa.sadb_sa_auth = SADB_X_AALG_SHA2_256;
+ sa2_payload->sa.sadb_sa_encrypt = SADB_X_EALG_AESCBC;
+ sa2_payload->sa.sadb_sa_flags |= (SADB_X_EXT_NATT | SADB_X_EXT_NATT_KEEPALIVE);
+ sa2_payload->sadb_sa_natt_src_port = htons(4500);
+ sa2_payload->sadb_sa_natt_port = 0; // Bad value to trigger failure
+ sa2_payload->sadb_sa_natt_interval = 20;
+ sa2_payload->sadb_sa_natt_offload_interval = 0;
+ tlen += sizeof(*sa2_payload);
+
+ struct sadb_x_sa2 *sa2_x_payload = (struct sadb_x_sa2 *)(void *)(payload + tlen);
+ sa2_x_payload->sadb_x_sa2_len = PFKEY_UNIT64(sizeof(*sa2_x_payload));
+ sa2_x_payload->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
+ sa2_x_payload->sadb_x_sa2_mode = IPSEC_MODE_TRANSPORT;
+ sa2_x_payload->sadb_x_sa2_reqid = 0;
+ tlen += sizeof(*sa2_x_payload);
+
+ struct sadb_address *src_address_payload = (struct sadb_address *)(void *)(payload + tlen);
+ src_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_SRC & 0xffff;
+ src_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
+ src_address_payload->sadb_address_prefixlen = (sizeof(struct in_addr) << 3);
+ src_address_payload->sadb_address_reserved = 0;
+ tlen += sizeof(*src_address_payload);
+
+ struct sockaddr_in *src = (struct sockaddr_in *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, TEST_SRC_ADDRESS_IPv4, &src->sin_addr), 1, "src address fail");
+ src->sin_family = AF_INET;
+ src->sin_len = sizeof(*src);
+ uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src->sin_len);
+ src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(src->sin_len);
+
+ struct sadb_address *dst_address_payload = (struct sadb_address *)(void *)(payload + tlen);
+ dst_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_DST & 0xffff;
+ dst_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
+ dst_address_payload->sadb_address_prefixlen = (sizeof(struct in_addr) << 3);
+ dst_address_payload->sadb_address_reserved = 0;
+ tlen += sizeof(*dst_address_payload);
+
+ struct sockaddr_in *dst = (struct sockaddr_in *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, TEST_DST_ADDRESS_IPv4, &dst->sin_addr), 1, "dst address fail");
+ dst->sin_family = AF_INET;
+ dst->sin_len = sizeof(*dst);
+ len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst->sin_len);
+ dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(dst->sin_len);
+
+ struct sadb_key *encrypt_key_payload = (struct sadb_key *)(void *)(payload + tlen);
+ len = sizeof(*encrypt_key_payload) + PFKEY_ALIGN8(32);
+ encrypt_key_payload->sadb_key_len = PFKEY_UNIT64(len);
+ encrypt_key_payload->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
+ encrypt_key_payload->sadb_key_bits = (uint16_t)(32 << 3);
+ encrypt_key_payload->sadb_key_reserved = 0;
+ tlen += sizeof(*encrypt_key_payload);
+ arc4random_buf(payload + tlen, 32);
+ tlen += PFKEY_ALIGN8(32);
+
+ struct sadb_key *auth_key_payload = (struct sadb_key *)(void *)(payload + tlen);
+ len = sizeof(*auth_key_payload) + PFKEY_ALIGN8(32);
+ auth_key_payload->sadb_key_len = PFKEY_UNIT64(len);
+ auth_key_payload->sadb_key_exttype = SADB_EXT_KEY_AUTH;
+ auth_key_payload->sadb_key_bits = (uint16_t)(32 << 3);
+ auth_key_payload->sadb_key_reserved = 0;
+ tlen += sizeof(*auth_key_payload);
+ arc4random_buf(payload + tlen, 32);
+ tlen += PFKEY_ALIGN8(32);
+
+ struct sadb_lifetime *hard_lifetime_payload = (struct sadb_lifetime *)(void *)(payload + tlen);
+ hard_lifetime_payload->sadb_lifetime_len = PFKEY_UNIT64(sizeof(*hard_lifetime_payload));
+ hard_lifetime_payload->sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
+ tlen += sizeof(*hard_lifetime_payload);
+
+ struct sadb_lifetime *soft_lifetime_payload = (struct sadb_lifetime *)(void *)(payload + tlen);
+ soft_lifetime_payload->sadb_lifetime_len = PFKEY_UNIT64(sizeof(*soft_lifetime_payload));
+ soft_lifetime_payload->sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
+ tlen += sizeof(*soft_lifetime_payload);
+
+ // Update the total length
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send update sa");
+}
+
+static void
+send_pkey_migrate_sa(int pfkey_socket, uint32_t spi, const char *src, const char *dst, int family,
+ const char *migrate_src, const char *migrate_dst, int migrate_family)
+{
+ uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
+ bzero(payload, sizeof(payload));
+ uint16_t tlen = 0;
+
+ struct sadb_msg *msg_payload = (struct sadb_msg *)payload;
+ msg_payload->sadb_msg_version = PF_KEY_V2;
+ msg_payload->sadb_msg_type = SADB_MIGRATE;
+ msg_payload->sadb_msg_errno = 0;
+ msg_payload->sadb_msg_satype = SADB_SATYPE_ESP;
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ msg_payload->sadb_msg_reserved = 0;
+ msg_payload->sadb_msg_seq = 0;
+ msg_payload->sadb_msg_pid = (u_int32_t)getpid();
+ tlen += sizeof(*msg_payload);
+
+ struct sadb_sa_2 *sa2_payload = (struct sadb_sa_2 *)(void *)(payload + tlen);
+ sa2_payload->sa.sadb_sa_len = PFKEY_UNIT64(sizeof(*sa2_payload));
+ sa2_payload->sa.sadb_sa_exttype = SADB_EXT_SA;
+ sa2_payload->sa.sadb_sa_spi = htonl(spi);
+ sa2_payload->sa.sadb_sa_replay = 4;
+ sa2_payload->sa.sadb_sa_state = SADB_SASTATE_LARVAL;
+ sa2_payload->sa.sadb_sa_auth = SADB_X_AALG_SHA2_256;
+ sa2_payload->sa.sadb_sa_encrypt = SADB_X_EALG_AESCBC;
+ sa2_payload->sa.sadb_sa_flags |= (SADB_X_EXT_NATT | SADB_X_EXT_NATT_KEEPALIVE);
+ sa2_payload->sadb_sa_natt_src_port = htons(4500);
+ sa2_payload->sadb_sa_natt_port = 0; // Bad value to trigger failure
+ sa2_payload->sadb_sa_natt_interval = 20;
+ sa2_payload->sadb_sa_natt_offload_interval = 0;
+ tlen += sizeof(*sa2_payload);
+
+ struct sadb_x_sa2 *sa2_x_payload = (struct sadb_x_sa2 *)(void *)(payload + tlen);
+ sa2_x_payload->sadb_x_sa2_len = PFKEY_UNIT64(sizeof(*sa2_x_payload));
+ sa2_x_payload->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
+ sa2_x_payload->sadb_x_sa2_mode = IPSEC_MODE_TRANSPORT;
+ sa2_x_payload->sadb_x_sa2_reqid = 0;
+ tlen += sizeof(*sa2_x_payload);
+
+ uint8_t prefixlen = (family == AF_INET) ? (sizeof(struct in_addr) << 3) : (sizeof(struct in6_addr) << 3);
+
+ struct sadb_address *src_address_payload = (struct sadb_address *)(void *)(payload + tlen);
+ src_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_SRC & 0xffff;
+ src_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
+ src_address_payload->sadb_address_prefixlen = prefixlen;
+ src_address_payload->sadb_address_reserved = 0;
+ tlen += sizeof(*src_address_payload);
+
+ if (family == AF_INET) {
+ struct sockaddr_in *src4 = (struct sockaddr_in *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, src, &src4->sin_addr), 1, "src address fail");
+ src4->sin_family = AF_INET;
+ src4->sin_len = sizeof(*src4);
+ uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src4->sin_len);
+ src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(src4->sin_len);
+ } else {
+ struct sockaddr_in6 *src6 = (struct sockaddr_in6 *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, src, &src6->sin6_addr), 1, "src address fail");
+ src6->sin6_family = AF_INET6;
+ src6->sin6_len = sizeof(*src6);
+ uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src6->sin6_len);
+ src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(src6->sin6_len);
+ }
+
+ struct sadb_address *dst_address_payload = (struct sadb_address *)(void *)(payload + tlen);
+ dst_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_DST & 0xffff;
+ dst_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
+ dst_address_payload->sadb_address_prefixlen = prefixlen;
+ dst_address_payload->sadb_address_reserved = 0;
+ tlen += sizeof(*dst_address_payload);
+
+ if (family == AF_INET) {
+ struct sockaddr_in *dst4 = (struct sockaddr_in *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, dst, &dst4->sin_addr), 1, "dst address fail");
+ dst4->sin_family = AF_INET;
+ dst4->sin_len = sizeof(*dst4);
+ uint16_t len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst4->sin_len);
+ dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(dst4->sin_len);
+ } else {
+ struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, dst, &dst6->sin6_addr), 1, "dst address fail");
+ dst6->sin6_family = AF_INET6;
+ dst6->sin6_len = sizeof(*dst6);
+ uint16_t len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst6->sin6_len);
+ dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(dst6->sin6_len);
+ }
+
+ prefixlen = (migrate_family == AF_INET) ? (sizeof(struct in_addr) << 3) : (sizeof(struct in6_addr) << 3);
+
+ struct sadb_address *migrate_src_address_payload = (struct sadb_address *)(void *)(payload + tlen);
+ migrate_src_address_payload->sadb_address_exttype = SADB_EXT_MIGRATE_ADDRESS_SRC & 0xffff;
+ migrate_src_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
+ migrate_src_address_payload->sadb_address_prefixlen = prefixlen;
+ migrate_src_address_payload->sadb_address_reserved = 0;
+ tlen += sizeof(*migrate_src_address_payload);
+
+ if (migrate_family == AF_INET) {
+ struct sockaddr_in *migrate_src4 = (struct sockaddr_in *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, migrate_src, &migrate_src4->sin_addr), 1, "migrate src fail");
+ migrate_src4->sin_family = AF_INET;
+ migrate_src4->sin_len = sizeof(*migrate_src4);
+ uint16_t len = sizeof(*migrate_src_address_payload) + PFKEY_ALIGN8(migrate_src4->sin_len);
+ migrate_src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(migrate_src4->sin_len);
+ } else if (migrate_family == AF_INET6) {
+ struct sockaddr_in6 *migrate_src6 = (struct sockaddr_in6 *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, migrate_src, &migrate_src6->sin6_addr), 1, "migrate src fail");
+ migrate_src6->sin6_family = AF_INET6;
+ migrate_src6->sin6_len = sizeof(*migrate_src6);
+ uint16_t len = sizeof(*migrate_src_address_payload) + PFKEY_ALIGN8(migrate_src6->sin6_len);
+ migrate_src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(migrate_src6->sin6_len);
+ } else if (migrate_family == AF_CHAOS) {
+ struct sockaddr_in6 *migrate_src6 = (struct sockaddr_in6 *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, migrate_src, &migrate_src6->sin6_addr), 1, "migrate src fail");
+ migrate_src6->sin6_family = AF_INET6;
+ migrate_src6->sin6_len = sizeof(*migrate_src6) + 100; // Bad value to trigger exploit
+ uint16_t len = sizeof(*migrate_src_address_payload) + PFKEY_ALIGN8(migrate_src6->sin6_len);
+ migrate_src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(migrate_src6->sin6_len);
+ }
+
+ struct sadb_address *migrate_dst_address_payload = (struct sadb_address *)(void *)(payload + tlen);
+ migrate_dst_address_payload->sadb_address_exttype = SADB_EXT_MIGRATE_ADDRESS_DST & 0xffff;
+ migrate_dst_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
+ migrate_dst_address_payload->sadb_address_prefixlen = prefixlen;
+ migrate_dst_address_payload->sadb_address_reserved = 0;
+
+ tlen += sizeof(*migrate_dst_address_payload);
+
+ if (migrate_family == AF_INET) {
+ struct sockaddr_in *migrate_dst4 = (struct sockaddr_in *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, migrate_dst, &migrate_dst4->sin_addr), 1, "migrate dst fail");
+ migrate_dst4->sin_family = AF_INET;
+ migrate_dst4->sin_len = sizeof(*migrate_dst4);
+ uint16_t len = sizeof(*migrate_dst_address_payload) + PFKEY_ALIGN8(migrate_dst4->sin_len);
+ migrate_dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(migrate_dst4->sin_len);
+ } else if (migrate_family == AF_INET6) {
+ struct sockaddr_in6 *migrate_dst6 = (struct sockaddr_in6 *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, migrate_dst, &migrate_dst6->sin6_addr), 1, "migrate dst fail");
+ migrate_dst6->sin6_family = AF_INET6;
+ migrate_dst6->sin6_len = sizeof(*migrate_dst6);
+ uint16_t len = sizeof(*migrate_dst_address_payload) + PFKEY_ALIGN8(migrate_dst6->sin6_len);
+ migrate_dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(migrate_dst6->sin6_len);
+ } else if (migrate_family == AF_CHAOS) {
+ struct sockaddr_in6 *migrate_dst6 = (struct sockaddr_in6 *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET6, migrate_dst, &migrate_dst6->sin6_addr), 1, "migrate dst fail");
+ migrate_dst6->sin6_family = AF_INET6;
+ migrate_dst6->sin6_len = sizeof(*migrate_dst6) + 100; // Bad value to trigger exploit
+ uint16_t len = sizeof(*migrate_dst_address_payload) + PFKEY_ALIGN8(migrate_dst6->sin6_len);
+ migrate_dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(migrate_dst6->sin6_len);
+ }
+
+ // Update the total length
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send migrate sa");
+}
+
+static void
+send_pfkey_get_sa_stat(int pfkey_socket, uint32_t spi, uint32_t stat_length)
+{
+ uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
+ bzero(payload, sizeof(payload));
+ uint16_t tlen = 0;
+
+ struct sadb_msg *msg_payload = (struct sadb_msg *)payload;
+ msg_payload->sadb_msg_version = PF_KEY_V2;
+ msg_payload->sadb_msg_type = SADB_GETSASTAT;
+ msg_payload->sadb_msg_errno = 0;
+ msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC;
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ msg_payload->sadb_msg_reserved = 0;
+ msg_payload->sadb_msg_seq = 0;
+ msg_payload->sadb_msg_pid = (u_int32_t)getpid();
+ tlen += sizeof(*msg_payload);
+
+ struct sadb_session_id *session_id_payload = (struct sadb_session_id *)(void *)(payload + tlen);
+ session_id_payload->sadb_session_id_len = PFKEY_UNIT64(sizeof(*session_id_payload));
+ session_id_payload->sadb_session_id_exttype = SADB_EXT_SESSION_ID;
+ session_id_payload->sadb_session_id_v[0] = 1;
+ tlen += sizeof(*session_id_payload);
+
+ struct sadb_sastat *sadb_stat_payload = (struct sadb_sastat *)(void *)(payload + tlen);
+ uint16_t length = sizeof(*sadb_stat_payload) + PFKEY_ALIGN8(sizeof(struct sastat));
+ sadb_stat_payload->sadb_sastat_len = PFKEY_UNIT64(length);
+ sadb_stat_payload->sadb_sastat_exttype = SADB_EXT_SASTAT;
+ sadb_stat_payload->sadb_sastat_dir = IPSEC_DIR_OUTBOUND;
+ sadb_stat_payload->sadb_sastat_list_len = stat_length;
+ tlen += sizeof(*sadb_stat_payload);
+
+ struct sastat *sastat_payload = (struct sastat *)(void *)(payload + tlen);
+ sastat_payload->spi = htonl(spi);
+ tlen += PFKEY_ALIGN8(sizeof(*sastat_payload));
+
+ // Update the total length
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send get sa stat");
+}
+
+static void
+send_pkey_delete_sa(int pfkey_socket, uint32_t spi)
+{
+ uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
+ bzero(payload, sizeof(payload));
+ uint16_t tlen = 0;
+
+ struct sadb_msg *msg_payload = (struct sadb_msg *)payload;
+ msg_payload->sadb_msg_version = PF_KEY_V2;
+ msg_payload->sadb_msg_type = SADB_DELETE;
+ msg_payload->sadb_msg_errno = 0;
+ msg_payload->sadb_msg_satype = SADB_SATYPE_ESP;
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ msg_payload->sadb_msg_reserved = 0;
+ msg_payload->sadb_msg_seq = 0;
+ msg_payload->sadb_msg_pid = (u_int32_t)getpid();
+ tlen += sizeof(*msg_payload);
+
+ struct sadb_sa_2 *sa2_payload = (struct sadb_sa_2 *)(void *)(payload + tlen);
+ sa2_payload->sa.sadb_sa_len = PFKEY_UNIT64(sizeof(*sa2_payload));
+ sa2_payload->sa.sadb_sa_exttype = SADB_EXT_SA;
+ sa2_payload->sa.sadb_sa_spi = htonl(spi);
+ tlen += sizeof(*sa2_payload);
+
+ struct sadb_address *src_address_payload = (struct sadb_address *)(void *)(payload + tlen);
+ src_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_SRC & 0xffff;
+ src_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
+ src_address_payload->sadb_address_prefixlen = (sizeof(struct in_addr) << 3);
+ src_address_payload->sadb_address_reserved = 0;
+ tlen += sizeof(*src_address_payload);
+
+ struct sockaddr_in *src = (struct sockaddr_in *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, TEST_SRC_ADDRESS_IPv4, &src->sin_addr), 1, "migrate src fail");
+ src->sin_family = AF_INET;
+ src->sin_len = sizeof(*src);
+ uint16_t len = sizeof(*src_address_payload) + PFKEY_ALIGN8(src->sin_len);
+ src_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(src->sin_len);
+
+ struct sadb_address *dst_address_payload = (struct sadb_address *)(void *)(payload + tlen);
+ dst_address_payload->sadb_address_exttype = SADB_EXT_ADDRESS_DST & 0xffff;
+ dst_address_payload->sadb_address_proto = IPSEC_ULPROTO_ANY & 0xff;
+ dst_address_payload->sadb_address_prefixlen = (sizeof(struct in_addr) << 3);
+ dst_address_payload->sadb_address_reserved = 0;
+ tlen += sizeof(*dst_address_payload);
+
+ struct sockaddr_in *dst = (struct sockaddr_in *)(void *)(payload + tlen);
+ T_QUIET; T_ASSERT_EQ_INT(inet_pton(AF_INET, TEST_DST_ADDRESS_IPv4, &dst->sin_addr), 1, "migrate dst fail");
+ dst->sin_family = AF_INET;
+ dst->sin_len = sizeof(*dst);
+ len = sizeof(*dst_address_payload) + PFKEY_ALIGN8(dst->sin_len);
+ dst_address_payload->sadb_address_len = PFKEY_UNIT64(len);
+ tlen += PFKEY_ALIGN8(dst->sin_len);
+
+ // Update the total length
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send delete sa");
+}
+
+static void
+send_pfkey_sa_dump_message(int pfkey_socket)
+{
+ uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
+ bzero(payload, sizeof(payload));
+ uint16_t tlen = 0;
+
+ struct sadb_msg *msg_payload = (struct sadb_msg *)(void *)payload;
+ msg_payload->sadb_msg_version = PF_KEY_V2;
+ msg_payload->sadb_msg_type = SADB_DUMP;
+ msg_payload->sadb_msg_errno = 0;
+ msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC;
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ msg_payload->sadb_msg_reserved = 0;
+ msg_payload->sadb_msg_seq = 0;
+ msg_payload->sadb_msg_pid = (uint32_t)getpid();
+ tlen += sizeof(*msg_payload);
+
+ // Update the total length
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey send sa dump failed");
+}
+
+static void
+send_pfkey_flush_sa(int pfkey_socket)
+{
+ uint8_t payload[MCLBYTES] __attribute__ ((aligned(32)));
+ bzero(payload, sizeof(payload));
+ uint16_t tlen = 0;
+
+ struct sadb_msg *msg_payload = (struct sadb_msg *)payload;
+ msg_payload->sadb_msg_version = PF_KEY_V2;
+ msg_payload->sadb_msg_type = SADB_FLUSH;
+ msg_payload->sadb_msg_errno = 0;
+ msg_payload->sadb_msg_satype = SADB_SATYPE_UNSPEC;
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ msg_payload->sadb_msg_reserved = 0;
+ msg_payload->sadb_msg_seq = 0;
+ msg_payload->sadb_msg_pid = (u_int32_t)getpid();
+ tlen += sizeof(*msg_payload);
+
+ // Update the total length
+ msg_payload->sadb_msg_len = PFKEY_UNIT64(tlen);
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(send(pfkey_socket, payload, (size_t)PFKEY_UNUNIT64(msg_payload->sadb_msg_len), 0), "pfkey flush sa");
+}
+
+static void
+pfkey_cleanup(void)
+{
+ if (pfkey_source != NULL) {
+ int pfkey_socket = (int)dispatch_source_get_handle(pfkey_source);
+ if (pfkey_socket > 0) {
+ send_pfkey_flush_sa(pfkey_socket);
+ send_pfkey_flush_sp(pfkey_socket);
+ }
+ dispatch_source_cancel(pfkey_source);
+ pfkey_source = NULL;
+ }
+}
+
+static int
+pfkey_setup_socket(void)
+{
+ int pfkey_socket = -1;
+ int bufsiz = 0;
+ const unsigned long newbufk = 1536;
+ unsigned long oldmax;
+ size_t oldmaxsize = sizeof(oldmax);
+ unsigned long newmax = newbufk * (1024 + 128);
+
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(pfkey_socket = socket(PF_KEY, SOCK_RAW, PF_KEY_V2), NULL);
+
+ if (sysctlbyname("kern.ipc.maxsockbuf", &oldmax, &oldmaxsize, &newmax, sizeof(newmax)) != 0) {
+ bufsiz = 233016; /* Max allowed by default */
+ } else {
+ bufsiz = newbufk * 1024;
+ }
+
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(setsockopt(pfkey_socket, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz)), "pfkey set snd socket buf failed %d", bufsiz);
+ T_QUIET; T_ASSERT_POSIX_SUCCESS(setsockopt(pfkey_socket, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz)), "pfkey set recv socket buf failed %d", bufsiz);
+
+ pfkey_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, (uintptr_t)pfkey_socket, 0, dispatch_get_main_queue());
+ T_QUIET; T_ASSERT_NOTNULL(pfkey_source, "dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, ...)");
+ dispatch_source_set_event_handler(pfkey_source, ^{
+ recv_pfkey_message(pfkey_socket);
+ });
+ dispatch_source_set_cancel_handler(pfkey_source, ^{
+ close(pfkey_socket);
+ });
+ dispatch_resume(pfkey_source);
+ return pfkey_socket;
+}
+
+static void
+pfkey_process_message_test_60822136(uint8_t **mhp, int pfkey_socket)
+{
+ struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0];
+ static int counter = 0;
+ static uint32_t policy_id = 0;
+
+ if (message->sadb_msg_pid != (uint32_t)getpid()) {
+ return;
+ }
+
+ if (message->sadb_msg_errno) {
+ T_QUIET; T_ASSERT_EQ(message->sadb_msg_type, SADB_X_SPDDUMP, "SADB error for type %u", message->sadb_msg_type);
+ pfkey_cleanup();
+ T_END;
+ }
+
+ switch (message->sadb_msg_type) {
+ case SADB_X_SPDADD:
+ {
+ struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY];
+ T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd add policy message is NULL");
+ policy_id = policy_message->sadb_x_policy_id;
+ T_LOG("Added policy id %u", policy_id);
+ send_pfkey_spd_get_message(pfkey_socket, policy_id);;
+ break;
+ }
+ case SADB_X_SPDGET:
+ {
+ struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY];
+ T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd get policy message is NULL");
+ T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_get: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id);
+ if (counter < MAX_SPD_CHECK) {
+ counter++;
+ send_pfkey_spd_get_message(pfkey_socket, policy_id);
+ } else {
+ T_LOG("Deleting policy id %u", policy_id);
+ send_pfkey_spd_delete_message(pfkey_socket, policy_id);
+ }
+ break;
+ }
+ case SADB_X_SPDDELETE2:
+ {
+ struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY];
+ T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd delete2 policy message is NULL");
+ T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_delete2: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id);
+ T_LOG("Deleted policy id %u", policy_id);
+ sleep(2);
+ send_pfkey_spd_dump_message(pfkey_socket);
+ break;
+ }
+ case SADB_X_SPDDUMP:
+ {
+ struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY];
+ T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd dump policy message is NULL");
+ T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_dump: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id);
+ T_FAIL("Policy id %u still exists", policy_id);
+ pfkey_cleanup();
+ T_END;
+ }
+ case SADB_FLUSH:
+ case SADB_X_SPDFLUSH:
+ break;
+ default:
+ T_FAIL("bad SADB message type %u", message->sadb_msg_type);
+ T_END;
+ }
+ return;
+}
+
+static void
+pfkey_process_message_test_60822924(uint8_t **mhp, int pfkey_socket)
+{
+ struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0];
+ static int counter = 0;
+ static uint32_t policy_id = 0;
+
+ if (message->sadb_msg_pid != (uint32_t)getpid()) {
+ return;
+ }
+
+ if (message->sadb_msg_errno) {
+ T_QUIET; T_ASSERT_EQ(message->sadb_msg_type, SADB_X_SPDDUMP, "SADB error for type %u", message->sadb_msg_type);
+ pfkey_cleanup();
+ T_END;
+ }
+
+ switch (message->sadb_msg_type) {
+ case SADB_X_SPDADD:
+ {
+ struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY];
+ T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd add policy message is NULL");
+ policy_id = policy_message->sadb_x_policy_id;
+ T_LOG("Added policy id %u", policy_id);
+ send_pfkey_spd_enable_message(pfkey_socket, policy_id);;
+ break;
+ }
+ case SADB_X_SPDENABLE:
+ {
+ struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY];
+ T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd enable policy message is NULL");
+ T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_enable: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id);
+ if (counter < MAX_SPD_CHECK) {
+ counter++;
+ send_pfkey_spd_enable_message(pfkey_socket, policy_id);
+ } else {
+ T_LOG("Deleting policy id %u", policy_id);
+ send_pfkey_spd_delete_message(pfkey_socket, policy_id);
+ }
+ break;
+ }
+ case SADB_X_SPDDELETE2:
+ {
+ struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY];
+ T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd delete2 policy message is NULL");
+ T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_delete2: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id);
+ T_LOG("Deleted policy id %u", policy_id);
+ sleep(2);
+ send_pfkey_spd_dump_message(pfkey_socket);
+ break;
+ }
+ case SADB_X_SPDDUMP:
+ {
+ struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY];
+ T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd dump policy message is NULL");
+ T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_dump: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id);
+ T_FAIL("Policy id %u still exists", policy_id);
+ pfkey_cleanup();
+ T_END;
+ }
+ case SADB_FLUSH:
+ case SADB_X_SPDFLUSH:
+ break;
+ default:
+ T_FAIL("bad SADB message type %u", message->sadb_msg_type);
+ T_END;
+ }
+ return;
+}
+
+static void
+pfkey_process_message_test_60822956(uint8_t **mhp, int pfkey_socket)
+{
+ struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0];
+ static int counter = 0;
+ static uint32_t policy_id = 0;
+
+ if (message->sadb_msg_pid != (uint32_t)getpid()) {
+ return;
+ }
+
+ if (message->sadb_msg_errno) {
+ T_QUIET; T_ASSERT_EQ(message->sadb_msg_type, SADB_X_SPDDUMP, "SADB error for type %u", message->sadb_msg_type);
+ pfkey_cleanup();
+ T_END;
+ }
+
+ switch (message->sadb_msg_type) {
+ case SADB_X_SPDADD:
+ {
+ struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY];
+ T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd add policy message is NULL");
+ policy_id = policy_message->sadb_x_policy_id;
+ T_LOG("Added policy id %u", policy_id);
+ send_pfkey_spd_disable_message(pfkey_socket, policy_id);;
+ break;
+ }
+ case SADB_X_SPDDISABLE:
+ {
+ struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY];
+ T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd disable policy message is NULL");
+ T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_disable: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id);
+ if (counter < MAX_SPD_CHECK) {
+ counter++;
+ send_pfkey_spd_disable_message(pfkey_socket, policy_id);
+ } else {
+ T_LOG("Deleting policy id %u", policy_id);
+ send_pfkey_spd_delete_message(pfkey_socket, policy_id);
+ }
+ break;
+ }
+ case SADB_X_SPDDELETE2:
+ {
+ struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY];
+ T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd delete2 policy message is NULL");
+ T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_delete2: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id);
+ T_LOG("Deleted policy id %u", policy_id);
+ sleep(2);
+ send_pfkey_spd_dump_message(pfkey_socket);
+ break;
+ }
+ case SADB_X_SPDDUMP:
+ {
+ struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY];
+ T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd dump policy message is NULL");
+ T_QUIET; T_ASSERT_EQ(policy_id, policy_message->sadb_x_policy_id, "spd_dump: spid mismatch %u != %u", policy_id, policy_message->sadb_x_policy_id);
+ T_FAIL("Policy id %u still exists", policy_id);
+ pfkey_cleanup();
+ T_END;
+ }
+ case SADB_FLUSH:
+ case SADB_X_SPDFLUSH:
+ break;
+ default:
+ T_FAIL("bad SADB message type %u", message->sadb_msg_type);
+ T_END;
+ }
+ return;
+}
+
+static void
+pfkey_process_message_test_60679513(uint8_t **mhp, int pfkey_socket)
+{
+ struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0];
+ static uint32_t spi = 0;
+
+ if (message->sadb_msg_pid != (uint32_t)getpid()) {
+ return;
+ }
+
+ if (message->sadb_msg_errno) {
+ T_QUIET; T_ASSERT_EQ(message->sadb_msg_type, SADB_UPDATE, "SADB error for type %u", message->sadb_msg_type);
+ }
+
+ switch (message->sadb_msg_type) {
+ case SADB_GETSPI:
+ {
+ struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA];
+ T_QUIET; T_ASSERT_NOTNULL(sa_message, "sa get spi message is NULL");
+ spi = ntohl(sa_message->sadb_sa_spi);
+ T_LOG("get spi 0x%x", spi);
+ send_pkey_update_sa(pfkey_socket, spi);
+ break;
+ }
+ case SADB_UPDATE:
+ {
+ struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA];
+ T_QUIET; T_ASSERT_NOTNULL(sa_message, "update sa message is NULL");
+ T_QUIET; T_ASSERT_EQ(spi, ntohl(sa_message->sadb_sa_spi), "sadb update: spi mismatch %u != %u", spi, ntohl(sa_message->sadb_sa_spi));
+ T_LOG("update sa 0x%x", spi);
+ send_pkey_delete_sa(pfkey_socket, spi);
+ break;
+ }
+ case SADB_DELETE:
+ {
+ struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA];
+ T_QUIET; T_ASSERT_NOTNULL(sa_message, "delete sa message is NULL");
+ T_QUIET; T_ASSERT_EQ(spi, ntohl(sa_message->sadb_sa_spi), "sadb delete: spi mismatch %u != %u", spi, ntohl(sa_message->sadb_sa_spi));
+ T_LOG("delete sa 0x%x", spi);
+ pfkey_cleanup();
+ T_END;
+ }
+ case SADB_FLUSH:
+ case SADB_X_SPDFLUSH:
+ break;
+ default:
+ T_FAIL("bad SADB message type %u", message->sadb_msg_type);
+ T_END;
+ }
+ return;
+}
+
+static void
+pfkey_process_message_test_60768729(uint8_t **mhp, int pfkey_socket)
+{
+ struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0];
+ uint32_t spi = 0;
+ static int counter = 0;
+
+ if (message->sadb_msg_pid != (uint32_t)getpid()) {
+ return;
+ }
+
+ T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, 0, "SADB error for type %u", message->sadb_msg_type);
+
+ switch (message->sadb_msg_type) {
+ case SADB_GETSPI:
+ {
+ struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA];
+ T_QUIET; T_ASSERT_NOTNULL(sa_message, "sa get spi message is NULL");
+ spi = ntohl(sa_message->sadb_sa_spi);
+ counter++;
+ if (counter <= 1000) {
+ send_pkey_get_spi(pfkey_socket);
+ } else {
+ T_LOG("SADB added 1000 Larval SPIs");
+ send_pfkey_sa_dump_message(pfkey_socket);
+ }
+ break;
+ }
+ case SADB_DUMP:
+ {
+ counter--;
+ if (counter == 0) {
+ T_PASS("SADB dump successful");
+ pfkey_cleanup();
+ T_END;
+ }
+ break;
+ }
+
+ case SADB_FLUSH:
+ case SADB_X_SPDFLUSH:
+ break;
+ default:
+ T_FAIL("bad SADB message type %u", message->sadb_msg_type);
+ T_END;
+ }
+ return;
+}
+
+static void
+pfkey_process_message_test_60769680(uint8_t **mhp, int pfkey_socket)
+{
+ struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0];
+ static uint8_t counter = 0;
+
+ if (message->sadb_msg_pid != (uint32_t)getpid()) {
+ return;
+ }
+
+ T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, 0, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno);
+
+ switch (message->sadb_msg_type) {
+ case SADB_X_SPDADD:
+ {
+ struct sadb_x_policy *policy_message = (struct sadb_x_policy *)(void *)mhp[SADB_X_EXT_POLICY];
+ T_QUIET; T_ASSERT_NOTNULL(policy_message, "spd add policy message is NULL");
+ counter++;
+ if (counter <= 240) {
+ send_pfkey_spd_add_message(pfkey_socket, counter + 1);
+ } else {
+ T_LOG("SADB added 240 security policies");
+ send_pfkey_spd_dump_message(pfkey_socket);
+ }
+ break;
+ }
+ case SADB_X_SPDDUMP:
+ {
+ counter--;
+ if (counter == 0) {
+ T_PASS("SADB policy dump successful");
+ pfkey_cleanup();
+ T_END;
+ }
+ break;
+ }
+
+ case SADB_FLUSH:
+ case SADB_X_SPDFLUSH:
+ break;
+ default:
+ T_FAIL("bad SADB message type %u", message->sadb_msg_type);
+ T_END;
+ }
+ return;
+}
+
+static void
+pfkey_process_message_test_60822823(uint8_t **mhp, int pfkey_socket)
+{
+ struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0];
+ static uint32_t spi = 0;
+
+ if (message->sadb_msg_pid != (uint32_t)getpid()) {
+ return;
+ }
+
+ if (message->sadb_msg_errno != 0) {
+ T_QUIET; T_ASSERT_EQ(message->sadb_msg_type, SADB_GETSASTAT, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno);
+ T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, EINVAL, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno);
+ T_PASS("SADB get SA Stat received EINVAL");
+ T_END;
+ }
+
+ switch (message->sadb_msg_type) {
+ case SADB_ADD:
+ {
+ struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA];
+ T_QUIET; T_ASSERT_NOTNULL(sa_message, "add sa message is NULL");
+ spi = ntohl(sa_message->sadb_sa_spi);
+ T_LOG("added sa 0x%x", spi);
+ send_pfkey_get_sa_stat(pfkey_socket, spi, 5);
+ break;
+ }
+ case SADB_GETSASTAT:
+ {
+ T_FAIL("get sa stat should fail %u", message->sadb_msg_type);
+ T_END;
+ }
+ case SADB_FLUSH:
+ case SADB_X_SPDFLUSH:
+ break;
+ default:
+ T_FAIL("bad SADB message type %u", message->sadb_msg_type);
+ T_END;
+ }
+ return;
+}
+
+static void
+pfkey_process_message_test_60822823_1(uint8_t **mhp, int pfkey_socket)
+{
+ struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0];
+ static uint32_t spi = 0;
+
+ if (message->sadb_msg_pid != (uint32_t)getpid()) {
+ return;
+ }
+
+ T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, 0, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno);
+
+ switch (message->sadb_msg_type) {
+ case SADB_ADD:
+ {
+ struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA];
+ T_QUIET; T_ASSERT_NOTNULL(sa_message, "add sa message is NULL");
+ spi = ntohl(sa_message->sadb_sa_spi);
+ T_LOG("added sa 0x%x", spi);
+ send_pfkey_get_sa_stat(pfkey_socket, spi, 1);
+ break;
+ }
+ case SADB_GETSASTAT:
+ {
+ struct sadb_session_id *session_id = (struct sadb_session_id *)(void *)mhp[SADB_EXT_SESSION_ID];
+ T_QUIET; T_ASSERT_NOTNULL(session_id, "session id is NULL");
+ T_QUIET; T_EXPECT_EQ_ULLONG(session_id->sadb_session_id_v[0], 1ULL, "Session id is not equal");
+ T_PASS("get sa stat success %u", message->sadb_msg_type);
+ T_END;
+ }
+ case SADB_FLUSH:
+ case SADB_X_SPDFLUSH:
+ break;
+ default:
+ T_FAIL("bad SADB message type %u", message->sadb_msg_type);
+ T_END;
+ }
+ return;
+}
+
+static void
+pfkey_process_message_test_60687183(uint8_t **mhp, int pfkey_socket)
+{
+ struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0];
+ static uint32_t spi = 0;
+
+ if (message->sadb_msg_pid != (uint32_t)getpid()) {
+ return;
+ }
+
+ T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, 0, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno);
+
+ switch (message->sadb_msg_type) {
+ case SADB_ADD:
+ {
+ struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA];
+ T_QUIET; T_ASSERT_NOTNULL(sa_message, "add sa message is NULL");
+ spi = ntohl(sa_message->sadb_sa_spi);
+ T_LOG("added sa 0x%x", spi);
+ send_pkey_migrate_sa(pfkey_socket, spi, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET,
+ TEST_MIGRATE_SRC_ADDRESS_IPv4, TEST_MIGRATE_DST_ADDRESS_IPv4, AF_INET);
+ break;
+ }
+ case SADB_MIGRATE:
+ {
+ T_PASS("migrate SA success");
+ T_END;
+ }
+ case SADB_FLUSH:
+ case SADB_X_SPDFLUSH:
+ break;
+ default:
+ T_FAIL("bad SADB message type %u", message->sadb_msg_type);
+ T_END;
+ }
+ return;
+}
+
+static void
+pfkey_process_message_test_60687183_1(uint8_t **mhp, int pfkey_socket)
+{
+ struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0];
+ static uint32_t spi = 0;
+
+ if (message->sadb_msg_pid != (uint32_t)getpid()) {
+ return;
+ }
+
+ T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, 0, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno);
+
+ switch (message->sadb_msg_type) {
+ case SADB_ADD:
+ {
+ struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA];
+ T_QUIET; T_ASSERT_NOTNULL(sa_message, "add sa message is NULL");
+ spi = ntohl(sa_message->sadb_sa_spi);
+ T_LOG("added sa 0x%x", spi);
+ send_pkey_migrate_sa(pfkey_socket, spi, TEST_SRC_ADDRESS_IPv6, TEST_DST_ADDRESS_IPv6, AF_INET6,
+ TEST_MIGRATE_SRC_ADDRESS_IPv6, TEST_MIGRATE_DST_ADDRESS_IPv6, AF_INET6);
+ break;
+ }
+ case SADB_MIGRATE:
+ {
+ T_PASS("migrate SA success");
+ T_END;
+ }
+ case SADB_FLUSH:
+ case SADB_X_SPDFLUSH:
+ break;
+ default:
+ T_FAIL("bad SADB message type %u", message->sadb_msg_type);
+ T_END;
+ }
+ return;
+}
+
+static void
+pfkey_process_message_test_60687183_2(uint8_t **mhp, int pfkey_socket)
+{
+ struct sadb_msg *message = (struct sadb_msg *)(void *)mhp[0];
+ static uint32_t spi = 0;
+
+ if (message->sadb_msg_pid != (uint32_t)getpid()) {
+ return;
+ }
+
+ if (message->sadb_msg_errno != 0) {
+ T_QUIET; T_ASSERT_EQ(message->sadb_msg_type, SADB_MIGRATE, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno);
+ T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, EINVAL, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno);
+ T_PASS("SADB migrate SA received EINVAL");
+ T_END;
+ }
+
+ T_QUIET; T_ASSERT_EQ(message->sadb_msg_errno, 0, "SADB error for type %u error %d", message->sadb_msg_type, message->sadb_msg_errno);
+
+ switch (message->sadb_msg_type) {
+ case SADB_ADD:
+ {
+ struct sadb_sa *sa_message = (struct sadb_sa *)(void *)mhp[SADB_EXT_SA];
+ T_QUIET; T_ASSERT_NOTNULL(sa_message, "add sa message is NULL");
+ spi = ntohl(sa_message->sadb_sa_spi);
+ T_LOG("added sa 0x%x", spi);
+ send_pkey_migrate_sa(pfkey_socket, spi, TEST_SRC_ADDRESS_IPv6, TEST_DST_ADDRESS_IPv6, AF_INET6,
+ TEST_MIGRATE_SRC_ADDRESS_IPv6, TEST_MIGRATE_DST_ADDRESS_IPv6, AF_CHAOS);
+ break;
+ }
+ case SADB_MIGRATE:
+ {
+ T_FAIL("migrate SA test for bad address failed");
+ T_END;
+ }
+ case SADB_FLUSH:
+ case SADB_X_SPDFLUSH:
+ break;
+ default:
+ T_FAIL("bad SADB message type %u", message->sadb_msg_type);
+ T_END;
+ }
+ return;
+}
+
+T_DECL(sadb_x_get_60822136, "security policy reference count overflow")
+{
+ test_id = TEST_SADB_X_GET_OVERFLOW_60822136;
+
+ int pfkey_socket = pfkey_setup_socket();
+ send_pfkey_flush_sa(pfkey_socket);
+ send_pfkey_flush_sp(pfkey_socket);
+ send_pfkey_spd_add_message(pfkey_socket, IPSEC_ULPROTO_ANY);
+
+ dispatch_main();
+}
+
+T_DECL(sadb_x_spd_enable_60822924, "security policy reference count overflow")
+{
+ test_id = TEST_SADB_X_SPDENABLE_OVERFLOW_60822924;
+
+ int pfkey_socket = pfkey_setup_socket();
+ send_pfkey_flush_sa(pfkey_socket);
+ send_pfkey_flush_sp(pfkey_socket);
+ send_pfkey_spd_add_message(pfkey_socket, IPSEC_ULPROTO_ANY);
+
+ dispatch_main();
+}
+
+T_DECL(sadb_x_spd_disable_60822956, "security policy reference count overflow")
+{
+ test_id = TEST_SADB_X_SPDDISABLE_OVERFLOW_60822956;
+
+ int pfkey_socket = pfkey_setup_socket();
+ send_pfkey_flush_sa(pfkey_socket);
+ send_pfkey_flush_sp(pfkey_socket);
+ send_pfkey_spd_add_message(pfkey_socket, IPSEC_ULPROTO_ANY);
+
+ dispatch_main();
+}
+
+T_DECL(sadb_update_60679513, "security association use after free")
+{
+ test_id = TEST_SADB_UPDATE_USE_AFTER_FREE_60679513;
+
+ int pfkey_socket = pfkey_setup_socket();
+ send_pfkey_flush_sa(pfkey_socket);
+ send_pfkey_flush_sp(pfkey_socket);
+ send_pkey_get_spi(pfkey_socket);
+
+ dispatch_main();
+}
+
+T_DECL(sadb_dump_60768729, "security association sa dump heap overflow")
+{
+ test_id = TEST_SADB_DUMP_HEAP_OVERFLOW_60768729;
+
+ int pfkey_socket = pfkey_setup_socket();
+ T_ATEND(pfkey_cleanup);
+ send_pfkey_flush_sa(pfkey_socket);
+ send_pfkey_flush_sp(pfkey_socket);
+ send_pkey_get_spi(pfkey_socket);
+
+ dispatch_main();
+}
+
+T_DECL(sadb_policy_dump_60769680, "security association sa policy dump heap overflow")
+{
+ test_id = TEST_SADB_POLICY_DUMP_HEAP_OVERFLOW_60769680;
+
+ int pfkey_socket = pfkey_setup_socket();
+ T_ATEND(pfkey_cleanup);
+ send_pfkey_flush_sa(pfkey_socket);
+ send_pfkey_flush_sp(pfkey_socket);
+ send_pfkey_spd_add_message(pfkey_socket, 1);
+
+ dispatch_main();
+}
+
+T_DECL(sadb_get_sastat_oob_60769680, "security association get sa stat oob read")
+{
+ test_id = TEST_SADB_GETSASTAT_OOB_READ_60822823;
+
+ int pfkey_socket = pfkey_setup_socket();
+ T_ATEND(pfkey_cleanup);
+ send_pfkey_flush_sa(pfkey_socket);
+ send_pfkey_flush_sp(pfkey_socket);
+ send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET);
+
+ dispatch_main();
+}
+
+T_DECL(sadb_get_sastat_success, "security association get sa stat")
+{
+ test_id = TEST_SADB_GETSASTAT_OOB_READ_SUCCESS;
+
+ int pfkey_socket = pfkey_setup_socket();
+ T_ATEND(pfkey_cleanup);
+ send_pfkey_flush_sa(pfkey_socket);
+ send_pfkey_flush_sp(pfkey_socket);
+ send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET);
+
+ dispatch_main();
+}
+
+T_DECL(sadb_key_migrate_address_ipv4, "security association migrate address ipv4")
+{
+ test_id = TEST_SADB_EXT_MIGRATE_ADDRESS_IPv4;
+
+ int pfkey_socket = pfkey_setup_socket();
+ T_ATEND(pfkey_cleanup);
+ send_pfkey_flush_sa(pfkey_socket);
+ send_pfkey_flush_sp(pfkey_socket);
+ send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv4, TEST_DST_ADDRESS_IPv4, AF_INET);
+
+ dispatch_main();
+}
+
+T_DECL(sadb_key_migrate_address_ipv6, "security association migrate address ipv6")
+{
+ test_id = TEST_SADB_EXT_MIGRATE_ADDRESS_IPv6;
+
+ int pfkey_socket = pfkey_setup_socket();
+ T_ATEND(pfkey_cleanup);
+ send_pfkey_flush_sa(pfkey_socket);
+ send_pfkey_flush_sp(pfkey_socket);
+ send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv6, TEST_DST_ADDRESS_IPv6, AF_INET6);
+
+ dispatch_main();
+}
+
+T_DECL(sadb_key_migrate_bad_address, "security association migrate bad address")
+{
+ test_id = TEST_SADB_EXT_MIGRATE_BAD_ADDRESS;
+
+ int pfkey_socket = pfkey_setup_socket();
+ T_ATEND(pfkey_cleanup);
+ send_pfkey_flush_sa(pfkey_socket);
+ send_pfkey_flush_sp(pfkey_socket);
+ send_pkey_add_sa(pfkey_socket, 0x12345678, TEST_SRC_ADDRESS_IPv6, TEST_DST_ADDRESS_IPv6, AF_INET6);
+
+ dispatch_main();
+}
diff --git a/tests/proc_info.c b/tests/proc_info.c
index 51206a2f4..5ce0747eb 100644
--- a/tests/proc_info.c
+++ b/tests/proc_info.c
@@ -263,8 +263,12 @@ static child_action_handler_t proc_info_call_pidinfo_handler = ^void (proc_confi
/*
* Allocate a page of memory
* Copy on write shared memory
+ *
+ * WARNING
+ * Don't add calls to T_LOG here as they can end up generating unwanted
+ * calls to mach_msg_send(). If curtask->messages_sent gets incremented
+ * at this point it will interfere with testing pti_messages_sent.
*/
- T_LOG("Child allocating a page of memory, and causing a copy-on-write");
retval = 0;
tmp_map = mmap(0, PAGE_SIZE, PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
if (tmp_map == MAP_FAILED) {
diff --git a/tests/sioc-if-addr-bounds.c b/tests/sioc-if-addr-bounds.c
new file mode 100644
index 000000000..b7b124a31
--- /dev/null
+++ b/tests/sioc-if-addr-bounds.c
@@ -0,0 +1,662 @@
+/*
+ * Copyright (c) 2020 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+/* -*- compile-command: "xcrun --sdk iphoneos.internal make sioc-if-addr-bounds" -*- */
+
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+
+#include
+#include
+
+#include
+
+#include
+#include
+
+#include
+
+#include
+
+#include "ioc_str.h"
+
+T_GLOBAL_META(T_META_NAMESPACE("xnu.net"));
+
+#ifndef STRINGIFY
+#define __STR(x) #x /* just a helper macro */
+#define STRINGIFY(x) __STR(x)
+#endif /* STRINGIFY */
+
+#define IF_NAME "bridge"
+
+/* On some platforms with DEBUG kernel, we need to wait a while */
+#define SIFCREATE_RETRY 600
+
+#define PATTERN_SIZE 8
+
+static int
+ifnet_destroy(int s, const char * ifname, bool fail_on_error)
+{
+ int err;
+ struct ifreq ifr;
+
+ bzero(&ifr, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ err = ioctl(s, SIOCIFDESTROY, &ifr);
+ if (fail_on_error) {
+ T_QUIET;
+ T_ASSERT_POSIX_SUCCESS(err, "SIOCSIFDESTROY %s", ifr.ifr_name);
+ }
+ if (err < 0) {
+ T_LOG("SIOCSIFDESTROY %s", ifr.ifr_name);
+ }
+ return err;
+}
+
+static int
+ifnet_set_flags(int s, const char * ifname,
+ uint16_t flags_set, uint16_t flags_clear)
+{
+ uint16_t flags_after;
+ uint16_t flags_before;
+ struct ifreq ifr;
+ int ret;
+
+ bzero(&ifr, sizeof(ifr));
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ ret = ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr);
+ if (ret != 0) {
+ T_LOG("SIOCGIFFLAGS %s", ifr.ifr_name);
+ return ret;
+ }
+ flags_before = (uint16_t)ifr.ifr_flags;
+ ifr.ifr_flags |= flags_set;
+ ifr.ifr_flags &= ~(flags_clear);
+ flags_after = (uint16_t)ifr.ifr_flags;
+ if (flags_before == flags_after) {
+ /* nothing to do */
+ ret = 0;
+ } else {
+ /* issue the ioctl */
+ T_QUIET;
+ T_ASSERT_POSIX_SUCCESS(ioctl(s, SIOCSIFFLAGS, &ifr),
+ "SIOCSIFFLAGS %s 0x%x",
+ ifr.ifr_name, (uint16_t)ifr.ifr_flags);
+ }
+ return ret;
+}
+
+static int
+ifnet_create(int s, char * ifname, size_t ifname_size)
+{
+ int error = 0;
+ struct ifreq ifr;
+
+ bzero(&ifr, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+ for (int i = 0; i < SIFCREATE_RETRY; i++) {
+ if (ioctl(s, SIOCIFCREATE, &ifr) < 0) {
+ error = errno;
+ T_LOG("SIOCSIFCREATE %s: %s", ifname,
+ strerror(error));
+ if (error == EBUSY) {
+ /* interface is tearing down, try again */
+ usleep(10000);
+ } else if (error == EEXIST) {
+ /* interface exists, try destroying it */
+ (void)ifnet_destroy(s, ifname, false);
+ } else {
+ /* unexpected failure */
+ break;
+ }
+ } else {
+ error = 0;
+ break;
+ }
+ }
+ if (error == 0) {
+ /* Copy back the interface name with unit number */
+ strlcpy(ifname, ifr.ifr_name, ifname_size);
+ error = ifnet_set_flags(s, ifname, IFF_UP, 0);
+ }
+ return error;
+}
+
+#define MAXBUF 32
+
+static void
+HexDump(void *data, size_t len)
+{
+ size_t i, j, k;
+ unsigned char *ptr = (unsigned char *)data;
+ unsigned char buf[3 * MAXBUF + 1];
+
+ for (i = 0; i < len; i += MAXBUF) {
+ for (j = i, k = 0; j < i + MAXBUF && j < len; j++) {
+ unsigned char msnbl = ptr[j] >> 4;
+ unsigned char lsnbl = ptr[j] & 0x0f;
+
+ buf[k++] = msnbl < 10 ? msnbl + '0' : msnbl + 'a' - 10;
+ buf[k++] = lsnbl < 10 ? lsnbl + '0' : lsnbl + 'a' - 10;
+ if ((j % 2) == 1) {
+ buf[k++] = ' ';
+ }
+ if ((j % MAXBUF) == MAXBUF - 1) {
+ buf[k++] = ' ';
+ }
+ }
+ buf[k] = 0;
+ T_LOG("%5zd: %s\n", i, buf);
+ }
+}
+
+
+static int
+check_rt_if_list_for_pattern(const char *label, unsigned char pattern, size_t pattern_size)
+{
+ size_t i;
+ size_t len;
+ int mib[6] = { CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST, 0 };
+ unsigned char *rt_if_list_buf = NULL;
+ int count = 0;
+ unsigned char *pattern_buf = NULL;
+
+ T_QUIET; T_ASSERT_NOTNULL(pattern_buf = calloc(1, pattern_size), "pattern_buf calloc(1, %zd)", pattern_size);
+ memset(pattern_buf, pattern, pattern_size);
+
+ T_QUIET; T_EXPECT_POSIX_SUCCESS(sysctl(mib, 6, NULL, &len, NULL, 0), "sysctl NET_RT_IFLIST");
+
+ T_QUIET; T_ASSERT_NOTNULL(rt_if_list_buf = calloc(1, len), "rt_if_list_buf calloc(1, %zd)", len);
+
+ T_QUIET; T_EXPECT_POSIX_SUCCESS(sysctl(mib, 6, rt_if_list_buf, &len, NULL, 0), "sysctl NET_RT_IFLIST");
+
+ if (label != NULL) {
+ T_LOG("%s sysctl NET_RT_IFLIST buffer length %zd\n", label, len);
+ }
+
+ count = 0;
+ for (i = 0; i < len - pattern_size; i++) {
+ if (memcmp(rt_if_list_buf + i, pattern_buf, pattern_size) == 0) {
+ count++;
+ i += pattern_size - 1;
+ }
+ }
+
+ if (label != NULL) {
+ if (label != NULL && count > 0) {
+ T_LOG("%s found pattern at %zd count %d times\n", label, i, count);
+ HexDump(rt_if_list_buf, len);
+ }
+ }
+ free(rt_if_list_buf);
+ free(pattern_buf);
+
+ return count;
+}
+
+static bool
+find_unused_pattern_in_rt_if_list(unsigned char *pattern, size_t pattern_size)
+{
+ bool found_pattern = false;
+ unsigned char i;
+ unsigned char *pattern_buf = NULL;
+
+ T_QUIET; T_ASSERT_NOTNULL(pattern_buf = calloc(1, pattern_size), "pattern_buf calloc(1, %zd)", pattern_size);
+
+ /* Try 10 times to find an unused pattern */
+ for (i = 1; i < 255; i++) {
+ if (check_rt_if_list_for_pattern(NULL, i, pattern_size) == 0) {
+ found_pattern = true;
+ *pattern = i;
+ memset(pattern_buf, i, pattern_size);
+ T_LOG("PATTERN: ");
+ HexDump(pattern_buf, pattern_size);
+ break;
+ }
+ }
+ free(pattern_buf);
+
+ return found_pattern;
+}
+
+static const char *
+ioc_str(unsigned long cmd)
+{
+#define X(a) case a: return #a;
+
+ switch (cmd) {
+ SIOC_LIST
+
+ default:
+ break;
+ }
+ return "";
+}
+
+struct ioc_ifreq {
+ unsigned long ioc_cmd;
+ uint8_t salen;
+ uint8_t safamily;
+ const char *sastr;
+ int error; // 0 means no error, -1, end of list, otherwise expected errno
+};
+
+static struct ioc_ifreq ioc_list[] = {
+ { SIOCSIFADDR, sizeof(struct sockaddr_in), AF_INET6, "10.2.3.1", EINVAL },
+ { SIOCDIFADDR, sizeof(struct sockaddr_in), AF_INET6, "10.2.3.1", EADDRNOTAVAIL },
+ { SIOCDIFADDR, sizeof(struct sockaddr_in6), AF_INET, "10.2.3.1", EADDRNOTAVAIL },
+ { SIOCDIFADDR, sizeof(struct sockaddr_in), AF_INET, "10.2.3.1", EADDRNOTAVAIL },
+
+ { SIOCSIFADDR, 0xf0, AF_INET6, "10.2.3.1", EINVAL },
+ { SIOCDIFADDR, 0xf0, AF_INET6, "10.2.3.1", EADDRNOTAVAIL },
+ { SIOCDIFADDR, 0xf0, AF_INET, "10.2.3.1", EADDRNOTAVAIL },
+ { SIOCDIFADDR, 0xf0, AF_INET, "10.2.3.1", EADDRNOTAVAIL },
+
+ { SIOCSIFADDR, 0, AF_INET6, "10.2.3.1", EINVAL },
+ { SIOCDIFADDR, 0, AF_INET6, "10.2.3.1", EADDRNOTAVAIL },
+ { SIOCDIFADDR, 0, AF_INET, "10.2.3.1", EADDRNOTAVAIL },
+ { SIOCDIFADDR, 0, AF_INET, "10.2.3.1", EADDRNOTAVAIL },
+
+ { SIOCSIFADDR, sizeof(struct sockaddr_in6), AF_INET, "10.2.3.2", 0 },
+ { SIOCDIFADDR, sizeof(struct sockaddr_in), AF_INET6, "10.2.3.2", 0 },
+
+ { SIOCSIFADDR, sizeof(struct sockaddr_in), AF_INET, "10.2.3.3", 0 },
+ { SIOCDIFADDR, sizeof(struct sockaddr_in6), AF_INET, "10.2.3.3", 0 },
+
+ { SIOCSIFADDR, sizeof(struct sockaddr_in6), AF_INET6, "10.2.3.4", EINVAL },
+ { SIOCDIFADDR, sizeof(struct sockaddr_in6), AF_INET, "10.2.3.4", EADDRNOTAVAIL },
+
+ { SIOCSIFADDR, sizeof(struct sockaddr_in), AF_INET, "10.2.3.5", 0 },
+ { SIOCDIFADDR, sizeof(struct sockaddr_in), AF_INET, "0.0.0.0", EADDRNOTAVAIL },
+ { SIOCDIFADDR, sizeof(struct sockaddr_in), AF_INET, "10.2.3.5", 0 },
+
+ { SIOCSIFADDR, sizeof(struct sockaddr_in), AF_INET, "10.2.3.6", 0 },
+
+ { SIOCSIFNETMASK, sizeof(struct sockaddr_in), 0, "ff.00.00.00", 0 },
+ { SIOCSIFNETMASK, sizeof(struct sockaddr_in), AF_INET, "ff.00.00.00", 0 },
+ { SIOCSIFNETMASK, sizeof(struct sockaddr_in), AF_INET6, "ff.f.00.00", 0 },
+
+ { SIOCSIFNETMASK, sizeof(struct sockaddr_in6), 0, "ff.ff.00.00", 0 },
+ { SIOCSIFNETMASK, sizeof(struct sockaddr_in6), AF_INET, "ff.ff.00.00", 0 },
+ { SIOCSIFNETMASK, sizeof(struct sockaddr_in6), AF_INET6, "ff.ff.f0.00", 0 },
+
+ { SIOCSIFNETMASK, 0, 0, "ff.ff.00.00", 0 },
+ { SIOCSIFNETMASK, 0, AF_INET, "ff.ff.00.00", 0 },
+ { SIOCSIFNETMASK, 0, AF_INET6, "ff.ff.f0.00", 0 },
+
+ { SIOCSIFNETMASK, 0xf0, 0, "ff.ff.00.00", 0 },
+ { SIOCSIFNETMASK, 0xf0, AF_INET, "ff.ff.00.00", 0 },
+ { SIOCSIFNETMASK, 0xf0, AF_INET6, "ff.ff.f0.00", 0 },
+
+ { SIOCSIFBRDADDR, sizeof(struct sockaddr_in), 0, "10.255.255.255", 0 },
+ { SIOCSIFBRDADDR, sizeof(struct sockaddr_in), AF_INET, "10.255.255.255", 0 },
+ { SIOCSIFBRDADDR, sizeof(struct sockaddr_in), AF_INET6, "10.255.255.255", 0 },
+ { SIOCSIFBRDADDR, sizeof(struct sockaddr_in6), AF_INET, "10.255.255.255", 0 },
+
+ { SIOCSIFBRDADDR, 0xf0, 0, "10.255.255.255", 0 },
+ { SIOCSIFBRDADDR, 0xf0, AF_INET, "10.255.255.255", 0 },
+ { SIOCSIFBRDADDR, 0xf0, AF_INET6, "10.255.255.255", 0 },
+ { SIOCSIFBRDADDR, 0xf0, AF_INET, "10.255.255.255", 0 },
+
+ { SIOCSIFBRDADDR, 0, 0, "10.255.255.255", 0 },
+ { SIOCSIFBRDADDR, 0, AF_INET, "10.255.255.255", 0 },
+ { SIOCSIFBRDADDR, 0, AF_INET6, "10.255.255.255", 0 },
+ { SIOCSIFBRDADDR, 0, AF_INET, "10.255.255.255", 0 },
+
+ { 0, 0, 0, "", -1 },
+};
+
+static void
+test_sioc_ifr_bounds(struct ioc_ifreq *ioc_ifreq, int s, const char *ifname)
+{
+ struct ifreq ifr = {};
+ unsigned char pattern;
+ struct sockaddr_in *sin;
+
+ T_LOG("");
+ T_LOG("TEST CASE: %s ioctl(%s, sa_len %u, sa_family %u, %s) -> %d", __func__,
+ ioc_str(ioc_ifreq->ioc_cmd), ioc_ifreq->salen, ioc_ifreq->safamily, ioc_ifreq->sastr, ioc_ifreq->error);
+
+
+ if (find_unused_pattern_in_rt_if_list(&pattern, PATTERN_SIZE) == false) {
+ T_SKIP("Could not find unused pattern");
+ }
+
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ memset(&ifr.ifr_addr.sa_data, pattern, sizeof(ifr.ifr_dstaddr.sa_data));
+
+ sin = (struct sockaddr_in *)(void *)&ifr.ifr_addr;
+ sin->sin_len = ioc_ifreq->salen;
+ sin->sin_family = ioc_ifreq->safamily;
+ sin->sin_addr.s_addr = inet_addr(ioc_ifreq->sastr);
+
+ int retval;
+ if (ioc_ifreq->error == 0) {
+ T_EXPECT_POSIX_SUCCESS(retval = ioctl(s, ioc_ifreq->ioc_cmd, &ifr),
+ "%s, %s: retval %d", ioc_str(ioc_ifreq->ioc_cmd), ioc_ifreq->sastr, retval);
+ } else {
+ T_EXPECT_POSIX_FAILURE(retval = ioctl(s, ioc_ifreq->ioc_cmd, &ifr), ioc_ifreq->error,
+ "%s, %s: retval %d errno %s", ioc_str(ioc_ifreq->ioc_cmd), ioc_ifreq->sastr, retval, strerror(errno));
+ }
+
+ T_EXPECT_EQ(check_rt_if_list_for_pattern("test_sioc_ifr_bounds", pattern, PATTERN_SIZE), 0, "pattern should not be found");
+
+ fflush(stdout);
+ fflush(stderr);
+}
+
+T_DECL(sioc_ifr_bounds, "test bound checks on struct ifreq addresses passed to interface ioctls",
+ T_META_ASROOT(true))
+{
+ int s = -1;
+ char ifname[IFNAMSIZ];
+
+ T_LOG("%s", __func__);
+
+ T_QUIET; T_EXPECT_POSIX_SUCCESS(s = socket(AF_INET, SOCK_DGRAM, 0), "socket");
+
+ strlcpy(ifname, IF_NAME, sizeof(ifname));
+
+ int error = 0;
+ if ((error = ifnet_create(s, ifname, sizeof(ifname))) != 0) {
+ if (error == EINVAL) {
+ T_SKIP("The system does not support the %s cloning interface", IF_NAME);
+ }
+ T_SKIP("This test failed creating a %s cloning interface", IF_NAME);
+ }
+ T_LOG("created clone interface '%s'", ifname);
+
+ struct ioc_ifreq *ioc_ifreq;
+ for (ioc_ifreq = ioc_list; ioc_ifreq->error != -1; ioc_ifreq++) {
+ test_sioc_ifr_bounds(ioc_ifreq, s, ifname);
+ }
+ (void)ifnet_destroy(s, ifname, true);
+
+ close(s);
+}
+
+struct ioc_ifra {
+ const char *description;
+
+ uint8_t addr_len;
+ uint8_t addr_fam;
+ const char *addr_str;
+
+ uint8_t broad_len;
+ uint8_t broad_fam;
+ const char *broad_str;
+
+ uint8_t mask_len;
+ uint8_t mask_fam;
+ const char *mask_str;
+
+ int error; // 0 means no error, -1, end of list, otherwise expected errno
+};
+
+static struct ioc_ifra ioc_ifra_list[] = {
+ {
+ .description = "fully formed",
+ .addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.1.1.1",
+ .broad_len = sizeof(struct sockaddr_in), .broad_fam = AF_INET, .broad_str = "1.1.1.255",
+ .mask_len = sizeof(struct sockaddr_in), .mask_fam = AF_INET, .mask_str = "255.255.0.0",
+ .error = 0
+ },
+ {
+ .description = "addr_len 0",
+ .addr_len = 0, .addr_fam = AF_INET, .addr_str = "10.2.2.0",
+ .broad_len = sizeof(struct sockaddr_in), .broad_fam = AF_INET, .broad_str = "10.2.2.255",
+ .mask_len = sizeof(struct sockaddr_in), .mask_fam = AF_INET, .mask_str = "255.0.0.0",
+ .error = 0
+ },
+ {
+ .description = "addr_len 1",
+ .addr_len = 1, .addr_fam = AF_INET, .addr_str = "10.2.2.1",
+ .broad_len = sizeof(struct sockaddr_in), .broad_fam = AF_INET, .broad_str = "10.2.2.255",
+ .mask_len = sizeof(struct sockaddr_in), .mask_fam = AF_INET, .mask_str = "255.0.0.0",
+ .error = 0
+ },
+ {
+ .description = "addr_len 250",
+ .addr_len = 250, .addr_fam = AF_INET, .addr_str = "10.2.2.250",
+ .broad_len = sizeof(struct sockaddr_in), .broad_fam = AF_INET, .broad_str = "10.2.2.255",
+ .mask_len = sizeof(struct sockaddr_in), .mask_fam = AF_INET, .mask_str = "255.0.0.0",
+ .error = 0
+ },
+ {
+ .description = "addr_family AF_INET6",
+ .addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET6, .addr_str = "10.3.3.3",
+ .broad_len = sizeof(struct sockaddr_in), .broad_fam = AF_INET, .broad_str = "10.3.255.255",
+ .mask_len = sizeof(struct sockaddr_in), .mask_fam = AF_INET, .mask_str = "255.255.255.0",
+ .error = EINVAL
+ },
+ {
+ .description = "broadcast_len 0xf0",
+ .addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.4.4.4",
+ .broad_len = 0xf0, .broad_fam = AF_INET, .broad_str = "10.4.4.255",
+ .mask_len = sizeof(struct sockaddr_in), .mask_fam = AF_INET, .mask_str = "255.255.255.0",
+ .error = 0
+ },
+ {
+ .description = "broadcast_family AF_INET6",
+ .addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.5.5.5",
+ .broad_len = sizeof(struct sockaddr_in), .broad_fam = AF_INET6, .broad_str = "10.5.5.255",
+ .mask_len = sizeof(struct sockaddr_in), .mask_fam = AF_INET, .mask_str = "255.255.0.0",
+ .error = 0
+ },
+ {
+ .description = "mask_len 0xf0",
+ .addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.6.6.6",
+ .broad_len = sizeof(struct sockaddr_in), .broad_fam = AF_INET, .broad_str = "1.6.6.255",
+ .mask_len = 0xf0, .mask_fam = AF_INET, .mask_str = "255.255.0.0",
+ .error = 0
+ },
+ {
+ .description = "mask_family AF_INET6",
+ .addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.7.7.7",
+ .broad_len = sizeof(struct sockaddr_in), .broad_fam = AF_INET, .broad_str = "10.7.7.255",
+ .mask_len = sizeof(struct sockaddr_in), .mask_fam = AF_INET6, .mask_str = "255.255.0.0",
+ .error = 0
+ },
+ {
+ .description = "ifra address only",
+ .addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.8.8.8",
+ .broad_len = 0, .broad_str = NULL,
+ .mask_len = 0, .mask_str = NULL,
+ .error = 0
+ },
+ {
+ .description = "ifra mask len 1",
+ .addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.9.9.1",
+ .broad_len = 0, .broad_str = NULL,
+ .mask_len = 1, .mask_fam = AF_INET, .mask_str = "255.255.255.0",
+ .error = 0
+ },
+ {
+ .description = "ifra mask len 3",
+ .addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.9.9.3",
+ .broad_len = 0, .broad_str = NULL,
+ .mask_len = 1, .mask_fam = AF_INET, .mask_str = "255.255.255.0",
+ .error = 0
+ },
+ {
+ .description = "ifra mask len 5",
+ .addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.9.9.5",
+ .broad_len = 0, .broad_str = NULL,
+ .mask_len = 1, .mask_fam = AF_INET, .mask_str = "255.255.255.0",
+ .error = 0
+ },
+ {
+ .description = "ifra mask len 7",
+ .addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.9.9.7",
+ .broad_len = 0, .broad_str = NULL,
+ .mask_len = 1, .mask_fam = AF_INET, .mask_str = "255.255.255.0",
+ .error = 0
+ },
+ {
+ .description = "ifra mask len 9",
+ .addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.9.9.9",
+ .broad_len = 0, .broad_str = NULL,
+ .mask_len = 1, .mask_fam = AF_INET, .mask_str = "255.255.255.0",
+ .error = 0
+ },
+ {
+ .description = "ifra mask len 11",
+ .addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.9.9.11",
+ .broad_len = 0, .broad_str = NULL,
+ .mask_len = 1, .mask_fam = AF_INET, .mask_str = "255.255.255.0",
+ .error = 0
+ },
+ {
+ .description = "ifra mask len 13",
+ .addr_len = sizeof(struct sockaddr_in), .addr_fam = AF_INET, .addr_str = "10.9.9.13",
+ .broad_len = 0, .broad_str = NULL,
+ .mask_len = 1, .mask_fam = AF_INET, .mask_str = "255.255.255.0",
+ .error = 0
+ },
+ {
+ .description = NULL,
+ .error = -1
+ }
+};
+
+T_DECL(sioc_ifra_addr_bounds, "test bound checks on socket address passed to interface ioctls",
+ T_META_ASROOT(true))
+{
+ int s = -1;
+
+ T_QUIET; T_EXPECT_POSIX_SUCCESS(s = socket(AF_INET, SOCK_DGRAM, 0), "socket");
+
+ char ifname[IFNAMSIZ];
+ strlcpy(ifname, IF_NAME, sizeof(ifname));
+ int error = 0;
+ if ((error = ifnet_create(s, ifname, sizeof(ifname))) != 0) {
+ if (error == EINVAL) {
+ T_SKIP("The system does not support the %s cloning interface", IF_NAME);
+ }
+ T_SKIP("This test failed creating a %s cloning interface", IF_NAME);
+ }
+ T_LOG("created clone interface '%s'", ifname);
+
+ struct ioc_ifra *ioc_ifra;
+
+ for (ioc_ifra = ioc_ifra_list; ioc_ifra->error != -1; ioc_ifra++) {
+ struct in_aliasreq ifra = {};
+ unsigned char pattern;
+ int retval;
+
+ T_LOG("");
+ T_LOG("TEST CASE: %s, ioctl(SIOCAIFADDR, %s)", ioc_ifra->description, ioc_ifra->addr_str != NULL ? ioc_ifra->addr_str : "");
+
+ if (find_unused_pattern_in_rt_if_list(&pattern, PATTERN_SIZE) == false) {
+ T_SKIP("Could not find unused pattern in rt_if_list");
+ return;
+ }
+
+ memset(&ifra, pattern, sizeof(ifra));
+
+ strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
+
+ ifra.ifra_addr.sin_len = ioc_ifra->addr_len;
+ ifra.ifra_addr.sin_family = ioc_ifra->addr_fam;
+ if (ioc_ifra->addr_str != NULL) {
+ ifra.ifra_addr.sin_addr.s_addr = inet_addr(ioc_ifra->addr_str);
+ }
+
+ ifra.ifra_broadaddr.sin_len = ioc_ifra->broad_len;
+ ifra.ifra_broadaddr.sin_family = ioc_ifra->broad_fam;
+ if (ioc_ifra->broad_str != NULL) {
+ ifra.ifra_broadaddr.sin_addr.s_addr = inet_addr(ioc_ifra->broad_str);
+ }
+
+ ifra.ifra_mask.sin_len = ioc_ifra->mask_len;
+ ifra.ifra_mask.sin_family = ioc_ifra->mask_fam;
+ if (ioc_ifra->mask_str != NULL) {
+ ifra.ifra_mask.sin_addr.s_addr = inet_addr(ioc_ifra->mask_str);
+ }
+
+ if (ioc_ifra->error == 0) {
+ T_EXPECT_POSIX_SUCCESS(retval = ioctl(s, SIOCAIFADDR, &ifra), "SIOCAIFADDR retval %d", retval);
+ } else {
+ T_EXPECT_POSIX_FAILURE(retval = ioctl(s, SIOCAIFADDR, &ifra), EINVAL, "SIOCAIFADDR retval %d, %s", retval, strerror(errno));
+ }
+
+ T_EXPECT_EQ(check_rt_if_list_for_pattern("after ioctl SIOCAIFADDR", pattern, PATTERN_SIZE), 0, "pattern should not be found");
+ }
+
+ (void)ifnet_destroy(s, ifname, true);
+
+ close(s);
+}
+
+T_DECL(sioc_ifr_dstaddr_leak, "test bound checks on socket address passed to interface ioctls",
+ T_META_ASROOT(true))
+{
+ int s = -1;
+ struct ifreq ifr = {};
+ unsigned char pattern;
+ struct ifaddrs *ifap = NULL, *ifa;
+ bool found_gif0 = false;
+
+ T_QUIET; T_EXPECT_POSIX_SUCCESS(getifaddrs(&ifap), "getifaddrs");
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ if (strcmp(ifa->ifa_name, "gif0") == 0) {
+ found_gif0 = true;
+ break;
+ }
+ }
+ freeifaddrs(ifap);
+ ifap = NULL;
+ if (found_gif0 == false) {
+ T_SKIP("gif0 does not exists");
+ }
+
+ if (find_unused_pattern_in_rt_if_list(&pattern, PATTERN_SIZE) == false) {
+ T_SKIP("Could not find unused pattern");
+ return;
+ }
+
+ T_QUIET; T_EXPECT_POSIX_SUCCESS(s = socket(AF_INET, SOCK_DGRAM, 0), "socket");
+
+ strlcpy(ifr.ifr_name, "gif0", sizeof(ifr.ifr_name));
+ ifr.ifr_dstaddr.sa_family = AF_INET6;
+ ifr.ifr_dstaddr.sa_len = 0xf0;
+ memset(&ifr.ifr_dstaddr.sa_data, pattern, PATTERN_SIZE);
+
+ T_EXPECT_POSIX_SUCCESS(ioctl(s, SIOCSIFDSTADDR, &ifr), "ioctl(SIOCSIFDSTADDR)");
+
+ close(s);
+
+ T_EXPECT_EQ(check_rt_if_list_for_pattern("AFTER", pattern, PATTERN_SIZE), 0, "pattern should not be found");
+}
diff --git a/tests/unp_connect_thread_uaf.c b/tests/unp_connect_thread_uaf.c
new file mode 100644
index 000000000..3d61b1394
--- /dev/null
+++ b/tests/unp_connect_thread_uaf.c
@@ -0,0 +1,149 @@
+/* This tests thread_t uaf vulnerability in the XNU kernel due to
+ * a race condition in unp_connect
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+int g_start = 0;
+int g_client = 0;
+int g_sever1 = 0;
+int g_sever2 = 0;
+
+static void
+server_thread1(char* path)
+{
+ struct sockaddr_un server_sockaddr;
+ memset(&server_sockaddr, 0, sizeof(struct sockaddr_un));
+ server_sockaddr.sun_family = AF_UNIX;
+ strcpy(server_sockaddr.sun_path, path);
+ unlink(server_sockaddr.sun_path);
+
+ int server_sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ g_sever1 = server_sock;
+ T_ASSERT_POSIX_SUCCESS(bind(server_sock,
+ (struct sockaddr *) &server_sockaddr, sizeof(server_sockaddr)), NULL);
+
+ /*********************************/
+ /* Listen for any client sockets */
+ /*********************************/
+ T_ASSERT_POSIX_SUCCESS(listen(server_sock, -1), NULL);
+
+ return;
+}
+
+static void
+server_thread2(char* path)
+{
+ struct sockaddr_un server_sockaddr;
+ memset(&server_sockaddr, 0, sizeof(struct sockaddr_un));
+ server_sockaddr.sun_family = AF_UNIX;
+ strcpy(server_sockaddr.sun_path, path);
+ unlink(server_sockaddr.sun_path);
+
+ int server_sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ g_sever2 = server_sock;
+ T_ASSERT_POSIX_SUCCESS(bind(server_sock,
+ (struct sockaddr *) &server_sockaddr, sizeof(server_sockaddr)), NULL);
+
+ /*********************************/
+ /* Listen for any client sockets */
+ /*********************************/
+ T_ASSERT_POSIX_SUCCESS(listen(server_sock, -1), NULL);
+
+ return;
+}
+
+static void
+try_to_connect(char* path)
+{
+ struct sockaddr_un server_sockaddr;
+ memset(&server_sockaddr, 0, sizeof(struct sockaddr_un));
+ server_sockaddr.sun_family = AF_UNIX;
+ strcpy(server_sockaddr.sun_path, path);
+ //unlink(server_sockaddr.sun_path);
+
+ while (g_start == 0) {
+ usleep(100);
+ }
+ int ret = connect(g_client, (struct sockaddr *)&server_sockaddr,
+ sizeof(server_sockaddr));
+
+ T_ASSERT_TRUE(ret == 0 || errno == EALREADY || errno == EISCONN,
+ "connect with ret: %d(%d)", ret, errno);
+}
+
+
+static void
+test_unp_connect_multithread()
+{
+ int client_sock;
+ char path[] = "/tmp/";
+ char path1[256];
+ char path2[256];
+ char path3[256];
+
+ strncpy(path1, path, 255);
+ strcat(path1, "/1");
+ strncpy(path2, path, 255);
+ strcat(path2, "/2");
+ strncpy(path3, path, 255);
+ strcat(path3, "/3");
+
+
+ for (int i = 0; i < 1024; i++) {
+ T_SETUPBEGIN;
+ server_thread1(path1);
+ server_thread2(path2);
+ T_ASSERT_POSIX_SUCCESS(client_sock = socket(AF_UNIX, SOCK_STREAM, 0), NULL);
+
+ unlink(path3);
+ struct sockaddr_un client_sockaddr;
+ client_sockaddr.sun_family = AF_UNIX;
+ strcpy(client_sockaddr.sun_path, path3);
+ T_ASSERT_POSIX_SUCCESS(bind(client_sock, (struct sockaddr *)&client_sockaddr,
+ sizeof(client_sockaddr)), NULL);
+ T_SETUPEND;
+ g_client = client_sock;
+ g_start = 0;
+ pthread_t runner1;
+ pthread_t runner2;
+ if (pthread_create(&runner1, 0, (void*)try_to_connect, path1)) {
+ T_ASSERT_FAIL("pthread_create failed");
+ }
+
+ if (pthread_create(&runner2, 0, (void*)try_to_connect, path2)) {
+ T_ASSERT_FAIL("pthread_create failed");
+ }
+ usleep(300);
+ g_start = 1;
+ pthread_join(runner1, 0);
+ pthread_join(runner2, 0);
+
+ usleep(3000);
+
+ struct socket_fdinfo si_1 = {0};
+ proc_pidfdinfo(getpid(), g_sever1, PROC_PIDFDSOCKETINFO, &si_1,
+ sizeof(si_1));
+ struct socket_fdinfo si_2 = {0};
+ proc_pidfdinfo(getpid(), g_sever2, PROC_PIDFDSOCKETINFO, &si_2,
+ sizeof(si_2));
+ if (si_1.psi.soi_incqlen || si_2.psi.soi_incqlen) {
+ close(g_sever2);
+ close(g_sever1);
+ }
+ close(client_sock);
+ close(g_sever2);
+ close(g_sever1);
+ }
+}
+
+T_DECL(unp_connect_thread_uaf, "Uaf due to multithreaded unp_connect")
+{
+ test_unp_connect_multithread();
+}
diff --git a/tools/lldbmacros/sysreg.py b/tools/lldbmacros/sysreg.py
index 376a0e202..b3fba544c 100755
--- a/tools/lldbmacros/sysreg.py
+++ b/tools/lldbmacros/sysreg.py
@@ -187,4 +187,4 @@ def _Colorify(color, msg):
_SYSREG_TO_DECODE_FUNC_MAP = {
'ESR_EL1': PrintEsrEl1Explanation
-}
+}
\ No newline at end of file
diff --git a/tools/lldbmacros/zonetriage.py b/tools/lldbmacros/zonetriage.py
index ef6f52dc0..fe58c09c6 100755
--- a/tools/lldbmacros/zonetriage.py
+++ b/tools/lldbmacros/zonetriage.py
@@ -121,4 +121,4 @@ def FindZoneBTLog(zone):
if zone == "%s" % zval.zone_name:
return "0x%lx" % zval.zlog_btlog
return None
-# EndMacro: zonetriage, zonetriage_freedelement, zonetriage_memoryleak
+# EndMacro: zonetriage, zonetriage_freedelement, zonetriage_memoryleak
\ No newline at end of file