diff --git a/components/net/lwip/origin.patch b/components/net/lwip/origin.patch index 0fb1a3f9f256694169de2e6b76e8edfb6d072f03..c7e4b3a56ab7ea78f0ebe9448528173c417c9fdd 100644 --- a/components/net/lwip/origin.patch +++ b/components/net/lwip/origin.patch @@ -1,6 +1,6 @@ diff -Nur a/lwip-2.1.2/src/api/api_lib.c b/lwip-2.1.2/src/api/api_lib.c ---- a/lwip-2.1.2/src/api/api_lib.c 2021-06-29 15:16:18.792893320 +0800 -+++ b/lwip-2.1.2/src/api/api_lib.c 2021-06-29 15:16:44.624898723 +0800 +--- a/lwip-2.1.2/src/api/api_lib.c 2022-02-16 16:06:59.162116000 +0800 ++++ b/lwip-2.1.2/src/api/api_lib.c 2022-01-27 19:50:36.581826000 +0800 @@ -146,7 +146,7 @@ * NULL on memory error */ @@ -82,6 +82,15 @@ diff -Nur a/lwip-2.1.2/src/api/api_lib.c b/lwip-2.1.2/src/api/api_lib.c if (sys_arch_mbox_tryfetch(&conn->recvmbox, &buf) == SYS_ARCH_TIMEOUT) { err_t err; NETCONN_MBOX_WAITING_DEC(conn); +@@ -616,7 +654,7 @@ + NETCONN_MBOX_WAITING_DEC(conn); + return ERR_TIMEOUT; + } +-#else ++#else + sys_arch_mbox_fetch(&conn->recvmbox, &buf, 0); + #endif /* LWIP_SO_RCVTIMEO*/ + } @@ -1144,8 +1182,7 @@ return ERR_OK; } @@ -93,8 +102,8 @@ diff -Nur a/lwip-2.1.2/src/api/api_lib.c b/lwip-2.1.2/src/api/api_lib.c return err; } diff -Nur a/lwip-2.1.2/src/api/api_msg.c b/lwip-2.1.2/src/api/api_msg.c ---- a/lwip-2.1.2/src/api/api_msg.c 2021-06-29 15:16:18.792893320 +0800 -+++ b/lwip-2.1.2/src/api/api_msg.c 2021-06-29 15:16:44.624898723 +0800 +--- a/lwip-2.1.2/src/api/api_msg.c 2022-02-16 16:06:59.162116000 +0800 ++++ b/lwip-2.1.2/src/api/api_msg.c 2022-01-27 20:10:56.375193000 +0800 @@ -184,10 +184,36 @@ return 0; } @@ -247,16 +256,19 @@ diff -Nur a/lwip-2.1.2/src/api/api_msg.c b/lwip-2.1.2/src/api/api_msg.c #endif /* LWIP_RAW */ #if LWIP_UDP case NETCONN_UDP: -@@ -1216,33 +1277,51 @@ +@@ -1216,33 +1277,56 @@ lwip_netconn_do_bind(void *m) { struct api_msg *msg = (struct api_msg *)m; - err_t err; ++#if !LWIP_NIP + struct netif *netif = NULL; + netif = netif_find_by_ipaddr(API_EXPR_REF(msg->msg.bc.ipaddr)); ++#endif - if (msg->conn->pcb.tcp != NULL) { - switch (NETCONNTYPE_GROUP(msg->conn->type)) { ++#if !LWIP_NIP + if (ERR_IS_FATAL(msg->conn->last_err)) { + msg->err = (err_t)((msg->conn->state == NETCONN_CLOSED) ? ERR_VAL : msg->conn->last_err); + } else if (!(ip_addr_isany(API_EXPR_REF(msg->msg.bc.ipaddr)) || @@ -264,7 +276,9 @@ diff -Nur a/lwip-2.1.2/src/api/api_msg.c b/lwip-2.1.2/src/api/api_msg.c + netif_ipaddr_isbrdcast(API_EXPR_REF(msg->msg.bc.ipaddr)) || + ((netif != NULL) && netif_is_up(netif)))) { + msg->err = ERR_NOADDR; -+ } else { ++ } else ++#endif ++ { + msg->err = ERR_VAL; + if (msg->conn->pcb.tcp != NULL) { + switch (NETCONNTYPE_GROUP(msg->conn->type)) { @@ -309,7 +323,7 @@ diff -Nur a/lwip-2.1.2/src/api/api_msg.c b/lwip-2.1.2/src/api/api_msg.c TCPIP_APIMSG_ACK(msg); } /** -@@ -1351,6 +1430,11 @@ +@@ -1351,6 +1435,11 @@ { struct api_msg *msg = (struct api_msg *)m; err_t err; @@ -321,7 +335,7 @@ diff -Nur a/lwip-2.1.2/src/api/api_msg.c b/lwip-2.1.2/src/api/api_msg.c if (msg->conn->pcb.tcp == NULL) { /* This may happen when calling netconn_connect() a second time */ -@@ -1540,11 +1624,44 @@ +@@ -1540,11 +1629,44 @@ #if LWIP_RAW case NETCONN_RAW: if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { @@ -366,7 +380,7 @@ diff -Nur a/lwip-2.1.2/src/api/api_msg.c b/lwip-2.1.2/src/api/api_msg.c #endif #if LWIP_UDP case NETCONN_UDP: -@@ -1868,6 +1985,11 @@ +@@ -1868,6 +1990,11 @@ { struct api_msg *msg = (struct api_msg *)m; @@ -378,7 +392,7 @@ diff -Nur a/lwip-2.1.2/src/api/api_msg.c b/lwip-2.1.2/src/api/api_msg.c if (msg->conn->pcb.ip != NULL) { if (msg->msg.ad.local) { ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), -@@ -1882,10 +2004,18 @@ +@@ -1882,10 +2009,18 @@ #if LWIP_RAW case NETCONN_RAW: if (msg->msg.ad.local) { @@ -400,7 +414,7 @@ diff -Nur a/lwip-2.1.2/src/api/api_msg.c b/lwip-2.1.2/src/api/api_msg.c } break; #endif /* LWIP_RAW */ -@@ -1923,6 +2053,47 @@ +@@ -1923,6 +2058,47 @@ TCPIP_APIMSG_ACK(msg); } @@ -449,8 +463,8 @@ diff -Nur a/lwip-2.1.2/src/api/api_msg.c b/lwip-2.1.2/src/api/api_msg.c * Close or half-shutdown a TCP pcb contained in a netconn * Called from netconn_close diff -Nur a/lwip-2.1.2/src/api/netbuf.c b/lwip-2.1.2/src/api/netbuf.c ---- a/lwip-2.1.2/src/api/netbuf.c 2021-06-29 15:16:18.792893320 +0800 -+++ b/lwip-2.1.2/src/api/netbuf.c 2021-06-29 15:16:44.624898723 +0800 +--- a/lwip-2.1.2/src/api/netbuf.c 2022-02-16 16:06:59.162116000 +0800 ++++ b/lwip-2.1.2/src/api/netbuf.c 2022-01-25 14:41:30.864899000 +0800 @@ -48,7 +48,7 @@ #include "lwip/netbuf.h" @@ -494,8 +508,8 @@ diff -Nur a/lwip-2.1.2/src/api/netbuf.c b/lwip-2.1.2/src/api/netbuf.c return NULL; } diff -Nur a/lwip-2.1.2/src/api/netdb.c b/lwip-2.1.2/src/api/netdb.c ---- a/lwip-2.1.2/src/api/netdb.c 2021-06-29 15:16:18.796893321 +0800 -+++ b/lwip-2.1.2/src/api/netdb.c 2021-06-29 15:16:44.624898723 +0800 +--- a/lwip-2.1.2/src/api/netdb.c 2022-02-16 16:06:59.162116000 +0800 ++++ b/lwip-2.1.2/src/api/netdb.c 2022-01-28 16:53:08.421137000 +0800 @@ -58,7 +58,7 @@ /** h_errno is exported in netdb.h for access by applications. */ @@ -514,7 +528,32 @@ diff -Nur a/lwip-2.1.2/src/api/netdb.c b/lwip-2.1.2/src/api/netdb.c return NULL; } -@@ -374,10 +374,14 @@ +@@ -295,6 +295,9 @@ + #if LWIP_IPV6 + && (ai_family != AF_INET6) + #endif /* LWIP_IPV6 */ ++#if LWIP_NIP ++ && (ai_family != AF_NIP) ++#endif /* LWIP_NIP */ + ) { + return EAI_FAMILY; + } +@@ -340,12 +343,14 @@ + } + } + } else { ++#if !LWIP_NIP + /* service location specified, use loopback address */ + if ((hints != NULL) && (hints->ai_flags & AI_PASSIVE)) { + ip_addr_set_any_val(ai_family == AF_INET6, addr); + } else { + ip_addr_set_loopback_val(ai_family == AF_INET6, addr); + } ++#endif + } + + total_size = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage); +@@ -374,10 +379,14 @@ /* set up sockaddr */ inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr)); sa6->sin6_family = AF_INET6; @@ -529,7 +568,7 @@ diff -Nur a/lwip-2.1.2/src/api/netdb.c b/lwip-2.1.2/src/api/netdb.c #endif /* LWIP_IPV6 */ } else { #if LWIP_IPV4 -@@ -385,9 +389,9 @@ +@@ -385,9 +394,9 @@ /* set up sockaddr */ inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr)); sa4->sin_family = AF_INET; @@ -540,7 +579,7 @@ diff -Nur a/lwip-2.1.2/src/api/netdb.c b/lwip-2.1.2/src/api/netdb.c #endif /* LWIP_IPV4 */ } -@@ -403,7 +407,6 @@ +@@ -403,7 +412,6 @@ MEMCPY(ai->ai_canonname, nodename, namelen); ai->ai_canonname[namelen] = 0; } @@ -549,8 +588,8 @@ diff -Nur a/lwip-2.1.2/src/api/netdb.c b/lwip-2.1.2/src/api/netdb.c *res = ai; diff -Nur a/lwip-2.1.2/src/api/netifapi.c b/lwip-2.1.2/src/api/netifapi.c ---- a/lwip-2.1.2/src/api/netifapi.c 2021-06-29 15:16:18.796893321 +0800 -+++ b/lwip-2.1.2/src/api/netifapi.c 2021-06-29 15:16:44.624898723 +0800 +--- a/lwip-2.1.2/src/api/netifapi.c 2022-02-16 16:06:59.162116000 +0800 ++++ b/lwip-2.1.2/src/api/netifapi.c 2022-01-25 15:39:07.614879000 +0800 @@ -54,6 +54,21 @@ #define NETIFAPI_VAR_ALLOC(name) API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, name, ERR_MEM) #define NETIFAPI_VAR_FREE(name) API_VAR_FREE(MEMP_NETIFAPI_MSG, name) @@ -573,8 +612,13 @@ diff -Nur a/lwip-2.1.2/src/api/netifapi.c b/lwip-2.1.2/src/api/netifapi.c /** * Call netif_add() inside the tcpip_thread context. */ -@@ -71,8 +86,8 @@ +@@ -69,10 +84,13 @@ + API_EXPR_REF(msg->msg.add.ipaddr), + API_EXPR_REF(msg->msg.add.netmask), API_EXPR_REF(msg->msg.add.gw), ++#elif LWIP_NIP ++ NULL, ++ NULL, #endif /* LWIP_IPV4 */ msg->msg.add.state, - msg->msg.add.init, @@ -584,7 +628,7 @@ diff -Nur a/lwip-2.1.2/src/api/netifapi.c b/lwip-2.1.2/src/api/netifapi.c return ERR_IF; } else { return ERR_OK; -@@ -248,8 +263,8 @@ +@@ -248,8 +266,8 @@ NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); #endif /* LWIP_IPV4 */ NETIFAPI_VAR_REF(msg).msg.add.state = state; @@ -595,7 +639,7 @@ diff -Nur a/lwip-2.1.2/src/api/netifapi.c b/lwip-2.1.2/src/api/netifapi.c err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call); NETIFAPI_VAR_FREE(msg); return err; -@@ -377,4 +392,60 @@ +@@ -377,4 +395,60 @@ return err; } @@ -657,8 +701,8 @@ diff -Nur a/lwip-2.1.2/src/api/netifapi.c b/lwip-2.1.2/src/api/netifapi.c +} #endif /* LWIP_NETIF_API */ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c ---- a/lwip-2.1.2/src/api/sockets.c 2021-06-29 15:16:18.796893321 +0800 -+++ b/lwip-2.1.2/src/api/sockets.c 2021-06-29 15:16:44.624898723 +0800 +--- a/lwip-2.1.2/src/api/sockets.c 2022-02-16 16:06:59.162116000 +0800 ++++ b/lwip-2.1.2/src/api/sockets.c 2022-01-28 17:25:28.049165000 +0800 @@ -54,6 +54,7 @@ #include "lwip/netif.h" #include "lwip/priv/tcpip_priv.h" @@ -700,7 +744,51 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c (sin6)->sin6_family = AF_INET6; \ (sin6)->sin6_port = lwip_htons((port)); \ (sin6)->sin6_flowinfo = 0; \ -@@ -283,6 +296,45 @@ +@@ -113,6 +126,17 @@ + (port) = lwip_ntohs((sin6)->sin6_port); }while(0) + #endif /* LWIP_IPV6 */ + ++#if LWIP_NIP ++#define NIPADDR_PORT_TO_SOCKADDR(snin, ipaddr, port) do { \ ++ (snin)->snin_len = sizeof(struct sockaddr_nin); \ ++ (snin)->snin_family = AF_NIP; \ ++ (snin)->snin_port = lwip_htons((port)); \ ++ nin_addr_from_nipaddr(&(snin)->snin_addr, ipaddr); }while(0) ++#define SOCKADDRN_TO_NIPADDR_PORT(snin, ipaddr, port) do { \ ++ nin_addr_to_nipaddr(ip_2_nip(ipaddr), &((snin)->snin_addr)); \ ++ (port) = lwip_ntohs((snin)->snin_port); }while(0) ++#endif /* LWIP_NIP */ ++ + #if LWIP_IPV4 && LWIP_IPV6 + static void sockaddr_to_ipaddr_port(const struct sockaddr *sockaddr, ip_addr_t *ipaddr, u16_t *port); + +@@ -141,6 +165,15 @@ + #define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ + SOCKADDR6_TO_IP6ADDR_PORT((const struct sockaddr_in6*)(const void*)(sockaddr), ipaddr, port) + #define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) ++#elif LWIP_NIP /* LWIP_IPV4 && LWIP_IPV6 */ ++#define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_nin)) ++#define IS_SOCK_ADDR_TYPE_VALID(name) (((struct sockaddr_nin*)name)->snin_family == AF_NIP) ++#define SOCK_ADDR_TYPE_MATCH(name, sock) 1 ++#define IPADDR_PORT_TO_SOCKADDR(sockaddr, ipaddr, port) \ ++ NIPADDR_PORT_TO_SOCKADDR((struct sockaddr_nin*)(void*)(sockaddr), ip_2_nip(ipaddr), port) ++#define SOCKADDR_TO_IPADDR_PORT(sockaddr, ipaddr, port) \ ++ SOCKADDRN_TO_NIPADDR_PORT((const struct sockaddr_nin*)(const void*)(sockaddr), ipaddr, port) ++#define DOMAIN_TO_NETCONN_TYPE(domain, netconn_type) (netconn_type) + #else /*-> LWIP_IPV4: LWIP_IPV4 && LWIP_IPV6 */ + #define IS_SOCK_ADDR_LEN_VALID(namelen) ((namelen) == sizeof(struct sockaddr_in)) + #define IS_SOCK_ADDR_TYPE_VALID(name) ((name)->sa_family == AF_INET) +@@ -211,6 +244,9 @@ + #if LWIP_IPV4 + struct sockaddr_in sin; + #endif /* LWIP_IPV4 */ ++#if LWIP_NIP ++ struct sockaddr_nin snin; ++#endif /* LWIP_NIP */ + }; + + /* Define the number of IPv4 multicast memberships, default is one per socket */ +@@ -283,6 +319,45 @@ set_errno(sockerr); \ } while (0) @@ -746,7 +834,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c /* Forward declaration of some functions */ #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len); -@@ -489,6 +541,29 @@ +@@ -489,6 +564,29 @@ return sock; } @@ -776,7 +864,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c /** * Allocate a new socket for a given netconn. * -@@ -696,8 +771,10 @@ +@@ -696,8 +794,10 @@ } IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); @@ -789,7 +877,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c } MEMCPY(addr, &tempaddr, *addrlen); -@@ -722,28 +799,58 @@ +@@ -722,28 +822,59 @@ u16_t local_port; err_t err; @@ -831,6 +919,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c + LWIP_ERROR("lwip_bind: invalid address", ((name != NULL) && IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_ALIGNED(name)), sock_set_errno(sock, err_to_errno(ERR_VAL)); + done_socket(sock); return -1); ++ + LWIP_ERROR("lwip_bind: invalid address", + (IS_SOCK_ADDR_TYPE_VALID(name)), sock_set_errno(sock, err_to_errno(ERR_AFNOSUPPORT)); + done_socket(sock); return -1); @@ -861,7 +950,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c #if LWIP_IPV4 && LWIP_IPV6 /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ -@@ -753,7 +860,11 @@ +@@ -753,7 +884,11 @@ } #endif /* LWIP_IPV4 && LWIP_IPV6 */ @@ -873,7 +962,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c if (err != ERR_OK) { LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); -@@ -820,6 +931,14 @@ +@@ -820,6 +955,14 @@ return -1; } @@ -888,7 +977,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c if (!SOCK_ADDR_TYPE_MATCH_OR_UNSPEC(name, sock)) { /* sockaddr does not match socket type (IPv4/IPv6) */ sock_set_errno(sock, err_to_errno(ERR_VAL)); -@@ -1025,6 +1144,7 @@ +@@ -1025,6 +1168,7 @@ { int truncated = 0; union sockaddr_aligned saddr; @@ -896,7 +985,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c LWIP_UNUSED_ARG(conn); -@@ -1041,10 +1161,20 @@ +@@ -1041,10 +1185,27 @@ #endif /* LWIP_IPV4 && LWIP_IPV6 */ IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port); @@ -904,9 +993,16 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c +#if LWIP_LITEOS_COMPAT + if (IP_IS_V4_VAL(*fromaddr)) { + sa_len = sizeof(struct sockaddr_in); -+ } else { ++ } ++#if LWIP_NIP ++ else if (IP_IS_NIP_VAL(*fromaddr)) { ++ sa_len = sizeof(struct sockaddr_nin); ++ } ++#endif ++ else { + sa_len = sizeof(struct sockaddr_in6); + } ++ +#else + sa_len = saddr.sa.sa_len; +#endif /* LWIP_LITEOS_COMPAT */ @@ -920,7 +1016,24 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c } MEMCPY(from, &saddr, *fromlen); return truncated; -@@ -1146,8 +1276,44 @@ +@@ -1092,7 +1253,7 @@ + err_t err; + u16_t buflen, copylen, copied; + int i; +- ++ + LWIP_UNUSED_ARG(dbg_s); + LWIP_ERROR("lwip_recvfrom_udp_raw: invalid arguments", (msg->msg_iov != NULL) || (msg->msg_iovlen <= 0), return ERR_ARG;); + +@@ -1120,7 +1281,6 @@ + } + buflen = buf->p->tot_len; + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom_udp_raw: buflen=%"U16_F"\n", buflen)); +- + copied = 0; + /* copy the pbuf payload into the iovs */ + for (i = 0; (i < msg->msg_iovlen) && (copied < buflen); i++) { +@@ -1146,10 +1306,47 @@ ip_addr_debug_print_val(SOCKETS_DEBUG, *netbuf_fromaddr(buf)); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F" len=%d\n", netbuf_fromport(buf), copied)); if (msg->msg_name && msg->msg_namelen) { @@ -966,8 +1079,19 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c + } } } ++ -@@ -1496,7 +1662,7 @@ + /* Initialize flag output */ + msg->msg_flags = 0; +@@ -1201,7 +1398,6 @@ + { + struct lwip_sock *sock; + ssize_t ret; +- + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom(%d, %p, %"SZT_F", 0x%x, ..)\n", s, mem, len, flags)); + sock = get_socket(s); + if (!sock) { +@@ -1496,7 +1692,7 @@ goto sendmsg_emsgsize; } /* Allocate a new netbuf and copy the data into it. */ @@ -976,7 +1100,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c err = ERR_MEM; } else { /* flatten the IO vectors */ -@@ -1588,8 +1754,14 @@ +@@ -1588,8 +1784,14 @@ struct lwip_sock *sock; err_t err; u16_t short_size; @@ -992,7 +1116,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c sock = get_socket(s); if (!sock) { -@@ -1608,11 +1780,62 @@ +@@ -1608,11 +1810,62 @@ #endif /* LWIP_TCP */ } @@ -1060,7 +1184,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c } short_size = (u16_t)size; LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || -@@ -1626,6 +1849,9 @@ +@@ -1626,6 +1879,9 @@ #if LWIP_CHECKSUM_ON_COPY buf.flags = 0; #endif /* LWIP_CHECKSUM_ON_COPY */ @@ -1070,7 +1194,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c if (to) { SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port); } else { -@@ -1637,17 +1863,29 @@ +@@ -1637,17 +1893,29 @@ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=", s, data, short_size, flags)); @@ -1105,20 +1229,23 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); netbuf_set_chksum(&buf, chksum); } else -@@ -1688,14 +1926,32 @@ +@@ -1686,16 +1954,34 @@ + { + struct netconn *conn; int i; - +- ++#if !LWIP_NIP LWIP_UNUSED_ARG(domain); /* @todo: check this */ + LWIP_ERROR("domain invalid\n", (LWIP_IS_VALID_DOMAIN(domain)), + set_errno(EAFNOSUPPORT); return -1); -+ + + LWIP_ERROR("flag invalid\n", !(type & ~SOCK_TYPE_MASK), + set_errno(EINVAL); return -1); +#if PF_PACKET_SOCKET + LWIP_ERROR("Invalid socket type for PF_PACKET domain\n", ((domain != PF_PACKET) || (type == SOCK_RAW)), + set_errno(ESOCKTNOSUPPORT); return -1); +#endif - ++#endif /* create a netconn */ switch (type) { case SOCK_RAW: @@ -1141,7 +1268,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c break; case SOCK_DGRAM: conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, -@@ -1983,10 +2239,11 @@ +@@ -1983,10 +2269,11 @@ timeout ? (s32_t)timeout->tv_sec : (s32_t) - 1, timeout ? (s32_t)timeout->tv_usec : (s32_t) - 1)); @@ -1154,7 +1281,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c lwip_select_inc_sockets_used(maxfdp1, readset, writeset, exceptset, &used_sockets); -@@ -2704,12 +2961,60 @@ +@@ -2704,12 +2991,60 @@ ip_addr_t naddr; u16_t port; err_t err; @@ -1215,7 +1342,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c /* get the IP address and port */ err = netconn_getaddr(sock->conn, &naddr, &port, local); if (err != ERR_OK) { -@@ -2732,9 +3037,14 @@ +@@ -2732,9 +3067,14 @@ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getaddrname(%d, addr=", s)); ip_addr_debug_print_val(SOCKETS_DEBUG, naddr); LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", port)); @@ -1232,7 +1359,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c } MEMCPY(name, &saddr, *namelen); -@@ -2775,6 +3085,14 @@ +@@ -2775,6 +3115,14 @@ return -1; } @@ -1247,7 +1374,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c #if LWIP_TCPIP_CORE_LOCKING /* core-locking can just call the -impl function */ LOCK_TCPIP_CORE(); -@@ -2826,8 +3144,9 @@ +@@ -2826,8 +3174,9 @@ err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); #endif /* LWIP_TCPIP_CORE_LOCKING */ @@ -1259,7 +1386,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c done_socket(sock); return err ? -1 : 0; } -@@ -2897,6 +3216,11 @@ +@@ -2897,6 +3246,11 @@ /* Level: SOL_SOCKET */ case SOL_SOCKET: @@ -1271,7 +1398,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c switch (optname) { #if LWIP_TCP -@@ -2920,6 +3244,10 @@ +@@ -2920,6 +3274,10 @@ #if SO_REUSE case SO_REUSEADDR: #endif /* SO_REUSE */ @@ -1282,7 +1409,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c if ((optname == SO_BROADCAST) && (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP)) { done_socket(sock); -@@ -2937,6 +3265,9 @@ +@@ -2937,6 +3295,9 @@ case SO_TYPE: LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) { @@ -1292,7 +1419,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c case NETCONN_RAW: *(int *)optval = SOCK_RAW; break; -@@ -2948,9 +3279,16 @@ +@@ -2948,9 +3309,16 @@ break; default: /* unrecognized socket type */ *(int *)optval = netconn_type(sock->conn); @@ -1309,7 +1436,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c } /* switch (netconn_type(sock->conn)) */ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", s, *(int *)optval)); -@@ -3739,92 +4077,450 @@ +@@ -3739,92 +4107,450 @@ return err; } @@ -1821,7 +1948,7 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c } /** A minimal implementation of fcntl. -@@ -3878,7 +4574,6 @@ +@@ -3878,7 +4604,6 @@ /* ensure O_RDWR for (O_RDONLY|O_WRONLY) != O_RDWR cases */ ret |= (op_mode == (O_RDONLY | O_WRONLY)) ? O_RDWR : op_mode; @@ -1830,8 +1957,8 @@ diff -Nur a/lwip-2.1.2/src/api/sockets.c b/lwip-2.1.2/src/api/sockets.c case F_SETFL: /* Bits corresponding to the file access mode and the file creation flags [..] that are set in arg shall be ignored */ diff -Nur a/lwip-2.1.2/src/apps/tftp/tftp_server.c b/lwip-2.1.2/src/apps/tftp/tftp_server.c ---- a/lwip-2.1.2/src/apps/tftp/tftp_server.c 2021-06-29 15:16:18.800893322 +0800 -+++ b/lwip-2.1.2/src/apps/tftp/tftp_server.c 2021-06-29 15:16:44.632898725 +0800 +--- a/lwip-2.1.2/src/apps/tftp/tftp_server.c 2022-02-16 16:06:59.174115000 +0800 ++++ b/lwip-2.1.2/src/apps/tftp/tftp_server.c 2022-01-25 14:41:30.915761000 +0800 @@ -201,7 +201,7 @@ } @@ -1850,10 +1977,132 @@ diff -Nur a/lwip-2.1.2/src/apps/tftp/tftp_server.c b/lwip-2.1.2/src/apps/tftp/tf return ERR_OK; } +diff -Nur a/lwip-2.1.2/src/core/dns.c b/lwip-2.1.2/src/core/dns.c +--- a/lwip-2.1.2/src/core/dns.c 2022-02-16 16:06:59.174115000 +0800 ++++ b/lwip-2.1.2/src/core/dns.c 2022-01-28 16:50:26.340953000 +0800 +@@ -1130,6 +1130,7 @@ + } + } + ++#if !LWIP_NIP + /** + * Save TTL and call dns_call_found for correct response. + */ +@@ -1162,6 +1163,7 @@ + } + } + } ++#endif /* !LWIP_NIP */ + + /** + * Receive input function for DNS response packets arriving for the dns UDP pcb. +diff -Nur a/lwip-2.1.2/src/core/inet_chksum.c b/lwip-2.1.2/src/core/inet_chksum.c +--- a/lwip-2.1.2/src/core/inet_chksum.c 2022-02-16 16:06:59.174115000 +0800 ++++ b/lwip-2.1.2/src/core/inet_chksum.c 2022-01-25 14:55:36.001731000 +0800 +@@ -363,6 +363,18 @@ + } + #endif /* LWIP_IPV6 */ + ++#if LWIP_NIP ++u16_t ++nip_chksum_pseudo(struct pbuf *p, u8_t proto, u16_t proto_len, ++ const nip_addr_t *src, const nip_addr_t *dest) ++{ ++ u32_t acc; ++ ++ acc = 5; ++ return inet_cksum_pseudo_base(p, proto, proto_len, acc); ++} ++#endif /* LWIP_NIP */ ++ + /* ip_chksum_pseudo: + * + * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain. +@@ -387,6 +399,11 @@ + #if LWIP_IPV4 && LWIP_IPV6 + else + #endif /* LWIP_IPV4 && LWIP_IPV6 */ ++#if LWIP_NIP ++ if (IP_IS_NIP(dest)) { ++ return nip_chksum_pseudo(p, proto, proto_len, ip_2_nip(src), ip_2_nip(dest)); ++ } ++#endif /* LWIP_NIP */ + #if LWIP_IPV4 + { + return inet_chksum_pseudo(p, proto, proto_len, ip_2_ip4(src), ip_2_ip4(dest)); +@@ -511,6 +528,17 @@ + } + #endif /* LWIP_IPV6 */ + ++#if LWIP_NIP ++u16_t ++nip_chksum_pseudo_partial(struct pbuf *p, u8_t proto, u16_t proto_len, ++ u16_t chksum_len, const nip_addr_t *src, const nip_addr_t *dest) ++{ ++ u32_t acc = 0; ++ ++ return inet_cksum_pseudo_partial_base(p, proto, proto_len, chksum_len, acc); ++} ++#endif /* LWIP_NIP */ ++ + /* ip_chksum_pseudo_partial: + * + * Calculates the IPv4 or IPv6 pseudo Internet checksum used by TCP and UDP for a pbuf chain. +@@ -534,6 +562,11 @@ + #if LWIP_IPV4 && LWIP_IPV6 + else + #endif /* LWIP_IPV4 && LWIP_IPV6 */ ++#if LWIP_NIP ++ if (IP_IS_NIP(dest)) { ++ return nip_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_nip(src), ip_2_nip(dest)); ++ } ++#endif /* LWIP_NIP */ + #if LWIP_IPV4 + { + return inet_chksum_pseudo_partial(p, proto, proto_len, chksum_len, ip_2_ip4(src), ip_2_ip4(dest)); diff -Nur a/lwip-2.1.2/src/core/ip.c b/lwip-2.1.2/src/core/ip.c ---- a/lwip-2.1.2/src/core/ip.c 2021-06-29 15:16:18.804893322 +0800 -+++ b/lwip-2.1.2/src/core/ip.c 2021-06-29 15:16:44.632898725 +0800 -@@ -122,14 +122,12 @@ +--- a/lwip-2.1.2/src/core/ip.c 2022-02-16 16:06:59.174115000 +0800 ++++ b/lwip-2.1.2/src/core/ip.c 2022-01-28 17:08:49.249192000 +0800 +@@ -55,7 +55,7 @@ + + #include "lwip/opt.h" + +-#if LWIP_IPV4 || LWIP_IPV6 ++#if LWIP_IPV4 || LWIP_IPV6 || LWIP_NIP + + #include "lwip/ip_addr.h" + #include "lwip/ip.h" +@@ -83,7 +83,13 @@ + } + if (IP_IS_V6(addr)) { + return ip6addr_ntoa(ip_2_ip6(addr)); +- } else { ++ } ++#if LWIP_NIP ++ else if (IP_IS_NIP(addr)){ ++ return nipaddr_ntoa(ip_2_nip(addr)); ++ } ++#endif ++ else { + return ip4addr_ntoa(ip_2_ip4(addr)); + } + } +@@ -105,7 +111,13 @@ + } + if (IP_IS_V6(addr)) { + return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen); +- } else { ++ } ++#if LWIP_NIP ++ else if (IP_IS_NIP(addr)) { ++ return nipaddr_ntoa_r(ip_2_nip(addr), buf, buflen); ++ } ++#endif ++ else { + return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen); + } + } +@@ -122,14 +134,12 @@ int ipaddr_aton(const char *cp, ip_addr_t *addr) { @@ -1870,7 +2119,7 @@ diff -Nur a/lwip-2.1.2/src/core/ip.c b/lwip-2.1.2/src/core/ip.c return ip6addr_aton(cp, ip_2_ip6(addr)); } else if (*c == '.') { /* contains a dot: IPv4 address */ -@@ -137,9 +135,7 @@ +@@ -137,9 +147,7 @@ } } /* call ip4addr_aton as fallback or if IPv4 was found */ @@ -1881,7 +2130,20 @@ diff -Nur a/lwip-2.1.2/src/core/ip.c b/lwip-2.1.2/src/core/ip.c return ip4addr_aton(cp, ip_2_ip4(addr)); } return 0; -@@ -164,4 +160,63 @@ +@@ -157,11 +165,75 @@ + if (IP_HDR_GET_VERSION(p->payload) == 6) { + return ip6_input(p, inp); + } +- return ip4_input(p, inp); ++#if LWIP_NIP ++ else if (IP_HDR_GET_VERSION(p->payload) == 4) ++#endif ++ { ++ return ip4_input(p, inp); ++ } + } + return ERR_VAL; + } #endif /* LWIP_IPV4 && LWIP_IPV6 */ @@ -1946,8 +2208,8 @@ diff -Nur a/lwip-2.1.2/src/core/ip.c b/lwip-2.1.2/src/core/ip.c + #endif /* LWIP_IPV4 || LWIP_IPV6 */ diff -Nur a/lwip-2.1.2/src/core/ipv6/icmp6.c b/lwip-2.1.2/src/core/ipv6/icmp6.c ---- a/lwip-2.1.2/src/core/ipv6/icmp6.c 2021-06-29 15:16:18.804893322 +0800 -+++ b/lwip-2.1.2/src/core/ipv6/icmp6.c 2021-06-29 15:16:44.632898725 +0800 +--- a/lwip-2.1.2/src/core/ipv6/icmp6.c 2022-02-16 16:06:59.174115000 +0800 ++++ b/lwip-2.1.2/src/core/ipv6/icmp6.c 2022-01-25 14:41:30.938672000 +0800 @@ -82,14 +82,14 @@ void icmp6_input(struct pbuf *p, struct netif *inp) @@ -2007,8 +2269,8 @@ diff -Nur a/lwip-2.1.2/src/core/ipv6/icmp6.c b/lwip-2.1.2/src/core/ipv6/icmp6.c /* calculate checksum */ diff -Nur a/lwip-2.1.2/src/core/ipv6/nd6.c b/lwip-2.1.2/src/core/ipv6/nd6.c ---- a/lwip-2.1.2/src/core/ipv6/nd6.c 2021-06-29 15:16:18.804893322 +0800 -+++ b/lwip-2.1.2/src/core/ipv6/nd6.c 2021-06-29 15:16:44.632898725 +0800 +--- a/lwip-2.1.2/src/core/ipv6/nd6.c 2022-02-16 16:06:59.174115000 +0800 ++++ b/lwip-2.1.2/src/core/ipv6/nd6.c 2022-01-25 14:41:30.956624000 +0800 @@ -894,13 +894,13 @@ } case ICMP6_TYPE_PTB: /* Packet too big */ @@ -2037,8 +2299,8 @@ diff -Nur a/lwip-2.1.2/src/core/ipv6/nd6.c b/lwip-2.1.2/src/core/ipv6/nd6.c /* Create an aligned, zoned copy of the destination address. */ ip6_addr_copy_from_packed(destination_address, ip6hdr->dest); diff -Nur a/lwip-2.1.2/src/core/netif.c b/lwip-2.1.2/src/core/netif.c ---- a/lwip-2.1.2/src/core/netif.c 2021-06-29 15:16:18.804893322 +0800 -+++ b/lwip-2.1.2/src/core/netif.c 2021-06-29 15:16:44.632898725 +0800 +--- a/lwip-2.1.2/src/core/netif.c 2022-02-16 16:06:59.178115000 +0800 ++++ b/lwip-2.1.2/src/core/netif.c 2022-01-25 15:38:09.493661000 +0800 @@ -89,6 +89,8 @@ #if LWIP_IPV6 #include "lwip/nd6.h" @@ -2057,7 +2319,55 @@ diff -Nur a/lwip-2.1.2/src/core/netif.c b/lwip-2.1.2/src/core/netif.c /** * @ingroup netif * Add a network interface to the list of lwIP netifs. -@@ -377,36 +381,23 @@ +@@ -242,7 +246,10 @@ + #if LWIP_IPV4 + NULL, NULL, NULL, + #endif /* LWIP_IPV4*/ +- state, init, input); ++#if LWIP_NIP ++ NULL, NULL, ++#endif /* LWIP_NIP*/ ++ state, init, input); + } + + /** +@@ -276,6 +283,8 @@ + netif_add(struct netif *netif, + #if LWIP_IPV4 + const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, const ip4_addr_t *gw, ++#elif LWIP_NIP ++ const nip_addr_t *ipaddr, const nip_addr_t *gw, + #endif /* LWIP_IPV4 */ + void *state, netif_init_fn init, netif_input_fn input) + { +@@ -294,7 +303,14 @@ + + LWIP_ERROR("netif_add: invalid netif", netif != NULL, return NULL); + LWIP_ERROR("netif_add: No init function given", init != NULL, return NULL); +- ++#if LWIP_NIP ++ if (ipaddr == NULL) { ++ ipaddr = ip_2_nip(NIP_ADDR_ANY); ++ } ++ if (gw == NULL) { ++ gw = ip_2_nip(NIP_ADDR_ANY); ++ } ++#endif + #if LWIP_IPV4 + if (ipaddr == NULL) { + ipaddr = ip_2_ip4(IP4_ADDR_ANY); +@@ -367,6 +383,10 @@ + netif_set_addr(netif, ipaddr, netmask, gw); + #endif /* LWIP_IPV4 */ + ++#if LWIP_NIP ++ netif_set_nipaddr(netif, ipaddr, gw); ++#endif /* LWIP_NIP */ ++ + /* call user specified initialization function for netif */ + if (init(netif) != ERR_OK) { + return NULL; +@@ -377,36 +397,23 @@ netif->mtu6 = netif->mtu; #endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ @@ -2105,7 +2415,7 @@ diff -Nur a/lwip-2.1.2/src/core/netif.c b/lwip-2.1.2/src/core/netif.c /* add this netif to the list */ netif->next = netif_list; -@@ -421,8 +412,8 @@ +@@ -421,8 +428,8 @@ } #endif /* LWIP_IGMP */ @@ -2116,7 +2426,79 @@ diff -Nur a/lwip-2.1.2/src/core/netif.c b/lwip-2.1.2/src/core/netif.c #if LWIP_IPV4 LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); ip4_addr_debug_print(NETIF_DEBUG, ipaddr); -@@ -818,7 +809,7 @@ +@@ -727,6 +734,71 @@ + } + #endif /* LWIP_IPV4*/ + ++#if LWIP_NIP ++int ++netif_do_set_nipgw(struct netif *netif, const nip_addr_t *gw, nip_addr_t *old_gw) ++{ ++ if (nip_addr_cmp(gw, netif_nip_gw(netif)) == 0) { ++#if LWIP_NETIF_EXT_STATUS_CALLBACK ++ LWIP_ASSERT("invalid pointer", old_gw != NULL); ++ nip_addr_copy(*old_gw, *netif_nip_gw(netif)); ++#else ++ LWIP_UNUSED_ARG(old_gw); ++#endif ++ ++ nip_addr_set(ip_2_nip(&netif->nip_gw), gw); ++ IP_SET_TYPE_VAL(netif->nip_gw, IPADDR_TYPE_NIP); ++ ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif: GW address of interface %c%c set to", netif->name[0], netif->name[1])); ++ nip_addr_debug_print(NETIF_DEBUG, gw); ++ LWIP_DEBUGF(NETIF_DEBUG, ("\n")); ++ return 1; /* gateway changed */ ++ } ++ return 0; /* gateway unchanged */ ++} ++ ++ ++static int ++netif_do_set_nipaddr(struct netif *netif, const nip_addr_t *ipaddr, nip_addr_t *old_addr) ++{ ++ LWIP_ASSERT("invalid pointer", ipaddr != NULL); ++ LWIP_ASSERT("invalid pointer", old_addr != NULL); ++ ++ if (nip_addr_cmp(ipaddr, netif_nip_addr(netif)) == 0) { ++ nip_addr_t new_addr; ++ nip_addr_copy(new_addr, *ipaddr); ++ IP_SET_TYPE_VAL(new_addr, IPADDR_TYPE_NIP); ++ ++ nip_addr_copy(*old_addr, *netif_nip_addr(netif)); ++ ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_set_ipaddr: netif address being changed\n")); ++ netif_do_ip_addr_changed(old_addr, &new_addr); ++ ++ nip_addr_set(ip_2_nip(&netif->nip_addr), ipaddr); ++ IP_SET_TYPE_VAL(netif->nip_addr, IPADDR_TYPE_NIP); ++ ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif ip addr : ")); ++ nip_addr_debug_print(NETIF_DEBUG, &(netif->nip_addr)); ++ return 1; /* address changed */ ++ } ++ return 0; /* address unchanged */ ++} ++ ++void ++netif_set_nipaddr(struct netif *netif, const nip_addr_t *ipaddr, const nip_addr_t *gw) ++{ ++ nip_addr_t *old_gw = NULL; ++ nip_addr_t old_addr; ++ ++ LWIP_ERROR("netif_set_nipaddr: invalid netif", netif != NULL, return); ++ ++ LWIP_ASSERT_CORE_LOCKED(); ++ ++ netif_do_set_nipgw(netif, gw, old_gw); ++ netif_do_set_nipaddr(netif, ipaddr, &old_addr); ++} ++#endif /* LWIP_NIP */ ++ + /** + * @ingroup netif + * Remove a network interface from the list of lwIP netifs. +@@ -818,7 +890,7 @@ * * @param netif the default network interface */ @@ -2125,7 +2507,7 @@ diff -Nur a/lwip-2.1.2/src/core/netif.c b/lwip-2.1.2/src/core/netif.c netif_set_default(struct netif *netif) { LWIP_ASSERT_CORE_LOCKED(); -@@ -833,6 +824,7 @@ +@@ -833,6 +905,7 @@ netif_default = netif; LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); @@ -2133,7 +2515,7 @@ diff -Nur a/lwip-2.1.2/src/core/netif.c b/lwip-2.1.2/src/core/netif.c } /** -@@ -1206,6 +1198,11 @@ +@@ -1206,6 +1279,11 @@ struct netif *stats_if = netif; #endif /* LWIP_HAVE_LOOPIF */ #endif /* MIB2_STATS */ @@ -2145,7 +2527,7 @@ diff -Nur a/lwip-2.1.2/src/core/netif.c b/lwip-2.1.2/src/core/netif.c SYS_ARCH_DECL_PROTECT(lev); LWIP_ASSERT("netif_poll: invalid netif", netif != NULL); -@@ -1251,6 +1248,31 @@ +@@ -1251,6 +1329,31 @@ LINK_STATS_INC(link.recv); MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len); MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts); @@ -2177,7 +2559,7 @@ diff -Nur a/lwip-2.1.2/src/core/netif.c b/lwip-2.1.2/src/core/netif.c /* loopback packets are always IP packets! */ if (ip_input(in, netif) != ERR_OK) { pbuf_free(in); -@@ -1700,29 +1722,68 @@ +@@ -1700,29 +1803,68 @@ struct netif * netif_find(const char *name) { @@ -2260,7 +2642,7 @@ diff -Nur a/lwip-2.1.2/src/core/netif.c b/lwip-2.1.2/src/core/netif.c #if LWIP_NETIF_EXT_STATUS_CALLBACK /** * @ingroup netif -@@ -1793,3 +1854,213 @@ +@@ -1793,3 +1935,213 @@ } } #endif /* LWIP_NETIF_EXT_STATUS_CALLBACK */ @@ -2474,68 +2856,2621 @@ diff -Nur a/lwip-2.1.2/src/core/netif.c b/lwip-2.1.2/src/core/netif.c + + return tmp_index; +} -diff -Nur a/lwip-2.1.2/src/core/raw.c b/lwip-2.1.2/src/core/raw.c ---- a/lwip-2.1.2/src/core/raw.c 2021-06-29 15:16:18.804893322 +0800 -+++ b/lwip-2.1.2/src/core/raw.c 2021-06-29 15:16:44.632898725 +0800 -@@ -63,7 +63,24 @@ - #include - - /** The list of RAW PCBs */ --static struct raw_pcb *raw_pcbs; -+struct raw_pcb *raw_pcbs; +diff -Nur a/lwip-2.1.2/src/core/nip/ethnip.c b/lwip-2.1.2/src/core/nip/ethnip.c +--- a/lwip-2.1.2/src/core/nip/ethnip.c 1970-01-01 07:00:00.000000000 +0700 ++++ b/lwip-2.1.2/src/core/nip/ethnip.c 2022-01-20 19:37:12.191437000 +0800 +@@ -0,0 +1,319 @@ ++#include "lwip/opt.h" + -+#if PF_PACKET_SOCKET -+const struct eth_hdr *g_lwip_current_eth_hdr; -+const struct netif *g_lwip_current_netif; -+struct raw_pcb *g_packet_raw_pcbs = NULL; -+struct raw_pcb *g_all_packet_raw_pcbs = NULL; ++#if LWIP_NIP /* don't build if not configured for use in lwipopts.h */ + -+struct raw_pcb* get_packet_raw_pcbs(void) ++#include "lwip/ethnip.h" ++#include "lwip/stats.h" ++#include "lwip/snmp.h" ++#include "lwip/dhcp.h" ++#include "lwip/autoip.h" ++#include "lwip/prot/iana.h" ++#include "netif/ethernet.h" ++#include "lwip/nip_addr.h" ++ ++#include ++ ++#ifdef LWIP_HOOK_FILENAME ++#include LWIP_HOOK_FILENAME ++#endif ++ ++int static_neigh_sum_nip = 0;//number of static neigh ++ ++static s16_t ++ethnip_find_entry(const nip_addr_t *ipaddr, u8_t flags, struct netif *netif); ++err_t ++ethnip_query(struct netif *netif, const nip_addr_t *ipaddr, struct pbuf *q); ++static err_t ++ethnip_output_to_arp_index(struct netif *netif, struct pbuf *q, netif_addr_idx_t arp_idx); ++#if LWIP_ARP ++ ++enum ethnip_state { ++ ETHNIP_STATE_EMPTY = 0, ++ ETHNIP_STATE_PENDING, ++ ETHNIP_STATE_STABLE, ++ ETHNIP_STATE_STABLE_REREQUESTING_1, ++ ETHNIP_STATE_STABLE_REREQUESTING_2, ++ ETHNIP_STATE_STATIC ++}; ++ ++ ++struct ethnip_entry { ++ nip_addr_t ipaddr; ++ struct netif *netif; ++ struct eth_addr ethaddr; ++ u8_t state; ++}; ++ ++static struct ethnip_entry niparp_table[ARP_TABLE_SIZE]; ++ ++#define ETHNIP_FLAG_TRY_HARD 1 ++#define ETHNIP_FLAG_FIND_ONLY 2 ++#if ETHNIP_SUPPORT_STATIC_ENTRIES ++#define ETHNIP_FLAG_STATIC_ENTRY 4 ++#endif /* ETHNIP_SUPPORT_STATIC_ENTRIES */ ++ ++ ++static s16_t ++ethnip_find_entry(const nip_addr_t *ipaddr, u8_t flags, struct netif *netif); ++err_t ++ethnip_query(struct netif *netif, const nip_addr_t *ipaddr, struct pbuf *q); ++static err_t ++ethnip_output_to_arp_index(struct netif *netif, struct pbuf *q, netif_addr_idx_t arp_idx); ++ ++static s16_t ++ethnip_find_entry(const nip_addr_t *ipaddr, u8_t flags, struct netif *netif) +{ -+ return g_packet_raw_pcbs; -+} ++ s16_t table_size = NIPARP_TABLE_SIZE; ++ s16_t i = 0; ++ s16_t num = -1; ++ for (i = 0; i < table_size; i++){ ++ u8_t state = niparp_table[i].state; ++ if (state != ETHNIP_STATE_STATIC){ ++ LWIP_DEBUGF(ETHNIP_DEBUG, ("ethnip_find_entry: not found static entry %d\n", (int)i)); ++ return -1; ++ }else { ++ if (ipaddr && nip_addr_cmp(ipaddr, &niparp_table[i].ipaddr)){ ++ num = i; ++ } ++ } ++ } ++ return num; ++} + -+struct raw_pcb* get_all_packet_raw_pcbs(void) ++/** ++ * Send an ARP request for the given IP address and/or queue a packet. ++ * ++ * If the IP address was not yet in the cache, a pending ARP cache entry ++ * is added and an ARP request is sent for the given address. The packet ++ * is queued on this entry. ++ * ++ * If the IP address was already pending in the cache, a new ARP request ++ * is sent for the given address. The packet is queued on this entry. ++ * ++ * If the IP address was already stable in the cache, and a packet is ++ * given, it is directly sent and no ARP request is sent out. ++ * ++ * If the IP address was already stable in the cache, and no packet is ++ * given, an ARP request is sent out. ++ * ++ * @param netif The lwIP network interface on which ipaddr ++ * must be queried for. ++ * @param nipaddr The IP address to be resolved. ++ * @param q If non-NULL, a pbuf that must be delivered to the IP address. ++ * q is not freed by this function. ++ * ++ * @note q must only be ONE packet, not a packet queue! ++ * ++ * @return ++ * - ERR_BUF Could not make room for Ethernet header. ++ * - ERR_MEM Hardware address unknown, and no more ARP entries available ++ * to query for address or queue the packet. ++ * - ERR_MEM Could not queue packet due to memory shortage. ++ * - ERR_RTE No route to destination (no gateway to external networks). ++ * - ERR_ARG Non-unicast address given, those will not appear in ARP cache. ++ * ++ */ ++err_t ++ethnip_query(struct netif *netif, const nip_addr_t *ipaddr, struct pbuf *q) +{ -+ return g_all_packet_raw_pcbs; -+} -+#endif - - static u8_t - raw_input_local_match(struct raw_pcb *pcb, u8_t broadcast) -@@ -164,7 +181,7 @@ - /* loop through all raw pcbs until the packet is eaten by one */ - /* this allows multiple pcbs to match against the packet by design */ - while (pcb != NULL) { -- if ((pcb->protocol == proto) && raw_input_local_match(pcb, broadcast) && -+ if ((pcb->raw_proto == proto) && raw_input_local_match(pcb, broadcast) && - (((pcb->flags & RAW_FLAGS_CONNECTED) == 0) || - ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()))) { - /* receive callback function available? */ -@@ -277,10 +294,21 @@ - err_t - raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr) - { -+ struct netif *netif = NULL; - LWIP_ASSERT_CORE_LOCKED(); - if ((pcb == NULL) || (ipaddr == NULL)) { - return ERR_VAL; - } ++ struct eth_addr *srcaddr = (struct eth_addr *)netif->hwaddr; ++ err_t result = ERR_MEM; ++ //int is_new_entry = 0; ++ s16_t i_err; ++ netif_addr_idx_t i; ++ ++ /* non-unicast address? */ ++ if (nip_addr_isbroadcast(ipaddr, netif) || ++ nip_addr_ismulticast(ipaddr) || ++ nip_addr_isany(ipaddr)) { ++ LWIP_DEBUGF(ETHNIP_DEBUG | LWIP_DBG_TRACE, ("ethnip_query: will not add non-unicast IP address to ARP cache\n")); ++ return ERR_ARG; ++ } + -+ netif = ip_route_pcb(ipaddr, (struct ip_pcb*)pcb); -+ if (netif == NULL) { -+ return ERR_NETUNREACH; ++ /* find entry in ARP cache, ask to create entry if queueing packet */ ++ i_err = ethnip_find_entry(ipaddr, ETHNIP_FLAG_FIND_ONLY, netif); ++ /* could not find or create entry? */ ++ if (i_err < 0) { ++ LWIP_DEBUGF(ETHNIP_DEBUG | LWIP_DBG_TRACE, ("ethnip_query: there is no cached entry\n")); ++ if (q) { ++ LWIP_DEBUGF(ETHNIP_DEBUG | LWIP_DBG_TRACE, ("ethnip_query: packet dropped\n")); ++ ETHARP_STATS_INC(ethnip.memerr); ++ } ++ return (err_t)i_err; ++ } ++ LWIP_ASSERT("type overflow", (size_t)i_err < NETIF_ADDR_IDX_MAX); ++ i = (netif_addr_idx_t)i_err; ++ ++ /* stable entry? */ ++ if (niparp_table[i].state == ETHNIP_STATE_STATIC) { ++ /* we have a valid IP->Ethernet address mapping */ ++ /* send the packet */ ++ result = ethernet_output(netif, q, srcaddr, &(niparp_table[i].ethaddr), ETHTYPE_NIP); ++ /* pending entry? (either just created or already pending */ + } ++ return result; ++} + -+ if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(ipaddr, netif)) { -+ return ERR_ACCESS; ++/** Just a small helper function that sends a pbuf to an ethernet address ++ * in the niparp_table specified by the index 'arp_idx'. ++ */ ++static err_t ++ethnip_output_to_arp_index(struct netif *netif, struct pbuf *q, netif_addr_idx_t arp_idx) ++{ ++ LWIP_ASSERT("niparp_table[arp_idx].state = ETHNIP_STATE_STATIC", ++ niparp_table[arp_idx].state == ETHNIP_STATE_STATIC); ++ /* if arp table entry is about to expire: re-request it, ++ but only if its state is ETHNIP_STATE_STABLE to prevent flooding the ++ network with ARP requests if this address is used frequently. */ ++ if (niparp_table[arp_idx].state != ETHNIP_STATE_STATIC) { ++ LWIP_DEBUGF(ETHNIP_DEBUG | LWIP_DBG_TRACE, ("this entry is not static!")); + } ++ return ethernet_output(netif, q, (struct eth_addr *)(netif->hwaddr), &niparp_table[arp_idx].ethaddr, ETHTYPE_NIP); ++} + - ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); - #if LWIP_IPV6 && LWIP_IPV6_SCOPES - /* If the given IP address should have a zone but doesn't, assign one now, -@@ -377,7 +405,7 @@ - if (netif == NULL) ++/** ++ * add entry to the ethnip table ++ * ++ * @param ipaddr ip address need to add ++ * @param ethaddr MAC address ++ * @return error code ++ */ ++int add_table_nip(nip_addr_t ipaddr, struct eth_addr ethaddr){ ++ if(static_neigh_sum_nip == 10) return -1; ++ for(int i = 0; i < static_neigh_sum_nip; i++){ ++ if(nip_addr_cmp(&ipaddr, &niparp_table[i].ipaddr)) return -2; ++ } ++ niparp_table[static_neigh_sum_nip].ipaddr = ipaddr; ++ niparp_table[static_neigh_sum_nip].ethaddr = ethaddr; ++ niparp_table[static_neigh_sum_nip].state = ETHNIP_STATE_STATIC; ++ static_neigh_sum_nip++; ++ return 0; ++} ++ ++/** ++ * show all the entrys in the ethnip table ++ * ++ * @param void ++ * @return none ++ */ ++void show_table_nip(void){ ++ for(int i = 0;i < static_neigh_sum_nip; i++){ ++ nip_addr_debug_print_val(0x80U, niparp_table[i].ipaddr); ++ printf(" %02x:%02x:%02x:%02x:%02x:%02x\n", niparp_table[i].ethaddr.addr[0], niparp_table[i].ethaddr.addr[1], ++ niparp_table[i].ethaddr.addr[2], niparp_table[i].ethaddr.addr[3], ++ niparp_table[i].ethaddr.addr[4], niparp_table[i].ethaddr.addr[5]); ++ } ++} ++ ++/** ++ * delete the entry in the ethnip table ++ * ++ * @param ipaddr ++ * @return error code ++ */ ++int del_table_nip(nip_addr_t ipaddr){ ++ for(int i = 0;i < static_neigh_sum_nip; i++){ ++ if(nip_addr_cmp(&ipaddr, &niparp_table[i].ipaddr)){ ++ for(int j = i;j < static_neigh_sum_nip - 1; j++){ ++ niparp_table[j] = niparp_table[j+1]; ++ } ++ static_neigh_sum_nip--; ++ return 0; ++ } ++ } ++ return -1; ++} ++ ++/** ++ * change the entry address or MAC address ++ * ++ * @param ipaddr address need to change ++ * @param ethaddr MAC address need to be changed ++ * @return error code ++ */ ++int set_table_nip(nip_addr_t ipaddr, struct eth_addr ethaddr){ ++ for(int i = 0;i < static_neigh_sum_nip; i++){ ++ if(nip_addr_cmp(&ipaddr, &niparp_table[i].ipaddr)){ ++ niparp_table[i].ethaddr = ethaddr; ++ return 0; ++ } ++ } ++ return -1; ++} ++ ++/** ++ * Resolve and fill-in Ethernet address header for outgoing IP packet. ++ * ++ * For IP multicast and broadcast, corresponding Ethernet addresses ++ * are selected and the packet is transmitted on the link. ++ * ++ * For unicast addresses, the packet is submitted to etharp_query(). In ++ * case the IP address is outside the local network, the IP address of ++ * the gateway is used. ++ * ++ * @param netif The lwIP network interface which the IP packet will be sent on. ++ * @param q The pbuf(s) containing the IP packet to be sent. ++ * @param ipaddr The IP address of the packet destination. ++ * ++ * @return ++ * - ERR_RTE No route to destination (no gateway to external networks), ++ * or the return type of either etharp_query() or ethernet_output(). ++ */ ++err_t ++ethnip_output(struct netif *netif, struct pbuf *q, const nip_addr_t *ipaddr) ++{ ++ const struct eth_addr *dest; ++ struct eth_addr mcastaddr; ++ const nip_addr_t *dst_addr = ipaddr; ++ LWIP_ASSERT_CORE_LOCKED(); ++ LWIP_ASSERT("netif != NULL", netif != NULL); ++ LWIP_ASSERT("q != NULL", q != NULL); ++ LWIP_ASSERT("ipaddr != NULL", ipaddr != NULL); ++ ++ /* Determine on destination hardware address. Broadcasts and multicasts ++ * are special, other IP addresses are looked up in the ARP table. */ ++ ++ /* broadcast destination IP address? */ ++ if (nip_addr_isbroadcast(ipaddr, netif)) { ++ /* broadcast on Ethernet also */ ++ dest = (const struct eth_addr *)ðbroadcast; ++ /* multicast destination IP address? */ ++ } else if (nip_addr_ismulticast(ipaddr)) { ++ /* Hash IP multicast address to MAC address.*/ ++ dest = &mcastaddr; ++ /* unicast destination IP address? */ ++ } else { ++ ++ // if(1){ //dest is not on the subnet as local, 0607 ++ // dst_addr = netif_nip_gw(netif); ++ // } ++ /* find stable entry: do this here since this is a critical path for ++ throughput and ethnip_find_entry() is kind of slow */ ++ for (s16_t i = 0; i < NIPARP_TABLE_SIZE; i++) { ++ if ((niparp_table[i].state >= ETHNIP_STATE_STABLE) && ++ (nip_addr_cmp(dst_addr, &niparp_table[i].ipaddr))) { ++ /* found an existing, stable entry */ ++ return ethnip_output_to_arp_index(netif, q, i); ++ } ++ } ++ //cant find dst_ip in the arp table, so to find fw, 0608 ++ dst_addr = netif_nip_gw(netif); ++ ++ for (s16_t i = 0; i < NIPARP_TABLE_SIZE; i++) { ++ if ((niparp_table[i].state >= ETHNIP_STATE_STABLE) && ++ (nip_addr_cmp(dst_addr, &niparp_table[i].ipaddr))) { ++ /* found an existing, stable entry */ ++ return ethnip_output_to_arp_index(netif, q, i); ++ } ++ } ++ /* no stable entry found, use the (slower) query function: ++ queue on destination Ethernet address belonging to ipaddr */ ++ return ethnip_query(netif, dst_addr, q); ++ } ++ /* continuation for multicast/broadcast destinations */ ++ /* obtain source Ethernet address of the given interface */ ++ /* send packet directly on the link */ ++ return ethernet_output(netif, q, (struct eth_addr *)(netif->hwaddr), dest, ETHTYPE_NIP); ++} ++#endif /* LWIP_ARP */ ++#endif /* LWIP_NIP*/ +diff -Nur a/lwip-2.1.2/src/core/nip/nip_addr.c b/lwip-2.1.2/src/core/nip/nip_addr.c +--- a/lwip-2.1.2/src/core/nip/nip_addr.c 1970-01-01 07:00:00.000000000 +0700 ++++ b/lwip-2.1.2/src/core/nip/nip_addr.c 2022-01-20 19:32:03.909961000 +0800 +@@ -0,0 +1,355 @@ ++#include "lwip/opt.h" ++#if LWIP_NIP ++#include "lwip/nip_addr.h" ++#include "lwip/netif.h" ++ ++nip_addr_t nip_loopback_addr = NIP_LOOPBACK_ADDR_LEVEL4_INIT; ++nip_addr_t nip_any_addr = NIP_ANY_ADDR_LEVEL4_INIT; ++/** ++ * reverse the order of each level nip_addr bytes ++ * ++ * @param addr address to be reversed ++ * @return nip_address after reversed ++ */ ++struct nip_addr *reverse_nip_order(nip_addr_t *addr){ ++ u8_t i, j, k; ++ u8_t level_num = addr->level_num; ++ static nip_addr_t addr_; ++ ++ addr_.level_num = level_num; ++ ++ for (i = 0; i < level_num; i++) ++ { ++ addr_.laddrs[i].type = addr->laddrs[i].type; ++ addr_.laddrs[i].u.top_addr.bitlen = addr->laddrs[i].u.top_addr.bitlen; ++ j = addr->laddrs[i].u.top_addr.bitlen / 8; ++ for (k = 0; k < j; k++){ ++ addr_.laddrs[i].u.top_addr.v.u.u8[k] = addr->laddrs[i].u.top_addr.v.u.u8[j - k - 1]; ++ } ++ } ++ return &addr_; ++} ++ ++/** ++ * turn character to digit ++ * ++ * @param ch character ++ * @return error code ++ */ ++int hex_digit_value (char ch) ++{ ++ if ('0' <= ch && ch <= '9') ++ return ch - '0'; ++ if ('a' <= ch && ch <= 'f') ++ return ch - 'a' + 10; ++ if ('A' <= ch && ch <= 'F') ++ return ch - 'A' + 10; ++ return -1; ++} ++ ++/** ++ * Compare whether the two addresses are the same ++ * ++ * @param a1 address 1 ++ * @param a2 address 2 ++ * @return result that compare ++ */ ++int nipaddr_cmp(const nip_addr_t *a1,const nip_addr_t *a2) ++{ ++ if(a1->level_num != a2->level_num) ++ return 0; ++ for(int i = 0;i < a1->level_num;i++){ ++ if(a1->laddrs[i].nip_addr_bitlen != a2->laddrs[i].nip_addr_bitlen) ++ return 0; ++ if(memcmp(a1->laddrs[i].nip_addr_field8, a2->laddrs[i].nip_addr_field8, ((a1->laddrs[i].nip_addr_bitlen) >> 3)) != 0) ++ return 0; ++ } ++ return 1; ++} ++ ++/** ++ * Convert numeric IP address into decimal dotted ASCII representation. ++ * returns ptr to static buffer; not reentrant! ++ * ++ * @param addr ip address in network order to convert ++ * @return pointer to a global static (!) buffer that holds the ASCII ++ * representation of addr ++ */ ++char *nipaddr_ntoa(const nip_addr_t *addr) ++{ ++ static char str[NIPADDR_STRLEN_MAX]; ++ return nipaddr_ntoa_r(addr, str, NIPADDR_STRLEN_MAX); ++} ++ ++/** ++ * Same as nipaddr_ntoa, but reentrant since a user-supplied buffer is used. ++ * ++ * @param addr ip address in network order to convert ++ * @param buf target buffer where the string is stored ++ * @param buflen length of buf ++ * @return either pointer to buf which now holds the ASCII ++ * representation of addr or NULL if buf was too small ++ */ ++char *nipaddr_ntoa_r(const nip_addr_t *addr, char *buf, int buflen) ++{ ++ char *tmp = buf; ++ const nip_addr_t *addr_1 = addr; ++ int level_num = addr->level_num; ++ int bytelen; ++ int i, j; ++ for(i = 0; i < level_num; i++){ ++ bytelen = addr_1->laddrs[i].u.top_addr.bitlen / 8; ++ for(j = 0; j < bytelen; j++){ ++ if(addr_1->laddrs[i].u.top_addr.v.u.u8[j] >> 4) ++ sprintf(tmp, "%x", addr_1->laddrs[i].u.top_addr.v.u.u8[j]); ++ else ++ sprintf(tmp, "0%x", addr_1->laddrs[i].u.top_addr.v.u.u8[j]); ++ tmp++; ++ tmp++; ++ if ((j % 2) && (j!= bytelen-1)) ++ { ++ *tmp = '.'; ++ tmp++; ++ } ++ } ++ if (i < level_num-1){ ++ *tmp = '-'; ++ tmp++; ++ } ++ } ++ return buf; ++} ++ ++/** ++ * Print NewIP address ++ * returns error code if address can't be printed. ++ * ++ * @param addr ip address needed to be printed ++ * @return error code if address can't be printed. ++ */ ++char *nipaddr_print(const nip_addr_t *addr){ ++ static char t[100]; ++ char *tmp = t; ++ const nip_addr_t *addr_1 = addr; ++ int level_num = addr->level_num; ++ int bytelen; ++ int i, j; ++ for(i = 0; i < level_num; i++){ ++ bytelen = addr_1->laddrs[i].u.top_addr.bitlen / 8; ++ for(j = 0; j < bytelen; j++){ ++ if(addr_1->laddrs[i].u.top_addr.v.u.u8[j] >> 4) ++ sprintf(tmp, "%x", addr_1->laddrs[i].u.top_addr.v.u.u8[j]); ++ else ++ sprintf(tmp, "0%x", addr_1->laddrs[i].u.top_addr.v.u.u8[j]); ++ tmp++; ++ tmp++; ++ if ((j % 2) && (j!= bytelen-1)) ++ { ++ *tmp = '.'; ++ tmp++; ++ } ++ } ++ if (i < level_num-1){ ++ *tmp = '-'; ++ tmp++; ++ } ++ } ++ *tmp = '\0'; ++ return t; ++} ++ ++/** ++ * set number of every Newip address level ++ * returns error code to figure out which error ++ * ++ * @param cp number of every level address to be set ++ * @param addr ip address needed to be set ++ * @return error code ++ */ ++int set_newip_level(char *cp, struct nip_addr *addr) ++{ ++ char *token, *tmp = NULL; ++ int i = 0, ch; ++ token = strtok_r(cp, "-", &tmp); ++ ++ while (token != NULL) ++ { ++ if (i > NEWIP_LEVEL_MAX-1) ++ return -1; ++ if (strlen(token) == 1){ ++ ch = hex_digit_value(token[0]); ++ if (ch > 0) ++ { ++ addr->laddrs[i].type = 1; ++ addr->laddrs[i].u.top_addr.bitlen = ch*8; ++ }else ++ return -1; ++ }else if (strlen(token) == 2 && (strcmp(token, "10") == 0)) ++ { ++ addr->laddrs[i].type = 1; ++ addr->laddrs[i].u.top_addr.bitlen = 16*8; ++ }else ++ return -1; ++ token = strtok_r(NULL, "-", &tmp); ++ i++; ++ } ++ addr->level_num = i; ++ return 0; ++} ++ ++/** ++ * Convert decimal dotted ASCII representation into numeric IP address. ++ * return error code ++ * ++ * @param src the header pointer of ip address ++ * @param src_endp the end pointer of ip address ++ * @param dst pointer to which to save the ip address in network order ++ * @param len length of src ++ * @return 0 if cp could be converted to addr, 1 on failure ++ */ ++int nipaddr_aton_r(const char *src, const char *src_endp, int len, struct nip_addr_field *dst) ++{ ++ unsigned char tmp[len], *tp, *endp, *colonp; ++ int ch, first_address, hexnum; ++ size_t xdigits_seen; /* Number of hex digits since colon. */ ++ unsigned int val; ++ ++ memset(dst, 0, 16); ++ tp = memset(tmp, '\0', len); ++ endp = tp + len; ++ colonp = NULL; ++ first_address = 1; ++ hexnum = 0; ++ /* Leading :: requires some special handling. */ ++ if (src == src_endp) ++ return -1; ++ if (*src == ':') ++ { ++ ++src; ++ if (src == src_endp || *src != ':') ++ return -1; ++ } ++ xdigits_seen = 0;/*record hex number */ ++ val = 0; ++ while (src < src_endp) ++ { ++ ch = *src++; ++ int digit = hex_digit_value (ch);/*hex*/ ++ if (digit >= 0) ++ { ++ hexnum++;/*count hexnum*/ ++ if (xdigits_seen == 4)/*0 1 2 3 legal*/ ++ return 0; ++ val <<= 4; ++ val |= digit; ++ if (val > 0xffff) ++ return -1; ++ ++xdigits_seen; ++ continue; ++ } ++ if (ch == ':') ++ { ++ if (xdigits_seen == 0) ++ { ++ if (colonp)/*if num of ':'>3*/ ++ return -1; ++ colonp = tp; ++ continue; ++ } ++ else if (src == src_endp) ++ return -1; ++ if (xdigits_seen == 2 && first_address) { ++ *tp++ = (unsigned char) val & 0xff; ++ first_address = 0; ++ } else if (xdigits_seen == 4 && first_address) ++ { ++ if (tp + NS_INT16SZ > endp) ++ return -1; ++ *tp++ = (unsigned char) (val >> 8) & 0xff; ++ *tp++ = (unsigned char) val & 0xff; ++ first_address = 0; ++ } ++ else if (xdigits_seen > 0 && !first_address) ++ { ++ if (tp + NS_INT16SZ > endp) ++ return -1; ++ *tp++ = (unsigned char) (val >> 8) & 0xff; ++ *tp++ = (unsigned char) val & 0xff; ++ } else ++ return -1; ++ xdigits_seen = 0; ++ val = 0; ++ continue; ++ } ++ return 0; ++ } ++ if (xdigits_seen > 0 && !first_address) ++ { ++ if (tp + NS_INT16SZ > endp) ++ return -1; ++ *tp++ = (unsigned char) (val >> 8) & 0xff;/* */ ++ *tp++ = (unsigned char) val & 0xff; ++ }else if (xdigits_seen == 2 && first_address) ++ *tp++ = (unsigned char) val & 0xff; ++ else if (xdigits_seen == 4 && first_address) ++ { ++ if (tp + NS_INT16SZ > endp) ++ return -1; ++ *tp++ = (unsigned char) (val >> 8) & 0xff;/* */ ++ *tp++ = (unsigned char) val & 0xff; ++ } ++ else ++ return -1; ++ if (colonp != NULL){ ++ /* Replace :: with zeros. */ ++ if (tp == endp)/* :: would expand to a zero-width field. */ ++ return -1; ++ size_t n = tp - colonp; ++ memmove (endp - n, colonp, n); ++ memset (colonp, 0, endp - n - colonp); ++ tp = endp; ++ } ++ if (tp != endp) ++ return -1; ++ memcpy(dst, tmp, len); ++ return 0; ++} ++int usecp1(char *cp){ ++ return 1; ++} ++ ++/** ++ * Convert decimal dotted ASCII representation into numeric IP address. ++ * return error code ++ * ++ * @param cp1 ip address ++ * @param cp2 ip address ++ * @param addr pointer to which to save the ip address in network order ++ * @return error code ++ */ ++int nipaddr_aton2(const char *cp,const char *cp2, struct nip_addr *addr) ++{ ++ char *token, *cp_1,*cp_2, *tmp = NULL; ++ int i = 0, level_num; ++ cp_1 = (char *)cp; ++ cp_2 = (char *)cp2; ++ usecp1(cp_1); ++ set_newip_level(cp_1, addr); ++ level_num = addr->level_num; ++ token = strtok_r(cp_2, "-", &tmp); ++ ++ while (token != NULL) { ++ if(i > level_num-1) ++ return -2; ++ if (nipaddr_aton_r(token, token + strlen(token), addr->laddrs[i].u.top_addr.bitlen/8, ++ &(addr->laddrs[i].u.top_addr.v)) < 0) ++ return -3; ++ token = strtok_r(NULL, "-", &tmp); ++ ++i; ++ } ++ if(i != level_num) ++ return -4; ++ else ++ return 0; ++} ++#endif /* LWIP_NIP */ +diff -Nur a/lwip-2.1.2/src/core/nip/nip.c b/lwip-2.1.2/src/core/nip/nip.c +--- a/lwip-2.1.2/src/core/nip/nip.c 1970-01-01 07:00:00.000000000 +0700 ++++ b/lwip-2.1.2/src/core/nip/nip.c 2022-01-25 14:17:03.303125000 +0800 +@@ -0,0 +1,785 @@ ++#include "lwip/opt.h" ++ ++#if LWIP_NIP ++ ++#include "lwip/nip.h" ++#include "lwip/def.h" ++#include "lwip/mem.h" ++#include "lwip/nip_frag.h" ++#include "lwip/nip_addr.h" ++#include "lwip/netif.h" ++#include "lwip/icmp.h" ++#include "lwip/igmp.h" ++#include "lwip/priv/raw_priv.h" ++#include "lwip/udp.h" ++#include "lwip/priv/tcp_priv.h" ++#include "lwip/autoip.h" ++#include "lwip/stats.h" ++#include "lwip/prot/iana.h" ++ ++#include ++ ++#ifdef LWIP_HOOK_FILENAME ++#include LWIP_HOOK_FILENAME ++#endif ++ ++ ++#if LWIP_DHCP || defined(LWIP_IP_ACCEPT_UDP_PORT) ++#define IP_ACCEPT_LINK_LAYER_ADDRESSING 1 ++ ++/** Some defines for DHCP to let link-layer-addressed packets through while the ++ * netif is down. ++ * To use this in your own application/protocol, define LWIP_IP_ACCEPT_UDP_PORT(port) ++ * to return 1 if the port is accepted and 0 if the port is not accepted. ++ */ ++#if LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) ++/* accept DHCP client port and custom port */ ++#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (((port) == PP_NTOHS(LWIP_IANA_PORT_DHCP_CLIENT)) \ ++ || (LWIP_IP_ACCEPT_UDP_PORT(port))) ++#elif defined(LWIP_IP_ACCEPT_UDP_PORT) /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ ++/* accept custom port only */ ++#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) (LWIP_IP_ACCEPT_UDP_PORT(port)) ++#else /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ ++/* accept DHCP client port only */ ++#define IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(port) ((port) == PP_NTOHS(LWIP_IANA_PORT_DHCP_CLIENT)) ++#endif /* LWIP_DHCP && defined(LWIP_IP_ACCEPT_UDP_PORT) */ ++ ++#else /* LWIP_DHCP */ ++#define IP_ACCEPT_LINK_LAYER_ADDRESSING 0 ++#endif /* LWIP_DHCP */ ++ ++#if NIP_FRAG ++/** The IP header ID of the next outgoing IP packet */ ++static u16_t nip_id; ++#endif /* NIP_FRAG */ ++ ++#if LWIP_MULTICAST_TX_OPTIONS ++/** The default netif used for multicast */ ++static struct netif *ip4_default_multicast_netif; ++ ++/** ++ * @ingroup ip4 ++ * Set a default netif for IPv4 multicast. */ ++void ++ip4_set_default_multicast_netif(struct netif *default_multicast_netif) ++{ ++ ip4_default_multicast_netif = default_multicast_netif; ++} ++#endif /* LWIP_MULTICAST_TX_OPTIONS */ ++ ++#ifdef LWIP_HOOK_IP4_ROUTE_SRC ++/** ++ * Source based IPv4 routing must be fully implemented in ++ * LWIP_HOOK_IP4_ROUTE_SRC(). This function only provides the parameters. ++ */ ++struct netif * ++ip4_route_src(const ip4_addr_t *src, const ip4_addr_t *dest) ++{ ++ if (src != NULL) { ++ /* when src==NULL, the hook is called from ip4_route(dest) */ ++ struct netif *netif = LWIP_HOOK_IP4_ROUTE_SRC(src, dest); ++ if (netif != NULL) { ++ return netif; ++ } ++ } ++ return ip4_route(dest); ++} ++#endif /* LWIP_HOOK_IP4_ROUTE_SRC */ ++ ++/** ++ * Finds the appropriate network interface for a given IP address. It ++ * searches the list of network interfaces linearly. A match is found ++ * if the masked IP address of the network interface equals the masked ++ * IP address given to the function. ++ * ++ * @param dest the destination IP address for which to find the route ++ * @return the netif on which to send to reach dest ++ */ ++struct netif * ++nip_route(const nip_addr_t *dest) ++{ ++#if !LWIP_SINGLE_NETIF//LWIP_SINGLE_NETIF==1: use a single netif only. ++ struct netif *netif; ++ ++ LWIP_ASSERT_CORE_LOCKED(); ++ ++#if LWIP_MULTICAST_TX_OPTIONS ++ /* Use administratively selected interface for multicast by default */ ++ if (ip4_addr_ismulticast(dest) && ip4_default_multicast_netif) { ++ return ip4_default_multicast_netif; ++ } ++#endif /* LWIP_MULTICAST_TX_OPTIONS */ ++ ++ /* bug #54569: in case LWIP_SINGLE_NETIF=1 and LWIP_DEBUGF() disabled, the following loop is optimized away */ ++ LWIP_UNUSED_ARG(dest); ++ ++ /* iterate through netifs */ ++ NETIF_FOREACH(netif) { ++ /* is the netif up, does it have a link and a valid address? */ ++ if (netif_is_up(netif) && netif_is_link_up(netif) && !nip_addr_isany_val(*netif_nip_addr(netif))) { ++ //whether this network interface is enabled and processes traffic ++ //If set, the interface has an active link ++ ++ /* network mask matches? */ ++ if (nip_addr_cmp(dest, netif_nip_addr(netif))) { ++ /* return netif on which to forward IP packet */ ++ return netif; ++ } ++ /* gateway matches on a non broadcast interface? (i.e. peer in a point to point interface) */ ++ if (((netif->flags & NETIF_FLAG_BROADCAST) == 0) && nip_addr_cmp(dest, netif_nip_gw(netif))) { ++ /* return netif on which to forward IP packet */ ++ return netif; ++ } ++ } ++ } ++ ++#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF ++ /* loopif is disabled, looopback traffic is passed through any netif */ ++ if (nip_addr_isloopback(dest)) { ++ /* don't check for link on loopback traffic */ ++ if (netif_default != NULL && netif_is_up(netif_default)) { ++ return netif_default; ++ } ++ /* default netif is not up, just use any netif for loopback traffic */ ++ NETIF_FOREACH(netif) { ++ if (netif_is_up(netif)) { ++ return netif; ++ } ++ } ++ return NULL; ++ } ++#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ ++ ++#ifdef LWIP_HOOK_IP4_ROUTE_SRC ++ netif = LWIP_HOOK_IP4_ROUTE_SRC(NULL, dest); ++ if (netif != NULL) { ++ return netif; ++ } ++#elif defined(LWIP_HOOK_IP4_ROUTE) ++ netif = LWIP_HOOK_IP4_ROUTE(dest); ++ if (netif != NULL) { ++ return netif; ++ } ++#endif ++#endif /* !LWIP_SINGLE_NETIF */ ++ ++ return netif_default; ++} ++ ++/** ++ * Sends an IP packet on a network interface. This function constructs ++ * the IP header and calculates the IP header checksum. If the source ++ * IP address is NULL, the IP address of the outgoing network ++ * interface is filled in as source address. ++ * If the destination IP address is LWIP_IP_HDRINCL, p is assumed to already ++ * include an IP header and p->payload points to it instead of the data. ++ * ++ * @param p the packet to send (p->payload points to the data, e.g. next ++ protocol header; if dest == LWIP_IP_HDRINCL, p already includes an ++ IP header and p->payload points to that IP header) ++ * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the ++ * IP address of the netif used to send is used as source address) ++ * @param dest the destination IP address to send the packet to ++ * @param ttl the TTL value to be set in the IP header ++ * @param tos the TOS value to be set in the IP header ++ * @param proto the PROTOCOL to be set in the IP header ++ * @param netif the netif on which to send this packet ++ * @return ERR_OK if the packet was sent OK ++ * ERR_BUF if p doesn't have enough space for IP/LINK headers ++ * returns errors returned by netif->output ++ * ++ * @note ip_id: RFC791 "some host may be able to simply use ++ * unique identifiers independent of destination" ++ */ ++err_t ++nip_output_if(struct pbuf *p, const nip_addr_t *src, const nip_addr_t *dest, ++ u8_t ttl, u8_t tos, u8_t proto, struct netif *netif) ++{ ++ const nip_addr_t *src_used = src; ++ if (dest != LWIP_IP_HDRINCL) { ++ if (nip_addr_isany(src)) { ++ LWIP_DEBUGF(IP_DEBUG, (" src \n")); ++ src_used = netif_nip_addr(netif); ++ } ++ } ++ ++ LWIP_DEBUGF(IP_DEBUG, (" nip_output_if_src\n")); ++ return nip_output_if_src(p, src_used, dest, ttl, tos, proto, netif); ++ ++} ++ ++u8_t* build_nip_addr(u8_t type, const nip_addr_t *addr, u8_t *buf){ ++ u8_t *p = buf; ++ u8_t *plen; ++ int i; ++ *p = type; ++ p++; ++ plen = p; ++ p++; ++ for(i = 0; i < addr->level_num; i++){ ++ int len = addr->laddrs[i].u.top_addr.bitlen >> 3; ++ *p = len; ++ p++; ++ memcpy(p, &addr->laddrs[i].u.top_addr.v.u, len); ++ p+= len; ++ } ++ ++ *plen = p - plen - 1; ++ return p; ++} ++ ++u8_t* build_tlv(u8_t type, u8_t len, u8_t *value, u8_t *buf){ ++ u8_t *p = buf; ++ *p = type; ++ p++; ++ *p = len; ++ p++; ++ memcpy(p, value, len); ++ p = p + len; ++ return p; ++} ++ ++int ++niphlen_cal(const nip_addr_t *src, const nip_addr_t *dst, u16_t payloadlen) ++{ ++ int nip_hlen = 0; ++ int srcaddr_len = 0, dstaddr_len = 0; ++ for(int i = 0; i < src->level_num; ++i){ ++ ++srcaddr_len; ++ srcaddr_len += src->laddrs[i].u.top_addr.bitlen >> 3; ++ } ++ for(int i = 0; i < dst->level_num; ++i){ ++ ++dstaddr_len; ++ dstaddr_len += dst->laddrs[i].u.top_addr.bitlen >> 3; ++ } ++ ++ nip_hlen += 2; ++ nip_hlen += srcaddr_len; ++ nip_hlen += 2; ++ nip_hlen += dstaddr_len; ++#if NIP_FRAG ++ nip_hlen += 6; ++#endif ++ nip_hlen += 3; ++ nip_hlen += 3; ++ nip_hlen += 3; ++ ++ nip_hlen += 3;//totallen ++ ++ u8_t nip_hlen_up = 4 * (u8_t)((nip_hlen + 3)/4); ++ if(nip_hlen_up + payloadlen > 255){ ++ nip_hlen++; ++ } ++ ++ return nip_hlen; ++} ++ ++/** ++ * Same as ip_output_if() but 'src' address is not replaced by netif address ++ * when it is 'any'. ++ */ ++err_t ++nip_output_if_src(struct pbuf *p, const nip_addr_t *src, const nip_addr_t *dest, ++ u8_t ttl, u8_t tos, u8_t proto, struct netif *netif) ++{ ++ ++ LWIP_ASSERT_CORE_LOCKED(); ++ LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); ++ ++ MIB2_STATS_INC(mib2.ipoutrequests); ++ ++ /* Should the IP header be generated or is it already included in p? */ ++ u16_t payloadlen = p->tot_len; ++ LWIP_DEBUGF(IP_DEBUG, ("nip_send: payloadlen: %"U16_F"\n", payloadlen)); ++ u8_t nip_hlen = niphlen_cal(src, dest, payloadlen); ++ u8_t nip_hlen_up = 4 * (u8_t)((nip_hlen + 3)/4); ++ LWIP_DEBUGF(IP_DEBUG, ("nip_send: nip_hlen: %"U16_F", nip_hlen_up: %"U16_F"\n", nip_hlen, nip_hlen_up)); ++ ++ /* generate IP header */ ++ if (pbuf_add_header(p, nip_hlen_up)) { ++ LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("nip_output: not enough room for IP header in pbuf\n")); ++ ++ IP_STATS_INC(ip.err); ++ MIB2_STATS_INC(mib2.ipoutdiscards); ++ return ERR_BUF; ++ } ++ ++ u8_t *ptr = p->payload; ++ ++ int i; ++ ++ ++ ptr = build_nip_addr(NIP_FIELDTYPE_DADDR, dest, ptr); ++ ptr = build_nip_addr(NIP_FIELDTYPE_SADDR, src, ptr); ++ ptr = build_tlv(NIP_FIELDTYPE_TTL, 1, &ttl, ptr); ++ ptr = build_tlv(NIP_FIELDTYPE_NEXTHEADER, 1, &proto, ptr); ++#if NIP_FRAG ++ *ptr = NIP_FIELDTYPE_FRAG; ++ ptr++; ++ *ptr = 4; ++ ptr++; ++ memset(ptr, 0, 2); ++ ptr += 2; ++ *ptr = (nip_id >> 8) & 0xff; ++ ptr++; ++ *ptr = (u8_t)nip_id & 0xff; ++ ptr++; ++ ++nip_id; ++#endif /* NIP_FRAG */ ++ *ptr = NIP_FIELDTYPE_HEADERLEN; ++ ptr++; ++ *ptr = 1; ++ ptr++; ++ *ptr = nip_hlen_up; ++ ptr++; ++ ++ *ptr = NIP_FIELDTYPE_TOTALLEN; ++ ptr++; ++ if(nip_hlen_up + payloadlen > 255){ ++ *ptr = 2; ++ } ++ else { ++ *ptr = 1; ++ } ++ ptr++; ++ if(nip_hlen_up + payloadlen > 255){ ++ *ptr = htons(nip_hlen_up + payloadlen); ++ ptr++; ++ *ptr = nip_hlen_up + payloadlen; ++ ptr++; ++ } ++ else { ++ *ptr = nip_hlen_up + payloadlen; ++ ptr += 1; ++ } ++ ++ LWIP_DEBUGF(IP_DEBUG, ("nip_send: ptr 1 %p\n", (void *)ptr)); ++ for(i = 0; i < nip_hlen_up - nip_hlen; i++){ ++ *ptr = 0; ++ ptr++; ++ } ++ LWIP_DEBUGF(IP_DEBUG, ("nip_send: ptr 2(nipheader end) %p\n", (void *)ptr)); ++ ++ IP_STATS_INC(ip.xmit); ++ ++ LWIP_DEBUGF(IP_DEBUG, ("nip_output_if: %c%c%"U16_F"\n", netif->name[0], netif->name[1], (u16_t)netif->num)); ++ ++#if ENABLE_LOOPBACK ++ if (nip_addr_cmp(dest, netif_nip_addr(netif)) ++#if !LWIP_HAVE_LOOPIF ++ || nip_addr_isloopback(dest) ++#endif /* !LWIP_HAVE_LOOPIF */ ++ ) { ++ /* Packet to self, enqueue it for loopback */ ++ LWIP_DEBUGF(IP_DEBUG, ("netif_loop_output()")); ++ return netif_loop_output(netif, p); ++ } ++#if LWIP_MULTICAST_TX_OPTIONS ++ if ((p->flags & PBUF_FLAG_MCASTLOOP) != 0) { ++ netif_loop_output(netif, p); ++ } ++#endif /* LWIP_MULTICAST_TX_OPTIONS */ ++#endif /* ENABLE_LOOPBACK */ ++#if NIP_FRAG ++ /* don't fragment if interface has mtu set to 0 [loopif] */ ++ if (netif->mtu && (p->tot_len > netif->mtu)) { ++ u8_t zeros = nip_hlen_up - nip_hlen; ++ return nip_frag(p, netif, dest, zeros); ++ } ++#endif /* NIP_FRAG */ ++ LWIP_DEBUGF(IP_DEBUG, ("nip_output_if: call netif->output()\n")); ++ return netif->output_nip(netif, p, dest); ++} ++ ++/** ++ * Simple interface to ip_output_if. It finds the outgoing network ++ * interface and calls upon ip_output_if to do the actual work. ++ * ++ * @param p the packet to send (p->payload points to the data, e.g. next ++ protocol header; if dest == LWIP_IP_HDRINCL, p already includes an ++ IP header and p->payload points to that IP header) ++ * @param src the source IP address to send from (if src == IP4_ADDR_ANY, the ++ * IP address of the netif used to send is used as source address) ++ * @param dest the destination IP address to send the packet to ++ * @param ttl the TTL value to be set in the IP header ++ * @param tos the TOS value to be set in the IP header ++ * @param proto the PROTOCOL to be set in the IP header ++ * ++ * @return ERR_RTE if no route is found ++ * see ip_output_if() for more return values ++ */ ++err_t ++nip_output(struct pbuf *p, const nip_addr_t *src, const nip_addr_t *dest, ++ u8_t ttl, u8_t tos, u8_t proto) ++{ ++ struct netif *netif; ++ ++ LWIP_IP_CHECK_PBUF_REF_COUNT_FOR_TX(p); ++ ++ if ((netif = nip_route(dest)) == NULL) { ++ LWIP_DEBUGF(IP_DEBUG, ("nip_output: No route to")); ++ nip_addr_debug_print(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, dest); ++ LWIP_DEBUGF(IP_DEBUG, ("\n")); ++ IP_STATS_INC(ip.rterr); ++ return ERR_RTE; ++ } ++ LWIP_DEBUGF(IP_DEBUG, ("nip_output\n")); ++ ++ return nip_output_if(p, src, dest, ttl, tos, proto, netif); ++} ++/*----------------------INPUT--------------------------*/ ++#if IP_FORWARD ++/** ++ * Determine whether an IP address is in a reserved set of addresses ++ * that may not be forwarded, or whether datagrams to that destination ++ * may be forwarded. ++ * @param p the packet to forward ++ * @return 1: can forward 0: discard ++ */ ++static int ++nip_canforward(struct pbuf *p) ++{ ++ u32_t addr = lwip_htonl(nip_addr_get_u32(nip_current_dest_addr())); ++ ++#ifdef LWIP_HOOK_NIP_CANFORWARD ++ int ret = LWIP_HOOK_NIP_CANFORWARD(p, addr); ++ if (ret >= 0) { ++ return ret; ++ } ++#endif /* LWIP_HOOK_IP4_CANFORWARD */ ++ ++ if (p->flags & PBUF_FLAG_LLBCAST) { ++ /* don't route link-layer broadcasts */ ++ return 0; ++ } ++ if (IP_EXPERIMENTAL(addr)) { ++ return 0; ++ } ++ if (IP_CLASSA(addr)) { ++ u32_t net = addr & IP_CLASSA_NET; ++ if ((net == 0) || (net == ((u32_t)IP_LOOPBACKNET << IP_CLASSA_NSHIFT))) { ++ /* don't route loopback packets */ ++ return 0; ++ } ++ } ++ return 1; ++} ++ ++/** ++ * Forwards an IP packet. It finds an appropriate route for the ++ * packet, decrements the TTL value of the packet, adjusts the ++ * checksum and outputs the packet on the appropriate interface. ++ * ++ * @param p the packet to forward (p->payload points to IP header) ++ * @param iphdr the IP header of the input packet ++ * @param inp the netif on which this packet was received ++ */ ++ ++static void ++nip_forward(struct pbuf *p, struct ip_hdr *iphdr, struct netif *inp) ++{ ++ struct netif *netif; ++ ++ PERF_START; ++ LWIP_UNUSED_ARG(inp); ++ ++ if (!nip_canforward(p)) { ++ goto return_noroute; ++ } ++ ++ /* RFC3927 2.7: do not forward link-local addresses */ ++ if (nip_addr_islinklocal(nip_current_dest_addr())) { ++ LWIP_DEBUGF(IP_DEBUG, ("nip_forward: not forwarding LLA %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", ++ nip_addr1_16(nip_current_dest_addr()), nip_addr2_16(nip_current_dest_addr()), ++ nip_addr3_16(nip_current_dest_addr()), nip_addr4_16(nip_current_dest_addr()))); ++ goto return_noroute; ++ } ++ ++ /* Find network interface where to forward this IP packet to. */ ++ netif = nip_route_src(nip_current_src_addr(), nip_current_dest_addr()); ++ if (netif == NULL) { ++ LWIP_DEBUGF(IP_DEBUG, ("nip_forward: no forwarding route for %"U16_F".%"U16_F".%"U16_F".%"U16_F" found\n", ++ nip_addr1_16(nip_current_dest_addr()), nip_addr2_16(nip_current_dest_addr()), ++ nip_addr3_16(nip_current_dest_addr()), nip_addr4_16(nip_current_dest_addr()))); ++ /* @todo: send ICMP_DUR_NET? */ ++ goto return_noroute; ++ } ++#if !IP_FORWARD_ALLOW_TX_ON_RX_NETIF ++ /* Do not forward packets onto the same network interface on which ++ * they arrived. */ ++ if (netif == inp) { ++ LWIP_DEBUGF(IP_DEBUG, ("nip_forward: not bouncing packets back on incoming interface.\n")); ++ goto return_noroute; ++ } ++#endif /* IP_FORWARD_ALLOW_TX_ON_RX_NETIF */ ++ ++ return; ++ } ++ ++ LWIP_DEBUGF(IP_DEBUG, ("nip_forward: forwarding packet to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n", ++ nip_addr1_16(nip_current_dest_addr()), nip_addr2_16(nip_current_dest_addr()), ++ nip_addr3_16(nip_current_dest_addr()), nip_addr4_16(nip_current_dest_addr()))); ++ ++ IP_STATS_INC(ip.fw); ++ MIB2_STATS_INC(mib2.ipforwdatagrams); ++ IP_STATS_INC(ip.xmit); ++ ++ PERF_STOP("nip_forward"); ++ ++ netif->output(netif, p, nip_current_dest_addr()); ++ return; ++return_noroute: ++ MIB2_STATS_INC(mib2.ipoutnoroutes); ++} ++#endif /* IP_FORWARD */ ++/** Return true if the current input packet should be accepted on this netif */ ++static int ++nip_input_accept(struct netif *netif) ++{ ++ /* interface is up and configured? */ ++ if ((netif_is_up(netif)) && (!nip_addr_isany_val(*netif_nip_addr(netif)))) { ++ /* unicast to this interface address? */ ++ if (nip_addr_cmp(nip_current_dest_addr(), netif_nip_addr(netif)) || ++ /* or broadcast on this interface network address? */ ++ nip_addr_isbroadcast(nip_current_dest_addr(), netif) ++#if LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF ++ || (nip_addr_get_u32(nip_current_dest_addr()) == PP_HTONL(IPADDR_LOOPBACK)) ++#endif /* LWIP_NETIF_LOOPBACK && !LWIP_HAVE_LOOPIF */ ++ ) { ++ LWIP_DEBUGF(IP_DEBUG, ("nip_input: packet accepted on interface %c%c\n", ++ netif->name[0], netif->name[1])); ++ /* accept on this netif */ ++ return 1; ++ } ++#if LWIP_AUTOIP ++ /* connections to link-local addresses must persist after changing ++ the netif's address (RFC3927 ch. 1.9) */ ++ if (autoip_accept_packet(netif, nip_current_dest_addr())) { ++ LWIP_DEBUGF(IP_DEBUG, ("nip_input: LLA packet accepted on interface %c%c\n", ++ netif->name[0], netif->name[1])); ++ /* accept on this netif */ ++ return 1; ++ } ++#endif /* LWIP_AUTOIP */ ++ } ++ return 0; ++} ++ ++/** ++ * This function is called by the network interface device driver when ++ * an IP packet is received. The function does the basic checks of the ++ * IP header such as packet size being at least larger than the header ++ * size etc. If the packet was not destined for us, the packet is ++ * forwarded (using ip_forward). The IP checksum is always checked. ++ * ++ * Finally, the packet is sent to the upper layer protocol input function. ++ * ++ * @param p the received IP packet (p->payload points to IP header) ++ * @param inp the netif on which this packet was received ++ * @return ERR_OK if the packet was processed (could return ERR_* if it wasn't ++ * processed, but currently always returns ERR_OK) ++ */ ++err_t ++nip_input(struct pbuf *p, struct netif *inp) ++{ ++ ++ struct netif *netif; ++ u8_t iphdr_hlen; ++ ++ LWIP_ASSERT_CORE_LOCKED(); ++#ifdef LWIP_HOOK_NIP_INPUT ++ if (LWIP_HOOK_NIP_INPUT(p, inp)) { ++ /* the packet has been eaten */ ++ return ERR_OK; ++ } ++#endif ++ ++ ++ if (nip_input_accept(inp)) { ++ netif = inp; ++ } else { ++ netif = NULL; ++ } ++ u16_t offset_frag = *(u16_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_FRAG, p->payload); ++ if ((offset_frag & PP_HTONS(0x1fffU | 0x2000U)) != 0) { ++#if NIP_REASSEMBLY /* packet fragment reassembly code present? */ ++ /* reassemble the packet*/ ++ ++ p = nip_reass(p); ++ if (p == NULL) { ++ return ERR_OK; ++ } ++ /* packet not fully reassembled yet? */ ++#else /* NIP_REASSEMBLY == 0, no packet fragment reassembly code present */ ++ ++ pbuf_free(p); ++ return ERR_OK; ++#endif /* NIP_REASSEMBLY */ ++ } ++ iphdr_hlen = get_nip_hdrlen(p); ++ /* send to upper layers */ ++ LWIP_DEBUGF(IP_DEBUG, ("nip_input: \n")); ++ LWIP_DEBUGF(IP_DEBUG, ("nip_input: p->len %"U16_F" p->tot_len %"U16_F"\n", p->len, p->tot_len)); ++ ++ ip_data.current_netif = netif; ++ ip_data.current_input_netif = inp; ++ ++ ++ pbuf_remove_header(p, iphdr_hlen); /* Move to payload, no check necessary. */ ++ MIB2_STATS_INC(mib2.ipindelivers); ++ udp_input(p, inp); ++ ++ return ERR_OK; ++} ++ ++u8_t get_nip_hdrlen(struct pbuf *buf) ++{ ++ u8_t type, len; ++ u8_t *p, *start; ++ u8_t hdrlen = 0; ++ u8_t totallen_c; ++ u16_t totallen; ++ u8_t nexth; ++ u8_t ttl; ++ totallen = 0; ++ start = buf->payload; ++ p = buf->payload; ++ ++ do ++ { ++ type = *p; ++ p++; ++ switch (type) ++ { ++ case NIP_FIELDTYPE_HEADERLEN: ++ len = *p; ++ p++; ++ p = decode_tlv(p, len, &hdrlen); ++ ip_data.current_nip_header->_v_hl = hdrlen; ++ if(p == NULL) ++ { ++ printf("failure when decode source address! \r\n"); ++ return -EFAULT; ++ } ++ break; ++ case NIP_FIELDTYPE_SADDR: ++ len = *p; ++ p++; ++ p = decode_nip_addr(p, len, &ip_data.current_iphdr_src); ++ ++ if(p == NULL) ++ { ++ printf("failure when decode source address! \r\n"); ++ return -EFAULT; ++ } ++ break; ++ case NIP_FIELDTYPE_DADDR: ++ len = *p; ++ p++; ++ p = decode_nip_addr(p, len, &ip_data.current_iphdr_dest); ++ if(p == NULL) ++ { ++ printf("failure when decode source address! \r\n"); ++ return -EFAULT; ++ } ++ break; ++ case NIP_FIELDTYPE_FRAG: ++ len = *p; ++ p++; ++ p += len; ++ if(p == NULL) ++ { ++ printf("failure when decode source address! \r\n"); ++ return -EFAULT; ++ } ++ break; ++ case NIP_FIELDTYPE_NEXTHEADER: ++ len = *p; ++ p++; ++ p = decode_tlv(p, len, &nexth); ++ ip_data.current_nip_header->_nexth = nexth; ++ if(p == NULL) ++ { ++ printf("failure when decode source address! \r\n"); ++ return -EFAULT; ++ } ++ break; ++ case NIP_FIELDTYPE_TTL: ++ len = *p; ++ p++; ++ p = decode_tlv(p, len, &ttl); ++ ip_data.current_nip_header->_ttl = ttl; ++ ++ if(p == NULL) ++ { ++ printf("failure when decode source address! \r\n"); ++ return -EFAULT; ++ } ++ break; ++ case NIP_FIELDTYPE_TOTALLEN: ++ len = *p; ++ p++; ++ if (len == 1){ ++ p = decode_tlv(p, len, &totallen_c); ++ totallen = (u16_t)totallen_c; ++ } else { ++ p = decode_tlv2(p, len, (u16_t *)&totallen); ++ } ++ ip_data.current_ip_header_tot_len = (u16_t)totallen; ++ ++ if(p == NULL) ++ { ++ printf("failure when decode source address! \r\n"); ++ return -EFAULT; ++ } ++ break; ++ default: ++ len = *p; ++ p++; ++ p += len; ++ if(p == NULL) ++ { ++ printf("failure when decode source address! \r\n"); ++ return -EFAULT; ++ } ++ break; ++ } ++ } while ((totallen == 0) || (hdrlen - (p - start)) > 4); ++ return hdrlen; ++} ++u8_t * decode_tlv(u8_t * buf, u8_t tlen, u8_t * value) { ++ u8_t *p =buf; ++ memcpy(value, p, tlen); ++ p += tlen; ++ return p; ++} ++u8_t * decode_tlv2(u8_t * buf, u8_t tlen, u16_t * value) { ++ u8_t *p =buf; ++ memcpy(value, p, tlen); ++ *value = htons(*value); ++ p += tlen; ++ return p; ++} ++u8_t * decode_nip_addr(u8_t *buf, u8_t tlen, ip_addr_t *addr) { ++ u8_t len, remainlen; ++ u8_t level_num = 0; ++ u8_t * p; ++ p = buf; ++ remainlen = tlen; ++ while(remainlen > 0) { ++ len = *p; ++ ++p; ++ if(len > NIP_ADDRLEN_MAX){ ++ printf("%s: invalid addren! len = %d!\n", __func__, len); ++ return NULL; ++ } ++ memcpy(addr->laddrs[level_num].nip_addr_field8, p, len); ++ addr->laddrs[level_num].nip_addr_bitlen = len << 3; ++ level_num++; ++ remainlen = remainlen - len - 1; ++ p += len; ++ } ++ addr->level_num = level_num; ++ return p; ++} ++#endif /* LWIP_NIP */ +diff -Nur a/lwip-2.1.2/src/core/nip/nip_frag.c b/lwip-2.1.2/src/core/nip/nip_frag.c +--- a/lwip-2.1.2/src/core/nip/nip_frag.c 1970-01-01 07:00:00.000000000 +0700 ++++ b/lwip-2.1.2/src/core/nip/nip_frag.c 2022-01-11 06:35:08.107401000 +0800 +@@ -0,0 +1,1078 @@ ++/** ++ * @file ++ * This is the NIP packet segmentation and reassembly implementation. ++ * ++ */ ++ ++/* ++ * 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: Jani Monoses ++ * Simon Goldschmidt ++ * original reassembly code by Adam Dunkels ++ * ++ */ ++ ++#include "lwip/opt.h" ++ ++#if LWIP_NIP ++ ++#include "lwip/nip_frag.h" ++#include "lwip/def.h" ++#include "lwip/inet_chksum.h" ++#include "lwip/netif.h" ++#include "lwip/stats.h" ++#include "lwip/icmp.h" ++#include "lwip/nip.h" ++ ++#include ++ ++/** ++ * Move the pointer to any position in the newip header ++ * @param len_or_value NIP_LEN represents the position of len, and NIP_VALUE represents the position of value ++ * @param type header field type ++ * @param niphdr the starting position of the header ++ * ++ * @return Pointer to len(value) in the header. ++*/ ++void *location_niphdr(u8_t len_or_value, u8_t type, void* niphdr) { ++ u8_t *p = (u8_t*)niphdr; ++ u8_t cur_type; ++ u8_t hdrlen = 0; ++ if (len_or_value != NIP_LEN && len_or_value != NIP_VALUE) ++ return NULL; ++ do { ++ cur_type = *p; ++ p++; ++ if(cur_type == type) { ++ if (len_or_value == 1)/*len*/ ++ return p; ++ else {/*value*/ ++ p++; ++ return p; ++ } ++ } else { ++ if (cur_type == NIP_FIELDTYPE_HEADERLEN) { ++ p++; ++ hdrlen = *p; ++ p++; ++ continue; ++ } ++ p = p + *p + 1; ++ } ++ } while (p - (u8_t*)niphdr != hdrlen); ++ return NULL; ++} ++ ++#if NIP_REASSEMBLY ++/** ++ * The IP reassembly code currently has the following limitations: ++ * - IP header options are not supported ++ * - fragments must not overlap (e.g. due to different routes), ++ * currently, overlapping or duplicate fragments are thrown away ++ * if IP_REASS_CHECK_OVERLAP=1 (the default)! ++ * ++ * @todo: work with IP header options ++ */ ++ ++/** Setting this to 0, you can turn off checking the fragments for overlapping ++ * regions. The code gets a little smaller. Only use this if you know that ++ * overlapping won't occur on your network! */ ++#ifndef NIP_REASS_CHECK_OVERLAP ++#define NIP_REASS_CHECK_OVERLAP 1 ++#endif /* NIP_REASS_CHECK_OVERLAP */ ++ ++/** Set to 0 to prevent freeing the oldest datagram when the reassembly buffer is ++ * full (IP_REASS_MAX_PBUFS pbufs are enqueued). The code gets a little smaller. ++ * Datagrams will be freed by timeout only. Especially useful when MEMP_NUM_REASSDATA ++ * is set to 1, so one datagram can be reassembled at a time, only. */ ++#ifndef NIP_REASS_FREE_OLDEST ++#define NIP_REASS_FREE_OLDEST 0 ++#endif /* NIP_REASS_FREE_OLDEST */ ++ ++#define NIP_REASS_FLAG_LASTFRAG 0x01 ++ ++#define NIP_REASS_VALIDATE_TELEGRAM_FINISHED 1 ++#define NIP_REASS_VALIDATE_PBUF_QUEUED 0 ++#define NIP_REASS_VALIDATE_PBUF_DROPPED -1 ++ ++/** This is a helper struct which holds the starting ++ * offset and the ending offset of this fragment to ++ * easily chain the fragments. ++ * It has the same packing requirements as the IP header, since it replaces ++ * the IP header in memory in incoming fragments (after copying it) to keep ++ * track of the various fragments. (-> If the IP header doesn't need packing, ++ * this struct doesn't need packing, too.) ++ */ ++#ifdef PACK_STRUCT_USE_INCLUDES ++# include "arch/bpstruct.h" ++#endif ++PACK_STRUCT_BEGIN ++struct nip_reass_helper { ++ PACK_STRUCT_FIELD(struct pbuf *next_pbuf); ++ PACK_STRUCT_FIELD(u16_t start); ++ PACK_STRUCT_FIELD(u16_t end); ++} PACK_STRUCT_STRUCT; ++PACK_STRUCT_END ++#ifdef PACK_STRUCT_USE_INCLUDES ++# include "arch/epstruct.h" ++#endif ++ ++bool nip_addresses_and_id_match(void* niphdrA, void* niphdrB){ ++ u16_t *pa_id = (u16_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_FRAG, niphdrA); ++ pa_id++; ++ u16_t *pb_id = (u16_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_FRAG, niphdrB); ++ pb_id++; ++ if(*pa_id != *pb_id) return false;/*id*/ ++ u8_t len_a_src = *(u8_t*)location_niphdr(NIP_LEN, NIP_FIELDTYPE_SADDR, niphdrA); ++ u8_t len_b_src = *(u8_t*)location_niphdr(NIP_LEN, NIP_FIELDTYPE_SADDR, niphdrB); ++ if(len_a_src != len_b_src) return false;/*scr_len*/ ++ u8_t len_a_dest = *(u8_t*)location_niphdr(NIP_LEN, NIP_FIELDTYPE_DADDR, niphdrA); ++ u8_t len_b_dest = *(u8_t*)location_niphdr(NIP_LEN, NIP_FIELDTYPE_DADDR, niphdrB); ++ if(len_a_dest != len_b_dest) return false;/*dest_len*/ ++ u8_t *pa_src = (u8_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_SADDR, niphdrA); ++ u8_t *pb_src = (u8_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_SADDR, niphdrB); ++ for(u8_t i = 0;i < len_a_src;i++){ ++ if(*pa_src != *pb_src) return false; ++ pa_src++; ++ pb_src++; ++ } ++ u8_t *pa_dest = (u8_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_DADDR, niphdrA); ++ u8_t *pb_dest = (u8_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_DADDR, niphdrB); ++ for(u8_t i = 0;i < len_a_dest;i++){ ++ if(*pa_dest != *pb_dest) return false; ++ pa_dest++; ++ pb_dest++; ++ } ++ return true; ++} ++ ++/* global variables */ ++static struct nip_reassdata *reassdatagrams; ++static u16_t nip_reass_pbufcount; ++ ++/* function prototypes */ ++static void nip_reass_dequeue_datagram(struct nip_reassdata *ipr, struct nip_reassdata *prev); ++static int nip_reass_free_complete_datagram(struct nip_reassdata *ipr, struct nip_reassdata *prev); ++ ++u8_t number_of_zeros(void* fraghdr, u16_t hlen){ ++ u8_t type, len; ++ u8_t *p; ++ p = (u8_t*)fraghdr; ++ do ++ { ++ type = *p; ++ p++; ++ switch (type) ++ { ++ case NIP_FIELDTYPE_TOTALLEN: ++ case NIP_FIELDTYPE_SADDR: ++ case NIP_FIELDTYPE_DADDR: ++ case NIP_FIELDTYPE_NEXTHEADER: ++ case NIP_FIELDTYPE_TTL: ++ case NIP_FIELDTYPE_FRAG: ++ case NIP_FIELDTYPE_HEADERLEN: ++ len = *p; ++ p++; ++ p += len; ++ break; ++ case 0: ++ return hlen - (p - (u8_t*)fraghdr - 1); ++ default: ++ printf("hdrType %d not suported yet! \r\n", type); ++ return -1; ++ } ++ } while (p - (u8_t*)fraghdr < hlen); ++ return 0; ++} ++ ++/** ++ * Reassembly timer base function ++ * for both NO_SYS == 0 and 1 (!). ++ * ++ * Should be called every 1000 msec (defined by IP_TMR_INTERVAL). ++ */ ++void ++nip_reass_tmr(void) ++{ ++ struct nip_reassdata *r, *prev = NULL; ++ ++ r = reassdatagrams; ++ while (r != NULL) { ++ /* Decrement the timer. Once it reaches 0, ++ * clean up the incomplete fragment assembly */ ++ if (r->timer > 0) { ++ r->timer--; ++ LWIP_DEBUGF(IP_REASS_DEBUG, ("nip_reass_tmr: timer dec %"U16_F"\n", (u16_t)r->timer)); ++ prev = r; ++ r = r->next; ++ } else { ++ /* reassembly timed out */ ++ struct nip_reassdata *tmp; ++ LWIP_DEBUGF(IP_REASS_DEBUG, ("nip_reass_tmr: timer timed out\n")); ++ tmp = r; ++ /* get the next pointer before freeing */ ++ r = r->next; ++ /* free the helper struct and all enqueued pbufs */ ++ nip_reass_free_complete_datagram(tmp, prev); ++ } ++ } ++} ++ ++/** ++ * Free a datagram (struct ip_reassdata) and all its pbufs. ++ * Updates the total count of enqueued pbufs (ip_reass_pbufcount), ++ * SNMP counters and sends an ICMP time exceeded packet. ++ * ++ * @param ipr datagram to free ++ * @param prev the previous datagram in the linked list ++ * @return the number of pbufs freed ++ */ ++static int ++nip_reass_free_complete_datagram(struct nip_reassdata *ipr, struct nip_reassdata *prev) ++{ ++ u16_t pbufs_freed = 0; ++ u16_t clen; ++ struct pbuf *p; ++ struct nip_reass_helper *iprh; ++ ++ LWIP_ASSERT("prev != ipr", prev != ipr); ++ if (prev != NULL) { ++ LWIP_ASSERT("prev->next == ipr", prev->next == ipr); ++ } ++ ++ MIB2_STATS_INC(mib2.ipreasmfails); ++ ++ /* First, free all received pbufs. The individual pbufs need to be released ++ separately as they have not yet been chained */ ++ p = ipr->p; ++ while (p != NULL) { ++ struct pbuf *pcur; ++ iprh = (struct nip_reass_helper *)p->payload; ++ pcur = p; ++ /* get the next pointer before freeing */ ++ p = iprh->next_pbuf; ++ clen = pbuf_clen(pcur); ++ LWIP_ASSERT("pbufs_freed + clen <= 0xffff", pbufs_freed + clen <= 0xffff); ++ pbufs_freed = (u16_t)(pbufs_freed + clen); ++ pbuf_free(pcur); ++ } ++ /* Then, unchain the struct ip_reassdata from the list and free it. */ ++ nip_reass_dequeue_datagram(ipr, prev); ++ LWIP_ASSERT("ip_reass_pbufcount >= pbufs_freed", nip_reass_pbufcount >= pbufs_freed); ++ nip_reass_pbufcount = (u16_t)(nip_reass_pbufcount - pbufs_freed); ++ ++ return pbufs_freed; ++} ++ ++#if IP_REASS_FREE_OLDEST ++/** ++ * Free the oldest datagram to make room for enqueueing new fragments. ++ * The datagram 'fraghdr' belongs to is not freed! ++ * ++ * @param fraghdr IP header of the current fragment ++ * @param pbufs_needed number of pbufs needed to enqueue ++ * (used for freeing other datagrams if not enough space) ++ * @return the number of pbufs freed ++ */ ++static int ++nip_reass_remove_oldest_datagram(struct nip_hdr *fraghdr, int pbufs_needed) ++{ ++ /* @todo Can't we simply remove the last datagram in the ++ * linked list behind reassdatagrams? ++ */ ++ struct ip_reassdata *r, *oldest, *prev, *oldest_prev; ++ int pbufs_freed = 0, pbufs_freed_current; ++ int other_datagrams; ++ ++ /* Free datagrams until being allowed to enqueue 'pbufs_needed' pbufs, ++ * but don't free the datagram that 'fraghdr' belongs to! */ ++ do { ++ oldest = NULL; ++ prev = NULL; ++ oldest_prev = NULL; ++ other_datagrams = 0; ++ r = reassdatagrams; ++ while (r != NULL) { ++ if (!IP_ADDRESSES_AND_ID_MATCH(&r->iphdr, fraghdr)) { ++ /* Not the same datagram as fraghdr */ ++ other_datagrams++; ++ if (oldest == NULL) { ++ oldest = r; ++ oldest_prev = prev; ++ } else if (r->timer <= oldest->timer) { ++ /* older than the previous oldest */ ++ oldest = r; ++ oldest_prev = prev; ++ } ++ } ++ if (r->next != NULL) { ++ prev = r; ++ } ++ r = r->next; ++ } ++ if (oldest != NULL) { ++ pbufs_freed_current = ip_reass_free_complete_datagram(oldest, oldest_prev); ++ pbufs_freed += pbufs_freed_current; ++ } ++ } while ((pbufs_freed < pbufs_needed) && (other_datagrams > 1)); ++ return pbufs_freed; ++} ++#endif /* IP_REASS_FREE_OLDEST */ ++ ++/** ++ * Enqueues a new fragment into the fragment queue ++ * @param fraghdr points to the new fragments IP hdr ++ * @param clen number of pbufs needed to enqueue (used for freeing other datagrams if not enough space) ++ * @return A pointer to the queue location into which the fragment was enqueued ++ */ ++static struct nip_reassdata * ++nip_reass_enqueue_new_datagram(void *fraghdr, int clen) ++{ ++ struct nip_reassdata *ipr; ++ u8_t hlen; ++#if ! NIP_REASS_FREE_OLDEST ++ LWIP_UNUSED_ARG(clen); ++#endif ++ ++ /* No matching previous fragment found, allocate a new reassdata struct */ ++ ipr = (struct nip_reassdata *)memp_malloc(MEMP_REASSDATA); ++ if (ipr == NULL) { ++#if NIP_REASS_FREE_OLDEST ++ if (ip_reass_remove_oldest_datagram(fraghdr, clen) >= clen) { ++ ipr = (struct ip_reassdata *)memp_malloc(MEMP_NUM_REASSDATA); ++ } ++ if (ipr == NULL) ++#endif /* NIP_REASS_FREE_OLDEST */ ++ { ++ //NIP_FRAG_STATS_INC(ip_frag.memerr); ++ LWIP_DEBUGF(IP_REASS_DEBUG, ("Failed to alloc reassdata struct\n")); ++ return NULL; ++ } ++ } ++ memset(ipr, 0, sizeof(struct nip_reassdata)); ++ ipr->timer = NIP_REASS_MAXAGE; ++ ++ /* enqueue the new structure to the front of the list */ ++ ipr->next = reassdatagrams; ++ reassdatagrams = ipr; ++ /* copy the ip header for later tests and input */ ++ /* @todo: no ip options supported? */ ++ hlen = *(u8_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_HEADERLEN, fraghdr); ++ SMEMCPY(ipr->niphdr, fraghdr, hlen); ++ return ipr; ++} ++ ++/** ++ * Dequeues a datagram from the datagram queue. Doesn't deallocate the pbufs. ++ * @param ipr points to the queue entry to dequeue ++ */ ++static void ++nip_reass_dequeue_datagram(struct nip_reassdata *ipr, struct nip_reassdata *prev) ++{ ++ /* dequeue the reass struct */ ++ if (reassdatagrams == ipr) { ++ /* it was the first in the list */ ++ reassdatagrams = ipr->next; ++ } else { ++ /* it wasn't the first, so it must have a valid 'prev' */ ++ LWIP_ASSERT("sanity check linked list", prev != NULL); ++ prev->next = ipr->next; ++ } ++ ++ /* now we can free the ip_reassdata struct */ ++ memp_free(MEMP_NUM_REASSDATA, ipr); ++} ++ ++/** ++ * Chain a new pbuf into the pbuf list that composes the datagram. The pbuf list ++ * will grow over time as new pbufs are rx. ++ * Also checks that the datagram passes basic continuity checks (if the last ++ * fragment was received at least once). ++ * @param ipr points to the reassembly state ++ * @param new_p points to the pbuf for the current fragment ++ * @param is_last is 1 if this pbuf has MF==0 (ipr->flags not updated yet) ++ * @return see IP_REASS_VALIDATE_* defines ++ */ ++static int ++nip_reass_chain_frag_into_datagram_and_validate(struct nip_reassdata *ipr, struct pbuf *new_p, int is_last) ++{ ++ struct nip_reass_helper *iprh, *iprh_tmp, *iprh_prev = NULL; ++ struct pbuf *q; ++ u16_t offset, len; ++ u8_t hlen, len_totallen; ++ void *fraghdr; ++ int valid = 1; ++ /* Extract length and fragment offset from current fragment */ ++ fraghdr = (void *)new_p->payload;/*ip header*/ ++ len_totallen = *(u8_t*)location_niphdr(NIP_LEN, NIP_FIELDTYPE_TOTALLEN, fraghdr);/*totallen's number of bytes(1 or 2)*/ ++ if(len_totallen == 2) ++ len = lwip_ntohs(*(u16_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_TOTALLEN, fraghdr));/*totallen*/ ++ else if(len_totallen == 1) ++ len = (u16_t)*(u8_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_TOTALLEN, fraghdr);/*totallen*/ ++ hlen = *(u8_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_HEADERLEN, fraghdr);/*header_len*/ ++ ++ if (hlen > len) { ++ /* invalid datagram */ ++ return NIP_REASS_VALIDATE_PBUF_DROPPED; ++ } ++ len = (u16_t)(len - hlen); ++ offset = (u16_t)((lwip_ntohs(*(u16_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_FRAG, fraghdr)) & 0x1fff)*8U); ++ /* overwrite the fragment's ip header from the pbuf with our helper struct, ++ * and setup the embedded helper structure. */ ++ /* make sure the struct ip_reass_helper fits into the IP header */ ++ // LWIP_ASSERT("sizeof(struct ip_reass_helper) <= IP_HLEN", ++ // sizeof(struct ip_reass_helper) <= IP_HLEN); ++ iprh = (struct nip_reass_helper *)new_p->payload; ++ iprh->next_pbuf = NULL; ++ iprh->start = offset; ++ iprh->end = (u16_t)(offset + len); ++ if (iprh->end < offset) { ++ /* u16_t overflow, cannot handle this */ ++ return NIP_REASS_VALIDATE_PBUF_DROPPED; ++ } ++ ++ /* Iterate through until we either get to the end of the list (append), ++ * or we find one with a larger offset (insert). */ ++ for (q = ipr->p; q != NULL;) {/*ipr->p initialized to 0*/ ++ iprh_tmp = (struct nip_reass_helper *)q->payload; ++ if (iprh->start < iprh_tmp->start) { ++ /* the new pbuf should be inserted before this */ ++ iprh->next_pbuf = q; ++ if (iprh_prev != NULL) { ++ /* not the fragment with the lowest offset */ ++#if NIP_REASS_CHECK_OVERLAP ++ if ((iprh->start < iprh_prev->end) || (iprh->end > iprh_tmp->start)) { ++ /* fragment overlaps with previous or following, throw away */ ++ return NIP_REASS_VALIDATE_PBUF_DROPPED; ++ } ++#endif /* NIP_REASS_CHECK_OVERLAP */ ++ iprh_prev->next_pbuf = new_p; ++ if (iprh_prev->end != iprh->start) { ++ /* There is a fragment missing between the current ++ * and the previous fragment */ ++ valid = 0; ++ } ++ } else {/*first fragment*/ ++#if NIP_REASS_CHECK_OVERLAP ++ if (iprh->end > iprh_tmp->start) { ++ /* fragment overlaps with following, throw away */ ++ return NIP_REASS_VALIDATE_PBUF_DROPPED; ++ } ++#endif /* NIP_REASS_CHECK_OVERLAP */ ++ /* fragment with the lowest offset */ ++ ipr->p = new_p; ++ } ++ break; ++ } else if (iprh->start == iprh_tmp->start) { ++ /* received the same datagram twice: no need to keep the datagram */ ++ return NIP_REASS_VALIDATE_PBUF_DROPPED; ++#if NIP_REASS_CHECK_OVERLAP ++ } else if (iprh->start < iprh_tmp->end) { ++ /* overlap: no need to keep the new datagram */ ++ return NIP_REASS_VALIDATE_PBUF_DROPPED; ++#endif /* NIP_REASS_CHECK_OVERLAP */ ++ } else {/*iprh->start >= iprh_tmp->end*/ ++ /* Check if the fragments received so far have no holes. */ ++ if (iprh_prev != NULL) { ++ if (iprh_prev->end != iprh_tmp->start) { ++ /* There is a fragment missing between the current ++ * and the previous fragment */ ++ valid = 0; ++ } ++ } ++ } ++ q = iprh_tmp->next_pbuf; ++ iprh_prev = iprh_tmp; ++ } ++ ++ /* If q is NULL, then we made it to the end of the list. Determine what to do now */ ++ if (q == NULL) { ++ if (iprh_prev != NULL) { ++ /* this is (for now), the fragment with the highest offset: ++ * chain it to the last fragment */ ++#if NIP_REASS_CHECK_OVERLAP ++ LWIP_ASSERT("check fragments don't overlap", iprh_prev->end <= iprh->start); ++#endif /* NIP_REASS_CHECK_OVERLAP */ ++ iprh_prev->next_pbuf = new_p; ++ if (iprh_prev->end != iprh->start) { ++ valid = 0; ++ } ++ } else { ++#if NIP_REASS_CHECK_OVERLAP ++ LWIP_ASSERT("no previous fragment, this must be the first fragment!", ++ ipr->p == NULL); ++#endif /* NIP_REASS_CHECK_OVERLAP */ ++ /* this is the first fragment we ever received for this ip datagram */ ++ ipr->p = new_p; ++ } ++ } ++ ++ /* At this point, the validation part begins: */ ++ /* If we already received the last fragment */ ++ if (is_last || ((ipr->flags & NIP_REASS_FLAG_LASTFRAG) != 0)) { ++ /* and had no holes so far */ ++ if (valid) { ++ /* then check if the rest of the fragments is here */ ++ /* Check if the queue starts with the first datagram */ ++ if ((ipr->p == NULL) || (((struct nip_reass_helper *)ipr->p->payload)->start != 0)) { ++ valid = 0; ++ } else { ++ /* and check that there are no holes after this datagram */ ++ iprh_prev = iprh; ++ q = iprh->next_pbuf; ++ while (q != NULL) { ++ iprh = (struct nip_reass_helper *)q->payload; ++ if (iprh_prev->end != iprh->start) { ++ valid = 0; ++ break; ++ } ++ iprh_prev = iprh; ++ q = iprh->next_pbuf; ++ } ++ /* if still valid, all fragments are received ++ * (because to the MF==0 already arrived */ ++ if (valid) { ++ LWIP_ASSERT("sanity check", ipr->p != NULL); ++ LWIP_ASSERT("sanity check", ++ ((struct nip_reass_helper *)ipr->p->payload) != iprh); ++ LWIP_ASSERT("validate_datagram:next_pbuf!=NULL", ++ iprh->next_pbuf == NULL); ++ } ++ } ++ } ++ /* If valid is 0 here, there are some fragments missing in the middle ++ * (since MF == 0 has already arrived). Such datagrams simply time out if ++ * no more fragments are received... */ ++ return valid ? NIP_REASS_VALIDATE_TELEGRAM_FINISHED : NIP_REASS_VALIDATE_PBUF_QUEUED; ++ } ++ /* If we come here, not all fragments were received, yet! */ ++ return NIP_REASS_VALIDATE_PBUF_QUEUED; /* not yet valid! */ ++} ++ ++/** ++ * Reassembles incoming IP fragments into an IP datagram. ++ * ++ * @param p points to a pbuf chain of the fragment ++ * @return NULL if reassembly is incomplete, ? otherwise ++ */ ++struct pbuf * ++nip_reass(struct pbuf *p) ++{ ++ struct pbuf *r; ++ void *fraghdr; ++ struct nip_reassdata *ipr; ++ struct nip_reass_helper *iprh; ++ u16_t offset, len, clen; ++ u8_t hlen; ++ u8_t len_totallen; ++ int valid; ++ int is_last; ++ ++ //NIP_FRAG_STATS_INC(nip_frag.recv); ++ //MIB2_STATS_INC(mib2.ipreasmreqds); ++ ++ fraghdr = p->payload;/*Get ip header*/ ++ offset = (u16_t)((lwip_ntohs(*(u16_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_FRAG, fraghdr)) & 0x1fff)*8U); ++ len_totallen = *(u8_t*)location_niphdr(NIP_LEN, NIP_FIELDTYPE_TOTALLEN, fraghdr);/*totallen's number of bytes(1 or 2)*/ ++ if(len_totallen == 2) ++ len = lwip_ntohs(*(u16_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_TOTALLEN, fraghdr));/*totallen*/ ++ else if(len_totallen == 1) ++ len = (u16_t)*(u8_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_TOTALLEN, fraghdr);/*totallen*/ ++ hlen = *(u8_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_HEADERLEN, fraghdr);/*headerlen*/ ++ if (hlen > len) { ++ /* invalid datagram */ ++ goto nullreturn; ++ } ++ len = (u16_t)(len - hlen);/*Message length*/ ++ clen = pbuf_clen(p);/*Number of pbuf chains*/ ++ if ((nip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS) {/*too many*/ ++#if NIP_REASS_FREE_OLDEST ++ if (!ip_reass_remove_oldest_datagram(fraghdr, clen) || ++ ((ip_reass_pbufcount + clen) > IP_REASS_MAX_PBUFS)) ++#endif /* NIP_REASS_FREE_OLDEST */ ++ { ++ /* No datagram could be freed and still too many pbufs enqueued */ ++ LWIP_DEBUGF(IP_REASS_DEBUG, ("nip_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n", ++ nip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS)); ++ //NIP_FRAG_STATS_INC(nip_frag.memerr); ++ /* @todo: send ICMP time exceeded here? */ ++ /* drop this pbuf */ ++ goto nullreturn; ++ } ++ } ++ ++ /* Look for the datagram the fragment belongs to in the current datagram queue, ++ * remembering the previous in the queue for later dequeueing. */ ++ for (ipr = reassdatagrams; ipr != NULL; ipr = ipr->next) { ++ /* Check if the incoming fragment matches the one currently present ++ in the reassembly buffer. If so, we proceed with copying the ++ fragment into the buffer. */ ++ if (nip_addresses_and_id_match((void*)ipr->niphdr, fraghdr)) { ++ // LWIP_DEBUGF(IP_REASS_DEBUG, ("ip4_reass: matching previous fragment ID=%"X16_F"\n", ++ // lwip_ntohs(IPH_ID(fraghdr)))); ++ //NIP_FRAG_STATS_INC(nip_frag.cachehit); ++ break; ++ } ++ } ++ u16_t offset_frag = lwip_ntohs(*(u16_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_FRAG, fraghdr)); ++ if (ipr == NULL) {/*first segment*/ ++ /* Enqueue a new datagram into the datagram queue */ ++ ipr = nip_reass_enqueue_new_datagram(fraghdr, clen); ++ /* Bail if unable to enqueue */ ++ if (ipr == NULL) { ++ goto nullreturn; ++ } ++ } else {/*not first segment*/ ++ u16_t offset_ipr = lwip_ntohs(*(u16_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_FRAG, (void*)ipr->niphdr)); ++ if (((offset_frag & 0x1fff) == 0) &&/*received*/ ++ (( offset_ipr & 0x1fff) != 0)) {/*origin*/ ++ /* ipr->iphdr is not the header from the first fragment, but fraghdr is ++ * -> copy fraghdr into ipr->iphdr since we want to have the header ++ * of the first fragment (for ICMP time exceeded and later, for copying ++ * all options, if supported)*/ ++ SMEMCPY(ipr->niphdr, fraghdr, hlen); ++ } ++ } ++ /* At this point, we have either created a new entry or pointing ++ * to an existing one */ ++ ++ /* check for 'no more fragments', and update queue entry*/ ++ is_last = (offset_frag & 0x2000U) == 0; ++ if (is_last) { ++ u16_t datagram_len = (u16_t)(offset + len); ++ if ((datagram_len < offset) || (datagram_len > (0xFFFF - hlen))) { ++ /* u16_t overflow, cannot handle this */ ++ goto nullreturn_ipr; ++ } ++ } ++ /* find the right place to insert this pbuf */ ++ /* @todo: trim pbufs if fragments are overlapping */ ++ u8_t zeros = number_of_zeros(fraghdr, hlen); ++ valid = nip_reass_chain_frag_into_datagram_and_validate(ipr, p, is_last); ++ if (valid == NIP_REASS_VALIDATE_PBUF_DROPPED) { ++ goto nullreturn_ipr; ++ } ++ /* if we come here, the pbuf has been enqueued */ ++ ++ /* Track the current number of pbufs current 'in-flight', in order to limit ++ the number of fragments that may be enqueued at any one time ++ (overflow checked by testing against IP_REASS_MAX_PBUFS) */ ++ nip_reass_pbufcount = (u16_t)(nip_reass_pbufcount + clen); ++ if (is_last) { ++ u16_t datagram_len = (u16_t)(offset + len); ++ ipr->datagram_len = datagram_len; ++ ipr->flags |= NIP_REASS_FLAG_LASTFRAG; ++ LWIP_DEBUGF(IP_REASS_DEBUG, ++ ("nip_reass: last fragment seen, total len %"S16_F"\n", ++ ipr->datagram_len)); ++ } ++ if (valid == NIP_REASS_VALIDATE_TELEGRAM_FINISHED) { ++ struct nip_reassdata *ipr_prev; ++ /* the totally last fragment (flag more fragments = 0) was received at least ++ * once AND all fragments are received */ ++ if(len_totallen == 1 && zeros == 0){ ++ hlen+=4; ++ } ++ u16_t datagram_len = (u16_t)(ipr->datagram_len + hlen); ++ /* save the second pbuf before copying the header over the pointer */ ++ r = ((struct nip_reass_helper *)ipr->p->payload)->next_pbuf; ++ ++ /* copy the original ip header back to the first pbuf */ ++ fraghdr = (void *)(ipr->p->payload); ++ SMEMCPY(fraghdr, ipr->niphdr, hlen); ++ u16_t *p_tmp = location_niphdr(NIP_VALUE, NIP_FIELDTYPE_TOTALLEN, fraghdr); ++ *p_tmp = lwip_htons(datagram_len); ++ p_tmp = location_niphdr(NIP_VALUE, NIP_FIELDTYPE_FRAG, fraghdr); ++ *p_tmp = 0; ++ //IPH_CHKSUM_SET(fraghdr, 0); ++ /* @todo: do we need to set/calculate the correct checksum? */ ++#if CHECKSUM_GEN_IP ++ IF__NETIF_CHECKSUM_ENABLED(ip_current_input_netif(), NETIF_CHECKSUM_GEN_IP) { ++ IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN)); ++ } ++#endif /* CHECKSUM_GEN_IP */ ++ p = ipr->p; ++ ++ /* chain together the pbufs contained within the reass_data list. */ ++ while (r != NULL) { ++ iprh = (struct nip_reass_helper *)r->payload; ++ if(iprh->next_pbuf == NULL && len_totallen == 1 && zeros == 0)/*The last message, and the header is 4 bytes less.*/ ++ /* hide the ip header for every succeeding fragment */ ++ pbuf_remove_header(r, hlen - 4); ++ else/*Not the last message.*/ ++ pbuf_remove_header(r, hlen); ++ pbuf_cat(p, r); ++ r = iprh->next_pbuf; ++ } ++ ++ /* find the previous entry in the linked list */ ++ if (ipr == reassdatagrams) { ++ ipr_prev = NULL; ++ } else { ++ for (ipr_prev = reassdatagrams; ipr_prev != NULL; ipr_prev = ipr_prev->next) { ++ if (ipr_prev->next == ipr) { ++ break; ++ } ++ } ++ } ++ /* release the sources allocate for the fragment queue entry */ ++ nip_reass_dequeue_datagram(ipr, ipr_prev); ++ ++ /* and adjust the number of pbufs currently queued for reassembly. */ ++ clen = pbuf_clen(p); ++ LWIP_ASSERT("nip_reass_pbufcount >= clen", nip_reass_pbufcount >= clen); ++ nip_reass_pbufcount = (u16_t)(nip_reass_pbufcount - clen); ++ ++ MIB2_STATS_INC(mib2.ipreasmoks); ++ ++ /* Return the pbuf chain */ ++ return p; ++ } ++ /* the datagram is not (yet?) reassembled completely */ ++ LWIP_DEBUGF(IP_REASS_DEBUG, ("nip_reass_pbufcount: %d out\n", nip_reass_pbufcount)); ++ return NULL; ++ ++nullreturn_ipr: ++ LWIP_ASSERT("ipr != NULL", ipr != NULL); ++ if (ipr->p == NULL) { ++ /* dropped pbuf after creating a new datagram entry: remove the entry, too */ ++ LWIP_ASSERT("not firstalthough just enqueued", ipr == reassdatagrams); ++ nip_reass_dequeue_datagram(ipr, NULL); ++ } ++ ++nullreturn: ++ LWIP_DEBUGF(IP_REASS_DEBUG, ("nip_reass: nullreturn\n")); ++ //NIP_FRAG_STATS_INC(nip_frag.drop); ++ pbuf_free(p); ++ return NULL; ++} ++#endif /* IP_REASSEMBLY */ ++ ++#if NIP_FRAG ++#if !LWIP_NETIF_TX_SINGLE_PBUF ++/** Allocate a new struct pbuf_custom_ref */ ++static struct pbuf_custom_ref * ++nip_frag_alloc_pbuf_custom_ref(void) ++{ ++ return (struct pbuf_custom_ref *)memp_malloc(MEMP_FRAG_PBUF); ++} ++ ++/** Free a struct pbuf_custom_ref */ ++static void ++nip_frag_free_pbuf_custom_ref(struct pbuf_custom_ref *p) ++{ ++ LWIP_ASSERT("p != NULL", p != NULL); ++ memp_free(MEMP_FRAG_PBUF, p); ++} ++ ++/** Free-callback function to free a 'struct pbuf_custom_ref', called by ++ * pbuf_free. */ ++static void ++nipfrag_free_pbuf_custom(struct pbuf *p) ++{ ++ struct pbuf_custom_ref *pcr = (struct pbuf_custom_ref *)p; ++ LWIP_ASSERT("pcr != NULL", pcr != NULL); ++ LWIP_ASSERT("pcr == p", (void *)pcr == (void *)p); ++ if (pcr->original != NULL) { ++ pbuf_free(pcr->original); ++ } ++ nip_frag_free_pbuf_custom_ref(pcr); ++} ++#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ ++ ++u8_t get_nip_hdrlen2(struct pbuf *buf) ++{ ++ u8_t type, len; ++ u8_t *p; ++ u8_t hdrlen = 0; ++ p = buf->payload; ++ do ++ { ++ type = *p; ++ p++; ++ switch (type) ++ { ++ case NIP_FIELDTYPE_HEADERLEN: ++ len = *p; ++ p++; ++ memcpy(&hdrlen, p, len); ++ p += len; ++ break; ++ case NIP_FIELDTYPE_SADDR: ++ case NIP_FIELDTYPE_DADDR: ++ case NIP_FIELDTYPE_NEXTHEADER: ++ case NIP_FIELDTYPE_TTL: ++ case NIP_FIELDTYPE_FRAG: ++ case NIP_FIELDTYPE_TOTALLEN: ++ len = *p; ++ p++; ++ p += len; ++ break; ++ default: ++ printf("hdrType %d not suported yet! \r\n", type); ++ return -1; ++ } ++ } while (hdrlen == 0); ++ return hdrlen; ++} ++u16_t get_nip_totlen(struct pbuf *buf) ++{ ++ u8_t type, len; ++ u8_t *p; ++ u8_t totlen_u8 = 0; ++ u16_t totlen = 0; ++ p = buf->payload; ++ do ++ { ++ type = *p; ++ p++; ++ switch (type) ++ { ++ case NIP_FIELDTYPE_TOTALLEN: ++ len = *p; ++ p++; ++ if (len == 1) ++ { ++ memcpy(&totlen_u8, p, len); ++ totlen = totlen_u8; ++ } else { ++ memcpy((u8_t *)&totlen, p, len); ++ } ++ p += len; ++ break; ++ case NIP_FIELDTYPE_SADDR: ++ case NIP_FIELDTYPE_DADDR: ++ case NIP_FIELDTYPE_NEXTHEADER: ++ case NIP_FIELDTYPE_TTL: ++ case NIP_FIELDTYPE_FRAG: ++ case NIP_FIELDTYPE_HEADERLEN: ++ len = *p; ++ p++; ++ p += len; ++ break; ++ default: ++ printf("hdrType %d not suported yet! \r\n", type); ++ return -1; ++ } ++ ++ } while (totlen == 0); ++ return totlen; ++} ++ ++/** ++ * Fragment an IP datagram if too large for the netif. ++ * ++ * Chop the datagram in MTU sized chunks and send them in order ++ * by pointing PBUF_REFs into p. ++ * ++ * @param p ip packet to send ++ * @param netif the netif on which to send ++ * @param dest destination ip address to which to send ++ * @param zeros the number of zeros it add ++ * ++ * @return ERR_OK if sent successfully, err_t otherwise ++ */ ++err_t ++nip_frag(struct pbuf *p, struct netif *netif, const nip_addr_t *dest, u8_t zeros) ++{ ++ struct pbuf *rambuf; ++#if !LWIP_NETIF_TX_SINGLE_PBUF ++ struct pbuf *newpbuf; ++ u16_t newpbuflen = 0; ++ u16_t left_to_copy; ++#endif ++ u16_t nip_hdrlen = (u16_t)get_nip_hdrlen2(p); ++ void *original_niphdr; ++ void *niphdr; ++ const u16_t nfb = (u16_t)((netif->mtu - nip_hdrlen) / 8); ++ /*Why divide by 8: The segments are all multiples of 8 bytes, and the offset is increased by 1 for every 8 bytes.*/ ++ u16_t left, fragsize; ++ u16_t ofo; ++ int last; ++ u16_t poff = nip_hdrlen; ++ u16_t tmp; ++ int mf_set; ++ u16_t *poffset, *ptotlen_16; ++ u8_t *ptotlen_8; ++ ++ original_niphdr = p->payload; ++ niphdr = original_niphdr; ++ /* Save original offset */ ++ tmp = lwip_ntohs(*((u16_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_FRAG, niphdr))); ++ ofo = tmp & IP_OFFMASK; ++ /* already fragmented? if so, the last fragment we create must have MF, too */ ++ mf_set = tmp & IP_MF; ++ ++ left = (u16_t)(p->tot_len - nip_hdrlen); ++ while (left) { ++ /* Fill this fragment */ ++ fragsize = LWIP_MIN(left, (u16_t)(nfb * 8)); ++ if (p->tot_len > 255 && fragsize + nip_hdrlen < 256){/*before_len(totlen)==2&&after_len(totlen)==1*/ ++ if(zeros == 3){ ++ nip_hdrlen -= 4; ++ u8_t *p1, *p2; ++ p1 = location_niphdr(NIP_VALUE, NIP_FIELDTYPE_HEADERLEN, original_niphdr); ++ (*p1) -= 4; ++ p2 = location_niphdr(NIP_LEN, NIP_FIELDTYPE_TOTALLEN, original_niphdr); ++ (*p2)--; ++ p2++; ++ memcpy(p2, p2 + 1, (u8_t*)original_niphdr - p2 + nip_hdrlen); ++ }else{ ++ u8_t *p1, *p2; ++ p1 = location_niphdr(NIP_LEN, NIP_FIELDTYPE_TOTALLEN, original_niphdr); ++ (*p1)--; ++ p1++; ++ memcpy(p1, p1 + 1, (u8_t*)original_niphdr - p2 + nip_hdrlen - 1); ++ p2 = (u8_t*)original_niphdr + nip_hdrlen - 1; ++ *p2 = 0; ++ } ++ } ++#if LWIP_NETIF_TX_SINGLE_PBUF ++ rambuf = pbuf_alloc(PBUF_IP, fragsize, PBUF_RAM); ++ if (rambuf == NULL) { ++ goto memerr; ++ } ++ LWIP_ASSERT("this needs a pbuf in one piece!", ++ (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); ++ poff += pbuf_copy_partial(p, rambuf->payload, fragsize, poff); ++ /* make room for the IP header */ ++ if (pbuf_add_header(rambuf, nip_hdrlen)) { ++ pbuf_free(rambuf); ++ goto memerr; ++ } ++ /* fill in the IP header */ ++ SMEMCPY(rambuf->payload, original_niphdr, nip_hdrlen); ++ niphdr = rambuf->payload; ++#else /* LWIP_NETIF_TX_SINGLE_PBUF */ ++ /* When not using a static buffer, create a chain of pbufs. ++ * The first will be a PBUF_RAM holding the link and IP header. ++ * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, ++ * but limited to the size of an mtu. ++ */ ++ rambuf = pbuf_alloc(PBUF_LINK, nip_hdrlen, PBUF_RAM); ++ if (rambuf == NULL) { ++ goto memerr; ++ } ++ LWIP_ASSERT("this needs a pbuf in one piece!", ++ (rambuf->len >= (nip_hdrlen))); ++ SMEMCPY(rambuf->payload, original_niphdr, nip_hdrlen); ++ memcpy(niphdr, rambuf->payload, nip_hdrlen); ++ ++ left_to_copy = fragsize; ++ while (left_to_copy) { ++ struct pbuf_custom_ref *pcr; ++ u16_t plen = (u16_t)(p->len - poff); ++ LWIP_ASSERT("p->len >= poff", p->len >= poff); ++ newpbuflen = LWIP_MIN(left_to_copy, plen); ++ /* Is this pbuf already empty? */ ++ if (!newpbuflen) { ++ poff = 0; ++ p = p->next; ++ continue; ++ } ++ pcr = nip_frag_alloc_pbuf_custom_ref(); ++ if (pcr == NULL) { ++ pbuf_free(rambuf); ++ goto memerr; ++ } ++ /* Mirror this pbuf, although we might not need all of it. */ ++ newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, ++ (u8_t *)p->payload + poff, newpbuflen); ++ if (newpbuf == NULL) { ++ nip_frag_free_pbuf_custom_ref(pcr); ++ pbuf_free(rambuf); ++ goto memerr; ++ } ++ pbuf_ref(p); ++ pcr->original = p; ++ pcr->pc.custom_free_function = nipfrag_free_pbuf_custom; ++ ++ /* Add it to end of rambuf's chain, but using pbuf_cat, not pbuf_chain ++ * so that it is removed when pbuf_dechain is later called on rambuf. ++ */ ++ pbuf_cat(rambuf, newpbuf); ++ left_to_copy = (u16_t)(left_to_copy - newpbuflen); ++ if (left_to_copy) {/*mtu>=plen*/ ++ poff = 0; ++ p = p->next; ++ } ++ } ++ poff = (u16_t)(poff + newpbuflen); ++#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ ++ ++ ++ /* Correct header */ ++ last = (left <= netif->mtu - nip_hdrlen); ++ ++ /* Set new offset and MF flag */ ++ tmp = (IP_OFFMASK & (ofo)); ++ if (!last || mf_set) { ++ /* the last fragment has MF set if the input frame had it */ ++ tmp = tmp | IP_MF; ++ } ++ poffset = (u16_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_FRAG, niphdr); ++ *poffset = lwip_htons(tmp); ++ if(fragsize + nip_hdrlen <256) { ++ ptotlen_8 = (u8_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_TOTALLEN, niphdr); ++ *ptotlen_8 = (u8_t)(fragsize + nip_hdrlen); ++ } else { ++ ptotlen_16 = (u16_t*)location_niphdr(NIP_VALUE, NIP_FIELDTYPE_TOTALLEN, niphdr); ++ *ptotlen_16 = lwip_htons((u16_t)(fragsize + nip_hdrlen)); ++ } ++// IPH_CHKSUM_SET(niphdr, 0); ++// #if CHECKSUM_GEN_IP ++// IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { ++// IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); ++// } ++// #endif /* CHECKSUM_GEN_IP */ ++ /* No need for separate header pbuf - we allowed room for it in rambuf ++ * when allocated. ++ */ ++ netif->output_nip(netif, rambuf, dest); ++ IPFRAG_STATS_INC(ip_frag.xmit); ++ ++ /* Unfortunately we can't reuse rambuf - the hardware may still be ++ * using the buffer. Instead we free it (and the ensuing chain) and ++ * recreate it next time round the loop. If we're lucky the hardware ++ * will have already sent the packet, the free will really free, and ++ * there will be zero memory penalty. ++ */ ++ pbuf_free(rambuf); ++ left = (u16_t)(left - fragsize); ++ ofo = (u16_t)(ofo + nfb); ++ } ++ MIB2_STATS_INC(mib2.ipfragoks); ++ return ERR_OK; ++memerr: ++ MIB2_STATS_INC(mib2.ipfragfails); ++ return ERR_MEM; ++} ++#endif /* NIP_FRAG */ ++ ++#endif /* LWIP_NIP */ +diff -Nur a/lwip-2.1.2/src/core/raw.c b/lwip-2.1.2/src/core/raw.c +--- a/lwip-2.1.2/src/core/raw.c 2022-02-16 16:06:59.178115000 +0800 ++++ b/lwip-2.1.2/src/core/raw.c 2022-01-25 14:54:47.567357000 +0800 +@@ -63,7 +63,24 @@ + #include + + /** The list of RAW PCBs */ +-static struct raw_pcb *raw_pcbs; ++struct raw_pcb *raw_pcbs; ++ ++#if PF_PACKET_SOCKET ++const struct eth_hdr *g_lwip_current_eth_hdr; ++const struct netif *g_lwip_current_netif; ++struct raw_pcb *g_packet_raw_pcbs = NULL; ++struct raw_pcb *g_all_packet_raw_pcbs = NULL; ++ ++struct raw_pcb* get_packet_raw_pcbs(void) ++{ ++ return g_packet_raw_pcbs; ++} ++ ++struct raw_pcb* get_all_packet_raw_pcbs(void) ++{ ++ return g_all_packet_raw_pcbs; ++} ++#endif + + static u8_t + raw_input_local_match(struct raw_pcb *pcb, u8_t broadcast) +@@ -164,7 +181,7 @@ + /* loop through all raw pcbs until the packet is eaten by one */ + /* this allows multiple pcbs to match against the packet by design */ + while (pcb != NULL) { +- if ((pcb->protocol == proto) && raw_input_local_match(pcb, broadcast) && ++ if ((pcb->raw_proto == proto) && raw_input_local_match(pcb, broadcast) && + (((pcb->flags & RAW_FLAGS_CONNECTED) == 0) || + ip_addr_cmp(&pcb->remote_ip, ip_current_src_addr()))) { + /* receive callback function available? */ +@@ -277,10 +294,21 @@ + err_t + raw_connect(struct raw_pcb *pcb, const ip_addr_t *ipaddr) + { ++ struct netif *netif = NULL; + LWIP_ASSERT_CORE_LOCKED(); + if ((pcb == NULL) || (ipaddr == NULL)) { + return ERR_VAL; + } ++ ++ netif = ip_route_pcb(ipaddr, (struct ip_pcb*)pcb); ++ if (netif == NULL) { ++ return ERR_NETUNREACH; ++ } ++ ++ if (!ip_get_option(pcb, SOF_BROADCAST) && ip_addr_isbroadcast(ipaddr, netif)) { ++ return ERR_ACCESS; ++ } ++ + ip_addr_set_ipaddr(&pcb->remote_ip, ipaddr); + #if LWIP_IPV6 && LWIP_IPV6_SCOPES + /* If the given IP address should have a zone but doesn't, assign one now, +@@ -377,7 +405,7 @@ + if (netif == NULL) #endif /* LWIP_MULTICAST_TX_OPTIONS */ { - netif = ip_route(&pcb->local_ip, ipaddr); @@ -2552,7 +5487,19 @@ diff -Nur a/lwip-2.1.2/src/core/raw.c b/lwip-2.1.2/src/core/raw.c /* use outgoing network interface IP address as source address */ src_ip = ip_netif_get_local_ip(netif, ipaddr); #if LWIP_IPV6 -@@ -523,7 +551,7 @@ +@@ -437,8 +465,10 @@ + IP_IS_V6(dst_ip) ? IP6_HLEN : IP_HLEN); + #elif LWIP_IPV4 + IP_HLEN); +-#else ++#elif LWIP_IPV6 + IP6_HLEN); ++#else ++ 0); + #endif + + /* Handle the HDRINCL option as an exception: none of the code below applies +@@ -523,7 +553,7 @@ #endif /* LWIP_MULTICAST_TX_OPTIONS */ NETIF_SET_HINTS(netif, &pcb->netif_hints); @@ -2561,7 +5508,7 @@ diff -Nur a/lwip-2.1.2/src/core/raw.c b/lwip-2.1.2/src/core/raw.c NETIF_RESET_HINTS(netif); /* did we chain a header earlier? */ -@@ -604,7 +632,12 @@ +@@ -604,7 +634,12 @@ if (pcb != NULL) { /* initialize PCB to all zeroes */ memset(pcb, 0, sizeof(struct raw_pcb)); @@ -2574,7 +5521,7 @@ diff -Nur a/lwip-2.1.2/src/core/raw.c b/lwip-2.1.2/src/core/raw.c pcb->ttl = RAW_TTL; #if LWIP_MULTICAST_TX_OPTIONS raw_set_multicast_ttl(pcb, RAW_TTL); -@@ -668,4 +701,227 @@ +@@ -668,4 +703,227 @@ } } @@ -2802,9 +5749,106 @@ diff -Nur a/lwip-2.1.2/src/core/raw.c b/lwip-2.1.2/src/core/raw.c +#endif /* PF_PACKET_SOCKET */ + #endif /* LWIP_RAW */ +diff -Nur a/lwip-2.1.2/src/core/tcp.c b/lwip-2.1.2/src/core/tcp.c +--- a/lwip-2.1.2/src/core/tcp.c 2022-02-16 16:06:59.178115000 +0800 ++++ b/lwip-2.1.2/src/core/tcp.c 2022-01-25 14:54:36.104796000 +0800 +@@ -2265,6 +2265,13 @@ + } + #endif /* LWIP_IPV4 */ + ++#if LWIP_NIP ++ if (outif == NULL) { ++ return sendmss; ++ } ++ mtu = outif->mtu; ++#endif ++ + if (mtu != 0) { + u16_t offset; + #if LWIP_IPV6 +diff -Nur a/lwip-2.1.2/src/core/udp.c b/lwip-2.1.2/src/core/udp.c +--- a/lwip-2.1.2/src/core/udp.c 2022-02-16 16:06:59.178115000 +0800 ++++ b/lwip-2.1.2/src/core/udp.c 2022-01-27 20:13:02.401026000 +0800 +@@ -56,6 +56,7 @@ + #include "lwip/ip_addr.h" + #include "lwip/ip6.h" + #include "lwip/ip6_addr.h" ++#include "lwip/nip_addr.h" + #include "lwip/netif.h" + #include "lwip/icmp.h" + #include "lwip/icmp6.h" +@@ -324,8 +325,12 @@ + for_us = ip4_addr_cmp(netif_ip4_addr(inp), ip4_current_dest_addr()); + } + #endif /* LWIP_IPV4 */ ++#if LWIP_NIP ++ if (ip_current_is_nip()) { ++ for_us = nip_addr_cmp(netif_nip_addr(inp), nip_current_dest_addr()); ++ } ++#endif /* LWIP_NIP */ + } +- + if (for_us) { + LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n")); + #if CHECKSUM_CHECK_UDP +@@ -686,6 +691,13 @@ + src_ip = &pcb->local_ip; + } + #endif /* LWIP_IPV4 */ ++ ++#if LWIP_NIP ++ src_ip = netif_nip_addr(netif); ++ pcb->local_ip = *src_ip; ++ ++#endif /* LWIP_NIP */ ++ + #if LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP + return udp_sendto_if_src_chksum(pcb, p, dst_ip, dst_port, netif, have_chksum, chksum, src_ip); + #else /* LWIP_CHECKSUM_ON_COPY && CHECKSUM_GEN_UDP */ +@@ -936,7 +948,6 @@ + #if LWIP_IPV6 && LWIP_IPV6_SCOPES + ip_addr_t zoned_ipaddr; + #endif /* LWIP_IPV6 && LWIP_IPV6_SCOPES */ +- + LWIP_ASSERT_CORE_LOCKED(); + + #if LWIP_IPV4 +@@ -1263,6 +1274,11 @@ + if (pcb != NULL) { + IP_SET_TYPE_VAL(pcb->local_ip, type); + IP_SET_TYPE_VAL(pcb->remote_ip, type); ++ } ++#elif LWIP_NIP ++ if (pcb != NULL) { ++ IP_SET_TYPE_VAL(pcb->local_ip, type); ++ IP_SET_TYPE_VAL(pcb->remote_ip, type); + } + #else + LWIP_UNUSED_ARG(type); +diff -Nur a/lwip-2.1.2/src/Filelists.mk b/lwip-2.1.2/src/Filelists.mk +--- a/lwip-2.1.2/src/Filelists.mk 2022-02-16 16:06:59.162116000 +0800 ++++ b/lwip-2.1.2/src/Filelists.mk 2022-01-25 14:56:19.694471000 +0800 +@@ -70,6 +70,9 @@ + $(LWIPDIR)/core/ipv6/mld6.c \ + $(LWIPDIR)/core/ipv6/nd6.c + ++CORENIPFILES=$(LWIPDIR)/core/nip/nip.c \ ++ $(LWIPDIR)/core/nip/nip_addr.c \ ++ + # APIFILES: The files which implement the sequential and socket APIs. + APIFILES=$(LWIPDIR)/api/api_lib.c \ + $(LWIPDIR)/api/api_msg.c \ +@@ -129,6 +132,7 @@ + LWIPNOAPPSFILES=$(COREFILES) \ + $(CORE4FILES) \ + $(CORE6FILES) \ ++ $(CORENIPFILES) \ + $(APIFILES) \ + $(NETIFFILES) \ + $(PPPFILES) \ diff -Nur a/lwip-2.1.2/src/include/lwip/api.h b/lwip-2.1.2/src/include/lwip/api.h ---- a/lwip-2.1.2/src/include/lwip/api.h 2021-06-29 15:16:18.804893322 +0800 -+++ b/lwip-2.1.2/src/include/lwip/api.h 2021-06-29 15:16:44.632898725 +0800 +--- a/lwip-2.1.2/src/include/lwip/api.h 2022-02-16 16:06:59.178115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/api.h 2022-02-21 10:24:12.736800000 +0800 @@ -48,6 +48,9 @@ #include "lwip/sys.h" #include "lwip/ip_addr.h" @@ -2815,17 +5859,36 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/api.h b/lwip-2.1.2/src/include/lwip/api. #ifdef __cplusplus extern "C" { -@@ -140,6 +143,9 @@ +@@ -101,6 +104,11 @@ + #define NETCONNTYPE_ISIPV6(t) (((t)&NETCONN_TYPE_IPV6) != 0) + #define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF3) == NETCONN_UDPLITE) + #define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF3) == NETCONN_UDPNOCHKSUM) ++#elif LWIP_NIP ++#define NETCONN_TYPE_NIP 0x04 ++#define NETCONNTYPE_ISUDPLITE(t) (((t)&0xF3) == NETCONN_UDPLITE) ++#define NETCONNTYPE_ISUDPNOCHKSUM(t) (((t)&0xF3) == NETCONN_UDPNOCHKSUM) ++#define NETCONNTYPE_ISIPV6(t) (0) + #else /* LWIP_IPV6 */ + #define NETCONNTYPE_ISIPV6(t) (0) + #define NETCONNTYPE_ISUDPLITE(t) ((t) == NETCONN_UDPLITE) +@@ -140,6 +148,16 @@ /** Raw connection IPv6 (dual-stack by default, unless you call @ref netconn_set_ipv6only) */ , NETCONN_RAW_IPV6 = NETCONN_RAW | NETCONN_TYPE_IPV6 /* 0x48 */ #endif /* LWIP_IPV6 */ +#if PF_PACKET_SOCKET + , NETCONN_PACKET_RAW = 0x80 +#endif /* PF_PACKET_SOCKET */ ++#if LWIP_NIP ++ , NETCONN_TCP_NIP = NETCONN_TCP | NETCONN_TYPE_NIP /* 0x14 */ ++ , NETCONN_UDP_NIP = NETCONN_UDP | NETCONN_TYPE_NIP /* 0x24 */ ++ , NETCONN_UDPLITE_NIP = NETCONN_UDPLITE | NETCONN_TYPE_NIP /* 0x25 */ ++ , NETCONN_UDPNOCHKSUM_NIP = NETCONN_UDPNOCHKSUM | NETCONN_TYPE_NIP /* 0x26 */ ++ , NETCONN_RAW_NIP = NETCONN_RAW | NETCONN_TYPE_NIP /* 0x44 */ ++#endif }; /** Current state of the netconn. Non-TCP netconns are always -@@ -149,7 +155,10 @@ +@@ -149,7 +167,10 @@ NETCONN_WRITE, NETCONN_LISTEN, NETCONN_CONNECT, @@ -2837,7 +5900,15 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/api.h b/lwip-2.1.2/src/include/lwip/api. }; /** Used to inform the callback function about changes -@@ -226,9 +235,12 @@ +@@ -201,6 +222,7 @@ + #define NETCONN_DNS_IPV6 1 + #define NETCONN_DNS_IPV4_IPV6 2 /* try to resolve IPv4 first, try IPv6 if IPv4 fails only */ + #define NETCONN_DNS_IPV6_IPV4 3 /* try to resolve IPv6 first, try IPv4 if IPv6 fails only */ ++#define NETCONN_DNS_NIP 4 + #endif /* LWIP_DNS */ + + /* forward-declare some structs to avoid to include their headers */ +@@ -226,9 +248,12 @@ struct tcp_pcb *tcp; struct udp_pcb *udp; struct raw_pcb *raw; @@ -2851,7 +5922,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/api.h b/lwip-2.1.2/src/include/lwip/api. #if !LWIP_NETCONN_SEM_PER_THREAD /** sem that is used to synchronously execute functions in the core context */ sys_sem_t op_completed; -@@ -283,6 +295,13 @@ +@@ -283,6 +308,13 @@ #endif /* LWIP_TCP */ /** A callback function that is informed about events for this netconn */ netconn_callback callback; @@ -2865,7 +5936,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/api.h b/lwip-2.1.2/src/include/lwip/api. }; /** This vector type is passed to @ref netconn_write_vectors_partly to send -@@ -309,21 +328,38 @@ +@@ -309,21 +341,38 @@ * @param t @ref netconn_type */ #define netconn_new(t) netconn_new_with_proto_and_callback(t, 0, NULL) #define netconn_new_with_callback(t, c) netconn_new_with_proto_and_callback(t, 0, c) @@ -2907,8 +5978,8 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/api.h b/lwip-2.1.2/src/include/lwip/api. err_t netconn_connect(struct netconn *conn, const ip_addr_t *addr, u16_t port); err_t netconn_disconnect (struct netconn *conn); diff -Nur a/lwip-2.1.2/src/include/lwip/arch.h b/lwip-2.1.2/src/include/lwip/arch.h ---- a/lwip-2.1.2/src/include/lwip/arch.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/arch.h 2021-06-29 15:16:44.632898725 +0800 +--- a/lwip-2.1.2/src/include/lwip/arch.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/arch.h 2022-01-25 14:41:31.002502000 +0800 @@ -37,14 +37,7 @@ #ifndef LWIP_HDR_ARCH_H #define LWIP_HDR_ARCH_H @@ -2938,8 +6009,8 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/arch.h b/lwip-2.1.2/src/include/lwip/arc #define U16_F PRIu16 #endif diff -Nur a/lwip-2.1.2/src/include/lwip/err.h b/lwip-2.1.2/src/include/lwip/err.h ---- a/lwip-2.1.2/src/include/lwip/err.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/err.h 2021-06-29 15:16:44.636898726 +0800 +--- a/lwip-2.1.2/src/include/lwip/err.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/err.h 2022-01-25 14:41:31.014470000 +0800 @@ -85,9 +85,50 @@ /** Connection closed. */ ERR_CLSD = -15, @@ -2989,36 +6060,148 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/err.h b/lwip-2.1.2/src/include/lwip/err. +#define ERR_IS_FATAL(e) ((e) < ERR_FATAL_START) +#endif /* LWIP_LITEOS_COMPAT */ + - /** Define LWIP_ERR_T in cc.h if you want to use - * a different type for your platform (must be signed). */ - #ifdef LWIP_ERR_T -diff -Nur a/lwip-2.1.2/src/include/lwip/etharp.h b/lwip-2.1.2/src/include/lwip/etharp.h ---- a/lwip-2.1.2/src/include/lwip/etharp.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/etharp.h 2021-06-29 15:16:44.636898726 +0800 -@@ -46,6 +46,9 @@ - - #if LWIP_ARP || LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ - -+#if LWIP_LITEOS_COMPAT -+#include "arch/sys_arch.h" -+#endif /* LWIP_LITEOS_COMPAT */ - #include "lwip/pbuf.h" - #include "lwip/ip4_addr.h" - #include "lwip/netif.h" -@@ -63,6 +66,10 @@ - /** 1 seconds period */ - #define ARP_TMR_INTERVAL 1000 - -+#if LWIP_LITEOS_COMPAT -+#define ETHTYPE_ALL 0x0003U /* All packets */ -+#endif /* LWIP_LITEOS_COMPAT */ + /** Define LWIP_ERR_T in cc.h if you want to use + * a different type for your platform (must be signed). */ + #ifdef LWIP_ERR_T +diff -Nur a/lwip-2.1.2/src/include/lwip/etharp.h b/lwip-2.1.2/src/include/lwip/etharp.h +--- a/lwip-2.1.2/src/include/lwip/etharp.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/etharp.h 2022-01-25 14:41:31.023446000 +0800 +@@ -46,6 +46,9 @@ + + #if LWIP_ARP || LWIP_ETHERNET /* don't build if not configured for use in lwipopts.h */ + ++#if LWIP_LITEOS_COMPAT ++#include "arch/sys_arch.h" ++#endif /* LWIP_LITEOS_COMPAT */ + #include "lwip/pbuf.h" + #include "lwip/ip4_addr.h" + #include "lwip/netif.h" +@@ -63,6 +66,10 @@ + /** 1 seconds period */ + #define ARP_TMR_INTERVAL 1000 + ++#if LWIP_LITEOS_COMPAT ++#define ETHTYPE_ALL 0x0003U /* All packets */ ++#endif /* LWIP_LITEOS_COMPAT */ ++ + #if ARP_QUEUEING + /** struct for queueing outgoing packets for unknown address + * defined here to be accessed by memp.h +diff -Nur a/lwip-2.1.2/src/include/lwip/ethnip.h b/lwip-2.1.2/src/include/lwip/ethnip.h +--- a/lwip-2.1.2/src/include/lwip/ethnip.h 1970-01-01 07:00:00.000000000 +0700 ++++ b/lwip-2.1.2/src/include/lwip/ethnip.h 2022-02-17 15:57:43.915005000 +0800 +@@ -0,0 +1,108 @@ ++/** ++ * @file ++ * Ethernet output function - handles OUTGOING ethernet level traffic, implements ++ * ARP resolving. ++ * To be used in most low-level netif implementations ++ */ ++ ++/* ++ * Copyright (c) 2001-2003 Swedish Institute of Computer Science. ++ * Copyright (c) 2003-2004 Leon Woestenberg ++ * Copyright (c) 2003-2004 Axon Digital Design B.V., The Netherlands. ++ * 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 ++ * ++ */ ++ ++#ifndef LWIP_HDR_NETIF_ETHNIP_H ++#define LWIP_HDR_NETIF_ETHNIP_H ++ ++#include "lwip/opt.h" ++ ++#if LWIP_ARP && LWIP_ETHERNET && LWIP_NIP ++ ++#include "lwip/pbuf.h" ++#include "lwip/nip_addr.h" ++#include "lwip/netif.h" ++#include "lwip/nip.h" ++#include "lwip/prot/ethernet.h" ++err_t ethnip_output(struct netif *netif, struct pbuf *q, const nip_addr_t *ipaddr); ++ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/** 1 seconds period */ ++#define ARP_TMR_INTERVAL 1000 ++ ++#if ARP_QUEUEING ++/** struct for queueing outgoing packets for unknown address ++ * defined here to be accessed by memp.h ++ */ ++struct ethnip_q_entry { ++ struct ethnip_q_entry *next; ++ struct pbuf *p; ++}; ++#endif /* ARP_QUEUEING */ ++ ++#define ethnip_init() /* Compatibility define, no init needed. */ + - #if ARP_QUEUEING - /** struct for queueing outgoing packets for unknown address - * defined here to be accessed by memp.h ++int add_table_nip(nip_addr_t ipaddr, struct eth_addr ethaddr); ++void show_table_nip(void); ++int del_table_nip(nip_addr_t ipaddr); ++int set_table_nip(nip_addr_t ipaddr, struct eth_addr ethaddr); ++ ++void etharp_tmr(void); ++ssize_t ethnip_find_addr(struct netif *netif, const nip_addr_t *ipaddr, ++ struct eth_addr **eth_ret, const nip_addr_t **ip_ret); ++int ethnip_get_entry(size_t i, nip_addr_t **ipaddr, struct netif **netif, struct eth_addr **eth_ret); ++ ++err_t ethnip_query(struct netif *netif, const nip_addr_t *ipaddr, struct pbuf *q); ++err_t ethnip_request(struct netif *netif, const nip_addr_t *ipaddr); ++/** For Ethernet network interfaces, we might want to send "gratuitous ARP"; ++ * this is an ARP packet sent by a node in order to spontaneously cause other ++ * nodes to update an entry in their ARP cache. ++ * From RFC 3220 "IP Mobility Support for IPv4" section 4.6. */ ++#define ethnip_gratuitous(netif) etharp_request((netif), netif_nip_addr(netif)) ++void etharp_cleanup_netif(struct netif *netif); ++ ++#if ETHNIP_SUPPORT_STATIC_ENTRIES ++err_t ethnip_add_static_entry(const nip_addr_t *ipaddr, struct eth_addr *ethaddr); ++err_t ethnip_remove_static_entry(const nip_addr_t *ipaddr); ++#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */ ++ ++void ethnip_input(struct pbuf *p, struct netif *netif); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif ++ ++#endif /* LWIP_HDR_NETIF_ETHARP_H */ diff -Nur a/lwip-2.1.2/src/include/lwip/if_api.h b/lwip-2.1.2/src/include/lwip/if_api.h ---- a/lwip-2.1.2/src/include/lwip/if_api.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/if_api.h 2021-06-29 15:16:44.636898726 +0800 +--- a/lwip-2.1.2/src/include/lwip/if_api.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/if_api.h 2022-01-25 14:41:31.032422000 +0800 @@ -49,10 +49,12 @@ extern "C" { #endif @@ -3033,9 +6216,15 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/if_api.h b/lwip-2.1.2/src/include/lwip/i #if LWIP_COMPAT_SOCKETS #define if_indextoname(ifindex, ifname) lwip_if_indextoname(ifindex,ifname) diff -Nur a/lwip-2.1.2/src/include/lwip/inet.h b/lwip-2.1.2/src/include/lwip/inet.h ---- a/lwip-2.1.2/src/include/lwip/inet.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/inet.h 2021-06-29 15:16:44.636898726 +0800 -@@ -49,6 +49,7 @@ +--- a/lwip-2.1.2/src/include/lwip/inet.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/inet.h 2022-01-25 14:51:34.203256000 +0800 +@@ -44,11 +44,13 @@ + #include "lwip/def.h" + #include "lwip/ip_addr.h" + #include "lwip/ip6_addr.h" ++#include "lwip/nip_addr.h" + + #ifdef __cplusplus extern "C" { #endif @@ -3043,7 +6232,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/inet.h b/lwip-2.1.2/src/include/lwip/ine /* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED to prevent this code from redefining it. */ #if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) -@@ -82,8 +83,6 @@ +@@ -82,8 +84,6 @@ /** This macro can be used to initialize a variable of type struct in6_addr to the IPv6 loopback address. */ #define IN6ADDR_LOOPBACK_INIT {{{0,0,0,PP_HTONL(1)}}} @@ -3052,7 +6241,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/inet.h b/lwip-2.1.2/src/include/lwip/ine /* Definitions of the bits in an (IPv4) Internet address integer. -@@ -119,7 +118,12 @@ +@@ -119,7 +119,12 @@ #define IN_BADCLASS(a) IP_BADCLASS(a) #define IN_LOOPBACKNET IP_LOOPBACKNET @@ -3065,7 +6254,18 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/inet.h b/lwip-2.1.2/src/include/lwip/ine #ifndef INET_ADDRSTRLEN #define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX -@@ -136,14 +140,37 @@ +@@ -129,6 +134,10 @@ + #define INET6_ADDRSTRLEN IP6ADDR_STRLEN_MAX + #endif + #endif ++#if LWIP_NIP ++#define NINET_ADDRSTRLEN NIPADDR_STRLEN_MAX ++#endif ++ + + #if LWIP_IPV4 + +@@ -136,14 +145,37 @@ #define inet_addr_to_ip4addr(target_ipaddr, source_inaddr) (ip4_addr_set_u32(target_ipaddr, (source_inaddr)->s_addr)) /* directly map this to the lwip internal functions */ @@ -3104,7 +6304,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/inet.h b/lwip-2.1.2/src/include/lwip/ine #define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) {(target_in6addr)->un.u32_addr[0] = (source_ip6addr)->addr[0]; \ (target_in6addr)->un.u32_addr[1] = (source_ip6addr)->addr[1]; \ (target_in6addr)->un.u32_addr[2] = (source_ip6addr)->addr[2]; \ -@@ -153,7 +180,7 @@ +@@ -153,7 +185,7 @@ (target_ip6addr)->addr[2] = (source_in6addr)->un.u32_addr[2]; \ (target_ip6addr)->addr[3] = (source_in6addr)->un.u32_addr[3]; \ ip6_addr_clear_zone(target_ip6addr);} @@ -3113,10 +6313,87 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/inet.h b/lwip-2.1.2/src/include/lwip/ine /* directly map this to the lwip internal functions */ #define inet6_aton(cp, addr) ip6addr_aton(cp, (ip6_addr_t*)addr) #define inet6_ntoa(addr) ip6addr_ntoa((const ip6_addr_t*)&(addr)) +@@ -161,6 +193,10 @@ + + #endif /* LWIP_IPV6 */ + ++#if LWIP_NIP ++#define nin_addr_from_nipaddr(target_ninaddr, source_nipaddr) memcpy(target_ninaddr, source_nipaddr, sizeof(nip_addr_t)) /* ok? */ ++#define nin_addr_to_nipaddr(target_nipaddr, source_ninaddr) memcpy(target_nipaddr, source_ninaddr, sizeof(nip_addr_t)) ++#endif /* LWIP_NIP */ + + #ifdef __cplusplus + } diff -Nur a/lwip-2.1.2/src/include/lwip/ip_addr.h b/lwip-2.1.2/src/include/lwip/ip_addr.h ---- a/lwip-2.1.2/src/include/lwip/ip_addr.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/ip_addr.h 2021-06-29 15:16:44.636898726 +0800 -@@ -158,18 +158,31 @@ +--- a/lwip-2.1.2/src/include/lwip/ip_addr.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/ip_addr.h 2022-01-28 17:20:38.362712000 +0800 +@@ -42,6 +42,7 @@ + + #include "lwip/ip4_addr.h" + #include "lwip/ip6_addr.h" ++#include "lwip/nip_addr.h" + + #ifdef __cplusplus + extern "C" { +@@ -57,10 +58,55 @@ + /** IPv6 */ + IPADDR_TYPE_V6 = 6U, + /** IPv4+IPv6 ("dual-stack") */ +- IPADDR_TYPE_ANY = 46U ++ IPADDR_TYPE_ANY = 46U, ++ /** NIP */ ++ IPADDR_TYPE_NIP = 64U + }; + +-#if LWIP_IPV4 && LWIP_IPV6 ++#if LWIP_NIP ++/** @ingroup nipaddr ++ * Convert generic ip address to specific protocol version ++ */ ++typedef nip_addr_t ip_addr_t; ++#define IP_IS_V4_VAL(ipaddr) 0 ++#define IP_IS_V6_VAL(ipaddr) 0 ++#define IP_IS_NIP_VAL(ipaddr) 1 ++#define IP_IS_V4(ipaddr) 0 ++#define IP_IS_V6(ipaddr) 0 ++#define IP_IS_NIP(ipaddr) 1 ++#define IP_IS_ANY_TYPE_VAL(ipaddr) 0 ++#define IP_SET_TYPE_VAL(ipaddr, iptype) ++#define IP_SET_TYPE(ipaddr, iptype) ++#define IP_GET_TYPE(ipaddr) IPADDR_TYPE_NIP ++#define ip_2_nip(ipaddr) (ipaddr) ++#define ip_addr_copy(dest, src) nip_addr_copy(dest, src) ++#define ip_addr_copy_from_nip(dest, src) nip_addr_copy(dest, src) ++#define ip_addr_set(dest, src) nip_addr_set(dest, src) ++#define ip_addr_set_ipaddr(dest, src) nip_addr_set(dest, src) ++#define ip_addr_set_zero(ipaddr) nip_addr_set_zero(ipaddr) ++#define ip_addr_set_zero_nip(ipaddr) nip_addr_set_zero(ipaddr) ++#define ip_addr_set_any(is_ipv6, ipaddr) nip_addr_set_any(ipaddr) ++#define ip_addr_set_loopback(is_ipv6, ipaddr) nip_addr_set_loopback(ipaddr) ++#define ip_addr_set_hton(dest, src) nip_addr_set_hton(dest, src) ++#define ip_addr_netcmp(addr1, addr2, mask) 0 ++#define ip_addr_cmp(addr1, addr2) nip_addr_cmp(addr1, addr2) ++#define ip_addr_isany(ipaddr) nip_addr_isany(ipaddr) ++#define ip_addr_isany_val(ipaddr) nip_addr_isany_val(ipaddr) ++#define ip_addr_isloopback(ipaddr) nip_addr_isloopback(ipaddr) ++#define ip_addr_islinklocal(ipaddr) nip_addr_islinklocal(ipaddr) ++#define ip_addr_isbroadcast(addr, netif) 0 ++#define ip_addr_ismulticast(ipaddr) nip_addr_ismulticast(ipaddr) ++#define ip_addr_debug_print(debug, ipaddr) nip_addr_debug_print(debug, ipaddr) ++#define ip_addr_debug_print_val(debug, ipaddr) nip_addr_debug_print_val(debug, ipaddr) ++#define ipaddr_ntoa(ipaddr) nipaddr_ntoa(ipaddr) ++#define ipaddr_ntoa_r(ipaddr, buf, buflen) nipaddr_ntoa_r(ipaddr, buf, buflen) ++#define ipaddr_aton(cp, addr) nipaddr_aton(cp, addr) ++#define IP_ADDR_PCB_VERSION_MATCH(addr, pcb) 1 ++#define IP_ADDR_PCB_VERSION_MATCH_EXACT(pcb, ipaddr) 1 ++#define IPADDR_STRLEN_MAX NIPADDR_STRLEN_MAX ++ ++ ++#elif LWIP_IPV4 && LWIP_IPV6 + /** + * @ingroup ipaddr + * A union struct for both IP version's addresses. +@@ -158,18 +204,31 @@ /** @ingroup ipaddr */ #define ip_addr_set(dest, src) do{ IP_SET_TYPE(dest, IP_GET_TYPE(src)); if(IP_IS_V6(src)){ \ ip6_addr_set(ip_2_ip6(dest), ip_2_ip6(src)); }else{ \ @@ -3151,7 +6428,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/ip_addr.h b/lwip-2.1.2/src/include/lwip/ /** @ingroup ipaddr */ #define ip_addr_set_any(is_ipv6, ipaddr) do{if(is_ipv6){ \ ip6_addr_set_any(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }else{ \ -@@ -198,6 +211,11 @@ +@@ -198,6 +257,11 @@ #define ip_addr_netcmp(addr1, addr2, mask) ((IP_IS_V6(addr1) && IP_IS_V6(addr2)) ? \ 0 : \ ip4_addr_netcmp(ip_2_ip4(addr1), ip_2_ip4(addr2), mask)) @@ -3163,7 +6440,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/ip_addr.h b/lwip-2.1.2/src/include/lwip/ /** @ingroup ipaddr */ #define ip_addr_cmp(addr1, addr2) ((IP_GET_TYPE(addr1) != IP_GET_TYPE(addr2)) ? 0 : (IP_IS_V6_VAL(*(addr1)) ? \ ip6_addr_cmp(ip_2_ip6(addr1), ip_2_ip6(addr2)) : \ -@@ -218,26 +236,50 @@ +@@ -218,26 +282,50 @@ #define ip_addr_isbroadcast(ipaddr, netif) ((IP_IS_V6(ipaddr)) ? \ 0 : \ ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) @@ -3216,7 +6493,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/ip_addr.h b/lwip-2.1.2/src/include/lwip/ int ipaddr_aton(const char *cp, ip_addr_t *addr); /** @ingroup ipaddr */ -@@ -282,29 +324,43 @@ +@@ -282,29 +370,43 @@ #define ip_2_ip4(ipaddr) (ipaddr) #define IP_ADDR4(ipaddr,a,b,c,d) IP4_ADDR(ipaddr,a,b,c,d) @@ -3260,7 +6537,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/ip_addr.h b/lwip-2.1.2/src/include/lwip/ #define ipaddr_ntoa(ipaddr) ip4addr_ntoa(ipaddr) #define ipaddr_ntoa_r(ipaddr, buf, buflen) ip4addr_ntoa_r(ipaddr, buf, buflen) #define ipaddr_aton(cp, addr) ip4addr_aton(cp, addr) -@@ -335,24 +391,39 @@ +@@ -335,24 +437,39 @@ #define ip_addr_copy_from_ip6(dest, src) ip6_addr_copy(dest, src) #define ip_addr_copy_from_ip6_packed(dest, src) ip6_addr_copy_from_packed(dest, src) #define ip_addr_set(dest, src) ip6_addr_set(dest, src) @@ -3300,10 +6577,29 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/ip_addr.h b/lwip-2.1.2/src/include/lwip/ #define ipaddr_ntoa(ipaddr) ip6addr_ntoa(ipaddr) #define ipaddr_ntoa_r(ipaddr, buf, buflen) ip6addr_ntoa_r(ipaddr, buf, buflen) #define ipaddr_aton(cp, addr) ip6addr_aton(cp, addr) +@@ -424,6 +541,10 @@ + + #endif + ++#if LWIP_NIP ++extern const ip_addr_t nip_addr_any; ++#define IP_ADDR_ANY NIP_ADDR_ANY ++#endif + #if LWIP_IPV4 && LWIP_IPV6 + /** @ingroup ipaddr */ + #define IP_ANY_TYPE (&ip_addr_any_type) diff -Nur a/lwip-2.1.2/src/include/lwip/ip.h b/lwip-2.1.2/src/include/lwip/ip.h ---- a/lwip-2.1.2/src/include/lwip/ip.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/ip.h 2021-06-29 15:16:44.636898726 +0800 -@@ -99,7 +99,10 @@ +--- a/lwip-2.1.2/src/include/lwip/ip.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/ip.h 2022-01-25 14:51:24.422482000 +0800 +@@ -46,6 +46,7 @@ + #include "lwip/netif.h" + #include "lwip/ip4.h" + #include "lwip/ip6.h" ++#include "lwip/nip.h" + #include "lwip/prot/ip.h" + + #ifdef __cplusplus +@@ -99,7 +100,10 @@ #define SOF_REUSEADDR 0x04U /* allow local address reuse */ #define SOF_KEEPALIVE 0x08U /* keep connections alive */ #define SOF_BROADCAST 0x20U /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ @@ -3315,7 +6611,16 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/ip.h b/lwip-2.1.2/src/include/lwip/ip.h /* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ #define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE) -@@ -124,6 +127,13 @@ +@@ -118,12 +122,22 @@ + /** Header of the input IPv6 packet currently being processed. */ + struct ip6_hdr *current_ip6_header; + #endif /* LWIP_IPV6 */ ++#if LWIP_NIP ++ struct nip_hdr *current_nip_header; ++#endif /* LWIP_IPV6 */ + /** Total header length of current_ip4/6_header (i.e. after this, the UDP/TCP header starts) */ + u16_t current_ip_header_tot_len; + /** Source IP address of current_header */ ip_addr_t current_iphdr_src; /** Destination IP address of current_header */ ip_addr_t current_iphdr_dest; @@ -3329,11 +6634,58 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/ip.h b/lwip-2.1.2/src/include/lwip/ip.h }; extern struct ip_globals ip_data; -@@ -315,7 +325,22 @@ +@@ -206,7 +220,24 @@ + /** Destination IP6 address of current_header */ + #define ip6_current_dest_addr() (&ip_data.current_iphdr_dest) + +-#endif /* LWIP_IPV6 */ ++#elif LWIP_NIP /* LWIP_IPV6 */ ++ ++/** Get the NIP header of the current packet. ++ * This function must only be called from a receive callback (udp_recv, ++ * raw_recv, tcp_accept). It will return NULL otherwise. */ ++#define nip_current_header() ((const struct nip_hdr*)(ip_data.current_nip_header)) ++/** Always returns TRUE when only supporting IPv6 only */ ++#define ip_current_is_nip() 1 ++/** Get the transport layer protocol */ ++#define ip_current_header_proto() NIPH_NEXTH(nip_current_header()) ++/** Get the transport layer header */ ++#define ip_next_header_ptr() ((const void*)(((const u8_t*)nip_current_header()) + ip_current_header_tot_len())) ++/** Source NIP address of current_header */ ++#define nip_current_src_addr() (&ip_data.current_iphdr_src) ++/** Destination NIP address of current_header */ ++#define nip_current_dest_addr() (&ip_data.current_iphdr_dest) ++ ++#endif /* LWIP_NIP */ + + /** Union source address of current_header */ + #define ip_current_src_addr() (&ip_data.current_iphdr_src) +@@ -314,8 +345,43 @@ + #define ip_input ip6_input - #endif /* LWIP_IPV6 */ -- +-#endif /* LWIP_IPV6 */ ++#elif LWIP_NIP /* LWIP_IPV6 */ + ++#define ip_output(p, src, dest, ttl, tos, proto) \ ++ nip_output(p, src, dest, ttl, tos, proto) ++#define ip_output_if(p, src, dest, ttl, tos, proto, netif) \ ++ nip_output_if(p, src, dest, ttl, tos, proto, netif) ++#define ip_output_if_src(p, src, dest, ttl, tos, proto, netif) \ ++ nip_output_if_src(p, src, dest, ttl, tos, proto, netif) ++#define ip_output_hinted(p, src, dest, ttl, tos, proto, netif_hint) \ ++ nip_output_hinted(p, src, dest, ttl, tos, proto, netif_hint) ++#define ip_output_if_hdrincl(p, src, dest, netif) \ ++ nip_output_if(p, src, LWIP_IP_HDRINCL, 0, 0, 0, netif) ++#define ip_route(src, dest) \ ++ nip_route_src(src, dest) ++#define ip_netif_get_local_ip(netif, dest) \ ++ nip_netif_get_local_ip(netif) ++#define ip_debug_print(is_nip, p) nip_debug_print(p) ++ ++#define ip_input nip_input ++ ++#endif /* LWIP_NIP */ +#if LWIP_LITEOS_COMPAT +/** + * Defines the assumed maximum MTU on any interface for IP fragment buffer @@ -3354,8 +6706,8 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/ip.h b/lwip-2.1.2/src/include/lwip/ip.h (netif) = ip_route(src, dest); \ (ipaddr) = ip_netif_get_local_ip(netif, dest); \ diff -Nur a/lwip-2.1.2/src/include/lwip/netbuf.h b/lwip-2.1.2/src/include/lwip/netbuf.h ---- a/lwip-2.1.2/src/include/lwip/netbuf.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/netbuf.h 2021-06-29 15:16:44.636898726 +0800 +--- a/lwip-2.1.2/src/include/lwip/netbuf.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/netbuf.h 2022-01-25 14:41:31.073312000 +0800 @@ -55,13 +55,22 @@ #define NETBUF_FLAG_DESTADDR 0x01 /** This netbuf includes a checksum */ @@ -3401,8 +6753,8 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/netbuf.h b/lwip-2.1.2/src/include/lwip/n #define netbuf_destaddr(buf) (&((buf)->toaddr)) #define netbuf_set_destaddr(buf, destaddr) ip_addr_set(&((buf)->toaddr), destaddr) diff -Nur a/lwip-2.1.2/src/include/lwip/netdb.h b/lwip-2.1.2/src/include/lwip/netdb.h ---- a/lwip-2.1.2/src/include/lwip/netdb.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/netdb.h 2021-06-29 15:16:44.636898726 +0800 +--- a/lwip-2.1.2/src/include/lwip/netdb.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/netdb.h 2022-01-25 14:41:31.082288000 +0800 @@ -36,6 +36,10 @@ #include "lwip/opt.h" @@ -3479,8 +6831,8 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/netdb.h b/lwip-2.1.2/src/include/lwip/ne #ifdef __cplusplus } diff -Nur a/lwip-2.1.2/src/include/lwip/netifapi.h b/lwip-2.1.2/src/include/lwip/netifapi.h ---- a/lwip-2.1.2/src/include/lwip/netifapi.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/netifapi.h 2021-06-29 15:16:44.636898726 +0800 +--- a/lwip-2.1.2/src/include/lwip/netifapi.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/netifapi.h 2022-01-25 14:41:31.091294000 +0800 @@ -73,6 +73,30 @@ const ip4_addr_t *netmask, const ip4_addr_t *gw); #endif /* LWIP_IPV4*/ @@ -3513,8 +6865,8 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/netifapi.h b/lwip-2.1.2/src/include/lwip netifapi_errt_fn errtfunc); diff -Nur a/lwip-2.1.2/src/include/lwip/netif.h b/lwip-2.1.2/src/include/lwip/netif.h ---- a/lwip-2.1.2/src/include/lwip/netif.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/netif.h 2021-06-29 15:16:44.640898726 +0800 +--- a/lwip-2.1.2/src/include/lwip/netif.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/netif.h 2022-01-25 14:50:32.956072000 +0800 @@ -48,6 +48,7 @@ #include "lwip/def.h" #include "lwip/pbuf.h" @@ -3533,9 +6885,9 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/netif.h b/lwip-2.1.2/src/include/lwip/ne +#else +#define NETIF_NAMESIZE 16 +#endif -+ -+#define NETIF_LOOPBACK_MTU ((16 * 1024) + 20 + 20 + 12) ++#define NETIF_LOOPBACK_MTU ((16 * 1024) + 20 + 20 + 12) ++ +/** Type of link layer, these macros should be used for link_layer_type of struct netif */ +#define LOOPBACK_IF 772 +#define NETIF_MTU_MIN 1280 @@ -3560,7 +6912,27 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/netif.h b/lwip-2.1.2/src/include/lwip/ne /** * @} */ -@@ -223,6 +244,9 @@ +@@ -203,6 +224,19 @@ + const ip6_addr_t *ipaddr); + #endif /* LWIP_IPV6 */ + ++#if LWIP_NIP ++/** Function prototype for netif->output_ip6 functions. Called by lwIP when a packet ++ * shall be sent. For ethernet netif, set this to 'ethip6_output' and set ++ * 'linkoutput'. ++ * ++ * @param netif The netif which shall send a packet ++ * @param p The packet to send (p->payload points to IP header) ++ * @param ipaddr The IPv6 address to which the packet shall be sent ++ */ ++typedef err_t (*netif_output_nip_fn)(struct netif *netif, struct pbuf *p, ++ const nip_addr_t *ipaddr); ++#endif /* LWIP_NIP */ ++ + /** Function prototype for netif->linkoutput functions. Only used for ethernet + * netifs. This function is called by ARP when a packet shall be sent. + * +@@ -223,6 +257,9 @@ const ip6_addr_t *group, enum netif_mac_filter_action action); #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ @@ -3570,7 +6942,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/netif.h b/lwip-2.1.2/src/include/lwip/ne #if LWIP_DHCP || LWIP_AUTOIP || LWIP_IGMP || LWIP_IPV6_MLD || LWIP_IPV6_DHCP6 || (LWIP_NUM_NETIF_CLIENT_DATA > 0) #if LWIP_NUM_NETIF_CLIENT_DATA > 0 u8_t netif_alloc_client_data_id(void); -@@ -236,6 +260,10 @@ +@@ -236,6 +273,10 @@ */ #define netif_get_client_data(netif, id) (netif)->client_data[(id)] #endif @@ -3581,7 +6953,21 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/netif.h b/lwip-2.1.2/src/include/lwip/ne #if (LWIP_IPV4 && LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) || (LWIP_IPV6 && (LWIP_ND6_NUM_DESTINATIONS > 0x7f)) typedef u16_t netif_addr_idx_t; -@@ -321,12 +349,21 @@ +@@ -283,6 +324,13 @@ + u32_t ip6_addr_pref_life[LWIP_IPV6_NUM_ADDRESSES]; + #endif /* LWIP_IPV6_ADDRESS_LIFETIMES */ + #endif /* LWIP_IPV6 */ ++#if LWIP_NIP ++ /** IP address configuration in network byte order ? */ ++ ip_addr_t nip_addr; ++ ip_addr_t nip_gw; ++ netif_output_nip_fn output_nip; ++#endif /* LWIP_NIP */ ++ + /** This function is called by the network device driver + * to pass a packet up the TCP/IP stack. */ + netif_input_fn input; +@@ -321,12 +369,21 @@ /** This field can be set by the device driver and could point * to state information for the device. */ void *state; @@ -3604,7 +6990,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/netif.h b/lwip-2.1.2/src/include/lwip/ne #endif /* LWIP_NETIF_HOSTNAME */ #if LWIP_CHECKSUM_CTRL_PER_NETIF u16_t chksum_flags; -@@ -341,13 +378,19 @@ +@@ -341,13 +398,19 @@ u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; /** number of bytes used in hwaddr */ u8_t hwaddr_len; @@ -3627,7 +7013,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/netif.h b/lwip-2.1.2/src/include/lwip/ne #if LWIP_IPV6_AUTOCONFIG /** is this netif enabled for IPv6 autoconfiguration */ u8_t ip6_autoconfig_enabled; -@@ -387,6 +430,15 @@ +@@ -387,6 +450,15 @@ u16_t loop_cnt_current; #endif /* LWIP_LOOPBACK_MAX_PBUFS */ #endif /* ENABLE_LOOPBACK */ @@ -3643,7 +7029,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/netif.h b/lwip-2.1.2/src/include/lwip/ne }; #if LWIP_CHECKSUM_CTRL_PER_NETIF -@@ -407,9 +459,15 @@ +@@ -407,9 +479,15 @@ #endif /* LWIP_SINGLE_NETIF */ /** The default network interface. */ extern struct netif *netif_default; @@ -3660,7 +7046,16 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/netif.h b/lwip-2.1.2/src/include/lwip/ne struct netif *netif_add_noaddr(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input); #if LWIP_IPV4 -@@ -429,12 +487,17 @@ +@@ -418,6 +496,8 @@ + void *state, netif_init_fn init, netif_input_fn input); + void netif_set_addr(struct netif *netif, const ip4_addr_t *ipaddr, const ip4_addr_t *netmask, + const ip4_addr_t *gw); ++#elif LWIP_NIP ++struct netif *netif_add(struct netif *netif, const nip_addr_t *ipaddr, const nip_addr_t *gw, void *state, netif_init_fn init, netif_input_fn input); + #else /* LWIP_IPV4 */ + struct netif *netif_add(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input); + #endif /* LWIP_IPV4 */ +@@ -429,12 +509,25 @@ structure. */ struct netif *netif_find(const char *name); @@ -3670,6 +7065,14 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/netif.h b/lwip-2.1.2/src/include/lwip/ne +struct netif *netif_find_by_ifindex(u8_t ifindex); +u8_t netif_ipaddr_isbrdcast(const ip_addr_t *ipaddr); +err_t netif_set_default(struct netif *netif); ++ ++#if LWIP_NIP ++void netif_set_nipaddr(struct netif *netif, const nip_addr_t *ipaddr, const nip_addr_t *gw); ++int netif_do_set_nipgw(struct netif *netif, const nip_addr_t *gw, nip_addr_t *old_gw); ++#define netif_nip_addr(netif) ((const nip_addr_t*)ip_2_nip(&((netif)->nip_addr))) ++#define netif_ip_addr4(netif) ((const ip_addr_t*)&((netif)->ip_addr)) ++#define netif_nip_gw(netif) ((const nip_addr_t*)ip_2_nip(&((netif)->nip_gw))) ++#endif /* LWIP_NIP */ #if LWIP_IPV4 void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr); @@ -3679,7 +7082,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/netif.h b/lwip-2.1.2/src/include/lwip/ne /** @ingroup netif_ip4 */ #define netif_ip4_addr(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->ip_addr))) /** @ingroup netif_ip4 */ -@@ -455,6 +518,9 @@ +@@ -455,6 +548,9 @@ void netif_set_up(struct netif *netif); void netif_set_down(struct netif *netif); @@ -3689,7 +7092,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/netif.h b/lwip-2.1.2/src/include/lwip/ne /** @ingroup netif * Ask if an interface is up */ -@@ -512,6 +578,8 @@ +@@ -512,6 +608,8 @@ /** @ingroup netif_ip6 */ #define netif_ip6_addr(netif, i) ((const ip6_addr_t*)ip_2_ip6(&((netif)->ip6_addr[i]))) void netif_ip6_addr_set(struct netif *netif, s8_t addr_idx, const ip6_addr_t *addr6); @@ -3698,9 +7101,442 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/netif.h b/lwip-2.1.2/src/include/lwip/ne void netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3); #define netif_ip6_addr_state(netif, i) ((netif)->ip6_addr_state[i]) void netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state); +diff -Nur a/lwip-2.1.2/src/include/lwip/nip_addr.h b/lwip-2.1.2/src/include/lwip/nip_addr.h +--- a/lwip-2.1.2/src/include/lwip/nip_addr.h 1970-01-01 07:00:00.000000000 +0700 ++++ b/lwip-2.1.2/src/include/lwip/nip_addr.h 2022-02-17 15:53:51.276215000 +0800 +@@ -0,0 +1,220 @@ ++/** ++ * @file ++ * NewIP address API ++ */ ++ /* ++ * This file is part of the lwIP TCP/IP stack. ++ */ ++/* ++* This file is added to describe the struction of NewIP. ++*/ ++ ++#ifndef LWIP_HDR_NIP_ADDR_H ++#define LWIP_HDR_NIP_ADDR_H ++ ++#include "lwip/opt.h" ++#if LWIP_NIP ++#include "lwip/def.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* ++ * newIP address field ++ */ ++struct nip_addr_field { ++ union { ++ u8_t u8[16]; ++ u16_t u16[8]; ++ u32_t u32[4]; ++ } u; ++}; ++ ++/* ++ * newIP topology address ++ */ ++struct nip_top_addr{ ++ u8_t bitlen; // address bitlength ++ u8_t resv; ++ u16_t resv2; ++ struct nip_addr_field v; ++}; ++ ++/* ++ * level address include topology address and non topology address, such as service ID ++ */ ++struct nip_level_addr{ ++ u8_t type; ++ u8_t recv; ++ u16_t recv2; ++ union { ++ struct nip_top_addr top_addr; ++ struct nip_addr_field field; ++ }u; ++}; ++ ++#define nip_addr_bitlen u.top_addr.bitlen ++#define nip_addr_field8 u.top_addr.v.u.u8 ++#define nip_addr_field16 u.top_addr.v.u.u16 ++#define nip_addr_field32 u.top_addr.v.u.u32 ++#define NS_INT16SZ (u16_t)2 ++ ++#define NEWIP_LEVEL_MAX 4 ++/* ++ * newIP address structure ++ */ ++struct nip_addr { ++ u8_t level_num; // address level num ++ struct nip_level_addr laddrs[NEWIP_LEVEL_MAX]; ++}; ++typedef struct nip_addr nip_addr_t; ++ ++/* ++ *newIP network address structure ++ *The currently defined name is in dispute ++ */ ++/* struct sockaddr_nin moved to sockets.h, wxf 0118 ++ ++*/ ++ ++/* ++ * general LV data structure ++ */ ++typedef struct nip_lvgen { ++ u8_t bitlen; ++ u8_t resv; ++ u16_t resv2; ++} nip_lvgen_t; ++ ++typedef struct nip_lv16 { ++ u8_t bitlen; ++ u8_t resv; ++ union { ++ u8_t u8[2]; ++ u16_t u16[1]; ++ } v; ++} nip_lv16_t; ++ ++typedef struct nip_lv32 { ++ u8_t bitlen; ++ u8_t resv; ++ u16_t resv2; ++ union { ++ u8_t u8[4]; ++ u16_t u16[2]; ++ u32_t u32[1]; ++ } v; ++} nip_lv32_t; ++ ++typedef struct nip_lv64 { ++ u8_t bitlen; ++ u8_t resv; ++ u16_t resv2; ++ union { ++ u8_t u8[8]; ++ u16_t u16[4]; ++ u32_t u32[2]; ++ }v; ++} nip_lv64_t; ++ ++typedef struct nip_lv128 { ++ u8_t bitlen; ++ u8_t resv; ++ u16_t resv2; ++ union { ++ u8_t u8[16]; ++ u16_t u16[8]; ++ u32_t u32[4]; ++ } v; ++} nip_lv128_t; ++ ++/* Forward declaration to not include netif.h */ ++struct netif; ++ ++/* used for initializing a 4-level nip loopback addr. */ ++#define NIP_LOOPBACK_ADDR_LEVEL4_INIT { \ ++ .level_num = 1, \ ++ .laddrs = { \ ++ { \ ++ .type = 1, \ ++ .u = { \ ++ .top_addr = { \ ++ .bitlen = 32,\ ++ .v = { { { 0x0, 0x0, 0x0, 0x1 } } } \ ++ } \ ++ } \ ++ }, \ ++ {}, \ ++ {}, \ ++ {}\ ++ }\ ++} ++extern nip_addr_t nip_loopback_addr; ++#define NIPADDR_LOOPBACK &nip_loopback_addr ++ ++/** define ANY address*/ ++#define NIP_ANY_ADDR_LEVEL4_INIT { \ ++ .level_num = 1, \ ++ .laddrs = { \ ++ { \ ++ .type = 1, \ ++ .u = { \ ++ .top_addr = { \ ++ .bitlen = 32,\ ++ .v = { { { 0x0, 0x0, 0x0, 0x0 } } } \ ++ } \ ++ } \ ++ }, \ ++ {}, \ ++ {}, \ ++ {}\ ++ }\ ++} ++ ++extern nip_addr_t nip_any_addr; ++#define NIP_ADDR_ANY &nip_any_addr ++#define nip_addr_set(dest_addr, src_addr) if((src_addr) == NULL){\ ++ memset(dest_addr, 0, sizeof(*src_addr)); }\ ++ else {\ ++ memcpy(dest_addr, src_addr, sizeof(*src_addr));} ++#define nip_addr_copy(dest, src) (memcpy(&dest, &src, sizeof(src))) ++#define nip_addr_set_zero(ipaddr) (memset(ipaddr, 0, NIPADDR_STRLEN_MAX)) ++#define nip_addr_set_any(ipaddr) (memcpy(ipaddr, &nip_any_addr, sizeof(nip_addr_t))) ++#define nip_addr_set_loopback(ipaddr) (memcpy(ipaddr, &nip_loopback_addr, sizeof(nip_addr_t))) ++#define nip_addr_set_hton(dest, src) if((src) == NULL){\ ++ memset(dest_addr, 0, sizeof(*src_addr)); }\ ++ else {\ ++ memcpy(dest_addr, reverse_nip_order(src), sizeof(*src_addr));} ++#define nip_addr_cmp(addr1, addr2) nipaddr_cmp(addr1, addr2) ++#define nip_addr_isany_val(ipaddr) nipaddr_cmp(&ipaddr, &nip_any_addr) ++#define nip_addr_isany(ipaddr) ((ipaddr == NULL || nip_addr_isany_val(*ipaddr))) ++#define nip_addr_isloopback(ipaddr) nipaddr_cmp(ipaddr, &nip_loopback_addr) ++#define nip_addr_islinklocal(ipaddr) 0 ++#define nip_addr_ismulticast(ipaddr) 0 ++#define nip_addr_isbroadcast(ipaddr, netif) 0 ++#define nip_addr_debug_print_parts(debug,s) LWIP_DEBUGF(debug, ("%s", nipaddr_print((nip_addr_t *)s))) ++#define nip_addr_debug_print(debug, ipaddr) nip_addr_debug_print_parts(debug, ipaddr) ++#define nip_addr_debug_print_val(debug, ipaddr) nip_addr_debug_print_parts(debug, &ipaddr) ++ ++#define nip_addr_get_ladder(ipaddr, idx) (idx > ipaddr.level_num ? \ ++ NULL:((struct nip_level_addr)(ipaddr.laddrs[idx]))) ++ ++ ++#define NIPADDR_STRLEN_MAX 100 ++int nipaddr_cmp(const nip_addr_t *a1,const nip_addr_t *a2); ++struct nip_addr *reverse_nip_order(nip_addr_t *addr); ++int hex_digit_value (char ch); ++char *nipaddr_ntoa(const nip_addr_t *addr); ++char *nipaddr_ntoa_r(const nip_addr_t *addr, char *buf, int buflen); ++int set_newip_level(char *cp, struct nip_addr *addr); ++int nipaddr_aton(const char *cp, struct nip_addr *addr); ++int nipaddr_aton2(const char *cp,const char *cp2, struct nip_addr *addr); ++int nipaddr_aton_r(const char *src, const char *src_endp, int len, struct nip_addr_field *dst); ++ ++char *nipaddr_print(const nip_addr_t *addr); ++#ifdef __cplusplus ++} ++#endif ++#endif ++#endif /* LWIP_HDR_NIP_ADDR_H */ +\ 文件尾没有换行符 +diff -Nur a/lwip-2.1.2/src/include/lwip/nip_frag.h b/lwip-2.1.2/src/include/lwip/nip_frag.h +--- a/lwip-2.1.2/src/include/lwip/nip_frag.h 1970-01-01 07:00:00.000000000 +0700 ++++ b/lwip-2.1.2/src/include/lwip/nip_frag.h 2022-02-17 15:53:18.346311000 +0800 +@@ -0,0 +1,101 @@ ++/** ++ * @file ++ * IP fragmentation/reassembly ++ */ ++ ++/* ++ * 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: Jani Monoses ++ * ++ */ ++ ++#ifndef LWIP_HDR_NIP_FRAG_H ++#define LWIP_HDR_NIP_FRAG_H ++ ++#include "lwip/opt.h" ++#if LWIP_NIP ++#include "lwip/err.h" ++#include "lwip/pbuf.h" ++#include "lwip/netif.h" ++#include "lwip/nip_addr.h" ++#include "lwip/nip.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++#define NIP_LEN 1 ++#define NIP_VALUE 2 ++void *location_niphdr(u8_t len_or_value, u8_t type, void* niphdr); ++#if NIP_REASSEMBLY ++/* The NIP reassembly timer interval in milliseconds. */ ++#define NIP_TMR_INTERVAL 1000 ++ ++/** NIP reassembly helper struct. ++ * This is exported because memp needs to know the size. ++ */ ++struct nip_reassdata { ++ struct nip_reassdata *next; ++ struct pbuf *p; ++ u8_t niphdr[255]; ++ u16_t datagram_len; ++ u8_t flags; ++ u8_t timer; ++}; ++u8_t number_of_zeros(void* fraghdr, u16_t hlen); ++void nip_reass_init(void); ++void nip_reass_tmr(void); ++struct pbuf * nip_reass(struct pbuf *p); ++#endif /* NIP_REASSEMBLY */ ++ ++#if NIP_FRAG ++#if !LWIP_NETIF_TX_SINGLE_PBUF ++#ifndef LWIP_PBUF_CUSTOM_REF_DEFINED ++#define LWIP_PBUF_CUSTOM_REF_DEFINED ++/** A custom pbuf that holds a reference to another pbuf, which is freed ++ * when this custom pbuf is freed. This is used to create a custom PBUF_REF ++ * that points into the original pbuf. */ ++struct pbuf_custom_ref { ++ /** base class */ ++ struct pbuf_custom pc; ++ /** pointer to the original pbuf that is referenced */ ++ struct pbuf *original; ++}; ++#endif /* LWIP_PBUF_CUSTOM_REF_DEFINED */ ++#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ ++ ++err_t nip_frag(struct pbuf *p, struct netif *netif, const nip_addr_t *dest, u8_t zeros); ++#endif /* NIP_FRAG */ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LWIP_NIP */ ++ ++#endif /* LWIP_HDR_NIP_FRAG_H */ +diff -Nur a/lwip-2.1.2/src/include/lwip/nip.h b/lwip-2.1.2/src/include/lwip/nip.h +--- a/lwip-2.1.2/src/include/lwip/nip.h 1970-01-01 07:00:00.000000000 +0700 ++++ b/lwip-2.1.2/src/include/lwip/nip.h 2022-02-17 15:54:31.059640000 +0800 +@@ -0,0 +1,99 @@ ++#ifndef LWIP_HDR_NIP_H ++#define LWIP_HDR_NIP_H ++ ++#include "lwip/opt.h" ++#if LWIP_NIP ++#include "lwip/def.h" ++#include "lwip/pbuf.h" ++#include "lwip/nip_addr.h" ++#include "lwip/err.h" ++#include "lwip/netif.h" ++ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++struct netif *nip_route(const nip_addr_t *dest); ++err_t nip_input(struct pbuf *p, struct netif *inp); ++#define nip_route_src(src, dest) nip_route(dest) ++#define nip_netif_get_local_ip(netif) (((netif) != NULL) ? netif_nip_addr(netif) : NULL) ++ ++err_t nip_output(struct pbuf *p, const nip_addr_t *src, const nip_addr_t *dest, ++ u8_t ttl, u8_t tos, u8_t proto); ++err_t nip_output_if(struct pbuf *p, const nip_addr_t *src, const nip_addr_t *dest, ++ u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); ++err_t nip_output_if_src(struct pbuf *p, const nip_addr_t *src, const nip_addr_t *dest, ++ u8_t ttl, u8_t tos, u8_t proto, struct netif *netif); ++u8_t* build_tlv(u8_t type, u8_t len, u8_t *value, u8_t *buf); ++u8_t* build_nip_addr(u8_t type, const nip_addr_t *addr, u8_t *buf); ++ ++u8_t get_nip_hdrlen(struct pbuf *buf); ++u8_t * decode_tlv(u8_t * buf, u8_t tlen, u8_t * value); ++u8_t * decode_tlv2(u8_t * buf, u8_t tlen, u16_t * value); ++u8_t * decode_nip_addr(u8_t *buf, u8_t tlen, ip_addr_t *addr); ++ ++#ifdef PACK_STRUCT_USE_INCLUDES ++# include "arch/bpstruct.h" ++#endif ++PACK_STRUCT_BEGIN ++struct nip_addr_packed { ++ PACK_STRUCT_FIELD(nip_addr_t addr); ++} PACK_STRUCT_STRUCT; ++PACK_STRUCT_END ++#ifdef PACK_STRUCT_USE_INCLUDES ++# include "arch/epstruct.h" ++#endif ++typedef struct nip_addr_packed nip_addr_p_t; ++ ++#ifdef PACK_STRUCT_USE_INCLUDES ++# include "arch/bpstruct.h" ++#endif ++ ++/* The nip header */ ++struct nip_hdr { ++ /* version / header length */ ++ PACK_STRUCT_FLD_8(u8_t _v_hl); ++ /* total length */ ++ PACK_STRUCT_FIELD(u16_t _len); ++ /* identification */ ++ PACK_STRUCT_FIELD(u16_t _id); ++ /* fragment offset field */ ++ PACK_STRUCT_FIELD(u16_t _offset); ++#define IP_RF 0x8000U /* reserved fragment flag */ ++#define IP_DF 0x4000U /* don't fragment flag */ ++#define IP_MF 0x2000U /* more fragments flag */ ++#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */ ++ /* time to live */ ++ PACK_STRUCT_FLD_8(u8_t _ttl); ++ /** next header */ ++ PACK_STRUCT_FLD_8(u8_t _nexth); ++ /* protocol*/ ++ PACK_STRUCT_FLD_8(u8_t _proto); ++ /* source and destination IP addresses */ ++ PACK_STRUCT_FLD_S(nip_addr_p_t src); ++ PACK_STRUCT_FLD_S(nip_addr_p_t dest); ++}; ++ ++#ifdef PACK_STRUCT_USE_INCLUDES ++# include "arch/epstruct.h" ++#endif ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#define NIP_FIELDTYPE_TTL 5 ++#define NIP_FIELDTYPE_NEXTHEADER 11 ++#define NIP_FIELDTYPE_SADDR 1 ++#define NIP_FIELDTYPE_DADDR 2 ++#define NIP_FIELDTYPE_HEADERLEN 10 ++#define NIP_FIELDTYPE_TOTALLEN 9 ++#define NIP_FIELDTYPE_FRAG 8 ++ ++#define NIP_ADDRLEN_MAX 128 ++ ++#endif ++#endif /* LWIP_HDR_NIP_H */ ++ ++ diff -Nur a/lwip-2.1.2/src/include/lwip/opt.h b/lwip-2.1.2/src/include/lwip/opt.h ---- a/lwip-2.1.2/src/include/lwip/opt.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/opt.h 2021-06-29 15:16:44.636898726 +0800 +--- a/lwip-2.1.2/src/include/lwip/opt.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/opt.h 2022-01-25 14:49:55.998715000 +0800 @@ -529,7 +529,7 @@ * (only needed if you use the sequential API, like api_lib.c) */ @@ -3710,10 +7546,79 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/opt.h b/lwip-2.1.2/src/include/lwip/opt. #endif /** +@@ -636,6 +636,9 @@ + #define ARP_TABLE_SIZE 10 + #endif + ++#if !defined NIPARP_TABLE_SIZE || defined __DOXYGEN__ ++#define NIPARP_TABLE_SIZE 10 ++#endif + /** the time an ARP entry stays valid after its last update, + * for ARP_TMR_INTERVAL = 1000, this is + * (60 * 5) seconds = 5 minutes. +@@ -2224,6 +2227,14 @@ + #endif + + /** ++ * NIP_FRAG_STATS==1: Enable IP fragmentation stats. Default is ++ * on if using either frag or reass. ++ */ ++#if !defined NIP_FRAG_STATS || defined __DOXYGEN__ ++#define NIP_FRAG_STATS (LWIP_NIP && (NIP_REASSEMBLY || NIP_FRAG)) ++#endif ++ ++/** + * MIB2_STATS==1: Stats for SNMP MIB2. + */ + #if !defined MIB2_STATS || defined __DOXYGEN__ +@@ -2358,6 +2369,20 @@ + + /* + --------------------------------------- ++ ---------- NIP options --------------- ++ --------------------------------------- ++*/ ++/** ++ * NIP_REASS_MAXAGE: Maximum time (in multiples of NIP_REASS_TMR_INTERVAL - so seconds, normally) ++ * a fragmented IP packet waits for all fragments to arrive. If not all fragments arrived ++ * in this time, the whole packet is discarded. ++ */ ++#if !defined NIP_REASS_MAXAGE || defined __DOXYGEN__ ++#define NIP_REASS_MAXAGE 15 ++#endif ++ ++/* ++ --------------------------------------- + ---------- IPv6 options --------------- + --------------------------------------- + */ +@@ -3260,6 +3285,11 @@ + #define ETHARP_DEBUG LWIP_DBG_OFF + #endif + ++#if !defined ETHNIP_DEBUG || defined __DOXYGEN__ ++#define ETHNIP_DEBUG LWIP_DBG_OFF ++#endif ++ ++ + /** + * NETIF_DEBUG: Enable debugging in netif.c. + */ diff -Nur a/lwip-2.1.2/src/include/lwip/pbuf.h b/lwip-2.1.2/src/include/lwip/pbuf.h ---- a/lwip-2.1.2/src/include/lwip/pbuf.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/pbuf.h 2021-06-29 15:16:44.636898726 +0800 -@@ -181,7 +181,10 @@ +--- a/lwip-2.1.2/src/include/lwip/pbuf.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/pbuf.h 2022-01-25 14:49:31.170855000 +0800 +@@ -78,7 +78,9 @@ + #define PBUF_TRANSPORT_HLEN 20 + #if LWIP_IPV6 + #define PBUF_IP_HLEN 40 +-#else ++#elif LWIP_NIP ++#define PBUF_IP_HLEN 80 ++#elif LWIP_IPV4 + #define PBUF_IP_HLEN 20 + #endif + +@@ -181,7 +183,10 @@ #define PBUF_FLAG_LLMCAST 0x10U /** indicates this pbuf includes a TCP FIN flag */ #define PBUF_FLAG_TCP_FIN 0x20U @@ -3726,8 +7631,8 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/pbuf.h b/lwip-2.1.2/src/include/lwip/pbu struct pbuf { /** next pbuf in singly linked pbuf chain */ diff -Nur a/lwip-2.1.2/src/include/lwip/priv/api_msg.h b/lwip-2.1.2/src/include/lwip/priv/api_msg.h ---- a/lwip-2.1.2/src/include/lwip/priv/api_msg.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/priv/api_msg.h 2021-06-29 15:16:44.636898726 +0800 +--- a/lwip-2.1.2/src/include/lwip/priv/api_msg.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/priv/api_msg.h 2022-01-25 14:41:31.132154000 +0800 @@ -46,6 +46,7 @@ #include "lwip/igmp.h" #include "lwip/api.h" @@ -3827,8 +7732,8 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/priv/api_msg.h b/lwip-2.1.2/src/include/ netifapi_void_fn voidfunc; netifapi_errt_fn errtfunc; diff -Nur a/lwip-2.1.2/src/include/lwip/priv/sockets_priv.h b/lwip-2.1.2/src/include/lwip/priv/sockets_priv.h ---- a/lwip-2.1.2/src/include/lwip/priv/sockets_priv.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/priv/sockets_priv.h 2021-06-29 15:16:44.636898726 +0800 +--- a/lwip-2.1.2/src/include/lwip/priv/sockets_priv.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/priv/sockets_priv.h 2022-01-25 14:41:31.140132000 +0800 @@ -49,7 +49,6 @@ extern "C" { #endif @@ -3857,8 +7762,8 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/priv/sockets_priv.h b/lwip-2.1.2/src/inc struct pollfd *poll_fds; /** nfds passed to poll; 0 if select */ diff -Nur a/lwip-2.1.2/src/include/lwip/prot/icmp6.h b/lwip-2.1.2/src/include/lwip/prot/icmp6.h ---- a/lwip-2.1.2/src/include/lwip/prot/icmp6.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/prot/icmp6.h 2021-06-29 15:16:44.636898726 +0800 +--- a/lwip-2.1.2/src/include/lwip/prot/icmp6.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/prot/icmp6.h 2022-01-25 14:41:31.149109000 +0800 @@ -135,7 +135,7 @@ # include "arch/bpstruct.h" #endif @@ -3868,9 +7773,23 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/prot/icmp6.h b/lwip-2.1.2/src/include/lw PACK_STRUCT_FLD_8(u8_t type); PACK_STRUCT_FLD_8(u8_t code); PACK_STRUCT_FIELD(u16_t chksum); +diff -Nur a/lwip-2.1.2/src/include/lwip/prot/ieee.h b/lwip-2.1.2/src/include/lwip/prot/ieee.h +--- a/lwip-2.1.2/src/include/lwip/prot/ieee.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/prot/ieee.h 2022-01-25 14:47:58.119229000 +0800 +@@ -81,7 +81,9 @@ + /** Precision time protocol */ + ETHTYPE_PTP = 0x88F7U, + /** Q-in-Q, 802.1ad */ +- ETHTYPE_QINQ = 0x9100U ++ ETHTYPE_QINQ = 0x9100U, ++ /** HUAWEI NewIP */ ++ ETHTYPE_NIP = 0xEADDU + }; + + #ifdef __cplusplus diff -Nur a/lwip-2.1.2/src/include/lwip/prot/ip4.h b/lwip-2.1.2/src/include/lwip/prot/ip4.h ---- a/lwip-2.1.2/src/include/lwip/prot/ip4.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/prot/ip4.h 2021-06-29 15:16:44.636898726 +0800 +--- a/lwip-2.1.2/src/include/lwip/prot/ip4.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/prot/ip4.h 2022-01-25 14:41:31.157088000 +0800 @@ -39,6 +39,9 @@ #include "lwip/arch.h" @@ -3894,9 +7813,99 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/prot/ip4.h b/lwip-2.1.2/src/include/lwip /* time to live */ PACK_STRUCT_FLD_8(u8_t _ttl); /* protocol*/ +diff -Nur a/lwip-2.1.2/src/include/lwip/prot/nip.h b/lwip-2.1.2/src/include/lwip/prot/nip.h +--- a/lwip-2.1.2/src/include/lwip/prot/nip.h 1970-01-01 07:00:00.000000000 +0700 ++++ b/lwip-2.1.2/src/include/lwip/prot/nip.h 2022-01-20 19:29:23.078369000 +0800 +@@ -0,0 +1,86 @@ ++#ifndef LWIP_HDR_PROT_NIP_H ++#define LWIP_HDR_PROT_NIP_H ++ ++#include "lwip/arch.h" ++#include "lwip/nip_addr.h" ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++ ++#ifdef PACK_STRUCT_USE_INCLUDES ++# include "arch/bpstruct.h" ++#endif ++ ++#ifdef PACK_STRUCT_USE_INCLUDES ++# include "arch/epstruct.h" ++#endif ++ ++typedef struct nip_addr_packed nip_addr_p_t; ++ ++ ++#ifdef PACK_STRUCT_USE_INCLUDES ++# include "arch/bpstruct.h" ++#endif ++PACK_STRUCT_BEGIN ++/* The nip header */ ++struct nip_hdr { ++ /* version / header length */ ++ PACK_STRUCT_FLD_8(u8_t _v_hl); ++ /* type of service */ ++ PACK_STRUCT_FLD_8(u8_t _tos); ++ /* total length */ ++ PACK_STRUCT_FIELD(u16_t _len); ++ /* identification */ ++ PACK_STRUCT_FIELD(u16_t _id); ++ /* fragment offset field */ ++ PACK_STRUCT_FIELD(u16_t _offset); ++#define IP_RF 0x8000U /* reserved fragment flag */ ++#define IP_DF 0x4000U /* don't fragment flag */ ++#define IP_MF 0x2000U /* more fragments flag */ ++#define IP_OFFMASK 0x1fffU /* mask for fragmenting bits */ ++ /* time to live */ ++ PACK_STRUCT_FLD_8(u8_t _ttl); ++ /* protocol*/ ++ PACK_STRUCT_FLD_8(u8_t _proto); ++ /* checksum */ ++ PACK_STRUCT_FIELD(u16_t _chksum); ++ /* source and destination IP addresses */ ++ PACK_STRUCT_FLD_S(ip4_addr_p_t src); ++ PACK_STRUCT_FLD_S(ip4_addr_p_t dest); ++} PACK_STRUCT_STRUCT; ++PACK_STRUCT_END ++#ifdef PACK_STRUCT_USE_INCLUDES ++# include "arch/epstruct.h" ++#endif ++ ++/* Macros to get struct ip_hdr fields: */ ++#define IPH_V(hdr) ((hdr)->_v_hl >> 4) ++#define IPH_HL(hdr) ((hdr)->_v_hl & 0x0f) ++#define IPH_HL_BYTES(hdr) ((u8_t)(IPH_HL(hdr) * 4)) ++#define IPH_TOS(hdr) ((hdr)->_tos) ++#define IPH_LEN(hdr) ((hdr)->_len) ++#define IPH_ID(hdr) ((hdr)->_id) ++#define IPH_OFFSET(hdr) ((hdr)->_offset) ++#define IPH_OFFSET_BYTES(hdr) ((u16_t)((lwip_ntohs(IPH_OFFSET(hdr)) & IP_OFFMASK) * 8U)) ++#define IPH_TTL(hdr) ((hdr)->_ttl) ++#define IPH_PROTO(hdr) ((hdr)->_proto) ++#define IPH_CHKSUM(hdr) ((hdr)->_chksum) ++ ++/* Macros to set struct ip_hdr fields: */ ++#define IPH_VHL_SET(hdr, v, hl) (hdr)->_v_hl = (u8_t)((((v) << 4) | (hl))) ++#define IPH_TOS_SET(hdr, tos) (hdr)->_tos = (tos) ++#define IPH_LEN_SET(hdr, len) (hdr)->_len = (len) ++#define IPH_ID_SET(hdr, id) (hdr)->_id = (id) ++#define IPH_OFFSET_SET(hdr, off) (hdr)->_offset = (off) ++#define IPH_TTL_SET(hdr, ttl) (hdr)->_ttl = (u8_t)(ttl) ++#define IPH_PROTO_SET(hdr, proto) (hdr)->_proto = (u8_t)(proto) ++#define IPH_CHKSUM_SET(hdr, chksum) (hdr)->_chksum = (chksum) ++ ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* LWIP_HDR_PROT_NIP_H */ diff -Nur a/lwip-2.1.2/src/include/lwip/raw.h b/lwip-2.1.2/src/include/lwip/raw.h ---- a/lwip-2.1.2/src/include/lwip/raw.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/raw.h 2021-06-29 15:16:44.640898726 +0800 +--- a/lwip-2.1.2/src/include/lwip/raw.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/raw.h 2022-01-25 14:41:31.167061000 +0800 @@ -47,6 +47,8 @@ #include "lwip/ip.h" #include "lwip/ip_addr.h" @@ -3962,9 +7971,9 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/raw.h b/lwip-2.1.2/src/include/lwip/raw. #define raw_setflags(pcb,f) ((pcb)->flags = (f)) diff -Nur a/lwip-2.1.2/src/include/lwip/sockets.h b/lwip-2.1.2/src/include/lwip/sockets.h ---- a/lwip-2.1.2/src/include/lwip/sockets.h 2021-06-29 15:16:18.808893323 +0800 -+++ b/lwip-2.1.2/src/include/lwip/sockets.h 2021-06-29 15:16:44.636898726 +0800 -@@ -51,10 +51,18 @@ +--- a/lwip-2.1.2/src/include/lwip/sockets.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/sockets.h 2022-01-26 16:48:37.175637000 +0800 +@@ -51,10 +51,26 @@ #include @@ -3978,12 +7987,31 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/sockets.h b/lwip-2.1.2/src/include/lwip/ #ifdef __cplusplus extern "C" { #endif - +- ++#if LWIP_NIP ++struct sockaddr_nin { ++ u8_t snin_len; /* length of this structure */ ++ sa_family_t snin_family; /* AF_INETNIP */ ++ in_port_t snin_port; /* Transport layer port # */ ++ struct nip_addr snin_addr; /* NIP address */ ++}; ++#define AF_NIP 46 ++#endif +#if !LWIP_LITEOS_COMPAT /* If your port already typedef's sa_family_t, define SA_FAMILY_T_DEFINED to prevent this code from redefining it. */ #if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED) -@@ -526,9 +534,43 @@ +@@ -103,6 +119,9 @@ + #if LWIP_IPV6 + u32_t s2_data3[3]; + #endif /* LWIP_IPV6 */ ++#if LWIP_NIP ++ u32_t s2_data4[4]; ++#endif /* LWIP_NIP */ + }; + + /* If your port already typedef's socklen_t, define SOCKLEN_T_DEFINED +@@ -526,9 +545,43 @@ #endif /* LWIP_TIMEVAL_PRIVATE */ #define lwip_socket_init() /* Compatibility define, no init needed. */ @@ -4027,7 +8055,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/sockets.h b/lwip-2.1.2/src/include/lwip/ #if LWIP_COMPAT_SOCKETS == 2 /* This helps code parsers/code completion by not having the COMPAT functions as defines */ #define lwip_accept accept -@@ -551,6 +593,9 @@ +@@ -551,6 +604,9 @@ #if LWIP_SOCKET_SELECT #define lwip_select select #endif @@ -4037,7 +8065,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/sockets.h b/lwip-2.1.2/src/include/lwip/ #if LWIP_SOCKET_POLL #define lwip_poll poll #endif -@@ -558,9 +603,18 @@ +@@ -558,9 +614,18 @@ #define lwip_inet_ntop inet_ntop #define lwip_inet_pton inet_pton @@ -4056,7 +8084,7 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/sockets.h b/lwip-2.1.2/src/include/lwip/ #define lwip_write write #define lwip_writev writev #undef lwip_close -@@ -682,7 +736,7 @@ +@@ -682,7 +747,7 @@ #ifdef __cplusplus } #endif @@ -4065,9 +8093,38 @@ diff -Nur a/lwip-2.1.2/src/include/lwip/sockets.h b/lwip-2.1.2/src/include/lwip/ #endif /* LWIP_SOCKET */ #endif /* LWIP_HDR_SOCKETS_H */ +diff -Nur a/lwip-2.1.2/src/include/lwip/stats.h b/lwip-2.1.2/src/include/lwip/stats.h +--- a/lwip-2.1.2/src/include/lwip/stats.h 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/stats.h 2022-01-25 14:48:13.934669000 +0800 +@@ -294,6 +294,10 @@ + /** Neighbor discovery */ + struct stats_proto nd6; + #endif ++#if NIP_FRAG_STATS ++ /** NIP fragmentation */ ++ struct stats_proto nip_frag; ++#endif + #if MIB2_STATS + /** SNMP MIB2 */ + struct stats_mib2 mib2; +@@ -461,6 +465,14 @@ + #define ND6_STATS_DISPLAY() + #endif + ++#if NIP_FRAG_STATS ++#define NIP_FRAG_STATS_INC(x) STATS_INC(x) ++#define NIP_FRAG_STATS_DISPLAY() ++#else ++#define NIP_FRAG_STATS_INC(x) ++#define NIP_FRAG_STATS_DISPLAY() ++#endif ++ + #if MIB2_STATS + #define MIB2_STATS_INC(x) STATS_INC(x) + #else diff -Nur a/lwip-2.1.2/src/include/netif/ifaddrs.h b/lwip-2.1.2/src/include/netif/ifaddrs.h ---- a/lwip-2.1.2/src/include/netif/ifaddrs.h 1970-01-01 08:00:00.000000000 +0800 -+++ b/lwip-2.1.2/src/include/netif/ifaddrs.h 2021-06-29 15:16:44.640898726 +0800 +--- a/lwip-2.1.2/src/include/netif/ifaddrs.h 1970-01-01 07:00:00.000000000 +0700 ++++ b/lwip-2.1.2/src/include/netif/ifaddrs.h 2022-01-25 14:41:31.184016000 +0800 @@ -0,0 +1,307 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved. @@ -4377,8 +8434,8 @@ diff -Nur a/lwip-2.1.2/src/include/netif/ifaddrs.h b/lwip-2.1.2/src/include/neti +#endif /* (LWIP_IPV4 || LWIP_IPV6) && LWIP_SOCKET */ +#endif /* __LWIP_IFADDRS_H */ diff -Nur a/lwip-2.1.2/src/netif/ethernet.c b/lwip-2.1.2/src/netif/ethernet.c ---- a/lwip-2.1.2/src/netif/ethernet.c 2021-06-29 15:16:18.812893324 +0800 -+++ b/lwip-2.1.2/src/netif/ethernet.c 2021-06-29 15:16:44.644898727 +0800 +--- a/lwip-2.1.2/src/netif/ethernet.c 2022-02-16 16:06:59.190115000 +0800 ++++ b/lwip-2.1.2/src/netif/ethernet.c 2022-01-25 14:47:40.196585000 +0800 @@ -48,7 +48,7 @@ #include "lwip/etharp.h" #include "lwip/ip.h" @@ -4388,6 +8445,15 @@ diff -Nur a/lwip-2.1.2/src/netif/ethernet.c b/lwip-2.1.2/src/netif/ethernet.c #include #include "netif/ppp/ppp_opts.h" +@@ -82,7 +82,7 @@ + { + struct eth_hdr *ethhdr; + u16_t type; +-#if LWIP_ARP || ETHARP_SUPPORT_VLAN || LWIP_IPV6 ++#if LWIP_ARP || ETHARP_SUPPORT_VLAN || LWIP_IPV6 || LWIP_NIP + u16_t next_hdr_offset = SIZEOF_ETH_HDR; + #endif /* LWIP_ARP || ETHARP_SUPPORT_VLAN */ + @@ -167,6 +167,12 @@ } } @@ -4401,3 +8467,37 @@ diff -Nur a/lwip-2.1.2/src/netif/ethernet.c b/lwip-2.1.2/src/netif/ethernet.c switch (type) { #if LWIP_IPV4 && LWIP_ARP /* IP packet? */ +@@ -231,6 +237,14 @@ + break; + #endif /* LWIP_IPV6 */ + ++#if LWIP_NIP ++ case PP_HTONS(ETHTYPE_NIP): /* LWIP_NIP */ ++ /* skip Ethernet header */ ++ pbuf_remove_header(p, next_hdr_offset); ++ nip_input(p, netif); ++ break; ++#endif /* LWIP_IPV6 */ ++ + default: + #ifdef LWIP_HOOK_UNKNOWN_ETH_PROTOCOL + if (LWIP_HOOK_UNKNOWN_ETH_PROTOCOL(p, netif) == ERR_OK) { +diff -Nur a/lwip-2.1.2/src/netif/slipif.c b/lwip-2.1.2/src/netif/slipif.c +--- a/lwip-2.1.2/src/netif/slipif.c 2022-02-16 16:06:59.198115000 +0800 ++++ b/lwip-2.1.2/src/netif/slipif.c 2022-01-28 15:46:12.938337000 +0800 +@@ -103,6 +103,7 @@ + #endif + }; + ++#if !LWIP_NIP + /** + * Send a pbuf doing the necessary SLIP encapsulation + * +@@ -156,6 +157,7 @@ + sio_send(SLIP_END, priv->sd); + return ERR_OK; + } ++#endif + + #if LWIP_IPV4 + /** diff --git a/components/net/lwip/patch.sha256 b/components/net/lwip/patch.sha256 index 271194671abf950a63c3fa9fb023b8a770b8bc44..68f9d1a893717fcd9897092c64d6d9a35529df27 100644 --- a/components/net/lwip/patch.sha256 +++ b/components/net/lwip/patch.sha256 @@ -1 +1 @@ -371f2079cd65ea018f5b3bf8638f8644cc82396b2801267c7d6eb0e67b31e3e4 origin.patch +6da71068eeb716399f4d5b0237aba082087b3abdf871e5b7f02174f79f8146a4 origin.patch