You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2016/09/30 00:31:05 UTC
[22/51] [abbrv] [partial] incubator-mynewt-core git commit:
net/ip/lwip_base; LwIP.
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f5a0f2a0/net/ip/lwip_base/src/core/inet_chksum.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/core/inet_chksum.c b/net/ip/lwip_base/src/core/inet_chksum.c
new file mode 100644
index 0000000..6ccf839
--- /dev/null
+++ b/net/ip/lwip_base/src/core/inet_chksum.c
@@ -0,0 +1,610 @@
+/**
+ * @file
+ * Incluse internet checksum functions.\n
+ *
+ * These are some reference implementations of the checksum algorithm, with the
+ * aim of being simple, correct and fully portable. Checksumming is the
+ * first thing you would want to optimize for your platform. If you create
+ * your own version, link it in and in your cc.h put:
+ *
+ * \#define LWIP_CHKSUM your_checksum_routine
+ *
+ * Or you can select from the implementations below by defining
+ * LWIP_CHKSUM_ALGORITHM to 1, 2 or 3.
+ */
+
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <ad...@sics.se>
+ *
+ */
+
+#include "lwip/opt.h"
+
+#include "lwip/inet_chksum.h"
+#include "lwip/def.h"
+#include "lwip/ip_addr.h"
+
+#include <stddef.h>
+#include <string.h>
+
+#ifndef LWIP_CHKSUM
+# define LWIP_CHKSUM lwip_standard_chksum
+# ifndef LWIP_CHKSUM_ALGORITHM
+# define LWIP_CHKSUM_ALGORITHM 2
+# endif
+u16_t lwip_standard_chksum(const void *dataptr, int len);
+#endif
+/* If none set: */
+#ifndef LWIP_CHKSUM_ALGORITHM
+# define LWIP_CHKSUM_ALGORITHM 0
+#endif
+
+#if (LWIP_CHKSUM_ALGORITHM == 1) /* Version #1 */
+/**
+ * lwip checksum
+ *
+ * @param dataptr points to start of data to be summed at any boundary
+ * @param len length of data to be summed
+ * @return host order (!) lwip checksum (non-inverted Internet sum)
+ *
+ * @note accumulator size limits summable length to 64k
+ * @note host endianess is irrelevant (p3 RFC1071)
+ */
+u16_t
+lwip_standard_chksum(const void *dataptr, int len)
+{
+ u32_t acc;
+ u16_t src;
+ const u8_t *octetptr;
+
+ acc = 0;
+ /* dataptr may be at odd or even addresses */
+ octetptr = (const u8_t*)dataptr;
+ while (len > 1) {
+ /* declare first octet as most significant
+ thus assume network order, ignoring host order */
+ src = (*octetptr) << 8;
+ octetptr++;
+ /* declare second octet as least significant */
+ src |= (*octetptr);
+ octetptr++;
+ acc += src;
+ len -= 2;
+ }
+ if (len > 0) {
+ /* accumulate remaining octet */
+ src = (*octetptr) << 8;
+ acc += src;
+ }
+ /* add deferred carry bits */
+ acc = (acc >> 16) + (acc & 0x0000ffffUL);
+ if ((acc & 0xffff0000UL) != 0) {
+ acc = (acc >> 16) + (acc & 0x0000ffffUL);
+ }
+ /* This maybe a little confusing: reorder sum using htons()
+ instead of ntohs() since it has a little less call overhead.
+ The caller must invert bits for Internet sum ! */
+ return htons((u16_t)acc);
+}
+#endif
+
+#if (LWIP_CHKSUM_ALGORITHM == 2) /* Alternative version #2 */
+/*
+ * Curt McDowell
+ * Broadcom Corp.
+ * csm@broadcom.com
+ *
+ * IP checksum two bytes at a time with support for
+ * unaligned buffer.
+ * Works for len up to and including 0x20000.
+ * by Curt McDowell, Broadcom Corp. 12/08/2005
+ *
+ * @param dataptr points to start of data to be summed at any boundary
+ * @param len length of data to be summed
+ * @return host order (!) lwip checksum (non-inverted Internet sum)
+ */
+u16_t
+lwip_standard_chksum(const void *dataptr, int len)
+{
+ const u8_t *pb = (const u8_t *)dataptr;
+ const u16_t *ps;
+ u16_t t = 0;
+ u32_t sum = 0;
+ int odd = ((mem_ptr_t)pb & 1);
+
+ /* Get aligned to u16_t */
+ if (odd && len > 0) {
+ ((u8_t *)&t)[1] = *pb++;
+ len--;
+ }
+
+ /* Add the bulk of the data */
+ ps = (const u16_t *)(const void *)pb;
+ while (len > 1) {
+ sum += *ps++;
+ len -= 2;
+ }
+
+ /* Consume left-over byte, if any */
+ if (len > 0) {
+ ((u8_t *)&t)[0] = *(const u8_t *)ps;
+ }
+
+ /* Add end bytes */
+ sum += t;
+
+ /* Fold 32-bit sum to 16 bits
+ calling this twice is probably faster than if statements... */
+ sum = FOLD_U32T(sum);
+ sum = FOLD_U32T(sum);
+
+ /* Swap if alignment was odd */
+ if (odd) {
+ sum = SWAP_BYTES_IN_WORD(sum);
+ }
+
+ return (u16_t)sum;
+}
+#endif
+
+#if (LWIP_CHKSUM_ALGORITHM == 3) /* Alternative version #3 */
+/**
+ * An optimized checksum routine. Basically, it uses loop-unrolling on
+ * the checksum loop, treating the head and tail bytes specially, whereas
+ * the inner loop acts on 8 bytes at a time.
+ *
+ * @arg start of buffer to be checksummed. May be an odd byte address.
+ * @len number of bytes in the buffer to be checksummed.
+ * @return host order (!) lwip checksum (non-inverted Internet sum)
+ *
+ * by Curt McDowell, Broadcom Corp. December 8th, 2005
+ */
+u16_t
+lwip_standard_chksum(const void *dataptr, int len)
+{
+ const u8_t *pb = (const u8_t *)dataptr;
+ const u16_t *ps;
+ u16_t t = 0;
+ const u32_t *pl;
+ u32_t sum = 0, tmp;
+ /* starts at odd byte address? */
+ int odd = ((mem_ptr_t)pb & 1);
+
+ if (odd && len > 0) {
+ ((u8_t *)&t)[1] = *pb++;
+ len--;
+ }
+
+ ps = (const u16_t *)(const void*)pb;
+
+ if (((mem_ptr_t)ps & 3) && len > 1) {
+ sum += *ps++;
+ len -= 2;
+ }
+
+ pl = (const u32_t *)(const void*)ps;
+
+ while (len > 7) {
+ tmp = sum + *pl++; /* ping */
+ if (tmp < sum) {
+ tmp++; /* add back carry */
+ }
+
+ sum = tmp + *pl++; /* pong */
+ if (sum < tmp) {
+ sum++; /* add back carry */
+ }
+
+ len -= 8;
+ }
+
+ /* make room in upper bits */
+ sum = FOLD_U32T(sum);
+
+ ps = (const u16_t *)pl;
+
+ /* 16-bit aligned word remaining? */
+ while (len > 1) {
+ sum += *ps++;
+ len -= 2;
+ }
+
+ /* dangling tail byte remaining? */
+ if (len > 0) { /* include odd byte */
+ ((u8_t *)&t)[0] = *(const u8_t *)ps;
+ }
+
+ sum += t; /* add end bytes */
+
+ /* Fold 32-bit sum to 16 bits
+ calling this twice is probably faster than if statements... */
+ sum = FOLD_U32T(sum);
+ sum = FOLD_U32T(sum);
+
+ if (odd) {
+ sum = SWAP_BYTES_IN_WORD(sum);
+ }
+
+ return (u16_t)sum;
+}
+#endif
+
+/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */
+static u16_t
+inet_cksum_pseudo_base(struct pbuf *p, u8_t proto, u16_t proto_len, u32_t acc)
+{
+ struct pbuf *q;
+ u8_t swapped = 0;
+
+ /* iterate through all pbuf in chain */
+ for (q = p; q != NULL; q = q->next) {
+ LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
+ (void *)q, (void *)q->next));
+ acc += LWIP_CHKSUM(q->payload, q->len);
+ /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
+ /* just executing this next line is probably faster that the if statement needed
+ to check whether we really need to execute it, and does no harm */
+ acc = FOLD_U32T(acc);
+ if (q->len % 2 != 0) {
+ swapped = 1 - swapped;
+ acc = SWAP_BYTES_IN_WORD(acc);
+ }
+ /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
+ }
+
+ if (swapped) {
+ acc = SWAP_BYTES_IN_WORD(acc);
+ }
+
+ acc += (u32_t)htons((u16_t)proto);
+ acc += (u32_t)htons(proto_len);
+
+ /* Fold 32-bit sum to 16 bits
+ calling this twice is probably faster than if statements... */
+ acc = FOLD_U32T(acc);
+ acc = FOLD_U32T(acc);
+ LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
+ return (u16_t)~(acc & 0xffffUL);
+}
+
+#if LWIP_IPV4
+/* inet_chksum_pseudo:
+ *
+ * Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain.
+ * IP addresses are expected to be in network byte order.
+ *
+ * @param p chain of pbufs over that a checksum should be calculated (ip data part)
+ * @param src source ip address (used for checksum of pseudo header)
+ * @param dst destination ip address (used for checksum of pseudo header)
+ * @param proto ip protocol (used for checksum of pseudo header)
+ * @param proto_len length of the ip data part (used for checksum of pseudo header)
+ * @return checksum (as u16_t) to be saved directly in the protocol header
+ */
+u16_t
+inet_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
+ const ip4_addr_t *src, const ip4_addr_t *dest)
+{
+ u32_t acc;
+ u32_t addr;
+
+ addr = ip4_addr_get_u32(src);
+ acc = (addr & 0xffffUL);
+ acc += ((addr >> 16) & 0xffffUL);
+ addr = ip4_addr_get_u32(dest);
+ acc += (addr & 0xffffUL);
+ acc += ((addr >> 16) & 0xffffUL);
+ /* fold down to 16 bits */
+ acc = FOLD_U32T(acc);
+ acc = FOLD_U32T(acc);
+
+ return inet_cksum_pseudo_base(p, proto, proto_len, acc);
+}
+#endif /* LWIP_IPV4 */
+
+#if LWIP_IPV6
+/**
+ * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain.
+ * IPv6 addresses are expected to be in network byte order.
+ *
+ * @param p chain of pbufs over that a checksum should be calculated (ip data part)
+ * @param proto ipv6 protocol/next header (used for checksum of pseudo header)
+ * @param proto_len length of the ipv6 payload (used for checksum of pseudo header)
+ * @param src source ipv6 address (used for checksum of pseudo header)
+ * @param dest destination ipv6 address (used for checksum of pseudo header)
+ * @return checksum (as u16_t) to be saved directly in the protocol header
+ */
+u16_t
+ip6_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
+ const ip6_addr_t *src, const ip6_addr_t *dest)
+{
+ u32_t acc = 0;
+ u32_t addr;
+ u8_t addr_part;
+
+ for (addr_part = 0; addr_part < 4; addr_part++) {
+ addr = src->addr[addr_part];
+ acc += (addr & 0xffffUL);
+ acc += ((addr >> 16) & 0xffffUL);
+ addr = dest->addr[addr_part];
+ acc += (addr & 0xffffUL);
+ acc += ((addr >> 16) & 0xffffUL);
+ }
+ /* fold down to 16 bits */
+ acc = FOLD_U32T(acc);
+ acc = FOLD_U32T(acc);
+
+ return inet_cksum_pseudo_base(p, proto, proto_len, acc);
+}
+#endif /* LWIP_IPV6 */
+
+/* ip_chksum_pseudo:
+ *
+ * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain.
+ * IP addresses are expected to be in network byte order.
+ *
+ * @param p chain of pbufs over that a checksum should be calculated (ip data part)
+ * @param src source ip address (used for checksum of pseudo header)
+ * @param dst destination ip address (used for checksum of pseudo header)
+ * @param proto ip protocol (used for checksum of pseudo header)
+ * @param proto_len length of the ip data part (used for checksum of pseudo header)
+ * @return checksum (as u16_t) to be saved directly in the protocol header
+ */
+u16_t
+ip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len,
+ const ip_addr_t *src, const ip_addr_t *dest)
+{
+#if LWIP_IPV6
+ if (IP_IS_V6(dest)) {
+ return ip6_chksum_pseudo(p, proto, proto_len, ip_2_ip6(src), ip_2_ip6(dest));
+ }
+#endif /* LWIP_IPV6 */
+#if LWIP_IPV4 && LWIP_IPV6
+ else
+#endif /* LWIP_IPV4 && LWIP_IPV6 */
+#if LWIP_IPV4
+ {
+ return inet_chksum_pseudo(p, proto, proto_len, ip_2_ip4(src), ip_2_ip4(dest));
+ }
+#endif /* LWIP_IPV4 */
+}
+
+/** Parts of the pseudo checksum which are common to IPv4 and IPv6 */
+static u16_t
+inet_cksum_pseudo_partial_base(struct pbuf *p, u8_t proto, u16_t proto_len,
+ u16_t chksum_len, u32_t acc)
+{
+ struct pbuf *q;
+ u8_t swapped = 0;
+ u16_t chklen;
+
+ /* iterate through all pbuf in chain */
+ for (q = p; (q != NULL) && (chksum_len > 0); q = q->next) {
+ LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): checksumming pbuf %p (has next %p) \n",
+ (void *)q, (void *)q->next));
+ chklen = q->len;
+ if (chklen > chksum_len) {
+ chklen = chksum_len;
+ }
+ acc += LWIP_CHKSUM(q->payload, chklen);
+ chksum_len -= chklen;
+ LWIP_ASSERT("delete me", chksum_len < 0x7fff);
+ /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): unwrapped lwip_chksum()=%"X32_F" \n", acc));*/
+ /* fold the upper bit down */
+ acc = FOLD_U32T(acc);
+ if (q->len % 2 != 0) {
+ swapped = 1 - swapped;
+ acc = SWAP_BYTES_IN_WORD(acc);
+ }
+ /*LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): wrapped lwip_chksum()=%"X32_F" \n", acc));*/
+ }
+
+ if (swapped) {
+ acc = SWAP_BYTES_IN_WORD(acc);
+ }
+
+ acc += (u32_t)htons((u16_t)proto);
+ acc += (u32_t)htons(proto_len);
+
+ /* Fold 32-bit sum to 16 bits
+ calling this twice is probably faster than if statements... */
+ acc = FOLD_U32T(acc);
+ acc = FOLD_U32T(acc);
+ LWIP_DEBUGF(INET_DEBUG, ("inet_chksum_pseudo(): pbuf chain lwip_chksum()=%"X32_F"\n", acc));
+ return (u16_t)~(acc & 0xffffUL);
+}
+
+#if LWIP_IPV4
+/* inet_chksum_pseudo_partial:
+ *
+ * Calculates the IPv4 pseudo Internet checksum used by TCP and UDP for a pbuf chain.
+ * IP addresses are expected to be in network byte order.
+ *
+ * @param p chain of pbufs over that a checksum should be calculated (ip data part)
+ * @param src source ip address (used for checksum of pseudo header)
+ * @param dst destination ip address (used for checksum of pseudo header)
+ * @param proto ip protocol (used for checksum of pseudo header)
+ * @param proto_len length of the ip data part (used for checksum of pseudo header)
+ * @return checksum (as u16_t) to be saved directly in the protocol header
+ */
+u16_t
+inet_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
+ u16_t chksum_len, const ip4_addr_t *src, const ip4_addr_t *dest)
+{
+ u32_t acc;
+ u32_t addr;
+
+ addr = ip4_addr_get_u32(src);
+ acc = (addr & 0xffffUL);
+ acc += ((addr >> 16) & 0xffffUL);
+ addr = ip4_addr_get_u32(dest);
+ acc += (addr & 0xffffUL);
+ acc += ((addr >> 16) & 0xffffUL);
+ /* fold down to 16 bits */
+ acc = FOLD_U32T(acc);
+ acc = FOLD_U32T(acc);
+
+ return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc);
+}
+#endif /* LWIP_IPV4 */
+
+#if LWIP_IPV6
+/**
+ * Calculates the checksum with IPv6 pseudo header used by TCP and UDP for a pbuf chain.
+ * IPv6 addresses are expected to be in network byte order. Will only compute for a
+ * portion of the payload.
+ *
+ * @param p chain of pbufs over that a checksum should be calculated (ip data part)
+ * @param proto ipv6 protocol/next header (used for checksum of pseudo header)
+ * @param proto_len length of the ipv6 payload (used for checksum of pseudo header)
+ * @param chksum_len number of payload bytes used to compute chksum
+ * @param src source ipv6 address (used for checksum of pseudo header)
+ * @param dest destination ipv6 address (used for checksum of pseudo header)
+ * @return checksum (as u16_t) to be saved directly in the protocol header
+ */
+u16_t
+ip6_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
+ u16_t chksum_len, const ip6_addr_t *src, const ip6_addr_t *dest)
+{
+ u32_t acc = 0;
+ u32_t addr;
+ u8_t addr_part;
+
+ for (addr_part = 0; addr_part < 4; addr_part++) {
+ addr = src->addr[addr_part];
+ acc += (addr & 0xffffUL);
+ acc += ((addr >> 16) & 0xffffUL);
+ addr = dest->addr[addr_part];
+ acc += (addr & 0xffffUL);
+ acc += ((addr >> 16) & 0xffffUL);
+ }
+ /* fold down to 16 bits */
+ acc = FOLD_U32T(acc);
+ acc = FOLD_U32T(acc);
+
+ return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc);
+}
+#endif /* LWIP_IPV6 */
+
+/* ip_chksum_pseudo_partial:
+ *
+ * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain.
+ *
+ * @param p chain of pbufs over that a checksum should be calculated (ip data part)
+ * @param src source ip address (used for checksum of pseudo header)
+ * @param dst destination ip address (used for checksum of pseudo header)
+ * @param proto ip protocol (used for checksum of pseudo header)
+ * @param proto_len length of the ip data part (used for checksum of pseudo header)
+ * @return checksum (as u16_t) to be saved directly in the protocol header
+ */
+u16_t
+ip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len,
+ u16_t chksum_len, const ip_addr_t *src, const ip_addr_t *dest)
+{
+#if LWIP_IPV6
+ if (IP_IS_V6(dest)) {
+ return ip6_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip6(src), ip_2_ip6(dest));
+ }
+#endif /* LWIP_IPV6 */
+#if LWIP_IPV4 && LWIP_IPV6
+ else
+#endif /* LWIP_IPV4 && LWIP_IPV6 */
+#if LWIP_IPV4
+ {
+ return inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip4(src), ip_2_ip4(dest));
+ }
+#endif /* LWIP_IPV4 */
+}
+
+/* inet_chksum:
+ *
+ * Calculates the Internet checksum over a portion of memory. Used primarily for IP
+ * and ICMP.
+ *
+ * @param dataptr start of the buffer to calculate the checksum (no alignment needed)
+ * @param len length of the buffer to calculate the checksum
+ * @return checksum (as u16_t) to be saved directly in the protocol header
+ */
+
+u16_t
+inet_chksum(const void *dataptr, u16_t len)
+{
+ return (u16_t)~(unsigned int)LWIP_CHKSUM(dataptr, len);
+}
+
+/**
+ * Calculate a checksum over a chain of pbufs (without pseudo-header, much like
+ * inet_chksum only pbufs are used).
+ *
+ * @param p pbuf chain over that the checksum should be calculated
+ * @return checksum (as u16_t) to be saved directly in the protocol header
+ */
+u16_t
+inet_chksum_pbuf(struct pbuf *p)
+{
+ u32_t acc;
+ struct pbuf *q;
+ u8_t swapped;
+
+ acc = 0;
+ swapped = 0;
+ for (q = p; q != NULL; q = q->next) {
+ acc += LWIP_CHKSUM(q->payload, q->len);
+ acc = FOLD_U32T(acc);
+ if (q->len % 2 != 0) {
+ swapped = 1 - swapped;
+ acc = SWAP_BYTES_IN_WORD(acc);
+ }
+ }
+
+ if (swapped) {
+ acc = SWAP_BYTES_IN_WORD(acc);
+ }
+ return (u16_t)~(acc & 0xffffUL);
+}
+
+/* These are some implementations for LWIP_CHKSUM_COPY, which copies data
+ * like MEMCPY but generates a checksum at the same time. Since this is a
+ * performance-sensitive function, you might want to create your own version
+ * in assembly targeted at your hardware by defining it in lwipopts.h:
+ * #define LWIP_CHKSUM_COPY(dst, src, len) your_chksum_copy(dst, src, len)
+ */
+
+#if (LWIP_CHKSUM_COPY_ALGORITHM == 1) /* Version #1 */
+/** Safe but slow: first call MEMCPY, then call LWIP_CHKSUM.
+ * For architectures with big caches, data might still be in cache when
+ * generating the checksum after copying.
+ */
+u16_t
+lwip_chksum_copy(void *dst, const void *src, u16_t len)
+{
+ MEMCPY(dst, src, len);
+ return LWIP_CHKSUM(dst, len);
+}
+#endif /* (LWIP_CHKSUM_COPY_ALGORITHM == 1) */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f5a0f2a0/net/ip/lwip_base/src/core/init.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/core/init.c b/net/ip/lwip_base/src/core/init.c
new file mode 100644
index 0000000..cf239f2
--- /dev/null
+++ b/net/ip/lwip_base/src/core/init.c
@@ -0,0 +1,383 @@
+/**
+ * @file
+ * Modules initialization
+ *
+ */
+
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <ad...@sics.se>
+ */
+
+#include "lwip/opt.h"
+
+#include "lwip/init.h"
+#include "lwip/stats.h"
+#include "lwip/sys.h"
+#include "lwip/mem.h"
+#include "lwip/memp.h"
+#include "lwip/pbuf.h"
+#include "lwip/netif.h"
+#include "lwip/sockets.h"
+#include "lwip/ip.h"
+#include "lwip/raw.h"
+#include "lwip/udp.h"
+#include "lwip/priv/tcp_priv.h"
+#include "lwip/igmp.h"
+#include "lwip/dns.h"
+#include "lwip/timeouts.h"
+#include "lwip/etharp.h"
+#include "lwip/ip6.h"
+#include "lwip/nd6.h"
+#include "lwip/mld6.h"
+#include "lwip/api.h"
+
+#include "netif/ppp/ppp_opts.h"
+#include "netif/ppp/ppp_impl.h"
+
+#ifndef LWIP_SKIP_PACKING_CHECK
+
+#ifdef PACK_STRUCT_USE_INCLUDES
+# include "arch/bpstruct.h"
+#endif
+PACK_STRUCT_BEGIN
+struct packed_struct_test
+{
+ PACK_STRUCT_FLD_8(u8_t dummy1);
+ PACK_STRUCT_FIELD(u32_t dummy2);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+#ifdef PACK_STRUCT_USE_INCLUDES
+# include "arch/epstruct.h"
+#endif
+#define PACKED_STRUCT_TEST_EXPECTED_SIZE 5
+
+#endif
+
+/* Compile-time sanity checks for configuration errors.
+ * These can be done independently of LWIP_DEBUG, without penalty.
+ */
+#ifndef BYTE_ORDER
+ #error "BYTE_ORDER is not defined, you have to define it in your cc.h"
+#endif
+#if (!IP_SOF_BROADCAST && IP_SOF_BROADCAST_RECV)
+ #error "If you want to use broadcast filter per pcb on recv operations, you have to define IP_SOF_BROADCAST=1 in your lwipopts.h"
+#endif
+#if (!LWIP_UDP && LWIP_UDPLITE)
+ #error "If you want to use UDP Lite, you have to define LWIP_UDP=1 in your lwipopts.h"
+#endif
+#if (!LWIP_UDP && LWIP_DHCP)
+ #error "If you want to use DHCP, you have to define LWIP_UDP=1 in your lwipopts.h"
+#endif
+#if (!LWIP_UDP && LWIP_MULTICAST_TX_OPTIONS)
+ #error "If you want to use IGMP/LWIP_MULTICAST_TX_OPTIONS, you have to define LWIP_UDP=1 in your lwipopts.h"
+#endif
+#if (!LWIP_UDP && LWIP_DNS)
+ #error "If you want to use DNS, you have to define LWIP_UDP=1 in your lwipopts.h"
+#endif
+#if !MEMP_MEM_MALLOC /* MEMP_NUM_* checks are disabled when not using the pool allocator */
+#if (LWIP_ARP && ARP_QUEUEING && (MEMP_NUM_ARP_QUEUE<=0))
+ #error "If you want to use ARP Queueing, you have to define MEMP_NUM_ARP_QUEUE>=1 in your lwipopts.h"
+#endif
+#if (LWIP_RAW && (MEMP_NUM_RAW_PCB<=0))
+ #error "If you want to use RAW, you have to define MEMP_NUM_RAW_PCB>=1 in your lwipopts.h"
+#endif
+#if (LWIP_UDP && (MEMP_NUM_UDP_PCB<=0))
+ #error "If you want to use UDP, you have to define MEMP_NUM_UDP_PCB>=1 in your lwipopts.h"
+#endif
+#if (LWIP_TCP && (MEMP_NUM_TCP_PCB<=0))
+ #error "If you want to use TCP, you have to define MEMP_NUM_TCP_PCB>=1 in your lwipopts.h"
+#endif
+#if (LWIP_IGMP && (MEMP_NUM_IGMP_GROUP<=1))
+ #error "If you want to use IGMP, you have to define MEMP_NUM_IGMP_GROUP>1 in your lwipopts.h"
+#endif
+#if (LWIP_IGMP && !LWIP_MULTICAST_TX_OPTIONS)
+ #error "If you want to use IGMP, you have to define LWIP_MULTICAST_TX_OPTIONS==1 in your lwipopts.h"
+#endif
+#if (LWIP_IGMP && !LWIP_IPV4)
+ #error "IGMP needs LWIP_IPV4 enabled in your lwipopts.h"
+#endif
+#if (LWIP_MULTICAST_TX_OPTIONS && !LWIP_IPV4)
+ #error "LWIP_MULTICAST_TX_OPTIONS needs LWIP_IPV4 enabled in your lwipopts.h"
+#endif
+#if ((LWIP_NETCONN || LWIP_SOCKET) && (MEMP_NUM_TCPIP_MSG_API<=0))
+ #error "If you want to use Sequential API, you have to define MEMP_NUM_TCPIP_MSG_API>=1 in your lwipopts.h"
+#endif
+/* There must be sufficient timeouts, taking into account requirements of the subsystems. */
+#if LWIP_TIMERS && (MEMP_NUM_SYS_TIMEOUT < (LWIP_TCP + IP_REASSEMBLY + LWIP_ARP + (2*LWIP_DHCP) + LWIP_AUTOIP + LWIP_IGMP + LWIP_DNS + PPP_SUPPORT + (LWIP_IPV6 ? (1 + LWIP_IPV6_REASS + LWIP_IPV6_MLD) : 0)))
+ #error "MEMP_NUM_SYS_TIMEOUT is too low to accomodate all required timeouts"
+#endif
+#if (IP_REASSEMBLY && (MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS))
+ #error "MEMP_NUM_REASSDATA > IP_REASS_MAX_PBUFS doesn't make sense since each struct ip_reassdata must hold 2 pbufs at least!"
+#endif
+#endif /* !MEMP_MEM_MALLOC */
+#if LWIP_WND_SCALE
+#if (LWIP_TCP && (TCP_WND > 0xffffffff))
+ #error "If you want to use TCP, TCP_WND must fit in an u32_t, so, you have to reduce it in your lwipopts.h"
+#endif
+#if (LWIP_TCP && LWIP_WND_SCALE && (TCP_RCV_SCALE > 14))
+ #error "The maximum valid window scale value is 14!"
+#endif
+#if (LWIP_TCP && (TCP_WND > (0xFFFFU << TCP_RCV_SCALE)))
+ #error "TCP_WND is bigger than the configured LWIP_WND_SCALE allows!"
+#endif
+#if (LWIP_TCP && ((TCP_WND >> TCP_RCV_SCALE) == 0))
+ #error "TCP_WND is too small for the configured LWIP_WND_SCALE (results in zero window)!"
+#endif
+#else /* LWIP_WND_SCALE */
+#if (LWIP_TCP && (TCP_WND > 0xffff))
+ #error "If you want to use TCP, TCP_WND must fit in an u16_t, so, you have to reduce it in your lwipopts.h (or enable window scaling)"
+#endif
+#endif /* LWIP_WND_SCALE */
+#if (LWIP_TCP && (TCP_SND_QUEUELEN > 0xffff))
+ #error "If you want to use TCP, TCP_SND_QUEUELEN must fit in an u16_t, so, you have to reduce it in your lwipopts.h"
+#endif
+#if (LWIP_TCP && (TCP_SND_QUEUELEN < 2))
+ #error "TCP_SND_QUEUELEN must be at least 2 for no-copy TCP writes to work"
+#endif
+#if (LWIP_TCP && ((TCP_MAXRTX > 12) || (TCP_SYNMAXRTX > 12)))
+ #error "If you want to use TCP, TCP_MAXRTX and TCP_SYNMAXRTX must less or equal to 12 (due to tcp_backoff table), so, you have to reduce them in your lwipopts.h"
+#endif
+#if (LWIP_TCP && TCP_LISTEN_BACKLOG && ((TCP_DEFAULT_LISTEN_BACKLOG < 0) || (TCP_DEFAULT_LISTEN_BACKLOG > 0xff)))
+ #error "If you want to use TCP backlog, TCP_DEFAULT_LISTEN_BACKLOG must fit into an u8_t"
+#endif
+#if (LWIP_NETIF_API && (NO_SYS==1))
+ #error "If you want to use NETIF API, you have to define NO_SYS=0 in your lwipopts.h"
+#endif
+#if ((LWIP_SOCKET || LWIP_NETCONN) && (NO_SYS==1))
+ #error "If you want to use Sequential API, you have to define NO_SYS=0 in your lwipopts.h"
+#endif
+#if (LWIP_PPP_API && (NO_SYS==1))
+ #error "If you want to use PPP API, you have to define NO_SYS=0 in your lwipopts.h"
+#endif
+#if (LWIP_PPP_API && (PPP_SUPPORT==0))
+ #error "If you want to use PPP API, you have to enable PPP_SUPPORT in your lwipopts.h"
+#endif
+#if (((!LWIP_DHCP) || (!LWIP_AUTOIP)) && LWIP_DHCP_AUTOIP_COOP)
+ #error "If you want to use DHCP/AUTOIP cooperation mode, you have to define LWIP_DHCP=1 and LWIP_AUTOIP=1 in your lwipopts.h"
+#endif
+#if (((!LWIP_DHCP) || (!LWIP_ARP)) && DHCP_DOES_ARP_CHECK)
+ #error "If you want to use DHCP ARP checking, you have to define LWIP_DHCP=1 and LWIP_ARP=1 in your lwipopts.h"
+#endif
+#if (!LWIP_ARP && LWIP_AUTOIP)
+ #error "If you want to use AUTOIP, you have to define LWIP_ARP=1 in your lwipopts.h"
+#endif
+#if (LWIP_TCP && ((LWIP_EVENT_API && LWIP_CALLBACK_API) || (!LWIP_EVENT_API && !LWIP_CALLBACK_API)))
+ #error "One and exactly one of LWIP_EVENT_API and LWIP_CALLBACK_API has to be enabled in your lwipopts.h"
+#endif
+#if (MEM_LIBC_MALLOC && MEM_USE_POOLS)
+ #error "MEM_LIBC_MALLOC and MEM_USE_POOLS may not both be simultaneously enabled in your lwipopts.h"
+#endif
+#if (MEM_USE_POOLS && !MEMP_USE_CUSTOM_POOLS)
+ #error "MEM_USE_POOLS requires custom pools (MEMP_USE_CUSTOM_POOLS) to be enabled in your lwipopts.h"
+#endif
+#if (PBUF_POOL_BUFSIZE <= MEM_ALIGNMENT)
+ #error "PBUF_POOL_BUFSIZE must be greater than MEM_ALIGNMENT or the offset may take the full first pbuf"
+#endif
+#if (DNS_LOCAL_HOSTLIST && !DNS_LOCAL_HOSTLIST_IS_DYNAMIC && !(defined(DNS_LOCAL_HOSTLIST_INIT)))
+ #error "you have to define define DNS_LOCAL_HOSTLIST_INIT {{'host1', 0x123}, {'host2', 0x234}} to initialize DNS_LOCAL_HOSTLIST"
+#endif
+#if PPP_SUPPORT && !PPPOS_SUPPORT && !PPPOE_SUPPORT && !PPPOL2TP_SUPPORT
+ #error "PPP_SUPPORT needs at least one of PPPOS_SUPPORT, PPPOE_SUPPORT or PPPOL2TP_SUPPORT turned on"
+#endif
+#if PPP_SUPPORT && !PPP_IPV4_SUPPORT && !PPP_IPV6_SUPPORT
+ #error "PPP_SUPPORT needs PPP_IPV4_SUPPORT and/or PPP_IPV6_SUPPORT turned on"
+#endif
+#if PPP_SUPPORT && PPP_IPV4_SUPPORT && !LWIP_IPV4
+ #error "PPP_IPV4_SUPPORT needs LWIP_IPV4 turned on"
+#endif
+#if PPP_SUPPORT && PPP_IPV6_SUPPORT && !LWIP_IPV6
+ #error "PPP_IPV6_SUPPORT needs LWIP_IPV6 turned on"
+#endif
+#if !LWIP_ETHERNET && (LWIP_ARP || PPPOE_SUPPORT)
+ #error "LWIP_ETHERNET needs to be turned on for LWIP_ARP or PPPOE_SUPPORT"
+#endif
+#if (LWIP_IGMP || LWIP_IPV6) && !defined(LWIP_RAND)
+ #error "When using IGMP or IPv6, LWIP_RAND() needs to be defined to a random-function returning an u32_t random value (in arch/cc.h)"
+#endif
+#if LWIP_TCPIP_CORE_LOCKING_INPUT && !LWIP_TCPIP_CORE_LOCKING
+ #error "When using LWIP_TCPIP_CORE_LOCKING_INPUT, LWIP_TCPIP_CORE_LOCKING must be enabled, too"
+#endif
+#if LWIP_TCP && LWIP_NETIF_TX_SINGLE_PBUF && !TCP_OVERSIZE
+ #error "LWIP_NETIF_TX_SINGLE_PBUF needs TCP_OVERSIZE enabled to create single-pbuf TCP packets"
+#endif
+#if LWIP_NETCONN && LWIP_TCP
+#if NETCONN_COPY != TCP_WRITE_FLAG_COPY
+ #error "NETCONN_COPY != TCP_WRITE_FLAG_COPY"
+#endif
+#if NETCONN_MORE != TCP_WRITE_FLAG_MORE
+ #error "NETCONN_MORE != TCP_WRITE_FLAG_MORE"
+#endif
+#endif /* LWIP_NETCONN && LWIP_TCP */
+#if LWIP_SOCKET
+/* Check that the SO_* socket options and SOF_* lwIP-internal flags match */
+#if SO_REUSEADDR != SOF_REUSEADDR
+ #error "WARNING: SO_REUSEADDR != SOF_REUSEADDR"
+#endif
+#if SO_KEEPALIVE != SOF_KEEPALIVE
+ #error "WARNING: SO_KEEPALIVE != SOF_KEEPALIVE"
+#endif
+#if SO_BROADCAST != SOF_BROADCAST
+ #error "WARNING: SO_BROADCAST != SOF_BROADCAST"
+#endif
+#endif /* LWIP_SOCKET */
+
+
+/* Compile-time checks for deprecated options.
+ */
+#ifdef MEMP_NUM_TCPIP_MSG
+ #error "MEMP_NUM_TCPIP_MSG option is deprecated. Remove it from your lwipopts.h."
+#endif
+#ifdef TCP_REXMIT_DEBUG
+ #error "TCP_REXMIT_DEBUG option is deprecated. Remove it from your lwipopts.h."
+#endif
+#ifdef RAW_STATS
+ #error "RAW_STATS option is deprecated. Remove it from your lwipopts.h."
+#endif
+#ifdef ETHARP_QUEUE_FIRST
+ #error "ETHARP_QUEUE_FIRST option is deprecated. Remove it from your lwipopts.h."
+#endif
+#ifdef ETHARP_ALWAYS_INSERT
+ #error "ETHARP_ALWAYS_INSERT option is deprecated. Remove it from your lwipopts.h."
+#endif
+#if !NO_SYS && LWIP_TCPIP_CORE_LOCKING && LWIP_COMPAT_MUTEX && !defined(LWIP_COMPAT_MUTEX_ALLOWED)
+ #error "LWIP_COMPAT_MUTEX cannot prevent priority inversion. It is recommended to implement priority-aware mutexes. (Define LWIP_COMPAT_MUTEX_ALLOWED to disable this error.)"
+#endif
+
+#ifndef LWIP_DISABLE_TCP_SANITY_CHECKS
+#define LWIP_DISABLE_TCP_SANITY_CHECKS 0
+#endif
+#ifndef LWIP_DISABLE_MEMP_SANITY_CHECKS
+#define LWIP_DISABLE_MEMP_SANITY_CHECKS 0
+#endif
+
+/* MEMP sanity checks */
+#if MEMP_MEM_MALLOC
+#if !LWIP_DISABLE_MEMP_SANITY_CHECKS
+#if LWIP_NETCONN || LWIP_SOCKET
+#if !MEMP_NUM_NETCONN && LWIP_SOCKET
+#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN cannot be 0 when using sockets!"
+#endif
+#else /* MEMP_MEM_MALLOC */
+#if MEMP_NUM_NETCONN > (MEMP_NUM_TCP_PCB+MEMP_NUM_TCP_PCB_LISTEN+MEMP_NUM_UDP_PCB+MEMP_NUM_RAW_PCB)
+#error "lwip_sanity_check: WARNING: MEMP_NUM_NETCONN should be less than the sum of MEMP_NUM_{TCP,RAW,UDP}_PCB+MEMP_NUM_TCP_PCB_LISTEN. If you know what you are doing, define LWIP_DISABLE_MEMP_SANITY_CHECKS to 1 to disable this error."
+#endif
+#endif /* LWIP_NETCONN || LWIP_SOCKET */
+#endif /* !LWIP_DISABLE_MEMP_SANITY_CHECKS */
+#if MEM_USE_POOLS
+#error "MEMP_MEM_MALLOC and MEM_USE_POOLS cannot be enabled at the same time"
+#endif
+#ifdef LWIP_HOOK_MEMP_AVAILABLE
+#error "LWIP_HOOK_MEMP_AVAILABLE doesn't make sense with MEMP_MEM_MALLOC"
+#endif
+#endif /* MEMP_MEM_MALLOC */
+
+/* TCP sanity checks */
+#if !LWIP_DISABLE_TCP_SANITY_CHECKS
+#if LWIP_TCP
+#if !MEMP_MEM_MALLOC && (MEMP_NUM_TCP_SEG < TCP_SND_QUEUELEN)
+ #error "lwip_sanity_check: WARNING: MEMP_NUM_TCP_SEG should be at least as big as TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
+#endif
+#if TCP_SND_BUF < (2 * TCP_MSS)
+ #error "lwip_sanity_check: WARNING: TCP_SND_BUF must be at least as much as (2 * TCP_MSS) for things to work smoothly. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
+#endif
+#if TCP_SND_QUEUELEN < (2 * (TCP_SND_BUF / TCP_MSS))
+ #error "lwip_sanity_check: WARNING: TCP_SND_QUEUELEN must be at least as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
+#endif
+#if TCP_SNDLOWAT >= TCP_SND_BUF
+ #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must be less than TCP_SND_BUF. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
+#endif
+#if TCP_SNDLOWAT >= (0xFFFF - (4 * TCP_MSS))
+ #error "lwip_sanity_check: WARNING: TCP_SNDLOWAT must at least be 4*MSS below u16_t overflow!"
+#endif
+#if TCP_SNDQUEUELOWAT >= TCP_SND_QUEUELEN
+ #error "lwip_sanity_check: WARNING: TCP_SNDQUEUELOWAT must be less than TCP_SND_QUEUELEN. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
+#endif
+#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (PBUF_POOL_BUFSIZE <= (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))
+ #error "lwip_sanity_check: WARNING: PBUF_POOL_BUFSIZE does not provide enough space for protocol headers. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
+#endif
+#if !MEMP_MEM_MALLOC && PBUF_POOL_SIZE && (TCP_WND > (PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - (PBUF_LINK_ENCAPSULATION_HLEN + PBUF_LINK_HLEN + PBUF_IP_HLEN + PBUF_TRANSPORT_HLEN))))
+ #error "lwip_sanity_check: WARNING: TCP_WND is larger than space provided by PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers). If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
+#endif
+#if TCP_WND < TCP_MSS
+ #error "lwip_sanity_check: WARNING: TCP_WND is smaller than MSS. If you know what you are doing, define LWIP_DISABLE_TCP_SANITY_CHECKS to 1 to disable this error."
+#endif
+#endif /* LWIP_TCP */
+#endif /* !LWIP_DISABLE_TCP_SANITY_CHECKS */
+
+/**
+ * @ingroup lwip_nosys
+ * Initialize all modules.
+ * Use this in NO_SYS mode. Use tcpip_init() otherwise.
+ */
+void
+lwip_init(void)
+{
+#ifndef LWIP_SKIP_PACKING_CHECK
+ LWIP_ASSERT("Struct packing not implemented correctly. Check your lwIP port.", sizeof(struct packed_struct_test) == PACKED_STRUCT_TEST_EXPECTED_SIZE);
+#endif
+
+ /* Modules initialization */
+ lwip_stats_init();
+#if !NO_SYS
+ sys_init();
+#endif /* !NO_SYS */
+ mem_init();
+ memp_init();
+ pbuf_init();
+ netif_init();
+#if LWIP_IPV4
+ ip_init();
+#if LWIP_ARP
+ etharp_init();
+#endif /* LWIP_ARP */
+#endif /* LWIP_IPV4 */
+#if LWIP_RAW
+ raw_init();
+#endif /* LWIP_RAW */
+#if LWIP_UDP
+ udp_init();
+#endif /* LWIP_UDP */
+#if LWIP_TCP
+ tcp_init();
+#endif /* LWIP_TCP */
+#if LWIP_IGMP
+ igmp_init();
+#endif /* LWIP_IGMP */
+#if LWIP_DNS
+ dns_init();
+#endif /* LWIP_DNS */
+#if PPP_SUPPORT
+ ppp_init();
+#endif
+
+#if LWIP_TIMERS
+ sys_timeouts_init();
+#endif /* LWIP_TIMERS */
+}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f5a0f2a0/net/ip/lwip_base/src/core/ip.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/core/ip.c b/net/ip/lwip_base/src/core/ip.c
new file mode 100644
index 0000000..2e02408
--- /dev/null
+++ b/net/ip/lwip_base/src/core/ip.c
@@ -0,0 +1,124 @@
+/**
+ * @file
+ * Common IPv4 and IPv6 code
+ *
+ * @defgroup ip IP
+ * @ingroup callbackstyle_api
+ *
+ * @defgroup ip4 IPv4
+ * @ingroup ip
+ *
+ * @defgroup ip6 IPv6
+ * @ingroup ip
+ *
+ * @defgroup ipaddr IP address handling
+ * @ingroup infrastructure
+ *
+ * @defgroup ip4addr IPv4 only
+ * @ingroup ipaddr
+ *
+ * @defgroup ip6addr IPv6 only
+ * @ingroup ipaddr
+ */
+
+/*
+ * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <ad...@sics.se>
+ *
+ */
+
+#include "lwip/opt.h"
+
+#if LWIP_IPV4 || LWIP_IPV6
+
+#include "lwip/ip_addr.h"
+#include "lwip/ip.h"
+
+/** Global data for both IPv4 and IPv6 */
+struct ip_globals ip_data;
+
+#if LWIP_IPV4 && LWIP_IPV6
+
+const ip_addr_t ip_addr_any_type = IPADDR_ANY_TYPE_INIT;
+
+/**
+ * @ingroup ipaddr
+ * Convert IP address string (both versions) to numeric.
+ * The version is auto-detected from the string.
+ *
+ * @param cp IP address string to convert
+ * @param addr conversion result is stored here
+ * @return 1 on success, 0 on error
+ */
+int
+ipaddr_aton(const char *cp, ip_addr_t *addr)
+{
+ if (cp != NULL) {
+ const char* c;
+ for (c = cp; *c != 0; c++) {
+ if (*c == ':') {
+ /* contains a colon: IPv6 address */
+ if (addr) {
+ IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6);
+ }
+ return ip6addr_aton(cp, ip_2_ip6(addr));
+ } else if (*c == '.') {
+ /* contains a dot: IPv4 address */
+ break;
+ }
+ }
+ /* call ip4addr_aton as fallback or if IPv4 was found */
+ if (addr) {
+ IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4);
+ }
+ return ip4addr_aton(cp, ip_2_ip4(addr));
+ }
+ return 0;
+}
+
+/**
+ * @ingroup lwip_nosys
+ * If both IP versions are enabled, this function can dispatch packets to the correct one.
+ * Don't call directly, pass to netif_add() and call netif->input().
+ */
+err_t
+ip_input(struct pbuf *p, struct netif *inp)
+{
+ if (p != NULL) {
+ if (IP_HDR_GET_VERSION(p->payload) == 6) {
+ return ip6_input(p, inp);
+ }
+ return ip4_input(p, inp);
+ }
+ return ERR_VAL;
+}
+
+#endif /* LWIP_IPV4 && LWIP_IPV6 */
+
+#endif /* LWIP_IPV4 || LWIP_IPV6 */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f5a0f2a0/net/ip/lwip_base/src/core/ipv4/autoip.c
----------------------------------------------------------------------
diff --git a/net/ip/lwip_base/src/core/ipv4/autoip.c b/net/ip/lwip_base/src/core/ipv4/autoip.c
new file mode 100644
index 0000000..01fccf8
--- /dev/null
+++ b/net/ip/lwip_base/src/core/ipv4/autoip.c
@@ -0,0 +1,529 @@
+/**
+ * @file
+ * AutoIP Automatic LinkLocal IP Configuration
+ *
+ * This is a AutoIP implementation for the lwIP TCP/IP stack. It aims to conform
+ * with RFC 3927.
+ *
+ * @defgroup autoip AUTOIP
+ * @ingroup ip4
+ * AUTOIP related functions
+ * USAGE:
+ *
+ * define @ref LWIP_AUTOIP 1 in your lwipopts.h
+ * Options:
+ * AUTOIP_TMR_INTERVAL msecs,
+ * I recommend a value of 100. The value must divide 1000 with a remainder almost 0.
+ * Possible values are 1000, 500, 333, 250, 200, 166, 142, 125, 111, 100 ....
+ *
+ * Without DHCP:
+ * - Call autoip_start() after netif_add().
+ *
+ * With DHCP:
+ * - define @ref LWIP_DHCP_AUTOIP_COOP 1 in your lwipopts.h.
+ * - Configure your DHCP Client.
+ *
+ * @see netifapi_autoip
+ */
+
+/*
+ *
+ * Copyright (c) 2007 Dominik Spies <ko...@dspies.de>
+ * 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. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ *
+ * Author: Dominik Spies <ko...@dspies.de>
+ */
+
+#include "lwip/opt.h"
+
+#if LWIP_IPV4 && LWIP_AUTOIP /* don't build if not configured for use in lwipopts.h */
+
+#include "lwip/mem.h"
+/* #include "lwip/udp.h" */
+#include "lwip/ip_addr.h"
+#include "lwip/netif.h"
+#include "lwip/autoip.h"
+#include "lwip/etharp.h"
+#include "lwip/prot/autoip.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/** Pseudo random macro based on netif informations.
+ * You could use "rand()" from the C Library if you define LWIP_AUTOIP_RAND in lwipopts.h */
+#ifndef LWIP_AUTOIP_RAND
+#define LWIP_AUTOIP_RAND(netif) ( (((u32_t)((netif->hwaddr[5]) & 0xff) << 24) | \
+ ((u32_t)((netif->hwaddr[3]) & 0xff) << 16) | \
+ ((u32_t)((netif->hwaddr[2]) & 0xff) << 8) | \
+ ((u32_t)((netif->hwaddr[4]) & 0xff))) + \
+ (netif_autoip_data(netif)? netif_autoip_data(netif)->tried_llipaddr : 0))
+#endif /* LWIP_AUTOIP_RAND */
+
+/**
+ * Macro that generates the initial IP address to be tried by AUTOIP.
+ * If you want to override this, define it to something else in lwipopts.h.
+ */
+#ifndef LWIP_AUTOIP_CREATE_SEED_ADDR
+#define LWIP_AUTOIP_CREATE_SEED_ADDR(netif) \
+ htonl(AUTOIP_RANGE_START + ((u32_t)(((u8_t)(netif->hwaddr[4])) | \
+ ((u32_t)((u8_t)(netif->hwaddr[5]))) << 8)))
+#endif /* LWIP_AUTOIP_CREATE_SEED_ADDR */
+
+/* static functions */
+static err_t autoip_arp_announce(struct netif *netif);
+static void autoip_start_probing(struct netif *netif);
+
+#define netif_autoip_data(netif) ((struct autoip*)netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP))
+
+/**
+ * @ingroup autoip
+ * Set a statically allocated struct autoip to work with.
+ * Using this prevents autoip_start to allocate it using mem_malloc.
+ *
+ * @param netif the netif for which to set the struct autoip
+ * @param autoip (uninitialised) autoip struct allocated by the application
+ */
+void
+autoip_set_struct(struct netif *netif, struct autoip *autoip)
+{
+ LWIP_ASSERT("netif != NULL", netif != NULL);
+ LWIP_ASSERT("autoip != NULL", autoip != NULL);
+ LWIP_ASSERT("netif already has a struct autoip set",
+ netif_autoip_data(netif) == NULL);
+
+ /* clear data structure */
+ memset(autoip, 0, sizeof(struct autoip));
+ /* autoip->state = AUTOIP_STATE_OFF; */
+ netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip);
+}
+
+/** Restart AutoIP client and check the next address (conflict detected)
+ *
+ * @param netif The netif under AutoIP control
+ */
+static void
+autoip_restart(struct netif *netif)
+{
+ struct autoip* autoip = netif_autoip_data(netif);
+ autoip->tried_llipaddr++;
+ autoip_start(netif);
+}
+
+/**
+ * Handle a IP address conflict after an ARP conflict detection
+ */
+static void
+autoip_handle_arp_conflict(struct netif *netif)
+{
+ struct autoip* autoip = netif_autoip_data(netif);
+
+ /* RFC3927, 2.5 "Conflict Detection and Defense" allows two options where
+ a) means retreat on the first conflict and
+ b) allows to keep an already configured address when having only one
+ conflict in 10 seconds
+ We use option b) since it helps to improve the chance that one of the two
+ conflicting hosts may be able to retain its address. */
+
+ if (autoip->lastconflict > 0) {
+ /* retreat, there was a conflicting ARP in the last DEFEND_INTERVAL seconds */
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
+ ("autoip_handle_arp_conflict(): we are defending, but in DEFEND_INTERVAL, retreating\n"));
+
+ /* Active TCP sessions are aborted when removing the ip addresss */
+ autoip_restart(netif);
+ } else {
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
+ ("autoip_handle_arp_conflict(): we are defend, send ARP Announce\n"));
+ autoip_arp_announce(netif);
+ autoip->lastconflict = DEFEND_INTERVAL * AUTOIP_TICKS_PER_SECOND;
+ }
+}
+
+/**
+ * Create an IP-Address out of range 169.254.1.0 to 169.254.254.255
+ *
+ * @param netif network interface on which create the IP-Address
+ * @param ipaddr ip address to initialize
+ */
+static void
+autoip_create_addr(struct netif *netif, ip4_addr_t *ipaddr)
+{
+ struct autoip* autoip = netif_autoip_data(netif);
+
+ /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255
+ * compliant to RFC 3927 Section 2.1
+ * We have 254 * 256 possibilities */
+
+ u32_t addr = ntohl(LWIP_AUTOIP_CREATE_SEED_ADDR(netif));
+ addr += autoip->tried_llipaddr;
+ addr = AUTOIP_NET | (addr & 0xffff);
+ /* Now, 169.254.0.0 <= addr <= 169.254.255.255 */
+
+ if (addr < AUTOIP_RANGE_START) {
+ addr += AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
+ }
+ if (addr > AUTOIP_RANGE_END) {
+ addr -= AUTOIP_RANGE_END - AUTOIP_RANGE_START + 1;
+ }
+ LWIP_ASSERT("AUTOIP address not in range", (addr >= AUTOIP_RANGE_START) &&
+ (addr <= AUTOIP_RANGE_END));
+ ip4_addr_set_u32(ipaddr, htonl(addr));
+
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
+ ("autoip_create_addr(): tried_llipaddr=%"U16_F", %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ (u16_t)(autoip->tried_llipaddr), ip4_addr1_16(ipaddr), ip4_addr2_16(ipaddr),
+ ip4_addr3_16(ipaddr), ip4_addr4_16(ipaddr)));
+}
+
+/**
+ * Sends an ARP probe from a network interface
+ *
+ * @param netif network interface used to send the probe
+ */
+static err_t
+autoip_arp_probe(struct netif *netif)
+{
+ struct autoip* autoip = netif_autoip_data(netif);
+ /* this works because netif->ip_addr is ANY */
+ return etharp_request(netif, &autoip->llipaddr);
+}
+
+/**
+ * Sends an ARP announce from a network interface
+ *
+ * @param netif network interface used to send the announce
+ */
+static err_t
+autoip_arp_announce(struct netif *netif)
+{
+ return etharp_gratuitous(netif);
+}
+
+/**
+ * Configure interface for use with current LL IP-Address
+ *
+ * @param netif network interface to configure with current LL IP-Address
+ */
+static err_t
+autoip_bind(struct netif *netif)
+{
+ struct autoip* autoip = netif_autoip_data(netif);
+ ip4_addr_t sn_mask, gw_addr;
+
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
+ ("autoip_bind(netif=%p) %c%c%"U16_F" %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ (void*)netif, netif->name[0], netif->name[1], (u16_t)netif->num,
+ ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
+ ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
+
+ IP4_ADDR(&sn_mask, 255, 255, 0, 0);
+ IP4_ADDR(&gw_addr, 0, 0, 0, 0);
+
+ netif_set_addr(netif, &autoip->llipaddr, &sn_mask, &gw_addr);
+ /* interface is used by routing now that an address is set */
+
+ return ERR_OK;
+}
+
+/**
+ * @ingroup autoip
+ * Start AutoIP client
+ *
+ * @param netif network interface on which start the AutoIP client
+ */
+err_t
+autoip_start(struct netif *netif)
+{
+ struct autoip* autoip = netif_autoip_data(netif);
+ err_t result = ERR_OK;
+
+ LWIP_ERROR("netif is not up, old style port?", netif_is_up(netif), return ERR_ARG;);
+
+ /* Set IP-Address, Netmask and Gateway to 0 to make sure that
+ * ARP Packets are formed correctly
+ */
+ netif_set_addr(netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY);
+
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
+ ("autoip_start(netif=%p) %c%c%"U16_F"\n", (void*)netif, netif->name[0],
+ netif->name[1], (u16_t)netif->num));
+ if (autoip == NULL) {
+ /* no AutoIP client attached yet? */
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
+ ("autoip_start(): starting new AUTOIP client\n"));
+ autoip = (struct autoip *)mem_malloc(sizeof(struct autoip));
+ if (autoip == NULL) {
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
+ ("autoip_start(): could not allocate autoip\n"));
+ return ERR_MEM;
+ }
+ memset(autoip, 0, sizeof(struct autoip));
+ /* store this AutoIP client in the netif */
+ netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_AUTOIP, autoip);
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_start(): allocated autoip"));
+ } else {
+ autoip->state = AUTOIP_STATE_OFF;
+ autoip->ttw = 0;
+ autoip->sent_num = 0;
+ ip4_addr_set_zero(&autoip->llipaddr);
+ autoip->lastconflict = 0;
+ }
+
+ autoip_create_addr(netif, &(autoip->llipaddr));
+ autoip_start_probing(netif);
+
+ return result;
+}
+
+static void
+autoip_start_probing(struct netif *netif)
+{
+ struct autoip* autoip = netif_autoip_data(netif);
+
+ autoip->state = AUTOIP_STATE_PROBING;
+ autoip->sent_num = 0;
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
+ ("autoip_start_probing(): changing state to PROBING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
+ ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
+
+ /* time to wait to first probe, this is randomly
+ * chosen out of 0 to PROBE_WAIT seconds.
+ * compliant to RFC 3927 Section 2.2.1
+ */
+ autoip->ttw = (u16_t)(LWIP_AUTOIP_RAND(netif) % (PROBE_WAIT * AUTOIP_TICKS_PER_SECOND));
+
+ /*
+ * if we tried more then MAX_CONFLICTS we must limit our rate for
+ * acquiring and probing address
+ * compliant to RFC 3927 Section 2.2.1
+ */
+ if (autoip->tried_llipaddr > MAX_CONFLICTS) {
+ autoip->ttw = RATE_LIMIT_INTERVAL * AUTOIP_TICKS_PER_SECOND;
+ }
+}
+
+/**
+ * Handle a possible change in the network configuration.
+ *
+ * If there is an AutoIP address configured, take the interface down
+ * and begin probing with the same address.
+ */
+void
+autoip_network_changed(struct netif *netif)
+{
+ struct autoip* autoip = netif_autoip_data(netif);
+
+ if (autoip && (autoip->state != AUTOIP_STATE_OFF)) {
+ autoip_start_probing(netif);
+ }
+}
+
+/**
+ * @ingroup autoip
+ * Stop AutoIP client
+ *
+ * @param netif network interface on which stop the AutoIP client
+ */
+err_t
+autoip_stop(struct netif *netif)
+{
+ struct autoip* autoip = netif_autoip_data(netif);
+
+ if (autoip != NULL) {
+ autoip->state = AUTOIP_STATE_OFF;
+ if (ip4_addr_islinklocal(netif_ip4_addr(netif))) {
+ netif_set_addr(netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY);
+ }
+ }
+ return ERR_OK;
+}
+
+/**
+ * Has to be called in loop every AUTOIP_TMR_INTERVAL milliseconds
+ */
+void
+autoip_tmr(void)
+{
+ struct netif *netif = netif_list;
+ /* loop through netif's */
+ while (netif != NULL) {
+ struct autoip* autoip = netif_autoip_data(netif);
+ /* only act on AutoIP configured interfaces */
+ if (autoip != NULL) {
+ if (autoip->lastconflict > 0) {
+ autoip->lastconflict--;
+ }
+
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE,
+ ("autoip_tmr() AutoIP-State: %"U16_F", ttw=%"U16_F"\n",
+ (u16_t)(autoip->state), autoip->ttw));
+
+ if (autoip->ttw > 0) {
+ autoip->ttw--;
+ }
+
+ switch(autoip->state) {
+ case AUTOIP_STATE_PROBING:
+ if (autoip->ttw == 0) {
+ if (autoip->sent_num >= PROBE_NUM) {
+ /* Switch to ANNOUNCING: now we can bind to an IP address and use it */
+ autoip->state = AUTOIP_STATE_ANNOUNCING;
+ autoip_bind(netif);
+ /* autoip_bind() calls netif_set_addr(): this triggers a gratuitous ARP
+ which counts as an announcement */
+ autoip->sent_num = 1;
+ autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
+ ("autoip_tmr(): changing state to ANNOUNCING: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
+ ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
+ } else {
+ autoip_arp_probe(netif);
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() PROBING Sent Probe\n"));
+ autoip->sent_num++;
+ if (autoip->sent_num == PROBE_NUM) {
+ /* calculate time to wait to for announce */
+ autoip->ttw = ANNOUNCE_WAIT * AUTOIP_TICKS_PER_SECOND;
+ } else {
+ /* calculate time to wait to next probe */
+ autoip->ttw = (u16_t)((LWIP_AUTOIP_RAND(netif) %
+ ((PROBE_MAX - PROBE_MIN) * AUTOIP_TICKS_PER_SECOND) ) +
+ PROBE_MIN * AUTOIP_TICKS_PER_SECOND);
+ }
+ }
+ }
+ break;
+
+ case AUTOIP_STATE_ANNOUNCING:
+ if (autoip->ttw == 0) {
+ autoip_arp_announce(netif);
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_tmr() ANNOUNCING Sent Announce\n"));
+ autoip->ttw = ANNOUNCE_INTERVAL * AUTOIP_TICKS_PER_SECOND;
+ autoip->sent_num++;
+
+ if (autoip->sent_num >= ANNOUNCE_NUM) {
+ autoip->state = AUTOIP_STATE_BOUND;
+ autoip->sent_num = 0;
+ autoip->ttw = 0;
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE,
+ ("autoip_tmr(): changing state to BOUND: %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
+ ip4_addr1_16(&autoip->llipaddr), ip4_addr2_16(&autoip->llipaddr),
+ ip4_addr3_16(&autoip->llipaddr), ip4_addr4_16(&autoip->llipaddr)));
+ }
+ }
+ break;
+
+ default:
+ /* nothing to do in other states */
+ break;
+ }
+ }
+ /* proceed to next network interface */
+ netif = netif->next;
+ }
+}
+
+/**
+ * Handles every incoming ARP Packet, called by etharp_input().
+ *
+ * @param netif network interface to use for autoip processing
+ * @param hdr Incoming ARP packet
+ */
+void
+autoip_arp_reply(struct netif *netif, struct etharp_hdr *hdr)
+{
+ struct autoip* autoip = netif_autoip_data(netif);
+
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE, ("autoip_arp_reply()\n"));
+ if ((autoip != NULL) && (autoip->state != AUTOIP_STATE_OFF)) {
+ /* when ip.src == llipaddr && hw.src != netif->hwaddr
+ *
+ * when probing ip.dst == llipaddr && hw.src != netif->hwaddr
+ * we have a conflict and must solve it
+ */
+ ip4_addr_t sipaddr, dipaddr;
+ struct eth_addr netifaddr;
+ ETHADDR16_COPY(netifaddr.addr, netif->hwaddr);
+
+ /* Copy struct ip4_addr2 to aligned ip4_addr, to support compilers without
+ * structure packing (not using structure copy which breaks strict-aliasing rules).
+ */
+ IPADDR2_COPY(&sipaddr, &hdr->sipaddr);
+ IPADDR2_COPY(&dipaddr, &hdr->dipaddr);
+
+ if (autoip->state == AUTOIP_STATE_PROBING) {
+ /* RFC 3927 Section 2.2.1:
+ * from beginning to after ANNOUNCE_WAIT
+ * seconds we have a conflict if
+ * ip.src == llipaddr OR
+ * ip.dst == llipaddr && hw.src != own hwaddr
+ */
+ if ((ip4_addr_cmp(&sipaddr, &autoip->llipaddr)) ||
+ (ip4_addr_cmp(&dipaddr, &autoip->llipaddr) &&
+ !eth_addr_cmp(&netifaddr, &hdr->shwaddr))) {
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
+ ("autoip_arp_reply(): Probe Conflict detected\n"));
+ autoip_restart(netif);
+ }
+ } else {
+ /* RFC 3927 Section 2.5:
+ * in any state we have a conflict if
+ * ip.src == llipaddr && hw.src != own hwaddr
+ */
+ if (ip4_addr_cmp(&sipaddr, &autoip->llipaddr) &&
+ !eth_addr_cmp(&netifaddr, &hdr->shwaddr)) {
+ LWIP_DEBUGF(AUTOIP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE | LWIP_DBG_LEVEL_WARNING,
+ ("autoip_arp_reply(): Conflicting ARP-Packet detected\n"));
+ autoip_handle_arp_conflict(netif);
+ }
+ }
+ }
+}
+
+/** check if AutoIP supplied netif->ip_addr
+ *
+ * @param netif the netif to check
+ * @return 1 if AutoIP supplied netif->ip_addr (state BOUND or ANNOUNCING),
+ * 0 otherwise
+ */
+u8_t
+autoip_supplied_address(const struct netif *netif)
+{
+ if ((netif != NULL) && (netif_autoip_data(netif) != NULL)) {
+ struct autoip* autoip = netif_autoip_data(netif);
+ return (autoip->state == AUTOIP_STATE_BOUND) || (autoip->state == AUTOIP_STATE_ANNOUNCING);
+ }
+ return 0;
+}
+
+u8_t
+autoip_accept_packet(struct netif *netif, const ip4_addr_t *addr)
+{
+ struct autoip* autoip = netif_autoip_data(netif);
+ return (autoip != NULL) && ip4_addr_cmp(addr, &(autoip->llipaddr));
+}
+
+#endif /* LWIP_IPV4 && LWIP_AUTOIP */