am b35d80f0: am 76299d19: Merge "Remove an extra register move."

* commit 'b35d80f0b0a6d87ba20aa2de594db19a0ccf93df':
  Remove an extra register move.
diff --git a/libc/Android.mk b/libc/Android.mk
index d940753..647739e 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -269,6 +269,7 @@
 	bionic/libc_init_common.c \
 	bionic/logd_write.c \
 	bionic/md5.c \
+	bionic/memmove_words.c \
 	bionic/pututline.c \
 	bionic/realpath.c \
 	bionic/sched_getaffinity.c \
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 5653c3c..bd3e4d4 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -219,7 +219,7 @@
 int           recvmsg:socketcall:17(int, struct msghdr *, unsigned int)   -1,102,-1
 
 # sockets for sh.
-int           __socketcall:__socketcall(int, unsigned long*) -1,-1,102
+int           __socketcall:socketcall(int, unsigned long*) -1,-1,102
 
 # scheduler & real-time
 int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param)  156
diff --git a/libc/arch-sh/syscalls/__socketcall.S b/libc/arch-sh/syscalls/__socketcall.S
index 864e9aa..7c705bb 100644
--- a/libc/arch-sh/syscalls/__socketcall.S
+++ b/libc/arch-sh/syscalls/__socketcall.S
@@ -14,7 +14,7 @@
 
     /* check return value */
     cmp/pz  r0
-    bt      __NR___socketcall_end
+    bt      __NR_socketcall_end
 
     /* keep error number */
     sts.l   pr, @-r15
@@ -23,10 +23,10 @@
     mov     r0, r4
     lds.l   @r15+, pr
 
-__NR___socketcall_end:
+__NR_socketcall_end:
     rts
     nop
 
     .align  2
-0:  .long   __NR___socketcall
+0:  .long   __NR_socketcall
 1:  .long   __set_syscall_errno
diff --git a/libc/bionic/md5.c b/libc/bionic/md5.c
index 087786f..1117c3b 100644
--- a/libc/bionic/md5.c
+++ b/libc/bionic/md5.c
@@ -237,7 +237,7 @@
 void
 MD5_Final (void *res, struct md5 *m)
 {
-  static unsigned char zeros[72];
+  unsigned char zeros[72];
   unsigned offset = (m->sz[0] / 8) % 64;
   unsigned int dstart = (120 - offset - 1) % 64 + 1;
 
diff --git a/libc/bionic/memmove_words.c b/libc/bionic/memmove_words.c
new file mode 100644
index 0000000..22058bc
--- /dev/null
+++ b/libc/bionic/memmove_words.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+
+/*
+ * Works like memmove(), except:
+ * - if all arguments are at least 32-bit aligned, we guarantee that we
+ *   will use operations that preserve atomicity of 32-bit values
+ * - if not, we guarantee atomicity of 16-bit values
+ *
+ * If all three arguments are not at least 16-bit aligned, the behavior
+ * of this function is undefined.  (We could remove this restriction by
+ * testing for unaligned values and punting to memmove(), but that's
+ * not currently useful.)
+ *
+ * TODO: add loop for 64-bit alignment
+ * TODO: use __builtin_prefetch
+ * TODO: write an ARM-optimized version
+ */
+void _memmove_words(void* dest, const void* src, size_t n)
+{
+    assert((((uintptr_t) dest | (uintptr_t) src | n) & 0x01) == 0);
+
+    char* d = (char*) dest;
+    const char* s = (const char*) src;
+    size_t copyCount;
+
+    /*
+     * If the source and destination pointers are the same, this is
+     * an expensive no-op.  Testing for an empty move now allows us
+     * to skip a check later.
+     */
+    if (n == 0 || d == s)
+        return;
+
+    /*
+     * Determine if the source and destination buffers will overlap if
+     * we copy data forward (i.e. *dest++ = *src++).
+     *
+     * It's okay if the destination buffer starts before the source and
+     * there is some overlap, because the reader is always ahead of the
+     * writer.
+     */
+    if (__builtin_expect((d < s) || ((size_t)(d - s) >= n), 1)) {
+        /*
+         * Copy forward.  We prefer 32-bit loads and stores even for 16-bit
+         * data, so sort that out.
+         */
+        if ((((uintptr_t) d | (uintptr_t) s) & 0x03) != 0) {
+            /*
+             * Not 32-bit aligned.  Two possibilities:
+             * (1) Congruent, we can align to 32-bit by copying one 16-bit val
+             * (2) Non-congruent, we can do one of:
+             *   a. copy whole buffer as a series of 16-bit values
+             *   b. load/store 32 bits, using shifts to ensure alignment
+             *   c. just copy the as 32-bit values and assume the CPU
+             *      will do a reasonable job
+             *
+             * We're currently using (a), which is suboptimal.
+             */
+            if ((((uintptr_t) d ^ (uintptr_t) s) & 0x03) != 0) {
+                copyCount = n;
+            } else {
+                copyCount = 2;
+            }
+            n -= copyCount;
+            copyCount /= sizeof(uint16_t);
+
+            while (copyCount--) {
+                *(uint16_t*)d = *(uint16_t*)s;
+                d += sizeof(uint16_t);
+                s += sizeof(uint16_t);
+            }
+        }
+
+        /*
+         * Copy 32-bit aligned words.
+         */
+        copyCount = n / sizeof(uint32_t);
+        while (copyCount--) {
+            *(uint32_t*)d = *(uint32_t*)s;
+            d += sizeof(uint32_t);
+            s += sizeof(uint32_t);
+        }
+
+        /*
+         * Check for leftovers.  Either we finished exactly, or we have
+         * one remaining 16-bit chunk.
+         */
+        if ((n & 0x02) != 0) {
+            *(uint16_t*)d = *(uint16_t*)s;
+        }
+    } else {
+        /*
+         * Copy backward, starting at the end.
+         */
+        d += n;
+        s += n;
+
+        if ((((uintptr_t) d | (uintptr_t) s) & 0x03) != 0) {
+            /* try for 32-bit alignment */
+            if ((((uintptr_t) d ^ (uintptr_t) s) & 0x03) != 0) {
+                copyCount = n;
+            } else {
+                copyCount = 2;
+            }
+            n -= copyCount;
+            copyCount /= sizeof(uint16_t);
+
+            while (copyCount--) {
+                d -= sizeof(uint16_t);
+                s -= sizeof(uint16_t);
+                *(uint16_t*)d = *(uint16_t*)s;
+            }
+        }
+
+        /* copy 32-bit aligned words */
+        copyCount = n / sizeof(uint32_t);
+        while (copyCount--) {
+            d -= sizeof(uint32_t);
+            s -= sizeof(uint32_t);
+            *(uint32_t*)d = *(uint32_t*)s;
+        }
+
+        /* copy leftovers */
+        if ((n & 0x02) != 0) {
+            d -= sizeof(uint16_t);
+            s -= sizeof(uint16_t);
+            *(uint16_t*)d = *(uint16_t*)s;
+        }
+    }
+}
diff --git a/libc/include/netinet/icmp6.h b/libc/include/netinet/icmp6.h
new file mode 100644
index 0000000..fbc8234
--- /dev/null
+++ b/libc/include/netinet/icmp6.h
@@ -0,0 +1,730 @@
+/*	$NetBSD: icmp6.h,v 1.40 2009/10/31 22:32:17 christos Exp $	*/
+/*	$KAME: icmp6.h,v 1.84 2003/04/23 10:26:51 itojun Exp $	*/
+
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)ip_icmp.h	8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _NETINET_ICMP6_H_
+#define _NETINET_ICMP6_H_
+
+#define ICMPV6_PLD_MAXLEN	1232	/* IPV6_MMTU - sizeof(struct ip6_hdr)
+					   - sizeof(struct icmp6_hdr) */
+
+struct icmp6_hdr {
+	u_int8_t	icmp6_type;	/* type field */
+	u_int8_t	icmp6_code;	/* code field */
+	u_int16_t	icmp6_cksum;	/* checksum field */
+	union {
+		u_int32_t	icmp6_un_data32[1]; /* type-specific field */
+		u_int16_t	icmp6_un_data16[2]; /* type-specific field */
+		u_int8_t	icmp6_un_data8[4];  /* type-specific field */
+	} icmp6_dataun;
+} __packed;
+
+#define icmp6_data32	icmp6_dataun.icmp6_un_data32
+#define icmp6_data16	icmp6_dataun.icmp6_un_data16
+#define icmp6_data8	icmp6_dataun.icmp6_un_data8
+#define icmp6_pptr	icmp6_data32[0]		/* parameter prob */
+#define icmp6_mtu	icmp6_data32[0]		/* packet too big */
+#define icmp6_id	icmp6_data16[0]		/* echo request/reply */
+#define icmp6_seq	icmp6_data16[1]		/* echo request/reply */
+#define icmp6_maxdelay	icmp6_data16[0]		/* mcast group membership */
+
+#define ICMP6_DST_UNREACH		1	/* dest unreachable, codes: */
+#define ICMP6_PACKET_TOO_BIG		2	/* packet too big */
+#define ICMP6_TIME_EXCEEDED		3	/* time exceeded, code: */
+#define ICMP6_PARAM_PROB		4	/* ip6 header bad */
+
+#define ICMP6_ECHO_REQUEST		128	/* echo service */
+#define ICMP6_ECHO_REPLY		129	/* echo reply */
+#define MLD_LISTENER_QUERY		130 	/* multicast listener query */
+#define MLD_LISTENER_REPORT		131	/* multicast listener report */
+#define MLD_LISTENER_DONE		132	/* multicast listener done */
+
+/* RFC2292 decls */
+#define ICMP6_MEMBERSHIP_QUERY		130	/* group membership query */
+#define ICMP6_MEMBERSHIP_REPORT		131	/* group membership report */
+#define ICMP6_MEMBERSHIP_REDUCTION	132	/* group membership termination */
+
+#ifndef _KERNEL
+/* the followings are for backward compatibility to old KAME apps. */
+#define MLD6_LISTENER_QUERY	MLD_LISTENER_QUERY
+#define MLD6_LISTENER_REPORT	MLD_LISTENER_REPORT
+#define MLD6_LISTENER_DONE	MLD_LISTENER_DONE
+#endif
+
+#define ND_ROUTER_SOLICIT		133	/* router solicitation */
+#define ND_ROUTER_ADVERT		134	/* router advertisement */
+#define ND_NEIGHBOR_SOLICIT		135	/* neighbor solicitation */
+#define ND_NEIGHBOR_ADVERT		136	/* neighbor advertisement */
+#define ND_REDIRECT			137	/* redirect */
+
+#define ICMP6_ROUTER_RENUMBERING	138	/* router renumbering */
+
+#define ICMP6_WRUREQUEST		139	/* who are you request */
+#define ICMP6_WRUREPLY			140	/* who are you reply */
+#define ICMP6_FQDN_QUERY		139	/* FQDN query */
+#define ICMP6_FQDN_REPLY		140	/* FQDN reply */
+#define ICMP6_NI_QUERY			139	/* node information request */
+#define ICMP6_NI_REPLY			140	/* node information reply */
+
+/* The definitions below are experimental. TBA */
+#define MLD_MTRACE_RESP			200	/* mtrace response(to sender) */
+#define MLD_MTRACE			201	/* mtrace messages */
+
+#ifndef _KERNEL
+/* the followings are for backward compatibility to old KAME apps. */
+#define MLD6_MTRACE_RESP	MLD_MTRACE_RESP
+#define MLD6_MTRACE		MLD_MTRACE
+#endif
+
+#define ICMP6_MAXTYPE			201
+
+#define ICMP6_DST_UNREACH_NOROUTE	0	/* no route to destination */
+#define ICMP6_DST_UNREACH_ADMIN	 	1	/* administratively prohibited */
+#define ICMP6_DST_UNREACH_NOTNEIGHBOR	2	/* not a neighbor(obsolete) */
+#define ICMP6_DST_UNREACH_BEYONDSCOPE	2	/* beyond scope of source address */
+#define ICMP6_DST_UNREACH_ADDR		3	/* address unreachable */
+#define ICMP6_DST_UNREACH_NOPORT	4	/* port unreachable */
+
+#define ICMP6_TIME_EXCEED_TRANSIT 	0	/* ttl==0 in transit */
+#define ICMP6_TIME_EXCEED_REASSEMBLY	1	/* ttl==0 in reass */
+
+#define ICMP6_PARAMPROB_HEADER 	 	0	/* erroneous header field */
+#define ICMP6_PARAMPROB_NEXTHEADER	1	/* unrecognized next header */
+#define ICMP6_PARAMPROB_OPTION		2	/* unrecognized option */
+
+#define ICMP6_INFOMSG_MASK		0x80	/* all informational messages */
+
+#define ICMP6_NI_SUBJ_IPV6	0	/* Query Subject is an IPv6 address */
+#define ICMP6_NI_SUBJ_FQDN	1	/* Query Subject is a Domain name */
+#define ICMP6_NI_SUBJ_IPV4	2	/* Query Subject is an IPv4 address */
+
+#define ICMP6_NI_SUCCESS	0	/* node information successful reply */
+#define ICMP6_NI_REFUSED	1	/* node information request is refused */
+#define ICMP6_NI_UNKNOWN	2	/* unknown Qtype */
+
+#define ICMP6_ROUTER_RENUMBERING_COMMAND  0	/* rr command */
+#define ICMP6_ROUTER_RENUMBERING_RESULT   1	/* rr result */
+#define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET   255	/* rr seq num reset */
+
+/* Used in kernel only */
+#define ND_REDIRECT_ONLINK	0	/* redirect to an on-link node */
+#define ND_REDIRECT_ROUTER	1	/* redirect to a better router */
+
+/*
+ * Multicast Listener Discovery
+ */
+struct mld_hdr {
+	struct icmp6_hdr	mld_icmp6_hdr;
+	struct in6_addr		mld_addr; /* multicast address */
+} __packed;
+
+/* definitions to provide backward compatibility to old KAME applications */
+#ifndef _KERNEL
+#define mld6_hdr	mld_hdr
+#define mld6_type	mld_type
+#define mld6_code	mld_code
+#define mld6_cksum	mld_cksum
+#define mld6_maxdelay	mld_maxdelay
+#define mld6_reserved	mld_reserved
+#define mld6_addr	mld_addr
+#endif
+
+/* shortcut macro definitions */
+#define mld_type	mld_icmp6_hdr.icmp6_type
+#define mld_code	mld_icmp6_hdr.icmp6_code
+#define mld_cksum	mld_icmp6_hdr.icmp6_cksum
+#define mld_maxdelay	mld_icmp6_hdr.icmp6_data16[0]
+#define mld_reserved	mld_icmp6_hdr.icmp6_data16[1]
+
+#define MLD_MINLEN			24
+
+/*
+ * Neighbor Discovery
+ */
+
+struct nd_router_solicit {	/* router solicitation */
+	struct icmp6_hdr 	nd_rs_hdr;
+	/* could be followed by options */
+} __packed;
+
+#define nd_rs_type	nd_rs_hdr.icmp6_type
+#define nd_rs_code	nd_rs_hdr.icmp6_code
+#define nd_rs_cksum	nd_rs_hdr.icmp6_cksum
+#define nd_rs_reserved	nd_rs_hdr.icmp6_data32[0]
+
+struct nd_router_advert {	/* router advertisement */
+	struct icmp6_hdr	nd_ra_hdr;
+	u_int32_t		nd_ra_reachable;	/* reachable time */
+	u_int32_t		nd_ra_retransmit;	/* retransmit timer */
+	/* could be followed by options */
+} __packed;
+
+#define nd_ra_type		nd_ra_hdr.icmp6_type
+#define nd_ra_code		nd_ra_hdr.icmp6_code
+#define nd_ra_cksum		nd_ra_hdr.icmp6_cksum
+#define nd_ra_curhoplimit	nd_ra_hdr.icmp6_data8[0]
+#define nd_ra_flags_reserved	nd_ra_hdr.icmp6_data8[1]
+#define ND_RA_FLAG_MANAGED	0x80
+#define ND_RA_FLAG_OTHER	0x40
+#define ND_RA_FLAG_HOME_AGENT	0x20
+
+/*
+ * Router preference values based on RFC4199.
+ */
+#define ND_RA_FLAG_RTPREF_MASK	0x18 /* 00011000 */
+
+#define ND_RA_FLAG_RTPREF_HIGH	0x08 /* 00001000 */
+#define ND_RA_FLAG_RTPREF_MEDIUM	0x00 /* 00000000 */
+#define ND_RA_FLAG_RTPREF_LOW	0x18 /* 00011000 */
+#define ND_RA_FLAG_RTPREF_RSV	0x10 /* 00010000 */
+
+#define nd_ra_router_lifetime	nd_ra_hdr.icmp6_data16[1]
+
+struct nd_neighbor_solicit {	/* neighbor solicitation */
+	struct icmp6_hdr	nd_ns_hdr;
+	struct in6_addr		nd_ns_target;	/*target address */
+	/* could be followed by options */
+} __packed;
+
+#define nd_ns_type		nd_ns_hdr.icmp6_type
+#define nd_ns_code		nd_ns_hdr.icmp6_code
+#define nd_ns_cksum		nd_ns_hdr.icmp6_cksum
+#define nd_ns_reserved		nd_ns_hdr.icmp6_data32[0]
+
+struct nd_neighbor_advert {	/* neighbor advertisement */
+	struct icmp6_hdr	nd_na_hdr;
+	struct in6_addr		nd_na_target;	/* target address */
+	/* could be followed by options */
+} __packed;
+
+#define nd_na_type		nd_na_hdr.icmp6_type
+#define nd_na_code		nd_na_hdr.icmp6_code
+#define nd_na_cksum		nd_na_hdr.icmp6_cksum
+#define nd_na_flags_reserved	nd_na_hdr.icmp6_data32[0]
+#if BYTE_ORDER == BIG_ENDIAN
+#define ND_NA_FLAG_ROUTER		0x80000000
+#define ND_NA_FLAG_SOLICITED		0x40000000
+#define ND_NA_FLAG_OVERRIDE		0x20000000
+#else
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define ND_NA_FLAG_ROUTER		0x80
+#define ND_NA_FLAG_SOLICITED		0x40
+#define ND_NA_FLAG_OVERRIDE		0x20
+#endif
+#endif
+
+struct nd_redirect {		/* redirect */
+	struct icmp6_hdr	nd_rd_hdr;
+	struct in6_addr		nd_rd_target;	/* target address */
+	struct in6_addr		nd_rd_dst;	/* destination address */
+	/* could be followed by options */
+} __packed;
+
+#define nd_rd_type		nd_rd_hdr.icmp6_type
+#define nd_rd_code		nd_rd_hdr.icmp6_code
+#define nd_rd_cksum		nd_rd_hdr.icmp6_cksum
+#define nd_rd_reserved		nd_rd_hdr.icmp6_data32[0]
+
+struct nd_opt_hdr {		/* Neighbor discovery option header */
+	u_int8_t	nd_opt_type;
+	u_int8_t	nd_opt_len;
+	/* followed by option specific data*/
+} __packed;
+
+#define ND_OPT_SOURCE_LINKADDR		1
+#define ND_OPT_TARGET_LINKADDR		2
+#define ND_OPT_PREFIX_INFORMATION	3
+#define ND_OPT_REDIRECTED_HEADER	4
+#define ND_OPT_MTU			5
+#define ND_OPT_ADVINTERVAL		7
+#define ND_OPT_HOMEAGENT_INFO		8
+#define ND_OPT_SOURCE_ADDRLIST		9
+#define ND_OPT_TARGET_ADDRLIST		10
+#define ND_OPT_RDNSS			25
+/* draft-ietf-ipngwg-router-preference, not officially assigned yet */
+#define ND_OPT_ROUTE_INFO		200
+/* draft-ietf-mobileip-hmipv6, not officially assigned yet */
+#define ND_OPT_MAP			201
+
+struct nd_opt_route_info {	/* route info */
+	u_int8_t	nd_opt_rti_type;
+	u_int8_t	nd_opt_rti_len;
+	u_int8_t	nd_opt_rti_prefixlen;
+	u_int8_t	nd_opt_rti_flags;
+	u_int32_t	nd_opt_rti_lifetime;
+	/* prefix follows */
+};
+
+struct nd_opt_prefix_info {	/* prefix information */
+	u_int8_t	nd_opt_pi_type;
+	u_int8_t	nd_opt_pi_len;
+	u_int8_t	nd_opt_pi_prefix_len;
+	u_int8_t	nd_opt_pi_flags_reserved;
+	u_int32_t	nd_opt_pi_valid_time;
+	u_int32_t	nd_opt_pi_preferred_time;
+	u_int32_t	nd_opt_pi_reserved2;
+	struct in6_addr	nd_opt_pi_prefix;
+} __packed;
+
+#define ND_OPT_PI_FLAG_ONLINK		0x80
+#define ND_OPT_PI_FLAG_AUTO		0x40
+
+struct nd_opt_rd_hdr {		/* redirected header */
+	u_int8_t	nd_opt_rh_type;
+	u_int8_t	nd_opt_rh_len;
+	u_int16_t	nd_opt_rh_reserved1;
+	u_int32_t	nd_opt_rh_reserved2;
+	/* followed by IP header and data */
+} __packed;
+
+struct nd_opt_mtu {		/* MTU option */
+	u_int8_t	nd_opt_mtu_type;
+	u_int8_t	nd_opt_mtu_len;
+	u_int16_t	nd_opt_mtu_reserved;
+	u_int32_t	nd_opt_mtu_mtu;
+} __packed;
+
+struct nd_opt_rdnss {		/* RDNSS option RFC 5006 */
+	u_int8_t	nd_opt_rdnss_type;
+	u_int8_t	nd_opt_rdnss_len;
+	u_int16_t	nd_opt_rdnss_reserved;
+	u_int32_t	nd_opt_rdnss_lifetime;
+	/* followed by list of IP prefixes */
+} __packed;
+
+/*
+ * icmp6 namelookup
+ */
+
+struct icmp6_namelookup {
+	struct icmp6_hdr 	icmp6_nl_hdr;
+	u_int8_t	icmp6_nl_nonce[8];
+	int32_t		icmp6_nl_ttl;
+#if 0
+	u_int8_t	icmp6_nl_len;
+	u_int8_t	icmp6_nl_name[3];
+#endif
+	/* could be followed by options */
+} __packed;
+
+/*
+ * icmp6 node information
+ */
+struct icmp6_nodeinfo {
+	struct icmp6_hdr icmp6_ni_hdr;
+	u_int8_t icmp6_ni_nonce[8];
+	/* could be followed by reply data */
+} __packed;
+
+#define ni_type		icmp6_ni_hdr.icmp6_type
+#define ni_code		icmp6_ni_hdr.icmp6_code
+#define ni_cksum	icmp6_ni_hdr.icmp6_cksum
+#define ni_qtype	icmp6_ni_hdr.icmp6_data16[0]
+#define ni_flags	icmp6_ni_hdr.icmp6_data16[1]
+
+#define NI_QTYPE_NOOP		0 /* NOOP  */
+#define NI_QTYPE_SUPTYPES	1 /* Supported Qtypes */
+#define NI_QTYPE_FQDN		2 /* FQDN (draft 04) */
+#define NI_QTYPE_DNSNAME	2 /* DNS Name */
+#define NI_QTYPE_NODEADDR	3 /* Node Addresses */
+#define NI_QTYPE_IPV4ADDR	4 /* IPv4 Addresses */
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define NI_SUPTYPE_FLAG_COMPRESS	0x1
+#define NI_FQDN_FLAG_VALIDTTL		0x1
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define NI_SUPTYPE_FLAG_COMPRESS	0x0100
+#define NI_FQDN_FLAG_VALIDTTL		0x0100
+#endif
+
+#ifdef NAME_LOOKUPS_04
+#if BYTE_ORDER == BIG_ENDIAN
+#define NI_NODEADDR_FLAG_LINKLOCAL	0x1
+#define NI_NODEADDR_FLAG_SITELOCAL	0x2
+#define NI_NODEADDR_FLAG_GLOBAL		0x4
+#define NI_NODEADDR_FLAG_ALL		0x8
+#define NI_NODEADDR_FLAG_TRUNCATE	0x10
+#define NI_NODEADDR_FLAG_ANYCAST	0x20 /* just experimental. not in spec */
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define NI_NODEADDR_FLAG_LINKLOCAL	0x0100
+#define NI_NODEADDR_FLAG_SITELOCAL	0x0200
+#define NI_NODEADDR_FLAG_GLOBAL		0x0400
+#define NI_NODEADDR_FLAG_ALL		0x0800
+#define NI_NODEADDR_FLAG_TRUNCATE	0x1000
+#define NI_NODEADDR_FLAG_ANYCAST	0x2000 /* just experimental. not in spec */
+#endif
+#else  /* draft-ietf-ipngwg-icmp-name-lookups-05 (and later?) */
+#if BYTE_ORDER == BIG_ENDIAN
+#define NI_NODEADDR_FLAG_TRUNCATE	0x1
+#define NI_NODEADDR_FLAG_ALL		0x2
+#define NI_NODEADDR_FLAG_COMPAT		0x4
+#define NI_NODEADDR_FLAG_LINKLOCAL	0x8
+#define NI_NODEADDR_FLAG_SITELOCAL	0x10
+#define NI_NODEADDR_FLAG_GLOBAL		0x20
+#define NI_NODEADDR_FLAG_ANYCAST	0x40 /* just experimental. not in spec */
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define NI_NODEADDR_FLAG_TRUNCATE	0x0100
+#define NI_NODEADDR_FLAG_ALL		0x0200
+#define NI_NODEADDR_FLAG_COMPAT		0x0400
+#define NI_NODEADDR_FLAG_LINKLOCAL	0x0800
+#define NI_NODEADDR_FLAG_SITELOCAL	0x1000
+#define NI_NODEADDR_FLAG_GLOBAL		0x2000
+#define NI_NODEADDR_FLAG_ANYCAST	0x4000 /* just experimental. not in spec */
+#endif
+#endif
+
+struct ni_reply_fqdn {
+	u_int32_t ni_fqdn_ttl;	/* TTL */
+	u_int8_t ni_fqdn_namelen; /* length in octets of the FQDN */
+	u_int8_t ni_fqdn_name[3]; /* XXX: alignment */
+} __packed;
+
+/*
+ * Router Renumbering. as router-renum-08.txt
+ */
+struct icmp6_router_renum {	/* router renumbering header */
+	struct icmp6_hdr	rr_hdr;
+	u_int8_t	rr_segnum;
+	u_int8_t	rr_flags;
+	u_int16_t	rr_maxdelay;
+	u_int32_t	rr_reserved;
+} __packed;
+
+#define ICMP6_RR_FLAGS_TEST		0x80
+#define ICMP6_RR_FLAGS_REQRESULT	0x40
+#define ICMP6_RR_FLAGS_FORCEAPPLY	0x20
+#define ICMP6_RR_FLAGS_SPECSITE		0x10
+#define ICMP6_RR_FLAGS_PREVDONE		0x08
+
+#define rr_type		rr_hdr.icmp6_type
+#define rr_code		rr_hdr.icmp6_code
+#define rr_cksum	rr_hdr.icmp6_cksum
+#define rr_seqnum 	rr_hdr.icmp6_data32[0]
+
+struct rr_pco_match {		/* match prefix part */
+	u_int8_t	rpm_code;
+	u_int8_t	rpm_len;
+	u_int8_t	rpm_ordinal;
+	u_int8_t	rpm_matchlen;
+	u_int8_t	rpm_minlen;
+	u_int8_t	rpm_maxlen;
+	u_int16_t	rpm_reserved;
+	struct	in6_addr	rpm_prefix;
+} __packed;
+
+#define RPM_PCO_ADD		1
+#define RPM_PCO_CHANGE		2
+#define RPM_PCO_SETGLOBAL	3
+#define RPM_PCO_MAX		4
+
+struct rr_pco_use {		/* use prefix part */
+	u_int8_t	rpu_uselen;
+	u_int8_t	rpu_keeplen;
+	u_int8_t	rpu_ramask;
+	u_int8_t	rpu_raflags;
+	u_int32_t	rpu_vltime;
+	u_int32_t	rpu_pltime;
+	u_int32_t	rpu_flags;
+	struct	in6_addr rpu_prefix;
+} __packed;
+#define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK	0x80
+#define ICMP6_RR_PCOUSE_RAFLAGS_AUTO	0x40
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME     0x80000000
+#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME     0x40000000
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME     0x80
+#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME     0x40
+#endif
+
+struct rr_result {		/* router renumbering result message */
+	u_int16_t	rrr_flags;
+	u_int8_t	rrr_ordinal;
+	u_int8_t	rrr_matchedlen;
+	u_int32_t	rrr_ifid;
+	struct	in6_addr rrr_prefix;
+} __packed;
+#if BYTE_ORDER == BIG_ENDIAN
+#define ICMP6_RR_RESULT_FLAGS_OOB		0x0002
+#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN		0x0001
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define ICMP6_RR_RESULT_FLAGS_OOB		0x0200
+#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN		0x0100
+#endif
+
+/*
+ * icmp6 filter structures.
+ */
+
+struct icmp6_filter {
+	u_int32_t icmp6_filt[8];
+};
+
+#define	ICMP6_FILTER_SETPASSALL(filterp) \
+	(void)memset(filterp, 0xff, sizeof(struct icmp6_filter))
+#define	ICMP6_FILTER_SETBLOCKALL(filterp) \
+	(void)memset(filterp, 0x00, sizeof(struct icmp6_filter))
+#define	ICMP6_FILTER_SETPASS(type, filterp) \
+	(((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31)))
+#define	ICMP6_FILTER_SETBLOCK(type, filterp) \
+	(((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31)))
+#define	ICMP6_FILTER_WILLPASS(type, filterp) \
+	((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
+#define	ICMP6_FILTER_WILLBLOCK(type, filterp) \
+	((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0)
+
+/*
+ * Variables related to this implementation
+ * of the internet control message protocol version 6.
+ */
+
+/*
+ * IPv6 ICMP statistics.
+ * Each counter is an unsigned 64-bit value.
+ */
+#define	ICMP6_STAT_ERROR	0	/* # of calls to icmp6_error */
+#define	ICMP6_STAT_CANTERROR	1	/* no error (old was icmp) */
+#define	ICMP6_STAT_TOOFREQ	2	/* no error (rate limitation) */
+#define	ICMP6_STAT_OUTHIST	3	/* # of output messages */
+		/* space for 256 counters */
+#define	ICMP6_STAT_BADCODE	259	/* icmp6_code out of range */
+#define	ICMP6_STAT_TOOSHORT	260	/* packet < sizeof(struct icmp6_hdr) */
+#define	ICMP6_STAT_CHECKSUM	261	/* bad checksum */
+#define	ICMP6_STAT_BADLEN	262	/* calculated bound mismatch */
+	/*
+	 * number of responses; this member is inherited from the netinet code,
+	 * but for netinet6 code, it is already available in outhist[].
+	 */
+#define	ICMP6_STAT_REFLECT	263
+#define	ICMP6_STAT_INHIST	264	/* # of input messages */
+		/* space for 256 counters */
+#define	ICMP6_STAT_ND_TOOMANYOPT 520	/* too many ND options */
+#define	ICMP6_STAT_OUTERRHIST	521
+		/* space for 13 counters */
+#define	ICMP6_STAT_PMTUCHG	534	/* path MTU changes */
+#define	ICMP6_STAT_ND_BADOPT	535	/* bad ND options */
+#define	ICMP6_STAT_BADNS	536	/* bad neighbor solicititation */
+#define	ICMP6_STAT_BADNA	537	/* bad neighbor advertisement */
+#define	ICMP6_STAT_BADRS	538	/* bad router solicitiation */
+#define	ICMP6_STAT_BADRA	539	/* bad router advertisement */
+#define	ICMP6_STAT_BADREDIRECT	540	/* bad redirect message */
+
+#define	ICMP6_NSTATS		541
+
+#define	ICMP6_ERRSTAT_DST_UNREACH_NOROUTE	0
+#define	ICMP6_ERRSTAT_DST_UNREACH_ADMIN		1
+#define	ICMP6_ERRSTAT_DST_UNREACH_BEYONDSCOPE	2
+#define	ICMP6_ERRSTAT_DST_UNREACH_ADDR		3
+#define	ICMP6_ERRSTAT_DST_UNREACH_NOPORT	4
+#define	ICMP6_ERRSTAT_PACKET_TOO_BIG		5
+#define	ICMP6_ERRSTAT_TIME_EXCEED_TRANSIT	6
+#define	ICMP6_ERRSTAT_TIME_EXCEED_REASSEMBLY	7
+#define	ICMP6_ERRSTAT_PARAMPROB_HEADER		8
+#define	ICMP6_ERRSTAT_PARAMPROB_NEXTHEADER	9
+#define	ICMP6_ERRSTAT_PARAMPROB_OPTION		10
+#define	ICMP6_ERRSTAT_REDIRECT			11
+#define	ICMP6_ERRSTAT_UNKNOWN			12
+
+/*
+ * Names for ICMP sysctl objects
+ */
+#define ICMPV6CTL_STATS		1
+#define ICMPV6CTL_REDIRACCEPT	2	/* accept/process redirects */
+#define ICMPV6CTL_REDIRTIMEOUT	3	/* redirect cache time */
+#if 0	/*obsoleted*/
+#define ICMPV6CTL_ERRRATELIMIT	5	/* ICMPv6 error rate limitation */
+#endif
+#define ICMPV6CTL_ND6_PRUNE	6
+#define ICMPV6CTL_ND6_DELAY	8
+#define ICMPV6CTL_ND6_UMAXTRIES	9
+#define ICMPV6CTL_ND6_MMAXTRIES		10
+#define ICMPV6CTL_ND6_USELOOPBACK	11
+/*#define ICMPV6CTL_ND6_PROXYALL	12	obsoleted, do not reuse here */
+#define ICMPV6CTL_NODEINFO	13
+#define ICMPV6CTL_ERRPPSLIMIT	14	/* ICMPv6 error pps limitation */
+#define ICMPV6CTL_ND6_MAXNUDHINT	15
+#define ICMPV6CTL_MTUDISC_HIWAT	16
+#define ICMPV6CTL_MTUDISC_LOWAT	17
+#define ICMPV6CTL_ND6_DEBUG	18
+#define ICMPV6CTL_ND6_DRLIST	19
+#define ICMPV6CTL_ND6_PRLIST	20
+#define	ICMPV6CTL_ND6_MAXQLEN	24
+#define ICMPV6CTL_MAXID		25
+
+#define ICMPV6CTL_NAMES { \
+	{ 0, 0 }, \
+	{ 0, 0 }, \
+	{ "rediraccept", CTLTYPE_INT }, \
+	{ "redirtimeout", CTLTYPE_INT }, \
+	{ 0, 0 }, \
+	{ 0, 0 }, \
+	{ "nd6_prune", CTLTYPE_INT }, \
+	{ 0, 0 }, \
+	{ "nd6_delay", CTLTYPE_INT }, \
+	{ "nd6_umaxtries", CTLTYPE_INT }, \
+	{ "nd6_mmaxtries", CTLTYPE_INT }, \
+	{ "nd6_useloopback", CTLTYPE_INT }, \
+	{ 0, 0 }, \
+	{ "nodeinfo", CTLTYPE_INT }, \
+	{ "errppslimit", CTLTYPE_INT }, \
+	{ "nd6_maxnudhint", CTLTYPE_INT }, \
+	{ "mtudisc_hiwat", CTLTYPE_INT }, \
+	{ "mtudisc_lowat", CTLTYPE_INT }, \
+	{ "nd6_debug", CTLTYPE_INT }, \
+	{ 0, 0 }, \
+	{ 0, 0 }, \
+	{ 0, 0 }, \
+	{ 0, 0 }, \
+	{ 0, 0 }, \
+	{ "nd6_maxqueuelen", CTLTYPE_INT }, \
+}
+
+#define RTF_PROBEMTU	RTF_PROTO1
+
+#ifdef _KERNEL
+struct	rtentry;
+struct	rttimer;
+struct	in6_multi;
+
+void	icmp6_init(void);
+void	icmp6_paramerror(struct mbuf *, int);
+void	icmp6_error(struct mbuf *, int, int, int);
+void	icmp6_error2(struct mbuf *, int, int, int, struct ifnet *);
+int	icmp6_input(struct mbuf **, int *, int);
+void	icmp6_fasttimo(void);
+void	icmp6_reflect(struct mbuf *, size_t);
+void	icmp6_prepare(struct mbuf *);
+void	icmp6_redirect_input(struct mbuf *, int);
+void	icmp6_redirect_output(struct mbuf *, struct rtentry *);
+int	icmp6_sysctl(int *, u_int, void *, size_t *, void *, size_t);
+
+void	icmp6_statinc(u_int);
+
+struct	ip6ctlparam;
+void	icmp6_mtudisc_update(struct ip6ctlparam *, int);
+void	icmp6_mtudisc_callback_register(void (*)(struct in6_addr *));
+
+/* XXX: is this the right place for these macros? */
+#define icmp6_ifstat_inc(ifp, tag) \
+do {								\
+	if (ifp)						\
+		((struct in6_ifextra *)((ifp)->if_afdata[AF_INET6]))->icmp6_ifstat->tag++; \
+} while (/*CONSTCOND*/ 0)
+
+#define icmp6_ifoutstat_inc(ifp, type, code) \
+do { \
+		icmp6_ifstat_inc(ifp, ifs6_out_msg); \
+		switch(type) { \
+		 case ICMP6_DST_UNREACH: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_dstunreach); \
+			 if (code == ICMP6_DST_UNREACH_ADMIN) \
+				 icmp6_ifstat_inc(ifp, ifs6_out_adminprohib); \
+			 break; \
+		 case ICMP6_PACKET_TOO_BIG: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_pkttoobig); \
+			 break; \
+		 case ICMP6_TIME_EXCEEDED: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_timeexceed); \
+			 break; \
+		 case ICMP6_PARAM_PROB: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_paramprob); \
+			 break; \
+		 case ICMP6_ECHO_REQUEST: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_echo); \
+			 break; \
+		 case ICMP6_ECHO_REPLY: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_echoreply); \
+			 break; \
+		 case MLD_LISTENER_QUERY: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_mldquery); \
+			 break; \
+		 case MLD_LISTENER_REPORT: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_mldreport); \
+			 break; \
+		 case MLD_LISTENER_DONE: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_mlddone); \
+			 break; \
+		 case ND_ROUTER_SOLICIT: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_routersolicit); \
+			 break; \
+		 case ND_ROUTER_ADVERT: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_routeradvert); \
+			 break; \
+		 case ND_NEIGHBOR_SOLICIT: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit); \
+			 break; \
+		 case ND_NEIGHBOR_ADVERT: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert); \
+			 break; \
+		 case ND_REDIRECT: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_redirect); \
+			 break; \
+		} \
+} while (/*CONSTCOND*/ 0)
+
+extern int	icmp6_rediraccept;	/* accept/process redirects */
+extern int	icmp6_redirtimeout;	/* cache time for redirect routes */
+#endif /* _KERNEL */
+
+#endif /* !_NETINET_ICMP6_H_ */
diff --git a/libc/include/netinet/in.h b/libc/include/netinet/in.h
index 7a4b6c7..01bf58e 100644
--- a/libc/include/netinet/in.h
+++ b/libc/include/netinet/in.h
@@ -32,6 +32,7 @@
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/in6.h>
+#include <linux/ipv6.h>
 #include <netinet/in6.h>
 
 __BEGIN_DECLS
diff --git a/libc/include/netinet/in6.h b/libc/include/netinet/in6.h
index 580a510..7f3286a 100644
--- a/libc/include/netinet/in6.h
+++ b/libc/include/netinet/in6.h
@@ -103,6 +103,7 @@
 #define IPV6_LEAVE_GROUP IPV6_DROP_MEMBERSHIP
 
 #define IN6ADDR_ANY_INIT {{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}
+#define IN6ADDR_LOOPBACK_INIT {{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1}}}
 
 #define ipv6mr_interface ipv6mr_ifindex
 
diff --git a/libc/include/netinet/ip6.h b/libc/include/netinet/ip6.h
new file mode 100644
index 0000000..aa816c2
--- /dev/null
+++ b/libc/include/netinet/ip6.h
@@ -0,0 +1,319 @@
+/*	$NetBSD: ip6.h,v 1.23 2007/12/25 18:33:46 perry Exp $	*/
+/*	$KAME: ip6.h,v 1.45 2003/06/05 04:46:38 keiichi Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)ip.h	8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _NETINET_IP6_H_
+#define _NETINET_IP6_H_
+
+/*
+ * Definition for internet protocol version 6.
+ * RFC 2460
+ */
+
+struct ip6_hdr {
+	union {
+		struct ip6_hdrctl {
+			u_int32_t ip6_un1_flow;	/* 20 bits of flow-ID */
+			u_int16_t ip6_un1_plen;	/* payload length */
+			u_int8_t  ip6_un1_nxt;	/* next header */
+			u_int8_t  ip6_un1_hlim;	/* hop limit */
+		} ip6_un1;
+		u_int8_t ip6_un2_vfc;	/* 4 bits version, top 4 bits class */
+	} ip6_ctlun;
+	struct in6_addr ip6_src;	/* source address */
+	struct in6_addr ip6_dst;	/* destination address */
+} __packed;
+
+#define ip6_vfc		ip6_ctlun.ip6_un2_vfc
+#define ip6_flow	ip6_ctlun.ip6_un1.ip6_un1_flow
+#define ip6_plen	ip6_ctlun.ip6_un1.ip6_un1_plen
+#define ip6_nxt		ip6_ctlun.ip6_un1.ip6_un1_nxt
+#define ip6_hlim	ip6_ctlun.ip6_un1.ip6_un1_hlim
+#define ip6_hops	ip6_ctlun.ip6_un1.ip6_un1_hlim
+
+#define IPV6_VERSION		0x60
+#define IPV6_VERSION_MASK	0xf0
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define IPV6_FLOWINFO_MASK	0x0fffffff	/* flow info (28 bits) */
+#define IPV6_FLOWLABEL_MASK	0x000fffff	/* flow label (20 bits) */
+#else
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define IPV6_FLOWINFO_MASK	0xffffff0f	/* flow info (28 bits) */
+#define IPV6_FLOWLABEL_MASK	0xffff0f00	/* flow label (20 bits) */
+#endif /* LITTLE_ENDIAN */
+#endif
+#if 1
+/* ECN bits proposed by Sally Floyd */
+#define IP6TOS_CE		0x01	/* congestion experienced */
+#define IP6TOS_ECT		0x02	/* ECN-capable transport */
+#endif
+
+#ifdef _KERNEL
+/*
+ * for IPv6 pseudo header checksum
+ * XXX nonstandard
+ */
+struct ip6_hdr_pseudo {
+	struct in6_addr ip6ph_src;
+	struct in6_addr ip6ph_dst;
+	u_int32_t	ip6ph_len;
+	u_int8_t	ip6ph_zero[3];
+	u_int8_t	ip6ph_nxt;
+} __packed;
+#endif
+
+/*
+ * Extension Headers
+ */
+
+struct	ip6_ext {
+	u_int8_t ip6e_nxt;
+	u_int8_t ip6e_len;
+} __packed;
+
+/* Hop-by-Hop options header */
+/* XXX should we pad it to force alignment on an 8-byte boundary? */
+struct ip6_hbh {
+	u_int8_t ip6h_nxt;	/* next header */
+	u_int8_t ip6h_len;	/* length in units of 8 octets */
+	/* followed by options */
+} __packed;
+
+/* Destination options header */
+/* XXX should we pad it to force alignment on an 8-byte boundary? */
+struct ip6_dest {
+	u_int8_t ip6d_nxt;	/* next header */
+	u_int8_t ip6d_len;	/* length in units of 8 octets */
+	/* followed by options */
+} __packed;
+
+/* Option types and related macros */
+#define IP6OPT_PAD1		0x00	/* 00 0 00000 */
+#define IP6OPT_PADN		0x01	/* 00 0 00001 */
+#define IP6OPT_JUMBO		0xC2	/* 11 0 00010 = 194 */
+#define IP6OPT_NSAP_ADDR	0xC3	/* 11 0 00011 */
+#define IP6OPT_TUNNEL_LIMIT	0x04	/* 00 0 00100 */
+#define IP6OPT_RTALERT		0x05	/* 00 0 00101 (KAME definition) */
+#define IP6OPT_ROUTER_ALERT	0x05	/* (RFC3542 def, recommended) */
+
+#define IP6OPT_RTALERT_LEN	4
+#define IP6OPT_RTALERT_MLD	0	/* Datagram contains an MLD message */
+#define IP6OPT_RTALERT_RSVP	1	/* Datagram contains an RSVP message */
+#define IP6OPT_RTALERT_ACTNET	2 	/* contains an Active Networks msg */
+#define IP6OPT_MINLEN		2
+
+#define IP6OPT_TYPE(o)		((o) & 0xC0)
+#define IP6OPT_TYPE_SKIP	0x00
+#define IP6OPT_TYPE_DISCARD	0x40
+#define IP6OPT_TYPE_FORCEICMP	0x80
+#define IP6OPT_TYPE_ICMP	0xC0
+
+#define IP6OPT_MUTABLE		0x20
+
+/* IPv6 options: common part */
+struct ip6_opt {
+	u_int8_t ip6o_type;
+	u_int8_t ip6o_len;
+} __packed;
+
+/* Jumbo Payload Option */
+struct ip6_opt_jumbo {
+	u_int8_t ip6oj_type;
+	u_int8_t ip6oj_len;
+	u_int8_t ip6oj_jumbo_len[4];
+} __packed;
+#define IP6OPT_JUMBO_LEN 6
+
+/* NSAP Address Option */
+struct ip6_opt_nsap {
+	u_int8_t ip6on_type;
+	u_int8_t ip6on_len;
+	u_int8_t ip6on_src_nsap_len;
+	u_int8_t ip6on_dst_nsap_len;
+	/* followed by source NSAP */
+	/* followed by destination NSAP */
+} __packed;
+
+/* Tunnel Limit Option */
+struct ip6_opt_tunnel {
+	u_int8_t ip6ot_type;
+	u_int8_t ip6ot_len;
+	u_int8_t ip6ot_encap_limit;
+} __packed;
+
+/* Router Alert Option */
+struct ip6_opt_router {
+	u_int8_t ip6or_type;
+	u_int8_t ip6or_len;
+	u_int8_t ip6or_value[2];
+} __packed;
+/* Router alert values (in network byte order) */
+#if BYTE_ORDER == BIG_ENDIAN
+#define IP6_ALERT_MLD	0x0000
+#define IP6_ALERT_RSVP	0x0001
+#define IP6_ALERT_AN	0x0002
+#else
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define IP6_ALERT_MLD	0x0000
+#define IP6_ALERT_RSVP	0x0100
+#define IP6_ALERT_AN	0x0200
+#endif /* LITTLE_ENDIAN */
+#endif
+
+/* Routing header */
+struct ip6_rthdr {
+	u_int8_t  ip6r_nxt;	/* next header */
+	u_int8_t  ip6r_len;	/* length in units of 8 octets */
+	u_int8_t  ip6r_type;	/* routing type */
+	u_int8_t  ip6r_segleft;	/* segments left */
+	/* followed by routing type specific data */
+} __packed;
+
+/* Type 0 Routing header */
+struct ip6_rthdr0 {
+	u_int8_t  ip6r0_nxt;		/* next header */
+	u_int8_t  ip6r0_len;		/* length in units of 8 octets */
+	u_int8_t  ip6r0_type;		/* always zero */
+	u_int8_t  ip6r0_segleft;	/* segments left */
+	u_int32_t ip6r0_reserved;	/* reserved field */
+} __packed;
+
+/* Fragment header */
+struct ip6_frag {
+	u_int8_t  ip6f_nxt;		/* next header */
+	u_int8_t  ip6f_reserved;	/* reserved field */
+	u_int16_t ip6f_offlg;		/* offset, reserved, and flag */
+	u_int32_t ip6f_ident;		/* identification */
+} __packed;
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define IP6F_OFF_MASK		0xfff8	/* mask out offset from _offlg */
+#define IP6F_RESERVED_MASK	0x0006	/* reserved bits in ip6f_offlg */
+#define IP6F_MORE_FRAG		0x0001	/* more-fragments flag */
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+#define IP6F_OFF_MASK		0xf8ff	/* mask out offset from _offlg */
+#define IP6F_RESERVED_MASK	0x0600	/* reserved bits in ip6f_offlg */
+#define IP6F_MORE_FRAG		0x0100	/* more-fragments flag */
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+/*
+ * Internet implementation parameters.
+ */
+#define IPV6_MAXHLIM	255	/* maximum hoplimit */
+#define IPV6_DEFHLIM	64	/* default hlim */
+#define IPV6_FRAGTTL	120	/* ttl for fragment packets, in slowtimo tick */
+#define IPV6_HLIMDEC	1	/* subtracted when forwarding */
+
+#define IPV6_MMTU	1280	/* minimal MTU and reassembly. 1024 + 256 */
+#define IPV6_MAXPACKET	65535	/* ip6 max packet size without Jumbo payload*/
+
+#ifdef _KERNEL
+/*
+ * IP6_EXTHDR_GET ensures that intermediate protocol header (from "off" to
+ * "len") is located in single mbuf, on contiguous memory region.
+ * The pointer to the region will be returned to pointer variable "val",
+ * with type "typ".
+ * IP6_EXTHDR_GET0 does the same, except that it aligns the structure at the
+ * very top of mbuf.  GET0 is likely to make memory copy than GET.
+ *
+ * XXX we're now testing this, needs m_pulldown()
+ */
+#define IP6_EXTHDR_GET(val, typ, m, off, len) \
+do {									\
+	struct mbuf *_t;						\
+	int _tmp;							\
+	if ((m)->m_len >= (off) + (len))				\
+		(val) = (typ)(mtod((m), char *) + (off));		\
+	else {								\
+		_t = m_pulldown((m), (off), (len), &_tmp);		\
+		if (_t) {						\
+			if (_t->m_len < _tmp + (len))			\
+				panic("m_pulldown malfunction");	\
+			(val) = (typ)(mtod(_t, char *) + _tmp);	\
+		} else {						\
+			(val) = (typ)NULL;				\
+			(m) = NULL;					\
+		}							\
+	}								\
+} while (/*CONSTCOND*/ 0)
+
+#define IP6_EXTHDR_GET0(val, typ, m, off, len) \
+do {									\
+	struct mbuf *_t;						\
+	if ((off) == 0 && (m)->m_len >= len)				\
+		(val) = (typ)mtod((m), void *);			\
+	else {								\
+		_t = m_pulldown((m), (off), (len), NULL);		\
+		if (_t) {						\
+			if (_t->m_len < (len))				\
+				panic("m_pulldown malfunction");	\
+			(val) = (typ)mtod(_t, void *);			\
+		} else {						\
+			(val) = (typ)NULL;				\
+			(m) = NULL;					\
+		}							\
+	}								\
+} while (/*CONSTCOND*/ 0)
+#endif /*_KERNEL*/
+
+#endif /* !_NETINET_IP6_H_ */
diff --git a/libc/include/sys/linux-syscalls.h b/libc/include/sys/linux-syscalls.h
index cb4d5e5..5b8e2b4 100644
--- a/libc/include/sys/linux-syscalls.h
+++ b/libc/include/sys/linux-syscalls.h
@@ -280,7 +280,7 @@
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
-#define __NR___socketcall                 (__NR_SYSCALL_BASE + 102)
+#define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
 #define __NR_getcpu                       (__NR_SYSCALL_BASE + 318)
 #define __NR_ioprio_set                   (__NR_SYSCALL_BASE + 288)
 #define __NR_ioprio_get                   (__NR_SYSCALL_BASE + 289)
diff --git a/libc/kernel/arch-arm/asm/ptrace.h b/libc/kernel/arch-arm/asm/ptrace.h
index 3faf738..a04eec3 100644
--- a/libc/kernel/arch-arm/asm/ptrace.h
+++ b/libc/kernel/arch-arm/asm/ptrace.h
@@ -64,12 +64,7 @@
 #ifndef __ASSEMBLY__
 
 struct pt_regs {
-  long uregs[18];
-};
-
-struct user_vfp {
-  unsigned long long fpregs[32];
-  unsigned long fpscr;
+ long uregs[18];
 };
 
 #define ARM_cpsr uregs[16]
diff --git a/libc/kernel/arch-arm/asm/user.h b/libc/kernel/arch-arm/asm/user.h
index 5f25850..d0baecd 100644
--- a/libc/kernel/arch-arm/asm/user.h
+++ b/libc/kernel/arch-arm/asm/user.h
@@ -58,4 +58,15 @@
 #define HOST_TEXT_START_ADDR (u.start_code)
 #define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
 
+struct user_vfp {
+ unsigned long long fpregs[32];
+ unsigned long fpscr;
+};
+
+struct user_vfp_exc {
+ unsigned long fpexc;
+ unsigned long fpinst;
+ unsigned long fpinst2;
+};
+
 #endif
diff --git a/libc/kernel/common/linux/icmpv6.h b/libc/kernel/common/linux/icmpv6.h
new file mode 100644
index 0000000..d1be8cd
--- /dev/null
+++ b/libc/kernel/common/linux/icmpv6.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _LINUX_ICMPV6_H
+#define _LINUX_ICMPV6_H
+
+#include <linux/types.h>
+#include <asm/byteorder.h>
+
+struct icmp6hdr {
+
+ __u8 icmp6_type;
+ __u8 icmp6_code;
+ __sum16 icmp6_cksum;
+
+ union {
+ __be32 un_data32[1];
+ __be16 un_data16[2];
+ __u8 un_data8[4];
+
+ struct icmpv6_echo {
+ __be16 identifier;
+ __be16 sequence;
+ } u_echo;
+
+ struct icmpv6_nd_advt {
+#ifdef __LITTLE_ENDIAN_BITFIELD
+ __u32 reserved:5,
+ override:1,
+ solicited:1,
+ router:1,
+ reserved2:24;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u32 router:1,
+ solicited:1,
+ override:1,
+ reserved:29;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+ } u_nd_advt;
+
+ struct icmpv6_nd_ra {
+ __u8 hop_limit;
+#ifdef __LITTLE_ENDIAN_BITFIELD
+ __u8 reserved:3,
+ router_pref:2,
+ home_agent:1,
+ other:1,
+ managed:1;
+
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u8 managed:1,
+ other:1,
+ home_agent:1,
+ router_pref:2,
+ reserved:3;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+ __be16 rt_lifetime;
+ } u_nd_ra;
+
+ } icmp6_dataun;
+
+#define icmp6_identifier icmp6_dataun.u_echo.identifier
+#define icmp6_sequence icmp6_dataun.u_echo.sequence
+#define icmp6_pointer icmp6_dataun.un_data32[0]
+#define icmp6_mtu icmp6_dataun.un_data32[0]
+#define icmp6_unused icmp6_dataun.un_data32[0]
+#define icmp6_maxdelay icmp6_dataun.un_data16[0]
+#define icmp6_router icmp6_dataun.u_nd_advt.router
+#define icmp6_solicited icmp6_dataun.u_nd_advt.solicited
+#define icmp6_override icmp6_dataun.u_nd_advt.override
+#define icmp6_ndiscreserved icmp6_dataun.u_nd_advt.reserved
+#define icmp6_hop_limit icmp6_dataun.u_nd_ra.hop_limit
+#define icmp6_addrconf_managed icmp6_dataun.u_nd_ra.managed
+#define icmp6_addrconf_other icmp6_dataun.u_nd_ra.other
+#define icmp6_rt_lifetime icmp6_dataun.u_nd_ra.rt_lifetime
+#define icmp6_router_pref icmp6_dataun.u_nd_ra.router_pref
+};
+
+#define ICMPV6_ROUTER_PREF_LOW 0x3
+#define ICMPV6_ROUTER_PREF_MEDIUM 0x0
+#define ICMPV6_ROUTER_PREF_HIGH 0x1
+#define ICMPV6_ROUTER_PREF_INVALID 0x2
+
+#define ICMPV6_DEST_UNREACH 1
+#define ICMPV6_PKT_TOOBIG 2
+#define ICMPV6_TIME_EXCEED 3
+#define ICMPV6_PARAMPROB 4
+
+#define ICMPV6_INFOMSG_MASK 0x80
+
+#define ICMPV6_ECHO_REQUEST 128
+#define ICMPV6_ECHO_REPLY 129
+#define ICMPV6_MGM_QUERY 130
+#define ICMPV6_MGM_REPORT 131
+#define ICMPV6_MGM_REDUCTION 132
+
+#define ICMPV6_NI_QUERY 139
+#define ICMPV6_NI_REPLY 140
+
+#define ICMPV6_MLD2_REPORT 143
+
+#define ICMPV6_DHAAD_REQUEST 144
+#define ICMPV6_DHAAD_REPLY 145
+#define ICMPV6_MOBILE_PREFIX_SOL 146
+#define ICMPV6_MOBILE_PREFIX_ADV 147
+
+#define ICMPV6_NOROUTE 0
+#define ICMPV6_ADM_PROHIBITED 1
+#define ICMPV6_NOT_NEIGHBOUR 2
+#define ICMPV6_ADDR_UNREACH 3
+#define ICMPV6_PORT_UNREACH 4
+
+#define ICMPV6_EXC_HOPLIMIT 0
+#define ICMPV6_EXC_FRAGTIME 1
+
+#define ICMPV6_HDR_FIELD 0
+#define ICMPV6_UNK_NEXTHDR 1
+#define ICMPV6_UNK_OPTION 2
+
+#define ICMPV6_FILTER 1
+
+#define ICMPV6_FILTER_BLOCK 1
+#define ICMPV6_FILTER_PASS 2
+#define ICMPV6_FILTER_BLOCKOTHERS 3
+#define ICMPV6_FILTER_PASSONLY 4
+
+struct icmp6_filter {
+ __u32 data[8];
+};
+
+#define MLD2_MODE_IS_INCLUDE 1
+#define MLD2_MODE_IS_EXCLUDE 2
+#define MLD2_CHANGE_TO_INCLUDE 3
+#define MLD2_CHANGE_TO_EXCLUDE 4
+#define MLD2_ALLOW_NEW_SOURCES 5
+#define MLD2_BLOCK_OLD_SOURCES 6
+
+#define MLD2_ALL_MCR_INIT { { { 0xff,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0,0x16 } } }
+
+#endif
diff --git a/libc/kernel/common/linux/if_arp.h b/libc/kernel/common/linux/if_arp.h
index a3df6c8..d8a4001 100644
--- a/libc/kernel/common/linux/if_arp.h
+++ b/libc/kernel/common/linux/if_arp.h
@@ -77,6 +77,7 @@
 
 #define ARPHRD_PHONET 820  
 #define ARPHRD_PHONET_PIPE 821  
+#define ARPHRD_CAIF 822  
 
 #define ARPHRD_VOID 0xFFFF  
 #define ARPHRD_NONE 0xFFFE  
@@ -111,8 +112,7 @@
 #define ATF_NETMASK 0x20  
 #define ATF_DONTPUB 0x40  
 
-struct arphdr
-{
+struct arphdr {
  __be16 ar_hrd;
  __be16 ar_pro;
  unsigned char ar_hln;
@@ -122,3 +122,4 @@
 };
 
 #endif
+
diff --git a/libc/kernel/common/linux/if_link.h b/libc/kernel/common/linux/if_link.h
index e9d77d4..4b83760 100644
--- a/libc/kernel/common/linux/if_link.h
+++ b/libc/kernel/common/linux/if_link.h
@@ -15,8 +15,7 @@
 #include <linux/types.h>
 #include <linux/netlink.h>
 
-struct rtnl_link_stats
-{
+struct rtnl_link_stats {
  __u32 rx_packets;
  __u32 tx_packets;
  __u32 rx_bytes;
@@ -45,8 +44,36 @@
  __u32 tx_compressed;
 };
 
-struct rtnl_link_ifmap
-{
+struct rtnl_link_stats64 {
+ __u64 rx_packets;
+ __u64 tx_packets;
+ __u64 rx_bytes;
+ __u64 tx_bytes;
+ __u64 rx_errors;
+ __u64 tx_errors;
+ __u64 rx_dropped;
+ __u64 tx_dropped;
+ __u64 multicast;
+ __u64 collisions;
+
+ __u64 rx_length_errors;
+ __u64 rx_over_errors;
+ __u64 rx_crc_errors;
+ __u64 rx_frame_errors;
+ __u64 rx_fifo_errors;
+ __u64 rx_missed_errors;
+
+ __u64 tx_aborted_errors;
+ __u64 tx_carrier_errors;
+ __u64 tx_fifo_errors;
+ __u64 tx_heartbeat_errors;
+ __u64 tx_window_errors;
+
+ __u64 rx_compressed;
+ __u64 tx_compressed;
+};
+
+struct rtnl_link_ifmap {
  __u64 mem_start;
  __u64 mem_end;
  __u64 base_addr;
@@ -55,8 +82,7 @@
  __u8 port;
 };
 
-enum
-{
+enum {
  IFLA_UNSPEC,
  IFLA_ADDRESS,
  IFLA_BROADCAST,
@@ -87,6 +113,11 @@
 #define IFLA_LINKINFO IFLA_LINKINFO
  IFLA_NET_NS_PID,
  IFLA_IFALIAS,
+ IFLA_NUM_VF,
+ IFLA_VFINFO_LIST,
+ IFLA_STATS64,
+ IFLA_VF_PORTS,
+ IFLA_PORT_SELF,
  __IFLA_MAX
 };
 
@@ -95,8 +126,7 @@
 #define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
 #define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
 
-enum
-{
+enum {
  IFLA_INET6_UNSPEC,
  IFLA_INET6_FLAGS,
  IFLA_INET6_CONF,
@@ -109,16 +139,14 @@
 
 #define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
 
-struct ifla_cacheinfo
-{
+struct ifla_cacheinfo {
  __u32 max_reasm_len;
  __u32 tstamp;
  __u32 reachable_time;
  __u32 retrans_time;
 };
 
-enum
-{
+enum {
  IFLA_INFO_UNSPEC,
  IFLA_INFO_KIND,
  IFLA_INFO_DATA,
@@ -128,8 +156,7 @@
 
 #define IFLA_INFO_MAX (__IFLA_INFO_MAX - 1)
 
-enum
-{
+enum {
  IFLA_VLAN_UNSPEC,
  IFLA_VLAN_ID,
  IFLA_VLAN_FLAGS,
@@ -145,8 +172,7 @@
  __u32 mask;
 };
 
-enum
-{
+enum {
  IFLA_VLAN_QOS_UNSPEC,
  IFLA_VLAN_QOS_MAPPING,
  __IFLA_VLAN_QOS_MAX
@@ -154,10 +180,123 @@
 
 #define IFLA_VLAN_QOS_MAX (__IFLA_VLAN_QOS_MAX - 1)
 
-struct ifla_vlan_qos_mapping
-{
+struct ifla_vlan_qos_mapping {
  __u32 from;
  __u32 to;
 };
 
+enum {
+ IFLA_MACVLAN_UNSPEC,
+ IFLA_MACVLAN_MODE,
+ __IFLA_MACVLAN_MAX,
+};
+
+#define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1)
+
+enum macvlan_mode {
+ MACVLAN_MODE_PRIVATE = 1,
+ MACVLAN_MODE_VEPA = 2,
+ MACVLAN_MODE_BRIDGE = 4,
+};
+
+enum {
+ IFLA_VF_INFO_UNSPEC,
+ IFLA_VF_INFO,
+ __IFLA_VF_INFO_MAX,
+};
+
+#define IFLA_VF_INFO_MAX (__IFLA_VF_INFO_MAX - 1)
+
+enum {
+ IFLA_VF_UNSPEC,
+ IFLA_VF_MAC,
+ IFLA_VF_VLAN,
+ IFLA_VF_TX_RATE,
+ __IFLA_VF_MAX,
+};
+
+#define IFLA_VF_MAX (__IFLA_VF_MAX - 1)
+
+struct ifla_vf_mac {
+ __u32 vf;
+ __u8 mac[32];
+};
+
+struct ifla_vf_vlan {
+ __u32 vf;
+ __u32 vlan;
+ __u32 qos;
+};
+
+struct ifla_vf_tx_rate {
+ __u32 vf;
+ __u32 rate;
+};
+
+struct ifla_vf_info {
+ __u32 vf;
+ __u8 mac[32];
+ __u32 vlan;
+ __u32 qos;
+ __u32 tx_rate;
+};
+
+enum {
+ IFLA_VF_PORT_UNSPEC,
+ IFLA_VF_PORT,
+ __IFLA_VF_PORT_MAX,
+};
+
+#define IFLA_VF_PORT_MAX (__IFLA_VF_PORT_MAX - 1)
+
+enum {
+ IFLA_PORT_UNSPEC,
+ IFLA_PORT_VF,
+ IFLA_PORT_PROFILE,
+ IFLA_PORT_VSI_TYPE,
+ IFLA_PORT_INSTANCE_UUID,
+ IFLA_PORT_HOST_UUID,
+ IFLA_PORT_REQUEST,
+ IFLA_PORT_RESPONSE,
+ __IFLA_PORT_MAX,
+};
+
+#define IFLA_PORT_MAX (__IFLA_PORT_MAX - 1)
+
+#define PORT_PROFILE_MAX 40
+#define PORT_UUID_MAX 16
+#define PORT_SELF_VF -1
+
+enum {
+ PORT_REQUEST_PREASSOCIATE = 0,
+ PORT_REQUEST_PREASSOCIATE_RR,
+ PORT_REQUEST_ASSOCIATE,
+ PORT_REQUEST_DISASSOCIATE,
+};
+
+enum {
+ PORT_VDP_RESPONSE_SUCCESS = 0,
+ PORT_VDP_RESPONSE_INVALID_FORMAT,
+ PORT_VDP_RESPONSE_INSUFFICIENT_RESOURCES,
+ PORT_VDP_RESPONSE_UNUSED_VTID,
+ PORT_VDP_RESPONSE_VTID_VIOLATION,
+ PORT_VDP_RESPONSE_VTID_VERSION_VIOALTION,
+ PORT_VDP_RESPONSE_OUT_OF_SYNC,
+
+ PORT_PROFILE_RESPONSE_SUCCESS = 0x100,
+ PORT_PROFILE_RESPONSE_INPROGRESS,
+ PORT_PROFILE_RESPONSE_INVALID,
+ PORT_PROFILE_RESPONSE_BADSTATE,
+ PORT_PROFILE_RESPONSE_INSUFFICIENT_RESOURCES,
+ PORT_PROFILE_RESPONSE_ERROR,
+};
+
+struct ifla_port_vsi {
+ __u8 vsi_mgr_id;
+ __u8 vsi_type_id[3];
+ __u8 vsi_type_version;
+ __u8 pad[3];
+};
+
 #endif
+
diff --git a/libc/kernel/common/linux/if_tun.h b/libc/kernel/common/linux/if_tun.h
index c5db4e0..9ed49f1 100644
--- a/libc/kernel/common/linux/if_tun.h
+++ b/libc/kernel/common/linux/if_tun.h
@@ -12,6 +12,10 @@
 #ifndef __IF_TUN_H
 #define __IF_TUN_H
 
+#include <linux/types.h>
+#include <linux/if_ether.h>
+#include <linux/filter.h>
+
 #define TUN_READQ_SIZE 500
 
 #define TUN_TUN_DEV 0x0001 
@@ -23,6 +27,7 @@
 #define TUN_NO_PI 0x0040
 #define TUN_ONE_QUEUE 0x0080
 #define TUN_PERSIST 0x0100 
+#define TUN_VNET_HDR 0x0200
 
 #define TUNSETNOCSUM _IOW('T', 200, int) 
 #define TUNSETDEBUG _IOW('T', 201, int) 
@@ -30,16 +35,43 @@
 #define TUNSETPERSIST _IOW('T', 203, int) 
 #define TUNSETOWNER _IOW('T', 204, int)
 #define TUNSETLINK _IOW('T', 205, int)
+#define TUNSETGROUP _IOW('T', 206, int)
+#define TUNGETFEATURES _IOR('T', 207, unsigned int)
+#define TUNSETOFFLOAD _IOW('T', 208, unsigned int)
+#define TUNSETTXFILTER _IOW('T', 209, unsigned int)
+#define TUNGETIFF _IOR('T', 210, unsigned int)
+#define TUNGETSNDBUF _IOR('T', 211, int)
+#define TUNSETSNDBUF _IOW('T', 212, int)
+#define TUNATTACHFILTER _IOW('T', 213, struct sock_fprog)
+#define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog)
+#define TUNGETVNETHDRSZ _IOR('T', 215, int)
+#define TUNSETVNETHDRSZ _IOW('T', 216, int)
 
 #define IFF_TUN 0x0001
 #define IFF_TAP 0x0002
 #define IFF_NO_PI 0x1000
 #define IFF_ONE_QUEUE 0x2000
+#define IFF_VNET_HDR 0x4000
+#define IFF_TUN_EXCL 0x8000
 
-struct tun_pi {
- unsigned short flags;
- unsigned short proto;
-};
+#define TUN_F_CSUM 0x01  
+#define TUN_F_TSO4 0x02  
+#define TUN_F_TSO6 0x04  
+#define TUN_F_TSO_ECN 0x08  
+#define TUN_F_UFO 0x10  
+
 #define TUN_PKT_STRIP 0x0001
+struct tun_pi {
+ __u16 flags;
+ __be16 proto;
+};
+
+#define TUN_FLT_ALLMULTI 0x0001  
+struct tun_filter {
+ __u16 flags;
+ __u16 count;
+ __u8 addr[0][ETH_ALEN];
+};
 
 #endif
+
diff --git a/libc/kernel/common/linux/in6.h b/libc/kernel/common/linux/in6.h
index ceaeb7d..d148dfd 100644
--- a/libc/kernel/common/linux/in6.h
+++ b/libc/kernel/common/linux/in6.h
@@ -14,25 +14,21 @@
 
 #include <linux/types.h>
 
-struct in6_addr
-{
- union
- {
+struct in6_addr {
+ union {
  __u8 u6_addr8[16];
- __u16 u6_addr16[8];
- __u32 u6_addr32[4];
+ __be16 u6_addr16[8];
+ __be32 u6_addr32[4];
  } in6_u;
 #define s6_addr in6_u.u6_addr8
 #define s6_addr16 in6_u.u6_addr16
 #define s6_addr32 in6_u.u6_addr32
 };
 
-#define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }
-
 struct sockaddr_in6 {
  unsigned short int sin6_family;
- __u16 sin6_port;
- __u32 sin6_flowinfo;
+ __be16 sin6_port;
+ __be32 sin6_flowinfo;
  struct in6_addr sin6_addr;
  __u32 sin6_scope_id;
 };
@@ -46,10 +42,9 @@
 
 #define ipv6mr_acaddr ipv6mr_multiaddr
 
-struct in6_flowlabel_req
-{
+struct in6_flowlabel_req {
  struct in6_addr flr_dst;
- __u32 flr_label;
+ __be32 flr_label;
  __u8 flr_action;
  __u8 flr_share;
  __u16 flr_flags;
@@ -98,11 +93,13 @@
 #define IPPROTO_ICMPV6 58  
 #define IPPROTO_NONE 59  
 #define IPPROTO_DSTOPTS 60  
+#define IPPROTO_MH 135  
 
 #define IPV6_TLV_PAD0 0
 #define IPV6_TLV_PADN 1
 #define IPV6_TLV_ROUTERALERT 5
 #define IPV6_TLV_JUMBO 194
+#define IPV6_TLV_HAO 201  
 
 #define IPV6_ADDRFORM 1
 #define IPV6_2292PKTINFO 2
@@ -133,6 +130,7 @@
 #define IPV6_PMTUDISC_DONT 0
 #define IPV6_PMTUDISC_WANT 1
 #define IPV6_PMTUDISC_DO 2
+#define IPV6_PMTUDISC_PROBE 3
 
 #define IPV6_FLOWLABEL_MGR 32
 #define IPV6_FLOWINFO_SEND 33
@@ -151,8 +149,27 @@
 #define IPV6_RTHDR 57
 #define IPV6_RECVDSTOPTS 58
 #define IPV6_DSTOPTS 59
+#define IPV6_RECVPATHMTU 60
+#define IPV6_PATHMTU 61
+#define IPV6_DONTFRAG 62
 
 #define IPV6_RECVTCLASS 66
 #define IPV6_TCLASS 67
 
+#define IPV6_ADDR_PREFERENCES 72
+
+#define IPV6_PREFER_SRC_TMP 0x0001
+#define IPV6_PREFER_SRC_PUBLIC 0x0002
+#define IPV6_PREFER_SRC_PUBTMP_DEFAULT 0x0100
+#define IPV6_PREFER_SRC_COA 0x0004
+#define IPV6_PREFER_SRC_HOME 0x0400
+#define IPV6_PREFER_SRC_CGA 0x0008
+#define IPV6_PREFER_SRC_NONCGA 0x0800
+
+#define IPV6_MINHOPCOUNT 73
+
+#define IPV6_ORIGDSTADDR 74
+#define IPV6_RECVORIGDSTADDR IPV6_ORIGDSTADDR
+#define IPV6_TRANSPARENT 75
+
 #endif
diff --git a/libc/kernel/common/linux/ipv6.h b/libc/kernel/common/linux/ipv6.h
new file mode 100644
index 0000000..f4ee9a1
--- /dev/null
+++ b/libc/kernel/common/linux/ipv6.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _IPV6_H
+#define _IPV6_H
+
+#include <linux/types.h>
+#include <linux/in6.h>
+#include <asm/byteorder.h>
+
+#define IPV6_MIN_MTU 1280
+
+struct in6_pktinfo {
+ struct in6_addr ipi6_addr;
+ int ipi6_ifindex;
+};
+
+struct ip6_mtuinfo {
+ struct sockaddr_in6 ip6m_addr;
+ __u32 ip6m_mtu;
+};
+
+struct in6_ifreq {
+ struct in6_addr ifr6_addr;
+ __u32 ifr6_prefixlen;
+ int ifr6_ifindex;
+};
+
+#define IPV6_SRCRT_STRICT 0x01  
+#define IPV6_SRCRT_TYPE_0 0  
+#define IPV6_SRCRT_TYPE_2 2  
+
+struct ipv6_rt_hdr {
+ __u8 nexthdr;
+ __u8 hdrlen;
+ __u8 type;
+ __u8 segments_left;
+
+};
+
+struct ipv6_opt_hdr {
+ __u8 nexthdr;
+ __u8 hdrlen;
+
+} __attribute__((packed));
+
+#define ipv6_destopt_hdr ipv6_opt_hdr
+#define ipv6_hopopt_hdr ipv6_opt_hdr
+
+struct rt0_hdr {
+ struct ipv6_rt_hdr rt_hdr;
+ __u32 reserved;
+ struct in6_addr addr[0];
+
+#define rt0_type rt_hdr.type
+};
+
+struct rt2_hdr {
+ struct ipv6_rt_hdr rt_hdr;
+ __u32 reserved;
+ struct in6_addr addr;
+
+#define rt2_type rt_hdr.type
+};
+
+struct ipv6_destopt_hao {
+ __u8 type;
+ __u8 length;
+ struct in6_addr addr;
+} __attribute__((packed));
+
+struct ipv6hdr {
+#ifdef __LITTLE_ENDIAN_BITFIELD
+ __u8 priority:4,
+ version:4;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+ __u8 version:4,
+ priority:4;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
+ __u8 flow_lbl[3];
+
+ __be16 payload_len;
+ __u8 nexthdr;
+ __u8 hop_limit;
+
+ struct in6_addr saddr;
+ struct in6_addr daddr;
+};
+
+enum {
+ DEVCONF_FORWARDING = 0,
+ DEVCONF_HOPLIMIT,
+ DEVCONF_MTU6,
+ DEVCONF_ACCEPT_RA,
+ DEVCONF_ACCEPT_REDIRECTS,
+ DEVCONF_AUTOCONF,
+ DEVCONF_DAD_TRANSMITS,
+ DEVCONF_RTR_SOLICITS,
+ DEVCONF_RTR_SOLICIT_INTERVAL,
+ DEVCONF_RTR_SOLICIT_DELAY,
+ DEVCONF_USE_TEMPADDR,
+ DEVCONF_TEMP_VALID_LFT,
+ DEVCONF_TEMP_PREFERED_LFT,
+ DEVCONF_REGEN_MAX_RETRY,
+ DEVCONF_MAX_DESYNC_FACTOR,
+ DEVCONF_MAX_ADDRESSES,
+ DEVCONF_FORCE_MLD_VERSION,
+ DEVCONF_ACCEPT_RA_DEFRTR,
+ DEVCONF_ACCEPT_RA_PINFO,
+ DEVCONF_ACCEPT_RA_RTR_PREF,
+ DEVCONF_RTR_PROBE_INTERVAL,
+ DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN,
+ DEVCONF_PROXY_NDP,
+ DEVCONF_OPTIMISTIC_DAD,
+ DEVCONF_ACCEPT_SOURCE_ROUTE,
+ DEVCONF_MC_FORWARDING,
+ DEVCONF_DISABLE_IPV6,
+ DEVCONF_ACCEPT_DAD,
+ DEVCONF_FORCE_TLLAO,
+ DEVCONF_MAX
+};
+
+#endif
diff --git a/libc/kernel/common/linux/mroute6.h b/libc/kernel/common/linux/mroute6.h
new file mode 100644
index 0000000..2b151b9
--- /dev/null
+++ b/libc/kernel/common/linux/mroute6.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __LINUX_MROUTE6_H
+#define __LINUX_MROUTE6_H
+
+#include <linux/types.h>
+#include <linux/sockios.h>
+
+#define MRT6_BASE 200
+#define MRT6_INIT (MRT6_BASE)  
+#define MRT6_DONE (MRT6_BASE+1)  
+#define MRT6_ADD_MIF (MRT6_BASE+2)  
+#define MRT6_DEL_MIF (MRT6_BASE+3)  
+#define MRT6_ADD_MFC (MRT6_BASE+4)  
+#define MRT6_DEL_MFC (MRT6_BASE+5)  
+#define MRT6_VERSION (MRT6_BASE+6)  
+#define MRT6_ASSERT (MRT6_BASE+7)  
+#define MRT6_PIM (MRT6_BASE+8)  
+#define MRT6_TABLE (MRT6_BASE+9)  
+
+#define SIOCGETMIFCNT_IN6 SIOCPROTOPRIVATE  
+#define SIOCGETSGCNT_IN6 (SIOCPROTOPRIVATE+1)
+#define SIOCGETRPF (SIOCPROTOPRIVATE+2)
+
+#define MAXMIFS 32
+typedef unsigned long mifbitmap_t;
+typedef unsigned short mifi_t;
+#define ALL_MIFS ((mifi_t)(-1))
+
+#ifndef IF_SETSIZE
+#define IF_SETSIZE 256
+#endif
+
+typedef __u32 if_mask;
+#define NIFBITS (sizeof(if_mask) * 8)  
+
+#ifndef DIV_ROUND_UP
+#define DIV_ROUND_UP(x,y) (((x) + ((y) - 1)) / (y))
+#endif
+
+typedef struct if_set {
+ if_mask ifs_bits[DIV_ROUND_UP(IF_SETSIZE, NIFBITS)];
+} if_set;
+
+#define IF_SET(n, p) ((p)->ifs_bits[(n)/NIFBITS] |= (1 << ((n) % NIFBITS)))
+#define IF_CLR(n, p) ((p)->ifs_bits[(n)/NIFBITS] &= ~(1 << ((n) % NIFBITS)))
+#define IF_ISSET(n, p) ((p)->ifs_bits[(n)/NIFBITS] & (1 << ((n) % NIFBITS)))
+#define IF_COPY(f, t) bcopy(f, t, sizeof(*(f)))
+#define IF_ZERO(p) bzero(p, sizeof(*(p)))
+
+struct mif6ctl {
+ mifi_t mif6c_mifi;
+ unsigned char mif6c_flags;
+ unsigned char vifc_threshold;
+ __u16 mif6c_pifi;
+ unsigned int vifc_rate_limit;
+};
+
+#define MIFF_REGISTER 0x1  
+
+struct mf6cctl {
+ struct sockaddr_in6 mf6cc_origin;
+ struct sockaddr_in6 mf6cc_mcastgrp;
+ mifi_t mf6cc_parent;
+ struct if_set mf6cc_ifset;
+};
+
+struct sioc_sg_req6 {
+ struct sockaddr_in6 src;
+ struct sockaddr_in6 grp;
+ unsigned long pktcnt;
+ unsigned long bytecnt;
+ unsigned long wrong_if;
+};
+
+struct sioc_mif_req6 {
+ mifi_t mifi;
+ unsigned long icount;
+ unsigned long ocount;
+ unsigned long ibytes;
+ unsigned long obytes;
+};
+
+struct mrt6msg {
+#define MRT6MSG_NOCACHE 1
+#define MRT6MSG_WRONGMIF 2
+#define MRT6MSG_WHOLEPKT 3  
+ __u8 im6_mbz;
+ __u8 im6_msgtype;
+ __u16 im6_mif;
+ __u32 im6_pad;
+ struct in6_addr im6_src, im6_dst;
+};
+
+#endif
diff --git a/libc/kernel/common/linux/netfilter_ipv6.h b/libc/kernel/common/linux/netfilter_ipv6.h
index 0d68cd9..ce2f12c 100644
--- a/libc/kernel/common/linux/netfilter_ipv6.h
+++ b/libc/kernel/common/linux/netfilter_ipv6.h
@@ -52,13 +52,13 @@
 enum nf_ip6_hook_priorities {
  NF_IP6_PRI_FIRST = INT_MIN,
  NF_IP6_PRI_CONNTRACK_DEFRAG = -400,
+ NF_IP6_PRI_RAW = -300,
  NF_IP6_PRI_SELINUX_FIRST = -225,
  NF_IP6_PRI_CONNTRACK = -200,
- NF_IP6_PRI_BRIDGE_SABOTAGE_FORWARD = -175,
  NF_IP6_PRI_MANGLE = -150,
  NF_IP6_PRI_NAT_DST = -100,
- NF_IP6_PRI_BRIDGE_SABOTAGE_LOCAL_OUT = -50,
  NF_IP6_PRI_FILTER = 0,
+ NF_IP6_PRI_SECURITY = 50,
  NF_IP6_PRI_NAT_SRC = 100,
  NF_IP6_PRI_SELINUX_LAST = 225,
  NF_IP6_PRI_LAST = INT_MAX,
diff --git a/libc/kernel/common/linux/rtnetlink.h b/libc/kernel/common/linux/rtnetlink.h
index e305505..bbd991a 100644
--- a/libc/kernel/common/linux/rtnetlink.h
+++ b/libc/kernel/common/linux/rtnetlink.h
@@ -18,6 +18,10 @@
 #include <linux/if_addr.h>
 #include <linux/neighbour.h>
 
+#define RTNL_FAMILY_IPMR 128
+#define RTNL_FAMILY_IP6MR 129
+#define RTNL_FAMILY_MAX 129
+
 enum {
  RTM_BASE = 16,
 #define RTM_BASE RTM_BASE
@@ -126,8 +130,7 @@
 #define RTM_NR_FAMILIES (RTM_NR_MSGTYPES >> 2)
 #define RTM_FAM(cmd) (((cmd) - RTM_BASE) >> 2)
 
-struct rtattr
-{
+struct rtattr {
  unsigned short rta_len;
  unsigned short rta_type;
 };
@@ -141,8 +144,7 @@
 #define RTA_DATA(rta) ((void*)(((char*)(rta)) + RTA_LENGTH(0)))
 #define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
 
-struct rtmsg
-{
+struct rtmsg {
  unsigned char rtm_family;
  unsigned char rtm_dst_len;
  unsigned char rtm_src_len;
@@ -156,8 +158,7 @@
  unsigned rtm_flags;
 };
 
-enum
-{
+enum {
  RTN_UNSPEC,
  RTN_UNICAST,
  RTN_LOCAL,
@@ -191,8 +192,7 @@
 #define RTPROT_NTK 15  
 #define RTPROT_DHCP 16  
 
-enum rt_scope_t
-{
+enum rt_scope_t {
  RT_SCOPE_UNIVERSE=0,
 
  RT_SCOPE_SITE=200,
@@ -206,8 +206,7 @@
 #define RTM_F_EQUALIZE 0x400  
 #define RTM_F_PREFIX 0x800  
 
-enum rt_class_t
-{
+enum rt_class_t {
  RT_TABLE_UNSPEC=0,
 
  RT_TABLE_COMPAT=252,
@@ -217,8 +216,7 @@
  RT_TABLE_MAX=0xFFFFFFFF
 };
 
-enum rtattr_type_t
-{
+enum rtattr_type_t {
  RTA_UNSPEC,
  RTA_DST,
  RTA_SRC,
@@ -235,6 +233,7 @@
  RTA_SESSION,
  RTA_MP_ALGO,
  RTA_TABLE,
+ RTA_MARK,
  __RTA_MAX
 };
 
@@ -243,8 +242,7 @@
 #define RTM_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtmsg))))
 #define RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtmsg))
 
-struct rtnexthop
-{
+struct rtnexthop {
  unsigned short rtnh_len;
  unsigned char rtnh_flags;
  unsigned char rtnh_hops;
@@ -263,8 +261,7 @@
 #define RTNH_SPACE(len) RTNH_ALIGN(RTNH_LENGTH(len))
 #define RTNH_DATA(rtnh) ((struct rtattr*)(((char*)(rtnh)) + RTNH_LENGTH(0)))
 
-struct rta_cacheinfo
-{
+struct rta_cacheinfo {
  __u32 rta_clntref;
  __u32 rta_lastuse;
  __s32 rta_expires;
@@ -277,8 +274,7 @@
  __u32 rta_tsage;
 };
 
-enum
-{
+enum {
  RTAX_UNSPEC,
 #define RTAX_UNSPEC RTAX_UNSPEC
  RTAX_LOCK,
@@ -307,6 +303,8 @@
 #define RTAX_FEATURES RTAX_FEATURES
  RTAX_RTO_MIN,
 #define RTAX_RTO_MIN RTAX_RTO_MIN
+ RTAX_INITRWND,
+#define RTAX_INITRWND RTAX_INITRWND
  __RTAX_MAX
 };
 
@@ -317,8 +315,7 @@
 #define RTAX_FEATURE_TIMESTAMP 0x00000004
 #define RTAX_FEATURE_ALLFRAG 0x00000008
 
-struct rta_session
-{
+struct rta_session {
  __u8 proto;
  __u8 pad1;
  __u16 pad2;
@@ -339,13 +336,11 @@
  } u;
 };
 
-struct rtgenmsg
-{
+struct rtgenmsg {
  unsigned char rtgen_family;
 };
 
-struct ifinfomsg
-{
+struct ifinfomsg {
  unsigned char ifi_family;
  unsigned char __ifi_pad;
  unsigned short ifi_type;
@@ -354,8 +349,7 @@
  unsigned ifi_change;
 };
 
-struct prefixmsg
-{
+struct prefixmsg {
  unsigned char prefix_family;
  unsigned char prefix_pad1;
  unsigned short prefix_pad2;
@@ -376,14 +370,12 @@
 
 #define PREFIX_MAX (__PREFIX_MAX - 1)
 
-struct prefix_cacheinfo
-{
+struct prefix_cacheinfo {
  __u32 preferred_time;
  __u32 valid_time;
 };
 
-struct tcmsg
-{
+struct tcmsg {
  unsigned char tcm_family;
  unsigned char tcm__pad1;
  unsigned short tcm__pad2;
@@ -393,8 +385,7 @@
  __u32 tcm_info;
 };
 
-enum
-{
+enum {
  TCA_UNSPEC,
  TCA_KIND,
  TCA_OPTIONS,
@@ -412,8 +403,7 @@
 #define TCA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg))))
 #define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg))
 
-struct nduseroptmsg
-{
+struct nduseroptmsg {
  unsigned char nduseropt_family;
  unsigned char nduseropt_pad1;
  unsigned short nduseropt_opts_len;
@@ -425,8 +415,7 @@
 
 };
 
-enum
-{
+enum {
  NDUSEROPT_UNSPEC,
  NDUSEROPT_SRCADDR,
  __NDUSEROPT_MAX
@@ -503,8 +492,7 @@
 };
 #define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
 
-struct tcamsg
-{
+struct tcamsg {
  unsigned char tca_family;
  unsigned char tca__pad1;
  unsigned short tca__pad2;
@@ -515,3 +503,4 @@
 #define TCAA_MAX 1
 
 #endif
+
diff --git a/libc/kernel/tools/clean_header.py b/libc/kernel/tools/clean_header.py
index dad9120..94b19ce 100755
--- a/libc/kernel/tools/clean_header.py
+++ b/libc/kernel/tools/clean_header.py
@@ -7,12 +7,12 @@
 
 noUpdate = 1
 
-def  cleanupFile( path ):
+def  cleanupFile( path, original_path=kernel_original_path ):
     """reads an original header and perform the cleanup operation on it
        this functions returns the destination path and the clean header
        as a single string"""
     # check the header path
-    src_path    = path
+    src_path = path
 
     if not os.path.exists(src_path):
         if noUpdate:
@@ -26,7 +26,6 @@
         sys.stderr.write( "warning: not a file: %s\n" % path )
         return None, None
 
-    original_path = kernel_original_path
     if os.path.commonprefix( [ src_path, original_path ] ) != original_path:
         if noUpdate:
             panic( "file is not in 'original' directory: %s\n" % path );
@@ -54,27 +53,27 @@
     else:
         dst_path = "common/" + src_path
 
-    dst_path = os.path.normpath( original_path + "/../" + dst_path )
+    dst_path = os.path.normpath( kernel_cleaned_path + "/" + dst_path )
 
     # now, let's parse the file
     #
-    list = cpp.BlockParser().parseFile(path)
-    if not list:
+    blocks = cpp.BlockParser().parseFile(path)
+    if not blocks:
         sys.stderr.write( "error: can't parse '%s'" % path )
         sys.exit(1)
 
 
-    list.optimizeMacros( kernel_known_macros )
-    list.optimizeIf01()
-    list.removeVarsAndFuncs( statics )
-    list.removeComments()
-    list.removeEmptyLines()
-    list.removeMacroDefines( kernel_ignored_macros )
-    list.insertDisclaimer( kernel.kernel_disclaimer )
-    list.replaceTokens( kernel_token_replacements )
+    blocks.optimizeMacros( kernel_known_macros )
+    blocks.optimizeIf01()
+    blocks.removeVarsAndFuncs( statics )
+    blocks.replaceTokens( kernel_token_replacements )
+    blocks.removeComments()
+    blocks.removeMacroDefines( kernel_ignored_macros )
+    blocks.removeWhiteSpace()
 
     out = StringOutput()
-    list.write(out)
+    out.write( kernel_disclaimer )
+    blocks.writeWithWarning(out, kernel_warning, 4)
     return dst_path, out.get()
 
 
@@ -92,12 +91,15 @@
                 if the content has changed. with this, you can pass more
                 than one file on the command-line
 
+            -k<path>  specify path of original kernel headers
+            -d<path>  specify path of cleaned kernel headers
+
         <header_path> must be in a subdirectory of 'original'
     """ % os.path.basename(sys.argv[0])
         sys.exit(1)
 
     try:
-        optlist, args = getopt.getopt( sys.argv[1:], 'uvk:' )
+        optlist, args = getopt.getopt( sys.argv[1:], 'uvk:d:' )
     except:
         # unrecognized option
         sys.stderr.write( "error: unrecognized option\n" )
@@ -111,6 +113,8 @@
             D_setlevel(1)
         elif opt == '-k':
             kernel_original_path = arg
+        elif opt == '-d':
+            kernel_cleaned_path = arg
 
     if len(args) == 0:
         usage()
@@ -143,9 +147,6 @@
         print "cleaning: %-*s -> %-*s (%s)" % ( 35, path, 35, dst_path, r )
 
 
-    if os.environ.has_key("ANDROID_PRODUCT_OUT"):
-        b.updateP4Files()
-    else:
-        b.updateFiles()
+    b.updateGitFiles()
 
     sys.exit(0)
diff --git a/libc/kernel/tools/cpp.py b/libc/kernel/tools/cpp.py
index 8828a5d..8e15a67 100644
--- a/libc/kernel/tools/cpp.py
+++ b/libc/kernel/tools/cpp.py
@@ -1529,7 +1529,7 @@
 
 class Block:
     """a class used to model a block of input source text. there are two block types:
-        - direcive blocks: contain the tokens of a single pre-processor directive (e.g. #if)
+        - directive blocks: contain the tokens of a single pre-processor directive (e.g. #if)
         - text blocks, contain the tokens of non-directive blocks
 
        the cpp parser class below will transform an input source file into a list of Block
@@ -1609,6 +1609,91 @@
         else:
             return None
 
+    def removeWhiteSpace(self):
+        # Remove trailing whitespace and empty lines
+        # All whitespace is also contracted to a single space
+        if self.directive != None:
+            return
+
+        tokens = []
+        line   = 0     # index of line start
+        space  = -1    # index of first space, or -1
+        ii = 0
+        nn = len(self.tokens)
+        while ii < nn:
+            tok = self.tokens[ii]
+
+            # If we find a space, record its position if this is the first
+            # one the line start or the previous character. Don't append
+            # anything to tokens array yet though.
+            if tok.id == tokSPACE:
+                if space < 0:
+                    space = ii
+                ii += 1
+                continue
+
+            # If this is a line space, ignore the spaces we found previously
+            # on the line, and remove empty lines.
+            if tok.id == tokLN:
+                old_line  = line
+                old_space = space
+                #print "N line=%d space=%d ii=%d" % (line, space, ii)
+                ii   += 1
+                line  = ii
+                space = -1
+                if old_space == old_line:  # line only contains spaces
+                    #print "-s"
+                    continue
+                if ii-1 == old_line:  # line is empty
+                    #print "-e"
+                    continue
+                tokens.append(tok)
+                continue
+
+            # Other token, append any space range if any, converting each
+            # one to a single space character, then append the token.
+            if space >= 0:
+                jj = space
+                space = -1
+                while jj < ii:
+                    tok2 = self.tokens[jj]
+                    tok2.value = " "
+                    tokens.append(tok2)
+                    jj += 1
+
+            tokens.append(tok)
+            ii += 1
+
+        self.tokens = tokens
+
+    def writeWithWarning(self,out,warning,left_count,repeat_count):
+        # removeWhiteSpace() will sometimes creates non-directive blocks
+        # without any tokens. These come from blocks that only contained
+        # empty lines and spaces. They should not be printed in the final
+        # output, and then should not be counted for this operation.
+        #
+        if not self.directive and self.tokens == []:
+            return left_count
+
+        if self.directive:
+            out.write(str(self) + "\n")
+            left_count -= 1
+            if left_count == 0:
+                out.write(warning)
+                left_count = repeat_count
+
+        else:
+            for tok in self.tokens:
+                out.write(str(tok))
+                if tok.id == tokLN:
+                    left_count -= 1
+                    if left_count == 0:
+                        out.write(warning)
+                        left_count = repeat_count
+
+        return left_count
+
+
     def __repr__(self):
         """generate the representation of a given block"""
         if self.directive:
@@ -1651,7 +1736,6 @@
 
         return result
 
-
 class BlockList:
     """a convenience class used to hold and process a list of blocks returned by
        the cpp parser"""
@@ -1694,6 +1778,10 @@
             if b.isIf():
                 b.expr.removePrefixed(prefix,names)
 
+    def removeWhiteSpace(self):
+        for b in self.blocks:
+            b.removeWhiteSpace()
+
     def optimizeAll(self,macros):
         self.optimizeMacros(macros)
         self.optimizeIf01()
@@ -1713,72 +1801,17 @@
     def write(self,out):
         out.write(str(self))
 
+    def writeWithWarning(self,out,warning,repeat_count):
+        left_count = repeat_count
+        for b in self.blocks:
+            left_count = b.writeWithWarning(out,warning,left_count,repeat_count)
+
     def removeComments(self):
         for b in self.blocks:
             for tok in b.tokens:
                 if tok.id == tokSPACE:
                     tok.value = " "
 
-    def removeEmptyLines(self):
-        # state = 1 => previous line was tokLN
-        # state = 0 => previous line was directive
-        state  = 1
-        for b in self.blocks:
-            if b.isDirective():
-                #print "$$$ directive %s" % str(b)
-                state = 0
-            else:
-                # a tokLN followed by spaces is replaced by a single tokLN
-                # several successive tokLN are replaced by a single one
-                #
-                dst   = []
-                src   = b.tokens
-                n     = len(src)
-                i     = 0
-                #print "$$$ parsing %s" % repr(src)
-                while i < n:
-                    # find final tokLN
-                    j = i
-                    while j < n and src[j].id != tokLN:
-                        j += 1
-
-                    if j >= n:
-                        # uhhh
-                        dst += src[i:]
-                        break
-
-                    if src[i].id == tokSPACE:
-                        k = i+1
-                        while src[k].id == tokSPACE:
-                            k += 1
-
-                        if k == j: # empty lines with spaces in it
-                            i = j  # remove the spaces
-
-                    if i == j:
-                        # an empty line
-                        if state == 1:
-                            i += 1   # remove it
-                        else:
-                            state = 1
-                            dst.append(src[i])
-                            i   += 1
-                    else:
-                        # this line is not empty, remove trailing spaces
-                        k = j
-                        while k > i and src[k-1].id == tokSPACE:
-                            k -= 1
-
-                        nn = i
-                        while nn < k:
-                            dst.append(src[nn])
-                            nn += 1
-                        dst.append(src[j])
-                        state = 0
-                        i = j+1
-
-                b.tokens = dst
-
     def removeVarsAndFuncs(self,knownStatics=set()):
         """remove all extern and static declarations corresponding
            to variable and function declarations. we only accept typedefs
@@ -1789,66 +1822,118 @@
            which is useful for optimized byteorder swap functions and
            stuff like that.
            """
-        # state = 1 => typedef/struct encountered
-        # state = 2 => vars or func declaration encountered, skipping until ";"
         # state = 0 => normal (i.e. LN + spaces)
+        # state = 1 => typedef/struct encountered, ends with ";"
+        # state = 2 => var declaration encountered, ends with ";"
+        # state = 3 => func declaration encountered, ends with "}"
         state      = 0
         depth      = 0
         blocks2    = []
+        skipTokens = False
         for b in self.blocks:
             if b.isDirective():
                 blocks2.append(b)
             else:
                 n     = len(b.tokens)
                 i     = 0
-                first = 0
-                if state == 2:
+                if skipTokens:
                     first = n
+                else:
+                    first = 0
                 while i < n:
                     tok = b.tokens[i]
-                    if state == 0:
-                        bad = 0
-                        if tok.id in [tokLN, tokSPACE]:
-                            pass
-                        elif tok.value in [ 'struct', 'typedef', 'enum', 'union', '__extension__' ]:
-                            state = 1
-                        else:
-                            if tok.value in [ 'static', 'extern', '__KINLINE' ]:
-                                j = i+1
-                                ident = ""
-                                while j < n and not (b.tokens[j].id in [ '(', ';' ]):
-                                    if b.tokens[j].id == tokIDENT:
-                                        ident = b.tokens[j].value
-                                    j += 1
-                                if j < n and ident in knownStatics:
-                                    # this is a known static, we're going to keep its
-                                    # definition in the final output
-                                    state = 1
-                                else:
-                                    #print "### skip static '%s'" % ident
-                                    pass
-
-                            if state == 0:
-                                if i > first:
-                                    #print "### intermediate from '%s': '%s'" % (tok.value, repr(b.tokens[first:i]))
-                                    blocks2.append( Block(b.tokens[first:i]) )
-                                state = 2
-                                first = n
-
-                    else:  # state > 0
-                        if tok.id == '{':
+                    tokid = tok.id
+                    # If we are not looking for the start of a new
+                    # type/var/func, then skip over tokens until
+                    # we find our terminator, managing the depth of
+                    # accolades as we go.
+                    if state > 0:
+                        terminator = False
+                        if tokid == '{':
                             depth += 1
-
-                        elif tok.id == '}':
+                        elif tokid == '}':
                             if depth > 0:
                                 depth -= 1
+                            if (depth == 0) and (state == 3):
+                                terminator = True
+                        elif tokid == ';' and depth == 0:
+                            terminator = True
 
-                        elif depth == 0 and tok.id == ';':
-                            if state == 2:
-                                first = i+1
+                        if terminator:
+                            # we found the terminator
                             state = 0
+                            if skipTokens:
+                                skipTokens = False
+                                first = i+1
 
-                    i += 1
+                        i = i+1
+                        continue
+
+                    # We are looking for the start of a new type/func/var
+                    # ignore whitespace
+                    if tokid in [tokLN, tokSPACE]:
+                        i = i+1
+                        continue
+
+                    # Is it a new type definition, then start recording it
+                    if tok.value in [ 'struct', 'typedef', 'enum', 'union', '__extension__' ]:
+                        #print "$$$ keep type declr" + repr(b.tokens[i:])
+                        state = 1
+                        i     = i+1
+                        continue
+
+                    # Is it a variable or function definition. If so, first
+                    # try to determine which type it is, and also extract
+                    # its name.
+                    #
+                    # We're going to parse the next tokens of the same block
+                    # until we find a semi-column or a left parenthesis.
+                    #
+                    # The semi-column corresponds to a variable definition,
+                    # the left-parenthesis to a function definition.
+                    #
+                    # We also assume that the var/func name is the last
+                    # identifier before the terminator.
+                    #
+                    j = i+1
+                    ident = ""
+                    while j < n:
+                        tokid = b.tokens[j].id
+                        if tokid == '(':  # a function declaration
+                            state = 3
+                            break
+                        elif tokid == ';': # a variable declaration
+                            state = 2
+                            break
+                        if tokid == tokIDENT:
+                            ident = b.tokens[j].value
+                        j += 1
+
+                    if j >= n:
+                        # This can only happen when the declaration
+                        # does not end on the current block (e.g. with
+                        # a directive mixed inside it.
+                        #
+                        # We will treat it as malformed because
+                        # it's very hard to recover from this case
+                        # without making our parser much more
+                        # complex.
+                        #
+                        #print "### skip unterminated static '%s'" % ident
+                        break
+
+                    if ident in knownStatics:
+                        #print "### keep var/func '%s': %s" % (ident,repr(b.tokens[i:j]))
+                        pass
+                    else:
+                        # We're going to skip the tokens for this declaration
+                        #print "### skip variable /func'%s': %s" % (ident,repr(b.tokens[i:j]))
+                        if i > first:
+                            blocks2.append( Block(b.tokens[first:i]))
+                        skipTokens = True
+                        first      = n
+
+                    i = i+1
 
                 if i > first:
                     #print "### final '%s'" % repr(b.tokens[first:i])
diff --git a/libc/kernel/tools/defaults.py b/libc/kernel/tools/defaults.py
index ca7e6bb..2bee4ec 100644
--- a/libc/kernel/tools/defaults.py
+++ b/libc/kernel/tools/defaults.py
@@ -16,7 +16,11 @@
 
 # path to the directory containing the original kernel headers
 #
-kernel_original_path = os.path.normpath( find_program_dir() + '/../original' )
+kernel_original_path = os.path.normpath( find_program_dir() + '/../../../../external/kernel-headers/original' )
+
+# path to the default location of the cleaned-up headers
+#
+kernel_cleaned_path = os.path.normpath( find_program_dir() + '/..' )
 
 # a special value that is used to indicate that a given macro is known to be
 # undefined during optimization
@@ -45,7 +49,7 @@
 
 # Replace tokens in the output according to this mapping
 kernel_token_replacements = {
-    {"asm": "__asm__"},
+    "asm": "__asm__",
     }
 
 # this is the set of known static inline functions that we want to keep
@@ -112,6 +116,18 @@
  ***   structures, and macros generated from the original header, and thus,
  ***   contains no copyrightable information.
  ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
  ****************************************************************************
  ****************************************************************************/
 """
+
+# This is the warning line that will be inserted every N-th line in the output
+kernel_warning = """\
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+"""
diff --git a/libc/kernel/tools/find_headers.py b/libc/kernel/tools/find_headers.py
index 8e72bb6..3d622a8 100755
--- a/libc/kernel/tools/find_headers.py
+++ b/libc/kernel/tools/find_headers.py
@@ -3,7 +3,7 @@
 # this program is used to find source code that includes linux kernel headers directly
 # (e.g. with #include <linux/...> or #include <asm/...>)
 #
-# then it lists
+# then it lists them on the standard output.
 
 import sys, cpp, glob, os, re, getopt, kernel
 from utils import *
@@ -12,20 +12,14 @@
 program_dir = find_program_dir()
 
 wanted_archs   = kernel_archs
-wanted_include = os.path.normpath(program_dir + '/../original')
-wanted_config  = os.path.normpath(program_dir + '/../original/config')
+wanted_config  = None
 
 def usage():
     print """\
-  usage:  find_headers.py [options] (file|directory|@listfile)+
+  usage:  find_headers.py [options] <kernel-root> (file|directory|@listfile)+
 
      options:
-        -d <include-dir>   specify alternate kernel headers
-                           'include' directory
-                           ('%s' by default)
-
-        -c <file>          specify alternate .config file
-                           ('%s' by default)
+        -c <file>          specify .config file (none by default)
 
         -a <archs>         used to specify an alternative list
                            of architectures to support
@@ -37,12 +31,12 @@
     by a set of source files or directories containing them. the search
     is recursive to find *all* required files.
 
-""" % ( wanted_include, wanted_config, string.join(kernel_archs,",") )
+""" % ( string.join(kernel_archs,",") )
     sys.exit(1)
 
 
 try:
-    optlist, args = getopt.getopt( sys.argv[1:], 'vc:d:a:' )
+    optlist, args = getopt.getopt( sys.argv[1:], 'vc:d:a:k:' )
 except:
     # unrecognized option
     print "error: unrecognized option"
@@ -51,8 +45,6 @@
 for opt, arg in optlist:
     if opt == '-a':
         wanted_archs = string.split(arg,',')
-    elif opt == '-d':
-        wanted_include = arg
     elif opt == '-c':
         wanted_config = arg
     elif opt == '-v':
@@ -62,10 +54,10 @@
     else:
         usage()
 
-if len(args) < 1:
+if len(args) < 2:
     usage()
 
-kernel_root = wanted_include
+kernel_root = args[0]
 if not os.path.exists(kernel_root):
     sys.stderr.write( "error: directory '%s' does not exist\n" % kernel_root )
     sys.exit(1)
@@ -74,26 +66,26 @@
     sys.stderr.write( "error: '%s' is not a directory\n" % kernel_root )
     sys.exit(1)
 
-if not os.path.isdir(kernel_root+"/linux"):
-    sys.stderr.write( "error: '%s' does not have a 'linux' directory\n" % kernel_root )
+if not os.path.isdir(kernel_root+"/include/linux"):
+    sys.stderr.write( "error: '%s' does not have an 'include/linux' directory\n" % kernel_root )
     sys.exit(1)
 
-if not os.path.exists(wanted_config):
-    sys.stderr.write( "error: file '%s' does not exist\n" % wanted_config )
-    sys.exit(1)
+if wanted_config:
+    if not os.path.exists(wanted_config):
+        sys.stderr.write( "error: file '%s' does not exist\n" % wanted_config )
+        sys.exit(1)
 
-if not os.path.isfile(wanted_config):
-    sys.stderr.write( "error: '%s' is not a file\n" % wanted_config )
-    sys.exit(1)
+    if not os.path.isfile(wanted_config):
+        sys.stderr.write( "error: '%s' is not a file\n" % wanted_config )
+        sys.exit(1)
 
 # find all architectures in the kernel tree
-re_asm_ = re.compile(r"asm-(\w+)")
 archs   = []
-for dir in os.listdir(kernel_root):
-    m = re_asm_.match(dir)
-    if m:
-        if verbose: print ">> found kernel arch '%s'" % m.group(1)
-        archs.append(m.group(1))
+for archdir in os.listdir(kernel_root+"/arch"):
+    if os.path.exists("%s/arch/%s/include/asm" % (kernel_root, archdir)):
+        if verbose:
+            print "Found arch '%s'" % archdir
+        archs.append(archdir)
 
 # if we're using the 'kernel_headers' directory, there is only asm/
 # and no other asm-<arch> directories (arm is assumed, which sucks)
@@ -126,6 +118,7 @@
 
 # helper function used to walk the user files
 def parse_file(path, parser):
+    #print "parse %s" % path
     parser.parseFile(path)
 
 
@@ -136,7 +129,8 @@
 # try to read the config file
 try:
     cparser = kernel.ConfigParser()
-    cparser.parseFile( wanted_config )
+    if wanted_config:
+        cparser.parseFile( wanted_config )
 except:
     sys.stderr.write( "error: can't parse '%s'" % wanted_config )
     sys.exit(1)
@@ -145,7 +139,8 @@
 
 # first, obtain the list of kernel files used by our clients
 fparser = kernel.HeaderScanner()
-walk_source_files( args, parse_file, fparser, excludes=["kernel_headers"] )
+dir_excludes=[".repo","external/kernel-headers","ndk","out","prebuilt","bionic/libc/kernel","development/ndk","external/qemu/distrib"]
+walk_source_files( args[1:], parse_file, fparser, excludes=["./"+f for f in dir_excludes] )
 headers = fparser.getHeaders()
 files   = fparser.getFiles()
 
@@ -170,6 +165,6 @@
     sys.exit(0)
 
 for h in sorted(headers):
-    print h
+    print "%s" % h
 
 sys.exit(0)
diff --git a/libc/kernel/tools/kernel.py b/libc/kernel/tools/kernel.py
index 9d9b5f0..c203985 100644
--- a/libc/kernel/tools/kernel.py
+++ b/libc/kernel/tools/kernel.py
@@ -55,8 +55,11 @@
     #    <asm-generic/*>
     #    <mtd/*>
     #
-    re_combined =\
-       re.compile(r"^.*<((%s)/[\d\w_\+\.\-/]*)>.*$" % string.join(kernel_dirs,"|") )
+    re_combined_str=\
+       r"^.*<((%s)/[\d\w_\+\.\-/]*)>.*$" % string.join(kernel_dirs,"|")
+
+    re_combined = re.compile(re_combined_str)
+
     # some kernel files choose to include files with relative paths (x86 32/64
     # dispatch for instance)
     re_rel_dir = re.compile(r'^.*"([\d\w_\+\.\-/]+)".*$')
diff --git a/libc/kernel/tools/update_all.py b/libc/kernel/tools/update_all.py
index d25dc0e..6a730a5 100755
--- a/libc/kernel/tools/update_all.py
+++ b/libc/kernel/tools/update_all.py
@@ -6,7 +6,7 @@
 
 def usage():
     print """\
-  usage: %(progname)s
+  usage: %(progname)s [kernel-original-path]
 
     this program is used to update all the auto-generated clean headers
     used by the Bionic C library. it assumes the following:
@@ -31,13 +31,19 @@
     sys.stderr.write( "error: unrecognized option\n" )
     usage()
 
-if len(optlist) > 0 or len(args) > 0:
+if len(optlist) > 0 or len(args) > 1:
     usage()
 
 progdir = find_program_dir()
-original_dir = os.path.normpath( progdir + "/../original" )
-if not os.path.isdir( original_dir ):
-    panic( "required directory does not exists: %s\n" % original_dir )
+
+if len(args) == 1:
+    original_dir = arg[0]
+    if not os.path.isdir(original_dir):
+        panic( "Not a directory: %s" % original_dir )
+else:
+    original_dir = kernel_original_path
+    if not os.path.isdir(original_dir):
+        panic( "Missing directory, please specify one through command-line: %s" % original_dir )
 
 # find all source files in 'original'
 #
@@ -57,29 +63,36 @@
 
 #print "OLD " + repr(b.old_files)
 
+oldlen = 120
 for path in sources:
-    dst_path, newdata = clean_header.cleanupFile(path)
+    dst_path, newdata = clean_header.cleanupFile(path, original_dir)
     if not dst_path:
         continue
 
     b.readFile( dst_path )
     r = b.editFile( dst_path, newdata )
     if r == 0:
-        r = "unchanged"
+        state = "unchanged"
     elif r == 1:
-        r = "edited"
+        state = "edited"
     else:
-        r = "added"
+        state = "added"
 
-    print "cleaning: %-*s -> %-*s (%s)" % ( 35, path, 35, dst_path, r )
+    str = "cleaning: %-*s -> %-*s (%s)" % ( 35, "<original>" + path[len(original_dir):], 35, dst_path, state )
+    if sys.stdout.isatty():
+        print "%-*s" % (oldlen,str),
+        if (r == 0):
+            print "\r",
+        else:
+            print "\n",
+            oldlen = 0
+    else:
+        print str
 
-# We don't use Perforce anymore, but just in case, define ANDROID_USE_P4
-# in your environment if you think you need it.
-usePerforce = os.environ.has_key("ANDROID_USE_P4")
+    oldlen = len(str)
 
-if usePerforce:
-    b.updateP4Files()
-else:
-    b.updateFiles()
+print "%-*s" % (oldlen,"Done!")
+
+b.updateGitFiles()
 
 sys.exit(0)
diff --git a/libc/kernel/tools/utils.py b/libc/kernel/tools/utils.py
index 763c7d2..f4cf540 100644
--- a/libc/kernel/tools/utils.py
+++ b/libc/kernel/tools/utils.py
@@ -231,6 +231,15 @@
 def walk_source_files(paths,callback,args,excludes=[]):
     """recursively walk a list of paths and files, only keeping the source files in directories"""
     for path in paths:
+        if len(path) > 0 and path[0] == '@':
+            # this is the name of another file, include it and parse it
+            path = path[1:]
+            if os.path.exists(path):
+                for line in open(path):
+                    if len(line) > 0 and line[-1] == '\n':
+                        line = line[:-1]
+                    walk_source_files([line],callback,args,excludes)
+            continue
         if not os.path.isdir(path):
             callback(path,args)
         else:
@@ -238,7 +247,7 @@
                 #print "w-- %s (ex: %s)" % (repr((root,dirs)), repr(excludes))
                 if len(excludes):
                     for d in dirs[:]:
-                        if d in excludes:
+                        if os.path.join(root,d) in excludes:
                             dirs.remove(d)
                 for f in files:
                     r, ext = os.path.splitext(f)
@@ -395,3 +404,19 @@
             D2("P4 DELETES: %s" % files)
             o = commands.getoutput( "p4 delete " + files )
             D2( o )
+
+    def updateGitFiles(self):
+        adds, deletes, edits = self.getChanges()
+
+        if adds:
+            for dst in sorted(adds):
+                self._writeFile(dst)
+            commands.getoutput("git add " + " ".join(adds))
+
+        if deletes:
+            commands.getoutput("git rm " + " ".join(deletes))
+
+        if edits:
+            for dst in sorted(edits):
+                self._writeFile(dst)
+            commands.getoutput("git add " + " ".join(edits))
diff --git a/libc/stdio/fvwrite.c b/libc/stdio/fvwrite.c
index 57a57e6..39d0604 100644
--- a/libc/stdio/fvwrite.c
+++ b/libc/stdio/fvwrite.c
@@ -48,7 +48,7 @@
 __sfvwrite(FILE *fp, struct __suio *uio)
 {
 	size_t len;
-	char *p;
+	const char *p;
 	struct __siov *iov;
 	int w, s;
 	char *nl;
diff --git a/libc/stdio/fvwrite.h b/libc/stdio/fvwrite.h
index 2344e42..96f65de 100644
--- a/libc/stdio/fvwrite.h
+++ b/libc/stdio/fvwrite.h
@@ -36,7 +36,7 @@
  * I/O descriptors for __sfvwrite().
  */
 struct __siov {
-	void	*iov_base;
+	const void	*iov_base;
 	size_t	iov_len;
 };
 struct __suio {
diff --git a/libc/stdio/vfprintf.c b/libc/stdio/vfprintf.c
index 2ce0361..9c36b79 100644
--- a/libc/stdio/vfprintf.c
+++ b/libc/stdio/vfprintf.c
@@ -203,9 +203,9 @@
 	 * below longer.
 	 */
 #define	PADSIZE	16		/* pad chunk size */
-	static char blanks[PADSIZE] =
+	static const char blanks[PADSIZE] =
 	 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
-	static char zeroes[PADSIZE] =
+	static const char zeroes[PADSIZE] =
 	 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
 
 	/*
@@ -1219,7 +1219,6 @@
 {
 	int mode, dsgn;
 	char *digits, *bp, *rve;
-	static  char  temp[64];
 
 	if (ch == 'f') {
 		mode = 3;		/* ndigits after the decimal point */
diff --git a/libc/stdlib/strtod.c b/libc/stdlib/strtod.c
index 2851506..ab637a1 100644
--- a/libc/stdlib/strtod.c
+++ b/libc/stdlib/strtod.c
@@ -754,6 +754,7 @@
 }
 
  static Bigint *p5s;
+ static pthread_mutex_t p5s_mutex = PTHREAD_MUTEX_INITIALIZER;
 
  static Bigint *
 pow5mult
@@ -775,11 +776,13 @@
 
 	if (!(k = (unsigned int) k >> 2))
 		return b;
+	mutex_lock(&p5s_mutex);
 	if (!(p5 = p5s)) {
 		/* first time */
 		p5 = i2b(625);
 		if (p5 == BIGINT_INVALID) {
 			Bfree(b);
+			mutex_unlock(&p5s_mutex);
 			return p5;
 		}
 		p5s = p5;
@@ -797,6 +800,7 @@
 			p51 = mult(p5,p5);
 			if (p51 == BIGINT_INVALID) {
 				Bfree(b);
+				mutex_unlock(&p5s_mutex);
 				return p51;
 			}
 			p5->next = p51;
@@ -804,6 +808,7 @@
 		}
 		p5 = p51;
 	}
+	mutex_unlock(&p5s_mutex);
 	return b;
 }
 
diff --git a/libc/tools/bionic_utils.py b/libc/tools/bionic_utils.py
index 17eef13..e7c8c2d 100644
--- a/libc/tools/bionic_utils.py
+++ b/libc/tools/bionic_utils.py
@@ -105,8 +105,29 @@
     else:
         return None
 
+def find_original_kernel_headers():
+    """try to find the directory containing the original kernel headers"""
+    bionic_root = find_bionic_root()
+    if not bionic_root:
+        D("Could not find Bionic root !!")
+        return None
+
+    path = os.path.normpath(bionic_root + "/../../external/kernel-headers/original")
+    if not os.path.isdir(path):
+        D("Could not find %s" % (path))
+        return None
+
+    return path
+
 def find_kernel_headers():
     """try to find the directory containing the kernel headers for this machine"""
+
+    # First try to find the original kernel headers.
+    ret = find_original_kernel_headers()
+    if ret:
+        D("found original kernel headers in: %s" % (ret))
+        return ret
+
     status, version = commands.getstatusoutput( "uname -r" )  # get Linux kernel version
     if status != 0:
         D("could not execute 'uname -r' command properly")
@@ -116,14 +137,39 @@
     if len(version) > 5 and version[-5:] == "-xenU":
         version = version[:-5]
 
-    path = "/usr/src/linux-headers-" + version
-    D("probing %s for kernel headers" % (path+"/include"))
+    path = "/usr/src/linux-headers-" + version + "/include"
+    D("probing %s for kernel headers" % (path))
     ret = os.path.isdir( path )
     if ret:
-        D("found kernel headers in: %s" % (path + "/include"))
+        D("found kernel headers in: %s" % (path))
         return path
     return None
 
+def find_arch_header(kernel_headers,arch,header):
+    # First, try in <root>/arch/<arm>/include/<header>
+    # corresponding to the location in the kernel source tree for
+    # certain architectures (e.g. arm).
+    path = "%s/arch/%s/include/asm/%s" % (kernel_headers, arch, header)
+    D("Probing for %s" % path)
+    if os.path.exists(path):
+        return path
+
+    # Try <root>/asm-<arch>/include/<header> corresponding to the location
+    # in the kernel source tree for other architectures (e.g. x86).
+    path = "%s/include/asm-%s/%s" % (kernel_headers, arch, header)
+    D("Probing for %s" % path)
+    if os.path.exists(path):
+        return path
+
+    # Otherwise, look under <root>/asm-<arch>/<header> corresponding
+    # the original kernel headers directory
+    path = "%s/asm-%s/%s" % (kernel_headers, arch, header)
+    D("Probing for %s" % path)
+    if os.path.exists(path):
+        return path
+
+
+    return None
 
 # parser for the SYSCALLS.TXT file
 #
@@ -212,7 +258,12 @@
                 E("invalid syscall number in '%s'" % line)
                 return
 
-        print str(syscall_id) + ':' + str(syscall_id2) + ':' + str(syscall_id3)
+		global verbose
+        if verbose >= 2:
+            if call_id < 0:
+                print "%s: %d,%d,%d" % (syscall_name, syscall_id, syscall_id2, syscall_id3)
+            else:
+                print "%s(%d): %d,%d,%d" % (syscall_name, call_id, syscall_id, syscall_id2, syscall_id3)
 
         t = { "id"     : syscall_id,
               "id2"    : syscall_id2,
diff --git a/libc/tools/checksyscalls.py b/libc/tools/checksyscalls.py
index 9edb390..f642e84 100755
--- a/libc/tools/checksyscalls.py
+++ b/libc/tools/checksyscalls.py
@@ -40,8 +40,8 @@
     if len(args) == 0:
         linux_root = find_kernel_headers()
         if linux_root == None:
-            print "could not locate this system kernel headers root directory, please"
-            print "specify one when calling this program, i.e. 'checksyscalls <headers-directory>'"
+            print "Could not locate original or system kernel headers root directory."
+            print "Please specify one when calling this program, i.e. 'checksyscalls <headers-directory>'"
             sys.exit(1)
         print "using the following kernel headers root: '%s'" % linux_root
     else:
@@ -112,62 +112,63 @@
 
 arm_dict = {}
 x86_dict = {}
+superh_dict = {}
 
-
-# remove trailing slash and '/include' from the linux_root, if any
+# remove trailing slash from the linux_root, if any
 if linux_root[-1] == '/':
     linux_root = linux_root[:-1]
 
-if len(linux_root) > 8 and linux_root[-8:] == '/include':
-    linux_root = linux_root[:-8]
-
-arm_unistd = linux_root + "/include/asm-arm/unistd.h"
-if not os.path.exists(arm_unistd):
-    print "WEIRD: could not locate the ARM unistd.h header file"
-    print "tried searching in '%s'" % arm_unistd
-    print "maybe using a different set of kernel headers might help"
+arm_unistd = find_arch_header(linux_root, "arm", "unistd.h")
+if not arm_unistd:
+    print "WEIRD: Could not locate the ARM unistd.h kernel header file,"
+    print "maybe using a different set of kernel headers might help."
     sys.exit(1)
 
 # on recent kernels, asm-i386 and asm-x64_64 have been merged into asm-x86
 # with two distinct unistd_32.h and unistd_64.h definition files.
 # take care of this here
 #
-x86_unistd = linux_root + "/include/asm-i386/unistd.h"
-if not os.path.exists(x86_unistd):
-    x86_unistd1 = x86_unistd
-    x86_unistd = linux_root + "/include/asm-x86/unistd_32.h"
-    if not os.path.exists(x86_unistd):
-        print "WEIRD: could not locate the i386/x86 unistd.h header file"
-        print "tried searching in '%s' and '%s'" % (x86_unistd1, x86_unistd)
-        print "maybe using a different set of kernel headers might help"
+x86_unistd = find_arch_header(linux_root, "i386", "unistd.h")
+if not x86_unistd:
+    x86_unistd = find_arch_header(linux_root, "x86", "unistd_32.h")
+    if not x86_unistd:
+        print "WEIRD: Could not locate the i386/x86 unistd.h header file,"
+        print "maybe using a different set of kernel headers might help."
         sys.exit(1)
 
-process_header( linux_root+"/include/asm-arm/unistd.h", arm_dict )
+superh_unistd = find_arch_header(linux_root, "sh", "unistd_32.h")
+if not superh_unistd:
+    print "WEIRD: Could not locate the SuperH unistd.h kernel header file,"
+    print "maybe using a different set of kernel headers might help."
+    sys.exit(1)
+
+process_header( arm_unistd, arm_dict )
 process_header( x86_unistd, x86_dict )
+process_header( superh_unistd, superh_dict )
 
 # now perform the comparison
 errors = 0
-for sc in syscalls:
-    sc_name = sc["name"]
-    sc_id   = sc["id"]
-    if sc_id >= 0:
-        if not arm_dict.has_key(sc_name):
-            print "arm syscall %s not defined !!" % sc_name
-            errors += 1
-        elif arm_dict[sc_name] != sc_id:
-            print "arm syscall %s should be %d instead of %d !!" % (sc_name, arm_dict[sc_name], sc_id)
-            errors += 1
 
-for sc in syscalls:
-    sc_name = sc["name"]
-    sc_id2  = sc["id2"]
-    if sc_id2 >= 0:
-        if not x86_dict.has_key(sc_name):
-            print "x86 syscall %s not defined !!" % sc_name
-            errors += 1
-        elif x86_dict[sc_name] != sc_id2:
-            print "x86 syscall %s should be %d instead of %d !!" % (sc_name, x86_dict[sc_name], sc_id2)
-            errors += 1
+def check_syscalls(archname, idname, arch_dict):
+    errors = 0
+    for sc in syscalls:
+        sc_name = sc["name"]
+        sc_id   = sc[idname]
+        if sc_id >= 0:
+            if not arch_dict.has_key(sc_name):
+                print "%s syscall %s not defined, should be %d !!" % (archname, sc_name, sc_id)
+                errors += 1
+            elif not arch_dict.has_key(sc_name):
+                print "%s syscall %s is not implemented!" % (archname, sc_name)
+                errors += 1
+            elif arch_dict[sc_name] != sc_id:
+                print "%s syscall %s should be %d instead of %d !!" % (archname, sc_name, arch_dict[sc_name], sc_id)
+                errors += 1
+    return errors
+
+errors += check_syscalls("arm", "id", arm_dict)
+errors += check_syscalls("x86", "id2", x86_dict)
+errors += check_syscalls("superh", "id3", superh_dict)
 
 if errors == 0:
     print "congratulations, everything's fine !!"
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index 0535e56..b58754b 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -557,7 +557,7 @@
         for sc in self.syscalls:
             if sc.has_key("asm-arm") and 'arm' in all_archs:
                 fname = "arch-arm/syscalls/%s.S" % sc["func"]
-                D( ">>> generating "+fname )
+                D2( ">>> generating "+fname )
                 fp = create_file( fname )
                 fp.write(sc["asm-arm"])
                 fp.close()
@@ -565,7 +565,7 @@
 
             if sc.has_key("asm-thumb") and 'arm' in all_archs:
                 fname = "arch-arm/syscalls/%s.S" % sc["func"]
-                D( ">>> generating "+fname )
+                D2( ">>> generating "+fname )
                 fp = create_file( fname )
                 fp.write(sc["asm-thumb"])
                 fp.close()
@@ -573,7 +573,7 @@
 
             if sc.has_key("asm-x86") and 'x86' in all_archs:
                 fname = "arch-x86/syscalls/%s.S" % sc["func"]
-                D( ">>> generating "+fname )
+                D2( ">>> generating "+fname )
                 fp = create_file( fname )
                 fp.write(sc["asm-x86"])
                 fp.close()
@@ -581,7 +581,7 @@
 
             if sc.has_key("asm-sh"):
                 fname = "arch-sh/syscalls/%s.S" % sc["func"]
-                D( ">>> generating "+fname )
+                D2( ">>> generating "+fname )
                 fp = create_file( fname )
                 fp.write(sc["asm-sh"])
                 fp.close()
@@ -626,7 +626,7 @@
 
         for stub in self.new_stubs + self.other_files:
             if not os.path.exists( bionic_root + stub ):
-                # new file, P4 add it
+                # new file, git add it
                 D( "new file:     " + stub)
                 adds.append( bionic_root + stub )
                 shutil.copyfile( bionic_temp + stub, bionic_root + stub )
@@ -643,16 +643,21 @@
 
 
         if adds:
-            commands.getoutput("p4 add " + " ".join(adds))
+            commands.getoutput("git add " + " ".join(adds))
         if deletes:
-            commands.getoutput("p4 delete " + " ".join(deletes))
+            commands.getoutput("git rm " + " ".join(deletes))
         if edits:
-            commands.getoutput("p4 edit " +
-                               " ".join((bionic_root + file) for file in edits))
             for file in edits:
                 shutil.copyfile( bionic_temp + file, bionic_root + file )
+            commands.getoutput("git add " +
+                               " ".join((bionic_root + file) for file in edits))
 
-        D("ready to go !!")
+        commands.getoutput("git add %s%s" % (bionic_root,"SYSCALLS.TXT"))
+
+        if (not adds) and (not deletes) and (not edits):
+            D("no changes detected!")
+        else:
+            D("ready to go!!")
 
 D_setlevel(1)
 
diff --git a/libc/tzcode/strptime.c b/libc/tzcode/strptime.c
index 1f481c9..0567aa4 100644
--- a/libc/tzcode/strptime.c
+++ b/libc/tzcode/strptime.c
@@ -89,29 +89,31 @@
 #define _LEGAL_ALT(x)       { if (alt_format & ~(x)) return (0); }
 
 
+struct century_relyear {
+    int century;
+    int relyear;
+};
 static  int _conv_num(const unsigned char **, int *, int, int);
-static  unsigned char *_strptime(const unsigned char *, const char *, struct tm *, int);
+static  unsigned char *_strptime(const unsigned char *, const char *, struct tm *,
+        struct century_relyear *);
 
 
 char *
 strptime(const char *buf, const char *fmt, struct tm *tm)
 {
-    return (char*)(_strptime((const unsigned char*)buf, fmt, tm, 1));
+    struct century_relyear cr;
+    cr.century = TM_YEAR_BASE;
+    cr.relyear = -1;
+    return (char*)(_strptime((const unsigned char*)buf, fmt, tm, &cr));
 }
 
 static unsigned char *
-_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, int initialize)
+_strptime(const unsigned char *buf, const char *fmt, struct tm *tm, struct century_relyear *cr)
 {
     unsigned char c;
     const unsigned char *bp;
     size_t len = 0;
     int alt_format, i;
-    static int century, relyear;
-
-    if (initialize) {
-        century = TM_YEAR_BASE;
-        relyear = -1;
-    }
 
     bp = (unsigned char *)buf;
     while ((c = *fmt) != '\0') {
@@ -158,43 +160,43 @@
          */
         case 'c':   /* Date and time, using the locale's format. */
             _LEGAL_ALT(_ALT_E);
-            if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, 0)))
+            if (!(bp = _strptime(bp, _ctloc(d_t_fmt), tm, cr)))
                 return (NULL);
             break;
 
         case 'D':   /* The date as "%m/%d/%y". */
             _LEGAL_ALT(0);
-            if (!(bp = _strptime(bp, "%m/%d/%y", tm, 0)))
+            if (!(bp = _strptime(bp, "%m/%d/%y", tm, cr)))
                 return (NULL);
             break;
     
         case 'R':   /* The time as "%H:%M". */
             _LEGAL_ALT(0);
-            if (!(bp = _strptime(bp, "%H:%M", tm, 0)))
+            if (!(bp = _strptime(bp, "%H:%M", tm, cr)))
                 return (NULL);
             break;
 
         case 'r':   /* The time as "%I:%M:%S %p". */
             _LEGAL_ALT(0);
-            if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, 0)))
+            if (!(bp = _strptime(bp, "%I:%M:%S %p", tm, cr)))
                 return (NULL);
             break;
 
         case 'T':   /* The time as "%H:%M:%S". */
             _LEGAL_ALT(0);
-            if (!(bp = _strptime(bp, "%H:%M:%S", tm, 0)))
+            if (!(bp = _strptime(bp, "%H:%M:%S", tm, cr)))
                 return (NULL);
             break;
 
         case 'X':   /* The time, using the locale's format. */
             _LEGAL_ALT(_ALT_E);
-            if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, 0)))
+            if (!(bp = _strptime(bp, _ctloc(t_fmt), tm, cr)))
                 return (NULL);
             break;
 
         case 'x':   /* The date, using the locale's format. */
             _LEGAL_ALT(_ALT_E);
-            if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, 0)))
+            if (!(bp = _strptime(bp, _ctloc(d_fmt), tm, cr)))
                 return (NULL);
             break;
 
@@ -253,7 +255,7 @@
             if (!(_conv_num(&bp, &i, 0, 99)))
                 return (NULL);
 
-            century = i * 100;
+            cr->century = i * 100;
             break;
 
         case 'd':   /* The day of month. */
@@ -359,13 +361,13 @@
             if (!(_conv_num(&bp, &i, 0, 9999)))
                 return (NULL);
 
-            relyear = -1;
+            cr->relyear = -1;
             tm->tm_year = i - TM_YEAR_BASE;
             break;
 
         case 'y':   /* The year within the century (2 digits). */
             _LEGAL_ALT(_ALT_E | _ALT_O);
-            if (!(_conv_num(&bp, &relyear, 0, 99)))
+            if (!(_conv_num(&bp, &cr->relyear, 0, 99)))
                 return (NULL);
             break;
 
@@ -391,14 +393,14 @@
      * We need to evaluate the two digit year spec (%y)
      * last as we can get a century spec (%C) at any time.
      */
-    if (relyear != -1) {
-        if (century == TM_YEAR_BASE) {
-            if (relyear <= 68)
-                tm->tm_year = relyear + 2000 - TM_YEAR_BASE;
+    if (cr->relyear != -1) {
+        if (cr->century == TM_YEAR_BASE) {
+            if (cr->relyear <= 68)
+                tm->tm_year = cr->relyear + 2000 - TM_YEAR_BASE;
             else
-                tm->tm_year = relyear + 1900 - TM_YEAR_BASE;
+                tm->tm_year = cr->relyear + 1900 - TM_YEAR_BASE;
         } else {
-            tm->tm_year = relyear + century - TM_YEAR_BASE;
+            tm->tm_year = cr->relyear + cr->century - TM_YEAR_BASE;
         }
     }
 
diff --git a/libc/unistd/time.c b/libc/unistd/time.c
index 13d7366..4b51675 100644
--- a/libc/unistd/time.c
+++ b/libc/unistd/time.c
@@ -42,21 +42,29 @@
 	return (tt.tv_sec);
 }
 
+// return monotonically increasing CPU time in ticks relative to unspecified epoch
+static inline clock_t clock_now(void)
+{
+	struct timespec tm;
+	clock_gettime( CLOCK_MONOTONIC, &tm);
+	return tm.tv_sec * CLOCKS_PER_SEC + (tm.tv_nsec * (CLOCKS_PER_SEC/1e9));
+}
 
+// initialized by the constructor below
+static clock_t clock_start;
+
+// called by dlopen when .so is loaded
+__attribute__((constructor)) static void clock_crt0(void)
+{
+	clock_start = clock_now();
+}
+
+// return elapsed CPU time in clock ticks, since start of program execution
+// (spec says epoch is undefined, but glibc uses crt0 as epoch)
 clock_t
 clock(void)
 {
-	struct timespec  tm;
-	static int       clock_inited;
-	static clock_t   clock_start;
-	clock_t          now;
-
-	clock_gettime( CLOCK_MONOTONIC, &tm);
-	now = tm.tv_sec * CLOCKS_PER_SEC + (tm.tv_nsec * (CLOCKS_PER_SEC/1e9));
-
-	if (!clock_inited) {
-		clock_start  = now;
-		clock_inited = 1;
-	}
-	return  now - clock_start;
+	// note that if we are executing in a different thread than crt0, then the
+	// pthread_create that made us had a memory barrier so clock_start is defined
+	return clock_now() - clock_start;
 }
diff --git a/linker/README.TXT b/linker/README.TXT
index 052a65b..a8efe35 100644
--- a/linker/README.TXT
+++ b/linker/README.TXT
@@ -77,7 +77,7 @@
       Same as DT_INITARRAY but for finalizers. Note that the
       functions must be called in reverse-order though
 
-      Note: this is generally stroed in a .fini_array section
+      Note: this is generally stored in a .fini_array section
 
   DT_FINI_ARRAYSZ
       Size of FT_FINIARRAY
@@ -88,7 +88,7 @@
       a list of functions that need to be called before any other
       initialization function (i.e. DT_INIT and/or DT_INIT_ARRAY)
 
-      Note: this is generally stroed in a .preinit_array section
+      Note: this is generally stored in a .preinit_array section
 
   DT_PREINIT_ARRAYSZ
       The size of DT_PREINIT_ARRAY
@@ -103,14 +103,14 @@
 much processor dependent, and may use different ELF sections.
 
 On the ARM (see "C++ ABI for ARM" document), the static constructors
-must be called explicitely from the DT_INIT_ARRAY, and each one of them
+must be called explicitly from the DT_INIT_ARRAY, and each one of them
 shall register a destructor by calling the special __eabi_atexit()
 function (provided by the C library). The DT_FINI_ARRAY is not used
 by static C++ destructors.
 
 On x86, the lists of constructors and destructors are placed in special
 sections named ".ctors" and ".dtors", and the DT_INIT / DT_FINI functions
-are in charge of calling them explicitely.
+are in charge of calling them explicitly.
 
 
 Debugging:
@@ -140,4 +140,4 @@
 
 By default, traces are sent to logcat, with the "linker" tag. You can
 change this to go to stdout instead by setting the definition of
-LINKER_DEBUG_TO_LOG to 0 in "linker_debug.h"
+LINKER_DEBUG_TO_LOG to 0 in "linker_debug.h".