]> git.saurik.com Git - apple/xnu.git/commitdiff
xnu-6153.141.1.tar.gz macos-10156 v6153.141.1
authorApple <opensource@apple.com>
Wed, 29 Jul 2020 21:28:34 +0000 (21:28 +0000)
committerApple <opensource@apple.com>
Wed, 29 Jul 2020 21:28:34 +0000 (21:28 +0000)
100 files changed:
bsd/kern/kern_aio.c
bsd/kern/kern_exec.c
bsd/kern/kern_exit.c
bsd/kern/kern_proc.c
bsd/kern/kern_sysctl.c
bsd/kern/mach_loader.c
bsd/kern/uipc_usrreq.c
bsd/net/content_filter.c
bsd/net/if.c
bsd/net/if_gif.c
bsd/net/if_stf.c
bsd/net/kpi_interface.c
bsd/net/necp.c
bsd/net/necp.h
bsd/netinet/flow_divert.c
bsd/netinet/in.c
bsd/netinet/ip_input.c
bsd/netinet/ip_var.h
bsd/netinet/kpi_ipfilter.c
bsd/netinet6/ah_input.c
bsd/netinet6/dest6.c
bsd/netinet6/esp_input.c
bsd/netinet6/frag6.c
bsd/netinet6/icmp6.c
bsd/netinet6/in6.c
bsd/netinet6/in6_ifattach.c
bsd/netinet6/in6_pcb.c
bsd/netinet6/in6_src.c
bsd/netinet6/in6_var.h
bsd/netinet6/ip6_input.c
bsd/netinet6/ip6_output.c
bsd/netinet6/ip6_var.h
bsd/netinet6/mld6.c
bsd/netinet6/nd6.c
bsd/netinet6/nd6_nbr.c
bsd/netinet6/nd6_rtr.c
bsd/netinet6/route6.c
bsd/netkey/key.c
bsd/nfs/nfs_socket.c
bsd/sys/proc.h
bsd/sys/reason.h
bsd/sys/vnode.h
bsd/sys/vnode_internal.h
bsd/vfs/vfs_cache.c
bsd/vfs/vfs_subr.c
config/IOKit.exports
config/MasterVersion
config/Private.exports
iokit/DriverKit/IODMACommand.iig [new file with mode: 0644]
iokit/DriverKit/IOInterruptDispatchSource.iig
iokit/IOKit/IODMACommand.h
iokit/IOKit/IOKitKeys.h
iokit/IOKit/IOService.h
iokit/Kernel/IOService.cpp
iokit/Kernel/IOUserServer.cpp
iokit/conf/files
osfmk/arm/pmap.c
osfmk/arm/status.c
osfmk/arm64/cswitch.s
osfmk/arm64/exception_asm.h
osfmk/arm64/locore.s
osfmk/arm64/pcb.c
osfmk/arm64/proc_reg.h
osfmk/arm64/sleh.c
osfmk/arm64/status.c
osfmk/i386/acpi.c
osfmk/i386/bsd_i386.c
osfmk/i386/cpuid.c
osfmk/i386/cpuid.h
osfmk/i386/fpu.c
osfmk/i386/i386_init.c
osfmk/i386/proc_reg.h
osfmk/i386/ucode.c
osfmk/i386/ucode.h
osfmk/ipc/ipc_importance.c
osfmk/ipc/ipc_kmsg.c
osfmk/ipc/ipc_mqueue.c
osfmk/ipc/mach_msg.c
osfmk/kern/exception.c
osfmk/kern/task.c
osfmk/kern/task.h
osfmk/kern/thread.h
osfmk/kern/zalloc.c
osfmk/kern/zalloc.h
osfmk/mach/arm/exception.h
osfmk/mach/message.h
osfmk/vm/vm_fault.c
osfmk/vm/vm_map.c
osfmk/vm/vm_map.h
osfmk/vm/vm_user.c
tests/IP6_EXTHDR_CHECK_61873584.c [new file with mode: 0644]
tests/Makefile
tests/ioc_str.h [new file with mode: 0644]
tests/macho_size_63133398.c [new file with mode: 0644]
tests/pfkey.c [new file with mode: 0644]
tests/proc_info.c
tests/sioc-if-addr-bounds.c [new file with mode: 0644]
tests/unp_connect_thread_uaf.c [new file with mode: 0644]
tools/lldbmacros/sysreg.py
tools/lldbmacros/zonetriage.py

index 3ad8a516da753807a270b500fe27aabc79135dbe..4a07657cbd7290c0ad91828ed7bd1db43d925dbd 100644 (file)
 #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 @@ ExitRoutine:
 __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 @@ ExitRoutine:
 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 @@ ExitRoutine:
 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 @@ ExitRoutine:
        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 @@ ExitRoutine:
 __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 @@ check_for_our_aiocbp:
                }
        } /* 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 @@ ExitThisRoutine:
                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 @@ ExitThisRoutine:
  */
 
 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 @@ ExitRoutine:
                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 @@ nowork:
 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++) {
index afa0cb8207ebcedde2c8b7568af9133b50bbda1b..a5704a7f2c56c628977cf02bc20a736adf7824d4 100644 (file)
@@ -3622,6 +3622,10 @@ bad:
                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
index 825508bf37ee77752a2b734ca0adcf255ce15d71..7349f618fd6c1bd2371bce4c336079493c55b83a 100644 (file)
@@ -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) */
index 1a11358bea2c631aade0feff61353651f177a703..01f548e798049535aa93104b00a90737993fb455 100644 (file)
@@ -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)
index edf8d8d22e72eabe235faf4422ab8e56c9590340..a6702441ce887acc5fabcf6d69f40ac695f0fb39 100644 (file)
@@ -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);
index d51e05c70f515aa613006c2d7da861227245dd83..0d91fdd482aba01cd3562a132c3b6c845a827ed3 100644 (file)
@@ -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;
index 2c4434dc2cc491f0f56809aa7d8a9783a241482c..b08bbbee7209c29353f05b67bd13c1b3cec88108 100644 (file)
@@ -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;
 
index 11b248d0cffd52d0edcca8f3fb13b00933502af6..68422f880a3099c21d9dc394747340acfc9de658 100644 (file)
@@ -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);
        }
 
index dcb728807e59aa1b923b92907331df85fd66059d..308c04b54d5d201eb02746c9fa8968d1af044c73 100644 (file)
@@ -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)) {
index 0ada425b6a731edbffb6d206b25eb216b7fbd6d3..9f9e6c574e74d9309de9e052002b133161edd7e2 100644 (file)
@@ -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 @@ end:
                /* 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 */
index 05e6087abb528330ae3173aee17f96c73528bfe5..5ceab5438c93ffbd484328bebd52051bab0767d5 100644 (file)
@@ -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));
index 2d5c6454b8f064f37c2e7381f2e78ea0e2fd2bd7..41fb91f697fc7aa3739a742c9faf63024e8dded6 100644 (file)
@@ -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;
index c73dadf89b2d019969640902efcae3a1af3f00c8..0c014f0be174d69e74fdbbcf7b5f63f9b2816c4d 100644 (file)
@@ -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 @@ done:
                soevent(inp->inp_socket, (SO_FILT_HINT_LOCKED | SO_FILT_HINT_IFDENIED));
        }
 
+       if (socket_proc) {
+               proc_rele(socket_proc);
+       }
+
        return allowed_to_receive;
 }
 
index f658ad1ed3a40e7a4d4e62238b8ea99f53c45c78..1da29404a36ac84aa47e87b8fccf193bba207c8f 100644 (file)
@@ -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;
index 83d34f1a70c317a769157d02232dabac773af4bd..a35ed9ab2daf0f9f5cdebd01e0d4447c1fba004d 100644 (file)
@@ -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;
 }
 
index f51b22b4e984cb4f19c5db0ddef0b021074619b9..1e8a637787c98fb37d40cb46dea47bab13b39c4c 100644 (file)
@@ -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;
index 1cdd96affd587207d1956599d0508083c17f4271..1c162bf8c7e1745b31128b1e0c48840eb4e03c65 100644 (file)
@@ -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@
  *
 #include <netkey/key.h>
 #endif /* IPSEC */
 
+#include <os/log.h>
+
 #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 @@ bad:
 #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 @@ pass:
                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 @@ pass:
         * 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 @@ pass:
                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;
+}
index a9ecaa856251927350a7c94c73b87dd84439de10..ab4d5336db0a8acdb88031c036388ecb8de4ecae 100644 (file)
@@ -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 {
index b783eb2141cef8f539c43ce64e40c11d8ba7e69a..a47c52b4a8cdeda3d617d2617161b0b49cc1bd39 100644 (file)
@@ -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;
index 67a664ec62312ff5c89858cf89bda424b1174436..a2620405fb346f17e84b949af739da3efc9d3b23 100644 (file)
@@ -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 @@ fail:
        }
        if (m) {
                m_freem(m);
+               *mp = NULL;
        }
        return IPPROTO_DONE;
 }
index ef80246c9c38d58fa27b43ea1e1d4eda92677dd5..48dc59cf16a41f760c6ebc9a9f0540a37f0d8df3 100644 (file)
@@ -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;
 }
index 8e99b3eb7014f154425f5acb6ca46afca13df985..849dc02af08df7f13c09d9a4f4c317adf6935fbd 100644 (file)
@@ -529,6 +529,7 @@ noreplaycheck:
                                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 @@ noreplaycheck:
                                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
index 9357d5e9960a4aad5e110fa729d0ffc2ab8d7853..001cd1f122572c1673f32c6d6a9a4b9fe878ebb8 100644 (file)
@@ -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 @@ insert:
 
 done:
        VERIFY(m == NULL);
+       *mp = m;
        if (!locked) {
                if (frag6_nfragpackets == 0) {
                        frag6_icmp6_paramprob_error(&diq6);
@@ -884,6 +900,7 @@ dropfrag:
        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;
index 042244b8364664991f7248efdbd7c420ac8893c9..b6f48a6662f7e93dfb62f27a90e76c5035fd2085 100644 (file)
@@ -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;
 
index 5ed97682799105354309706bf7af458feb963249..176bd11cc6367810288badcc7b7d00cad8144f86 100644 (file)
@@ -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);
+}
index bd4ad95c04a049fb7007cdd0759b1ed2ebc622ed..194e996e12c73a79f3350be4b444c9827667fa54 100644 (file)
@@ -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
index c1d2ff08ebd155d220983a2f29c1fb6615494270..1af6aa5836a706410f3b3f16134988f17a4303af 100644 (file)
@@ -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.
index f018e5111f0ecfe9aff7851ea87f37510f269bef..4af6fed4ad2cd617b4b08be38bbce2f10c2244b3 100644 (file)
@@ -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;
index b7c08035205e54f76de0f2b2e13caa6e7f8ffff6..bd1a424ae04d519c14007aeec541b3279d517c3d 100644 (file)
@@ -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;
index 8d9241fc1a37869ff6b1422842f7c32877c07711..0a9a2d13a78fd0170ee970b9a4ada8b7de3e53b8 100644 (file)
@@ -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@
  *
 #endif /* INET */
 #include <netinet/kpi_ipfilter_var.h>
 #include <netinet/ip6.h>
+#include <netinet/udp.h>
 #include <netinet6/in6_var.h>
 #include <netinet6/ip6_var.h>
 #include <netinet/in_pcb.h>
@@ -158,6 +159,8 @@ extern int ipsec_bypass;
 #include <net/pfvar.h>
 #endif /* PF */
 
+#include <os/log.h>
+
 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 @@ check_with_pf:
                        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 @@ check_with_pf:
        }
 
 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;
+}
index 1d2f1a9a4dff8e3396108fadb172451d348fb4d9..ccb9a37d0bbd5f6969ad25eb18c7067585cd6b47 100644 (file)
@@ -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)) {
index 3dca8411e4a9491f1f80f28712b02b15ef5ee773..a9b9cab15087f088e75ba9a584756dc5a52dc47d 100644 (file)
@@ -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);
index ba2daacdc8af07b7401cb6dc919167a3ccf63729..9f5d020bf8fd088a749278a5c22e1b5ce48c905d 100644 (file)
@@ -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 @@ out:
 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
index 0af74cc8da20f75e69f6446a4973a0af096d11e9..e55d05571e6e44c27d19eeadec7420cdf16c0914 100644 (file)
@@ -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 @@ again:
         */
 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);
index ae3e33e539e4e65aed41e4ef5b30d8593c98ed74..5b57e6387ccec3a739551136be9d2948ac303b63 100644 (file)
@@ -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;
 
index e0c8b48644f80e72db264c50e387acc4c008684c..e47f614baff6cebc06124ecc83cc03a0a64d3ce4 100644 (file)
@@ -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);
index cc0886d44464222ddd3180855aa055f858db553a..87af9c753bae7a37991a2acb19c6567a1ed3f89d 100644 (file)
@@ -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;
 }
index 87d8808975ecba901ff29c62280bd3308cd20070..2639379d1b8593fd08d4257a20493bcb715e661f 100644 (file)
@@ -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))) {
                                // <rdar://6768487> 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),
index e5c2a590ef55fac4286f6eb3ce28bb0f76d5c827..b0fad27f148ddfc3372d4824107c12d90ee98ba4 100644 (file)
@@ -1799,23 +1799,21 @@ keepsearching:
                        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;
index e427f2ebeb9124c7a12a3b600cc4d9d761498f09..65ab9901a8da10bcae24fcd31c71ddb76765917a 100644 (file)
@@ -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]);
 
index 355b59ae97c7c3a32ca91f42c87e19e598b5dea1..516521f9f5ad791532af9739c8be765bd1c5f465 100644 (file)
@@ -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
 
index 7dfb01ef2abcd2a739fa3587c19d22b1e0ecf9d9..3a727171c5201cda15e58d5b8a836cceed8d0828 100644 (file)
@@ -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
index 29d6d9f72ca4ffe48a5f6f2c9a67cfb62568770b..0bc52b141bc1f21d99eb430b21beedcfb5d7ce74 100644 (file)
@@ -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 *);
index b027e9535ec7d725527ca713a10c65ab8ae4281b..e6a80232336fd0263d435be524f65c2dc925885c 100644 (file)
@@ -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 @@ again:
 
        end = &buff[buflen - 1];
        *end = '\0';
+       mntpt_end = NULL;
 
        /*
         * holding the NAME_CACHE_LOCK in shared mode is
@@ -520,6 +523,9 @@ again:
                                goto out_unlock;
                        } else {
                                vp = vp->v_mount->mnt_vnodecovered;
+                               if (!mntpt_end && vp) {
+                                       mntpt_end = end;
+                               }
                        }
                }
        }
@@ -761,6 +767,9 @@ bad_news:
                                tvp = NULL;
                        } else {
                                tvp = tvp->v_mount->mnt_vnodecovered;
+                               if (!mntpt_end && tvp) {
+                                       mntpt_end = end;
+                               }
                        }
                }
                if (tvp == NULLVP) {
@@ -782,7 +791,10 @@ out:
        /*
         * 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 @@ out:
 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);
 }
 
 /*
index 0d44e828be508ec33dcb3fa9aaf35afe6d1abaf0..08459f52960339c5d9ace5f6d32a9718a79d3f8f 100644 (file)
@@ -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;
index d29f1f01c3a71339d73b759d1566762309cbb887..86f00a27d7ce7a271a7a77020df0b76ac8b41743 100644 (file)
@@ -8,6 +8,9 @@ __ZN22IOInterruptEventSource27getPimaryInterruptTimestampEv
 __ZN22IOInterruptEventSource31enablePrimaryInterruptTimestampEb
 
 __ZN14IOPMrootDomain11setWakeTimeEy
+
+__ZN12IODMACommand8DispatchE5IORPC
+
 _IOAlignmentToSize
 _IOBSDNameMatching
 _IOBSDRegistryEntryForDeviceTree
index 9259dc79e6684b65a6cad1a5ead9cc81fbd5aa33..3686593d58377f99d02c6e65ca7150e8d302d754 100644 (file)
@@ -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.
index 0436ff54fae04742ddf06f77139790de2213a17a..2a85477574a88f67689fb2de39c79776b815f130 100644 (file)
@@ -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 (file)
index 0000000..de4dd6d
--- /dev/null
@@ -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 <IOKit/IODMACommand.h>
+#endif
+#endif
+
+#ifndef _IOKIT_UIODMACOMMMAND_H
+#define _IOKIT_UIODMACOMMMAND_H
+
+#include <DriverKit/IOMemoryDescriptor.iig>
+#include <DriverKit/IOService.iig>
+
+// 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 */
index ecd4b5c806a4e046ffd895bd2662fe96d359fe65..855d6beb14da3cdeba5e26f25c5ac3f1e0c8f815 100644 (file)
@@ -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;
 
index adaaf4cd0e70627470b85e2ebeeab830e0018a7e..2188f95770a0afa4ed11e20b7ffa8b4aaa6e6f1e 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <IOKit/IOCommand.h>
 #include <IOKit/IOMemoryDescriptor.h>
+#include <DriverKit/IODMACommand.h>
 class IOMapper;
 class IOBufferMemoryDescriptor;
 
@@ -61,7 +62,7 @@ enum{
 
 class IODMACommand : public IOCommand
 {
-       OSDeclareDefaultStructors(IODMACommand);
+       OSDeclareDefaultStructorsWithDispatch(IODMACommand);
 
        friend class IODMAEventSource;
 
index 34da31735a939090ee57f207db5fc1ae143d0271..2e1a2fe0450a3827a95558cae3190ff7bc01ef38 100644 (file)
 // 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"
index 28c99e74c6bdd8b459cf90986090281ef01ffc18..b99bf60b006f009e4f68671c80b1c52a778f12d5 100644 (file)
@@ -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 );
index a8387bf2abe092b0b3717c1d9908db9c50a7f7a8..3189e590c73fc77ded6abf88ab76b05fed33ea62 100644 (file)
@@ -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);
index 52508a7611a58abd2984a027b12360c8948c5427..df4172f3c81587c0de8a678bb95c2c3df7e51b26 100644 (file)
@@ -35,6 +35,7 @@
 #include <IOKit/IOCatalogue.h>
 #include <IOKit/IOMemoryDescriptor.h>
 #include <IOKit/IOBufferMemoryDescriptor.h>
+#include <IOKit/IOMapper.h>
 #include <IOKit/IOLib.h>
 #include <IOKit/IOBSD.h>
 #include <IOKit/system.h>
@@ -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);
index 77b47578c5b2e5b11593978cdccd5f13af2ddb81..48db7bedffe35ee504608e1810d01194970ed11d 100644 (file)
@@ -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
 
index cd07ccabac89356de4bbdd744b28336ca96fee1c..2d082d60dad7ca152fadd6a47d6671e2aae65ead 100644 (file)
@@ -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
index 2f35514a37c24e4cab0e469871df5e68cb32016d..40c1f5e1de7f7b83abb6a853bbbb1e1db84ca582 100644 (file)
@@ -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;
 
                        /*
index c9b1893a1f8d63c4b922fe76ab0e7dd7e2b7bb22..d691acc1aa7f6a87e3860a54793816f5161633a2 100644 (file)
@@ -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
index 60aa8b83fd6ae1b62e4482e8c7a3c86dcc4949e5..8234158e991b5c588f165b93d35fa80d520d9ab9 100644 (file)
@@ -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]
index 1efc217f9af371c8d714cef165268d237c004ed7..75b314e83fc6d2c2a1344d23867298ed0d6f3af3 100644 (file)
 
        /* Save the context that was interrupted. */ 
        ldp             x2, x3, [x3, SS64_X2]
-       stp             fp, lr, [x0, SS64_FP]
        SPILL_REGISTERS KERNEL_MODE
 
        /*
 #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
index 29f2b71854aeb80fe55f911370551ceebe880836..9b2b057b1dece4ab38adff954c931911c9c9016f 100644 (file)
@@ -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);
 }
index 69533e29e132d9c83b7b45ab2cfca0c970c802a1..7226338adeb763bfcf5be0f57d22722fa66a23eb 100644 (file)
 #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)
index b6a1f10aede0d5e6e717795114e706020b76e95b..87891018b2cc7a604e548cbe70f468be544c665f 100644 (file)
@@ -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();
 }
index a9f1eec26e307eef8e38a02a564091e2f28bfa78..0d8b7c7c9b5ce5b212bf33e4ecf174cc23115dff 100644 (file)
@@ -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;
 
                /*
index ee93c2eb8d27c78782773d01c73df0202babe796..ecd26bfae7ef36297f5999ee66083e0bd7c5fcb2 100644 (file)
@@ -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 */
index 039a31bb63c4918a5cf27916f45ea52a8fdf27e4..ee93e5b10fe008f41999f23bb2fcf0deabb51f31 100644 (file)
@@ -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;
index ff6c8c1fc472cd8418a0ecd01d5dbe0b64edbb00..2187c593873f6c9e18bd072fa8f416e01862bd20 100644 (file)
@@ -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;
        }
index 146e77b1570f67b867313b19c7f56b36dda7cf49..b63bd71bb31b7a1c7cacd239d6a46f432416a5c9 100644 (file)
 #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 */
index 1d747542959d6cbc12fdd4fbe4f2a2a42d7e0cdc..2e90ed7521e6d3460eb00c89ac9c24001de7ad3b 100644 (file)
@@ -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 @@ Retry:
                        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 @@ Retry:
                        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;
index 70fa633d7c95449b35cd22dd028132081739d0a9..8c1662eea22d66b8a1e1e35b5ed9bd769e0cd394 100644 (file)
@@ -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;
        }
index 4ff579713150b220e085d570516be7c8e33f67eb..c6b8f0be9ed87a27bb508cdfcd7edbbdce31069a 100644 (file)
@@ -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@
  *
index 13925061727b24b95c675e226f4f2cd971e88e70..9c10adb4d5002429abc81acf17b9a9864cc01dc6 100644 (file)
@@ -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
        }
index e36380ba9730cdd98cdb587377aa4d73ee30c07f..9c42e0ca46d67b93b9b4ae88b95eef1a1bbd4ad0 100644 (file)
@@ -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);
index c403b9f4654a03f2c4ddfbc5ade69519cc1098e0..2b7391cd6dd2ce9eac4342b9dc9b69ab3cab6fe1 100644 (file)
@@ -2659,7 +2659,7 @@ portupdate:
 #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? */
index 3a40a39ff0620048bc55372a5f0062f36fe6b314..95ff1fb2992ca046d0da70e42922ea7aa1bb6697 100644 (file)
@@ -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)) {
index 360879748d76c9db446377ebad1bd6cdc0c907e2..7626a1ad23ac6e5311262bfe610181cf97b968c0 100644 (file)
@@ -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) {
index f367c8e00c826b2189bcdbd64d2b1b6780b15489..01a5531cfd0d20442f12bd798c5e94a74595abb7 100644 (file)
@@ -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,
index c059f1c50f5075e52d11f6b7dd02a5dc57030ff3..4cbd102c1e52fe72b766b383572541d467678ec8 100644 (file)
@@ -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);
 }
 
index df259cf29923ad330f93567a37fcf1a2aef24627..6c1d1aa80cf942fb33f6b41a1b85d14b6a6c7785 100644 (file)
 #include <security/mac_mach_internal.h>
 #endif
 
+#include <IOKit/IOBSD.h>
+
 #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) */
index 1c7ec758b822272c5ed669aef9c9a95fe7934c76..df8c779dd76b4c7443bd874368c6bcc3b25b54be 100644 (file)
@@ -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
index f5b7cf612b191fd1174487d119ccaa660befdf62..380c3ad40945ba6048f74df6e207133451a2a2fe 100644 (file)
@@ -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 */
index f25e4040768d77eda5cf7fb7878e7148ba494457..3ee2ae14fd4d76772a6efc172a3512e033959d72 100644 (file)
@@ -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=<zone>: enable per-cpu zone caching for <zone>. */
        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);
 }
 
index c5f356ff960ebbec4406ea56754131f933e9e2af..5e3caa6de090afe1f906bb60beb0a8680127d047 100644 (file)
@@ -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 */
 
index 06658bc1ea03000db61c0f1c298d76a03ab94363..42a8028247f183e29cacdc9dfbdc09766fc9f495 100644 (file)
 
 #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.
  */
index a1a3a032599a2a049184672e9b3f0481526d6bf5..cb789b57b2dab0f4981cbe8ae615a59d28be4bae 100644 (file)
@@ -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 <os/base.h>
+#include <os/overflow.h>
+#include <kern/debug.h>
+
+#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.
  */
index 0cfa661698a9cf90f409897399c50fd06a2edc19..e558508d780af6021c6524c13f1b9990d68b8b45 100644 (file)
@@ -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) &&
index ab0d87614e7a3d13ae0e22ac4d2a2087a57754ed..9aa1eb9b5a3f0cb4af7418e57797e6c4c159c0af 100644 (file)
@@ -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 @@ blunt_copy:
            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 @@ blunt_copy:
                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 @@ blunt_copy:
        }
        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 @@ blunt_copy:
                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 @@ blunt_copy:
                    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 @@ blunt_copy:
                    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 @@ blunt_copy:
 
 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
         */
index e49170c5d7ceae7d075c7fa9f64d2e1ea4931260..f56606f8f43ce3727cb070c8a58f7160bb86b9a3 100644 (file)
@@ -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,
index 027d0c99265c9e96584fcea33415a0f70c2537a0..2dc0be56b43593bff0c5d385c091b5a903384f65 100644 (file)
@@ -800,9 +800,13 @@ mach_vm_read_overwrite(
            (vm_map_size_t)size, FALSE, &copy);
 
        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, &copy);
 
        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, &copy);
 
        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, &copy);
 
        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 (file)
index 0000000..3569cde
--- /dev/null
@@ -0,0 +1,83 @@
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <net/if_var.h>
+#include <netinet/ip6.h>
+#include <darwintest.h>
+
+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);
+}
index 790dc11c114b05b4ecde7a1315a4736fc9170ed7..5fef05882c791ab6d97616a6babe7b4726f97ad3 100644 (file)
@@ -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 (file)
index 0000000..f1794bf
--- /dev/null
@@ -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 <sys/socket.h>
+#include <sys/kern_event.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+
+#include <netinet/in.h>
+
+#include <netinet6/in6_var.h>
+#include <netinet6/nd6.h>
+
+#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 (file)
index 0000000..7266fb0
--- /dev/null
@@ -0,0 +1,3223 @@
+/*
+ * rdar://63133398 (XNU: load_machfile improperly validates macho_size)
+ *
+ * Chris J-D <chrisjd@apple.com>
+ * SEAR Red Team / 2020-May-18
+ */
+#include <err.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+#include <sys/types.h>
+#include <fcntl.h>
+#include <mach/mach_host.h>
+#include <mach/processor.h>
+#include <mach/processor_info.h>
+#include <mach/vm_param.h>
+#include <mach-o/fat.h>
+#include <mach-o/loader.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <darwintest.h>
+
+#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 (file)
index 0000000..cebd5a7
--- /dev/null
@@ -0,0 +1,1778 @@
+#include <darwintest.h>
+#include <darwintest_utils.h>
+#include <dispatch/dispatch.h>
+#include <net/pfkeyv2.h>
+#include <netinet6/ipsec.h>
+#include <arpa/inet.h>
+
+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();
+}
index 51206a2f42bdb4cddd84232cfb1727715e8fbb92..5ce0747ebca6f7b29d5f5be636bd166e100e084c 100644 (file)
@@ -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 (file)
index 0000000..b7b124a
--- /dev/null
@@ -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 <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+
+#include <string.h>
+#include <unistd.h>
+
+#include <arpa/inet.h>
+
+#include <darwintest.h>
+#include <darwintest_utils.h>
+
+#include <uuid/uuid.h>
+
+#include <ifaddrs.h>
+
+#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 (file)
index 0000000..3d61b13
--- /dev/null
@@ -0,0 +1,149 @@
+/* This tests thread_t uaf vulnerability in the XNU kernel due to
+ * a race condition in unp_connect
+ */
+
+#include <sys/un.h>
+#include <sys/socket.h>
+#include <pthread.h>
+#include <sys/proc_info.h>
+#include <libproc.h>
+#include <darwintest.h>
+#include <unistd.h>
+
+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();
+}
index 376a0e20276ecbf532f8b89a24a3b8f93525745e..b3fba544c899b0a84e195ef2d7a5f270055c5751 100755 (executable)
@@ -187,4 +187,4 @@ def _Colorify(color, msg):
 
 _SYSREG_TO_DECODE_FUNC_MAP = {
     'ESR_EL1': PrintEsrEl1Explanation
-}
+}
\ No newline at end of file
index ef6f52dc09c278112533e84775a4ee84c38f4d78..fe58c09c635cc1c4cd8d743cadfb16447e3636b8 100755 (executable)
@@ -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