From 40ac8ba5d73b5414af6931555e2d9f4cdb533309 Mon Sep 17 00:00:00 2001 From: Terder-su Date: Wed, 16 Feb 2022 09:22:20 +0000 Subject: [PATCH 01/14] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20co?= =?UTF-8?q?mponents/net/lwip/origin.patch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/lwip/origin.patch | 4403 ------------------------------ 1 file changed, 4403 deletions(-) delete mode 100644 components/net/lwip/origin.patch diff --git a/components/net/lwip/origin.patch b/components/net/lwip/origin.patch deleted file mode 100644 index 0fb1a3f..0000000 --- a/components/net/lwip/origin.patch +++ /dev/null @@ -1,4403 +0,0 @@ -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 -@@ -146,7 +146,7 @@ - * NULL on memory error - */ - struct netconn * --netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) -+netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, netconn_callback callback) - { - struct netconn *conn; - API_MSG_VAR_DECLARE(msg); -@@ -292,6 +292,37 @@ - return err; - } - -+#if PF_PACKET_SOCKET -+/** -+ * Get the local or remote IP address and port of a netconn. -+ * For pf packet netconns, this returns the struct pf_packet_sockaddr_ll of the netconn! -+ * @param conn the netconn to query -+ * @param local 1 to get the local IP address, 0 to get the remote one -+ * @return ERR_CONN for invalid connections -+ * ERR_OK if the information was retrieved -+ * ERR_OPNOTSUPP if the option is not support -+ */ -+err_t -+netconn_get_sockaddr_pf_packet(struct netconn *conn, struct pf_packet_sockaddr_ll *ll, u8_t local) -+{ -+ err_t err; -+ API_MSG_VAR_DECLARE(msg); -+ API_MSG_VAR_ALLOC(msg); -+ API_MSG_VAR_REF(msg).conn = conn; -+ API_MSG_VAR_REF(msg).msg.adpkt.local = local; -+#if LWIP_MPU_COMPATIBLE -+ err = netconn_apimsg(lwip_netconn_do_getaddr_pfpkt, &API_MSG_VAR_REF(msg)); -+ *ll = msg->msg.adpkt.ll; -+#else /* LWIP_MPU_COMPATIBLE */ -+ API_MSG_VAR_REF(msg).msg.adpkt.ll = ll; -+ err = netconn_apimsg(lwip_netconn_do_getaddr_pfpkt, &msg); -+#endif /* LWIP_MPU_COMPATIBLE */ -+ API_MSG_VAR_FREE(msg); -+ -+ return err; -+} -+#endif -+ - /** - * @ingroup netconn_common - * Bind a netconn to a specific local IP address and port. -@@ -304,9 +335,13 @@ - * @return ERR_OK if bound, any other err_t on failure - */ - err_t -+#if PF_PACKET_SOCKET -+netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port, u8_t if_idx) -+#else /* PF_PACKET_SOCKET */ - netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port) -+#endif - { -- API_MSG_VAR_DECLARE(msg); -+ API_MSG_VAR_DECLARE(msg); /* struct api_msg *msg */ - err_t err; - - LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); -@@ -332,6 +367,9 @@ - API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); - API_MSG_VAR_REF(msg).msg.bc.port = port; -+#if PF_PACKET_SOCKET -+ API_MSG_VAR_REF(msg).msg.bc.if_idx = if_idx; -+#endif /* PF_PACKET_SOCKET */ - err = netconn_apimsg(lwip_netconn_do_bind, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - -@@ -596,7 +634,7 @@ - - NETCONN_MBOX_WAITING_INC(conn); - if (netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK) || -- (conn->flags & NETCONN_FLAG_MBOXCLOSED) || (conn->pending_err != ERR_OK)) { -+ (conn->flags & NETCONN_FLAG_MBOXCLOSED)) { - if (sys_arch_mbox_tryfetch(&conn->recvmbox, &buf) == SYS_ARCH_TIMEOUT) { - err_t err; - NETCONN_MBOX_WAITING_DEC(conn); -@@ -1144,8 +1182,7 @@ - return ERR_OK; - } - SYS_ARCH_PROTECT(lev); -- err = conn->pending_err; -- conn->pending_err = ERR_OK; -+ err = conn->last_err; - SYS_ARCH_UNPROTECT(lev); - 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 -@@ -184,10 +184,36 @@ - return 0; - } - -+#if PF_PACKET_SOCKET -+ /* To get the pkt type filtered in ethernet_input */ -+ q->flags = p->flags; -+#if ETH_PAD_SIZE -+ /* exclude the begining two padding bytes in struct eth_hdr */ -+ if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_PACKET_RAW) && (pbuf_header(q, -ETH_PAD_SIZE))) { -+ (void)pbuf_free(q); -+ memp_free(MEMP_NETBUF, buf); -+ return 0; -+ } -+#endif -+#endif -+ - buf->p = q; - buf->ptr = q; -+#if PF_PACKET_SOCKET -+ /* IP addr is NULL only when RAW packets are received for PF_PACKET sockets */ -+ if (addr == NULL) { -+ ip_addr_set_any(IP_IS_V6_VAL(buf->addr), &buf->addr); -+ buf->port = eth_current_hdr()->type; -+ buf->hatype = eth_current_netif()->link_layer_type; -+ buf->netifindex = eth_current_netif()->ifindex; -+ } else { -+ ip_addr_copy(buf->addr, *ip_current_src_addr()); -+ buf->port = pcb->raw_proto; -+ } -+#else - ip_addr_copy(buf->addr, *ip_current_src_addr()); - buf->port = pcb->protocol; -+#endif - - len = q->tot_len; - if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { -@@ -444,7 +470,7 @@ - /* when err is called, the pcb is deallocated, so delete the reference */ - conn->pcb.tcp = NULL; - /* store pending error */ -- conn->pending_err = err; -+ conn->last_err = err; - /* prevent application threads from blocking on 'recvmbox'/'acceptmbox' */ - conn->flags |= NETCONN_FLAG_MBOXCLOSED; - -@@ -627,23 +653,41 @@ - if (msg->conn->pcb.raw != NULL) { - #if LWIP_IPV6 - /* ICMPv6 packets should always have checksum calculated by the stack as per RFC 3542 chapter 3.1 */ -- if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->protocol == IP6_NEXTH_ICMP6) { -+ if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->raw_proto == IP6_NEXTH_ICMP6) { - msg->conn->pcb.raw->chksum_reqd = 1; - msg->conn->pcb.raw->chksum_offset = 2; - } - #endif /* LWIP_IPV6 */ -+ -+#if LWIP_IPV4 -+ /* IP_HDRINCL is enabled by default */ -+ if (!(NETCONNTYPE_ISIPV6(msg->conn->type)) && (msg->msg.n.proto == IPPROTO_RAW)) { -+ raw_set_flags(msg->conn->pcb.raw, RAW_FLAGS_HDRINCL); -+ } -+#endif - raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); - } - break; -+ -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+ msg->conn->pcb.packet_raw = raw_packet_new(msg->msg.n.proto); -+ if (msg->conn->pcb.packet_raw == NULL) { -+ msg->err = ERR_MEM; -+ break; -+ } -+ raw_recv(msg->conn->pcb.packet_raw, recv_raw, msg->conn); -+ break; -+#endif - #endif /* LWIP_RAW */ - #if LWIP_UDP -- case NETCONN_UDP: -- msg->conn->pcb.udp = udp_new_ip_type(iptype); -- if (msg->conn->pcb.udp != NULL) { -+ case NETCONN_UDP: -+ msg->conn->pcb.udp = udp_new_ip_type(iptype); -+ if (msg->conn->pcb.udp != NULL) { - #if LWIP_UDPLITE -- if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { -- udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); -- } -+ if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { -+ udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); -+ } - #endif /* LWIP_UDPLITE */ - if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) { - udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); -@@ -683,7 +727,7 @@ - - msg->err = ERR_OK; - if (msg->conn->pcb.tcp == NULL) { -- pcb_new(msg); -+ pcb_new(msg); //raw_recv() - } - /* Else? This "new" connection already has a PCB allocated. */ - /* Is this an error condition? Should it be deleted? */ -@@ -713,13 +757,16 @@ - return NULL; - } - -- conn->pending_err = ERR_OK; -+ conn->last_err = ERR_OK; - conn->type = t; - conn->pcb.tcp = NULL; - - /* If all sizes are the same, every compiler should optimize this switch to nothing */ - switch (NETCONNTYPE_GROUP(t)) { - #if LWIP_RAW -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+#endif - case NETCONN_RAW: - size = DEFAULT_RAW_RECVMBOX_SIZE; - break; -@@ -778,8 +825,17 @@ - conn->linger = -1; - #endif /* LWIP_SO_LINGER */ - conn->flags = init_flags; -+#if LWIP_TCP -+ conn->pending_err = 0; -+ conn->refused_data = NULL; -+ ip_addr_set_zero(&conn->remote_ip); -+ conn->remote_port = 0; -+#endif - return conn; - free_and_return: -+ if (sys_sem_valid(&conn->op_completed) != 0) { -+ sys_sem_free(&conn->op_completed); -+ } - memp_free(MEMP_NETCONN, conn); - return NULL; - } -@@ -1160,6 +1216,11 @@ - case NETCONN_RAW: - raw_remove(msg->conn->pcb.raw); - break; -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+ raw_packet_remove(msg->conn->pcb.packet_raw); -+ break; -+#endif - #endif /* LWIP_RAW */ - #if LWIP_UDP - case NETCONN_UDP: -@@ -1216,33 +1277,51 @@ - lwip_netconn_do_bind(void *m) - { - struct api_msg *msg = (struct api_msg *)m; -- err_t err; -+ struct netif *netif = NULL; -+ netif = netif_find_by_ipaddr(API_EXPR_REF(msg->msg.bc.ipaddr)); - -- if (msg->conn->pcb.tcp != NULL) { -- switch (NETCONNTYPE_GROUP(msg->conn->type)) { -+ 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)) || -+ ip_addr_ismulticast(API_EXPR_REF(msg->msg.bc.ipaddr)) || -+ netif_ipaddr_isbrdcast(API_EXPR_REF(msg->msg.bc.ipaddr)) || -+ ((netif != NULL) && netif_is_up(netif)))) { -+ msg->err = ERR_NOADDR; -+ } else { -+ msg->err = ERR_VAL; -+ if (msg->conn->pcb.tcp != NULL) { -+ switch (NETCONNTYPE_GROUP(msg->conn->type)) { - #if LWIP_RAW - case NETCONN_RAW: -- err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); -+ msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); -+ break; -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+ msg->err = raw_packet_bind(msg->conn->pcb.packet_raw, msg->msg.bc.if_idx, msg->msg.bc.port); - break; -+#endif - #endif /* LWIP_RAW */ - #if LWIP_UDP - case NETCONN_UDP: -- err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); -+ msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); - break; - #endif /* LWIP_UDP */ - #if LWIP_TCP - case NETCONN_TCP: -- err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); -+ if (msg->conn->pcb.tcp->local_port == 0) { -+ msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); -+ } else { -+ msg->err = ERR_VAL; -+ } -+ - break; - #endif /* LWIP_TCP */ - default: -- err = ERR_VAL; -+ msg->err = ERR_OPNOTSUPP; - break; -+ } - } -- } else { -- err = ERR_VAL; - } -- msg->err = err; - TCPIP_APIMSG_ACK(msg); - } - /** -@@ -1351,6 +1430,11 @@ - { - struct api_msg *msg = (struct api_msg *)m; - err_t err; -+ if (ERR_IS_FATAL(msg->conn->last_err)) { -+ msg->err = msg->conn->last_err; -+ TCPIP_APIMSG_ACK(msg); -+ return; -+ } - - if (msg->conn->pcb.tcp == NULL) { - /* This may happen when calling netconn_connect() a second time */ -@@ -1540,11 +1624,44 @@ - #if LWIP_RAW - case NETCONN_RAW: - if (ip_addr_isany(&msg->msg.b->addr) || IP_IS_ANY_TYPE_VAL(msg->msg.b->addr)) { -+#if PF_PACKET_SOCKET -+ struct ip_hdr *iphdr = NULL; -+ ip_addr_t dest_addr; -+ -+ if (!(msg->conn->pcb.raw->flags & RAW_FLAGS_CONNECTED) || -+ ip_addr_isany(&msg->conn->pcb.raw->remote_ip)) { -+ if (raw_is_flag_set(msg->conn->pcb.raw, RAW_FLAGS_HDRINCL)) { -+ if (msg->msg.b->p->len < IP_HLEN) { -+ err = ERR_MSGSIZE; -+ break; -+ } -+ -+ /* IP header already included in p */ -+ iphdr = (struct ip_hdr *)msg->msg.b->p->payload; -+ ip_addr_copy_from_ip4(dest_addr, iphdr->dest); -+ err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &dest_addr); -+ break; -+ } -+ -+ err = ERR_NODEST; -+ break; -+ } -+#endif /* PF_PACKET_SOCKET */ - err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); - } else { - err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr); - } - break; -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+ /* Check if its for sending RAW packets for PF_PACKET family */ -+ if (msg->msg.b->flags & NETBUF_FLAG_IFINDEX) { -+ err = raw_packet_sendto(msg->conn->pcb.packet_raw, msg->msg.b->p, msg->msg.b->netifindex); -+ } else { -+ err = raw_packet_sendto(msg->conn->pcb.packet_raw, msg->msg.b->p, 0); -+ } -+ break; -+#endif - #endif - #if LWIP_UDP - case NETCONN_UDP: -@@ -1868,6 +1985,11 @@ - { - struct api_msg *msg = (struct api_msg *)m; - -+ if ((msg->conn == NULL) || (msg->conn->pcb.tcp == NULL)) { -+ msg->err = ERR_CONN; -+ TCPIP_APIMSG_ACK(msg); -+ return; -+ } - 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 @@ - #if LWIP_RAW - case NETCONN_RAW: - if (msg->msg.ad.local) { -- API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; -+ ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), -+ msg->conn->pcb.raw->local_ip); -+ API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->raw_proto; - } else { -- /* return an error as connecting is only a helper for upper layers */ -- msg->err = ERR_CONN; -+ if (raw_is_flag_set(msg->conn->pcb.raw, RAW_FLAGS_CONNECTED)) { -+ ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), -+ msg->conn->pcb.raw->remote_ip); -+ API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->raw_proto; -+ } else { -+ /* return an error as connecting is only a helper for upper layers */ -+ msg->err = ERR_CONN; -+ } - } - break; - #endif /* LWIP_RAW */ -@@ -1923,6 +2053,47 @@ - TCPIP_APIMSG_ACK(msg); - } - -+#if PF_PACKET_SOCKET -+/** -+ * Return a pf pkt socket's local address -+ * Called from netconn_getaddr -+ * -+ * @param m the api_msg pointing to the connection -+ */ -+void -+lwip_netconn_do_getaddr_pfpkt(void *m) -+{ -+ struct api_msg *msg = (struct api_msg *)m; -+ struct pf_packet_sockaddr_ll ll; -+ msg->err = ERR_OK; -+ if (msg->conn->pcb.ip != NULL) { -+ /* Non standard way of do it, but doing it :( */ -+ if (msg->msg.adpkt.local) { -+ ll.sll_protocol = msg->conn->pcb.packet_raw->proto.eth_proto; -+ ll.if_idx = msg->conn->pcb.packet_raw->netifindex; -+ struct netif *netif = netif_find_by_ifindex(msg->conn->pcb.packet_raw->netifindex); -+ if (netif == NULL) { -+ LWIP_DEBUGF(SOCKETS_DEBUG, -+ ("lwip_getaddrname:netif not found for given ifindex (%u)\n", -+ msg->conn->pcb.packet_raw->netifindex)); -+ ll.sll_halen = 0; -+ ll.sll_hatype = 0; -+ } else { -+ ll.sll_hatype = netif->link_layer_type; -+ ll.sll_halen = NETIF_MAX_HWADDR_LEN; -+ (void)memcpy_s(ll.sll_addr, ll.sll_halen, netif->hwaddr, NETIF_MAX_HWADDR_LEN); -+ } -+ API_EXPR_DEREF(msg->msg.adpkt.ll) = ll; -+ } else { -+ msg->err = ERR_OPNOTSUPP; -+ } -+ } else { -+ msg->err = ERR_CONN; -+ } -+ TCPIP_APIMSG_ACK(msg); -+} -+#endif -+ - /** - * 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 -@@ -48,7 +48,7 @@ - - #include "lwip/netbuf.h" - #include "lwip/memp.h" -- -+#include "lwip/api.h" - #include - - /** -@@ -99,7 +99,7 @@ - * NULL if no memory could be allocated - */ - void * --netbuf_alloc(struct netbuf *buf, u16_t size) -+netbuf_alloc(struct netbuf *buf, u16_t size, u8_t netconn_type) - { - LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); - -@@ -107,7 +107,22 @@ - if (buf->p != NULL) { - pbuf_free(buf->p); - } -- buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); -+ -+ switch (netconn_type) { -+#if LWIP_RAW -+ case NETCONN_RAW: -+ buf->p = pbuf_alloc(PBUF_IP, size, PBUF_RAM); -+ break; -+#endif /* LWIP_RAW */ -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+ buf->p = pbuf_alloc(PBUF_LINK, size, PBUF_RAM); -+ break; -+#endif /* PF_PACKET_SOCKET */ -+ default: -+ buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); -+ } -+ - if (buf->p == NULL) { - 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 -@@ -58,7 +58,7 @@ - - /** h_errno is exported in netdb.h for access by applications. */ - #if LWIP_DNS_API_DECLARE_H_ERRNO --int h_errno; -+int h_err_no; - #endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ - - /** define "hostent" variables storage: 0 if we use a static (but unprotected) -@@ -100,7 +100,7 @@ - err = netconn_gethostbyname(name, &addr); - if (err != ERR_OK) { - LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); -- h_errno = HOST_NOT_FOUND; -+ h_err_no = HOST_NOT_FOUND; - return NULL; - } - -@@ -374,10 +374,14 @@ - /* set up sockaddr */ - inet6_addr_from_ip6addr(&sa6->sin6_addr, ip_2_ip6(&addr)); - sa6->sin6_family = AF_INET6; -+#if defined(SIN6_LEN) - sa6->sin6_len = sizeof(struct sockaddr_in6); -+#endif -+ sa6->sin6_flowinfo = 0; - sa6->sin6_port = lwip_htons((u16_t)port_nr); - sa6->sin6_scope_id = ip6_addr_zone(ip_2_ip6(&addr)); - ai->ai_family = AF_INET6; -+ ai->ai_addrlen = sizeof(struct sockaddr_in6); - #endif /* LWIP_IPV6 */ - } else { - #if LWIP_IPV4 -@@ -385,9 +389,9 @@ - /* set up sockaddr */ - inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr)); - sa4->sin_family = AF_INET; -- sa4->sin_len = sizeof(struct sockaddr_in); - sa4->sin_port = lwip_htons((u16_t)port_nr); - ai->ai_family = AF_INET; -+ ai->ai_addrlen = sizeof(struct sockaddr_in); - #endif /* LWIP_IPV4 */ - } - -@@ -403,7 +407,6 @@ - MEMCPY(ai->ai_canonname, nodename, namelen); - ai->ai_canonname[namelen] = 0; - } -- ai->ai_addrlen = sizeof(struct sockaddr_storage); - ai->ai_addr = (struct sockaddr *)sa; - - *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 -@@ -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) - -+#if LWIP_MPU_COMPATIBLE -+static inline err_t netifapi_msg_alloc(struct netifapi_msg **name) -+{ -+ API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, (*name), ERR_MEM); -+ LWIP_UNUSED_ARG(name); -+ return ERR_OK; -+} -+#else -+static inline err_t netifapi_msg_alloc(struct netifapi_msg *name) -+{ -+ LWIP_UNUSED_ARG(name); -+ return ERR_OK; -+} -+#endif -+ - /** - * Call netif_add() inside the tcpip_thread context. - */ -@@ -71,8 +86,8 @@ - API_EXPR_REF(msg->msg.add.gw), - #endif /* LWIP_IPV4 */ - msg->msg.add.state, -- msg->msg.add.init, -- msg->msg.add.input)) { -+ msg->msg.add_get.init, -+ msg->msg.add_get.input)) { - return ERR_IF; - } else { - return ERR_OK; -@@ -248,8 +263,8 @@ - NETIFAPI_VAR_REF(msg).msg.add.gw = NETIFAPI_VAR_REF(gw); - #endif /* LWIP_IPV4 */ - NETIFAPI_VAR_REF(msg).msg.add.state = state; -- NETIFAPI_VAR_REF(msg).msg.add.init = init; -- NETIFAPI_VAR_REF(msg).msg.add.input = input; -+ NETIFAPI_VAR_REF(msg).msg.add_get.init = init; -+ NETIFAPI_VAR_REF(msg).msg.add_get.input = input; - err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call); - NETIFAPI_VAR_FREE(msg); - return err; -@@ -377,4 +392,60 @@ - return err; - } - -+/** -+ * Call netif_find() inside the tcpip_thread context. -+ */ -+static err_t -+do_netifapi_netif_find_by_name(struct tcpip_api_call_data *m) -+{ -+ struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; -+ -+ msg->netif = netif_find(msg->msg.find_by_name.name); -+ return ERR_OK; -+} -+ -+struct netif* -+netifapi_netif_find_by_name(const char *name) -+{ -+ struct netif *netif = NULL; -+ NETIFAPI_VAR_DECLARE(msg); -+ if (netifapi_msg_alloc(&msg) != ERR_OK) { -+ return NULL; -+ } -+ -+ NETIFAPI_VAR_REF(msg).netif = NULL; -+ NETIFAPI_VAR_REF(msg).msg.find_by_name.name = name; -+ (void)tcpip_api_call(do_netifapi_netif_find_by_name, &API_VAR_REF(msg).call); -+ netif = NETIFAPI_VAR_REF(msg).netif; -+ NETIFAPI_VAR_FREE(msg); -+ return netif; -+} -+ -+/** -+ * Call netif_find_by_ipaddr() inside the tcpip_thread context. -+ */ -+static err_t -+do_netifapi_netif_find_by_ipaddr(struct tcpip_api_call_data *m) -+{ -+ struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; -+ msg->netif = netif_find_by_ipaddr(msg->msg.find_by_ipaddr.ipaddr); -+ return ERR_OK; -+} -+ -+struct netif * -+netifapi_netif_find_by_ipaddr(const ip_addr_t *ipaddr) -+{ -+ struct netif *netif = NULL; -+ NETIFAPI_VAR_DECLARE(msg); -+ if (netifapi_msg_alloc(&msg) != ERR_OK) { -+ return NULL; -+ } -+ -+ NETIFAPI_VAR_REF(msg).netif = NULL; -+ NETIFAPI_VAR_REF(msg).msg.find_by_ipaddr.ipaddr = ipaddr; -+ (void)tcpip_api_call(do_netifapi_netif_find_by_ipaddr, &API_VAR_REF(msg).call); -+ netif = NETIFAPI_VAR_REF(msg).netif; -+ NETIFAPI_VAR_FREE(msg); -+ return netif; -+} - #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 -@@ -54,6 +54,7 @@ - #include "lwip/netif.h" - #include "lwip/priv/tcpip_priv.h" - #include "lwip/mld6.h" -+#include "lwip/dhcp.h" - #if LWIP_CHECKSUM_ON_COPY - #include "lwip/inet_chksum.h" - #endif -@@ -85,9 +86,19 @@ - #define API_SELECT_CB_VAR_ALLOC(name, retblock) API_VAR_ALLOC_EXT(struct lwip_select_cb, MEMP_SELECT_CB, name, retblock) - #define API_SELECT_CB_VAR_FREE(name) API_VAR_FREE(MEMP_SELECT_CB, name) - -+#if !LWIP_LITEOS_COMPAT -+#defeine SIN4_LEN(x) \ -+ (x)->sin_len = sizeof(struct sockaddr_in) -+#defeine SIN6_LEN(x) \ -+ (x)->sin6_len = sizeof(struct sockaddr_in6) -+#else -+#define SIN4_LEN(x) -+#define SIN6_LEN(x) -+#endif /* LWIP_LITEOS_COMPAT */ -+ - #if LWIP_IPV4 - #define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \ -- (sin)->sin_len = sizeof(struct sockaddr_in); \ -+ SIN4_LEN(sin); \ - (sin)->sin_family = AF_INET; \ - (sin)->sin_port = lwip_htons((port)); \ - inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \ -@@ -98,8 +109,10 @@ - #endif /* LWIP_IPV4 */ - - #if LWIP_IPV6 -+/* SIN6_LEN macro is to differntiate whether stack is using 4.3BSD or 4.4BSD variants of sockaddr_in6 -+structure */ - #define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \ -- (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ -+ SIN6_LEN(sin6); \ - (sin6)->sin6_family = AF_INET6; \ - (sin6)->sin6_port = lwip_htons((port)); \ - (sin6)->sin6_flowinfo = 0; \ -@@ -283,6 +296,45 @@ - set_errno(sockerr); \ - } while (0) - -+#if LWIP_LITEOS_COMPAT -+#define VALIDATE_GET_RAW_OPTNAME_RET(_sock, _optname) do { \ -+ if ((_sock)->conn != NULL && (NETCONNTYPE_GROUP((_sock)->conn->type) == NETCONN_RAW) && \ -+ (((_optname) != SO_BROADCAST) && ((_optname) != SO_RCVTIMEO) && \ -+ ((_optname) != SO_RCVBUF) && ((_optname) != SO_TYPE) && \ -+ ((_optname) != SO_DONTROUTE) && ((_optname) != SO_BINDTODEVICE))) { \ -+ done_socket(_sock); \ -+ return ENOPROTOOPT; \ -+ } \ -+ } while (0) -+ -+#if PF_PACKET_SOCKET -+#define VALIDATE_SET_PF_PKT_OPTNAME_RET(_s, _sock, _level, _optname) do { \ -+ if ((_level) == SOL_PACKET && ((_optname) != SO_RCVTIMEO && (_optname) != SO_RCVBUF) && \ -+ (_optname) != SO_ATTACH_FILTER && (_optname) != SO_DETACH_FILTER) { \ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_PACKET, UNIMPL: optname=0x%x, ..)\n", \ -+ (_s), (_optname))); \ -+ done_socket(_sock); \ -+ return ENOPROTOOPT; \ -+ } \ -+ } while (0) -+ -+#define VALIDATE_GET_PF_PKT_OPTNAME_RET(_s,_sock,_level,_optname) do { \ -+ if ((_sock)->conn != NULL && (NETCONNTYPE_GROUP((_sock)->conn->type) == NETCONN_PACKET_RAW) && \ -+ (_level) == SOL_PACKET && ((_optname) != SO_RCVTIMEO && (_optname) != SO_RCVBUF && (_optname) != SO_TYPE)) { \ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%p, SOL_PACKET, UNIMPL: optname=0x%x, ..)\n", \ -+ (_s), (_optname))); \ -+ done_socket(_sock); \ -+ return ENOPROTOOPT; \ -+ } \ -+ } while (0) -+ -+#define VALIDATE_LEVEL_PF_PACKET(_sock,_level) \ -+ if ((_sock)->conn != NULL && ((NETCONNTYPE_GROUP(netconn_type(_sock->conn)) == NETCONN_PACKET_RAW \ -+ && SOL_SOCKET != (_level) && SOL_PACKET != (_level)) || \ -+ (NETCONNTYPE_GROUP((_sock)->conn->type) != NETCONN_PACKET_RAW && SOL_PACKET == (_level)))) -+#endif -+#endif /* LWIP_LITEOS_COMPAT */ -+ - /* 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 @@ - return sock; - } - -+#if LWIP_LITEOS_COMPAT -+/* get numbers of unused sockets */ -+int get_unused_socket_num(void) -+{ -+ int unused = 0, i; -+ SYS_ARCH_DECL_PROTECT(lev); -+ SYS_ARCH_PROTECT(lev); -+ -+ for (i = 0; i < (int)(NUM_SOCKETS); i++) { -+ if (!sockets[i].conn -+#if LWIP_NETCONN_FULLDUPLEX -+ && !sockets[i].fd_used -+#endif -+ ) { -+ unused++; -+ } -+ } -+ -+ SYS_ARCH_UNPROTECT(lev); -+ return unused; -+} -+#endif /* LWIP_LITEOS_COMPAT */ -+ - /** - * Allocate a new socket for a given netconn. - * -@@ -696,8 +771,10 @@ - } - - IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); -- if (*addrlen > tempaddr.sa.sa_len) { -- *addrlen = tempaddr.sa.sa_len; -+ if (IP_IS_V4_VAL(naddr) && (*addrlen > (int)sizeof(struct sockaddr_in))) { -+ *addrlen = sizeof(struct sockaddr_in); -+ } else if (IP_IS_V6_VAL(naddr) && (*addrlen > (int)sizeof(struct sockaddr_in6))) { -+ *addrlen = sizeof(struct sockaddr_in6); - } - MEMCPY(addr, &tempaddr, *addrlen); - -@@ -722,28 +799,58 @@ - u16_t local_port; - err_t err; - -+#if PF_PACKET_SOCKET -+ const struct sockaddr_ll *name_ll = NULL; -+ u8_t local_if_idx = 0; -+#endif - sock = get_socket(s); - if (!sock) { - return -1; - } - -- if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { -- /* sockaddr does not match socket type (IPv4/IPv6) */ -- sock_set_errno(sock, err_to_errno(ERR_VAL)); -- done_socket(sock); -- return -1; -- } -- - /* check size, family and alignment of 'name' */ -- LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && -+#if PF_PACKET_SOCKET -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { -+ name_ll = (const struct sockaddr_ll *)(void*)name; -+ LWIP_ERROR("lwip_bind: invalid address", ((name_ll != NULL)&&(namelen == sizeof(struct sockaddr_ll)) && -+ ((name_ll->sll_family) == PF_PACKET) && IS_SOCK_ADDR_ALIGNED(name) && -+ (name_ll->sll_ifindex <= LWIP_NETIF_IFINDEX_MAX)), sock_set_errno(sock, err_to_errno(ERR_VAL)); -+ done_socket(sock); return -1); -+ -+ ip_addr_set_any_val(IPADDR_TYPE_V4, local_addr); -+ local_port = name_ll->sll_protocol; -+ local_if_idx = (u8_t)name_ll->sll_ifindex; -+ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, ", s)); -+ LWIP_DEBUGF(SOCKETS_DEBUG, (" ifindex=%u proto=%"U16_F")\n", local_if_idx, local_port)); -+ } else -+#endif -+ { -+ 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); -+ -+ if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { -+ /* sockaddr does not match socket type (IPv4/IPv6) */ -+ sock_set_errno(sock, err_to_errno(ERR_VAL)); -+ done_socket(sock); -+ return -1; -+ } -+ -+ /* check size, family and alignment of 'name' */ -+ LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && - IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)), - sock_set_errno(sock, err_to_errno(ERR_ARG)); done_socket(sock); return -1;); -- LWIP_UNUSED_ARG(namelen); -+ LWIP_UNUSED_ARG(namelen); - -- SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); -- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); -- ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); -- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); -+ SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); -+ ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); -+ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); -+ } - - #if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ -@@ -753,7 +860,11 @@ - } - #endif /* LWIP_IPV4 && LWIP_IPV6 */ - -+#if PF_PACKET_SOCKET -+ err = netconn_bind(sock->conn, &local_addr, local_port, local_if_idx); -+#else /* PF_PACKET_SOCKET */ - err = netconn_bind(sock->conn, &local_addr, local_port); -+#endif - - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); -@@ -820,6 +931,14 @@ - return -1; - } - -+#if PF_PACKET_SOCKET -+ if (NETCONN_PACKET_RAW & NETCONNTYPE_GROUP(netconn_type(sock->conn))) { -+ sock_set_errno(sock, EOPNOTSUPP); -+ done_socket(sock); -+ return -1; -+ } -+#endif -+ - 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 @@ - { - int truncated = 0; - union sockaddr_aligned saddr; -+ socklen_t sa_len; - - LWIP_UNUSED_ARG(conn); - -@@ -1041,10 +1161,20 @@ - #endif /* LWIP_IPV4 && LWIP_IPV6 */ - - IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port); -- if (*fromlen < saddr.sa.sa_len) { -+#if LWIP_LITEOS_COMPAT -+ if (IP_IS_V4_VAL(*fromaddr)) { -+ sa_len = sizeof(struct sockaddr_in); -+ } else { -+ sa_len = sizeof(struct sockaddr_in6); -+ } -+#else -+ sa_len = saddr.sa.sa_len; -+#endif /* LWIP_LITEOS_COMPAT */ -+ -+ if (*fromlen < sa_len) { - truncated = 1; -- } else if (*fromlen > saddr.sa.sa_len) { -- *fromlen = saddr.sa.sa_len; -+ } else if (*fromlen > sa_len) { -+ *fromlen = sa_len; - } - MEMCPY(from, &saddr, *fromlen); - return truncated; -@@ -1146,8 +1276,44 @@ - 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) { -- lwip_sock_make_addr(sock->conn, netbuf_fromaddr(buf), netbuf_fromport(buf), -- (struct sockaddr *)msg->msg_name, &msg->msg_namelen); -+#if PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT -+ struct sockaddr_ll sll; -+ -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { -+ if (msg->msg_namelen > sizeof(sll)) { -+ msg->msg_namelen = sizeof(sll); -+ } -+ -+ if (msg->msg_namelen) { -+ (void)memset_s(&sll, sizeof(sll), 0, sizeof(sll)); -+ sll.sll_family = PF_PACKET; -+ sll.sll_protocol = netbuf_fromport(buf); -+ sll.sll_hatype = netbuf_fromhatype(buf); -+ sll.sll_ifindex = netbuf_fromifindex(buf); -+ -+ if (buf->p->flags & PBUF_FLAG_LLBCAST) { -+ sll.sll_pkttype = PACKET_BROADCAST; -+ } else if (buf->p->flags & PBUF_FLAG_LLMCAST) { -+ sll.sll_pkttype = PACKET_MULTICAST; -+ } else if (buf->p->flags & PBUF_FLAG_HOST) { -+ sll.sll_pkttype = PACKET_HOST; -+ } else if (buf->p->flags & PBUF_FLAG_OUTGOING) { -+ sll.sll_pkttype = PACKET_OUTGOING; -+ } else { -+ sll.sll_pkttype = PACKET_OTHERHOST; -+ } -+ -+ (void)memcpy_s(msg->msg_name, msg->msg_namelen, (void *)&sll, msg->msg_namelen); -+ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom_udp_raw(%d): hatype=%u", dbg_s, ntohs(sll.sll_hatype))); -+ LWIP_DEBUGF(SOCKETS_DEBUG, (" packet type = %u\n", sll.sll_pkttype)); -+ } -+ } else -+#endif /* PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT */ -+ { -+ lwip_sock_make_addr(sock->conn, netbuf_fromaddr(buf), netbuf_fromport(buf), -+ (struct sockaddr *)msg->msg_name, &msg->msg_namelen); -+ } - } - } - -@@ -1496,7 +1662,7 @@ - goto sendmsg_emsgsize; - } - /* Allocate a new netbuf and copy the data into it. */ -- if (netbuf_alloc(&chain_buf, (u16_t)size) == NULL) { -+ if (netbuf_alloc(&chain_buf, (u16_t)size, NETCONNTYPE_GROUP(netconn_type(sock->conn))) == NULL) { - err = ERR_MEM; - } else { - /* flatten the IO vectors */ -@@ -1588,8 +1754,14 @@ - struct lwip_sock *sock; - err_t err; - u16_t short_size; -- u16_t remote_port; -+ u16_t remote_port = 0; - struct netbuf buf; -+#if (PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT) -+ const struct sockaddr_ll *to_ll = NULL; -+#endif -+ const struct sockaddr_in *to_in = NULL; -+ -+ unsigned int acceptable_flags = 0; - - sock = get_socket(s); - if (!sock) { -@@ -1608,11 +1780,62 @@ - #endif /* LWIP_TCP */ - } - -- if (size > LWIP_MIN(0xFFFF, SSIZE_MAX)) { -- /* cannot fit into one datagram (at least for us) */ -- sock_set_errno(sock, EMSGSIZE); -- done_socket(sock); -- return -1; -+#if PF_PACKET_SOCKET -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { -+ to_ll = (const struct sockaddr_ll *)(void *)to; -+ -+ LWIP_ERROR("lwip_sendto: invalid address", (((data != NULL) && (size!=0)) && -+ (((to_ll != NULL) && (tolen == sizeof(struct sockaddr_ll))) && -+ ((to_ll->sll_family) == PF_PACKET) && ((((mem_ptr_t)to_ll) % 4) == 0)) && -+ (to_ll->sll_ifindex <= LWIP_NETIF_IFINDEX_MAX)), -+ sock_set_errno(sock, err_to_errno(ERR_VAL)); -+ done_socket(sock); return -1); -+ -+ LWIP_ERROR("lwip_sendto: invalid address family", ((to_ll->sll_family) == PF_PACKET), -+ sock_set_errno(sock, err_to_errno(ERR_AFNOSUPP)); -+ done_socket(sock); return -1); -+ -+ LWIP_ERROR("lwip_sendto: invalid flags. Should be 0", (flags == 0), -+ sock_set_errno(sock, err_to_errno(ERR_OPNOTSUPP)); -+ done_socket(sock); return -1); -+ -+ if (size > LWIP_MAX_PF_RAW_SEND_SIZE) { -+ sock_set_errno(sock, EMSGSIZE); -+ done_socket(sock); -+ return -1; -+ } -+ } else -+#endif /* PF_PACKET_SOCKET */ -+ { -+ to_in = (const struct sockaddr_in *)(void*)to; -+ acceptable_flags = acceptable_flags | MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL; -+ if ((~acceptable_flags) & (unsigned int)flags) { -+ sock_set_errno(sock, err_to_errno(ERR_OPNOTSUPP)); -+ done_socket(sock); -+ return -1; -+ } -+ -+ LWIP_ERROR("lwip_sendto: invalid address", ((data != NULL) && (size!=0) && (flags>=0)), -+ sock_set_errno(sock, err_to_errno(ERR_VAL)); -+ done_socket(sock); return -1); -+ -+ LWIP_ERROR("lwip_sendto: invalid address", (((to_in == NULL) && (tolen == 0)) || -+ (((to_in == NULL) && (tolen != 0)) || IS_SOCK_ADDR_LEN_VALID(tolen))), -+ sock_set_errno(sock, err_to_errno(ERR_VAL)); -+ done_socket(sock); -+ return -1); -+ -+ LWIP_ERROR("lwip_sendto: invalid address", (to == NULL || IS_SOCK_ADDR_TYPE_VALID(to)), -+ sock_set_errno(sock, err_to_errno(ERR_AFNOSUPPORT)); -+ done_socket(sock); -+ return -1); -+ -+ if (size > LWIP_MAX_UDP_RAW_SEND_SIZE) { -+ sock_set_errno(sock, EMSGSIZE); -+ done_socket(sock); -+ return -1; -+ } -+ - } - short_size = (u16_t)size; - LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || -@@ -1626,6 +1849,9 @@ - #if LWIP_CHECKSUM_ON_COPY - buf.flags = 0; - #endif /* LWIP_CHECKSUM_ON_COPY */ -+#if PF_PACKET_SOCKET -+ buf.netifindex = 0; -+#endif - if (to) { - SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port); - } else { -@@ -1637,17 +1863,29 @@ - - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_sendto(%d, data=%p, short_size=%"U16_F", flags=0x%x to=", - s, data, short_size, flags)); -- ip_addr_debug_print_val(SOCKETS_DEBUG, buf.addr); -- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); -- -+#if PF_PACKET_SOCKET -+ if (buf.flags & NETBUF_FLAG_IFINDEX) { -+ LWIP_DEBUGF(SOCKETS_DEBUG, (" netifindex = %d\n", buf.netifindex)); -+ } else -+#endif -+ { -+ ip_addr_debug_print_val(SOCKETS_DEBUG, buf.addr); -+ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); -+ } - /* make the buffer point to the data that should be sent */ - #if LWIP_NETIF_TX_SINGLE_PBUF - /* Allocate a new netbuf and copy the data into it. */ -- if (netbuf_alloc(&buf, short_size) == NULL) { -+ if (netbuf_alloc(&buf, short_size, NETCONNTYPE_GROUP(netconn_type(sock->conn))) == NULL) { - err = ERR_MEM; - } else { - #if LWIP_CHECKSUM_ON_COPY -- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { -+#if PF_PACKET_SOCKET -+ if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_PACKET_RAW) && -+ (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW)) -+#else -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) -+#endif -+ { - u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); - netbuf_set_chksum(&buf, chksum); - } else -@@ -1688,14 +1926,32 @@ - int i; - - 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 - - /* create a netconn */ - switch (type) { - case SOCK_RAW: -- conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), -- (u8_t)protocol, DEFAULT_SOCKET_EVENTCB); -- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", -+#if PF_PACKET_SOCKET -+ if (domain == PF_PACKET) { -+ conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_PACKET_RAW), -+ (u16_t)protocol, event_callback); -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", "PF_PACKET", protocol)); -+ } else -+#endif -+ { -+ conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), -+ (u8_t)protocol, DEFAULT_SOCKET_EVENTCB); -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", - domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); -+ } - break; - case SOCK_DGRAM: - conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, -@@ -1983,10 +2239,11 @@ - timeout ? (s32_t)timeout->tv_sec : (s32_t) - 1, - timeout ? (s32_t)timeout->tv_usec : (s32_t) - 1)); - -- if ((maxfdp1 < 0) || (maxfdp1 > LWIP_SELECT_MAXNFDS)) { -+/*if ((maxfdp1 < 0) || (maxfdp1 > LWIP_SELECT_MAXNFDS)) { - set_errno(EINVAL); - return -1; - } -+ */ - - lwip_select_inc_sockets_used(maxfdp1, readset, writeset, exceptset, &used_sockets); - -@@ -2704,12 +2961,60 @@ - ip_addr_t naddr; - u16_t port; - err_t err; -+ socklen_t sa_len; -+ -+#if PF_PACKET_SOCKET -+ struct sockaddr_ll addr_sin; -+ struct pf_packet_sockaddr_ll sll; -+ socklen_t outlen; -+#endif -+ -+ LWIP_ERROR("lwip_getaddrname: invalid arguments", ((name != NULL) && (namelen != NULL)), -+ set_errno(EINVAL); return -1); - - sock = get_socket(s); - if (!sock) { - return -1; - } - -+#if PF_PACKET_SOCKET -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_PACKET_RAW) { -+ err = netconn_get_sockaddr_pf_packet(sock->conn, &sll, local); -+ if (err != ERR_OK) { -+ sock_set_errno(sock, err_to_errno(err)); -+ done_socket(sock); -+ return -1; -+ } -+ -+ (void)memset_s(&addr_sin, sizeof(struct sockaddr_ll), 0, sizeof(struct sockaddr_ll)); -+ addr_sin.sll_family = PF_PACKET; -+ addr_sin.sll_protocol = sll.sll_protocol; -+ addr_sin.sll_pkttype = 0; -+ addr_sin.sll_ifindex = sll.if_idx; -+ addr_sin.sll_hatype = sll.sll_hatype; -+ addr_sin.sll_halen = sll.sll_halen; -+ -+ if ((sll.sll_halen > 0) && (memcpy_s(addr_sin.sll_addr, addr_sin.sll_halen, sll.sll_addr, sll.sll_halen) != EOK)) { -+ sock_set_errno(sock, err_to_errno(ERR_MEM)); -+ done_socket(sock); -+ return -1; -+ } -+ -+ outlen = sizeof(struct sockaddr_ll); -+ if (outlen > *namelen) { -+ outlen = *namelen; -+ } -+ if (memcpy_s(name, *namelen, &addr_sin, outlen) != EOK) { -+ sock_set_errno(sock, err_to_errno(ERR_MEM)); -+ done_socket(sock); -+ return -1; -+ } -+ *namelen = outlen; -+ done_socket(sock); -+ return 0; -+ } -+#endif /* PF_PACKET_SOCKET */ -+ - /* get the IP address and port */ - err = netconn_getaddr(sock->conn, &naddr, &port, local); - if (err != ERR_OK) { -@@ -2732,9 +3037,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)); -+ if (IP_IS_V4_VAL(naddr)) { -+ sa_len = sizeof(struct sockaddr_in); -+ } else { -+ sa_len = sizeof(struct sockaddr_in6); -+ } - -- if (*namelen > saddr.sa.sa_len) { -- *namelen = saddr.sa.sa_len; -+ if (*namelen > sa_len) { -+ *namelen = sa_len; - } - MEMCPY(name, &saddr, *namelen); - -@@ -2775,6 +3085,14 @@ - return -1; - } - -+#if PF_PACKET_SOCKET -+ VALIDATE_LEVEL_PF_PACKET(sock, level) { -+ sock_set_errno(sock, EINVAL); -+ done_socket(sock); -+ return -1; -+ } -+#endif /* PF_PACKET_SOCKET */ -+ - #if LWIP_TCPIP_CORE_LOCKING - /* core-locking can just call the -impl function */ - LOCK_TCPIP_CORE(); -@@ -2826,8 +3144,9 @@ - err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; - LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); - #endif /* LWIP_TCPIP_CORE_LOCKING */ -- -- sock_set_errno(sock, err); -+ if (err != ERR_OK) { -+ sock_set_errno(sock, err); -+ } - done_socket(sock); - return err ? -1 : 0; - } -@@ -2897,6 +3216,11 @@ - - /* Level: SOL_SOCKET */ - case SOL_SOCKET: -+#if PF_PACKET_SOCKET -+ case SOL_PACKET: -+ VALIDATE_GET_PF_PKT_OPTNAME_RET(s, sock, level, optname); -+#endif /* PF_PACKET_SOCKET */ -+ VALIDATE_GET_RAW_OPTNAME_RET(sock, optname); - switch (optname) { - - #if LWIP_TCP -@@ -2920,6 +3244,10 @@ - #if SO_REUSE - case SO_REUSEADDR: - #endif /* SO_REUSE */ -+ if (sock->conn == NULL) { -+ done_socket(sock); -+ return EINVAL; -+ } - if ((optname == SO_BROADCAST) && - (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP)) { - done_socket(sock); -@@ -2937,6 +3265,9 @@ - case SO_TYPE: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); - switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) { -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+#endif - case NETCONN_RAW: - *(int *)optval = SOCK_RAW; - break; -@@ -2948,9 +3279,16 @@ - break; - default: /* unrecognized socket type */ - *(int *)optval = netconn_type(sock->conn); -+#if PF_PACKET_SOCKET -+ LWIP_DEBUGF(SOCKETS_DEBUG, -+ ("lwip_getsockopt(%d, %s, SO_TYPE): unrecognized socket type %d\n", -+ s, (NETCONN_PACKET_RAW != NETCONNTYPE_GROUP(sock->conn->type)) ? "SOL_SOCKET" : "SOL_PACKET", -+ *(int *)optval)); -+#else - LWIP_DEBUGF(SOCKETS_DEBUG, - ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", - s, *(int *)optval)); -+#endif - } /* 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 @@ - return err; - } - --int --lwip_ioctl(int s, long cmd, void *argp) -+#if PF_PACKET_SOCKET || LOSCFG_COMPONENTS_UPNP -+#if LWIP_IOCTL_IF -+static u8_t lwip_ioctl_internal_SIOCGIFCONF(struct ifreq *ifr) -+{ -+ struct ifconf *ifc = NULL; -+ struct netif *netif = NULL; -+ struct ifreq ifreq; -+ struct sockaddr_in *sock_in = NULL; -+ int pos; -+ int len; -+ int ret; -+ -+ /* Format the caller's buffer. */ -+ ifc = (struct ifconf*)ifr; -+ len = ifc->ifc_len; -+ -+ /* Loop over the interfaces, and write an info block for each. */ -+ pos = 0; -+ for (netif = netif_list; netif != NULL; netif = netif->next) { -+ if (ifc->ifc_buf == NULL) { -+ pos = (pos + (int)sizeof(struct ifreq)); -+ continue; -+ } -+ -+ if (len < (int)sizeof(ifreq)) { -+ break; -+ } -+ -+ if (memset_s(&ifreq, sizeof(struct ifreq), 0, sizeof(struct ifreq)) != EOK) { -+ return ENOBUFS; -+ } -+ if (netif->link_layer_type == LOOPBACK_IF) { -+ ret = snprintf_s(ifreq.ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s", netif->name); -+ if ((ret <= 0) || (ret >= IFNAMSIZ)) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed.")); -+ return ENOBUFS; -+ } -+ } else { -+ ret = snprintf_s(ifreq.ifr_name, NETIF_NAMESIZE, NETIF_NAMESIZE - 1, "%s%"U8_F, netif->name, netif->num); -+ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed.")); -+ return ENOBUFS; -+ } -+ } -+ -+ sock_in = (struct sockaddr_in *)&ifreq.ifr_addr; -+ sock_in->sin_family = AF_INET; -+ sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr; -+ if (memcpy_s(ifc->ifc_buf + pos, sizeof(struct ifreq), &ifreq, sizeof(struct ifreq)) != EOK) { -+ return ENOBUFS; -+ } -+ pos += (int)sizeof(struct ifreq); -+ len -= (int)sizeof(struct ifreq); -+ } -+ -+ ifc->ifc_len = pos; -+ -+ return 0; -+} -+ -+static u8_t lwip_ioctl_internal_SIOCGIFADDR(struct ifreq *ifr) -+{ -+ struct netif *netif = NULL; -+ struct sockaddr_in *sock_in = NULL; -+ -+ /* get netif ipaddr */ -+ netif = netif_find(ifr->ifr_name); -+ if (netif == NULL) { -+ return ENODEV; -+ } else { -+ sock_in = (struct sockaddr_in *)&ifr->ifr_addr; -+ sock_in->sin_family = AF_INET; -+ sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr; -+ return 0; -+ } -+} -+ -+static u8_t lwip_ioctl_internal_SIOCSIFFLAGS(const struct ifreq *ifr) -+{ -+ struct netif *netif = NULL; -+ -+ /* set netif hw addr */ -+ netif = netif_find(ifr->ifr_name); -+ if (netif == NULL) { -+ return ENODEV; -+ } -+#if LWIP_HAVE_LOOPIF -+ else if (netif->link_layer_type == LOOPBACK_IF) { -+ return EPERM; -+ } -+#endif /* LWIP_HAVE_LOOPIF */ -+ else { -+ if ((ifr->ifr_flags & IFF_UP) && !(netif->flags & NETIF_FLAG_UP)) { -+ (void)netif_set_up(netif); -+ } else if (!(ifr->ifr_flags & IFF_UP) && (netif->flags & NETIF_FLAG_UP)) { -+ (void)netif_set_down(netif); -+ } -+ if ((ifr->ifr_flags & IFF_RUNNING) && !(netif->flags & NETIF_FLAG_LINK_UP)) { -+ (void)netif_set_link_up(netif); -+ } else if (!(ifr->ifr_flags & IFF_RUNNING) && (netif->flags & NETIF_FLAG_LINK_UP)) { -+ (void)netif_set_link_down(netif); -+ } -+ -+ if (ifr->ifr_flags & IFF_BROADCAST) { -+ netif->flags |= NETIF_FLAG_BROADCAST; -+ } else { -+ netif->flags = netif->flags & (~NETIF_FLAG_BROADCAST); -+ } -+ if (ifr->ifr_flags & IFF_NOARP) { -+ netif->flags = (netif->flags & (~NETIF_FLAG_ETHARP)); -+ } else { -+ netif->flags |= NETIF_FLAG_ETHARP; -+ } -+ -+ if (ifr->ifr_flags & IFF_MULTICAST) { -+#if LWIP_IGMP -+ netif->flags |= NETIF_FLAG_IGMP; -+#endif /* LWIP_IGMP */ -+#if LWIP_IPV6 && LWIP_IPV6_MLD -+ netif->flags |= NETIF_FLAG_MLD6; -+#endif /* LWIP_IPV6_MLD */ -+ } -+ else { -+#if LWIP_IGMP -+ netif->flags = (netif->flags & ~NETIF_FLAG_IGMP); -+#endif /* LWIP_IGMP */ -+#if LWIP_IPV6 && LWIP_IPV6_MLD -+ netif->flags = (netif->flags & ~NETIF_FLAG_MLD6); -+#endif /* LWIP_IPV6_MLD */ -+ } -+ -+#if 0 -+ if (ifr->ifr_flags & IFF_DYNAMIC) { -+ (void)dhcp_start(netif); -+ } else { -+ dhcp_stop(netif); -+ dhcp_cleanup(netif); -+ } -+#endif -+ -+ return 0; -+ } -+} -+ -+static u8_t lwip_ioctl_internal_SIOCGIFFLAGS(struct ifreq *ifr) -+{ -+ struct netif *netif = NULL; -+ -+ /* set netif hw addr */ -+ netif = netif_find(ifr->ifr_name); -+ if (netif == NULL) { -+ return ENODEV; -+ } else { -+ if (netif->flags & NETIF_FLAG_UP) { -+ ifr->ifr_flags |= IFF_UP; -+ } else { -+ ifr->ifr_flags &= ~IFF_UP; -+ } -+ if (netif->flags & NETIF_FLAG_LINK_UP) { -+ ifr->ifr_flags |= IFF_RUNNING; -+ } else { -+ ifr->ifr_flags &= ~IFF_RUNNING; -+ } -+ if (netif->flags & NETIF_FLAG_BROADCAST) { -+ ifr->ifr_flags |= IFF_BROADCAST; -+ } else { -+ ifr->ifr_flags &= ~IFF_BROADCAST; -+ } -+ if (netif->flags & NETIF_FLAG_ETHARP) { -+ ifr->ifr_flags &= ~IFF_NOARP; -+ } else { -+ ifr->ifr_flags |= IFF_NOARP; -+ } -+ -+#if LWIP_IGMP || LWIP_IPV6_MLD -+ if ( -+#if LWIP_IGMP -+ (netif->flags & NETIF_FLAG_IGMP) -+#endif /* LWIP_IGMP */ -+#if LWIP_IGMP && LWIP_IPV6_MLD -+ || -+#endif /* LWIP_IGMP && LWIP_IPV6_MLD */ -+#if LWIP_IPV6_MLD -+ (netif->flags & NETIF_FLAG_MLD6) -+#endif /* LWIP_IPV6_MLD */ -+ ) { -+ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_MULTICAST); -+ } else { -+ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_MULTICAST)); -+ } -+#endif /* LWIP_IGMP || LWIP_IPV6_MLD */ -+ -+#if LWIP_DHCP -+ if (netif->flags & NETIF_FLAG_DHCP) { -+ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_DYNAMIC); -+ } else { -+ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_DYNAMIC)); -+ } -+#endif -+ -+#if LWIP_HAVE_LOOPIF -+ if (netif->link_layer_type == LOOPBACK_IF) { -+ ifr->ifr_flags |= IFF_LOOPBACK; -+ } -+#endif -+ -+ return 0; -+ } -+} -+ -+static u8_t lwip_ioctl_internal_SIOCGIFNAME(struct ifreq *ifr) -+{ -+ struct netif *netif = NULL; -+ int ret; -+ -+ for (netif = netif_list; netif != NULL; netif = netif->next) { -+ if (ifr->ifr_ifindex == netif->ifindex) { -+ break; -+ } -+ } -+ -+ if (netif == NULL) { -+ return ENODEV; -+ } -+ if (netif->link_layer_type == LOOPBACK_IF) { -+ ret = snprintf_s(ifr->ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s", netif->name); -+ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { -+ return ENOBUFS; -+ } -+ } else { -+ ret = snprintf_s(ifr->ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s%"U8_F, netif->name, netif->num); -+ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { -+ return ENOBUFS; -+ } -+ } -+ return 0; -+} -+ -+static u8_t lwip_ioctl_internal_SIOCGIFINDEX(struct ifreq *ifr) -+{ -+ struct netif *netif = NULL; -+ netif = netif_find(ifr->ifr_name); -+ if (netif == NULL) { -+ return ENODEV; -+ } -+ ifr->ifr_ifindex = netif->ifindex; -+ return 0; -+} -+#endif /* LWIP_IOCTL_IF */ -+#endif /* PF_PACKET_SOCKET */ -+ -+#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE -+static u8_t lwip_ioctl_internal_FIONREAD(struct lwip_sock *sock, void *argp) - { -- struct lwip_sock *sock = get_socket(s); -- u8_t val; - #if LWIP_SO_RCVBUF - int recv_avail; --#endif /* LWIP_SO_RCVBUF */ -+#endif -+#if LWIP_FIONREAD_LINUXMODE -+ SYS_ARCH_DECL_PROTECT(lev); -+#endif - -- if (!sock) { -- return -1; -+ if (!argp) { -+ return EINVAL; - } - -- switch (cmd) { --#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE -- case FIONREAD: -- if (!argp) { -- sock_set_errno(sock, EINVAL); -- done_socket(sock); -- return -1; -- } -+ lwip_sock_lock(sock); - #if LWIP_FIONREAD_LINUXMODE -- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { -- struct netbuf *nb; -- if (sock->lastdata.netbuf) { -- nb = sock->lastdata.netbuf; -- *((int *)argp) = nb->p->tot_len; -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { -+ struct netbuf *nb; -+ if (sock->lastdata.netbuf) { -+ nb = sock->lastdata.netbuf; -+ *((int *)argp) = nb->p->tot_len; -+ } else { -+ struct netbuf *rxbuf; -+ err_t err; -+ -+ SYS_ARCH_PROTECT(lev); -+ if (sock->rcvevent <= 0) { -+ *((int*)argp) = 0; -+ SYS_ARCH_UNPROTECT(lev); -+ } else { -+ SYS_ARCH_UNPROTECT(lev); -+ err = netconn_recv_udp_raw_netbuf_flags(sock->conn, &rxbuf, NETCONN_DONTBLOCK); -+ if (err != ERR_OK) { -+ *((int *)argp) = 0; - } else { -- struct netbuf *rxbuf; -- err_t err = netconn_recv_udp_raw_netbuf_flags(sock->conn, &rxbuf, NETCONN_DONTBLOCK); -- if (err != ERR_OK) { -- *((int *)argp) = 0; -- } else { -- sock->lastdata.netbuf = rxbuf; -- *((int *)argp) = rxbuf->p->tot_len; -- } -+ sock->lastdata.netbuf = rxbuf; -+ *((int *)argp) = rxbuf->p->tot_len; - } -- done_socket(sock); -- return 0; - } -+ } -+ -+ lwip_sock_unlock(sock); -+ return 0; -+ } - #endif /* LWIP_FIONREAD_LINUXMODE */ - - #if LWIP_SO_RCVBUF -- /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ -- SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); -- if (recv_avail < 0) { -- recv_avail = 0; -- } -+ /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ -+ SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); -+ if (recv_avail < 0) { -+ recv_avail = 0; -+ } - -- /* Check if there is data left from the last recv operation. /maq 041215 */ -- if (sock->lastdata.netbuf) { -- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { -- recv_avail += sock->lastdata.pbuf->tot_len; -- } else { -- recv_avail += sock->lastdata.netbuf->p->tot_len; -- } -- } -- *((int *)argp) = recv_avail; -+ /* Check if there is data left from the last recv operation. /maq 041215 */ -+ if (sock->lastdata.netbuf) { -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { -+ recv_avail += sock->lastdata.pbuf->tot_len; -+ } else { -+ recv_avail += sock->lastdata.netbuf->p->tot_len; -+ } -+ } -+ *((int *)argp) = recv_avail; - -- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t *)argp))); -- sock_set_errno(sock, 0); -- done_socket(sock); -- return 0; -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(FIONREAD, %p) = %"U16_F"\n", argp, *((u16_t *)argp))); -+ lwip_sock_unlock(sock); -+ return 0; - #else /* LWIP_SO_RCVBUF */ -- break; -+ lwip_sock_unlock(sock); -+ return ENOSYS; - #endif /* LWIP_SO_RCVBUF */ -+} - #endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ - -- case (long)FIONBIO: -- val = 0; -- if (argp && *(int *)argp) { -- val = 1; -+static u8_t lwip_ioctl_internal_FIONBIO(struct lwip_sock *sock, const void *argp) -+{ -+ u8_t val = 0; -+ SYS_ARCH_DECL_PROTECT(lev); -+ if (argp == NULL) { -+ return EINVAL; -+ } -+ if (*(int *)argp) { -+ val = 1; -+ } -+ SYS_ARCH_PROTECT(lev); -+ netconn_set_nonblocking(sock->conn, val); -+ SYS_ARCH_UNPROTECT(lev); -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(FIONBIO, %d)\n", val)); -+ return 0; -+} -+ -+static u8_t lwip_ioctl_impl(struct lwip_sock *sock, long cmd, void *argp) -+{ -+ u8_t err = 0; -+#if LWIP_NETIF_ETHTOOL -+ s32_t ret; -+#endif -+#if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_IF || LWIP_NETIF_ETHTOOL -+ struct ifreq *ifr = (struct ifreq *)argp; -+#endif -+#if LWIP_IOCTL_ROUTE -+ struct rtentry *rmten = (struct rtentry *)argp; -+#endif -+#if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_ROUTE || LWIP_IOCTL_IF -+ u8_t is_ipv6 = NETCONNTYPE_ISIPV6(sock->conn->type); -+#endif -+ -+ LWIP_ASSERT("no socket given", sock != NULL); -+ -+ switch (cmd) { -+#if PF_PACKET_SOCKET || LOSCFG_COMPONENTS_UPNP -+#if LWIP_IOCTL_IF -+ case SIOCGIFCONF: -+ /* Do not allow if socket is AF_INET6 */ -+ if (is_ipv6) { -+ err = EINVAL; -+ } else { -+ err = lwip_ioctl_internal_SIOCGIFCONF(ifr); //add: SIOCGIFCONF - } -- netconn_set_nonblocking(sock->conn, val); -- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); -- sock_set_errno(sock, 0); -- done_socket(sock); -- return 0; -+ break; -+ case SIOCGIFADDR: -+ if (is_ipv6) { -+ err = EINVAL; -+ } else { -+ err = lwip_ioctl_internal_SIOCGIFADDR(ifr); //add: SIOCGIFADDR -+ } -+ break; -+ case SIOCSIFFLAGS: -+ err = lwip_ioctl_internal_SIOCSIFFLAGS(ifr); //add: SIOCSIFFLAGS -+ break; -+ case SIOCGIFFLAGS: -+ err = lwip_ioctl_internal_SIOCGIFFLAGS(ifr); //add: SIOCSIFFLAGS -+ break; -+ case SIOCGIFNAME: -+ err = lwip_ioctl_internal_SIOCGIFNAME(ifr); //add: SIOCGIFNAME -+ break; -+ /* Need to support the get index through ioctl -+ * As of now the options is restricted to PF_PACKET scenario , so removed the compiler flag Begin -+ */ -+ case SIOCGIFINDEX: -+ err = lwip_ioctl_internal_SIOCGIFINDEX(ifr); //add: SIOCGIFINDEX -+ break; -+#endif /* LWIP_IOCTL_IF */ -+#else -+ (void)ifr; -+ (void)is_ipv6; -+#endif /* PF_PACKET_SOCKET */ -+#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE -+ case FIONREAD: -+ err = lwip_ioctl_internal_FIONREAD(sock, argp); -+ break; -+#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ - -+ case FIONBIO: -+ err = lwip_ioctl_internal_FIONBIO(sock, argp); -+ break; -+ /* -1 should return EINVAL */ -+ case -1: -+ err = EINVAL; -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl_impl(INVALID: 0x%lx)\n", cmd)); -+ break; - default: -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(UNIMPL: 0x%lx, %p)\n", cmd, argp)); -+ err = ENOSYS; /* not yet implemented */ - break; - } /* switch (cmd) */ -- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); -- sock_set_errno(sock, ENOSYS); /* not yet implemented */ -+ -+ return err; -+} -+ -+int -+lwip_ioctl(int s, long cmd, void *argp) -+{ -+ u8_t err; -+ struct lwip_sock *sock = get_socket(s); -+ if (!sock) { -+ /* get_socket has updated errno */ -+ return -1; -+ } -+ if (argp == NULL) { -+ sock_set_errno(sock, EFAULT); -+ done_socket(sock); -+ return -1; -+ } -+ -+ LOCK_TCPIP_CORE(); -+ err = lwip_ioctl_impl(sock, cmd, argp); -+ UNLOCK_TCPIP_CORE(); -+ if (err != ERR_OK) { -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, cmd: 0x%lx, %p)\n", s, cmd, argp)); -+ sock_set_errno(sock, err); -+ } - done_socket(sock); -- return -1; -+ return (err == 0) ? 0 : -1; - } - - /** A minimal implementation of fcntl. -@@ -3878,7 +4574,6 @@ - - /* ensure O_RDWR for (O_RDONLY|O_WRONLY) != O_RDWR cases */ - ret |= (op_mode == (O_RDONLY | O_WRONLY)) ? O_RDWR : op_mode; -- - break; - 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 -@@ -201,7 +201,7 @@ - } - - static void --recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -+tftp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) - { - u16_t *sbuf = (u16_t *) p->payload; - int opcode; -@@ -416,7 +416,7 @@ - tftp_state.last_data = NULL; - tftp_state.upcb = pcb; - -- udp_recv(pcb, recv, NULL); -+ udp_recv(pcb, tftp_recv, NULL); - - return ERR_OK; - } -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 @@ - int - ipaddr_aton(const char *cp, ip_addr_t *addr) - { -- if (cp != NULL) { -+ if (cp != NULL && addr != NULL) { - const char *c; - for (c = cp; *c != 0; c++) { - if (*c == ':') { - /* contains a colon: IPv6 address */ -- if (addr) { -- IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); -- } -+ IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); - return ip6addr_aton(cp, ip_2_ip6(addr)); - } else if (*c == '.') { - /* contains a dot: IPv4 address */ -@@ -137,9 +135,7 @@ - } - } - /* call ip4addr_aton as fallback or if IPv4 was found */ -- if (addr) { -- IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); -- } -+ IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); - return ip4addr_aton(cp, ip_2_ip4(addr)); - } - return 0; -@@ -164,4 +160,63 @@ - - #endif /* LWIP_IPV4 && LWIP_IPV6 */ - -+struct netif* -+ip_route_pcb(const ip_addr_t *dest, const struct ip_pcb* pcb) -+{ -+ struct netif *netif = NULL; -+#if LWIP_SO_DONTROUTE -+ rt_scope_t scope = RT_SCOPE_UNIVERSAL; -+ -+ LWIP_ASSERT("Expecting ipaddr to be not NULL ", dest != NULL); -+ if (pcb != NULL) { -+ scope = ip_get_option(pcb, SOF_DONTROUTE) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSAL; -+ } -+#endif -+ -+ if ((pcb != NULL) && (pcb->netif_idx != NETIF_NO_INDEX)) { -+ return netif_find_by_ifindex(pcb->netif_idx); -+ } -+ -+ if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { -+ /* Don't call ip_route() with IP_ANY_TYPE */ -+ netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(dest)), dest); -+ } else { -+ netif = ip_route(&pcb->local_ip, dest); -+ } -+ -+ if (netif == NULL) { -+ return NULL; -+ } -+ -+#if LWIP_SO_DONTROUTE -+ if (netif->scope < scope) { -+ return NULL; -+ } -+#endif -+ return netif; -+} -+ -+#if LWIP_INET_ADDR_FUNC -+in_addr_t inet_addr(const char *cp) -+{ -+ LWIP_ERROR("inet_aton:cp is NULL", (cp != NULL), return (INADDR_NONE)); -+ return ipaddr_addr(cp); -+} -+#endif -+ -+#if LWIP_INET_ATON_FUNC -+int inet_aton(const char *cp, struct in_addr *inp) -+{ -+ LWIP_ERROR("inet_aton:cp is NULL", (cp != NULL), return 0); -+ return ip4addr_aton(cp, (ip4_addr_t *)inp); -+} -+#endif -+ -+#if LWIP_INET_NTOA_FUNC -+char* inet_ntoa(struct in_addr in) -+{ -+ return ip4addr_ntoa((const ip4_addr_t *)&in); -+} -+#endif -+ - #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 -@@ -82,14 +82,14 @@ - void - icmp6_input(struct pbuf *p, struct netif *inp) - { -- struct icmp6_hdr *icmp6hdr; -+ struct icmpv6_hdr *icmp6hdr; - struct pbuf *r; - const ip6_addr_t *reply_src; - - ICMP6_STATS_INC(icmp6.recv); - - /* Check that ICMPv6 header fits in payload */ -- if (p->len < sizeof(struct icmp6_hdr)) { -+ if (p->len < sizeof(struct icmpv6_hdr)) { - /* drop short packets */ - pbuf_free(p); - ICMP6_STATS_INC(icmp6.lenerr); -@@ -97,7 +97,7 @@ - return; - } - -- icmp6hdr = (struct icmp6_hdr *)p->payload; -+ icmp6hdr = (struct icmpv6_hdr *)p->payload; - - #if CHECKSUM_CHECK_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP6) { -@@ -386,10 +386,10 @@ - const ip6_addr_t *reply_src, const ip6_addr_t *reply_dest, struct netif *netif) - { - struct pbuf *q; -- struct icmp6_hdr *icmp6hdr; -+ struct icmpv6_hdr *icmp6hdr; - - /* ICMPv6 header + IPv6 header + data */ -- q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, -+ q = pbuf_alloc(PBUF_IP, sizeof(struct icmpv6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, - PBUF_RAM); - if (q == NULL) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n")); -@@ -397,15 +397,15 @@ - return; - } - LWIP_ASSERT("check that first pbuf can hold icmp 6message", -- (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); -+ (q->len >= (sizeof(struct icmpv6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); - -- icmp6hdr = (struct icmp6_hdr *)q->payload; -+ icmp6hdr = (struct icmpv6_hdr *)q->payload; - icmp6hdr->type = type; - icmp6hdr->code = code; - icmp6hdr->data = lwip_htonl(data); - - /* copy fields from original packet */ -- SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload, -+ SMEMCPY((u8_t *)q->payload + sizeof(struct icmpv6_hdr), (u8_t *)p->payload, - IP6_HLEN + LWIP_ICMP6_DATASIZE); - - /* 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 -@@ -894,13 +894,13 @@ - } - case ICMP6_TYPE_PTB: /* Packet too big */ - { -- struct icmp6_hdr *icmp6hdr; /* Packet too big message */ -+ struct icmpv6_hdr *icmp6hdr; /* Packet too big message */ - struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */ - u32_t pmtu; - ip6_addr_t destination_address; - - /* Check that ICMPv6 header + IPv6 header fit in payload */ -- if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { -+ if (p->len < (sizeof(struct icmpv6_hdr) + IP6_HLEN)) { - /* drop short packets */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); -@@ -908,8 +908,8 @@ - return; - } - -- icmp6hdr = (struct icmp6_hdr *)p->payload; -- ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); -+ icmp6hdr = (struct icmpv6_hdr *)p->payload; -+ ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmpv6_hdr)); - - /* 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 -@@ -89,6 +89,8 @@ - #if LWIP_IPV6 - #include "lwip/nd6.h" - #endif -+#include "lwip/tcpip.h" -+ - - #if LWIP_NETIF_STATUS_CALLBACK - #define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) -@@ -229,6 +231,8 @@ - return ip_input(p, inp); - } - -+static u8_t netif_alloc_ifindex(void); -+ - /** - * @ingroup netif - * Add a network interface to the list of lwIP netifs. -@@ -377,36 +381,23 @@ - netif->mtu6 = netif->mtu; - #endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ - -+ /* -+ * Need to support the get index for all families -+ * removed PF_PACKET_SOCKET flag , as this flags restricts the usage to only PF_FAMILY -+ */ -+ netif->ifindex = netif_alloc_ifindex(); -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif: netif->ifindex=%d", netif->ifindex)); -+ if ((netif->ifindex < LWIP_NETIF_IFINDEX_START) || (netif->ifindex > LWIP_NETIF_IFINDEX_MAX)) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif: interface index alloc fail")); -+ return NULL; -+ } -+ - #if !LWIP_SINGLE_NETIF - /* Assign a unique netif number in the range [0..254], so that (num+1) can - serve as an interface index that fits in a u8_t. - We assume that the new netif has not yet been added to the list here. - This algorithm is O(n^2), but that should be OK for lwIP. - */ -- { -- struct netif *netif2; -- int num_netifs; -- do { -- if (netif->num == 255) { -- netif->num = 0; -- } -- num_netifs = 0; -- for (netif2 = netif_list; netif2 != NULL; netif2 = netif2->next) { -- LWIP_ASSERT("netif already added", netif2 != netif); -- num_netifs++; -- LWIP_ASSERT("too many netifs, max. supported number is 255", num_netifs <= 255); -- if (netif2->num == netif->num) { -- netif->num++; -- break; -- } -- } -- } while (netif2 != NULL); -- } -- if (netif->num == 254) { -- netif_num = 0; -- } else { -- netif_num = (u8_t)(netif->num + 1); -- } - - /* add this netif to the list */ - netif->next = netif_list; -@@ -421,8 +412,8 @@ - } - #endif /* LWIP_IGMP */ - -- LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", -- netif->name[0], netif->name[1])); -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %s IP", -+ netif->name)); - #if LWIP_IPV4 - LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); - ip4_addr_debug_print(NETIF_DEBUG, ipaddr); -@@ -818,7 +809,7 @@ - * - * @param netif the default network interface - */ --void -+err_t - netif_set_default(struct netif *netif) - { - LWIP_ASSERT_CORE_LOCKED(); -@@ -833,6 +824,7 @@ - netif_default = netif; - LWIP_DEBUGF(NETIF_DEBUG, ("netif: setting default interface %c%c\n", - netif ? netif->name[0] : '\'', netif ? netif->name[1] : '\'')); -+ return ERR_OK; - } - - /** -@@ -1206,6 +1198,11 @@ - struct netif *stats_if = netif; - #endif /* LWIP_HAVE_LOOPIF */ - #endif /* MIB2_STATS */ -+#if PF_PACKET_SOCKET -+ struct raw_pcb *pcb; -+ int match = 0; -+#endif /* PF_PACKET_SOCKET */ -+ - SYS_ARCH_DECL_PROTECT(lev); - - LWIP_ASSERT("netif_poll: invalid netif", netif != NULL); -@@ -1251,6 +1248,31 @@ - LINK_STATS_INC(link.recv); - MIB2_STATS_NETIF_ADD(stats_if, ifinoctets, in->tot_len); - MIB2_STATS_NETIF_INC(stats_if, ifinucastpkts); -+ -+#if PF_PACKET_SOCKET -+ for (pcb = get_packet_raw_pcbs(); pcb != NULL; pcb = pcb->next) { -+ if (((pcb->proto.eth_proto == htons(ETHTYPE_ALL)) || (pcb->proto.eth_proto == htons(ETHTYPE_IP))) && -+ ((!pcb->netifindex) || (pcb->netifindex == netif->ifindex))) { -+ match = 1; -+ break; -+ } -+ } -+ -+ /* always succeed because the alloc layer of loopback pbuf was PBUF_LINK */ -+ if (match && pbuf_header(in, PBUF_LINK_HLEN) == 0) { -+ struct eth_hdr *ethhdr; -+ /* add ethernet header */ -+ ethhdr = (struct eth_hdr *)(in->payload); -+ /* smac and dmac set to all zeros for loopback IP packet */ -+ (void)memset_s(ethhdr, sizeof(struct eth_hdr), 0, sizeof(struct eth_hdr)); -+ ethhdr->type = htons(ETHTYPE_IP); /* eth protocol, should be ETH_P_IP(0x800) */ -+ in->flags = (u16_t)(in->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_OUTGOING)); -+ in->flags |= PBUF_FLAG_HOST; -+ raw_packet_input(in, netif, NULL); -+ (void)pbuf_header(in, -PBUF_LINK_HLEN); -+ } -+#endif /* PF_PACKET_SOCKET */ -+ - /* loopback packets are always IP packets! */ - if (ip_input(in, netif) != ERR_OK) { - pbuf_free(in); -@@ -1700,29 +1722,68 @@ - struct netif * - netif_find(const char *name) - { -- struct netif *netif; -- u8_t num; -- -- LWIP_ASSERT_CORE_LOCKED(); -- -- if (name == NULL) { -- return NULL; -- } -+ struct netif *netif = NULL; -+ char candidate_name[NETIF_NAMESIZE]; -+ int ret; - -- num = (u8_t)atoi(&name[2]); -+ LWIP_ERROR("netif_find : invalid value.", (name != NULL), return NULL); - - NETIF_FOREACH(netif) { -- if (num == netif->num && -- name[0] == netif->name[0] && -- name[1] == netif->name[1]) { -- LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); -+ if (strncmp(name, netif->name, NETIF_NAMESIZE) == 0) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %s\n", name)); - return netif; - } -+ -+ if (netif->link_layer_type != LOOPBACK_IF) { -+ ret = snprintf_s(candidate_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s%"U8_F, netif->name, netif->num); -+ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: name '%s'is too long\n", netif->name)); -+ continue; -+ } -+ if (strncmp(name, candidate_name, NETIF_NAMESIZE) == 0) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %s\n", name)); -+ return netif; -+ } -+ } - } -- LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %s\n", name)); - return NULL; - } - -+/* -+ * Change mtu setting for a network interface -+ * -+ * @param netif the network interface to change -+ * @param netif_mtu the new MTU for the interface -+ */ -+ -+err_t -+netif_set_mtu_api(struct netif *netif, u16_t netif_mtu) -+{ -+ /* As per RFC 791, "Every internet module must be able to forward a datagram of 68 -+ * octets without further fragmentation. This is because an internet header -+ * may be up to 60 octets, and the minimum fragment is 8 octets." */ -+ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif != NULL), return ERR_VAL); -+ -+#if LWIP_IPV6 -+ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif_mtu >= NETIF_MTU_MIN) && (netif_mtu <= IP_FRAG_MAX_MTU), -+ return ERR_ARG); -+#else -+ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif_mtu >= IP_FRAG_MIN_MTU) && (netif_mtu <= IP_FRAG_MAX_MTU), -+ return ERR_ARG); -+#endif -+ -+ netif->mtu = netif_mtu; -+#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES -+ netif->mtu6 = netif_mtu; -+#endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ -+ -+ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif: MTU of interface %s%"U16_F" is changed to %d\n", -+ netif->name, netif->num, netif->mtu)); -+ -+ return ERR_OK; -+} -+ - #if LWIP_NETIF_EXT_STATUS_CALLBACK - /** - * @ingroup netif -@@ -1793,3 +1854,213 @@ - } - } - #endif /* LWIP_NETIF_EXT_STATUS_CALLBACK */ -+ -+struct netif * -+netif_find_by_ipaddr(const ip_addr_t *ipaddr) -+{ -+ LWIP_ERROR("netif_find_by_ipaddr : invalid arguments", (ipaddr != NULL), return NULL); -+#if LWIP_IPV4 -+ if (IP_IS_V4(ipaddr)) { -+ return netif_find_by_ip4addr(ipaddr); -+ } -+#endif -+ -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ipaddr: didn't find\n")); -+ return NULL; -+} -+ -+void -+netif_get_hwaddr(const struct netif *netif, unsigned char *hw_addr, int hw_len) -+{ -+ int i; -+ LWIP_ERROR("netif_get_hwaddr : invalid arguments", (netif != NULL), return); -+ -+ LWIP_ERROR("netif_get_hwaddr : invalid arguments", (hw_addr != NULL), return); -+ -+ LWIP_ERROR("netif_get_hwaddr: invalid arguments", -+ ((unsigned int)hw_len == NETIF_MAX_HWADDR_LEN), return); -+ -+ for (i = 0; i < hw_len; i++) { -+ hw_addr[i] = netif->hwaddr[i]; -+ } -+} -+ -+/* -+ * Change the hardware address for a network interface -+ * -+ * NOTE:Application should call set_link_down before calling -+ * the netif_set_hwaddr and then set_link_up, in order -+ * to ensure that all IPs are announced after changing -+ * hw address -+ * -+ * @param netif the network interface to change -+ * @param hw_addr the new hardware address -+ * @param hw_len the length of new hardware address, -+ * -+ */ -+err_t -+netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw_len) -+{ -+ LWIP_ERROR("netif_set_hwaddr : invalid arguments", (netif != NULL), return ERR_VAL); -+ -+ LWIP_ERROR("netif_set_hwaddr : invalid arguments", (hw_addr != NULL), return ERR_VAL); -+ -+ LWIP_ERROR("netif_set_hwaddr: invalid arguments", -+ ((unsigned int)hw_len == NETIF_MAX_HWADDR_LEN), return ERR_VAL); -+ -+ if (netif->drv_set_hwaddr == NULL) { -+ return ERR_OPNOTSUPP; -+ } -+ -+ if (netif->drv_set_hwaddr(netif, (u8_t *)hw_addr, hw_len) != ERR_OK) { -+ return ERR_VAL; -+ } -+ -+ if (memcpy_s(netif->hwaddr, NETIF_MAX_HWADDR_LEN, hw_addr, (u32_t)hw_len) != EOK) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_set_hwaddr: memcpy_s error\n")); -+ return ERR_VAL; -+ } -+ -+ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, -+ ("netif: HW address of interface %s%"U16_F" set to %02X:%02X:%02X:%02X:%02X:%02X\n", -+ netif->name, netif->num, -+ netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], -+ netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5])); -+ -+ return ERR_OK; -+} -+ -+#if LWIP_IPV4 -+/* -+ * Find a network interface by searching for its ipaddress -+ * -+ * @param ipaddr IP_add of the netif -+ * @return netif if the its found -+ * NULL if there is no netif with ipaddr -+ */ -+struct netif * -+netif_find_by_ip4addr(const ip_addr_t *ipaddr) -+{ -+ struct netif *netif = NULL; -+ -+ LWIP_ASSERT("Expecting ipaddr to be not NULL ", ipaddr != NULL); -+ -+ for (netif = netif_list; netif != NULL; netif = netif->next) { -+ if (ip_addr_cmp(&(netif->ip_addr), ipaddr)) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ipaddr: found\n")); -+ return netif; -+ } -+ } -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ip4addr: didn't find\n")); -+ return NULL; -+} -+ -+s8_t netif_find_dst_ipaddr(const ip_addr_t *ipaddr, ip_addr_t **dst_addr) -+{ -+ struct netif *netif = NULL; -+ ip_addr_t *pdst_addr = NULL; -+ -+ pdst_addr = *dst_addr; -+ netif = netif_find_by_ipaddr(ipaddr); -+ if (netif == NULL) { -+ return -1; -+ } -+ if ((pdst_addr != NULL) && (!ip_addr_netcmp(pdst_addr, &(netif->ip_addr), ip_2_ip4(&netif->netmask))) && -+ !ip_addr_islinklocal(pdst_addr)) { -+ if (!ip_addr_isany(&netif->gw)) { -+ *dst_addr = &(netif->gw); -+ } -+ } -+ -+ return 0; -+} -+#endif /* LWIP_IPV4 */ -+ -+ -+ -+#if LWIP_DHCP -+/* -+ * Close DHCP and set static network. -+ * -+ * @param netif a pre-allocated netif structure -+ * -+ * @return ERR_OK, or ERR_VAL if failed. -+ */ -+err_t -+netif_dhcp_off(struct netif *netif) -+{ -+ ip_addr_t old_ipaddr; -+ ip_addr_t old_netmask; -+ ip_addr_t old_gateway; -+ -+ if (netif == NULL) { -+ return ERR_VAL; -+ } -+ old_ipaddr = netif->ip_addr; -+ old_netmask = netif->netmask; -+ old_gateway = netif->gw; -+ -+ if (netif_dhcp_data(netif)) { -+ (void)dhcp_release(netif); -+ dhcp_stop(netif); -+ dhcp_cleanup(netif); -+ LWIP_DEBUGF(NETIF_DEBUG, ("DHCP is close;set static IP\n")); -+ } -+ -+ ip_addr_set_val(netif->ip_addr, old_ipaddr); -+ ip_addr_set_val(netif->netmask, old_netmask); -+ ip_addr_set_val(netif->gw, old_gateway); -+ (void)netif_set_up(netif); -+ -+ return ERR_OK; -+} -+#endif /* LWIP_DHCP */ -+ -+u8_t netif_ipaddr_isbrdcast(const ip_addr_t *ipaddr) -+{ -+ struct netif *netif = NULL; -+ -+ for (netif = netif_list; netif != NULL; netif = netif->next) { -+ if (netif_is_up(netif) && ip_addr_isbroadcast(ipaddr, netif)) { -+ return 1; -+ } -+ } -+ -+ return 0; -+} -+ -+struct netif * -+netif_find_by_ifindex(u8_t ifindex) -+{ -+ struct netif *netif = NULL; -+ -+ if (ifindex < LWIP_NETIF_IFINDEX_START) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: Invalid ifindex(%u) \n", ifindex)); -+ return netif; -+ } -+ -+ for (netif = netif_list; netif != NULL; netif = netif->next) { -+ if (netif->ifindex == ifindex) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: found\n")); -+ return netif; -+ } -+ } -+ -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: didn't find\n")); -+ return NULL; -+} -+ -+/* Need to support the get index for all families -+removed PF_PACKET_SOCKET flag , as this flags restricts the usage to only PF_FAMILY Begin */ -+static u8_t -+netif_alloc_ifindex(void) -+{ -+ u8_t tmp_index; -+ for (tmp_index = LWIP_NETIF_IFINDEX_START; tmp_index <= LWIP_NETIF_IFINDEX_MAX; tmp_index++) { -+ if (netif_get_by_index(tmp_index) == NULL) { -+ break; -+ } -+ } -+ -+ 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; -+ -+#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); -+ netif = ip_route_pcb(ipaddr, (struct ip_pcb*)pcb); - } - } - -@@ -387,7 +415,7 @@ - return ERR_RTE; - } - -- if (ip_addr_isany(&pcb->local_ip) || ip_addr_ismulticast(&pcb->local_ip)) { -+ if (ip_addr_isany(&pcb->local_ip) || ip_get_option(pcb, SOF_BINDNONUNICAST)) { - /* 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 @@ - #endif /* LWIP_MULTICAST_TX_OPTIONS */ - - NETIF_SET_HINTS(netif, &pcb->netif_hints); -- err = ip_output_if(q, src_ip, dst_ip, ttl, pcb->tos, pcb->protocol, netif); -+ err = ip_output_if(q, src_ip, dst_ip, ttl, pcb->tos, pcb->raw_proto, netif); - NETIF_RESET_HINTS(netif); - - /* did we chain a header earlier? */ -@@ -604,7 +632,12 @@ - if (pcb != NULL) { - /* initialize PCB to all zeroes */ - memset(pcb, 0, sizeof(struct raw_pcb)); -+#if PF_PACKET_SOCKET -+ pcb->proto.protocol = proto; -+#else - pcb->protocol = proto; -+#endif -+ - pcb->ttl = RAW_TTL; - #if LWIP_MULTICAST_TX_OPTIONS - raw_set_multicast_ttl(pcb, RAW_TTL); -@@ -668,4 +701,227 @@ - } - } - -+#if PF_PACKET_SOCKET -+void raw_packet_input(struct pbuf *p, const struct netif *inp, const struct raw_pcb *from) -+{ -+ struct raw_pcb *pcb = NULL; -+ struct eth_hdr *ethhdr = NULL; -+ u16_t proto; -+ -+ LWIP_UNUSED_ARG(inp); -+ -+ ethhdr = (struct eth_hdr *)p->payload; -+ proto = ethhdr->type; -+ -+ g_lwip_current_eth_hdr = ethhdr; -+ g_lwip_current_netif = inp; -+ -+ pcb = g_packet_raw_pcbs; -+ /* 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->proto.eth_proto == htons(ETHTYPE_ALL)) || ((p != NULL) && !(p->flags & PBUF_FLAG_OUTGOING) && -+ pcb->proto.eth_proto == proto)) && -+ ((!pcb->netifindex) || (pcb->netifindex == inp->ifindex)) && (pcb != from)) { -+ /* receive callback function available? */ -+ if (pcb->recv != NULL) { -+ /* the receive callback function did not eat the packet? */ -+ if (pcb->recv(pcb->recv_arg, pcb, p, NULL) != 0) { -+ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_input: packets recved failed \n")); -+ } -+ } -+ /* no receive callback function was set for this raw PCB */ -+ } -+ -+ pcb = pcb->next; -+ } -+ -+ g_lwip_current_eth_hdr = NULL; -+ return; -+} -+ -+err_t -+raw_packet_bind(struct raw_pcb *pcb, u8_t ifindex, u16_t proto) -+{ -+ struct netif *loc_netif = NULL; -+ -+ if (ifindex != 0) { -+ for (loc_netif = netif_list; loc_netif != NULL; loc_netif = loc_netif->next) { -+ if (ifindex == loc_netif->ifindex) { -+ break; -+ } -+ } -+ -+ /* Return if no matching netifs to bind */ -+ if (loc_netif == NULL) { -+ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_bind: No matching netif found for ifindex(%u)\n", ifindex)); -+ return ERR_NODEV; -+ } -+ } else { -+ return ERR_NODEV; -+ } -+ -+#if DRIVER_STATUS_CHECK -+ if (!netif_is_up(loc_netif) || !netif_is_ready(loc_netif)) -+#else -+ if (!netif_is_up(loc_netif)) -+#endif -+ { -+ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_bind: bind failed as netif (index %u) was down\n", ifindex)); -+ return ERR_NETDOWN; -+ } -+ -+ pcb->netifindex = ifindex; -+ pcb->proto.eth_proto = proto; -+ -+ return ERR_OK; -+} -+ -+/* -+ * Send the raw IP packet through the given netif driver. Note that actually you cannot -+ * modify the link layer header here. Packet need to be sent to driver as it is through the -+ * given netif -+ * @param pcb the raw pcb which to send -+ * @param p the ethernet packet to send -+ * @param ifindex the Interface index of the netif through which packet needs to be sent -+ */ -+err_t -+raw_packet_sendto(const struct raw_pcb *pcb, struct pbuf *p, u8_t ifindex) -+{ -+ struct netif *netif = NULL; -+ u8_t netifindex; -+ LWIP_UNUSED_ARG(pcb); -+ -+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_packet_sendto: ifindex=%d\n", ifindex)); -+ LWIP_ASSERT("p != NULL", p != NULL); -+ -+ netifindex = ifindex; -+ -+ if (ifindex == 0) { -+ if (pcb->netifindex != 0) { -+ netifindex = pcb->netifindex; -+ } else { -+ return ERR_NODEVADDR; -+ } -+ } -+ -+ /* Find the netif corresponding to the interface index */ -+ netif = netif_find_by_ifindex(netifindex); -+ if (netif == NULL) { -+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("netif not found for given ifindex (%u)\n", ifindex)); -+ return ERR_NODEVADDR; -+ } -+ -+#if DRIVER_STATUS_CHECK -+ if ((!netif_is_up(netif)) || (!netif_is_ready(netif))) -+#else -+ if ((!netif_is_up(netif))) -+#endif -+ { -+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("netif was down for given ifindex (%u)\n", ifindex)); -+ return ERR_NETDOWN; -+ } -+ -+ if ((p->tot_len - (SIZEOF_ETH_HDR - ETH_PAD_SIZE)) > netif->mtu) { -+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("Message too long (%u)\n", p->tot_len)); -+ return ERR_MSGSIZE; -+ } -+ -+ if (pbuf_header(p, ETH_PAD_SIZE) == 0) { -+ p->flags = (u16_t)(p->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_HOST)); -+ p->flags |= PBUF_FLAG_OUTGOING; -+ raw_packet_input(p, netif, pcb); -+ (void)pbuf_header(p, -ETH_PAD_SIZE); -+ } -+ -+ /* For RAW packets of PF_PACKET family, do not modify the packets as it is -+ already supposed to contain the link layer header. So send directly to the driver */ -+ LINK_STATS_INC(link.xmit); -+ return ERR_OK; -+} -+ -+/* -+ * Create a RAW PCB for Packet family. -+ * -+ * @return The RAW PCB which was created. NULL if the PCB data structure -+ * could not be allocated. -+ * -+ * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) -+ * -+ * @see raw_remove() -+ */ -+struct raw_pcb * -+raw_packet_new(u16_t proto) -+{ -+ struct raw_pcb *pcb = NULL; -+ -+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_packet_new\n")); -+ -+ pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); -+ /* could allocate RAW PCB? */ -+ if (pcb != NULL) { -+ /* initialize PCB to all zeroes */ -+ (void)memset(pcb, 0, sizeof(struct raw_pcb)); -+ pcb->proto.eth_proto = proto; -+ pcb->ttl = RAW_TTL; -+ pcb->next = g_packet_raw_pcbs; -+ g_packet_raw_pcbs = pcb; -+ pcb->all_next = g_all_packet_raw_pcbs; -+ g_all_packet_raw_pcbs = pcb; -+ } -+ return pcb; -+} -+ -+/* -+ * Remove an RAW PCB of packet family type -+ * -+ * @param pcb RAW PCB to be removed. The PCB is removed from the list of -+ * RAW PCB's and the data structure is freed from memory. -+ * -+ * @see raw_packet_new() -+ */ -+void -+raw_packet_remove(struct raw_pcb *pcb) -+{ -+ struct raw_pcb *pcb2 = NULL; -+ -+ /* NULL check */ -+ if (pcb == NULL) { -+ return; -+ } -+ -+ /* pcb to be removed is first in all_pkt list? */ -+ if (g_all_packet_raw_pcbs == pcb) { -+ /* make list start at 2nd pcb */ -+ g_all_packet_raw_pcbs = g_all_packet_raw_pcbs->all_next; -+ /* pcb not 1st in list */ -+ } else { -+ for (pcb2 = g_all_packet_raw_pcbs; pcb2 != NULL; pcb2 = pcb2->all_next) { -+ /* find pcb in g_all_packet_raw_pcbs list */ -+ if (pcb2->all_next == pcb) { -+ /* remove pcb from list */ -+ pcb2->all_next = pcb->all_next; -+ } -+ } -+ } -+ -+ /* pcb to be removed is first in list? */ -+ if (g_packet_raw_pcbs == pcb) { -+ /* make list start at 2nd pcb */ -+ g_packet_raw_pcbs = g_packet_raw_pcbs->next; -+ /* pcb not 1st in list */ -+ } else { -+ for (pcb2 = g_packet_raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { -+ /* find pcb in raw_pcbs list */ -+ if (pcb2->next == pcb) { -+ /* remove pcb from list */ -+ pcb2->next = pcb->next; -+ } -+ } -+ } -+ -+ memp_free(MEMP_RAW_PCB, pcb); -+} -+#endif /* PF_PACKET_SOCKET */ -+ - #endif /* LWIP_RAW */ -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 -@@ -48,6 +48,9 @@ - #include "lwip/sys.h" - #include "lwip/ip_addr.h" - #include "lwip/err.h" -+#if LWIP_LITEOS_COMPAT -+#include "lwip/netif.h" -+#endif - - #ifdef __cplusplus - extern "C" { -@@ -140,6 +143,9 @@ - /** 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 */ - }; - - /** Current state of the netconn. Non-TCP netconns are always -@@ -149,7 +155,10 @@ - NETCONN_WRITE, - NETCONN_LISTEN, - NETCONN_CONNECT, -- NETCONN_CLOSE -+ NETCONN_CLOSE, -+#if LWIP_LITEOS_COMPAT -+ NETCONN_CLOSED, -+#endif /* LWIP_LITEOS_COMPAT */ - }; - - /** Used to inform the callback function about changes -@@ -226,9 +235,12 @@ - struct tcp_pcb *tcp; - struct udp_pcb *udp; - struct raw_pcb *raw; -+#if PF_PACKET_SOCKET -+ struct raw_pcb *packet_raw; -+#endif /* PF_PACKET_SOCKET */ - } pcb; - /** the last asynchronous unreported error this netconn had */ -- err_t pending_err; -+ err_t last_err; - #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 @@ - #endif /* LWIP_TCP */ - /** A callback function that is informed about events for this netconn */ - netconn_callback callback; -+#if LWIP_TCP -+ struct pbuf *refused_data; -+ ip_addr_t remote_ip; -+ u16_t remote_port; -+ /** record pending error state after recving RST */ -+ u16_t pending_err; -+#endif - }; - - /** This vector type is passed to @ref netconn_write_vectors_partly to send -@@ -309,21 +328,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) --struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, -+struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, - netconn_callback callback); - err_t netconn_prepare_delete(struct netconn *conn); - err_t netconn_delete(struct netconn *conn); - /** Get the type of a netconn (as enum netconn_type). */ --#define netconn_type(conn) (conn->type) -+#define netconn_type(conn) ((u32_t)(conn->type)) - - err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, - u16_t *port, u8_t local); -+#if LWIP_LITEOS_COMPAT -+#if PF_PACKET_SOCKET -+struct pf_packet_sockaddr_ll { -+ u16_t sll_protocol; -+ u16_t sll_hatype; -+ u8_t if_idx; -+ u8_t sll_halen; -+ u8_t sll_addr[NETIF_MAX_HWADDR_LEN]; -+}; -+err_t netconn_get_sockaddr_pf_packet(struct netconn *conn, struct pf_packet_sockaddr_ll *ll, u8_t local); -+#endif /* PF_PACKET_SOCKET */ -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup netconn_common */ - #define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) - /** @ingroup netconn_common */ - #define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) - -+#if PF_PACKET_SOCKET -+err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port, u8_t ifindex); -+#else - err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port); -+#endif /* PF_PACKET_SOCKET */ -+ - err_t netconn_bind_if(struct netconn *conn, u8_t if_idx); - 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 -@@ -37,14 +37,7 @@ - #ifndef LWIP_HDR_ARCH_H - #define LWIP_HDR_ARCH_H - --#ifndef LITTLE_ENDIAN --#define LITTLE_ENDIAN 1234 --#endif -- --#ifndef BIG_ENDIAN --#define BIG_ENDIAN 4321 --#endif -- -+#include - #include "arch/cc.h" - - /** -@@ -149,6 +142,11 @@ - #ifndef X8_F - #define X8_F "02" PRIx8 - #endif -+#if LWIP_LITEOS_COMPAT -+#ifndef U8_F -+#define U8_F PRIu8 -+#endif -+#endif /* LWIP_LITEOS_COMPAT */ - #ifndef U16_F - #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 -@@ -85,9 +85,50 @@ - /** Connection closed. */ - ERR_CLSD = -15, - /** Illegal argument. */ -- ERR_ARG = -16 -+ ERR_ARG = -16, -+#ifdef LWIP_LITEOS_COMPAT -+/** Message too long. */ -+ ERR_MSGSIZE = -17, -+/** No such device. */ -+ ERR_NODEV = -18, -+/** No such device or address. */ -+ ERR_NODEVADDR = -19, -+/** socket is not connection-mode & no peer address is set */ -+ ERR_NODEST = -20, -+/** Network is down */ -+ ERR_NETDOWN = -21, -+/** Address family not supported by protocol */ -+ ERR_AFNOSUPP = -22, -+/** No such address */ -+ ERR_NOADDR = -23, -+/** Operation not supported on transport endpoint */ -+ ERR_OPNOTSUPP = -24, -+ ERR_NETUNREACH = -25, -+/** connection request timedout */ -+ ERR_CONNECTIMEOUT = -26, -+/** Error pipe */ -+ ERR_PIPE = -27, -+/** AF not supported */ -+ ERR_AFNOSUPPORT = -28, -+/** Protocol not available */ -+ ERR_NOPROTOOPT = -29, -+ ERR_ACCESS = -30, -+ ERR_NFILE = -31, -+ ERR_RESERVE3 = -32, -+ ERR_RESERVE4 = -33, -+ ERR_RESERVE5 = -34, -+ ERR_RESERVE6 = -35, -+ ERR_FATAL_START = -36, -+ ERR_CONNREFUSED = -41, -+/** FIN mbox post fail. */ -+ ERR_FIN_POST = -42, -+#endif /* LWIP_LITEOS_COMPAT */ - } err_enum_t; - -+#ifdef LWIP_LITEOS_COMPAT -+#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 */ -+ - #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/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 -@@ -49,10 +49,12 @@ - extern "C" { - #endif - -+#if !LWIP_LITEOS_COMPAT - #define IF_NAMESIZE NETIF_NAMESIZE - - char * lwip_if_indextoname(unsigned int ifindex, char *ifname); - unsigned int lwip_if_nametoindex(const char *ifname); -+#endif - - #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 @@ - extern "C" { - #endif - -+#if !LWIP_LITEOS_COMPAT - /* 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 @@ - /** 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)}}} --/** This variable is initialized by the system to contain the wildcard IPv6 address. */ --extern const struct in6_addr in6addr_any; - - /* Definitions of the bits in an (IPv4) Internet address integer. - -@@ -119,7 +118,12 @@ - #define IN_BADCLASS(a) IP_BADCLASS(a) - - #define IN_LOOPBACKNET IP_LOOPBACKNET -+#endif /* !LWIP_LITEOS_COMPAT */ - -+/** This variable is initialized by the system to contain the wildcard IPv6 address. */ -+extern const struct in6_addr in6addr_any; -+/** Added new structure for ipv6 loopback as per section 3.9 of rfc 2553/3493 */ -+extern const struct in6_addr in6addr_loopback; - - #ifndef INET_ADDRSTRLEN - #define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX -@@ -136,14 +140,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 */ --#define inet_addr(cp) ipaddr_addr(cp) -+#if LWIP_INET_ADDR_FUNC -+unsigned int inet_addr(const char *cp); -+#else -+#define inet_addr(cp) ipaddr_addr(cp) -+#endif -+ -+#if LWIP_INET_ATON_FUNC -+int inet_aton(const char *cp, struct in_addr *addr); -+#else - #define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) -+#endif -+ -+#if LWIP_INET_NTOA_FUNC -+char *inet_ntoa (struct in_addr in); -+#else - #define inet_ntoa(addr) ip4addr_ntoa((const ip4_addr_t*)&(addr)) -+#endif -+ - #define inet_ntoa_r(addr, buf, buflen) ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) - - #endif /* LWIP_IPV4 */ - - #if LWIP_IPV6 -+/* current the struct ip6_addr for define LWIP_IPV6_SCOPES 0 */ -+#if LWIP_LITEOS_COMPAT -+#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) { \ -+ memcpy((target_in6addr)->s6_addr, (source_ip6addr)->addr, sizeof(struct ip6_addr)); } -+#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) { \ -+ memcpy((target_ip6addr)->addr, (source_in6addr)->s6_addr, sizeof(struct ip6_addr)); \ -+ ip6_addr_clear_zone(target_ip6addr);} -+#else - #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 @@ - (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);} -- -+#endif /* LWIP_LITEOS_COMPAT */ - /* 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)) -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 @@ - /** @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{ \ -- ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); ip_clear_no4(dest); }}while(0) -+ ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); ip_clear_no4(dest); }} while (0) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_set_val(dest, src) do { IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&(src))); if(IP_IS_V6_VAL(src)) { \ -+ ip6_addr_set(ip_2_ip6(&(dest)), ip_2_ip6(&(src))); } else { \ -+ ip4_addr_set(ip_2_ip4(&(dest)), ip_2_ip4(&(src))); }} while (0) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup ipaddr */ - #define ip_addr_set_ipaddr(dest, src) ip_addr_set(dest, src) - /** @ingroup ipaddr */ - #define ip_addr_set_zero(ipaddr) do{ \ -- ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0) -+ ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); } while (0) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_set_zero_val(ipaddr) do{ \ -+ ip6_addr_set_zero(ip_2_ip6(&(ipaddr))); IP_SET_TYPE_VAL(ipaddr, 0); } while (0) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup ip5addr */ - #define ip_addr_set_zero_ip4(ipaddr) do{ \ - ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }while(0) - /** @ingroup ip6addr */ - #define ip_addr_set_zero_ip6(ipaddr) do{ \ -- ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }while(0) -+ ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); } while (0) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_set_zero_ip6_val(ipaddr) do{ \ -+ ip6_addr_set_zero(ip_2_ip6(&(ipaddr))); IP_SET_TYPE_VAL(ipaddr, IPADDR_TYPE_V6); } while (0) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @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 @@ - #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)) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_netcmp_val(addr1, addr2, mask) ((IP_IS_V6_VAL((addr1)) && IP_IS_V6_VAL((addr2))) ? \ -+ 0 : \ -+ ip4_addr_netcmp(ip_2_ip4(&addr1), ip_2_ip4(&addr2), mask)) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @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 @@ - #define ip_addr_isbroadcast(ipaddr, netif) ((IP_IS_V6(ipaddr)) ? \ - 0 : \ - ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_isbroadcast_val(ipaddr, netif) ((IP_IS_V6_VAL(ipaddr)) ? \ -+ 0 : \ -+ ip4_addr_isbroadcast(ip_2_ip4(&ipaddr), netif)) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup ipaddr */ - #define ip_addr_ismulticast(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ - ip4_addr_ismulticast(ip_2_ip4(ipaddr))) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_ismulticast_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ -+ ip6_addr_ismulticast(ip_2_ip6(&ipaddr)) : \ -+ ip4_addr_ismulticast(ip_2_ip4(&ipaddr))) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup ipaddr */ - #define ip_addr_isloopback(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_isloopback(ip_2_ip6(ipaddr)) : \ - ip4_addr_isloopback(ip_2_ip4(ipaddr))) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_isloopback_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ -+ ip6_addr_isloopback(ip_2_ip6(&ipaddr)) : \ -+ ip4_addr_isloopback(ip_2_ip4(&ipaddr))) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup ipaddr */ - #define ip_addr_islinklocal(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_islinklocal(ip_2_ip6(ipaddr)) : \ - ip4_addr_islinklocal(ip_2_ip4(ipaddr))) -+#ifdef LWIP_DEBUG - #define ip_addr_debug_print(debug, ipaddr) do { if(IP_IS_V6(ipaddr)) { \ - ip6_addr_debug_print(debug, ip_2_ip6(ipaddr)); } else { \ -- ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }}while(0) -+ ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }} while (0) - #define ip_addr_debug_print_val(debug, ipaddr) do { if(IP_IS_V6_VAL(ipaddr)) { \ - ip6_addr_debug_print_val(debug, *ip_2_ip6(&(ipaddr))); } else { \ -- ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }}while(0) -+ ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }} while (0) -+#else -+#define ip_addr_debug_print(debug, ipaddr) -+#define ip_addr_debug_print_val(debug, ipaddr) -+#endif /* LWIP_LITEOS_COMPAT */ -+ - char *ipaddr_ntoa(const ip_addr_t *addr); - char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen); -+#if LWIP_LITEOS_COMPAT -+#define ipaddr_ntoa_unsafe(addr) ((IP_IS_V6_VAL(*addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr))) -+#endif /* LWIP_LITEOS_COMPAT */ - int ipaddr_aton(const char *cp, ip_addr_t *addr); - - /** @ingroup ipaddr */ -@@ -282,29 +324,43 @@ - #define ip_2_ip4(ipaddr) (ipaddr) - #define IP_ADDR4(ipaddr,a,b,c,d) IP4_ADDR(ipaddr,a,b,c,d) - -+#define ip_addr_cmp_zoneless(addr1, addr2) ip4_addr_cmp(addr1, addr2) - #define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) - #define ip_addr_copy_from_ip4(dest, src) ip4_addr_copy(dest, src) - #define ip_addr_set_ip4_u32(ipaddr, val) ip4_addr_set_u32(ip_2_ip4(ipaddr), val) - #define ip_addr_set_ip4_u32_val(ipaddr, val) ip_addr_set_ip4_u32(&(ipaddr), val) - #define ip_addr_get_ip4_u32(ipaddr) ip4_addr_get_u32(ip_2_ip4(ipaddr)) - #define ip_addr_set(dest, src) ip4_addr_set(dest, src) -+#define ip_addr_set_val(dest, src) ip4_addr_copy(dest, src) - #define ip_addr_set_ipaddr(dest, src) ip4_addr_set(dest, src) - #define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) -+#define ip_addr_set_zero_val(ipaddr) ip4_addr_set_zero(&(ipaddr)) - #define ip_addr_set_zero_ip4(ipaddr) ip4_addr_set_zero(ipaddr) - #define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) - #define ip_addr_set_loopback(is_ipv6, ipaddr) ip4_addr_set_loopback(ipaddr) - #define ip_addr_set_hton(dest, src) ip4_addr_set_hton(dest, src) - #define ip_addr_get_network(target, host, mask) ip4_addr_get_network(target, host, mask) - #define ip_addr_netcmp(addr1, addr2, mask) ip4_addr_netcmp(addr1, addr2, mask) -+#define ip_addr_netcmp_val(addr1, addr2, mask) ip4_addr_netcmp(&(addr1), &(addr2), mask) - #define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) - #define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) -+#define ip_addr_isnone(ipaddr) ip4_addr_isnone(ipaddr) - #define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) - #define ip_addr_isloopback(ipaddr) ip4_addr_isloopback(ipaddr) -+#define ip_addr_isloopback_val(ipaddr) ip4_addr_isloopback(&(ipaddr)) - #define ip_addr_islinklocal(ipaddr) ip4_addr_islinklocal(ipaddr) - #define ip_addr_isbroadcast(addr, netif) ip4_addr_isbroadcast(addr, netif) -+#define ip_addr_isbroadcast_val(addr, netif) ip4_addr_isbroadcast(&(addr), netif) - #define ip_addr_ismulticast(ipaddr) ip4_addr_ismulticast(ipaddr) -+#define ip_addr_ismulticast_val(ipaddr) ip4_addr_ismulticast(&(ipaddr)) -+#ifdef LWIP_DEBUG - #define ip_addr_debug_print(debug, ipaddr) ip4_addr_debug_print(debug, ipaddr) - #define ip_addr_debug_print_val(debug, ipaddr) ip4_addr_debug_print_val(debug, ipaddr) -+#else -+#define ip_addr_debug_print(debug, ipaddr) -+#define ip_addr_debug_print_val(debug, ipaddr) -+#endif -+ - #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 @@ - #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) -+#define ip_addr_set_val(dest, src) ip6_addr_copy(dest, src) -+ - #define ip_addr_set_ipaddr(dest, src) ip6_addr_set(dest, src) - #define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr) -+#define ip_addr_set_zero_val(ipaddr) ip6_addr_set_zero(&(ipaddr)) - #define ip_addr_set_zero_ip6(ipaddr) ip6_addr_set_zero(ipaddr) -+#define ip_addr_set_zero_ip6_val(ipaddr) ip6_addr_set_zero(&(ipaddr)) - #define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr) - #define ip_addr_set_loopback(is_ipv6, ipaddr) ip6_addr_set_loopback(ipaddr) - #define ip_addr_set_hton(dest, src) ip6_addr_set_hton(dest, src) - #define ip_addr_get_network(target, host, mask) ip6_addr_set_zero(target) - #define ip_addr_netcmp(addr1, addr2, mask) 0 -+#define ip_addr_netcmp_val(addr1, addr2, mask) 0 - #define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) - #define ip_addr_cmp_zoneless(addr1, addr2) ip6_addr_cmp_zoneless(addr1, addr2) - #define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) -+#define ip_addr_isnone(ipaddr) ip6_addr_isnone(ipaddr) - #define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) - #define ip_addr_isloopback(ipaddr) ip6_addr_isloopback(ipaddr) -+#define ip_addr_isloopback_val(ipaddr) ip6_addr_isloopback(&(ipaddr)) - #define ip_addr_islinklocal(ipaddr) ip6_addr_islinklocal(ipaddr) - #define ip_addr_isbroadcast(addr, netif) 0 -+#define ip_addr_isbroadcast_val(addr, netif) 0 - #define ip_addr_ismulticast(ipaddr) ip6_addr_ismulticast(ipaddr) -+#define ip_addr_ismulticast_val(ipaddr) ip6_addr_ismulticast(&(ipaddr)) -+#ifdef LWIP_DEBUG - #define ip_addr_debug_print(debug, ipaddr) ip6_addr_debug_print(debug, ipaddr) - #define ip_addr_debug_print_val(debug, ipaddr) ip6_addr_debug_print_val(debug, ipaddr) -+#else -+#define ip_addr_debug_print(debug, ipaddr) -+#define ip_addr_debug_print_val(debug, ipaddr) -+#endif -+ - #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) -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 @@ - #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) */ -- -+#if LWIP_LITEOS_COMPAT -+#define SOF_DONTROUTE 0x01U /* all packets sent from this socket should only be routed with link scope entry */ -+#define SOF_BINDNONUNICAST 0x10U /* socket has bind to a non unicast */ -+#endif /* LWIP_LITEOS_COMPAT */ - /* 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 @@ - ip_addr_t current_iphdr_src; - /** Destination IP address of current_header */ - ip_addr_t current_iphdr_dest; -+#if LWIP_LITEOS_COMPAT -+ /* The IP header ID of the next outgoing IP packet */ -+#if LWIP_IPV4 -+ /* ensure this member of this sturcture is not mem set to zero */ -+ u16_t ip_id; -+#endif /* LWIP_IPV4 */ -+#endif /* LWIP_LITEOS_COMPAT */ - }; - extern struct ip_globals ip_data; - -@@ -315,7 +325,22 @@ - #define ip_input ip6_input - - #endif /* LWIP_IPV6 */ -- -+#if LWIP_LITEOS_COMPAT -+/** -+ * Defines the assumed maximum MTU on any interface for IP fragment buffer -+ * (requires IP_FRAG_USES_STATIC_BUF==1).This is not a configurable value. -+ */ -+#if !defined(IP_FRAG_MAX_MTU) -+#define IP_FRAG_MAX_MTU 1500 -+#endif -+/* As per RFC 791, "Every internet module must be able to forward a datagram of 68 -+ * octets without further fragmentation. This is because an internet header -+ * may be up to 60 octets, and the minimum fragment is 8 octets." */ -+#if !defined(IP_FRAG_MIN_MTU) -+#define IP_FRAG_MIN_MTU 68 -+#endif -+struct netif *ip_route_pcb(const ip_addr_t *dest, const struct ip_pcb* pcb); -+#endif /* LWIP_LITEOS_COMPAT */ - #define ip_route_get_local_ip(src, dest, netif, ipaddr) do { \ - (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 -@@ -55,13 +55,22 @@ - #define NETBUF_FLAG_DESTADDR 0x01 - /** This netbuf includes a checksum */ - #define NETBUF_FLAG_CHKSUM 0x02 -+#if PF_PACKET_SOCKET -+#define NETBUF_FLAG_IFINDEX 0x04 -+#endif /* PF_PACKET_SOCKET */ - - /** "Network buffer" - contains data and addressing info */ - struct netbuf { - struct pbuf *p, *ptr; - ip_addr_t addr; - u16_t port; --#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY -+#if PF_PACKET_SOCKET -+ u16_t hatype; -+ u16_t reserve; /* padded */ -+ u8_t netifindex; -+#endif /* PF_PACKET_SOCKET */ -+ -+#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY || PF_PACKET_SOCKET - u8_t flags; - u16_t toport_chksum; - #if LWIP_NETBUF_RECVINFO -@@ -73,7 +82,7 @@ - /* Network buffer functions: */ - struct netbuf * netbuf_new (void); - void netbuf_delete (struct netbuf *buf); --void * netbuf_alloc (struct netbuf *buf, u16_t size); -+void * netbuf_alloc (struct netbuf *buf, u16_t size, u8_t netconn_type); - void netbuf_free (struct netbuf *buf); - err_t netbuf_ref (struct netbuf *buf, - const void *dataptr, u16_t size); -@@ -93,6 +102,10 @@ - #define netbuf_fromaddr(buf) (&((buf)->addr)) - #define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set(&((buf)->addr), fromaddr) - #define netbuf_fromport(buf) ((buf)->port) -+#if LWIP_LITEOS_COMPAT -+#define netbuf_fromifindex(buf) ((buf)->netifindex) -+#define netbuf_fromhatype(buf) ((buf)->hatype) -+#endif /* LWIP_LITEOS_COMPAT */ - #if LWIP_NETBUF_RECVINFO - #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 -@@ -36,6 +36,10 @@ - - #include "lwip/opt.h" - -+#if LWIP_LITEOS_COMPAT -+#include -+#endif -+ - #if LWIP_DNS && LWIP_SOCKET - - #include "lwip/arch.h" -@@ -63,6 +67,7 @@ - #define LWIP_DNS_API_DECLARE_STRUCTS 1 - #endif - -+#if !LWIP_LITEOS_COMPAT - #if LWIP_DNS_API_DEFINE_ERRORS - /** Errors used by the DNS API functions, h_errno can be one of them */ - #define EAI_NONAME 200 -@@ -112,23 +117,39 @@ - }; - #endif /* LWIP_DNS_API_DECLARE_STRUCTS */ - --#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) - - #if LWIP_DNS_API_DECLARE_H_ERRNO - /* application accessible error code set by the DNS API functions */ - extern int h_errno; - #endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ -+#endif /* !LWIP_LITEOS_COMPAT */ - -+#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) -+ -+#if LWIP_GETHOSTBYNAME || (defined(LWIP_COMPAT_SOCKETS) && (LWIP_COMPAT_SOCKETS != 2)) - struct hostent *lwip_gethostbyname(const char *name); -+#endif /* LWIP_GETHOSTBYNAME || (defined(LWIP_COMPAT_SOCKETS) && (LWIP_COMPAT_SOCKETS != 2)) */ -+#if (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) - int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, - size_t buflen, struct hostent **result, int *h_errnop); -+#endif /* (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) */ -+#if (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) - void lwip_freeaddrinfo(struct addrinfo *ai); - int lwip_getaddrinfo(const char *nodename, - const char *servname, - const struct addrinfo *hints, - struct addrinfo **res); -- --#if LWIP_COMPAT_SOCKETS -+#endif /* (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) */ -+#if LWIP_DNS_REVERSE -+int lwip_getnameinfo(const struct sockaddr *sa, -+ socklen_t salen, -+ char *host, -+ size_t hostlen, -+ char *serv, -+ size_t servlen, -+ int flags); -+#endif /* LWIP_DNS_REVERSE */ -+#if defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2 - /** @ingroup netdbapi */ - #define gethostbyname(name) lwip_gethostbyname(name) - /** @ingroup netdbapi */ -@@ -139,7 +160,11 @@ - /** @ingroup netdbapi */ - #define getaddrinfo(nodname, servname, hints, res) \ - lwip_getaddrinfo(nodname, servname, hints, res) --#endif /* LWIP_COMPAT_SOCKETS */ -+ -+/* @ingroup netdbapi */ -+#define getnameinfo(sock, sock_size, host, host_len, servname, servname_size, flags) \ -+ lwip_getnameinfo(sock, sock_size, host, host_len, servname, servname_size, flags) -+#endif /* defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2 */ - - #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 -@@ -73,6 +73,30 @@ - const ip4_addr_t *netmask, const ip4_addr_t *gw); - #endif /* LWIP_IPV4*/ - -+/* -+Func Name: netifapi_netif_find_by_name -+*/ -+/** -+* @ingroup netifapi_netif -+* -+* @brief -+* This is a thread safe API, used to get the netif pointer whoes name was the input argument. -+* It is recommended to use this API instead of netif_find_by_name(). -+* Call netif_find() in a thread-safe way by running that function inside the tcpip_thread -+* context. -+* -+* @param[in] name Name of the netif. -+* -+* @returns -+* The netif pointer : On success \n -+* NULL : the netif was NOT exist \n -+* -+* @par Related Topics -+* netif_find_by_name() -+* -+*/ -+ -+struct netif* netifapi_netif_find_by_name(const char *name); - err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, - 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 -@@ -48,6 +48,7 @@ - #include "lwip/def.h" - #include "lwip/pbuf.h" - #include "lwip/stats.h" -+#include "lwip/prot/ethernet.h" - - #ifdef __cplusplus - extern "C" { -@@ -67,8 +68,17 @@ - * netif can be identified by in APIs. Composed of - * 2 chars, 3 (max) digits, and 1 \0 - */ --#define NETIF_NAMESIZE 6 -+#ifdef IFNAMSIZ -+#define NETIF_NAMESIZE IFNAMSIZ -+#else -+#define NETIF_NAMESIZE 16 -+#endif -+ -+#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 - /** - * @defgroup netif_flags Flags - * @ingroup netif -@@ -106,6 +116,17 @@ - * Set by the netif driver in its init function. */ - #define NETIF_FLAG_MLD6 0x40U - -+/** If set, the interface is configured using DHCP. -+ * Set by the DHCP code when starting or stopping DHCP. */ -+#define NETIF_FLAG_DHCP 0x80U -+ -+#if DRIVER_STATUS_CHECK -+/** If set, the netif has send capability. -+ * Set by the netif driver when its is ready to send. */ -+#define NETIF_FLAG_DRIVER_RDY 0x100U -+#endif -+ -+#define NETIF_FLAG_LOOPBACK 0x800 - /** - * @} - */ -@@ -223,6 +244,9 @@ - const ip6_addr_t *group, enum netif_mac_filter_action action); - #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */ - -+/** Function pointer of driver set hw address function */ -+typedef u8_t (*drv_set_hwaddr_fn)(struct netif *netif, u8_t *addr, u8_t len); -+ - #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 @@ - */ - #define netif_get_client_data(netif, id) (netif)->client_data[(id)] - #endif -+#ifndef LOOPBACK_IF -+/** Type of link layer, these macros should be used for link_layer_type of struct netif */ -+#define LOOPBACK_IF 772 -+#endif - - #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 @@ - /** This field can be set by the device driver and could point - * to state information for the device. */ - void *state; -+ /* This function is to set the mac_address of the interface. */ -+ drv_set_hwaddr_fn drv_set_hwaddr; -+#if LWIP_NETIF_ETHTOOL && LWIP_SOCKET -+ void *ethtool_ops; -+#endif -+#if LWIP_DHCPS -+ /* DHCP Server Informarion for this netif */ -+ struct dhcps *dhcps; -+#endif - #ifdef netif_get_client_data - void* client_data[LWIP_NETIF_CLIENT_DATA_INDEX_MAX + LWIP_NUM_NETIF_CLIENT_DATA]; - #endif - #if LWIP_NETIF_HOSTNAME - /* the hostname for this netif, NULL is a valid value */ -- const char* hostname; -+ char hostname[NETIF_HOSTNAME_MAX_LEN]; - #endif /* LWIP_NETIF_HOSTNAME */ - #if LWIP_CHECKSUM_CTRL_PER_NETIF - u16_t chksum_flags; -@@ -341,13 +378,19 @@ - u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; - /** number of bytes used in hwaddr */ - u8_t hwaddr_len; -+ /* link layer type, ethernet or wifi */ -+ u16_t link_layer_type; /**< Indicates whether the link layer type is ethernet or wifi. */ - /** flags (@see @ref netif_flags) */ -- u8_t flags; -+ u32_t flags; - /** descriptive abbreviation */ -- char name[2]; -- /** number of this interface. Used for @ref if_api and @ref netifapi_netif, -+ char name[NETIF_NAMESIZE]; -+ /** number of this interface. Used for @ref if_api and @ref netifapi_netif, - * as well as for IPv6 zones */ - u8_t num; -+ u8_t ifindex; /* Interface Index mapped to each netif. Starts from 1 */ -+#if DRIVER_STATUS_CHECK -+ s32_t waketime; /**< Started when netif_stop_queue is called from driver. */ -+#endif - #if LWIP_IPV6_AUTOCONFIG - /** is this netif enabled for IPv6 autoconfiguration */ - u8_t ip6_autoconfig_enabled; -@@ -387,6 +430,15 @@ - u16_t loop_cnt_current; - #endif /* LWIP_LOOPBACK_MAX_PBUFS */ - #endif /* ENABLE_LOOPBACK */ -+#if LWIP_SO_DONTROUTE -+ /** The scope of the netif, this is set in ip4_route/ip6_route, the usr can use this -+ to decide whether the netif is in desired sope */ -+ rt_scope_t scope; -+#endif -+#if LWIP_IPV6 -+ /** Call back needs to be registered if adaptor requires notification for IPv6 DAD */ -+ u8_t ipv6_flags; -+#endif - }; - - #if LWIP_CHECKSUM_CTRL_PER_NETIF -@@ -407,9 +459,15 @@ - #endif /* LWIP_SINGLE_NETIF */ - /** The default network interface. */ - extern struct netif *netif_default; -- -+s8_t netif_find_dst_ipaddr(const ip_addr_t *ipaddr, ip_addr_t **dst_addr); - void netif_init(void); - -+#if LWIP_DHCP -+err_t netif_dhcp_off(struct netif *netif); -+#endif -+ -+u8_t netif_check_num_isusing(const char* ifname, const u8_t num); -+ - 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 @@ - structure. */ - struct netif *netif_find(const char *name); - --void netif_set_default(struct netif *netif); -+struct netif *netif_find_by_ipaddr(const ip_addr_t *ipaddr); -+ -+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_IPV4 - void netif_set_ipaddr(struct netif *netif, const ip4_addr_t *ipaddr); - void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask); - void netif_set_gw(struct netif *netif, const ip4_addr_t *gw); -+struct netif *netif_find_by_ip4addr(const ip_addr_t *ipaddr); - /** @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 @@ - - void netif_set_up(struct netif *netif); - void netif_set_down(struct netif *netif); -+err_t netif_set_mtu_api(struct netif *netif, u16_t netif_mtu); -+err_t netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw_len); -+void netif_get_hwaddr(const struct netif *netif, unsigned char *hw_addr, int hw_len); - /** @ingroup netif - * Ask if an interface is up - */ -@@ -512,6 +578,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); -+err_t netif_do_add_ipv6_addr(struct netif *netif, void *arguments); -+err_t netif_do_rmv_ipv6_addr(struct netif *netif, void *arguments); - 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/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 -@@ -529,7 +529,7 @@ - * (only needed if you use the sequential API, like api_lib.c) - */ - #if !defined MEMP_NUM_NETCONN || defined __DOXYGEN__ --#define MEMP_NUM_NETCONN 4 -+#define MEMP_NUM_NETCONN 16 - #endif - - /** -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 @@ - #define PBUF_FLAG_LLMCAST 0x10U - /** indicates this pbuf includes a TCP FIN flag */ - #define PBUF_FLAG_TCP_FIN 0x20U -- -+#ifdef LWIP_LITEOS_COMPAT -+#define PBUF_FLAG_HOST 0x100U -+#define PBUF_FLAG_OUTGOING 0x200U -+#endif - /** Main packet buffer struct */ - 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 -@@ -46,6 +46,7 @@ - #include "lwip/igmp.h" - #include "lwip/api.h" - #include "lwip/priv/tcpip_priv.h" -+#include "lwip/ip.h" - - #ifdef __cplusplus - extern "C" { -@@ -70,6 +71,14 @@ - #define NETCONN_SHUT_WR 2 - #define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) - -+#if PF_PACKET_SOCKET -+/* Packet Types */ -+#define PACKET_HOST 0 /* To us */ -+#define PACKET_BROADCAST 1 /* To all */ -+#define PACKET_MULTICAST 2 /* To group */ -+#define PACKET_OTHERHOST 3 /* To someone else */ -+#define PACKET_OUTGOING 4 -+#endif - /* IP addresses and port numbers are expected to be in - * the same byte order as in the corresponding pcb. - */ -@@ -88,7 +97,7 @@ - struct netbuf *b; - /** used for lwip_netconn_do_newconn */ - struct { -- u8_t proto; -+ u16_t proto; - } n; - /** used for lwip_netconn_do_bind and lwip_netconn_do_connect */ - struct { -@@ -102,6 +111,12 @@ - u16_t API_MSG_M_DEF(port); - u8_t local; - } ad; -+#if PF_PACKET_SOCKET -+ struct { -+ struct pf_packet_sockaddr_ll API_MSG_M_DEF(ll); -+ u8_t local; -+ } adpkt; -+#endif - /** used for lwip_netconn_do_write */ - struct { - /** current vector to write */ -@@ -205,6 +220,7 @@ - #endif /* TCP_LISTEN_BACKLOG */ - void lwip_netconn_do_write (void *m); - void lwip_netconn_do_getaddr (void *m); -+void lwip_netconn_do_getaddr_pfpkt (void *m); - void lwip_netconn_do_close (void *m); - void lwip_netconn_do_shutdown (void *m); - #if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) -@@ -214,6 +230,7 @@ - - #if LWIP_DNS - void lwip_netconn_do_gethostbyname(void *arg); -+void lwip_netconn_do_getnamebyhost(void *arg); - #endif /* LWIP_DNS */ - - struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); -@@ -233,6 +250,7 @@ - - typedef void (*netifapi_void_fn)(struct netif *netif); - typedef err_t (*netifapi_errt_fn)(struct netif *netif); -+typedef err_t (*netifapi_arg_fn)(struct netif *netif, void *arg); - - struct netifapi_msg { - struct tcpip_api_call_data call; -@@ -245,9 +263,27 @@ - NETIFAPI_IPADDR_DEF(ip4_addr_t, gw); - #endif /* LWIP_IPV4 */ - void *state; -+ } add; -+ -+ struct { -+ const ip_addr_t *ipaddr; -+ } find_by_ipaddr; -+ struct { -+ const char *name; -+ } find_by_name; -+ struct { -+ unsigned char ifindex; -+ } find_by_ifindex; -+ struct { -+#if LWIP_IPV4 -+ ip4_addr_t *ipaddr; -+ ip4_addr_t *netmask; -+ ip4_addr_t *gw; -+#endif /* LWIP_IPV4 */ -+ void *state; - netif_init_fn init; - netif_input_fn input; -- } add; -+ } add_get; - struct { - 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 -@@ -49,7 +49,6 @@ - extern "C" { - #endif - --#define NUM_SOCKETS MEMP_NUM_NETCONN - - /** This is overridable for the rare case where more than 255 threads - * select on the same socket... -@@ -69,6 +68,10 @@ - struct netconn *conn; - /** data that was left from the previous read */ - union lwip_sock_lastdata lastdata; -+ /** offset in the data that was left from the previous read */ -+ u16_t lastoffset; -+ /* socket level mutex used for multithread recv support */ -+ sys_mutex_t mutex; - #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL - /** number of times data was received, set by event_callback(), - tested by the receive and select functions */ -@@ -158,6 +161,7 @@ - fd_set *exceptset; - #endif /* LWIP_SOCKET_SELECT */ - #if LWIP_SOCKET_POLL -+ - /** fds passed to poll; NULL if select */ - 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 -@@ -135,7 +135,7 @@ - # include "arch/bpstruct.h" - #endif - PACK_STRUCT_BEGIN --struct icmp6_hdr { -+struct icmpv6_hdr { - 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/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 -@@ -39,6 +39,9 @@ - - #include "lwip/arch.h" - #include "lwip/ip4_addr.h" -+#if LWIP_LITEOS_COMPAT -+#include -+#endif - - #ifdef __cplusplus - extern "C" { -@@ -81,10 +84,12 @@ - PACK_STRUCT_FIELD(u16_t _id); - /* fragment offset field */ - PACK_STRUCT_FIELD(u16_t _offset); -+#if !LWIP_LITEOS_COMPAT - #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 */ -+#endif - /* time to live */ - PACK_STRUCT_FLD_8(u8_t _ttl); - /* protocol*/ -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 -@@ -47,6 +47,8 @@ - #include "lwip/ip.h" - #include "lwip/ip_addr.h" - #include "lwip/ip6_addr.h" -+#include "lwip/etharp.h" -+#include "lwip/icmp6.h" - - #ifdef __cplusplus - extern "C" { -@@ -57,6 +59,18 @@ - #define RAW_FLAGS_MULTICAST_LOOP 0x04U - - struct raw_pcb; -+extern struct raw_pcb* raw_pcbs; -+ -+#if PF_PACKET_SOCKET -+extern const struct eth_hdr *g_lwip_current_eth_hdr; -+extern const struct netif *g_lwip_current_netif; -+/* Dest MAC add of current ethernet header of RAW packets -+ * received for PF_PACKET family */ -+#define eth_current_hdr() (g_lwip_current_eth_hdr) -+#define eth_current_netif() (g_lwip_current_netif) -+struct raw_pcb* get_packet_raw_pcbs(void); -+struct raw_pcb* get_all_packet_raw_pcbs(void); -+#endif /* PF_PACKET_SOCKET */ - - /** Function prototype for raw pcb receive callback functions. - * @param arg user supplied argument (raw_pcb.recv_arg) -@@ -77,8 +91,19 @@ - IP_PCB; - - struct raw_pcb *next; -- -+#if PF_PACKET_SOCKET -+ struct raw_pcb *all_next; -+ u8_t netifindex; -+ -+ union { -+ u16_t eth_proto; /* Ethernet HeaderType/Protocol for Packet sockets */ -+#define raw_proto proto.protocol -+ u8_t protocol; /* IP protocol for AF_INET sockets */ -+ } proto; -+#else -+#define raw_proto protocol - u8_t protocol; -+#endif - u8_t flags; - - #if LWIP_MULTICAST_TX_OPTIONS -@@ -115,6 +140,14 @@ - - void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); - -+#if PF_PACKET_SOCKET -+struct raw_pcb * raw_packet_new (u16_t proto); -+void raw_packet_remove (struct raw_pcb *pcb); -+void raw_packet_input (struct pbuf *p, const struct netif *inp, const struct raw_pcb *from); -+err_t raw_packet_sendto (const struct raw_pcb *pcb, struct pbuf *p, u8_t ifindex); -+err_t raw_packet_bind (struct raw_pcb *pcb, u8_t ifindex, u16_t proto); -+#endif /* PF_PACKET_SOCKET */ -+ - #define raw_flags(pcb) ((pcb)->flags) - #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 @@ - - #include - -+#if LWIP_LITEOS_COMPAT -+#include "sys/select.h" -+#include "sys/socket.h" -+#include "poll.h" -+#include "netinet/tcp.h" -+#endif /* LWIP_LITEOS_COMPAT */ -+ - #ifdef __cplusplus - extern "C" { - #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 @@ - #endif /* LWIP_TIMEVAL_PRIVATE */ - - #define lwip_socket_init() /* Compatibility define, no init needed. */ -+#else /* LWIP_LITEOS_COMPAT */ -+#if LWIP_LITEOS_COMPAT -+#ifndef TCP_KEEPALIVE -+#define TCP_KEEPALIVE 0x02 -+#endif /* TCP_KEEPALIVE */ -+ -+#ifndef SIN_ZERO_LEN -+#define SIN_ZERO_LEN 8 -+#endif /* SIN_ZERO_LEN */ -+ -+#ifndef SOCK_MAX -+#define SOCK_MAX (SOCK_RAW + 1) -+#endif /* SOCK_MAX */ -+ -+#ifndef SOCK_TYPE_MASK -+#define SOCK_TYPE_MASK 0xf -+#endif /* SOCK_TYPE_MASK */ -+#endif -+ - void lwip_socket_thread_init(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ - void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ - -+#if LWIP_IPV6 -+#define LWIP_IS_IPPROTOCOL(protocol) ((protocol) == IPPROTO_IP || (protocol) == IPPROTO_IPV6 || (protocol) == 0) -+#if PF_PACKET -+#define LWIP_IS_VALID_DOMAIN(domain) (((domain) == AF_INET) || ((domain) == AF_INET6) || ((domain) == PF_PACKET)) -+#else -+#define LWIP_IS_VALID_DOMAIN(domain) ((domain) == AF_INET) || ((domain) == AF_INET6) -+#endif -+#else -+#define LWIP_IS_IPPROTOCOL(protocol) ((protocol) == IPPROTO_IP || (protocol) == 0) -+#if PF_PACKET -+#define LWIP_IS_VALID_DOMAIN(domain) (((domain) == AF_INET) || ((domain) == PF_PACKET)) -+#else -+#define LWIP_IS_VALID_DOMAIN(domain) ((domain) == AF_INET) || ((domain) == AF_INET6) -+#endif -+#endif - #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 @@ - #if LWIP_SOCKET_SELECT - #define lwip_select select - #endif -+ -+#define lwip_gethostbyname(name) gethostbyname(name) -+ - #if LWIP_SOCKET_POLL - #define lwip_poll poll - #endif -@@ -558,9 +603,18 @@ - #define lwip_inet_ntop inet_ntop - #define lwip_inet_pton inet_pton - -+#if LWIP_DNS -+#define lwip_gethostbyname(name) gethostbyname(name) -+#define lwip_gethostbyname_r gethostbyname_r -+#define lwip_freeaddrinfo freeaddrinfo -+#define lwip_getaddrinfo getaddrinfo -+#define lwip_getnameinfo getnameinfo -+#endif -+ - #if LWIP_POSIX_SOCKETS_IO_NAMES - #define lwip_read read - #define lwip_readv readv -+ - #define lwip_write write - #define lwip_writev writev - #undef lwip_close -@@ -682,7 +736,7 @@ - #ifdef __cplusplus - } - #endif -- -+#endif - #endif /* LWIP_SOCKET */ - - #endif /* LWIP_HDR_SOCKETS_H */ -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 -@@ -0,0 +1,307 @@ -+/* -+ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved. -+ * Description: declare BSD APIs : getifaddrs freeifaddrs -+ * Author: none -+ * Create: 2020 -+ */ -+ -+#ifndef __LWIP_IFADDRS_H -+#define __LWIP_IFADDRS_H -+ -+#if (LWIP_IPV4 || LWIP_IPV6) && LWIP_SOCKET -+ -+#include "lwip/netif.h" -+#include "lwip/sockets.h" -+ -+#ifdef LWIP_COMPAT_SOCKETS -+#if LWIP_COMPAT_SOCKETS != 2 -+/* @ingroup socket */ -+#define getifaddrs(ifap) lwip_getifaddrs(ifap) -+#define freeifaddrs(ifa) lwip_freeifaddrs(ifa) -+#else /* LWIP_COMPAT_SOCKETS != 2 */ -+/* @ingroup socket */ -+#define lwip_getifaddrs(ifap) getifaddrs(ifap) -+#define lwip_freeifaddrs(ifa) freeifaddrs(ifa) -+#endif /* LWIP_COMPAT_SOCKETS == 2 */ -+#endif /* LWIP_COMPAT_SOCKETS */ -+ -+#if LWIP_LITEOS_COMPAT -+ -+#ifndef SIOCETHTOOL -+#define SIOCETHTOOL _IOW('i', 56, struct ifreq) -+#endif -+#define IFF_DRV_RUNNING 0x40 -+ -+#else -+#define SIOCADDRT _IOW('R', 9, struct rtentry) -+#define SIOCDELRT _IOW('R', 10, struct rtentry) -+ -+#define SIOCGIFFLAGS _IOWR('i', 17, struct ifreq) /* get ifnet flags */ -+#define SIOCSIFFLAGS _IOW('i', 16, struct ifreq) /* set ifnet flags */ -+#define SIOCGIFADDR _IOWR('i', 33, struct ifreq) /* get ifnet address */ -+#define SIOCSIFADDR _IOW('i', 12, struct ifreq) /* set ifnet address */ -+ -+#define SIOCDIFADDR _IOW('i', 25, struct ifreq) /* delete IF addr */ -+ -+#define SIOCGIFNETMASK _IOWR('i', 37, struct ifreq) /* get net addr mask */ -+#define SIOCSIFNETMASK _IOW('i', 22, struct ifreq) /* set net addr mask */ -+#define SIOCSIFHWADDR _IOW('i', 140, struct ifreq) /* set IF name */ -+#define SIOCGIFHWADDR _IOW('i', 141, struct ifreq) /* set IF name */ -+#define SIOCGIFNAME _IOW('i', 142, struct ifreq) /* set IF name */ -+#define SIOCSIFNAME _IOW('i', 40, struct ifreq) /* set IF name */ -+ -+/** Gets IF mtu */ -+#define SIOCGIFMTU _IOWR('i', 51, struct ifreq) -+/** Sets IF mtu */ -+#define SIOCSIFMTU _IOW('i', 52, struct ifreq) -+/** ethtool */ -+#define SIOCETHTOOL _IOW('i', 56, struct ifreq) -+ -+/* provide PF_PACKET option on SOCK_RAW */ -+#define SIOCGIFINDEX _IOWR('i', 32, struct ifreq) /* get IF index */ -+#define SIOCGIFCONF _IOWR('i', 36, struct ifconf) /* get ifnet list */ -+ -+/** (n) Indicates that the interface is up */ -+#define IFF_UP 0x1 -+/** (i) Indicates that the broadcast address valid */ -+#define IFF_BROADCAST 0x2 -+/** (n) Turns on debugging */ -+#define IFF_DEBUG 0x4 -+/** (i) A loopback net */ -+#define IFF_LOOPBACK 0x8 -+/** (i) Indicates a point-to-point link */ -+#define IFF_POINTOPOINT 0x10 -+/* 0x20 was IFF_SMART */ -+/** (d) Indicates that the resources are allocated */ -+#define IFF_DRV_RUNNING 0x40 -+/** (n) No address resolution protocol */ -+#define IFF_NOARP 0x80 -+/** (n) Receive all packets */ -+#define IFF_PROMISC 0x100 -+/** (n) Receive all multicast packets */ -+#define IFF_ALLMULTI 0x200 -+/** (d) Indicates that the tx hardware queue is full */ -+#define IFF_DRV_OACTIVE 0x400 -+ /** (i) Cannot hear own transmissions */ -+#define IFF_SIMPLEX 0x800 -+/** Per link layer defined bit */ -+#define IFF_LINK0 0x1000 -+/** Per link layer defined bit */ -+#define IFF_LINK1 0x2000 -+/** Per link layer defined bit */ -+#define IFF_LINK2 0x4000 -+/** Use alternate physical connection */ -+#define IFF_ALTPHYS IFF_LINK2 -+/** Supports multicast */ -+#define IFF_MULTICAST 0x8000 -+ /** (i) Unconfigurable using ioctl(2) */ -+#define IFF_CANTCONFIG 0x10000 -+/** (n) User-requested promisc mode */ -+#define IFF_PPROMISC 0x20000 -+/** (n) User-requested IFF_MONITOR mode */ -+#define IFF_MONITOR 0x40000 -+ /** (n) Static ARP */ -+#define IFF_STATICARP 0x80000 -+/** (n) Interface is winding down */ -+#define IFF_DYING 0x200000 -+/** (n) Interface is being renamed */ -+#define IFF_RENAMING 0x400000 -+/** (n) Dialup device with changing addresses */ -+#define IFF_DYNAMIC 0x800000 -+/** (n) Dialup device with changing addresses */ -+#define IFF_DYNAMIC_S 0x1000000 -+ -+#define IFF_RUNNING IFF_DRV_RUNNING -+ -+#ifndef IFNAMSIZ -+#define IFNAMSIZ NETIF_NAMESIZE -+#endif -+ -+struct ifreq { -+#define IFHWADDRLEN 6 -+ union { -+ char ifrn_name[IFNAMSIZ]; -+ } ifr_ifrn; -+ union { -+ struct sockaddr ifru_addr; -+ struct sockaddr ifru_dstaddr; -+ struct sockaddr ifru_broadaddr; -+ struct sockaddr ifru_netmask; -+ struct sockaddr ifru_hwaddr; -+ short ifru_flags[2]; -+ int ifru_ivalue; -+ int ifru_mtu; -+ char ifru_slave[IFNAMSIZ]; -+ char ifru_newname[IFNAMSIZ]; -+ void *ifru_data; -+ } ifr_ifru; -+}; -+#define ifr_name ifr_ifrn.ifrn_name -+#define ifr_hwaddr ifr_ifru.ifru_hwaddr -+#define ifr_addr ifr_ifru.ifru_addr -+#define ifr_dstaddr ifr_ifru.ifru_dstaddr -+#define ifr_broadaddr ifr_ifru.ifru_broadaddr -+#define ifr_netmask ifr_ifru.ifru_netmask -+#define ifr_flags ifr_ifru.ifru_flags[0] /* flags (low 16 bits) */ -+#define ifr_flagshigh ifr_ifru.ifru_flags[1] /* flags (high 16 bits) */ -+#define ifr_metric ifr_ifru.ifru_ivalue -+#define ifr_mtu ifr_ifru.ifru_mtu -+#define ifr_slave ifr_ifru.ifru_slave -+#define ifr_data ifr_ifru.ifru_data -+#define ifr_ifindex ifr_ifru.ifru_ivalue -+#define ifr_bandwidth ifr_ifru.ifru_ivalue -+#define ifr_qlen ifr_ifru.ifru_ivalue -+#define ifr_newname ifr_ifru.ifru_newname -+#define ifr_index ifr_ifindex -+ -+struct ifconf { -+ int ifc_len; -+ union { -+ char *ifcu_buf; -+ struct ifreq *ifcu_req; -+ } ifc_ifcu; -+}; -+ -+#define ifc_buf ifc_ifcu.ifcu_buf -+#define ifc_req ifc_ifcu.ifcu_req -+ -+struct ifaddrs { -+ struct ifaddrs *ifa_next; /**< Pointer to the next network interfaces.f */ -+ char *ifa_name; /**< Pointer to the name of the network interfaces */ -+ unsigned int ifa_flags; /**< Pointer to the status flag. */ -+ struct sockaddr *ifa_addr; /**< Pointer to the address. */ -+ struct sockaddr *ifa_netmask; /**< Pointer to the net masking. */ -+ struct sockaddr *ifa_dstaddr; /**< Pointer to the destination address. */ -+ void *ifa_data; /**< Pointer to the data. */ -+}; -+ -+ #ifndef ifa_broadaddr -+ #define ifa_broadaddr ifa_dstaddr /* brcast address interface */ -+#endif -+ -+struct rtentry { -+ struct sockaddr rt_dst; /**< Indicates the target address. */ -+ struct sockaddr rt_gateway; /**< Indicates the gateway address (RTF_GATEWAY). */ -+ struct sockaddr rt_genmask; /**< Indicates the target network mask (IP). */ -+ unsigned int rt_flags; -+}; -+/** Indicates that the route is usable */ -+#define RTF_UP 0x1 -+/** Indicates that the destination is a gateway */ -+#define RTF_GATEWAY 0x2 -+/** Indicates the host entry (net otherwise) */ -+#define RTF_HOST 0x4 -+/** Indicates the host or net is unreachable */ -+#define RTF_REJECT 0x8 -+/** Created dynamically (by redirect) */ -+#define RTF_DYNAMIC 0x10 -+/** Modified dynamically (by redirect) */ -+#define RTF_MODIFIED 0x20 -+/** Message confirmed. */ -+#define RTF_DONE 0x40 -+/* 0x80 unused, was RTF_DELCLONE */ -+/* 0x100 unused, was RTF_CLONING */ -+/** Indicates that the external daemon resolves name */ -+#define RTF_XRESOLVE 0x200 -+/** DEPRECATED - exists ONLY for backward -+ compatibility */ -+#define RTF_LLINFO 0x400 -+/** Used by apps to add/del L2 entries */ -+#define RTF_LLDATA 0x400 -+/** Manually added */ -+#define RTF_STATIC 0x800 -+ /** Discard packets */ -+#define RTF_BLACKHOLE 0x1000 -+/** Protocol specific routing flag */ -+#define RTF_PROTO2 0x4000 -+/** Protocol specific routing flag */ -+/* 0x10000 unused, was RTF_PRCLONING */ -+#define RTF_PROTO1 0x8000 -+/* 0x10000 unused, was RTF_PRCLONING */ -+/* 0x20000 unused, was RTF_WASCLONED */ -+/** Protocol specific routing flag */ -+#define RTF_PROTO3 0x40000 -+/** MTU was explicitly specified */ -+#define RTF_FIXEDMTU 0x80000 -+/** Route is immutable */ -+#define RTF_PINNED 0x100000 -+/** Route represents a local address */ -+#define RTF_LOCAL 0x200000 -+/** Route represents a broadcast address */ -+#define RTF_BROADCAST 0x400000 -+ /** Route represents a multicast address */ -+#define RTF_MULTICAST 0x800000 -+ /* 0x8000000 and up unassigned */ -+/** Always route dst->src */ -+#define RTF_STICKY 0x10000000 -+/** Radix node head is locked */ -+#define RTF_RNH_LOCKED 0x40000000 -+/** Indicates the compatibility bit for interacting -+ with existing routing apps */ -+#define RTF_GWFLAG_COMPAT 0x80000000 -+ -+/* Mask of RTF flags that are allowed to be modified by RTM_CHANGE. */ -+#define RTF_FMASK \ -+ (RTF_PROTO1 | RTF_PROTO2 | RTF_PROTO3 | RTF_BLACKHOLE | \ -+ RTF_REJECT | RTF_STATIC | RTF_STICKY) -+ -+/** -+* @defgroup ifaddrs_api ifaddrs API -+* This section contains the interfaces to get information about Network interfaces in lwIP. -+* @ingroup socket -+*/ -+ -+/* -+Func Name: lwip_getifaddrs -+*/ -+ -+/** -+* @ingroup ifaddrs_api -+* @brief Creates a linked list of struct ifaddrs, which holds the information -+* about the network interfaces of the local system. The ifa_next field contains a -+* pointer to the next structure on the list, or NULL if this is the last item of the list. -+* The ifa_name points to the null-terminated interface name. The ifa_flags field -+* contains the interface flags. The ifa_addr field points to a structure containing -+* the interface address. The ifa_netmask field points to a structure containing -+* the netmask associated with ifa_addr, if applicable, for the address family. -+* Depending on whether the bit IFF_brcast or IFF_POINTOPOINT is set -+* in ifa_flags (only one can be set at a time), either ifa_broadaddr will contain -+* the broadcast address associated with ifa_addr (if applicable for the address -+* family) or ifa_dstaddr will contain the destination address of the point-to-point -+* interface. -+* For IPv6, stack supports only IFF_UP,IFF_MULTICAST, IFF_DRV_RUNNING, and IFF_LOOPBACK -+* flags. -+* @param[in] ifap Indicates a double pointer to the ifaddrs structure. -+* @return -+* On success, lwip_getifaddrs() returns zero; on error, -1 is returned, and errno is set appropriately. -+* @par Errors -+* @li The lwip_getifaddrs() function shall fail if: -+* - [EACCES] : \n Invalid state of system. -+* - [ENOMEM] : \n In-sufficient memory. -+* @note -+* None -+*/ -+int lwip_getifaddrs(struct ifaddrs **ifap); -+ -+/* -+Func Name: lwip_freeifaddrs -+*/ -+ -+/** -+* @ingroup ifaddrs_api -+* @brief The function lwip_freeifaddrs, provides the list of network interfaces in the ifaddrs* structure. -+* The application has to free the memory of the ifaddrs * structure by using this function. -+* @param[in] ifa Indicates a pointer to the ifaddrs structure. -+* @return -+* Void -+* @note -+* None -+*/ -+void lwip_freeifaddrs(struct ifaddrs *ifa); -+ -+#endif /* !LWIP_LITEOS_COMPAT */ -+int get_ipv6_ifaddr(struct netif *netif, struct ifaddrs *ifaddr, int tmp_index); -+int get_ipv4_ifaddr(struct netif *netif, struct ifaddrs *ifaddr); -+struct ifaddrs_storage *new_ifaddrs_storage(void); -+#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 -@@ -48,7 +48,7 @@ - #include "lwip/etharp.h" - #include "lwip/ip.h" - #include "lwip/snmp.h" -- -+#include "lwip/raw.h" - #include - - #include "netif/ppp/ppp_opts.h" -@@ -167,6 +167,12 @@ - } - } - -+#if PF_PACKET_SOCKET -+ p->flags = (u16_t)(p->flags & ~PBUF_FLAG_OUTGOING); -+ if (get_packet_raw_pcbs() != NULL) { -+ raw_packet_input(p, netif, NULL); -+ } -+#endif /* PF_PACKET_SOCKET */ - switch (type) { - #if LWIP_IPV4 && LWIP_ARP - /* IP packet? */ -- Gitee From f9353a90e5671d2d4a964fedb68694bff6224f98 Mon Sep 17 00:00:00 2001 From: Terder-su Date: Wed, 16 Feb 2022 09:22:43 +0000 Subject: [PATCH 02/14] update origin.patch --- components/net/lwip/origin.patch | 8508 ++++++++++++++++++++++++++++++ 1 file changed, 8508 insertions(+) create mode 100644 components/net/lwip/origin.patch diff --git a/components/net/lwip/origin.patch b/components/net/lwip/origin.patch new file mode 100644 index 0000000..53bd155 --- /dev/null +++ b/components/net/lwip/origin.patch @@ -0,0 +1,8508 @@ +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 2022-02-16 16:06:59.162116000 +0800 ++++ b/lwip-2.1.2/src/api/api_lib.c 2022-01-28 11:50:38.000000000 +0800 +@@ -146,7 +146,7 @@ + * NULL on memory error + */ + struct netconn * +-netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) ++netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, netconn_callback callback) + { + struct netconn *conn; + API_MSG_VAR_DECLARE(msg); +@@ -292,6 +292,37 @@ + return err; + } + ++#if PF_PACKET_SOCKET ++/** ++ * Get the local or remote IP address and port of a netconn. ++ * For pf packet netconns, this returns the struct pf_packet_sockaddr_ll of the netconn! ++ * @param conn the netconn to query ++ * @param local 1 to get the local IP address, 0 to get the remote one ++ * @return ERR_CONN for invalid connections ++ * ERR_OK if the information was retrieved ++ * ERR_OPNOTSUPP if the option is not support ++ */ ++err_t ++netconn_get_sockaddr_pf_packet(struct netconn *conn, struct pf_packet_sockaddr_ll *ll, u8_t local) ++{ ++ err_t err; ++ API_MSG_VAR_DECLARE(msg); ++ API_MSG_VAR_ALLOC(msg); ++ API_MSG_VAR_REF(msg).conn = conn; ++ API_MSG_VAR_REF(msg).msg.adpkt.local = local; ++#if LWIP_MPU_COMPATIBLE ++ err = netconn_apimsg(lwip_netconn_do_getaddr_pfpkt, &API_MSG_VAR_REF(msg)); ++ *ll = msg->msg.adpkt.ll; ++#else /* LWIP_MPU_COMPATIBLE */ ++ API_MSG_VAR_REF(msg).msg.adpkt.ll = ll; ++ err = netconn_apimsg(lwip_netconn_do_getaddr_pfpkt, &msg); ++#endif /* LWIP_MPU_COMPATIBLE */ ++ API_MSG_VAR_FREE(msg); ++ ++ return err; ++} ++#endif ++ + /** + * @ingroup netconn_common + * Bind a netconn to a specific local IP address and port. +@@ -304,9 +335,13 @@ + * @return ERR_OK if bound, any other err_t on failure + */ + err_t ++#if PF_PACKET_SOCKET ++netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port, u8_t if_idx) ++#else /* PF_PACKET_SOCKET */ + netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port) ++#endif + { +- API_MSG_VAR_DECLARE(msg); ++ API_MSG_VAR_DECLARE(msg); /* struct api_msg *msg */ + err_t err; + + LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); +@@ -332,6 +367,9 @@ + API_MSG_VAR_REF(msg).conn = conn; + API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); + API_MSG_VAR_REF(msg).msg.bc.port = port; ++#if PF_PACKET_SOCKET ++ API_MSG_VAR_REF(msg).msg.bc.if_idx = if_idx; ++#endif /* PF_PACKET_SOCKET */ + err = netconn_apimsg(lwip_netconn_do_bind, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + +@@ -596,7 +634,7 @@ + + NETCONN_MBOX_WAITING_INC(conn); + if (netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK) || +- (conn->flags & NETCONN_FLAG_MBOXCLOSED) || (conn->pending_err != ERR_OK)) { ++ (conn->flags & NETCONN_FLAG_MBOXCLOSED)) { + 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; + } + SYS_ARCH_PROTECT(lev); +- err = conn->pending_err; +- conn->pending_err = ERR_OK; ++ err = conn->last_err; + SYS_ARCH_UNPROTECT(lev); + 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 2022-02-16 16:06:59.162116000 +0800 ++++ b/lwip-2.1.2/src/api/api_msg.c 2022-01-28 12:10:58.000000000 +0800 +@@ -184,10 +184,36 @@ + return 0; + } + ++#if PF_PACKET_SOCKET ++ /* To get the pkt type filtered in ethernet_input */ ++ q->flags = p->flags; ++#if ETH_PAD_SIZE ++ /* exclude the begining two padding bytes in struct eth_hdr */ ++ if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_PACKET_RAW) && (pbuf_header(q, -ETH_PAD_SIZE))) { ++ (void)pbuf_free(q); ++ memp_free(MEMP_NETBUF, buf); ++ return 0; ++ } ++#endif ++#endif ++ + buf->p = q; + buf->ptr = q; ++#if PF_PACKET_SOCKET ++ /* IP addr is NULL only when RAW packets are received for PF_PACKET sockets */ ++ if (addr == NULL) { ++ ip_addr_set_any(IP_IS_V6_VAL(buf->addr), &buf->addr); ++ buf->port = eth_current_hdr()->type; ++ buf->hatype = eth_current_netif()->link_layer_type; ++ buf->netifindex = eth_current_netif()->ifindex; ++ } else { ++ ip_addr_copy(buf->addr, *ip_current_src_addr()); ++ buf->port = pcb->raw_proto; ++ } ++#else + ip_addr_copy(buf->addr, *ip_current_src_addr()); + buf->port = pcb->protocol; ++#endif + + len = q->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { +@@ -444,7 +470,7 @@ + /* when err is called, the pcb is deallocated, so delete the reference */ + conn->pcb.tcp = NULL; + /* store pending error */ +- conn->pending_err = err; ++ conn->last_err = err; + /* prevent application threads from blocking on 'recvmbox'/'acceptmbox' */ + conn->flags |= NETCONN_FLAG_MBOXCLOSED; + +@@ -627,23 +653,41 @@ + if (msg->conn->pcb.raw != NULL) { + #if LWIP_IPV6 + /* ICMPv6 packets should always have checksum calculated by the stack as per RFC 3542 chapter 3.1 */ +- if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->protocol == IP6_NEXTH_ICMP6) { ++ if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->raw_proto == IP6_NEXTH_ICMP6) { + msg->conn->pcb.raw->chksum_reqd = 1; + msg->conn->pcb.raw->chksum_offset = 2; + } + #endif /* LWIP_IPV6 */ ++ ++#if LWIP_IPV4 ++ /* IP_HDRINCL is enabled by default */ ++ if (!(NETCONNTYPE_ISIPV6(msg->conn->type)) && (msg->msg.n.proto == IPPROTO_RAW)) { ++ raw_set_flags(msg->conn->pcb.raw, RAW_FLAGS_HDRINCL); ++ } ++#endif + raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); + } + break; ++ ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++ msg->conn->pcb.packet_raw = raw_packet_new(msg->msg.n.proto); ++ if (msg->conn->pcb.packet_raw == NULL) { ++ msg->err = ERR_MEM; ++ break; ++ } ++ raw_recv(msg->conn->pcb.packet_raw, recv_raw, msg->conn); ++ break; ++#endif + #endif /* LWIP_RAW */ + #if LWIP_UDP +- case NETCONN_UDP: +- msg->conn->pcb.udp = udp_new_ip_type(iptype); +- if (msg->conn->pcb.udp != NULL) { ++ case NETCONN_UDP: ++ msg->conn->pcb.udp = udp_new_ip_type(iptype); ++ if (msg->conn->pcb.udp != NULL) { + #if LWIP_UDPLITE +- if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { +- udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); +- } ++ if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { ++ udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); ++ } + #endif /* LWIP_UDPLITE */ + if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); +@@ -683,7 +727,7 @@ + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp == NULL) { +- pcb_new(msg); ++ pcb_new(msg); //raw_recv() + } + /* Else? This "new" connection already has a PCB allocated. */ + /* Is this an error condition? Should it be deleted? */ +@@ -713,13 +757,16 @@ + return NULL; + } + +- conn->pending_err = ERR_OK; ++ conn->last_err = ERR_OK; + conn->type = t; + conn->pcb.tcp = NULL; + + /* If all sizes are the same, every compiler should optimize this switch to nothing */ + switch (NETCONNTYPE_GROUP(t)) { + #if LWIP_RAW ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++#endif + case NETCONN_RAW: + size = DEFAULT_RAW_RECVMBOX_SIZE; + break; +@@ -778,8 +825,17 @@ + conn->linger = -1; + #endif /* LWIP_SO_LINGER */ + conn->flags = init_flags; ++#if LWIP_TCP ++ conn->pending_err = 0; ++ conn->refused_data = NULL; ++ ip_addr_set_zero(&conn->remote_ip); ++ conn->remote_port = 0; ++#endif + return conn; + free_and_return: ++ if (sys_sem_valid(&conn->op_completed) != 0) { ++ sys_sem_free(&conn->op_completed); ++ } + memp_free(MEMP_NETCONN, conn); + return NULL; + } +@@ -1160,6 +1216,11 @@ + case NETCONN_RAW: + raw_remove(msg->conn->pcb.raw); + break; ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++ raw_packet_remove(msg->conn->pcb.packet_raw); ++ break; ++#endif + #endif /* LWIP_RAW */ + #if LWIP_UDP + case NETCONN_UDP: +@@ -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)) || ++ ip_addr_ismulticast(API_EXPR_REF(msg->msg.bc.ipaddr)) || ++ netif_ipaddr_isbrdcast(API_EXPR_REF(msg->msg.bc.ipaddr)) || ++ ((netif != NULL) && netif_is_up(netif)))) { ++ msg->err = ERR_NOADDR; ++ } else ++#endif ++ { ++ msg->err = ERR_VAL; ++ if (msg->conn->pcb.tcp != NULL) { ++ switch (NETCONNTYPE_GROUP(msg->conn->type)) { + #if LWIP_RAW + case NETCONN_RAW: +- err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); ++ msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); ++ break; ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++ msg->err = raw_packet_bind(msg->conn->pcb.packet_raw, msg->msg.bc.if_idx, msg->msg.bc.port); + break; ++#endif + #endif /* LWIP_RAW */ + #if LWIP_UDP + case NETCONN_UDP: +- err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); ++ msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; + #endif /* LWIP_UDP */ + #if LWIP_TCP + case NETCONN_TCP: +- err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); ++ if (msg->conn->pcb.tcp->local_port == 0) { ++ msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); ++ } else { ++ msg->err = ERR_VAL; ++ } ++ + break; + #endif /* LWIP_TCP */ + default: +- err = ERR_VAL; ++ msg->err = ERR_OPNOTSUPP; + break; ++ } + } +- } else { +- err = ERR_VAL; + } +- msg->err = err; + TCPIP_APIMSG_ACK(msg); + } + /** +@@ -1351,6 +1435,11 @@ + { + struct api_msg *msg = (struct api_msg *)m; + err_t err; ++ if (ERR_IS_FATAL(msg->conn->last_err)) { ++ msg->err = msg->conn->last_err; ++ TCPIP_APIMSG_ACK(msg); ++ return; ++ } + + if (msg->conn->pcb.tcp == NULL) { + /* This may happen when calling netconn_connect() a second time */ +@@ -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)) { ++#if PF_PACKET_SOCKET ++ struct ip_hdr *iphdr = NULL; ++ ip_addr_t dest_addr; ++ ++ if (!(msg->conn->pcb.raw->flags & RAW_FLAGS_CONNECTED) || ++ ip_addr_isany(&msg->conn->pcb.raw->remote_ip)) { ++ if (raw_is_flag_set(msg->conn->pcb.raw, RAW_FLAGS_HDRINCL)) { ++ if (msg->msg.b->p->len < IP_HLEN) { ++ err = ERR_MSGSIZE; ++ break; ++ } ++ ++ /* IP header already included in p */ ++ iphdr = (struct ip_hdr *)msg->msg.b->p->payload; ++ ip_addr_copy_from_ip4(dest_addr, iphdr->dest); ++ err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &dest_addr); ++ break; ++ } ++ ++ err = ERR_NODEST; ++ break; ++ } ++#endif /* PF_PACKET_SOCKET */ + err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); + } else { + err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr); + } + break; ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++ /* Check if its for sending RAW packets for PF_PACKET family */ ++ if (msg->msg.b->flags & NETBUF_FLAG_IFINDEX) { ++ err = raw_packet_sendto(msg->conn->pcb.packet_raw, msg->msg.b->p, msg->msg.b->netifindex); ++ } else { ++ err = raw_packet_sendto(msg->conn->pcb.packet_raw, msg->msg.b->p, 0); ++ } ++ break; ++#endif + #endif + #if LWIP_UDP + case NETCONN_UDP: +@@ -1868,6 +1990,11 @@ + { + struct api_msg *msg = (struct api_msg *)m; + ++ if ((msg->conn == NULL) || (msg->conn->pcb.tcp == NULL)) { ++ msg->err = ERR_CONN; ++ TCPIP_APIMSG_ACK(msg); ++ return; ++ } + if (msg->conn->pcb.ip != NULL) { + if (msg->msg.ad.local) { + ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), +@@ -1882,10 +2009,18 @@ + #if LWIP_RAW + case NETCONN_RAW: + if (msg->msg.ad.local) { +- API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; ++ ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), ++ msg->conn->pcb.raw->local_ip); ++ API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->raw_proto; + } else { +- /* return an error as connecting is only a helper for upper layers */ +- msg->err = ERR_CONN; ++ if (raw_is_flag_set(msg->conn->pcb.raw, RAW_FLAGS_CONNECTED)) { ++ ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), ++ msg->conn->pcb.raw->remote_ip); ++ API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->raw_proto; ++ } else { ++ /* return an error as connecting is only a helper for upper layers */ ++ msg->err = ERR_CONN; ++ } + } + break; + #endif /* LWIP_RAW */ +@@ -1923,6 +2058,47 @@ + TCPIP_APIMSG_ACK(msg); + } + ++#if PF_PACKET_SOCKET ++/** ++ * Return a pf pkt socket's local address ++ * Called from netconn_getaddr ++ * ++ * @param m the api_msg pointing to the connection ++ */ ++void ++lwip_netconn_do_getaddr_pfpkt(void *m) ++{ ++ struct api_msg *msg = (struct api_msg *)m; ++ struct pf_packet_sockaddr_ll ll; ++ msg->err = ERR_OK; ++ if (msg->conn->pcb.ip != NULL) { ++ /* Non standard way of do it, but doing it :( */ ++ if (msg->msg.adpkt.local) { ++ ll.sll_protocol = msg->conn->pcb.packet_raw->proto.eth_proto; ++ ll.if_idx = msg->conn->pcb.packet_raw->netifindex; ++ struct netif *netif = netif_find_by_ifindex(msg->conn->pcb.packet_raw->netifindex); ++ if (netif == NULL) { ++ LWIP_DEBUGF(SOCKETS_DEBUG, ++ ("lwip_getaddrname:netif not found for given ifindex (%u)\n", ++ msg->conn->pcb.packet_raw->netifindex)); ++ ll.sll_halen = 0; ++ ll.sll_hatype = 0; ++ } else { ++ ll.sll_hatype = netif->link_layer_type; ++ ll.sll_halen = NETIF_MAX_HWADDR_LEN; ++ (void)memcpy_s(ll.sll_addr, ll.sll_halen, netif->hwaddr, NETIF_MAX_HWADDR_LEN); ++ } ++ API_EXPR_DEREF(msg->msg.adpkt.ll) = ll; ++ } else { ++ msg->err = ERR_OPNOTSUPP; ++ } ++ } else { ++ msg->err = ERR_CONN; ++ } ++ TCPIP_APIMSG_ACK(msg); ++} ++#endif ++ + /** + * 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 2022-02-16 16:06:59.162116000 +0800 ++++ b/lwip-2.1.2/src/api/netbuf.c 2022-01-26 06:41:32.000000000 +0800 +@@ -48,7 +48,7 @@ + + #include "lwip/netbuf.h" + #include "lwip/memp.h" +- ++#include "lwip/api.h" + #include + + /** +@@ -99,7 +99,7 @@ + * NULL if no memory could be allocated + */ + void * +-netbuf_alloc(struct netbuf *buf, u16_t size) ++netbuf_alloc(struct netbuf *buf, u16_t size, u8_t netconn_type) + { + LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); + +@@ -107,7 +107,22 @@ + if (buf->p != NULL) { + pbuf_free(buf->p); + } +- buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); ++ ++ switch (netconn_type) { ++#if LWIP_RAW ++ case NETCONN_RAW: ++ buf->p = pbuf_alloc(PBUF_IP, size, PBUF_RAM); ++ break; ++#endif /* LWIP_RAW */ ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++ buf->p = pbuf_alloc(PBUF_LINK, size, PBUF_RAM); ++ break; ++#endif /* PF_PACKET_SOCKET */ ++ default: ++ buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); ++ } ++ + if (buf->p == NULL) { + 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 2022-02-16 16:06:59.162116000 +0800 ++++ b/lwip-2.1.2/src/api/netdb.c 2022-01-29 08:53:10.000000000 +0800 +@@ -58,7 +58,7 @@ + + /** h_errno is exported in netdb.h for access by applications. */ + #if LWIP_DNS_API_DECLARE_H_ERRNO +-int h_errno; ++int h_err_no; + #endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ + + /** define "hostent" variables storage: 0 if we use a static (but unprotected) +@@ -100,7 +100,7 @@ + err = netconn_gethostbyname(name, &addr); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); +- h_errno = HOST_NOT_FOUND; ++ h_err_no = HOST_NOT_FOUND; + return NULL; + } + +@@ -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; ++#if defined(SIN6_LEN) + sa6->sin6_len = sizeof(struct sockaddr_in6); ++#endif ++ sa6->sin6_flowinfo = 0; + sa6->sin6_port = lwip_htons((u16_t)port_nr); + sa6->sin6_scope_id = ip6_addr_zone(ip_2_ip6(&addr)); + ai->ai_family = AF_INET6; ++ ai->ai_addrlen = sizeof(struct sockaddr_in6); + #endif /* LWIP_IPV6 */ + } else { + #if LWIP_IPV4 +@@ -385,9 +394,9 @@ + /* set up sockaddr */ + inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr)); + sa4->sin_family = AF_INET; +- sa4->sin_len = sizeof(struct sockaddr_in); + sa4->sin_port = lwip_htons((u16_t)port_nr); + ai->ai_family = AF_INET; ++ ai->ai_addrlen = sizeof(struct sockaddr_in); + #endif /* LWIP_IPV4 */ + } + +@@ -403,7 +412,6 @@ + MEMCPY(ai->ai_canonname, nodename, namelen); + ai->ai_canonname[namelen] = 0; + } +- ai->ai_addrlen = sizeof(struct sockaddr_storage); + ai->ai_addr = (struct sockaddr *)sa; + + *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 2022-02-16 16:06:59.162116000 +0800 ++++ b/lwip-2.1.2/src/api/netifapi.c 2022-01-26 07:39:08.000000000 +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) + ++#if LWIP_MPU_COMPATIBLE ++static inline err_t netifapi_msg_alloc(struct netifapi_msg **name) ++{ ++ API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, (*name), ERR_MEM); ++ LWIP_UNUSED_ARG(name); ++ return ERR_OK; ++} ++#else ++static inline err_t netifapi_msg_alloc(struct netifapi_msg *name) ++{ ++ LWIP_UNUSED_ARG(name); ++ return ERR_OK; ++} ++#endif ++ + /** + * Call netif_add() inside the tcpip_thread context. + */ +@@ -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, +- msg->msg.add.input)) { ++ msg->msg.add_get.init, ++ msg->msg.add_get.input)) { + return ERR_IF; + } else { + return ERR_OK; +@@ -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; +- NETIFAPI_VAR_REF(msg).msg.add.init = init; +- NETIFAPI_VAR_REF(msg).msg.add.input = input; ++ NETIFAPI_VAR_REF(msg).msg.add_get.init = init; ++ NETIFAPI_VAR_REF(msg).msg.add_get.input = input; + err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call); + NETIFAPI_VAR_FREE(msg); + return err; +@@ -377,4 +395,60 @@ + return err; + } + ++/** ++ * Call netif_find() inside the tcpip_thread context. ++ */ ++static err_t ++do_netifapi_netif_find_by_name(struct tcpip_api_call_data *m) ++{ ++ struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; ++ ++ msg->netif = netif_find(msg->msg.find_by_name.name); ++ return ERR_OK; ++} ++ ++struct netif* ++netifapi_netif_find_by_name(const char *name) ++{ ++ struct netif *netif = NULL; ++ NETIFAPI_VAR_DECLARE(msg); ++ if (netifapi_msg_alloc(&msg) != ERR_OK) { ++ return NULL; ++ } ++ ++ NETIFAPI_VAR_REF(msg).netif = NULL; ++ NETIFAPI_VAR_REF(msg).msg.find_by_name.name = name; ++ (void)tcpip_api_call(do_netifapi_netif_find_by_name, &API_VAR_REF(msg).call); ++ netif = NETIFAPI_VAR_REF(msg).netif; ++ NETIFAPI_VAR_FREE(msg); ++ return netif; ++} ++ ++/** ++ * Call netif_find_by_ipaddr() inside the tcpip_thread context. ++ */ ++static err_t ++do_netifapi_netif_find_by_ipaddr(struct tcpip_api_call_data *m) ++{ ++ struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; ++ msg->netif = netif_find_by_ipaddr(msg->msg.find_by_ipaddr.ipaddr); ++ return ERR_OK; ++} ++ ++struct netif * ++netifapi_netif_find_by_ipaddr(const ip_addr_t *ipaddr) ++{ ++ struct netif *netif = NULL; ++ NETIFAPI_VAR_DECLARE(msg); ++ if (netifapi_msg_alloc(&msg) != ERR_OK) { ++ return NULL; ++ } ++ ++ NETIFAPI_VAR_REF(msg).netif = NULL; ++ NETIFAPI_VAR_REF(msg).msg.find_by_ipaddr.ipaddr = ipaddr; ++ (void)tcpip_api_call(do_netifapi_netif_find_by_ipaddr, &API_VAR_REF(msg).call); ++ netif = NETIFAPI_VAR_REF(msg).netif; ++ NETIFAPI_VAR_FREE(msg); ++ return netif; ++} + #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 2022-02-16 16:06:59.162116000 +0800 ++++ b/lwip-2.1.2/src/api/sockets.c 2022-01-29 09:25:30.000000000 +0800 +@@ -54,6 +54,7 @@ + #include "lwip/netif.h" + #include "lwip/priv/tcpip_priv.h" + #include "lwip/mld6.h" ++#include "lwip/dhcp.h" + #if LWIP_CHECKSUM_ON_COPY + #include "lwip/inet_chksum.h" + #endif +@@ -85,9 +86,19 @@ + #define API_SELECT_CB_VAR_ALLOC(name, retblock) API_VAR_ALLOC_EXT(struct lwip_select_cb, MEMP_SELECT_CB, name, retblock) + #define API_SELECT_CB_VAR_FREE(name) API_VAR_FREE(MEMP_SELECT_CB, name) + ++#if !LWIP_LITEOS_COMPAT ++#defeine SIN4_LEN(x) \ ++ (x)->sin_len = sizeof(struct sockaddr_in) ++#defeine SIN6_LEN(x) \ ++ (x)->sin6_len = sizeof(struct sockaddr_in6) ++#else ++#define SIN4_LEN(x) ++#define SIN6_LEN(x) ++#endif /* LWIP_LITEOS_COMPAT */ ++ + #if LWIP_IPV4 + #define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \ +- (sin)->sin_len = sizeof(struct sockaddr_in); \ ++ SIN4_LEN(sin); \ + (sin)->sin_family = AF_INET; \ + (sin)->sin_port = lwip_htons((port)); \ + inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \ +@@ -98,8 +109,10 @@ + #endif /* LWIP_IPV4 */ + + #if LWIP_IPV6 ++/* SIN6_LEN macro is to differntiate whether stack is using 4.3BSD or 4.4BSD variants of sockaddr_in6 ++structure */ + #define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \ +- (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ ++ SIN6_LEN(sin6); \ + (sin6)->sin6_family = AF_INET6; \ + (sin6)->sin6_port = lwip_htons((port)); \ + (sin6)->sin6_flowinfo = 0; \ +@@ -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) + ++#if LWIP_LITEOS_COMPAT ++#define VALIDATE_GET_RAW_OPTNAME_RET(_sock, _optname) do { \ ++ if ((_sock)->conn != NULL && (NETCONNTYPE_GROUP((_sock)->conn->type) == NETCONN_RAW) && \ ++ (((_optname) != SO_BROADCAST) && ((_optname) != SO_RCVTIMEO) && \ ++ ((_optname) != SO_RCVBUF) && ((_optname) != SO_TYPE) && \ ++ ((_optname) != SO_DONTROUTE) && ((_optname) != SO_BINDTODEVICE))) { \ ++ done_socket(_sock); \ ++ return ENOPROTOOPT; \ ++ } \ ++ } while (0) ++ ++#if PF_PACKET_SOCKET ++#define VALIDATE_SET_PF_PKT_OPTNAME_RET(_s, _sock, _level, _optname) do { \ ++ if ((_level) == SOL_PACKET && ((_optname) != SO_RCVTIMEO && (_optname) != SO_RCVBUF) && \ ++ (_optname) != SO_ATTACH_FILTER && (_optname) != SO_DETACH_FILTER) { \ ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_PACKET, UNIMPL: optname=0x%x, ..)\n", \ ++ (_s), (_optname))); \ ++ done_socket(_sock); \ ++ return ENOPROTOOPT; \ ++ } \ ++ } while (0) ++ ++#define VALIDATE_GET_PF_PKT_OPTNAME_RET(_s,_sock,_level,_optname) do { \ ++ if ((_sock)->conn != NULL && (NETCONNTYPE_GROUP((_sock)->conn->type) == NETCONN_PACKET_RAW) && \ ++ (_level) == SOL_PACKET && ((_optname) != SO_RCVTIMEO && (_optname) != SO_RCVBUF && (_optname) != SO_TYPE)) { \ ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%p, SOL_PACKET, UNIMPL: optname=0x%x, ..)\n", \ ++ (_s), (_optname))); \ ++ done_socket(_sock); \ ++ return ENOPROTOOPT; \ ++ } \ ++ } while (0) ++ ++#define VALIDATE_LEVEL_PF_PACKET(_sock,_level) \ ++ if ((_sock)->conn != NULL && ((NETCONNTYPE_GROUP(netconn_type(_sock->conn)) == NETCONN_PACKET_RAW \ ++ && SOL_SOCKET != (_level) && SOL_PACKET != (_level)) || \ ++ (NETCONNTYPE_GROUP((_sock)->conn->type) != NETCONN_PACKET_RAW && SOL_PACKET == (_level)))) ++#endif ++#endif /* LWIP_LITEOS_COMPAT */ ++ + /* 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 +564,29 @@ + return sock; + } + ++#if LWIP_LITEOS_COMPAT ++/* get numbers of unused sockets */ ++int get_unused_socket_num(void) ++{ ++ int unused = 0, i; ++ SYS_ARCH_DECL_PROTECT(lev); ++ SYS_ARCH_PROTECT(lev); ++ ++ for (i = 0; i < (int)(NUM_SOCKETS); i++) { ++ if (!sockets[i].conn ++#if LWIP_NETCONN_FULLDUPLEX ++ && !sockets[i].fd_used ++#endif ++ ) { ++ unused++; ++ } ++ } ++ ++ SYS_ARCH_UNPROTECT(lev); ++ return unused; ++} ++#endif /* LWIP_LITEOS_COMPAT */ ++ + /** + * Allocate a new socket for a given netconn. + * +@@ -696,8 +794,10 @@ + } + + IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); +- if (*addrlen > tempaddr.sa.sa_len) { +- *addrlen = tempaddr.sa.sa_len; ++ if (IP_IS_V4_VAL(naddr) && (*addrlen > (int)sizeof(struct sockaddr_in))) { ++ *addrlen = sizeof(struct sockaddr_in); ++ } else if (IP_IS_V6_VAL(naddr) && (*addrlen > (int)sizeof(struct sockaddr_in6))) { ++ *addrlen = sizeof(struct sockaddr_in6); + } + MEMCPY(addr, &tempaddr, *addrlen); + +@@ -722,28 +822,59 @@ + u16_t local_port; + err_t err; + ++#if PF_PACKET_SOCKET ++ const struct sockaddr_ll *name_ll = NULL; ++ u8_t local_if_idx = 0; ++#endif + sock = get_socket(s); + if (!sock) { + return -1; + } + +- if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { +- /* sockaddr does not match socket type (IPv4/IPv6) */ +- sock_set_errno(sock, err_to_errno(ERR_VAL)); +- done_socket(sock); +- return -1; +- } +- + /* check size, family and alignment of 'name' */ +- LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && ++#if PF_PACKET_SOCKET ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { ++ name_ll = (const struct sockaddr_ll *)(void*)name; ++ LWIP_ERROR("lwip_bind: invalid address", ((name_ll != NULL)&&(namelen == sizeof(struct sockaddr_ll)) && ++ ((name_ll->sll_family) == PF_PACKET) && IS_SOCK_ADDR_ALIGNED(name) && ++ (name_ll->sll_ifindex <= LWIP_NETIF_IFINDEX_MAX)), sock_set_errno(sock, err_to_errno(ERR_VAL)); ++ done_socket(sock); return -1); ++ ++ ip_addr_set_any_val(IPADDR_TYPE_V4, local_addr); ++ local_port = name_ll->sll_protocol; ++ local_if_idx = (u8_t)name_ll->sll_ifindex; ++ ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, ", s)); ++ LWIP_DEBUGF(SOCKETS_DEBUG, (" ifindex=%u proto=%"U16_F")\n", local_if_idx, local_port)); ++ } else ++#endif ++ { ++ 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); ++ ++ if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { ++ /* sockaddr does not match socket type (IPv4/IPv6) */ ++ sock_set_errno(sock, err_to_errno(ERR_VAL)); ++ done_socket(sock); ++ return -1; ++ } ++ ++ /* check size, family and alignment of 'name' */ ++ LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)), + sock_set_errno(sock, err_to_errno(ERR_ARG)); done_socket(sock); return -1;); +- LWIP_UNUSED_ARG(namelen); ++ LWIP_UNUSED_ARG(namelen); + +- SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); +- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); +- ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); +- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); ++ SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); ++ ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); ++ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); ++ } + + #if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ +@@ -753,7 +884,11 @@ + } + #endif /* LWIP_IPV4 && LWIP_IPV6 */ + ++#if PF_PACKET_SOCKET ++ err = netconn_bind(sock->conn, &local_addr, local_port, local_if_idx); ++#else /* PF_PACKET_SOCKET */ + err = netconn_bind(sock->conn, &local_addr, local_port); ++#endif + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); +@@ -820,6 +955,14 @@ + return -1; + } + ++#if PF_PACKET_SOCKET ++ if (NETCONN_PACKET_RAW & NETCONNTYPE_GROUP(netconn_type(sock->conn))) { ++ sock_set_errno(sock, EOPNOTSUPP); ++ done_socket(sock); ++ return -1; ++ } ++#endif ++ + 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 +1168,7 @@ + { + int truncated = 0; + union sockaddr_aligned saddr; ++ socklen_t sa_len; + + LWIP_UNUSED_ARG(conn); + +@@ -1041,10 +1185,27 @@ + #endif /* LWIP_IPV4 && LWIP_IPV6 */ + + IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port); +- if (*fromlen < saddr.sa.sa_len) { ++#if LWIP_LITEOS_COMPAT ++ if (IP_IS_V4_VAL(*fromaddr)) { ++ sa_len = sizeof(struct sockaddr_in); ++ } ++#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 */ ++ ++ if (*fromlen < sa_len) { + truncated = 1; +- } else if (*fromlen > saddr.sa.sa_len) { +- *fromlen = saddr.sa.sa_len; ++ } else if (*fromlen > sa_len) { ++ *fromlen = sa_len; + } + MEMCPY(from, &saddr, *fromlen); + return truncated; +@@ -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) { +- lwip_sock_make_addr(sock->conn, netbuf_fromaddr(buf), netbuf_fromport(buf), +- (struct sockaddr *)msg->msg_name, &msg->msg_namelen); ++#if PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT ++ struct sockaddr_ll sll; ++ ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { ++ if (msg->msg_namelen > sizeof(sll)) { ++ msg->msg_namelen = sizeof(sll); ++ } ++ ++ if (msg->msg_namelen) { ++ (void)memset_s(&sll, sizeof(sll), 0, sizeof(sll)); ++ sll.sll_family = PF_PACKET; ++ sll.sll_protocol = netbuf_fromport(buf); ++ sll.sll_hatype = netbuf_fromhatype(buf); ++ sll.sll_ifindex = netbuf_fromifindex(buf); ++ ++ if (buf->p->flags & PBUF_FLAG_LLBCAST) { ++ sll.sll_pkttype = PACKET_BROADCAST; ++ } else if (buf->p->flags & PBUF_FLAG_LLMCAST) { ++ sll.sll_pkttype = PACKET_MULTICAST; ++ } else if (buf->p->flags & PBUF_FLAG_HOST) { ++ sll.sll_pkttype = PACKET_HOST; ++ } else if (buf->p->flags & PBUF_FLAG_OUTGOING) { ++ sll.sll_pkttype = PACKET_OUTGOING; ++ } else { ++ sll.sll_pkttype = PACKET_OTHERHOST; ++ } ++ ++ (void)memcpy_s(msg->msg_name, msg->msg_namelen, (void *)&sll, msg->msg_namelen); ++ ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom_udp_raw(%d): hatype=%u", dbg_s, ntohs(sll.sll_hatype))); ++ LWIP_DEBUGF(SOCKETS_DEBUG, (" packet type = %u\n", sll.sll_pkttype)); ++ } ++ } else ++#endif /* PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT */ ++ { ++ lwip_sock_make_addr(sock->conn, netbuf_fromaddr(buf), netbuf_fromport(buf), ++ (struct sockaddr *)msg->msg_name, &msg->msg_namelen); ++ } + } + } ++ + + /* 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. */ +- if (netbuf_alloc(&chain_buf, (u16_t)size) == NULL) { ++ if (netbuf_alloc(&chain_buf, (u16_t)size, NETCONNTYPE_GROUP(netconn_type(sock->conn))) == NULL) { + err = ERR_MEM; + } else { + /* flatten the IO vectors */ +@@ -1588,8 +1784,14 @@ + struct lwip_sock *sock; + err_t err; + u16_t short_size; +- u16_t remote_port; ++ u16_t remote_port = 0; + struct netbuf buf; ++#if (PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT) ++ const struct sockaddr_ll *to_ll = NULL; ++#endif ++ const struct sockaddr_in *to_in = NULL; ++ ++ unsigned int acceptable_flags = 0; + + sock = get_socket(s); + if (!sock) { +@@ -1608,11 +1810,62 @@ + #endif /* LWIP_TCP */ + } + +- if (size > LWIP_MIN(0xFFFF, SSIZE_MAX)) { +- /* cannot fit into one datagram (at least for us) */ +- sock_set_errno(sock, EMSGSIZE); +- done_socket(sock); +- return -1; ++#if PF_PACKET_SOCKET ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { ++ to_ll = (const struct sockaddr_ll *)(void *)to; ++ ++ LWIP_ERROR("lwip_sendto: invalid address", (((data != NULL) && (size!=0)) && ++ (((to_ll != NULL) && (tolen == sizeof(struct sockaddr_ll))) && ++ ((to_ll->sll_family) == PF_PACKET) && ((((mem_ptr_t)to_ll) % 4) == 0)) && ++ (to_ll->sll_ifindex <= LWIP_NETIF_IFINDEX_MAX)), ++ sock_set_errno(sock, err_to_errno(ERR_VAL)); ++ done_socket(sock); return -1); ++ ++ LWIP_ERROR("lwip_sendto: invalid address family", ((to_ll->sll_family) == PF_PACKET), ++ sock_set_errno(sock, err_to_errno(ERR_AFNOSUPP)); ++ done_socket(sock); return -1); ++ ++ LWIP_ERROR("lwip_sendto: invalid flags. Should be 0", (flags == 0), ++ sock_set_errno(sock, err_to_errno(ERR_OPNOTSUPP)); ++ done_socket(sock); return -1); ++ ++ if (size > LWIP_MAX_PF_RAW_SEND_SIZE) { ++ sock_set_errno(sock, EMSGSIZE); ++ done_socket(sock); ++ return -1; ++ } ++ } else ++#endif /* PF_PACKET_SOCKET */ ++ { ++ to_in = (const struct sockaddr_in *)(void*)to; ++ acceptable_flags = acceptable_flags | MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL; ++ if ((~acceptable_flags) & (unsigned int)flags) { ++ sock_set_errno(sock, err_to_errno(ERR_OPNOTSUPP)); ++ done_socket(sock); ++ return -1; ++ } ++ ++ LWIP_ERROR("lwip_sendto: invalid address", ((data != NULL) && (size!=0) && (flags>=0)), ++ sock_set_errno(sock, err_to_errno(ERR_VAL)); ++ done_socket(sock); return -1); ++ ++ LWIP_ERROR("lwip_sendto: invalid address", (((to_in == NULL) && (tolen == 0)) || ++ (((to_in == NULL) && (tolen != 0)) || IS_SOCK_ADDR_LEN_VALID(tolen))), ++ sock_set_errno(sock, err_to_errno(ERR_VAL)); ++ done_socket(sock); ++ return -1); ++ ++ LWIP_ERROR("lwip_sendto: invalid address", (to == NULL || IS_SOCK_ADDR_TYPE_VALID(to)), ++ sock_set_errno(sock, err_to_errno(ERR_AFNOSUPPORT)); ++ done_socket(sock); ++ return -1); ++ ++ if (size > LWIP_MAX_UDP_RAW_SEND_SIZE) { ++ sock_set_errno(sock, EMSGSIZE); ++ done_socket(sock); ++ return -1; ++ } ++ + } + short_size = (u16_t)size; + LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || +@@ -1626,6 +1879,9 @@ + #if LWIP_CHECKSUM_ON_COPY + buf.flags = 0; + #endif /* LWIP_CHECKSUM_ON_COPY */ ++#if PF_PACKET_SOCKET ++ buf.netifindex = 0; ++#endif + if (to) { + SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port); + } else { +@@ -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)); +- ip_addr_debug_print_val(SOCKETS_DEBUG, buf.addr); +- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); +- ++#if PF_PACKET_SOCKET ++ if (buf.flags & NETBUF_FLAG_IFINDEX) { ++ LWIP_DEBUGF(SOCKETS_DEBUG, (" netifindex = %d\n", buf.netifindex)); ++ } else ++#endif ++ { ++ ip_addr_debug_print_val(SOCKETS_DEBUG, buf.addr); ++ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); ++ } + /* make the buffer point to the data that should be sent */ + #if LWIP_NETIF_TX_SINGLE_PBUF + /* Allocate a new netbuf and copy the data into it. */ +- if (netbuf_alloc(&buf, short_size) == NULL) { ++ if (netbuf_alloc(&buf, short_size, NETCONNTYPE_GROUP(netconn_type(sock->conn))) == NULL) { + err = ERR_MEM; + } else { + #if LWIP_CHECKSUM_ON_COPY +- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { ++#if PF_PACKET_SOCKET ++ if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_PACKET_RAW) && ++ (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW)) ++#else ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) ++#endif ++ { + u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); + netbuf_set_chksum(&buf, chksum); + } else +@@ -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: +- conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), +- (u8_t)protocol, DEFAULT_SOCKET_EVENTCB); +- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", ++#if PF_PACKET_SOCKET ++ if (domain == PF_PACKET) { ++ conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_PACKET_RAW), ++ (u16_t)protocol, event_callback); ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", "PF_PACKET", protocol)); ++ } else ++#endif ++ { ++ conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), ++ (u8_t)protocol, DEFAULT_SOCKET_EVENTCB); ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); ++ } + break; + case SOCK_DGRAM: + conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, +@@ -1983,10 +2269,11 @@ + timeout ? (s32_t)timeout->tv_sec : (s32_t) - 1, + timeout ? (s32_t)timeout->tv_usec : (s32_t) - 1)); + +- if ((maxfdp1 < 0) || (maxfdp1 > LWIP_SELECT_MAXNFDS)) { ++/*if ((maxfdp1 < 0) || (maxfdp1 > LWIP_SELECT_MAXNFDS)) { + set_errno(EINVAL); + return -1; + } ++ */ + + lwip_select_inc_sockets_used(maxfdp1, readset, writeset, exceptset, &used_sockets); + +@@ -2704,12 +2991,60 @@ + ip_addr_t naddr; + u16_t port; + err_t err; ++ socklen_t sa_len; ++ ++#if PF_PACKET_SOCKET ++ struct sockaddr_ll addr_sin; ++ struct pf_packet_sockaddr_ll sll; ++ socklen_t outlen; ++#endif ++ ++ LWIP_ERROR("lwip_getaddrname: invalid arguments", ((name != NULL) && (namelen != NULL)), ++ set_errno(EINVAL); return -1); + + sock = get_socket(s); + if (!sock) { + return -1; + } + ++#if PF_PACKET_SOCKET ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_PACKET_RAW) { ++ err = netconn_get_sockaddr_pf_packet(sock->conn, &sll, local); ++ if (err != ERR_OK) { ++ sock_set_errno(sock, err_to_errno(err)); ++ done_socket(sock); ++ return -1; ++ } ++ ++ (void)memset_s(&addr_sin, sizeof(struct sockaddr_ll), 0, sizeof(struct sockaddr_ll)); ++ addr_sin.sll_family = PF_PACKET; ++ addr_sin.sll_protocol = sll.sll_protocol; ++ addr_sin.sll_pkttype = 0; ++ addr_sin.sll_ifindex = sll.if_idx; ++ addr_sin.sll_hatype = sll.sll_hatype; ++ addr_sin.sll_halen = sll.sll_halen; ++ ++ if ((sll.sll_halen > 0) && (memcpy_s(addr_sin.sll_addr, addr_sin.sll_halen, sll.sll_addr, sll.sll_halen) != EOK)) { ++ sock_set_errno(sock, err_to_errno(ERR_MEM)); ++ done_socket(sock); ++ return -1; ++ } ++ ++ outlen = sizeof(struct sockaddr_ll); ++ if (outlen > *namelen) { ++ outlen = *namelen; ++ } ++ if (memcpy_s(name, *namelen, &addr_sin, outlen) != EOK) { ++ sock_set_errno(sock, err_to_errno(ERR_MEM)); ++ done_socket(sock); ++ return -1; ++ } ++ *namelen = outlen; ++ done_socket(sock); ++ return 0; ++ } ++#endif /* PF_PACKET_SOCKET */ ++ + /* get the IP address and port */ + err = netconn_getaddr(sock->conn, &naddr, &port, local); + if (err != ERR_OK) { +@@ -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)); ++ if (IP_IS_V4_VAL(naddr)) { ++ sa_len = sizeof(struct sockaddr_in); ++ } else { ++ sa_len = sizeof(struct sockaddr_in6); ++ } + +- if (*namelen > saddr.sa.sa_len) { +- *namelen = saddr.sa.sa_len; ++ if (*namelen > sa_len) { ++ *namelen = sa_len; + } + MEMCPY(name, &saddr, *namelen); + +@@ -2775,6 +3115,14 @@ + return -1; + } + ++#if PF_PACKET_SOCKET ++ VALIDATE_LEVEL_PF_PACKET(sock, level) { ++ sock_set_errno(sock, EINVAL); ++ done_socket(sock); ++ return -1; ++ } ++#endif /* PF_PACKET_SOCKET */ ++ + #if LWIP_TCPIP_CORE_LOCKING + /* core-locking can just call the -impl function */ + LOCK_TCPIP_CORE(); +@@ -2826,8 +3174,9 @@ + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); + #endif /* LWIP_TCPIP_CORE_LOCKING */ +- +- sock_set_errno(sock, err); ++ if (err != ERR_OK) { ++ sock_set_errno(sock, err); ++ } + done_socket(sock); + return err ? -1 : 0; + } +@@ -2897,6 +3246,11 @@ + + /* Level: SOL_SOCKET */ + case SOL_SOCKET: ++#if PF_PACKET_SOCKET ++ case SOL_PACKET: ++ VALIDATE_GET_PF_PKT_OPTNAME_RET(s, sock, level, optname); ++#endif /* PF_PACKET_SOCKET */ ++ VALIDATE_GET_RAW_OPTNAME_RET(sock, optname); + switch (optname) { + + #if LWIP_TCP +@@ -2920,6 +3274,10 @@ + #if SO_REUSE + case SO_REUSEADDR: + #endif /* SO_REUSE */ ++ if (sock->conn == NULL) { ++ done_socket(sock); ++ return EINVAL; ++ } + if ((optname == SO_BROADCAST) && + (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP)) { + done_socket(sock); +@@ -2937,6 +3295,9 @@ + case SO_TYPE: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) { ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++#endif + case NETCONN_RAW: + *(int *)optval = SOCK_RAW; + break; +@@ -2948,9 +3309,16 @@ + break; + default: /* unrecognized socket type */ + *(int *)optval = netconn_type(sock->conn); ++#if PF_PACKET_SOCKET ++ LWIP_DEBUGF(SOCKETS_DEBUG, ++ ("lwip_getsockopt(%d, %s, SO_TYPE): unrecognized socket type %d\n", ++ s, (NETCONN_PACKET_RAW != NETCONNTYPE_GROUP(sock->conn->type)) ? "SOL_SOCKET" : "SOL_PACKET", ++ *(int *)optval)); ++#else + LWIP_DEBUGF(SOCKETS_DEBUG, + ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", + s, *(int *)optval)); ++#endif + } /* switch (netconn_type(sock->conn)) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", + s, *(int *)optval)); +@@ -3739,92 +4107,450 @@ + return err; + } + +-int +-lwip_ioctl(int s, long cmd, void *argp) ++#if PF_PACKET_SOCKET || LOSCFG_COMPONENTS_UPNP ++#if LWIP_IOCTL_IF ++static u8_t lwip_ioctl_internal_SIOCGIFCONF(struct ifreq *ifr) ++{ ++ struct ifconf *ifc = NULL; ++ struct netif *netif = NULL; ++ struct ifreq ifreq; ++ struct sockaddr_in *sock_in = NULL; ++ int pos; ++ int len; ++ int ret; ++ ++ /* Format the caller's buffer. */ ++ ifc = (struct ifconf*)ifr; ++ len = ifc->ifc_len; ++ ++ /* Loop over the interfaces, and write an info block for each. */ ++ pos = 0; ++ for (netif = netif_list; netif != NULL; netif = netif->next) { ++ if (ifc->ifc_buf == NULL) { ++ pos = (pos + (int)sizeof(struct ifreq)); ++ continue; ++ } ++ ++ if (len < (int)sizeof(ifreq)) { ++ break; ++ } ++ ++ if (memset_s(&ifreq, sizeof(struct ifreq), 0, sizeof(struct ifreq)) != EOK) { ++ return ENOBUFS; ++ } ++ if (netif->link_layer_type == LOOPBACK_IF) { ++ ret = snprintf_s(ifreq.ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s", netif->name); ++ if ((ret <= 0) || (ret >= IFNAMSIZ)) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed.")); ++ return ENOBUFS; ++ } ++ } else { ++ ret = snprintf_s(ifreq.ifr_name, NETIF_NAMESIZE, NETIF_NAMESIZE - 1, "%s%"U8_F, netif->name, netif->num); ++ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed.")); ++ return ENOBUFS; ++ } ++ } ++ ++ sock_in = (struct sockaddr_in *)&ifreq.ifr_addr; ++ sock_in->sin_family = AF_INET; ++ sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr; ++ if (memcpy_s(ifc->ifc_buf + pos, sizeof(struct ifreq), &ifreq, sizeof(struct ifreq)) != EOK) { ++ return ENOBUFS; ++ } ++ pos += (int)sizeof(struct ifreq); ++ len -= (int)sizeof(struct ifreq); ++ } ++ ++ ifc->ifc_len = pos; ++ ++ return 0; ++} ++ ++static u8_t lwip_ioctl_internal_SIOCGIFADDR(struct ifreq *ifr) ++{ ++ struct netif *netif = NULL; ++ struct sockaddr_in *sock_in = NULL; ++ ++ /* get netif ipaddr */ ++ netif = netif_find(ifr->ifr_name); ++ if (netif == NULL) { ++ return ENODEV; ++ } else { ++ sock_in = (struct sockaddr_in *)&ifr->ifr_addr; ++ sock_in->sin_family = AF_INET; ++ sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr; ++ return 0; ++ } ++} ++ ++static u8_t lwip_ioctl_internal_SIOCSIFFLAGS(const struct ifreq *ifr) ++{ ++ struct netif *netif = NULL; ++ ++ /* set netif hw addr */ ++ netif = netif_find(ifr->ifr_name); ++ if (netif == NULL) { ++ return ENODEV; ++ } ++#if LWIP_HAVE_LOOPIF ++ else if (netif->link_layer_type == LOOPBACK_IF) { ++ return EPERM; ++ } ++#endif /* LWIP_HAVE_LOOPIF */ ++ else { ++ if ((ifr->ifr_flags & IFF_UP) && !(netif->flags & NETIF_FLAG_UP)) { ++ (void)netif_set_up(netif); ++ } else if (!(ifr->ifr_flags & IFF_UP) && (netif->flags & NETIF_FLAG_UP)) { ++ (void)netif_set_down(netif); ++ } ++ if ((ifr->ifr_flags & IFF_RUNNING) && !(netif->flags & NETIF_FLAG_LINK_UP)) { ++ (void)netif_set_link_up(netif); ++ } else if (!(ifr->ifr_flags & IFF_RUNNING) && (netif->flags & NETIF_FLAG_LINK_UP)) { ++ (void)netif_set_link_down(netif); ++ } ++ ++ if (ifr->ifr_flags & IFF_BROADCAST) { ++ netif->flags |= NETIF_FLAG_BROADCAST; ++ } else { ++ netif->flags = netif->flags & (~NETIF_FLAG_BROADCAST); ++ } ++ if (ifr->ifr_flags & IFF_NOARP) { ++ netif->flags = (netif->flags & (~NETIF_FLAG_ETHARP)); ++ } else { ++ netif->flags |= NETIF_FLAG_ETHARP; ++ } ++ ++ if (ifr->ifr_flags & IFF_MULTICAST) { ++#if LWIP_IGMP ++ netif->flags |= NETIF_FLAG_IGMP; ++#endif /* LWIP_IGMP */ ++#if LWIP_IPV6 && LWIP_IPV6_MLD ++ netif->flags |= NETIF_FLAG_MLD6; ++#endif /* LWIP_IPV6_MLD */ ++ } ++ else { ++#if LWIP_IGMP ++ netif->flags = (netif->flags & ~NETIF_FLAG_IGMP); ++#endif /* LWIP_IGMP */ ++#if LWIP_IPV6 && LWIP_IPV6_MLD ++ netif->flags = (netif->flags & ~NETIF_FLAG_MLD6); ++#endif /* LWIP_IPV6_MLD */ ++ } ++ ++#if 0 ++ if (ifr->ifr_flags & IFF_DYNAMIC) { ++ (void)dhcp_start(netif); ++ } else { ++ dhcp_stop(netif); ++ dhcp_cleanup(netif); ++ } ++#endif ++ ++ return 0; ++ } ++} ++ ++static u8_t lwip_ioctl_internal_SIOCGIFFLAGS(struct ifreq *ifr) ++{ ++ struct netif *netif = NULL; ++ ++ /* set netif hw addr */ ++ netif = netif_find(ifr->ifr_name); ++ if (netif == NULL) { ++ return ENODEV; ++ } else { ++ if (netif->flags & NETIF_FLAG_UP) { ++ ifr->ifr_flags |= IFF_UP; ++ } else { ++ ifr->ifr_flags &= ~IFF_UP; ++ } ++ if (netif->flags & NETIF_FLAG_LINK_UP) { ++ ifr->ifr_flags |= IFF_RUNNING; ++ } else { ++ ifr->ifr_flags &= ~IFF_RUNNING; ++ } ++ if (netif->flags & NETIF_FLAG_BROADCAST) { ++ ifr->ifr_flags |= IFF_BROADCAST; ++ } else { ++ ifr->ifr_flags &= ~IFF_BROADCAST; ++ } ++ if (netif->flags & NETIF_FLAG_ETHARP) { ++ ifr->ifr_flags &= ~IFF_NOARP; ++ } else { ++ ifr->ifr_flags |= IFF_NOARP; ++ } ++ ++#if LWIP_IGMP || LWIP_IPV6_MLD ++ if ( ++#if LWIP_IGMP ++ (netif->flags & NETIF_FLAG_IGMP) ++#endif /* LWIP_IGMP */ ++#if LWIP_IGMP && LWIP_IPV6_MLD ++ || ++#endif /* LWIP_IGMP && LWIP_IPV6_MLD */ ++#if LWIP_IPV6_MLD ++ (netif->flags & NETIF_FLAG_MLD6) ++#endif /* LWIP_IPV6_MLD */ ++ ) { ++ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_MULTICAST); ++ } else { ++ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_MULTICAST)); ++ } ++#endif /* LWIP_IGMP || LWIP_IPV6_MLD */ ++ ++#if LWIP_DHCP ++ if (netif->flags & NETIF_FLAG_DHCP) { ++ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_DYNAMIC); ++ } else { ++ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_DYNAMIC)); ++ } ++#endif ++ ++#if LWIP_HAVE_LOOPIF ++ if (netif->link_layer_type == LOOPBACK_IF) { ++ ifr->ifr_flags |= IFF_LOOPBACK; ++ } ++#endif ++ ++ return 0; ++ } ++} ++ ++static u8_t lwip_ioctl_internal_SIOCGIFNAME(struct ifreq *ifr) ++{ ++ struct netif *netif = NULL; ++ int ret; ++ ++ for (netif = netif_list; netif != NULL; netif = netif->next) { ++ if (ifr->ifr_ifindex == netif->ifindex) { ++ break; ++ } ++ } ++ ++ if (netif == NULL) { ++ return ENODEV; ++ } ++ if (netif->link_layer_type == LOOPBACK_IF) { ++ ret = snprintf_s(ifr->ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s", netif->name); ++ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { ++ return ENOBUFS; ++ } ++ } else { ++ ret = snprintf_s(ifr->ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s%"U8_F, netif->name, netif->num); ++ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { ++ return ENOBUFS; ++ } ++ } ++ return 0; ++} ++ ++static u8_t lwip_ioctl_internal_SIOCGIFINDEX(struct ifreq *ifr) ++{ ++ struct netif *netif = NULL; ++ netif = netif_find(ifr->ifr_name); ++ if (netif == NULL) { ++ return ENODEV; ++ } ++ ifr->ifr_ifindex = netif->ifindex; ++ return 0; ++} ++#endif /* LWIP_IOCTL_IF */ ++#endif /* PF_PACKET_SOCKET */ ++ ++#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE ++static u8_t lwip_ioctl_internal_FIONREAD(struct lwip_sock *sock, void *argp) + { +- struct lwip_sock *sock = get_socket(s); +- u8_t val; + #if LWIP_SO_RCVBUF + int recv_avail; +-#endif /* LWIP_SO_RCVBUF */ ++#endif ++#if LWIP_FIONREAD_LINUXMODE ++ SYS_ARCH_DECL_PROTECT(lev); ++#endif + +- if (!sock) { +- return -1; ++ if (!argp) { ++ return EINVAL; + } + +- switch (cmd) { +-#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE +- case FIONREAD: +- if (!argp) { +- sock_set_errno(sock, EINVAL); +- done_socket(sock); +- return -1; +- } ++ lwip_sock_lock(sock); + #if LWIP_FIONREAD_LINUXMODE +- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { +- struct netbuf *nb; +- if (sock->lastdata.netbuf) { +- nb = sock->lastdata.netbuf; +- *((int *)argp) = nb->p->tot_len; ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { ++ struct netbuf *nb; ++ if (sock->lastdata.netbuf) { ++ nb = sock->lastdata.netbuf; ++ *((int *)argp) = nb->p->tot_len; ++ } else { ++ struct netbuf *rxbuf; ++ err_t err; ++ ++ SYS_ARCH_PROTECT(lev); ++ if (sock->rcvevent <= 0) { ++ *((int*)argp) = 0; ++ SYS_ARCH_UNPROTECT(lev); ++ } else { ++ SYS_ARCH_UNPROTECT(lev); ++ err = netconn_recv_udp_raw_netbuf_flags(sock->conn, &rxbuf, NETCONN_DONTBLOCK); ++ if (err != ERR_OK) { ++ *((int *)argp) = 0; + } else { +- struct netbuf *rxbuf; +- err_t err = netconn_recv_udp_raw_netbuf_flags(sock->conn, &rxbuf, NETCONN_DONTBLOCK); +- if (err != ERR_OK) { +- *((int *)argp) = 0; +- } else { +- sock->lastdata.netbuf = rxbuf; +- *((int *)argp) = rxbuf->p->tot_len; +- } ++ sock->lastdata.netbuf = rxbuf; ++ *((int *)argp) = rxbuf->p->tot_len; + } +- done_socket(sock); +- return 0; + } ++ } ++ ++ lwip_sock_unlock(sock); ++ return 0; ++ } + #endif /* LWIP_FIONREAD_LINUXMODE */ + + #if LWIP_SO_RCVBUF +- /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ +- SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); +- if (recv_avail < 0) { +- recv_avail = 0; +- } ++ /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ ++ SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); ++ if (recv_avail < 0) { ++ recv_avail = 0; ++ } + +- /* Check if there is data left from the last recv operation. /maq 041215 */ +- if (sock->lastdata.netbuf) { +- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { +- recv_avail += sock->lastdata.pbuf->tot_len; +- } else { +- recv_avail += sock->lastdata.netbuf->p->tot_len; +- } +- } +- *((int *)argp) = recv_avail; ++ /* Check if there is data left from the last recv operation. /maq 041215 */ ++ if (sock->lastdata.netbuf) { ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { ++ recv_avail += sock->lastdata.pbuf->tot_len; ++ } else { ++ recv_avail += sock->lastdata.netbuf->p->tot_len; ++ } ++ } ++ *((int *)argp) = recv_avail; + +- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t *)argp))); +- sock_set_errno(sock, 0); +- done_socket(sock); +- return 0; ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(FIONREAD, %p) = %"U16_F"\n", argp, *((u16_t *)argp))); ++ lwip_sock_unlock(sock); ++ return 0; + #else /* LWIP_SO_RCVBUF */ +- break; ++ lwip_sock_unlock(sock); ++ return ENOSYS; + #endif /* LWIP_SO_RCVBUF */ ++} + #endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ + +- case (long)FIONBIO: +- val = 0; +- if (argp && *(int *)argp) { +- val = 1; ++static u8_t lwip_ioctl_internal_FIONBIO(struct lwip_sock *sock, const void *argp) ++{ ++ u8_t val = 0; ++ SYS_ARCH_DECL_PROTECT(lev); ++ if (argp == NULL) { ++ return EINVAL; ++ } ++ if (*(int *)argp) { ++ val = 1; ++ } ++ SYS_ARCH_PROTECT(lev); ++ netconn_set_nonblocking(sock->conn, val); ++ SYS_ARCH_UNPROTECT(lev); ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(FIONBIO, %d)\n", val)); ++ return 0; ++} ++ ++static u8_t lwip_ioctl_impl(struct lwip_sock *sock, long cmd, void *argp) ++{ ++ u8_t err = 0; ++#if LWIP_NETIF_ETHTOOL ++ s32_t ret; ++#endif ++#if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_IF || LWIP_NETIF_ETHTOOL ++ struct ifreq *ifr = (struct ifreq *)argp; ++#endif ++#if LWIP_IOCTL_ROUTE ++ struct rtentry *rmten = (struct rtentry *)argp; ++#endif ++#if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_ROUTE || LWIP_IOCTL_IF ++ u8_t is_ipv6 = NETCONNTYPE_ISIPV6(sock->conn->type); ++#endif ++ ++ LWIP_ASSERT("no socket given", sock != NULL); ++ ++ switch (cmd) { ++#if PF_PACKET_SOCKET || LOSCFG_COMPONENTS_UPNP ++#if LWIP_IOCTL_IF ++ case SIOCGIFCONF: ++ /* Do not allow if socket is AF_INET6 */ ++ if (is_ipv6) { ++ err = EINVAL; ++ } else { ++ err = lwip_ioctl_internal_SIOCGIFCONF(ifr); //add: SIOCGIFCONF + } +- netconn_set_nonblocking(sock->conn, val); +- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); +- sock_set_errno(sock, 0); +- done_socket(sock); +- return 0; ++ break; ++ case SIOCGIFADDR: ++ if (is_ipv6) { ++ err = EINVAL; ++ } else { ++ err = lwip_ioctl_internal_SIOCGIFADDR(ifr); //add: SIOCGIFADDR ++ } ++ break; ++ case SIOCSIFFLAGS: ++ err = lwip_ioctl_internal_SIOCSIFFLAGS(ifr); //add: SIOCSIFFLAGS ++ break; ++ case SIOCGIFFLAGS: ++ err = lwip_ioctl_internal_SIOCGIFFLAGS(ifr); //add: SIOCSIFFLAGS ++ break; ++ case SIOCGIFNAME: ++ err = lwip_ioctl_internal_SIOCGIFNAME(ifr); //add: SIOCGIFNAME ++ break; ++ /* Need to support the get index through ioctl ++ * As of now the options is restricted to PF_PACKET scenario , so removed the compiler flag Begin ++ */ ++ case SIOCGIFINDEX: ++ err = lwip_ioctl_internal_SIOCGIFINDEX(ifr); //add: SIOCGIFINDEX ++ break; ++#endif /* LWIP_IOCTL_IF */ ++#else ++ (void)ifr; ++ (void)is_ipv6; ++#endif /* PF_PACKET_SOCKET */ ++#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE ++ case FIONREAD: ++ err = lwip_ioctl_internal_FIONREAD(sock, argp); ++ break; ++#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ + ++ case FIONBIO: ++ err = lwip_ioctl_internal_FIONBIO(sock, argp); ++ break; ++ /* -1 should return EINVAL */ ++ case -1: ++ err = EINVAL; ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl_impl(INVALID: 0x%lx)\n", cmd)); ++ break; + default: ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(UNIMPL: 0x%lx, %p)\n", cmd, argp)); ++ err = ENOSYS; /* not yet implemented */ + break; + } /* switch (cmd) */ +- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); +- sock_set_errno(sock, ENOSYS); /* not yet implemented */ ++ ++ return err; ++} ++ ++int ++lwip_ioctl(int s, long cmd, void *argp) ++{ ++ u8_t err; ++ struct lwip_sock *sock = get_socket(s); ++ if (!sock) { ++ /* get_socket has updated errno */ ++ return -1; ++ } ++ if (argp == NULL) { ++ sock_set_errno(sock, EFAULT); ++ done_socket(sock); ++ return -1; ++ } ++ ++ LOCK_TCPIP_CORE(); ++ err = lwip_ioctl_impl(sock, cmd, argp); ++ UNLOCK_TCPIP_CORE(); ++ if (err != ERR_OK) { ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, cmd: 0x%lx, %p)\n", s, cmd, argp)); ++ sock_set_errno(sock, err); ++ } + done_socket(sock); +- return -1; ++ return (err == 0) ? 0 : -1; + } + + /** A minimal implementation of fcntl. +@@ -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; +- + break; + 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 2022-02-16 16:06:59.174115000 +0800 ++++ b/lwip-2.1.2/src/apps/tftp/tftp_server.c 2022-01-26 06:41:32.000000000 +0800 +@@ -201,7 +201,7 @@ + } + + static void +-recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) ++tftp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) + { + u16_t *sbuf = (u16_t *) p->payload; + int opcode; +@@ -416,7 +416,7 @@ + tftp_state.last_data = NULL; + tftp_state.upcb = pcb; + +- udp_recv(pcb, recv, NULL); ++ udp_recv(pcb, tftp_recv, NULL); + + 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-29 08:50:28.000000000 +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-26 06:55:38.000000000 +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 2022-02-16 16:06:59.174115000 +0800 ++++ b/lwip-2.1.2/src/core/ip.c 2022-01-29 09:08:50.000000000 +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) + { +- if (cp != NULL) { ++ if (cp != NULL && addr != NULL) { + const char *c; + for (c = cp; *c != 0; c++) { + if (*c == ':') { + /* contains a colon: IPv6 address */ +- if (addr) { +- IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); +- } ++ IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); + return ip6addr_aton(cp, ip_2_ip6(addr)); + } else if (*c == '.') { + /* contains a dot: IPv4 address */ +@@ -137,9 +147,7 @@ + } + } + /* call ip4addr_aton as fallback or if IPv4 was found */ +- if (addr) { +- IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); +- } ++ IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); + return ip4addr_aton(cp, ip_2_ip4(addr)); + } + return 0; +@@ -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 */ + ++struct netif* ++ip_route_pcb(const ip_addr_t *dest, const struct ip_pcb* pcb) ++{ ++ struct netif *netif = NULL; ++#if LWIP_SO_DONTROUTE ++ rt_scope_t scope = RT_SCOPE_UNIVERSAL; ++ ++ LWIP_ASSERT("Expecting ipaddr to be not NULL ", dest != NULL); ++ if (pcb != NULL) { ++ scope = ip_get_option(pcb, SOF_DONTROUTE) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSAL; ++ } ++#endif ++ ++ if ((pcb != NULL) && (pcb->netif_idx != NETIF_NO_INDEX)) { ++ return netif_find_by_ifindex(pcb->netif_idx); ++ } ++ ++ if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { ++ /* Don't call ip_route() with IP_ANY_TYPE */ ++ netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(dest)), dest); ++ } else { ++ netif = ip_route(&pcb->local_ip, dest); ++ } ++ ++ if (netif == NULL) { ++ return NULL; ++ } ++ ++#if LWIP_SO_DONTROUTE ++ if (netif->scope < scope) { ++ return NULL; ++ } ++#endif ++ return netif; ++} ++ ++#if LWIP_INET_ADDR_FUNC ++in_addr_t inet_addr(const char *cp) ++{ ++ LWIP_ERROR("inet_aton:cp is NULL", (cp != NULL), return (INADDR_NONE)); ++ return ipaddr_addr(cp); ++} ++#endif ++ ++#if LWIP_INET_ATON_FUNC ++int inet_aton(const char *cp, struct in_addr *inp) ++{ ++ LWIP_ERROR("inet_aton:cp is NULL", (cp != NULL), return 0); ++ return ip4addr_aton(cp, (ip4_addr_t *)inp); ++} ++#endif ++ ++#if LWIP_INET_NTOA_FUNC ++char* inet_ntoa(struct in_addr in) ++{ ++ return ip4addr_ntoa((const ip4_addr_t *)&in); ++} ++#endif ++ + #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 2022-02-16 16:06:59.174115000 +0800 ++++ b/lwip-2.1.2/src/core/ipv6/icmp6.c 2022-01-26 06:41:32.000000000 +0800 +@@ -82,14 +82,14 @@ + void + icmp6_input(struct pbuf *p, struct netif *inp) + { +- struct icmp6_hdr *icmp6hdr; ++ struct icmpv6_hdr *icmp6hdr; + struct pbuf *r; + const ip6_addr_t *reply_src; + + ICMP6_STATS_INC(icmp6.recv); + + /* Check that ICMPv6 header fits in payload */ +- if (p->len < sizeof(struct icmp6_hdr)) { ++ if (p->len < sizeof(struct icmpv6_hdr)) { + /* drop short packets */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.lenerr); +@@ -97,7 +97,7 @@ + return; + } + +- icmp6hdr = (struct icmp6_hdr *)p->payload; ++ icmp6hdr = (struct icmpv6_hdr *)p->payload; + + #if CHECKSUM_CHECK_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP6) { +@@ -386,10 +386,10 @@ + const ip6_addr_t *reply_src, const ip6_addr_t *reply_dest, struct netif *netif) + { + struct pbuf *q; +- struct icmp6_hdr *icmp6hdr; ++ struct icmpv6_hdr *icmp6hdr; + + /* ICMPv6 header + IPv6 header + data */ +- q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, ++ q = pbuf_alloc(PBUF_IP, sizeof(struct icmpv6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, + PBUF_RAM); + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n")); +@@ -397,15 +397,15 @@ + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp 6message", +- (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); ++ (q->len >= (sizeof(struct icmpv6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); + +- icmp6hdr = (struct icmp6_hdr *)q->payload; ++ icmp6hdr = (struct icmpv6_hdr *)q->payload; + icmp6hdr->type = type; + icmp6hdr->code = code; + icmp6hdr->data = lwip_htonl(data); + + /* copy fields from original packet */ +- SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload, ++ SMEMCPY((u8_t *)q->payload + sizeof(struct icmpv6_hdr), (u8_t *)p->payload, + IP6_HLEN + LWIP_ICMP6_DATASIZE); + + /* 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 2022-02-16 16:06:59.174115000 +0800 ++++ b/lwip-2.1.2/src/core/ipv6/nd6.c 2022-01-26 06:41:32.000000000 +0800 +@@ -894,13 +894,13 @@ + } + case ICMP6_TYPE_PTB: /* Packet too big */ + { +- struct icmp6_hdr *icmp6hdr; /* Packet too big message */ ++ struct icmpv6_hdr *icmp6hdr; /* Packet too big message */ + struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */ + u32_t pmtu; + ip6_addr_t destination_address; + + /* Check that ICMPv6 header + IPv6 header fit in payload */ +- if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { ++ if (p->len < (sizeof(struct icmpv6_hdr) + IP6_HLEN)) { + /* drop short packets */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); +@@ -908,8 +908,8 @@ + return; + } + +- icmp6hdr = (struct icmp6_hdr *)p->payload; +- ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); ++ icmp6hdr = (struct icmpv6_hdr *)p->payload; ++ ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmpv6_hdr)); + + /* 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 2022-02-16 16:06:59.178115000 +0800 ++++ b/lwip-2.1.2/src/core/netif.c 2022-01-26 07:38:10.000000000 +0800 +@@ -89,6 +89,8 @@ + #if LWIP_IPV6 + #include "lwip/nd6.h" + #endif ++#include "lwip/tcpip.h" ++ + + #if LWIP_NETIF_STATUS_CALLBACK + #define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) +@@ -229,6 +231,8 @@ + return ip_input(p, inp); + } + ++static u8_t netif_alloc_ifindex(void); ++ + /** + * @ingroup netif + * Add a network interface to the list of lwIP netifs. +@@ -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 */ + ++ /* ++ * Need to support the get index for all families ++ * removed PF_PACKET_SOCKET flag , as this flags restricts the usage to only PF_FAMILY ++ */ ++ netif->ifindex = netif_alloc_ifindex(); ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif: netif->ifindex=%d", netif->ifindex)); ++ if ((netif->ifindex < LWIP_NETIF_IFINDEX_START) || (netif->ifindex > LWIP_NETIF_IFINDEX_MAX)) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif: interface index alloc fail")); ++ return NULL; ++ } ++ + #if !LWIP_SINGLE_NETIF + /* Assign a unique netif number in the range [0..254], so that (num+1) can + serve as an interface index that fits in a u8_t. + We assume that the new netif has not yet been added to the list here. + This algorithm is O(n^2), but that should be OK for lwIP. + */ +- { +- struct netif *netif2; +- int num_netifs; +- do { +- if (netif->num == 255) { +- netif->num = 0; +- } +- num_netifs = 0; +- for (netif2 = netif_list; netif2 != NULL; netif2 = netif2->next) { +- LWIP_ASSERT("netif already added", netif2 != netif); +- num_netifs++; +- LWIP_ASSERT("too many netifs, max. supported number is 255", num_netifs <= 255); +- if (netif2->num == netif->num) { +- netif->num++; +- break; +- } +- } +- } while (netif2 != NULL); +- } +- if (netif->num == 254) { +- netif_num = 0; +- } else { +- netif_num = (u8_t)(netif->num + 1); +- } + + /* add this netif to the list */ + netif->next = netif_list; +@@ -421,8 +428,8 @@ + } + #endif /* LWIP_IGMP */ + +- LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", +- netif->name[0], netif->name[1])); ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %s IP", ++ netif->name)); + #if LWIP_IPV4 + LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); + ip4_addr_debug_print(NETIF_DEBUG, ipaddr); +@@ -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 + */ +-void ++err_t + netif_set_default(struct netif *netif) + { + LWIP_ASSERT_CORE_LOCKED(); +@@ -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] : '\'')); ++ return ERR_OK; + } + + /** +@@ -1206,6 +1279,11 @@ + struct netif *stats_if = netif; + #endif /* LWIP_HAVE_LOOPIF */ + #endif /* MIB2_STATS */ ++#if PF_PACKET_SOCKET ++ struct raw_pcb *pcb; ++ int match = 0; ++#endif /* PF_PACKET_SOCKET */ ++ + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_ASSERT("netif_poll: invalid netif", netif != NULL); +@@ -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); ++ ++#if PF_PACKET_SOCKET ++ for (pcb = get_packet_raw_pcbs(); pcb != NULL; pcb = pcb->next) { ++ if (((pcb->proto.eth_proto == htons(ETHTYPE_ALL)) || (pcb->proto.eth_proto == htons(ETHTYPE_IP))) && ++ ((!pcb->netifindex) || (pcb->netifindex == netif->ifindex))) { ++ match = 1; ++ break; ++ } ++ } ++ ++ /* always succeed because the alloc layer of loopback pbuf was PBUF_LINK */ ++ if (match && pbuf_header(in, PBUF_LINK_HLEN) == 0) { ++ struct eth_hdr *ethhdr; ++ /* add ethernet header */ ++ ethhdr = (struct eth_hdr *)(in->payload); ++ /* smac and dmac set to all zeros for loopback IP packet */ ++ (void)memset_s(ethhdr, sizeof(struct eth_hdr), 0, sizeof(struct eth_hdr)); ++ ethhdr->type = htons(ETHTYPE_IP); /* eth protocol, should be ETH_P_IP(0x800) */ ++ in->flags = (u16_t)(in->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_OUTGOING)); ++ in->flags |= PBUF_FLAG_HOST; ++ raw_packet_input(in, netif, NULL); ++ (void)pbuf_header(in, -PBUF_LINK_HLEN); ++ } ++#endif /* PF_PACKET_SOCKET */ ++ + /* loopback packets are always IP packets! */ + if (ip_input(in, netif) != ERR_OK) { + pbuf_free(in); +@@ -1700,29 +1803,68 @@ + struct netif * + netif_find(const char *name) + { +- struct netif *netif; +- u8_t num; +- +- LWIP_ASSERT_CORE_LOCKED(); +- +- if (name == NULL) { +- return NULL; +- } ++ struct netif *netif = NULL; ++ char candidate_name[NETIF_NAMESIZE]; ++ int ret; + +- num = (u8_t)atoi(&name[2]); ++ LWIP_ERROR("netif_find : invalid value.", (name != NULL), return NULL); + + NETIF_FOREACH(netif) { +- if (num == netif->num && +- name[0] == netif->name[0] && +- name[1] == netif->name[1]) { +- LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); ++ if (strncmp(name, netif->name, NETIF_NAMESIZE) == 0) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %s\n", name)); + return netif; + } ++ ++ if (netif->link_layer_type != LOOPBACK_IF) { ++ ret = snprintf_s(candidate_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s%"U8_F, netif->name, netif->num); ++ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: name '%s'is too long\n", netif->name)); ++ continue; ++ } ++ if (strncmp(name, candidate_name, NETIF_NAMESIZE) == 0) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %s\n", name)); ++ return netif; ++ } ++ } + } +- LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %s\n", name)); + return NULL; + } + ++/* ++ * Change mtu setting for a network interface ++ * ++ * @param netif the network interface to change ++ * @param netif_mtu the new MTU for the interface ++ */ ++ ++err_t ++netif_set_mtu_api(struct netif *netif, u16_t netif_mtu) ++{ ++ /* As per RFC 791, "Every internet module must be able to forward a datagram of 68 ++ * octets without further fragmentation. This is because an internet header ++ * may be up to 60 octets, and the minimum fragment is 8 octets." */ ++ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif != NULL), return ERR_VAL); ++ ++#if LWIP_IPV6 ++ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif_mtu >= NETIF_MTU_MIN) && (netif_mtu <= IP_FRAG_MAX_MTU), ++ return ERR_ARG); ++#else ++ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif_mtu >= IP_FRAG_MIN_MTU) && (netif_mtu <= IP_FRAG_MAX_MTU), ++ return ERR_ARG); ++#endif ++ ++ netif->mtu = netif_mtu; ++#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES ++ netif->mtu6 = netif_mtu; ++#endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ ++ ++ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif: MTU of interface %s%"U16_F" is changed to %d\n", ++ netif->name, netif->num, netif->mtu)); ++ ++ return ERR_OK; ++} ++ + #if LWIP_NETIF_EXT_STATUS_CALLBACK + /** + * @ingroup netif +@@ -1793,3 +1935,213 @@ + } + } + #endif /* LWIP_NETIF_EXT_STATUS_CALLBACK */ ++ ++struct netif * ++netif_find_by_ipaddr(const ip_addr_t *ipaddr) ++{ ++ LWIP_ERROR("netif_find_by_ipaddr : invalid arguments", (ipaddr != NULL), return NULL); ++#if LWIP_IPV4 ++ if (IP_IS_V4(ipaddr)) { ++ return netif_find_by_ip4addr(ipaddr); ++ } ++#endif ++ ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ipaddr: didn't find\n")); ++ return NULL; ++} ++ ++void ++netif_get_hwaddr(const struct netif *netif, unsigned char *hw_addr, int hw_len) ++{ ++ int i; ++ LWIP_ERROR("netif_get_hwaddr : invalid arguments", (netif != NULL), return); ++ ++ LWIP_ERROR("netif_get_hwaddr : invalid arguments", (hw_addr != NULL), return); ++ ++ LWIP_ERROR("netif_get_hwaddr: invalid arguments", ++ ((unsigned int)hw_len == NETIF_MAX_HWADDR_LEN), return); ++ ++ for (i = 0; i < hw_len; i++) { ++ hw_addr[i] = netif->hwaddr[i]; ++ } ++} ++ ++/* ++ * Change the hardware address for a network interface ++ * ++ * NOTE:Application should call set_link_down before calling ++ * the netif_set_hwaddr and then set_link_up, in order ++ * to ensure that all IPs are announced after changing ++ * hw address ++ * ++ * @param netif the network interface to change ++ * @param hw_addr the new hardware address ++ * @param hw_len the length of new hardware address, ++ * ++ */ ++err_t ++netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw_len) ++{ ++ LWIP_ERROR("netif_set_hwaddr : invalid arguments", (netif != NULL), return ERR_VAL); ++ ++ LWIP_ERROR("netif_set_hwaddr : invalid arguments", (hw_addr != NULL), return ERR_VAL); ++ ++ LWIP_ERROR("netif_set_hwaddr: invalid arguments", ++ ((unsigned int)hw_len == NETIF_MAX_HWADDR_LEN), return ERR_VAL); ++ ++ if (netif->drv_set_hwaddr == NULL) { ++ return ERR_OPNOTSUPP; ++ } ++ ++ if (netif->drv_set_hwaddr(netif, (u8_t *)hw_addr, hw_len) != ERR_OK) { ++ return ERR_VAL; ++ } ++ ++ if (memcpy_s(netif->hwaddr, NETIF_MAX_HWADDR_LEN, hw_addr, (u32_t)hw_len) != EOK) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_set_hwaddr: memcpy_s error\n")); ++ return ERR_VAL; ++ } ++ ++ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ++ ("netif: HW address of interface %s%"U16_F" set to %02X:%02X:%02X:%02X:%02X:%02X\n", ++ netif->name, netif->num, ++ netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], ++ netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5])); ++ ++ return ERR_OK; ++} ++ ++#if LWIP_IPV4 ++/* ++ * Find a network interface by searching for its ipaddress ++ * ++ * @param ipaddr IP_add of the netif ++ * @return netif if the its found ++ * NULL if there is no netif with ipaddr ++ */ ++struct netif * ++netif_find_by_ip4addr(const ip_addr_t *ipaddr) ++{ ++ struct netif *netif = NULL; ++ ++ LWIP_ASSERT("Expecting ipaddr to be not NULL ", ipaddr != NULL); ++ ++ for (netif = netif_list; netif != NULL; netif = netif->next) { ++ if (ip_addr_cmp(&(netif->ip_addr), ipaddr)) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ipaddr: found\n")); ++ return netif; ++ } ++ } ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ip4addr: didn't find\n")); ++ return NULL; ++} ++ ++s8_t netif_find_dst_ipaddr(const ip_addr_t *ipaddr, ip_addr_t **dst_addr) ++{ ++ struct netif *netif = NULL; ++ ip_addr_t *pdst_addr = NULL; ++ ++ pdst_addr = *dst_addr; ++ netif = netif_find_by_ipaddr(ipaddr); ++ if (netif == NULL) { ++ return -1; ++ } ++ if ((pdst_addr != NULL) && (!ip_addr_netcmp(pdst_addr, &(netif->ip_addr), ip_2_ip4(&netif->netmask))) && ++ !ip_addr_islinklocal(pdst_addr)) { ++ if (!ip_addr_isany(&netif->gw)) { ++ *dst_addr = &(netif->gw); ++ } ++ } ++ ++ return 0; ++} ++#endif /* LWIP_IPV4 */ ++ ++ ++ ++#if LWIP_DHCP ++/* ++ * Close DHCP and set static network. ++ * ++ * @param netif a pre-allocated netif structure ++ * ++ * @return ERR_OK, or ERR_VAL if failed. ++ */ ++err_t ++netif_dhcp_off(struct netif *netif) ++{ ++ ip_addr_t old_ipaddr; ++ ip_addr_t old_netmask; ++ ip_addr_t old_gateway; ++ ++ if (netif == NULL) { ++ return ERR_VAL; ++ } ++ old_ipaddr = netif->ip_addr; ++ old_netmask = netif->netmask; ++ old_gateway = netif->gw; ++ ++ if (netif_dhcp_data(netif)) { ++ (void)dhcp_release(netif); ++ dhcp_stop(netif); ++ dhcp_cleanup(netif); ++ LWIP_DEBUGF(NETIF_DEBUG, ("DHCP is close;set static IP\n")); ++ } ++ ++ ip_addr_set_val(netif->ip_addr, old_ipaddr); ++ ip_addr_set_val(netif->netmask, old_netmask); ++ ip_addr_set_val(netif->gw, old_gateway); ++ (void)netif_set_up(netif); ++ ++ return ERR_OK; ++} ++#endif /* LWIP_DHCP */ ++ ++u8_t netif_ipaddr_isbrdcast(const ip_addr_t *ipaddr) ++{ ++ struct netif *netif = NULL; ++ ++ for (netif = netif_list; netif != NULL; netif = netif->next) { ++ if (netif_is_up(netif) && ip_addr_isbroadcast(ipaddr, netif)) { ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++struct netif * ++netif_find_by_ifindex(u8_t ifindex) ++{ ++ struct netif *netif = NULL; ++ ++ if (ifindex < LWIP_NETIF_IFINDEX_START) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: Invalid ifindex(%u) \n", ifindex)); ++ return netif; ++ } ++ ++ for (netif = netif_list; netif != NULL; netif = netif->next) { ++ if (netif->ifindex == ifindex) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: found\n")); ++ return netif; ++ } ++ } ++ ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: didn't find\n")); ++ return NULL; ++} ++ ++/* Need to support the get index for all families ++removed PF_PACKET_SOCKET flag , as this flags restricts the usage to only PF_FAMILY Begin */ ++static u8_t ++netif_alloc_ifindex(void) ++{ ++ u8_t tmp_index; ++ for (tmp_index = LWIP_NETIF_IFINDEX_START; tmp_index <= LWIP_NETIF_IFINDEX_MAX; tmp_index++) { ++ if (netif_get_by_index(tmp_index) == NULL) { ++ break; ++ } ++ } ++ ++ return tmp_index; ++} +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-21 11:37:14.000000000 +0800 +@@ -0,0 +1,319 @@ ++#include "lwip/opt.h" ++ ++#if LWIP_NIP /* don't build if not configured for use in lwipopts.h */ ++ ++#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) ++{ ++ 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; ++} ++ ++/** ++ * 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) ++{ ++ 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; ++ } ++ ++ /* 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; ++} ++ ++/** 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); ++} ++ ++/** ++ * 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-21 11:32:04.000000000 +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-26 06:17:04.000000000 +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 22:35:10.000000000 +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-26 06:54:48.000000000 +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); ++ netif = ip_route_pcb(ipaddr, (struct ip_pcb*)pcb); + } + } + +@@ -387,7 +415,7 @@ + return ERR_RTE; + } + +- if (ip_addr_isany(&pcb->local_ip) || ip_addr_ismulticast(&pcb->local_ip)) { ++ if (ip_addr_isany(&pcb->local_ip) || ip_get_option(pcb, SOF_BINDNONUNICAST)) { + /* use outgoing network interface IP address as source address */ + src_ip = ip_netif_get_local_ip(netif, ipaddr); + #if LWIP_IPV6 +@@ -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); +- err = ip_output_if(q, src_ip, dst_ip, ttl, pcb->tos, pcb->protocol, netif); ++ err = ip_output_if(q, src_ip, dst_ip, ttl, pcb->tos, pcb->raw_proto, netif); + NETIF_RESET_HINTS(netif); + + /* did we chain a header earlier? */ +@@ -604,7 +634,12 @@ + if (pcb != NULL) { + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct raw_pcb)); ++#if PF_PACKET_SOCKET ++ pcb->proto.protocol = proto; ++#else + pcb->protocol = proto; ++#endif ++ + pcb->ttl = RAW_TTL; + #if LWIP_MULTICAST_TX_OPTIONS + raw_set_multicast_ttl(pcb, RAW_TTL); +@@ -668,4 +703,227 @@ + } + } + ++#if PF_PACKET_SOCKET ++void raw_packet_input(struct pbuf *p, const struct netif *inp, const struct raw_pcb *from) ++{ ++ struct raw_pcb *pcb = NULL; ++ struct eth_hdr *ethhdr = NULL; ++ u16_t proto; ++ ++ LWIP_UNUSED_ARG(inp); ++ ++ ethhdr = (struct eth_hdr *)p->payload; ++ proto = ethhdr->type; ++ ++ g_lwip_current_eth_hdr = ethhdr; ++ g_lwip_current_netif = inp; ++ ++ pcb = g_packet_raw_pcbs; ++ /* 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->proto.eth_proto == htons(ETHTYPE_ALL)) || ((p != NULL) && !(p->flags & PBUF_FLAG_OUTGOING) && ++ pcb->proto.eth_proto == proto)) && ++ ((!pcb->netifindex) || (pcb->netifindex == inp->ifindex)) && (pcb != from)) { ++ /* receive callback function available? */ ++ if (pcb->recv != NULL) { ++ /* the receive callback function did not eat the packet? */ ++ if (pcb->recv(pcb->recv_arg, pcb, p, NULL) != 0) { ++ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_input: packets recved failed \n")); ++ } ++ } ++ /* no receive callback function was set for this raw PCB */ ++ } ++ ++ pcb = pcb->next; ++ } ++ ++ g_lwip_current_eth_hdr = NULL; ++ return; ++} ++ ++err_t ++raw_packet_bind(struct raw_pcb *pcb, u8_t ifindex, u16_t proto) ++{ ++ struct netif *loc_netif = NULL; ++ ++ if (ifindex != 0) { ++ for (loc_netif = netif_list; loc_netif != NULL; loc_netif = loc_netif->next) { ++ if (ifindex == loc_netif->ifindex) { ++ break; ++ } ++ } ++ ++ /* Return if no matching netifs to bind */ ++ if (loc_netif == NULL) { ++ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_bind: No matching netif found for ifindex(%u)\n", ifindex)); ++ return ERR_NODEV; ++ } ++ } else { ++ return ERR_NODEV; ++ } ++ ++#if DRIVER_STATUS_CHECK ++ if (!netif_is_up(loc_netif) || !netif_is_ready(loc_netif)) ++#else ++ if (!netif_is_up(loc_netif)) ++#endif ++ { ++ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_bind: bind failed as netif (index %u) was down\n", ifindex)); ++ return ERR_NETDOWN; ++ } ++ ++ pcb->netifindex = ifindex; ++ pcb->proto.eth_proto = proto; ++ ++ return ERR_OK; ++} ++ ++/* ++ * Send the raw IP packet through the given netif driver. Note that actually you cannot ++ * modify the link layer header here. Packet need to be sent to driver as it is through the ++ * given netif ++ * @param pcb the raw pcb which to send ++ * @param p the ethernet packet to send ++ * @param ifindex the Interface index of the netif through which packet needs to be sent ++ */ ++err_t ++raw_packet_sendto(const struct raw_pcb *pcb, struct pbuf *p, u8_t ifindex) ++{ ++ struct netif *netif = NULL; ++ u8_t netifindex; ++ LWIP_UNUSED_ARG(pcb); ++ ++ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_packet_sendto: ifindex=%d\n", ifindex)); ++ LWIP_ASSERT("p != NULL", p != NULL); ++ ++ netifindex = ifindex; ++ ++ if (ifindex == 0) { ++ if (pcb->netifindex != 0) { ++ netifindex = pcb->netifindex; ++ } else { ++ return ERR_NODEVADDR; ++ } ++ } ++ ++ /* Find the netif corresponding to the interface index */ ++ netif = netif_find_by_ifindex(netifindex); ++ if (netif == NULL) { ++ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("netif not found for given ifindex (%u)\n", ifindex)); ++ return ERR_NODEVADDR; ++ } ++ ++#if DRIVER_STATUS_CHECK ++ if ((!netif_is_up(netif)) || (!netif_is_ready(netif))) ++#else ++ if ((!netif_is_up(netif))) ++#endif ++ { ++ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("netif was down for given ifindex (%u)\n", ifindex)); ++ return ERR_NETDOWN; ++ } ++ ++ if ((p->tot_len - (SIZEOF_ETH_HDR - ETH_PAD_SIZE)) > netif->mtu) { ++ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("Message too long (%u)\n", p->tot_len)); ++ return ERR_MSGSIZE; ++ } ++ ++ if (pbuf_header(p, ETH_PAD_SIZE) == 0) { ++ p->flags = (u16_t)(p->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_HOST)); ++ p->flags |= PBUF_FLAG_OUTGOING; ++ raw_packet_input(p, netif, pcb); ++ (void)pbuf_header(p, -ETH_PAD_SIZE); ++ } ++ ++ /* For RAW packets of PF_PACKET family, do not modify the packets as it is ++ already supposed to contain the link layer header. So send directly to the driver */ ++ LINK_STATS_INC(link.xmit); ++ return ERR_OK; ++} ++ ++/* ++ * Create a RAW PCB for Packet family. ++ * ++ * @return The RAW PCB which was created. NULL if the PCB data structure ++ * could not be allocated. ++ * ++ * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) ++ * ++ * @see raw_remove() ++ */ ++struct raw_pcb * ++raw_packet_new(u16_t proto) ++{ ++ struct raw_pcb *pcb = NULL; ++ ++ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_packet_new\n")); ++ ++ pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); ++ /* could allocate RAW PCB? */ ++ if (pcb != NULL) { ++ /* initialize PCB to all zeroes */ ++ (void)memset(pcb, 0, sizeof(struct raw_pcb)); ++ pcb->proto.eth_proto = proto; ++ pcb->ttl = RAW_TTL; ++ pcb->next = g_packet_raw_pcbs; ++ g_packet_raw_pcbs = pcb; ++ pcb->all_next = g_all_packet_raw_pcbs; ++ g_all_packet_raw_pcbs = pcb; ++ } ++ return pcb; ++} ++ ++/* ++ * Remove an RAW PCB of packet family type ++ * ++ * @param pcb RAW PCB to be removed. The PCB is removed from the list of ++ * RAW PCB's and the data structure is freed from memory. ++ * ++ * @see raw_packet_new() ++ */ ++void ++raw_packet_remove(struct raw_pcb *pcb) ++{ ++ struct raw_pcb *pcb2 = NULL; ++ ++ /* NULL check */ ++ if (pcb == NULL) { ++ return; ++ } ++ ++ /* pcb to be removed is first in all_pkt list? */ ++ if (g_all_packet_raw_pcbs == pcb) { ++ /* make list start at 2nd pcb */ ++ g_all_packet_raw_pcbs = g_all_packet_raw_pcbs->all_next; ++ /* pcb not 1st in list */ ++ } else { ++ for (pcb2 = g_all_packet_raw_pcbs; pcb2 != NULL; pcb2 = pcb2->all_next) { ++ /* find pcb in g_all_packet_raw_pcbs list */ ++ if (pcb2->all_next == pcb) { ++ /* remove pcb from list */ ++ pcb2->all_next = pcb->all_next; ++ } ++ } ++ } ++ ++ /* pcb to be removed is first in list? */ ++ if (g_packet_raw_pcbs == pcb) { ++ /* make list start at 2nd pcb */ ++ g_packet_raw_pcbs = g_packet_raw_pcbs->next; ++ /* pcb not 1st in list */ ++ } else { ++ for (pcb2 = g_packet_raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { ++ /* find pcb in raw_pcbs list */ ++ if (pcb2->next == pcb) { ++ /* remove pcb from list */ ++ pcb2->next = pcb->next; ++ } ++ } ++ } ++ ++ memp_free(MEMP_RAW_PCB, pcb); ++} ++#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-26 06:54:38.000000000 +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-28 12:13:04.000000000 +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-26 06:56:20.000000000 +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 2022-02-16 16:06:59.178115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/api.h 2022-01-26 06:54:12.000000000 +0800 +@@ -48,6 +48,9 @@ + #include "lwip/sys.h" + #include "lwip/ip_addr.h" + #include "lwip/err.h" ++#if LWIP_LITEOS_COMPAT ++#include "lwip/netif.h" ++#endif + + #ifdef __cplusplus + extern "C" { +@@ -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,15 @@ + /** 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 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 +166,10 @@ + NETCONN_WRITE, + NETCONN_LISTEN, + NETCONN_CONNECT, +- NETCONN_CLOSE ++ NETCONN_CLOSE, ++#if LWIP_LITEOS_COMPAT ++ NETCONN_CLOSED, ++#endif /* LWIP_LITEOS_COMPAT */ + }; + + /** Used to inform the callback function about changes +@@ -201,6 +221,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 +247,12 @@ + struct tcp_pcb *tcp; + struct udp_pcb *udp; + struct raw_pcb *raw; ++#if PF_PACKET_SOCKET ++ struct raw_pcb *packet_raw; ++#endif /* PF_PACKET_SOCKET */ + } pcb; + /** the last asynchronous unreported error this netconn had */ +- err_t pending_err; ++ err_t last_err; + #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 +307,13 @@ + #endif /* LWIP_TCP */ + /** A callback function that is informed about events for this netconn */ + netconn_callback callback; ++#if LWIP_TCP ++ struct pbuf *refused_data; ++ ip_addr_t remote_ip; ++ u16_t remote_port; ++ /** record pending error state after recving RST */ ++ u16_t pending_err; ++#endif + }; + + /** This vector type is passed to @ref netconn_write_vectors_partly to send +@@ -309,21 +340,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) +-struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, ++struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, + netconn_callback callback); + err_t netconn_prepare_delete(struct netconn *conn); + err_t netconn_delete(struct netconn *conn); + /** Get the type of a netconn (as enum netconn_type). */ +-#define netconn_type(conn) (conn->type) ++#define netconn_type(conn) ((u32_t)(conn->type)) + + err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, + u16_t *port, u8_t local); ++#if LWIP_LITEOS_COMPAT ++#if PF_PACKET_SOCKET ++struct pf_packet_sockaddr_ll { ++ u16_t sll_protocol; ++ u16_t sll_hatype; ++ u8_t if_idx; ++ u8_t sll_halen; ++ u8_t sll_addr[NETIF_MAX_HWADDR_LEN]; ++}; ++err_t netconn_get_sockaddr_pf_packet(struct netconn *conn, struct pf_packet_sockaddr_ll *ll, u8_t local); ++#endif /* PF_PACKET_SOCKET */ ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup netconn_common */ + #define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) + /** @ingroup netconn_common */ + #define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) + ++#if PF_PACKET_SOCKET ++err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port, u8_t ifindex); ++#else + err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port); ++#endif /* PF_PACKET_SOCKET */ ++ + err_t netconn_bind_if(struct netconn *conn, u8_t if_idx); + 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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/arch.h 2022-01-26 06:41:32.000000000 +0800 +@@ -37,14 +37,7 @@ + #ifndef LWIP_HDR_ARCH_H + #define LWIP_HDR_ARCH_H + +-#ifndef LITTLE_ENDIAN +-#define LITTLE_ENDIAN 1234 +-#endif +- +-#ifndef BIG_ENDIAN +-#define BIG_ENDIAN 4321 +-#endif +- ++#include + #include "arch/cc.h" + + /** +@@ -149,6 +142,11 @@ + #ifndef X8_F + #define X8_F "02" PRIx8 + #endif ++#if LWIP_LITEOS_COMPAT ++#ifndef U8_F ++#define U8_F PRIu8 ++#endif ++#endif /* LWIP_LITEOS_COMPAT */ + #ifndef U16_F + #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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/err.h 2022-01-26 06:41:32.000000000 +0800 +@@ -85,9 +85,50 @@ + /** Connection closed. */ + ERR_CLSD = -15, + /** Illegal argument. */ +- ERR_ARG = -16 ++ ERR_ARG = -16, ++#ifdef LWIP_LITEOS_COMPAT ++/** Message too long. */ ++ ERR_MSGSIZE = -17, ++/** No such device. */ ++ ERR_NODEV = -18, ++/** No such device or address. */ ++ ERR_NODEVADDR = -19, ++/** socket is not connection-mode & no peer address is set */ ++ ERR_NODEST = -20, ++/** Network is down */ ++ ERR_NETDOWN = -21, ++/** Address family not supported by protocol */ ++ ERR_AFNOSUPP = -22, ++/** No such address */ ++ ERR_NOADDR = -23, ++/** Operation not supported on transport endpoint */ ++ ERR_OPNOTSUPP = -24, ++ ERR_NETUNREACH = -25, ++/** connection request timedout */ ++ ERR_CONNECTIMEOUT = -26, ++/** Error pipe */ ++ ERR_PIPE = -27, ++/** AF not supported */ ++ ERR_AFNOSUPPORT = -28, ++/** Protocol not available */ ++ ERR_NOPROTOOPT = -29, ++ ERR_ACCESS = -30, ++ ERR_NFILE = -31, ++ ERR_RESERVE3 = -32, ++ ERR_RESERVE4 = -33, ++ ERR_RESERVE5 = -34, ++ ERR_RESERVE6 = -35, ++ ERR_FATAL_START = -36, ++ ERR_CONNREFUSED = -41, ++/** FIN mbox post fail. */ ++ ERR_FIN_POST = -42, ++#endif /* LWIP_LITEOS_COMPAT */ + } err_enum_t; + ++#ifdef LWIP_LITEOS_COMPAT ++#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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/etharp.h 2022-01-26 06:41:32.000000000 +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-01-26 07:48:02.000000000 +0800 +@@ -0,0 +1,113 @@ ++/** ++ * @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 /* don't build if not configured for use in lwipopts.h */ ++ ++#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); ++ ++#endif ++ ++#if LWIP_NIP && LWIP_ARP /* don't build if not configured for use in lwipopts.h */ ++ ++// #include "lwip/prot/ethnip.h" ++ ++#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. */ ++ ++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 /* LWIP_IPV4 && LWIP_ARP */ ++ ++#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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/if_api.h 2022-01-26 06:41:32.000000000 +0800 +@@ -49,10 +49,12 @@ + extern "C" { + #endif + ++#if !LWIP_LITEOS_COMPAT + #define IF_NAMESIZE NETIF_NAMESIZE + + char * lwip_if_indextoname(unsigned int ifindex, char *ifname); + unsigned int lwip_if_nametoindex(const char *ifname); ++#endif + + #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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/inet.h 2022-01-26 06:51:36.000000000 +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 + ++#if !LWIP_LITEOS_COMPAT + /* 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 +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)}}} +-/** This variable is initialized by the system to contain the wildcard IPv6 address. */ +-extern const struct in6_addr in6addr_any; + + /* Definitions of the bits in an (IPv4) Internet address integer. + +@@ -119,7 +119,12 @@ + #define IN_BADCLASS(a) IP_BADCLASS(a) + + #define IN_LOOPBACKNET IP_LOOPBACKNET ++#endif /* !LWIP_LITEOS_COMPAT */ + ++/** This variable is initialized by the system to contain the wildcard IPv6 address. */ ++extern const struct in6_addr in6addr_any; ++/** Added new structure for ipv6 loopback as per section 3.9 of rfc 2553/3493 */ ++extern const struct in6_addr in6addr_loopback; + + #ifndef INET_ADDRSTRLEN + #define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX +@@ -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 */ +-#define inet_addr(cp) ipaddr_addr(cp) ++#if LWIP_INET_ADDR_FUNC ++unsigned int inet_addr(const char *cp); ++#else ++#define inet_addr(cp) ipaddr_addr(cp) ++#endif ++ ++#if LWIP_INET_ATON_FUNC ++int inet_aton(const char *cp, struct in_addr *addr); ++#else + #define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) ++#endif ++ ++#if LWIP_INET_NTOA_FUNC ++char *inet_ntoa (struct in_addr in); ++#else + #define inet_ntoa(addr) ip4addr_ntoa((const ip4_addr_t*)&(addr)) ++#endif ++ + #define inet_ntoa_r(addr, buf, buflen) ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) + + #endif /* LWIP_IPV4 */ + + #if LWIP_IPV6 ++/* current the struct ip6_addr for define LWIP_IPV6_SCOPES 0 */ ++#if LWIP_LITEOS_COMPAT ++#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) { \ ++ memcpy((target_in6addr)->s6_addr, (source_ip6addr)->addr, sizeof(struct ip6_addr)); } ++#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) { \ ++ memcpy((target_ip6addr)->addr, (source_in6addr)->s6_addr, sizeof(struct ip6_addr)); \ ++ ip6_addr_clear_zone(target_ip6addr);} ++#else + #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 +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);} +- ++#endif /* LWIP_LITEOS_COMPAT */ + /* 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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/ip_addr.h 2022-01-29 09:20:40.000000000 +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{ \ +- ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); ip_clear_no4(dest); }}while(0) ++ ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); ip_clear_no4(dest); }} while (0) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_set_val(dest, src) do { IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&(src))); if(IP_IS_V6_VAL(src)) { \ ++ ip6_addr_set(ip_2_ip6(&(dest)), ip_2_ip6(&(src))); } else { \ ++ ip4_addr_set(ip_2_ip4(&(dest)), ip_2_ip4(&(src))); }} while (0) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup ipaddr */ + #define ip_addr_set_ipaddr(dest, src) ip_addr_set(dest, src) + /** @ingroup ipaddr */ + #define ip_addr_set_zero(ipaddr) do{ \ +- ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0) ++ ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); } while (0) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_set_zero_val(ipaddr) do{ \ ++ ip6_addr_set_zero(ip_2_ip6(&(ipaddr))); IP_SET_TYPE_VAL(ipaddr, 0); } while (0) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup ip5addr */ + #define ip_addr_set_zero_ip4(ipaddr) do{ \ + ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }while(0) + /** @ingroup ip6addr */ + #define ip_addr_set_zero_ip6(ipaddr) do{ \ +- ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }while(0) ++ ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); } while (0) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_set_zero_ip6_val(ipaddr) do{ \ ++ ip6_addr_set_zero(ip_2_ip6(&(ipaddr))); IP_SET_TYPE_VAL(ipaddr, IPADDR_TYPE_V6); } while (0) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @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 +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)) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_netcmp_val(addr1, addr2, mask) ((IP_IS_V6_VAL((addr1)) && IP_IS_V6_VAL((addr2))) ? \ ++ 0 : \ ++ ip4_addr_netcmp(ip_2_ip4(&addr1), ip_2_ip4(&addr2), mask)) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @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 +282,50 @@ + #define ip_addr_isbroadcast(ipaddr, netif) ((IP_IS_V6(ipaddr)) ? \ + 0 : \ + ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_isbroadcast_val(ipaddr, netif) ((IP_IS_V6_VAL(ipaddr)) ? \ ++ 0 : \ ++ ip4_addr_isbroadcast(ip_2_ip4(&ipaddr), netif)) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup ipaddr */ + #define ip_addr_ismulticast(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ + ip4_addr_ismulticast(ip_2_ip4(ipaddr))) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_ismulticast_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ ++ ip6_addr_ismulticast(ip_2_ip6(&ipaddr)) : \ ++ ip4_addr_ismulticast(ip_2_ip4(&ipaddr))) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup ipaddr */ + #define ip_addr_isloopback(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_isloopback(ip_2_ip6(ipaddr)) : \ + ip4_addr_isloopback(ip_2_ip4(ipaddr))) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_isloopback_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ ++ ip6_addr_isloopback(ip_2_ip6(&ipaddr)) : \ ++ ip4_addr_isloopback(ip_2_ip4(&ipaddr))) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup ipaddr */ + #define ip_addr_islinklocal(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_islinklocal(ip_2_ip6(ipaddr)) : \ + ip4_addr_islinklocal(ip_2_ip4(ipaddr))) ++#ifdef LWIP_DEBUG + #define ip_addr_debug_print(debug, ipaddr) do { if(IP_IS_V6(ipaddr)) { \ + ip6_addr_debug_print(debug, ip_2_ip6(ipaddr)); } else { \ +- ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }}while(0) ++ ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }} while (0) + #define ip_addr_debug_print_val(debug, ipaddr) do { if(IP_IS_V6_VAL(ipaddr)) { \ + ip6_addr_debug_print_val(debug, *ip_2_ip6(&(ipaddr))); } else { \ +- ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }}while(0) ++ ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }} while (0) ++#else ++#define ip_addr_debug_print(debug, ipaddr) ++#define ip_addr_debug_print_val(debug, ipaddr) ++#endif /* LWIP_LITEOS_COMPAT */ ++ + char *ipaddr_ntoa(const ip_addr_t *addr); + char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen); ++#if LWIP_LITEOS_COMPAT ++#define ipaddr_ntoa_unsafe(addr) ((IP_IS_V6_VAL(*addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr))) ++#endif /* LWIP_LITEOS_COMPAT */ + int ipaddr_aton(const char *cp, ip_addr_t *addr); + + /** @ingroup ipaddr */ +@@ -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) + ++#define ip_addr_cmp_zoneless(addr1, addr2) ip4_addr_cmp(addr1, addr2) + #define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) + #define ip_addr_copy_from_ip4(dest, src) ip4_addr_copy(dest, src) + #define ip_addr_set_ip4_u32(ipaddr, val) ip4_addr_set_u32(ip_2_ip4(ipaddr), val) + #define ip_addr_set_ip4_u32_val(ipaddr, val) ip_addr_set_ip4_u32(&(ipaddr), val) + #define ip_addr_get_ip4_u32(ipaddr) ip4_addr_get_u32(ip_2_ip4(ipaddr)) + #define ip_addr_set(dest, src) ip4_addr_set(dest, src) ++#define ip_addr_set_val(dest, src) ip4_addr_copy(dest, src) + #define ip_addr_set_ipaddr(dest, src) ip4_addr_set(dest, src) + #define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) ++#define ip_addr_set_zero_val(ipaddr) ip4_addr_set_zero(&(ipaddr)) + #define ip_addr_set_zero_ip4(ipaddr) ip4_addr_set_zero(ipaddr) + #define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) + #define ip_addr_set_loopback(is_ipv6, ipaddr) ip4_addr_set_loopback(ipaddr) + #define ip_addr_set_hton(dest, src) ip4_addr_set_hton(dest, src) + #define ip_addr_get_network(target, host, mask) ip4_addr_get_network(target, host, mask) + #define ip_addr_netcmp(addr1, addr2, mask) ip4_addr_netcmp(addr1, addr2, mask) ++#define ip_addr_netcmp_val(addr1, addr2, mask) ip4_addr_netcmp(&(addr1), &(addr2), mask) + #define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) + #define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) ++#define ip_addr_isnone(ipaddr) ip4_addr_isnone(ipaddr) + #define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) + #define ip_addr_isloopback(ipaddr) ip4_addr_isloopback(ipaddr) ++#define ip_addr_isloopback_val(ipaddr) ip4_addr_isloopback(&(ipaddr)) + #define ip_addr_islinklocal(ipaddr) ip4_addr_islinklocal(ipaddr) + #define ip_addr_isbroadcast(addr, netif) ip4_addr_isbroadcast(addr, netif) ++#define ip_addr_isbroadcast_val(addr, netif) ip4_addr_isbroadcast(&(addr), netif) + #define ip_addr_ismulticast(ipaddr) ip4_addr_ismulticast(ipaddr) ++#define ip_addr_ismulticast_val(ipaddr) ip4_addr_ismulticast(&(ipaddr)) ++#ifdef LWIP_DEBUG + #define ip_addr_debug_print(debug, ipaddr) ip4_addr_debug_print(debug, ipaddr) + #define ip_addr_debug_print_val(debug, ipaddr) ip4_addr_debug_print_val(debug, ipaddr) ++#else ++#define ip_addr_debug_print(debug, ipaddr) ++#define ip_addr_debug_print_val(debug, ipaddr) ++#endif ++ + #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 +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) ++#define ip_addr_set_val(dest, src) ip6_addr_copy(dest, src) ++ + #define ip_addr_set_ipaddr(dest, src) ip6_addr_set(dest, src) + #define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr) ++#define ip_addr_set_zero_val(ipaddr) ip6_addr_set_zero(&(ipaddr)) + #define ip_addr_set_zero_ip6(ipaddr) ip6_addr_set_zero(ipaddr) ++#define ip_addr_set_zero_ip6_val(ipaddr) ip6_addr_set_zero(&(ipaddr)) + #define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr) + #define ip_addr_set_loopback(is_ipv6, ipaddr) ip6_addr_set_loopback(ipaddr) + #define ip_addr_set_hton(dest, src) ip6_addr_set_hton(dest, src) + #define ip_addr_get_network(target, host, mask) ip6_addr_set_zero(target) + #define ip_addr_netcmp(addr1, addr2, mask) 0 ++#define ip_addr_netcmp_val(addr1, addr2, mask) 0 + #define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) + #define ip_addr_cmp_zoneless(addr1, addr2) ip6_addr_cmp_zoneless(addr1, addr2) + #define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) ++#define ip_addr_isnone(ipaddr) ip6_addr_isnone(ipaddr) + #define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) + #define ip_addr_isloopback(ipaddr) ip6_addr_isloopback(ipaddr) ++#define ip_addr_isloopback_val(ipaddr) ip6_addr_isloopback(&(ipaddr)) + #define ip_addr_islinklocal(ipaddr) ip6_addr_islinklocal(ipaddr) + #define ip_addr_isbroadcast(addr, netif) 0 ++#define ip_addr_isbroadcast_val(addr, netif) 0 + #define ip_addr_ismulticast(ipaddr) ip6_addr_ismulticast(ipaddr) ++#define ip_addr_ismulticast_val(ipaddr) ip6_addr_ismulticast(&(ipaddr)) ++#ifdef LWIP_DEBUG + #define ip_addr_debug_print(debug, ipaddr) ip6_addr_debug_print(debug, ipaddr) + #define ip_addr_debug_print_val(debug, ipaddr) ip6_addr_debug_print_val(debug, ipaddr) ++#else ++#define ip_addr_debug_print(debug, ipaddr) ++#define ip_addr_debug_print_val(debug, ipaddr) ++#endif ++ + #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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/ip.h 2022-01-26 06:51:26.000000000 +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) */ +- ++#if LWIP_LITEOS_COMPAT ++#define SOF_DONTROUTE 0x01U /* all packets sent from this socket should only be routed with link scope entry */ ++#define SOF_BINDNONUNICAST 0x10U /* socket has bind to a non unicast */ ++#endif /* LWIP_LITEOS_COMPAT */ + /* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ + #define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE) + +@@ -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; ++#if LWIP_LITEOS_COMPAT ++ /* The IP header ID of the next outgoing IP packet */ ++#if LWIP_IPV4 ++ /* ensure this member of this sturcture is not mem set to zero */ ++ u16_t ip_id; ++#endif /* LWIP_IPV4 */ ++#endif /* LWIP_LITEOS_COMPAT */ + }; + extern struct ip_globals ip_data; + +@@ -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 */ ++#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 ++ * (requires IP_FRAG_USES_STATIC_BUF==1).This is not a configurable value. ++ */ ++#if !defined(IP_FRAG_MAX_MTU) ++#define IP_FRAG_MAX_MTU 1500 ++#endif ++/* As per RFC 791, "Every internet module must be able to forward a datagram of 68 ++ * octets without further fragmentation. This is because an internet header ++ * may be up to 60 octets, and the minimum fragment is 8 octets." */ ++#if !defined(IP_FRAG_MIN_MTU) ++#define IP_FRAG_MIN_MTU 68 ++#endif ++struct netif *ip_route_pcb(const ip_addr_t *dest, const struct ip_pcb* pcb); ++#endif /* LWIP_LITEOS_COMPAT */ + #define ip_route_get_local_ip(src, dest, netif, ipaddr) do { \ + (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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/netbuf.h 2022-01-26 06:41:32.000000000 +0800 +@@ -55,13 +55,22 @@ + #define NETBUF_FLAG_DESTADDR 0x01 + /** This netbuf includes a checksum */ + #define NETBUF_FLAG_CHKSUM 0x02 ++#if PF_PACKET_SOCKET ++#define NETBUF_FLAG_IFINDEX 0x04 ++#endif /* PF_PACKET_SOCKET */ + + /** "Network buffer" - contains data and addressing info */ + struct netbuf { + struct pbuf *p, *ptr; + ip_addr_t addr; + u16_t port; +-#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY ++#if PF_PACKET_SOCKET ++ u16_t hatype; ++ u16_t reserve; /* padded */ ++ u8_t netifindex; ++#endif /* PF_PACKET_SOCKET */ ++ ++#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY || PF_PACKET_SOCKET + u8_t flags; + u16_t toport_chksum; + #if LWIP_NETBUF_RECVINFO +@@ -73,7 +82,7 @@ + /* Network buffer functions: */ + struct netbuf * netbuf_new (void); + void netbuf_delete (struct netbuf *buf); +-void * netbuf_alloc (struct netbuf *buf, u16_t size); ++void * netbuf_alloc (struct netbuf *buf, u16_t size, u8_t netconn_type); + void netbuf_free (struct netbuf *buf); + err_t netbuf_ref (struct netbuf *buf, + const void *dataptr, u16_t size); +@@ -93,6 +102,10 @@ + #define netbuf_fromaddr(buf) (&((buf)->addr)) + #define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set(&((buf)->addr), fromaddr) + #define netbuf_fromport(buf) ((buf)->port) ++#if LWIP_LITEOS_COMPAT ++#define netbuf_fromifindex(buf) ((buf)->netifindex) ++#define netbuf_fromhatype(buf) ((buf)->hatype) ++#endif /* LWIP_LITEOS_COMPAT */ + #if LWIP_NETBUF_RECVINFO + #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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/netdb.h 2022-01-26 06:41:32.000000000 +0800 +@@ -36,6 +36,10 @@ + + #include "lwip/opt.h" + ++#if LWIP_LITEOS_COMPAT ++#include ++#endif ++ + #if LWIP_DNS && LWIP_SOCKET + + #include "lwip/arch.h" +@@ -63,6 +67,7 @@ + #define LWIP_DNS_API_DECLARE_STRUCTS 1 + #endif + ++#if !LWIP_LITEOS_COMPAT + #if LWIP_DNS_API_DEFINE_ERRORS + /** Errors used by the DNS API functions, h_errno can be one of them */ + #define EAI_NONAME 200 +@@ -112,23 +117,39 @@ + }; + #endif /* LWIP_DNS_API_DECLARE_STRUCTS */ + +-#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) + + #if LWIP_DNS_API_DECLARE_H_ERRNO + /* application accessible error code set by the DNS API functions */ + extern int h_errno; + #endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ ++#endif /* !LWIP_LITEOS_COMPAT */ + ++#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) ++ ++#if LWIP_GETHOSTBYNAME || (defined(LWIP_COMPAT_SOCKETS) && (LWIP_COMPAT_SOCKETS != 2)) + struct hostent *lwip_gethostbyname(const char *name); ++#endif /* LWIP_GETHOSTBYNAME || (defined(LWIP_COMPAT_SOCKETS) && (LWIP_COMPAT_SOCKETS != 2)) */ ++#if (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) + int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop); ++#endif /* (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) */ ++#if (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) + void lwip_freeaddrinfo(struct addrinfo *ai); + int lwip_getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); +- +-#if LWIP_COMPAT_SOCKETS ++#endif /* (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) */ ++#if LWIP_DNS_REVERSE ++int lwip_getnameinfo(const struct sockaddr *sa, ++ socklen_t salen, ++ char *host, ++ size_t hostlen, ++ char *serv, ++ size_t servlen, ++ int flags); ++#endif /* LWIP_DNS_REVERSE */ ++#if defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2 + /** @ingroup netdbapi */ + #define gethostbyname(name) lwip_gethostbyname(name) + /** @ingroup netdbapi */ +@@ -139,7 +160,11 @@ + /** @ingroup netdbapi */ + #define getaddrinfo(nodname, servname, hints, res) \ + lwip_getaddrinfo(nodname, servname, hints, res) +-#endif /* LWIP_COMPAT_SOCKETS */ ++ ++/* @ingroup netdbapi */ ++#define getnameinfo(sock, sock_size, host, host_len, servname, servname_size, flags) \ ++ lwip_getnameinfo(sock, sock_size, host, host_len, servname, servname_size, flags) ++#endif /* defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2 */ + + #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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/netifapi.h 2022-01-26 06:41:32.000000000 +0800 +@@ -73,6 +73,30 @@ + const ip4_addr_t *netmask, const ip4_addr_t *gw); + #endif /* LWIP_IPV4*/ + ++/* ++Func Name: netifapi_netif_find_by_name ++*/ ++/** ++* @ingroup netifapi_netif ++* ++* @brief ++* This is a thread safe API, used to get the netif pointer whoes name was the input argument. ++* It is recommended to use this API instead of netif_find_by_name(). ++* Call netif_find() in a thread-safe way by running that function inside the tcpip_thread ++* context. ++* ++* @param[in] name Name of the netif. ++* ++* @returns ++* The netif pointer : On success \n ++* NULL : the netif was NOT exist \n ++* ++* @par Related Topics ++* netif_find_by_name() ++* ++*/ ++ ++struct netif* netifapi_netif_find_by_name(const char *name); + err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, + 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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/netif.h 2022-01-26 06:50:34.000000000 +0800 +@@ -48,6 +48,7 @@ + #include "lwip/def.h" + #include "lwip/pbuf.h" + #include "lwip/stats.h" ++#include "lwip/prot/ethernet.h" + + #ifdef __cplusplus + extern "C" { +@@ -67,8 +68,17 @@ + * netif can be identified by in APIs. Composed of + * 2 chars, 3 (max) digits, and 1 \0 + */ +-#define NETIF_NAMESIZE 6 ++#ifdef IFNAMSIZ ++#define NETIF_NAMESIZE IFNAMSIZ ++#else ++#define NETIF_NAMESIZE 16 ++#endif + ++#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 + /** + * @defgroup netif_flags Flags + * @ingroup netif +@@ -106,6 +116,17 @@ + * Set by the netif driver in its init function. */ + #define NETIF_FLAG_MLD6 0x40U + ++/** If set, the interface is configured using DHCP. ++ * Set by the DHCP code when starting or stopping DHCP. */ ++#define NETIF_FLAG_DHCP 0x80U ++ ++#if DRIVER_STATUS_CHECK ++/** If set, the netif has send capability. ++ * Set by the netif driver when its is ready to send. */ ++#define NETIF_FLAG_DRIVER_RDY 0x100U ++#endif ++ ++#define NETIF_FLAG_LOOPBACK 0x800 + /** + * @} + */ +@@ -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 */ + ++/** Function pointer of driver set hw address function */ ++typedef u8_t (*drv_set_hwaddr_fn)(struct netif *netif, u8_t *addr, u8_t len); ++ + #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 +273,10 @@ + */ + #define netif_get_client_data(netif, id) (netif)->client_data[(id)] + #endif ++#ifndef LOOPBACK_IF ++/** Type of link layer, these macros should be used for link_layer_type of struct netif */ ++#define LOOPBACK_IF 772 ++#endif + + #if (LWIP_IPV4 && LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) || (LWIP_IPV6 && (LWIP_ND6_NUM_DESTINATIONS > 0x7f)) + typedef u16_t netif_addr_idx_t; +@@ -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; ++ /* This function is to set the mac_address of the interface. */ ++ drv_set_hwaddr_fn drv_set_hwaddr; ++#if LWIP_NETIF_ETHTOOL && LWIP_SOCKET ++ void *ethtool_ops; ++#endif ++#if LWIP_DHCPS ++ /* DHCP Server Informarion for this netif */ ++ struct dhcps *dhcps; ++#endif + #ifdef netif_get_client_data + void* client_data[LWIP_NETIF_CLIENT_DATA_INDEX_MAX + LWIP_NUM_NETIF_CLIENT_DATA]; + #endif + #if LWIP_NETIF_HOSTNAME + /* the hostname for this netif, NULL is a valid value */ +- const char* hostname; ++ char hostname[NETIF_HOSTNAME_MAX_LEN]; + #endif /* LWIP_NETIF_HOSTNAME */ + #if LWIP_CHECKSUM_CTRL_PER_NETIF + u16_t chksum_flags; +@@ -341,13 +398,19 @@ + u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; + /** number of bytes used in hwaddr */ + u8_t hwaddr_len; ++ /* link layer type, ethernet or wifi */ ++ u16_t link_layer_type; /**< Indicates whether the link layer type is ethernet or wifi. */ + /** flags (@see @ref netif_flags) */ +- u8_t flags; ++ u32_t flags; + /** descriptive abbreviation */ +- char name[2]; +- /** number of this interface. Used for @ref if_api and @ref netifapi_netif, ++ char name[NETIF_NAMESIZE]; ++ /** number of this interface. Used for @ref if_api and @ref netifapi_netif, + * as well as for IPv6 zones */ + u8_t num; ++ u8_t ifindex; /* Interface Index mapped to each netif. Starts from 1 */ ++#if DRIVER_STATUS_CHECK ++ s32_t waketime; /**< Started when netif_stop_queue is called from driver. */ ++#endif + #if LWIP_IPV6_AUTOCONFIG + /** is this netif enabled for IPv6 autoconfiguration */ + u8_t ip6_autoconfig_enabled; +@@ -387,6 +450,15 @@ + u16_t loop_cnt_current; + #endif /* LWIP_LOOPBACK_MAX_PBUFS */ + #endif /* ENABLE_LOOPBACK */ ++#if LWIP_SO_DONTROUTE ++ /** The scope of the netif, this is set in ip4_route/ip6_route, the usr can use this ++ to decide whether the netif is in desired sope */ ++ rt_scope_t scope; ++#endif ++#if LWIP_IPV6 ++ /** Call back needs to be registered if adaptor requires notification for IPv6 DAD */ ++ u8_t ipv6_flags; ++#endif + }; + + #if LWIP_CHECKSUM_CTRL_PER_NETIF +@@ -407,9 +479,15 @@ + #endif /* LWIP_SINGLE_NETIF */ + /** The default network interface. */ + extern struct netif *netif_default; +- ++s8_t netif_find_dst_ipaddr(const ip_addr_t *ipaddr, ip_addr_t **dst_addr); + void netif_init(void); + ++#if LWIP_DHCP ++err_t netif_dhcp_off(struct netif *netif); ++#endif ++ ++u8_t netif_check_num_isusing(const char* ifname, const u8_t num); ++ + struct netif *netif_add_noaddr(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input); + + #if LWIP_IPV4 +@@ -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); + +-void netif_set_default(struct netif *netif); ++struct netif *netif_find_by_ipaddr(const ip_addr_t *ipaddr); ++ ++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); + void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask); + void netif_set_gw(struct netif *netif, const ip4_addr_t *gw); ++struct netif *netif_find_by_ip4addr(const ip_addr_t *ipaddr); + /** @ingroup netif_ip4 */ + #define netif_ip4_addr(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->ip_addr))) + /** @ingroup netif_ip4 */ +@@ -455,6 +548,9 @@ + + void netif_set_up(struct netif *netif); + void netif_set_down(struct netif *netif); ++err_t netif_set_mtu_api(struct netif *netif, u16_t netif_mtu); ++err_t netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw_len); ++void netif_get_hwaddr(const struct netif *netif, unsigned char *hw_addr, int hw_len); + /** @ingroup netif + * Ask if an interface is up + */ +@@ -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); ++err_t netif_do_add_ipv6_addr(struct netif *netif, void *arguments); ++err_t netif_do_rmv_ipv6_addr(struct netif *netif, void *arguments); + 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-01-21 11:35:10.000000000 +0800 +@@ -0,0 +1,219 @@ ++/** ++ * @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" ++#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 /* ok? wxf0203 */ ++#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 /* 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-01-11 22:35:10.000000000 +0800 +@@ -0,0 +1,105 @@ ++/** ++ * @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" ++#include "lwip/err.h" ++#include "lwip/pbuf.h" ++#include "lwip/netif.h" ++#include "lwip/nip_addr.h" ++#include "lwip/nip.h" ++ ++#if LWIP_NIP ++ ++#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];//headerlen最大多少? ++ 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. */ ++/*保存对另一个pbuf的引用的自定义pbuf, ++在释放该自定义pbuf时释放该引用。这用于创建指向原始pbuf的自定义PBUF_REF。*/ ++struct pbuf_custom_ref { ++ /** 'base class' */ ++ struct pbuf_custom pc; ++ /** pointer to the original pbuf that is referenced */ ++ //指向被引用的原始pbuf的指针 ++ 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-01-21 11:28:28.000000000 +0800 +@@ -0,0 +1,97 @@ ++#ifndef LWIP_HDR_NIP_H ++#define LWIP_HDR_NIP_H ++ ++#include "lwip/opt.h" ++#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 ++//PACK_STRUCT_BEGIN ++/* 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); ++};//PACK_STRUCT_STRUCT; ++//PACK_STRUCT_END ++#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 /* 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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/opt.h 2022-01-26 06:49:56.000000000 +0800 +@@ -529,7 +529,7 @@ + * (only needed if you use the sequential API, like api_lib.c) + */ + #if !defined MEMP_NUM_NETCONN || defined __DOXYGEN__ +-#define MEMP_NUM_NETCONN 4 ++#define MEMP_NUM_NETCONN 16 + #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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/pbuf.h 2022-01-26 06:49:32.000000000 +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 +- ++#ifdef LWIP_LITEOS_COMPAT ++#define PBUF_FLAG_HOST 0x100U ++#define PBUF_FLAG_OUTGOING 0x200U ++#endif + /** Main packet buffer struct */ + 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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/priv/api_msg.h 2022-01-26 06:41:32.000000000 +0800 +@@ -46,6 +46,7 @@ + #include "lwip/igmp.h" + #include "lwip/api.h" + #include "lwip/priv/tcpip_priv.h" ++#include "lwip/ip.h" + + #ifdef __cplusplus + extern "C" { +@@ -70,6 +71,14 @@ + #define NETCONN_SHUT_WR 2 + #define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) + ++#if PF_PACKET_SOCKET ++/* Packet Types */ ++#define PACKET_HOST 0 /* To us */ ++#define PACKET_BROADCAST 1 /* To all */ ++#define PACKET_MULTICAST 2 /* To group */ ++#define PACKET_OTHERHOST 3 /* To someone else */ ++#define PACKET_OUTGOING 4 ++#endif + /* IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ +@@ -88,7 +97,7 @@ + struct netbuf *b; + /** used for lwip_netconn_do_newconn */ + struct { +- u8_t proto; ++ u16_t proto; + } n; + /** used for lwip_netconn_do_bind and lwip_netconn_do_connect */ + struct { +@@ -102,6 +111,12 @@ + u16_t API_MSG_M_DEF(port); + u8_t local; + } ad; ++#if PF_PACKET_SOCKET ++ struct { ++ struct pf_packet_sockaddr_ll API_MSG_M_DEF(ll); ++ u8_t local; ++ } adpkt; ++#endif + /** used for lwip_netconn_do_write */ + struct { + /** current vector to write */ +@@ -205,6 +220,7 @@ + #endif /* TCP_LISTEN_BACKLOG */ + void lwip_netconn_do_write (void *m); + void lwip_netconn_do_getaddr (void *m); ++void lwip_netconn_do_getaddr_pfpkt (void *m); + void lwip_netconn_do_close (void *m); + void lwip_netconn_do_shutdown (void *m); + #if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +@@ -214,6 +230,7 @@ + + #if LWIP_DNS + void lwip_netconn_do_gethostbyname(void *arg); ++void lwip_netconn_do_getnamebyhost(void *arg); + #endif /* LWIP_DNS */ + + struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); +@@ -233,6 +250,7 @@ + + typedef void (*netifapi_void_fn)(struct netif *netif); + typedef err_t (*netifapi_errt_fn)(struct netif *netif); ++typedef err_t (*netifapi_arg_fn)(struct netif *netif, void *arg); + + struct netifapi_msg { + struct tcpip_api_call_data call; +@@ -245,9 +263,27 @@ + NETIFAPI_IPADDR_DEF(ip4_addr_t, gw); + #endif /* LWIP_IPV4 */ + void *state; ++ } add; ++ ++ struct { ++ const ip_addr_t *ipaddr; ++ } find_by_ipaddr; ++ struct { ++ const char *name; ++ } find_by_name; ++ struct { ++ unsigned char ifindex; ++ } find_by_ifindex; ++ struct { ++#if LWIP_IPV4 ++ ip4_addr_t *ipaddr; ++ ip4_addr_t *netmask; ++ ip4_addr_t *gw; ++#endif /* LWIP_IPV4 */ ++ void *state; + netif_init_fn init; + netif_input_fn input; +- } add; ++ } add_get; + struct { + 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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/priv/sockets_priv.h 2022-01-26 06:41:32.000000000 +0800 +@@ -49,7 +49,6 @@ + extern "C" { + #endif + +-#define NUM_SOCKETS MEMP_NUM_NETCONN + + /** This is overridable for the rare case where more than 255 threads + * select on the same socket... +@@ -69,6 +68,10 @@ + struct netconn *conn; + /** data that was left from the previous read */ + union lwip_sock_lastdata lastdata; ++ /** offset in the data that was left from the previous read */ ++ u16_t lastoffset; ++ /* socket level mutex used for multithread recv support */ ++ sys_mutex_t mutex; + #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL + /** number of times data was received, set by event_callback(), + tested by the receive and select functions */ +@@ -158,6 +161,7 @@ + fd_set *exceptset; + #endif /* LWIP_SOCKET_SELECT */ + #if LWIP_SOCKET_POLL ++ + /** fds passed to poll; NULL if select */ + 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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/prot/icmp6.h 2022-01-26 06:41:32.000000000 +0800 +@@ -135,7 +135,7 @@ + # include "arch/bpstruct.h" + #endif + PACK_STRUCT_BEGIN +-struct icmp6_hdr { ++struct icmpv6_hdr { + 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-26 06:48:00.000000000 +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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/prot/ip4.h 2022-01-26 06:41:32.000000000 +0800 +@@ -39,6 +39,9 @@ + + #include "lwip/arch.h" + #include "lwip/ip4_addr.h" ++#if LWIP_LITEOS_COMPAT ++#include ++#endif + + #ifdef __cplusplus + extern "C" { +@@ -81,10 +84,12 @@ + PACK_STRUCT_FIELD(u16_t _id); + /* fragment offset field */ + PACK_STRUCT_FIELD(u16_t _offset); ++#if !LWIP_LITEOS_COMPAT + #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 */ ++#endif + /* 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-21 11:29:24.000000000 +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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/raw.h 2022-01-26 06:41:32.000000000 +0800 +@@ -47,6 +47,8 @@ + #include "lwip/ip.h" + #include "lwip/ip_addr.h" + #include "lwip/ip6_addr.h" ++#include "lwip/etharp.h" ++#include "lwip/icmp6.h" + + #ifdef __cplusplus + extern "C" { +@@ -57,6 +59,18 @@ + #define RAW_FLAGS_MULTICAST_LOOP 0x04U + + struct raw_pcb; ++extern struct raw_pcb* raw_pcbs; ++ ++#if PF_PACKET_SOCKET ++extern const struct eth_hdr *g_lwip_current_eth_hdr; ++extern const struct netif *g_lwip_current_netif; ++/* Dest MAC add of current ethernet header of RAW packets ++ * received for PF_PACKET family */ ++#define eth_current_hdr() (g_lwip_current_eth_hdr) ++#define eth_current_netif() (g_lwip_current_netif) ++struct raw_pcb* get_packet_raw_pcbs(void); ++struct raw_pcb* get_all_packet_raw_pcbs(void); ++#endif /* PF_PACKET_SOCKET */ + + /** Function prototype for raw pcb receive callback functions. + * @param arg user supplied argument (raw_pcb.recv_arg) +@@ -77,8 +91,19 @@ + IP_PCB; + + struct raw_pcb *next; +- ++#if PF_PACKET_SOCKET ++ struct raw_pcb *all_next; ++ u8_t netifindex; ++ ++ union { ++ u16_t eth_proto; /* Ethernet HeaderType/Protocol for Packet sockets */ ++#define raw_proto proto.protocol ++ u8_t protocol; /* IP protocol for AF_INET sockets */ ++ } proto; ++#else ++#define raw_proto protocol + u8_t protocol; ++#endif + u8_t flags; + + #if LWIP_MULTICAST_TX_OPTIONS +@@ -115,6 +140,14 @@ + + void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); + ++#if PF_PACKET_SOCKET ++struct raw_pcb * raw_packet_new (u16_t proto); ++void raw_packet_remove (struct raw_pcb *pcb); ++void raw_packet_input (struct pbuf *p, const struct netif *inp, const struct raw_pcb *from); ++err_t raw_packet_sendto (const struct raw_pcb *pcb, struct pbuf *p, u8_t ifindex); ++err_t raw_packet_bind (struct raw_pcb *pcb, u8_t ifindex, u16_t proto); ++#endif /* PF_PACKET_SOCKET */ ++ + #define raw_flags(pcb) ((pcb)->flags) + #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 2022-02-16 16:06:59.186115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/sockets.h 2022-01-27 08:48:38.000000000 +0800 +@@ -51,10 +51,26 @@ + + #include + ++#if LWIP_LITEOS_COMPAT ++#include "sys/select.h" ++#include "sys/socket.h" ++#include "poll.h" ++#include "netinet/tcp.h" ++#endif /* LWIP_LITEOS_COMPAT */ ++ + #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) +@@ -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. */ ++#else /* LWIP_LITEOS_COMPAT */ ++#if LWIP_LITEOS_COMPAT ++#ifndef TCP_KEEPALIVE ++#define TCP_KEEPALIVE 0x02 ++#endif /* TCP_KEEPALIVE */ ++ ++#ifndef SIN_ZERO_LEN ++#define SIN_ZERO_LEN 8 ++#endif /* SIN_ZERO_LEN */ ++ ++#ifndef SOCK_MAX ++#define SOCK_MAX (SOCK_RAW + 1) ++#endif /* SOCK_MAX */ ++ ++#ifndef SOCK_TYPE_MASK ++#define SOCK_TYPE_MASK 0xf ++#endif /* SOCK_TYPE_MASK */ ++#endif ++ + void lwip_socket_thread_init(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ + void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ + ++#if LWIP_IPV6 ++#define LWIP_IS_IPPROTOCOL(protocol) ((protocol) == IPPROTO_IP || (protocol) == IPPROTO_IPV6 || (protocol) == 0) ++#if PF_PACKET ++#define LWIP_IS_VALID_DOMAIN(domain) (((domain) == AF_INET) || ((domain) == AF_INET6) || ((domain) == PF_PACKET)) ++#else ++#define LWIP_IS_VALID_DOMAIN(domain) ((domain) == AF_INET) || ((domain) == AF_INET6) ++#endif ++#else ++#define LWIP_IS_IPPROTOCOL(protocol) ((protocol) == IPPROTO_IP || (protocol) == 0) ++#if PF_PACKET ++#define LWIP_IS_VALID_DOMAIN(domain) (((domain) == AF_INET) || ((domain) == PF_PACKET)) ++#else ++#define LWIP_IS_VALID_DOMAIN(domain) ((domain) == AF_INET) || ((domain) == AF_INET6) ++#endif ++#endif + #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 +604,9 @@ + #if LWIP_SOCKET_SELECT + #define lwip_select select + #endif ++ ++#define lwip_gethostbyname(name) gethostbyname(name) ++ + #if LWIP_SOCKET_POLL + #define lwip_poll poll + #endif +@@ -558,9 +614,18 @@ + #define lwip_inet_ntop inet_ntop + #define lwip_inet_pton inet_pton + ++#if LWIP_DNS ++#define lwip_gethostbyname(name) gethostbyname(name) ++#define lwip_gethostbyname_r gethostbyname_r ++#define lwip_freeaddrinfo freeaddrinfo ++#define lwip_getaddrinfo getaddrinfo ++#define lwip_getnameinfo getnameinfo ++#endif ++ + #if LWIP_POSIX_SOCKETS_IO_NAMES + #define lwip_read read + #define lwip_readv readv ++ + #define lwip_write write + #define lwip_writev writev + #undef lwip_close +@@ -682,7 +747,7 @@ + #ifdef __cplusplus + } + #endif +- ++#endif + #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-26 06:48:14.000000000 +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 07:00:00.000000000 +0700 ++++ b/lwip-2.1.2/src/include/netif/ifaddrs.h 2022-01-26 06:41:32.000000000 +0800 +@@ -0,0 +1,307 @@ ++/* ++ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved. ++ * Description: declare BSD APIs : getifaddrs freeifaddrs ++ * Author: none ++ * Create: 2020 ++ */ ++ ++#ifndef __LWIP_IFADDRS_H ++#define __LWIP_IFADDRS_H ++ ++#if (LWIP_IPV4 || LWIP_IPV6) && LWIP_SOCKET ++ ++#include "lwip/netif.h" ++#include "lwip/sockets.h" ++ ++#ifdef LWIP_COMPAT_SOCKETS ++#if LWIP_COMPAT_SOCKETS != 2 ++/* @ingroup socket */ ++#define getifaddrs(ifap) lwip_getifaddrs(ifap) ++#define freeifaddrs(ifa) lwip_freeifaddrs(ifa) ++#else /* LWIP_COMPAT_SOCKETS != 2 */ ++/* @ingroup socket */ ++#define lwip_getifaddrs(ifap) getifaddrs(ifap) ++#define lwip_freeifaddrs(ifa) freeifaddrs(ifa) ++#endif /* LWIP_COMPAT_SOCKETS == 2 */ ++#endif /* LWIP_COMPAT_SOCKETS */ ++ ++#if LWIP_LITEOS_COMPAT ++ ++#ifndef SIOCETHTOOL ++#define SIOCETHTOOL _IOW('i', 56, struct ifreq) ++#endif ++#define IFF_DRV_RUNNING 0x40 ++ ++#else ++#define SIOCADDRT _IOW('R', 9, struct rtentry) ++#define SIOCDELRT _IOW('R', 10, struct rtentry) ++ ++#define SIOCGIFFLAGS _IOWR('i', 17, struct ifreq) /* get ifnet flags */ ++#define SIOCSIFFLAGS _IOW('i', 16, struct ifreq) /* set ifnet flags */ ++#define SIOCGIFADDR _IOWR('i', 33, struct ifreq) /* get ifnet address */ ++#define SIOCSIFADDR _IOW('i', 12, struct ifreq) /* set ifnet address */ ++ ++#define SIOCDIFADDR _IOW('i', 25, struct ifreq) /* delete IF addr */ ++ ++#define SIOCGIFNETMASK _IOWR('i', 37, struct ifreq) /* get net addr mask */ ++#define SIOCSIFNETMASK _IOW('i', 22, struct ifreq) /* set net addr mask */ ++#define SIOCSIFHWADDR _IOW('i', 140, struct ifreq) /* set IF name */ ++#define SIOCGIFHWADDR _IOW('i', 141, struct ifreq) /* set IF name */ ++#define SIOCGIFNAME _IOW('i', 142, struct ifreq) /* set IF name */ ++#define SIOCSIFNAME _IOW('i', 40, struct ifreq) /* set IF name */ ++ ++/** Gets IF mtu */ ++#define SIOCGIFMTU _IOWR('i', 51, struct ifreq) ++/** Sets IF mtu */ ++#define SIOCSIFMTU _IOW('i', 52, struct ifreq) ++/** ethtool */ ++#define SIOCETHTOOL _IOW('i', 56, struct ifreq) ++ ++/* provide PF_PACKET option on SOCK_RAW */ ++#define SIOCGIFINDEX _IOWR('i', 32, struct ifreq) /* get IF index */ ++#define SIOCGIFCONF _IOWR('i', 36, struct ifconf) /* get ifnet list */ ++ ++/** (n) Indicates that the interface is up */ ++#define IFF_UP 0x1 ++/** (i) Indicates that the broadcast address valid */ ++#define IFF_BROADCAST 0x2 ++/** (n) Turns on debugging */ ++#define IFF_DEBUG 0x4 ++/** (i) A loopback net */ ++#define IFF_LOOPBACK 0x8 ++/** (i) Indicates a point-to-point link */ ++#define IFF_POINTOPOINT 0x10 ++/* 0x20 was IFF_SMART */ ++/** (d) Indicates that the resources are allocated */ ++#define IFF_DRV_RUNNING 0x40 ++/** (n) No address resolution protocol */ ++#define IFF_NOARP 0x80 ++/** (n) Receive all packets */ ++#define IFF_PROMISC 0x100 ++/** (n) Receive all multicast packets */ ++#define IFF_ALLMULTI 0x200 ++/** (d) Indicates that the tx hardware queue is full */ ++#define IFF_DRV_OACTIVE 0x400 ++ /** (i) Cannot hear own transmissions */ ++#define IFF_SIMPLEX 0x800 ++/** Per link layer defined bit */ ++#define IFF_LINK0 0x1000 ++/** Per link layer defined bit */ ++#define IFF_LINK1 0x2000 ++/** Per link layer defined bit */ ++#define IFF_LINK2 0x4000 ++/** Use alternate physical connection */ ++#define IFF_ALTPHYS IFF_LINK2 ++/** Supports multicast */ ++#define IFF_MULTICAST 0x8000 ++ /** (i) Unconfigurable using ioctl(2) */ ++#define IFF_CANTCONFIG 0x10000 ++/** (n) User-requested promisc mode */ ++#define IFF_PPROMISC 0x20000 ++/** (n) User-requested IFF_MONITOR mode */ ++#define IFF_MONITOR 0x40000 ++ /** (n) Static ARP */ ++#define IFF_STATICARP 0x80000 ++/** (n) Interface is winding down */ ++#define IFF_DYING 0x200000 ++/** (n) Interface is being renamed */ ++#define IFF_RENAMING 0x400000 ++/** (n) Dialup device with changing addresses */ ++#define IFF_DYNAMIC 0x800000 ++/** (n) Dialup device with changing addresses */ ++#define IFF_DYNAMIC_S 0x1000000 ++ ++#define IFF_RUNNING IFF_DRV_RUNNING ++ ++#ifndef IFNAMSIZ ++#define IFNAMSIZ NETIF_NAMESIZE ++#endif ++ ++struct ifreq { ++#define IFHWADDRLEN 6 ++ union { ++ char ifrn_name[IFNAMSIZ]; ++ } ifr_ifrn; ++ union { ++ struct sockaddr ifru_addr; ++ struct sockaddr ifru_dstaddr; ++ struct sockaddr ifru_broadaddr; ++ struct sockaddr ifru_netmask; ++ struct sockaddr ifru_hwaddr; ++ short ifru_flags[2]; ++ int ifru_ivalue; ++ int ifru_mtu; ++ char ifru_slave[IFNAMSIZ]; ++ char ifru_newname[IFNAMSIZ]; ++ void *ifru_data; ++ } ifr_ifru; ++}; ++#define ifr_name ifr_ifrn.ifrn_name ++#define ifr_hwaddr ifr_ifru.ifru_hwaddr ++#define ifr_addr ifr_ifru.ifru_addr ++#define ifr_dstaddr ifr_ifru.ifru_dstaddr ++#define ifr_broadaddr ifr_ifru.ifru_broadaddr ++#define ifr_netmask ifr_ifru.ifru_netmask ++#define ifr_flags ifr_ifru.ifru_flags[0] /* flags (low 16 bits) */ ++#define ifr_flagshigh ifr_ifru.ifru_flags[1] /* flags (high 16 bits) */ ++#define ifr_metric ifr_ifru.ifru_ivalue ++#define ifr_mtu ifr_ifru.ifru_mtu ++#define ifr_slave ifr_ifru.ifru_slave ++#define ifr_data ifr_ifru.ifru_data ++#define ifr_ifindex ifr_ifru.ifru_ivalue ++#define ifr_bandwidth ifr_ifru.ifru_ivalue ++#define ifr_qlen ifr_ifru.ifru_ivalue ++#define ifr_newname ifr_ifru.ifru_newname ++#define ifr_index ifr_ifindex ++ ++struct ifconf { ++ int ifc_len; ++ union { ++ char *ifcu_buf; ++ struct ifreq *ifcu_req; ++ } ifc_ifcu; ++}; ++ ++#define ifc_buf ifc_ifcu.ifcu_buf ++#define ifc_req ifc_ifcu.ifcu_req ++ ++struct ifaddrs { ++ struct ifaddrs *ifa_next; /**< Pointer to the next network interfaces.f */ ++ char *ifa_name; /**< Pointer to the name of the network interfaces */ ++ unsigned int ifa_flags; /**< Pointer to the status flag. */ ++ struct sockaddr *ifa_addr; /**< Pointer to the address. */ ++ struct sockaddr *ifa_netmask; /**< Pointer to the net masking. */ ++ struct sockaddr *ifa_dstaddr; /**< Pointer to the destination address. */ ++ void *ifa_data; /**< Pointer to the data. */ ++}; ++ ++ #ifndef ifa_broadaddr ++ #define ifa_broadaddr ifa_dstaddr /* brcast address interface */ ++#endif ++ ++struct rtentry { ++ struct sockaddr rt_dst; /**< Indicates the target address. */ ++ struct sockaddr rt_gateway; /**< Indicates the gateway address (RTF_GATEWAY). */ ++ struct sockaddr rt_genmask; /**< Indicates the target network mask (IP). */ ++ unsigned int rt_flags; ++}; ++/** Indicates that the route is usable */ ++#define RTF_UP 0x1 ++/** Indicates that the destination is a gateway */ ++#define RTF_GATEWAY 0x2 ++/** Indicates the host entry (net otherwise) */ ++#define RTF_HOST 0x4 ++/** Indicates the host or net is unreachable */ ++#define RTF_REJECT 0x8 ++/** Created dynamically (by redirect) */ ++#define RTF_DYNAMIC 0x10 ++/** Modified dynamically (by redirect) */ ++#define RTF_MODIFIED 0x20 ++/** Message confirmed. */ ++#define RTF_DONE 0x40 ++/* 0x80 unused, was RTF_DELCLONE */ ++/* 0x100 unused, was RTF_CLONING */ ++/** Indicates that the external daemon resolves name */ ++#define RTF_XRESOLVE 0x200 ++/** DEPRECATED - exists ONLY for backward ++ compatibility */ ++#define RTF_LLINFO 0x400 ++/** Used by apps to add/del L2 entries */ ++#define RTF_LLDATA 0x400 ++/** Manually added */ ++#define RTF_STATIC 0x800 ++ /** Discard packets */ ++#define RTF_BLACKHOLE 0x1000 ++/** Protocol specific routing flag */ ++#define RTF_PROTO2 0x4000 ++/** Protocol specific routing flag */ ++/* 0x10000 unused, was RTF_PRCLONING */ ++#define RTF_PROTO1 0x8000 ++/* 0x10000 unused, was RTF_PRCLONING */ ++/* 0x20000 unused, was RTF_WASCLONED */ ++/** Protocol specific routing flag */ ++#define RTF_PROTO3 0x40000 ++/** MTU was explicitly specified */ ++#define RTF_FIXEDMTU 0x80000 ++/** Route is immutable */ ++#define RTF_PINNED 0x100000 ++/** Route represents a local address */ ++#define RTF_LOCAL 0x200000 ++/** Route represents a broadcast address */ ++#define RTF_BROADCAST 0x400000 ++ /** Route represents a multicast address */ ++#define RTF_MULTICAST 0x800000 ++ /* 0x8000000 and up unassigned */ ++/** Always route dst->src */ ++#define RTF_STICKY 0x10000000 ++/** Radix node head is locked */ ++#define RTF_RNH_LOCKED 0x40000000 ++/** Indicates the compatibility bit for interacting ++ with existing routing apps */ ++#define RTF_GWFLAG_COMPAT 0x80000000 ++ ++/* Mask of RTF flags that are allowed to be modified by RTM_CHANGE. */ ++#define RTF_FMASK \ ++ (RTF_PROTO1 | RTF_PROTO2 | RTF_PROTO3 | RTF_BLACKHOLE | \ ++ RTF_REJECT | RTF_STATIC | RTF_STICKY) ++ ++/** ++* @defgroup ifaddrs_api ifaddrs API ++* This section contains the interfaces to get information about Network interfaces in lwIP. ++* @ingroup socket ++*/ ++ ++/* ++Func Name: lwip_getifaddrs ++*/ ++ ++/** ++* @ingroup ifaddrs_api ++* @brief Creates a linked list of struct ifaddrs, which holds the information ++* about the network interfaces of the local system. The ifa_next field contains a ++* pointer to the next structure on the list, or NULL if this is the last item of the list. ++* The ifa_name points to the null-terminated interface name. The ifa_flags field ++* contains the interface flags. The ifa_addr field points to a structure containing ++* the interface address. The ifa_netmask field points to a structure containing ++* the netmask associated with ifa_addr, if applicable, for the address family. ++* Depending on whether the bit IFF_brcast or IFF_POINTOPOINT is set ++* in ifa_flags (only one can be set at a time), either ifa_broadaddr will contain ++* the broadcast address associated with ifa_addr (if applicable for the address ++* family) or ifa_dstaddr will contain the destination address of the point-to-point ++* interface. ++* For IPv6, stack supports only IFF_UP,IFF_MULTICAST, IFF_DRV_RUNNING, and IFF_LOOPBACK ++* flags. ++* @param[in] ifap Indicates a double pointer to the ifaddrs structure. ++* @return ++* On success, lwip_getifaddrs() returns zero; on error, -1 is returned, and errno is set appropriately. ++* @par Errors ++* @li The lwip_getifaddrs() function shall fail if: ++* - [EACCES] : \n Invalid state of system. ++* - [ENOMEM] : \n In-sufficient memory. ++* @note ++* None ++*/ ++int lwip_getifaddrs(struct ifaddrs **ifap); ++ ++/* ++Func Name: lwip_freeifaddrs ++*/ ++ ++/** ++* @ingroup ifaddrs_api ++* @brief The function lwip_freeifaddrs, provides the list of network interfaces in the ifaddrs* structure. ++* The application has to free the memory of the ifaddrs * structure by using this function. ++* @param[in] ifa Indicates a pointer to the ifaddrs structure. ++* @return ++* Void ++* @note ++* None ++*/ ++void lwip_freeifaddrs(struct ifaddrs *ifa); ++ ++#endif /* !LWIP_LITEOS_COMPAT */ ++int get_ipv6_ifaddr(struct netif *netif, struct ifaddrs *ifaddr, int tmp_index); ++int get_ipv4_ifaddr(struct netif *netif, struct ifaddrs *ifaddr); ++struct ifaddrs_storage *new_ifaddrs_storage(void); ++#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 2022-02-16 16:06:59.190115000 +0800 ++++ b/lwip-2.1.2/src/netif/ethernet.c 2022-01-26 06:47:42.000000000 +0800 +@@ -48,7 +48,7 @@ + #include "lwip/etharp.h" + #include "lwip/ip.h" + #include "lwip/snmp.h" +- ++#include "lwip/raw.h" + #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 @@ + } + } + ++#if PF_PACKET_SOCKET ++ p->flags = (u16_t)(p->flags & ~PBUF_FLAG_OUTGOING); ++ if (get_packet_raw_pcbs() != NULL) { ++ raw_packet_input(p, netif, NULL); ++ } ++#endif /* PF_PACKET_SOCKET */ + 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-29 07:46:14.000000000 +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 + /** -- Gitee From b49a08bc770b05e3fe20bb9e659a7c629e7d8fe0 Mon Sep 17 00:00:00 2001 From: Terder-su Date: Wed, 16 Feb 2022 09:22:49 +0000 Subject: [PATCH 03/14] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20co?= =?UTF-8?q?mponents/net/lwip/patch.sha256?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/lwip/patch.sha256 | 1 - 1 file changed, 1 deletion(-) delete mode 100644 components/net/lwip/patch.sha256 diff --git a/components/net/lwip/patch.sha256 b/components/net/lwip/patch.sha256 deleted file mode 100644 index 2711946..0000000 --- a/components/net/lwip/patch.sha256 +++ /dev/null @@ -1 +0,0 @@ -371f2079cd65ea018f5b3bf8638f8644cc82396b2801267c7d6eb0e67b31e3e4 origin.patch -- Gitee From 6becaeb6dc0cd25fb69b71ce59208d3f0b6fb762 Mon Sep 17 00:00:00 2001 From: Terder-su Date: Wed, 16 Feb 2022 09:23:03 +0000 Subject: [PATCH 04/14] update patch.sha256 --- components/net/lwip/patch.sha256 | 1 + 1 file changed, 1 insertion(+) create mode 100644 components/net/lwip/patch.sha256 diff --git a/components/net/lwip/patch.sha256 b/components/net/lwip/patch.sha256 new file mode 100644 index 0000000..ce66a54 --- /dev/null +++ b/components/net/lwip/patch.sha256 @@ -0,0 +1 @@ +4848d0862f749d465d8fe8dd3cc7bffd8d668369982f1f6724fa8e934ebdf6b2 origin.patch -- Gitee From 9fdbedbe771e90378fd6b0178e2cfeaa45e6c495 Mon Sep 17 00:00:00 2001 From: Terder-su Date: Thu, 17 Feb 2022 08:29:35 +0000 Subject: [PATCH 05/14] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20co?= =?UTF-8?q?mponents/net/lwip/origin.patch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/lwip/origin.patch | 8508 ------------------------------ 1 file changed, 8508 deletions(-) delete mode 100644 components/net/lwip/origin.patch diff --git a/components/net/lwip/origin.patch b/components/net/lwip/origin.patch deleted file mode 100644 index 53bd155..0000000 --- a/components/net/lwip/origin.patch +++ /dev/null @@ -1,8508 +0,0 @@ -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 2022-02-16 16:06:59.162116000 +0800 -+++ b/lwip-2.1.2/src/api/api_lib.c 2022-01-28 11:50:38.000000000 +0800 -@@ -146,7 +146,7 @@ - * NULL on memory error - */ - struct netconn * --netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) -+netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, netconn_callback callback) - { - struct netconn *conn; - API_MSG_VAR_DECLARE(msg); -@@ -292,6 +292,37 @@ - return err; - } - -+#if PF_PACKET_SOCKET -+/** -+ * Get the local or remote IP address and port of a netconn. -+ * For pf packet netconns, this returns the struct pf_packet_sockaddr_ll of the netconn! -+ * @param conn the netconn to query -+ * @param local 1 to get the local IP address, 0 to get the remote one -+ * @return ERR_CONN for invalid connections -+ * ERR_OK if the information was retrieved -+ * ERR_OPNOTSUPP if the option is not support -+ */ -+err_t -+netconn_get_sockaddr_pf_packet(struct netconn *conn, struct pf_packet_sockaddr_ll *ll, u8_t local) -+{ -+ err_t err; -+ API_MSG_VAR_DECLARE(msg); -+ API_MSG_VAR_ALLOC(msg); -+ API_MSG_VAR_REF(msg).conn = conn; -+ API_MSG_VAR_REF(msg).msg.adpkt.local = local; -+#if LWIP_MPU_COMPATIBLE -+ err = netconn_apimsg(lwip_netconn_do_getaddr_pfpkt, &API_MSG_VAR_REF(msg)); -+ *ll = msg->msg.adpkt.ll; -+#else /* LWIP_MPU_COMPATIBLE */ -+ API_MSG_VAR_REF(msg).msg.adpkt.ll = ll; -+ err = netconn_apimsg(lwip_netconn_do_getaddr_pfpkt, &msg); -+#endif /* LWIP_MPU_COMPATIBLE */ -+ API_MSG_VAR_FREE(msg); -+ -+ return err; -+} -+#endif -+ - /** - * @ingroup netconn_common - * Bind a netconn to a specific local IP address and port. -@@ -304,9 +335,13 @@ - * @return ERR_OK if bound, any other err_t on failure - */ - err_t -+#if PF_PACKET_SOCKET -+netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port, u8_t if_idx) -+#else /* PF_PACKET_SOCKET */ - netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port) -+#endif - { -- API_MSG_VAR_DECLARE(msg); -+ API_MSG_VAR_DECLARE(msg); /* struct api_msg *msg */ - err_t err; - - LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); -@@ -332,6 +367,9 @@ - API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); - API_MSG_VAR_REF(msg).msg.bc.port = port; -+#if PF_PACKET_SOCKET -+ API_MSG_VAR_REF(msg).msg.bc.if_idx = if_idx; -+#endif /* PF_PACKET_SOCKET */ - err = netconn_apimsg(lwip_netconn_do_bind, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - -@@ -596,7 +634,7 @@ - - NETCONN_MBOX_WAITING_INC(conn); - if (netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK) || -- (conn->flags & NETCONN_FLAG_MBOXCLOSED) || (conn->pending_err != ERR_OK)) { -+ (conn->flags & NETCONN_FLAG_MBOXCLOSED)) { - 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; - } - SYS_ARCH_PROTECT(lev); -- err = conn->pending_err; -- conn->pending_err = ERR_OK; -+ err = conn->last_err; - SYS_ARCH_UNPROTECT(lev); - 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 2022-02-16 16:06:59.162116000 +0800 -+++ b/lwip-2.1.2/src/api/api_msg.c 2022-01-28 12:10:58.000000000 +0800 -@@ -184,10 +184,36 @@ - return 0; - } - -+#if PF_PACKET_SOCKET -+ /* To get the pkt type filtered in ethernet_input */ -+ q->flags = p->flags; -+#if ETH_PAD_SIZE -+ /* exclude the begining two padding bytes in struct eth_hdr */ -+ if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_PACKET_RAW) && (pbuf_header(q, -ETH_PAD_SIZE))) { -+ (void)pbuf_free(q); -+ memp_free(MEMP_NETBUF, buf); -+ return 0; -+ } -+#endif -+#endif -+ - buf->p = q; - buf->ptr = q; -+#if PF_PACKET_SOCKET -+ /* IP addr is NULL only when RAW packets are received for PF_PACKET sockets */ -+ if (addr == NULL) { -+ ip_addr_set_any(IP_IS_V6_VAL(buf->addr), &buf->addr); -+ buf->port = eth_current_hdr()->type; -+ buf->hatype = eth_current_netif()->link_layer_type; -+ buf->netifindex = eth_current_netif()->ifindex; -+ } else { -+ ip_addr_copy(buf->addr, *ip_current_src_addr()); -+ buf->port = pcb->raw_proto; -+ } -+#else - ip_addr_copy(buf->addr, *ip_current_src_addr()); - buf->port = pcb->protocol; -+#endif - - len = q->tot_len; - if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { -@@ -444,7 +470,7 @@ - /* when err is called, the pcb is deallocated, so delete the reference */ - conn->pcb.tcp = NULL; - /* store pending error */ -- conn->pending_err = err; -+ conn->last_err = err; - /* prevent application threads from blocking on 'recvmbox'/'acceptmbox' */ - conn->flags |= NETCONN_FLAG_MBOXCLOSED; - -@@ -627,23 +653,41 @@ - if (msg->conn->pcb.raw != NULL) { - #if LWIP_IPV6 - /* ICMPv6 packets should always have checksum calculated by the stack as per RFC 3542 chapter 3.1 */ -- if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->protocol == IP6_NEXTH_ICMP6) { -+ if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->raw_proto == IP6_NEXTH_ICMP6) { - msg->conn->pcb.raw->chksum_reqd = 1; - msg->conn->pcb.raw->chksum_offset = 2; - } - #endif /* LWIP_IPV6 */ -+ -+#if LWIP_IPV4 -+ /* IP_HDRINCL is enabled by default */ -+ if (!(NETCONNTYPE_ISIPV6(msg->conn->type)) && (msg->msg.n.proto == IPPROTO_RAW)) { -+ raw_set_flags(msg->conn->pcb.raw, RAW_FLAGS_HDRINCL); -+ } -+#endif - raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); - } - break; -+ -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+ msg->conn->pcb.packet_raw = raw_packet_new(msg->msg.n.proto); -+ if (msg->conn->pcb.packet_raw == NULL) { -+ msg->err = ERR_MEM; -+ break; -+ } -+ raw_recv(msg->conn->pcb.packet_raw, recv_raw, msg->conn); -+ break; -+#endif - #endif /* LWIP_RAW */ - #if LWIP_UDP -- case NETCONN_UDP: -- msg->conn->pcb.udp = udp_new_ip_type(iptype); -- if (msg->conn->pcb.udp != NULL) { -+ case NETCONN_UDP: -+ msg->conn->pcb.udp = udp_new_ip_type(iptype); -+ if (msg->conn->pcb.udp != NULL) { - #if LWIP_UDPLITE -- if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { -- udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); -- } -+ if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { -+ udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); -+ } - #endif /* LWIP_UDPLITE */ - if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) { - udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); -@@ -683,7 +727,7 @@ - - msg->err = ERR_OK; - if (msg->conn->pcb.tcp == NULL) { -- pcb_new(msg); -+ pcb_new(msg); //raw_recv() - } - /* Else? This "new" connection already has a PCB allocated. */ - /* Is this an error condition? Should it be deleted? */ -@@ -713,13 +757,16 @@ - return NULL; - } - -- conn->pending_err = ERR_OK; -+ conn->last_err = ERR_OK; - conn->type = t; - conn->pcb.tcp = NULL; - - /* If all sizes are the same, every compiler should optimize this switch to nothing */ - switch (NETCONNTYPE_GROUP(t)) { - #if LWIP_RAW -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+#endif - case NETCONN_RAW: - size = DEFAULT_RAW_RECVMBOX_SIZE; - break; -@@ -778,8 +825,17 @@ - conn->linger = -1; - #endif /* LWIP_SO_LINGER */ - conn->flags = init_flags; -+#if LWIP_TCP -+ conn->pending_err = 0; -+ conn->refused_data = NULL; -+ ip_addr_set_zero(&conn->remote_ip); -+ conn->remote_port = 0; -+#endif - return conn; - free_and_return: -+ if (sys_sem_valid(&conn->op_completed) != 0) { -+ sys_sem_free(&conn->op_completed); -+ } - memp_free(MEMP_NETCONN, conn); - return NULL; - } -@@ -1160,6 +1216,11 @@ - case NETCONN_RAW: - raw_remove(msg->conn->pcb.raw); - break; -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+ raw_packet_remove(msg->conn->pcb.packet_raw); -+ break; -+#endif - #endif /* LWIP_RAW */ - #if LWIP_UDP - case NETCONN_UDP: -@@ -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)) || -+ ip_addr_ismulticast(API_EXPR_REF(msg->msg.bc.ipaddr)) || -+ netif_ipaddr_isbrdcast(API_EXPR_REF(msg->msg.bc.ipaddr)) || -+ ((netif != NULL) && netif_is_up(netif)))) { -+ msg->err = ERR_NOADDR; -+ } else -+#endif -+ { -+ msg->err = ERR_VAL; -+ if (msg->conn->pcb.tcp != NULL) { -+ switch (NETCONNTYPE_GROUP(msg->conn->type)) { - #if LWIP_RAW - case NETCONN_RAW: -- err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); -+ msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); -+ break; -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+ msg->err = raw_packet_bind(msg->conn->pcb.packet_raw, msg->msg.bc.if_idx, msg->msg.bc.port); - break; -+#endif - #endif /* LWIP_RAW */ - #if LWIP_UDP - case NETCONN_UDP: -- err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); -+ msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); - break; - #endif /* LWIP_UDP */ - #if LWIP_TCP - case NETCONN_TCP: -- err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); -+ if (msg->conn->pcb.tcp->local_port == 0) { -+ msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); -+ } else { -+ msg->err = ERR_VAL; -+ } -+ - break; - #endif /* LWIP_TCP */ - default: -- err = ERR_VAL; -+ msg->err = ERR_OPNOTSUPP; - break; -+ } - } -- } else { -- err = ERR_VAL; - } -- msg->err = err; - TCPIP_APIMSG_ACK(msg); - } - /** -@@ -1351,6 +1435,11 @@ - { - struct api_msg *msg = (struct api_msg *)m; - err_t err; -+ if (ERR_IS_FATAL(msg->conn->last_err)) { -+ msg->err = msg->conn->last_err; -+ TCPIP_APIMSG_ACK(msg); -+ return; -+ } - - if (msg->conn->pcb.tcp == NULL) { - /* This may happen when calling netconn_connect() a second time */ -@@ -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)) { -+#if PF_PACKET_SOCKET -+ struct ip_hdr *iphdr = NULL; -+ ip_addr_t dest_addr; -+ -+ if (!(msg->conn->pcb.raw->flags & RAW_FLAGS_CONNECTED) || -+ ip_addr_isany(&msg->conn->pcb.raw->remote_ip)) { -+ if (raw_is_flag_set(msg->conn->pcb.raw, RAW_FLAGS_HDRINCL)) { -+ if (msg->msg.b->p->len < IP_HLEN) { -+ err = ERR_MSGSIZE; -+ break; -+ } -+ -+ /* IP header already included in p */ -+ iphdr = (struct ip_hdr *)msg->msg.b->p->payload; -+ ip_addr_copy_from_ip4(dest_addr, iphdr->dest); -+ err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &dest_addr); -+ break; -+ } -+ -+ err = ERR_NODEST; -+ break; -+ } -+#endif /* PF_PACKET_SOCKET */ - err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); - } else { - err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr); - } - break; -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+ /* Check if its for sending RAW packets for PF_PACKET family */ -+ if (msg->msg.b->flags & NETBUF_FLAG_IFINDEX) { -+ err = raw_packet_sendto(msg->conn->pcb.packet_raw, msg->msg.b->p, msg->msg.b->netifindex); -+ } else { -+ err = raw_packet_sendto(msg->conn->pcb.packet_raw, msg->msg.b->p, 0); -+ } -+ break; -+#endif - #endif - #if LWIP_UDP - case NETCONN_UDP: -@@ -1868,6 +1990,11 @@ - { - struct api_msg *msg = (struct api_msg *)m; - -+ if ((msg->conn == NULL) || (msg->conn->pcb.tcp == NULL)) { -+ msg->err = ERR_CONN; -+ TCPIP_APIMSG_ACK(msg); -+ return; -+ } - if (msg->conn->pcb.ip != NULL) { - if (msg->msg.ad.local) { - ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), -@@ -1882,10 +2009,18 @@ - #if LWIP_RAW - case NETCONN_RAW: - if (msg->msg.ad.local) { -- API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; -+ ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), -+ msg->conn->pcb.raw->local_ip); -+ API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->raw_proto; - } else { -- /* return an error as connecting is only a helper for upper layers */ -- msg->err = ERR_CONN; -+ if (raw_is_flag_set(msg->conn->pcb.raw, RAW_FLAGS_CONNECTED)) { -+ ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), -+ msg->conn->pcb.raw->remote_ip); -+ API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->raw_proto; -+ } else { -+ /* return an error as connecting is only a helper for upper layers */ -+ msg->err = ERR_CONN; -+ } - } - break; - #endif /* LWIP_RAW */ -@@ -1923,6 +2058,47 @@ - TCPIP_APIMSG_ACK(msg); - } - -+#if PF_PACKET_SOCKET -+/** -+ * Return a pf pkt socket's local address -+ * Called from netconn_getaddr -+ * -+ * @param m the api_msg pointing to the connection -+ */ -+void -+lwip_netconn_do_getaddr_pfpkt(void *m) -+{ -+ struct api_msg *msg = (struct api_msg *)m; -+ struct pf_packet_sockaddr_ll ll; -+ msg->err = ERR_OK; -+ if (msg->conn->pcb.ip != NULL) { -+ /* Non standard way of do it, but doing it :( */ -+ if (msg->msg.adpkt.local) { -+ ll.sll_protocol = msg->conn->pcb.packet_raw->proto.eth_proto; -+ ll.if_idx = msg->conn->pcb.packet_raw->netifindex; -+ struct netif *netif = netif_find_by_ifindex(msg->conn->pcb.packet_raw->netifindex); -+ if (netif == NULL) { -+ LWIP_DEBUGF(SOCKETS_DEBUG, -+ ("lwip_getaddrname:netif not found for given ifindex (%u)\n", -+ msg->conn->pcb.packet_raw->netifindex)); -+ ll.sll_halen = 0; -+ ll.sll_hatype = 0; -+ } else { -+ ll.sll_hatype = netif->link_layer_type; -+ ll.sll_halen = NETIF_MAX_HWADDR_LEN; -+ (void)memcpy_s(ll.sll_addr, ll.sll_halen, netif->hwaddr, NETIF_MAX_HWADDR_LEN); -+ } -+ API_EXPR_DEREF(msg->msg.adpkt.ll) = ll; -+ } else { -+ msg->err = ERR_OPNOTSUPP; -+ } -+ } else { -+ msg->err = ERR_CONN; -+ } -+ TCPIP_APIMSG_ACK(msg); -+} -+#endif -+ - /** - * 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 2022-02-16 16:06:59.162116000 +0800 -+++ b/lwip-2.1.2/src/api/netbuf.c 2022-01-26 06:41:32.000000000 +0800 -@@ -48,7 +48,7 @@ - - #include "lwip/netbuf.h" - #include "lwip/memp.h" -- -+#include "lwip/api.h" - #include - - /** -@@ -99,7 +99,7 @@ - * NULL if no memory could be allocated - */ - void * --netbuf_alloc(struct netbuf *buf, u16_t size) -+netbuf_alloc(struct netbuf *buf, u16_t size, u8_t netconn_type) - { - LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); - -@@ -107,7 +107,22 @@ - if (buf->p != NULL) { - pbuf_free(buf->p); - } -- buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); -+ -+ switch (netconn_type) { -+#if LWIP_RAW -+ case NETCONN_RAW: -+ buf->p = pbuf_alloc(PBUF_IP, size, PBUF_RAM); -+ break; -+#endif /* LWIP_RAW */ -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+ buf->p = pbuf_alloc(PBUF_LINK, size, PBUF_RAM); -+ break; -+#endif /* PF_PACKET_SOCKET */ -+ default: -+ buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); -+ } -+ - if (buf->p == NULL) { - 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 2022-02-16 16:06:59.162116000 +0800 -+++ b/lwip-2.1.2/src/api/netdb.c 2022-01-29 08:53:10.000000000 +0800 -@@ -58,7 +58,7 @@ - - /** h_errno is exported in netdb.h for access by applications. */ - #if LWIP_DNS_API_DECLARE_H_ERRNO --int h_errno; -+int h_err_no; - #endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ - - /** define "hostent" variables storage: 0 if we use a static (but unprotected) -@@ -100,7 +100,7 @@ - err = netconn_gethostbyname(name, &addr); - if (err != ERR_OK) { - LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); -- h_errno = HOST_NOT_FOUND; -+ h_err_no = HOST_NOT_FOUND; - return NULL; - } - -@@ -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; -+#if defined(SIN6_LEN) - sa6->sin6_len = sizeof(struct sockaddr_in6); -+#endif -+ sa6->sin6_flowinfo = 0; - sa6->sin6_port = lwip_htons((u16_t)port_nr); - sa6->sin6_scope_id = ip6_addr_zone(ip_2_ip6(&addr)); - ai->ai_family = AF_INET6; -+ ai->ai_addrlen = sizeof(struct sockaddr_in6); - #endif /* LWIP_IPV6 */ - } else { - #if LWIP_IPV4 -@@ -385,9 +394,9 @@ - /* set up sockaddr */ - inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr)); - sa4->sin_family = AF_INET; -- sa4->sin_len = sizeof(struct sockaddr_in); - sa4->sin_port = lwip_htons((u16_t)port_nr); - ai->ai_family = AF_INET; -+ ai->ai_addrlen = sizeof(struct sockaddr_in); - #endif /* LWIP_IPV4 */ - } - -@@ -403,7 +412,6 @@ - MEMCPY(ai->ai_canonname, nodename, namelen); - ai->ai_canonname[namelen] = 0; - } -- ai->ai_addrlen = sizeof(struct sockaddr_storage); - ai->ai_addr = (struct sockaddr *)sa; - - *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 2022-02-16 16:06:59.162116000 +0800 -+++ b/lwip-2.1.2/src/api/netifapi.c 2022-01-26 07:39:08.000000000 +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) - -+#if LWIP_MPU_COMPATIBLE -+static inline err_t netifapi_msg_alloc(struct netifapi_msg **name) -+{ -+ API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, (*name), ERR_MEM); -+ LWIP_UNUSED_ARG(name); -+ return ERR_OK; -+} -+#else -+static inline err_t netifapi_msg_alloc(struct netifapi_msg *name) -+{ -+ LWIP_UNUSED_ARG(name); -+ return ERR_OK; -+} -+#endif -+ - /** - * Call netif_add() inside the tcpip_thread context. - */ -@@ -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, -- msg->msg.add.input)) { -+ msg->msg.add_get.init, -+ msg->msg.add_get.input)) { - return ERR_IF; - } else { - return ERR_OK; -@@ -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; -- NETIFAPI_VAR_REF(msg).msg.add.init = init; -- NETIFAPI_VAR_REF(msg).msg.add.input = input; -+ NETIFAPI_VAR_REF(msg).msg.add_get.init = init; -+ NETIFAPI_VAR_REF(msg).msg.add_get.input = input; - err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call); - NETIFAPI_VAR_FREE(msg); - return err; -@@ -377,4 +395,60 @@ - return err; - } - -+/** -+ * Call netif_find() inside the tcpip_thread context. -+ */ -+static err_t -+do_netifapi_netif_find_by_name(struct tcpip_api_call_data *m) -+{ -+ struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; -+ -+ msg->netif = netif_find(msg->msg.find_by_name.name); -+ return ERR_OK; -+} -+ -+struct netif* -+netifapi_netif_find_by_name(const char *name) -+{ -+ struct netif *netif = NULL; -+ NETIFAPI_VAR_DECLARE(msg); -+ if (netifapi_msg_alloc(&msg) != ERR_OK) { -+ return NULL; -+ } -+ -+ NETIFAPI_VAR_REF(msg).netif = NULL; -+ NETIFAPI_VAR_REF(msg).msg.find_by_name.name = name; -+ (void)tcpip_api_call(do_netifapi_netif_find_by_name, &API_VAR_REF(msg).call); -+ netif = NETIFAPI_VAR_REF(msg).netif; -+ NETIFAPI_VAR_FREE(msg); -+ return netif; -+} -+ -+/** -+ * Call netif_find_by_ipaddr() inside the tcpip_thread context. -+ */ -+static err_t -+do_netifapi_netif_find_by_ipaddr(struct tcpip_api_call_data *m) -+{ -+ struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; -+ msg->netif = netif_find_by_ipaddr(msg->msg.find_by_ipaddr.ipaddr); -+ return ERR_OK; -+} -+ -+struct netif * -+netifapi_netif_find_by_ipaddr(const ip_addr_t *ipaddr) -+{ -+ struct netif *netif = NULL; -+ NETIFAPI_VAR_DECLARE(msg); -+ if (netifapi_msg_alloc(&msg) != ERR_OK) { -+ return NULL; -+ } -+ -+ NETIFAPI_VAR_REF(msg).netif = NULL; -+ NETIFAPI_VAR_REF(msg).msg.find_by_ipaddr.ipaddr = ipaddr; -+ (void)tcpip_api_call(do_netifapi_netif_find_by_ipaddr, &API_VAR_REF(msg).call); -+ netif = NETIFAPI_VAR_REF(msg).netif; -+ NETIFAPI_VAR_FREE(msg); -+ return netif; -+} - #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 2022-02-16 16:06:59.162116000 +0800 -+++ b/lwip-2.1.2/src/api/sockets.c 2022-01-29 09:25:30.000000000 +0800 -@@ -54,6 +54,7 @@ - #include "lwip/netif.h" - #include "lwip/priv/tcpip_priv.h" - #include "lwip/mld6.h" -+#include "lwip/dhcp.h" - #if LWIP_CHECKSUM_ON_COPY - #include "lwip/inet_chksum.h" - #endif -@@ -85,9 +86,19 @@ - #define API_SELECT_CB_VAR_ALLOC(name, retblock) API_VAR_ALLOC_EXT(struct lwip_select_cb, MEMP_SELECT_CB, name, retblock) - #define API_SELECT_CB_VAR_FREE(name) API_VAR_FREE(MEMP_SELECT_CB, name) - -+#if !LWIP_LITEOS_COMPAT -+#defeine SIN4_LEN(x) \ -+ (x)->sin_len = sizeof(struct sockaddr_in) -+#defeine SIN6_LEN(x) \ -+ (x)->sin6_len = sizeof(struct sockaddr_in6) -+#else -+#define SIN4_LEN(x) -+#define SIN6_LEN(x) -+#endif /* LWIP_LITEOS_COMPAT */ -+ - #if LWIP_IPV4 - #define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \ -- (sin)->sin_len = sizeof(struct sockaddr_in); \ -+ SIN4_LEN(sin); \ - (sin)->sin_family = AF_INET; \ - (sin)->sin_port = lwip_htons((port)); \ - inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \ -@@ -98,8 +109,10 @@ - #endif /* LWIP_IPV4 */ - - #if LWIP_IPV6 -+/* SIN6_LEN macro is to differntiate whether stack is using 4.3BSD or 4.4BSD variants of sockaddr_in6 -+structure */ - #define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \ -- (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ -+ SIN6_LEN(sin6); \ - (sin6)->sin6_family = AF_INET6; \ - (sin6)->sin6_port = lwip_htons((port)); \ - (sin6)->sin6_flowinfo = 0; \ -@@ -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) - -+#if LWIP_LITEOS_COMPAT -+#define VALIDATE_GET_RAW_OPTNAME_RET(_sock, _optname) do { \ -+ if ((_sock)->conn != NULL && (NETCONNTYPE_GROUP((_sock)->conn->type) == NETCONN_RAW) && \ -+ (((_optname) != SO_BROADCAST) && ((_optname) != SO_RCVTIMEO) && \ -+ ((_optname) != SO_RCVBUF) && ((_optname) != SO_TYPE) && \ -+ ((_optname) != SO_DONTROUTE) && ((_optname) != SO_BINDTODEVICE))) { \ -+ done_socket(_sock); \ -+ return ENOPROTOOPT; \ -+ } \ -+ } while (0) -+ -+#if PF_PACKET_SOCKET -+#define VALIDATE_SET_PF_PKT_OPTNAME_RET(_s, _sock, _level, _optname) do { \ -+ if ((_level) == SOL_PACKET && ((_optname) != SO_RCVTIMEO && (_optname) != SO_RCVBUF) && \ -+ (_optname) != SO_ATTACH_FILTER && (_optname) != SO_DETACH_FILTER) { \ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_PACKET, UNIMPL: optname=0x%x, ..)\n", \ -+ (_s), (_optname))); \ -+ done_socket(_sock); \ -+ return ENOPROTOOPT; \ -+ } \ -+ } while (0) -+ -+#define VALIDATE_GET_PF_PKT_OPTNAME_RET(_s,_sock,_level,_optname) do { \ -+ if ((_sock)->conn != NULL && (NETCONNTYPE_GROUP((_sock)->conn->type) == NETCONN_PACKET_RAW) && \ -+ (_level) == SOL_PACKET && ((_optname) != SO_RCVTIMEO && (_optname) != SO_RCVBUF && (_optname) != SO_TYPE)) { \ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%p, SOL_PACKET, UNIMPL: optname=0x%x, ..)\n", \ -+ (_s), (_optname))); \ -+ done_socket(_sock); \ -+ return ENOPROTOOPT; \ -+ } \ -+ } while (0) -+ -+#define VALIDATE_LEVEL_PF_PACKET(_sock,_level) \ -+ if ((_sock)->conn != NULL && ((NETCONNTYPE_GROUP(netconn_type(_sock->conn)) == NETCONN_PACKET_RAW \ -+ && SOL_SOCKET != (_level) && SOL_PACKET != (_level)) || \ -+ (NETCONNTYPE_GROUP((_sock)->conn->type) != NETCONN_PACKET_RAW && SOL_PACKET == (_level)))) -+#endif -+#endif /* LWIP_LITEOS_COMPAT */ -+ - /* 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 +564,29 @@ - return sock; - } - -+#if LWIP_LITEOS_COMPAT -+/* get numbers of unused sockets */ -+int get_unused_socket_num(void) -+{ -+ int unused = 0, i; -+ SYS_ARCH_DECL_PROTECT(lev); -+ SYS_ARCH_PROTECT(lev); -+ -+ for (i = 0; i < (int)(NUM_SOCKETS); i++) { -+ if (!sockets[i].conn -+#if LWIP_NETCONN_FULLDUPLEX -+ && !sockets[i].fd_used -+#endif -+ ) { -+ unused++; -+ } -+ } -+ -+ SYS_ARCH_UNPROTECT(lev); -+ return unused; -+} -+#endif /* LWIP_LITEOS_COMPAT */ -+ - /** - * Allocate a new socket for a given netconn. - * -@@ -696,8 +794,10 @@ - } - - IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); -- if (*addrlen > tempaddr.sa.sa_len) { -- *addrlen = tempaddr.sa.sa_len; -+ if (IP_IS_V4_VAL(naddr) && (*addrlen > (int)sizeof(struct sockaddr_in))) { -+ *addrlen = sizeof(struct sockaddr_in); -+ } else if (IP_IS_V6_VAL(naddr) && (*addrlen > (int)sizeof(struct sockaddr_in6))) { -+ *addrlen = sizeof(struct sockaddr_in6); - } - MEMCPY(addr, &tempaddr, *addrlen); - -@@ -722,28 +822,59 @@ - u16_t local_port; - err_t err; - -+#if PF_PACKET_SOCKET -+ const struct sockaddr_ll *name_ll = NULL; -+ u8_t local_if_idx = 0; -+#endif - sock = get_socket(s); - if (!sock) { - return -1; - } - -- if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { -- /* sockaddr does not match socket type (IPv4/IPv6) */ -- sock_set_errno(sock, err_to_errno(ERR_VAL)); -- done_socket(sock); -- return -1; -- } -- - /* check size, family and alignment of 'name' */ -- LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && -+#if PF_PACKET_SOCKET -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { -+ name_ll = (const struct sockaddr_ll *)(void*)name; -+ LWIP_ERROR("lwip_bind: invalid address", ((name_ll != NULL)&&(namelen == sizeof(struct sockaddr_ll)) && -+ ((name_ll->sll_family) == PF_PACKET) && IS_SOCK_ADDR_ALIGNED(name) && -+ (name_ll->sll_ifindex <= LWIP_NETIF_IFINDEX_MAX)), sock_set_errno(sock, err_to_errno(ERR_VAL)); -+ done_socket(sock); return -1); -+ -+ ip_addr_set_any_val(IPADDR_TYPE_V4, local_addr); -+ local_port = name_ll->sll_protocol; -+ local_if_idx = (u8_t)name_ll->sll_ifindex; -+ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, ", s)); -+ LWIP_DEBUGF(SOCKETS_DEBUG, (" ifindex=%u proto=%"U16_F")\n", local_if_idx, local_port)); -+ } else -+#endif -+ { -+ 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); -+ -+ if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { -+ /* sockaddr does not match socket type (IPv4/IPv6) */ -+ sock_set_errno(sock, err_to_errno(ERR_VAL)); -+ done_socket(sock); -+ return -1; -+ } -+ -+ /* check size, family and alignment of 'name' */ -+ LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && - IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)), - sock_set_errno(sock, err_to_errno(ERR_ARG)); done_socket(sock); return -1;); -- LWIP_UNUSED_ARG(namelen); -+ LWIP_UNUSED_ARG(namelen); - -- SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); -- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); -- ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); -- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); -+ SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); -+ ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); -+ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); -+ } - - #if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ -@@ -753,7 +884,11 @@ - } - #endif /* LWIP_IPV4 && LWIP_IPV6 */ - -+#if PF_PACKET_SOCKET -+ err = netconn_bind(sock->conn, &local_addr, local_port, local_if_idx); -+#else /* PF_PACKET_SOCKET */ - err = netconn_bind(sock->conn, &local_addr, local_port); -+#endif - - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); -@@ -820,6 +955,14 @@ - return -1; - } - -+#if PF_PACKET_SOCKET -+ if (NETCONN_PACKET_RAW & NETCONNTYPE_GROUP(netconn_type(sock->conn))) { -+ sock_set_errno(sock, EOPNOTSUPP); -+ done_socket(sock); -+ return -1; -+ } -+#endif -+ - 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 +1168,7 @@ - { - int truncated = 0; - union sockaddr_aligned saddr; -+ socklen_t sa_len; - - LWIP_UNUSED_ARG(conn); - -@@ -1041,10 +1185,27 @@ - #endif /* LWIP_IPV4 && LWIP_IPV6 */ - - IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port); -- if (*fromlen < saddr.sa.sa_len) { -+#if LWIP_LITEOS_COMPAT -+ if (IP_IS_V4_VAL(*fromaddr)) { -+ sa_len = sizeof(struct sockaddr_in); -+ } -+#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 */ -+ -+ if (*fromlen < sa_len) { - truncated = 1; -- } else if (*fromlen > saddr.sa.sa_len) { -- *fromlen = saddr.sa.sa_len; -+ } else if (*fromlen > sa_len) { -+ *fromlen = sa_len; - } - MEMCPY(from, &saddr, *fromlen); - return truncated; -@@ -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) { -- lwip_sock_make_addr(sock->conn, netbuf_fromaddr(buf), netbuf_fromport(buf), -- (struct sockaddr *)msg->msg_name, &msg->msg_namelen); -+#if PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT -+ struct sockaddr_ll sll; -+ -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { -+ if (msg->msg_namelen > sizeof(sll)) { -+ msg->msg_namelen = sizeof(sll); -+ } -+ -+ if (msg->msg_namelen) { -+ (void)memset_s(&sll, sizeof(sll), 0, sizeof(sll)); -+ sll.sll_family = PF_PACKET; -+ sll.sll_protocol = netbuf_fromport(buf); -+ sll.sll_hatype = netbuf_fromhatype(buf); -+ sll.sll_ifindex = netbuf_fromifindex(buf); -+ -+ if (buf->p->flags & PBUF_FLAG_LLBCAST) { -+ sll.sll_pkttype = PACKET_BROADCAST; -+ } else if (buf->p->flags & PBUF_FLAG_LLMCAST) { -+ sll.sll_pkttype = PACKET_MULTICAST; -+ } else if (buf->p->flags & PBUF_FLAG_HOST) { -+ sll.sll_pkttype = PACKET_HOST; -+ } else if (buf->p->flags & PBUF_FLAG_OUTGOING) { -+ sll.sll_pkttype = PACKET_OUTGOING; -+ } else { -+ sll.sll_pkttype = PACKET_OTHERHOST; -+ } -+ -+ (void)memcpy_s(msg->msg_name, msg->msg_namelen, (void *)&sll, msg->msg_namelen); -+ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom_udp_raw(%d): hatype=%u", dbg_s, ntohs(sll.sll_hatype))); -+ LWIP_DEBUGF(SOCKETS_DEBUG, (" packet type = %u\n", sll.sll_pkttype)); -+ } -+ } else -+#endif /* PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT */ -+ { -+ lwip_sock_make_addr(sock->conn, netbuf_fromaddr(buf), netbuf_fromport(buf), -+ (struct sockaddr *)msg->msg_name, &msg->msg_namelen); -+ } - } - } -+ - - /* 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. */ -- if (netbuf_alloc(&chain_buf, (u16_t)size) == NULL) { -+ if (netbuf_alloc(&chain_buf, (u16_t)size, NETCONNTYPE_GROUP(netconn_type(sock->conn))) == NULL) { - err = ERR_MEM; - } else { - /* flatten the IO vectors */ -@@ -1588,8 +1784,14 @@ - struct lwip_sock *sock; - err_t err; - u16_t short_size; -- u16_t remote_port; -+ u16_t remote_port = 0; - struct netbuf buf; -+#if (PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT) -+ const struct sockaddr_ll *to_ll = NULL; -+#endif -+ const struct sockaddr_in *to_in = NULL; -+ -+ unsigned int acceptable_flags = 0; - - sock = get_socket(s); - if (!sock) { -@@ -1608,11 +1810,62 @@ - #endif /* LWIP_TCP */ - } - -- if (size > LWIP_MIN(0xFFFF, SSIZE_MAX)) { -- /* cannot fit into one datagram (at least for us) */ -- sock_set_errno(sock, EMSGSIZE); -- done_socket(sock); -- return -1; -+#if PF_PACKET_SOCKET -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { -+ to_ll = (const struct sockaddr_ll *)(void *)to; -+ -+ LWIP_ERROR("lwip_sendto: invalid address", (((data != NULL) && (size!=0)) && -+ (((to_ll != NULL) && (tolen == sizeof(struct sockaddr_ll))) && -+ ((to_ll->sll_family) == PF_PACKET) && ((((mem_ptr_t)to_ll) % 4) == 0)) && -+ (to_ll->sll_ifindex <= LWIP_NETIF_IFINDEX_MAX)), -+ sock_set_errno(sock, err_to_errno(ERR_VAL)); -+ done_socket(sock); return -1); -+ -+ LWIP_ERROR("lwip_sendto: invalid address family", ((to_ll->sll_family) == PF_PACKET), -+ sock_set_errno(sock, err_to_errno(ERR_AFNOSUPP)); -+ done_socket(sock); return -1); -+ -+ LWIP_ERROR("lwip_sendto: invalid flags. Should be 0", (flags == 0), -+ sock_set_errno(sock, err_to_errno(ERR_OPNOTSUPP)); -+ done_socket(sock); return -1); -+ -+ if (size > LWIP_MAX_PF_RAW_SEND_SIZE) { -+ sock_set_errno(sock, EMSGSIZE); -+ done_socket(sock); -+ return -1; -+ } -+ } else -+#endif /* PF_PACKET_SOCKET */ -+ { -+ to_in = (const struct sockaddr_in *)(void*)to; -+ acceptable_flags = acceptable_flags | MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL; -+ if ((~acceptable_flags) & (unsigned int)flags) { -+ sock_set_errno(sock, err_to_errno(ERR_OPNOTSUPP)); -+ done_socket(sock); -+ return -1; -+ } -+ -+ LWIP_ERROR("lwip_sendto: invalid address", ((data != NULL) && (size!=0) && (flags>=0)), -+ sock_set_errno(sock, err_to_errno(ERR_VAL)); -+ done_socket(sock); return -1); -+ -+ LWIP_ERROR("lwip_sendto: invalid address", (((to_in == NULL) && (tolen == 0)) || -+ (((to_in == NULL) && (tolen != 0)) || IS_SOCK_ADDR_LEN_VALID(tolen))), -+ sock_set_errno(sock, err_to_errno(ERR_VAL)); -+ done_socket(sock); -+ return -1); -+ -+ LWIP_ERROR("lwip_sendto: invalid address", (to == NULL || IS_SOCK_ADDR_TYPE_VALID(to)), -+ sock_set_errno(sock, err_to_errno(ERR_AFNOSUPPORT)); -+ done_socket(sock); -+ return -1); -+ -+ if (size > LWIP_MAX_UDP_RAW_SEND_SIZE) { -+ sock_set_errno(sock, EMSGSIZE); -+ done_socket(sock); -+ return -1; -+ } -+ - } - short_size = (u16_t)size; - LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || -@@ -1626,6 +1879,9 @@ - #if LWIP_CHECKSUM_ON_COPY - buf.flags = 0; - #endif /* LWIP_CHECKSUM_ON_COPY */ -+#if PF_PACKET_SOCKET -+ buf.netifindex = 0; -+#endif - if (to) { - SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port); - } else { -@@ -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)); -- ip_addr_debug_print_val(SOCKETS_DEBUG, buf.addr); -- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); -- -+#if PF_PACKET_SOCKET -+ if (buf.flags & NETBUF_FLAG_IFINDEX) { -+ LWIP_DEBUGF(SOCKETS_DEBUG, (" netifindex = %d\n", buf.netifindex)); -+ } else -+#endif -+ { -+ ip_addr_debug_print_val(SOCKETS_DEBUG, buf.addr); -+ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); -+ } - /* make the buffer point to the data that should be sent */ - #if LWIP_NETIF_TX_SINGLE_PBUF - /* Allocate a new netbuf and copy the data into it. */ -- if (netbuf_alloc(&buf, short_size) == NULL) { -+ if (netbuf_alloc(&buf, short_size, NETCONNTYPE_GROUP(netconn_type(sock->conn))) == NULL) { - err = ERR_MEM; - } else { - #if LWIP_CHECKSUM_ON_COPY -- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { -+#if PF_PACKET_SOCKET -+ if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_PACKET_RAW) && -+ (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW)) -+#else -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) -+#endif -+ { - u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); - netbuf_set_chksum(&buf, chksum); - } else -@@ -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: -- conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), -- (u8_t)protocol, DEFAULT_SOCKET_EVENTCB); -- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", -+#if PF_PACKET_SOCKET -+ if (domain == PF_PACKET) { -+ conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_PACKET_RAW), -+ (u16_t)protocol, event_callback); -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", "PF_PACKET", protocol)); -+ } else -+#endif -+ { -+ conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), -+ (u8_t)protocol, DEFAULT_SOCKET_EVENTCB); -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", - domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); -+ } - break; - case SOCK_DGRAM: - conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, -@@ -1983,10 +2269,11 @@ - timeout ? (s32_t)timeout->tv_sec : (s32_t) - 1, - timeout ? (s32_t)timeout->tv_usec : (s32_t) - 1)); - -- if ((maxfdp1 < 0) || (maxfdp1 > LWIP_SELECT_MAXNFDS)) { -+/*if ((maxfdp1 < 0) || (maxfdp1 > LWIP_SELECT_MAXNFDS)) { - set_errno(EINVAL); - return -1; - } -+ */ - - lwip_select_inc_sockets_used(maxfdp1, readset, writeset, exceptset, &used_sockets); - -@@ -2704,12 +2991,60 @@ - ip_addr_t naddr; - u16_t port; - err_t err; -+ socklen_t sa_len; -+ -+#if PF_PACKET_SOCKET -+ struct sockaddr_ll addr_sin; -+ struct pf_packet_sockaddr_ll sll; -+ socklen_t outlen; -+#endif -+ -+ LWIP_ERROR("lwip_getaddrname: invalid arguments", ((name != NULL) && (namelen != NULL)), -+ set_errno(EINVAL); return -1); - - sock = get_socket(s); - if (!sock) { - return -1; - } - -+#if PF_PACKET_SOCKET -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_PACKET_RAW) { -+ err = netconn_get_sockaddr_pf_packet(sock->conn, &sll, local); -+ if (err != ERR_OK) { -+ sock_set_errno(sock, err_to_errno(err)); -+ done_socket(sock); -+ return -1; -+ } -+ -+ (void)memset_s(&addr_sin, sizeof(struct sockaddr_ll), 0, sizeof(struct sockaddr_ll)); -+ addr_sin.sll_family = PF_PACKET; -+ addr_sin.sll_protocol = sll.sll_protocol; -+ addr_sin.sll_pkttype = 0; -+ addr_sin.sll_ifindex = sll.if_idx; -+ addr_sin.sll_hatype = sll.sll_hatype; -+ addr_sin.sll_halen = sll.sll_halen; -+ -+ if ((sll.sll_halen > 0) && (memcpy_s(addr_sin.sll_addr, addr_sin.sll_halen, sll.sll_addr, sll.sll_halen) != EOK)) { -+ sock_set_errno(sock, err_to_errno(ERR_MEM)); -+ done_socket(sock); -+ return -1; -+ } -+ -+ outlen = sizeof(struct sockaddr_ll); -+ if (outlen > *namelen) { -+ outlen = *namelen; -+ } -+ if (memcpy_s(name, *namelen, &addr_sin, outlen) != EOK) { -+ sock_set_errno(sock, err_to_errno(ERR_MEM)); -+ done_socket(sock); -+ return -1; -+ } -+ *namelen = outlen; -+ done_socket(sock); -+ return 0; -+ } -+#endif /* PF_PACKET_SOCKET */ -+ - /* get the IP address and port */ - err = netconn_getaddr(sock->conn, &naddr, &port, local); - if (err != ERR_OK) { -@@ -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)); -+ if (IP_IS_V4_VAL(naddr)) { -+ sa_len = sizeof(struct sockaddr_in); -+ } else { -+ sa_len = sizeof(struct sockaddr_in6); -+ } - -- if (*namelen > saddr.sa.sa_len) { -- *namelen = saddr.sa.sa_len; -+ if (*namelen > sa_len) { -+ *namelen = sa_len; - } - MEMCPY(name, &saddr, *namelen); - -@@ -2775,6 +3115,14 @@ - return -1; - } - -+#if PF_PACKET_SOCKET -+ VALIDATE_LEVEL_PF_PACKET(sock, level) { -+ sock_set_errno(sock, EINVAL); -+ done_socket(sock); -+ return -1; -+ } -+#endif /* PF_PACKET_SOCKET */ -+ - #if LWIP_TCPIP_CORE_LOCKING - /* core-locking can just call the -impl function */ - LOCK_TCPIP_CORE(); -@@ -2826,8 +3174,9 @@ - err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; - LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); - #endif /* LWIP_TCPIP_CORE_LOCKING */ -- -- sock_set_errno(sock, err); -+ if (err != ERR_OK) { -+ sock_set_errno(sock, err); -+ } - done_socket(sock); - return err ? -1 : 0; - } -@@ -2897,6 +3246,11 @@ - - /* Level: SOL_SOCKET */ - case SOL_SOCKET: -+#if PF_PACKET_SOCKET -+ case SOL_PACKET: -+ VALIDATE_GET_PF_PKT_OPTNAME_RET(s, sock, level, optname); -+#endif /* PF_PACKET_SOCKET */ -+ VALIDATE_GET_RAW_OPTNAME_RET(sock, optname); - switch (optname) { - - #if LWIP_TCP -@@ -2920,6 +3274,10 @@ - #if SO_REUSE - case SO_REUSEADDR: - #endif /* SO_REUSE */ -+ if (sock->conn == NULL) { -+ done_socket(sock); -+ return EINVAL; -+ } - if ((optname == SO_BROADCAST) && - (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP)) { - done_socket(sock); -@@ -2937,6 +3295,9 @@ - case SO_TYPE: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); - switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) { -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+#endif - case NETCONN_RAW: - *(int *)optval = SOCK_RAW; - break; -@@ -2948,9 +3309,16 @@ - break; - default: /* unrecognized socket type */ - *(int *)optval = netconn_type(sock->conn); -+#if PF_PACKET_SOCKET -+ LWIP_DEBUGF(SOCKETS_DEBUG, -+ ("lwip_getsockopt(%d, %s, SO_TYPE): unrecognized socket type %d\n", -+ s, (NETCONN_PACKET_RAW != NETCONNTYPE_GROUP(sock->conn->type)) ? "SOL_SOCKET" : "SOL_PACKET", -+ *(int *)optval)); -+#else - LWIP_DEBUGF(SOCKETS_DEBUG, - ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", - s, *(int *)optval)); -+#endif - } /* switch (netconn_type(sock->conn)) */ - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", - s, *(int *)optval)); -@@ -3739,92 +4107,450 @@ - return err; - } - --int --lwip_ioctl(int s, long cmd, void *argp) -+#if PF_PACKET_SOCKET || LOSCFG_COMPONENTS_UPNP -+#if LWIP_IOCTL_IF -+static u8_t lwip_ioctl_internal_SIOCGIFCONF(struct ifreq *ifr) -+{ -+ struct ifconf *ifc = NULL; -+ struct netif *netif = NULL; -+ struct ifreq ifreq; -+ struct sockaddr_in *sock_in = NULL; -+ int pos; -+ int len; -+ int ret; -+ -+ /* Format the caller's buffer. */ -+ ifc = (struct ifconf*)ifr; -+ len = ifc->ifc_len; -+ -+ /* Loop over the interfaces, and write an info block for each. */ -+ pos = 0; -+ for (netif = netif_list; netif != NULL; netif = netif->next) { -+ if (ifc->ifc_buf == NULL) { -+ pos = (pos + (int)sizeof(struct ifreq)); -+ continue; -+ } -+ -+ if (len < (int)sizeof(ifreq)) { -+ break; -+ } -+ -+ if (memset_s(&ifreq, sizeof(struct ifreq), 0, sizeof(struct ifreq)) != EOK) { -+ return ENOBUFS; -+ } -+ if (netif->link_layer_type == LOOPBACK_IF) { -+ ret = snprintf_s(ifreq.ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s", netif->name); -+ if ((ret <= 0) || (ret >= IFNAMSIZ)) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed.")); -+ return ENOBUFS; -+ } -+ } else { -+ ret = snprintf_s(ifreq.ifr_name, NETIF_NAMESIZE, NETIF_NAMESIZE - 1, "%s%"U8_F, netif->name, netif->num); -+ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed.")); -+ return ENOBUFS; -+ } -+ } -+ -+ sock_in = (struct sockaddr_in *)&ifreq.ifr_addr; -+ sock_in->sin_family = AF_INET; -+ sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr; -+ if (memcpy_s(ifc->ifc_buf + pos, sizeof(struct ifreq), &ifreq, sizeof(struct ifreq)) != EOK) { -+ return ENOBUFS; -+ } -+ pos += (int)sizeof(struct ifreq); -+ len -= (int)sizeof(struct ifreq); -+ } -+ -+ ifc->ifc_len = pos; -+ -+ return 0; -+} -+ -+static u8_t lwip_ioctl_internal_SIOCGIFADDR(struct ifreq *ifr) -+{ -+ struct netif *netif = NULL; -+ struct sockaddr_in *sock_in = NULL; -+ -+ /* get netif ipaddr */ -+ netif = netif_find(ifr->ifr_name); -+ if (netif == NULL) { -+ return ENODEV; -+ } else { -+ sock_in = (struct sockaddr_in *)&ifr->ifr_addr; -+ sock_in->sin_family = AF_INET; -+ sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr; -+ return 0; -+ } -+} -+ -+static u8_t lwip_ioctl_internal_SIOCSIFFLAGS(const struct ifreq *ifr) -+{ -+ struct netif *netif = NULL; -+ -+ /* set netif hw addr */ -+ netif = netif_find(ifr->ifr_name); -+ if (netif == NULL) { -+ return ENODEV; -+ } -+#if LWIP_HAVE_LOOPIF -+ else if (netif->link_layer_type == LOOPBACK_IF) { -+ return EPERM; -+ } -+#endif /* LWIP_HAVE_LOOPIF */ -+ else { -+ if ((ifr->ifr_flags & IFF_UP) && !(netif->flags & NETIF_FLAG_UP)) { -+ (void)netif_set_up(netif); -+ } else if (!(ifr->ifr_flags & IFF_UP) && (netif->flags & NETIF_FLAG_UP)) { -+ (void)netif_set_down(netif); -+ } -+ if ((ifr->ifr_flags & IFF_RUNNING) && !(netif->flags & NETIF_FLAG_LINK_UP)) { -+ (void)netif_set_link_up(netif); -+ } else if (!(ifr->ifr_flags & IFF_RUNNING) && (netif->flags & NETIF_FLAG_LINK_UP)) { -+ (void)netif_set_link_down(netif); -+ } -+ -+ if (ifr->ifr_flags & IFF_BROADCAST) { -+ netif->flags |= NETIF_FLAG_BROADCAST; -+ } else { -+ netif->flags = netif->flags & (~NETIF_FLAG_BROADCAST); -+ } -+ if (ifr->ifr_flags & IFF_NOARP) { -+ netif->flags = (netif->flags & (~NETIF_FLAG_ETHARP)); -+ } else { -+ netif->flags |= NETIF_FLAG_ETHARP; -+ } -+ -+ if (ifr->ifr_flags & IFF_MULTICAST) { -+#if LWIP_IGMP -+ netif->flags |= NETIF_FLAG_IGMP; -+#endif /* LWIP_IGMP */ -+#if LWIP_IPV6 && LWIP_IPV6_MLD -+ netif->flags |= NETIF_FLAG_MLD6; -+#endif /* LWIP_IPV6_MLD */ -+ } -+ else { -+#if LWIP_IGMP -+ netif->flags = (netif->flags & ~NETIF_FLAG_IGMP); -+#endif /* LWIP_IGMP */ -+#if LWIP_IPV6 && LWIP_IPV6_MLD -+ netif->flags = (netif->flags & ~NETIF_FLAG_MLD6); -+#endif /* LWIP_IPV6_MLD */ -+ } -+ -+#if 0 -+ if (ifr->ifr_flags & IFF_DYNAMIC) { -+ (void)dhcp_start(netif); -+ } else { -+ dhcp_stop(netif); -+ dhcp_cleanup(netif); -+ } -+#endif -+ -+ return 0; -+ } -+} -+ -+static u8_t lwip_ioctl_internal_SIOCGIFFLAGS(struct ifreq *ifr) -+{ -+ struct netif *netif = NULL; -+ -+ /* set netif hw addr */ -+ netif = netif_find(ifr->ifr_name); -+ if (netif == NULL) { -+ return ENODEV; -+ } else { -+ if (netif->flags & NETIF_FLAG_UP) { -+ ifr->ifr_flags |= IFF_UP; -+ } else { -+ ifr->ifr_flags &= ~IFF_UP; -+ } -+ if (netif->flags & NETIF_FLAG_LINK_UP) { -+ ifr->ifr_flags |= IFF_RUNNING; -+ } else { -+ ifr->ifr_flags &= ~IFF_RUNNING; -+ } -+ if (netif->flags & NETIF_FLAG_BROADCAST) { -+ ifr->ifr_flags |= IFF_BROADCAST; -+ } else { -+ ifr->ifr_flags &= ~IFF_BROADCAST; -+ } -+ if (netif->flags & NETIF_FLAG_ETHARP) { -+ ifr->ifr_flags &= ~IFF_NOARP; -+ } else { -+ ifr->ifr_flags |= IFF_NOARP; -+ } -+ -+#if LWIP_IGMP || LWIP_IPV6_MLD -+ if ( -+#if LWIP_IGMP -+ (netif->flags & NETIF_FLAG_IGMP) -+#endif /* LWIP_IGMP */ -+#if LWIP_IGMP && LWIP_IPV6_MLD -+ || -+#endif /* LWIP_IGMP && LWIP_IPV6_MLD */ -+#if LWIP_IPV6_MLD -+ (netif->flags & NETIF_FLAG_MLD6) -+#endif /* LWIP_IPV6_MLD */ -+ ) { -+ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_MULTICAST); -+ } else { -+ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_MULTICAST)); -+ } -+#endif /* LWIP_IGMP || LWIP_IPV6_MLD */ -+ -+#if LWIP_DHCP -+ if (netif->flags & NETIF_FLAG_DHCP) { -+ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_DYNAMIC); -+ } else { -+ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_DYNAMIC)); -+ } -+#endif -+ -+#if LWIP_HAVE_LOOPIF -+ if (netif->link_layer_type == LOOPBACK_IF) { -+ ifr->ifr_flags |= IFF_LOOPBACK; -+ } -+#endif -+ -+ return 0; -+ } -+} -+ -+static u8_t lwip_ioctl_internal_SIOCGIFNAME(struct ifreq *ifr) -+{ -+ struct netif *netif = NULL; -+ int ret; -+ -+ for (netif = netif_list; netif != NULL; netif = netif->next) { -+ if (ifr->ifr_ifindex == netif->ifindex) { -+ break; -+ } -+ } -+ -+ if (netif == NULL) { -+ return ENODEV; -+ } -+ if (netif->link_layer_type == LOOPBACK_IF) { -+ ret = snprintf_s(ifr->ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s", netif->name); -+ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { -+ return ENOBUFS; -+ } -+ } else { -+ ret = snprintf_s(ifr->ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s%"U8_F, netif->name, netif->num); -+ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { -+ return ENOBUFS; -+ } -+ } -+ return 0; -+} -+ -+static u8_t lwip_ioctl_internal_SIOCGIFINDEX(struct ifreq *ifr) -+{ -+ struct netif *netif = NULL; -+ netif = netif_find(ifr->ifr_name); -+ if (netif == NULL) { -+ return ENODEV; -+ } -+ ifr->ifr_ifindex = netif->ifindex; -+ return 0; -+} -+#endif /* LWIP_IOCTL_IF */ -+#endif /* PF_PACKET_SOCKET */ -+ -+#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE -+static u8_t lwip_ioctl_internal_FIONREAD(struct lwip_sock *sock, void *argp) - { -- struct lwip_sock *sock = get_socket(s); -- u8_t val; - #if LWIP_SO_RCVBUF - int recv_avail; --#endif /* LWIP_SO_RCVBUF */ -+#endif -+#if LWIP_FIONREAD_LINUXMODE -+ SYS_ARCH_DECL_PROTECT(lev); -+#endif - -- if (!sock) { -- return -1; -+ if (!argp) { -+ return EINVAL; - } - -- switch (cmd) { --#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE -- case FIONREAD: -- if (!argp) { -- sock_set_errno(sock, EINVAL); -- done_socket(sock); -- return -1; -- } -+ lwip_sock_lock(sock); - #if LWIP_FIONREAD_LINUXMODE -- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { -- struct netbuf *nb; -- if (sock->lastdata.netbuf) { -- nb = sock->lastdata.netbuf; -- *((int *)argp) = nb->p->tot_len; -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { -+ struct netbuf *nb; -+ if (sock->lastdata.netbuf) { -+ nb = sock->lastdata.netbuf; -+ *((int *)argp) = nb->p->tot_len; -+ } else { -+ struct netbuf *rxbuf; -+ err_t err; -+ -+ SYS_ARCH_PROTECT(lev); -+ if (sock->rcvevent <= 0) { -+ *((int*)argp) = 0; -+ SYS_ARCH_UNPROTECT(lev); -+ } else { -+ SYS_ARCH_UNPROTECT(lev); -+ err = netconn_recv_udp_raw_netbuf_flags(sock->conn, &rxbuf, NETCONN_DONTBLOCK); -+ if (err != ERR_OK) { -+ *((int *)argp) = 0; - } else { -- struct netbuf *rxbuf; -- err_t err = netconn_recv_udp_raw_netbuf_flags(sock->conn, &rxbuf, NETCONN_DONTBLOCK); -- if (err != ERR_OK) { -- *((int *)argp) = 0; -- } else { -- sock->lastdata.netbuf = rxbuf; -- *((int *)argp) = rxbuf->p->tot_len; -- } -+ sock->lastdata.netbuf = rxbuf; -+ *((int *)argp) = rxbuf->p->tot_len; - } -- done_socket(sock); -- return 0; - } -+ } -+ -+ lwip_sock_unlock(sock); -+ return 0; -+ } - #endif /* LWIP_FIONREAD_LINUXMODE */ - - #if LWIP_SO_RCVBUF -- /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ -- SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); -- if (recv_avail < 0) { -- recv_avail = 0; -- } -+ /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ -+ SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); -+ if (recv_avail < 0) { -+ recv_avail = 0; -+ } - -- /* Check if there is data left from the last recv operation. /maq 041215 */ -- if (sock->lastdata.netbuf) { -- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { -- recv_avail += sock->lastdata.pbuf->tot_len; -- } else { -- recv_avail += sock->lastdata.netbuf->p->tot_len; -- } -- } -- *((int *)argp) = recv_avail; -+ /* Check if there is data left from the last recv operation. /maq 041215 */ -+ if (sock->lastdata.netbuf) { -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { -+ recv_avail += sock->lastdata.pbuf->tot_len; -+ } else { -+ recv_avail += sock->lastdata.netbuf->p->tot_len; -+ } -+ } -+ *((int *)argp) = recv_avail; - -- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t *)argp))); -- sock_set_errno(sock, 0); -- done_socket(sock); -- return 0; -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(FIONREAD, %p) = %"U16_F"\n", argp, *((u16_t *)argp))); -+ lwip_sock_unlock(sock); -+ return 0; - #else /* LWIP_SO_RCVBUF */ -- break; -+ lwip_sock_unlock(sock); -+ return ENOSYS; - #endif /* LWIP_SO_RCVBUF */ -+} - #endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ - -- case (long)FIONBIO: -- val = 0; -- if (argp && *(int *)argp) { -- val = 1; -+static u8_t lwip_ioctl_internal_FIONBIO(struct lwip_sock *sock, const void *argp) -+{ -+ u8_t val = 0; -+ SYS_ARCH_DECL_PROTECT(lev); -+ if (argp == NULL) { -+ return EINVAL; -+ } -+ if (*(int *)argp) { -+ val = 1; -+ } -+ SYS_ARCH_PROTECT(lev); -+ netconn_set_nonblocking(sock->conn, val); -+ SYS_ARCH_UNPROTECT(lev); -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(FIONBIO, %d)\n", val)); -+ return 0; -+} -+ -+static u8_t lwip_ioctl_impl(struct lwip_sock *sock, long cmd, void *argp) -+{ -+ u8_t err = 0; -+#if LWIP_NETIF_ETHTOOL -+ s32_t ret; -+#endif -+#if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_IF || LWIP_NETIF_ETHTOOL -+ struct ifreq *ifr = (struct ifreq *)argp; -+#endif -+#if LWIP_IOCTL_ROUTE -+ struct rtentry *rmten = (struct rtentry *)argp; -+#endif -+#if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_ROUTE || LWIP_IOCTL_IF -+ u8_t is_ipv6 = NETCONNTYPE_ISIPV6(sock->conn->type); -+#endif -+ -+ LWIP_ASSERT("no socket given", sock != NULL); -+ -+ switch (cmd) { -+#if PF_PACKET_SOCKET || LOSCFG_COMPONENTS_UPNP -+#if LWIP_IOCTL_IF -+ case SIOCGIFCONF: -+ /* Do not allow if socket is AF_INET6 */ -+ if (is_ipv6) { -+ err = EINVAL; -+ } else { -+ err = lwip_ioctl_internal_SIOCGIFCONF(ifr); //add: SIOCGIFCONF - } -- netconn_set_nonblocking(sock->conn, val); -- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); -- sock_set_errno(sock, 0); -- done_socket(sock); -- return 0; -+ break; -+ case SIOCGIFADDR: -+ if (is_ipv6) { -+ err = EINVAL; -+ } else { -+ err = lwip_ioctl_internal_SIOCGIFADDR(ifr); //add: SIOCGIFADDR -+ } -+ break; -+ case SIOCSIFFLAGS: -+ err = lwip_ioctl_internal_SIOCSIFFLAGS(ifr); //add: SIOCSIFFLAGS -+ break; -+ case SIOCGIFFLAGS: -+ err = lwip_ioctl_internal_SIOCGIFFLAGS(ifr); //add: SIOCSIFFLAGS -+ break; -+ case SIOCGIFNAME: -+ err = lwip_ioctl_internal_SIOCGIFNAME(ifr); //add: SIOCGIFNAME -+ break; -+ /* Need to support the get index through ioctl -+ * As of now the options is restricted to PF_PACKET scenario , so removed the compiler flag Begin -+ */ -+ case SIOCGIFINDEX: -+ err = lwip_ioctl_internal_SIOCGIFINDEX(ifr); //add: SIOCGIFINDEX -+ break; -+#endif /* LWIP_IOCTL_IF */ -+#else -+ (void)ifr; -+ (void)is_ipv6; -+#endif /* PF_PACKET_SOCKET */ -+#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE -+ case FIONREAD: -+ err = lwip_ioctl_internal_FIONREAD(sock, argp); -+ break; -+#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ - -+ case FIONBIO: -+ err = lwip_ioctl_internal_FIONBIO(sock, argp); -+ break; -+ /* -1 should return EINVAL */ -+ case -1: -+ err = EINVAL; -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl_impl(INVALID: 0x%lx)\n", cmd)); -+ break; - default: -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(UNIMPL: 0x%lx, %p)\n", cmd, argp)); -+ err = ENOSYS; /* not yet implemented */ - break; - } /* switch (cmd) */ -- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); -- sock_set_errno(sock, ENOSYS); /* not yet implemented */ -+ -+ return err; -+} -+ -+int -+lwip_ioctl(int s, long cmd, void *argp) -+{ -+ u8_t err; -+ struct lwip_sock *sock = get_socket(s); -+ if (!sock) { -+ /* get_socket has updated errno */ -+ return -1; -+ } -+ if (argp == NULL) { -+ sock_set_errno(sock, EFAULT); -+ done_socket(sock); -+ return -1; -+ } -+ -+ LOCK_TCPIP_CORE(); -+ err = lwip_ioctl_impl(sock, cmd, argp); -+ UNLOCK_TCPIP_CORE(); -+ if (err != ERR_OK) { -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, cmd: 0x%lx, %p)\n", s, cmd, argp)); -+ sock_set_errno(sock, err); -+ } - done_socket(sock); -- return -1; -+ return (err == 0) ? 0 : -1; - } - - /** A minimal implementation of fcntl. -@@ -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; -- - break; - 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 2022-02-16 16:06:59.174115000 +0800 -+++ b/lwip-2.1.2/src/apps/tftp/tftp_server.c 2022-01-26 06:41:32.000000000 +0800 -@@ -201,7 +201,7 @@ - } - - static void --recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -+tftp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) - { - u16_t *sbuf = (u16_t *) p->payload; - int opcode; -@@ -416,7 +416,7 @@ - tftp_state.last_data = NULL; - tftp_state.upcb = pcb; - -- udp_recv(pcb, recv, NULL); -+ udp_recv(pcb, tftp_recv, NULL); - - 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-29 08:50:28.000000000 +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-26 06:55:38.000000000 +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 2022-02-16 16:06:59.174115000 +0800 -+++ b/lwip-2.1.2/src/core/ip.c 2022-01-29 09:08:50.000000000 +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) - { -- if (cp != NULL) { -+ if (cp != NULL && addr != NULL) { - const char *c; - for (c = cp; *c != 0; c++) { - if (*c == ':') { - /* contains a colon: IPv6 address */ -- if (addr) { -- IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); -- } -+ IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); - return ip6addr_aton(cp, ip_2_ip6(addr)); - } else if (*c == '.') { - /* contains a dot: IPv4 address */ -@@ -137,9 +147,7 @@ - } - } - /* call ip4addr_aton as fallback or if IPv4 was found */ -- if (addr) { -- IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); -- } -+ IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); - return ip4addr_aton(cp, ip_2_ip4(addr)); - } - return 0; -@@ -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 */ - -+struct netif* -+ip_route_pcb(const ip_addr_t *dest, const struct ip_pcb* pcb) -+{ -+ struct netif *netif = NULL; -+#if LWIP_SO_DONTROUTE -+ rt_scope_t scope = RT_SCOPE_UNIVERSAL; -+ -+ LWIP_ASSERT("Expecting ipaddr to be not NULL ", dest != NULL); -+ if (pcb != NULL) { -+ scope = ip_get_option(pcb, SOF_DONTROUTE) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSAL; -+ } -+#endif -+ -+ if ((pcb != NULL) && (pcb->netif_idx != NETIF_NO_INDEX)) { -+ return netif_find_by_ifindex(pcb->netif_idx); -+ } -+ -+ if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { -+ /* Don't call ip_route() with IP_ANY_TYPE */ -+ netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(dest)), dest); -+ } else { -+ netif = ip_route(&pcb->local_ip, dest); -+ } -+ -+ if (netif == NULL) { -+ return NULL; -+ } -+ -+#if LWIP_SO_DONTROUTE -+ if (netif->scope < scope) { -+ return NULL; -+ } -+#endif -+ return netif; -+} -+ -+#if LWIP_INET_ADDR_FUNC -+in_addr_t inet_addr(const char *cp) -+{ -+ LWIP_ERROR("inet_aton:cp is NULL", (cp != NULL), return (INADDR_NONE)); -+ return ipaddr_addr(cp); -+} -+#endif -+ -+#if LWIP_INET_ATON_FUNC -+int inet_aton(const char *cp, struct in_addr *inp) -+{ -+ LWIP_ERROR("inet_aton:cp is NULL", (cp != NULL), return 0); -+ return ip4addr_aton(cp, (ip4_addr_t *)inp); -+} -+#endif -+ -+#if LWIP_INET_NTOA_FUNC -+char* inet_ntoa(struct in_addr in) -+{ -+ return ip4addr_ntoa((const ip4_addr_t *)&in); -+} -+#endif -+ - #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 2022-02-16 16:06:59.174115000 +0800 -+++ b/lwip-2.1.2/src/core/ipv6/icmp6.c 2022-01-26 06:41:32.000000000 +0800 -@@ -82,14 +82,14 @@ - void - icmp6_input(struct pbuf *p, struct netif *inp) - { -- struct icmp6_hdr *icmp6hdr; -+ struct icmpv6_hdr *icmp6hdr; - struct pbuf *r; - const ip6_addr_t *reply_src; - - ICMP6_STATS_INC(icmp6.recv); - - /* Check that ICMPv6 header fits in payload */ -- if (p->len < sizeof(struct icmp6_hdr)) { -+ if (p->len < sizeof(struct icmpv6_hdr)) { - /* drop short packets */ - pbuf_free(p); - ICMP6_STATS_INC(icmp6.lenerr); -@@ -97,7 +97,7 @@ - return; - } - -- icmp6hdr = (struct icmp6_hdr *)p->payload; -+ icmp6hdr = (struct icmpv6_hdr *)p->payload; - - #if CHECKSUM_CHECK_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP6) { -@@ -386,10 +386,10 @@ - const ip6_addr_t *reply_src, const ip6_addr_t *reply_dest, struct netif *netif) - { - struct pbuf *q; -- struct icmp6_hdr *icmp6hdr; -+ struct icmpv6_hdr *icmp6hdr; - - /* ICMPv6 header + IPv6 header + data */ -- q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, -+ q = pbuf_alloc(PBUF_IP, sizeof(struct icmpv6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, - PBUF_RAM); - if (q == NULL) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n")); -@@ -397,15 +397,15 @@ - return; - } - LWIP_ASSERT("check that first pbuf can hold icmp 6message", -- (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); -+ (q->len >= (sizeof(struct icmpv6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); - -- icmp6hdr = (struct icmp6_hdr *)q->payload; -+ icmp6hdr = (struct icmpv6_hdr *)q->payload; - icmp6hdr->type = type; - icmp6hdr->code = code; - icmp6hdr->data = lwip_htonl(data); - - /* copy fields from original packet */ -- SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload, -+ SMEMCPY((u8_t *)q->payload + sizeof(struct icmpv6_hdr), (u8_t *)p->payload, - IP6_HLEN + LWIP_ICMP6_DATASIZE); - - /* 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 2022-02-16 16:06:59.174115000 +0800 -+++ b/lwip-2.1.2/src/core/ipv6/nd6.c 2022-01-26 06:41:32.000000000 +0800 -@@ -894,13 +894,13 @@ - } - case ICMP6_TYPE_PTB: /* Packet too big */ - { -- struct icmp6_hdr *icmp6hdr; /* Packet too big message */ -+ struct icmpv6_hdr *icmp6hdr; /* Packet too big message */ - struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */ - u32_t pmtu; - ip6_addr_t destination_address; - - /* Check that ICMPv6 header + IPv6 header fit in payload */ -- if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { -+ if (p->len < (sizeof(struct icmpv6_hdr) + IP6_HLEN)) { - /* drop short packets */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); -@@ -908,8 +908,8 @@ - return; - } - -- icmp6hdr = (struct icmp6_hdr *)p->payload; -- ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); -+ icmp6hdr = (struct icmpv6_hdr *)p->payload; -+ ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmpv6_hdr)); - - /* 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 2022-02-16 16:06:59.178115000 +0800 -+++ b/lwip-2.1.2/src/core/netif.c 2022-01-26 07:38:10.000000000 +0800 -@@ -89,6 +89,8 @@ - #if LWIP_IPV6 - #include "lwip/nd6.h" - #endif -+#include "lwip/tcpip.h" -+ - - #if LWIP_NETIF_STATUS_CALLBACK - #define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) -@@ -229,6 +231,8 @@ - return ip_input(p, inp); - } - -+static u8_t netif_alloc_ifindex(void); -+ - /** - * @ingroup netif - * Add a network interface to the list of lwIP netifs. -@@ -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 */ - -+ /* -+ * Need to support the get index for all families -+ * removed PF_PACKET_SOCKET flag , as this flags restricts the usage to only PF_FAMILY -+ */ -+ netif->ifindex = netif_alloc_ifindex(); -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif: netif->ifindex=%d", netif->ifindex)); -+ if ((netif->ifindex < LWIP_NETIF_IFINDEX_START) || (netif->ifindex > LWIP_NETIF_IFINDEX_MAX)) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif: interface index alloc fail")); -+ return NULL; -+ } -+ - #if !LWIP_SINGLE_NETIF - /* Assign a unique netif number in the range [0..254], so that (num+1) can - serve as an interface index that fits in a u8_t. - We assume that the new netif has not yet been added to the list here. - This algorithm is O(n^2), but that should be OK for lwIP. - */ -- { -- struct netif *netif2; -- int num_netifs; -- do { -- if (netif->num == 255) { -- netif->num = 0; -- } -- num_netifs = 0; -- for (netif2 = netif_list; netif2 != NULL; netif2 = netif2->next) { -- LWIP_ASSERT("netif already added", netif2 != netif); -- num_netifs++; -- LWIP_ASSERT("too many netifs, max. supported number is 255", num_netifs <= 255); -- if (netif2->num == netif->num) { -- netif->num++; -- break; -- } -- } -- } while (netif2 != NULL); -- } -- if (netif->num == 254) { -- netif_num = 0; -- } else { -- netif_num = (u8_t)(netif->num + 1); -- } - - /* add this netif to the list */ - netif->next = netif_list; -@@ -421,8 +428,8 @@ - } - #endif /* LWIP_IGMP */ - -- LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", -- netif->name[0], netif->name[1])); -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %s IP", -+ netif->name)); - #if LWIP_IPV4 - LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); - ip4_addr_debug_print(NETIF_DEBUG, ipaddr); -@@ -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 - */ --void -+err_t - netif_set_default(struct netif *netif) - { - LWIP_ASSERT_CORE_LOCKED(); -@@ -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] : '\'')); -+ return ERR_OK; - } - - /** -@@ -1206,6 +1279,11 @@ - struct netif *stats_if = netif; - #endif /* LWIP_HAVE_LOOPIF */ - #endif /* MIB2_STATS */ -+#if PF_PACKET_SOCKET -+ struct raw_pcb *pcb; -+ int match = 0; -+#endif /* PF_PACKET_SOCKET */ -+ - SYS_ARCH_DECL_PROTECT(lev); - - LWIP_ASSERT("netif_poll: invalid netif", netif != NULL); -@@ -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); -+ -+#if PF_PACKET_SOCKET -+ for (pcb = get_packet_raw_pcbs(); pcb != NULL; pcb = pcb->next) { -+ if (((pcb->proto.eth_proto == htons(ETHTYPE_ALL)) || (pcb->proto.eth_proto == htons(ETHTYPE_IP))) && -+ ((!pcb->netifindex) || (pcb->netifindex == netif->ifindex))) { -+ match = 1; -+ break; -+ } -+ } -+ -+ /* always succeed because the alloc layer of loopback pbuf was PBUF_LINK */ -+ if (match && pbuf_header(in, PBUF_LINK_HLEN) == 0) { -+ struct eth_hdr *ethhdr; -+ /* add ethernet header */ -+ ethhdr = (struct eth_hdr *)(in->payload); -+ /* smac and dmac set to all zeros for loopback IP packet */ -+ (void)memset_s(ethhdr, sizeof(struct eth_hdr), 0, sizeof(struct eth_hdr)); -+ ethhdr->type = htons(ETHTYPE_IP); /* eth protocol, should be ETH_P_IP(0x800) */ -+ in->flags = (u16_t)(in->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_OUTGOING)); -+ in->flags |= PBUF_FLAG_HOST; -+ raw_packet_input(in, netif, NULL); -+ (void)pbuf_header(in, -PBUF_LINK_HLEN); -+ } -+#endif /* PF_PACKET_SOCKET */ -+ - /* loopback packets are always IP packets! */ - if (ip_input(in, netif) != ERR_OK) { - pbuf_free(in); -@@ -1700,29 +1803,68 @@ - struct netif * - netif_find(const char *name) - { -- struct netif *netif; -- u8_t num; -- -- LWIP_ASSERT_CORE_LOCKED(); -- -- if (name == NULL) { -- return NULL; -- } -+ struct netif *netif = NULL; -+ char candidate_name[NETIF_NAMESIZE]; -+ int ret; - -- num = (u8_t)atoi(&name[2]); -+ LWIP_ERROR("netif_find : invalid value.", (name != NULL), return NULL); - - NETIF_FOREACH(netif) { -- if (num == netif->num && -- name[0] == netif->name[0] && -- name[1] == netif->name[1]) { -- LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); -+ if (strncmp(name, netif->name, NETIF_NAMESIZE) == 0) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %s\n", name)); - return netif; - } -+ -+ if (netif->link_layer_type != LOOPBACK_IF) { -+ ret = snprintf_s(candidate_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s%"U8_F, netif->name, netif->num); -+ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: name '%s'is too long\n", netif->name)); -+ continue; -+ } -+ if (strncmp(name, candidate_name, NETIF_NAMESIZE) == 0) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %s\n", name)); -+ return netif; -+ } -+ } - } -- LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %s\n", name)); - return NULL; - } - -+/* -+ * Change mtu setting for a network interface -+ * -+ * @param netif the network interface to change -+ * @param netif_mtu the new MTU for the interface -+ */ -+ -+err_t -+netif_set_mtu_api(struct netif *netif, u16_t netif_mtu) -+{ -+ /* As per RFC 791, "Every internet module must be able to forward a datagram of 68 -+ * octets without further fragmentation. This is because an internet header -+ * may be up to 60 octets, and the minimum fragment is 8 octets." */ -+ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif != NULL), return ERR_VAL); -+ -+#if LWIP_IPV6 -+ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif_mtu >= NETIF_MTU_MIN) && (netif_mtu <= IP_FRAG_MAX_MTU), -+ return ERR_ARG); -+#else -+ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif_mtu >= IP_FRAG_MIN_MTU) && (netif_mtu <= IP_FRAG_MAX_MTU), -+ return ERR_ARG); -+#endif -+ -+ netif->mtu = netif_mtu; -+#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES -+ netif->mtu6 = netif_mtu; -+#endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ -+ -+ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif: MTU of interface %s%"U16_F" is changed to %d\n", -+ netif->name, netif->num, netif->mtu)); -+ -+ return ERR_OK; -+} -+ - #if LWIP_NETIF_EXT_STATUS_CALLBACK - /** - * @ingroup netif -@@ -1793,3 +1935,213 @@ - } - } - #endif /* LWIP_NETIF_EXT_STATUS_CALLBACK */ -+ -+struct netif * -+netif_find_by_ipaddr(const ip_addr_t *ipaddr) -+{ -+ LWIP_ERROR("netif_find_by_ipaddr : invalid arguments", (ipaddr != NULL), return NULL); -+#if LWIP_IPV4 -+ if (IP_IS_V4(ipaddr)) { -+ return netif_find_by_ip4addr(ipaddr); -+ } -+#endif -+ -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ipaddr: didn't find\n")); -+ return NULL; -+} -+ -+void -+netif_get_hwaddr(const struct netif *netif, unsigned char *hw_addr, int hw_len) -+{ -+ int i; -+ LWIP_ERROR("netif_get_hwaddr : invalid arguments", (netif != NULL), return); -+ -+ LWIP_ERROR("netif_get_hwaddr : invalid arguments", (hw_addr != NULL), return); -+ -+ LWIP_ERROR("netif_get_hwaddr: invalid arguments", -+ ((unsigned int)hw_len == NETIF_MAX_HWADDR_LEN), return); -+ -+ for (i = 0; i < hw_len; i++) { -+ hw_addr[i] = netif->hwaddr[i]; -+ } -+} -+ -+/* -+ * Change the hardware address for a network interface -+ * -+ * NOTE:Application should call set_link_down before calling -+ * the netif_set_hwaddr and then set_link_up, in order -+ * to ensure that all IPs are announced after changing -+ * hw address -+ * -+ * @param netif the network interface to change -+ * @param hw_addr the new hardware address -+ * @param hw_len the length of new hardware address, -+ * -+ */ -+err_t -+netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw_len) -+{ -+ LWIP_ERROR("netif_set_hwaddr : invalid arguments", (netif != NULL), return ERR_VAL); -+ -+ LWIP_ERROR("netif_set_hwaddr : invalid arguments", (hw_addr != NULL), return ERR_VAL); -+ -+ LWIP_ERROR("netif_set_hwaddr: invalid arguments", -+ ((unsigned int)hw_len == NETIF_MAX_HWADDR_LEN), return ERR_VAL); -+ -+ if (netif->drv_set_hwaddr == NULL) { -+ return ERR_OPNOTSUPP; -+ } -+ -+ if (netif->drv_set_hwaddr(netif, (u8_t *)hw_addr, hw_len) != ERR_OK) { -+ return ERR_VAL; -+ } -+ -+ if (memcpy_s(netif->hwaddr, NETIF_MAX_HWADDR_LEN, hw_addr, (u32_t)hw_len) != EOK) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_set_hwaddr: memcpy_s error\n")); -+ return ERR_VAL; -+ } -+ -+ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, -+ ("netif: HW address of interface %s%"U16_F" set to %02X:%02X:%02X:%02X:%02X:%02X\n", -+ netif->name, netif->num, -+ netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], -+ netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5])); -+ -+ return ERR_OK; -+} -+ -+#if LWIP_IPV4 -+/* -+ * Find a network interface by searching for its ipaddress -+ * -+ * @param ipaddr IP_add of the netif -+ * @return netif if the its found -+ * NULL if there is no netif with ipaddr -+ */ -+struct netif * -+netif_find_by_ip4addr(const ip_addr_t *ipaddr) -+{ -+ struct netif *netif = NULL; -+ -+ LWIP_ASSERT("Expecting ipaddr to be not NULL ", ipaddr != NULL); -+ -+ for (netif = netif_list; netif != NULL; netif = netif->next) { -+ if (ip_addr_cmp(&(netif->ip_addr), ipaddr)) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ipaddr: found\n")); -+ return netif; -+ } -+ } -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ip4addr: didn't find\n")); -+ return NULL; -+} -+ -+s8_t netif_find_dst_ipaddr(const ip_addr_t *ipaddr, ip_addr_t **dst_addr) -+{ -+ struct netif *netif = NULL; -+ ip_addr_t *pdst_addr = NULL; -+ -+ pdst_addr = *dst_addr; -+ netif = netif_find_by_ipaddr(ipaddr); -+ if (netif == NULL) { -+ return -1; -+ } -+ if ((pdst_addr != NULL) && (!ip_addr_netcmp(pdst_addr, &(netif->ip_addr), ip_2_ip4(&netif->netmask))) && -+ !ip_addr_islinklocal(pdst_addr)) { -+ if (!ip_addr_isany(&netif->gw)) { -+ *dst_addr = &(netif->gw); -+ } -+ } -+ -+ return 0; -+} -+#endif /* LWIP_IPV4 */ -+ -+ -+ -+#if LWIP_DHCP -+/* -+ * Close DHCP and set static network. -+ * -+ * @param netif a pre-allocated netif structure -+ * -+ * @return ERR_OK, or ERR_VAL if failed. -+ */ -+err_t -+netif_dhcp_off(struct netif *netif) -+{ -+ ip_addr_t old_ipaddr; -+ ip_addr_t old_netmask; -+ ip_addr_t old_gateway; -+ -+ if (netif == NULL) { -+ return ERR_VAL; -+ } -+ old_ipaddr = netif->ip_addr; -+ old_netmask = netif->netmask; -+ old_gateway = netif->gw; -+ -+ if (netif_dhcp_data(netif)) { -+ (void)dhcp_release(netif); -+ dhcp_stop(netif); -+ dhcp_cleanup(netif); -+ LWIP_DEBUGF(NETIF_DEBUG, ("DHCP is close;set static IP\n")); -+ } -+ -+ ip_addr_set_val(netif->ip_addr, old_ipaddr); -+ ip_addr_set_val(netif->netmask, old_netmask); -+ ip_addr_set_val(netif->gw, old_gateway); -+ (void)netif_set_up(netif); -+ -+ return ERR_OK; -+} -+#endif /* LWIP_DHCP */ -+ -+u8_t netif_ipaddr_isbrdcast(const ip_addr_t *ipaddr) -+{ -+ struct netif *netif = NULL; -+ -+ for (netif = netif_list; netif != NULL; netif = netif->next) { -+ if (netif_is_up(netif) && ip_addr_isbroadcast(ipaddr, netif)) { -+ return 1; -+ } -+ } -+ -+ return 0; -+} -+ -+struct netif * -+netif_find_by_ifindex(u8_t ifindex) -+{ -+ struct netif *netif = NULL; -+ -+ if (ifindex < LWIP_NETIF_IFINDEX_START) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: Invalid ifindex(%u) \n", ifindex)); -+ return netif; -+ } -+ -+ for (netif = netif_list; netif != NULL; netif = netif->next) { -+ if (netif->ifindex == ifindex) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: found\n")); -+ return netif; -+ } -+ } -+ -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: didn't find\n")); -+ return NULL; -+} -+ -+/* Need to support the get index for all families -+removed PF_PACKET_SOCKET flag , as this flags restricts the usage to only PF_FAMILY Begin */ -+static u8_t -+netif_alloc_ifindex(void) -+{ -+ u8_t tmp_index; -+ for (tmp_index = LWIP_NETIF_IFINDEX_START; tmp_index <= LWIP_NETIF_IFINDEX_MAX; tmp_index++) { -+ if (netif_get_by_index(tmp_index) == NULL) { -+ break; -+ } -+ } -+ -+ return tmp_index; -+} -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-21 11:37:14.000000000 +0800 -@@ -0,0 +1,319 @@ -+#include "lwip/opt.h" -+ -+#if LWIP_NIP /* don't build if not configured for use in lwipopts.h */ -+ -+#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) -+{ -+ 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; -+} -+ -+/** -+ * 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) -+{ -+ 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; -+ } -+ -+ /* 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; -+} -+ -+/** 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); -+} -+ -+/** -+ * 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-21 11:32:04.000000000 +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-26 06:17:04.000000000 +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 22:35:10.000000000 +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-26 06:54:48.000000000 +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); -+ netif = ip_route_pcb(ipaddr, (struct ip_pcb*)pcb); - } - } - -@@ -387,7 +415,7 @@ - return ERR_RTE; - } - -- if (ip_addr_isany(&pcb->local_ip) || ip_addr_ismulticast(&pcb->local_ip)) { -+ if (ip_addr_isany(&pcb->local_ip) || ip_get_option(pcb, SOF_BINDNONUNICAST)) { - /* use outgoing network interface IP address as source address */ - src_ip = ip_netif_get_local_ip(netif, ipaddr); - #if LWIP_IPV6 -@@ -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); -- err = ip_output_if(q, src_ip, dst_ip, ttl, pcb->tos, pcb->protocol, netif); -+ err = ip_output_if(q, src_ip, dst_ip, ttl, pcb->tos, pcb->raw_proto, netif); - NETIF_RESET_HINTS(netif); - - /* did we chain a header earlier? */ -@@ -604,7 +634,12 @@ - if (pcb != NULL) { - /* initialize PCB to all zeroes */ - memset(pcb, 0, sizeof(struct raw_pcb)); -+#if PF_PACKET_SOCKET -+ pcb->proto.protocol = proto; -+#else - pcb->protocol = proto; -+#endif -+ - pcb->ttl = RAW_TTL; - #if LWIP_MULTICAST_TX_OPTIONS - raw_set_multicast_ttl(pcb, RAW_TTL); -@@ -668,4 +703,227 @@ - } - } - -+#if PF_PACKET_SOCKET -+void raw_packet_input(struct pbuf *p, const struct netif *inp, const struct raw_pcb *from) -+{ -+ struct raw_pcb *pcb = NULL; -+ struct eth_hdr *ethhdr = NULL; -+ u16_t proto; -+ -+ LWIP_UNUSED_ARG(inp); -+ -+ ethhdr = (struct eth_hdr *)p->payload; -+ proto = ethhdr->type; -+ -+ g_lwip_current_eth_hdr = ethhdr; -+ g_lwip_current_netif = inp; -+ -+ pcb = g_packet_raw_pcbs; -+ /* 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->proto.eth_proto == htons(ETHTYPE_ALL)) || ((p != NULL) && !(p->flags & PBUF_FLAG_OUTGOING) && -+ pcb->proto.eth_proto == proto)) && -+ ((!pcb->netifindex) || (pcb->netifindex == inp->ifindex)) && (pcb != from)) { -+ /* receive callback function available? */ -+ if (pcb->recv != NULL) { -+ /* the receive callback function did not eat the packet? */ -+ if (pcb->recv(pcb->recv_arg, pcb, p, NULL) != 0) { -+ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_input: packets recved failed \n")); -+ } -+ } -+ /* no receive callback function was set for this raw PCB */ -+ } -+ -+ pcb = pcb->next; -+ } -+ -+ g_lwip_current_eth_hdr = NULL; -+ return; -+} -+ -+err_t -+raw_packet_bind(struct raw_pcb *pcb, u8_t ifindex, u16_t proto) -+{ -+ struct netif *loc_netif = NULL; -+ -+ if (ifindex != 0) { -+ for (loc_netif = netif_list; loc_netif != NULL; loc_netif = loc_netif->next) { -+ if (ifindex == loc_netif->ifindex) { -+ break; -+ } -+ } -+ -+ /* Return if no matching netifs to bind */ -+ if (loc_netif == NULL) { -+ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_bind: No matching netif found for ifindex(%u)\n", ifindex)); -+ return ERR_NODEV; -+ } -+ } else { -+ return ERR_NODEV; -+ } -+ -+#if DRIVER_STATUS_CHECK -+ if (!netif_is_up(loc_netif) || !netif_is_ready(loc_netif)) -+#else -+ if (!netif_is_up(loc_netif)) -+#endif -+ { -+ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_bind: bind failed as netif (index %u) was down\n", ifindex)); -+ return ERR_NETDOWN; -+ } -+ -+ pcb->netifindex = ifindex; -+ pcb->proto.eth_proto = proto; -+ -+ return ERR_OK; -+} -+ -+/* -+ * Send the raw IP packet through the given netif driver. Note that actually you cannot -+ * modify the link layer header here. Packet need to be sent to driver as it is through the -+ * given netif -+ * @param pcb the raw pcb which to send -+ * @param p the ethernet packet to send -+ * @param ifindex the Interface index of the netif through which packet needs to be sent -+ */ -+err_t -+raw_packet_sendto(const struct raw_pcb *pcb, struct pbuf *p, u8_t ifindex) -+{ -+ struct netif *netif = NULL; -+ u8_t netifindex; -+ LWIP_UNUSED_ARG(pcb); -+ -+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_packet_sendto: ifindex=%d\n", ifindex)); -+ LWIP_ASSERT("p != NULL", p != NULL); -+ -+ netifindex = ifindex; -+ -+ if (ifindex == 0) { -+ if (pcb->netifindex != 0) { -+ netifindex = pcb->netifindex; -+ } else { -+ return ERR_NODEVADDR; -+ } -+ } -+ -+ /* Find the netif corresponding to the interface index */ -+ netif = netif_find_by_ifindex(netifindex); -+ if (netif == NULL) { -+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("netif not found for given ifindex (%u)\n", ifindex)); -+ return ERR_NODEVADDR; -+ } -+ -+#if DRIVER_STATUS_CHECK -+ if ((!netif_is_up(netif)) || (!netif_is_ready(netif))) -+#else -+ if ((!netif_is_up(netif))) -+#endif -+ { -+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("netif was down for given ifindex (%u)\n", ifindex)); -+ return ERR_NETDOWN; -+ } -+ -+ if ((p->tot_len - (SIZEOF_ETH_HDR - ETH_PAD_SIZE)) > netif->mtu) { -+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("Message too long (%u)\n", p->tot_len)); -+ return ERR_MSGSIZE; -+ } -+ -+ if (pbuf_header(p, ETH_PAD_SIZE) == 0) { -+ p->flags = (u16_t)(p->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_HOST)); -+ p->flags |= PBUF_FLAG_OUTGOING; -+ raw_packet_input(p, netif, pcb); -+ (void)pbuf_header(p, -ETH_PAD_SIZE); -+ } -+ -+ /* For RAW packets of PF_PACKET family, do not modify the packets as it is -+ already supposed to contain the link layer header. So send directly to the driver */ -+ LINK_STATS_INC(link.xmit); -+ return ERR_OK; -+} -+ -+/* -+ * Create a RAW PCB for Packet family. -+ * -+ * @return The RAW PCB which was created. NULL if the PCB data structure -+ * could not be allocated. -+ * -+ * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) -+ * -+ * @see raw_remove() -+ */ -+struct raw_pcb * -+raw_packet_new(u16_t proto) -+{ -+ struct raw_pcb *pcb = NULL; -+ -+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_packet_new\n")); -+ -+ pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); -+ /* could allocate RAW PCB? */ -+ if (pcb != NULL) { -+ /* initialize PCB to all zeroes */ -+ (void)memset(pcb, 0, sizeof(struct raw_pcb)); -+ pcb->proto.eth_proto = proto; -+ pcb->ttl = RAW_TTL; -+ pcb->next = g_packet_raw_pcbs; -+ g_packet_raw_pcbs = pcb; -+ pcb->all_next = g_all_packet_raw_pcbs; -+ g_all_packet_raw_pcbs = pcb; -+ } -+ return pcb; -+} -+ -+/* -+ * Remove an RAW PCB of packet family type -+ * -+ * @param pcb RAW PCB to be removed. The PCB is removed from the list of -+ * RAW PCB's and the data structure is freed from memory. -+ * -+ * @see raw_packet_new() -+ */ -+void -+raw_packet_remove(struct raw_pcb *pcb) -+{ -+ struct raw_pcb *pcb2 = NULL; -+ -+ /* NULL check */ -+ if (pcb == NULL) { -+ return; -+ } -+ -+ /* pcb to be removed is first in all_pkt list? */ -+ if (g_all_packet_raw_pcbs == pcb) { -+ /* make list start at 2nd pcb */ -+ g_all_packet_raw_pcbs = g_all_packet_raw_pcbs->all_next; -+ /* pcb not 1st in list */ -+ } else { -+ for (pcb2 = g_all_packet_raw_pcbs; pcb2 != NULL; pcb2 = pcb2->all_next) { -+ /* find pcb in g_all_packet_raw_pcbs list */ -+ if (pcb2->all_next == pcb) { -+ /* remove pcb from list */ -+ pcb2->all_next = pcb->all_next; -+ } -+ } -+ } -+ -+ /* pcb to be removed is first in list? */ -+ if (g_packet_raw_pcbs == pcb) { -+ /* make list start at 2nd pcb */ -+ g_packet_raw_pcbs = g_packet_raw_pcbs->next; -+ /* pcb not 1st in list */ -+ } else { -+ for (pcb2 = g_packet_raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { -+ /* find pcb in raw_pcbs list */ -+ if (pcb2->next == pcb) { -+ /* remove pcb from list */ -+ pcb2->next = pcb->next; -+ } -+ } -+ } -+ -+ memp_free(MEMP_RAW_PCB, pcb); -+} -+#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-26 06:54:38.000000000 +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-28 12:13:04.000000000 +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-26 06:56:20.000000000 +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 2022-02-16 16:06:59.178115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/api.h 2022-01-26 06:54:12.000000000 +0800 -@@ -48,6 +48,9 @@ - #include "lwip/sys.h" - #include "lwip/ip_addr.h" - #include "lwip/err.h" -+#if LWIP_LITEOS_COMPAT -+#include "lwip/netif.h" -+#endif - - #ifdef __cplusplus - extern "C" { -@@ -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,15 @@ - /** 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 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 +166,10 @@ - NETCONN_WRITE, - NETCONN_LISTEN, - NETCONN_CONNECT, -- NETCONN_CLOSE -+ NETCONN_CLOSE, -+#if LWIP_LITEOS_COMPAT -+ NETCONN_CLOSED, -+#endif /* LWIP_LITEOS_COMPAT */ - }; - - /** Used to inform the callback function about changes -@@ -201,6 +221,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 +247,12 @@ - struct tcp_pcb *tcp; - struct udp_pcb *udp; - struct raw_pcb *raw; -+#if PF_PACKET_SOCKET -+ struct raw_pcb *packet_raw; -+#endif /* PF_PACKET_SOCKET */ - } pcb; - /** the last asynchronous unreported error this netconn had */ -- err_t pending_err; -+ err_t last_err; - #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 +307,13 @@ - #endif /* LWIP_TCP */ - /** A callback function that is informed about events for this netconn */ - netconn_callback callback; -+#if LWIP_TCP -+ struct pbuf *refused_data; -+ ip_addr_t remote_ip; -+ u16_t remote_port; -+ /** record pending error state after recving RST */ -+ u16_t pending_err; -+#endif - }; - - /** This vector type is passed to @ref netconn_write_vectors_partly to send -@@ -309,21 +340,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) --struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, -+struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, - netconn_callback callback); - err_t netconn_prepare_delete(struct netconn *conn); - err_t netconn_delete(struct netconn *conn); - /** Get the type of a netconn (as enum netconn_type). */ --#define netconn_type(conn) (conn->type) -+#define netconn_type(conn) ((u32_t)(conn->type)) - - err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, - u16_t *port, u8_t local); -+#if LWIP_LITEOS_COMPAT -+#if PF_PACKET_SOCKET -+struct pf_packet_sockaddr_ll { -+ u16_t sll_protocol; -+ u16_t sll_hatype; -+ u8_t if_idx; -+ u8_t sll_halen; -+ u8_t sll_addr[NETIF_MAX_HWADDR_LEN]; -+}; -+err_t netconn_get_sockaddr_pf_packet(struct netconn *conn, struct pf_packet_sockaddr_ll *ll, u8_t local); -+#endif /* PF_PACKET_SOCKET */ -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup netconn_common */ - #define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) - /** @ingroup netconn_common */ - #define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) - -+#if PF_PACKET_SOCKET -+err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port, u8_t ifindex); -+#else - err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port); -+#endif /* PF_PACKET_SOCKET */ -+ - err_t netconn_bind_if(struct netconn *conn, u8_t if_idx); - 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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/arch.h 2022-01-26 06:41:32.000000000 +0800 -@@ -37,14 +37,7 @@ - #ifndef LWIP_HDR_ARCH_H - #define LWIP_HDR_ARCH_H - --#ifndef LITTLE_ENDIAN --#define LITTLE_ENDIAN 1234 --#endif -- --#ifndef BIG_ENDIAN --#define BIG_ENDIAN 4321 --#endif -- -+#include - #include "arch/cc.h" - - /** -@@ -149,6 +142,11 @@ - #ifndef X8_F - #define X8_F "02" PRIx8 - #endif -+#if LWIP_LITEOS_COMPAT -+#ifndef U8_F -+#define U8_F PRIu8 -+#endif -+#endif /* LWIP_LITEOS_COMPAT */ - #ifndef U16_F - #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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/err.h 2022-01-26 06:41:32.000000000 +0800 -@@ -85,9 +85,50 @@ - /** Connection closed. */ - ERR_CLSD = -15, - /** Illegal argument. */ -- ERR_ARG = -16 -+ ERR_ARG = -16, -+#ifdef LWIP_LITEOS_COMPAT -+/** Message too long. */ -+ ERR_MSGSIZE = -17, -+/** No such device. */ -+ ERR_NODEV = -18, -+/** No such device or address. */ -+ ERR_NODEVADDR = -19, -+/** socket is not connection-mode & no peer address is set */ -+ ERR_NODEST = -20, -+/** Network is down */ -+ ERR_NETDOWN = -21, -+/** Address family not supported by protocol */ -+ ERR_AFNOSUPP = -22, -+/** No such address */ -+ ERR_NOADDR = -23, -+/** Operation not supported on transport endpoint */ -+ ERR_OPNOTSUPP = -24, -+ ERR_NETUNREACH = -25, -+/** connection request timedout */ -+ ERR_CONNECTIMEOUT = -26, -+/** Error pipe */ -+ ERR_PIPE = -27, -+/** AF not supported */ -+ ERR_AFNOSUPPORT = -28, -+/** Protocol not available */ -+ ERR_NOPROTOOPT = -29, -+ ERR_ACCESS = -30, -+ ERR_NFILE = -31, -+ ERR_RESERVE3 = -32, -+ ERR_RESERVE4 = -33, -+ ERR_RESERVE5 = -34, -+ ERR_RESERVE6 = -35, -+ ERR_FATAL_START = -36, -+ ERR_CONNREFUSED = -41, -+/** FIN mbox post fail. */ -+ ERR_FIN_POST = -42, -+#endif /* LWIP_LITEOS_COMPAT */ - } err_enum_t; - -+#ifdef LWIP_LITEOS_COMPAT -+#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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/etharp.h 2022-01-26 06:41:32.000000000 +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-01-26 07:48:02.000000000 +0800 -@@ -0,0 +1,113 @@ -+/** -+ * @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 /* don't build if not configured for use in lwipopts.h */ -+ -+#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); -+ -+#endif -+ -+#if LWIP_NIP && LWIP_ARP /* don't build if not configured for use in lwipopts.h */ -+ -+// #include "lwip/prot/ethnip.h" -+ -+#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. */ -+ -+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 /* LWIP_IPV4 && LWIP_ARP */ -+ -+#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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/if_api.h 2022-01-26 06:41:32.000000000 +0800 -@@ -49,10 +49,12 @@ - extern "C" { - #endif - -+#if !LWIP_LITEOS_COMPAT - #define IF_NAMESIZE NETIF_NAMESIZE - - char * lwip_if_indextoname(unsigned int ifindex, char *ifname); - unsigned int lwip_if_nametoindex(const char *ifname); -+#endif - - #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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/inet.h 2022-01-26 06:51:36.000000000 +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 - -+#if !LWIP_LITEOS_COMPAT - /* 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 +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)}}} --/** This variable is initialized by the system to contain the wildcard IPv6 address. */ --extern const struct in6_addr in6addr_any; - - /* Definitions of the bits in an (IPv4) Internet address integer. - -@@ -119,7 +119,12 @@ - #define IN_BADCLASS(a) IP_BADCLASS(a) - - #define IN_LOOPBACKNET IP_LOOPBACKNET -+#endif /* !LWIP_LITEOS_COMPAT */ - -+/** This variable is initialized by the system to contain the wildcard IPv6 address. */ -+extern const struct in6_addr in6addr_any; -+/** Added new structure for ipv6 loopback as per section 3.9 of rfc 2553/3493 */ -+extern const struct in6_addr in6addr_loopback; - - #ifndef INET_ADDRSTRLEN - #define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX -@@ -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 */ --#define inet_addr(cp) ipaddr_addr(cp) -+#if LWIP_INET_ADDR_FUNC -+unsigned int inet_addr(const char *cp); -+#else -+#define inet_addr(cp) ipaddr_addr(cp) -+#endif -+ -+#if LWIP_INET_ATON_FUNC -+int inet_aton(const char *cp, struct in_addr *addr); -+#else - #define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) -+#endif -+ -+#if LWIP_INET_NTOA_FUNC -+char *inet_ntoa (struct in_addr in); -+#else - #define inet_ntoa(addr) ip4addr_ntoa((const ip4_addr_t*)&(addr)) -+#endif -+ - #define inet_ntoa_r(addr, buf, buflen) ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) - - #endif /* LWIP_IPV4 */ - - #if LWIP_IPV6 -+/* current the struct ip6_addr for define LWIP_IPV6_SCOPES 0 */ -+#if LWIP_LITEOS_COMPAT -+#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) { \ -+ memcpy((target_in6addr)->s6_addr, (source_ip6addr)->addr, sizeof(struct ip6_addr)); } -+#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) { \ -+ memcpy((target_ip6addr)->addr, (source_in6addr)->s6_addr, sizeof(struct ip6_addr)); \ -+ ip6_addr_clear_zone(target_ip6addr);} -+#else - #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 +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);} -- -+#endif /* LWIP_LITEOS_COMPAT */ - /* 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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/ip_addr.h 2022-01-29 09:20:40.000000000 +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{ \ -- ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); ip_clear_no4(dest); }}while(0) -+ ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); ip_clear_no4(dest); }} while (0) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_set_val(dest, src) do { IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&(src))); if(IP_IS_V6_VAL(src)) { \ -+ ip6_addr_set(ip_2_ip6(&(dest)), ip_2_ip6(&(src))); } else { \ -+ ip4_addr_set(ip_2_ip4(&(dest)), ip_2_ip4(&(src))); }} while (0) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup ipaddr */ - #define ip_addr_set_ipaddr(dest, src) ip_addr_set(dest, src) - /** @ingroup ipaddr */ - #define ip_addr_set_zero(ipaddr) do{ \ -- ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0) -+ ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); } while (0) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_set_zero_val(ipaddr) do{ \ -+ ip6_addr_set_zero(ip_2_ip6(&(ipaddr))); IP_SET_TYPE_VAL(ipaddr, 0); } while (0) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup ip5addr */ - #define ip_addr_set_zero_ip4(ipaddr) do{ \ - ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }while(0) - /** @ingroup ip6addr */ - #define ip_addr_set_zero_ip6(ipaddr) do{ \ -- ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }while(0) -+ ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); } while (0) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_set_zero_ip6_val(ipaddr) do{ \ -+ ip6_addr_set_zero(ip_2_ip6(&(ipaddr))); IP_SET_TYPE_VAL(ipaddr, IPADDR_TYPE_V6); } while (0) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @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 +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)) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_netcmp_val(addr1, addr2, mask) ((IP_IS_V6_VAL((addr1)) && IP_IS_V6_VAL((addr2))) ? \ -+ 0 : \ -+ ip4_addr_netcmp(ip_2_ip4(&addr1), ip_2_ip4(&addr2), mask)) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @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 +282,50 @@ - #define ip_addr_isbroadcast(ipaddr, netif) ((IP_IS_V6(ipaddr)) ? \ - 0 : \ - ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_isbroadcast_val(ipaddr, netif) ((IP_IS_V6_VAL(ipaddr)) ? \ -+ 0 : \ -+ ip4_addr_isbroadcast(ip_2_ip4(&ipaddr), netif)) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup ipaddr */ - #define ip_addr_ismulticast(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ - ip4_addr_ismulticast(ip_2_ip4(ipaddr))) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_ismulticast_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ -+ ip6_addr_ismulticast(ip_2_ip6(&ipaddr)) : \ -+ ip4_addr_ismulticast(ip_2_ip4(&ipaddr))) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup ipaddr */ - #define ip_addr_isloopback(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_isloopback(ip_2_ip6(ipaddr)) : \ - ip4_addr_isloopback(ip_2_ip4(ipaddr))) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_isloopback_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ -+ ip6_addr_isloopback(ip_2_ip6(&ipaddr)) : \ -+ ip4_addr_isloopback(ip_2_ip4(&ipaddr))) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup ipaddr */ - #define ip_addr_islinklocal(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_islinklocal(ip_2_ip6(ipaddr)) : \ - ip4_addr_islinklocal(ip_2_ip4(ipaddr))) -+#ifdef LWIP_DEBUG - #define ip_addr_debug_print(debug, ipaddr) do { if(IP_IS_V6(ipaddr)) { \ - ip6_addr_debug_print(debug, ip_2_ip6(ipaddr)); } else { \ -- ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }}while(0) -+ ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }} while (0) - #define ip_addr_debug_print_val(debug, ipaddr) do { if(IP_IS_V6_VAL(ipaddr)) { \ - ip6_addr_debug_print_val(debug, *ip_2_ip6(&(ipaddr))); } else { \ -- ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }}while(0) -+ ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }} while (0) -+#else -+#define ip_addr_debug_print(debug, ipaddr) -+#define ip_addr_debug_print_val(debug, ipaddr) -+#endif /* LWIP_LITEOS_COMPAT */ -+ - char *ipaddr_ntoa(const ip_addr_t *addr); - char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen); -+#if LWIP_LITEOS_COMPAT -+#define ipaddr_ntoa_unsafe(addr) ((IP_IS_V6_VAL(*addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr))) -+#endif /* LWIP_LITEOS_COMPAT */ - int ipaddr_aton(const char *cp, ip_addr_t *addr); - - /** @ingroup ipaddr */ -@@ -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) - -+#define ip_addr_cmp_zoneless(addr1, addr2) ip4_addr_cmp(addr1, addr2) - #define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) - #define ip_addr_copy_from_ip4(dest, src) ip4_addr_copy(dest, src) - #define ip_addr_set_ip4_u32(ipaddr, val) ip4_addr_set_u32(ip_2_ip4(ipaddr), val) - #define ip_addr_set_ip4_u32_val(ipaddr, val) ip_addr_set_ip4_u32(&(ipaddr), val) - #define ip_addr_get_ip4_u32(ipaddr) ip4_addr_get_u32(ip_2_ip4(ipaddr)) - #define ip_addr_set(dest, src) ip4_addr_set(dest, src) -+#define ip_addr_set_val(dest, src) ip4_addr_copy(dest, src) - #define ip_addr_set_ipaddr(dest, src) ip4_addr_set(dest, src) - #define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) -+#define ip_addr_set_zero_val(ipaddr) ip4_addr_set_zero(&(ipaddr)) - #define ip_addr_set_zero_ip4(ipaddr) ip4_addr_set_zero(ipaddr) - #define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) - #define ip_addr_set_loopback(is_ipv6, ipaddr) ip4_addr_set_loopback(ipaddr) - #define ip_addr_set_hton(dest, src) ip4_addr_set_hton(dest, src) - #define ip_addr_get_network(target, host, mask) ip4_addr_get_network(target, host, mask) - #define ip_addr_netcmp(addr1, addr2, mask) ip4_addr_netcmp(addr1, addr2, mask) -+#define ip_addr_netcmp_val(addr1, addr2, mask) ip4_addr_netcmp(&(addr1), &(addr2), mask) - #define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) - #define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) -+#define ip_addr_isnone(ipaddr) ip4_addr_isnone(ipaddr) - #define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) - #define ip_addr_isloopback(ipaddr) ip4_addr_isloopback(ipaddr) -+#define ip_addr_isloopback_val(ipaddr) ip4_addr_isloopback(&(ipaddr)) - #define ip_addr_islinklocal(ipaddr) ip4_addr_islinklocal(ipaddr) - #define ip_addr_isbroadcast(addr, netif) ip4_addr_isbroadcast(addr, netif) -+#define ip_addr_isbroadcast_val(addr, netif) ip4_addr_isbroadcast(&(addr), netif) - #define ip_addr_ismulticast(ipaddr) ip4_addr_ismulticast(ipaddr) -+#define ip_addr_ismulticast_val(ipaddr) ip4_addr_ismulticast(&(ipaddr)) -+#ifdef LWIP_DEBUG - #define ip_addr_debug_print(debug, ipaddr) ip4_addr_debug_print(debug, ipaddr) - #define ip_addr_debug_print_val(debug, ipaddr) ip4_addr_debug_print_val(debug, ipaddr) -+#else -+#define ip_addr_debug_print(debug, ipaddr) -+#define ip_addr_debug_print_val(debug, ipaddr) -+#endif -+ - #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 +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) -+#define ip_addr_set_val(dest, src) ip6_addr_copy(dest, src) -+ - #define ip_addr_set_ipaddr(dest, src) ip6_addr_set(dest, src) - #define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr) -+#define ip_addr_set_zero_val(ipaddr) ip6_addr_set_zero(&(ipaddr)) - #define ip_addr_set_zero_ip6(ipaddr) ip6_addr_set_zero(ipaddr) -+#define ip_addr_set_zero_ip6_val(ipaddr) ip6_addr_set_zero(&(ipaddr)) - #define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr) - #define ip_addr_set_loopback(is_ipv6, ipaddr) ip6_addr_set_loopback(ipaddr) - #define ip_addr_set_hton(dest, src) ip6_addr_set_hton(dest, src) - #define ip_addr_get_network(target, host, mask) ip6_addr_set_zero(target) - #define ip_addr_netcmp(addr1, addr2, mask) 0 -+#define ip_addr_netcmp_val(addr1, addr2, mask) 0 - #define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) - #define ip_addr_cmp_zoneless(addr1, addr2) ip6_addr_cmp_zoneless(addr1, addr2) - #define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) -+#define ip_addr_isnone(ipaddr) ip6_addr_isnone(ipaddr) - #define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) - #define ip_addr_isloopback(ipaddr) ip6_addr_isloopback(ipaddr) -+#define ip_addr_isloopback_val(ipaddr) ip6_addr_isloopback(&(ipaddr)) - #define ip_addr_islinklocal(ipaddr) ip6_addr_islinklocal(ipaddr) - #define ip_addr_isbroadcast(addr, netif) 0 -+#define ip_addr_isbroadcast_val(addr, netif) 0 - #define ip_addr_ismulticast(ipaddr) ip6_addr_ismulticast(ipaddr) -+#define ip_addr_ismulticast_val(ipaddr) ip6_addr_ismulticast(&(ipaddr)) -+#ifdef LWIP_DEBUG - #define ip_addr_debug_print(debug, ipaddr) ip6_addr_debug_print(debug, ipaddr) - #define ip_addr_debug_print_val(debug, ipaddr) ip6_addr_debug_print_val(debug, ipaddr) -+#else -+#define ip_addr_debug_print(debug, ipaddr) -+#define ip_addr_debug_print_val(debug, ipaddr) -+#endif -+ - #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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/ip.h 2022-01-26 06:51:26.000000000 +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) */ -- -+#if LWIP_LITEOS_COMPAT -+#define SOF_DONTROUTE 0x01U /* all packets sent from this socket should only be routed with link scope entry */ -+#define SOF_BINDNONUNICAST 0x10U /* socket has bind to a non unicast */ -+#endif /* LWIP_LITEOS_COMPAT */ - /* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ - #define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE) - -@@ -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; -+#if LWIP_LITEOS_COMPAT -+ /* The IP header ID of the next outgoing IP packet */ -+#if LWIP_IPV4 -+ /* ensure this member of this sturcture is not mem set to zero */ -+ u16_t ip_id; -+#endif /* LWIP_IPV4 */ -+#endif /* LWIP_LITEOS_COMPAT */ - }; - extern struct ip_globals ip_data; - -@@ -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 */ -+#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 -+ * (requires IP_FRAG_USES_STATIC_BUF==1).This is not a configurable value. -+ */ -+#if !defined(IP_FRAG_MAX_MTU) -+#define IP_FRAG_MAX_MTU 1500 -+#endif -+/* As per RFC 791, "Every internet module must be able to forward a datagram of 68 -+ * octets without further fragmentation. This is because an internet header -+ * may be up to 60 octets, and the minimum fragment is 8 octets." */ -+#if !defined(IP_FRAG_MIN_MTU) -+#define IP_FRAG_MIN_MTU 68 -+#endif -+struct netif *ip_route_pcb(const ip_addr_t *dest, const struct ip_pcb* pcb); -+#endif /* LWIP_LITEOS_COMPAT */ - #define ip_route_get_local_ip(src, dest, netif, ipaddr) do { \ - (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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/netbuf.h 2022-01-26 06:41:32.000000000 +0800 -@@ -55,13 +55,22 @@ - #define NETBUF_FLAG_DESTADDR 0x01 - /** This netbuf includes a checksum */ - #define NETBUF_FLAG_CHKSUM 0x02 -+#if PF_PACKET_SOCKET -+#define NETBUF_FLAG_IFINDEX 0x04 -+#endif /* PF_PACKET_SOCKET */ - - /** "Network buffer" - contains data and addressing info */ - struct netbuf { - struct pbuf *p, *ptr; - ip_addr_t addr; - u16_t port; --#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY -+#if PF_PACKET_SOCKET -+ u16_t hatype; -+ u16_t reserve; /* padded */ -+ u8_t netifindex; -+#endif /* PF_PACKET_SOCKET */ -+ -+#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY || PF_PACKET_SOCKET - u8_t flags; - u16_t toport_chksum; - #if LWIP_NETBUF_RECVINFO -@@ -73,7 +82,7 @@ - /* Network buffer functions: */ - struct netbuf * netbuf_new (void); - void netbuf_delete (struct netbuf *buf); --void * netbuf_alloc (struct netbuf *buf, u16_t size); -+void * netbuf_alloc (struct netbuf *buf, u16_t size, u8_t netconn_type); - void netbuf_free (struct netbuf *buf); - err_t netbuf_ref (struct netbuf *buf, - const void *dataptr, u16_t size); -@@ -93,6 +102,10 @@ - #define netbuf_fromaddr(buf) (&((buf)->addr)) - #define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set(&((buf)->addr), fromaddr) - #define netbuf_fromport(buf) ((buf)->port) -+#if LWIP_LITEOS_COMPAT -+#define netbuf_fromifindex(buf) ((buf)->netifindex) -+#define netbuf_fromhatype(buf) ((buf)->hatype) -+#endif /* LWIP_LITEOS_COMPAT */ - #if LWIP_NETBUF_RECVINFO - #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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/netdb.h 2022-01-26 06:41:32.000000000 +0800 -@@ -36,6 +36,10 @@ - - #include "lwip/opt.h" - -+#if LWIP_LITEOS_COMPAT -+#include -+#endif -+ - #if LWIP_DNS && LWIP_SOCKET - - #include "lwip/arch.h" -@@ -63,6 +67,7 @@ - #define LWIP_DNS_API_DECLARE_STRUCTS 1 - #endif - -+#if !LWIP_LITEOS_COMPAT - #if LWIP_DNS_API_DEFINE_ERRORS - /** Errors used by the DNS API functions, h_errno can be one of them */ - #define EAI_NONAME 200 -@@ -112,23 +117,39 @@ - }; - #endif /* LWIP_DNS_API_DECLARE_STRUCTS */ - --#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) - - #if LWIP_DNS_API_DECLARE_H_ERRNO - /* application accessible error code set by the DNS API functions */ - extern int h_errno; - #endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ -+#endif /* !LWIP_LITEOS_COMPAT */ - -+#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) -+ -+#if LWIP_GETHOSTBYNAME || (defined(LWIP_COMPAT_SOCKETS) && (LWIP_COMPAT_SOCKETS != 2)) - struct hostent *lwip_gethostbyname(const char *name); -+#endif /* LWIP_GETHOSTBYNAME || (defined(LWIP_COMPAT_SOCKETS) && (LWIP_COMPAT_SOCKETS != 2)) */ -+#if (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) - int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, - size_t buflen, struct hostent **result, int *h_errnop); -+#endif /* (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) */ -+#if (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) - void lwip_freeaddrinfo(struct addrinfo *ai); - int lwip_getaddrinfo(const char *nodename, - const char *servname, - const struct addrinfo *hints, - struct addrinfo **res); -- --#if LWIP_COMPAT_SOCKETS -+#endif /* (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) */ -+#if LWIP_DNS_REVERSE -+int lwip_getnameinfo(const struct sockaddr *sa, -+ socklen_t salen, -+ char *host, -+ size_t hostlen, -+ char *serv, -+ size_t servlen, -+ int flags); -+#endif /* LWIP_DNS_REVERSE */ -+#if defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2 - /** @ingroup netdbapi */ - #define gethostbyname(name) lwip_gethostbyname(name) - /** @ingroup netdbapi */ -@@ -139,7 +160,11 @@ - /** @ingroup netdbapi */ - #define getaddrinfo(nodname, servname, hints, res) \ - lwip_getaddrinfo(nodname, servname, hints, res) --#endif /* LWIP_COMPAT_SOCKETS */ -+ -+/* @ingroup netdbapi */ -+#define getnameinfo(sock, sock_size, host, host_len, servname, servname_size, flags) \ -+ lwip_getnameinfo(sock, sock_size, host, host_len, servname, servname_size, flags) -+#endif /* defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2 */ - - #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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/netifapi.h 2022-01-26 06:41:32.000000000 +0800 -@@ -73,6 +73,30 @@ - const ip4_addr_t *netmask, const ip4_addr_t *gw); - #endif /* LWIP_IPV4*/ - -+/* -+Func Name: netifapi_netif_find_by_name -+*/ -+/** -+* @ingroup netifapi_netif -+* -+* @brief -+* This is a thread safe API, used to get the netif pointer whoes name was the input argument. -+* It is recommended to use this API instead of netif_find_by_name(). -+* Call netif_find() in a thread-safe way by running that function inside the tcpip_thread -+* context. -+* -+* @param[in] name Name of the netif. -+* -+* @returns -+* The netif pointer : On success \n -+* NULL : the netif was NOT exist \n -+* -+* @par Related Topics -+* netif_find_by_name() -+* -+*/ -+ -+struct netif* netifapi_netif_find_by_name(const char *name); - err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, - 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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/netif.h 2022-01-26 06:50:34.000000000 +0800 -@@ -48,6 +48,7 @@ - #include "lwip/def.h" - #include "lwip/pbuf.h" - #include "lwip/stats.h" -+#include "lwip/prot/ethernet.h" - - #ifdef __cplusplus - extern "C" { -@@ -67,8 +68,17 @@ - * netif can be identified by in APIs. Composed of - * 2 chars, 3 (max) digits, and 1 \0 - */ --#define NETIF_NAMESIZE 6 -+#ifdef IFNAMSIZ -+#define NETIF_NAMESIZE IFNAMSIZ -+#else -+#define NETIF_NAMESIZE 16 -+#endif - -+#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 - /** - * @defgroup netif_flags Flags - * @ingroup netif -@@ -106,6 +116,17 @@ - * Set by the netif driver in its init function. */ - #define NETIF_FLAG_MLD6 0x40U - -+/** If set, the interface is configured using DHCP. -+ * Set by the DHCP code when starting or stopping DHCP. */ -+#define NETIF_FLAG_DHCP 0x80U -+ -+#if DRIVER_STATUS_CHECK -+/** If set, the netif has send capability. -+ * Set by the netif driver when its is ready to send. */ -+#define NETIF_FLAG_DRIVER_RDY 0x100U -+#endif -+ -+#define NETIF_FLAG_LOOPBACK 0x800 - /** - * @} - */ -@@ -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 */ - -+/** Function pointer of driver set hw address function */ -+typedef u8_t (*drv_set_hwaddr_fn)(struct netif *netif, u8_t *addr, u8_t len); -+ - #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 +273,10 @@ - */ - #define netif_get_client_data(netif, id) (netif)->client_data[(id)] - #endif -+#ifndef LOOPBACK_IF -+/** Type of link layer, these macros should be used for link_layer_type of struct netif */ -+#define LOOPBACK_IF 772 -+#endif - - #if (LWIP_IPV4 && LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) || (LWIP_IPV6 && (LWIP_ND6_NUM_DESTINATIONS > 0x7f)) - typedef u16_t netif_addr_idx_t; -@@ -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; -+ /* This function is to set the mac_address of the interface. */ -+ drv_set_hwaddr_fn drv_set_hwaddr; -+#if LWIP_NETIF_ETHTOOL && LWIP_SOCKET -+ void *ethtool_ops; -+#endif -+#if LWIP_DHCPS -+ /* DHCP Server Informarion for this netif */ -+ struct dhcps *dhcps; -+#endif - #ifdef netif_get_client_data - void* client_data[LWIP_NETIF_CLIENT_DATA_INDEX_MAX + LWIP_NUM_NETIF_CLIENT_DATA]; - #endif - #if LWIP_NETIF_HOSTNAME - /* the hostname for this netif, NULL is a valid value */ -- const char* hostname; -+ char hostname[NETIF_HOSTNAME_MAX_LEN]; - #endif /* LWIP_NETIF_HOSTNAME */ - #if LWIP_CHECKSUM_CTRL_PER_NETIF - u16_t chksum_flags; -@@ -341,13 +398,19 @@ - u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; - /** number of bytes used in hwaddr */ - u8_t hwaddr_len; -+ /* link layer type, ethernet or wifi */ -+ u16_t link_layer_type; /**< Indicates whether the link layer type is ethernet or wifi. */ - /** flags (@see @ref netif_flags) */ -- u8_t flags; -+ u32_t flags; - /** descriptive abbreviation */ -- char name[2]; -- /** number of this interface. Used for @ref if_api and @ref netifapi_netif, -+ char name[NETIF_NAMESIZE]; -+ /** number of this interface. Used for @ref if_api and @ref netifapi_netif, - * as well as for IPv6 zones */ - u8_t num; -+ u8_t ifindex; /* Interface Index mapped to each netif. Starts from 1 */ -+#if DRIVER_STATUS_CHECK -+ s32_t waketime; /**< Started when netif_stop_queue is called from driver. */ -+#endif - #if LWIP_IPV6_AUTOCONFIG - /** is this netif enabled for IPv6 autoconfiguration */ - u8_t ip6_autoconfig_enabled; -@@ -387,6 +450,15 @@ - u16_t loop_cnt_current; - #endif /* LWIP_LOOPBACK_MAX_PBUFS */ - #endif /* ENABLE_LOOPBACK */ -+#if LWIP_SO_DONTROUTE -+ /** The scope of the netif, this is set in ip4_route/ip6_route, the usr can use this -+ to decide whether the netif is in desired sope */ -+ rt_scope_t scope; -+#endif -+#if LWIP_IPV6 -+ /** Call back needs to be registered if adaptor requires notification for IPv6 DAD */ -+ u8_t ipv6_flags; -+#endif - }; - - #if LWIP_CHECKSUM_CTRL_PER_NETIF -@@ -407,9 +479,15 @@ - #endif /* LWIP_SINGLE_NETIF */ - /** The default network interface. */ - extern struct netif *netif_default; -- -+s8_t netif_find_dst_ipaddr(const ip_addr_t *ipaddr, ip_addr_t **dst_addr); - void netif_init(void); - -+#if LWIP_DHCP -+err_t netif_dhcp_off(struct netif *netif); -+#endif -+ -+u8_t netif_check_num_isusing(const char* ifname, const u8_t num); -+ - struct netif *netif_add_noaddr(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input); - - #if LWIP_IPV4 -@@ -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); - --void netif_set_default(struct netif *netif); -+struct netif *netif_find_by_ipaddr(const ip_addr_t *ipaddr); -+ -+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); - void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask); - void netif_set_gw(struct netif *netif, const ip4_addr_t *gw); -+struct netif *netif_find_by_ip4addr(const ip_addr_t *ipaddr); - /** @ingroup netif_ip4 */ - #define netif_ip4_addr(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->ip_addr))) - /** @ingroup netif_ip4 */ -@@ -455,6 +548,9 @@ - - void netif_set_up(struct netif *netif); - void netif_set_down(struct netif *netif); -+err_t netif_set_mtu_api(struct netif *netif, u16_t netif_mtu); -+err_t netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw_len); -+void netif_get_hwaddr(const struct netif *netif, unsigned char *hw_addr, int hw_len); - /** @ingroup netif - * Ask if an interface is up - */ -@@ -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); -+err_t netif_do_add_ipv6_addr(struct netif *netif, void *arguments); -+err_t netif_do_rmv_ipv6_addr(struct netif *netif, void *arguments); - 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-01-21 11:35:10.000000000 +0800 -@@ -0,0 +1,219 @@ -+/** -+ * @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" -+#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 /* ok? wxf0203 */ -+#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 /* 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-01-11 22:35:10.000000000 +0800 -@@ -0,0 +1,105 @@ -+/** -+ * @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" -+#include "lwip/err.h" -+#include "lwip/pbuf.h" -+#include "lwip/netif.h" -+#include "lwip/nip_addr.h" -+#include "lwip/nip.h" -+ -+#if LWIP_NIP -+ -+#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];//headerlen最大多少? -+ 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. */ -+/*保存对另一个pbuf的引用的自定义pbuf, -+在释放该自定义pbuf时释放该引用。这用于创建指向原始pbuf的自定义PBUF_REF。*/ -+struct pbuf_custom_ref { -+ /** 'base class' */ -+ struct pbuf_custom pc; -+ /** pointer to the original pbuf that is referenced */ -+ //指向被引用的原始pbuf的指针 -+ 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-01-21 11:28:28.000000000 +0800 -@@ -0,0 +1,97 @@ -+#ifndef LWIP_HDR_NIP_H -+#define LWIP_HDR_NIP_H -+ -+#include "lwip/opt.h" -+#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 -+//PACK_STRUCT_BEGIN -+/* 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); -+};//PACK_STRUCT_STRUCT; -+//PACK_STRUCT_END -+#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 /* 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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/opt.h 2022-01-26 06:49:56.000000000 +0800 -@@ -529,7 +529,7 @@ - * (only needed if you use the sequential API, like api_lib.c) - */ - #if !defined MEMP_NUM_NETCONN || defined __DOXYGEN__ --#define MEMP_NUM_NETCONN 4 -+#define MEMP_NUM_NETCONN 16 - #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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/pbuf.h 2022-01-26 06:49:32.000000000 +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 -- -+#ifdef LWIP_LITEOS_COMPAT -+#define PBUF_FLAG_HOST 0x100U -+#define PBUF_FLAG_OUTGOING 0x200U -+#endif - /** Main packet buffer struct */ - 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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/priv/api_msg.h 2022-01-26 06:41:32.000000000 +0800 -@@ -46,6 +46,7 @@ - #include "lwip/igmp.h" - #include "lwip/api.h" - #include "lwip/priv/tcpip_priv.h" -+#include "lwip/ip.h" - - #ifdef __cplusplus - extern "C" { -@@ -70,6 +71,14 @@ - #define NETCONN_SHUT_WR 2 - #define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) - -+#if PF_PACKET_SOCKET -+/* Packet Types */ -+#define PACKET_HOST 0 /* To us */ -+#define PACKET_BROADCAST 1 /* To all */ -+#define PACKET_MULTICAST 2 /* To group */ -+#define PACKET_OTHERHOST 3 /* To someone else */ -+#define PACKET_OUTGOING 4 -+#endif - /* IP addresses and port numbers are expected to be in - * the same byte order as in the corresponding pcb. - */ -@@ -88,7 +97,7 @@ - struct netbuf *b; - /** used for lwip_netconn_do_newconn */ - struct { -- u8_t proto; -+ u16_t proto; - } n; - /** used for lwip_netconn_do_bind and lwip_netconn_do_connect */ - struct { -@@ -102,6 +111,12 @@ - u16_t API_MSG_M_DEF(port); - u8_t local; - } ad; -+#if PF_PACKET_SOCKET -+ struct { -+ struct pf_packet_sockaddr_ll API_MSG_M_DEF(ll); -+ u8_t local; -+ } adpkt; -+#endif - /** used for lwip_netconn_do_write */ - struct { - /** current vector to write */ -@@ -205,6 +220,7 @@ - #endif /* TCP_LISTEN_BACKLOG */ - void lwip_netconn_do_write (void *m); - void lwip_netconn_do_getaddr (void *m); -+void lwip_netconn_do_getaddr_pfpkt (void *m); - void lwip_netconn_do_close (void *m); - void lwip_netconn_do_shutdown (void *m); - #if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) -@@ -214,6 +230,7 @@ - - #if LWIP_DNS - void lwip_netconn_do_gethostbyname(void *arg); -+void lwip_netconn_do_getnamebyhost(void *arg); - #endif /* LWIP_DNS */ - - struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); -@@ -233,6 +250,7 @@ - - typedef void (*netifapi_void_fn)(struct netif *netif); - typedef err_t (*netifapi_errt_fn)(struct netif *netif); -+typedef err_t (*netifapi_arg_fn)(struct netif *netif, void *arg); - - struct netifapi_msg { - struct tcpip_api_call_data call; -@@ -245,9 +263,27 @@ - NETIFAPI_IPADDR_DEF(ip4_addr_t, gw); - #endif /* LWIP_IPV4 */ - void *state; -+ } add; -+ -+ struct { -+ const ip_addr_t *ipaddr; -+ } find_by_ipaddr; -+ struct { -+ const char *name; -+ } find_by_name; -+ struct { -+ unsigned char ifindex; -+ } find_by_ifindex; -+ struct { -+#if LWIP_IPV4 -+ ip4_addr_t *ipaddr; -+ ip4_addr_t *netmask; -+ ip4_addr_t *gw; -+#endif /* LWIP_IPV4 */ -+ void *state; - netif_init_fn init; - netif_input_fn input; -- } add; -+ } add_get; - struct { - 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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/priv/sockets_priv.h 2022-01-26 06:41:32.000000000 +0800 -@@ -49,7 +49,6 @@ - extern "C" { - #endif - --#define NUM_SOCKETS MEMP_NUM_NETCONN - - /** This is overridable for the rare case where more than 255 threads - * select on the same socket... -@@ -69,6 +68,10 @@ - struct netconn *conn; - /** data that was left from the previous read */ - union lwip_sock_lastdata lastdata; -+ /** offset in the data that was left from the previous read */ -+ u16_t lastoffset; -+ /* socket level mutex used for multithread recv support */ -+ sys_mutex_t mutex; - #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL - /** number of times data was received, set by event_callback(), - tested by the receive and select functions */ -@@ -158,6 +161,7 @@ - fd_set *exceptset; - #endif /* LWIP_SOCKET_SELECT */ - #if LWIP_SOCKET_POLL -+ - /** fds passed to poll; NULL if select */ - 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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/prot/icmp6.h 2022-01-26 06:41:32.000000000 +0800 -@@ -135,7 +135,7 @@ - # include "arch/bpstruct.h" - #endif - PACK_STRUCT_BEGIN --struct icmp6_hdr { -+struct icmpv6_hdr { - 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-26 06:48:00.000000000 +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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/prot/ip4.h 2022-01-26 06:41:32.000000000 +0800 -@@ -39,6 +39,9 @@ - - #include "lwip/arch.h" - #include "lwip/ip4_addr.h" -+#if LWIP_LITEOS_COMPAT -+#include -+#endif - - #ifdef __cplusplus - extern "C" { -@@ -81,10 +84,12 @@ - PACK_STRUCT_FIELD(u16_t _id); - /* fragment offset field */ - PACK_STRUCT_FIELD(u16_t _offset); -+#if !LWIP_LITEOS_COMPAT - #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 */ -+#endif - /* 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-21 11:29:24.000000000 +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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/raw.h 2022-01-26 06:41:32.000000000 +0800 -@@ -47,6 +47,8 @@ - #include "lwip/ip.h" - #include "lwip/ip_addr.h" - #include "lwip/ip6_addr.h" -+#include "lwip/etharp.h" -+#include "lwip/icmp6.h" - - #ifdef __cplusplus - extern "C" { -@@ -57,6 +59,18 @@ - #define RAW_FLAGS_MULTICAST_LOOP 0x04U - - struct raw_pcb; -+extern struct raw_pcb* raw_pcbs; -+ -+#if PF_PACKET_SOCKET -+extern const struct eth_hdr *g_lwip_current_eth_hdr; -+extern const struct netif *g_lwip_current_netif; -+/* Dest MAC add of current ethernet header of RAW packets -+ * received for PF_PACKET family */ -+#define eth_current_hdr() (g_lwip_current_eth_hdr) -+#define eth_current_netif() (g_lwip_current_netif) -+struct raw_pcb* get_packet_raw_pcbs(void); -+struct raw_pcb* get_all_packet_raw_pcbs(void); -+#endif /* PF_PACKET_SOCKET */ - - /** Function prototype for raw pcb receive callback functions. - * @param arg user supplied argument (raw_pcb.recv_arg) -@@ -77,8 +91,19 @@ - IP_PCB; - - struct raw_pcb *next; -- -+#if PF_PACKET_SOCKET -+ struct raw_pcb *all_next; -+ u8_t netifindex; -+ -+ union { -+ u16_t eth_proto; /* Ethernet HeaderType/Protocol for Packet sockets */ -+#define raw_proto proto.protocol -+ u8_t protocol; /* IP protocol for AF_INET sockets */ -+ } proto; -+#else -+#define raw_proto protocol - u8_t protocol; -+#endif - u8_t flags; - - #if LWIP_MULTICAST_TX_OPTIONS -@@ -115,6 +140,14 @@ - - void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); - -+#if PF_PACKET_SOCKET -+struct raw_pcb * raw_packet_new (u16_t proto); -+void raw_packet_remove (struct raw_pcb *pcb); -+void raw_packet_input (struct pbuf *p, const struct netif *inp, const struct raw_pcb *from); -+err_t raw_packet_sendto (const struct raw_pcb *pcb, struct pbuf *p, u8_t ifindex); -+err_t raw_packet_bind (struct raw_pcb *pcb, u8_t ifindex, u16_t proto); -+#endif /* PF_PACKET_SOCKET */ -+ - #define raw_flags(pcb) ((pcb)->flags) - #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 2022-02-16 16:06:59.186115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/sockets.h 2022-01-27 08:48:38.000000000 +0800 -@@ -51,10 +51,26 @@ - - #include - -+#if LWIP_LITEOS_COMPAT -+#include "sys/select.h" -+#include "sys/socket.h" -+#include "poll.h" -+#include "netinet/tcp.h" -+#endif /* LWIP_LITEOS_COMPAT */ -+ - #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) -@@ -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. */ -+#else /* LWIP_LITEOS_COMPAT */ -+#if LWIP_LITEOS_COMPAT -+#ifndef TCP_KEEPALIVE -+#define TCP_KEEPALIVE 0x02 -+#endif /* TCP_KEEPALIVE */ -+ -+#ifndef SIN_ZERO_LEN -+#define SIN_ZERO_LEN 8 -+#endif /* SIN_ZERO_LEN */ -+ -+#ifndef SOCK_MAX -+#define SOCK_MAX (SOCK_RAW + 1) -+#endif /* SOCK_MAX */ -+ -+#ifndef SOCK_TYPE_MASK -+#define SOCK_TYPE_MASK 0xf -+#endif /* SOCK_TYPE_MASK */ -+#endif -+ - void lwip_socket_thread_init(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ - void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ - -+#if LWIP_IPV6 -+#define LWIP_IS_IPPROTOCOL(protocol) ((protocol) == IPPROTO_IP || (protocol) == IPPROTO_IPV6 || (protocol) == 0) -+#if PF_PACKET -+#define LWIP_IS_VALID_DOMAIN(domain) (((domain) == AF_INET) || ((domain) == AF_INET6) || ((domain) == PF_PACKET)) -+#else -+#define LWIP_IS_VALID_DOMAIN(domain) ((domain) == AF_INET) || ((domain) == AF_INET6) -+#endif -+#else -+#define LWIP_IS_IPPROTOCOL(protocol) ((protocol) == IPPROTO_IP || (protocol) == 0) -+#if PF_PACKET -+#define LWIP_IS_VALID_DOMAIN(domain) (((domain) == AF_INET) || ((domain) == PF_PACKET)) -+#else -+#define LWIP_IS_VALID_DOMAIN(domain) ((domain) == AF_INET) || ((domain) == AF_INET6) -+#endif -+#endif - #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 +604,9 @@ - #if LWIP_SOCKET_SELECT - #define lwip_select select - #endif -+ -+#define lwip_gethostbyname(name) gethostbyname(name) -+ - #if LWIP_SOCKET_POLL - #define lwip_poll poll - #endif -@@ -558,9 +614,18 @@ - #define lwip_inet_ntop inet_ntop - #define lwip_inet_pton inet_pton - -+#if LWIP_DNS -+#define lwip_gethostbyname(name) gethostbyname(name) -+#define lwip_gethostbyname_r gethostbyname_r -+#define lwip_freeaddrinfo freeaddrinfo -+#define lwip_getaddrinfo getaddrinfo -+#define lwip_getnameinfo getnameinfo -+#endif -+ - #if LWIP_POSIX_SOCKETS_IO_NAMES - #define lwip_read read - #define lwip_readv readv -+ - #define lwip_write write - #define lwip_writev writev - #undef lwip_close -@@ -682,7 +747,7 @@ - #ifdef __cplusplus - } - #endif -- -+#endif - #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-26 06:48:14.000000000 +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 07:00:00.000000000 +0700 -+++ b/lwip-2.1.2/src/include/netif/ifaddrs.h 2022-01-26 06:41:32.000000000 +0800 -@@ -0,0 +1,307 @@ -+/* -+ * Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved. -+ * Description: declare BSD APIs : getifaddrs freeifaddrs -+ * Author: none -+ * Create: 2020 -+ */ -+ -+#ifndef __LWIP_IFADDRS_H -+#define __LWIP_IFADDRS_H -+ -+#if (LWIP_IPV4 || LWIP_IPV6) && LWIP_SOCKET -+ -+#include "lwip/netif.h" -+#include "lwip/sockets.h" -+ -+#ifdef LWIP_COMPAT_SOCKETS -+#if LWIP_COMPAT_SOCKETS != 2 -+/* @ingroup socket */ -+#define getifaddrs(ifap) lwip_getifaddrs(ifap) -+#define freeifaddrs(ifa) lwip_freeifaddrs(ifa) -+#else /* LWIP_COMPAT_SOCKETS != 2 */ -+/* @ingroup socket */ -+#define lwip_getifaddrs(ifap) getifaddrs(ifap) -+#define lwip_freeifaddrs(ifa) freeifaddrs(ifa) -+#endif /* LWIP_COMPAT_SOCKETS == 2 */ -+#endif /* LWIP_COMPAT_SOCKETS */ -+ -+#if LWIP_LITEOS_COMPAT -+ -+#ifndef SIOCETHTOOL -+#define SIOCETHTOOL _IOW('i', 56, struct ifreq) -+#endif -+#define IFF_DRV_RUNNING 0x40 -+ -+#else -+#define SIOCADDRT _IOW('R', 9, struct rtentry) -+#define SIOCDELRT _IOW('R', 10, struct rtentry) -+ -+#define SIOCGIFFLAGS _IOWR('i', 17, struct ifreq) /* get ifnet flags */ -+#define SIOCSIFFLAGS _IOW('i', 16, struct ifreq) /* set ifnet flags */ -+#define SIOCGIFADDR _IOWR('i', 33, struct ifreq) /* get ifnet address */ -+#define SIOCSIFADDR _IOW('i', 12, struct ifreq) /* set ifnet address */ -+ -+#define SIOCDIFADDR _IOW('i', 25, struct ifreq) /* delete IF addr */ -+ -+#define SIOCGIFNETMASK _IOWR('i', 37, struct ifreq) /* get net addr mask */ -+#define SIOCSIFNETMASK _IOW('i', 22, struct ifreq) /* set net addr mask */ -+#define SIOCSIFHWADDR _IOW('i', 140, struct ifreq) /* set IF name */ -+#define SIOCGIFHWADDR _IOW('i', 141, struct ifreq) /* set IF name */ -+#define SIOCGIFNAME _IOW('i', 142, struct ifreq) /* set IF name */ -+#define SIOCSIFNAME _IOW('i', 40, struct ifreq) /* set IF name */ -+ -+/** Gets IF mtu */ -+#define SIOCGIFMTU _IOWR('i', 51, struct ifreq) -+/** Sets IF mtu */ -+#define SIOCSIFMTU _IOW('i', 52, struct ifreq) -+/** ethtool */ -+#define SIOCETHTOOL _IOW('i', 56, struct ifreq) -+ -+/* provide PF_PACKET option on SOCK_RAW */ -+#define SIOCGIFINDEX _IOWR('i', 32, struct ifreq) /* get IF index */ -+#define SIOCGIFCONF _IOWR('i', 36, struct ifconf) /* get ifnet list */ -+ -+/** (n) Indicates that the interface is up */ -+#define IFF_UP 0x1 -+/** (i) Indicates that the broadcast address valid */ -+#define IFF_BROADCAST 0x2 -+/** (n) Turns on debugging */ -+#define IFF_DEBUG 0x4 -+/** (i) A loopback net */ -+#define IFF_LOOPBACK 0x8 -+/** (i) Indicates a point-to-point link */ -+#define IFF_POINTOPOINT 0x10 -+/* 0x20 was IFF_SMART */ -+/** (d) Indicates that the resources are allocated */ -+#define IFF_DRV_RUNNING 0x40 -+/** (n) No address resolution protocol */ -+#define IFF_NOARP 0x80 -+/** (n) Receive all packets */ -+#define IFF_PROMISC 0x100 -+/** (n) Receive all multicast packets */ -+#define IFF_ALLMULTI 0x200 -+/** (d) Indicates that the tx hardware queue is full */ -+#define IFF_DRV_OACTIVE 0x400 -+ /** (i) Cannot hear own transmissions */ -+#define IFF_SIMPLEX 0x800 -+/** Per link layer defined bit */ -+#define IFF_LINK0 0x1000 -+/** Per link layer defined bit */ -+#define IFF_LINK1 0x2000 -+/** Per link layer defined bit */ -+#define IFF_LINK2 0x4000 -+/** Use alternate physical connection */ -+#define IFF_ALTPHYS IFF_LINK2 -+/** Supports multicast */ -+#define IFF_MULTICAST 0x8000 -+ /** (i) Unconfigurable using ioctl(2) */ -+#define IFF_CANTCONFIG 0x10000 -+/** (n) User-requested promisc mode */ -+#define IFF_PPROMISC 0x20000 -+/** (n) User-requested IFF_MONITOR mode */ -+#define IFF_MONITOR 0x40000 -+ /** (n) Static ARP */ -+#define IFF_STATICARP 0x80000 -+/** (n) Interface is winding down */ -+#define IFF_DYING 0x200000 -+/** (n) Interface is being renamed */ -+#define IFF_RENAMING 0x400000 -+/** (n) Dialup device with changing addresses */ -+#define IFF_DYNAMIC 0x800000 -+/** (n) Dialup device with changing addresses */ -+#define IFF_DYNAMIC_S 0x1000000 -+ -+#define IFF_RUNNING IFF_DRV_RUNNING -+ -+#ifndef IFNAMSIZ -+#define IFNAMSIZ NETIF_NAMESIZE -+#endif -+ -+struct ifreq { -+#define IFHWADDRLEN 6 -+ union { -+ char ifrn_name[IFNAMSIZ]; -+ } ifr_ifrn; -+ union { -+ struct sockaddr ifru_addr; -+ struct sockaddr ifru_dstaddr; -+ struct sockaddr ifru_broadaddr; -+ struct sockaddr ifru_netmask; -+ struct sockaddr ifru_hwaddr; -+ short ifru_flags[2]; -+ int ifru_ivalue; -+ int ifru_mtu; -+ char ifru_slave[IFNAMSIZ]; -+ char ifru_newname[IFNAMSIZ]; -+ void *ifru_data; -+ } ifr_ifru; -+}; -+#define ifr_name ifr_ifrn.ifrn_name -+#define ifr_hwaddr ifr_ifru.ifru_hwaddr -+#define ifr_addr ifr_ifru.ifru_addr -+#define ifr_dstaddr ifr_ifru.ifru_dstaddr -+#define ifr_broadaddr ifr_ifru.ifru_broadaddr -+#define ifr_netmask ifr_ifru.ifru_netmask -+#define ifr_flags ifr_ifru.ifru_flags[0] /* flags (low 16 bits) */ -+#define ifr_flagshigh ifr_ifru.ifru_flags[1] /* flags (high 16 bits) */ -+#define ifr_metric ifr_ifru.ifru_ivalue -+#define ifr_mtu ifr_ifru.ifru_mtu -+#define ifr_slave ifr_ifru.ifru_slave -+#define ifr_data ifr_ifru.ifru_data -+#define ifr_ifindex ifr_ifru.ifru_ivalue -+#define ifr_bandwidth ifr_ifru.ifru_ivalue -+#define ifr_qlen ifr_ifru.ifru_ivalue -+#define ifr_newname ifr_ifru.ifru_newname -+#define ifr_index ifr_ifindex -+ -+struct ifconf { -+ int ifc_len; -+ union { -+ char *ifcu_buf; -+ struct ifreq *ifcu_req; -+ } ifc_ifcu; -+}; -+ -+#define ifc_buf ifc_ifcu.ifcu_buf -+#define ifc_req ifc_ifcu.ifcu_req -+ -+struct ifaddrs { -+ struct ifaddrs *ifa_next; /**< Pointer to the next network interfaces.f */ -+ char *ifa_name; /**< Pointer to the name of the network interfaces */ -+ unsigned int ifa_flags; /**< Pointer to the status flag. */ -+ struct sockaddr *ifa_addr; /**< Pointer to the address. */ -+ struct sockaddr *ifa_netmask; /**< Pointer to the net masking. */ -+ struct sockaddr *ifa_dstaddr; /**< Pointer to the destination address. */ -+ void *ifa_data; /**< Pointer to the data. */ -+}; -+ -+ #ifndef ifa_broadaddr -+ #define ifa_broadaddr ifa_dstaddr /* brcast address interface */ -+#endif -+ -+struct rtentry { -+ struct sockaddr rt_dst; /**< Indicates the target address. */ -+ struct sockaddr rt_gateway; /**< Indicates the gateway address (RTF_GATEWAY). */ -+ struct sockaddr rt_genmask; /**< Indicates the target network mask (IP). */ -+ unsigned int rt_flags; -+}; -+/** Indicates that the route is usable */ -+#define RTF_UP 0x1 -+/** Indicates that the destination is a gateway */ -+#define RTF_GATEWAY 0x2 -+/** Indicates the host entry (net otherwise) */ -+#define RTF_HOST 0x4 -+/** Indicates the host or net is unreachable */ -+#define RTF_REJECT 0x8 -+/** Created dynamically (by redirect) */ -+#define RTF_DYNAMIC 0x10 -+/** Modified dynamically (by redirect) */ -+#define RTF_MODIFIED 0x20 -+/** Message confirmed. */ -+#define RTF_DONE 0x40 -+/* 0x80 unused, was RTF_DELCLONE */ -+/* 0x100 unused, was RTF_CLONING */ -+/** Indicates that the external daemon resolves name */ -+#define RTF_XRESOLVE 0x200 -+/** DEPRECATED - exists ONLY for backward -+ compatibility */ -+#define RTF_LLINFO 0x400 -+/** Used by apps to add/del L2 entries */ -+#define RTF_LLDATA 0x400 -+/** Manually added */ -+#define RTF_STATIC 0x800 -+ /** Discard packets */ -+#define RTF_BLACKHOLE 0x1000 -+/** Protocol specific routing flag */ -+#define RTF_PROTO2 0x4000 -+/** Protocol specific routing flag */ -+/* 0x10000 unused, was RTF_PRCLONING */ -+#define RTF_PROTO1 0x8000 -+/* 0x10000 unused, was RTF_PRCLONING */ -+/* 0x20000 unused, was RTF_WASCLONED */ -+/** Protocol specific routing flag */ -+#define RTF_PROTO3 0x40000 -+/** MTU was explicitly specified */ -+#define RTF_FIXEDMTU 0x80000 -+/** Route is immutable */ -+#define RTF_PINNED 0x100000 -+/** Route represents a local address */ -+#define RTF_LOCAL 0x200000 -+/** Route represents a broadcast address */ -+#define RTF_BROADCAST 0x400000 -+ /** Route represents a multicast address */ -+#define RTF_MULTICAST 0x800000 -+ /* 0x8000000 and up unassigned */ -+/** Always route dst->src */ -+#define RTF_STICKY 0x10000000 -+/** Radix node head is locked */ -+#define RTF_RNH_LOCKED 0x40000000 -+/** Indicates the compatibility bit for interacting -+ with existing routing apps */ -+#define RTF_GWFLAG_COMPAT 0x80000000 -+ -+/* Mask of RTF flags that are allowed to be modified by RTM_CHANGE. */ -+#define RTF_FMASK \ -+ (RTF_PROTO1 | RTF_PROTO2 | RTF_PROTO3 | RTF_BLACKHOLE | \ -+ RTF_REJECT | RTF_STATIC | RTF_STICKY) -+ -+/** -+* @defgroup ifaddrs_api ifaddrs API -+* This section contains the interfaces to get information about Network interfaces in lwIP. -+* @ingroup socket -+*/ -+ -+/* -+Func Name: lwip_getifaddrs -+*/ -+ -+/** -+* @ingroup ifaddrs_api -+* @brief Creates a linked list of struct ifaddrs, which holds the information -+* about the network interfaces of the local system. The ifa_next field contains a -+* pointer to the next structure on the list, or NULL if this is the last item of the list. -+* The ifa_name points to the null-terminated interface name. The ifa_flags field -+* contains the interface flags. The ifa_addr field points to a structure containing -+* the interface address. The ifa_netmask field points to a structure containing -+* the netmask associated with ifa_addr, if applicable, for the address family. -+* Depending on whether the bit IFF_brcast or IFF_POINTOPOINT is set -+* in ifa_flags (only one can be set at a time), either ifa_broadaddr will contain -+* the broadcast address associated with ifa_addr (if applicable for the address -+* family) or ifa_dstaddr will contain the destination address of the point-to-point -+* interface. -+* For IPv6, stack supports only IFF_UP,IFF_MULTICAST, IFF_DRV_RUNNING, and IFF_LOOPBACK -+* flags. -+* @param[in] ifap Indicates a double pointer to the ifaddrs structure. -+* @return -+* On success, lwip_getifaddrs() returns zero; on error, -1 is returned, and errno is set appropriately. -+* @par Errors -+* @li The lwip_getifaddrs() function shall fail if: -+* - [EACCES] : \n Invalid state of system. -+* - [ENOMEM] : \n In-sufficient memory. -+* @note -+* None -+*/ -+int lwip_getifaddrs(struct ifaddrs **ifap); -+ -+/* -+Func Name: lwip_freeifaddrs -+*/ -+ -+/** -+* @ingroup ifaddrs_api -+* @brief The function lwip_freeifaddrs, provides the list of network interfaces in the ifaddrs* structure. -+* The application has to free the memory of the ifaddrs * structure by using this function. -+* @param[in] ifa Indicates a pointer to the ifaddrs structure. -+* @return -+* Void -+* @note -+* None -+*/ -+void lwip_freeifaddrs(struct ifaddrs *ifa); -+ -+#endif /* !LWIP_LITEOS_COMPAT */ -+int get_ipv6_ifaddr(struct netif *netif, struct ifaddrs *ifaddr, int tmp_index); -+int get_ipv4_ifaddr(struct netif *netif, struct ifaddrs *ifaddr); -+struct ifaddrs_storage *new_ifaddrs_storage(void); -+#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 2022-02-16 16:06:59.190115000 +0800 -+++ b/lwip-2.1.2/src/netif/ethernet.c 2022-01-26 06:47:42.000000000 +0800 -@@ -48,7 +48,7 @@ - #include "lwip/etharp.h" - #include "lwip/ip.h" - #include "lwip/snmp.h" -- -+#include "lwip/raw.h" - #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 @@ - } - } - -+#if PF_PACKET_SOCKET -+ p->flags = (u16_t)(p->flags & ~PBUF_FLAG_OUTGOING); -+ if (get_packet_raw_pcbs() != NULL) { -+ raw_packet_input(p, netif, NULL); -+ } -+#endif /* PF_PACKET_SOCKET */ - 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-29 07:46:14.000000000 +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 - /** -- Gitee From ac04b57007838d6379491d61ea61fa3e18a8025f Mon Sep 17 00:00:00 2001 From: Terder-su Date: Thu, 17 Feb 2022 08:29:46 +0000 Subject: [PATCH 06/14] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20co?= =?UTF-8?q?mponents/net/lwip/patch.sha256?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/lwip/patch.sha256 | 1 - 1 file changed, 1 deletion(-) delete mode 100644 components/net/lwip/patch.sha256 diff --git a/components/net/lwip/patch.sha256 b/components/net/lwip/patch.sha256 deleted file mode 100644 index ce66a54..0000000 --- a/components/net/lwip/patch.sha256 +++ /dev/null @@ -1 +0,0 @@ -4848d0862f749d465d8fe8dd3cc7bffd8d668369982f1f6724fa8e934ebdf6b2 origin.patch -- Gitee From afaa6cb95ff62410960b97488780adeeef5b1e3c Mon Sep 17 00:00:00 2001 From: Terder-su Date: Thu, 17 Feb 2022 08:30:10 +0000 Subject: [PATCH 07/14] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20lwip?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/lwip/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 components/net/lwip/.keep diff --git a/components/net/lwip/.keep b/components/net/lwip/.keep new file mode 100644 index 0000000..e69de29 -- Gitee From 099bcd14aac42d19b135e6abef879b2449b3e4a0 Mon Sep 17 00:00:00 2001 From: Terder-su Date: Thu, 17 Feb 2022 08:30:23 +0000 Subject: [PATCH 08/14] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20co?= =?UTF-8?q?mponents/net/lwip/.keep?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/lwip/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 components/net/lwip/.keep diff --git a/components/net/lwip/.keep b/components/net/lwip/.keep deleted file mode 100644 index e69de29..0000000 -- Gitee From bb75590adea31f31bb0241857f98ca3523be7614 Mon Sep 17 00:00:00 2001 From: Terder-su Date: Thu, 17 Feb 2022 08:33:11 +0000 Subject: [PATCH 09/14] update lwip origin.patch --- components/net/lwip/origin.patch | 8502 +++++++++++++++++++++++++++++ components/net/lwip/origin.sha256 | 1 + 2 files changed, 8503 insertions(+) create mode 100644 components/net/lwip/origin.patch create mode 100644 components/net/lwip/origin.sha256 diff --git a/components/net/lwip/origin.patch b/components/net/lwip/origin.patch new file mode 100644 index 0000000..8c36118 --- /dev/null +++ b/components/net/lwip/origin.patch @@ -0,0 +1,8502 @@ +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 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 + */ + struct netconn * +-netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) ++netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, netconn_callback callback) + { + struct netconn *conn; + API_MSG_VAR_DECLARE(msg); +@@ -292,6 +292,37 @@ + return err; + } + ++#if PF_PACKET_SOCKET ++/** ++ * Get the local or remote IP address and port of a netconn. ++ * For pf packet netconns, this returns the struct pf_packet_sockaddr_ll of the netconn! ++ * @param conn the netconn to query ++ * @param local 1 to get the local IP address, 0 to get the remote one ++ * @return ERR_CONN for invalid connections ++ * ERR_OK if the information was retrieved ++ * ERR_OPNOTSUPP if the option is not support ++ */ ++err_t ++netconn_get_sockaddr_pf_packet(struct netconn *conn, struct pf_packet_sockaddr_ll *ll, u8_t local) ++{ ++ err_t err; ++ API_MSG_VAR_DECLARE(msg); ++ API_MSG_VAR_ALLOC(msg); ++ API_MSG_VAR_REF(msg).conn = conn; ++ API_MSG_VAR_REF(msg).msg.adpkt.local = local; ++#if LWIP_MPU_COMPATIBLE ++ err = netconn_apimsg(lwip_netconn_do_getaddr_pfpkt, &API_MSG_VAR_REF(msg)); ++ *ll = msg->msg.adpkt.ll; ++#else /* LWIP_MPU_COMPATIBLE */ ++ API_MSG_VAR_REF(msg).msg.adpkt.ll = ll; ++ err = netconn_apimsg(lwip_netconn_do_getaddr_pfpkt, &msg); ++#endif /* LWIP_MPU_COMPATIBLE */ ++ API_MSG_VAR_FREE(msg); ++ ++ return err; ++} ++#endif ++ + /** + * @ingroup netconn_common + * Bind a netconn to a specific local IP address and port. +@@ -304,9 +335,13 @@ + * @return ERR_OK if bound, any other err_t on failure + */ + err_t ++#if PF_PACKET_SOCKET ++netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port, u8_t if_idx) ++#else /* PF_PACKET_SOCKET */ + netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port) ++#endif + { +- API_MSG_VAR_DECLARE(msg); ++ API_MSG_VAR_DECLARE(msg); /* struct api_msg *msg */ + err_t err; + + LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); +@@ -332,6 +367,9 @@ + API_MSG_VAR_REF(msg).conn = conn; + API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); + API_MSG_VAR_REF(msg).msg.bc.port = port; ++#if PF_PACKET_SOCKET ++ API_MSG_VAR_REF(msg).msg.bc.if_idx = if_idx; ++#endif /* PF_PACKET_SOCKET */ + err = netconn_apimsg(lwip_netconn_do_bind, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + +@@ -596,7 +634,7 @@ + + NETCONN_MBOX_WAITING_INC(conn); + if (netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK) || +- (conn->flags & NETCONN_FLAG_MBOXCLOSED) || (conn->pending_err != ERR_OK)) { ++ (conn->flags & NETCONN_FLAG_MBOXCLOSED)) { + 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; + } + SYS_ARCH_PROTECT(lev); +- err = conn->pending_err; +- conn->pending_err = ERR_OK; ++ err = conn->last_err; + SYS_ARCH_UNPROTECT(lev); + 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 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; + } + ++#if PF_PACKET_SOCKET ++ /* To get the pkt type filtered in ethernet_input */ ++ q->flags = p->flags; ++#if ETH_PAD_SIZE ++ /* exclude the begining two padding bytes in struct eth_hdr */ ++ if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_PACKET_RAW) && (pbuf_header(q, -ETH_PAD_SIZE))) { ++ (void)pbuf_free(q); ++ memp_free(MEMP_NETBUF, buf); ++ return 0; ++ } ++#endif ++#endif ++ + buf->p = q; + buf->ptr = q; ++#if PF_PACKET_SOCKET ++ /* IP addr is NULL only when RAW packets are received for PF_PACKET sockets */ ++ if (addr == NULL) { ++ ip_addr_set_any(IP_IS_V6_VAL(buf->addr), &buf->addr); ++ buf->port = eth_current_hdr()->type; ++ buf->hatype = eth_current_netif()->link_layer_type; ++ buf->netifindex = eth_current_netif()->ifindex; ++ } else { ++ ip_addr_copy(buf->addr, *ip_current_src_addr()); ++ buf->port = pcb->raw_proto; ++ } ++#else + ip_addr_copy(buf->addr, *ip_current_src_addr()); + buf->port = pcb->protocol; ++#endif + + len = q->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { +@@ -444,7 +470,7 @@ + /* when err is called, the pcb is deallocated, so delete the reference */ + conn->pcb.tcp = NULL; + /* store pending error */ +- conn->pending_err = err; ++ conn->last_err = err; + /* prevent application threads from blocking on 'recvmbox'/'acceptmbox' */ + conn->flags |= NETCONN_FLAG_MBOXCLOSED; + +@@ -627,23 +653,41 @@ + if (msg->conn->pcb.raw != NULL) { + #if LWIP_IPV6 + /* ICMPv6 packets should always have checksum calculated by the stack as per RFC 3542 chapter 3.1 */ +- if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->protocol == IP6_NEXTH_ICMP6) { ++ if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->raw_proto == IP6_NEXTH_ICMP6) { + msg->conn->pcb.raw->chksum_reqd = 1; + msg->conn->pcb.raw->chksum_offset = 2; + } + #endif /* LWIP_IPV6 */ ++ ++#if LWIP_IPV4 ++ /* IP_HDRINCL is enabled by default */ ++ if (!(NETCONNTYPE_ISIPV6(msg->conn->type)) && (msg->msg.n.proto == IPPROTO_RAW)) { ++ raw_set_flags(msg->conn->pcb.raw, RAW_FLAGS_HDRINCL); ++ } ++#endif + raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); + } + break; ++ ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++ msg->conn->pcb.packet_raw = raw_packet_new(msg->msg.n.proto); ++ if (msg->conn->pcb.packet_raw == NULL) { ++ msg->err = ERR_MEM; ++ break; ++ } ++ raw_recv(msg->conn->pcb.packet_raw, recv_raw, msg->conn); ++ break; ++#endif + #endif /* LWIP_RAW */ + #if LWIP_UDP +- case NETCONN_UDP: +- msg->conn->pcb.udp = udp_new_ip_type(iptype); +- if (msg->conn->pcb.udp != NULL) { ++ case NETCONN_UDP: ++ msg->conn->pcb.udp = udp_new_ip_type(iptype); ++ if (msg->conn->pcb.udp != NULL) { + #if LWIP_UDPLITE +- if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { +- udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); +- } ++ if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { ++ udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); ++ } + #endif /* LWIP_UDPLITE */ + if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); +@@ -683,7 +727,7 @@ + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp == NULL) { +- pcb_new(msg); ++ pcb_new(msg); //raw_recv() + } + /* Else? This "new" connection already has a PCB allocated. */ + /* Is this an error condition? Should it be deleted? */ +@@ -713,13 +757,16 @@ + return NULL; + } + +- conn->pending_err = ERR_OK; ++ conn->last_err = ERR_OK; + conn->type = t; + conn->pcb.tcp = NULL; + + /* If all sizes are the same, every compiler should optimize this switch to nothing */ + switch (NETCONNTYPE_GROUP(t)) { + #if LWIP_RAW ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++#endif + case NETCONN_RAW: + size = DEFAULT_RAW_RECVMBOX_SIZE; + break; +@@ -778,8 +825,17 @@ + conn->linger = -1; + #endif /* LWIP_SO_LINGER */ + conn->flags = init_flags; ++#if LWIP_TCP ++ conn->pending_err = 0; ++ conn->refused_data = NULL; ++ ip_addr_set_zero(&conn->remote_ip); ++ conn->remote_port = 0; ++#endif + return conn; + free_and_return: ++ if (sys_sem_valid(&conn->op_completed) != 0) { ++ sys_sem_free(&conn->op_completed); ++ } + memp_free(MEMP_NETCONN, conn); + return NULL; + } +@@ -1160,6 +1216,11 @@ + case NETCONN_RAW: + raw_remove(msg->conn->pcb.raw); + break; ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++ raw_packet_remove(msg->conn->pcb.packet_raw); ++ break; ++#endif + #endif /* LWIP_RAW */ + #if LWIP_UDP + case NETCONN_UDP: +@@ -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)) || ++ ip_addr_ismulticast(API_EXPR_REF(msg->msg.bc.ipaddr)) || ++ netif_ipaddr_isbrdcast(API_EXPR_REF(msg->msg.bc.ipaddr)) || ++ ((netif != NULL) && netif_is_up(netif)))) { ++ msg->err = ERR_NOADDR; ++ } else ++#endif ++ { ++ msg->err = ERR_VAL; ++ if (msg->conn->pcb.tcp != NULL) { ++ switch (NETCONNTYPE_GROUP(msg->conn->type)) { + #if LWIP_RAW + case NETCONN_RAW: +- err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); ++ msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); ++ break; ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++ msg->err = raw_packet_bind(msg->conn->pcb.packet_raw, msg->msg.bc.if_idx, msg->msg.bc.port); + break; ++#endif + #endif /* LWIP_RAW */ + #if LWIP_UDP + case NETCONN_UDP: +- err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); ++ msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; + #endif /* LWIP_UDP */ + #if LWIP_TCP + case NETCONN_TCP: +- err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); ++ if (msg->conn->pcb.tcp->local_port == 0) { ++ msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); ++ } else { ++ msg->err = ERR_VAL; ++ } ++ + break; + #endif /* LWIP_TCP */ + default: +- err = ERR_VAL; ++ msg->err = ERR_OPNOTSUPP; + break; ++ } + } +- } else { +- err = ERR_VAL; + } +- msg->err = err; + TCPIP_APIMSG_ACK(msg); + } + /** +@@ -1351,6 +1435,11 @@ + { + struct api_msg *msg = (struct api_msg *)m; + err_t err; ++ if (ERR_IS_FATAL(msg->conn->last_err)) { ++ msg->err = msg->conn->last_err; ++ TCPIP_APIMSG_ACK(msg); ++ return; ++ } + + if (msg->conn->pcb.tcp == NULL) { + /* This may happen when calling netconn_connect() a second time */ +@@ -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)) { ++#if PF_PACKET_SOCKET ++ struct ip_hdr *iphdr = NULL; ++ ip_addr_t dest_addr; ++ ++ if (!(msg->conn->pcb.raw->flags & RAW_FLAGS_CONNECTED) || ++ ip_addr_isany(&msg->conn->pcb.raw->remote_ip)) { ++ if (raw_is_flag_set(msg->conn->pcb.raw, RAW_FLAGS_HDRINCL)) { ++ if (msg->msg.b->p->len < IP_HLEN) { ++ err = ERR_MSGSIZE; ++ break; ++ } ++ ++ /* IP header already included in p */ ++ iphdr = (struct ip_hdr *)msg->msg.b->p->payload; ++ ip_addr_copy_from_ip4(dest_addr, iphdr->dest); ++ err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &dest_addr); ++ break; ++ } ++ ++ err = ERR_NODEST; ++ break; ++ } ++#endif /* PF_PACKET_SOCKET */ + err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); + } else { + err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr); + } + break; ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++ /* Check if its for sending RAW packets for PF_PACKET family */ ++ if (msg->msg.b->flags & NETBUF_FLAG_IFINDEX) { ++ err = raw_packet_sendto(msg->conn->pcb.packet_raw, msg->msg.b->p, msg->msg.b->netifindex); ++ } else { ++ err = raw_packet_sendto(msg->conn->pcb.packet_raw, msg->msg.b->p, 0); ++ } ++ break; ++#endif + #endif + #if LWIP_UDP + case NETCONN_UDP: +@@ -1868,6 +1990,11 @@ + { + struct api_msg *msg = (struct api_msg *)m; + ++ if ((msg->conn == NULL) || (msg->conn->pcb.tcp == NULL)) { ++ msg->err = ERR_CONN; ++ TCPIP_APIMSG_ACK(msg); ++ return; ++ } + if (msg->conn->pcb.ip != NULL) { + if (msg->msg.ad.local) { + ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), +@@ -1882,10 +2009,18 @@ + #if LWIP_RAW + case NETCONN_RAW: + if (msg->msg.ad.local) { +- API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; ++ ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), ++ msg->conn->pcb.raw->local_ip); ++ API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->raw_proto; + } else { +- /* return an error as connecting is only a helper for upper layers */ +- msg->err = ERR_CONN; ++ if (raw_is_flag_set(msg->conn->pcb.raw, RAW_FLAGS_CONNECTED)) { ++ ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), ++ msg->conn->pcb.raw->remote_ip); ++ API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->raw_proto; ++ } else { ++ /* return an error as connecting is only a helper for upper layers */ ++ msg->err = ERR_CONN; ++ } + } + break; + #endif /* LWIP_RAW */ +@@ -1923,6 +2058,47 @@ + TCPIP_APIMSG_ACK(msg); + } + ++#if PF_PACKET_SOCKET ++/** ++ * Return a pf pkt socket's local address ++ * Called from netconn_getaddr ++ * ++ * @param m the api_msg pointing to the connection ++ */ ++void ++lwip_netconn_do_getaddr_pfpkt(void *m) ++{ ++ struct api_msg *msg = (struct api_msg *)m; ++ struct pf_packet_sockaddr_ll ll; ++ msg->err = ERR_OK; ++ if (msg->conn->pcb.ip != NULL) { ++ /* Non standard way of do it, but doing it :( */ ++ if (msg->msg.adpkt.local) { ++ ll.sll_protocol = msg->conn->pcb.packet_raw->proto.eth_proto; ++ ll.if_idx = msg->conn->pcb.packet_raw->netifindex; ++ struct netif *netif = netif_find_by_ifindex(msg->conn->pcb.packet_raw->netifindex); ++ if (netif == NULL) { ++ LWIP_DEBUGF(SOCKETS_DEBUG, ++ ("lwip_getaddrname:netif not found for given ifindex (%u)\n", ++ msg->conn->pcb.packet_raw->netifindex)); ++ ll.sll_halen = 0; ++ ll.sll_hatype = 0; ++ } else { ++ ll.sll_hatype = netif->link_layer_type; ++ ll.sll_halen = NETIF_MAX_HWADDR_LEN; ++ (void)memcpy_s(ll.sll_addr, ll.sll_halen, netif->hwaddr, NETIF_MAX_HWADDR_LEN); ++ } ++ API_EXPR_DEREF(msg->msg.adpkt.ll) = ll; ++ } else { ++ msg->err = ERR_OPNOTSUPP; ++ } ++ } else { ++ msg->err = ERR_CONN; ++ } ++ TCPIP_APIMSG_ACK(msg); ++} ++#endif ++ + /** + * 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 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" + #include "lwip/memp.h" +- ++#include "lwip/api.h" + #include + + /** +@@ -99,7 +99,7 @@ + * NULL if no memory could be allocated + */ + void * +-netbuf_alloc(struct netbuf *buf, u16_t size) ++netbuf_alloc(struct netbuf *buf, u16_t size, u8_t netconn_type) + { + LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); + +@@ -107,7 +107,22 @@ + if (buf->p != NULL) { + pbuf_free(buf->p); + } +- buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); ++ ++ switch (netconn_type) { ++#if LWIP_RAW ++ case NETCONN_RAW: ++ buf->p = pbuf_alloc(PBUF_IP, size, PBUF_RAM); ++ break; ++#endif /* LWIP_RAW */ ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++ buf->p = pbuf_alloc(PBUF_LINK, size, PBUF_RAM); ++ break; ++#endif /* PF_PACKET_SOCKET */ ++ default: ++ buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); ++ } ++ + if (buf->p == NULL) { + 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 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. */ + #if LWIP_DNS_API_DECLARE_H_ERRNO +-int h_errno; ++int h_err_no; + #endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ + + /** define "hostent" variables storage: 0 if we use a static (but unprotected) +@@ -100,7 +100,7 @@ + err = netconn_gethostbyname(name, &addr); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); +- h_errno = HOST_NOT_FOUND; ++ h_err_no = HOST_NOT_FOUND; + return NULL; + } + +@@ -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; ++#if defined(SIN6_LEN) + sa6->sin6_len = sizeof(struct sockaddr_in6); ++#endif ++ sa6->sin6_flowinfo = 0; + sa6->sin6_port = lwip_htons((u16_t)port_nr); + sa6->sin6_scope_id = ip6_addr_zone(ip_2_ip6(&addr)); + ai->ai_family = AF_INET6; ++ ai->ai_addrlen = sizeof(struct sockaddr_in6); + #endif /* LWIP_IPV6 */ + } else { + #if LWIP_IPV4 +@@ -385,9 +394,9 @@ + /* set up sockaddr */ + inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr)); + sa4->sin_family = AF_INET; +- sa4->sin_len = sizeof(struct sockaddr_in); + sa4->sin_port = lwip_htons((u16_t)port_nr); + ai->ai_family = AF_INET; ++ ai->ai_addrlen = sizeof(struct sockaddr_in); + #endif /* LWIP_IPV4 */ + } + +@@ -403,7 +412,6 @@ + MEMCPY(ai->ai_canonname, nodename, namelen); + ai->ai_canonname[namelen] = 0; + } +- ai->ai_addrlen = sizeof(struct sockaddr_storage); + ai->ai_addr = (struct sockaddr *)sa; + + *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 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) + ++#if LWIP_MPU_COMPATIBLE ++static inline err_t netifapi_msg_alloc(struct netifapi_msg **name) ++{ ++ API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, (*name), ERR_MEM); ++ LWIP_UNUSED_ARG(name); ++ return ERR_OK; ++} ++#else ++static inline err_t netifapi_msg_alloc(struct netifapi_msg *name) ++{ ++ LWIP_UNUSED_ARG(name); ++ return ERR_OK; ++} ++#endif ++ + /** + * Call netif_add() inside the tcpip_thread context. + */ +@@ -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, +- msg->msg.add.input)) { ++ msg->msg.add_get.init, ++ msg->msg.add_get.input)) { + return ERR_IF; + } else { + return ERR_OK; +@@ -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; +- NETIFAPI_VAR_REF(msg).msg.add.init = init; +- NETIFAPI_VAR_REF(msg).msg.add.input = input; ++ NETIFAPI_VAR_REF(msg).msg.add_get.init = init; ++ NETIFAPI_VAR_REF(msg).msg.add_get.input = input; + err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call); + NETIFAPI_VAR_FREE(msg); + return err; +@@ -377,4 +395,60 @@ + return err; + } + ++/** ++ * Call netif_find() inside the tcpip_thread context. ++ */ ++static err_t ++do_netifapi_netif_find_by_name(struct tcpip_api_call_data *m) ++{ ++ struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; ++ ++ msg->netif = netif_find(msg->msg.find_by_name.name); ++ return ERR_OK; ++} ++ ++struct netif* ++netifapi_netif_find_by_name(const char *name) ++{ ++ struct netif *netif = NULL; ++ NETIFAPI_VAR_DECLARE(msg); ++ if (netifapi_msg_alloc(&msg) != ERR_OK) { ++ return NULL; ++ } ++ ++ NETIFAPI_VAR_REF(msg).netif = NULL; ++ NETIFAPI_VAR_REF(msg).msg.find_by_name.name = name; ++ (void)tcpip_api_call(do_netifapi_netif_find_by_name, &API_VAR_REF(msg).call); ++ netif = NETIFAPI_VAR_REF(msg).netif; ++ NETIFAPI_VAR_FREE(msg); ++ return netif; ++} ++ ++/** ++ * Call netif_find_by_ipaddr() inside the tcpip_thread context. ++ */ ++static err_t ++do_netifapi_netif_find_by_ipaddr(struct tcpip_api_call_data *m) ++{ ++ struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; ++ msg->netif = netif_find_by_ipaddr(msg->msg.find_by_ipaddr.ipaddr); ++ return ERR_OK; ++} ++ ++struct netif * ++netifapi_netif_find_by_ipaddr(const ip_addr_t *ipaddr) ++{ ++ struct netif *netif = NULL; ++ NETIFAPI_VAR_DECLARE(msg); ++ if (netifapi_msg_alloc(&msg) != ERR_OK) { ++ return NULL; ++ } ++ ++ NETIFAPI_VAR_REF(msg).netif = NULL; ++ NETIFAPI_VAR_REF(msg).msg.find_by_ipaddr.ipaddr = ipaddr; ++ (void)tcpip_api_call(do_netifapi_netif_find_by_ipaddr, &API_VAR_REF(msg).call); ++ netif = NETIFAPI_VAR_REF(msg).netif; ++ NETIFAPI_VAR_FREE(msg); ++ return netif; ++} + #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 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" + #include "lwip/mld6.h" ++#include "lwip/dhcp.h" + #if LWIP_CHECKSUM_ON_COPY + #include "lwip/inet_chksum.h" + #endif +@@ -85,9 +86,19 @@ + #define API_SELECT_CB_VAR_ALLOC(name, retblock) API_VAR_ALLOC_EXT(struct lwip_select_cb, MEMP_SELECT_CB, name, retblock) + #define API_SELECT_CB_VAR_FREE(name) API_VAR_FREE(MEMP_SELECT_CB, name) + ++#if !LWIP_LITEOS_COMPAT ++#defeine SIN4_LEN(x) \ ++ (x)->sin_len = sizeof(struct sockaddr_in) ++#defeine SIN6_LEN(x) \ ++ (x)->sin6_len = sizeof(struct sockaddr_in6) ++#else ++#define SIN4_LEN(x) ++#define SIN6_LEN(x) ++#endif /* LWIP_LITEOS_COMPAT */ ++ + #if LWIP_IPV4 + #define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \ +- (sin)->sin_len = sizeof(struct sockaddr_in); \ ++ SIN4_LEN(sin); \ + (sin)->sin_family = AF_INET; \ + (sin)->sin_port = lwip_htons((port)); \ + inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \ +@@ -98,8 +109,10 @@ + #endif /* LWIP_IPV4 */ + + #if LWIP_IPV6 ++/* SIN6_LEN macro is to differntiate whether stack is using 4.3BSD or 4.4BSD variants of sockaddr_in6 ++structure */ + #define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \ +- (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ ++ SIN6_LEN(sin6); \ + (sin6)->sin6_family = AF_INET6; \ + (sin6)->sin6_port = lwip_htons((port)); \ + (sin6)->sin6_flowinfo = 0; \ +@@ -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) + ++#if LWIP_LITEOS_COMPAT ++#define VALIDATE_GET_RAW_OPTNAME_RET(_sock, _optname) do { \ ++ if ((_sock)->conn != NULL && (NETCONNTYPE_GROUP((_sock)->conn->type) == NETCONN_RAW) && \ ++ (((_optname) != SO_BROADCAST) && ((_optname) != SO_RCVTIMEO) && \ ++ ((_optname) != SO_RCVBUF) && ((_optname) != SO_TYPE) && \ ++ ((_optname) != SO_DONTROUTE) && ((_optname) != SO_BINDTODEVICE))) { \ ++ done_socket(_sock); \ ++ return ENOPROTOOPT; \ ++ } \ ++ } while (0) ++ ++#if PF_PACKET_SOCKET ++#define VALIDATE_SET_PF_PKT_OPTNAME_RET(_s, _sock, _level, _optname) do { \ ++ if ((_level) == SOL_PACKET && ((_optname) != SO_RCVTIMEO && (_optname) != SO_RCVBUF) && \ ++ (_optname) != SO_ATTACH_FILTER && (_optname) != SO_DETACH_FILTER) { \ ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_PACKET, UNIMPL: optname=0x%x, ..)\n", \ ++ (_s), (_optname))); \ ++ done_socket(_sock); \ ++ return ENOPROTOOPT; \ ++ } \ ++ } while (0) ++ ++#define VALIDATE_GET_PF_PKT_OPTNAME_RET(_s,_sock,_level,_optname) do { \ ++ if ((_sock)->conn != NULL && (NETCONNTYPE_GROUP((_sock)->conn->type) == NETCONN_PACKET_RAW) && \ ++ (_level) == SOL_PACKET && ((_optname) != SO_RCVTIMEO && (_optname) != SO_RCVBUF && (_optname) != SO_TYPE)) { \ ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%p, SOL_PACKET, UNIMPL: optname=0x%x, ..)\n", \ ++ (_s), (_optname))); \ ++ done_socket(_sock); \ ++ return ENOPROTOOPT; \ ++ } \ ++ } while (0) ++ ++#define VALIDATE_LEVEL_PF_PACKET(_sock,_level) \ ++ if ((_sock)->conn != NULL && ((NETCONNTYPE_GROUP(netconn_type(_sock->conn)) == NETCONN_PACKET_RAW \ ++ && SOL_SOCKET != (_level) && SOL_PACKET != (_level)) || \ ++ (NETCONNTYPE_GROUP((_sock)->conn->type) != NETCONN_PACKET_RAW && SOL_PACKET == (_level)))) ++#endif ++#endif /* LWIP_LITEOS_COMPAT */ ++ + /* 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 +564,29 @@ + return sock; + } + ++#if LWIP_LITEOS_COMPAT ++/* get numbers of unused sockets */ ++int get_unused_socket_num(void) ++{ ++ int unused = 0, i; ++ SYS_ARCH_DECL_PROTECT(lev); ++ SYS_ARCH_PROTECT(lev); ++ ++ for (i = 0; i < (int)(NUM_SOCKETS); i++) { ++ if (!sockets[i].conn ++#if LWIP_NETCONN_FULLDUPLEX ++ && !sockets[i].fd_used ++#endif ++ ) { ++ unused++; ++ } ++ } ++ ++ SYS_ARCH_UNPROTECT(lev); ++ return unused; ++} ++#endif /* LWIP_LITEOS_COMPAT */ ++ + /** + * Allocate a new socket for a given netconn. + * +@@ -696,8 +794,10 @@ + } + + IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); +- if (*addrlen > tempaddr.sa.sa_len) { +- *addrlen = tempaddr.sa.sa_len; ++ if (IP_IS_V4_VAL(naddr) && (*addrlen > (int)sizeof(struct sockaddr_in))) { ++ *addrlen = sizeof(struct sockaddr_in); ++ } else if (IP_IS_V6_VAL(naddr) && (*addrlen > (int)sizeof(struct sockaddr_in6))) { ++ *addrlen = sizeof(struct sockaddr_in6); + } + MEMCPY(addr, &tempaddr, *addrlen); + +@@ -722,28 +822,59 @@ + u16_t local_port; + err_t err; + ++#if PF_PACKET_SOCKET ++ const struct sockaddr_ll *name_ll = NULL; ++ u8_t local_if_idx = 0; ++#endif + sock = get_socket(s); + if (!sock) { + return -1; + } + +- if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { +- /* sockaddr does not match socket type (IPv4/IPv6) */ +- sock_set_errno(sock, err_to_errno(ERR_VAL)); +- done_socket(sock); +- return -1; +- } +- + /* check size, family and alignment of 'name' */ +- LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && ++#if PF_PACKET_SOCKET ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { ++ name_ll = (const struct sockaddr_ll *)(void*)name; ++ LWIP_ERROR("lwip_bind: invalid address", ((name_ll != NULL)&&(namelen == sizeof(struct sockaddr_ll)) && ++ ((name_ll->sll_family) == PF_PACKET) && IS_SOCK_ADDR_ALIGNED(name) && ++ (name_ll->sll_ifindex <= LWIP_NETIF_IFINDEX_MAX)), sock_set_errno(sock, err_to_errno(ERR_VAL)); ++ done_socket(sock); return -1); ++ ++ ip_addr_set_any_val(IPADDR_TYPE_V4, local_addr); ++ local_port = name_ll->sll_protocol; ++ local_if_idx = (u8_t)name_ll->sll_ifindex; ++ ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, ", s)); ++ LWIP_DEBUGF(SOCKETS_DEBUG, (" ifindex=%u proto=%"U16_F")\n", local_if_idx, local_port)); ++ } else ++#endif ++ { ++ 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); ++ ++ if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { ++ /* sockaddr does not match socket type (IPv4/IPv6) */ ++ sock_set_errno(sock, err_to_errno(ERR_VAL)); ++ done_socket(sock); ++ return -1; ++ } ++ ++ /* check size, family and alignment of 'name' */ ++ LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)), + sock_set_errno(sock, err_to_errno(ERR_ARG)); done_socket(sock); return -1;); +- LWIP_UNUSED_ARG(namelen); ++ LWIP_UNUSED_ARG(namelen); + +- SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); +- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); +- ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); +- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); ++ SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); ++ ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); ++ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); ++ } + + #if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ +@@ -753,7 +884,11 @@ + } + #endif /* LWIP_IPV4 && LWIP_IPV6 */ + ++#if PF_PACKET_SOCKET ++ err = netconn_bind(sock->conn, &local_addr, local_port, local_if_idx); ++#else /* PF_PACKET_SOCKET */ + err = netconn_bind(sock->conn, &local_addr, local_port); ++#endif + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); +@@ -820,6 +955,14 @@ + return -1; + } + ++#if PF_PACKET_SOCKET ++ if (NETCONN_PACKET_RAW & NETCONNTYPE_GROUP(netconn_type(sock->conn))) { ++ sock_set_errno(sock, EOPNOTSUPP); ++ done_socket(sock); ++ return -1; ++ } ++#endif ++ + 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 +1168,7 @@ + { + int truncated = 0; + union sockaddr_aligned saddr; ++ socklen_t sa_len; + + LWIP_UNUSED_ARG(conn); + +@@ -1041,10 +1185,27 @@ + #endif /* LWIP_IPV4 && LWIP_IPV6 */ + + IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port); +- if (*fromlen < saddr.sa.sa_len) { ++#if LWIP_LITEOS_COMPAT ++ if (IP_IS_V4_VAL(*fromaddr)) { ++ sa_len = sizeof(struct sockaddr_in); ++ } ++#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 */ ++ ++ if (*fromlen < sa_len) { + truncated = 1; +- } else if (*fromlen > saddr.sa.sa_len) { +- *fromlen = saddr.sa.sa_len; ++ } else if (*fromlen > sa_len) { ++ *fromlen = sa_len; + } + MEMCPY(from, &saddr, *fromlen); + return truncated; +@@ -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) { +- lwip_sock_make_addr(sock->conn, netbuf_fromaddr(buf), netbuf_fromport(buf), +- (struct sockaddr *)msg->msg_name, &msg->msg_namelen); ++#if PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT ++ struct sockaddr_ll sll; ++ ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { ++ if (msg->msg_namelen > sizeof(sll)) { ++ msg->msg_namelen = sizeof(sll); ++ } ++ ++ if (msg->msg_namelen) { ++ (void)memset_s(&sll, sizeof(sll), 0, sizeof(sll)); ++ sll.sll_family = PF_PACKET; ++ sll.sll_protocol = netbuf_fromport(buf); ++ sll.sll_hatype = netbuf_fromhatype(buf); ++ sll.sll_ifindex = netbuf_fromifindex(buf); ++ ++ if (buf->p->flags & PBUF_FLAG_LLBCAST) { ++ sll.sll_pkttype = PACKET_BROADCAST; ++ } else if (buf->p->flags & PBUF_FLAG_LLMCAST) { ++ sll.sll_pkttype = PACKET_MULTICAST; ++ } else if (buf->p->flags & PBUF_FLAG_HOST) { ++ sll.sll_pkttype = PACKET_HOST; ++ } else if (buf->p->flags & PBUF_FLAG_OUTGOING) { ++ sll.sll_pkttype = PACKET_OUTGOING; ++ } else { ++ sll.sll_pkttype = PACKET_OTHERHOST; ++ } ++ ++ (void)memcpy_s(msg->msg_name, msg->msg_namelen, (void *)&sll, msg->msg_namelen); ++ ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom_udp_raw(%d): hatype=%u", dbg_s, ntohs(sll.sll_hatype))); ++ LWIP_DEBUGF(SOCKETS_DEBUG, (" packet type = %u\n", sll.sll_pkttype)); ++ } ++ } else ++#endif /* PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT */ ++ { ++ lwip_sock_make_addr(sock->conn, netbuf_fromaddr(buf), netbuf_fromport(buf), ++ (struct sockaddr *)msg->msg_name, &msg->msg_namelen); ++ } + } + } ++ + + /* 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. */ +- if (netbuf_alloc(&chain_buf, (u16_t)size) == NULL) { ++ if (netbuf_alloc(&chain_buf, (u16_t)size, NETCONNTYPE_GROUP(netconn_type(sock->conn))) == NULL) { + err = ERR_MEM; + } else { + /* flatten the IO vectors */ +@@ -1588,8 +1784,14 @@ + struct lwip_sock *sock; + err_t err; + u16_t short_size; +- u16_t remote_port; ++ u16_t remote_port = 0; + struct netbuf buf; ++#if (PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT) ++ const struct sockaddr_ll *to_ll = NULL; ++#endif ++ const struct sockaddr_in *to_in = NULL; ++ ++ unsigned int acceptable_flags = 0; + + sock = get_socket(s); + if (!sock) { +@@ -1608,11 +1810,62 @@ + #endif /* LWIP_TCP */ + } + +- if (size > LWIP_MIN(0xFFFF, SSIZE_MAX)) { +- /* cannot fit into one datagram (at least for us) */ +- sock_set_errno(sock, EMSGSIZE); +- done_socket(sock); +- return -1; ++#if PF_PACKET_SOCKET ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { ++ to_ll = (const struct sockaddr_ll *)(void *)to; ++ ++ LWIP_ERROR("lwip_sendto: invalid address", (((data != NULL) && (size!=0)) && ++ (((to_ll != NULL) && (tolen == sizeof(struct sockaddr_ll))) && ++ ((to_ll->sll_family) == PF_PACKET) && ((((mem_ptr_t)to_ll) % 4) == 0)) && ++ (to_ll->sll_ifindex <= LWIP_NETIF_IFINDEX_MAX)), ++ sock_set_errno(sock, err_to_errno(ERR_VAL)); ++ done_socket(sock); return -1); ++ ++ LWIP_ERROR("lwip_sendto: invalid address family", ((to_ll->sll_family) == PF_PACKET), ++ sock_set_errno(sock, err_to_errno(ERR_AFNOSUPP)); ++ done_socket(sock); return -1); ++ ++ LWIP_ERROR("lwip_sendto: invalid flags. Should be 0", (flags == 0), ++ sock_set_errno(sock, err_to_errno(ERR_OPNOTSUPP)); ++ done_socket(sock); return -1); ++ ++ if (size > LWIP_MAX_PF_RAW_SEND_SIZE) { ++ sock_set_errno(sock, EMSGSIZE); ++ done_socket(sock); ++ return -1; ++ } ++ } else ++#endif /* PF_PACKET_SOCKET */ ++ { ++ to_in = (const struct sockaddr_in *)(void*)to; ++ acceptable_flags = acceptable_flags | MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL; ++ if ((~acceptable_flags) & (unsigned int)flags) { ++ sock_set_errno(sock, err_to_errno(ERR_OPNOTSUPP)); ++ done_socket(sock); ++ return -1; ++ } ++ ++ LWIP_ERROR("lwip_sendto: invalid address", ((data != NULL) && (size!=0) && (flags>=0)), ++ sock_set_errno(sock, err_to_errno(ERR_VAL)); ++ done_socket(sock); return -1); ++ ++ LWIP_ERROR("lwip_sendto: invalid address", (((to_in == NULL) && (tolen == 0)) || ++ (((to_in == NULL) && (tolen != 0)) || IS_SOCK_ADDR_LEN_VALID(tolen))), ++ sock_set_errno(sock, err_to_errno(ERR_VAL)); ++ done_socket(sock); ++ return -1); ++ ++ LWIP_ERROR("lwip_sendto: invalid address", (to == NULL || IS_SOCK_ADDR_TYPE_VALID(to)), ++ sock_set_errno(sock, err_to_errno(ERR_AFNOSUPPORT)); ++ done_socket(sock); ++ return -1); ++ ++ if (size > LWIP_MAX_UDP_RAW_SEND_SIZE) { ++ sock_set_errno(sock, EMSGSIZE); ++ done_socket(sock); ++ return -1; ++ } ++ + } + short_size = (u16_t)size; + LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || +@@ -1626,6 +1879,9 @@ + #if LWIP_CHECKSUM_ON_COPY + buf.flags = 0; + #endif /* LWIP_CHECKSUM_ON_COPY */ ++#if PF_PACKET_SOCKET ++ buf.netifindex = 0; ++#endif + if (to) { + SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port); + } else { +@@ -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)); +- ip_addr_debug_print_val(SOCKETS_DEBUG, buf.addr); +- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); +- ++#if PF_PACKET_SOCKET ++ if (buf.flags & NETBUF_FLAG_IFINDEX) { ++ LWIP_DEBUGF(SOCKETS_DEBUG, (" netifindex = %d\n", buf.netifindex)); ++ } else ++#endif ++ { ++ ip_addr_debug_print_val(SOCKETS_DEBUG, buf.addr); ++ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); ++ } + /* make the buffer point to the data that should be sent */ + #if LWIP_NETIF_TX_SINGLE_PBUF + /* Allocate a new netbuf and copy the data into it. */ +- if (netbuf_alloc(&buf, short_size) == NULL) { ++ if (netbuf_alloc(&buf, short_size, NETCONNTYPE_GROUP(netconn_type(sock->conn))) == NULL) { + err = ERR_MEM; + } else { + #if LWIP_CHECKSUM_ON_COPY +- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { ++#if PF_PACKET_SOCKET ++ if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_PACKET_RAW) && ++ (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW)) ++#else ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) ++#endif ++ { + u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); + netbuf_set_chksum(&buf, chksum); + } else +@@ -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: +- conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), +- (u8_t)protocol, DEFAULT_SOCKET_EVENTCB); +- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", ++#if PF_PACKET_SOCKET ++ if (domain == PF_PACKET) { ++ conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_PACKET_RAW), ++ (u16_t)protocol, event_callback); ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", "PF_PACKET", protocol)); ++ } else ++#endif ++ { ++ conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), ++ (u8_t)protocol, DEFAULT_SOCKET_EVENTCB); ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); ++ } + break; + case SOCK_DGRAM: + conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, +@@ -1983,10 +2269,11 @@ + timeout ? (s32_t)timeout->tv_sec : (s32_t) - 1, + timeout ? (s32_t)timeout->tv_usec : (s32_t) - 1)); + +- if ((maxfdp1 < 0) || (maxfdp1 > LWIP_SELECT_MAXNFDS)) { ++/*if ((maxfdp1 < 0) || (maxfdp1 > LWIP_SELECT_MAXNFDS)) { + set_errno(EINVAL); + return -1; + } ++ */ + + lwip_select_inc_sockets_used(maxfdp1, readset, writeset, exceptset, &used_sockets); + +@@ -2704,12 +2991,60 @@ + ip_addr_t naddr; + u16_t port; + err_t err; ++ socklen_t sa_len; ++ ++#if PF_PACKET_SOCKET ++ struct sockaddr_ll addr_sin; ++ struct pf_packet_sockaddr_ll sll; ++ socklen_t outlen; ++#endif ++ ++ LWIP_ERROR("lwip_getaddrname: invalid arguments", ((name != NULL) && (namelen != NULL)), ++ set_errno(EINVAL); return -1); + + sock = get_socket(s); + if (!sock) { + return -1; + } + ++#if PF_PACKET_SOCKET ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_PACKET_RAW) { ++ err = netconn_get_sockaddr_pf_packet(sock->conn, &sll, local); ++ if (err != ERR_OK) { ++ sock_set_errno(sock, err_to_errno(err)); ++ done_socket(sock); ++ return -1; ++ } ++ ++ (void)memset_s(&addr_sin, sizeof(struct sockaddr_ll), 0, sizeof(struct sockaddr_ll)); ++ addr_sin.sll_family = PF_PACKET; ++ addr_sin.sll_protocol = sll.sll_protocol; ++ addr_sin.sll_pkttype = 0; ++ addr_sin.sll_ifindex = sll.if_idx; ++ addr_sin.sll_hatype = sll.sll_hatype; ++ addr_sin.sll_halen = sll.sll_halen; ++ ++ if ((sll.sll_halen > 0) && (memcpy_s(addr_sin.sll_addr, addr_sin.sll_halen, sll.sll_addr, sll.sll_halen) != EOK)) { ++ sock_set_errno(sock, err_to_errno(ERR_MEM)); ++ done_socket(sock); ++ return -1; ++ } ++ ++ outlen = sizeof(struct sockaddr_ll); ++ if (outlen > *namelen) { ++ outlen = *namelen; ++ } ++ if (memcpy_s(name, *namelen, &addr_sin, outlen) != EOK) { ++ sock_set_errno(sock, err_to_errno(ERR_MEM)); ++ done_socket(sock); ++ return -1; ++ } ++ *namelen = outlen; ++ done_socket(sock); ++ return 0; ++ } ++#endif /* PF_PACKET_SOCKET */ ++ + /* get the IP address and port */ + err = netconn_getaddr(sock->conn, &naddr, &port, local); + if (err != ERR_OK) { +@@ -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)); ++ if (IP_IS_V4_VAL(naddr)) { ++ sa_len = sizeof(struct sockaddr_in); ++ } else { ++ sa_len = sizeof(struct sockaddr_in6); ++ } + +- if (*namelen > saddr.sa.sa_len) { +- *namelen = saddr.sa.sa_len; ++ if (*namelen > sa_len) { ++ *namelen = sa_len; + } + MEMCPY(name, &saddr, *namelen); + +@@ -2775,6 +3115,14 @@ + return -1; + } + ++#if PF_PACKET_SOCKET ++ VALIDATE_LEVEL_PF_PACKET(sock, level) { ++ sock_set_errno(sock, EINVAL); ++ done_socket(sock); ++ return -1; ++ } ++#endif /* PF_PACKET_SOCKET */ ++ + #if LWIP_TCPIP_CORE_LOCKING + /* core-locking can just call the -impl function */ + LOCK_TCPIP_CORE(); +@@ -2826,8 +3174,9 @@ + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); + #endif /* LWIP_TCPIP_CORE_LOCKING */ +- +- sock_set_errno(sock, err); ++ if (err != ERR_OK) { ++ sock_set_errno(sock, err); ++ } + done_socket(sock); + return err ? -1 : 0; + } +@@ -2897,6 +3246,11 @@ + + /* Level: SOL_SOCKET */ + case SOL_SOCKET: ++#if PF_PACKET_SOCKET ++ case SOL_PACKET: ++ VALIDATE_GET_PF_PKT_OPTNAME_RET(s, sock, level, optname); ++#endif /* PF_PACKET_SOCKET */ ++ VALIDATE_GET_RAW_OPTNAME_RET(sock, optname); + switch (optname) { + + #if LWIP_TCP +@@ -2920,6 +3274,10 @@ + #if SO_REUSE + case SO_REUSEADDR: + #endif /* SO_REUSE */ ++ if (sock->conn == NULL) { ++ done_socket(sock); ++ return EINVAL; ++ } + if ((optname == SO_BROADCAST) && + (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP)) { + done_socket(sock); +@@ -2937,6 +3295,9 @@ + case SO_TYPE: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) { ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++#endif + case NETCONN_RAW: + *(int *)optval = SOCK_RAW; + break; +@@ -2948,9 +3309,16 @@ + break; + default: /* unrecognized socket type */ + *(int *)optval = netconn_type(sock->conn); ++#if PF_PACKET_SOCKET ++ LWIP_DEBUGF(SOCKETS_DEBUG, ++ ("lwip_getsockopt(%d, %s, SO_TYPE): unrecognized socket type %d\n", ++ s, (NETCONN_PACKET_RAW != NETCONNTYPE_GROUP(sock->conn->type)) ? "SOL_SOCKET" : "SOL_PACKET", ++ *(int *)optval)); ++#else + LWIP_DEBUGF(SOCKETS_DEBUG, + ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", + s, *(int *)optval)); ++#endif + } /* switch (netconn_type(sock->conn)) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", + s, *(int *)optval)); +@@ -3739,92 +4107,450 @@ + return err; + } + +-int +-lwip_ioctl(int s, long cmd, void *argp) ++#if PF_PACKET_SOCKET || LOSCFG_COMPONENTS_UPNP ++#if LWIP_IOCTL_IF ++static u8_t lwip_ioctl_internal_SIOCGIFCONF(struct ifreq *ifr) ++{ ++ struct ifconf *ifc = NULL; ++ struct netif *netif = NULL; ++ struct ifreq ifreq; ++ struct sockaddr_in *sock_in = NULL; ++ int pos; ++ int len; ++ int ret; ++ ++ /* Format the caller's buffer. */ ++ ifc = (struct ifconf*)ifr; ++ len = ifc->ifc_len; ++ ++ /* Loop over the interfaces, and write an info block for each. */ ++ pos = 0; ++ for (netif = netif_list; netif != NULL; netif = netif->next) { ++ if (ifc->ifc_buf == NULL) { ++ pos = (pos + (int)sizeof(struct ifreq)); ++ continue; ++ } ++ ++ if (len < (int)sizeof(ifreq)) { ++ break; ++ } ++ ++ if (memset_s(&ifreq, sizeof(struct ifreq), 0, sizeof(struct ifreq)) != EOK) { ++ return ENOBUFS; ++ } ++ if (netif->link_layer_type == LOOPBACK_IF) { ++ ret = snprintf_s(ifreq.ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s", netif->name); ++ if ((ret <= 0) || (ret >= IFNAMSIZ)) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed.")); ++ return ENOBUFS; ++ } ++ } else { ++ ret = snprintf_s(ifreq.ifr_name, NETIF_NAMESIZE, NETIF_NAMESIZE - 1, "%s%"U8_F, netif->name, netif->num); ++ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed.")); ++ return ENOBUFS; ++ } ++ } ++ ++ sock_in = (struct sockaddr_in *)&ifreq.ifr_addr; ++ sock_in->sin_family = AF_INET; ++ sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr; ++ if (memcpy_s(ifc->ifc_buf + pos, sizeof(struct ifreq), &ifreq, sizeof(struct ifreq)) != EOK) { ++ return ENOBUFS; ++ } ++ pos += (int)sizeof(struct ifreq); ++ len -= (int)sizeof(struct ifreq); ++ } ++ ++ ifc->ifc_len = pos; ++ ++ return 0; ++} ++ ++static u8_t lwip_ioctl_internal_SIOCGIFADDR(struct ifreq *ifr) ++{ ++ struct netif *netif = NULL; ++ struct sockaddr_in *sock_in = NULL; ++ ++ /* get netif ipaddr */ ++ netif = netif_find(ifr->ifr_name); ++ if (netif == NULL) { ++ return ENODEV; ++ } else { ++ sock_in = (struct sockaddr_in *)&ifr->ifr_addr; ++ sock_in->sin_family = AF_INET; ++ sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr; ++ return 0; ++ } ++} ++ ++static u8_t lwip_ioctl_internal_SIOCSIFFLAGS(const struct ifreq *ifr) ++{ ++ struct netif *netif = NULL; ++ ++ /* set netif hw addr */ ++ netif = netif_find(ifr->ifr_name); ++ if (netif == NULL) { ++ return ENODEV; ++ } ++#if LWIP_HAVE_LOOPIF ++ else if (netif->link_layer_type == LOOPBACK_IF) { ++ return EPERM; ++ } ++#endif /* LWIP_HAVE_LOOPIF */ ++ else { ++ if ((ifr->ifr_flags & IFF_UP) && !(netif->flags & NETIF_FLAG_UP)) { ++ (void)netif_set_up(netif); ++ } else if (!(ifr->ifr_flags & IFF_UP) && (netif->flags & NETIF_FLAG_UP)) { ++ (void)netif_set_down(netif); ++ } ++ if ((ifr->ifr_flags & IFF_RUNNING) && !(netif->flags & NETIF_FLAG_LINK_UP)) { ++ (void)netif_set_link_up(netif); ++ } else if (!(ifr->ifr_flags & IFF_RUNNING) && (netif->flags & NETIF_FLAG_LINK_UP)) { ++ (void)netif_set_link_down(netif); ++ } ++ ++ if (ifr->ifr_flags & IFF_BROADCAST) { ++ netif->flags |= NETIF_FLAG_BROADCAST; ++ } else { ++ netif->flags = netif->flags & (~NETIF_FLAG_BROADCAST); ++ } ++ if (ifr->ifr_flags & IFF_NOARP) { ++ netif->flags = (netif->flags & (~NETIF_FLAG_ETHARP)); ++ } else { ++ netif->flags |= NETIF_FLAG_ETHARP; ++ } ++ ++ if (ifr->ifr_flags & IFF_MULTICAST) { ++#if LWIP_IGMP ++ netif->flags |= NETIF_FLAG_IGMP; ++#endif /* LWIP_IGMP */ ++#if LWIP_IPV6 && LWIP_IPV6_MLD ++ netif->flags |= NETIF_FLAG_MLD6; ++#endif /* LWIP_IPV6_MLD */ ++ } ++ else { ++#if LWIP_IGMP ++ netif->flags = (netif->flags & ~NETIF_FLAG_IGMP); ++#endif /* LWIP_IGMP */ ++#if LWIP_IPV6 && LWIP_IPV6_MLD ++ netif->flags = (netif->flags & ~NETIF_FLAG_MLD6); ++#endif /* LWIP_IPV6_MLD */ ++ } ++ ++#if 0 ++ if (ifr->ifr_flags & IFF_DYNAMIC) { ++ (void)dhcp_start(netif); ++ } else { ++ dhcp_stop(netif); ++ dhcp_cleanup(netif); ++ } ++#endif ++ ++ return 0; ++ } ++} ++ ++static u8_t lwip_ioctl_internal_SIOCGIFFLAGS(struct ifreq *ifr) ++{ ++ struct netif *netif = NULL; ++ ++ /* set netif hw addr */ ++ netif = netif_find(ifr->ifr_name); ++ if (netif == NULL) { ++ return ENODEV; ++ } else { ++ if (netif->flags & NETIF_FLAG_UP) { ++ ifr->ifr_flags |= IFF_UP; ++ } else { ++ ifr->ifr_flags &= ~IFF_UP; ++ } ++ if (netif->flags & NETIF_FLAG_LINK_UP) { ++ ifr->ifr_flags |= IFF_RUNNING; ++ } else { ++ ifr->ifr_flags &= ~IFF_RUNNING; ++ } ++ if (netif->flags & NETIF_FLAG_BROADCAST) { ++ ifr->ifr_flags |= IFF_BROADCAST; ++ } else { ++ ifr->ifr_flags &= ~IFF_BROADCAST; ++ } ++ if (netif->flags & NETIF_FLAG_ETHARP) { ++ ifr->ifr_flags &= ~IFF_NOARP; ++ } else { ++ ifr->ifr_flags |= IFF_NOARP; ++ } ++ ++#if LWIP_IGMP || LWIP_IPV6_MLD ++ if ( ++#if LWIP_IGMP ++ (netif->flags & NETIF_FLAG_IGMP) ++#endif /* LWIP_IGMP */ ++#if LWIP_IGMP && LWIP_IPV6_MLD ++ || ++#endif /* LWIP_IGMP && LWIP_IPV6_MLD */ ++#if LWIP_IPV6_MLD ++ (netif->flags & NETIF_FLAG_MLD6) ++#endif /* LWIP_IPV6_MLD */ ++ ) { ++ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_MULTICAST); ++ } else { ++ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_MULTICAST)); ++ } ++#endif /* LWIP_IGMP || LWIP_IPV6_MLD */ ++ ++#if LWIP_DHCP ++ if (netif->flags & NETIF_FLAG_DHCP) { ++ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_DYNAMIC); ++ } else { ++ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_DYNAMIC)); ++ } ++#endif ++ ++#if LWIP_HAVE_LOOPIF ++ if (netif->link_layer_type == LOOPBACK_IF) { ++ ifr->ifr_flags |= IFF_LOOPBACK; ++ } ++#endif ++ ++ return 0; ++ } ++} ++ ++static u8_t lwip_ioctl_internal_SIOCGIFNAME(struct ifreq *ifr) ++{ ++ struct netif *netif = NULL; ++ int ret; ++ ++ for (netif = netif_list; netif != NULL; netif = netif->next) { ++ if (ifr->ifr_ifindex == netif->ifindex) { ++ break; ++ } ++ } ++ ++ if (netif == NULL) { ++ return ENODEV; ++ } ++ if (netif->link_layer_type == LOOPBACK_IF) { ++ ret = snprintf_s(ifr->ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s", netif->name); ++ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { ++ return ENOBUFS; ++ } ++ } else { ++ ret = snprintf_s(ifr->ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s%"U8_F, netif->name, netif->num); ++ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { ++ return ENOBUFS; ++ } ++ } ++ return 0; ++} ++ ++static u8_t lwip_ioctl_internal_SIOCGIFINDEX(struct ifreq *ifr) ++{ ++ struct netif *netif = NULL; ++ netif = netif_find(ifr->ifr_name); ++ if (netif == NULL) { ++ return ENODEV; ++ } ++ ifr->ifr_ifindex = netif->ifindex; ++ return 0; ++} ++#endif /* LWIP_IOCTL_IF */ ++#endif /* PF_PACKET_SOCKET */ ++ ++#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE ++static u8_t lwip_ioctl_internal_FIONREAD(struct lwip_sock *sock, void *argp) + { +- struct lwip_sock *sock = get_socket(s); +- u8_t val; + #if LWIP_SO_RCVBUF + int recv_avail; +-#endif /* LWIP_SO_RCVBUF */ ++#endif ++#if LWIP_FIONREAD_LINUXMODE ++ SYS_ARCH_DECL_PROTECT(lev); ++#endif + +- if (!sock) { +- return -1; ++ if (!argp) { ++ return EINVAL; + } + +- switch (cmd) { +-#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE +- case FIONREAD: +- if (!argp) { +- sock_set_errno(sock, EINVAL); +- done_socket(sock); +- return -1; +- } ++ lwip_sock_lock(sock); + #if LWIP_FIONREAD_LINUXMODE +- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { +- struct netbuf *nb; +- if (sock->lastdata.netbuf) { +- nb = sock->lastdata.netbuf; +- *((int *)argp) = nb->p->tot_len; ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { ++ struct netbuf *nb; ++ if (sock->lastdata.netbuf) { ++ nb = sock->lastdata.netbuf; ++ *((int *)argp) = nb->p->tot_len; ++ } else { ++ struct netbuf *rxbuf; ++ err_t err; ++ ++ SYS_ARCH_PROTECT(lev); ++ if (sock->rcvevent <= 0) { ++ *((int*)argp) = 0; ++ SYS_ARCH_UNPROTECT(lev); ++ } else { ++ SYS_ARCH_UNPROTECT(lev); ++ err = netconn_recv_udp_raw_netbuf_flags(sock->conn, &rxbuf, NETCONN_DONTBLOCK); ++ if (err != ERR_OK) { ++ *((int *)argp) = 0; + } else { +- struct netbuf *rxbuf; +- err_t err = netconn_recv_udp_raw_netbuf_flags(sock->conn, &rxbuf, NETCONN_DONTBLOCK); +- if (err != ERR_OK) { +- *((int *)argp) = 0; +- } else { +- sock->lastdata.netbuf = rxbuf; +- *((int *)argp) = rxbuf->p->tot_len; +- } ++ sock->lastdata.netbuf = rxbuf; ++ *((int *)argp) = rxbuf->p->tot_len; + } +- done_socket(sock); +- return 0; + } ++ } ++ ++ lwip_sock_unlock(sock); ++ return 0; ++ } + #endif /* LWIP_FIONREAD_LINUXMODE */ + + #if LWIP_SO_RCVBUF +- /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ +- SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); +- if (recv_avail < 0) { +- recv_avail = 0; +- } ++ /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ ++ SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); ++ if (recv_avail < 0) { ++ recv_avail = 0; ++ } + +- /* Check if there is data left from the last recv operation. /maq 041215 */ +- if (sock->lastdata.netbuf) { +- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { +- recv_avail += sock->lastdata.pbuf->tot_len; +- } else { +- recv_avail += sock->lastdata.netbuf->p->tot_len; +- } +- } +- *((int *)argp) = recv_avail; ++ /* Check if there is data left from the last recv operation. /maq 041215 */ ++ if (sock->lastdata.netbuf) { ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { ++ recv_avail += sock->lastdata.pbuf->tot_len; ++ } else { ++ recv_avail += sock->lastdata.netbuf->p->tot_len; ++ } ++ } ++ *((int *)argp) = recv_avail; + +- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t *)argp))); +- sock_set_errno(sock, 0); +- done_socket(sock); +- return 0; ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(FIONREAD, %p) = %"U16_F"\n", argp, *((u16_t *)argp))); ++ lwip_sock_unlock(sock); ++ return 0; + #else /* LWIP_SO_RCVBUF */ +- break; ++ lwip_sock_unlock(sock); ++ return ENOSYS; + #endif /* LWIP_SO_RCVBUF */ ++} + #endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ + +- case (long)FIONBIO: +- val = 0; +- if (argp && *(int *)argp) { +- val = 1; ++static u8_t lwip_ioctl_internal_FIONBIO(struct lwip_sock *sock, const void *argp) ++{ ++ u8_t val = 0; ++ SYS_ARCH_DECL_PROTECT(lev); ++ if (argp == NULL) { ++ return EINVAL; ++ } ++ if (*(int *)argp) { ++ val = 1; ++ } ++ SYS_ARCH_PROTECT(lev); ++ netconn_set_nonblocking(sock->conn, val); ++ SYS_ARCH_UNPROTECT(lev); ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(FIONBIO, %d)\n", val)); ++ return 0; ++} ++ ++static u8_t lwip_ioctl_impl(struct lwip_sock *sock, long cmd, void *argp) ++{ ++ u8_t err = 0; ++#if LWIP_NETIF_ETHTOOL ++ s32_t ret; ++#endif ++#if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_IF || LWIP_NETIF_ETHTOOL ++ struct ifreq *ifr = (struct ifreq *)argp; ++#endif ++#if LWIP_IOCTL_ROUTE ++ struct rtentry *rmten = (struct rtentry *)argp; ++#endif ++#if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_ROUTE || LWIP_IOCTL_IF ++ u8_t is_ipv6 = NETCONNTYPE_ISIPV6(sock->conn->type); ++#endif ++ ++ LWIP_ASSERT("no socket given", sock != NULL); ++ ++ switch (cmd) { ++#if PF_PACKET_SOCKET || LOSCFG_COMPONENTS_UPNP ++#if LWIP_IOCTL_IF ++ case SIOCGIFCONF: ++ /* Do not allow if socket is AF_INET6 */ ++ if (is_ipv6) { ++ err = EINVAL; ++ } else { ++ err = lwip_ioctl_internal_SIOCGIFCONF(ifr); //add: SIOCGIFCONF + } +- netconn_set_nonblocking(sock->conn, val); +- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); +- sock_set_errno(sock, 0); +- done_socket(sock); +- return 0; ++ break; ++ case SIOCGIFADDR: ++ if (is_ipv6) { ++ err = EINVAL; ++ } else { ++ err = lwip_ioctl_internal_SIOCGIFADDR(ifr); //add: SIOCGIFADDR ++ } ++ break; ++ case SIOCSIFFLAGS: ++ err = lwip_ioctl_internal_SIOCSIFFLAGS(ifr); //add: SIOCSIFFLAGS ++ break; ++ case SIOCGIFFLAGS: ++ err = lwip_ioctl_internal_SIOCGIFFLAGS(ifr); //add: SIOCSIFFLAGS ++ break; ++ case SIOCGIFNAME: ++ err = lwip_ioctl_internal_SIOCGIFNAME(ifr); //add: SIOCGIFNAME ++ break; ++ /* Need to support the get index through ioctl ++ * As of now the options is restricted to PF_PACKET scenario , so removed the compiler flag Begin ++ */ ++ case SIOCGIFINDEX: ++ err = lwip_ioctl_internal_SIOCGIFINDEX(ifr); //add: SIOCGIFINDEX ++ break; ++#endif /* LWIP_IOCTL_IF */ ++#else ++ (void)ifr; ++ (void)is_ipv6; ++#endif /* PF_PACKET_SOCKET */ ++#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE ++ case FIONREAD: ++ err = lwip_ioctl_internal_FIONREAD(sock, argp); ++ break; ++#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ + ++ case FIONBIO: ++ err = lwip_ioctl_internal_FIONBIO(sock, argp); ++ break; ++ /* -1 should return EINVAL */ ++ case -1: ++ err = EINVAL; ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl_impl(INVALID: 0x%lx)\n", cmd)); ++ break; + default: ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(UNIMPL: 0x%lx, %p)\n", cmd, argp)); ++ err = ENOSYS; /* not yet implemented */ + break; + } /* switch (cmd) */ +- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); +- sock_set_errno(sock, ENOSYS); /* not yet implemented */ ++ ++ return err; ++} ++ ++int ++lwip_ioctl(int s, long cmd, void *argp) ++{ ++ u8_t err; ++ struct lwip_sock *sock = get_socket(s); ++ if (!sock) { ++ /* get_socket has updated errno */ ++ return -1; ++ } ++ if (argp == NULL) { ++ sock_set_errno(sock, EFAULT); ++ done_socket(sock); ++ return -1; ++ } ++ ++ LOCK_TCPIP_CORE(); ++ err = lwip_ioctl_impl(sock, cmd, argp); ++ UNLOCK_TCPIP_CORE(); ++ if (err != ERR_OK) { ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, cmd: 0x%lx, %p)\n", s, cmd, argp)); ++ sock_set_errno(sock, err); ++ } + done_socket(sock); +- return -1; ++ return (err == 0) ? 0 : -1; + } + + /** A minimal implementation of fcntl. +@@ -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; +- + break; + 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 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 @@ + } + + static void +-recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) ++tftp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) + { + u16_t *sbuf = (u16_t *) p->payload; + int opcode; +@@ -416,7 +416,7 @@ + tftp_state.last_data = NULL; + tftp_state.upcb = pcb; + +- udp_recv(pcb, recv, NULL); ++ udp_recv(pcb, tftp_recv, NULL); + + 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 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) + { +- if (cp != NULL) { ++ if (cp != NULL && addr != NULL) { + const char *c; + for (c = cp; *c != 0; c++) { + if (*c == ':') { + /* contains a colon: IPv6 address */ +- if (addr) { +- IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); +- } ++ IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); + return ip6addr_aton(cp, ip_2_ip6(addr)); + } else if (*c == '.') { + /* contains a dot: IPv4 address */ +@@ -137,9 +147,7 @@ + } + } + /* call ip4addr_aton as fallback or if IPv4 was found */ +- if (addr) { +- IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); +- } ++ IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); + return ip4addr_aton(cp, ip_2_ip4(addr)); + } + return 0; +@@ -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 */ + ++struct netif* ++ip_route_pcb(const ip_addr_t *dest, const struct ip_pcb* pcb) ++{ ++ struct netif *netif = NULL; ++#if LWIP_SO_DONTROUTE ++ rt_scope_t scope = RT_SCOPE_UNIVERSAL; ++ ++ LWIP_ASSERT("Expecting ipaddr to be not NULL ", dest != NULL); ++ if (pcb != NULL) { ++ scope = ip_get_option(pcb, SOF_DONTROUTE) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSAL; ++ } ++#endif ++ ++ if ((pcb != NULL) && (pcb->netif_idx != NETIF_NO_INDEX)) { ++ return netif_find_by_ifindex(pcb->netif_idx); ++ } ++ ++ if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { ++ /* Don't call ip_route() with IP_ANY_TYPE */ ++ netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(dest)), dest); ++ } else { ++ netif = ip_route(&pcb->local_ip, dest); ++ } ++ ++ if (netif == NULL) { ++ return NULL; ++ } ++ ++#if LWIP_SO_DONTROUTE ++ if (netif->scope < scope) { ++ return NULL; ++ } ++#endif ++ return netif; ++} ++ ++#if LWIP_INET_ADDR_FUNC ++in_addr_t inet_addr(const char *cp) ++{ ++ LWIP_ERROR("inet_aton:cp is NULL", (cp != NULL), return (INADDR_NONE)); ++ return ipaddr_addr(cp); ++} ++#endif ++ ++#if LWIP_INET_ATON_FUNC ++int inet_aton(const char *cp, struct in_addr *inp) ++{ ++ LWIP_ERROR("inet_aton:cp is NULL", (cp != NULL), return 0); ++ return ip4addr_aton(cp, (ip4_addr_t *)inp); ++} ++#endif ++ ++#if LWIP_INET_NTOA_FUNC ++char* inet_ntoa(struct in_addr in) ++{ ++ return ip4addr_ntoa((const ip4_addr_t *)&in); ++} ++#endif ++ + #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 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) + { +- struct icmp6_hdr *icmp6hdr; ++ struct icmpv6_hdr *icmp6hdr; + struct pbuf *r; + const ip6_addr_t *reply_src; + + ICMP6_STATS_INC(icmp6.recv); + + /* Check that ICMPv6 header fits in payload */ +- if (p->len < sizeof(struct icmp6_hdr)) { ++ if (p->len < sizeof(struct icmpv6_hdr)) { + /* drop short packets */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.lenerr); +@@ -97,7 +97,7 @@ + return; + } + +- icmp6hdr = (struct icmp6_hdr *)p->payload; ++ icmp6hdr = (struct icmpv6_hdr *)p->payload; + + #if CHECKSUM_CHECK_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP6) { +@@ -386,10 +386,10 @@ + const ip6_addr_t *reply_src, const ip6_addr_t *reply_dest, struct netif *netif) + { + struct pbuf *q; +- struct icmp6_hdr *icmp6hdr; ++ struct icmpv6_hdr *icmp6hdr; + + /* ICMPv6 header + IPv6 header + data */ +- q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, ++ q = pbuf_alloc(PBUF_IP, sizeof(struct icmpv6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, + PBUF_RAM); + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n")); +@@ -397,15 +397,15 @@ + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp 6message", +- (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); ++ (q->len >= (sizeof(struct icmpv6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); + +- icmp6hdr = (struct icmp6_hdr *)q->payload; ++ icmp6hdr = (struct icmpv6_hdr *)q->payload; + icmp6hdr->type = type; + icmp6hdr->code = code; + icmp6hdr->data = lwip_htonl(data); + + /* copy fields from original packet */ +- SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload, ++ SMEMCPY((u8_t *)q->payload + sizeof(struct icmpv6_hdr), (u8_t *)p->payload, + IP6_HLEN + LWIP_ICMP6_DATASIZE); + + /* 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 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 */ + { +- struct icmp6_hdr *icmp6hdr; /* Packet too big message */ ++ struct icmpv6_hdr *icmp6hdr; /* Packet too big message */ + struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */ + u32_t pmtu; + ip6_addr_t destination_address; + + /* Check that ICMPv6 header + IPv6 header fit in payload */ +- if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { ++ if (p->len < (sizeof(struct icmpv6_hdr) + IP6_HLEN)) { + /* drop short packets */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); +@@ -908,8 +908,8 @@ + return; + } + +- icmp6hdr = (struct icmp6_hdr *)p->payload; +- ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); ++ icmp6hdr = (struct icmpv6_hdr *)p->payload; ++ ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmpv6_hdr)); + + /* 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 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" + #endif ++#include "lwip/tcpip.h" ++ + + #if LWIP_NETIF_STATUS_CALLBACK + #define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) +@@ -229,6 +231,8 @@ + return ip_input(p, inp); + } + ++static u8_t netif_alloc_ifindex(void); ++ + /** + * @ingroup netif + * Add a network interface to the list of lwIP netifs. +@@ -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 */ + ++ /* ++ * Need to support the get index for all families ++ * removed PF_PACKET_SOCKET flag , as this flags restricts the usage to only PF_FAMILY ++ */ ++ netif->ifindex = netif_alloc_ifindex(); ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif: netif->ifindex=%d", netif->ifindex)); ++ if ((netif->ifindex < LWIP_NETIF_IFINDEX_START) || (netif->ifindex > LWIP_NETIF_IFINDEX_MAX)) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif: interface index alloc fail")); ++ return NULL; ++ } ++ + #if !LWIP_SINGLE_NETIF + /* Assign a unique netif number in the range [0..254], so that (num+1) can + serve as an interface index that fits in a u8_t. + We assume that the new netif has not yet been added to the list here. + This algorithm is O(n^2), but that should be OK for lwIP. + */ +- { +- struct netif *netif2; +- int num_netifs; +- do { +- if (netif->num == 255) { +- netif->num = 0; +- } +- num_netifs = 0; +- for (netif2 = netif_list; netif2 != NULL; netif2 = netif2->next) { +- LWIP_ASSERT("netif already added", netif2 != netif); +- num_netifs++; +- LWIP_ASSERT("too many netifs, max. supported number is 255", num_netifs <= 255); +- if (netif2->num == netif->num) { +- netif->num++; +- break; +- } +- } +- } while (netif2 != NULL); +- } +- if (netif->num == 254) { +- netif_num = 0; +- } else { +- netif_num = (u8_t)(netif->num + 1); +- } + + /* add this netif to the list */ + netif->next = netif_list; +@@ -421,8 +428,8 @@ + } + #endif /* LWIP_IGMP */ + +- LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", +- netif->name[0], netif->name[1])); ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %s IP", ++ netif->name)); + #if LWIP_IPV4 + LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); + ip4_addr_debug_print(NETIF_DEBUG, ipaddr); +@@ -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 + */ +-void ++err_t + netif_set_default(struct netif *netif) + { + LWIP_ASSERT_CORE_LOCKED(); +@@ -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] : '\'')); ++ return ERR_OK; + } + + /** +@@ -1206,6 +1279,11 @@ + struct netif *stats_if = netif; + #endif /* LWIP_HAVE_LOOPIF */ + #endif /* MIB2_STATS */ ++#if PF_PACKET_SOCKET ++ struct raw_pcb *pcb; ++ int match = 0; ++#endif /* PF_PACKET_SOCKET */ ++ + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_ASSERT("netif_poll: invalid netif", netif != NULL); +@@ -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); ++ ++#if PF_PACKET_SOCKET ++ for (pcb = get_packet_raw_pcbs(); pcb != NULL; pcb = pcb->next) { ++ if (((pcb->proto.eth_proto == htons(ETHTYPE_ALL)) || (pcb->proto.eth_proto == htons(ETHTYPE_IP))) && ++ ((!pcb->netifindex) || (pcb->netifindex == netif->ifindex))) { ++ match = 1; ++ break; ++ } ++ } ++ ++ /* always succeed because the alloc layer of loopback pbuf was PBUF_LINK */ ++ if (match && pbuf_header(in, PBUF_LINK_HLEN) == 0) { ++ struct eth_hdr *ethhdr; ++ /* add ethernet header */ ++ ethhdr = (struct eth_hdr *)(in->payload); ++ /* smac and dmac set to all zeros for loopback IP packet */ ++ (void)memset_s(ethhdr, sizeof(struct eth_hdr), 0, sizeof(struct eth_hdr)); ++ ethhdr->type = htons(ETHTYPE_IP); /* eth protocol, should be ETH_P_IP(0x800) */ ++ in->flags = (u16_t)(in->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_OUTGOING)); ++ in->flags |= PBUF_FLAG_HOST; ++ raw_packet_input(in, netif, NULL); ++ (void)pbuf_header(in, -PBUF_LINK_HLEN); ++ } ++#endif /* PF_PACKET_SOCKET */ ++ + /* loopback packets are always IP packets! */ + if (ip_input(in, netif) != ERR_OK) { + pbuf_free(in); +@@ -1700,29 +1803,68 @@ + struct netif * + netif_find(const char *name) + { +- struct netif *netif; +- u8_t num; +- +- LWIP_ASSERT_CORE_LOCKED(); +- +- if (name == NULL) { +- return NULL; +- } ++ struct netif *netif = NULL; ++ char candidate_name[NETIF_NAMESIZE]; ++ int ret; + +- num = (u8_t)atoi(&name[2]); ++ LWIP_ERROR("netif_find : invalid value.", (name != NULL), return NULL); + + NETIF_FOREACH(netif) { +- if (num == netif->num && +- name[0] == netif->name[0] && +- name[1] == netif->name[1]) { +- LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); ++ if (strncmp(name, netif->name, NETIF_NAMESIZE) == 0) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %s\n", name)); + return netif; + } ++ ++ if (netif->link_layer_type != LOOPBACK_IF) { ++ ret = snprintf_s(candidate_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s%"U8_F, netif->name, netif->num); ++ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: name '%s'is too long\n", netif->name)); ++ continue; ++ } ++ if (strncmp(name, candidate_name, NETIF_NAMESIZE) == 0) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %s\n", name)); ++ return netif; ++ } ++ } + } +- LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %s\n", name)); + return NULL; + } + ++/* ++ * Change mtu setting for a network interface ++ * ++ * @param netif the network interface to change ++ * @param netif_mtu the new MTU for the interface ++ */ ++ ++err_t ++netif_set_mtu_api(struct netif *netif, u16_t netif_mtu) ++{ ++ /* As per RFC 791, "Every internet module must be able to forward a datagram of 68 ++ * octets without further fragmentation. This is because an internet header ++ * may be up to 60 octets, and the minimum fragment is 8 octets." */ ++ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif != NULL), return ERR_VAL); ++ ++#if LWIP_IPV6 ++ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif_mtu >= NETIF_MTU_MIN) && (netif_mtu <= IP_FRAG_MAX_MTU), ++ return ERR_ARG); ++#else ++ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif_mtu >= IP_FRAG_MIN_MTU) && (netif_mtu <= IP_FRAG_MAX_MTU), ++ return ERR_ARG); ++#endif ++ ++ netif->mtu = netif_mtu; ++#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES ++ netif->mtu6 = netif_mtu; ++#endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ ++ ++ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif: MTU of interface %s%"U16_F" is changed to %d\n", ++ netif->name, netif->num, netif->mtu)); ++ ++ return ERR_OK; ++} ++ + #if LWIP_NETIF_EXT_STATUS_CALLBACK + /** + * @ingroup netif +@@ -1793,3 +1935,213 @@ + } + } + #endif /* LWIP_NETIF_EXT_STATUS_CALLBACK */ ++ ++struct netif * ++netif_find_by_ipaddr(const ip_addr_t *ipaddr) ++{ ++ LWIP_ERROR("netif_find_by_ipaddr : invalid arguments", (ipaddr != NULL), return NULL); ++#if LWIP_IPV4 ++ if (IP_IS_V4(ipaddr)) { ++ return netif_find_by_ip4addr(ipaddr); ++ } ++#endif ++ ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ipaddr: didn't find\n")); ++ return NULL; ++} ++ ++void ++netif_get_hwaddr(const struct netif *netif, unsigned char *hw_addr, int hw_len) ++{ ++ int i; ++ LWIP_ERROR("netif_get_hwaddr : invalid arguments", (netif != NULL), return); ++ ++ LWIP_ERROR("netif_get_hwaddr : invalid arguments", (hw_addr != NULL), return); ++ ++ LWIP_ERROR("netif_get_hwaddr: invalid arguments", ++ ((unsigned int)hw_len == NETIF_MAX_HWADDR_LEN), return); ++ ++ for (i = 0; i < hw_len; i++) { ++ hw_addr[i] = netif->hwaddr[i]; ++ } ++} ++ ++/* ++ * Change the hardware address for a network interface ++ * ++ * NOTE:Application should call set_link_down before calling ++ * the netif_set_hwaddr and then set_link_up, in order ++ * to ensure that all IPs are announced after changing ++ * hw address ++ * ++ * @param netif the network interface to change ++ * @param hw_addr the new hardware address ++ * @param hw_len the length of new hardware address, ++ * ++ */ ++err_t ++netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw_len) ++{ ++ LWIP_ERROR("netif_set_hwaddr : invalid arguments", (netif != NULL), return ERR_VAL); ++ ++ LWIP_ERROR("netif_set_hwaddr : invalid arguments", (hw_addr != NULL), return ERR_VAL); ++ ++ LWIP_ERROR("netif_set_hwaddr: invalid arguments", ++ ((unsigned int)hw_len == NETIF_MAX_HWADDR_LEN), return ERR_VAL); ++ ++ if (netif->drv_set_hwaddr == NULL) { ++ return ERR_OPNOTSUPP; ++ } ++ ++ if (netif->drv_set_hwaddr(netif, (u8_t *)hw_addr, hw_len) != ERR_OK) { ++ return ERR_VAL; ++ } ++ ++ if (memcpy_s(netif->hwaddr, NETIF_MAX_HWADDR_LEN, hw_addr, (u32_t)hw_len) != EOK) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_set_hwaddr: memcpy_s error\n")); ++ return ERR_VAL; ++ } ++ ++ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ++ ("netif: HW address of interface %s%"U16_F" set to %02X:%02X:%02X:%02X:%02X:%02X\n", ++ netif->name, netif->num, ++ netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], ++ netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5])); ++ ++ return ERR_OK; ++} ++ ++#if LWIP_IPV4 ++/* ++ * Find a network interface by searching for its ipaddress ++ * ++ * @param ipaddr IP_add of the netif ++ * @return netif if the its found ++ * NULL if there is no netif with ipaddr ++ */ ++struct netif * ++netif_find_by_ip4addr(const ip_addr_t *ipaddr) ++{ ++ struct netif *netif = NULL; ++ ++ LWIP_ASSERT("Expecting ipaddr to be not NULL ", ipaddr != NULL); ++ ++ for (netif = netif_list; netif != NULL; netif = netif->next) { ++ if (ip_addr_cmp(&(netif->ip_addr), ipaddr)) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ipaddr: found\n")); ++ return netif; ++ } ++ } ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ip4addr: didn't find\n")); ++ return NULL; ++} ++ ++s8_t netif_find_dst_ipaddr(const ip_addr_t *ipaddr, ip_addr_t **dst_addr) ++{ ++ struct netif *netif = NULL; ++ ip_addr_t *pdst_addr = NULL; ++ ++ pdst_addr = *dst_addr; ++ netif = netif_find_by_ipaddr(ipaddr); ++ if (netif == NULL) { ++ return -1; ++ } ++ if ((pdst_addr != NULL) && (!ip_addr_netcmp(pdst_addr, &(netif->ip_addr), ip_2_ip4(&netif->netmask))) && ++ !ip_addr_islinklocal(pdst_addr)) { ++ if (!ip_addr_isany(&netif->gw)) { ++ *dst_addr = &(netif->gw); ++ } ++ } ++ ++ return 0; ++} ++#endif /* LWIP_IPV4 */ ++ ++ ++ ++#if LWIP_DHCP ++/* ++ * Close DHCP and set static network. ++ * ++ * @param netif a pre-allocated netif structure ++ * ++ * @return ERR_OK, or ERR_VAL if failed. ++ */ ++err_t ++netif_dhcp_off(struct netif *netif) ++{ ++ ip_addr_t old_ipaddr; ++ ip_addr_t old_netmask; ++ ip_addr_t old_gateway; ++ ++ if (netif == NULL) { ++ return ERR_VAL; ++ } ++ old_ipaddr = netif->ip_addr; ++ old_netmask = netif->netmask; ++ old_gateway = netif->gw; ++ ++ if (netif_dhcp_data(netif)) { ++ (void)dhcp_release(netif); ++ dhcp_stop(netif); ++ dhcp_cleanup(netif); ++ LWIP_DEBUGF(NETIF_DEBUG, ("DHCP is close;set static IP\n")); ++ } ++ ++ ip_addr_set_val(netif->ip_addr, old_ipaddr); ++ ip_addr_set_val(netif->netmask, old_netmask); ++ ip_addr_set_val(netif->gw, old_gateway); ++ (void)netif_set_up(netif); ++ ++ return ERR_OK; ++} ++#endif /* LWIP_DHCP */ ++ ++u8_t netif_ipaddr_isbrdcast(const ip_addr_t *ipaddr) ++{ ++ struct netif *netif = NULL; ++ ++ for (netif = netif_list; netif != NULL; netif = netif->next) { ++ if (netif_is_up(netif) && ip_addr_isbroadcast(ipaddr, netif)) { ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++struct netif * ++netif_find_by_ifindex(u8_t ifindex) ++{ ++ struct netif *netif = NULL; ++ ++ if (ifindex < LWIP_NETIF_IFINDEX_START) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: Invalid ifindex(%u) \n", ifindex)); ++ return netif; ++ } ++ ++ for (netif = netif_list; netif != NULL; netif = netif->next) { ++ if (netif->ifindex == ifindex) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: found\n")); ++ return netif; ++ } ++ } ++ ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: didn't find\n")); ++ return NULL; ++} ++ ++/* Need to support the get index for all families ++removed PF_PACKET_SOCKET flag , as this flags restricts the usage to only PF_FAMILY Begin */ ++static u8_t ++netif_alloc_ifindex(void) ++{ ++ u8_t tmp_index; ++ for (tmp_index = LWIP_NETIF_IFINDEX_START; tmp_index <= LWIP_NETIF_IFINDEX_MAX; tmp_index++) { ++ if (netif_get_by_index(tmp_index) == NULL) { ++ break; ++ } ++ } ++ ++ return tmp_index; ++} +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 LWIP_NIP /* don't build if not configured for use in lwipopts.h */ ++ ++#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) ++{ ++ 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; ++} ++ ++/** ++ * 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) ++{ ++ 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; ++ } ++ ++ /* 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; ++} ++ ++/** 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); ++} ++ ++/** ++ * 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); ++ netif = ip_route_pcb(ipaddr, (struct ip_pcb*)pcb); + } + } + +@@ -387,7 +415,7 @@ + return ERR_RTE; + } + +- if (ip_addr_isany(&pcb->local_ip) || ip_addr_ismulticast(&pcb->local_ip)) { ++ if (ip_addr_isany(&pcb->local_ip) || ip_get_option(pcb, SOF_BINDNONUNICAST)) { + /* use outgoing network interface IP address as source address */ + src_ip = ip_netif_get_local_ip(netif, ipaddr); + #if LWIP_IPV6 +@@ -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); +- err = ip_output_if(q, src_ip, dst_ip, ttl, pcb->tos, pcb->protocol, netif); ++ err = ip_output_if(q, src_ip, dst_ip, ttl, pcb->tos, pcb->raw_proto, netif); + NETIF_RESET_HINTS(netif); + + /* did we chain a header earlier? */ +@@ -604,7 +634,12 @@ + if (pcb != NULL) { + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct raw_pcb)); ++#if PF_PACKET_SOCKET ++ pcb->proto.protocol = proto; ++#else + pcb->protocol = proto; ++#endif ++ + pcb->ttl = RAW_TTL; + #if LWIP_MULTICAST_TX_OPTIONS + raw_set_multicast_ttl(pcb, RAW_TTL); +@@ -668,4 +703,227 @@ + } + } + ++#if PF_PACKET_SOCKET ++void raw_packet_input(struct pbuf *p, const struct netif *inp, const struct raw_pcb *from) ++{ ++ struct raw_pcb *pcb = NULL; ++ struct eth_hdr *ethhdr = NULL; ++ u16_t proto; ++ ++ LWIP_UNUSED_ARG(inp); ++ ++ ethhdr = (struct eth_hdr *)p->payload; ++ proto = ethhdr->type; ++ ++ g_lwip_current_eth_hdr = ethhdr; ++ g_lwip_current_netif = inp; ++ ++ pcb = g_packet_raw_pcbs; ++ /* 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->proto.eth_proto == htons(ETHTYPE_ALL)) || ((p != NULL) && !(p->flags & PBUF_FLAG_OUTGOING) && ++ pcb->proto.eth_proto == proto)) && ++ ((!pcb->netifindex) || (pcb->netifindex == inp->ifindex)) && (pcb != from)) { ++ /* receive callback function available? */ ++ if (pcb->recv != NULL) { ++ /* the receive callback function did not eat the packet? */ ++ if (pcb->recv(pcb->recv_arg, pcb, p, NULL) != 0) { ++ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_input: packets recved failed \n")); ++ } ++ } ++ /* no receive callback function was set for this raw PCB */ ++ } ++ ++ pcb = pcb->next; ++ } ++ ++ g_lwip_current_eth_hdr = NULL; ++ return; ++} ++ ++err_t ++raw_packet_bind(struct raw_pcb *pcb, u8_t ifindex, u16_t proto) ++{ ++ struct netif *loc_netif = NULL; ++ ++ if (ifindex != 0) { ++ for (loc_netif = netif_list; loc_netif != NULL; loc_netif = loc_netif->next) { ++ if (ifindex == loc_netif->ifindex) { ++ break; ++ } ++ } ++ ++ /* Return if no matching netifs to bind */ ++ if (loc_netif == NULL) { ++ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_bind: No matching netif found for ifindex(%u)\n", ifindex)); ++ return ERR_NODEV; ++ } ++ } else { ++ return ERR_NODEV; ++ } ++ ++#if DRIVER_STATUS_CHECK ++ if (!netif_is_up(loc_netif) || !netif_is_ready(loc_netif)) ++#else ++ if (!netif_is_up(loc_netif)) ++#endif ++ { ++ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_bind: bind failed as netif (index %u) was down\n", ifindex)); ++ return ERR_NETDOWN; ++ } ++ ++ pcb->netifindex = ifindex; ++ pcb->proto.eth_proto = proto; ++ ++ return ERR_OK; ++} ++ ++/* ++ * Send the raw IP packet through the given netif driver. Note that actually you cannot ++ * modify the link layer header here. Packet need to be sent to driver as it is through the ++ * given netif ++ * @param pcb the raw pcb which to send ++ * @param p the ethernet packet to send ++ * @param ifindex the Interface index of the netif through which packet needs to be sent ++ */ ++err_t ++raw_packet_sendto(const struct raw_pcb *pcb, struct pbuf *p, u8_t ifindex) ++{ ++ struct netif *netif = NULL; ++ u8_t netifindex; ++ LWIP_UNUSED_ARG(pcb); ++ ++ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_packet_sendto: ifindex=%d\n", ifindex)); ++ LWIP_ASSERT("p != NULL", p != NULL); ++ ++ netifindex = ifindex; ++ ++ if (ifindex == 0) { ++ if (pcb->netifindex != 0) { ++ netifindex = pcb->netifindex; ++ } else { ++ return ERR_NODEVADDR; ++ } ++ } ++ ++ /* Find the netif corresponding to the interface index */ ++ netif = netif_find_by_ifindex(netifindex); ++ if (netif == NULL) { ++ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("netif not found for given ifindex (%u)\n", ifindex)); ++ return ERR_NODEVADDR; ++ } ++ ++#if DRIVER_STATUS_CHECK ++ if ((!netif_is_up(netif)) || (!netif_is_ready(netif))) ++#else ++ if ((!netif_is_up(netif))) ++#endif ++ { ++ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("netif was down for given ifindex (%u)\n", ifindex)); ++ return ERR_NETDOWN; ++ } ++ ++ if ((p->tot_len - (SIZEOF_ETH_HDR - ETH_PAD_SIZE)) > netif->mtu) { ++ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("Message too long (%u)\n", p->tot_len)); ++ return ERR_MSGSIZE; ++ } ++ ++ if (pbuf_header(p, ETH_PAD_SIZE) == 0) { ++ p->flags = (u16_t)(p->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_HOST)); ++ p->flags |= PBUF_FLAG_OUTGOING; ++ raw_packet_input(p, netif, pcb); ++ (void)pbuf_header(p, -ETH_PAD_SIZE); ++ } ++ ++ /* For RAW packets of PF_PACKET family, do not modify the packets as it is ++ already supposed to contain the link layer header. So send directly to the driver */ ++ LINK_STATS_INC(link.xmit); ++ return ERR_OK; ++} ++ ++/* ++ * Create a RAW PCB for Packet family. ++ * ++ * @return The RAW PCB which was created. NULL if the PCB data structure ++ * could not be allocated. ++ * ++ * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) ++ * ++ * @see raw_remove() ++ */ ++struct raw_pcb * ++raw_packet_new(u16_t proto) ++{ ++ struct raw_pcb *pcb = NULL; ++ ++ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_packet_new\n")); ++ ++ pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); ++ /* could allocate RAW PCB? */ ++ if (pcb != NULL) { ++ /* initialize PCB to all zeroes */ ++ (void)memset(pcb, 0, sizeof(struct raw_pcb)); ++ pcb->proto.eth_proto = proto; ++ pcb->ttl = RAW_TTL; ++ pcb->next = g_packet_raw_pcbs; ++ g_packet_raw_pcbs = pcb; ++ pcb->all_next = g_all_packet_raw_pcbs; ++ g_all_packet_raw_pcbs = pcb; ++ } ++ return pcb; ++} ++ ++/* ++ * Remove an RAW PCB of packet family type ++ * ++ * @param pcb RAW PCB to be removed. The PCB is removed from the list of ++ * RAW PCB's and the data structure is freed from memory. ++ * ++ * @see raw_packet_new() ++ */ ++void ++raw_packet_remove(struct raw_pcb *pcb) ++{ ++ struct raw_pcb *pcb2 = NULL; ++ ++ /* NULL check */ ++ if (pcb == NULL) { ++ return; ++ } ++ ++ /* pcb to be removed is first in all_pkt list? */ ++ if (g_all_packet_raw_pcbs == pcb) { ++ /* make list start at 2nd pcb */ ++ g_all_packet_raw_pcbs = g_all_packet_raw_pcbs->all_next; ++ /* pcb not 1st in list */ ++ } else { ++ for (pcb2 = g_all_packet_raw_pcbs; pcb2 != NULL; pcb2 = pcb2->all_next) { ++ /* find pcb in g_all_packet_raw_pcbs list */ ++ if (pcb2->all_next == pcb) { ++ /* remove pcb from list */ ++ pcb2->all_next = pcb->all_next; ++ } ++ } ++ } ++ ++ /* pcb to be removed is first in list? */ ++ if (g_packet_raw_pcbs == pcb) { ++ /* make list start at 2nd pcb */ ++ g_packet_raw_pcbs = g_packet_raw_pcbs->next; ++ /* pcb not 1st in list */ ++ } else { ++ for (pcb2 = g_packet_raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { ++ /* find pcb in raw_pcbs list */ ++ if (pcb2->next == pcb) { ++ /* remove pcb from list */ ++ pcb2->next = pcb->next; ++ } ++ } ++ } ++ ++ memp_free(MEMP_RAW_PCB, pcb); ++} ++#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 2022-02-16 16:06:59.178115000 +0800 ++++ b/lwip-2.1.2/src/include/lwip/api.h 2022-01-25 14:54:11.006695000 +0800 +@@ -48,6 +48,9 @@ + #include "lwip/sys.h" + #include "lwip/ip_addr.h" + #include "lwip/err.h" ++#if LWIP_LITEOS_COMPAT ++#include "lwip/netif.h" ++#endif + + #ifdef __cplusplus + extern "C" { +@@ -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,15 @@ + /** 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 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 +166,10 @@ + NETCONN_WRITE, + NETCONN_LISTEN, + NETCONN_CONNECT, +- NETCONN_CLOSE ++ NETCONN_CLOSE, ++#if LWIP_LITEOS_COMPAT ++ NETCONN_CLOSED, ++#endif /* LWIP_LITEOS_COMPAT */ + }; + + /** Used to inform the callback function about changes +@@ -201,6 +221,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 +247,12 @@ + struct tcp_pcb *tcp; + struct udp_pcb *udp; + struct raw_pcb *raw; ++#if PF_PACKET_SOCKET ++ struct raw_pcb *packet_raw; ++#endif /* PF_PACKET_SOCKET */ + } pcb; + /** the last asynchronous unreported error this netconn had */ +- err_t pending_err; ++ err_t last_err; + #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 +307,13 @@ + #endif /* LWIP_TCP */ + /** A callback function that is informed about events for this netconn */ + netconn_callback callback; ++#if LWIP_TCP ++ struct pbuf *refused_data; ++ ip_addr_t remote_ip; ++ u16_t remote_port; ++ /** record pending error state after recving RST */ ++ u16_t pending_err; ++#endif + }; + + /** This vector type is passed to @ref netconn_write_vectors_partly to send +@@ -309,21 +340,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) +-struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, ++struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, + netconn_callback callback); + err_t netconn_prepare_delete(struct netconn *conn); + err_t netconn_delete(struct netconn *conn); + /** Get the type of a netconn (as enum netconn_type). */ +-#define netconn_type(conn) (conn->type) ++#define netconn_type(conn) ((u32_t)(conn->type)) + + err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, + u16_t *port, u8_t local); ++#if LWIP_LITEOS_COMPAT ++#if PF_PACKET_SOCKET ++struct pf_packet_sockaddr_ll { ++ u16_t sll_protocol; ++ u16_t sll_hatype; ++ u8_t if_idx; ++ u8_t sll_halen; ++ u8_t sll_addr[NETIF_MAX_HWADDR_LEN]; ++}; ++err_t netconn_get_sockaddr_pf_packet(struct netconn *conn, struct pf_packet_sockaddr_ll *ll, u8_t local); ++#endif /* PF_PACKET_SOCKET */ ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup netconn_common */ + #define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) + /** @ingroup netconn_common */ + #define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) + ++#if PF_PACKET_SOCKET ++err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port, u8_t ifindex); ++#else + err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port); ++#endif /* PF_PACKET_SOCKET */ ++ + err_t netconn_bind_if(struct netconn *conn, u8_t if_idx); + 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 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 + +-#ifndef LITTLE_ENDIAN +-#define LITTLE_ENDIAN 1234 +-#endif +- +-#ifndef BIG_ENDIAN +-#define BIG_ENDIAN 4321 +-#endif +- ++#include + #include "arch/cc.h" + + /** +@@ -149,6 +142,11 @@ + #ifndef X8_F + #define X8_F "02" PRIx8 + #endif ++#if LWIP_LITEOS_COMPAT ++#ifndef U8_F ++#define U8_F PRIu8 ++#endif ++#endif /* LWIP_LITEOS_COMPAT */ + #ifndef U16_F + #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 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, + /** Illegal argument. */ +- ERR_ARG = -16 ++ ERR_ARG = -16, ++#ifdef LWIP_LITEOS_COMPAT ++/** Message too long. */ ++ ERR_MSGSIZE = -17, ++/** No such device. */ ++ ERR_NODEV = -18, ++/** No such device or address. */ ++ ERR_NODEVADDR = -19, ++/** socket is not connection-mode & no peer address is set */ ++ ERR_NODEST = -20, ++/** Network is down */ ++ ERR_NETDOWN = -21, ++/** Address family not supported by protocol */ ++ ERR_AFNOSUPP = -22, ++/** No such address */ ++ ERR_NOADDR = -23, ++/** Operation not supported on transport endpoint */ ++ ERR_OPNOTSUPP = -24, ++ ERR_NETUNREACH = -25, ++/** connection request timedout */ ++ ERR_CONNECTIMEOUT = -26, ++/** Error pipe */ ++ ERR_PIPE = -27, ++/** AF not supported */ ++ ERR_AFNOSUPPORT = -28, ++/** Protocol not available */ ++ ERR_NOPROTOOPT = -29, ++ ERR_ACCESS = -30, ++ ERR_NFILE = -31, ++ ERR_RESERVE3 = -32, ++ ERR_RESERVE4 = -33, ++ ERR_RESERVE5 = -34, ++ ERR_RESERVE6 = -35, ++ ERR_FATAL_START = -36, ++ ERR_CONNREFUSED = -41, ++/** FIN mbox post fail. */ ++ ERR_FIN_POST = -42, ++#endif /* LWIP_LITEOS_COMPAT */ + } err_enum_t; + ++#ifdef LWIP_LITEOS_COMPAT ++#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 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. */ ++ ++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 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 + ++#if !LWIP_LITEOS_COMPAT + #define IF_NAMESIZE NETIF_NAMESIZE + + char * lwip_if_indextoname(unsigned int ifindex, char *ifname); + unsigned int lwip_if_nametoindex(const char *ifname); ++#endif + + #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 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 + ++#if !LWIP_LITEOS_COMPAT + /* 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 +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)}}} +-/** This variable is initialized by the system to contain the wildcard IPv6 address. */ +-extern const struct in6_addr in6addr_any; + + /* Definitions of the bits in an (IPv4) Internet address integer. + +@@ -119,7 +119,12 @@ + #define IN_BADCLASS(a) IP_BADCLASS(a) + + #define IN_LOOPBACKNET IP_LOOPBACKNET ++#endif /* !LWIP_LITEOS_COMPAT */ + ++/** This variable is initialized by the system to contain the wildcard IPv6 address. */ ++extern const struct in6_addr in6addr_any; ++/** Added new structure for ipv6 loopback as per section 3.9 of rfc 2553/3493 */ ++extern const struct in6_addr in6addr_loopback; + + #ifndef INET_ADDRSTRLEN + #define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX +@@ -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 */ +-#define inet_addr(cp) ipaddr_addr(cp) ++#if LWIP_INET_ADDR_FUNC ++unsigned int inet_addr(const char *cp); ++#else ++#define inet_addr(cp) ipaddr_addr(cp) ++#endif ++ ++#if LWIP_INET_ATON_FUNC ++int inet_aton(const char *cp, struct in_addr *addr); ++#else + #define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) ++#endif ++ ++#if LWIP_INET_NTOA_FUNC ++char *inet_ntoa (struct in_addr in); ++#else + #define inet_ntoa(addr) ip4addr_ntoa((const ip4_addr_t*)&(addr)) ++#endif ++ + #define inet_ntoa_r(addr, buf, buflen) ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) + + #endif /* LWIP_IPV4 */ + + #if LWIP_IPV6 ++/* current the struct ip6_addr for define LWIP_IPV6_SCOPES 0 */ ++#if LWIP_LITEOS_COMPAT ++#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) { \ ++ memcpy((target_in6addr)->s6_addr, (source_ip6addr)->addr, sizeof(struct ip6_addr)); } ++#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) { \ ++ memcpy((target_ip6addr)->addr, (source_in6addr)->s6_addr, sizeof(struct ip6_addr)); \ ++ ip6_addr_clear_zone(target_ip6addr);} ++#else + #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 +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);} +- ++#endif /* LWIP_LITEOS_COMPAT */ + /* 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 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{ \ +- ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); ip_clear_no4(dest); }}while(0) ++ ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); ip_clear_no4(dest); }} while (0) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_set_val(dest, src) do { IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&(src))); if(IP_IS_V6_VAL(src)) { \ ++ ip6_addr_set(ip_2_ip6(&(dest)), ip_2_ip6(&(src))); } else { \ ++ ip4_addr_set(ip_2_ip4(&(dest)), ip_2_ip4(&(src))); }} while (0) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup ipaddr */ + #define ip_addr_set_ipaddr(dest, src) ip_addr_set(dest, src) + /** @ingroup ipaddr */ + #define ip_addr_set_zero(ipaddr) do{ \ +- ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0) ++ ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); } while (0) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_set_zero_val(ipaddr) do{ \ ++ ip6_addr_set_zero(ip_2_ip6(&(ipaddr))); IP_SET_TYPE_VAL(ipaddr, 0); } while (0) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup ip5addr */ + #define ip_addr_set_zero_ip4(ipaddr) do{ \ + ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }while(0) + /** @ingroup ip6addr */ + #define ip_addr_set_zero_ip6(ipaddr) do{ \ +- ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }while(0) ++ ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); } while (0) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_set_zero_ip6_val(ipaddr) do{ \ ++ ip6_addr_set_zero(ip_2_ip6(&(ipaddr))); IP_SET_TYPE_VAL(ipaddr, IPADDR_TYPE_V6); } while (0) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @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 +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)) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_netcmp_val(addr1, addr2, mask) ((IP_IS_V6_VAL((addr1)) && IP_IS_V6_VAL((addr2))) ? \ ++ 0 : \ ++ ip4_addr_netcmp(ip_2_ip4(&addr1), ip_2_ip4(&addr2), mask)) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @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 +282,50 @@ + #define ip_addr_isbroadcast(ipaddr, netif) ((IP_IS_V6(ipaddr)) ? \ + 0 : \ + ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_isbroadcast_val(ipaddr, netif) ((IP_IS_V6_VAL(ipaddr)) ? \ ++ 0 : \ ++ ip4_addr_isbroadcast(ip_2_ip4(&ipaddr), netif)) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup ipaddr */ + #define ip_addr_ismulticast(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ + ip4_addr_ismulticast(ip_2_ip4(ipaddr))) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_ismulticast_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ ++ ip6_addr_ismulticast(ip_2_ip6(&ipaddr)) : \ ++ ip4_addr_ismulticast(ip_2_ip4(&ipaddr))) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup ipaddr */ + #define ip_addr_isloopback(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_isloopback(ip_2_ip6(ipaddr)) : \ + ip4_addr_isloopback(ip_2_ip4(ipaddr))) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_isloopback_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ ++ ip6_addr_isloopback(ip_2_ip6(&ipaddr)) : \ ++ ip4_addr_isloopback(ip_2_ip4(&ipaddr))) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup ipaddr */ + #define ip_addr_islinklocal(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_islinklocal(ip_2_ip6(ipaddr)) : \ + ip4_addr_islinklocal(ip_2_ip4(ipaddr))) ++#ifdef LWIP_DEBUG + #define ip_addr_debug_print(debug, ipaddr) do { if(IP_IS_V6(ipaddr)) { \ + ip6_addr_debug_print(debug, ip_2_ip6(ipaddr)); } else { \ +- ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }}while(0) ++ ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }} while (0) + #define ip_addr_debug_print_val(debug, ipaddr) do { if(IP_IS_V6_VAL(ipaddr)) { \ + ip6_addr_debug_print_val(debug, *ip_2_ip6(&(ipaddr))); } else { \ +- ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }}while(0) ++ ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }} while (0) ++#else ++#define ip_addr_debug_print(debug, ipaddr) ++#define ip_addr_debug_print_val(debug, ipaddr) ++#endif /* LWIP_LITEOS_COMPAT */ ++ + char *ipaddr_ntoa(const ip_addr_t *addr); + char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen); ++#if LWIP_LITEOS_COMPAT ++#define ipaddr_ntoa_unsafe(addr) ((IP_IS_V6_VAL(*addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr))) ++#endif /* LWIP_LITEOS_COMPAT */ + int ipaddr_aton(const char *cp, ip_addr_t *addr); + + /** @ingroup ipaddr */ +@@ -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) + ++#define ip_addr_cmp_zoneless(addr1, addr2) ip4_addr_cmp(addr1, addr2) + #define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) + #define ip_addr_copy_from_ip4(dest, src) ip4_addr_copy(dest, src) + #define ip_addr_set_ip4_u32(ipaddr, val) ip4_addr_set_u32(ip_2_ip4(ipaddr), val) + #define ip_addr_set_ip4_u32_val(ipaddr, val) ip_addr_set_ip4_u32(&(ipaddr), val) + #define ip_addr_get_ip4_u32(ipaddr) ip4_addr_get_u32(ip_2_ip4(ipaddr)) + #define ip_addr_set(dest, src) ip4_addr_set(dest, src) ++#define ip_addr_set_val(dest, src) ip4_addr_copy(dest, src) + #define ip_addr_set_ipaddr(dest, src) ip4_addr_set(dest, src) + #define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) ++#define ip_addr_set_zero_val(ipaddr) ip4_addr_set_zero(&(ipaddr)) + #define ip_addr_set_zero_ip4(ipaddr) ip4_addr_set_zero(ipaddr) + #define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) + #define ip_addr_set_loopback(is_ipv6, ipaddr) ip4_addr_set_loopback(ipaddr) + #define ip_addr_set_hton(dest, src) ip4_addr_set_hton(dest, src) + #define ip_addr_get_network(target, host, mask) ip4_addr_get_network(target, host, mask) + #define ip_addr_netcmp(addr1, addr2, mask) ip4_addr_netcmp(addr1, addr2, mask) ++#define ip_addr_netcmp_val(addr1, addr2, mask) ip4_addr_netcmp(&(addr1), &(addr2), mask) + #define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) + #define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) ++#define ip_addr_isnone(ipaddr) ip4_addr_isnone(ipaddr) + #define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) + #define ip_addr_isloopback(ipaddr) ip4_addr_isloopback(ipaddr) ++#define ip_addr_isloopback_val(ipaddr) ip4_addr_isloopback(&(ipaddr)) + #define ip_addr_islinklocal(ipaddr) ip4_addr_islinklocal(ipaddr) + #define ip_addr_isbroadcast(addr, netif) ip4_addr_isbroadcast(addr, netif) ++#define ip_addr_isbroadcast_val(addr, netif) ip4_addr_isbroadcast(&(addr), netif) + #define ip_addr_ismulticast(ipaddr) ip4_addr_ismulticast(ipaddr) ++#define ip_addr_ismulticast_val(ipaddr) ip4_addr_ismulticast(&(ipaddr)) ++#ifdef LWIP_DEBUG + #define ip_addr_debug_print(debug, ipaddr) ip4_addr_debug_print(debug, ipaddr) + #define ip_addr_debug_print_val(debug, ipaddr) ip4_addr_debug_print_val(debug, ipaddr) ++#else ++#define ip_addr_debug_print(debug, ipaddr) ++#define ip_addr_debug_print_val(debug, ipaddr) ++#endif ++ + #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 +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) ++#define ip_addr_set_val(dest, src) ip6_addr_copy(dest, src) ++ + #define ip_addr_set_ipaddr(dest, src) ip6_addr_set(dest, src) + #define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr) ++#define ip_addr_set_zero_val(ipaddr) ip6_addr_set_zero(&(ipaddr)) + #define ip_addr_set_zero_ip6(ipaddr) ip6_addr_set_zero(ipaddr) ++#define ip_addr_set_zero_ip6_val(ipaddr) ip6_addr_set_zero(&(ipaddr)) + #define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr) + #define ip_addr_set_loopback(is_ipv6, ipaddr) ip6_addr_set_loopback(ipaddr) + #define ip_addr_set_hton(dest, src) ip6_addr_set_hton(dest, src) + #define ip_addr_get_network(target, host, mask) ip6_addr_set_zero(target) + #define ip_addr_netcmp(addr1, addr2, mask) 0 ++#define ip_addr_netcmp_val(addr1, addr2, mask) 0 + #define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) + #define ip_addr_cmp_zoneless(addr1, addr2) ip6_addr_cmp_zoneless(addr1, addr2) + #define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) ++#define ip_addr_isnone(ipaddr) ip6_addr_isnone(ipaddr) + #define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) + #define ip_addr_isloopback(ipaddr) ip6_addr_isloopback(ipaddr) ++#define ip_addr_isloopback_val(ipaddr) ip6_addr_isloopback(&(ipaddr)) + #define ip_addr_islinklocal(ipaddr) ip6_addr_islinklocal(ipaddr) + #define ip_addr_isbroadcast(addr, netif) 0 ++#define ip_addr_isbroadcast_val(addr, netif) 0 + #define ip_addr_ismulticast(ipaddr) ip6_addr_ismulticast(ipaddr) ++#define ip_addr_ismulticast_val(ipaddr) ip6_addr_ismulticast(&(ipaddr)) ++#ifdef LWIP_DEBUG + #define ip_addr_debug_print(debug, ipaddr) ip6_addr_debug_print(debug, ipaddr) + #define ip_addr_debug_print_val(debug, ipaddr) ip6_addr_debug_print_val(debug, ipaddr) ++#else ++#define ip_addr_debug_print(debug, ipaddr) ++#define ip_addr_debug_print_val(debug, ipaddr) ++#endif ++ + #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 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) */ +- ++#if LWIP_LITEOS_COMPAT ++#define SOF_DONTROUTE 0x01U /* all packets sent from this socket should only be routed with link scope entry */ ++#define SOF_BINDNONUNICAST 0x10U /* socket has bind to a non unicast */ ++#endif /* LWIP_LITEOS_COMPAT */ + /* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ + #define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE) + +@@ -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; ++#if LWIP_LITEOS_COMPAT ++ /* The IP header ID of the next outgoing IP packet */ ++#if LWIP_IPV4 ++ /* ensure this member of this sturcture is not mem set to zero */ ++ u16_t ip_id; ++#endif /* LWIP_IPV4 */ ++#endif /* LWIP_LITEOS_COMPAT */ + }; + extern struct ip_globals ip_data; + +@@ -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 */ ++#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 ++ * (requires IP_FRAG_USES_STATIC_BUF==1).This is not a configurable value. ++ */ ++#if !defined(IP_FRAG_MAX_MTU) ++#define IP_FRAG_MAX_MTU 1500 ++#endif ++/* As per RFC 791, "Every internet module must be able to forward a datagram of 68 ++ * octets without further fragmentation. This is because an internet header ++ * may be up to 60 octets, and the minimum fragment is 8 octets." */ ++#if !defined(IP_FRAG_MIN_MTU) ++#define IP_FRAG_MIN_MTU 68 ++#endif ++struct netif *ip_route_pcb(const ip_addr_t *dest, const struct ip_pcb* pcb); ++#endif /* LWIP_LITEOS_COMPAT */ + #define ip_route_get_local_ip(src, dest, netif, ipaddr) do { \ + (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 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 */ + #define NETBUF_FLAG_CHKSUM 0x02 ++#if PF_PACKET_SOCKET ++#define NETBUF_FLAG_IFINDEX 0x04 ++#endif /* PF_PACKET_SOCKET */ + + /** "Network buffer" - contains data and addressing info */ + struct netbuf { + struct pbuf *p, *ptr; + ip_addr_t addr; + u16_t port; +-#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY ++#if PF_PACKET_SOCKET ++ u16_t hatype; ++ u16_t reserve; /* padded */ ++ u8_t netifindex; ++#endif /* PF_PACKET_SOCKET */ ++ ++#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY || PF_PACKET_SOCKET + u8_t flags; + u16_t toport_chksum; + #if LWIP_NETBUF_RECVINFO +@@ -73,7 +82,7 @@ + /* Network buffer functions: */ + struct netbuf * netbuf_new (void); + void netbuf_delete (struct netbuf *buf); +-void * netbuf_alloc (struct netbuf *buf, u16_t size); ++void * netbuf_alloc (struct netbuf *buf, u16_t size, u8_t netconn_type); + void netbuf_free (struct netbuf *buf); + err_t netbuf_ref (struct netbuf *buf, + const void *dataptr, u16_t size); +@@ -93,6 +102,10 @@ + #define netbuf_fromaddr(buf) (&((buf)->addr)) + #define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set(&((buf)->addr), fromaddr) + #define netbuf_fromport(buf) ((buf)->port) ++#if LWIP_LITEOS_COMPAT ++#define netbuf_fromifindex(buf) ((buf)->netifindex) ++#define netbuf_fromhatype(buf) ((buf)->hatype) ++#endif /* LWIP_LITEOS_COMPAT */ + #if LWIP_NETBUF_RECVINFO + #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 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" + ++#if LWIP_LITEOS_COMPAT ++#include ++#endif ++ + #if LWIP_DNS && LWIP_SOCKET + + #include "lwip/arch.h" +@@ -63,6 +67,7 @@ + #define LWIP_DNS_API_DECLARE_STRUCTS 1 + #endif + ++#if !LWIP_LITEOS_COMPAT + #if LWIP_DNS_API_DEFINE_ERRORS + /** Errors used by the DNS API functions, h_errno can be one of them */ + #define EAI_NONAME 200 +@@ -112,23 +117,39 @@ + }; + #endif /* LWIP_DNS_API_DECLARE_STRUCTS */ + +-#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) + + #if LWIP_DNS_API_DECLARE_H_ERRNO + /* application accessible error code set by the DNS API functions */ + extern int h_errno; + #endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ ++#endif /* !LWIP_LITEOS_COMPAT */ + ++#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) ++ ++#if LWIP_GETHOSTBYNAME || (defined(LWIP_COMPAT_SOCKETS) && (LWIP_COMPAT_SOCKETS != 2)) + struct hostent *lwip_gethostbyname(const char *name); ++#endif /* LWIP_GETHOSTBYNAME || (defined(LWIP_COMPAT_SOCKETS) && (LWIP_COMPAT_SOCKETS != 2)) */ ++#if (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) + int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop); ++#endif /* (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) */ ++#if (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) + void lwip_freeaddrinfo(struct addrinfo *ai); + int lwip_getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); +- +-#if LWIP_COMPAT_SOCKETS ++#endif /* (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) */ ++#if LWIP_DNS_REVERSE ++int lwip_getnameinfo(const struct sockaddr *sa, ++ socklen_t salen, ++ char *host, ++ size_t hostlen, ++ char *serv, ++ size_t servlen, ++ int flags); ++#endif /* LWIP_DNS_REVERSE */ ++#if defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2 + /** @ingroup netdbapi */ + #define gethostbyname(name) lwip_gethostbyname(name) + /** @ingroup netdbapi */ +@@ -139,7 +160,11 @@ + /** @ingroup netdbapi */ + #define getaddrinfo(nodname, servname, hints, res) \ + lwip_getaddrinfo(nodname, servname, hints, res) +-#endif /* LWIP_COMPAT_SOCKETS */ ++ ++/* @ingroup netdbapi */ ++#define getnameinfo(sock, sock_size, host, host_len, servname, servname_size, flags) \ ++ lwip_getnameinfo(sock, sock_size, host, host_len, servname, servname_size, flags) ++#endif /* defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2 */ + + #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 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*/ + ++/* ++Func Name: netifapi_netif_find_by_name ++*/ ++/** ++* @ingroup netifapi_netif ++* ++* @brief ++* This is a thread safe API, used to get the netif pointer whoes name was the input argument. ++* It is recommended to use this API instead of netif_find_by_name(). ++* Call netif_find() in a thread-safe way by running that function inside the tcpip_thread ++* context. ++* ++* @param[in] name Name of the netif. ++* ++* @returns ++* The netif pointer : On success \n ++* NULL : the netif was NOT exist \n ++* ++* @par Related Topics ++* netif_find_by_name() ++* ++*/ ++ ++struct netif* netifapi_netif_find_by_name(const char *name); + err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, + 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 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" + #include "lwip/stats.h" ++#include "lwip/prot/ethernet.h" + + #ifdef __cplusplus + extern "C" { +@@ -67,8 +68,17 @@ + * netif can be identified by in APIs. Composed of + * 2 chars, 3 (max) digits, and 1 \0 + */ +-#define NETIF_NAMESIZE 6 ++#ifdef IFNAMSIZ ++#define NETIF_NAMESIZE IFNAMSIZ ++#else ++#define NETIF_NAMESIZE 16 ++#endif + ++#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 + /** + * @defgroup netif_flags Flags + * @ingroup netif +@@ -106,6 +116,17 @@ + * Set by the netif driver in its init function. */ + #define NETIF_FLAG_MLD6 0x40U + ++/** If set, the interface is configured using DHCP. ++ * Set by the DHCP code when starting or stopping DHCP. */ ++#define NETIF_FLAG_DHCP 0x80U ++ ++#if DRIVER_STATUS_CHECK ++/** If set, the netif has send capability. ++ * Set by the netif driver when its is ready to send. */ ++#define NETIF_FLAG_DRIVER_RDY 0x100U ++#endif ++ ++#define NETIF_FLAG_LOOPBACK 0x800 + /** + * @} + */ +@@ -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 */ + ++/** Function pointer of driver set hw address function */ ++typedef u8_t (*drv_set_hwaddr_fn)(struct netif *netif, u8_t *addr, u8_t len); ++ + #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 +273,10 @@ + */ + #define netif_get_client_data(netif, id) (netif)->client_data[(id)] + #endif ++#ifndef LOOPBACK_IF ++/** Type of link layer, these macros should be used for link_layer_type of struct netif */ ++#define LOOPBACK_IF 772 ++#endif + + #if (LWIP_IPV4 && LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) || (LWIP_IPV6 && (LWIP_ND6_NUM_DESTINATIONS > 0x7f)) + typedef u16_t netif_addr_idx_t; +@@ -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; ++ /* This function is to set the mac_address of the interface. */ ++ drv_set_hwaddr_fn drv_set_hwaddr; ++#if LWIP_NETIF_ETHTOOL && LWIP_SOCKET ++ void *ethtool_ops; ++#endif ++#if LWIP_DHCPS ++ /* DHCP Server Informarion for this netif */ ++ struct dhcps *dhcps; ++#endif + #ifdef netif_get_client_data + void* client_data[LWIP_NETIF_CLIENT_DATA_INDEX_MAX + LWIP_NUM_NETIF_CLIENT_DATA]; + #endif + #if LWIP_NETIF_HOSTNAME + /* the hostname for this netif, NULL is a valid value */ +- const char* hostname; ++ char hostname[NETIF_HOSTNAME_MAX_LEN]; + #endif /* LWIP_NETIF_HOSTNAME */ + #if LWIP_CHECKSUM_CTRL_PER_NETIF + u16_t chksum_flags; +@@ -341,13 +398,19 @@ + u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; + /** number of bytes used in hwaddr */ + u8_t hwaddr_len; ++ /* link layer type, ethernet or wifi */ ++ u16_t link_layer_type; /**< Indicates whether the link layer type is ethernet or wifi. */ + /** flags (@see @ref netif_flags) */ +- u8_t flags; ++ u32_t flags; + /** descriptive abbreviation */ +- char name[2]; +- /** number of this interface. Used for @ref if_api and @ref netifapi_netif, ++ char name[NETIF_NAMESIZE]; ++ /** number of this interface. Used for @ref if_api and @ref netifapi_netif, + * as well as for IPv6 zones */ + u8_t num; ++ u8_t ifindex; /* Interface Index mapped to each netif. Starts from 1 */ ++#if DRIVER_STATUS_CHECK ++ s32_t waketime; /**< Started when netif_stop_queue is called from driver. */ ++#endif + #if LWIP_IPV6_AUTOCONFIG + /** is this netif enabled for IPv6 autoconfiguration */ + u8_t ip6_autoconfig_enabled; +@@ -387,6 +450,15 @@ + u16_t loop_cnt_current; + #endif /* LWIP_LOOPBACK_MAX_PBUFS */ + #endif /* ENABLE_LOOPBACK */ ++#if LWIP_SO_DONTROUTE ++ /** The scope of the netif, this is set in ip4_route/ip6_route, the usr can use this ++ to decide whether the netif is in desired sope */ ++ rt_scope_t scope; ++#endif ++#if LWIP_IPV6 ++ /** Call back needs to be registered if adaptor requires notification for IPv6 DAD */ ++ u8_t ipv6_flags; ++#endif + }; + + #if LWIP_CHECKSUM_CTRL_PER_NETIF +@@ -407,9 +479,15 @@ + #endif /* LWIP_SINGLE_NETIF */ + /** The default network interface. */ + extern struct netif *netif_default; +- ++s8_t netif_find_dst_ipaddr(const ip_addr_t *ipaddr, ip_addr_t **dst_addr); + void netif_init(void); + ++#if LWIP_DHCP ++err_t netif_dhcp_off(struct netif *netif); ++#endif ++ ++u8_t netif_check_num_isusing(const char* ifname, const u8_t num); ++ + struct netif *netif_add_noaddr(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input); + + #if LWIP_IPV4 +@@ -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); + +-void netif_set_default(struct netif *netif); ++struct netif *netif_find_by_ipaddr(const ip_addr_t *ipaddr); ++ ++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); + void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask); + void netif_set_gw(struct netif *netif, const ip4_addr_t *gw); ++struct netif *netif_find_by_ip4addr(const ip_addr_t *ipaddr); + /** @ingroup netif_ip4 */ + #define netif_ip4_addr(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->ip_addr))) + /** @ingroup netif_ip4 */ +@@ -455,6 +548,9 @@ + + void netif_set_up(struct netif *netif); + void netif_set_down(struct netif *netif); ++err_t netif_set_mtu_api(struct netif *netif, u16_t netif_mtu); ++err_t netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw_len); ++void netif_get_hwaddr(const struct netif *netif, unsigned char *hw_addr, int hw_len); + /** @ingroup netif + * Ask if an interface is up + */ +@@ -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); ++err_t netif_do_add_ipv6_addr(struct netif *netif, void *arguments); ++err_t netif_do_rmv_ipv6_addr(struct netif *netif, void *arguments); + 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 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) + */ + #if !defined MEMP_NUM_NETCONN || defined __DOXYGEN__ +-#define MEMP_NUM_NETCONN 4 ++#define MEMP_NUM_NETCONN 16 + #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 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 +- ++#ifdef LWIP_LITEOS_COMPAT ++#define PBUF_FLAG_HOST 0x100U ++#define PBUF_FLAG_OUTGOING 0x200U ++#endif + /** Main packet buffer struct */ + 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 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" + #include "lwip/priv/tcpip_priv.h" ++#include "lwip/ip.h" + + #ifdef __cplusplus + extern "C" { +@@ -70,6 +71,14 @@ + #define NETCONN_SHUT_WR 2 + #define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) + ++#if PF_PACKET_SOCKET ++/* Packet Types */ ++#define PACKET_HOST 0 /* To us */ ++#define PACKET_BROADCAST 1 /* To all */ ++#define PACKET_MULTICAST 2 /* To group */ ++#define PACKET_OTHERHOST 3 /* To someone else */ ++#define PACKET_OUTGOING 4 ++#endif + /* IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ +@@ -88,7 +97,7 @@ + struct netbuf *b; + /** used for lwip_netconn_do_newconn */ + struct { +- u8_t proto; ++ u16_t proto; + } n; + /** used for lwip_netconn_do_bind and lwip_netconn_do_connect */ + struct { +@@ -102,6 +111,12 @@ + u16_t API_MSG_M_DEF(port); + u8_t local; + } ad; ++#if PF_PACKET_SOCKET ++ struct { ++ struct pf_packet_sockaddr_ll API_MSG_M_DEF(ll); ++ u8_t local; ++ } adpkt; ++#endif + /** used for lwip_netconn_do_write */ + struct { + /** current vector to write */ +@@ -205,6 +220,7 @@ + #endif /* TCP_LISTEN_BACKLOG */ + void lwip_netconn_do_write (void *m); + void lwip_netconn_do_getaddr (void *m); ++void lwip_netconn_do_getaddr_pfpkt (void *m); + void lwip_netconn_do_close (void *m); + void lwip_netconn_do_shutdown (void *m); + #if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +@@ -214,6 +230,7 @@ + + #if LWIP_DNS + void lwip_netconn_do_gethostbyname(void *arg); ++void lwip_netconn_do_getnamebyhost(void *arg); + #endif /* LWIP_DNS */ + + struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); +@@ -233,6 +250,7 @@ + + typedef void (*netifapi_void_fn)(struct netif *netif); + typedef err_t (*netifapi_errt_fn)(struct netif *netif); ++typedef err_t (*netifapi_arg_fn)(struct netif *netif, void *arg); + + struct netifapi_msg { + struct tcpip_api_call_data call; +@@ -245,9 +263,27 @@ + NETIFAPI_IPADDR_DEF(ip4_addr_t, gw); + #endif /* LWIP_IPV4 */ + void *state; ++ } add; ++ ++ struct { ++ const ip_addr_t *ipaddr; ++ } find_by_ipaddr; ++ struct { ++ const char *name; ++ } find_by_name; ++ struct { ++ unsigned char ifindex; ++ } find_by_ifindex; ++ struct { ++#if LWIP_IPV4 ++ ip4_addr_t *ipaddr; ++ ip4_addr_t *netmask; ++ ip4_addr_t *gw; ++#endif /* LWIP_IPV4 */ ++ void *state; + netif_init_fn init; + netif_input_fn input; +- } add; ++ } add_get; + struct { + 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 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 + +-#define NUM_SOCKETS MEMP_NUM_NETCONN + + /** This is overridable for the rare case where more than 255 threads + * select on the same socket... +@@ -69,6 +68,10 @@ + struct netconn *conn; + /** data that was left from the previous read */ + union lwip_sock_lastdata lastdata; ++ /** offset in the data that was left from the previous read */ ++ u16_t lastoffset; ++ /* socket level mutex used for multithread recv support */ ++ sys_mutex_t mutex; + #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL + /** number of times data was received, set by event_callback(), + tested by the receive and select functions */ +@@ -158,6 +161,7 @@ + fd_set *exceptset; + #endif /* LWIP_SOCKET_SELECT */ + #if LWIP_SOCKET_POLL ++ + /** fds passed to poll; NULL if select */ + 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 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 + PACK_STRUCT_BEGIN +-struct icmp6_hdr { ++struct icmpv6_hdr { + 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 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" + #include "lwip/ip4_addr.h" ++#if LWIP_LITEOS_COMPAT ++#include ++#endif + + #ifdef __cplusplus + extern "C" { +@@ -81,10 +84,12 @@ + PACK_STRUCT_FIELD(u16_t _id); + /* fragment offset field */ + PACK_STRUCT_FIELD(u16_t _offset); ++#if !LWIP_LITEOS_COMPAT + #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 */ ++#endif + /* 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 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" + #include "lwip/ip6_addr.h" ++#include "lwip/etharp.h" ++#include "lwip/icmp6.h" + + #ifdef __cplusplus + extern "C" { +@@ -57,6 +59,18 @@ + #define RAW_FLAGS_MULTICAST_LOOP 0x04U + + struct raw_pcb; ++extern struct raw_pcb* raw_pcbs; ++ ++#if PF_PACKET_SOCKET ++extern const struct eth_hdr *g_lwip_current_eth_hdr; ++extern const struct netif *g_lwip_current_netif; ++/* Dest MAC add of current ethernet header of RAW packets ++ * received for PF_PACKET family */ ++#define eth_current_hdr() (g_lwip_current_eth_hdr) ++#define eth_current_netif() (g_lwip_current_netif) ++struct raw_pcb* get_packet_raw_pcbs(void); ++struct raw_pcb* get_all_packet_raw_pcbs(void); ++#endif /* PF_PACKET_SOCKET */ + + /** Function prototype for raw pcb receive callback functions. + * @param arg user supplied argument (raw_pcb.recv_arg) +@@ -77,8 +91,19 @@ + IP_PCB; + + struct raw_pcb *next; +- ++#if PF_PACKET_SOCKET ++ struct raw_pcb *all_next; ++ u8_t netifindex; ++ ++ union { ++ u16_t eth_proto; /* Ethernet HeaderType/Protocol for Packet sockets */ ++#define raw_proto proto.protocol ++ u8_t protocol; /* IP protocol for AF_INET sockets */ ++ } proto; ++#else ++#define raw_proto protocol + u8_t protocol; ++#endif + u8_t flags; + + #if LWIP_MULTICAST_TX_OPTIONS +@@ -115,6 +140,14 @@ + + void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); + ++#if PF_PACKET_SOCKET ++struct raw_pcb * raw_packet_new (u16_t proto); ++void raw_packet_remove (struct raw_pcb *pcb); ++void raw_packet_input (struct pbuf *p, const struct netif *inp, const struct raw_pcb *from); ++err_t raw_packet_sendto (const struct raw_pcb *pcb, struct pbuf *p, u8_t ifindex); ++err_t raw_packet_bind (struct raw_pcb *pcb, u8_t ifindex, u16_t proto); ++#endif /* PF_PACKET_SOCKET */ ++ + #define raw_flags(pcb) ((pcb)->flags) + #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 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 + ++#if LWIP_LITEOS_COMPAT ++#include "sys/select.h" ++#include "sys/socket.h" ++#include "poll.h" ++#include "netinet/tcp.h" ++#endif /* LWIP_LITEOS_COMPAT */ ++ + #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) +@@ -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. */ ++#else /* LWIP_LITEOS_COMPAT */ ++#if LWIP_LITEOS_COMPAT ++#ifndef TCP_KEEPALIVE ++#define TCP_KEEPALIVE 0x02 ++#endif /* TCP_KEEPALIVE */ ++ ++#ifndef SIN_ZERO_LEN ++#define SIN_ZERO_LEN 8 ++#endif /* SIN_ZERO_LEN */ ++ ++#ifndef SOCK_MAX ++#define SOCK_MAX (SOCK_RAW + 1) ++#endif /* SOCK_MAX */ ++ ++#ifndef SOCK_TYPE_MASK ++#define SOCK_TYPE_MASK 0xf ++#endif /* SOCK_TYPE_MASK */ ++#endif ++ + void lwip_socket_thread_init(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ + void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ + ++#if LWIP_IPV6 ++#define LWIP_IS_IPPROTOCOL(protocol) ((protocol) == IPPROTO_IP || (protocol) == IPPROTO_IPV6 || (protocol) == 0) ++#if PF_PACKET ++#define LWIP_IS_VALID_DOMAIN(domain) (((domain) == AF_INET) || ((domain) == AF_INET6) || ((domain) == PF_PACKET)) ++#else ++#define LWIP_IS_VALID_DOMAIN(domain) ((domain) == AF_INET) || ((domain) == AF_INET6) ++#endif ++#else ++#define LWIP_IS_IPPROTOCOL(protocol) ((protocol) == IPPROTO_IP || (protocol) == 0) ++#if PF_PACKET ++#define LWIP_IS_VALID_DOMAIN(domain) (((domain) == AF_INET) || ((domain) == PF_PACKET)) ++#else ++#define LWIP_IS_VALID_DOMAIN(domain) ((domain) == AF_INET) || ((domain) == AF_INET6) ++#endif ++#endif + #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 +604,9 @@ + #if LWIP_SOCKET_SELECT + #define lwip_select select + #endif ++ ++#define lwip_gethostbyname(name) gethostbyname(name) ++ + #if LWIP_SOCKET_POLL + #define lwip_poll poll + #endif +@@ -558,9 +614,18 @@ + #define lwip_inet_ntop inet_ntop + #define lwip_inet_pton inet_pton + ++#if LWIP_DNS ++#define lwip_gethostbyname(name) gethostbyname(name) ++#define lwip_gethostbyname_r gethostbyname_r ++#define lwip_freeaddrinfo freeaddrinfo ++#define lwip_getaddrinfo getaddrinfo ++#define lwip_getnameinfo getnameinfo ++#endif ++ + #if LWIP_POSIX_SOCKETS_IO_NAMES + #define lwip_read read + #define lwip_readv readv ++ + #define lwip_write write + #define lwip_writev writev + #undef lwip_close +@@ -682,7 +747,7 @@ + #ifdef __cplusplus + } + #endif +- ++#endif + #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 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. ++ * Description: declare BSD APIs : getifaddrs freeifaddrs ++ * Author: none ++ * Create: 2020 ++ */ ++ ++#ifndef __LWIP_IFADDRS_H ++#define __LWIP_IFADDRS_H ++ ++#if (LWIP_IPV4 || LWIP_IPV6) && LWIP_SOCKET ++ ++#include "lwip/netif.h" ++#include "lwip/sockets.h" ++ ++#ifdef LWIP_COMPAT_SOCKETS ++#if LWIP_COMPAT_SOCKETS != 2 ++/* @ingroup socket */ ++#define getifaddrs(ifap) lwip_getifaddrs(ifap) ++#define freeifaddrs(ifa) lwip_freeifaddrs(ifa) ++#else /* LWIP_COMPAT_SOCKETS != 2 */ ++/* @ingroup socket */ ++#define lwip_getifaddrs(ifap) getifaddrs(ifap) ++#define lwip_freeifaddrs(ifa) freeifaddrs(ifa) ++#endif /* LWIP_COMPAT_SOCKETS == 2 */ ++#endif /* LWIP_COMPAT_SOCKETS */ ++ ++#if LWIP_LITEOS_COMPAT ++ ++#ifndef SIOCETHTOOL ++#define SIOCETHTOOL _IOW('i', 56, struct ifreq) ++#endif ++#define IFF_DRV_RUNNING 0x40 ++ ++#else ++#define SIOCADDRT _IOW('R', 9, struct rtentry) ++#define SIOCDELRT _IOW('R', 10, struct rtentry) ++ ++#define SIOCGIFFLAGS _IOWR('i', 17, struct ifreq) /* get ifnet flags */ ++#define SIOCSIFFLAGS _IOW('i', 16, struct ifreq) /* set ifnet flags */ ++#define SIOCGIFADDR _IOWR('i', 33, struct ifreq) /* get ifnet address */ ++#define SIOCSIFADDR _IOW('i', 12, struct ifreq) /* set ifnet address */ ++ ++#define SIOCDIFADDR _IOW('i', 25, struct ifreq) /* delete IF addr */ ++ ++#define SIOCGIFNETMASK _IOWR('i', 37, struct ifreq) /* get net addr mask */ ++#define SIOCSIFNETMASK _IOW('i', 22, struct ifreq) /* set net addr mask */ ++#define SIOCSIFHWADDR _IOW('i', 140, struct ifreq) /* set IF name */ ++#define SIOCGIFHWADDR _IOW('i', 141, struct ifreq) /* set IF name */ ++#define SIOCGIFNAME _IOW('i', 142, struct ifreq) /* set IF name */ ++#define SIOCSIFNAME _IOW('i', 40, struct ifreq) /* set IF name */ ++ ++/** Gets IF mtu */ ++#define SIOCGIFMTU _IOWR('i', 51, struct ifreq) ++/** Sets IF mtu */ ++#define SIOCSIFMTU _IOW('i', 52, struct ifreq) ++/** ethtool */ ++#define SIOCETHTOOL _IOW('i', 56, struct ifreq) ++ ++/* provide PF_PACKET option on SOCK_RAW */ ++#define SIOCGIFINDEX _IOWR('i', 32, struct ifreq) /* get IF index */ ++#define SIOCGIFCONF _IOWR('i', 36, struct ifconf) /* get ifnet list */ ++ ++/** (n) Indicates that the interface is up */ ++#define IFF_UP 0x1 ++/** (i) Indicates that the broadcast address valid */ ++#define IFF_BROADCAST 0x2 ++/** (n) Turns on debugging */ ++#define IFF_DEBUG 0x4 ++/** (i) A loopback net */ ++#define IFF_LOOPBACK 0x8 ++/** (i) Indicates a point-to-point link */ ++#define IFF_POINTOPOINT 0x10 ++/* 0x20 was IFF_SMART */ ++/** (d) Indicates that the resources are allocated */ ++#define IFF_DRV_RUNNING 0x40 ++/** (n) No address resolution protocol */ ++#define IFF_NOARP 0x80 ++/** (n) Receive all packets */ ++#define IFF_PROMISC 0x100 ++/** (n) Receive all multicast packets */ ++#define IFF_ALLMULTI 0x200 ++/** (d) Indicates that the tx hardware queue is full */ ++#define IFF_DRV_OACTIVE 0x400 ++ /** (i) Cannot hear own transmissions */ ++#define IFF_SIMPLEX 0x800 ++/** Per link layer defined bit */ ++#define IFF_LINK0 0x1000 ++/** Per link layer defined bit */ ++#define IFF_LINK1 0x2000 ++/** Per link layer defined bit */ ++#define IFF_LINK2 0x4000 ++/** Use alternate physical connection */ ++#define IFF_ALTPHYS IFF_LINK2 ++/** Supports multicast */ ++#define IFF_MULTICAST 0x8000 ++ /** (i) Unconfigurable using ioctl(2) */ ++#define IFF_CANTCONFIG 0x10000 ++/** (n) User-requested promisc mode */ ++#define IFF_PPROMISC 0x20000 ++/** (n) User-requested IFF_MONITOR mode */ ++#define IFF_MONITOR 0x40000 ++ /** (n) Static ARP */ ++#define IFF_STATICARP 0x80000 ++/** (n) Interface is winding down */ ++#define IFF_DYING 0x200000 ++/** (n) Interface is being renamed */ ++#define IFF_RENAMING 0x400000 ++/** (n) Dialup device with changing addresses */ ++#define IFF_DYNAMIC 0x800000 ++/** (n) Dialup device with changing addresses */ ++#define IFF_DYNAMIC_S 0x1000000 ++ ++#define IFF_RUNNING IFF_DRV_RUNNING ++ ++#ifndef IFNAMSIZ ++#define IFNAMSIZ NETIF_NAMESIZE ++#endif ++ ++struct ifreq { ++#define IFHWADDRLEN 6 ++ union { ++ char ifrn_name[IFNAMSIZ]; ++ } ifr_ifrn; ++ union { ++ struct sockaddr ifru_addr; ++ struct sockaddr ifru_dstaddr; ++ struct sockaddr ifru_broadaddr; ++ struct sockaddr ifru_netmask; ++ struct sockaddr ifru_hwaddr; ++ short ifru_flags[2]; ++ int ifru_ivalue; ++ int ifru_mtu; ++ char ifru_slave[IFNAMSIZ]; ++ char ifru_newname[IFNAMSIZ]; ++ void *ifru_data; ++ } ifr_ifru; ++}; ++#define ifr_name ifr_ifrn.ifrn_name ++#define ifr_hwaddr ifr_ifru.ifru_hwaddr ++#define ifr_addr ifr_ifru.ifru_addr ++#define ifr_dstaddr ifr_ifru.ifru_dstaddr ++#define ifr_broadaddr ifr_ifru.ifru_broadaddr ++#define ifr_netmask ifr_ifru.ifru_netmask ++#define ifr_flags ifr_ifru.ifru_flags[0] /* flags (low 16 bits) */ ++#define ifr_flagshigh ifr_ifru.ifru_flags[1] /* flags (high 16 bits) */ ++#define ifr_metric ifr_ifru.ifru_ivalue ++#define ifr_mtu ifr_ifru.ifru_mtu ++#define ifr_slave ifr_ifru.ifru_slave ++#define ifr_data ifr_ifru.ifru_data ++#define ifr_ifindex ifr_ifru.ifru_ivalue ++#define ifr_bandwidth ifr_ifru.ifru_ivalue ++#define ifr_qlen ifr_ifru.ifru_ivalue ++#define ifr_newname ifr_ifru.ifru_newname ++#define ifr_index ifr_ifindex ++ ++struct ifconf { ++ int ifc_len; ++ union { ++ char *ifcu_buf; ++ struct ifreq *ifcu_req; ++ } ifc_ifcu; ++}; ++ ++#define ifc_buf ifc_ifcu.ifcu_buf ++#define ifc_req ifc_ifcu.ifcu_req ++ ++struct ifaddrs { ++ struct ifaddrs *ifa_next; /**< Pointer to the next network interfaces.f */ ++ char *ifa_name; /**< Pointer to the name of the network interfaces */ ++ unsigned int ifa_flags; /**< Pointer to the status flag. */ ++ struct sockaddr *ifa_addr; /**< Pointer to the address. */ ++ struct sockaddr *ifa_netmask; /**< Pointer to the net masking. */ ++ struct sockaddr *ifa_dstaddr; /**< Pointer to the destination address. */ ++ void *ifa_data; /**< Pointer to the data. */ ++}; ++ ++ #ifndef ifa_broadaddr ++ #define ifa_broadaddr ifa_dstaddr /* brcast address interface */ ++#endif ++ ++struct rtentry { ++ struct sockaddr rt_dst; /**< Indicates the target address. */ ++ struct sockaddr rt_gateway; /**< Indicates the gateway address (RTF_GATEWAY). */ ++ struct sockaddr rt_genmask; /**< Indicates the target network mask (IP). */ ++ unsigned int rt_flags; ++}; ++/** Indicates that the route is usable */ ++#define RTF_UP 0x1 ++/** Indicates that the destination is a gateway */ ++#define RTF_GATEWAY 0x2 ++/** Indicates the host entry (net otherwise) */ ++#define RTF_HOST 0x4 ++/** Indicates the host or net is unreachable */ ++#define RTF_REJECT 0x8 ++/** Created dynamically (by redirect) */ ++#define RTF_DYNAMIC 0x10 ++/** Modified dynamically (by redirect) */ ++#define RTF_MODIFIED 0x20 ++/** Message confirmed. */ ++#define RTF_DONE 0x40 ++/* 0x80 unused, was RTF_DELCLONE */ ++/* 0x100 unused, was RTF_CLONING */ ++/** Indicates that the external daemon resolves name */ ++#define RTF_XRESOLVE 0x200 ++/** DEPRECATED - exists ONLY for backward ++ compatibility */ ++#define RTF_LLINFO 0x400 ++/** Used by apps to add/del L2 entries */ ++#define RTF_LLDATA 0x400 ++/** Manually added */ ++#define RTF_STATIC 0x800 ++ /** Discard packets */ ++#define RTF_BLACKHOLE 0x1000 ++/** Protocol specific routing flag */ ++#define RTF_PROTO2 0x4000 ++/** Protocol specific routing flag */ ++/* 0x10000 unused, was RTF_PRCLONING */ ++#define RTF_PROTO1 0x8000 ++/* 0x10000 unused, was RTF_PRCLONING */ ++/* 0x20000 unused, was RTF_WASCLONED */ ++/** Protocol specific routing flag */ ++#define RTF_PROTO3 0x40000 ++/** MTU was explicitly specified */ ++#define RTF_FIXEDMTU 0x80000 ++/** Route is immutable */ ++#define RTF_PINNED 0x100000 ++/** Route represents a local address */ ++#define RTF_LOCAL 0x200000 ++/** Route represents a broadcast address */ ++#define RTF_BROADCAST 0x400000 ++ /** Route represents a multicast address */ ++#define RTF_MULTICAST 0x800000 ++ /* 0x8000000 and up unassigned */ ++/** Always route dst->src */ ++#define RTF_STICKY 0x10000000 ++/** Radix node head is locked */ ++#define RTF_RNH_LOCKED 0x40000000 ++/** Indicates the compatibility bit for interacting ++ with existing routing apps */ ++#define RTF_GWFLAG_COMPAT 0x80000000 ++ ++/* Mask of RTF flags that are allowed to be modified by RTM_CHANGE. */ ++#define RTF_FMASK \ ++ (RTF_PROTO1 | RTF_PROTO2 | RTF_PROTO3 | RTF_BLACKHOLE | \ ++ RTF_REJECT | RTF_STATIC | RTF_STICKY) ++ ++/** ++* @defgroup ifaddrs_api ifaddrs API ++* This section contains the interfaces to get information about Network interfaces in lwIP. ++* @ingroup socket ++*/ ++ ++/* ++Func Name: lwip_getifaddrs ++*/ ++ ++/** ++* @ingroup ifaddrs_api ++* @brief Creates a linked list of struct ifaddrs, which holds the information ++* about the network interfaces of the local system. The ifa_next field contains a ++* pointer to the next structure on the list, or NULL if this is the last item of the list. ++* The ifa_name points to the null-terminated interface name. The ifa_flags field ++* contains the interface flags. The ifa_addr field points to a structure containing ++* the interface address. The ifa_netmask field points to a structure containing ++* the netmask associated with ifa_addr, if applicable, for the address family. ++* Depending on whether the bit IFF_brcast or IFF_POINTOPOINT is set ++* in ifa_flags (only one can be set at a time), either ifa_broadaddr will contain ++* the broadcast address associated with ifa_addr (if applicable for the address ++* family) or ifa_dstaddr will contain the destination address of the point-to-point ++* interface. ++* For IPv6, stack supports only IFF_UP,IFF_MULTICAST, IFF_DRV_RUNNING, and IFF_LOOPBACK ++* flags. ++* @param[in] ifap Indicates a double pointer to the ifaddrs structure. ++* @return ++* On success, lwip_getifaddrs() returns zero; on error, -1 is returned, and errno is set appropriately. ++* @par Errors ++* @li The lwip_getifaddrs() function shall fail if: ++* - [EACCES] : \n Invalid state of system. ++* - [ENOMEM] : \n In-sufficient memory. ++* @note ++* None ++*/ ++int lwip_getifaddrs(struct ifaddrs **ifap); ++ ++/* ++Func Name: lwip_freeifaddrs ++*/ ++ ++/** ++* @ingroup ifaddrs_api ++* @brief The function lwip_freeifaddrs, provides the list of network interfaces in the ifaddrs* structure. ++* The application has to free the memory of the ifaddrs * structure by using this function. ++* @param[in] ifa Indicates a pointer to the ifaddrs structure. ++* @return ++* Void ++* @note ++* None ++*/ ++void lwip_freeifaddrs(struct ifaddrs *ifa); ++ ++#endif /* !LWIP_LITEOS_COMPAT */ ++int get_ipv6_ifaddr(struct netif *netif, struct ifaddrs *ifaddr, int tmp_index); ++int get_ipv4_ifaddr(struct netif *netif, struct ifaddrs *ifaddr); ++struct ifaddrs_storage *new_ifaddrs_storage(void); ++#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 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" + #include "lwip/snmp.h" +- ++#include "lwip/raw.h" + #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 @@ + } + } + ++#if PF_PACKET_SOCKET ++ p->flags = (u16_t)(p->flags & ~PBUF_FLAG_OUTGOING); ++ if (get_packet_raw_pcbs() != NULL) { ++ raw_packet_input(p, netif, NULL); ++ } ++#endif /* PF_PACKET_SOCKET */ + 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/origin.sha256 b/components/net/lwip/origin.sha256 new file mode 100644 index 0000000..b3e5dd2 --- /dev/null +++ b/components/net/lwip/origin.sha256 @@ -0,0 +1 @@ +51971ada3e5453e582b4a7fd15db583693e0a3a614650decbe25d79fc7bcffbd origin.patch -- Gitee From 60a9683817e6f3eb2011fb8cb30099fea2f2739d Mon Sep 17 00:00:00 2001 From: Terder-su Date: Thu, 17 Feb 2022 08:38:46 +0000 Subject: [PATCH 10/14] =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=20components/?= =?UTF-8?q?net/lwip/origin.sha256=20=E4=B8=BA=20components/net/lwip/patch.?= =?UTF-8?q?sha256?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/lwip/{origin.sha256 => patch.sha256} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename components/net/lwip/{origin.sha256 => patch.sha256} (100%) diff --git a/components/net/lwip/origin.sha256 b/components/net/lwip/patch.sha256 similarity index 100% rename from components/net/lwip/origin.sha256 rename to components/net/lwip/patch.sha256 -- Gitee From a0ce97f471639f5c762e8753a9901c329b27212f Mon Sep 17 00:00:00 2001 From: Terder-su Date: Mon, 21 Feb 2022 02:58:23 +0000 Subject: [PATCH 11/14] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20co?= =?UTF-8?q?mponents/net/lwip/origin.patch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/lwip/origin.patch | 8502 ------------------------------ 1 file changed, 8502 deletions(-) delete mode 100644 components/net/lwip/origin.patch diff --git a/components/net/lwip/origin.patch b/components/net/lwip/origin.patch deleted file mode 100644 index 8c36118..0000000 --- a/components/net/lwip/origin.patch +++ /dev/null @@ -1,8502 +0,0 @@ -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 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 - */ - struct netconn * --netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) -+netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, netconn_callback callback) - { - struct netconn *conn; - API_MSG_VAR_DECLARE(msg); -@@ -292,6 +292,37 @@ - return err; - } - -+#if PF_PACKET_SOCKET -+/** -+ * Get the local or remote IP address and port of a netconn. -+ * For pf packet netconns, this returns the struct pf_packet_sockaddr_ll of the netconn! -+ * @param conn the netconn to query -+ * @param local 1 to get the local IP address, 0 to get the remote one -+ * @return ERR_CONN for invalid connections -+ * ERR_OK if the information was retrieved -+ * ERR_OPNOTSUPP if the option is not support -+ */ -+err_t -+netconn_get_sockaddr_pf_packet(struct netconn *conn, struct pf_packet_sockaddr_ll *ll, u8_t local) -+{ -+ err_t err; -+ API_MSG_VAR_DECLARE(msg); -+ API_MSG_VAR_ALLOC(msg); -+ API_MSG_VAR_REF(msg).conn = conn; -+ API_MSG_VAR_REF(msg).msg.adpkt.local = local; -+#if LWIP_MPU_COMPATIBLE -+ err = netconn_apimsg(lwip_netconn_do_getaddr_pfpkt, &API_MSG_VAR_REF(msg)); -+ *ll = msg->msg.adpkt.ll; -+#else /* LWIP_MPU_COMPATIBLE */ -+ API_MSG_VAR_REF(msg).msg.adpkt.ll = ll; -+ err = netconn_apimsg(lwip_netconn_do_getaddr_pfpkt, &msg); -+#endif /* LWIP_MPU_COMPATIBLE */ -+ API_MSG_VAR_FREE(msg); -+ -+ return err; -+} -+#endif -+ - /** - * @ingroup netconn_common - * Bind a netconn to a specific local IP address and port. -@@ -304,9 +335,13 @@ - * @return ERR_OK if bound, any other err_t on failure - */ - err_t -+#if PF_PACKET_SOCKET -+netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port, u8_t if_idx) -+#else /* PF_PACKET_SOCKET */ - netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port) -+#endif - { -- API_MSG_VAR_DECLARE(msg); -+ API_MSG_VAR_DECLARE(msg); /* struct api_msg *msg */ - err_t err; - - LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); -@@ -332,6 +367,9 @@ - API_MSG_VAR_REF(msg).conn = conn; - API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); - API_MSG_VAR_REF(msg).msg.bc.port = port; -+#if PF_PACKET_SOCKET -+ API_MSG_VAR_REF(msg).msg.bc.if_idx = if_idx; -+#endif /* PF_PACKET_SOCKET */ - err = netconn_apimsg(lwip_netconn_do_bind, &API_MSG_VAR_REF(msg)); - API_MSG_VAR_FREE(msg); - -@@ -596,7 +634,7 @@ - - NETCONN_MBOX_WAITING_INC(conn); - if (netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK) || -- (conn->flags & NETCONN_FLAG_MBOXCLOSED) || (conn->pending_err != ERR_OK)) { -+ (conn->flags & NETCONN_FLAG_MBOXCLOSED)) { - 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; - } - SYS_ARCH_PROTECT(lev); -- err = conn->pending_err; -- conn->pending_err = ERR_OK; -+ err = conn->last_err; - SYS_ARCH_UNPROTECT(lev); - 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 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; - } - -+#if PF_PACKET_SOCKET -+ /* To get the pkt type filtered in ethernet_input */ -+ q->flags = p->flags; -+#if ETH_PAD_SIZE -+ /* exclude the begining two padding bytes in struct eth_hdr */ -+ if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_PACKET_RAW) && (pbuf_header(q, -ETH_PAD_SIZE))) { -+ (void)pbuf_free(q); -+ memp_free(MEMP_NETBUF, buf); -+ return 0; -+ } -+#endif -+#endif -+ - buf->p = q; - buf->ptr = q; -+#if PF_PACKET_SOCKET -+ /* IP addr is NULL only when RAW packets are received for PF_PACKET sockets */ -+ if (addr == NULL) { -+ ip_addr_set_any(IP_IS_V6_VAL(buf->addr), &buf->addr); -+ buf->port = eth_current_hdr()->type; -+ buf->hatype = eth_current_netif()->link_layer_type; -+ buf->netifindex = eth_current_netif()->ifindex; -+ } else { -+ ip_addr_copy(buf->addr, *ip_current_src_addr()); -+ buf->port = pcb->raw_proto; -+ } -+#else - ip_addr_copy(buf->addr, *ip_current_src_addr()); - buf->port = pcb->protocol; -+#endif - - len = q->tot_len; - if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { -@@ -444,7 +470,7 @@ - /* when err is called, the pcb is deallocated, so delete the reference */ - conn->pcb.tcp = NULL; - /* store pending error */ -- conn->pending_err = err; -+ conn->last_err = err; - /* prevent application threads from blocking on 'recvmbox'/'acceptmbox' */ - conn->flags |= NETCONN_FLAG_MBOXCLOSED; - -@@ -627,23 +653,41 @@ - if (msg->conn->pcb.raw != NULL) { - #if LWIP_IPV6 - /* ICMPv6 packets should always have checksum calculated by the stack as per RFC 3542 chapter 3.1 */ -- if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->protocol == IP6_NEXTH_ICMP6) { -+ if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->raw_proto == IP6_NEXTH_ICMP6) { - msg->conn->pcb.raw->chksum_reqd = 1; - msg->conn->pcb.raw->chksum_offset = 2; - } - #endif /* LWIP_IPV6 */ -+ -+#if LWIP_IPV4 -+ /* IP_HDRINCL is enabled by default */ -+ if (!(NETCONNTYPE_ISIPV6(msg->conn->type)) && (msg->msg.n.proto == IPPROTO_RAW)) { -+ raw_set_flags(msg->conn->pcb.raw, RAW_FLAGS_HDRINCL); -+ } -+#endif - raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); - } - break; -+ -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+ msg->conn->pcb.packet_raw = raw_packet_new(msg->msg.n.proto); -+ if (msg->conn->pcb.packet_raw == NULL) { -+ msg->err = ERR_MEM; -+ break; -+ } -+ raw_recv(msg->conn->pcb.packet_raw, recv_raw, msg->conn); -+ break; -+#endif - #endif /* LWIP_RAW */ - #if LWIP_UDP -- case NETCONN_UDP: -- msg->conn->pcb.udp = udp_new_ip_type(iptype); -- if (msg->conn->pcb.udp != NULL) { -+ case NETCONN_UDP: -+ msg->conn->pcb.udp = udp_new_ip_type(iptype); -+ if (msg->conn->pcb.udp != NULL) { - #if LWIP_UDPLITE -- if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { -- udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); -- } -+ if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { -+ udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); -+ } - #endif /* LWIP_UDPLITE */ - if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) { - udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); -@@ -683,7 +727,7 @@ - - msg->err = ERR_OK; - if (msg->conn->pcb.tcp == NULL) { -- pcb_new(msg); -+ pcb_new(msg); //raw_recv() - } - /* Else? This "new" connection already has a PCB allocated. */ - /* Is this an error condition? Should it be deleted? */ -@@ -713,13 +757,16 @@ - return NULL; - } - -- conn->pending_err = ERR_OK; -+ conn->last_err = ERR_OK; - conn->type = t; - conn->pcb.tcp = NULL; - - /* If all sizes are the same, every compiler should optimize this switch to nothing */ - switch (NETCONNTYPE_GROUP(t)) { - #if LWIP_RAW -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+#endif - case NETCONN_RAW: - size = DEFAULT_RAW_RECVMBOX_SIZE; - break; -@@ -778,8 +825,17 @@ - conn->linger = -1; - #endif /* LWIP_SO_LINGER */ - conn->flags = init_flags; -+#if LWIP_TCP -+ conn->pending_err = 0; -+ conn->refused_data = NULL; -+ ip_addr_set_zero(&conn->remote_ip); -+ conn->remote_port = 0; -+#endif - return conn; - free_and_return: -+ if (sys_sem_valid(&conn->op_completed) != 0) { -+ sys_sem_free(&conn->op_completed); -+ } - memp_free(MEMP_NETCONN, conn); - return NULL; - } -@@ -1160,6 +1216,11 @@ - case NETCONN_RAW: - raw_remove(msg->conn->pcb.raw); - break; -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+ raw_packet_remove(msg->conn->pcb.packet_raw); -+ break; -+#endif - #endif /* LWIP_RAW */ - #if LWIP_UDP - case NETCONN_UDP: -@@ -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)) || -+ ip_addr_ismulticast(API_EXPR_REF(msg->msg.bc.ipaddr)) || -+ netif_ipaddr_isbrdcast(API_EXPR_REF(msg->msg.bc.ipaddr)) || -+ ((netif != NULL) && netif_is_up(netif)))) { -+ msg->err = ERR_NOADDR; -+ } else -+#endif -+ { -+ msg->err = ERR_VAL; -+ if (msg->conn->pcb.tcp != NULL) { -+ switch (NETCONNTYPE_GROUP(msg->conn->type)) { - #if LWIP_RAW - case NETCONN_RAW: -- err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); -+ msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); -+ break; -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+ msg->err = raw_packet_bind(msg->conn->pcb.packet_raw, msg->msg.bc.if_idx, msg->msg.bc.port); - break; -+#endif - #endif /* LWIP_RAW */ - #if LWIP_UDP - case NETCONN_UDP: -- err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); -+ msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); - break; - #endif /* LWIP_UDP */ - #if LWIP_TCP - case NETCONN_TCP: -- err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); -+ if (msg->conn->pcb.tcp->local_port == 0) { -+ msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); -+ } else { -+ msg->err = ERR_VAL; -+ } -+ - break; - #endif /* LWIP_TCP */ - default: -- err = ERR_VAL; -+ msg->err = ERR_OPNOTSUPP; - break; -+ } - } -- } else { -- err = ERR_VAL; - } -- msg->err = err; - TCPIP_APIMSG_ACK(msg); - } - /** -@@ -1351,6 +1435,11 @@ - { - struct api_msg *msg = (struct api_msg *)m; - err_t err; -+ if (ERR_IS_FATAL(msg->conn->last_err)) { -+ msg->err = msg->conn->last_err; -+ TCPIP_APIMSG_ACK(msg); -+ return; -+ } - - if (msg->conn->pcb.tcp == NULL) { - /* This may happen when calling netconn_connect() a second time */ -@@ -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)) { -+#if PF_PACKET_SOCKET -+ struct ip_hdr *iphdr = NULL; -+ ip_addr_t dest_addr; -+ -+ if (!(msg->conn->pcb.raw->flags & RAW_FLAGS_CONNECTED) || -+ ip_addr_isany(&msg->conn->pcb.raw->remote_ip)) { -+ if (raw_is_flag_set(msg->conn->pcb.raw, RAW_FLAGS_HDRINCL)) { -+ if (msg->msg.b->p->len < IP_HLEN) { -+ err = ERR_MSGSIZE; -+ break; -+ } -+ -+ /* IP header already included in p */ -+ iphdr = (struct ip_hdr *)msg->msg.b->p->payload; -+ ip_addr_copy_from_ip4(dest_addr, iphdr->dest); -+ err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &dest_addr); -+ break; -+ } -+ -+ err = ERR_NODEST; -+ break; -+ } -+#endif /* PF_PACKET_SOCKET */ - err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); - } else { - err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr); - } - break; -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+ /* Check if its for sending RAW packets for PF_PACKET family */ -+ if (msg->msg.b->flags & NETBUF_FLAG_IFINDEX) { -+ err = raw_packet_sendto(msg->conn->pcb.packet_raw, msg->msg.b->p, msg->msg.b->netifindex); -+ } else { -+ err = raw_packet_sendto(msg->conn->pcb.packet_raw, msg->msg.b->p, 0); -+ } -+ break; -+#endif - #endif - #if LWIP_UDP - case NETCONN_UDP: -@@ -1868,6 +1990,11 @@ - { - struct api_msg *msg = (struct api_msg *)m; - -+ if ((msg->conn == NULL) || (msg->conn->pcb.tcp == NULL)) { -+ msg->err = ERR_CONN; -+ TCPIP_APIMSG_ACK(msg); -+ return; -+ } - if (msg->conn->pcb.ip != NULL) { - if (msg->msg.ad.local) { - ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), -@@ -1882,10 +2009,18 @@ - #if LWIP_RAW - case NETCONN_RAW: - if (msg->msg.ad.local) { -- API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; -+ ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), -+ msg->conn->pcb.raw->local_ip); -+ API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->raw_proto; - } else { -- /* return an error as connecting is only a helper for upper layers */ -- msg->err = ERR_CONN; -+ if (raw_is_flag_set(msg->conn->pcb.raw, RAW_FLAGS_CONNECTED)) { -+ ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), -+ msg->conn->pcb.raw->remote_ip); -+ API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->raw_proto; -+ } else { -+ /* return an error as connecting is only a helper for upper layers */ -+ msg->err = ERR_CONN; -+ } - } - break; - #endif /* LWIP_RAW */ -@@ -1923,6 +2058,47 @@ - TCPIP_APIMSG_ACK(msg); - } - -+#if PF_PACKET_SOCKET -+/** -+ * Return a pf pkt socket's local address -+ * Called from netconn_getaddr -+ * -+ * @param m the api_msg pointing to the connection -+ */ -+void -+lwip_netconn_do_getaddr_pfpkt(void *m) -+{ -+ struct api_msg *msg = (struct api_msg *)m; -+ struct pf_packet_sockaddr_ll ll; -+ msg->err = ERR_OK; -+ if (msg->conn->pcb.ip != NULL) { -+ /* Non standard way of do it, but doing it :( */ -+ if (msg->msg.adpkt.local) { -+ ll.sll_protocol = msg->conn->pcb.packet_raw->proto.eth_proto; -+ ll.if_idx = msg->conn->pcb.packet_raw->netifindex; -+ struct netif *netif = netif_find_by_ifindex(msg->conn->pcb.packet_raw->netifindex); -+ if (netif == NULL) { -+ LWIP_DEBUGF(SOCKETS_DEBUG, -+ ("lwip_getaddrname:netif not found for given ifindex (%u)\n", -+ msg->conn->pcb.packet_raw->netifindex)); -+ ll.sll_halen = 0; -+ ll.sll_hatype = 0; -+ } else { -+ ll.sll_hatype = netif->link_layer_type; -+ ll.sll_halen = NETIF_MAX_HWADDR_LEN; -+ (void)memcpy_s(ll.sll_addr, ll.sll_halen, netif->hwaddr, NETIF_MAX_HWADDR_LEN); -+ } -+ API_EXPR_DEREF(msg->msg.adpkt.ll) = ll; -+ } else { -+ msg->err = ERR_OPNOTSUPP; -+ } -+ } else { -+ msg->err = ERR_CONN; -+ } -+ TCPIP_APIMSG_ACK(msg); -+} -+#endif -+ - /** - * 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 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" - #include "lwip/memp.h" -- -+#include "lwip/api.h" - #include - - /** -@@ -99,7 +99,7 @@ - * NULL if no memory could be allocated - */ - void * --netbuf_alloc(struct netbuf *buf, u16_t size) -+netbuf_alloc(struct netbuf *buf, u16_t size, u8_t netconn_type) - { - LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); - -@@ -107,7 +107,22 @@ - if (buf->p != NULL) { - pbuf_free(buf->p); - } -- buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); -+ -+ switch (netconn_type) { -+#if LWIP_RAW -+ case NETCONN_RAW: -+ buf->p = pbuf_alloc(PBUF_IP, size, PBUF_RAM); -+ break; -+#endif /* LWIP_RAW */ -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+ buf->p = pbuf_alloc(PBUF_LINK, size, PBUF_RAM); -+ break; -+#endif /* PF_PACKET_SOCKET */ -+ default: -+ buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); -+ } -+ - if (buf->p == NULL) { - 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 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. */ - #if LWIP_DNS_API_DECLARE_H_ERRNO --int h_errno; -+int h_err_no; - #endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ - - /** define "hostent" variables storage: 0 if we use a static (but unprotected) -@@ -100,7 +100,7 @@ - err = netconn_gethostbyname(name, &addr); - if (err != ERR_OK) { - LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); -- h_errno = HOST_NOT_FOUND; -+ h_err_no = HOST_NOT_FOUND; - return NULL; - } - -@@ -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; -+#if defined(SIN6_LEN) - sa6->sin6_len = sizeof(struct sockaddr_in6); -+#endif -+ sa6->sin6_flowinfo = 0; - sa6->sin6_port = lwip_htons((u16_t)port_nr); - sa6->sin6_scope_id = ip6_addr_zone(ip_2_ip6(&addr)); - ai->ai_family = AF_INET6; -+ ai->ai_addrlen = sizeof(struct sockaddr_in6); - #endif /* LWIP_IPV6 */ - } else { - #if LWIP_IPV4 -@@ -385,9 +394,9 @@ - /* set up sockaddr */ - inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr)); - sa4->sin_family = AF_INET; -- sa4->sin_len = sizeof(struct sockaddr_in); - sa4->sin_port = lwip_htons((u16_t)port_nr); - ai->ai_family = AF_INET; -+ ai->ai_addrlen = sizeof(struct sockaddr_in); - #endif /* LWIP_IPV4 */ - } - -@@ -403,7 +412,6 @@ - MEMCPY(ai->ai_canonname, nodename, namelen); - ai->ai_canonname[namelen] = 0; - } -- ai->ai_addrlen = sizeof(struct sockaddr_storage); - ai->ai_addr = (struct sockaddr *)sa; - - *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 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) - -+#if LWIP_MPU_COMPATIBLE -+static inline err_t netifapi_msg_alloc(struct netifapi_msg **name) -+{ -+ API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, (*name), ERR_MEM); -+ LWIP_UNUSED_ARG(name); -+ return ERR_OK; -+} -+#else -+static inline err_t netifapi_msg_alloc(struct netifapi_msg *name) -+{ -+ LWIP_UNUSED_ARG(name); -+ return ERR_OK; -+} -+#endif -+ - /** - * Call netif_add() inside the tcpip_thread context. - */ -@@ -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, -- msg->msg.add.input)) { -+ msg->msg.add_get.init, -+ msg->msg.add_get.input)) { - return ERR_IF; - } else { - return ERR_OK; -@@ -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; -- NETIFAPI_VAR_REF(msg).msg.add.init = init; -- NETIFAPI_VAR_REF(msg).msg.add.input = input; -+ NETIFAPI_VAR_REF(msg).msg.add_get.init = init; -+ NETIFAPI_VAR_REF(msg).msg.add_get.input = input; - err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call); - NETIFAPI_VAR_FREE(msg); - return err; -@@ -377,4 +395,60 @@ - return err; - } - -+/** -+ * Call netif_find() inside the tcpip_thread context. -+ */ -+static err_t -+do_netifapi_netif_find_by_name(struct tcpip_api_call_data *m) -+{ -+ struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; -+ -+ msg->netif = netif_find(msg->msg.find_by_name.name); -+ return ERR_OK; -+} -+ -+struct netif* -+netifapi_netif_find_by_name(const char *name) -+{ -+ struct netif *netif = NULL; -+ NETIFAPI_VAR_DECLARE(msg); -+ if (netifapi_msg_alloc(&msg) != ERR_OK) { -+ return NULL; -+ } -+ -+ NETIFAPI_VAR_REF(msg).netif = NULL; -+ NETIFAPI_VAR_REF(msg).msg.find_by_name.name = name; -+ (void)tcpip_api_call(do_netifapi_netif_find_by_name, &API_VAR_REF(msg).call); -+ netif = NETIFAPI_VAR_REF(msg).netif; -+ NETIFAPI_VAR_FREE(msg); -+ return netif; -+} -+ -+/** -+ * Call netif_find_by_ipaddr() inside the tcpip_thread context. -+ */ -+static err_t -+do_netifapi_netif_find_by_ipaddr(struct tcpip_api_call_data *m) -+{ -+ struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; -+ msg->netif = netif_find_by_ipaddr(msg->msg.find_by_ipaddr.ipaddr); -+ return ERR_OK; -+} -+ -+struct netif * -+netifapi_netif_find_by_ipaddr(const ip_addr_t *ipaddr) -+{ -+ struct netif *netif = NULL; -+ NETIFAPI_VAR_DECLARE(msg); -+ if (netifapi_msg_alloc(&msg) != ERR_OK) { -+ return NULL; -+ } -+ -+ NETIFAPI_VAR_REF(msg).netif = NULL; -+ NETIFAPI_VAR_REF(msg).msg.find_by_ipaddr.ipaddr = ipaddr; -+ (void)tcpip_api_call(do_netifapi_netif_find_by_ipaddr, &API_VAR_REF(msg).call); -+ netif = NETIFAPI_VAR_REF(msg).netif; -+ NETIFAPI_VAR_FREE(msg); -+ return netif; -+} - #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 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" - #include "lwip/mld6.h" -+#include "lwip/dhcp.h" - #if LWIP_CHECKSUM_ON_COPY - #include "lwip/inet_chksum.h" - #endif -@@ -85,9 +86,19 @@ - #define API_SELECT_CB_VAR_ALLOC(name, retblock) API_VAR_ALLOC_EXT(struct lwip_select_cb, MEMP_SELECT_CB, name, retblock) - #define API_SELECT_CB_VAR_FREE(name) API_VAR_FREE(MEMP_SELECT_CB, name) - -+#if !LWIP_LITEOS_COMPAT -+#defeine SIN4_LEN(x) \ -+ (x)->sin_len = sizeof(struct sockaddr_in) -+#defeine SIN6_LEN(x) \ -+ (x)->sin6_len = sizeof(struct sockaddr_in6) -+#else -+#define SIN4_LEN(x) -+#define SIN6_LEN(x) -+#endif /* LWIP_LITEOS_COMPAT */ -+ - #if LWIP_IPV4 - #define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \ -- (sin)->sin_len = sizeof(struct sockaddr_in); \ -+ SIN4_LEN(sin); \ - (sin)->sin_family = AF_INET; \ - (sin)->sin_port = lwip_htons((port)); \ - inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \ -@@ -98,8 +109,10 @@ - #endif /* LWIP_IPV4 */ - - #if LWIP_IPV6 -+/* SIN6_LEN macro is to differntiate whether stack is using 4.3BSD or 4.4BSD variants of sockaddr_in6 -+structure */ - #define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \ -- (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ -+ SIN6_LEN(sin6); \ - (sin6)->sin6_family = AF_INET6; \ - (sin6)->sin6_port = lwip_htons((port)); \ - (sin6)->sin6_flowinfo = 0; \ -@@ -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) - -+#if LWIP_LITEOS_COMPAT -+#define VALIDATE_GET_RAW_OPTNAME_RET(_sock, _optname) do { \ -+ if ((_sock)->conn != NULL && (NETCONNTYPE_GROUP((_sock)->conn->type) == NETCONN_RAW) && \ -+ (((_optname) != SO_BROADCAST) && ((_optname) != SO_RCVTIMEO) && \ -+ ((_optname) != SO_RCVBUF) && ((_optname) != SO_TYPE) && \ -+ ((_optname) != SO_DONTROUTE) && ((_optname) != SO_BINDTODEVICE))) { \ -+ done_socket(_sock); \ -+ return ENOPROTOOPT; \ -+ } \ -+ } while (0) -+ -+#if PF_PACKET_SOCKET -+#define VALIDATE_SET_PF_PKT_OPTNAME_RET(_s, _sock, _level, _optname) do { \ -+ if ((_level) == SOL_PACKET && ((_optname) != SO_RCVTIMEO && (_optname) != SO_RCVBUF) && \ -+ (_optname) != SO_ATTACH_FILTER && (_optname) != SO_DETACH_FILTER) { \ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_PACKET, UNIMPL: optname=0x%x, ..)\n", \ -+ (_s), (_optname))); \ -+ done_socket(_sock); \ -+ return ENOPROTOOPT; \ -+ } \ -+ } while (0) -+ -+#define VALIDATE_GET_PF_PKT_OPTNAME_RET(_s,_sock,_level,_optname) do { \ -+ if ((_sock)->conn != NULL && (NETCONNTYPE_GROUP((_sock)->conn->type) == NETCONN_PACKET_RAW) && \ -+ (_level) == SOL_PACKET && ((_optname) != SO_RCVTIMEO && (_optname) != SO_RCVBUF && (_optname) != SO_TYPE)) { \ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%p, SOL_PACKET, UNIMPL: optname=0x%x, ..)\n", \ -+ (_s), (_optname))); \ -+ done_socket(_sock); \ -+ return ENOPROTOOPT; \ -+ } \ -+ } while (0) -+ -+#define VALIDATE_LEVEL_PF_PACKET(_sock,_level) \ -+ if ((_sock)->conn != NULL && ((NETCONNTYPE_GROUP(netconn_type(_sock->conn)) == NETCONN_PACKET_RAW \ -+ && SOL_SOCKET != (_level) && SOL_PACKET != (_level)) || \ -+ (NETCONNTYPE_GROUP((_sock)->conn->type) != NETCONN_PACKET_RAW && SOL_PACKET == (_level)))) -+#endif -+#endif /* LWIP_LITEOS_COMPAT */ -+ - /* 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 +564,29 @@ - return sock; - } - -+#if LWIP_LITEOS_COMPAT -+/* get numbers of unused sockets */ -+int get_unused_socket_num(void) -+{ -+ int unused = 0, i; -+ SYS_ARCH_DECL_PROTECT(lev); -+ SYS_ARCH_PROTECT(lev); -+ -+ for (i = 0; i < (int)(NUM_SOCKETS); i++) { -+ if (!sockets[i].conn -+#if LWIP_NETCONN_FULLDUPLEX -+ && !sockets[i].fd_used -+#endif -+ ) { -+ unused++; -+ } -+ } -+ -+ SYS_ARCH_UNPROTECT(lev); -+ return unused; -+} -+#endif /* LWIP_LITEOS_COMPAT */ -+ - /** - * Allocate a new socket for a given netconn. - * -@@ -696,8 +794,10 @@ - } - - IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); -- if (*addrlen > tempaddr.sa.sa_len) { -- *addrlen = tempaddr.sa.sa_len; -+ if (IP_IS_V4_VAL(naddr) && (*addrlen > (int)sizeof(struct sockaddr_in))) { -+ *addrlen = sizeof(struct sockaddr_in); -+ } else if (IP_IS_V6_VAL(naddr) && (*addrlen > (int)sizeof(struct sockaddr_in6))) { -+ *addrlen = sizeof(struct sockaddr_in6); - } - MEMCPY(addr, &tempaddr, *addrlen); - -@@ -722,28 +822,59 @@ - u16_t local_port; - err_t err; - -+#if PF_PACKET_SOCKET -+ const struct sockaddr_ll *name_ll = NULL; -+ u8_t local_if_idx = 0; -+#endif - sock = get_socket(s); - if (!sock) { - return -1; - } - -- if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { -- /* sockaddr does not match socket type (IPv4/IPv6) */ -- sock_set_errno(sock, err_to_errno(ERR_VAL)); -- done_socket(sock); -- return -1; -- } -- - /* check size, family and alignment of 'name' */ -- LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && -+#if PF_PACKET_SOCKET -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { -+ name_ll = (const struct sockaddr_ll *)(void*)name; -+ LWIP_ERROR("lwip_bind: invalid address", ((name_ll != NULL)&&(namelen == sizeof(struct sockaddr_ll)) && -+ ((name_ll->sll_family) == PF_PACKET) && IS_SOCK_ADDR_ALIGNED(name) && -+ (name_ll->sll_ifindex <= LWIP_NETIF_IFINDEX_MAX)), sock_set_errno(sock, err_to_errno(ERR_VAL)); -+ done_socket(sock); return -1); -+ -+ ip_addr_set_any_val(IPADDR_TYPE_V4, local_addr); -+ local_port = name_ll->sll_protocol; -+ local_if_idx = (u8_t)name_ll->sll_ifindex; -+ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, ", s)); -+ LWIP_DEBUGF(SOCKETS_DEBUG, (" ifindex=%u proto=%"U16_F")\n", local_if_idx, local_port)); -+ } else -+#endif -+ { -+ 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); -+ -+ if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { -+ /* sockaddr does not match socket type (IPv4/IPv6) */ -+ sock_set_errno(sock, err_to_errno(ERR_VAL)); -+ done_socket(sock); -+ return -1; -+ } -+ -+ /* check size, family and alignment of 'name' */ -+ LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && - IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)), - sock_set_errno(sock, err_to_errno(ERR_ARG)); done_socket(sock); return -1;); -- LWIP_UNUSED_ARG(namelen); -+ LWIP_UNUSED_ARG(namelen); - -- SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); -- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); -- ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); -- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); -+ SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); -+ ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); -+ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); -+ } - - #if LWIP_IPV4 && LWIP_IPV6 - /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ -@@ -753,7 +884,11 @@ - } - #endif /* LWIP_IPV4 && LWIP_IPV6 */ - -+#if PF_PACKET_SOCKET -+ err = netconn_bind(sock->conn, &local_addr, local_port, local_if_idx); -+#else /* PF_PACKET_SOCKET */ - err = netconn_bind(sock->conn, &local_addr, local_port); -+#endif - - if (err != ERR_OK) { - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); -@@ -820,6 +955,14 @@ - return -1; - } - -+#if PF_PACKET_SOCKET -+ if (NETCONN_PACKET_RAW & NETCONNTYPE_GROUP(netconn_type(sock->conn))) { -+ sock_set_errno(sock, EOPNOTSUPP); -+ done_socket(sock); -+ return -1; -+ } -+#endif -+ - 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 +1168,7 @@ - { - int truncated = 0; - union sockaddr_aligned saddr; -+ socklen_t sa_len; - - LWIP_UNUSED_ARG(conn); - -@@ -1041,10 +1185,27 @@ - #endif /* LWIP_IPV4 && LWIP_IPV6 */ - - IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port); -- if (*fromlen < saddr.sa.sa_len) { -+#if LWIP_LITEOS_COMPAT -+ if (IP_IS_V4_VAL(*fromaddr)) { -+ sa_len = sizeof(struct sockaddr_in); -+ } -+#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 */ -+ -+ if (*fromlen < sa_len) { - truncated = 1; -- } else if (*fromlen > saddr.sa.sa_len) { -- *fromlen = saddr.sa.sa_len; -+ } else if (*fromlen > sa_len) { -+ *fromlen = sa_len; - } - MEMCPY(from, &saddr, *fromlen); - return truncated; -@@ -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) { -- lwip_sock_make_addr(sock->conn, netbuf_fromaddr(buf), netbuf_fromport(buf), -- (struct sockaddr *)msg->msg_name, &msg->msg_namelen); -+#if PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT -+ struct sockaddr_ll sll; -+ -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { -+ if (msg->msg_namelen > sizeof(sll)) { -+ msg->msg_namelen = sizeof(sll); -+ } -+ -+ if (msg->msg_namelen) { -+ (void)memset_s(&sll, sizeof(sll), 0, sizeof(sll)); -+ sll.sll_family = PF_PACKET; -+ sll.sll_protocol = netbuf_fromport(buf); -+ sll.sll_hatype = netbuf_fromhatype(buf); -+ sll.sll_ifindex = netbuf_fromifindex(buf); -+ -+ if (buf->p->flags & PBUF_FLAG_LLBCAST) { -+ sll.sll_pkttype = PACKET_BROADCAST; -+ } else if (buf->p->flags & PBUF_FLAG_LLMCAST) { -+ sll.sll_pkttype = PACKET_MULTICAST; -+ } else if (buf->p->flags & PBUF_FLAG_HOST) { -+ sll.sll_pkttype = PACKET_HOST; -+ } else if (buf->p->flags & PBUF_FLAG_OUTGOING) { -+ sll.sll_pkttype = PACKET_OUTGOING; -+ } else { -+ sll.sll_pkttype = PACKET_OTHERHOST; -+ } -+ -+ (void)memcpy_s(msg->msg_name, msg->msg_namelen, (void *)&sll, msg->msg_namelen); -+ -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom_udp_raw(%d): hatype=%u", dbg_s, ntohs(sll.sll_hatype))); -+ LWIP_DEBUGF(SOCKETS_DEBUG, (" packet type = %u\n", sll.sll_pkttype)); -+ } -+ } else -+#endif /* PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT */ -+ { -+ lwip_sock_make_addr(sock->conn, netbuf_fromaddr(buf), netbuf_fromport(buf), -+ (struct sockaddr *)msg->msg_name, &msg->msg_namelen); -+ } - } - } -+ - - /* 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. */ -- if (netbuf_alloc(&chain_buf, (u16_t)size) == NULL) { -+ if (netbuf_alloc(&chain_buf, (u16_t)size, NETCONNTYPE_GROUP(netconn_type(sock->conn))) == NULL) { - err = ERR_MEM; - } else { - /* flatten the IO vectors */ -@@ -1588,8 +1784,14 @@ - struct lwip_sock *sock; - err_t err; - u16_t short_size; -- u16_t remote_port; -+ u16_t remote_port = 0; - struct netbuf buf; -+#if (PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT) -+ const struct sockaddr_ll *to_ll = NULL; -+#endif -+ const struct sockaddr_in *to_in = NULL; -+ -+ unsigned int acceptable_flags = 0; - - sock = get_socket(s); - if (!sock) { -@@ -1608,11 +1810,62 @@ - #endif /* LWIP_TCP */ - } - -- if (size > LWIP_MIN(0xFFFF, SSIZE_MAX)) { -- /* cannot fit into one datagram (at least for us) */ -- sock_set_errno(sock, EMSGSIZE); -- done_socket(sock); -- return -1; -+#if PF_PACKET_SOCKET -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { -+ to_ll = (const struct sockaddr_ll *)(void *)to; -+ -+ LWIP_ERROR("lwip_sendto: invalid address", (((data != NULL) && (size!=0)) && -+ (((to_ll != NULL) && (tolen == sizeof(struct sockaddr_ll))) && -+ ((to_ll->sll_family) == PF_PACKET) && ((((mem_ptr_t)to_ll) % 4) == 0)) && -+ (to_ll->sll_ifindex <= LWIP_NETIF_IFINDEX_MAX)), -+ sock_set_errno(sock, err_to_errno(ERR_VAL)); -+ done_socket(sock); return -1); -+ -+ LWIP_ERROR("lwip_sendto: invalid address family", ((to_ll->sll_family) == PF_PACKET), -+ sock_set_errno(sock, err_to_errno(ERR_AFNOSUPP)); -+ done_socket(sock); return -1); -+ -+ LWIP_ERROR("lwip_sendto: invalid flags. Should be 0", (flags == 0), -+ sock_set_errno(sock, err_to_errno(ERR_OPNOTSUPP)); -+ done_socket(sock); return -1); -+ -+ if (size > LWIP_MAX_PF_RAW_SEND_SIZE) { -+ sock_set_errno(sock, EMSGSIZE); -+ done_socket(sock); -+ return -1; -+ } -+ } else -+#endif /* PF_PACKET_SOCKET */ -+ { -+ to_in = (const struct sockaddr_in *)(void*)to; -+ acceptable_flags = acceptable_flags | MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL; -+ if ((~acceptable_flags) & (unsigned int)flags) { -+ sock_set_errno(sock, err_to_errno(ERR_OPNOTSUPP)); -+ done_socket(sock); -+ return -1; -+ } -+ -+ LWIP_ERROR("lwip_sendto: invalid address", ((data != NULL) && (size!=0) && (flags>=0)), -+ sock_set_errno(sock, err_to_errno(ERR_VAL)); -+ done_socket(sock); return -1); -+ -+ LWIP_ERROR("lwip_sendto: invalid address", (((to_in == NULL) && (tolen == 0)) || -+ (((to_in == NULL) && (tolen != 0)) || IS_SOCK_ADDR_LEN_VALID(tolen))), -+ sock_set_errno(sock, err_to_errno(ERR_VAL)); -+ done_socket(sock); -+ return -1); -+ -+ LWIP_ERROR("lwip_sendto: invalid address", (to == NULL || IS_SOCK_ADDR_TYPE_VALID(to)), -+ sock_set_errno(sock, err_to_errno(ERR_AFNOSUPPORT)); -+ done_socket(sock); -+ return -1); -+ -+ if (size > LWIP_MAX_UDP_RAW_SEND_SIZE) { -+ sock_set_errno(sock, EMSGSIZE); -+ done_socket(sock); -+ return -1; -+ } -+ - } - short_size = (u16_t)size; - LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || -@@ -1626,6 +1879,9 @@ - #if LWIP_CHECKSUM_ON_COPY - buf.flags = 0; - #endif /* LWIP_CHECKSUM_ON_COPY */ -+#if PF_PACKET_SOCKET -+ buf.netifindex = 0; -+#endif - if (to) { - SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port); - } else { -@@ -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)); -- ip_addr_debug_print_val(SOCKETS_DEBUG, buf.addr); -- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); -- -+#if PF_PACKET_SOCKET -+ if (buf.flags & NETBUF_FLAG_IFINDEX) { -+ LWIP_DEBUGF(SOCKETS_DEBUG, (" netifindex = %d\n", buf.netifindex)); -+ } else -+#endif -+ { -+ ip_addr_debug_print_val(SOCKETS_DEBUG, buf.addr); -+ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); -+ } - /* make the buffer point to the data that should be sent */ - #if LWIP_NETIF_TX_SINGLE_PBUF - /* Allocate a new netbuf and copy the data into it. */ -- if (netbuf_alloc(&buf, short_size) == NULL) { -+ if (netbuf_alloc(&buf, short_size, NETCONNTYPE_GROUP(netconn_type(sock->conn))) == NULL) { - err = ERR_MEM; - } else { - #if LWIP_CHECKSUM_ON_COPY -- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { -+#if PF_PACKET_SOCKET -+ if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_PACKET_RAW) && -+ (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW)) -+#else -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) -+#endif -+ { - u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); - netbuf_set_chksum(&buf, chksum); - } else -@@ -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: -- conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), -- (u8_t)protocol, DEFAULT_SOCKET_EVENTCB); -- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", -+#if PF_PACKET_SOCKET -+ if (domain == PF_PACKET) { -+ conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_PACKET_RAW), -+ (u16_t)protocol, event_callback); -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", "PF_PACKET", protocol)); -+ } else -+#endif -+ { -+ conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), -+ (u8_t)protocol, DEFAULT_SOCKET_EVENTCB); -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", - domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); -+ } - break; - case SOCK_DGRAM: - conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, -@@ -1983,10 +2269,11 @@ - timeout ? (s32_t)timeout->tv_sec : (s32_t) - 1, - timeout ? (s32_t)timeout->tv_usec : (s32_t) - 1)); - -- if ((maxfdp1 < 0) || (maxfdp1 > LWIP_SELECT_MAXNFDS)) { -+/*if ((maxfdp1 < 0) || (maxfdp1 > LWIP_SELECT_MAXNFDS)) { - set_errno(EINVAL); - return -1; - } -+ */ - - lwip_select_inc_sockets_used(maxfdp1, readset, writeset, exceptset, &used_sockets); - -@@ -2704,12 +2991,60 @@ - ip_addr_t naddr; - u16_t port; - err_t err; -+ socklen_t sa_len; -+ -+#if PF_PACKET_SOCKET -+ struct sockaddr_ll addr_sin; -+ struct pf_packet_sockaddr_ll sll; -+ socklen_t outlen; -+#endif -+ -+ LWIP_ERROR("lwip_getaddrname: invalid arguments", ((name != NULL) && (namelen != NULL)), -+ set_errno(EINVAL); return -1); - - sock = get_socket(s); - if (!sock) { - return -1; - } - -+#if PF_PACKET_SOCKET -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_PACKET_RAW) { -+ err = netconn_get_sockaddr_pf_packet(sock->conn, &sll, local); -+ if (err != ERR_OK) { -+ sock_set_errno(sock, err_to_errno(err)); -+ done_socket(sock); -+ return -1; -+ } -+ -+ (void)memset_s(&addr_sin, sizeof(struct sockaddr_ll), 0, sizeof(struct sockaddr_ll)); -+ addr_sin.sll_family = PF_PACKET; -+ addr_sin.sll_protocol = sll.sll_protocol; -+ addr_sin.sll_pkttype = 0; -+ addr_sin.sll_ifindex = sll.if_idx; -+ addr_sin.sll_hatype = sll.sll_hatype; -+ addr_sin.sll_halen = sll.sll_halen; -+ -+ if ((sll.sll_halen > 0) && (memcpy_s(addr_sin.sll_addr, addr_sin.sll_halen, sll.sll_addr, sll.sll_halen) != EOK)) { -+ sock_set_errno(sock, err_to_errno(ERR_MEM)); -+ done_socket(sock); -+ return -1; -+ } -+ -+ outlen = sizeof(struct sockaddr_ll); -+ if (outlen > *namelen) { -+ outlen = *namelen; -+ } -+ if (memcpy_s(name, *namelen, &addr_sin, outlen) != EOK) { -+ sock_set_errno(sock, err_to_errno(ERR_MEM)); -+ done_socket(sock); -+ return -1; -+ } -+ *namelen = outlen; -+ done_socket(sock); -+ return 0; -+ } -+#endif /* PF_PACKET_SOCKET */ -+ - /* get the IP address and port */ - err = netconn_getaddr(sock->conn, &naddr, &port, local); - if (err != ERR_OK) { -@@ -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)); -+ if (IP_IS_V4_VAL(naddr)) { -+ sa_len = sizeof(struct sockaddr_in); -+ } else { -+ sa_len = sizeof(struct sockaddr_in6); -+ } - -- if (*namelen > saddr.sa.sa_len) { -- *namelen = saddr.sa.sa_len; -+ if (*namelen > sa_len) { -+ *namelen = sa_len; - } - MEMCPY(name, &saddr, *namelen); - -@@ -2775,6 +3115,14 @@ - return -1; - } - -+#if PF_PACKET_SOCKET -+ VALIDATE_LEVEL_PF_PACKET(sock, level) { -+ sock_set_errno(sock, EINVAL); -+ done_socket(sock); -+ return -1; -+ } -+#endif /* PF_PACKET_SOCKET */ -+ - #if LWIP_TCPIP_CORE_LOCKING - /* core-locking can just call the -impl function */ - LOCK_TCPIP_CORE(); -@@ -2826,8 +3174,9 @@ - err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; - LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); - #endif /* LWIP_TCPIP_CORE_LOCKING */ -- -- sock_set_errno(sock, err); -+ if (err != ERR_OK) { -+ sock_set_errno(sock, err); -+ } - done_socket(sock); - return err ? -1 : 0; - } -@@ -2897,6 +3246,11 @@ - - /* Level: SOL_SOCKET */ - case SOL_SOCKET: -+#if PF_PACKET_SOCKET -+ case SOL_PACKET: -+ VALIDATE_GET_PF_PKT_OPTNAME_RET(s, sock, level, optname); -+#endif /* PF_PACKET_SOCKET */ -+ VALIDATE_GET_RAW_OPTNAME_RET(sock, optname); - switch (optname) { - - #if LWIP_TCP -@@ -2920,6 +3274,10 @@ - #if SO_REUSE - case SO_REUSEADDR: - #endif /* SO_REUSE */ -+ if (sock->conn == NULL) { -+ done_socket(sock); -+ return EINVAL; -+ } - if ((optname == SO_BROADCAST) && - (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP)) { - done_socket(sock); -@@ -2937,6 +3295,9 @@ - case SO_TYPE: - LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); - switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) { -+#if PF_PACKET_SOCKET -+ case NETCONN_PACKET_RAW: -+#endif - case NETCONN_RAW: - *(int *)optval = SOCK_RAW; - break; -@@ -2948,9 +3309,16 @@ - break; - default: /* unrecognized socket type */ - *(int *)optval = netconn_type(sock->conn); -+#if PF_PACKET_SOCKET -+ LWIP_DEBUGF(SOCKETS_DEBUG, -+ ("lwip_getsockopt(%d, %s, SO_TYPE): unrecognized socket type %d\n", -+ s, (NETCONN_PACKET_RAW != NETCONNTYPE_GROUP(sock->conn->type)) ? "SOL_SOCKET" : "SOL_PACKET", -+ *(int *)optval)); -+#else - LWIP_DEBUGF(SOCKETS_DEBUG, - ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", - s, *(int *)optval)); -+#endif - } /* switch (netconn_type(sock->conn)) */ - LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", - s, *(int *)optval)); -@@ -3739,92 +4107,450 @@ - return err; - } - --int --lwip_ioctl(int s, long cmd, void *argp) -+#if PF_PACKET_SOCKET || LOSCFG_COMPONENTS_UPNP -+#if LWIP_IOCTL_IF -+static u8_t lwip_ioctl_internal_SIOCGIFCONF(struct ifreq *ifr) -+{ -+ struct ifconf *ifc = NULL; -+ struct netif *netif = NULL; -+ struct ifreq ifreq; -+ struct sockaddr_in *sock_in = NULL; -+ int pos; -+ int len; -+ int ret; -+ -+ /* Format the caller's buffer. */ -+ ifc = (struct ifconf*)ifr; -+ len = ifc->ifc_len; -+ -+ /* Loop over the interfaces, and write an info block for each. */ -+ pos = 0; -+ for (netif = netif_list; netif != NULL; netif = netif->next) { -+ if (ifc->ifc_buf == NULL) { -+ pos = (pos + (int)sizeof(struct ifreq)); -+ continue; -+ } -+ -+ if (len < (int)sizeof(ifreq)) { -+ break; -+ } -+ -+ if (memset_s(&ifreq, sizeof(struct ifreq), 0, sizeof(struct ifreq)) != EOK) { -+ return ENOBUFS; -+ } -+ if (netif->link_layer_type == LOOPBACK_IF) { -+ ret = snprintf_s(ifreq.ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s", netif->name); -+ if ((ret <= 0) || (ret >= IFNAMSIZ)) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed.")); -+ return ENOBUFS; -+ } -+ } else { -+ ret = snprintf_s(ifreq.ifr_name, NETIF_NAMESIZE, NETIF_NAMESIZE - 1, "%s%"U8_F, netif->name, netif->num); -+ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed.")); -+ return ENOBUFS; -+ } -+ } -+ -+ sock_in = (struct sockaddr_in *)&ifreq.ifr_addr; -+ sock_in->sin_family = AF_INET; -+ sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr; -+ if (memcpy_s(ifc->ifc_buf + pos, sizeof(struct ifreq), &ifreq, sizeof(struct ifreq)) != EOK) { -+ return ENOBUFS; -+ } -+ pos += (int)sizeof(struct ifreq); -+ len -= (int)sizeof(struct ifreq); -+ } -+ -+ ifc->ifc_len = pos; -+ -+ return 0; -+} -+ -+static u8_t lwip_ioctl_internal_SIOCGIFADDR(struct ifreq *ifr) -+{ -+ struct netif *netif = NULL; -+ struct sockaddr_in *sock_in = NULL; -+ -+ /* get netif ipaddr */ -+ netif = netif_find(ifr->ifr_name); -+ if (netif == NULL) { -+ return ENODEV; -+ } else { -+ sock_in = (struct sockaddr_in *)&ifr->ifr_addr; -+ sock_in->sin_family = AF_INET; -+ sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr; -+ return 0; -+ } -+} -+ -+static u8_t lwip_ioctl_internal_SIOCSIFFLAGS(const struct ifreq *ifr) -+{ -+ struct netif *netif = NULL; -+ -+ /* set netif hw addr */ -+ netif = netif_find(ifr->ifr_name); -+ if (netif == NULL) { -+ return ENODEV; -+ } -+#if LWIP_HAVE_LOOPIF -+ else if (netif->link_layer_type == LOOPBACK_IF) { -+ return EPERM; -+ } -+#endif /* LWIP_HAVE_LOOPIF */ -+ else { -+ if ((ifr->ifr_flags & IFF_UP) && !(netif->flags & NETIF_FLAG_UP)) { -+ (void)netif_set_up(netif); -+ } else if (!(ifr->ifr_flags & IFF_UP) && (netif->flags & NETIF_FLAG_UP)) { -+ (void)netif_set_down(netif); -+ } -+ if ((ifr->ifr_flags & IFF_RUNNING) && !(netif->flags & NETIF_FLAG_LINK_UP)) { -+ (void)netif_set_link_up(netif); -+ } else if (!(ifr->ifr_flags & IFF_RUNNING) && (netif->flags & NETIF_FLAG_LINK_UP)) { -+ (void)netif_set_link_down(netif); -+ } -+ -+ if (ifr->ifr_flags & IFF_BROADCAST) { -+ netif->flags |= NETIF_FLAG_BROADCAST; -+ } else { -+ netif->flags = netif->flags & (~NETIF_FLAG_BROADCAST); -+ } -+ if (ifr->ifr_flags & IFF_NOARP) { -+ netif->flags = (netif->flags & (~NETIF_FLAG_ETHARP)); -+ } else { -+ netif->flags |= NETIF_FLAG_ETHARP; -+ } -+ -+ if (ifr->ifr_flags & IFF_MULTICAST) { -+#if LWIP_IGMP -+ netif->flags |= NETIF_FLAG_IGMP; -+#endif /* LWIP_IGMP */ -+#if LWIP_IPV6 && LWIP_IPV6_MLD -+ netif->flags |= NETIF_FLAG_MLD6; -+#endif /* LWIP_IPV6_MLD */ -+ } -+ else { -+#if LWIP_IGMP -+ netif->flags = (netif->flags & ~NETIF_FLAG_IGMP); -+#endif /* LWIP_IGMP */ -+#if LWIP_IPV6 && LWIP_IPV6_MLD -+ netif->flags = (netif->flags & ~NETIF_FLAG_MLD6); -+#endif /* LWIP_IPV6_MLD */ -+ } -+ -+#if 0 -+ if (ifr->ifr_flags & IFF_DYNAMIC) { -+ (void)dhcp_start(netif); -+ } else { -+ dhcp_stop(netif); -+ dhcp_cleanup(netif); -+ } -+#endif -+ -+ return 0; -+ } -+} -+ -+static u8_t lwip_ioctl_internal_SIOCGIFFLAGS(struct ifreq *ifr) -+{ -+ struct netif *netif = NULL; -+ -+ /* set netif hw addr */ -+ netif = netif_find(ifr->ifr_name); -+ if (netif == NULL) { -+ return ENODEV; -+ } else { -+ if (netif->flags & NETIF_FLAG_UP) { -+ ifr->ifr_flags |= IFF_UP; -+ } else { -+ ifr->ifr_flags &= ~IFF_UP; -+ } -+ if (netif->flags & NETIF_FLAG_LINK_UP) { -+ ifr->ifr_flags |= IFF_RUNNING; -+ } else { -+ ifr->ifr_flags &= ~IFF_RUNNING; -+ } -+ if (netif->flags & NETIF_FLAG_BROADCAST) { -+ ifr->ifr_flags |= IFF_BROADCAST; -+ } else { -+ ifr->ifr_flags &= ~IFF_BROADCAST; -+ } -+ if (netif->flags & NETIF_FLAG_ETHARP) { -+ ifr->ifr_flags &= ~IFF_NOARP; -+ } else { -+ ifr->ifr_flags |= IFF_NOARP; -+ } -+ -+#if LWIP_IGMP || LWIP_IPV6_MLD -+ if ( -+#if LWIP_IGMP -+ (netif->flags & NETIF_FLAG_IGMP) -+#endif /* LWIP_IGMP */ -+#if LWIP_IGMP && LWIP_IPV6_MLD -+ || -+#endif /* LWIP_IGMP && LWIP_IPV6_MLD */ -+#if LWIP_IPV6_MLD -+ (netif->flags & NETIF_FLAG_MLD6) -+#endif /* LWIP_IPV6_MLD */ -+ ) { -+ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_MULTICAST); -+ } else { -+ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_MULTICAST)); -+ } -+#endif /* LWIP_IGMP || LWIP_IPV6_MLD */ -+ -+#if LWIP_DHCP -+ if (netif->flags & NETIF_FLAG_DHCP) { -+ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_DYNAMIC); -+ } else { -+ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_DYNAMIC)); -+ } -+#endif -+ -+#if LWIP_HAVE_LOOPIF -+ if (netif->link_layer_type == LOOPBACK_IF) { -+ ifr->ifr_flags |= IFF_LOOPBACK; -+ } -+#endif -+ -+ return 0; -+ } -+} -+ -+static u8_t lwip_ioctl_internal_SIOCGIFNAME(struct ifreq *ifr) -+{ -+ struct netif *netif = NULL; -+ int ret; -+ -+ for (netif = netif_list; netif != NULL; netif = netif->next) { -+ if (ifr->ifr_ifindex == netif->ifindex) { -+ break; -+ } -+ } -+ -+ if (netif == NULL) { -+ return ENODEV; -+ } -+ if (netif->link_layer_type == LOOPBACK_IF) { -+ ret = snprintf_s(ifr->ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s", netif->name); -+ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { -+ return ENOBUFS; -+ } -+ } else { -+ ret = snprintf_s(ifr->ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s%"U8_F, netif->name, netif->num); -+ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { -+ return ENOBUFS; -+ } -+ } -+ return 0; -+} -+ -+static u8_t lwip_ioctl_internal_SIOCGIFINDEX(struct ifreq *ifr) -+{ -+ struct netif *netif = NULL; -+ netif = netif_find(ifr->ifr_name); -+ if (netif == NULL) { -+ return ENODEV; -+ } -+ ifr->ifr_ifindex = netif->ifindex; -+ return 0; -+} -+#endif /* LWIP_IOCTL_IF */ -+#endif /* PF_PACKET_SOCKET */ -+ -+#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE -+static u8_t lwip_ioctl_internal_FIONREAD(struct lwip_sock *sock, void *argp) - { -- struct lwip_sock *sock = get_socket(s); -- u8_t val; - #if LWIP_SO_RCVBUF - int recv_avail; --#endif /* LWIP_SO_RCVBUF */ -+#endif -+#if LWIP_FIONREAD_LINUXMODE -+ SYS_ARCH_DECL_PROTECT(lev); -+#endif - -- if (!sock) { -- return -1; -+ if (!argp) { -+ return EINVAL; - } - -- switch (cmd) { --#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE -- case FIONREAD: -- if (!argp) { -- sock_set_errno(sock, EINVAL); -- done_socket(sock); -- return -1; -- } -+ lwip_sock_lock(sock); - #if LWIP_FIONREAD_LINUXMODE -- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { -- struct netbuf *nb; -- if (sock->lastdata.netbuf) { -- nb = sock->lastdata.netbuf; -- *((int *)argp) = nb->p->tot_len; -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { -+ struct netbuf *nb; -+ if (sock->lastdata.netbuf) { -+ nb = sock->lastdata.netbuf; -+ *((int *)argp) = nb->p->tot_len; -+ } else { -+ struct netbuf *rxbuf; -+ err_t err; -+ -+ SYS_ARCH_PROTECT(lev); -+ if (sock->rcvevent <= 0) { -+ *((int*)argp) = 0; -+ SYS_ARCH_UNPROTECT(lev); -+ } else { -+ SYS_ARCH_UNPROTECT(lev); -+ err = netconn_recv_udp_raw_netbuf_flags(sock->conn, &rxbuf, NETCONN_DONTBLOCK); -+ if (err != ERR_OK) { -+ *((int *)argp) = 0; - } else { -- struct netbuf *rxbuf; -- err_t err = netconn_recv_udp_raw_netbuf_flags(sock->conn, &rxbuf, NETCONN_DONTBLOCK); -- if (err != ERR_OK) { -- *((int *)argp) = 0; -- } else { -- sock->lastdata.netbuf = rxbuf; -- *((int *)argp) = rxbuf->p->tot_len; -- } -+ sock->lastdata.netbuf = rxbuf; -+ *((int *)argp) = rxbuf->p->tot_len; - } -- done_socket(sock); -- return 0; - } -+ } -+ -+ lwip_sock_unlock(sock); -+ return 0; -+ } - #endif /* LWIP_FIONREAD_LINUXMODE */ - - #if LWIP_SO_RCVBUF -- /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ -- SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); -- if (recv_avail < 0) { -- recv_avail = 0; -- } -+ /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ -+ SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); -+ if (recv_avail < 0) { -+ recv_avail = 0; -+ } - -- /* Check if there is data left from the last recv operation. /maq 041215 */ -- if (sock->lastdata.netbuf) { -- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { -- recv_avail += sock->lastdata.pbuf->tot_len; -- } else { -- recv_avail += sock->lastdata.netbuf->p->tot_len; -- } -- } -- *((int *)argp) = recv_avail; -+ /* Check if there is data left from the last recv operation. /maq 041215 */ -+ if (sock->lastdata.netbuf) { -+ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { -+ recv_avail += sock->lastdata.pbuf->tot_len; -+ } else { -+ recv_avail += sock->lastdata.netbuf->p->tot_len; -+ } -+ } -+ *((int *)argp) = recv_avail; - -- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t *)argp))); -- sock_set_errno(sock, 0); -- done_socket(sock); -- return 0; -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(FIONREAD, %p) = %"U16_F"\n", argp, *((u16_t *)argp))); -+ lwip_sock_unlock(sock); -+ return 0; - #else /* LWIP_SO_RCVBUF */ -- break; -+ lwip_sock_unlock(sock); -+ return ENOSYS; - #endif /* LWIP_SO_RCVBUF */ -+} - #endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ - -- case (long)FIONBIO: -- val = 0; -- if (argp && *(int *)argp) { -- val = 1; -+static u8_t lwip_ioctl_internal_FIONBIO(struct lwip_sock *sock, const void *argp) -+{ -+ u8_t val = 0; -+ SYS_ARCH_DECL_PROTECT(lev); -+ if (argp == NULL) { -+ return EINVAL; -+ } -+ if (*(int *)argp) { -+ val = 1; -+ } -+ SYS_ARCH_PROTECT(lev); -+ netconn_set_nonblocking(sock->conn, val); -+ SYS_ARCH_UNPROTECT(lev); -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(FIONBIO, %d)\n", val)); -+ return 0; -+} -+ -+static u8_t lwip_ioctl_impl(struct lwip_sock *sock, long cmd, void *argp) -+{ -+ u8_t err = 0; -+#if LWIP_NETIF_ETHTOOL -+ s32_t ret; -+#endif -+#if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_IF || LWIP_NETIF_ETHTOOL -+ struct ifreq *ifr = (struct ifreq *)argp; -+#endif -+#if LWIP_IOCTL_ROUTE -+ struct rtentry *rmten = (struct rtentry *)argp; -+#endif -+#if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_ROUTE || LWIP_IOCTL_IF -+ u8_t is_ipv6 = NETCONNTYPE_ISIPV6(sock->conn->type); -+#endif -+ -+ LWIP_ASSERT("no socket given", sock != NULL); -+ -+ switch (cmd) { -+#if PF_PACKET_SOCKET || LOSCFG_COMPONENTS_UPNP -+#if LWIP_IOCTL_IF -+ case SIOCGIFCONF: -+ /* Do not allow if socket is AF_INET6 */ -+ if (is_ipv6) { -+ err = EINVAL; -+ } else { -+ err = lwip_ioctl_internal_SIOCGIFCONF(ifr); //add: SIOCGIFCONF - } -- netconn_set_nonblocking(sock->conn, val); -- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); -- sock_set_errno(sock, 0); -- done_socket(sock); -- return 0; -+ break; -+ case SIOCGIFADDR: -+ if (is_ipv6) { -+ err = EINVAL; -+ } else { -+ err = lwip_ioctl_internal_SIOCGIFADDR(ifr); //add: SIOCGIFADDR -+ } -+ break; -+ case SIOCSIFFLAGS: -+ err = lwip_ioctl_internal_SIOCSIFFLAGS(ifr); //add: SIOCSIFFLAGS -+ break; -+ case SIOCGIFFLAGS: -+ err = lwip_ioctl_internal_SIOCGIFFLAGS(ifr); //add: SIOCSIFFLAGS -+ break; -+ case SIOCGIFNAME: -+ err = lwip_ioctl_internal_SIOCGIFNAME(ifr); //add: SIOCGIFNAME -+ break; -+ /* Need to support the get index through ioctl -+ * As of now the options is restricted to PF_PACKET scenario , so removed the compiler flag Begin -+ */ -+ case SIOCGIFINDEX: -+ err = lwip_ioctl_internal_SIOCGIFINDEX(ifr); //add: SIOCGIFINDEX -+ break; -+#endif /* LWIP_IOCTL_IF */ -+#else -+ (void)ifr; -+ (void)is_ipv6; -+#endif /* PF_PACKET_SOCKET */ -+#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE -+ case FIONREAD: -+ err = lwip_ioctl_internal_FIONREAD(sock, argp); -+ break; -+#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ - -+ case FIONBIO: -+ err = lwip_ioctl_internal_FIONBIO(sock, argp); -+ break; -+ /* -1 should return EINVAL */ -+ case -1: -+ err = EINVAL; -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl_impl(INVALID: 0x%lx)\n", cmd)); -+ break; - default: -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(UNIMPL: 0x%lx, %p)\n", cmd, argp)); -+ err = ENOSYS; /* not yet implemented */ - break; - } /* switch (cmd) */ -- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); -- sock_set_errno(sock, ENOSYS); /* not yet implemented */ -+ -+ return err; -+} -+ -+int -+lwip_ioctl(int s, long cmd, void *argp) -+{ -+ u8_t err; -+ struct lwip_sock *sock = get_socket(s); -+ if (!sock) { -+ /* get_socket has updated errno */ -+ return -1; -+ } -+ if (argp == NULL) { -+ sock_set_errno(sock, EFAULT); -+ done_socket(sock); -+ return -1; -+ } -+ -+ LOCK_TCPIP_CORE(); -+ err = lwip_ioctl_impl(sock, cmd, argp); -+ UNLOCK_TCPIP_CORE(); -+ if (err != ERR_OK) { -+ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, cmd: 0x%lx, %p)\n", s, cmd, argp)); -+ sock_set_errno(sock, err); -+ } - done_socket(sock); -- return -1; -+ return (err == 0) ? 0 : -1; - } - - /** A minimal implementation of fcntl. -@@ -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; -- - break; - 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 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 @@ - } - - static void --recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) -+tftp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) - { - u16_t *sbuf = (u16_t *) p->payload; - int opcode; -@@ -416,7 +416,7 @@ - tftp_state.last_data = NULL; - tftp_state.upcb = pcb; - -- udp_recv(pcb, recv, NULL); -+ udp_recv(pcb, tftp_recv, NULL); - - 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 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) - { -- if (cp != NULL) { -+ if (cp != NULL && addr != NULL) { - const char *c; - for (c = cp; *c != 0; c++) { - if (*c == ':') { - /* contains a colon: IPv6 address */ -- if (addr) { -- IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); -- } -+ IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); - return ip6addr_aton(cp, ip_2_ip6(addr)); - } else if (*c == '.') { - /* contains a dot: IPv4 address */ -@@ -137,9 +147,7 @@ - } - } - /* call ip4addr_aton as fallback or if IPv4 was found */ -- if (addr) { -- IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); -- } -+ IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); - return ip4addr_aton(cp, ip_2_ip4(addr)); - } - return 0; -@@ -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 */ - -+struct netif* -+ip_route_pcb(const ip_addr_t *dest, const struct ip_pcb* pcb) -+{ -+ struct netif *netif = NULL; -+#if LWIP_SO_DONTROUTE -+ rt_scope_t scope = RT_SCOPE_UNIVERSAL; -+ -+ LWIP_ASSERT("Expecting ipaddr to be not NULL ", dest != NULL); -+ if (pcb != NULL) { -+ scope = ip_get_option(pcb, SOF_DONTROUTE) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSAL; -+ } -+#endif -+ -+ if ((pcb != NULL) && (pcb->netif_idx != NETIF_NO_INDEX)) { -+ return netif_find_by_ifindex(pcb->netif_idx); -+ } -+ -+ if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { -+ /* Don't call ip_route() with IP_ANY_TYPE */ -+ netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(dest)), dest); -+ } else { -+ netif = ip_route(&pcb->local_ip, dest); -+ } -+ -+ if (netif == NULL) { -+ return NULL; -+ } -+ -+#if LWIP_SO_DONTROUTE -+ if (netif->scope < scope) { -+ return NULL; -+ } -+#endif -+ return netif; -+} -+ -+#if LWIP_INET_ADDR_FUNC -+in_addr_t inet_addr(const char *cp) -+{ -+ LWIP_ERROR("inet_aton:cp is NULL", (cp != NULL), return (INADDR_NONE)); -+ return ipaddr_addr(cp); -+} -+#endif -+ -+#if LWIP_INET_ATON_FUNC -+int inet_aton(const char *cp, struct in_addr *inp) -+{ -+ LWIP_ERROR("inet_aton:cp is NULL", (cp != NULL), return 0); -+ return ip4addr_aton(cp, (ip4_addr_t *)inp); -+} -+#endif -+ -+#if LWIP_INET_NTOA_FUNC -+char* inet_ntoa(struct in_addr in) -+{ -+ return ip4addr_ntoa((const ip4_addr_t *)&in); -+} -+#endif -+ - #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 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) - { -- struct icmp6_hdr *icmp6hdr; -+ struct icmpv6_hdr *icmp6hdr; - struct pbuf *r; - const ip6_addr_t *reply_src; - - ICMP6_STATS_INC(icmp6.recv); - - /* Check that ICMPv6 header fits in payload */ -- if (p->len < sizeof(struct icmp6_hdr)) { -+ if (p->len < sizeof(struct icmpv6_hdr)) { - /* drop short packets */ - pbuf_free(p); - ICMP6_STATS_INC(icmp6.lenerr); -@@ -97,7 +97,7 @@ - return; - } - -- icmp6hdr = (struct icmp6_hdr *)p->payload; -+ icmp6hdr = (struct icmpv6_hdr *)p->payload; - - #if CHECKSUM_CHECK_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP6) { -@@ -386,10 +386,10 @@ - const ip6_addr_t *reply_src, const ip6_addr_t *reply_dest, struct netif *netif) - { - struct pbuf *q; -- struct icmp6_hdr *icmp6hdr; -+ struct icmpv6_hdr *icmp6hdr; - - /* ICMPv6 header + IPv6 header + data */ -- q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, -+ q = pbuf_alloc(PBUF_IP, sizeof(struct icmpv6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, - PBUF_RAM); - if (q == NULL) { - LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n")); -@@ -397,15 +397,15 @@ - return; - } - LWIP_ASSERT("check that first pbuf can hold icmp 6message", -- (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); -+ (q->len >= (sizeof(struct icmpv6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); - -- icmp6hdr = (struct icmp6_hdr *)q->payload; -+ icmp6hdr = (struct icmpv6_hdr *)q->payload; - icmp6hdr->type = type; - icmp6hdr->code = code; - icmp6hdr->data = lwip_htonl(data); - - /* copy fields from original packet */ -- SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload, -+ SMEMCPY((u8_t *)q->payload + sizeof(struct icmpv6_hdr), (u8_t *)p->payload, - IP6_HLEN + LWIP_ICMP6_DATASIZE); - - /* 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 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 */ - { -- struct icmp6_hdr *icmp6hdr; /* Packet too big message */ -+ struct icmpv6_hdr *icmp6hdr; /* Packet too big message */ - struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */ - u32_t pmtu; - ip6_addr_t destination_address; - - /* Check that ICMPv6 header + IPv6 header fit in payload */ -- if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { -+ if (p->len < (sizeof(struct icmpv6_hdr) + IP6_HLEN)) { - /* drop short packets */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); -@@ -908,8 +908,8 @@ - return; - } - -- icmp6hdr = (struct icmp6_hdr *)p->payload; -- ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); -+ icmp6hdr = (struct icmpv6_hdr *)p->payload; -+ ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmpv6_hdr)); - - /* 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 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" - #endif -+#include "lwip/tcpip.h" -+ - - #if LWIP_NETIF_STATUS_CALLBACK - #define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) -@@ -229,6 +231,8 @@ - return ip_input(p, inp); - } - -+static u8_t netif_alloc_ifindex(void); -+ - /** - * @ingroup netif - * Add a network interface to the list of lwIP netifs. -@@ -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 */ - -+ /* -+ * Need to support the get index for all families -+ * removed PF_PACKET_SOCKET flag , as this flags restricts the usage to only PF_FAMILY -+ */ -+ netif->ifindex = netif_alloc_ifindex(); -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif: netif->ifindex=%d", netif->ifindex)); -+ if ((netif->ifindex < LWIP_NETIF_IFINDEX_START) || (netif->ifindex > LWIP_NETIF_IFINDEX_MAX)) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif: interface index alloc fail")); -+ return NULL; -+ } -+ - #if !LWIP_SINGLE_NETIF - /* Assign a unique netif number in the range [0..254], so that (num+1) can - serve as an interface index that fits in a u8_t. - We assume that the new netif has not yet been added to the list here. - This algorithm is O(n^2), but that should be OK for lwIP. - */ -- { -- struct netif *netif2; -- int num_netifs; -- do { -- if (netif->num == 255) { -- netif->num = 0; -- } -- num_netifs = 0; -- for (netif2 = netif_list; netif2 != NULL; netif2 = netif2->next) { -- LWIP_ASSERT("netif already added", netif2 != netif); -- num_netifs++; -- LWIP_ASSERT("too many netifs, max. supported number is 255", num_netifs <= 255); -- if (netif2->num == netif->num) { -- netif->num++; -- break; -- } -- } -- } while (netif2 != NULL); -- } -- if (netif->num == 254) { -- netif_num = 0; -- } else { -- netif_num = (u8_t)(netif->num + 1); -- } - - /* add this netif to the list */ - netif->next = netif_list; -@@ -421,8 +428,8 @@ - } - #endif /* LWIP_IGMP */ - -- LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", -- netif->name[0], netif->name[1])); -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %s IP", -+ netif->name)); - #if LWIP_IPV4 - LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); - ip4_addr_debug_print(NETIF_DEBUG, ipaddr); -@@ -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 - */ --void -+err_t - netif_set_default(struct netif *netif) - { - LWIP_ASSERT_CORE_LOCKED(); -@@ -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] : '\'')); -+ return ERR_OK; - } - - /** -@@ -1206,6 +1279,11 @@ - struct netif *stats_if = netif; - #endif /* LWIP_HAVE_LOOPIF */ - #endif /* MIB2_STATS */ -+#if PF_PACKET_SOCKET -+ struct raw_pcb *pcb; -+ int match = 0; -+#endif /* PF_PACKET_SOCKET */ -+ - SYS_ARCH_DECL_PROTECT(lev); - - LWIP_ASSERT("netif_poll: invalid netif", netif != NULL); -@@ -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); -+ -+#if PF_PACKET_SOCKET -+ for (pcb = get_packet_raw_pcbs(); pcb != NULL; pcb = pcb->next) { -+ if (((pcb->proto.eth_proto == htons(ETHTYPE_ALL)) || (pcb->proto.eth_proto == htons(ETHTYPE_IP))) && -+ ((!pcb->netifindex) || (pcb->netifindex == netif->ifindex))) { -+ match = 1; -+ break; -+ } -+ } -+ -+ /* always succeed because the alloc layer of loopback pbuf was PBUF_LINK */ -+ if (match && pbuf_header(in, PBUF_LINK_HLEN) == 0) { -+ struct eth_hdr *ethhdr; -+ /* add ethernet header */ -+ ethhdr = (struct eth_hdr *)(in->payload); -+ /* smac and dmac set to all zeros for loopback IP packet */ -+ (void)memset_s(ethhdr, sizeof(struct eth_hdr), 0, sizeof(struct eth_hdr)); -+ ethhdr->type = htons(ETHTYPE_IP); /* eth protocol, should be ETH_P_IP(0x800) */ -+ in->flags = (u16_t)(in->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_OUTGOING)); -+ in->flags |= PBUF_FLAG_HOST; -+ raw_packet_input(in, netif, NULL); -+ (void)pbuf_header(in, -PBUF_LINK_HLEN); -+ } -+#endif /* PF_PACKET_SOCKET */ -+ - /* loopback packets are always IP packets! */ - if (ip_input(in, netif) != ERR_OK) { - pbuf_free(in); -@@ -1700,29 +1803,68 @@ - struct netif * - netif_find(const char *name) - { -- struct netif *netif; -- u8_t num; -- -- LWIP_ASSERT_CORE_LOCKED(); -- -- if (name == NULL) { -- return NULL; -- } -+ struct netif *netif = NULL; -+ char candidate_name[NETIF_NAMESIZE]; -+ int ret; - -- num = (u8_t)atoi(&name[2]); -+ LWIP_ERROR("netif_find : invalid value.", (name != NULL), return NULL); - - NETIF_FOREACH(netif) { -- if (num == netif->num && -- name[0] == netif->name[0] && -- name[1] == netif->name[1]) { -- LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); -+ if (strncmp(name, netif->name, NETIF_NAMESIZE) == 0) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %s\n", name)); - return netif; - } -+ -+ if (netif->link_layer_type != LOOPBACK_IF) { -+ ret = snprintf_s(candidate_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s%"U8_F, netif->name, netif->num); -+ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: name '%s'is too long\n", netif->name)); -+ continue; -+ } -+ if (strncmp(name, candidate_name, NETIF_NAMESIZE) == 0) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %s\n", name)); -+ return netif; -+ } -+ } - } -- LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %s\n", name)); - return NULL; - } - -+/* -+ * Change mtu setting for a network interface -+ * -+ * @param netif the network interface to change -+ * @param netif_mtu the new MTU for the interface -+ */ -+ -+err_t -+netif_set_mtu_api(struct netif *netif, u16_t netif_mtu) -+{ -+ /* As per RFC 791, "Every internet module must be able to forward a datagram of 68 -+ * octets without further fragmentation. This is because an internet header -+ * may be up to 60 octets, and the minimum fragment is 8 octets." */ -+ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif != NULL), return ERR_VAL); -+ -+#if LWIP_IPV6 -+ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif_mtu >= NETIF_MTU_MIN) && (netif_mtu <= IP_FRAG_MAX_MTU), -+ return ERR_ARG); -+#else -+ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif_mtu >= IP_FRAG_MIN_MTU) && (netif_mtu <= IP_FRAG_MAX_MTU), -+ return ERR_ARG); -+#endif -+ -+ netif->mtu = netif_mtu; -+#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES -+ netif->mtu6 = netif_mtu; -+#endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ -+ -+ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif: MTU of interface %s%"U16_F" is changed to %d\n", -+ netif->name, netif->num, netif->mtu)); -+ -+ return ERR_OK; -+} -+ - #if LWIP_NETIF_EXT_STATUS_CALLBACK - /** - * @ingroup netif -@@ -1793,3 +1935,213 @@ - } - } - #endif /* LWIP_NETIF_EXT_STATUS_CALLBACK */ -+ -+struct netif * -+netif_find_by_ipaddr(const ip_addr_t *ipaddr) -+{ -+ LWIP_ERROR("netif_find_by_ipaddr : invalid arguments", (ipaddr != NULL), return NULL); -+#if LWIP_IPV4 -+ if (IP_IS_V4(ipaddr)) { -+ return netif_find_by_ip4addr(ipaddr); -+ } -+#endif -+ -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ipaddr: didn't find\n")); -+ return NULL; -+} -+ -+void -+netif_get_hwaddr(const struct netif *netif, unsigned char *hw_addr, int hw_len) -+{ -+ int i; -+ LWIP_ERROR("netif_get_hwaddr : invalid arguments", (netif != NULL), return); -+ -+ LWIP_ERROR("netif_get_hwaddr : invalid arguments", (hw_addr != NULL), return); -+ -+ LWIP_ERROR("netif_get_hwaddr: invalid arguments", -+ ((unsigned int)hw_len == NETIF_MAX_HWADDR_LEN), return); -+ -+ for (i = 0; i < hw_len; i++) { -+ hw_addr[i] = netif->hwaddr[i]; -+ } -+} -+ -+/* -+ * Change the hardware address for a network interface -+ * -+ * NOTE:Application should call set_link_down before calling -+ * the netif_set_hwaddr and then set_link_up, in order -+ * to ensure that all IPs are announced after changing -+ * hw address -+ * -+ * @param netif the network interface to change -+ * @param hw_addr the new hardware address -+ * @param hw_len the length of new hardware address, -+ * -+ */ -+err_t -+netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw_len) -+{ -+ LWIP_ERROR("netif_set_hwaddr : invalid arguments", (netif != NULL), return ERR_VAL); -+ -+ LWIP_ERROR("netif_set_hwaddr : invalid arguments", (hw_addr != NULL), return ERR_VAL); -+ -+ LWIP_ERROR("netif_set_hwaddr: invalid arguments", -+ ((unsigned int)hw_len == NETIF_MAX_HWADDR_LEN), return ERR_VAL); -+ -+ if (netif->drv_set_hwaddr == NULL) { -+ return ERR_OPNOTSUPP; -+ } -+ -+ if (netif->drv_set_hwaddr(netif, (u8_t *)hw_addr, hw_len) != ERR_OK) { -+ return ERR_VAL; -+ } -+ -+ if (memcpy_s(netif->hwaddr, NETIF_MAX_HWADDR_LEN, hw_addr, (u32_t)hw_len) != EOK) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_set_hwaddr: memcpy_s error\n")); -+ return ERR_VAL; -+ } -+ -+ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, -+ ("netif: HW address of interface %s%"U16_F" set to %02X:%02X:%02X:%02X:%02X:%02X\n", -+ netif->name, netif->num, -+ netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], -+ netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5])); -+ -+ return ERR_OK; -+} -+ -+#if LWIP_IPV4 -+/* -+ * Find a network interface by searching for its ipaddress -+ * -+ * @param ipaddr IP_add of the netif -+ * @return netif if the its found -+ * NULL if there is no netif with ipaddr -+ */ -+struct netif * -+netif_find_by_ip4addr(const ip_addr_t *ipaddr) -+{ -+ struct netif *netif = NULL; -+ -+ LWIP_ASSERT("Expecting ipaddr to be not NULL ", ipaddr != NULL); -+ -+ for (netif = netif_list; netif != NULL; netif = netif->next) { -+ if (ip_addr_cmp(&(netif->ip_addr), ipaddr)) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ipaddr: found\n")); -+ return netif; -+ } -+ } -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ip4addr: didn't find\n")); -+ return NULL; -+} -+ -+s8_t netif_find_dst_ipaddr(const ip_addr_t *ipaddr, ip_addr_t **dst_addr) -+{ -+ struct netif *netif = NULL; -+ ip_addr_t *pdst_addr = NULL; -+ -+ pdst_addr = *dst_addr; -+ netif = netif_find_by_ipaddr(ipaddr); -+ if (netif == NULL) { -+ return -1; -+ } -+ if ((pdst_addr != NULL) && (!ip_addr_netcmp(pdst_addr, &(netif->ip_addr), ip_2_ip4(&netif->netmask))) && -+ !ip_addr_islinklocal(pdst_addr)) { -+ if (!ip_addr_isany(&netif->gw)) { -+ *dst_addr = &(netif->gw); -+ } -+ } -+ -+ return 0; -+} -+#endif /* LWIP_IPV4 */ -+ -+ -+ -+#if LWIP_DHCP -+/* -+ * Close DHCP and set static network. -+ * -+ * @param netif a pre-allocated netif structure -+ * -+ * @return ERR_OK, or ERR_VAL if failed. -+ */ -+err_t -+netif_dhcp_off(struct netif *netif) -+{ -+ ip_addr_t old_ipaddr; -+ ip_addr_t old_netmask; -+ ip_addr_t old_gateway; -+ -+ if (netif == NULL) { -+ return ERR_VAL; -+ } -+ old_ipaddr = netif->ip_addr; -+ old_netmask = netif->netmask; -+ old_gateway = netif->gw; -+ -+ if (netif_dhcp_data(netif)) { -+ (void)dhcp_release(netif); -+ dhcp_stop(netif); -+ dhcp_cleanup(netif); -+ LWIP_DEBUGF(NETIF_DEBUG, ("DHCP is close;set static IP\n")); -+ } -+ -+ ip_addr_set_val(netif->ip_addr, old_ipaddr); -+ ip_addr_set_val(netif->netmask, old_netmask); -+ ip_addr_set_val(netif->gw, old_gateway); -+ (void)netif_set_up(netif); -+ -+ return ERR_OK; -+} -+#endif /* LWIP_DHCP */ -+ -+u8_t netif_ipaddr_isbrdcast(const ip_addr_t *ipaddr) -+{ -+ struct netif *netif = NULL; -+ -+ for (netif = netif_list; netif != NULL; netif = netif->next) { -+ if (netif_is_up(netif) && ip_addr_isbroadcast(ipaddr, netif)) { -+ return 1; -+ } -+ } -+ -+ return 0; -+} -+ -+struct netif * -+netif_find_by_ifindex(u8_t ifindex) -+{ -+ struct netif *netif = NULL; -+ -+ if (ifindex < LWIP_NETIF_IFINDEX_START) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: Invalid ifindex(%u) \n", ifindex)); -+ return netif; -+ } -+ -+ for (netif = netif_list; netif != NULL; netif = netif->next) { -+ if (netif->ifindex == ifindex) { -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: found\n")); -+ return netif; -+ } -+ } -+ -+ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: didn't find\n")); -+ return NULL; -+} -+ -+/* Need to support the get index for all families -+removed PF_PACKET_SOCKET flag , as this flags restricts the usage to only PF_FAMILY Begin */ -+static u8_t -+netif_alloc_ifindex(void) -+{ -+ u8_t tmp_index; -+ for (tmp_index = LWIP_NETIF_IFINDEX_START; tmp_index <= LWIP_NETIF_IFINDEX_MAX; tmp_index++) { -+ if (netif_get_by_index(tmp_index) == NULL) { -+ break; -+ } -+ } -+ -+ return tmp_index; -+} -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 LWIP_NIP /* don't build if not configured for use in lwipopts.h */ -+ -+#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) -+{ -+ 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; -+} -+ -+/** -+ * 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) -+{ -+ 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; -+ } -+ -+ /* 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; -+} -+ -+/** 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); -+} -+ -+/** -+ * 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); -+ netif = ip_route_pcb(ipaddr, (struct ip_pcb*)pcb); - } - } - -@@ -387,7 +415,7 @@ - return ERR_RTE; - } - -- if (ip_addr_isany(&pcb->local_ip) || ip_addr_ismulticast(&pcb->local_ip)) { -+ if (ip_addr_isany(&pcb->local_ip) || ip_get_option(pcb, SOF_BINDNONUNICAST)) { - /* use outgoing network interface IP address as source address */ - src_ip = ip_netif_get_local_ip(netif, ipaddr); - #if LWIP_IPV6 -@@ -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); -- err = ip_output_if(q, src_ip, dst_ip, ttl, pcb->tos, pcb->protocol, netif); -+ err = ip_output_if(q, src_ip, dst_ip, ttl, pcb->tos, pcb->raw_proto, netif); - NETIF_RESET_HINTS(netif); - - /* did we chain a header earlier? */ -@@ -604,7 +634,12 @@ - if (pcb != NULL) { - /* initialize PCB to all zeroes */ - memset(pcb, 0, sizeof(struct raw_pcb)); -+#if PF_PACKET_SOCKET -+ pcb->proto.protocol = proto; -+#else - pcb->protocol = proto; -+#endif -+ - pcb->ttl = RAW_TTL; - #if LWIP_MULTICAST_TX_OPTIONS - raw_set_multicast_ttl(pcb, RAW_TTL); -@@ -668,4 +703,227 @@ - } - } - -+#if PF_PACKET_SOCKET -+void raw_packet_input(struct pbuf *p, const struct netif *inp, const struct raw_pcb *from) -+{ -+ struct raw_pcb *pcb = NULL; -+ struct eth_hdr *ethhdr = NULL; -+ u16_t proto; -+ -+ LWIP_UNUSED_ARG(inp); -+ -+ ethhdr = (struct eth_hdr *)p->payload; -+ proto = ethhdr->type; -+ -+ g_lwip_current_eth_hdr = ethhdr; -+ g_lwip_current_netif = inp; -+ -+ pcb = g_packet_raw_pcbs; -+ /* 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->proto.eth_proto == htons(ETHTYPE_ALL)) || ((p != NULL) && !(p->flags & PBUF_FLAG_OUTGOING) && -+ pcb->proto.eth_proto == proto)) && -+ ((!pcb->netifindex) || (pcb->netifindex == inp->ifindex)) && (pcb != from)) { -+ /* receive callback function available? */ -+ if (pcb->recv != NULL) { -+ /* the receive callback function did not eat the packet? */ -+ if (pcb->recv(pcb->recv_arg, pcb, p, NULL) != 0) { -+ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_input: packets recved failed \n")); -+ } -+ } -+ /* no receive callback function was set for this raw PCB */ -+ } -+ -+ pcb = pcb->next; -+ } -+ -+ g_lwip_current_eth_hdr = NULL; -+ return; -+} -+ -+err_t -+raw_packet_bind(struct raw_pcb *pcb, u8_t ifindex, u16_t proto) -+{ -+ struct netif *loc_netif = NULL; -+ -+ if (ifindex != 0) { -+ for (loc_netif = netif_list; loc_netif != NULL; loc_netif = loc_netif->next) { -+ if (ifindex == loc_netif->ifindex) { -+ break; -+ } -+ } -+ -+ /* Return if no matching netifs to bind */ -+ if (loc_netif == NULL) { -+ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_bind: No matching netif found for ifindex(%u)\n", ifindex)); -+ return ERR_NODEV; -+ } -+ } else { -+ return ERR_NODEV; -+ } -+ -+#if DRIVER_STATUS_CHECK -+ if (!netif_is_up(loc_netif) || !netif_is_ready(loc_netif)) -+#else -+ if (!netif_is_up(loc_netif)) -+#endif -+ { -+ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_bind: bind failed as netif (index %u) was down\n", ifindex)); -+ return ERR_NETDOWN; -+ } -+ -+ pcb->netifindex = ifindex; -+ pcb->proto.eth_proto = proto; -+ -+ return ERR_OK; -+} -+ -+/* -+ * Send the raw IP packet through the given netif driver. Note that actually you cannot -+ * modify the link layer header here. Packet need to be sent to driver as it is through the -+ * given netif -+ * @param pcb the raw pcb which to send -+ * @param p the ethernet packet to send -+ * @param ifindex the Interface index of the netif through which packet needs to be sent -+ */ -+err_t -+raw_packet_sendto(const struct raw_pcb *pcb, struct pbuf *p, u8_t ifindex) -+{ -+ struct netif *netif = NULL; -+ u8_t netifindex; -+ LWIP_UNUSED_ARG(pcb); -+ -+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_packet_sendto: ifindex=%d\n", ifindex)); -+ LWIP_ASSERT("p != NULL", p != NULL); -+ -+ netifindex = ifindex; -+ -+ if (ifindex == 0) { -+ if (pcb->netifindex != 0) { -+ netifindex = pcb->netifindex; -+ } else { -+ return ERR_NODEVADDR; -+ } -+ } -+ -+ /* Find the netif corresponding to the interface index */ -+ netif = netif_find_by_ifindex(netifindex); -+ if (netif == NULL) { -+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("netif not found for given ifindex (%u)\n", ifindex)); -+ return ERR_NODEVADDR; -+ } -+ -+#if DRIVER_STATUS_CHECK -+ if ((!netif_is_up(netif)) || (!netif_is_ready(netif))) -+#else -+ if ((!netif_is_up(netif))) -+#endif -+ { -+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("netif was down for given ifindex (%u)\n", ifindex)); -+ return ERR_NETDOWN; -+ } -+ -+ if ((p->tot_len - (SIZEOF_ETH_HDR - ETH_PAD_SIZE)) > netif->mtu) { -+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("Message too long (%u)\n", p->tot_len)); -+ return ERR_MSGSIZE; -+ } -+ -+ if (pbuf_header(p, ETH_PAD_SIZE) == 0) { -+ p->flags = (u16_t)(p->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_HOST)); -+ p->flags |= PBUF_FLAG_OUTGOING; -+ raw_packet_input(p, netif, pcb); -+ (void)pbuf_header(p, -ETH_PAD_SIZE); -+ } -+ -+ /* For RAW packets of PF_PACKET family, do not modify the packets as it is -+ already supposed to contain the link layer header. So send directly to the driver */ -+ LINK_STATS_INC(link.xmit); -+ return ERR_OK; -+} -+ -+/* -+ * Create a RAW PCB for Packet family. -+ * -+ * @return The RAW PCB which was created. NULL if the PCB data structure -+ * could not be allocated. -+ * -+ * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) -+ * -+ * @see raw_remove() -+ */ -+struct raw_pcb * -+raw_packet_new(u16_t proto) -+{ -+ struct raw_pcb *pcb = NULL; -+ -+ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_packet_new\n")); -+ -+ pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); -+ /* could allocate RAW PCB? */ -+ if (pcb != NULL) { -+ /* initialize PCB to all zeroes */ -+ (void)memset(pcb, 0, sizeof(struct raw_pcb)); -+ pcb->proto.eth_proto = proto; -+ pcb->ttl = RAW_TTL; -+ pcb->next = g_packet_raw_pcbs; -+ g_packet_raw_pcbs = pcb; -+ pcb->all_next = g_all_packet_raw_pcbs; -+ g_all_packet_raw_pcbs = pcb; -+ } -+ return pcb; -+} -+ -+/* -+ * Remove an RAW PCB of packet family type -+ * -+ * @param pcb RAW PCB to be removed. The PCB is removed from the list of -+ * RAW PCB's and the data structure is freed from memory. -+ * -+ * @see raw_packet_new() -+ */ -+void -+raw_packet_remove(struct raw_pcb *pcb) -+{ -+ struct raw_pcb *pcb2 = NULL; -+ -+ /* NULL check */ -+ if (pcb == NULL) { -+ return; -+ } -+ -+ /* pcb to be removed is first in all_pkt list? */ -+ if (g_all_packet_raw_pcbs == pcb) { -+ /* make list start at 2nd pcb */ -+ g_all_packet_raw_pcbs = g_all_packet_raw_pcbs->all_next; -+ /* pcb not 1st in list */ -+ } else { -+ for (pcb2 = g_all_packet_raw_pcbs; pcb2 != NULL; pcb2 = pcb2->all_next) { -+ /* find pcb in g_all_packet_raw_pcbs list */ -+ if (pcb2->all_next == pcb) { -+ /* remove pcb from list */ -+ pcb2->all_next = pcb->all_next; -+ } -+ } -+ } -+ -+ /* pcb to be removed is first in list? */ -+ if (g_packet_raw_pcbs == pcb) { -+ /* make list start at 2nd pcb */ -+ g_packet_raw_pcbs = g_packet_raw_pcbs->next; -+ /* pcb not 1st in list */ -+ } else { -+ for (pcb2 = g_packet_raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { -+ /* find pcb in raw_pcbs list */ -+ if (pcb2->next == pcb) { -+ /* remove pcb from list */ -+ pcb2->next = pcb->next; -+ } -+ } -+ } -+ -+ memp_free(MEMP_RAW_PCB, pcb); -+} -+#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 2022-02-16 16:06:59.178115000 +0800 -+++ b/lwip-2.1.2/src/include/lwip/api.h 2022-01-25 14:54:11.006695000 +0800 -@@ -48,6 +48,9 @@ - #include "lwip/sys.h" - #include "lwip/ip_addr.h" - #include "lwip/err.h" -+#if LWIP_LITEOS_COMPAT -+#include "lwip/netif.h" -+#endif - - #ifdef __cplusplus - extern "C" { -@@ -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,15 @@ - /** 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 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 +166,10 @@ - NETCONN_WRITE, - NETCONN_LISTEN, - NETCONN_CONNECT, -- NETCONN_CLOSE -+ NETCONN_CLOSE, -+#if LWIP_LITEOS_COMPAT -+ NETCONN_CLOSED, -+#endif /* LWIP_LITEOS_COMPAT */ - }; - - /** Used to inform the callback function about changes -@@ -201,6 +221,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 +247,12 @@ - struct tcp_pcb *tcp; - struct udp_pcb *udp; - struct raw_pcb *raw; -+#if PF_PACKET_SOCKET -+ struct raw_pcb *packet_raw; -+#endif /* PF_PACKET_SOCKET */ - } pcb; - /** the last asynchronous unreported error this netconn had */ -- err_t pending_err; -+ err_t last_err; - #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 +307,13 @@ - #endif /* LWIP_TCP */ - /** A callback function that is informed about events for this netconn */ - netconn_callback callback; -+#if LWIP_TCP -+ struct pbuf *refused_data; -+ ip_addr_t remote_ip; -+ u16_t remote_port; -+ /** record pending error state after recving RST */ -+ u16_t pending_err; -+#endif - }; - - /** This vector type is passed to @ref netconn_write_vectors_partly to send -@@ -309,21 +340,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) --struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, -+struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, - netconn_callback callback); - err_t netconn_prepare_delete(struct netconn *conn); - err_t netconn_delete(struct netconn *conn); - /** Get the type of a netconn (as enum netconn_type). */ --#define netconn_type(conn) (conn->type) -+#define netconn_type(conn) ((u32_t)(conn->type)) - - err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, - u16_t *port, u8_t local); -+#if LWIP_LITEOS_COMPAT -+#if PF_PACKET_SOCKET -+struct pf_packet_sockaddr_ll { -+ u16_t sll_protocol; -+ u16_t sll_hatype; -+ u8_t if_idx; -+ u8_t sll_halen; -+ u8_t sll_addr[NETIF_MAX_HWADDR_LEN]; -+}; -+err_t netconn_get_sockaddr_pf_packet(struct netconn *conn, struct pf_packet_sockaddr_ll *ll, u8_t local); -+#endif /* PF_PACKET_SOCKET */ -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup netconn_common */ - #define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) - /** @ingroup netconn_common */ - #define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) - -+#if PF_PACKET_SOCKET -+err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port, u8_t ifindex); -+#else - err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port); -+#endif /* PF_PACKET_SOCKET */ -+ - err_t netconn_bind_if(struct netconn *conn, u8_t if_idx); - 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 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 - --#ifndef LITTLE_ENDIAN --#define LITTLE_ENDIAN 1234 --#endif -- --#ifndef BIG_ENDIAN --#define BIG_ENDIAN 4321 --#endif -- -+#include - #include "arch/cc.h" - - /** -@@ -149,6 +142,11 @@ - #ifndef X8_F - #define X8_F "02" PRIx8 - #endif -+#if LWIP_LITEOS_COMPAT -+#ifndef U8_F -+#define U8_F PRIu8 -+#endif -+#endif /* LWIP_LITEOS_COMPAT */ - #ifndef U16_F - #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 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, - /** Illegal argument. */ -- ERR_ARG = -16 -+ ERR_ARG = -16, -+#ifdef LWIP_LITEOS_COMPAT -+/** Message too long. */ -+ ERR_MSGSIZE = -17, -+/** No such device. */ -+ ERR_NODEV = -18, -+/** No such device or address. */ -+ ERR_NODEVADDR = -19, -+/** socket is not connection-mode & no peer address is set */ -+ ERR_NODEST = -20, -+/** Network is down */ -+ ERR_NETDOWN = -21, -+/** Address family not supported by protocol */ -+ ERR_AFNOSUPP = -22, -+/** No such address */ -+ ERR_NOADDR = -23, -+/** Operation not supported on transport endpoint */ -+ ERR_OPNOTSUPP = -24, -+ ERR_NETUNREACH = -25, -+/** connection request timedout */ -+ ERR_CONNECTIMEOUT = -26, -+/** Error pipe */ -+ ERR_PIPE = -27, -+/** AF not supported */ -+ ERR_AFNOSUPPORT = -28, -+/** Protocol not available */ -+ ERR_NOPROTOOPT = -29, -+ ERR_ACCESS = -30, -+ ERR_NFILE = -31, -+ ERR_RESERVE3 = -32, -+ ERR_RESERVE4 = -33, -+ ERR_RESERVE5 = -34, -+ ERR_RESERVE6 = -35, -+ ERR_FATAL_START = -36, -+ ERR_CONNREFUSED = -41, -+/** FIN mbox post fail. */ -+ ERR_FIN_POST = -42, -+#endif /* LWIP_LITEOS_COMPAT */ - } err_enum_t; - -+#ifdef LWIP_LITEOS_COMPAT -+#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 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. */ -+ -+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 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 - -+#if !LWIP_LITEOS_COMPAT - #define IF_NAMESIZE NETIF_NAMESIZE - - char * lwip_if_indextoname(unsigned int ifindex, char *ifname); - unsigned int lwip_if_nametoindex(const char *ifname); -+#endif - - #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 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 - -+#if !LWIP_LITEOS_COMPAT - /* 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 +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)}}} --/** This variable is initialized by the system to contain the wildcard IPv6 address. */ --extern const struct in6_addr in6addr_any; - - /* Definitions of the bits in an (IPv4) Internet address integer. - -@@ -119,7 +119,12 @@ - #define IN_BADCLASS(a) IP_BADCLASS(a) - - #define IN_LOOPBACKNET IP_LOOPBACKNET -+#endif /* !LWIP_LITEOS_COMPAT */ - -+/** This variable is initialized by the system to contain the wildcard IPv6 address. */ -+extern const struct in6_addr in6addr_any; -+/** Added new structure for ipv6 loopback as per section 3.9 of rfc 2553/3493 */ -+extern const struct in6_addr in6addr_loopback; - - #ifndef INET_ADDRSTRLEN - #define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX -@@ -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 */ --#define inet_addr(cp) ipaddr_addr(cp) -+#if LWIP_INET_ADDR_FUNC -+unsigned int inet_addr(const char *cp); -+#else -+#define inet_addr(cp) ipaddr_addr(cp) -+#endif -+ -+#if LWIP_INET_ATON_FUNC -+int inet_aton(const char *cp, struct in_addr *addr); -+#else - #define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) -+#endif -+ -+#if LWIP_INET_NTOA_FUNC -+char *inet_ntoa (struct in_addr in); -+#else - #define inet_ntoa(addr) ip4addr_ntoa((const ip4_addr_t*)&(addr)) -+#endif -+ - #define inet_ntoa_r(addr, buf, buflen) ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) - - #endif /* LWIP_IPV4 */ - - #if LWIP_IPV6 -+/* current the struct ip6_addr for define LWIP_IPV6_SCOPES 0 */ -+#if LWIP_LITEOS_COMPAT -+#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) { \ -+ memcpy((target_in6addr)->s6_addr, (source_ip6addr)->addr, sizeof(struct ip6_addr)); } -+#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) { \ -+ memcpy((target_ip6addr)->addr, (source_in6addr)->s6_addr, sizeof(struct ip6_addr)); \ -+ ip6_addr_clear_zone(target_ip6addr);} -+#else - #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 +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);} -- -+#endif /* LWIP_LITEOS_COMPAT */ - /* 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 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{ \ -- ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); ip_clear_no4(dest); }}while(0) -+ ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); ip_clear_no4(dest); }} while (0) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_set_val(dest, src) do { IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&(src))); if(IP_IS_V6_VAL(src)) { \ -+ ip6_addr_set(ip_2_ip6(&(dest)), ip_2_ip6(&(src))); } else { \ -+ ip4_addr_set(ip_2_ip4(&(dest)), ip_2_ip4(&(src))); }} while (0) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup ipaddr */ - #define ip_addr_set_ipaddr(dest, src) ip_addr_set(dest, src) - /** @ingroup ipaddr */ - #define ip_addr_set_zero(ipaddr) do{ \ -- ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0) -+ ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); } while (0) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_set_zero_val(ipaddr) do{ \ -+ ip6_addr_set_zero(ip_2_ip6(&(ipaddr))); IP_SET_TYPE_VAL(ipaddr, 0); } while (0) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup ip5addr */ - #define ip_addr_set_zero_ip4(ipaddr) do{ \ - ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }while(0) - /** @ingroup ip6addr */ - #define ip_addr_set_zero_ip6(ipaddr) do{ \ -- ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }while(0) -+ ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); } while (0) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_set_zero_ip6_val(ipaddr) do{ \ -+ ip6_addr_set_zero(ip_2_ip6(&(ipaddr))); IP_SET_TYPE_VAL(ipaddr, IPADDR_TYPE_V6); } while (0) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @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 +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)) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_netcmp_val(addr1, addr2, mask) ((IP_IS_V6_VAL((addr1)) && IP_IS_V6_VAL((addr2))) ? \ -+ 0 : \ -+ ip4_addr_netcmp(ip_2_ip4(&addr1), ip_2_ip4(&addr2), mask)) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @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 +282,50 @@ - #define ip_addr_isbroadcast(ipaddr, netif) ((IP_IS_V6(ipaddr)) ? \ - 0 : \ - ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_isbroadcast_val(ipaddr, netif) ((IP_IS_V6_VAL(ipaddr)) ? \ -+ 0 : \ -+ ip4_addr_isbroadcast(ip_2_ip4(&ipaddr), netif)) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup ipaddr */ - #define ip_addr_ismulticast(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ - ip4_addr_ismulticast(ip_2_ip4(ipaddr))) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_ismulticast_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ -+ ip6_addr_ismulticast(ip_2_ip6(&ipaddr)) : \ -+ ip4_addr_ismulticast(ip_2_ip4(&ipaddr))) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup ipaddr */ - #define ip_addr_isloopback(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_isloopback(ip_2_ip6(ipaddr)) : \ - ip4_addr_isloopback(ip_2_ip4(ipaddr))) -+#if LWIP_LITEOS_COMPAT -+#define ip_addr_isloopback_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ -+ ip6_addr_isloopback(ip_2_ip6(&ipaddr)) : \ -+ ip4_addr_isloopback(ip_2_ip4(&ipaddr))) -+#endif /* LWIP_LITEOS_COMPAT */ - /** @ingroup ipaddr */ - #define ip_addr_islinklocal(ipaddr) ((IP_IS_V6(ipaddr)) ? \ - ip6_addr_islinklocal(ip_2_ip6(ipaddr)) : \ - ip4_addr_islinklocal(ip_2_ip4(ipaddr))) -+#ifdef LWIP_DEBUG - #define ip_addr_debug_print(debug, ipaddr) do { if(IP_IS_V6(ipaddr)) { \ - ip6_addr_debug_print(debug, ip_2_ip6(ipaddr)); } else { \ -- ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }}while(0) -+ ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }} while (0) - #define ip_addr_debug_print_val(debug, ipaddr) do { if(IP_IS_V6_VAL(ipaddr)) { \ - ip6_addr_debug_print_val(debug, *ip_2_ip6(&(ipaddr))); } else { \ -- ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }}while(0) -+ ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }} while (0) -+#else -+#define ip_addr_debug_print(debug, ipaddr) -+#define ip_addr_debug_print_val(debug, ipaddr) -+#endif /* LWIP_LITEOS_COMPAT */ -+ - char *ipaddr_ntoa(const ip_addr_t *addr); - char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen); -+#if LWIP_LITEOS_COMPAT -+#define ipaddr_ntoa_unsafe(addr) ((IP_IS_V6_VAL(*addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr))) -+#endif /* LWIP_LITEOS_COMPAT */ - int ipaddr_aton(const char *cp, ip_addr_t *addr); - - /** @ingroup ipaddr */ -@@ -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) - -+#define ip_addr_cmp_zoneless(addr1, addr2) ip4_addr_cmp(addr1, addr2) - #define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) - #define ip_addr_copy_from_ip4(dest, src) ip4_addr_copy(dest, src) - #define ip_addr_set_ip4_u32(ipaddr, val) ip4_addr_set_u32(ip_2_ip4(ipaddr), val) - #define ip_addr_set_ip4_u32_val(ipaddr, val) ip_addr_set_ip4_u32(&(ipaddr), val) - #define ip_addr_get_ip4_u32(ipaddr) ip4_addr_get_u32(ip_2_ip4(ipaddr)) - #define ip_addr_set(dest, src) ip4_addr_set(dest, src) -+#define ip_addr_set_val(dest, src) ip4_addr_copy(dest, src) - #define ip_addr_set_ipaddr(dest, src) ip4_addr_set(dest, src) - #define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) -+#define ip_addr_set_zero_val(ipaddr) ip4_addr_set_zero(&(ipaddr)) - #define ip_addr_set_zero_ip4(ipaddr) ip4_addr_set_zero(ipaddr) - #define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) - #define ip_addr_set_loopback(is_ipv6, ipaddr) ip4_addr_set_loopback(ipaddr) - #define ip_addr_set_hton(dest, src) ip4_addr_set_hton(dest, src) - #define ip_addr_get_network(target, host, mask) ip4_addr_get_network(target, host, mask) - #define ip_addr_netcmp(addr1, addr2, mask) ip4_addr_netcmp(addr1, addr2, mask) -+#define ip_addr_netcmp_val(addr1, addr2, mask) ip4_addr_netcmp(&(addr1), &(addr2), mask) - #define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) - #define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) -+#define ip_addr_isnone(ipaddr) ip4_addr_isnone(ipaddr) - #define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) - #define ip_addr_isloopback(ipaddr) ip4_addr_isloopback(ipaddr) -+#define ip_addr_isloopback_val(ipaddr) ip4_addr_isloopback(&(ipaddr)) - #define ip_addr_islinklocal(ipaddr) ip4_addr_islinklocal(ipaddr) - #define ip_addr_isbroadcast(addr, netif) ip4_addr_isbroadcast(addr, netif) -+#define ip_addr_isbroadcast_val(addr, netif) ip4_addr_isbroadcast(&(addr), netif) - #define ip_addr_ismulticast(ipaddr) ip4_addr_ismulticast(ipaddr) -+#define ip_addr_ismulticast_val(ipaddr) ip4_addr_ismulticast(&(ipaddr)) -+#ifdef LWIP_DEBUG - #define ip_addr_debug_print(debug, ipaddr) ip4_addr_debug_print(debug, ipaddr) - #define ip_addr_debug_print_val(debug, ipaddr) ip4_addr_debug_print_val(debug, ipaddr) -+#else -+#define ip_addr_debug_print(debug, ipaddr) -+#define ip_addr_debug_print_val(debug, ipaddr) -+#endif -+ - #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 +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) -+#define ip_addr_set_val(dest, src) ip6_addr_copy(dest, src) -+ - #define ip_addr_set_ipaddr(dest, src) ip6_addr_set(dest, src) - #define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr) -+#define ip_addr_set_zero_val(ipaddr) ip6_addr_set_zero(&(ipaddr)) - #define ip_addr_set_zero_ip6(ipaddr) ip6_addr_set_zero(ipaddr) -+#define ip_addr_set_zero_ip6_val(ipaddr) ip6_addr_set_zero(&(ipaddr)) - #define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr) - #define ip_addr_set_loopback(is_ipv6, ipaddr) ip6_addr_set_loopback(ipaddr) - #define ip_addr_set_hton(dest, src) ip6_addr_set_hton(dest, src) - #define ip_addr_get_network(target, host, mask) ip6_addr_set_zero(target) - #define ip_addr_netcmp(addr1, addr2, mask) 0 -+#define ip_addr_netcmp_val(addr1, addr2, mask) 0 - #define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) - #define ip_addr_cmp_zoneless(addr1, addr2) ip6_addr_cmp_zoneless(addr1, addr2) - #define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) -+#define ip_addr_isnone(ipaddr) ip6_addr_isnone(ipaddr) - #define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) - #define ip_addr_isloopback(ipaddr) ip6_addr_isloopback(ipaddr) -+#define ip_addr_isloopback_val(ipaddr) ip6_addr_isloopback(&(ipaddr)) - #define ip_addr_islinklocal(ipaddr) ip6_addr_islinklocal(ipaddr) - #define ip_addr_isbroadcast(addr, netif) 0 -+#define ip_addr_isbroadcast_val(addr, netif) 0 - #define ip_addr_ismulticast(ipaddr) ip6_addr_ismulticast(ipaddr) -+#define ip_addr_ismulticast_val(ipaddr) ip6_addr_ismulticast(&(ipaddr)) -+#ifdef LWIP_DEBUG - #define ip_addr_debug_print(debug, ipaddr) ip6_addr_debug_print(debug, ipaddr) - #define ip_addr_debug_print_val(debug, ipaddr) ip6_addr_debug_print_val(debug, ipaddr) -+#else -+#define ip_addr_debug_print(debug, ipaddr) -+#define ip_addr_debug_print_val(debug, ipaddr) -+#endif -+ - #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 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) */ -- -+#if LWIP_LITEOS_COMPAT -+#define SOF_DONTROUTE 0x01U /* all packets sent from this socket should only be routed with link scope entry */ -+#define SOF_BINDNONUNICAST 0x10U /* socket has bind to a non unicast */ -+#endif /* LWIP_LITEOS_COMPAT */ - /* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ - #define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE) - -@@ -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; -+#if LWIP_LITEOS_COMPAT -+ /* The IP header ID of the next outgoing IP packet */ -+#if LWIP_IPV4 -+ /* ensure this member of this sturcture is not mem set to zero */ -+ u16_t ip_id; -+#endif /* LWIP_IPV4 */ -+#endif /* LWIP_LITEOS_COMPAT */ - }; - extern struct ip_globals ip_data; - -@@ -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 */ -+#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 -+ * (requires IP_FRAG_USES_STATIC_BUF==1).This is not a configurable value. -+ */ -+#if !defined(IP_FRAG_MAX_MTU) -+#define IP_FRAG_MAX_MTU 1500 -+#endif -+/* As per RFC 791, "Every internet module must be able to forward a datagram of 68 -+ * octets without further fragmentation. This is because an internet header -+ * may be up to 60 octets, and the minimum fragment is 8 octets." */ -+#if !defined(IP_FRAG_MIN_MTU) -+#define IP_FRAG_MIN_MTU 68 -+#endif -+struct netif *ip_route_pcb(const ip_addr_t *dest, const struct ip_pcb* pcb); -+#endif /* LWIP_LITEOS_COMPAT */ - #define ip_route_get_local_ip(src, dest, netif, ipaddr) do { \ - (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 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 */ - #define NETBUF_FLAG_CHKSUM 0x02 -+#if PF_PACKET_SOCKET -+#define NETBUF_FLAG_IFINDEX 0x04 -+#endif /* PF_PACKET_SOCKET */ - - /** "Network buffer" - contains data and addressing info */ - struct netbuf { - struct pbuf *p, *ptr; - ip_addr_t addr; - u16_t port; --#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY -+#if PF_PACKET_SOCKET -+ u16_t hatype; -+ u16_t reserve; /* padded */ -+ u8_t netifindex; -+#endif /* PF_PACKET_SOCKET */ -+ -+#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY || PF_PACKET_SOCKET - u8_t flags; - u16_t toport_chksum; - #if LWIP_NETBUF_RECVINFO -@@ -73,7 +82,7 @@ - /* Network buffer functions: */ - struct netbuf * netbuf_new (void); - void netbuf_delete (struct netbuf *buf); --void * netbuf_alloc (struct netbuf *buf, u16_t size); -+void * netbuf_alloc (struct netbuf *buf, u16_t size, u8_t netconn_type); - void netbuf_free (struct netbuf *buf); - err_t netbuf_ref (struct netbuf *buf, - const void *dataptr, u16_t size); -@@ -93,6 +102,10 @@ - #define netbuf_fromaddr(buf) (&((buf)->addr)) - #define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set(&((buf)->addr), fromaddr) - #define netbuf_fromport(buf) ((buf)->port) -+#if LWIP_LITEOS_COMPAT -+#define netbuf_fromifindex(buf) ((buf)->netifindex) -+#define netbuf_fromhatype(buf) ((buf)->hatype) -+#endif /* LWIP_LITEOS_COMPAT */ - #if LWIP_NETBUF_RECVINFO - #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 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" - -+#if LWIP_LITEOS_COMPAT -+#include -+#endif -+ - #if LWIP_DNS && LWIP_SOCKET - - #include "lwip/arch.h" -@@ -63,6 +67,7 @@ - #define LWIP_DNS_API_DECLARE_STRUCTS 1 - #endif - -+#if !LWIP_LITEOS_COMPAT - #if LWIP_DNS_API_DEFINE_ERRORS - /** Errors used by the DNS API functions, h_errno can be one of them */ - #define EAI_NONAME 200 -@@ -112,23 +117,39 @@ - }; - #endif /* LWIP_DNS_API_DECLARE_STRUCTS */ - --#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) - - #if LWIP_DNS_API_DECLARE_H_ERRNO - /* application accessible error code set by the DNS API functions */ - extern int h_errno; - #endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ -+#endif /* !LWIP_LITEOS_COMPAT */ - -+#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) -+ -+#if LWIP_GETHOSTBYNAME || (defined(LWIP_COMPAT_SOCKETS) && (LWIP_COMPAT_SOCKETS != 2)) - struct hostent *lwip_gethostbyname(const char *name); -+#endif /* LWIP_GETHOSTBYNAME || (defined(LWIP_COMPAT_SOCKETS) && (LWIP_COMPAT_SOCKETS != 2)) */ -+#if (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) - int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, - size_t buflen, struct hostent **result, int *h_errnop); -+#endif /* (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) */ -+#if (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) - void lwip_freeaddrinfo(struct addrinfo *ai); - int lwip_getaddrinfo(const char *nodename, - const char *servname, - const struct addrinfo *hints, - struct addrinfo **res); -- --#if LWIP_COMPAT_SOCKETS -+#endif /* (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) */ -+#if LWIP_DNS_REVERSE -+int lwip_getnameinfo(const struct sockaddr *sa, -+ socklen_t salen, -+ char *host, -+ size_t hostlen, -+ char *serv, -+ size_t servlen, -+ int flags); -+#endif /* LWIP_DNS_REVERSE */ -+#if defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2 - /** @ingroup netdbapi */ - #define gethostbyname(name) lwip_gethostbyname(name) - /** @ingroup netdbapi */ -@@ -139,7 +160,11 @@ - /** @ingroup netdbapi */ - #define getaddrinfo(nodname, servname, hints, res) \ - lwip_getaddrinfo(nodname, servname, hints, res) --#endif /* LWIP_COMPAT_SOCKETS */ -+ -+/* @ingroup netdbapi */ -+#define getnameinfo(sock, sock_size, host, host_len, servname, servname_size, flags) \ -+ lwip_getnameinfo(sock, sock_size, host, host_len, servname, servname_size, flags) -+#endif /* defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2 */ - - #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 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*/ - -+/* -+Func Name: netifapi_netif_find_by_name -+*/ -+/** -+* @ingroup netifapi_netif -+* -+* @brief -+* This is a thread safe API, used to get the netif pointer whoes name was the input argument. -+* It is recommended to use this API instead of netif_find_by_name(). -+* Call netif_find() in a thread-safe way by running that function inside the tcpip_thread -+* context. -+* -+* @param[in] name Name of the netif. -+* -+* @returns -+* The netif pointer : On success \n -+* NULL : the netif was NOT exist \n -+* -+* @par Related Topics -+* netif_find_by_name() -+* -+*/ -+ -+struct netif* netifapi_netif_find_by_name(const char *name); - err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, - 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 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" - #include "lwip/stats.h" -+#include "lwip/prot/ethernet.h" - - #ifdef __cplusplus - extern "C" { -@@ -67,8 +68,17 @@ - * netif can be identified by in APIs. Composed of - * 2 chars, 3 (max) digits, and 1 \0 - */ --#define NETIF_NAMESIZE 6 -+#ifdef IFNAMSIZ -+#define NETIF_NAMESIZE IFNAMSIZ -+#else -+#define NETIF_NAMESIZE 16 -+#endif - -+#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 - /** - * @defgroup netif_flags Flags - * @ingroup netif -@@ -106,6 +116,17 @@ - * Set by the netif driver in its init function. */ - #define NETIF_FLAG_MLD6 0x40U - -+/** If set, the interface is configured using DHCP. -+ * Set by the DHCP code when starting or stopping DHCP. */ -+#define NETIF_FLAG_DHCP 0x80U -+ -+#if DRIVER_STATUS_CHECK -+/** If set, the netif has send capability. -+ * Set by the netif driver when its is ready to send. */ -+#define NETIF_FLAG_DRIVER_RDY 0x100U -+#endif -+ -+#define NETIF_FLAG_LOOPBACK 0x800 - /** - * @} - */ -@@ -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 */ - -+/** Function pointer of driver set hw address function */ -+typedef u8_t (*drv_set_hwaddr_fn)(struct netif *netif, u8_t *addr, u8_t len); -+ - #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 +273,10 @@ - */ - #define netif_get_client_data(netif, id) (netif)->client_data[(id)] - #endif -+#ifndef LOOPBACK_IF -+/** Type of link layer, these macros should be used for link_layer_type of struct netif */ -+#define LOOPBACK_IF 772 -+#endif - - #if (LWIP_IPV4 && LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) || (LWIP_IPV6 && (LWIP_ND6_NUM_DESTINATIONS > 0x7f)) - typedef u16_t netif_addr_idx_t; -@@ -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; -+ /* This function is to set the mac_address of the interface. */ -+ drv_set_hwaddr_fn drv_set_hwaddr; -+#if LWIP_NETIF_ETHTOOL && LWIP_SOCKET -+ void *ethtool_ops; -+#endif -+#if LWIP_DHCPS -+ /* DHCP Server Informarion for this netif */ -+ struct dhcps *dhcps; -+#endif - #ifdef netif_get_client_data - void* client_data[LWIP_NETIF_CLIENT_DATA_INDEX_MAX + LWIP_NUM_NETIF_CLIENT_DATA]; - #endif - #if LWIP_NETIF_HOSTNAME - /* the hostname for this netif, NULL is a valid value */ -- const char* hostname; -+ char hostname[NETIF_HOSTNAME_MAX_LEN]; - #endif /* LWIP_NETIF_HOSTNAME */ - #if LWIP_CHECKSUM_CTRL_PER_NETIF - u16_t chksum_flags; -@@ -341,13 +398,19 @@ - u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; - /** number of bytes used in hwaddr */ - u8_t hwaddr_len; -+ /* link layer type, ethernet or wifi */ -+ u16_t link_layer_type; /**< Indicates whether the link layer type is ethernet or wifi. */ - /** flags (@see @ref netif_flags) */ -- u8_t flags; -+ u32_t flags; - /** descriptive abbreviation */ -- char name[2]; -- /** number of this interface. Used for @ref if_api and @ref netifapi_netif, -+ char name[NETIF_NAMESIZE]; -+ /** number of this interface. Used for @ref if_api and @ref netifapi_netif, - * as well as for IPv6 zones */ - u8_t num; -+ u8_t ifindex; /* Interface Index mapped to each netif. Starts from 1 */ -+#if DRIVER_STATUS_CHECK -+ s32_t waketime; /**< Started when netif_stop_queue is called from driver. */ -+#endif - #if LWIP_IPV6_AUTOCONFIG - /** is this netif enabled for IPv6 autoconfiguration */ - u8_t ip6_autoconfig_enabled; -@@ -387,6 +450,15 @@ - u16_t loop_cnt_current; - #endif /* LWIP_LOOPBACK_MAX_PBUFS */ - #endif /* ENABLE_LOOPBACK */ -+#if LWIP_SO_DONTROUTE -+ /** The scope of the netif, this is set in ip4_route/ip6_route, the usr can use this -+ to decide whether the netif is in desired sope */ -+ rt_scope_t scope; -+#endif -+#if LWIP_IPV6 -+ /** Call back needs to be registered if adaptor requires notification for IPv6 DAD */ -+ u8_t ipv6_flags; -+#endif - }; - - #if LWIP_CHECKSUM_CTRL_PER_NETIF -@@ -407,9 +479,15 @@ - #endif /* LWIP_SINGLE_NETIF */ - /** The default network interface. */ - extern struct netif *netif_default; -- -+s8_t netif_find_dst_ipaddr(const ip_addr_t *ipaddr, ip_addr_t **dst_addr); - void netif_init(void); - -+#if LWIP_DHCP -+err_t netif_dhcp_off(struct netif *netif); -+#endif -+ -+u8_t netif_check_num_isusing(const char* ifname, const u8_t num); -+ - struct netif *netif_add_noaddr(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input); - - #if LWIP_IPV4 -@@ -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); - --void netif_set_default(struct netif *netif); -+struct netif *netif_find_by_ipaddr(const ip_addr_t *ipaddr); -+ -+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); - void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask); - void netif_set_gw(struct netif *netif, const ip4_addr_t *gw); -+struct netif *netif_find_by_ip4addr(const ip_addr_t *ipaddr); - /** @ingroup netif_ip4 */ - #define netif_ip4_addr(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->ip_addr))) - /** @ingroup netif_ip4 */ -@@ -455,6 +548,9 @@ - - void netif_set_up(struct netif *netif); - void netif_set_down(struct netif *netif); -+err_t netif_set_mtu_api(struct netif *netif, u16_t netif_mtu); -+err_t netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw_len); -+void netif_get_hwaddr(const struct netif *netif, unsigned char *hw_addr, int hw_len); - /** @ingroup netif - * Ask if an interface is up - */ -@@ -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); -+err_t netif_do_add_ipv6_addr(struct netif *netif, void *arguments); -+err_t netif_do_rmv_ipv6_addr(struct netif *netif, void *arguments); - 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 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) - */ - #if !defined MEMP_NUM_NETCONN || defined __DOXYGEN__ --#define MEMP_NUM_NETCONN 4 -+#define MEMP_NUM_NETCONN 16 - #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 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 -- -+#ifdef LWIP_LITEOS_COMPAT -+#define PBUF_FLAG_HOST 0x100U -+#define PBUF_FLAG_OUTGOING 0x200U -+#endif - /** Main packet buffer struct */ - 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 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" - #include "lwip/priv/tcpip_priv.h" -+#include "lwip/ip.h" - - #ifdef __cplusplus - extern "C" { -@@ -70,6 +71,14 @@ - #define NETCONN_SHUT_WR 2 - #define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) - -+#if PF_PACKET_SOCKET -+/* Packet Types */ -+#define PACKET_HOST 0 /* To us */ -+#define PACKET_BROADCAST 1 /* To all */ -+#define PACKET_MULTICAST 2 /* To group */ -+#define PACKET_OTHERHOST 3 /* To someone else */ -+#define PACKET_OUTGOING 4 -+#endif - /* IP addresses and port numbers are expected to be in - * the same byte order as in the corresponding pcb. - */ -@@ -88,7 +97,7 @@ - struct netbuf *b; - /** used for lwip_netconn_do_newconn */ - struct { -- u8_t proto; -+ u16_t proto; - } n; - /** used for lwip_netconn_do_bind and lwip_netconn_do_connect */ - struct { -@@ -102,6 +111,12 @@ - u16_t API_MSG_M_DEF(port); - u8_t local; - } ad; -+#if PF_PACKET_SOCKET -+ struct { -+ struct pf_packet_sockaddr_ll API_MSG_M_DEF(ll); -+ u8_t local; -+ } adpkt; -+#endif - /** used for lwip_netconn_do_write */ - struct { - /** current vector to write */ -@@ -205,6 +220,7 @@ - #endif /* TCP_LISTEN_BACKLOG */ - void lwip_netconn_do_write (void *m); - void lwip_netconn_do_getaddr (void *m); -+void lwip_netconn_do_getaddr_pfpkt (void *m); - void lwip_netconn_do_close (void *m); - void lwip_netconn_do_shutdown (void *m); - #if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) -@@ -214,6 +230,7 @@ - - #if LWIP_DNS - void lwip_netconn_do_gethostbyname(void *arg); -+void lwip_netconn_do_getnamebyhost(void *arg); - #endif /* LWIP_DNS */ - - struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); -@@ -233,6 +250,7 @@ - - typedef void (*netifapi_void_fn)(struct netif *netif); - typedef err_t (*netifapi_errt_fn)(struct netif *netif); -+typedef err_t (*netifapi_arg_fn)(struct netif *netif, void *arg); - - struct netifapi_msg { - struct tcpip_api_call_data call; -@@ -245,9 +263,27 @@ - NETIFAPI_IPADDR_DEF(ip4_addr_t, gw); - #endif /* LWIP_IPV4 */ - void *state; -+ } add; -+ -+ struct { -+ const ip_addr_t *ipaddr; -+ } find_by_ipaddr; -+ struct { -+ const char *name; -+ } find_by_name; -+ struct { -+ unsigned char ifindex; -+ } find_by_ifindex; -+ struct { -+#if LWIP_IPV4 -+ ip4_addr_t *ipaddr; -+ ip4_addr_t *netmask; -+ ip4_addr_t *gw; -+#endif /* LWIP_IPV4 */ -+ void *state; - netif_init_fn init; - netif_input_fn input; -- } add; -+ } add_get; - struct { - 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 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 - --#define NUM_SOCKETS MEMP_NUM_NETCONN - - /** This is overridable for the rare case where more than 255 threads - * select on the same socket... -@@ -69,6 +68,10 @@ - struct netconn *conn; - /** data that was left from the previous read */ - union lwip_sock_lastdata lastdata; -+ /** offset in the data that was left from the previous read */ -+ u16_t lastoffset; -+ /* socket level mutex used for multithread recv support */ -+ sys_mutex_t mutex; - #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL - /** number of times data was received, set by event_callback(), - tested by the receive and select functions */ -@@ -158,6 +161,7 @@ - fd_set *exceptset; - #endif /* LWIP_SOCKET_SELECT */ - #if LWIP_SOCKET_POLL -+ - /** fds passed to poll; NULL if select */ - 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 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 - PACK_STRUCT_BEGIN --struct icmp6_hdr { -+struct icmpv6_hdr { - 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 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" - #include "lwip/ip4_addr.h" -+#if LWIP_LITEOS_COMPAT -+#include -+#endif - - #ifdef __cplusplus - extern "C" { -@@ -81,10 +84,12 @@ - PACK_STRUCT_FIELD(u16_t _id); - /* fragment offset field */ - PACK_STRUCT_FIELD(u16_t _offset); -+#if !LWIP_LITEOS_COMPAT - #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 */ -+#endif - /* 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 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" - #include "lwip/ip6_addr.h" -+#include "lwip/etharp.h" -+#include "lwip/icmp6.h" - - #ifdef __cplusplus - extern "C" { -@@ -57,6 +59,18 @@ - #define RAW_FLAGS_MULTICAST_LOOP 0x04U - - struct raw_pcb; -+extern struct raw_pcb* raw_pcbs; -+ -+#if PF_PACKET_SOCKET -+extern const struct eth_hdr *g_lwip_current_eth_hdr; -+extern const struct netif *g_lwip_current_netif; -+/* Dest MAC add of current ethernet header of RAW packets -+ * received for PF_PACKET family */ -+#define eth_current_hdr() (g_lwip_current_eth_hdr) -+#define eth_current_netif() (g_lwip_current_netif) -+struct raw_pcb* get_packet_raw_pcbs(void); -+struct raw_pcb* get_all_packet_raw_pcbs(void); -+#endif /* PF_PACKET_SOCKET */ - - /** Function prototype for raw pcb receive callback functions. - * @param arg user supplied argument (raw_pcb.recv_arg) -@@ -77,8 +91,19 @@ - IP_PCB; - - struct raw_pcb *next; -- -+#if PF_PACKET_SOCKET -+ struct raw_pcb *all_next; -+ u8_t netifindex; -+ -+ union { -+ u16_t eth_proto; /* Ethernet HeaderType/Protocol for Packet sockets */ -+#define raw_proto proto.protocol -+ u8_t protocol; /* IP protocol for AF_INET sockets */ -+ } proto; -+#else -+#define raw_proto protocol - u8_t protocol; -+#endif - u8_t flags; - - #if LWIP_MULTICAST_TX_OPTIONS -@@ -115,6 +140,14 @@ - - void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); - -+#if PF_PACKET_SOCKET -+struct raw_pcb * raw_packet_new (u16_t proto); -+void raw_packet_remove (struct raw_pcb *pcb); -+void raw_packet_input (struct pbuf *p, const struct netif *inp, const struct raw_pcb *from); -+err_t raw_packet_sendto (const struct raw_pcb *pcb, struct pbuf *p, u8_t ifindex); -+err_t raw_packet_bind (struct raw_pcb *pcb, u8_t ifindex, u16_t proto); -+#endif /* PF_PACKET_SOCKET */ -+ - #define raw_flags(pcb) ((pcb)->flags) - #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 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 - -+#if LWIP_LITEOS_COMPAT -+#include "sys/select.h" -+#include "sys/socket.h" -+#include "poll.h" -+#include "netinet/tcp.h" -+#endif /* LWIP_LITEOS_COMPAT */ -+ - #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) -@@ -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. */ -+#else /* LWIP_LITEOS_COMPAT */ -+#if LWIP_LITEOS_COMPAT -+#ifndef TCP_KEEPALIVE -+#define TCP_KEEPALIVE 0x02 -+#endif /* TCP_KEEPALIVE */ -+ -+#ifndef SIN_ZERO_LEN -+#define SIN_ZERO_LEN 8 -+#endif /* SIN_ZERO_LEN */ -+ -+#ifndef SOCK_MAX -+#define SOCK_MAX (SOCK_RAW + 1) -+#endif /* SOCK_MAX */ -+ -+#ifndef SOCK_TYPE_MASK -+#define SOCK_TYPE_MASK 0xf -+#endif /* SOCK_TYPE_MASK */ -+#endif -+ - void lwip_socket_thread_init(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ - void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ - -+#if LWIP_IPV6 -+#define LWIP_IS_IPPROTOCOL(protocol) ((protocol) == IPPROTO_IP || (protocol) == IPPROTO_IPV6 || (protocol) == 0) -+#if PF_PACKET -+#define LWIP_IS_VALID_DOMAIN(domain) (((domain) == AF_INET) || ((domain) == AF_INET6) || ((domain) == PF_PACKET)) -+#else -+#define LWIP_IS_VALID_DOMAIN(domain) ((domain) == AF_INET) || ((domain) == AF_INET6) -+#endif -+#else -+#define LWIP_IS_IPPROTOCOL(protocol) ((protocol) == IPPROTO_IP || (protocol) == 0) -+#if PF_PACKET -+#define LWIP_IS_VALID_DOMAIN(domain) (((domain) == AF_INET) || ((domain) == PF_PACKET)) -+#else -+#define LWIP_IS_VALID_DOMAIN(domain) ((domain) == AF_INET) || ((domain) == AF_INET6) -+#endif -+#endif - #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 +604,9 @@ - #if LWIP_SOCKET_SELECT - #define lwip_select select - #endif -+ -+#define lwip_gethostbyname(name) gethostbyname(name) -+ - #if LWIP_SOCKET_POLL - #define lwip_poll poll - #endif -@@ -558,9 +614,18 @@ - #define lwip_inet_ntop inet_ntop - #define lwip_inet_pton inet_pton - -+#if LWIP_DNS -+#define lwip_gethostbyname(name) gethostbyname(name) -+#define lwip_gethostbyname_r gethostbyname_r -+#define lwip_freeaddrinfo freeaddrinfo -+#define lwip_getaddrinfo getaddrinfo -+#define lwip_getnameinfo getnameinfo -+#endif -+ - #if LWIP_POSIX_SOCKETS_IO_NAMES - #define lwip_read read - #define lwip_readv readv -+ - #define lwip_write write - #define lwip_writev writev - #undef lwip_close -@@ -682,7 +747,7 @@ - #ifdef __cplusplus - } - #endif -- -+#endif - #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 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. -+ * Description: declare BSD APIs : getifaddrs freeifaddrs -+ * Author: none -+ * Create: 2020 -+ */ -+ -+#ifndef __LWIP_IFADDRS_H -+#define __LWIP_IFADDRS_H -+ -+#if (LWIP_IPV4 || LWIP_IPV6) && LWIP_SOCKET -+ -+#include "lwip/netif.h" -+#include "lwip/sockets.h" -+ -+#ifdef LWIP_COMPAT_SOCKETS -+#if LWIP_COMPAT_SOCKETS != 2 -+/* @ingroup socket */ -+#define getifaddrs(ifap) lwip_getifaddrs(ifap) -+#define freeifaddrs(ifa) lwip_freeifaddrs(ifa) -+#else /* LWIP_COMPAT_SOCKETS != 2 */ -+/* @ingroup socket */ -+#define lwip_getifaddrs(ifap) getifaddrs(ifap) -+#define lwip_freeifaddrs(ifa) freeifaddrs(ifa) -+#endif /* LWIP_COMPAT_SOCKETS == 2 */ -+#endif /* LWIP_COMPAT_SOCKETS */ -+ -+#if LWIP_LITEOS_COMPAT -+ -+#ifndef SIOCETHTOOL -+#define SIOCETHTOOL _IOW('i', 56, struct ifreq) -+#endif -+#define IFF_DRV_RUNNING 0x40 -+ -+#else -+#define SIOCADDRT _IOW('R', 9, struct rtentry) -+#define SIOCDELRT _IOW('R', 10, struct rtentry) -+ -+#define SIOCGIFFLAGS _IOWR('i', 17, struct ifreq) /* get ifnet flags */ -+#define SIOCSIFFLAGS _IOW('i', 16, struct ifreq) /* set ifnet flags */ -+#define SIOCGIFADDR _IOWR('i', 33, struct ifreq) /* get ifnet address */ -+#define SIOCSIFADDR _IOW('i', 12, struct ifreq) /* set ifnet address */ -+ -+#define SIOCDIFADDR _IOW('i', 25, struct ifreq) /* delete IF addr */ -+ -+#define SIOCGIFNETMASK _IOWR('i', 37, struct ifreq) /* get net addr mask */ -+#define SIOCSIFNETMASK _IOW('i', 22, struct ifreq) /* set net addr mask */ -+#define SIOCSIFHWADDR _IOW('i', 140, struct ifreq) /* set IF name */ -+#define SIOCGIFHWADDR _IOW('i', 141, struct ifreq) /* set IF name */ -+#define SIOCGIFNAME _IOW('i', 142, struct ifreq) /* set IF name */ -+#define SIOCSIFNAME _IOW('i', 40, struct ifreq) /* set IF name */ -+ -+/** Gets IF mtu */ -+#define SIOCGIFMTU _IOWR('i', 51, struct ifreq) -+/** Sets IF mtu */ -+#define SIOCSIFMTU _IOW('i', 52, struct ifreq) -+/** ethtool */ -+#define SIOCETHTOOL _IOW('i', 56, struct ifreq) -+ -+/* provide PF_PACKET option on SOCK_RAW */ -+#define SIOCGIFINDEX _IOWR('i', 32, struct ifreq) /* get IF index */ -+#define SIOCGIFCONF _IOWR('i', 36, struct ifconf) /* get ifnet list */ -+ -+/** (n) Indicates that the interface is up */ -+#define IFF_UP 0x1 -+/** (i) Indicates that the broadcast address valid */ -+#define IFF_BROADCAST 0x2 -+/** (n) Turns on debugging */ -+#define IFF_DEBUG 0x4 -+/** (i) A loopback net */ -+#define IFF_LOOPBACK 0x8 -+/** (i) Indicates a point-to-point link */ -+#define IFF_POINTOPOINT 0x10 -+/* 0x20 was IFF_SMART */ -+/** (d) Indicates that the resources are allocated */ -+#define IFF_DRV_RUNNING 0x40 -+/** (n) No address resolution protocol */ -+#define IFF_NOARP 0x80 -+/** (n) Receive all packets */ -+#define IFF_PROMISC 0x100 -+/** (n) Receive all multicast packets */ -+#define IFF_ALLMULTI 0x200 -+/** (d) Indicates that the tx hardware queue is full */ -+#define IFF_DRV_OACTIVE 0x400 -+ /** (i) Cannot hear own transmissions */ -+#define IFF_SIMPLEX 0x800 -+/** Per link layer defined bit */ -+#define IFF_LINK0 0x1000 -+/** Per link layer defined bit */ -+#define IFF_LINK1 0x2000 -+/** Per link layer defined bit */ -+#define IFF_LINK2 0x4000 -+/** Use alternate physical connection */ -+#define IFF_ALTPHYS IFF_LINK2 -+/** Supports multicast */ -+#define IFF_MULTICAST 0x8000 -+ /** (i) Unconfigurable using ioctl(2) */ -+#define IFF_CANTCONFIG 0x10000 -+/** (n) User-requested promisc mode */ -+#define IFF_PPROMISC 0x20000 -+/** (n) User-requested IFF_MONITOR mode */ -+#define IFF_MONITOR 0x40000 -+ /** (n) Static ARP */ -+#define IFF_STATICARP 0x80000 -+/** (n) Interface is winding down */ -+#define IFF_DYING 0x200000 -+/** (n) Interface is being renamed */ -+#define IFF_RENAMING 0x400000 -+/** (n) Dialup device with changing addresses */ -+#define IFF_DYNAMIC 0x800000 -+/** (n) Dialup device with changing addresses */ -+#define IFF_DYNAMIC_S 0x1000000 -+ -+#define IFF_RUNNING IFF_DRV_RUNNING -+ -+#ifndef IFNAMSIZ -+#define IFNAMSIZ NETIF_NAMESIZE -+#endif -+ -+struct ifreq { -+#define IFHWADDRLEN 6 -+ union { -+ char ifrn_name[IFNAMSIZ]; -+ } ifr_ifrn; -+ union { -+ struct sockaddr ifru_addr; -+ struct sockaddr ifru_dstaddr; -+ struct sockaddr ifru_broadaddr; -+ struct sockaddr ifru_netmask; -+ struct sockaddr ifru_hwaddr; -+ short ifru_flags[2]; -+ int ifru_ivalue; -+ int ifru_mtu; -+ char ifru_slave[IFNAMSIZ]; -+ char ifru_newname[IFNAMSIZ]; -+ void *ifru_data; -+ } ifr_ifru; -+}; -+#define ifr_name ifr_ifrn.ifrn_name -+#define ifr_hwaddr ifr_ifru.ifru_hwaddr -+#define ifr_addr ifr_ifru.ifru_addr -+#define ifr_dstaddr ifr_ifru.ifru_dstaddr -+#define ifr_broadaddr ifr_ifru.ifru_broadaddr -+#define ifr_netmask ifr_ifru.ifru_netmask -+#define ifr_flags ifr_ifru.ifru_flags[0] /* flags (low 16 bits) */ -+#define ifr_flagshigh ifr_ifru.ifru_flags[1] /* flags (high 16 bits) */ -+#define ifr_metric ifr_ifru.ifru_ivalue -+#define ifr_mtu ifr_ifru.ifru_mtu -+#define ifr_slave ifr_ifru.ifru_slave -+#define ifr_data ifr_ifru.ifru_data -+#define ifr_ifindex ifr_ifru.ifru_ivalue -+#define ifr_bandwidth ifr_ifru.ifru_ivalue -+#define ifr_qlen ifr_ifru.ifru_ivalue -+#define ifr_newname ifr_ifru.ifru_newname -+#define ifr_index ifr_ifindex -+ -+struct ifconf { -+ int ifc_len; -+ union { -+ char *ifcu_buf; -+ struct ifreq *ifcu_req; -+ } ifc_ifcu; -+}; -+ -+#define ifc_buf ifc_ifcu.ifcu_buf -+#define ifc_req ifc_ifcu.ifcu_req -+ -+struct ifaddrs { -+ struct ifaddrs *ifa_next; /**< Pointer to the next network interfaces.f */ -+ char *ifa_name; /**< Pointer to the name of the network interfaces */ -+ unsigned int ifa_flags; /**< Pointer to the status flag. */ -+ struct sockaddr *ifa_addr; /**< Pointer to the address. */ -+ struct sockaddr *ifa_netmask; /**< Pointer to the net masking. */ -+ struct sockaddr *ifa_dstaddr; /**< Pointer to the destination address. */ -+ void *ifa_data; /**< Pointer to the data. */ -+}; -+ -+ #ifndef ifa_broadaddr -+ #define ifa_broadaddr ifa_dstaddr /* brcast address interface */ -+#endif -+ -+struct rtentry { -+ struct sockaddr rt_dst; /**< Indicates the target address. */ -+ struct sockaddr rt_gateway; /**< Indicates the gateway address (RTF_GATEWAY). */ -+ struct sockaddr rt_genmask; /**< Indicates the target network mask (IP). */ -+ unsigned int rt_flags; -+}; -+/** Indicates that the route is usable */ -+#define RTF_UP 0x1 -+/** Indicates that the destination is a gateway */ -+#define RTF_GATEWAY 0x2 -+/** Indicates the host entry (net otherwise) */ -+#define RTF_HOST 0x4 -+/** Indicates the host or net is unreachable */ -+#define RTF_REJECT 0x8 -+/** Created dynamically (by redirect) */ -+#define RTF_DYNAMIC 0x10 -+/** Modified dynamically (by redirect) */ -+#define RTF_MODIFIED 0x20 -+/** Message confirmed. */ -+#define RTF_DONE 0x40 -+/* 0x80 unused, was RTF_DELCLONE */ -+/* 0x100 unused, was RTF_CLONING */ -+/** Indicates that the external daemon resolves name */ -+#define RTF_XRESOLVE 0x200 -+/** DEPRECATED - exists ONLY for backward -+ compatibility */ -+#define RTF_LLINFO 0x400 -+/** Used by apps to add/del L2 entries */ -+#define RTF_LLDATA 0x400 -+/** Manually added */ -+#define RTF_STATIC 0x800 -+ /** Discard packets */ -+#define RTF_BLACKHOLE 0x1000 -+/** Protocol specific routing flag */ -+#define RTF_PROTO2 0x4000 -+/** Protocol specific routing flag */ -+/* 0x10000 unused, was RTF_PRCLONING */ -+#define RTF_PROTO1 0x8000 -+/* 0x10000 unused, was RTF_PRCLONING */ -+/* 0x20000 unused, was RTF_WASCLONED */ -+/** Protocol specific routing flag */ -+#define RTF_PROTO3 0x40000 -+/** MTU was explicitly specified */ -+#define RTF_FIXEDMTU 0x80000 -+/** Route is immutable */ -+#define RTF_PINNED 0x100000 -+/** Route represents a local address */ -+#define RTF_LOCAL 0x200000 -+/** Route represents a broadcast address */ -+#define RTF_BROADCAST 0x400000 -+ /** Route represents a multicast address */ -+#define RTF_MULTICAST 0x800000 -+ /* 0x8000000 and up unassigned */ -+/** Always route dst->src */ -+#define RTF_STICKY 0x10000000 -+/** Radix node head is locked */ -+#define RTF_RNH_LOCKED 0x40000000 -+/** Indicates the compatibility bit for interacting -+ with existing routing apps */ -+#define RTF_GWFLAG_COMPAT 0x80000000 -+ -+/* Mask of RTF flags that are allowed to be modified by RTM_CHANGE. */ -+#define RTF_FMASK \ -+ (RTF_PROTO1 | RTF_PROTO2 | RTF_PROTO3 | RTF_BLACKHOLE | \ -+ RTF_REJECT | RTF_STATIC | RTF_STICKY) -+ -+/** -+* @defgroup ifaddrs_api ifaddrs API -+* This section contains the interfaces to get information about Network interfaces in lwIP. -+* @ingroup socket -+*/ -+ -+/* -+Func Name: lwip_getifaddrs -+*/ -+ -+/** -+* @ingroup ifaddrs_api -+* @brief Creates a linked list of struct ifaddrs, which holds the information -+* about the network interfaces of the local system. The ifa_next field contains a -+* pointer to the next structure on the list, or NULL if this is the last item of the list. -+* The ifa_name points to the null-terminated interface name. The ifa_flags field -+* contains the interface flags. The ifa_addr field points to a structure containing -+* the interface address. The ifa_netmask field points to a structure containing -+* the netmask associated with ifa_addr, if applicable, for the address family. -+* Depending on whether the bit IFF_brcast or IFF_POINTOPOINT is set -+* in ifa_flags (only one can be set at a time), either ifa_broadaddr will contain -+* the broadcast address associated with ifa_addr (if applicable for the address -+* family) or ifa_dstaddr will contain the destination address of the point-to-point -+* interface. -+* For IPv6, stack supports only IFF_UP,IFF_MULTICAST, IFF_DRV_RUNNING, and IFF_LOOPBACK -+* flags. -+* @param[in] ifap Indicates a double pointer to the ifaddrs structure. -+* @return -+* On success, lwip_getifaddrs() returns zero; on error, -1 is returned, and errno is set appropriately. -+* @par Errors -+* @li The lwip_getifaddrs() function shall fail if: -+* - [EACCES] : \n Invalid state of system. -+* - [ENOMEM] : \n In-sufficient memory. -+* @note -+* None -+*/ -+int lwip_getifaddrs(struct ifaddrs **ifap); -+ -+/* -+Func Name: lwip_freeifaddrs -+*/ -+ -+/** -+* @ingroup ifaddrs_api -+* @brief The function lwip_freeifaddrs, provides the list of network interfaces in the ifaddrs* structure. -+* The application has to free the memory of the ifaddrs * structure by using this function. -+* @param[in] ifa Indicates a pointer to the ifaddrs structure. -+* @return -+* Void -+* @note -+* None -+*/ -+void lwip_freeifaddrs(struct ifaddrs *ifa); -+ -+#endif /* !LWIP_LITEOS_COMPAT */ -+int get_ipv6_ifaddr(struct netif *netif, struct ifaddrs *ifaddr, int tmp_index); -+int get_ipv4_ifaddr(struct netif *netif, struct ifaddrs *ifaddr); -+struct ifaddrs_storage *new_ifaddrs_storage(void); -+#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 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" - #include "lwip/snmp.h" -- -+#include "lwip/raw.h" - #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 @@ - } - } - -+#if PF_PACKET_SOCKET -+ p->flags = (u16_t)(p->flags & ~PBUF_FLAG_OUTGOING); -+ if (get_packet_raw_pcbs() != NULL) { -+ raw_packet_input(p, netif, NULL); -+ } -+#endif /* PF_PACKET_SOCKET */ - 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 - /** -- Gitee From a9e4150d7b4f8d7d8db3951d58bc0809e5e7ea86 Mon Sep 17 00:00:00 2001 From: Terder-su Date: Mon, 21 Feb 2022 02:58:37 +0000 Subject: [PATCH 12/14] update lwip origin.patch --- components/net/lwip/origin.patch | 8503 ++++++++++++++++++++++++++++++ 1 file changed, 8503 insertions(+) create mode 100644 components/net/lwip/origin.patch diff --git a/components/net/lwip/origin.patch b/components/net/lwip/origin.patch new file mode 100644 index 0000000..c7e4b3a --- /dev/null +++ b/components/net/lwip/origin.patch @@ -0,0 +1,8503 @@ +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 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 + */ + struct netconn * +-netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback) ++netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, netconn_callback callback) + { + struct netconn *conn; + API_MSG_VAR_DECLARE(msg); +@@ -292,6 +292,37 @@ + return err; + } + ++#if PF_PACKET_SOCKET ++/** ++ * Get the local or remote IP address and port of a netconn. ++ * For pf packet netconns, this returns the struct pf_packet_sockaddr_ll of the netconn! ++ * @param conn the netconn to query ++ * @param local 1 to get the local IP address, 0 to get the remote one ++ * @return ERR_CONN for invalid connections ++ * ERR_OK if the information was retrieved ++ * ERR_OPNOTSUPP if the option is not support ++ */ ++err_t ++netconn_get_sockaddr_pf_packet(struct netconn *conn, struct pf_packet_sockaddr_ll *ll, u8_t local) ++{ ++ err_t err; ++ API_MSG_VAR_DECLARE(msg); ++ API_MSG_VAR_ALLOC(msg); ++ API_MSG_VAR_REF(msg).conn = conn; ++ API_MSG_VAR_REF(msg).msg.adpkt.local = local; ++#if LWIP_MPU_COMPATIBLE ++ err = netconn_apimsg(lwip_netconn_do_getaddr_pfpkt, &API_MSG_VAR_REF(msg)); ++ *ll = msg->msg.adpkt.ll; ++#else /* LWIP_MPU_COMPATIBLE */ ++ API_MSG_VAR_REF(msg).msg.adpkt.ll = ll; ++ err = netconn_apimsg(lwip_netconn_do_getaddr_pfpkt, &msg); ++#endif /* LWIP_MPU_COMPATIBLE */ ++ API_MSG_VAR_FREE(msg); ++ ++ return err; ++} ++#endif ++ + /** + * @ingroup netconn_common + * Bind a netconn to a specific local IP address and port. +@@ -304,9 +335,13 @@ + * @return ERR_OK if bound, any other err_t on failure + */ + err_t ++#if PF_PACKET_SOCKET ++netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port, u8_t if_idx) ++#else /* PF_PACKET_SOCKET */ + netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port) ++#endif + { +- API_MSG_VAR_DECLARE(msg); ++ API_MSG_VAR_DECLARE(msg); /* struct api_msg *msg */ + err_t err; + + LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); +@@ -332,6 +367,9 @@ + API_MSG_VAR_REF(msg).conn = conn; + API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); + API_MSG_VAR_REF(msg).msg.bc.port = port; ++#if PF_PACKET_SOCKET ++ API_MSG_VAR_REF(msg).msg.bc.if_idx = if_idx; ++#endif /* PF_PACKET_SOCKET */ + err = netconn_apimsg(lwip_netconn_do_bind, &API_MSG_VAR_REF(msg)); + API_MSG_VAR_FREE(msg); + +@@ -596,7 +634,7 @@ + + NETCONN_MBOX_WAITING_INC(conn); + if (netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK) || +- (conn->flags & NETCONN_FLAG_MBOXCLOSED) || (conn->pending_err != ERR_OK)) { ++ (conn->flags & NETCONN_FLAG_MBOXCLOSED)) { + 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; + } + SYS_ARCH_PROTECT(lev); +- err = conn->pending_err; +- conn->pending_err = ERR_OK; ++ err = conn->last_err; + SYS_ARCH_UNPROTECT(lev); + 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 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; + } + ++#if PF_PACKET_SOCKET ++ /* To get the pkt type filtered in ethernet_input */ ++ q->flags = p->flags; ++#if ETH_PAD_SIZE ++ /* exclude the begining two padding bytes in struct eth_hdr */ ++ if ((NETCONNTYPE_GROUP(conn->type) == NETCONN_PACKET_RAW) && (pbuf_header(q, -ETH_PAD_SIZE))) { ++ (void)pbuf_free(q); ++ memp_free(MEMP_NETBUF, buf); ++ return 0; ++ } ++#endif ++#endif ++ + buf->p = q; + buf->ptr = q; ++#if PF_PACKET_SOCKET ++ /* IP addr is NULL only when RAW packets are received for PF_PACKET sockets */ ++ if (addr == NULL) { ++ ip_addr_set_any(IP_IS_V6_VAL(buf->addr), &buf->addr); ++ buf->port = eth_current_hdr()->type; ++ buf->hatype = eth_current_netif()->link_layer_type; ++ buf->netifindex = eth_current_netif()->ifindex; ++ } else { ++ ip_addr_copy(buf->addr, *ip_current_src_addr()); ++ buf->port = pcb->raw_proto; ++ } ++#else + ip_addr_copy(buf->addr, *ip_current_src_addr()); + buf->port = pcb->protocol; ++#endif + + len = q->tot_len; + if (sys_mbox_trypost(&conn->recvmbox, buf) != ERR_OK) { +@@ -444,7 +470,7 @@ + /* when err is called, the pcb is deallocated, so delete the reference */ + conn->pcb.tcp = NULL; + /* store pending error */ +- conn->pending_err = err; ++ conn->last_err = err; + /* prevent application threads from blocking on 'recvmbox'/'acceptmbox' */ + conn->flags |= NETCONN_FLAG_MBOXCLOSED; + +@@ -627,23 +653,41 @@ + if (msg->conn->pcb.raw != NULL) { + #if LWIP_IPV6 + /* ICMPv6 packets should always have checksum calculated by the stack as per RFC 3542 chapter 3.1 */ +- if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->protocol == IP6_NEXTH_ICMP6) { ++ if (NETCONNTYPE_ISIPV6(msg->conn->type) && msg->conn->pcb.raw->raw_proto == IP6_NEXTH_ICMP6) { + msg->conn->pcb.raw->chksum_reqd = 1; + msg->conn->pcb.raw->chksum_offset = 2; + } + #endif /* LWIP_IPV6 */ ++ ++#if LWIP_IPV4 ++ /* IP_HDRINCL is enabled by default */ ++ if (!(NETCONNTYPE_ISIPV6(msg->conn->type)) && (msg->msg.n.proto == IPPROTO_RAW)) { ++ raw_set_flags(msg->conn->pcb.raw, RAW_FLAGS_HDRINCL); ++ } ++#endif + raw_recv(msg->conn->pcb.raw, recv_raw, msg->conn); + } + break; ++ ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++ msg->conn->pcb.packet_raw = raw_packet_new(msg->msg.n.proto); ++ if (msg->conn->pcb.packet_raw == NULL) { ++ msg->err = ERR_MEM; ++ break; ++ } ++ raw_recv(msg->conn->pcb.packet_raw, recv_raw, msg->conn); ++ break; ++#endif + #endif /* LWIP_RAW */ + #if LWIP_UDP +- case NETCONN_UDP: +- msg->conn->pcb.udp = udp_new_ip_type(iptype); +- if (msg->conn->pcb.udp != NULL) { ++ case NETCONN_UDP: ++ msg->conn->pcb.udp = udp_new_ip_type(iptype); ++ if (msg->conn->pcb.udp != NULL) { + #if LWIP_UDPLITE +- if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { +- udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); +- } ++ if (NETCONNTYPE_ISUDPLITE(msg->conn->type)) { ++ udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_UDPLITE); ++ } + #endif /* LWIP_UDPLITE */ + if (NETCONNTYPE_ISUDPNOCHKSUM(msg->conn->type)) { + udp_setflags(msg->conn->pcb.udp, UDP_FLAGS_NOCHKSUM); +@@ -683,7 +727,7 @@ + + msg->err = ERR_OK; + if (msg->conn->pcb.tcp == NULL) { +- pcb_new(msg); ++ pcb_new(msg); //raw_recv() + } + /* Else? This "new" connection already has a PCB allocated. */ + /* Is this an error condition? Should it be deleted? */ +@@ -713,13 +757,16 @@ + return NULL; + } + +- conn->pending_err = ERR_OK; ++ conn->last_err = ERR_OK; + conn->type = t; + conn->pcb.tcp = NULL; + + /* If all sizes are the same, every compiler should optimize this switch to nothing */ + switch (NETCONNTYPE_GROUP(t)) { + #if LWIP_RAW ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++#endif + case NETCONN_RAW: + size = DEFAULT_RAW_RECVMBOX_SIZE; + break; +@@ -778,8 +825,17 @@ + conn->linger = -1; + #endif /* LWIP_SO_LINGER */ + conn->flags = init_flags; ++#if LWIP_TCP ++ conn->pending_err = 0; ++ conn->refused_data = NULL; ++ ip_addr_set_zero(&conn->remote_ip); ++ conn->remote_port = 0; ++#endif + return conn; + free_and_return: ++ if (sys_sem_valid(&conn->op_completed) != 0) { ++ sys_sem_free(&conn->op_completed); ++ } + memp_free(MEMP_NETCONN, conn); + return NULL; + } +@@ -1160,6 +1216,11 @@ + case NETCONN_RAW: + raw_remove(msg->conn->pcb.raw); + break; ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++ raw_packet_remove(msg->conn->pcb.packet_raw); ++ break; ++#endif + #endif /* LWIP_RAW */ + #if LWIP_UDP + case NETCONN_UDP: +@@ -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)) || ++ ip_addr_ismulticast(API_EXPR_REF(msg->msg.bc.ipaddr)) || ++ netif_ipaddr_isbrdcast(API_EXPR_REF(msg->msg.bc.ipaddr)) || ++ ((netif != NULL) && netif_is_up(netif)))) { ++ msg->err = ERR_NOADDR; ++ } else ++#endif ++ { ++ msg->err = ERR_VAL; ++ if (msg->conn->pcb.tcp != NULL) { ++ switch (NETCONNTYPE_GROUP(msg->conn->type)) { + #if LWIP_RAW + case NETCONN_RAW: +- err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); ++ msg->err = raw_bind(msg->conn->pcb.raw, API_EXPR_REF(msg->msg.bc.ipaddr)); ++ break; ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++ msg->err = raw_packet_bind(msg->conn->pcb.packet_raw, msg->msg.bc.if_idx, msg->msg.bc.port); + break; ++#endif + #endif /* LWIP_RAW */ + #if LWIP_UDP + case NETCONN_UDP: +- err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); ++ msg->err = udp_bind(msg->conn->pcb.udp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); + break; + #endif /* LWIP_UDP */ + #if LWIP_TCP + case NETCONN_TCP: +- err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); ++ if (msg->conn->pcb.tcp->local_port == 0) { ++ msg->err = tcp_bind(msg->conn->pcb.tcp, API_EXPR_REF(msg->msg.bc.ipaddr), msg->msg.bc.port); ++ } else { ++ msg->err = ERR_VAL; ++ } ++ + break; + #endif /* LWIP_TCP */ + default: +- err = ERR_VAL; ++ msg->err = ERR_OPNOTSUPP; + break; ++ } + } +- } else { +- err = ERR_VAL; + } +- msg->err = err; + TCPIP_APIMSG_ACK(msg); + } + /** +@@ -1351,6 +1435,11 @@ + { + struct api_msg *msg = (struct api_msg *)m; + err_t err; ++ if (ERR_IS_FATAL(msg->conn->last_err)) { ++ msg->err = msg->conn->last_err; ++ TCPIP_APIMSG_ACK(msg); ++ return; ++ } + + if (msg->conn->pcb.tcp == NULL) { + /* This may happen when calling netconn_connect() a second time */ +@@ -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)) { ++#if PF_PACKET_SOCKET ++ struct ip_hdr *iphdr = NULL; ++ ip_addr_t dest_addr; ++ ++ if (!(msg->conn->pcb.raw->flags & RAW_FLAGS_CONNECTED) || ++ ip_addr_isany(&msg->conn->pcb.raw->remote_ip)) { ++ if (raw_is_flag_set(msg->conn->pcb.raw, RAW_FLAGS_HDRINCL)) { ++ if (msg->msg.b->p->len < IP_HLEN) { ++ err = ERR_MSGSIZE; ++ break; ++ } ++ ++ /* IP header already included in p */ ++ iphdr = (struct ip_hdr *)msg->msg.b->p->payload; ++ ip_addr_copy_from_ip4(dest_addr, iphdr->dest); ++ err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &dest_addr); ++ break; ++ } ++ ++ err = ERR_NODEST; ++ break; ++ } ++#endif /* PF_PACKET_SOCKET */ + err = raw_send(msg->conn->pcb.raw, msg->msg.b->p); + } else { + err = raw_sendto(msg->conn->pcb.raw, msg->msg.b->p, &msg->msg.b->addr); + } + break; ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++ /* Check if its for sending RAW packets for PF_PACKET family */ ++ if (msg->msg.b->flags & NETBUF_FLAG_IFINDEX) { ++ err = raw_packet_sendto(msg->conn->pcb.packet_raw, msg->msg.b->p, msg->msg.b->netifindex); ++ } else { ++ err = raw_packet_sendto(msg->conn->pcb.packet_raw, msg->msg.b->p, 0); ++ } ++ break; ++#endif + #endif + #if LWIP_UDP + case NETCONN_UDP: +@@ -1868,6 +1990,11 @@ + { + struct api_msg *msg = (struct api_msg *)m; + ++ if ((msg->conn == NULL) || (msg->conn->pcb.tcp == NULL)) { ++ msg->err = ERR_CONN; ++ TCPIP_APIMSG_ACK(msg); ++ return; ++ } + if (msg->conn->pcb.ip != NULL) { + if (msg->msg.ad.local) { + ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), +@@ -1882,10 +2009,18 @@ + #if LWIP_RAW + case NETCONN_RAW: + if (msg->msg.ad.local) { +- API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->protocol; ++ ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), ++ msg->conn->pcb.raw->local_ip); ++ API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->raw_proto; + } else { +- /* return an error as connecting is only a helper for upper layers */ +- msg->err = ERR_CONN; ++ if (raw_is_flag_set(msg->conn->pcb.raw, RAW_FLAGS_CONNECTED)) { ++ ip_addr_copy(API_EXPR_DEREF(msg->msg.ad.ipaddr), ++ msg->conn->pcb.raw->remote_ip); ++ API_EXPR_DEREF(msg->msg.ad.port) = msg->conn->pcb.raw->raw_proto; ++ } else { ++ /* return an error as connecting is only a helper for upper layers */ ++ msg->err = ERR_CONN; ++ } + } + break; + #endif /* LWIP_RAW */ +@@ -1923,6 +2058,47 @@ + TCPIP_APIMSG_ACK(msg); + } + ++#if PF_PACKET_SOCKET ++/** ++ * Return a pf pkt socket's local address ++ * Called from netconn_getaddr ++ * ++ * @param m the api_msg pointing to the connection ++ */ ++void ++lwip_netconn_do_getaddr_pfpkt(void *m) ++{ ++ struct api_msg *msg = (struct api_msg *)m; ++ struct pf_packet_sockaddr_ll ll; ++ msg->err = ERR_OK; ++ if (msg->conn->pcb.ip != NULL) { ++ /* Non standard way of do it, but doing it :( */ ++ if (msg->msg.adpkt.local) { ++ ll.sll_protocol = msg->conn->pcb.packet_raw->proto.eth_proto; ++ ll.if_idx = msg->conn->pcb.packet_raw->netifindex; ++ struct netif *netif = netif_find_by_ifindex(msg->conn->pcb.packet_raw->netifindex); ++ if (netif == NULL) { ++ LWIP_DEBUGF(SOCKETS_DEBUG, ++ ("lwip_getaddrname:netif not found for given ifindex (%u)\n", ++ msg->conn->pcb.packet_raw->netifindex)); ++ ll.sll_halen = 0; ++ ll.sll_hatype = 0; ++ } else { ++ ll.sll_hatype = netif->link_layer_type; ++ ll.sll_halen = NETIF_MAX_HWADDR_LEN; ++ (void)memcpy_s(ll.sll_addr, ll.sll_halen, netif->hwaddr, NETIF_MAX_HWADDR_LEN); ++ } ++ API_EXPR_DEREF(msg->msg.adpkt.ll) = ll; ++ } else { ++ msg->err = ERR_OPNOTSUPP; ++ } ++ } else { ++ msg->err = ERR_CONN; ++ } ++ TCPIP_APIMSG_ACK(msg); ++} ++#endif ++ + /** + * 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 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" + #include "lwip/memp.h" +- ++#include "lwip/api.h" + #include + + /** +@@ -99,7 +99,7 @@ + * NULL if no memory could be allocated + */ + void * +-netbuf_alloc(struct netbuf *buf, u16_t size) ++netbuf_alloc(struct netbuf *buf, u16_t size, u8_t netconn_type) + { + LWIP_ERROR("netbuf_alloc: invalid buf", (buf != NULL), return NULL;); + +@@ -107,7 +107,22 @@ + if (buf->p != NULL) { + pbuf_free(buf->p); + } +- buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); ++ ++ switch (netconn_type) { ++#if LWIP_RAW ++ case NETCONN_RAW: ++ buf->p = pbuf_alloc(PBUF_IP, size, PBUF_RAM); ++ break; ++#endif /* LWIP_RAW */ ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++ buf->p = pbuf_alloc(PBUF_LINK, size, PBUF_RAM); ++ break; ++#endif /* PF_PACKET_SOCKET */ ++ default: ++ buf->p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM); ++ } ++ + if (buf->p == NULL) { + 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 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. */ + #if LWIP_DNS_API_DECLARE_H_ERRNO +-int h_errno; ++int h_err_no; + #endif /* LWIP_DNS_API_DECLARE_H_ERRNO */ + + /** define "hostent" variables storage: 0 if we use a static (but unprotected) +@@ -100,7 +100,7 @@ + err = netconn_gethostbyname(name, &addr); + if (err != ERR_OK) { + LWIP_DEBUGF(DNS_DEBUG, ("lwip_gethostbyname(%s) failed, err=%d\n", name, err)); +- h_errno = HOST_NOT_FOUND; ++ h_err_no = HOST_NOT_FOUND; + return NULL; + } + +@@ -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; ++#if defined(SIN6_LEN) + sa6->sin6_len = sizeof(struct sockaddr_in6); ++#endif ++ sa6->sin6_flowinfo = 0; + sa6->sin6_port = lwip_htons((u16_t)port_nr); + sa6->sin6_scope_id = ip6_addr_zone(ip_2_ip6(&addr)); + ai->ai_family = AF_INET6; ++ ai->ai_addrlen = sizeof(struct sockaddr_in6); + #endif /* LWIP_IPV6 */ + } else { + #if LWIP_IPV4 +@@ -385,9 +394,9 @@ + /* set up sockaddr */ + inet_addr_from_ip4addr(&sa4->sin_addr, ip_2_ip4(&addr)); + sa4->sin_family = AF_INET; +- sa4->sin_len = sizeof(struct sockaddr_in); + sa4->sin_port = lwip_htons((u16_t)port_nr); + ai->ai_family = AF_INET; ++ ai->ai_addrlen = sizeof(struct sockaddr_in); + #endif /* LWIP_IPV4 */ + } + +@@ -403,7 +412,6 @@ + MEMCPY(ai->ai_canonname, nodename, namelen); + ai->ai_canonname[namelen] = 0; + } +- ai->ai_addrlen = sizeof(struct sockaddr_storage); + ai->ai_addr = (struct sockaddr *)sa; + + *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 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) + ++#if LWIP_MPU_COMPATIBLE ++static inline err_t netifapi_msg_alloc(struct netifapi_msg **name) ++{ ++ API_VAR_ALLOC(struct netifapi_msg, MEMP_NETIFAPI_MSG, (*name), ERR_MEM); ++ LWIP_UNUSED_ARG(name); ++ return ERR_OK; ++} ++#else ++static inline err_t netifapi_msg_alloc(struct netifapi_msg *name) ++{ ++ LWIP_UNUSED_ARG(name); ++ return ERR_OK; ++} ++#endif ++ + /** + * Call netif_add() inside the tcpip_thread context. + */ +@@ -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, +- msg->msg.add.input)) { ++ msg->msg.add_get.init, ++ msg->msg.add_get.input)) { + return ERR_IF; + } else { + return ERR_OK; +@@ -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; +- NETIFAPI_VAR_REF(msg).msg.add.init = init; +- NETIFAPI_VAR_REF(msg).msg.add.input = input; ++ NETIFAPI_VAR_REF(msg).msg.add_get.init = init; ++ NETIFAPI_VAR_REF(msg).msg.add_get.input = input; + err = tcpip_api_call(netifapi_do_netif_add, &API_VAR_REF(msg).call); + NETIFAPI_VAR_FREE(msg); + return err; +@@ -377,4 +395,60 @@ + return err; + } + ++/** ++ * Call netif_find() inside the tcpip_thread context. ++ */ ++static err_t ++do_netifapi_netif_find_by_name(struct tcpip_api_call_data *m) ++{ ++ struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; ++ ++ msg->netif = netif_find(msg->msg.find_by_name.name); ++ return ERR_OK; ++} ++ ++struct netif* ++netifapi_netif_find_by_name(const char *name) ++{ ++ struct netif *netif = NULL; ++ NETIFAPI_VAR_DECLARE(msg); ++ if (netifapi_msg_alloc(&msg) != ERR_OK) { ++ return NULL; ++ } ++ ++ NETIFAPI_VAR_REF(msg).netif = NULL; ++ NETIFAPI_VAR_REF(msg).msg.find_by_name.name = name; ++ (void)tcpip_api_call(do_netifapi_netif_find_by_name, &API_VAR_REF(msg).call); ++ netif = NETIFAPI_VAR_REF(msg).netif; ++ NETIFAPI_VAR_FREE(msg); ++ return netif; ++} ++ ++/** ++ * Call netif_find_by_ipaddr() inside the tcpip_thread context. ++ */ ++static err_t ++do_netifapi_netif_find_by_ipaddr(struct tcpip_api_call_data *m) ++{ ++ struct netifapi_msg *msg = (struct netifapi_msg*)(void*)m; ++ msg->netif = netif_find_by_ipaddr(msg->msg.find_by_ipaddr.ipaddr); ++ return ERR_OK; ++} ++ ++struct netif * ++netifapi_netif_find_by_ipaddr(const ip_addr_t *ipaddr) ++{ ++ struct netif *netif = NULL; ++ NETIFAPI_VAR_DECLARE(msg); ++ if (netifapi_msg_alloc(&msg) != ERR_OK) { ++ return NULL; ++ } ++ ++ NETIFAPI_VAR_REF(msg).netif = NULL; ++ NETIFAPI_VAR_REF(msg).msg.find_by_ipaddr.ipaddr = ipaddr; ++ (void)tcpip_api_call(do_netifapi_netif_find_by_ipaddr, &API_VAR_REF(msg).call); ++ netif = NETIFAPI_VAR_REF(msg).netif; ++ NETIFAPI_VAR_FREE(msg); ++ return netif; ++} + #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 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" + #include "lwip/mld6.h" ++#include "lwip/dhcp.h" + #if LWIP_CHECKSUM_ON_COPY + #include "lwip/inet_chksum.h" + #endif +@@ -85,9 +86,19 @@ + #define API_SELECT_CB_VAR_ALLOC(name, retblock) API_VAR_ALLOC_EXT(struct lwip_select_cb, MEMP_SELECT_CB, name, retblock) + #define API_SELECT_CB_VAR_FREE(name) API_VAR_FREE(MEMP_SELECT_CB, name) + ++#if !LWIP_LITEOS_COMPAT ++#defeine SIN4_LEN(x) \ ++ (x)->sin_len = sizeof(struct sockaddr_in) ++#defeine SIN6_LEN(x) \ ++ (x)->sin6_len = sizeof(struct sockaddr_in6) ++#else ++#define SIN4_LEN(x) ++#define SIN6_LEN(x) ++#endif /* LWIP_LITEOS_COMPAT */ ++ + #if LWIP_IPV4 + #define IP4ADDR_PORT_TO_SOCKADDR(sin, ipaddr, port) do { \ +- (sin)->sin_len = sizeof(struct sockaddr_in); \ ++ SIN4_LEN(sin); \ + (sin)->sin_family = AF_INET; \ + (sin)->sin_port = lwip_htons((port)); \ + inet_addr_from_ip4addr(&(sin)->sin_addr, ipaddr); \ +@@ -98,8 +109,10 @@ + #endif /* LWIP_IPV4 */ + + #if LWIP_IPV6 ++/* SIN6_LEN macro is to differntiate whether stack is using 4.3BSD or 4.4BSD variants of sockaddr_in6 ++structure */ + #define IP6ADDR_PORT_TO_SOCKADDR(sin6, ipaddr, port) do { \ +- (sin6)->sin6_len = sizeof(struct sockaddr_in6); \ ++ SIN6_LEN(sin6); \ + (sin6)->sin6_family = AF_INET6; \ + (sin6)->sin6_port = lwip_htons((port)); \ + (sin6)->sin6_flowinfo = 0; \ +@@ -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) + ++#if LWIP_LITEOS_COMPAT ++#define VALIDATE_GET_RAW_OPTNAME_RET(_sock, _optname) do { \ ++ if ((_sock)->conn != NULL && (NETCONNTYPE_GROUP((_sock)->conn->type) == NETCONN_RAW) && \ ++ (((_optname) != SO_BROADCAST) && ((_optname) != SO_RCVTIMEO) && \ ++ ((_optname) != SO_RCVBUF) && ((_optname) != SO_TYPE) && \ ++ ((_optname) != SO_DONTROUTE) && ((_optname) != SO_BINDTODEVICE))) { \ ++ done_socket(_sock); \ ++ return ENOPROTOOPT; \ ++ } \ ++ } while (0) ++ ++#if PF_PACKET_SOCKET ++#define VALIDATE_SET_PF_PKT_OPTNAME_RET(_s, _sock, _level, _optname) do { \ ++ if ((_level) == SOL_PACKET && ((_optname) != SO_RCVTIMEO && (_optname) != SO_RCVBUF) && \ ++ (_optname) != SO_ATTACH_FILTER && (_optname) != SO_DETACH_FILTER) { \ ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, SOL_PACKET, UNIMPL: optname=0x%x, ..)\n", \ ++ (_s), (_optname))); \ ++ done_socket(_sock); \ ++ return ENOPROTOOPT; \ ++ } \ ++ } while (0) ++ ++#define VALIDATE_GET_PF_PKT_OPTNAME_RET(_s,_sock,_level,_optname) do { \ ++ if ((_sock)->conn != NULL && (NETCONNTYPE_GROUP((_sock)->conn->type) == NETCONN_PACKET_RAW) && \ ++ (_level) == SOL_PACKET && ((_optname) != SO_RCVTIMEO && (_optname) != SO_RCVBUF && (_optname) != SO_TYPE)) { \ ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%p, SOL_PACKET, UNIMPL: optname=0x%x, ..)\n", \ ++ (_s), (_optname))); \ ++ done_socket(_sock); \ ++ return ENOPROTOOPT; \ ++ } \ ++ } while (0) ++ ++#define VALIDATE_LEVEL_PF_PACKET(_sock,_level) \ ++ if ((_sock)->conn != NULL && ((NETCONNTYPE_GROUP(netconn_type(_sock->conn)) == NETCONN_PACKET_RAW \ ++ && SOL_SOCKET != (_level) && SOL_PACKET != (_level)) || \ ++ (NETCONNTYPE_GROUP((_sock)->conn->type) != NETCONN_PACKET_RAW && SOL_PACKET == (_level)))) ++#endif ++#endif /* LWIP_LITEOS_COMPAT */ ++ + /* 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 +564,29 @@ + return sock; + } + ++#if LWIP_LITEOS_COMPAT ++/* get numbers of unused sockets */ ++int get_unused_socket_num(void) ++{ ++ int unused = 0, i; ++ SYS_ARCH_DECL_PROTECT(lev); ++ SYS_ARCH_PROTECT(lev); ++ ++ for (i = 0; i < (int)(NUM_SOCKETS); i++) { ++ if (!sockets[i].conn ++#if LWIP_NETCONN_FULLDUPLEX ++ && !sockets[i].fd_used ++#endif ++ ) { ++ unused++; ++ } ++ } ++ ++ SYS_ARCH_UNPROTECT(lev); ++ return unused; ++} ++#endif /* LWIP_LITEOS_COMPAT */ ++ + /** + * Allocate a new socket for a given netconn. + * +@@ -696,8 +794,10 @@ + } + + IPADDR_PORT_TO_SOCKADDR(&tempaddr, &naddr, port); +- if (*addrlen > tempaddr.sa.sa_len) { +- *addrlen = tempaddr.sa.sa_len; ++ if (IP_IS_V4_VAL(naddr) && (*addrlen > (int)sizeof(struct sockaddr_in))) { ++ *addrlen = sizeof(struct sockaddr_in); ++ } else if (IP_IS_V6_VAL(naddr) && (*addrlen > (int)sizeof(struct sockaddr_in6))) { ++ *addrlen = sizeof(struct sockaddr_in6); + } + MEMCPY(addr, &tempaddr, *addrlen); + +@@ -722,28 +822,59 @@ + u16_t local_port; + err_t err; + ++#if PF_PACKET_SOCKET ++ const struct sockaddr_ll *name_ll = NULL; ++ u8_t local_if_idx = 0; ++#endif + sock = get_socket(s); + if (!sock) { + return -1; + } + +- if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { +- /* sockaddr does not match socket type (IPv4/IPv6) */ +- sock_set_errno(sock, err_to_errno(ERR_VAL)); +- done_socket(sock); +- return -1; +- } +- + /* check size, family and alignment of 'name' */ +- LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && ++#if PF_PACKET_SOCKET ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { ++ name_ll = (const struct sockaddr_ll *)(void*)name; ++ LWIP_ERROR("lwip_bind: invalid address", ((name_ll != NULL)&&(namelen == sizeof(struct sockaddr_ll)) && ++ ((name_ll->sll_family) == PF_PACKET) && IS_SOCK_ADDR_ALIGNED(name) && ++ (name_ll->sll_ifindex <= LWIP_NETIF_IFINDEX_MAX)), sock_set_errno(sock, err_to_errno(ERR_VAL)); ++ done_socket(sock); return -1); ++ ++ ip_addr_set_any_val(IPADDR_TYPE_V4, local_addr); ++ local_port = name_ll->sll_protocol; ++ local_if_idx = (u8_t)name_ll->sll_ifindex; ++ ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, ", s)); ++ LWIP_DEBUGF(SOCKETS_DEBUG, (" ifindex=%u proto=%"U16_F")\n", local_if_idx, local_port)); ++ } else ++#endif ++ { ++ 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); ++ ++ if (!SOCK_ADDR_TYPE_MATCH(name, sock)) { ++ /* sockaddr does not match socket type (IPv4/IPv6) */ ++ sock_set_errno(sock, err_to_errno(ERR_VAL)); ++ done_socket(sock); ++ return -1; ++ } ++ ++ /* check size, family and alignment of 'name' */ ++ LWIP_ERROR("lwip_bind: invalid address", (IS_SOCK_ADDR_LEN_VALID(namelen) && + IS_SOCK_ADDR_TYPE_VALID(name) && IS_SOCK_ADDR_ALIGNED(name)), + sock_set_errno(sock, err_to_errno(ERR_ARG)); done_socket(sock); return -1;); +- LWIP_UNUSED_ARG(namelen); ++ LWIP_UNUSED_ARG(namelen); + +- SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); +- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); +- ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); +- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); ++ SOCKADDR_TO_IPADDR_PORT(name, &local_addr, local_port); ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d, addr=", s)); ++ ip_addr_debug_print_val(SOCKETS_DEBUG, local_addr); ++ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F")\n", local_port)); ++ } + + #if LWIP_IPV4 && LWIP_IPV6 + /* Dual-stack: Unmap IPv4 mapped IPv6 addresses */ +@@ -753,7 +884,11 @@ + } + #endif /* LWIP_IPV4 && LWIP_IPV6 */ + ++#if PF_PACKET_SOCKET ++ err = netconn_bind(sock->conn, &local_addr, local_port, local_if_idx); ++#else /* PF_PACKET_SOCKET */ + err = netconn_bind(sock->conn, &local_addr, local_port); ++#endif + + if (err != ERR_OK) { + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_bind(%d) failed, err=%d\n", s, err)); +@@ -820,6 +955,14 @@ + return -1; + } + ++#if PF_PACKET_SOCKET ++ if (NETCONN_PACKET_RAW & NETCONNTYPE_GROUP(netconn_type(sock->conn))) { ++ sock_set_errno(sock, EOPNOTSUPP); ++ done_socket(sock); ++ return -1; ++ } ++#endif ++ + 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 +1168,7 @@ + { + int truncated = 0; + union sockaddr_aligned saddr; ++ socklen_t sa_len; + + LWIP_UNUSED_ARG(conn); + +@@ -1041,10 +1185,27 @@ + #endif /* LWIP_IPV4 && LWIP_IPV6 */ + + IPADDR_PORT_TO_SOCKADDR(&saddr, fromaddr, port); +- if (*fromlen < saddr.sa.sa_len) { ++#if LWIP_LITEOS_COMPAT ++ if (IP_IS_V4_VAL(*fromaddr)) { ++ sa_len = sizeof(struct sockaddr_in); ++ } ++#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 */ ++ ++ if (*fromlen < sa_len) { + truncated = 1; +- } else if (*fromlen > saddr.sa.sa_len) { +- *fromlen = saddr.sa.sa_len; ++ } else if (*fromlen > sa_len) { ++ *fromlen = sa_len; + } + MEMCPY(from, &saddr, *fromlen); + return truncated; +@@ -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) { +- lwip_sock_make_addr(sock->conn, netbuf_fromaddr(buf), netbuf_fromport(buf), +- (struct sockaddr *)msg->msg_name, &msg->msg_namelen); ++#if PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT ++ struct sockaddr_ll sll; ++ ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { ++ if (msg->msg_namelen > sizeof(sll)) { ++ msg->msg_namelen = sizeof(sll); ++ } ++ ++ if (msg->msg_namelen) { ++ (void)memset_s(&sll, sizeof(sll), 0, sizeof(sll)); ++ sll.sll_family = PF_PACKET; ++ sll.sll_protocol = netbuf_fromport(buf); ++ sll.sll_hatype = netbuf_fromhatype(buf); ++ sll.sll_ifindex = netbuf_fromifindex(buf); ++ ++ if (buf->p->flags & PBUF_FLAG_LLBCAST) { ++ sll.sll_pkttype = PACKET_BROADCAST; ++ } else if (buf->p->flags & PBUF_FLAG_LLMCAST) { ++ sll.sll_pkttype = PACKET_MULTICAST; ++ } else if (buf->p->flags & PBUF_FLAG_HOST) { ++ sll.sll_pkttype = PACKET_HOST; ++ } else if (buf->p->flags & PBUF_FLAG_OUTGOING) { ++ sll.sll_pkttype = PACKET_OUTGOING; ++ } else { ++ sll.sll_pkttype = PACKET_OTHERHOST; ++ } ++ ++ (void)memcpy_s(msg->msg_name, msg->msg_namelen, (void *)&sll, msg->msg_namelen); ++ ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_recvfrom_udp_raw(%d): hatype=%u", dbg_s, ntohs(sll.sll_hatype))); ++ LWIP_DEBUGF(SOCKETS_DEBUG, (" packet type = %u\n", sll.sll_pkttype)); ++ } ++ } else ++#endif /* PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT */ ++ { ++ lwip_sock_make_addr(sock->conn, netbuf_fromaddr(buf), netbuf_fromport(buf), ++ (struct sockaddr *)msg->msg_name, &msg->msg_namelen); ++ } + } + } ++ + + /* 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. */ +- if (netbuf_alloc(&chain_buf, (u16_t)size) == NULL) { ++ if (netbuf_alloc(&chain_buf, (u16_t)size, NETCONNTYPE_GROUP(netconn_type(sock->conn))) == NULL) { + err = ERR_MEM; + } else { + /* flatten the IO vectors */ +@@ -1588,8 +1784,14 @@ + struct lwip_sock *sock; + err_t err; + u16_t short_size; +- u16_t remote_port; ++ u16_t remote_port = 0; + struct netbuf buf; ++#if (PF_PACKET_SOCKET & LWIP_LITEOS_COMPAT) ++ const struct sockaddr_ll *to_ll = NULL; ++#endif ++ const struct sockaddr_in *to_in = NULL; ++ ++ unsigned int acceptable_flags = 0; + + sock = get_socket(s); + if (!sock) { +@@ -1608,11 +1810,62 @@ + #endif /* LWIP_TCP */ + } + +- if (size > LWIP_MIN(0xFFFF, SSIZE_MAX)) { +- /* cannot fit into one datagram (at least for us) */ +- sock_set_errno(sock, EMSGSIZE); +- done_socket(sock); +- return -1; ++#if PF_PACKET_SOCKET ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) & NETCONN_PACKET_RAW) { ++ to_ll = (const struct sockaddr_ll *)(void *)to; ++ ++ LWIP_ERROR("lwip_sendto: invalid address", (((data != NULL) && (size!=0)) && ++ (((to_ll != NULL) && (tolen == sizeof(struct sockaddr_ll))) && ++ ((to_ll->sll_family) == PF_PACKET) && ((((mem_ptr_t)to_ll) % 4) == 0)) && ++ (to_ll->sll_ifindex <= LWIP_NETIF_IFINDEX_MAX)), ++ sock_set_errno(sock, err_to_errno(ERR_VAL)); ++ done_socket(sock); return -1); ++ ++ LWIP_ERROR("lwip_sendto: invalid address family", ((to_ll->sll_family) == PF_PACKET), ++ sock_set_errno(sock, err_to_errno(ERR_AFNOSUPP)); ++ done_socket(sock); return -1); ++ ++ LWIP_ERROR("lwip_sendto: invalid flags. Should be 0", (flags == 0), ++ sock_set_errno(sock, err_to_errno(ERR_OPNOTSUPP)); ++ done_socket(sock); return -1); ++ ++ if (size > LWIP_MAX_PF_RAW_SEND_SIZE) { ++ sock_set_errno(sock, EMSGSIZE); ++ done_socket(sock); ++ return -1; ++ } ++ } else ++#endif /* PF_PACKET_SOCKET */ ++ { ++ to_in = (const struct sockaddr_in *)(void*)to; ++ acceptable_flags = acceptable_flags | MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL; ++ if ((~acceptable_flags) & (unsigned int)flags) { ++ sock_set_errno(sock, err_to_errno(ERR_OPNOTSUPP)); ++ done_socket(sock); ++ return -1; ++ } ++ ++ LWIP_ERROR("lwip_sendto: invalid address", ((data != NULL) && (size!=0) && (flags>=0)), ++ sock_set_errno(sock, err_to_errno(ERR_VAL)); ++ done_socket(sock); return -1); ++ ++ LWIP_ERROR("lwip_sendto: invalid address", (((to_in == NULL) && (tolen == 0)) || ++ (((to_in == NULL) && (tolen != 0)) || IS_SOCK_ADDR_LEN_VALID(tolen))), ++ sock_set_errno(sock, err_to_errno(ERR_VAL)); ++ done_socket(sock); ++ return -1); ++ ++ LWIP_ERROR("lwip_sendto: invalid address", (to == NULL || IS_SOCK_ADDR_TYPE_VALID(to)), ++ sock_set_errno(sock, err_to_errno(ERR_AFNOSUPPORT)); ++ done_socket(sock); ++ return -1); ++ ++ if (size > LWIP_MAX_UDP_RAW_SEND_SIZE) { ++ sock_set_errno(sock, EMSGSIZE); ++ done_socket(sock); ++ return -1; ++ } ++ + } + short_size = (u16_t)size; + LWIP_ERROR("lwip_sendto: invalid address", (((to == NULL) && (tolen == 0)) || +@@ -1626,6 +1879,9 @@ + #if LWIP_CHECKSUM_ON_COPY + buf.flags = 0; + #endif /* LWIP_CHECKSUM_ON_COPY */ ++#if PF_PACKET_SOCKET ++ buf.netifindex = 0; ++#endif + if (to) { + SOCKADDR_TO_IPADDR_PORT(to, &buf.addr, remote_port); + } else { +@@ -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)); +- ip_addr_debug_print_val(SOCKETS_DEBUG, buf.addr); +- LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); +- ++#if PF_PACKET_SOCKET ++ if (buf.flags & NETBUF_FLAG_IFINDEX) { ++ LWIP_DEBUGF(SOCKETS_DEBUG, (" netifindex = %d\n", buf.netifindex)); ++ } else ++#endif ++ { ++ ip_addr_debug_print_val(SOCKETS_DEBUG, buf.addr); ++ LWIP_DEBUGF(SOCKETS_DEBUG, (" port=%"U16_F"\n", remote_port)); ++ } + /* make the buffer point to the data that should be sent */ + #if LWIP_NETIF_TX_SINGLE_PBUF + /* Allocate a new netbuf and copy the data into it. */ +- if (netbuf_alloc(&buf, short_size) == NULL) { ++ if (netbuf_alloc(&buf, short_size, NETCONNTYPE_GROUP(netconn_type(sock->conn))) == NULL) { + err = ERR_MEM; + } else { + #if LWIP_CHECKSUM_ON_COPY +- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) { ++#if PF_PACKET_SOCKET ++ if ((NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_PACKET_RAW) && ++ (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW)) ++#else ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_RAW) ++#endif ++ { + u16_t chksum = LWIP_CHKSUM_COPY(buf.p->payload, data, short_size); + netbuf_set_chksum(&buf, chksum); + } else +@@ -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: +- conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), +- (u8_t)protocol, DEFAULT_SOCKET_EVENTCB); +- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", ++#if PF_PACKET_SOCKET ++ if (domain == PF_PACKET) { ++ conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_PACKET_RAW), ++ (u16_t)protocol, event_callback); ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", "PF_PACKET", protocol)); ++ } else ++#endif ++ { ++ conn = netconn_new_with_proto_and_callback(DOMAIN_TO_NETCONN_TYPE(domain, NETCONN_RAW), ++ (u8_t)protocol, DEFAULT_SOCKET_EVENTCB); ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_RAW, %d) = ", + domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); ++ } + break; + case SOCK_DGRAM: + conn = netconn_new_with_callback(DOMAIN_TO_NETCONN_TYPE(domain, +@@ -1983,10 +2269,11 @@ + timeout ? (s32_t)timeout->tv_sec : (s32_t) - 1, + timeout ? (s32_t)timeout->tv_usec : (s32_t) - 1)); + +- if ((maxfdp1 < 0) || (maxfdp1 > LWIP_SELECT_MAXNFDS)) { ++/*if ((maxfdp1 < 0) || (maxfdp1 > LWIP_SELECT_MAXNFDS)) { + set_errno(EINVAL); + return -1; + } ++ */ + + lwip_select_inc_sockets_used(maxfdp1, readset, writeset, exceptset, &used_sockets); + +@@ -2704,12 +2991,60 @@ + ip_addr_t naddr; + u16_t port; + err_t err; ++ socklen_t sa_len; ++ ++#if PF_PACKET_SOCKET ++ struct sockaddr_ll addr_sin; ++ struct pf_packet_sockaddr_ll sll; ++ socklen_t outlen; ++#endif ++ ++ LWIP_ERROR("lwip_getaddrname: invalid arguments", ((name != NULL) && (namelen != NULL)), ++ set_errno(EINVAL); return -1); + + sock = get_socket(s); + if (!sock) { + return -1; + } + ++#if PF_PACKET_SOCKET ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_PACKET_RAW) { ++ err = netconn_get_sockaddr_pf_packet(sock->conn, &sll, local); ++ if (err != ERR_OK) { ++ sock_set_errno(sock, err_to_errno(err)); ++ done_socket(sock); ++ return -1; ++ } ++ ++ (void)memset_s(&addr_sin, sizeof(struct sockaddr_ll), 0, sizeof(struct sockaddr_ll)); ++ addr_sin.sll_family = PF_PACKET; ++ addr_sin.sll_protocol = sll.sll_protocol; ++ addr_sin.sll_pkttype = 0; ++ addr_sin.sll_ifindex = sll.if_idx; ++ addr_sin.sll_hatype = sll.sll_hatype; ++ addr_sin.sll_halen = sll.sll_halen; ++ ++ if ((sll.sll_halen > 0) && (memcpy_s(addr_sin.sll_addr, addr_sin.sll_halen, sll.sll_addr, sll.sll_halen) != EOK)) { ++ sock_set_errno(sock, err_to_errno(ERR_MEM)); ++ done_socket(sock); ++ return -1; ++ } ++ ++ outlen = sizeof(struct sockaddr_ll); ++ if (outlen > *namelen) { ++ outlen = *namelen; ++ } ++ if (memcpy_s(name, *namelen, &addr_sin, outlen) != EOK) { ++ sock_set_errno(sock, err_to_errno(ERR_MEM)); ++ done_socket(sock); ++ return -1; ++ } ++ *namelen = outlen; ++ done_socket(sock); ++ return 0; ++ } ++#endif /* PF_PACKET_SOCKET */ ++ + /* get the IP address and port */ + err = netconn_getaddr(sock->conn, &naddr, &port, local); + if (err != ERR_OK) { +@@ -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)); ++ if (IP_IS_V4_VAL(naddr)) { ++ sa_len = sizeof(struct sockaddr_in); ++ } else { ++ sa_len = sizeof(struct sockaddr_in6); ++ } + +- if (*namelen > saddr.sa.sa_len) { +- *namelen = saddr.sa.sa_len; ++ if (*namelen > sa_len) { ++ *namelen = sa_len; + } + MEMCPY(name, &saddr, *namelen); + +@@ -2775,6 +3115,14 @@ + return -1; + } + ++#if PF_PACKET_SOCKET ++ VALIDATE_LEVEL_PF_PACKET(sock, level) { ++ sock_set_errno(sock, EINVAL); ++ done_socket(sock); ++ return -1; ++ } ++#endif /* PF_PACKET_SOCKET */ ++ + #if LWIP_TCPIP_CORE_LOCKING + /* core-locking can just call the -impl function */ + LOCK_TCPIP_CORE(); +@@ -2826,8 +3174,9 @@ + err = LWIP_SETGETSOCKOPT_DATA_VAR_REF(data).err; + LWIP_SETGETSOCKOPT_DATA_VAR_FREE(data); + #endif /* LWIP_TCPIP_CORE_LOCKING */ +- +- sock_set_errno(sock, err); ++ if (err != ERR_OK) { ++ sock_set_errno(sock, err); ++ } + done_socket(sock); + return err ? -1 : 0; + } +@@ -2897,6 +3246,11 @@ + + /* Level: SOL_SOCKET */ + case SOL_SOCKET: ++#if PF_PACKET_SOCKET ++ case SOL_PACKET: ++ VALIDATE_GET_PF_PKT_OPTNAME_RET(s, sock, level, optname); ++#endif /* PF_PACKET_SOCKET */ ++ VALIDATE_GET_RAW_OPTNAME_RET(sock, optname); + switch (optname) { + + #if LWIP_TCP +@@ -2920,6 +3274,10 @@ + #if SO_REUSE + case SO_REUSEADDR: + #endif /* SO_REUSE */ ++ if (sock->conn == NULL) { ++ done_socket(sock); ++ return EINVAL; ++ } + if ((optname == SO_BROADCAST) && + (NETCONNTYPE_GROUP(sock->conn->type) != NETCONN_UDP)) { + done_socket(sock); +@@ -2937,6 +3295,9 @@ + case SO_TYPE: + LWIP_SOCKOPT_CHECK_OPTLEN_CONN(sock, *optlen, int); + switch (NETCONNTYPE_GROUP(netconn_type(sock->conn))) { ++#if PF_PACKET_SOCKET ++ case NETCONN_PACKET_RAW: ++#endif + case NETCONN_RAW: + *(int *)optval = SOCK_RAW; + break; +@@ -2948,9 +3309,16 @@ + break; + default: /* unrecognized socket type */ + *(int *)optval = netconn_type(sock->conn); ++#if PF_PACKET_SOCKET ++ LWIP_DEBUGF(SOCKETS_DEBUG, ++ ("lwip_getsockopt(%d, %s, SO_TYPE): unrecognized socket type %d\n", ++ s, (NETCONN_PACKET_RAW != NETCONNTYPE_GROUP(sock->conn->type)) ? "SOL_SOCKET" : "SOL_PACKET", ++ *(int *)optval)); ++#else + LWIP_DEBUGF(SOCKETS_DEBUG, + ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE): unrecognized socket type %d\n", + s, *(int *)optval)); ++#endif + } /* switch (netconn_type(sock->conn)) */ + LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, SOL_SOCKET, SO_TYPE) = %d\n", + s, *(int *)optval)); +@@ -3739,92 +4107,450 @@ + return err; + } + +-int +-lwip_ioctl(int s, long cmd, void *argp) ++#if PF_PACKET_SOCKET || LOSCFG_COMPONENTS_UPNP ++#if LWIP_IOCTL_IF ++static u8_t lwip_ioctl_internal_SIOCGIFCONF(struct ifreq *ifr) ++{ ++ struct ifconf *ifc = NULL; ++ struct netif *netif = NULL; ++ struct ifreq ifreq; ++ struct sockaddr_in *sock_in = NULL; ++ int pos; ++ int len; ++ int ret; ++ ++ /* Format the caller's buffer. */ ++ ifc = (struct ifconf*)ifr; ++ len = ifc->ifc_len; ++ ++ /* Loop over the interfaces, and write an info block for each. */ ++ pos = 0; ++ for (netif = netif_list; netif != NULL; netif = netif->next) { ++ if (ifc->ifc_buf == NULL) { ++ pos = (pos + (int)sizeof(struct ifreq)); ++ continue; ++ } ++ ++ if (len < (int)sizeof(ifreq)) { ++ break; ++ } ++ ++ if (memset_s(&ifreq, sizeof(struct ifreq), 0, sizeof(struct ifreq)) != EOK) { ++ return ENOBUFS; ++ } ++ if (netif->link_layer_type == LOOPBACK_IF) { ++ ret = snprintf_s(ifreq.ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s", netif->name); ++ if ((ret <= 0) || (ret >= IFNAMSIZ)) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed.")); ++ return ENOBUFS; ++ } ++ } else { ++ ret = snprintf_s(ifreq.ifr_name, NETIF_NAMESIZE, NETIF_NAMESIZE - 1, "%s%"U8_F, netif->name, netif->num); ++ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("lwip_ioctl: snprintf_s ifr_name failed.")); ++ return ENOBUFS; ++ } ++ } ++ ++ sock_in = (struct sockaddr_in *)&ifreq.ifr_addr; ++ sock_in->sin_family = AF_INET; ++ sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr; ++ if (memcpy_s(ifc->ifc_buf + pos, sizeof(struct ifreq), &ifreq, sizeof(struct ifreq)) != EOK) { ++ return ENOBUFS; ++ } ++ pos += (int)sizeof(struct ifreq); ++ len -= (int)sizeof(struct ifreq); ++ } ++ ++ ifc->ifc_len = pos; ++ ++ return 0; ++} ++ ++static u8_t lwip_ioctl_internal_SIOCGIFADDR(struct ifreq *ifr) ++{ ++ struct netif *netif = NULL; ++ struct sockaddr_in *sock_in = NULL; ++ ++ /* get netif ipaddr */ ++ netif = netif_find(ifr->ifr_name); ++ if (netif == NULL) { ++ return ENODEV; ++ } else { ++ sock_in = (struct sockaddr_in *)&ifr->ifr_addr; ++ sock_in->sin_family = AF_INET; ++ sock_in->sin_addr.s_addr = ip_2_ip4(&netif->ip_addr)->addr; ++ return 0; ++ } ++} ++ ++static u8_t lwip_ioctl_internal_SIOCSIFFLAGS(const struct ifreq *ifr) ++{ ++ struct netif *netif = NULL; ++ ++ /* set netif hw addr */ ++ netif = netif_find(ifr->ifr_name); ++ if (netif == NULL) { ++ return ENODEV; ++ } ++#if LWIP_HAVE_LOOPIF ++ else if (netif->link_layer_type == LOOPBACK_IF) { ++ return EPERM; ++ } ++#endif /* LWIP_HAVE_LOOPIF */ ++ else { ++ if ((ifr->ifr_flags & IFF_UP) && !(netif->flags & NETIF_FLAG_UP)) { ++ (void)netif_set_up(netif); ++ } else if (!(ifr->ifr_flags & IFF_UP) && (netif->flags & NETIF_FLAG_UP)) { ++ (void)netif_set_down(netif); ++ } ++ if ((ifr->ifr_flags & IFF_RUNNING) && !(netif->flags & NETIF_FLAG_LINK_UP)) { ++ (void)netif_set_link_up(netif); ++ } else if (!(ifr->ifr_flags & IFF_RUNNING) && (netif->flags & NETIF_FLAG_LINK_UP)) { ++ (void)netif_set_link_down(netif); ++ } ++ ++ if (ifr->ifr_flags & IFF_BROADCAST) { ++ netif->flags |= NETIF_FLAG_BROADCAST; ++ } else { ++ netif->flags = netif->flags & (~NETIF_FLAG_BROADCAST); ++ } ++ if (ifr->ifr_flags & IFF_NOARP) { ++ netif->flags = (netif->flags & (~NETIF_FLAG_ETHARP)); ++ } else { ++ netif->flags |= NETIF_FLAG_ETHARP; ++ } ++ ++ if (ifr->ifr_flags & IFF_MULTICAST) { ++#if LWIP_IGMP ++ netif->flags |= NETIF_FLAG_IGMP; ++#endif /* LWIP_IGMP */ ++#if LWIP_IPV6 && LWIP_IPV6_MLD ++ netif->flags |= NETIF_FLAG_MLD6; ++#endif /* LWIP_IPV6_MLD */ ++ } ++ else { ++#if LWIP_IGMP ++ netif->flags = (netif->flags & ~NETIF_FLAG_IGMP); ++#endif /* LWIP_IGMP */ ++#if LWIP_IPV6 && LWIP_IPV6_MLD ++ netif->flags = (netif->flags & ~NETIF_FLAG_MLD6); ++#endif /* LWIP_IPV6_MLD */ ++ } ++ ++#if 0 ++ if (ifr->ifr_flags & IFF_DYNAMIC) { ++ (void)dhcp_start(netif); ++ } else { ++ dhcp_stop(netif); ++ dhcp_cleanup(netif); ++ } ++#endif ++ ++ return 0; ++ } ++} ++ ++static u8_t lwip_ioctl_internal_SIOCGIFFLAGS(struct ifreq *ifr) ++{ ++ struct netif *netif = NULL; ++ ++ /* set netif hw addr */ ++ netif = netif_find(ifr->ifr_name); ++ if (netif == NULL) { ++ return ENODEV; ++ } else { ++ if (netif->flags & NETIF_FLAG_UP) { ++ ifr->ifr_flags |= IFF_UP; ++ } else { ++ ifr->ifr_flags &= ~IFF_UP; ++ } ++ if (netif->flags & NETIF_FLAG_LINK_UP) { ++ ifr->ifr_flags |= IFF_RUNNING; ++ } else { ++ ifr->ifr_flags &= ~IFF_RUNNING; ++ } ++ if (netif->flags & NETIF_FLAG_BROADCAST) { ++ ifr->ifr_flags |= IFF_BROADCAST; ++ } else { ++ ifr->ifr_flags &= ~IFF_BROADCAST; ++ } ++ if (netif->flags & NETIF_FLAG_ETHARP) { ++ ifr->ifr_flags &= ~IFF_NOARP; ++ } else { ++ ifr->ifr_flags |= IFF_NOARP; ++ } ++ ++#if LWIP_IGMP || LWIP_IPV6_MLD ++ if ( ++#if LWIP_IGMP ++ (netif->flags & NETIF_FLAG_IGMP) ++#endif /* LWIP_IGMP */ ++#if LWIP_IGMP && LWIP_IPV6_MLD ++ || ++#endif /* LWIP_IGMP && LWIP_IPV6_MLD */ ++#if LWIP_IPV6_MLD ++ (netif->flags & NETIF_FLAG_MLD6) ++#endif /* LWIP_IPV6_MLD */ ++ ) { ++ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_MULTICAST); ++ } else { ++ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_MULTICAST)); ++ } ++#endif /* LWIP_IGMP || LWIP_IPV6_MLD */ ++ ++#if LWIP_DHCP ++ if (netif->flags & NETIF_FLAG_DHCP) { ++ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags | IFF_DYNAMIC); ++ } else { ++ ifr->ifr_flags = (short)((unsigned short)ifr->ifr_flags & (~IFF_DYNAMIC)); ++ } ++#endif ++ ++#if LWIP_HAVE_LOOPIF ++ if (netif->link_layer_type == LOOPBACK_IF) { ++ ifr->ifr_flags |= IFF_LOOPBACK; ++ } ++#endif ++ ++ return 0; ++ } ++} ++ ++static u8_t lwip_ioctl_internal_SIOCGIFNAME(struct ifreq *ifr) ++{ ++ struct netif *netif = NULL; ++ int ret; ++ ++ for (netif = netif_list; netif != NULL; netif = netif->next) { ++ if (ifr->ifr_ifindex == netif->ifindex) { ++ break; ++ } ++ } ++ ++ if (netif == NULL) { ++ return ENODEV; ++ } ++ if (netif->link_layer_type == LOOPBACK_IF) { ++ ret = snprintf_s(ifr->ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s", netif->name); ++ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { ++ return ENOBUFS; ++ } ++ } else { ++ ret = snprintf_s(ifr->ifr_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s%"U8_F, netif->name, netif->num); ++ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { ++ return ENOBUFS; ++ } ++ } ++ return 0; ++} ++ ++static u8_t lwip_ioctl_internal_SIOCGIFINDEX(struct ifreq *ifr) ++{ ++ struct netif *netif = NULL; ++ netif = netif_find(ifr->ifr_name); ++ if (netif == NULL) { ++ return ENODEV; ++ } ++ ifr->ifr_ifindex = netif->ifindex; ++ return 0; ++} ++#endif /* LWIP_IOCTL_IF */ ++#endif /* PF_PACKET_SOCKET */ ++ ++#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE ++static u8_t lwip_ioctl_internal_FIONREAD(struct lwip_sock *sock, void *argp) + { +- struct lwip_sock *sock = get_socket(s); +- u8_t val; + #if LWIP_SO_RCVBUF + int recv_avail; +-#endif /* LWIP_SO_RCVBUF */ ++#endif ++#if LWIP_FIONREAD_LINUXMODE ++ SYS_ARCH_DECL_PROTECT(lev); ++#endif + +- if (!sock) { +- return -1; ++ if (!argp) { ++ return EINVAL; + } + +- switch (cmd) { +-#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE +- case FIONREAD: +- if (!argp) { +- sock_set_errno(sock, EINVAL); +- done_socket(sock); +- return -1; +- } ++ lwip_sock_lock(sock); + #if LWIP_FIONREAD_LINUXMODE +- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { +- struct netbuf *nb; +- if (sock->lastdata.netbuf) { +- nb = sock->lastdata.netbuf; +- *((int *)argp) = nb->p->tot_len; ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) != NETCONN_TCP) { ++ struct netbuf *nb; ++ if (sock->lastdata.netbuf) { ++ nb = sock->lastdata.netbuf; ++ *((int *)argp) = nb->p->tot_len; ++ } else { ++ struct netbuf *rxbuf; ++ err_t err; ++ ++ SYS_ARCH_PROTECT(lev); ++ if (sock->rcvevent <= 0) { ++ *((int*)argp) = 0; ++ SYS_ARCH_UNPROTECT(lev); ++ } else { ++ SYS_ARCH_UNPROTECT(lev); ++ err = netconn_recv_udp_raw_netbuf_flags(sock->conn, &rxbuf, NETCONN_DONTBLOCK); ++ if (err != ERR_OK) { ++ *((int *)argp) = 0; + } else { +- struct netbuf *rxbuf; +- err_t err = netconn_recv_udp_raw_netbuf_flags(sock->conn, &rxbuf, NETCONN_DONTBLOCK); +- if (err != ERR_OK) { +- *((int *)argp) = 0; +- } else { +- sock->lastdata.netbuf = rxbuf; +- *((int *)argp) = rxbuf->p->tot_len; +- } ++ sock->lastdata.netbuf = rxbuf; ++ *((int *)argp) = rxbuf->p->tot_len; + } +- done_socket(sock); +- return 0; + } ++ } ++ ++ lwip_sock_unlock(sock); ++ return 0; ++ } + #endif /* LWIP_FIONREAD_LINUXMODE */ + + #if LWIP_SO_RCVBUF +- /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ +- SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); +- if (recv_avail < 0) { +- recv_avail = 0; +- } ++ /* we come here if either LWIP_FIONREAD_LINUXMODE==0 or this is a TCP socket */ ++ SYS_ARCH_GET(sock->conn->recv_avail, recv_avail); ++ if (recv_avail < 0) { ++ recv_avail = 0; ++ } + +- /* Check if there is data left from the last recv operation. /maq 041215 */ +- if (sock->lastdata.netbuf) { +- if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { +- recv_avail += sock->lastdata.pbuf->tot_len; +- } else { +- recv_avail += sock->lastdata.netbuf->p->tot_len; +- } +- } +- *((int *)argp) = recv_avail; ++ /* Check if there is data left from the last recv operation. /maq 041215 */ ++ if (sock->lastdata.netbuf) { ++ if (NETCONNTYPE_GROUP(netconn_type(sock->conn)) == NETCONN_TCP) { ++ recv_avail += sock->lastdata.pbuf->tot_len; ++ } else { ++ recv_avail += sock->lastdata.netbuf->p->tot_len; ++ } ++ } ++ *((int *)argp) = recv_avail; + +- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONREAD, %p) = %"U16_F"\n", s, argp, *((u16_t *)argp))); +- sock_set_errno(sock, 0); +- done_socket(sock); +- return 0; ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(FIONREAD, %p) = %"U16_F"\n", argp, *((u16_t *)argp))); ++ lwip_sock_unlock(sock); ++ return 0; + #else /* LWIP_SO_RCVBUF */ +- break; ++ lwip_sock_unlock(sock); ++ return ENOSYS; + #endif /* LWIP_SO_RCVBUF */ ++} + #endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ + +- case (long)FIONBIO: +- val = 0; +- if (argp && *(int *)argp) { +- val = 1; ++static u8_t lwip_ioctl_internal_FIONBIO(struct lwip_sock *sock, const void *argp) ++{ ++ u8_t val = 0; ++ SYS_ARCH_DECL_PROTECT(lev); ++ if (argp == NULL) { ++ return EINVAL; ++ } ++ if (*(int *)argp) { ++ val = 1; ++ } ++ SYS_ARCH_PROTECT(lev); ++ netconn_set_nonblocking(sock->conn, val); ++ SYS_ARCH_UNPROTECT(lev); ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(FIONBIO, %d)\n", val)); ++ return 0; ++} ++ ++static u8_t lwip_ioctl_impl(struct lwip_sock *sock, long cmd, void *argp) ++{ ++ u8_t err = 0; ++#if LWIP_NETIF_ETHTOOL ++ s32_t ret; ++#endif ++#if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_IF || LWIP_NETIF_ETHTOOL ++ struct ifreq *ifr = (struct ifreq *)argp; ++#endif ++#if LWIP_IOCTL_ROUTE ++ struct rtentry *rmten = (struct rtentry *)argp; ++#endif ++#if LWIP_IPV6_DUP_DETECT_ATTEMPTS || LWIP_IOCTL_IPV6DPCTD || LWIP_IOCTL_ROUTE || LWIP_IOCTL_IF ++ u8_t is_ipv6 = NETCONNTYPE_ISIPV6(sock->conn->type); ++#endif ++ ++ LWIP_ASSERT("no socket given", sock != NULL); ++ ++ switch (cmd) { ++#if PF_PACKET_SOCKET || LOSCFG_COMPONENTS_UPNP ++#if LWIP_IOCTL_IF ++ case SIOCGIFCONF: ++ /* Do not allow if socket is AF_INET6 */ ++ if (is_ipv6) { ++ err = EINVAL; ++ } else { ++ err = lwip_ioctl_internal_SIOCGIFCONF(ifr); //add: SIOCGIFCONF + } +- netconn_set_nonblocking(sock->conn, val); +- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, FIONBIO, %d)\n", s, val)); +- sock_set_errno(sock, 0); +- done_socket(sock); +- return 0; ++ break; ++ case SIOCGIFADDR: ++ if (is_ipv6) { ++ err = EINVAL; ++ } else { ++ err = lwip_ioctl_internal_SIOCGIFADDR(ifr); //add: SIOCGIFADDR ++ } ++ break; ++ case SIOCSIFFLAGS: ++ err = lwip_ioctl_internal_SIOCSIFFLAGS(ifr); //add: SIOCSIFFLAGS ++ break; ++ case SIOCGIFFLAGS: ++ err = lwip_ioctl_internal_SIOCGIFFLAGS(ifr); //add: SIOCSIFFLAGS ++ break; ++ case SIOCGIFNAME: ++ err = lwip_ioctl_internal_SIOCGIFNAME(ifr); //add: SIOCGIFNAME ++ break; ++ /* Need to support the get index through ioctl ++ * As of now the options is restricted to PF_PACKET scenario , so removed the compiler flag Begin ++ */ ++ case SIOCGIFINDEX: ++ err = lwip_ioctl_internal_SIOCGIFINDEX(ifr); //add: SIOCGIFINDEX ++ break; ++#endif /* LWIP_IOCTL_IF */ ++#else ++ (void)ifr; ++ (void)is_ipv6; ++#endif /* PF_PACKET_SOCKET */ ++#if LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE ++ case FIONREAD: ++ err = lwip_ioctl_internal_FIONREAD(sock, argp); ++ break; ++#endif /* LWIP_SO_RCVBUF || LWIP_FIONREAD_LINUXMODE */ + ++ case FIONBIO: ++ err = lwip_ioctl_internal_FIONBIO(sock, argp); ++ break; ++ /* -1 should return EINVAL */ ++ case -1: ++ err = EINVAL; ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl_impl(INVALID: 0x%lx)\n", cmd)); ++ break; + default: ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(UNIMPL: 0x%lx, %p)\n", cmd, argp)); ++ err = ENOSYS; /* not yet implemented */ + break; + } /* switch (cmd) */ +- LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, UNIMPL: 0x%lx, %p)\n", s, cmd, argp)); +- sock_set_errno(sock, ENOSYS); /* not yet implemented */ ++ ++ return err; ++} ++ ++int ++lwip_ioctl(int s, long cmd, void *argp) ++{ ++ u8_t err; ++ struct lwip_sock *sock = get_socket(s); ++ if (!sock) { ++ /* get_socket has updated errno */ ++ return -1; ++ } ++ if (argp == NULL) { ++ sock_set_errno(sock, EFAULT); ++ done_socket(sock); ++ return -1; ++ } ++ ++ LOCK_TCPIP_CORE(); ++ err = lwip_ioctl_impl(sock, cmd, argp); ++ UNLOCK_TCPIP_CORE(); ++ if (err != ERR_OK) { ++ LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_ioctl(%d, cmd: 0x%lx, %p)\n", s, cmd, argp)); ++ sock_set_errno(sock, err); ++ } + done_socket(sock); +- return -1; ++ return (err == 0) ? 0 : -1; + } + + /** A minimal implementation of fcntl. +@@ -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; +- + break; + 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 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 @@ + } + + static void +-recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) ++tftp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) + { + u16_t *sbuf = (u16_t *) p->payload; + int opcode; +@@ -416,7 +416,7 @@ + tftp_state.last_data = NULL; + tftp_state.upcb = pcb; + +- udp_recv(pcb, recv, NULL); ++ udp_recv(pcb, tftp_recv, NULL); + + 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 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) + { +- if (cp != NULL) { ++ if (cp != NULL && addr != NULL) { + const char *c; + for (c = cp; *c != 0; c++) { + if (*c == ':') { + /* contains a colon: IPv6 address */ +- if (addr) { +- IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); +- } ++ IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V6); + return ip6addr_aton(cp, ip_2_ip6(addr)); + } else if (*c == '.') { + /* contains a dot: IPv4 address */ +@@ -137,9 +147,7 @@ + } + } + /* call ip4addr_aton as fallback or if IPv4 was found */ +- if (addr) { +- IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); +- } ++ IP_SET_TYPE_VAL(*addr, IPADDR_TYPE_V4); + return ip4addr_aton(cp, ip_2_ip4(addr)); + } + return 0; +@@ -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 */ + ++struct netif* ++ip_route_pcb(const ip_addr_t *dest, const struct ip_pcb* pcb) ++{ ++ struct netif *netif = NULL; ++#if LWIP_SO_DONTROUTE ++ rt_scope_t scope = RT_SCOPE_UNIVERSAL; ++ ++ LWIP_ASSERT("Expecting ipaddr to be not NULL ", dest != NULL); ++ if (pcb != NULL) { ++ scope = ip_get_option(pcb, SOF_DONTROUTE) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSAL; ++ } ++#endif ++ ++ if ((pcb != NULL) && (pcb->netif_idx != NETIF_NO_INDEX)) { ++ return netif_find_by_ifindex(pcb->netif_idx); ++ } ++ ++ if ((pcb == NULL) || IP_IS_ANY_TYPE_VAL(pcb->local_ip)) { ++ /* Don't call ip_route() with IP_ANY_TYPE */ ++ netif = ip_route(IP46_ADDR_ANY(IP_GET_TYPE(dest)), dest); ++ } else { ++ netif = ip_route(&pcb->local_ip, dest); ++ } ++ ++ if (netif == NULL) { ++ return NULL; ++ } ++ ++#if LWIP_SO_DONTROUTE ++ if (netif->scope < scope) { ++ return NULL; ++ } ++#endif ++ return netif; ++} ++ ++#if LWIP_INET_ADDR_FUNC ++in_addr_t inet_addr(const char *cp) ++{ ++ LWIP_ERROR("inet_aton:cp is NULL", (cp != NULL), return (INADDR_NONE)); ++ return ipaddr_addr(cp); ++} ++#endif ++ ++#if LWIP_INET_ATON_FUNC ++int inet_aton(const char *cp, struct in_addr *inp) ++{ ++ LWIP_ERROR("inet_aton:cp is NULL", (cp != NULL), return 0); ++ return ip4addr_aton(cp, (ip4_addr_t *)inp); ++} ++#endif ++ ++#if LWIP_INET_NTOA_FUNC ++char* inet_ntoa(struct in_addr in) ++{ ++ return ip4addr_ntoa((const ip4_addr_t *)&in); ++} ++#endif ++ + #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 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) + { +- struct icmp6_hdr *icmp6hdr; ++ struct icmpv6_hdr *icmp6hdr; + struct pbuf *r; + const ip6_addr_t *reply_src; + + ICMP6_STATS_INC(icmp6.recv); + + /* Check that ICMPv6 header fits in payload */ +- if (p->len < sizeof(struct icmp6_hdr)) { ++ if (p->len < sizeof(struct icmpv6_hdr)) { + /* drop short packets */ + pbuf_free(p); + ICMP6_STATS_INC(icmp6.lenerr); +@@ -97,7 +97,7 @@ + return; + } + +- icmp6hdr = (struct icmp6_hdr *)p->payload; ++ icmp6hdr = (struct icmpv6_hdr *)p->payload; + + #if CHECKSUM_CHECK_ICMP6 + IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP6) { +@@ -386,10 +386,10 @@ + const ip6_addr_t *reply_src, const ip6_addr_t *reply_dest, struct netif *netif) + { + struct pbuf *q; +- struct icmp6_hdr *icmp6hdr; ++ struct icmpv6_hdr *icmp6hdr; + + /* ICMPv6 header + IPv6 header + data */ +- q = pbuf_alloc(PBUF_IP, sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, ++ q = pbuf_alloc(PBUF_IP, sizeof(struct icmpv6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE, + PBUF_RAM); + if (q == NULL) { + LWIP_DEBUGF(ICMP_DEBUG, ("icmp_time_exceeded: failed to allocate pbuf for ICMPv6 packet.\n")); +@@ -397,15 +397,15 @@ + return; + } + LWIP_ASSERT("check that first pbuf can hold icmp 6message", +- (q->len >= (sizeof(struct icmp6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); ++ (q->len >= (sizeof(struct icmpv6_hdr) + IP6_HLEN + LWIP_ICMP6_DATASIZE))); + +- icmp6hdr = (struct icmp6_hdr *)q->payload; ++ icmp6hdr = (struct icmpv6_hdr *)q->payload; + icmp6hdr->type = type; + icmp6hdr->code = code; + icmp6hdr->data = lwip_htonl(data); + + /* copy fields from original packet */ +- SMEMCPY((u8_t *)q->payload + sizeof(struct icmp6_hdr), (u8_t *)p->payload, ++ SMEMCPY((u8_t *)q->payload + sizeof(struct icmpv6_hdr), (u8_t *)p->payload, + IP6_HLEN + LWIP_ICMP6_DATASIZE); + + /* 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 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 */ + { +- struct icmp6_hdr *icmp6hdr; /* Packet too big message */ ++ struct icmpv6_hdr *icmp6hdr; /* Packet too big message */ + struct ip6_hdr *ip6hdr; /* IPv6 header of the packet which caused the error */ + u32_t pmtu; + ip6_addr_t destination_address; + + /* Check that ICMPv6 header + IPv6 header fit in payload */ +- if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { ++ if (p->len < (sizeof(struct icmpv6_hdr) + IP6_HLEN)) { + /* drop short packets */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); +@@ -908,8 +908,8 @@ + return; + } + +- icmp6hdr = (struct icmp6_hdr *)p->payload; +- ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); ++ icmp6hdr = (struct icmpv6_hdr *)p->payload; ++ ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmpv6_hdr)); + + /* 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 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" + #endif ++#include "lwip/tcpip.h" ++ + + #if LWIP_NETIF_STATUS_CALLBACK + #define NETIF_STATUS_CALLBACK(n) do{ if (n->status_callback) { (n->status_callback)(n); }}while(0) +@@ -229,6 +231,8 @@ + return ip_input(p, inp); + } + ++static u8_t netif_alloc_ifindex(void); ++ + /** + * @ingroup netif + * Add a network interface to the list of lwIP netifs. +@@ -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 */ + ++ /* ++ * Need to support the get index for all families ++ * removed PF_PACKET_SOCKET flag , as this flags restricts the usage to only PF_FAMILY ++ */ ++ netif->ifindex = netif_alloc_ifindex(); ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif: netif->ifindex=%d", netif->ifindex)); ++ if ((netif->ifindex < LWIP_NETIF_IFINDEX_START) || (netif->ifindex > LWIP_NETIF_IFINDEX_MAX)) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif: interface index alloc fail")); ++ return NULL; ++ } ++ + #if !LWIP_SINGLE_NETIF + /* Assign a unique netif number in the range [0..254], so that (num+1) can + serve as an interface index that fits in a u8_t. + We assume that the new netif has not yet been added to the list here. + This algorithm is O(n^2), but that should be OK for lwIP. + */ +- { +- struct netif *netif2; +- int num_netifs; +- do { +- if (netif->num == 255) { +- netif->num = 0; +- } +- num_netifs = 0; +- for (netif2 = netif_list; netif2 != NULL; netif2 = netif2->next) { +- LWIP_ASSERT("netif already added", netif2 != netif); +- num_netifs++; +- LWIP_ASSERT("too many netifs, max. supported number is 255", num_netifs <= 255); +- if (netif2->num == netif->num) { +- netif->num++; +- break; +- } +- } +- } while (netif2 != NULL); +- } +- if (netif->num == 254) { +- netif_num = 0; +- } else { +- netif_num = (u8_t)(netif->num + 1); +- } + + /* add this netif to the list */ + netif->next = netif_list; +@@ -421,8 +428,8 @@ + } + #endif /* LWIP_IGMP */ + +- LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %c%c IP", +- netif->name[0], netif->name[1])); ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif: added interface %s IP", ++ netif->name)); + #if LWIP_IPV4 + LWIP_DEBUGF(NETIF_DEBUG, (" addr ")); + ip4_addr_debug_print(NETIF_DEBUG, ipaddr); +@@ -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 + */ +-void ++err_t + netif_set_default(struct netif *netif) + { + LWIP_ASSERT_CORE_LOCKED(); +@@ -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] : '\'')); ++ return ERR_OK; + } + + /** +@@ -1206,6 +1279,11 @@ + struct netif *stats_if = netif; + #endif /* LWIP_HAVE_LOOPIF */ + #endif /* MIB2_STATS */ ++#if PF_PACKET_SOCKET ++ struct raw_pcb *pcb; ++ int match = 0; ++#endif /* PF_PACKET_SOCKET */ ++ + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_ASSERT("netif_poll: invalid netif", netif != NULL); +@@ -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); ++ ++#if PF_PACKET_SOCKET ++ for (pcb = get_packet_raw_pcbs(); pcb != NULL; pcb = pcb->next) { ++ if (((pcb->proto.eth_proto == htons(ETHTYPE_ALL)) || (pcb->proto.eth_proto == htons(ETHTYPE_IP))) && ++ ((!pcb->netifindex) || (pcb->netifindex == netif->ifindex))) { ++ match = 1; ++ break; ++ } ++ } ++ ++ /* always succeed because the alloc layer of loopback pbuf was PBUF_LINK */ ++ if (match && pbuf_header(in, PBUF_LINK_HLEN) == 0) { ++ struct eth_hdr *ethhdr; ++ /* add ethernet header */ ++ ethhdr = (struct eth_hdr *)(in->payload); ++ /* smac and dmac set to all zeros for loopback IP packet */ ++ (void)memset_s(ethhdr, sizeof(struct eth_hdr), 0, sizeof(struct eth_hdr)); ++ ethhdr->type = htons(ETHTYPE_IP); /* eth protocol, should be ETH_P_IP(0x800) */ ++ in->flags = (u16_t)(in->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_OUTGOING)); ++ in->flags |= PBUF_FLAG_HOST; ++ raw_packet_input(in, netif, NULL); ++ (void)pbuf_header(in, -PBUF_LINK_HLEN); ++ } ++#endif /* PF_PACKET_SOCKET */ ++ + /* loopback packets are always IP packets! */ + if (ip_input(in, netif) != ERR_OK) { + pbuf_free(in); +@@ -1700,29 +1803,68 @@ + struct netif * + netif_find(const char *name) + { +- struct netif *netif; +- u8_t num; +- +- LWIP_ASSERT_CORE_LOCKED(); +- +- if (name == NULL) { +- return NULL; +- } ++ struct netif *netif = NULL; ++ char candidate_name[NETIF_NAMESIZE]; ++ int ret; + +- num = (u8_t)atoi(&name[2]); ++ LWIP_ERROR("netif_find : invalid value.", (name != NULL), return NULL); + + NETIF_FOREACH(netif) { +- if (num == netif->num && +- name[0] == netif->name[0] && +- name[1] == netif->name[1]) { +- LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %c%c\n", name[0], name[1])); ++ if (strncmp(name, netif->name, NETIF_NAMESIZE) == 0) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %s\n", name)); + return netif; + } ++ ++ if (netif->link_layer_type != LOOPBACK_IF) { ++ ret = snprintf_s(candidate_name, NETIF_NAMESIZE, (NETIF_NAMESIZE - 1), "%s%"U8_F, netif->name, netif->num); ++ if ((ret <= 0) || (ret >= NETIF_NAMESIZE)) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: name '%s'is too long\n", netif->name)); ++ continue; ++ } ++ if (strncmp(name, candidate_name, NETIF_NAMESIZE) == 0) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: found %s\n", name)); ++ return netif; ++ } ++ } + } +- LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %c%c\n", name[0], name[1])); ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find: didn't find %s\n", name)); + return NULL; + } + ++/* ++ * Change mtu setting for a network interface ++ * ++ * @param netif the network interface to change ++ * @param netif_mtu the new MTU for the interface ++ */ ++ ++err_t ++netif_set_mtu_api(struct netif *netif, u16_t netif_mtu) ++{ ++ /* As per RFC 791, "Every internet module must be able to forward a datagram of 68 ++ * octets without further fragmentation. This is because an internet header ++ * may be up to 60 octets, and the minimum fragment is 8 octets." */ ++ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif != NULL), return ERR_VAL); ++ ++#if LWIP_IPV6 ++ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif_mtu >= NETIF_MTU_MIN) && (netif_mtu <= IP_FRAG_MAX_MTU), ++ return ERR_ARG); ++#else ++ LWIP_ERROR("netif_set_mtu: invalid arguments", (netif_mtu >= IP_FRAG_MIN_MTU) && (netif_mtu <= IP_FRAG_MAX_MTU), ++ return ERR_ARG); ++#endif ++ ++ netif->mtu = netif_mtu; ++#if LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES ++ netif->mtu6 = netif_mtu; ++#endif /* LWIP_IPV6 && LWIP_ND6_ALLOW_RA_UPDATES */ ++ ++ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif: MTU of interface %s%"U16_F" is changed to %d\n", ++ netif->name, netif->num, netif->mtu)); ++ ++ return ERR_OK; ++} ++ + #if LWIP_NETIF_EXT_STATUS_CALLBACK + /** + * @ingroup netif +@@ -1793,3 +1935,213 @@ + } + } + #endif /* LWIP_NETIF_EXT_STATUS_CALLBACK */ ++ ++struct netif * ++netif_find_by_ipaddr(const ip_addr_t *ipaddr) ++{ ++ LWIP_ERROR("netif_find_by_ipaddr : invalid arguments", (ipaddr != NULL), return NULL); ++#if LWIP_IPV4 ++ if (IP_IS_V4(ipaddr)) { ++ return netif_find_by_ip4addr(ipaddr); ++ } ++#endif ++ ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ipaddr: didn't find\n")); ++ return NULL; ++} ++ ++void ++netif_get_hwaddr(const struct netif *netif, unsigned char *hw_addr, int hw_len) ++{ ++ int i; ++ LWIP_ERROR("netif_get_hwaddr : invalid arguments", (netif != NULL), return); ++ ++ LWIP_ERROR("netif_get_hwaddr : invalid arguments", (hw_addr != NULL), return); ++ ++ LWIP_ERROR("netif_get_hwaddr: invalid arguments", ++ ((unsigned int)hw_len == NETIF_MAX_HWADDR_LEN), return); ++ ++ for (i = 0; i < hw_len; i++) { ++ hw_addr[i] = netif->hwaddr[i]; ++ } ++} ++ ++/* ++ * Change the hardware address for a network interface ++ * ++ * NOTE:Application should call set_link_down before calling ++ * the netif_set_hwaddr and then set_link_up, in order ++ * to ensure that all IPs are announced after changing ++ * hw address ++ * ++ * @param netif the network interface to change ++ * @param hw_addr the new hardware address ++ * @param hw_len the length of new hardware address, ++ * ++ */ ++err_t ++netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw_len) ++{ ++ LWIP_ERROR("netif_set_hwaddr : invalid arguments", (netif != NULL), return ERR_VAL); ++ ++ LWIP_ERROR("netif_set_hwaddr : invalid arguments", (hw_addr != NULL), return ERR_VAL); ++ ++ LWIP_ERROR("netif_set_hwaddr: invalid arguments", ++ ((unsigned int)hw_len == NETIF_MAX_HWADDR_LEN), return ERR_VAL); ++ ++ if (netif->drv_set_hwaddr == NULL) { ++ return ERR_OPNOTSUPP; ++ } ++ ++ if (netif->drv_set_hwaddr(netif, (u8_t *)hw_addr, hw_len) != ERR_OK) { ++ return ERR_VAL; ++ } ++ ++ if (memcpy_s(netif->hwaddr, NETIF_MAX_HWADDR_LEN, hw_addr, (u32_t)hw_len) != EOK) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_set_hwaddr: memcpy_s error\n")); ++ return ERR_VAL; ++ } ++ ++ LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ++ ("netif: HW address of interface %s%"U16_F" set to %02X:%02X:%02X:%02X:%02X:%02X\n", ++ netif->name, netif->num, ++ netif->hwaddr[0], netif->hwaddr[1], netif->hwaddr[2], ++ netif->hwaddr[3], netif->hwaddr[4], netif->hwaddr[5])); ++ ++ return ERR_OK; ++} ++ ++#if LWIP_IPV4 ++/* ++ * Find a network interface by searching for its ipaddress ++ * ++ * @param ipaddr IP_add of the netif ++ * @return netif if the its found ++ * NULL if there is no netif with ipaddr ++ */ ++struct netif * ++netif_find_by_ip4addr(const ip_addr_t *ipaddr) ++{ ++ struct netif *netif = NULL; ++ ++ LWIP_ASSERT("Expecting ipaddr to be not NULL ", ipaddr != NULL); ++ ++ for (netif = netif_list; netif != NULL; netif = netif->next) { ++ if (ip_addr_cmp(&(netif->ip_addr), ipaddr)) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ipaddr: found\n")); ++ return netif; ++ } ++ } ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_using_ip4addr: didn't find\n")); ++ return NULL; ++} ++ ++s8_t netif_find_dst_ipaddr(const ip_addr_t *ipaddr, ip_addr_t **dst_addr) ++{ ++ struct netif *netif = NULL; ++ ip_addr_t *pdst_addr = NULL; ++ ++ pdst_addr = *dst_addr; ++ netif = netif_find_by_ipaddr(ipaddr); ++ if (netif == NULL) { ++ return -1; ++ } ++ if ((pdst_addr != NULL) && (!ip_addr_netcmp(pdst_addr, &(netif->ip_addr), ip_2_ip4(&netif->netmask))) && ++ !ip_addr_islinklocal(pdst_addr)) { ++ if (!ip_addr_isany(&netif->gw)) { ++ *dst_addr = &(netif->gw); ++ } ++ } ++ ++ return 0; ++} ++#endif /* LWIP_IPV4 */ ++ ++ ++ ++#if LWIP_DHCP ++/* ++ * Close DHCP and set static network. ++ * ++ * @param netif a pre-allocated netif structure ++ * ++ * @return ERR_OK, or ERR_VAL if failed. ++ */ ++err_t ++netif_dhcp_off(struct netif *netif) ++{ ++ ip_addr_t old_ipaddr; ++ ip_addr_t old_netmask; ++ ip_addr_t old_gateway; ++ ++ if (netif == NULL) { ++ return ERR_VAL; ++ } ++ old_ipaddr = netif->ip_addr; ++ old_netmask = netif->netmask; ++ old_gateway = netif->gw; ++ ++ if (netif_dhcp_data(netif)) { ++ (void)dhcp_release(netif); ++ dhcp_stop(netif); ++ dhcp_cleanup(netif); ++ LWIP_DEBUGF(NETIF_DEBUG, ("DHCP is close;set static IP\n")); ++ } ++ ++ ip_addr_set_val(netif->ip_addr, old_ipaddr); ++ ip_addr_set_val(netif->netmask, old_netmask); ++ ip_addr_set_val(netif->gw, old_gateway); ++ (void)netif_set_up(netif); ++ ++ return ERR_OK; ++} ++#endif /* LWIP_DHCP */ ++ ++u8_t netif_ipaddr_isbrdcast(const ip_addr_t *ipaddr) ++{ ++ struct netif *netif = NULL; ++ ++ for (netif = netif_list; netif != NULL; netif = netif->next) { ++ if (netif_is_up(netif) && ip_addr_isbroadcast(ipaddr, netif)) { ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++struct netif * ++netif_find_by_ifindex(u8_t ifindex) ++{ ++ struct netif *netif = NULL; ++ ++ if (ifindex < LWIP_NETIF_IFINDEX_START) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: Invalid ifindex(%u) \n", ifindex)); ++ return netif; ++ } ++ ++ for (netif = netif_list; netif != NULL; netif = netif->next) { ++ if (netif->ifindex == ifindex) { ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: found\n")); ++ return netif; ++ } ++ } ++ ++ LWIP_DEBUGF(NETIF_DEBUG, ("netif_find_by_ifindex: didn't find\n")); ++ return NULL; ++} ++ ++/* Need to support the get index for all families ++removed PF_PACKET_SOCKET flag , as this flags restricts the usage to only PF_FAMILY Begin */ ++static u8_t ++netif_alloc_ifindex(void) ++{ ++ u8_t tmp_index; ++ for (tmp_index = LWIP_NETIF_IFINDEX_START; tmp_index <= LWIP_NETIF_IFINDEX_MAX; tmp_index++) { ++ if (netif_get_by_index(tmp_index) == NULL) { ++ break; ++ } ++ } ++ ++ return tmp_index; ++} +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 LWIP_NIP /* don't build if not configured for use in lwipopts.h */ ++ ++#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) ++{ ++ 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; ++} ++ ++/** ++ * 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) ++{ ++ 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; ++ } ++ ++ /* 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; ++} ++ ++/** 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); ++} ++ ++/** ++ * 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); ++ netif = ip_route_pcb(ipaddr, (struct ip_pcb*)pcb); + } + } + +@@ -387,7 +415,7 @@ + return ERR_RTE; + } + +- if (ip_addr_isany(&pcb->local_ip) || ip_addr_ismulticast(&pcb->local_ip)) { ++ if (ip_addr_isany(&pcb->local_ip) || ip_get_option(pcb, SOF_BINDNONUNICAST)) { + /* use outgoing network interface IP address as source address */ + src_ip = ip_netif_get_local_ip(netif, ipaddr); + #if LWIP_IPV6 +@@ -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); +- err = ip_output_if(q, src_ip, dst_ip, ttl, pcb->tos, pcb->protocol, netif); ++ err = ip_output_if(q, src_ip, dst_ip, ttl, pcb->tos, pcb->raw_proto, netif); + NETIF_RESET_HINTS(netif); + + /* did we chain a header earlier? */ +@@ -604,7 +634,12 @@ + if (pcb != NULL) { + /* initialize PCB to all zeroes */ + memset(pcb, 0, sizeof(struct raw_pcb)); ++#if PF_PACKET_SOCKET ++ pcb->proto.protocol = proto; ++#else + pcb->protocol = proto; ++#endif ++ + pcb->ttl = RAW_TTL; + #if LWIP_MULTICAST_TX_OPTIONS + raw_set_multicast_ttl(pcb, RAW_TTL); +@@ -668,4 +703,227 @@ + } + } + ++#if PF_PACKET_SOCKET ++void raw_packet_input(struct pbuf *p, const struct netif *inp, const struct raw_pcb *from) ++{ ++ struct raw_pcb *pcb = NULL; ++ struct eth_hdr *ethhdr = NULL; ++ u16_t proto; ++ ++ LWIP_UNUSED_ARG(inp); ++ ++ ethhdr = (struct eth_hdr *)p->payload; ++ proto = ethhdr->type; ++ ++ g_lwip_current_eth_hdr = ethhdr; ++ g_lwip_current_netif = inp; ++ ++ pcb = g_packet_raw_pcbs; ++ /* 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->proto.eth_proto == htons(ETHTYPE_ALL)) || ((p != NULL) && !(p->flags & PBUF_FLAG_OUTGOING) && ++ pcb->proto.eth_proto == proto)) && ++ ((!pcb->netifindex) || (pcb->netifindex == inp->ifindex)) && (pcb != from)) { ++ /* receive callback function available? */ ++ if (pcb->recv != NULL) { ++ /* the receive callback function did not eat the packet? */ ++ if (pcb->recv(pcb->recv_arg, pcb, p, NULL) != 0) { ++ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_input: packets recved failed \n")); ++ } ++ } ++ /* no receive callback function was set for this raw PCB */ ++ } ++ ++ pcb = pcb->next; ++ } ++ ++ g_lwip_current_eth_hdr = NULL; ++ return; ++} ++ ++err_t ++raw_packet_bind(struct raw_pcb *pcb, u8_t ifindex, u16_t proto) ++{ ++ struct netif *loc_netif = NULL; ++ ++ if (ifindex != 0) { ++ for (loc_netif = netif_list; loc_netif != NULL; loc_netif = loc_netif->next) { ++ if (ifindex == loc_netif->ifindex) { ++ break; ++ } ++ } ++ ++ /* Return if no matching netifs to bind */ ++ if (loc_netif == NULL) { ++ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_bind: No matching netif found for ifindex(%u)\n", ifindex)); ++ return ERR_NODEV; ++ } ++ } else { ++ return ERR_NODEV; ++ } ++ ++#if DRIVER_STATUS_CHECK ++ if (!netif_is_up(loc_netif) || !netif_is_ready(loc_netif)) ++#else ++ if (!netif_is_up(loc_netif)) ++#endif ++ { ++ LWIP_DEBUGF(RAW_DEBUG, ("raw_packet_bind: bind failed as netif (index %u) was down\n", ifindex)); ++ return ERR_NETDOWN; ++ } ++ ++ pcb->netifindex = ifindex; ++ pcb->proto.eth_proto = proto; ++ ++ return ERR_OK; ++} ++ ++/* ++ * Send the raw IP packet through the given netif driver. Note that actually you cannot ++ * modify the link layer header here. Packet need to be sent to driver as it is through the ++ * given netif ++ * @param pcb the raw pcb which to send ++ * @param p the ethernet packet to send ++ * @param ifindex the Interface index of the netif through which packet needs to be sent ++ */ ++err_t ++raw_packet_sendto(const struct raw_pcb *pcb, struct pbuf *p, u8_t ifindex) ++{ ++ struct netif *netif = NULL; ++ u8_t netifindex; ++ LWIP_UNUSED_ARG(pcb); ++ ++ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_packet_sendto: ifindex=%d\n", ifindex)); ++ LWIP_ASSERT("p != NULL", p != NULL); ++ ++ netifindex = ifindex; ++ ++ if (ifindex == 0) { ++ if (pcb->netifindex != 0) { ++ netifindex = pcb->netifindex; ++ } else { ++ return ERR_NODEVADDR; ++ } ++ } ++ ++ /* Find the netif corresponding to the interface index */ ++ netif = netif_find_by_ifindex(netifindex); ++ if (netif == NULL) { ++ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("netif not found for given ifindex (%u)\n", ifindex)); ++ return ERR_NODEVADDR; ++ } ++ ++#if DRIVER_STATUS_CHECK ++ if ((!netif_is_up(netif)) || (!netif_is_ready(netif))) ++#else ++ if ((!netif_is_up(netif))) ++#endif ++ { ++ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("netif was down for given ifindex (%u)\n", ifindex)); ++ return ERR_NETDOWN; ++ } ++ ++ if ((p->tot_len - (SIZEOF_ETH_HDR - ETH_PAD_SIZE)) > netif->mtu) { ++ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("Message too long (%u)\n", p->tot_len)); ++ return ERR_MSGSIZE; ++ } ++ ++ if (pbuf_header(p, ETH_PAD_SIZE) == 0) { ++ p->flags = (u16_t)(p->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_HOST)); ++ p->flags |= PBUF_FLAG_OUTGOING; ++ raw_packet_input(p, netif, pcb); ++ (void)pbuf_header(p, -ETH_PAD_SIZE); ++ } ++ ++ /* For RAW packets of PF_PACKET family, do not modify the packets as it is ++ already supposed to contain the link layer header. So send directly to the driver */ ++ LINK_STATS_INC(link.xmit); ++ return ERR_OK; ++} ++ ++/* ++ * Create a RAW PCB for Packet family. ++ * ++ * @return The RAW PCB which was created. NULL if the PCB data structure ++ * could not be allocated. ++ * ++ * @param proto the protocol number of the IPs payload (e.g. IP_PROTO_ICMP) ++ * ++ * @see raw_remove() ++ */ ++struct raw_pcb * ++raw_packet_new(u16_t proto) ++{ ++ struct raw_pcb *pcb = NULL; ++ ++ LWIP_DEBUGF(RAW_DEBUG | LWIP_DBG_TRACE, ("raw_packet_new\n")); ++ ++ pcb = (struct raw_pcb *)memp_malloc(MEMP_RAW_PCB); ++ /* could allocate RAW PCB? */ ++ if (pcb != NULL) { ++ /* initialize PCB to all zeroes */ ++ (void)memset(pcb, 0, sizeof(struct raw_pcb)); ++ pcb->proto.eth_proto = proto; ++ pcb->ttl = RAW_TTL; ++ pcb->next = g_packet_raw_pcbs; ++ g_packet_raw_pcbs = pcb; ++ pcb->all_next = g_all_packet_raw_pcbs; ++ g_all_packet_raw_pcbs = pcb; ++ } ++ return pcb; ++} ++ ++/* ++ * Remove an RAW PCB of packet family type ++ * ++ * @param pcb RAW PCB to be removed. The PCB is removed from the list of ++ * RAW PCB's and the data structure is freed from memory. ++ * ++ * @see raw_packet_new() ++ */ ++void ++raw_packet_remove(struct raw_pcb *pcb) ++{ ++ struct raw_pcb *pcb2 = NULL; ++ ++ /* NULL check */ ++ if (pcb == NULL) { ++ return; ++ } ++ ++ /* pcb to be removed is first in all_pkt list? */ ++ if (g_all_packet_raw_pcbs == pcb) { ++ /* make list start at 2nd pcb */ ++ g_all_packet_raw_pcbs = g_all_packet_raw_pcbs->all_next; ++ /* pcb not 1st in list */ ++ } else { ++ for (pcb2 = g_all_packet_raw_pcbs; pcb2 != NULL; pcb2 = pcb2->all_next) { ++ /* find pcb in g_all_packet_raw_pcbs list */ ++ if (pcb2->all_next == pcb) { ++ /* remove pcb from list */ ++ pcb2->all_next = pcb->all_next; ++ } ++ } ++ } ++ ++ /* pcb to be removed is first in list? */ ++ if (g_packet_raw_pcbs == pcb) { ++ /* make list start at 2nd pcb */ ++ g_packet_raw_pcbs = g_packet_raw_pcbs->next; ++ /* pcb not 1st in list */ ++ } else { ++ for (pcb2 = g_packet_raw_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { ++ /* find pcb in raw_pcbs list */ ++ if (pcb2->next == pcb) { ++ /* remove pcb from list */ ++ pcb2->next = pcb->next; ++ } ++ } ++ } ++ ++ memp_free(MEMP_RAW_PCB, pcb); ++} ++#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 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" + #include "lwip/err.h" ++#if LWIP_LITEOS_COMPAT ++#include "lwip/netif.h" ++#endif + + #ifdef __cplusplus + extern "C" { +@@ -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 +167,10 @@ + NETCONN_WRITE, + NETCONN_LISTEN, + NETCONN_CONNECT, +- NETCONN_CLOSE ++ NETCONN_CLOSE, ++#if LWIP_LITEOS_COMPAT ++ NETCONN_CLOSED, ++#endif /* LWIP_LITEOS_COMPAT */ + }; + + /** Used to inform the callback function about changes +@@ -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; ++#if PF_PACKET_SOCKET ++ struct raw_pcb *packet_raw; ++#endif /* PF_PACKET_SOCKET */ + } pcb; + /** the last asynchronous unreported error this netconn had */ +- err_t pending_err; ++ err_t last_err; + #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 +308,13 @@ + #endif /* LWIP_TCP */ + /** A callback function that is informed about events for this netconn */ + netconn_callback callback; ++#if LWIP_TCP ++ struct pbuf *refused_data; ++ ip_addr_t remote_ip; ++ u16_t remote_port; ++ /** record pending error state after recving RST */ ++ u16_t pending_err; ++#endif + }; + + /** This vector type is passed to @ref netconn_write_vectors_partly to send +@@ -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) +-struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, ++struct netconn *netconn_new_with_proto_and_callback(enum netconn_type t, u16_t proto, + netconn_callback callback); + err_t netconn_prepare_delete(struct netconn *conn); + err_t netconn_delete(struct netconn *conn); + /** Get the type of a netconn (as enum netconn_type). */ +-#define netconn_type(conn) (conn->type) ++#define netconn_type(conn) ((u32_t)(conn->type)) + + err_t netconn_getaddr(struct netconn *conn, ip_addr_t *addr, + u16_t *port, u8_t local); ++#if LWIP_LITEOS_COMPAT ++#if PF_PACKET_SOCKET ++struct pf_packet_sockaddr_ll { ++ u16_t sll_protocol; ++ u16_t sll_hatype; ++ u8_t if_idx; ++ u8_t sll_halen; ++ u8_t sll_addr[NETIF_MAX_HWADDR_LEN]; ++}; ++err_t netconn_get_sockaddr_pf_packet(struct netconn *conn, struct pf_packet_sockaddr_ll *ll, u8_t local); ++#endif /* PF_PACKET_SOCKET */ ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup netconn_common */ + #define netconn_peer(c,i,p) netconn_getaddr(c,i,p,0) + /** @ingroup netconn_common */ + #define netconn_addr(c,i,p) netconn_getaddr(c,i,p,1) + ++#if PF_PACKET_SOCKET ++err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port, u8_t ifindex); ++#else + err_t netconn_bind(struct netconn *conn, const ip_addr_t *addr, u16_t port); ++#endif /* PF_PACKET_SOCKET */ ++ + err_t netconn_bind_if(struct netconn *conn, u8_t if_idx); + 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 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 + +-#ifndef LITTLE_ENDIAN +-#define LITTLE_ENDIAN 1234 +-#endif +- +-#ifndef BIG_ENDIAN +-#define BIG_ENDIAN 4321 +-#endif +- ++#include + #include "arch/cc.h" + + /** +@@ -149,6 +142,11 @@ + #ifndef X8_F + #define X8_F "02" PRIx8 + #endif ++#if LWIP_LITEOS_COMPAT ++#ifndef U8_F ++#define U8_F PRIu8 ++#endif ++#endif /* LWIP_LITEOS_COMPAT */ + #ifndef U16_F + #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 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, + /** Illegal argument. */ +- ERR_ARG = -16 ++ ERR_ARG = -16, ++#ifdef LWIP_LITEOS_COMPAT ++/** Message too long. */ ++ ERR_MSGSIZE = -17, ++/** No such device. */ ++ ERR_NODEV = -18, ++/** No such device or address. */ ++ ERR_NODEVADDR = -19, ++/** socket is not connection-mode & no peer address is set */ ++ ERR_NODEST = -20, ++/** Network is down */ ++ ERR_NETDOWN = -21, ++/** Address family not supported by protocol */ ++ ERR_AFNOSUPP = -22, ++/** No such address */ ++ ERR_NOADDR = -23, ++/** Operation not supported on transport endpoint */ ++ ERR_OPNOTSUPP = -24, ++ ERR_NETUNREACH = -25, ++/** connection request timedout */ ++ ERR_CONNECTIMEOUT = -26, ++/** Error pipe */ ++ ERR_PIPE = -27, ++/** AF not supported */ ++ ERR_AFNOSUPPORT = -28, ++/** Protocol not available */ ++ ERR_NOPROTOOPT = -29, ++ ERR_ACCESS = -30, ++ ERR_NFILE = -31, ++ ERR_RESERVE3 = -32, ++ ERR_RESERVE4 = -33, ++ ERR_RESERVE5 = -34, ++ ERR_RESERVE6 = -35, ++ ERR_FATAL_START = -36, ++ ERR_CONNREFUSED = -41, ++/** FIN mbox post fail. */ ++ ERR_FIN_POST = -42, ++#endif /* LWIP_LITEOS_COMPAT */ + } err_enum_t; + ++#ifdef LWIP_LITEOS_COMPAT ++#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 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. */ ++ ++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 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 + ++#if !LWIP_LITEOS_COMPAT + #define IF_NAMESIZE NETIF_NAMESIZE + + char * lwip_if_indextoname(unsigned int ifindex, char *ifname); + unsigned int lwip_if_nametoindex(const char *ifname); ++#endif + + #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 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 + ++#if !LWIP_LITEOS_COMPAT + /* 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 +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)}}} +-/** This variable is initialized by the system to contain the wildcard IPv6 address. */ +-extern const struct in6_addr in6addr_any; + + /* Definitions of the bits in an (IPv4) Internet address integer. + +@@ -119,7 +119,12 @@ + #define IN_BADCLASS(a) IP_BADCLASS(a) + + #define IN_LOOPBACKNET IP_LOOPBACKNET ++#endif /* !LWIP_LITEOS_COMPAT */ + ++/** This variable is initialized by the system to contain the wildcard IPv6 address. */ ++extern const struct in6_addr in6addr_any; ++/** Added new structure for ipv6 loopback as per section 3.9 of rfc 2553/3493 */ ++extern const struct in6_addr in6addr_loopback; + + #ifndef INET_ADDRSTRLEN + #define INET_ADDRSTRLEN IP4ADDR_STRLEN_MAX +@@ -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 */ +-#define inet_addr(cp) ipaddr_addr(cp) ++#if LWIP_INET_ADDR_FUNC ++unsigned int inet_addr(const char *cp); ++#else ++#define inet_addr(cp) ipaddr_addr(cp) ++#endif ++ ++#if LWIP_INET_ATON_FUNC ++int inet_aton(const char *cp, struct in_addr *addr); ++#else + #define inet_aton(cp, addr) ip4addr_aton(cp, (ip4_addr_t*)addr) ++#endif ++ ++#if LWIP_INET_NTOA_FUNC ++char *inet_ntoa (struct in_addr in); ++#else + #define inet_ntoa(addr) ip4addr_ntoa((const ip4_addr_t*)&(addr)) ++#endif ++ + #define inet_ntoa_r(addr, buf, buflen) ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) + + #endif /* LWIP_IPV4 */ + + #if LWIP_IPV6 ++/* current the struct ip6_addr for define LWIP_IPV6_SCOPES 0 */ ++#if LWIP_LITEOS_COMPAT ++#define inet6_addr_from_ip6addr(target_in6addr, source_ip6addr) { \ ++ memcpy((target_in6addr)->s6_addr, (source_ip6addr)->addr, sizeof(struct ip6_addr)); } ++#define inet6_addr_to_ip6addr(target_ip6addr, source_in6addr) { \ ++ memcpy((target_ip6addr)->addr, (source_in6addr)->s6_addr, sizeof(struct ip6_addr)); \ ++ ip6_addr_clear_zone(target_ip6addr);} ++#else + #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 +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);} +- ++#endif /* LWIP_LITEOS_COMPAT */ + /* 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 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{ \ +- ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); ip_clear_no4(dest); }}while(0) ++ ip4_addr_set(ip_2_ip4(dest), ip_2_ip4(src)); ip_clear_no4(dest); }} while (0) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_set_val(dest, src) do { IP_SET_TYPE_VAL(dest, IP_GET_TYPE(&(src))); if(IP_IS_V6_VAL(src)) { \ ++ ip6_addr_set(ip_2_ip6(&(dest)), ip_2_ip6(&(src))); } else { \ ++ ip4_addr_set(ip_2_ip4(&(dest)), ip_2_ip4(&(src))); }} while (0) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup ipaddr */ + #define ip_addr_set_ipaddr(dest, src) ip_addr_set(dest, src) + /** @ingroup ipaddr */ + #define ip_addr_set_zero(ipaddr) do{ \ +- ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); }while(0) ++ ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, 0); } while (0) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_set_zero_val(ipaddr) do{ \ ++ ip6_addr_set_zero(ip_2_ip6(&(ipaddr))); IP_SET_TYPE_VAL(ipaddr, 0); } while (0) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup ip5addr */ + #define ip_addr_set_zero_ip4(ipaddr) do{ \ + ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V4); }while(0) + /** @ingroup ip6addr */ + #define ip_addr_set_zero_ip6(ipaddr) do{ \ +- ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); }while(0) ++ ip6_addr_set_zero(ip_2_ip6(ipaddr)); IP_SET_TYPE(ipaddr, IPADDR_TYPE_V6); } while (0) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_set_zero_ip6_val(ipaddr) do{ \ ++ ip6_addr_set_zero(ip_2_ip6(&(ipaddr))); IP_SET_TYPE_VAL(ipaddr, IPADDR_TYPE_V6); } while (0) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @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 +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)) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_netcmp_val(addr1, addr2, mask) ((IP_IS_V6_VAL((addr1)) && IP_IS_V6_VAL((addr2))) ? \ ++ 0 : \ ++ ip4_addr_netcmp(ip_2_ip4(&addr1), ip_2_ip4(&addr2), mask)) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @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 +282,50 @@ + #define ip_addr_isbroadcast(ipaddr, netif) ((IP_IS_V6(ipaddr)) ? \ + 0 : \ + ip4_addr_isbroadcast(ip_2_ip4(ipaddr), netif)) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_isbroadcast_val(ipaddr, netif) ((IP_IS_V6_VAL(ipaddr)) ? \ ++ 0 : \ ++ ip4_addr_isbroadcast(ip_2_ip4(&ipaddr), netif)) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup ipaddr */ + #define ip_addr_ismulticast(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_ismulticast(ip_2_ip6(ipaddr)) : \ + ip4_addr_ismulticast(ip_2_ip4(ipaddr))) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_ismulticast_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ ++ ip6_addr_ismulticast(ip_2_ip6(&ipaddr)) : \ ++ ip4_addr_ismulticast(ip_2_ip4(&ipaddr))) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup ipaddr */ + #define ip_addr_isloopback(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_isloopback(ip_2_ip6(ipaddr)) : \ + ip4_addr_isloopback(ip_2_ip4(ipaddr))) ++#if LWIP_LITEOS_COMPAT ++#define ip_addr_isloopback_val(ipaddr) ((IP_IS_V6_VAL(ipaddr)) ? \ ++ ip6_addr_isloopback(ip_2_ip6(&ipaddr)) : \ ++ ip4_addr_isloopback(ip_2_ip4(&ipaddr))) ++#endif /* LWIP_LITEOS_COMPAT */ + /** @ingroup ipaddr */ + #define ip_addr_islinklocal(ipaddr) ((IP_IS_V6(ipaddr)) ? \ + ip6_addr_islinklocal(ip_2_ip6(ipaddr)) : \ + ip4_addr_islinklocal(ip_2_ip4(ipaddr))) ++#ifdef LWIP_DEBUG + #define ip_addr_debug_print(debug, ipaddr) do { if(IP_IS_V6(ipaddr)) { \ + ip6_addr_debug_print(debug, ip_2_ip6(ipaddr)); } else { \ +- ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }}while(0) ++ ip4_addr_debug_print(debug, ip_2_ip4(ipaddr)); }} while (0) + #define ip_addr_debug_print_val(debug, ipaddr) do { if(IP_IS_V6_VAL(ipaddr)) { \ + ip6_addr_debug_print_val(debug, *ip_2_ip6(&(ipaddr))); } else { \ +- ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }}while(0) ++ ip4_addr_debug_print_val(debug, *ip_2_ip4(&(ipaddr))); }} while (0) ++#else ++#define ip_addr_debug_print(debug, ipaddr) ++#define ip_addr_debug_print_val(debug, ipaddr) ++#endif /* LWIP_LITEOS_COMPAT */ ++ + char *ipaddr_ntoa(const ip_addr_t *addr); + char *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen); ++#if LWIP_LITEOS_COMPAT ++#define ipaddr_ntoa_unsafe(addr) ((IP_IS_V6_VAL(*addr)) ? ip6addr_ntoa(ip_2_ip6(addr)) : ip4addr_ntoa(ip_2_ip4(addr))) ++#endif /* LWIP_LITEOS_COMPAT */ + int ipaddr_aton(const char *cp, ip_addr_t *addr); + + /** @ingroup ipaddr */ +@@ -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) + ++#define ip_addr_cmp_zoneless(addr1, addr2) ip4_addr_cmp(addr1, addr2) + #define ip_addr_copy(dest, src) ip4_addr_copy(dest, src) + #define ip_addr_copy_from_ip4(dest, src) ip4_addr_copy(dest, src) + #define ip_addr_set_ip4_u32(ipaddr, val) ip4_addr_set_u32(ip_2_ip4(ipaddr), val) + #define ip_addr_set_ip4_u32_val(ipaddr, val) ip_addr_set_ip4_u32(&(ipaddr), val) + #define ip_addr_get_ip4_u32(ipaddr) ip4_addr_get_u32(ip_2_ip4(ipaddr)) + #define ip_addr_set(dest, src) ip4_addr_set(dest, src) ++#define ip_addr_set_val(dest, src) ip4_addr_copy(dest, src) + #define ip_addr_set_ipaddr(dest, src) ip4_addr_set(dest, src) + #define ip_addr_set_zero(ipaddr) ip4_addr_set_zero(ipaddr) ++#define ip_addr_set_zero_val(ipaddr) ip4_addr_set_zero(&(ipaddr)) + #define ip_addr_set_zero_ip4(ipaddr) ip4_addr_set_zero(ipaddr) + #define ip_addr_set_any(is_ipv6, ipaddr) ip4_addr_set_any(ipaddr) + #define ip_addr_set_loopback(is_ipv6, ipaddr) ip4_addr_set_loopback(ipaddr) + #define ip_addr_set_hton(dest, src) ip4_addr_set_hton(dest, src) + #define ip_addr_get_network(target, host, mask) ip4_addr_get_network(target, host, mask) + #define ip_addr_netcmp(addr1, addr2, mask) ip4_addr_netcmp(addr1, addr2, mask) ++#define ip_addr_netcmp_val(addr1, addr2, mask) ip4_addr_netcmp(&(addr1), &(addr2), mask) + #define ip_addr_cmp(addr1, addr2) ip4_addr_cmp(addr1, addr2) + #define ip_addr_isany(ipaddr) ip4_addr_isany(ipaddr) ++#define ip_addr_isnone(ipaddr) ip4_addr_isnone(ipaddr) + #define ip_addr_isany_val(ipaddr) ip4_addr_isany_val(ipaddr) + #define ip_addr_isloopback(ipaddr) ip4_addr_isloopback(ipaddr) ++#define ip_addr_isloopback_val(ipaddr) ip4_addr_isloopback(&(ipaddr)) + #define ip_addr_islinklocal(ipaddr) ip4_addr_islinklocal(ipaddr) + #define ip_addr_isbroadcast(addr, netif) ip4_addr_isbroadcast(addr, netif) ++#define ip_addr_isbroadcast_val(addr, netif) ip4_addr_isbroadcast(&(addr), netif) + #define ip_addr_ismulticast(ipaddr) ip4_addr_ismulticast(ipaddr) ++#define ip_addr_ismulticast_val(ipaddr) ip4_addr_ismulticast(&(ipaddr)) ++#ifdef LWIP_DEBUG + #define ip_addr_debug_print(debug, ipaddr) ip4_addr_debug_print(debug, ipaddr) + #define ip_addr_debug_print_val(debug, ipaddr) ip4_addr_debug_print_val(debug, ipaddr) ++#else ++#define ip_addr_debug_print(debug, ipaddr) ++#define ip_addr_debug_print_val(debug, ipaddr) ++#endif ++ + #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 +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) ++#define ip_addr_set_val(dest, src) ip6_addr_copy(dest, src) ++ + #define ip_addr_set_ipaddr(dest, src) ip6_addr_set(dest, src) + #define ip_addr_set_zero(ipaddr) ip6_addr_set_zero(ipaddr) ++#define ip_addr_set_zero_val(ipaddr) ip6_addr_set_zero(&(ipaddr)) + #define ip_addr_set_zero_ip6(ipaddr) ip6_addr_set_zero(ipaddr) ++#define ip_addr_set_zero_ip6_val(ipaddr) ip6_addr_set_zero(&(ipaddr)) + #define ip_addr_set_any(is_ipv6, ipaddr) ip6_addr_set_any(ipaddr) + #define ip_addr_set_loopback(is_ipv6, ipaddr) ip6_addr_set_loopback(ipaddr) + #define ip_addr_set_hton(dest, src) ip6_addr_set_hton(dest, src) + #define ip_addr_get_network(target, host, mask) ip6_addr_set_zero(target) + #define ip_addr_netcmp(addr1, addr2, mask) 0 ++#define ip_addr_netcmp_val(addr1, addr2, mask) 0 + #define ip_addr_cmp(addr1, addr2) ip6_addr_cmp(addr1, addr2) + #define ip_addr_cmp_zoneless(addr1, addr2) ip6_addr_cmp_zoneless(addr1, addr2) + #define ip_addr_isany(ipaddr) ip6_addr_isany(ipaddr) ++#define ip_addr_isnone(ipaddr) ip6_addr_isnone(ipaddr) + #define ip_addr_isany_val(ipaddr) ip6_addr_isany_val(ipaddr) + #define ip_addr_isloopback(ipaddr) ip6_addr_isloopback(ipaddr) ++#define ip_addr_isloopback_val(ipaddr) ip6_addr_isloopback(&(ipaddr)) + #define ip_addr_islinklocal(ipaddr) ip6_addr_islinklocal(ipaddr) + #define ip_addr_isbroadcast(addr, netif) 0 ++#define ip_addr_isbroadcast_val(addr, netif) 0 + #define ip_addr_ismulticast(ipaddr) ip6_addr_ismulticast(ipaddr) ++#define ip_addr_ismulticast_val(ipaddr) ip6_addr_ismulticast(&(ipaddr)) ++#ifdef LWIP_DEBUG + #define ip_addr_debug_print(debug, ipaddr) ip6_addr_debug_print(debug, ipaddr) + #define ip_addr_debug_print_val(debug, ipaddr) ip6_addr_debug_print_val(debug, ipaddr) ++#else ++#define ip_addr_debug_print(debug, ipaddr) ++#define ip_addr_debug_print_val(debug, ipaddr) ++#endif ++ + #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 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) */ +- ++#if LWIP_LITEOS_COMPAT ++#define SOF_DONTROUTE 0x01U /* all packets sent from this socket should only be routed with link scope entry */ ++#define SOF_BINDNONUNICAST 0x10U /* socket has bind to a non unicast */ ++#endif /* LWIP_LITEOS_COMPAT */ + /* These flags are inherited (e.g. from a listen-pcb to a connection-pcb): */ + #define SOF_INHERITED (SOF_REUSEADDR|SOF_KEEPALIVE) + +@@ -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; ++#if LWIP_LITEOS_COMPAT ++ /* The IP header ID of the next outgoing IP packet */ ++#if LWIP_IPV4 ++ /* ensure this member of this sturcture is not mem set to zero */ ++ u16_t ip_id; ++#endif /* LWIP_IPV4 */ ++#endif /* LWIP_LITEOS_COMPAT */ + }; + extern struct ip_globals ip_data; + +@@ -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 */ ++#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 ++ * (requires IP_FRAG_USES_STATIC_BUF==1).This is not a configurable value. ++ */ ++#if !defined(IP_FRAG_MAX_MTU) ++#define IP_FRAG_MAX_MTU 1500 ++#endif ++/* As per RFC 791, "Every internet module must be able to forward a datagram of 68 ++ * octets without further fragmentation. This is because an internet header ++ * may be up to 60 octets, and the minimum fragment is 8 octets." */ ++#if !defined(IP_FRAG_MIN_MTU) ++#define IP_FRAG_MIN_MTU 68 ++#endif ++struct netif *ip_route_pcb(const ip_addr_t *dest, const struct ip_pcb* pcb); ++#endif /* LWIP_LITEOS_COMPAT */ + #define ip_route_get_local_ip(src, dest, netif, ipaddr) do { \ + (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 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 */ + #define NETBUF_FLAG_CHKSUM 0x02 ++#if PF_PACKET_SOCKET ++#define NETBUF_FLAG_IFINDEX 0x04 ++#endif /* PF_PACKET_SOCKET */ + + /** "Network buffer" - contains data and addressing info */ + struct netbuf { + struct pbuf *p, *ptr; + ip_addr_t addr; + u16_t port; +-#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY ++#if PF_PACKET_SOCKET ++ u16_t hatype; ++ u16_t reserve; /* padded */ ++ u8_t netifindex; ++#endif /* PF_PACKET_SOCKET */ ++ ++#if LWIP_NETBUF_RECVINFO || LWIP_CHECKSUM_ON_COPY || PF_PACKET_SOCKET + u8_t flags; + u16_t toport_chksum; + #if LWIP_NETBUF_RECVINFO +@@ -73,7 +82,7 @@ + /* Network buffer functions: */ + struct netbuf * netbuf_new (void); + void netbuf_delete (struct netbuf *buf); +-void * netbuf_alloc (struct netbuf *buf, u16_t size); ++void * netbuf_alloc (struct netbuf *buf, u16_t size, u8_t netconn_type); + void netbuf_free (struct netbuf *buf); + err_t netbuf_ref (struct netbuf *buf, + const void *dataptr, u16_t size); +@@ -93,6 +102,10 @@ + #define netbuf_fromaddr(buf) (&((buf)->addr)) + #define netbuf_set_fromaddr(buf, fromaddr) ip_addr_set(&((buf)->addr), fromaddr) + #define netbuf_fromport(buf) ((buf)->port) ++#if LWIP_LITEOS_COMPAT ++#define netbuf_fromifindex(buf) ((buf)->netifindex) ++#define netbuf_fromhatype(buf) ((buf)->hatype) ++#endif /* LWIP_LITEOS_COMPAT */ + #if LWIP_NETBUF_RECVINFO + #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 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" + ++#if LWIP_LITEOS_COMPAT ++#include ++#endif ++ + #if LWIP_DNS && LWIP_SOCKET + + #include "lwip/arch.h" +@@ -63,6 +67,7 @@ + #define LWIP_DNS_API_DECLARE_STRUCTS 1 + #endif + ++#if !LWIP_LITEOS_COMPAT + #if LWIP_DNS_API_DEFINE_ERRORS + /** Errors used by the DNS API functions, h_errno can be one of them */ + #define EAI_NONAME 200 +@@ -112,23 +117,39 @@ + }; + #endif /* LWIP_DNS_API_DECLARE_STRUCTS */ + +-#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) + + #if LWIP_DNS_API_DECLARE_H_ERRNO + /* application accessible error code set by the DNS API functions */ + extern int h_errno; + #endif /* LWIP_DNS_API_DECLARE_H_ERRNO*/ ++#endif /* !LWIP_LITEOS_COMPAT */ + ++#define NETDB_ELEM_SIZE (sizeof(struct addrinfo) + sizeof(struct sockaddr_storage) + DNS_MAX_NAME_LENGTH + 1) ++ ++#if LWIP_GETHOSTBYNAME || (defined(LWIP_COMPAT_SOCKETS) && (LWIP_COMPAT_SOCKETS != 2)) + struct hostent *lwip_gethostbyname(const char *name); ++#endif /* LWIP_GETHOSTBYNAME || (defined(LWIP_COMPAT_SOCKETS) && (LWIP_COMPAT_SOCKETS != 2)) */ ++#if (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) + int lwip_gethostbyname_r(const char *name, struct hostent *ret, char *buf, + size_t buflen, struct hostent **result, int *h_errnop); ++#endif /* (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) */ ++#if (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) + void lwip_freeaddrinfo(struct addrinfo *ai); + int lwip_getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); +- +-#if LWIP_COMPAT_SOCKETS ++#endif /* (defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2) */ ++#if LWIP_DNS_REVERSE ++int lwip_getnameinfo(const struct sockaddr *sa, ++ socklen_t salen, ++ char *host, ++ size_t hostlen, ++ char *serv, ++ size_t servlen, ++ int flags); ++#endif /* LWIP_DNS_REVERSE */ ++#if defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2 + /** @ingroup netdbapi */ + #define gethostbyname(name) lwip_gethostbyname(name) + /** @ingroup netdbapi */ +@@ -139,7 +160,11 @@ + /** @ingroup netdbapi */ + #define getaddrinfo(nodname, servname, hints, res) \ + lwip_getaddrinfo(nodname, servname, hints, res) +-#endif /* LWIP_COMPAT_SOCKETS */ ++ ++/* @ingroup netdbapi */ ++#define getnameinfo(sock, sock_size, host, host_len, servname, servname_size, flags) \ ++ lwip_getnameinfo(sock, sock_size, host, host_len, servname, servname_size, flags) ++#endif /* defined(LWIP_COMPAT_SOCKETS) && LWIP_COMPAT_SOCKETS != 2 */ + + #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 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*/ + ++/* ++Func Name: netifapi_netif_find_by_name ++*/ ++/** ++* @ingroup netifapi_netif ++* ++* @brief ++* This is a thread safe API, used to get the netif pointer whoes name was the input argument. ++* It is recommended to use this API instead of netif_find_by_name(). ++* Call netif_find() in a thread-safe way by running that function inside the tcpip_thread ++* context. ++* ++* @param[in] name Name of the netif. ++* ++* @returns ++* The netif pointer : On success \n ++* NULL : the netif was NOT exist \n ++* ++* @par Related Topics ++* netif_find_by_name() ++* ++*/ ++ ++struct netif* netifapi_netif_find_by_name(const char *name); + err_t netifapi_netif_common(struct netif *netif, netifapi_void_fn voidfunc, + 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 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" + #include "lwip/stats.h" ++#include "lwip/prot/ethernet.h" + + #ifdef __cplusplus + extern "C" { +@@ -67,8 +68,17 @@ + * netif can be identified by in APIs. Composed of + * 2 chars, 3 (max) digits, and 1 \0 + */ +-#define NETIF_NAMESIZE 6 ++#ifdef IFNAMSIZ ++#define NETIF_NAMESIZE IFNAMSIZ ++#else ++#define NETIF_NAMESIZE 16 ++#endif + ++#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 + /** + * @defgroup netif_flags Flags + * @ingroup netif +@@ -106,6 +116,17 @@ + * Set by the netif driver in its init function. */ + #define NETIF_FLAG_MLD6 0x40U + ++/** If set, the interface is configured using DHCP. ++ * Set by the DHCP code when starting or stopping DHCP. */ ++#define NETIF_FLAG_DHCP 0x80U ++ ++#if DRIVER_STATUS_CHECK ++/** If set, the netif has send capability. ++ * Set by the netif driver when its is ready to send. */ ++#define NETIF_FLAG_DRIVER_RDY 0x100U ++#endif ++ ++#define NETIF_FLAG_LOOPBACK 0x800 + /** + * @} + */ +@@ -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 */ + ++/** Function pointer of driver set hw address function */ ++typedef u8_t (*drv_set_hwaddr_fn)(struct netif *netif, u8_t *addr, u8_t len); ++ + #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 +273,10 @@ + */ + #define netif_get_client_data(netif, id) (netif)->client_data[(id)] + #endif ++#ifndef LOOPBACK_IF ++/** Type of link layer, these macros should be used for link_layer_type of struct netif */ ++#define LOOPBACK_IF 772 ++#endif + + #if (LWIP_IPV4 && LWIP_ARP && (ARP_TABLE_SIZE > 0x7f)) || (LWIP_IPV6 && (LWIP_ND6_NUM_DESTINATIONS > 0x7f)) + typedef u16_t netif_addr_idx_t; +@@ -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; ++ /* This function is to set the mac_address of the interface. */ ++ drv_set_hwaddr_fn drv_set_hwaddr; ++#if LWIP_NETIF_ETHTOOL && LWIP_SOCKET ++ void *ethtool_ops; ++#endif ++#if LWIP_DHCPS ++ /* DHCP Server Informarion for this netif */ ++ struct dhcps *dhcps; ++#endif + #ifdef netif_get_client_data + void* client_data[LWIP_NETIF_CLIENT_DATA_INDEX_MAX + LWIP_NUM_NETIF_CLIENT_DATA]; + #endif + #if LWIP_NETIF_HOSTNAME + /* the hostname for this netif, NULL is a valid value */ +- const char* hostname; ++ char hostname[NETIF_HOSTNAME_MAX_LEN]; + #endif /* LWIP_NETIF_HOSTNAME */ + #if LWIP_CHECKSUM_CTRL_PER_NETIF + u16_t chksum_flags; +@@ -341,13 +398,19 @@ + u8_t hwaddr[NETIF_MAX_HWADDR_LEN]; + /** number of bytes used in hwaddr */ + u8_t hwaddr_len; ++ /* link layer type, ethernet or wifi */ ++ u16_t link_layer_type; /**< Indicates whether the link layer type is ethernet or wifi. */ + /** flags (@see @ref netif_flags) */ +- u8_t flags; ++ u32_t flags; + /** descriptive abbreviation */ +- char name[2]; +- /** number of this interface. Used for @ref if_api and @ref netifapi_netif, ++ char name[NETIF_NAMESIZE]; ++ /** number of this interface. Used for @ref if_api and @ref netifapi_netif, + * as well as for IPv6 zones */ + u8_t num; ++ u8_t ifindex; /* Interface Index mapped to each netif. Starts from 1 */ ++#if DRIVER_STATUS_CHECK ++ s32_t waketime; /**< Started when netif_stop_queue is called from driver. */ ++#endif + #if LWIP_IPV6_AUTOCONFIG + /** is this netif enabled for IPv6 autoconfiguration */ + u8_t ip6_autoconfig_enabled; +@@ -387,6 +450,15 @@ + u16_t loop_cnt_current; + #endif /* LWIP_LOOPBACK_MAX_PBUFS */ + #endif /* ENABLE_LOOPBACK */ ++#if LWIP_SO_DONTROUTE ++ /** The scope of the netif, this is set in ip4_route/ip6_route, the usr can use this ++ to decide whether the netif is in desired sope */ ++ rt_scope_t scope; ++#endif ++#if LWIP_IPV6 ++ /** Call back needs to be registered if adaptor requires notification for IPv6 DAD */ ++ u8_t ipv6_flags; ++#endif + }; + + #if LWIP_CHECKSUM_CTRL_PER_NETIF +@@ -407,9 +479,15 @@ + #endif /* LWIP_SINGLE_NETIF */ + /** The default network interface. */ + extern struct netif *netif_default; +- ++s8_t netif_find_dst_ipaddr(const ip_addr_t *ipaddr, ip_addr_t **dst_addr); + void netif_init(void); + ++#if LWIP_DHCP ++err_t netif_dhcp_off(struct netif *netif); ++#endif ++ ++u8_t netif_check_num_isusing(const char* ifname, const u8_t num); ++ + struct netif *netif_add_noaddr(struct netif *netif, void *state, netif_init_fn init, netif_input_fn input); + + #if LWIP_IPV4 +@@ -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); + +-void netif_set_default(struct netif *netif); ++struct netif *netif_find_by_ipaddr(const ip_addr_t *ipaddr); ++ ++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); + void netif_set_netmask(struct netif *netif, const ip4_addr_t *netmask); + void netif_set_gw(struct netif *netif, const ip4_addr_t *gw); ++struct netif *netif_find_by_ip4addr(const ip_addr_t *ipaddr); + /** @ingroup netif_ip4 */ + #define netif_ip4_addr(netif) ((const ip4_addr_t*)ip_2_ip4(&((netif)->ip_addr))) + /** @ingroup netif_ip4 */ +@@ -455,6 +548,9 @@ + + void netif_set_up(struct netif *netif); + void netif_set_down(struct netif *netif); ++err_t netif_set_mtu_api(struct netif *netif, u16_t netif_mtu); ++err_t netif_set_hwaddr(struct netif *netif, const unsigned char *hw_addr, int hw_len); ++void netif_get_hwaddr(const struct netif *netif, unsigned char *hw_addr, int hw_len); + /** @ingroup netif + * Ask if an interface is up + */ +@@ -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); ++err_t netif_do_add_ipv6_addr(struct netif *netif, void *arguments); ++err_t netif_do_rmv_ipv6_addr(struct netif *netif, void *arguments); + 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 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) + */ + #if !defined MEMP_NUM_NETCONN || defined __DOXYGEN__ +-#define MEMP_NUM_NETCONN 4 ++#define MEMP_NUM_NETCONN 16 + #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 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 +- ++#ifdef LWIP_LITEOS_COMPAT ++#define PBUF_FLAG_HOST 0x100U ++#define PBUF_FLAG_OUTGOING 0x200U ++#endif + /** Main packet buffer struct */ + 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 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" + #include "lwip/priv/tcpip_priv.h" ++#include "lwip/ip.h" + + #ifdef __cplusplus + extern "C" { +@@ -70,6 +71,14 @@ + #define NETCONN_SHUT_WR 2 + #define NETCONN_SHUT_RDWR (NETCONN_SHUT_RD | NETCONN_SHUT_WR) + ++#if PF_PACKET_SOCKET ++/* Packet Types */ ++#define PACKET_HOST 0 /* To us */ ++#define PACKET_BROADCAST 1 /* To all */ ++#define PACKET_MULTICAST 2 /* To group */ ++#define PACKET_OTHERHOST 3 /* To someone else */ ++#define PACKET_OUTGOING 4 ++#endif + /* IP addresses and port numbers are expected to be in + * the same byte order as in the corresponding pcb. + */ +@@ -88,7 +97,7 @@ + struct netbuf *b; + /** used for lwip_netconn_do_newconn */ + struct { +- u8_t proto; ++ u16_t proto; + } n; + /** used for lwip_netconn_do_bind and lwip_netconn_do_connect */ + struct { +@@ -102,6 +111,12 @@ + u16_t API_MSG_M_DEF(port); + u8_t local; + } ad; ++#if PF_PACKET_SOCKET ++ struct { ++ struct pf_packet_sockaddr_ll API_MSG_M_DEF(ll); ++ u8_t local; ++ } adpkt; ++#endif + /** used for lwip_netconn_do_write */ + struct { + /** current vector to write */ +@@ -205,6 +220,7 @@ + #endif /* TCP_LISTEN_BACKLOG */ + void lwip_netconn_do_write (void *m); + void lwip_netconn_do_getaddr (void *m); ++void lwip_netconn_do_getaddr_pfpkt (void *m); + void lwip_netconn_do_close (void *m); + void lwip_netconn_do_shutdown (void *m); + #if LWIP_IGMP || (LWIP_IPV6 && LWIP_IPV6_MLD) +@@ -214,6 +230,7 @@ + + #if LWIP_DNS + void lwip_netconn_do_gethostbyname(void *arg); ++void lwip_netconn_do_getnamebyhost(void *arg); + #endif /* LWIP_DNS */ + + struct netconn* netconn_alloc(enum netconn_type t, netconn_callback callback); +@@ -233,6 +250,7 @@ + + typedef void (*netifapi_void_fn)(struct netif *netif); + typedef err_t (*netifapi_errt_fn)(struct netif *netif); ++typedef err_t (*netifapi_arg_fn)(struct netif *netif, void *arg); + + struct netifapi_msg { + struct tcpip_api_call_data call; +@@ -245,9 +263,27 @@ + NETIFAPI_IPADDR_DEF(ip4_addr_t, gw); + #endif /* LWIP_IPV4 */ + void *state; ++ } add; ++ ++ struct { ++ const ip_addr_t *ipaddr; ++ } find_by_ipaddr; ++ struct { ++ const char *name; ++ } find_by_name; ++ struct { ++ unsigned char ifindex; ++ } find_by_ifindex; ++ struct { ++#if LWIP_IPV4 ++ ip4_addr_t *ipaddr; ++ ip4_addr_t *netmask; ++ ip4_addr_t *gw; ++#endif /* LWIP_IPV4 */ ++ void *state; + netif_init_fn init; + netif_input_fn input; +- } add; ++ } add_get; + struct { + 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 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 + +-#define NUM_SOCKETS MEMP_NUM_NETCONN + + /** This is overridable for the rare case where more than 255 threads + * select on the same socket... +@@ -69,6 +68,10 @@ + struct netconn *conn; + /** data that was left from the previous read */ + union lwip_sock_lastdata lastdata; ++ /** offset in the data that was left from the previous read */ ++ u16_t lastoffset; ++ /* socket level mutex used for multithread recv support */ ++ sys_mutex_t mutex; + #if LWIP_SOCKET_SELECT || LWIP_SOCKET_POLL + /** number of times data was received, set by event_callback(), + tested by the receive and select functions */ +@@ -158,6 +161,7 @@ + fd_set *exceptset; + #endif /* LWIP_SOCKET_SELECT */ + #if LWIP_SOCKET_POLL ++ + /** fds passed to poll; NULL if select */ + 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 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 + PACK_STRUCT_BEGIN +-struct icmp6_hdr { ++struct icmpv6_hdr { + 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 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" + #include "lwip/ip4_addr.h" ++#if LWIP_LITEOS_COMPAT ++#include ++#endif + + #ifdef __cplusplus + extern "C" { +@@ -81,10 +84,12 @@ + PACK_STRUCT_FIELD(u16_t _id); + /* fragment offset field */ + PACK_STRUCT_FIELD(u16_t _offset); ++#if !LWIP_LITEOS_COMPAT + #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 */ ++#endif + /* 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 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" + #include "lwip/ip6_addr.h" ++#include "lwip/etharp.h" ++#include "lwip/icmp6.h" + + #ifdef __cplusplus + extern "C" { +@@ -57,6 +59,18 @@ + #define RAW_FLAGS_MULTICAST_LOOP 0x04U + + struct raw_pcb; ++extern struct raw_pcb* raw_pcbs; ++ ++#if PF_PACKET_SOCKET ++extern const struct eth_hdr *g_lwip_current_eth_hdr; ++extern const struct netif *g_lwip_current_netif; ++/* Dest MAC add of current ethernet header of RAW packets ++ * received for PF_PACKET family */ ++#define eth_current_hdr() (g_lwip_current_eth_hdr) ++#define eth_current_netif() (g_lwip_current_netif) ++struct raw_pcb* get_packet_raw_pcbs(void); ++struct raw_pcb* get_all_packet_raw_pcbs(void); ++#endif /* PF_PACKET_SOCKET */ + + /** Function prototype for raw pcb receive callback functions. + * @param arg user supplied argument (raw_pcb.recv_arg) +@@ -77,8 +91,19 @@ + IP_PCB; + + struct raw_pcb *next; +- ++#if PF_PACKET_SOCKET ++ struct raw_pcb *all_next; ++ u8_t netifindex; ++ ++ union { ++ u16_t eth_proto; /* Ethernet HeaderType/Protocol for Packet sockets */ ++#define raw_proto proto.protocol ++ u8_t protocol; /* IP protocol for AF_INET sockets */ ++ } proto; ++#else ++#define raw_proto protocol + u8_t protocol; ++#endif + u8_t flags; + + #if LWIP_MULTICAST_TX_OPTIONS +@@ -115,6 +140,14 @@ + + void raw_recv (struct raw_pcb *pcb, raw_recv_fn recv, void *recv_arg); + ++#if PF_PACKET_SOCKET ++struct raw_pcb * raw_packet_new (u16_t proto); ++void raw_packet_remove (struct raw_pcb *pcb); ++void raw_packet_input (struct pbuf *p, const struct netif *inp, const struct raw_pcb *from); ++err_t raw_packet_sendto (const struct raw_pcb *pcb, struct pbuf *p, u8_t ifindex); ++err_t raw_packet_bind (struct raw_pcb *pcb, u8_t ifindex, u16_t proto); ++#endif /* PF_PACKET_SOCKET */ ++ + #define raw_flags(pcb) ((pcb)->flags) + #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 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 + ++#if LWIP_LITEOS_COMPAT ++#include "sys/select.h" ++#include "sys/socket.h" ++#include "poll.h" ++#include "netinet/tcp.h" ++#endif /* LWIP_LITEOS_COMPAT */ ++ + #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) +@@ -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. */ ++#else /* LWIP_LITEOS_COMPAT */ ++#if LWIP_LITEOS_COMPAT ++#ifndef TCP_KEEPALIVE ++#define TCP_KEEPALIVE 0x02 ++#endif /* TCP_KEEPALIVE */ ++ ++#ifndef SIN_ZERO_LEN ++#define SIN_ZERO_LEN 8 ++#endif /* SIN_ZERO_LEN */ ++ ++#ifndef SOCK_MAX ++#define SOCK_MAX (SOCK_RAW + 1) ++#endif /* SOCK_MAX */ ++ ++#ifndef SOCK_TYPE_MASK ++#define SOCK_TYPE_MASK 0xf ++#endif /* SOCK_TYPE_MASK */ ++#endif ++ + void lwip_socket_thread_init(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: initialize thread-local semaphore */ + void lwip_socket_thread_cleanup(void); /* LWIP_NETCONN_SEM_PER_THREAD==1: destroy thread-local semaphore */ + ++#if LWIP_IPV6 ++#define LWIP_IS_IPPROTOCOL(protocol) ((protocol) == IPPROTO_IP || (protocol) == IPPROTO_IPV6 || (protocol) == 0) ++#if PF_PACKET ++#define LWIP_IS_VALID_DOMAIN(domain) (((domain) == AF_INET) || ((domain) == AF_INET6) || ((domain) == PF_PACKET)) ++#else ++#define LWIP_IS_VALID_DOMAIN(domain) ((domain) == AF_INET) || ((domain) == AF_INET6) ++#endif ++#else ++#define LWIP_IS_IPPROTOCOL(protocol) ((protocol) == IPPROTO_IP || (protocol) == 0) ++#if PF_PACKET ++#define LWIP_IS_VALID_DOMAIN(domain) (((domain) == AF_INET) || ((domain) == PF_PACKET)) ++#else ++#define LWIP_IS_VALID_DOMAIN(domain) ((domain) == AF_INET) || ((domain) == AF_INET6) ++#endif ++#endif + #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 +604,9 @@ + #if LWIP_SOCKET_SELECT + #define lwip_select select + #endif ++ ++#define lwip_gethostbyname(name) gethostbyname(name) ++ + #if LWIP_SOCKET_POLL + #define lwip_poll poll + #endif +@@ -558,9 +614,18 @@ + #define lwip_inet_ntop inet_ntop + #define lwip_inet_pton inet_pton + ++#if LWIP_DNS ++#define lwip_gethostbyname(name) gethostbyname(name) ++#define lwip_gethostbyname_r gethostbyname_r ++#define lwip_freeaddrinfo freeaddrinfo ++#define lwip_getaddrinfo getaddrinfo ++#define lwip_getnameinfo getnameinfo ++#endif ++ + #if LWIP_POSIX_SOCKETS_IO_NAMES + #define lwip_read read + #define lwip_readv readv ++ + #define lwip_write write + #define lwip_writev writev + #undef lwip_close +@@ -682,7 +747,7 @@ + #ifdef __cplusplus + } + #endif +- ++#endif + #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 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. ++ * Description: declare BSD APIs : getifaddrs freeifaddrs ++ * Author: none ++ * Create: 2020 ++ */ ++ ++#ifndef __LWIP_IFADDRS_H ++#define __LWIP_IFADDRS_H ++ ++#if (LWIP_IPV4 || LWIP_IPV6) && LWIP_SOCKET ++ ++#include "lwip/netif.h" ++#include "lwip/sockets.h" ++ ++#ifdef LWIP_COMPAT_SOCKETS ++#if LWIP_COMPAT_SOCKETS != 2 ++/* @ingroup socket */ ++#define getifaddrs(ifap) lwip_getifaddrs(ifap) ++#define freeifaddrs(ifa) lwip_freeifaddrs(ifa) ++#else /* LWIP_COMPAT_SOCKETS != 2 */ ++/* @ingroup socket */ ++#define lwip_getifaddrs(ifap) getifaddrs(ifap) ++#define lwip_freeifaddrs(ifa) freeifaddrs(ifa) ++#endif /* LWIP_COMPAT_SOCKETS == 2 */ ++#endif /* LWIP_COMPAT_SOCKETS */ ++ ++#if LWIP_LITEOS_COMPAT ++ ++#ifndef SIOCETHTOOL ++#define SIOCETHTOOL _IOW('i', 56, struct ifreq) ++#endif ++#define IFF_DRV_RUNNING 0x40 ++ ++#else ++#define SIOCADDRT _IOW('R', 9, struct rtentry) ++#define SIOCDELRT _IOW('R', 10, struct rtentry) ++ ++#define SIOCGIFFLAGS _IOWR('i', 17, struct ifreq) /* get ifnet flags */ ++#define SIOCSIFFLAGS _IOW('i', 16, struct ifreq) /* set ifnet flags */ ++#define SIOCGIFADDR _IOWR('i', 33, struct ifreq) /* get ifnet address */ ++#define SIOCSIFADDR _IOW('i', 12, struct ifreq) /* set ifnet address */ ++ ++#define SIOCDIFADDR _IOW('i', 25, struct ifreq) /* delete IF addr */ ++ ++#define SIOCGIFNETMASK _IOWR('i', 37, struct ifreq) /* get net addr mask */ ++#define SIOCSIFNETMASK _IOW('i', 22, struct ifreq) /* set net addr mask */ ++#define SIOCSIFHWADDR _IOW('i', 140, struct ifreq) /* set IF name */ ++#define SIOCGIFHWADDR _IOW('i', 141, struct ifreq) /* set IF name */ ++#define SIOCGIFNAME _IOW('i', 142, struct ifreq) /* set IF name */ ++#define SIOCSIFNAME _IOW('i', 40, struct ifreq) /* set IF name */ ++ ++/** Gets IF mtu */ ++#define SIOCGIFMTU _IOWR('i', 51, struct ifreq) ++/** Sets IF mtu */ ++#define SIOCSIFMTU _IOW('i', 52, struct ifreq) ++/** ethtool */ ++#define SIOCETHTOOL _IOW('i', 56, struct ifreq) ++ ++/* provide PF_PACKET option on SOCK_RAW */ ++#define SIOCGIFINDEX _IOWR('i', 32, struct ifreq) /* get IF index */ ++#define SIOCGIFCONF _IOWR('i', 36, struct ifconf) /* get ifnet list */ ++ ++/** (n) Indicates that the interface is up */ ++#define IFF_UP 0x1 ++/** (i) Indicates that the broadcast address valid */ ++#define IFF_BROADCAST 0x2 ++/** (n) Turns on debugging */ ++#define IFF_DEBUG 0x4 ++/** (i) A loopback net */ ++#define IFF_LOOPBACK 0x8 ++/** (i) Indicates a point-to-point link */ ++#define IFF_POINTOPOINT 0x10 ++/* 0x20 was IFF_SMART */ ++/** (d) Indicates that the resources are allocated */ ++#define IFF_DRV_RUNNING 0x40 ++/** (n) No address resolution protocol */ ++#define IFF_NOARP 0x80 ++/** (n) Receive all packets */ ++#define IFF_PROMISC 0x100 ++/** (n) Receive all multicast packets */ ++#define IFF_ALLMULTI 0x200 ++/** (d) Indicates that the tx hardware queue is full */ ++#define IFF_DRV_OACTIVE 0x400 ++ /** (i) Cannot hear own transmissions */ ++#define IFF_SIMPLEX 0x800 ++/** Per link layer defined bit */ ++#define IFF_LINK0 0x1000 ++/** Per link layer defined bit */ ++#define IFF_LINK1 0x2000 ++/** Per link layer defined bit */ ++#define IFF_LINK2 0x4000 ++/** Use alternate physical connection */ ++#define IFF_ALTPHYS IFF_LINK2 ++/** Supports multicast */ ++#define IFF_MULTICAST 0x8000 ++ /** (i) Unconfigurable using ioctl(2) */ ++#define IFF_CANTCONFIG 0x10000 ++/** (n) User-requested promisc mode */ ++#define IFF_PPROMISC 0x20000 ++/** (n) User-requested IFF_MONITOR mode */ ++#define IFF_MONITOR 0x40000 ++ /** (n) Static ARP */ ++#define IFF_STATICARP 0x80000 ++/** (n) Interface is winding down */ ++#define IFF_DYING 0x200000 ++/** (n) Interface is being renamed */ ++#define IFF_RENAMING 0x400000 ++/** (n) Dialup device with changing addresses */ ++#define IFF_DYNAMIC 0x800000 ++/** (n) Dialup device with changing addresses */ ++#define IFF_DYNAMIC_S 0x1000000 ++ ++#define IFF_RUNNING IFF_DRV_RUNNING ++ ++#ifndef IFNAMSIZ ++#define IFNAMSIZ NETIF_NAMESIZE ++#endif ++ ++struct ifreq { ++#define IFHWADDRLEN 6 ++ union { ++ char ifrn_name[IFNAMSIZ]; ++ } ifr_ifrn; ++ union { ++ struct sockaddr ifru_addr; ++ struct sockaddr ifru_dstaddr; ++ struct sockaddr ifru_broadaddr; ++ struct sockaddr ifru_netmask; ++ struct sockaddr ifru_hwaddr; ++ short ifru_flags[2]; ++ int ifru_ivalue; ++ int ifru_mtu; ++ char ifru_slave[IFNAMSIZ]; ++ char ifru_newname[IFNAMSIZ]; ++ void *ifru_data; ++ } ifr_ifru; ++}; ++#define ifr_name ifr_ifrn.ifrn_name ++#define ifr_hwaddr ifr_ifru.ifru_hwaddr ++#define ifr_addr ifr_ifru.ifru_addr ++#define ifr_dstaddr ifr_ifru.ifru_dstaddr ++#define ifr_broadaddr ifr_ifru.ifru_broadaddr ++#define ifr_netmask ifr_ifru.ifru_netmask ++#define ifr_flags ifr_ifru.ifru_flags[0] /* flags (low 16 bits) */ ++#define ifr_flagshigh ifr_ifru.ifru_flags[1] /* flags (high 16 bits) */ ++#define ifr_metric ifr_ifru.ifru_ivalue ++#define ifr_mtu ifr_ifru.ifru_mtu ++#define ifr_slave ifr_ifru.ifru_slave ++#define ifr_data ifr_ifru.ifru_data ++#define ifr_ifindex ifr_ifru.ifru_ivalue ++#define ifr_bandwidth ifr_ifru.ifru_ivalue ++#define ifr_qlen ifr_ifru.ifru_ivalue ++#define ifr_newname ifr_ifru.ifru_newname ++#define ifr_index ifr_ifindex ++ ++struct ifconf { ++ int ifc_len; ++ union { ++ char *ifcu_buf; ++ struct ifreq *ifcu_req; ++ } ifc_ifcu; ++}; ++ ++#define ifc_buf ifc_ifcu.ifcu_buf ++#define ifc_req ifc_ifcu.ifcu_req ++ ++struct ifaddrs { ++ struct ifaddrs *ifa_next; /**< Pointer to the next network interfaces.f */ ++ char *ifa_name; /**< Pointer to the name of the network interfaces */ ++ unsigned int ifa_flags; /**< Pointer to the status flag. */ ++ struct sockaddr *ifa_addr; /**< Pointer to the address. */ ++ struct sockaddr *ifa_netmask; /**< Pointer to the net masking. */ ++ struct sockaddr *ifa_dstaddr; /**< Pointer to the destination address. */ ++ void *ifa_data; /**< Pointer to the data. */ ++}; ++ ++ #ifndef ifa_broadaddr ++ #define ifa_broadaddr ifa_dstaddr /* brcast address interface */ ++#endif ++ ++struct rtentry { ++ struct sockaddr rt_dst; /**< Indicates the target address. */ ++ struct sockaddr rt_gateway; /**< Indicates the gateway address (RTF_GATEWAY). */ ++ struct sockaddr rt_genmask; /**< Indicates the target network mask (IP). */ ++ unsigned int rt_flags; ++}; ++/** Indicates that the route is usable */ ++#define RTF_UP 0x1 ++/** Indicates that the destination is a gateway */ ++#define RTF_GATEWAY 0x2 ++/** Indicates the host entry (net otherwise) */ ++#define RTF_HOST 0x4 ++/** Indicates the host or net is unreachable */ ++#define RTF_REJECT 0x8 ++/** Created dynamically (by redirect) */ ++#define RTF_DYNAMIC 0x10 ++/** Modified dynamically (by redirect) */ ++#define RTF_MODIFIED 0x20 ++/** Message confirmed. */ ++#define RTF_DONE 0x40 ++/* 0x80 unused, was RTF_DELCLONE */ ++/* 0x100 unused, was RTF_CLONING */ ++/** Indicates that the external daemon resolves name */ ++#define RTF_XRESOLVE 0x200 ++/** DEPRECATED - exists ONLY for backward ++ compatibility */ ++#define RTF_LLINFO 0x400 ++/** Used by apps to add/del L2 entries */ ++#define RTF_LLDATA 0x400 ++/** Manually added */ ++#define RTF_STATIC 0x800 ++ /** Discard packets */ ++#define RTF_BLACKHOLE 0x1000 ++/** Protocol specific routing flag */ ++#define RTF_PROTO2 0x4000 ++/** Protocol specific routing flag */ ++/* 0x10000 unused, was RTF_PRCLONING */ ++#define RTF_PROTO1 0x8000 ++/* 0x10000 unused, was RTF_PRCLONING */ ++/* 0x20000 unused, was RTF_WASCLONED */ ++/** Protocol specific routing flag */ ++#define RTF_PROTO3 0x40000 ++/** MTU was explicitly specified */ ++#define RTF_FIXEDMTU 0x80000 ++/** Route is immutable */ ++#define RTF_PINNED 0x100000 ++/** Route represents a local address */ ++#define RTF_LOCAL 0x200000 ++/** Route represents a broadcast address */ ++#define RTF_BROADCAST 0x400000 ++ /** Route represents a multicast address */ ++#define RTF_MULTICAST 0x800000 ++ /* 0x8000000 and up unassigned */ ++/** Always route dst->src */ ++#define RTF_STICKY 0x10000000 ++/** Radix node head is locked */ ++#define RTF_RNH_LOCKED 0x40000000 ++/** Indicates the compatibility bit for interacting ++ with existing routing apps */ ++#define RTF_GWFLAG_COMPAT 0x80000000 ++ ++/* Mask of RTF flags that are allowed to be modified by RTM_CHANGE. */ ++#define RTF_FMASK \ ++ (RTF_PROTO1 | RTF_PROTO2 | RTF_PROTO3 | RTF_BLACKHOLE | \ ++ RTF_REJECT | RTF_STATIC | RTF_STICKY) ++ ++/** ++* @defgroup ifaddrs_api ifaddrs API ++* This section contains the interfaces to get information about Network interfaces in lwIP. ++* @ingroup socket ++*/ ++ ++/* ++Func Name: lwip_getifaddrs ++*/ ++ ++/** ++* @ingroup ifaddrs_api ++* @brief Creates a linked list of struct ifaddrs, which holds the information ++* about the network interfaces of the local system. The ifa_next field contains a ++* pointer to the next structure on the list, or NULL if this is the last item of the list. ++* The ifa_name points to the null-terminated interface name. The ifa_flags field ++* contains the interface flags. The ifa_addr field points to a structure containing ++* the interface address. The ifa_netmask field points to a structure containing ++* the netmask associated with ifa_addr, if applicable, for the address family. ++* Depending on whether the bit IFF_brcast or IFF_POINTOPOINT is set ++* in ifa_flags (only one can be set at a time), either ifa_broadaddr will contain ++* the broadcast address associated with ifa_addr (if applicable for the address ++* family) or ifa_dstaddr will contain the destination address of the point-to-point ++* interface. ++* For IPv6, stack supports only IFF_UP,IFF_MULTICAST, IFF_DRV_RUNNING, and IFF_LOOPBACK ++* flags. ++* @param[in] ifap Indicates a double pointer to the ifaddrs structure. ++* @return ++* On success, lwip_getifaddrs() returns zero; on error, -1 is returned, and errno is set appropriately. ++* @par Errors ++* @li The lwip_getifaddrs() function shall fail if: ++* - [EACCES] : \n Invalid state of system. ++* - [ENOMEM] : \n In-sufficient memory. ++* @note ++* None ++*/ ++int lwip_getifaddrs(struct ifaddrs **ifap); ++ ++/* ++Func Name: lwip_freeifaddrs ++*/ ++ ++/** ++* @ingroup ifaddrs_api ++* @brief The function lwip_freeifaddrs, provides the list of network interfaces in the ifaddrs* structure. ++* The application has to free the memory of the ifaddrs * structure by using this function. ++* @param[in] ifa Indicates a pointer to the ifaddrs structure. ++* @return ++* Void ++* @note ++* None ++*/ ++void lwip_freeifaddrs(struct ifaddrs *ifa); ++ ++#endif /* !LWIP_LITEOS_COMPAT */ ++int get_ipv6_ifaddr(struct netif *netif, struct ifaddrs *ifaddr, int tmp_index); ++int get_ipv4_ifaddr(struct netif *netif, struct ifaddrs *ifaddr); ++struct ifaddrs_storage *new_ifaddrs_storage(void); ++#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 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" + #include "lwip/snmp.h" +- ++#include "lwip/raw.h" + #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 @@ + } + } + ++#if PF_PACKET_SOCKET ++ p->flags = (u16_t)(p->flags & ~PBUF_FLAG_OUTGOING); ++ if (get_packet_raw_pcbs() != NULL) { ++ raw_packet_input(p, netif, NULL); ++ } ++#endif /* PF_PACKET_SOCKET */ + 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 + /** -- Gitee From a9f9832ad05ebdb995c405ccb06a12f6395d657f Mon Sep 17 00:00:00 2001 From: Terder-su Date: Mon, 21 Feb 2022 03:00:04 +0000 Subject: [PATCH 13/14] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20co?= =?UTF-8?q?mponents/net/lwip/patch.sha256?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/net/lwip/patch.sha256 | 1 - 1 file changed, 1 deletion(-) delete mode 100644 components/net/lwip/patch.sha256 diff --git a/components/net/lwip/patch.sha256 b/components/net/lwip/patch.sha256 deleted file mode 100644 index b3e5dd2..0000000 --- a/components/net/lwip/patch.sha256 +++ /dev/null @@ -1 +0,0 @@ -51971ada3e5453e582b4a7fd15db583693e0a3a614650decbe25d79fc7bcffbd origin.patch -- Gitee From 8eeac88a3379e18aeb6452c27ad9835ac99c66f5 Mon Sep 17 00:00:00 2001 From: Terder-su Date: Mon, 21 Feb 2022 03:00:17 +0000 Subject: [PATCH 14/14] update patch.sha256 --- components/net/lwip/patch.sha256 | 1 + 1 file changed, 1 insertion(+) create mode 100644 components/net/lwip/patch.sha256 diff --git a/components/net/lwip/patch.sha256 b/components/net/lwip/patch.sha256 new file mode 100644 index 0000000..68f9d1a --- /dev/null +++ b/components/net/lwip/patch.sha256 @@ -0,0 +1 @@ +6da71068eeb716399f4d5b0237aba082087b3abdf871e5b7f02174f79f8146a4 origin.patch -- Gitee