http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/ipv4/icmp.c ---------------------------------------------------------------------- diff --git a/net/ip/lwip_base/src/core/ipv4/icmp.c b/net/ip/lwip_base/src/core/ipv4/icmp.c index e60e448..5ee24ee 100644 --- a/net/ip/lwip_base/src/core/ipv4/icmp.c +++ b/net/ip/lwip_base/src/core/ipv4/icmp.c @@ -51,6 +51,10 @@ #include <string.h> +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + /** Small optimization: set to 0 if incoming PBUF_POOL pbuf always can be * used to modify and send a response packet (and to 1 if this is not the case, * e.g. when link header is stripped of when receiving) */ @@ -81,7 +85,7 @@ icmp_input(struct pbuf *p, struct netif *inp) #endif /* LWIP_DEBUG */ struct icmp_echo_hdr *iecho; const struct ip_hdr *iphdr_in; - s16_t hlen; + u16_t hlen; const ip4_addr_t* src; ICMP_STATS_INC(icmp.recv); @@ -148,7 +152,7 @@ icmp_input(struct pbuf *p, struct netif *inp) } #endif #if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN - if (pbuf_header(p, (hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) { + if (pbuf_header(p, (s16_t)(hlen + PBUF_LINK_HLEN + PBUF_LINK_ENCAPSULATION_HLEN))) { /* p is not big enough to contain link headers * allocate a new one and copy p into it */ @@ -167,7 +171,7 @@ icmp_input(struct pbuf *p, struct netif *inp) /* copy the ip header */ MEMCPY(r->payload, iphdr_in, hlen); /* switch r->payload back to icmp header (cannot fail) */ - if (pbuf_header(r, -hlen)) { + if (pbuf_header(r, (s16_t)-hlen)) { LWIP_ASSERT("icmp_input: moving r->payload to icmp header failed\n", 0); pbuf_free(r); goto icmperr; @@ -194,7 +198,7 @@ icmp_input(struct pbuf *p, struct netif *inp) /* We generate an answer by switching the dest and src ip addresses, * setting the icmp type to ECHO_RESPONSE and updating the checksum. */ iecho = (struct icmp_echo_hdr *)p->payload; - if (pbuf_header(p, hlen)) { + if (pbuf_header(p, (s16_t)hlen)) { LWIP_DEBUGF(ICMP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("Can't move over header in packet")); } else { err_t ret; @@ -247,7 +251,7 @@ icmp_input(struct pbuf *p, struct netif *inp) if (type == ICMP_DUR) { MIB2_STATS_INC(mib2.icmpindestunreachs); } else if (type == ICMP_TE) { - MIB2_STATS_INC(mib2.icmpindestunreachs); + MIB2_STATS_INC(mib2.icmpintimeexcds); } else if (type == ICMP_PP) { MIB2_STATS_INC(mib2.icmpinparmprobs); } else if (type == ICMP_SQ) {
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/ipv4/igmp.c ---------------------------------------------------------------------- diff --git a/net/ip/lwip_base/src/core/ipv4/igmp.c b/net/ip/lwip_base/src/core/ipv4/igmp.c index f3db591..74a6c37 100644 --- a/net/ip/lwip_base/src/core/ipv4/igmp.c +++ b/net/ip/lwip_base/src/core/ipv4/igmp.c @@ -195,10 +195,13 @@ igmp_report_groups(struct netif *netif) LWIP_DEBUGF(IGMP_DEBUG, ("igmp_report_groups: sending IGMP reports on if %p\n", (void*)netif)); + /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ + if(group != NULL) { + group = group->next; + } + while (group != NULL) { - if (!(ip4_addr_cmp(&(group->group_address), &allsystems))) { - igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR); - } + igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR); group = group->next; } } @@ -237,10 +240,11 @@ igmp_lookfor_group(struct netif *ifp, const ip4_addr_t *addr) * @return a struct igmp_group*, * NULL on memory error. */ -struct igmp_group * +static struct igmp_group * igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr) { struct igmp_group *group; + struct igmp_group *list_head = netif_igmp_data(ifp); /* Search if the group already exists */ group = igmp_lookfor_group(ifp, addr); @@ -248,7 +252,7 @@ igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr) /* Group already exists. */ return group; } - + /* Group doesn't exist yet, create a new one */ group = (struct igmp_group *)memp_malloc(MEMP_IGMP_GROUP); if (group != NULL) { @@ -257,9 +261,21 @@ igmp_lookup_group(struct netif *ifp, const ip4_addr_t *addr) group->group_state = IGMP_GROUP_NON_MEMBER; group->last_reporter_flag = 0; group->use = 0; - group->next = netif_igmp_data(ifp); - netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group); + /* Ensure allsystems group is always first in list */ + if (list_head == NULL) { + /* this is the first entry in linked list */ + LWIP_ASSERT("igmp_lookup_group: first group must be allsystems", + (ip4_addr_cmp(addr, &allsystems) != 0)); + group->next = NULL; + netif_set_client_data(ifp, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group); + } else { + /* append _after_ first entry */ + LWIP_ASSERT("igmp_lookup_group: all except first group must not be allsystems", + (ip4_addr_cmp(addr, &allsystems) == 0)); + group->next = list_head->next; + list_head->next = group; + } } LWIP_DEBUGF(IGMP_DEBUG, ("igmp_lookup_group: %sallocated a new group with address ", (group?"":"impossible to "))); @@ -279,24 +295,19 @@ static err_t igmp_remove_group(struct netif* netif, struct igmp_group *group) { err_t err = ERR_OK; + struct igmp_group *tmp_group; - /* Is it the first group? */ - if (netif_igmp_data(netif) == group) { - netif_set_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_IGMP, group->next); - } else { - /* look for group further down the list */ - struct igmp_group *tmpGroup; - for (tmpGroup = netif_igmp_data(netif); tmpGroup != NULL; tmpGroup = tmpGroup->next) { - if (tmpGroup->next == group) { - tmpGroup->next = group->next; - break; - } - } - /* Group not found in the global igmp_group_list */ - if (tmpGroup == NULL) { - err = ERR_ARG; + /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ + for (tmp_group = netif_igmp_data(netif); tmp_group != NULL; tmp_group = tmp_group->next) { + if (tmp_group->next == group) { + tmp_group->next = group->next; + break; } } + /* Group not found in the global igmp_group_list */ + if (tmp_group == NULL) { + err = ERR_ARG; + } return err; } @@ -368,11 +379,15 @@ igmp_input(struct pbuf *p, struct netif *inp, const ip4_addr_t *dest) } groupref = netif_igmp_data(inp); + + /* Do not send messages on the all systems group address! */ + /* Skip the first group in the list, it is always the allsystems group added in igmp_start() */ + if(groupref != NULL) { + groupref = groupref->next; + } + while (groupref) { - /* Do not send messages on the all systems group address! */ - if (!(ip4_addr_cmp(&(groupref->group_address), &allsystems))) { - igmp_delaying_member(groupref, igmp->igmp_maxresp); - } + igmp_delaying_member(groupref, igmp->igmp_maxresp); groupref = groupref->next; } } else { @@ -658,6 +673,8 @@ igmp_timeout(struct netif *netif, struct igmp_group *group) ip4_addr_debug_print(IGMP_DEBUG, &(group->group_address)); LWIP_DEBUGF(IGMP_DEBUG, (" on if %p\n", (void*)netif)); + group->group_state = IGMP_GROUP_IDLE_MEMBER; + IGMP_STATS_INC(igmp.tx_report); igmp_send(netif, group, IGMP_V2_MEMB_REPORT); } @@ -711,11 +728,9 @@ igmp_delaying_member(struct igmp_group *group, u8_t maxresp) * @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 == IP_ADDR_ANY, the + * @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 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 @@ -743,7 +758,7 @@ igmp_send(struct netif *netif, struct igmp_group *group, u8_t type) { struct pbuf* p = NULL; struct igmp_msg* igmp = NULL; - ip4_addr_t src = *IP4_ADDR_ANY; + ip4_addr_t src = *IP4_ADDR_ANY4; ip4_addr_t* dest = NULL; /* IP header + "router alert" option + IGMP header */ http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/ipv4/ip4.c ---------------------------------------------------------------------- diff --git a/net/ip/lwip_base/src/core/ipv4/ip4.c b/net/ip/lwip_base/src/core/ipv4/ip4.c index 27747ea..4e4eb61 100644 --- a/net/ip/lwip_base/src/core/ipv4/ip4.c +++ b/net/ip/lwip_base/src/core/ipv4/ip4.c @@ -59,6 +59,10 @@ #include <string.h> +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + /** Set this to 0 in the rare case of wanting to call an extra function to * generate the IP checksum (in contrast to calculating it on-the-fly). */ #ifndef LWIP_INLINE_IP_CHKSUM @@ -177,7 +181,7 @@ ip4_route(const ip4_addr_t *dest) /* loopif is disabled, looopback traffic is passed through any netif */ if (ip4_addr_isloopback(dest)) { /* don't check for link on loopback traffic */ - if (netif_is_up(netif_default)) { + if (netif_default != NULL && netif_is_up(netif_default)) { return netif_default; } /* default netif is not up, just use any netif for loopback traffic */ @@ -222,13 +226,12 @@ ip4_route(const ip4_addr_t *dest) * that may not be forwarded, or whether datagrams to that destination * may be forwarded. * @param p the packet to forward - * @param dest the destination IP address * @return 1: can forward 0: discard */ static int ip4_canforward(struct pbuf *p) { - u32_t addr = htonl(ip4_addr_get_u32(ip4_current_dest_addr())); + u32_t addr = lwip_htonl(ip4_addr_get_u32(ip4_current_dest_addr())); if (p->flags & PBUF_FLAG_LLBCAST) { /* don't route link-layer broadcasts */ @@ -405,7 +408,7 @@ ip4_input(struct pbuf *p, struct netif *inp) /* calculate IP header length in bytes */ iphdr_hlen *= 4; /* obtain ip length in bytes */ - iphdr_len = ntohs(IPH_LEN(iphdr)); + iphdr_len = lwip_ntohs(IPH_LEN(iphdr)); /* Trim pbuf. This is especially required for packets < 60 bytes. */ if (iphdr_len < p->tot_len) { @@ -519,6 +522,15 @@ ip4_input(struct pbuf *p, struct netif *inp) #endif /* LWIP_AUTOIP */ } if (first) { +#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF + /* Packets sent to the loopback address must not be accepted on an + * interface that does not have the loopback address assigned to it, + * unless a non-loopback interface is used for loopback traffic. */ + if (ip4_addr_isloopback(ip4_current_dest_addr())) { + netif = NULL; + break; + } +#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */ first = 0; netif = netif_list; } else { @@ -545,7 +557,7 @@ ip4_input(struct pbuf *p, struct netif *inp) if (IPH_PROTO(iphdr) == IP_PROTO_UDP) { struct udp_hdr *udphdr = (struct udp_hdr *)((u8_t *)iphdr + iphdr_hlen); LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: UDP packet to DHCP client port %"U16_F"\n", - ntohs(udphdr->dest))); + lwip_ntohs(udphdr->dest))); if (IP_ACCEPT_LINK_LAYER_ADDRESSED_PORT(udphdr->dest)) { LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_TRACE, ("ip4_input: DHCP packet accepted.\n")); netif = inp; @@ -590,6 +602,7 @@ ip4_input(struct pbuf *p, struct netif *inp) } else #endif /* IP_FORWARD */ { + IP_STATS_INC(ip.drop); MIB2_STATS_INC(mib2.ipinaddrerrors); MIB2_STATS_INC(mib2.ipindiscards); } @@ -600,7 +613,7 @@ ip4_input(struct pbuf *p, struct netif *inp) if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) { #if IP_REASSEMBLY /* packet fragment reassembly code present? */ LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip4_reass()\n", - ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), (u16_t)!!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (u16_t)((ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8))); + lwip_ntohs(IPH_ID(iphdr)), p->tot_len, lwip_ntohs(IPH_LEN(iphdr)), (u16_t)!!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (u16_t)((lwip_ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8))); /* reassemble the packet*/ p = ip4_reass(p); /* packet not fully reassembled yet? */ @@ -611,7 +624,7 @@ ip4_input(struct pbuf *p, struct netif *inp) #else /* IP_REASSEMBLY == 0, no packet fragment reassembly code present */ pbuf_free(p); LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("IP packet dropped since it was fragmented (0x%"X16_F") (while IP_REASSEMBLY == 0).\n", - ntohs(IPH_OFFSET(iphdr)))); + lwip_ntohs(IPH_OFFSET(iphdr)))); IP_STATS_INC(ip.opterr); IP_STATS_INC(ip.drop); /* unsupported protocol feature */ @@ -724,7 +737,7 @@ ip4_input(struct pbuf *p, struct netif *inp) * @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 == IP_ADDR_ANY, the + * @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 @@ -854,7 +867,7 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d IPH_TTL_SET(iphdr, ttl); IPH_PROTO_SET(iphdr, proto); #if CHECKSUM_GEN_IP_INLINE - chk_sum += LWIP_MAKE_U16(proto, ttl); + chk_sum += PP_NTOHS(proto | (ttl << 8)); #endif /* CHECKSUM_GEN_IP_INLINE */ /* dest cannot be NULL here */ @@ -867,21 +880,21 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d IPH_VHL_SET(iphdr, 4, ip_hlen / 4); IPH_TOS_SET(iphdr, tos); #if CHECKSUM_GEN_IP_INLINE - chk_sum += LWIP_MAKE_U16(tos, iphdr->_v_hl); + chk_sum += PP_NTOHS(tos | (iphdr->_v_hl << 8)); #endif /* CHECKSUM_GEN_IP_INLINE */ - IPH_LEN_SET(iphdr, htons(p->tot_len)); + IPH_LEN_SET(iphdr, lwip_htons(p->tot_len)); #if CHECKSUM_GEN_IP_INLINE chk_sum += iphdr->_len; #endif /* CHECKSUM_GEN_IP_INLINE */ IPH_OFFSET_SET(iphdr, 0); - IPH_ID_SET(iphdr, htons(ip_id)); + IPH_ID_SET(iphdr, lwip_htons(ip_id)); #if CHECKSUM_GEN_IP_INLINE chk_sum += iphdr->_id; #endif /* CHECKSUM_GEN_IP_INLINE */ ++ip_id; if (src == NULL) { - ip4_addr_copy(iphdr->src, *IP4_ADDR_ANY); + ip4_addr_copy(iphdr->src, *IP4_ADDR_ANY4); } else { /* src cannot be NULL here */ ip4_addr_copy(iphdr->src, *src); @@ -955,7 +968,7 @@ ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *d * @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 == IP_ADDR_ANY, the + * @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 @@ -990,7 +1003,7 @@ ip4_output(struct pbuf *p, const ip4_addr_t *src, const ip4_addr_t *dest, * @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 == IP_ADDR_ANY, the + * @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 @@ -1041,19 +1054,19 @@ ip4_debug_print(struct pbuf *p) (u16_t)IPH_V(iphdr), (u16_t)IPH_HL(iphdr), (u16_t)IPH_TOS(iphdr), - ntohs(IPH_LEN(iphdr)))); + lwip_ntohs(IPH_LEN(iphdr)))); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(IP_DEBUG, ("| %5"U16_F" |%"U16_F"%"U16_F"%"U16_F"| %4"U16_F" | (id, flags, offset)\n", - ntohs(IPH_ID(iphdr)), - (u16_t)(ntohs(IPH_OFFSET(iphdr)) >> 15 & 1), - (u16_t)(ntohs(IPH_OFFSET(iphdr)) >> 14 & 1), - (u16_t)(ntohs(IPH_OFFSET(iphdr)) >> 13 & 1), - (u16_t)(ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK))); + lwip_ntohs(IPH_ID(iphdr)), + (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 15 & 1), + (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 14 & 1), + (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) >> 13 & 1), + (u16_t)(lwip_ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK))); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | 0x%04"X16_F" | (ttl, proto, chksum)\n", (u16_t)IPH_TTL(iphdr), (u16_t)IPH_PROTO(iphdr), - ntohs(IPH_CHKSUM(iphdr)))); + lwip_ntohs(IPH_CHKSUM(iphdr)))); LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n")); LWIP_DEBUGF(IP_DEBUG, ("| %3"U16_F" | %3"U16_F" | %3"U16_F" | %3"U16_F" | (src)\n", ip4_addr1_16(&iphdr->src), http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/ipv4/ip4_addr.c ---------------------------------------------------------------------- diff --git a/net/ip/lwip_base/src/core/ipv4/ip4_addr.c b/net/ip/lwip_base/src/core/ipv4/ip4_addr.c index 7fe35c9..2d47992 100644 --- a/net/ip/lwip_base/src/core/ipv4/ip4_addr.c +++ b/net/ip/lwip_base/src/core/ipv4/ip4_addr.c @@ -43,7 +43,7 @@ #include "lwip/ip_addr.h" #include "lwip/netif.h" -/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ +/* used by IP4_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */ const ip_addr_t ip_addr_any = IPADDR4_INIT(IPADDR_ANY); const ip_addr_t ip_addr_broadcast = IPADDR4_INIT(IPADDR_BROADCAST); @@ -183,10 +183,10 @@ ip4addr_aton(const char *cp, ip4_addr_t *addr) } for (;;) { if (isdigit(c)) { - val = (val * base) + (int)(c - '0'); + val = (val * base) + (u32_t)(c - '0'); c = *++cp; } else if (base == 16 && isxdigit(c)) { - val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A')); + val = (val << 4) | (u32_t)(c + 10 - (islower(c) ? 'a' : 'A')); c = *++cp; } else { break; @@ -260,7 +260,7 @@ ip4addr_aton(const char *cp, ip4_addr_t *addr) break; } if (addr) { - ip4_addr_set_u32(addr, htonl(val)); + ip4_addr_set_u32(addr, lwip_htonl(val)); } return 1; } @@ -310,7 +310,7 @@ ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen) do { rem = *ap % (u8_t)10; *ap /= (u8_t)10; - inv[i++] = '0' + rem; + inv[i++] = (char)('0' + rem); } while (*ap); while (i--) { if (len++ >= buflen) { http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/ipv4/ip4_frag.c ---------------------------------------------------------------------- diff --git a/net/ip/lwip_base/src/core/ipv4/ip4_frag.c b/net/ip/lwip_base/src/core/ipv4/ip4_frag.c index 50edd12..57fb44c 100644 --- a/net/ip/lwip_base/src/core/ipv4/ip4_frag.c +++ b/net/ip/lwip_base/src/core/ipv4/ip4_frag.c @@ -160,7 +160,7 @@ static int ip_reass_free_complete_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) { u16_t pbufs_freed = 0; - u8_t clen; + u16_t clen; struct pbuf *p; struct ip_reass_helper *iprh; @@ -331,7 +331,7 @@ ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev) * 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 root_p points to the 'root' pbuf for the current datagram being assembled. + * @param ipr points to the reassembly state * @param new_p points to the pbuf for the current fragment * @return 0 if invalid, >0 otherwise */ @@ -346,8 +346,8 @@ ip_reass_chain_frag_into_datagram_and_validate(struct ip_reassdata *ipr, struct /* Extract length and fragment offset from current fragment */ fraghdr = (struct ip_hdr*)new_p->payload; - len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; - offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; /* overwrite the fragment's ip header from the pbuf with our helper struct, * and setup the embedded helper structure. */ @@ -487,8 +487,7 @@ ip4_reass(struct pbuf *p) struct ip_hdr *fraghdr; struct ip_reassdata *ipr; struct ip_reass_helper *iprh; - u16_t offset, len; - u8_t clen; + u16_t offset, len, clen; IPFRAG_STATS_INC(ip_frag.recv); MIB2_STATS_INC(mib2.ipreasmreqds); @@ -501,8 +500,8 @@ ip4_reass(struct pbuf *p) goto nullreturn; } - offset = (ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; - len = ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; + offset = (lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) * 8; + len = lwip_ntohs(IPH_LEN(fraghdr)) - IPH_HL(fraghdr) * 4; /* Check if we are allowed to enqueue more datagrams. */ clen = pbuf_clen(p); @@ -530,7 +529,7 @@ ip4_reass(struct pbuf *p) fragment into the buffer. */ if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) { LWIP_DEBUGF(IP_REASS_DEBUG, ("ip4_reass: matching previous fragment ID=%"X16_F"\n", - ntohs(IPH_ID(fraghdr)))); + lwip_ntohs(IPH_ID(fraghdr)))); IPFRAG_STATS_INC(ip_frag.cachehit); break; } @@ -544,8 +543,8 @@ ip4_reass(struct pbuf *p) goto nullreturn; } } else { - if (((ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && - ((ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { + if (((lwip_ntohs(IPH_OFFSET(fraghdr)) & IP_OFFMASK) == 0) && + ((lwip_ntohs(IPH_OFFSET(&ipr->iphdr)) & IP_OFFMASK) != 0)) { /* 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 @@ -582,7 +581,7 @@ ip4_reass(struct pbuf *p) /* copy the original ip header back to the first pbuf */ fraghdr = (struct ip_hdr*)(ipr->p->payload); SMEMCPY(fraghdr, &ipr->iphdr, IP_HLEN); - IPH_LEN_SET(fraghdr, htons(ipr->datagram_len)); + IPH_LEN_SET(fraghdr, lwip_htons(ipr->datagram_len)); IPH_OFFSET_SET(fraghdr, 0); IPH_CHKSUM_SET(fraghdr, 0); /* @todo: do we need to set/calculate the correct checksum? */ @@ -688,53 +687,41 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) struct pbuf *rambuf; #if !LWIP_NETIF_TX_SINGLE_PBUF struct pbuf *newpbuf; + u16_t newpbuflen = 0; + u16_t left_to_copy; #endif struct ip_hdr *original_iphdr; struct ip_hdr *iphdr; - u16_t nfb; - u16_t left, cop; - u16_t mtu = netif->mtu; - u16_t ofo, omf; - u16_t last; + const u16_t nfb = (netif->mtu - IP_HLEN) / 8; + u16_t left, fragsize; + u16_t ofo; + int last; u16_t poff = IP_HLEN; u16_t tmp; -#if !LWIP_NETIF_TX_SINGLE_PBUF - u16_t newpbuflen = 0; - u16_t left_to_copy; -#endif original_iphdr = (struct ip_hdr *)p->payload; iphdr = original_iphdr; + LWIP_ERROR("ip4_frag() does not support IP options", IPH_HL(iphdr) * 4 == IP_HLEN, return ERR_VAL); /* Save original offset */ - tmp = ntohs(IPH_OFFSET(iphdr)); + tmp = lwip_ntohs(IPH_OFFSET(iphdr)); ofo = tmp & IP_OFFMASK; - omf = tmp & IP_MF; + LWIP_ERROR("ip_frag(): MF already set", (tmp & IP_MF) == 0, return ERR_VAL); left = p->tot_len - IP_HLEN; - nfb = (mtu - IP_HLEN) / 8; - while (left) { - last = (left <= mtu - IP_HLEN); - - /* Set new offset and MF flag */ - tmp = omf | (IP_OFFMASK & (ofo)); - if (!last) { - tmp = tmp | IP_MF; - } - /* Fill this fragment */ - cop = last ? left : nfb * 8; + fragsize = LWIP_MIN(left, nfb * 8); #if LWIP_NETIF_TX_SINGLE_PBUF - rambuf = pbuf_alloc(PBUF_IP, cop, PBUF_RAM); + 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, cop, poff); + poff += pbuf_copy_partial(p, rambuf->payload, fragsize, poff); /* make room for the IP header */ if (pbuf_header(rambuf, IP_HLEN)) { pbuf_free(rambuf); @@ -758,16 +745,14 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) SMEMCPY(rambuf->payload, original_iphdr, IP_HLEN); iphdr = (struct ip_hdr *)rambuf->payload; - /* Can just adjust p directly for needed offset. */ - p->payload = (u8_t *)p->payload + poff; - p->len -= poff; - - left_to_copy = cop; + left_to_copy = fragsize; while (left_to_copy) { struct pbuf_custom_ref *pcr; - newpbuflen = (left_to_copy < p->len) ? left_to_copy : p->len; + u16_t plen = p->len - poff; + newpbuflen = LWIP_MIN(left_to_copy, plen); /* Is this pbuf already empty? */ if (!newpbuflen) { + poff = 0; p = p->next; continue; } @@ -777,7 +762,8 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) goto memerr; } /* Mirror this pbuf, although we might not need all of it. */ - newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, p->payload, newpbuflen); + newpbuf = pbuf_alloced_custom(PBUF_RAW, newpbuflen, PBUF_REF, &pcr->pc, + (u8_t*)p->payload + poff, newpbuflen); if (newpbuf == NULL) { ip_frag_free_pbuf_custom_ref(pcr); pbuf_free(rambuf); @@ -793,15 +779,23 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) pbuf_cat(rambuf, newpbuf); left_to_copy -= newpbuflen; if (left_to_copy) { + poff = 0; p = p->next; } } - poff = newpbuflen; + poff += newpbuflen; #endif /* LWIP_NETIF_TX_SINGLE_PBUF */ /* Correct header */ - IPH_OFFSET_SET(iphdr, htons(tmp)); - IPH_LEN_SET(iphdr, htons(cop + IP_HLEN)); + last = (left <= netif->mtu - IP_HLEN); + + /* Set new offset and MF flag */ + tmp = (IP_OFFMASK & (ofo)); + if (!last) { + tmp = tmp | IP_MF; + } + IPH_OFFSET_SET(iphdr, lwip_htons(tmp)); + IPH_LEN_SET(iphdr, lwip_htons(fragsize + IP_HLEN)); IPH_CHKSUM_SET(iphdr, 0); #if CHECKSUM_GEN_IP IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) { @@ -823,7 +817,7 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest) */ pbuf_free(rambuf); - left -= cop; + left -= fragsize; ofo += nfb; } MIB2_STATS_INC(mib2.ipfragoks); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/ipv6/ethip6.c ---------------------------------------------------------------------- diff --git a/net/ip/lwip_base/src/core/ipv6/ethip6.c b/net/ip/lwip_base/src/core/ipv6/ethip6.c index 1ae784f..8f9a91b 100644 --- a/net/ip/lwip_base/src/core/ipv6/ethip6.c +++ b/net/ip/lwip_base/src/core/ipv6/ethip6.c @@ -62,7 +62,9 @@ * For IPv6 multicast, corresponding Ethernet addresses * are selected and the packet is transmitted on the link. * - * For unicast addresses, ... + * For unicast addresses, ask the ND6 module what to do. It will either let us + * send the the packet right away, or queue the packet for later itself, unless + * an error occurs. * * @todo anycast addresses * @@ -71,14 +73,14 @@ * @param ip6addr 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_OK or the return value of @ref nd6_get_next_hop_addr_or_queue. */ err_t ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) { struct eth_addr dest; - s8_t i; + const u8_t *hwaddr; + err_t result; /* multicast destination IP address? */ if (ip6_addr_ismulticast(ip6addr)) { @@ -91,36 +93,26 @@ ethip6_output(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr) dest.addr[5] = ((const u8_t *)(&(ip6addr->addr[3])))[3]; /* Send out. */ - return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6); + return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6); } /* We have a unicast destination IP address */ /* @todo anycast? */ - /* Get next hop record. */ - i = nd6_get_next_hop_entry(ip6addr, netif); - if (i < 0) { - /* failed to get a next hop neighbor record. */ - return ERR_MEM; - } - /* Now that we have a destination record, send or queue the packet. */ - if (neighbor_cache[i].state == ND6_STALE) { - /* Switch to delay state. */ - neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + /* Ask ND6 what to do with the packet. */ + result = nd6_get_next_hop_addr_or_queue(netif, q, ip6addr, &hwaddr); + if (result != ERR_OK) { + return result; } - /* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */ - if ((neighbor_cache[i].state == ND6_REACHABLE) || - (neighbor_cache[i].state == ND6_DELAY) || - (neighbor_cache[i].state == ND6_PROBE)) { - /* Send out. */ - SMEMCPY(dest.addr, neighbor_cache[i].lladdr, 6); - return ethernet_output(netif, q, (struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6); + /* If no hardware address is returned, nd6 has queued the packet for later. */ + if (hwaddr == NULL) { + return ERR_OK; } - /* We should queue packet on this interface. */ - return nd6_queue_packet(i, q); + /* Send out the packet using the returned hardware address. */ + SMEMCPY(dest.addr, hwaddr, 6); + return ethernet_output(netif, q, (const struct eth_addr*)(netif->hwaddr), &dest, ETHTYPE_IPV6); } #endif /* LWIP_IPV6 && LWIP_ETHERNET */ http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/ipv6/ip6.c ---------------------------------------------------------------------- diff --git a/net/ip/lwip_base/src/core/ipv6/ip6.c b/net/ip/lwip_base/src/core/ipv6/ip6.c index 8cc9c01..f14e334 100644 --- a/net/ip/lwip_base/src/core/ipv6/ip6.c +++ b/net/ip/lwip_base/src/core/ipv6/ip6.c @@ -60,6 +60,10 @@ #include "lwip/debug.h" #include "lwip/stats.h" +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + /** * Finds the appropriate network interface for a given IPv6 address. It tries to select * a netif following a sequence of heuristics: @@ -94,7 +98,8 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) if (ip6_addr_islinklocal(dest)) { if (ip6_addr_isany(src)) { /* Use default netif, if Up. */ - if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) { + if (netif_default == NULL || !netif_is_up(netif_default) || + !netif_is_link_up(netif_default)) { return NULL; } return netif_default; @@ -114,7 +119,8 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) } /* netif not found, use default netif, if up */ - if (!netif_is_up(netif_default) || !netif_is_link_up(netif_default)) { + if (netif_default == NULL || !netif_is_up(netif_default) || + !netif_is_link_up(netif_default)) { return NULL; } return netif_default; @@ -142,15 +148,9 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) } /* Get the netif for a suitable router. */ - i = nd6_select_router(dest, NULL); - if (i >= 0) { - if (default_router_list[i].neighbor_entry != NULL) { - if (default_router_list[i].neighbor_entry->netif != NULL) { - if (netif_is_up(default_router_list[i].neighbor_entry->netif) && netif_is_link_up(default_router_list[i].neighbor_entry->netif)) { - return default_router_list[i].neighbor_entry->netif; - } - } - } + netif = nd6_find_route(dest); + if ((netif != NULL) && netif_is_up(netif) && netif_is_link_up(netif)) { + return netif; } /* try with the netif that matches the source address. */ @@ -172,7 +172,7 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest) /* loopif is disabled, loopback traffic is passed through any netif */ if (ip6_addr_isloopback(dest)) { /* don't check for link on loopback traffic */ - if (netif_is_up(netif_default)) { + if (netif_default != NULL && netif_is_up(netif_default)) { return netif_default; } /* default netif is not up, just use any netif for loopback traffic */ @@ -290,8 +290,9 @@ ip6_forward(struct pbuf *p, struct ip6_hdr *iphdr, struct netif *inp) { struct netif *netif; - /* do not forward link-local addresses */ - if (ip6_addr_islinklocal(ip6_current_dest_addr())) { + /* do not forward link-local or loopback addresses */ + if (ip6_addr_islinklocal(ip6_current_dest_addr()) || + ip6_addr_isloopback(ip6_current_dest_addr())) { LWIP_DEBUGF(IP6_DEBUG, ("ip6_forward: not forwarding link-local address.\n")); IP6_STATS_INC(ip6.rterr); IP6_STATS_INC(ip6.drop); @@ -446,9 +447,11 @@ ip6_input(struct pbuf *p, struct netif *inp) ip_addr_copy_from_ip6(ip_data.current_iphdr_dest, ip6hdr->dest); ip_addr_copy_from_ip6(ip_data.current_iphdr_src, ip6hdr->src); - /* Don't accept virtual IPv6 mapped IPv4 addresses */ - if (ip6_addr_isipv6mappedipv4(ip_2_ip6(&ip_data.current_iphdr_dest)) || - ip6_addr_isipv6mappedipv4(ip_2_ip6(&ip_data.current_iphdr_src)) ) { + /* Don't accept virtual IPv4 mapped IPv6 addresses. + * Don't accept multicast source addresses. */ + if (ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_dest)) || + ip6_addr_isipv4mappedipv6(ip_2_ip6(&ip_data.current_iphdr_src)) || + ip6_addr_ismulticast(ip_2_ip6(&ip_data.current_iphdr_src))) { IP6_STATS_INC(ip6.err); IP6_STATS_INC(ip6.drop); return ERR_OK; @@ -509,12 +512,21 @@ ip6_input(struct pbuf *p, struct netif *inp) } } } - if (ip6_addr_islinklocal(ip6_current_dest_addr())) { - /* Do not match link-local addresses to other netifs. */ - netif = NULL; - break; - } if (first) { + if (ip6_addr_islinklocal(ip6_current_dest_addr()) +#if !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF + || ip6_addr_isloopback(ip6_current_dest_addr()) +#endif /* !LWIP_NETIF_LOOPBACK || LWIP_HAVE_LOOPIF */ + ) { + /* Do not match link-local addresses to other netifs. The loopback + * address is to be considered link-local and packets to it should be + * dropped on other interfaces, as per RFC 4291 Sec. 2.5.3. This + * requirement cannot be implemented in the case that loopback + * traffic is sent across a non-loopback interface, however. + */ + netif = NULL; + break; + } first = 0; netif = netif_list; } else { @@ -709,7 +721,7 @@ netif_found: options_done: /* p points to IPv6 header again. */ - pbuf_header_force(p, ip_data.current_ip_header_tot_len); + pbuf_header_force(p, (s16_t)ip_data.current_ip_header_tot_len); /* send to upper layers */ LWIP_DEBUGF(IP6_DEBUG, ("ip6_input: \n")); @@ -809,8 +821,8 @@ ip6_output_if(struct pbuf *p, const ip6_addr_t *src, const ip6_addr_t *dest, const ip6_addr_t *src_used = src; if (dest != LWIP_IP_HDRINCL) { if (src != NULL && ip6_addr_isany(src)) { - src = ip_2_ip6(ip6_select_source_address(netif, dest)); - if ((src == NULL) || ip6_addr_isany(src)) { + src_used = ip_2_ip6(ip6_select_source_address(netif, dest)); + if ((src_used == NULL) || ip6_addr_isany(src_used)) { /* No appropriate source address was found for this packet. */ LWIP_DEBUGF(IP6_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip6_output: No suitable source address for packet.\n")); IP6_STATS_INC(ip6.rterr); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/ipv6/ip6_addr.c ---------------------------------------------------------------------- diff --git a/net/ip/lwip_base/src/core/ipv6/ip6_addr.c b/net/ip/lwip_base/src/core/ipv6/ip6_addr.c index 1792f62..aa06659 100644 --- a/net/ip/lwip_base/src/core/ipv6/ip6_addr.c +++ b/net/ip/lwip_base/src/core/ipv6/ip6_addr.c @@ -132,8 +132,8 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr) } else if (isxdigit(*s)) { /* add current digit */ current_block_value = (current_block_value << 4) + - (isdigit(*s) ? *s - '0' : - 10 + (islower(*s) ? *s - 'a' : *s - 'A')); + (isdigit(*s) ? (u32_t)(*s - '0') : + (u32_t)(10 + (islower(*s) ? *s - 'a' : *s - 'A'))); } else { /* unexpected digit, space? CRLF? */ break; @@ -152,7 +152,7 @@ ip6addr_aton(const char *cp, ip6_addr_t *addr) /* convert to network byte order. */ if (addr) { for (addr_index = 0; addr_index < 4; addr_index++) { - addr->addr[addr_index] = htonl(addr->addr[addr_index]); + addr->addr[addr_index] = lwip_htonl(addr->addr[addr_index]); } } @@ -199,7 +199,7 @@ ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) for (current_block_index = 0; current_block_index < 8; current_block_index++) { /* get the current 16-bit block */ - current_block_value = htonl(addr->addr[current_block_index >> 1]); + current_block_value = lwip_htonl(addr->addr[current_block_index >> 1]); if ((current_block_index & 0x1) == 0) { current_block_value = current_block_value >> 16; } @@ -218,7 +218,7 @@ ip6addr_ntoa_r(const ip6_addr_t *addr, char *buf, int buflen) if (empty_block_flag == 0) { /* generate empty block "::", but only if more than one contiguous zero block, * according to current formatting suggestions RFC 5952. */ - next_block_value = htonl(addr->addr[(current_block_index + 1) >> 1]); + next_block_value = lwip_htonl(addr->addr[(current_block_index + 1) >> 1]); if ((current_block_index & 0x1) == 0x01) { next_block_value = next_block_value >> 16; } http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/ipv6/ip6_frag.c ---------------------------------------------------------------------- diff --git a/net/ip/lwip_base/src/core/ipv6/ip6_frag.c b/net/ip/lwip_base/src/core/ipv6/ip6_frag.c index f41d167..ff07f71 100644 --- a/net/ip/lwip_base/src/core/ipv6/ip6_frag.c +++ b/net/ip/lwip_base/src/core/ipv6/ip6_frag.c @@ -147,7 +147,7 @@ ip6_reass_free_complete_datagram(struct ip6_reassdata *ipr) { struct ip6_reassdata *prev; u16_t pbufs_freed = 0; - u8_t clen; + u16_t clen; struct pbuf *p; struct ip6_reass_helper *iprh; @@ -262,7 +262,8 @@ ip6_reass(struct pbuf *p) struct ip6_reass_helper *iprh, *iprh_tmp, *iprh_prev=NULL; struct ip6_frag_hdr *frag_hdr; u16_t offset, len; - u8_t clen, valid = 1; + u16_t clen; + u8_t valid = 1; struct pbuf *q; IP6_FRAG_STATS_INC(ip6_frag.recv); @@ -278,12 +279,12 @@ ip6_reass(struct pbuf *p) clen = pbuf_clen(p); - offset = ntohs(frag_hdr->_fragment_offset); + offset = lwip_ntohs(frag_hdr->_fragment_offset); /* Calculate fragment length from IPv6 payload length. * Adjust for headers before Fragment Header. * And finally adjust by Fragment Header length. */ - len = ntohs(ip6_current_header()->_plen); + len = lwip_ntohs(ip6_current_header()->_plen); len -= (u16_t)(((u8_t*)p->payload - (const u8_t*)ip6_current_header()) - IP6_HLEN); len -= IP6_FRAG_HLEN; @@ -378,6 +379,7 @@ ip6_reass(struct pbuf *p) /* Make room for struct ip6_reass_helper (only required if sizeof(void*) > 4). This cannot fail since we already checked when receiving this fragment. */ u8_t hdrerr = pbuf_header_force(p, IPV6_FRAG_REQROOM); + LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */ LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); } #else /* IPV6_FRAG_COPYHEADER */ @@ -529,6 +531,7 @@ ip6_reass(struct pbuf *p) if (IPV6_FRAG_REQROOM > 0) { /* hide the extra bytes borrowed from ip6_hdr for struct ip6_reass_helper */ u8_t hdrerr = pbuf_header(next_pbuf, -(s16_t)(IPV6_FRAG_REQROOM)); + LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */ LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); } #endif @@ -545,6 +548,7 @@ ip6_reass(struct pbuf *p) if (IPV6_FRAG_REQROOM > 0) { /* get back room for struct ip6_reass_helper (only required if sizeof(void*) > 4) */ u8_t hdrerr = pbuf_header(ipr->p, -(s16_t)(IPV6_FRAG_REQROOM)); + LWIP_UNUSED_ARG(hdrerr); /* in case of LWIP_NOASSERT */ LWIP_ASSERT("no room for struct ip6_reass_helper", hdrerr == 0); } iphdr_ptr = (struct ip6_hdr*)((u8_t*)ipr->p->payload - IP6_HLEN); @@ -559,7 +563,7 @@ ip6_reass(struct pbuf *p) - IP6_HLEN); /* Set payload length in ip header. */ - iphdr_ptr->_plen = htons(ipr->datagram_len); + iphdr_ptr->_plen = lwip_htons(ipr->datagram_len); /* Get the first pbuf. */ p = ipr->p; @@ -609,6 +613,7 @@ nullreturn: #if LWIP_IPV6 && LWIP_IPV6_FRAG +#if !LWIP_NETIF_TX_SINGLE_PBUF /** Allocate a new struct pbuf_custom_ref */ static struct pbuf_custom_ref* ip6_frag_alloc_pbuf_custom_ref(void) @@ -637,6 +642,7 @@ ip6_frag_free_pbuf_custom(struct pbuf *p) } ip6_frag_free_pbuf_custom_ref(pcr); } +#endif /* !LWIP_NETIF_TX_SINGLE_PBUF */ /** * Fragment an IPv6 datagram if too large for the netif or path MTU. @@ -657,7 +663,11 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) struct ip6_hdr *ip6hdr; struct ip6_frag_hdr *frag_hdr; struct pbuf *rambuf; +#if !LWIP_NETIF_TX_SINGLE_PBUF struct pbuf *newpbuf; + u16_t newpbuflen = 0; + u16_t left_to_copy; +#endif static u32_t identification; u16_t nfb; u16_t left, cop; @@ -665,8 +675,6 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) u16_t fragment_offset = 0; u16_t last; u16_t poff = IP6_HLEN; - u16_t newpbuflen = 0; - u16_t left_to_copy; identification++; @@ -685,6 +693,26 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) /* Fill this fragment */ cop = last ? left : nfb; +#if LWIP_NETIF_TX_SINGLE_PBUF + rambuf = pbuf_alloc(PBUF_IP, cop + IP6_FRAG_HLEN, PBUF_RAM); + if (rambuf == NULL) { + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + LWIP_ASSERT("this needs a pbuf in one piece!", + (rambuf->len == rambuf->tot_len) && (rambuf->next == NULL)); + poff += pbuf_copy_partial(p, (u8_t*)rambuf->payload + IP6_FRAG_HLEN, cop, poff); + /* make room for the IP header */ + if (pbuf_header(rambuf, IP6_HLEN)) { + pbuf_free(rambuf); + IP6_FRAG_STATS_INC(ip6_frag.memerr); + return ERR_MEM; + } + /* fill in the IP header */ + SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN); + ip6hdr = (struct ip6_hdr *)rambuf->payload; + frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN); +#else /* When not using a static buffer, create a chain of pbufs. * The first will be a PBUF_RAM holding the link, IPv6, and Fragment header. * The rest will be PBUF_REFs mirroring the pbuf chain to be fragged, @@ -696,7 +724,7 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) return ERR_MEM; } LWIP_ASSERT("this needs a pbuf in one piece!", - (p->len >= (IP6_HLEN + IP6_FRAG_HLEN))); + (p->len >= (IP6_HLEN))); SMEMCPY(rambuf->payload, original_ip6hdr, IP6_HLEN); ip6hdr = (struct ip6_hdr *)rambuf->payload; frag_hdr = (struct ip6_frag_hdr *)((u8_t*)rambuf->payload + IP6_HLEN); @@ -743,12 +771,13 @@ ip6_frag(struct pbuf *p, struct netif *netif, const ip6_addr_t *dest) } } poff = newpbuflen; +#endif /* LWIP_NETIF_TX_SINGLE_PBUF */ /* Set headers */ frag_hdr->_nexth = original_ip6hdr->_nexth; frag_hdr->reserved = 0; - frag_hdr->_fragment_offset = htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG)); - frag_hdr->_identification = htonl(identification); + frag_hdr->_fragment_offset = lwip_htons((fragment_offset & IP6_FRAG_OFFSET_MASK) | (last ? 0 : IP6_FRAG_MORE_FLAG)); + frag_hdr->_identification = lwip_htonl(identification); IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT); IP6H_PLEN_SET(ip6hdr, cop + IP6_FRAG_HLEN); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/ipv6/mld6.c ---------------------------------------------------------------------- diff --git a/net/ip/lwip_base/src/core/ipv6/mld6.c b/net/ip/lwip_base/src/core/ipv6/mld6.c index 2ebcff3..9acb82f 100644 --- a/net/ip/lwip_base/src/core/ipv6/mld6.c +++ b/net/ip/lwip_base/src/core/ipv6/mld6.c @@ -564,7 +564,7 @@ mld6_send(struct netif *netif, struct mld_group *group, u8_t type) ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address)); #if CHECKSUM_GEN_ICMP6 - IF__NETIF_CHECKSUM_ENABLED(group->netif, NETIF_CHECKSUM_GEN_ICMP6) { + IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) { mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr, &(group->group_address)); } @@ -573,6 +573,11 @@ mld6_send(struct netif *netif, struct mld_group *group, u8_t type) /* Add hop-by-hop headers options: router alert with MLD value. */ ip6_options_add_hbh_ra(p, IP6_NEXTH_ICMP6, IP6_ROUTER_ALERT_VALUE_MLD); + if (type == ICMP6_TYPE_MLR) { + /* Remember we were the last to report */ + group->last_reporter_flag = 1; + } + /* Send the packet out. */ MLD6_STATS_INC(mld6.xmit); ip6_output_if(p, (ip6_addr_isany(src_addr)) ? NULL : src_addr, &(group->group_address), http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/ipv6/nd6.c ---------------------------------------------------------------------- diff --git a/net/ip/lwip_base/src/core/ipv6/nd6.c b/net/ip/lwip_base/src/core/ipv6/nd6.c index 7806f6e..0b36718 100644 --- a/net/ip/lwip_base/src/core/ipv6/nd6.c +++ b/net/ip/lwip_base/src/core/ipv6/nd6.c @@ -46,6 +46,7 @@ #if LWIP_IPV6 /* don't build if not configured for use in lwipopts.h */ #include "lwip/nd6.h" +#include "lwip/priv/nd6_priv.h" #include "lwip/prot/nd6.h" #include "lwip/prot/icmp6.h" #include "lwip/pbuf.h" @@ -59,9 +60,14 @@ #include "lwip/mld6.h" #include "lwip/ip.h" #include "lwip/stats.h" +#include "lwip/dns.h" #include <string.h> +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + #if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK #error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK #endif @@ -93,10 +99,13 @@ static void nd6_free_neighbor_cache_entry(s8_t i); static s8_t nd6_find_destination_cache_entry(const ip6_addr_t *ip6addr); static s8_t nd6_new_destination_cache_entry(void); static s8_t nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif); +static s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif); static s8_t nd6_get_router(const ip6_addr_t *router_addr, struct netif *netif); static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif); static s8_t nd6_get_onlink_prefix(ip6_addr_t *prefix, struct netif *netif); static s8_t nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif); +static s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif); +static err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf *q); #define ND6_SEND_FLAG_MULTICAST_DEST 0x01 #define ND6_SEND_FLAG_ALLNODES_DEST 0x02 @@ -149,50 +158,27 @@ nd6_input(struct pbuf *p, struct netif *inp) /* Unsolicited NA?*/ if (ip6_addr_ismulticast(ip6_current_dest_addr())) { + ip6_addr_t target_address; + /* This is an unsolicited NA. * link-layer changed? * part of DAD mechanism? */ - /* Check that link-layer address option also fits in packet. */ - if (p->len < (sizeof(struct na_header) + 2)) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); - - if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) { - /* @todo debug message */ - pbuf_free(p); - ND6_STATS_INC(nd6.lenerr); - ND6_STATS_INC(nd6.drop); - return; - } - - /* Override ip6_current_dest_addr() so that we have an aligned copy. */ - ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address)); + /* Create an aligned copy. */ + ip6_addr_set(&target_address, &(na_hdr->target_address)); #if LWIP_IPV6_DUP_DETECT_ATTEMPTS /* If the target address matches this netif, it is a DAD response. */ for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) && - ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) { + ip6_addr_cmp(&target_address, netif_ip6_addr(inp, i))) { /* We are using a duplicate address. */ netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID); -#if LWIP_IPV6_MLD - /* Leave solicited node multicast group. */ - ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(inp, i)->addr[3]); - mld6_leavegroup(netif_ip6_addr(inp, i), &multicast_address); -#endif /* LWIP_IPV6_MLD */ - #if LWIP_IPV6_AUTOCONFIG /* Check to see if this address was autoconfigured. */ - if (!ip6_addr_islinklocal(ip6_current_dest_addr())) { - i = nd6_get_onlink_prefix(ip6_current_dest_addr(), inp); + if (!ip6_addr_islinklocal(&target_address)) { + i = nd6_get_onlink_prefix(&target_address, inp); if (i >= 0) { /* Mark this prefix as duplicate, so that we don't use it * to generate this address again. */ @@ -207,23 +193,44 @@ nd6_input(struct pbuf *p, struct netif *inp) } #endif /* LWIP_IPV6_DUP_DETECT_ATTEMPTS */ + /* Check that link-layer address option also fits in packet. */ + if (p->len < (sizeof(struct na_header) + 2)) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + + lladdr_opt = (struct lladdr_option *)((u8_t*)p->payload + sizeof(struct na_header)); + + if (p->len < (sizeof(struct na_header) + (lladdr_opt->length << 3))) { + /* @todo debug message */ + pbuf_free(p); + ND6_STATS_INC(nd6.lenerr); + ND6_STATS_INC(nd6.drop); + return; + } + /* This is an unsolicited NA, most likely there was a LLADDR change. */ - i = nd6_find_neighbor_cache_entry(ip6_current_dest_addr()); + i = nd6_find_neighbor_cache_entry(&target_address); if (i >= 0) { if (na_hdr->flags & ND6_FLAG_OVERRIDE) { MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); } } } else { + ip6_addr_t target_address; + /* This is a solicited NA. * neighbor address resolution response? * neighbor unreachability detection response? */ - /* Override ip6_current_dest_addr() so that we have an aligned copy. */ - ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address)); + /* Create an aligned copy. */ + ip6_addr_set(&target_address, &(na_hdr->target_address)); /* Find the cache entry corresponding to this na. */ - i = nd6_find_neighbor_cache_entry(ip6_current_dest_addr()); + i = nd6_find_neighbor_cache_entry(&target_address); if (i < 0) { /* We no longer care about this target address. drop it. */ pbuf_free(p); @@ -231,8 +238,6 @@ nd6_input(struct pbuf *p, struct netif *inp) } /* Update cache entry. */ - neighbor_cache[i].netif = inp; - neighbor_cache[i].counter.reachable_time = reachable_time; if ((na_hdr->flags & ND6_FLAG_OVERRIDE) || (neighbor_cache[i].state == ND6_INCOMPLETE)) { /* Check that link-layer address option also fits in packet. */ @@ -256,7 +261,10 @@ nd6_input(struct pbuf *p, struct netif *inp) MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); } + + neighbor_cache[i].netif = inp; neighbor_cache[i].state = ND6_REACHABLE; + neighbor_cache[i].counter.reachable_time = reachable_time; /* Send queued packets, if any. */ if (neighbor_cache[i].q != NULL) { @@ -326,6 +334,8 @@ nd6_input(struct pbuf *p, struct netif *inp) } } } else { + ip6_addr_t target_address; + /* Sender is trying to resolve our address. */ /* Verify that they included their own link-layer address. */ if (lladdr_opt == NULL) { @@ -345,7 +355,7 @@ nd6_input(struct pbuf *p, struct netif *inp) /* Delay probe in case we get confirmation of reachability from upper layer (TCP). */ neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; } } else { /* Add their IPv6 address and link-layer address to neighbor cache. @@ -366,14 +376,14 @@ nd6_input(struct pbuf *p, struct netif *inp) /* Receiving a message does not prove reachability: only in one direction. * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; } - /* Override ip6_current_dest_addr() so that we have an aligned copy. */ - ip6_addr_set(ip6_current_dest_addr(), &(ns_hdr->target_address)); + /* Create an aligned copy. */ + ip6_addr_set(&target_address, &(ns_hdr->target_address)); /* Send back a NA for us. Allocate the reply pbuf. */ - nd6_send_na(inp, ip6_current_dest_addr(), ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE); + nd6_send_na(inp, &target_address, ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE); } break; /* ICMP6_TYPE_NS */ @@ -383,6 +393,10 @@ nd6_input(struct pbuf *p, struct netif *inp) struct ra_header *ra_hdr; u8_t *buffer; /* Used to copy options. */ u16_t offset; +#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS + /* There can by multiple RDNSS options per RA */ + u8_t rdnss_server_idx = 0; +#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */ /* Check that RA header fits in packet. */ if (p->len < sizeof(struct ra_header)) { @@ -419,15 +433,15 @@ nd6_input(struct pbuf *p, struct netif *inp) } /* Re-set invalidation timer. */ - default_router_list[i].invalidation_timer = htons(ra_hdr->router_lifetime); + default_router_list[i].invalidation_timer = lwip_htons(ra_hdr->router_lifetime); /* Re-set default timer values. */ #if LWIP_ND6_ALLOW_RA_UPDATES if (ra_hdr->retrans_timer > 0) { - retrans_timer = htonl(ra_hdr->retrans_timer); + retrans_timer = lwip_htonl(ra_hdr->retrans_timer); } if (ra_hdr->reachable_time > 0) { - reachable_time = htonl(ra_hdr->reachable_time); + reachable_time = lwip_htonl(ra_hdr->reachable_time); } #endif /* LWIP_ND6_ALLOW_RA_UPDATES */ @@ -478,9 +492,9 @@ nd6_input(struct pbuf *p, struct netif *inp) { struct mtu_option *mtu_opt; mtu_opt = (struct mtu_option *)buffer; - if (htonl(mtu_opt->mtu) >= 1280) { + if (lwip_htonl(mtu_opt->mtu) >= 1280) { #if LWIP_ND6_ALLOW_RA_UPDATES - inp->mtu = (u16_t)htonl(mtu_opt->mtu); + inp->mtu = (u16_t)lwip_htonl(mtu_opt->mtu); #endif /* LWIP_ND6_ALLOW_RA_UPDATES */ } break; @@ -495,18 +509,19 @@ nd6_input(struct pbuf *p, struct netif *inp) !ip6_addr_islinklocal(&(prefix_opt->prefix))) { /* Add to on-link prefix list. */ s8_t prefix; + ip6_addr_t prefix_addr; /* Get a memory-aligned copy of the prefix. */ - ip6_addr_set(ip6_current_dest_addr(), &(prefix_opt->prefix)); + ip6_addr_set(&prefix_addr, &(prefix_opt->prefix)); /* find cache entry for this prefix. */ - prefix = nd6_get_onlink_prefix(ip6_current_dest_addr(), inp); + prefix = nd6_get_onlink_prefix(&prefix_addr, inp); if (prefix < 0) { /* Create a new cache entry. */ - prefix = nd6_new_onlink_prefix(ip6_current_dest_addr(), inp); + prefix = nd6_new_onlink_prefix(&prefix_addr, inp); } if (prefix >= 0) { - prefix_list[prefix].invalidation_timer = htonl(prefix_opt->valid_lifetime); + prefix_list[prefix].invalidation_timer = lwip_htonl(prefix_opt->valid_lifetime); #if LWIP_IPV6_AUTOCONFIG if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) { @@ -526,6 +541,37 @@ nd6_input(struct pbuf *p, struct netif *inp) route_opt = (struct route_option *)buffer;*/ break; +#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS + case ND6_OPTION_TYPE_RDNSS: + { + u8_t num, n; + struct rdnss_option * rdnss_opt; + + rdnss_opt = (struct rdnss_option *)buffer; + num = (rdnss_opt->length - 1) / 2; + for (n = 0; (rdnss_server_idx < DNS_MAX_SERVERS) && (n < num); n++) { + ip_addr_t rdnss_address; + + /* Get a memory-aligned copy of the prefix. */ + ip_addr_copy_from_ip6(rdnss_address, rdnss_opt->rdnss_address[n]); + + if (htonl(rdnss_opt->lifetime) > 0) { + /* TODO implement Lifetime > 0 */ + dns_setserver(rdnss_server_idx++, &rdnss_address); + } else { + /* TODO implement DNS removal in dns.c */ + u8_t s; + for (s = 0; s < DNS_MAX_SERVERS; s++) { + const ip_addr_t *addr = dns_getserver(s); + if(ip_addr_cmp(addr, &rdnss_address)) { + dns_setserver(s, NULL); + } + } + } + } + break; + } +#endif /* LWIP_ND6_RDNSS_MAX_DNS_SERVERS */ default: /* Unrecognized option, abort. */ ND6_STATS_INC(nd6.proterr); @@ -541,6 +587,7 @@ nd6_input(struct pbuf *p, struct netif *inp) { struct redirect_header *redir_hdr; struct lladdr_option *lladdr_opt; + ip6_addr_t tmp; /* Check that Redir header fits in packet. */ if (p->len < sizeof(struct redirect_header)) { @@ -563,10 +610,10 @@ nd6_input(struct pbuf *p, struct netif *inp) } /* Copy original destination address to current source address, to have an aligned copy. */ - ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->destination_address)); + ip6_addr_set(&tmp, &(redir_hdr->destination_address)); /* Find dest address in cache */ - i = nd6_find_destination_cache_entry(ip6_current_src_addr()); + i = nd6_find_destination_cache_entry(&tmp); if (i < 0) { /* Destination not in cache, drop packet. */ pbuf_free(p); @@ -580,20 +627,20 @@ nd6_input(struct pbuf *p, struct netif *inp) if (lladdr_opt != NULL) { if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) { /* Copy target address to current source address, to have an aligned copy. */ - ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->target_address)); + ip6_addr_set(&tmp, &(redir_hdr->target_address)); - i = nd6_find_neighbor_cache_entry(ip6_current_src_addr()); + i = nd6_find_neighbor_cache_entry(&tmp); if (i < 0) { i = nd6_new_neighbor_cache_entry(); if (i >= 0) { neighbor_cache[i].netif = inp; MEMCPY(neighbor_cache[i].lladdr, lladdr_opt->addr, inp->hwaddr_len); - ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr()); + ip6_addr_set(&(neighbor_cache[i].next_hop_address), &tmp); /* Receiving a message does not prove reachability: only in one direction. * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; } } if (i >= 0) { @@ -602,7 +649,7 @@ nd6_input(struct pbuf *p, struct netif *inp) /* Receiving a message does not prove reachability: only in one direction. * Delay probe in case we get confirmation of reachability from upper layer (TCP). */ neighbor_cache[i].state = ND6_DELAY; - neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; } } } @@ -614,6 +661,7 @@ nd6_input(struct pbuf *p, struct netif *inp) struct icmp6_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 tmp; /* Check that ICMPv6 header + IPv6 header fit in payload */ if (p->len < (sizeof(struct icmp6_hdr) + IP6_HLEN)) { @@ -628,10 +676,10 @@ nd6_input(struct pbuf *p, struct netif *inp) ip6hdr = (struct ip6_hdr *)((u8_t*)p->payload + sizeof(struct icmp6_hdr)); /* Copy original destination address to current source address, to have an aligned copy. */ - ip6_addr_set(ip6_current_src_addr(), &(ip6hdr->dest)); + ip6_addr_set(&tmp, &(ip6hdr->dest)); /* Look for entry in destination cache. */ - i = nd6_find_destination_cache_entry(ip6_current_src_addr()); + i = nd6_find_destination_cache_entry(&tmp); if (i < 0) { /* Destination not in cache, drop packet. */ pbuf_free(p); @@ -639,7 +687,7 @@ nd6_input(struct pbuf *p, struct netif *inp) } /* Change the Path MTU. */ - pmtu = htonl(icmp6hdr->data); + pmtu = lwip_htonl(icmp6hdr->data); destination_cache[i].pmtu = (u16_t)LWIP_MIN(pmtu, 0xFFFF); break; /* ICMP6_TYPE_PTB */ @@ -698,15 +746,15 @@ nd6_tmr(void) } break; case ND6_STALE: - neighbor_cache[i].counter.stale_time += ND6_TMR_INTERVAL; + neighbor_cache[i].counter.stale_time++; break; case ND6_DELAY: - if (neighbor_cache[i].counter.delay_time <= ND6_TMR_INTERVAL) { + if (neighbor_cache[i].counter.delay_time <= 1) { /* Change to PROBE state. */ neighbor_cache[i].state = ND6_PROBE; neighbor_cache[i].counter.probes_sent = 0; } else { - neighbor_cache[i].counter.delay_time -= ND6_TMR_INTERVAL; + neighbor_cache[i].counter.delay_time--; } break; case ND6_PROBE: @@ -821,13 +869,6 @@ nd6_tmr(void) netif_ip6_addr_set_state(netif, i, IP6_ADDR_PREFERRED); /* @todo implement preferred and valid lifetimes. */ } else if (netif->flags & NETIF_FLAG_UP) { -#if LWIP_IPV6_MLD - if ((addr_state & IP6_ADDR_TENTATIVE_COUNT_MASK) == 0) { - /* Join solicited node multicast group. */ - ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, i)->addr[3]); - mld6_joingroup(netif_ip6_addr(netif, i), &multicast_address); - } -#endif /* LWIP_IPV6_MLD */ /* Send a NS for this address. */ nd6_send_ns(netif, netif_ip6_addr(netif, i), ND6_SEND_FLAG_MULTICAST_DEST); /* tentative: set next state by increasing by one */ @@ -1286,6 +1327,22 @@ nd6_new_destination_cache_entry(void) } /** + * Clear the destination cache. + * + * This operation may be necessary for consistency in the light of changing + * local addresses and/or use of the gateway hook. + */ +void +nd6_clear_destination_cache(void) +{ + int i; + + for (i = 0; i < LWIP_ND6_NUM_DESTINATIONS; i++) { + ip6_addr_set_any(&destination_cache[i].destination_addr); + } +} + +/** * Determine whether an address matches an on-link prefix. * * @param ip6addr the IPv6 address to match @@ -1320,7 +1377,7 @@ nd6_is_prefix_in_netif(const ip6_addr_t *ip6addr, struct netif *netif) * @return the default router entry index, or -1 if no suitable * router is found */ -s8_t +static s8_t nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif) { s8_t i; @@ -1373,6 +1430,30 @@ nd6_select_router(const ip6_addr_t *ip6addr, struct netif *netif) } /** + * Find a router-announced route to the given destination. + * + * The caller is responsible for checking whether the returned netif, if any, + * is in a suitable state (up, link up) to be used for packet transmission. + * + * @param ip6addr the destination IPv6 address + * @return the netif to use for the destination, or NULL if none found + */ +struct netif * +nd6_find_route(const ip6_addr_t *ip6addr) +{ + s8_t i; + + i = nd6_select_router(ip6addr, NULL); + if (i >= 0) { + if (default_router_list[i].neighbor_entry != NULL) { + return default_router_list[i].neighbor_entry->netif; /* may be NULL */ + } + } + + return NULL; +} + +/** * Find an entry for a default router. * * @param router_addr the IPv6 address of the router @@ -1408,6 +1489,7 @@ static s8_t nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif) { s8_t router_index; + s8_t free_router_index; s8_t neighbor_index; /* Do we have a neighbor entry for this router? */ @@ -1431,12 +1513,22 @@ nd6_new_router(const ip6_addr_t *router_addr, struct netif *netif) neighbor_cache[neighbor_index].isrouter = 1; /* Look for empty entry. */ - for (router_index = 0; router_index < LWIP_ND6_NUM_ROUTERS; router_index++) { + free_router_index = LWIP_ND6_NUM_ROUTERS; + for (router_index = LWIP_ND6_NUM_ROUTERS - 1; router_index >= 0; router_index--) { + /* check if router already exists (this is a special case for 2 netifs on the same subnet + - e.g. wifi and cable) */ + if(default_router_list[router_index].neighbor_entry == &(neighbor_cache[neighbor_index])){ + return router_index; + } if (default_router_list[router_index].neighbor_entry == NULL) { - default_router_list[router_index].neighbor_entry = &(neighbor_cache[neighbor_index]); - return router_index; + /* remember lowest free index to create a new entry */ + free_router_index = router_index; } } + if (free_router_index < LWIP_ND6_NUM_ROUTERS) { + default_router_list[free_router_index].neighbor_entry = &(neighbor_cache[neighbor_index]); + return free_router_index; + } /* Could not create a router entry. */ @@ -1513,9 +1605,12 @@ nd6_new_onlink_prefix(ip6_addr_t *prefix, struct netif *netif) * suitable next hop was found, ERR_MEM if no cache entry * could be created */ -s8_t +static s8_t nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) { +#ifdef LWIP_HOOK_ND6_GET_GW + const ip6_addr_t *next_hop_addr; +#endif /* LWIP_HOOK_ND6_GET_GW */ s8_t i; #if LWIP_NETIF_HWADDRHINT @@ -1559,6 +1654,12 @@ nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) /* Destination in local link. */ destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr); +#ifdef LWIP_HOOK_ND6_GET_GW + } else if ((next_hop_addr = LWIP_HOOK_ND6_GET_GW(netif, ip6addr)) != NULL) { + /* Next hop for destination provided by hook function. */ + destination_cache[nd6_cached_destination_index].pmtu = netif->mtu; + ip6_addr_set(&destination_cache[nd6_cached_destination_index].next_hop_addr, next_hop_addr); +#endif /* LWIP_HOOK_ND6_GET_GW */ } else { /* We need to select a router. */ i = nd6_select_router(ip6addr, netif); @@ -1626,7 +1727,7 @@ nd6_get_next_hop_entry(const ip6_addr_t *ip6addr, struct netif *netif) * @param q packet to be queued * @return ERR_OK if succeeded, ERR_MEM if out of memory */ -err_t +static err_t nd6_queue_packet(s8_t neighbor_index, struct pbuf *q) { err_t result = ERR_MEM; @@ -1762,6 +1863,7 @@ static void nd6_send_q(s8_t i) { struct ip6_hdr *ip6hdr; + ip6_addr_t dest; #if LWIP_ND6_QUEUEING struct nd6_q_entry *q; #endif /* LWIP_ND6_QUEUEING */ @@ -1778,10 +1880,10 @@ nd6_send_q(s8_t i) neighbor_cache[i].q = q->next; /* Get ipv6 header. */ ip6hdr = (struct ip6_hdr *)(q->p->payload); - /* Override ip6_current_dest_addr() so that we have an aligned copy. */ - ip6_addr_set(ip6_current_dest_addr(), &(ip6hdr->dest)); + /* Create an aligned copy. */ + ip6_addr_set(&dest, &(ip6hdr->dest)); /* send the queued IPv6 packet */ - (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, ip6_current_dest_addr()); + (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, &dest); /* free the queued IP packet */ pbuf_free(q->p); /* now queue entry can be freed */ @@ -1791,10 +1893,10 @@ nd6_send_q(s8_t i) if (neighbor_cache[i].q != NULL) { /* Get ipv6 header. */ ip6hdr = (struct ip6_hdr *)(neighbor_cache[i].q->payload); - /* Override ip6_current_dest_addr() so that we have an aligned copy. */ - ip6_addr_set(ip6_current_dest_addr(), &(ip6hdr->dest)); + /* Create an aligned copy. */ + ip6_addr_set(&dest, &(ip6hdr->dest)); /* send the queued IPv6 packet */ - (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, ip6_current_dest_addr()); + (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, &dest); /* free the queued IP packet */ pbuf_free(neighbor_cache[i].q); neighbor_cache[i].q = NULL; @@ -1802,6 +1904,61 @@ nd6_send_q(s8_t i) #endif /* LWIP_ND6_QUEUEING */ } +/** + * A packet is to be transmitted to a specific IPv6 destination on a specific + * interface. Check if we can find the hardware address of the next hop to use + * for the packet. If so, give the hardware address to the caller, which should + * use it to send the packet right away. Otherwise, enqueue the packet for + * later transmission while looking up the hardware address, if possible. + * + * As such, this function returns one of three different possible results: + * + * - ERR_OK with a non-NULL 'hwaddrp': the caller should send the packet now. + * - ERR_OK with a NULL 'hwaddrp': the packet has been enqueued for later. + * - not ERR_OK: something went wrong; forward the error upward in the stack. + * + * @param netif The lwIP network interface on which the IP packet will be sent. + * @param q The pbuf(s) containing the IP packet to be sent. + * @param ip6addr The destination IPv6 address of the packet. + * @param hwaddrp On success, filled with a pointer to a HW address or NULL (meaning + * the packet has been queued). + * @return + * - ERR_OK on success, ERR_RTE if no route was found for the packet, + * or ERR_MEM if low memory conditions prohibit sending the packet at all. + */ +err_t +nd6_get_next_hop_addr_or_queue(struct netif *netif, struct pbuf *q, const ip6_addr_t *ip6addr, const u8_t **hwaddrp) +{ + s8_t i; + + /* Get next hop record. */ + i = nd6_get_next_hop_entry(ip6addr, netif); + if (i < 0) { + /* failed to get a next hop neighbor record. */ + return i; + } + + /* Now that we have a destination record, send or queue the packet. */ + if (neighbor_cache[i].state == ND6_STALE) { + /* Switch to delay state. */ + neighbor_cache[i].state = ND6_DELAY; + neighbor_cache[i].counter.delay_time = LWIP_ND6_DELAY_FIRST_PROBE_TIME / ND6_TMR_INTERVAL; + } + /* @todo should we send or queue if PROBE? send for now, to let unicast NS pass. */ + if ((neighbor_cache[i].state == ND6_REACHABLE) || + (neighbor_cache[i].state == ND6_DELAY) || + (neighbor_cache[i].state == ND6_PROBE)) { + + /* Tell the caller to send out the packet now. */ + *hwaddrp = neighbor_cache[i].lladdr; + return ERR_OK; + } + + /* We should queue packet on this interface. */ + *hwaddrp = NULL; + return nd6_queue_packet(i, q); +} + /** * Get the Path MTU for a destination. @@ -1908,4 +2065,38 @@ nd6_cleanup_netif(struct netif *netif) } } +#if LWIP_IPV6_MLD +/** + * The state of a local IPv6 address entry is about to change. If needed, join + * or leave the solicited-node multicast group for the address. + * + * @param netif The netif that owns the address. + * @param addr_idx The index of the address. + * @param new_state The new (IP6_ADDR_) state for the address. + */ +void +nd6_adjust_mld_membership(struct netif *netif, s8_t addr_idx, u8_t new_state) +{ + u8_t old_state, old_member, new_member; + + old_state = netif_ip6_addr_state(netif, addr_idx); + + /* Determine whether we were, and should be, a member of the solicited-node + * multicast group for this address. For tentative addresses, the group is + * not joined until the address enters the TENTATIVE_1 (or VALID) state. */ + old_member = (old_state != IP6_ADDR_INVALID && old_state != IP6_ADDR_TENTATIVE); + new_member = (new_state != IP6_ADDR_INVALID && new_state != IP6_ADDR_TENTATIVE); + + if (old_member != new_member) { + ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, addr_idx)->addr[3]); + + if (new_member) { + mld6_joingroup_netif(netif, &multicast_address); + } else { + mld6_leavegroup_netif(netif, &multicast_address); + } + } +} +#endif /* LWIP_IPV6_MLD */ + #endif /* LWIP_IPV6 */ http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/mem.c ---------------------------------------------------------------------- diff --git a/net/ip/lwip_base/src/core/mem.c b/net/ip/lwip_base/src/core/mem.c index 40f4cb9..db3b7cc 100644 --- a/net/ip/lwip_base/src/core/mem.c +++ b/net/ip/lwip_base/src/core/mem.c @@ -61,9 +61,13 @@ #include "lwip/err.h" #include <string.h> -#include <stdlib.h> + +#if MEM_LIBC_MALLOC +#include <stdlib.h> /* for malloc()/free() */ +#endif #if MEM_LIBC_MALLOC || MEM_USE_POOLS + /** mem_init is not used when using pools instead of a heap or using * C library malloc(). */ @@ -162,7 +166,7 @@ void * mem_malloc(mem_size_t size) { void *ret; - struct memp_malloc_helper *element; + struct memp_malloc_helper *element = NULL; memp_t poolnr; mem_size_t required_size = size + LWIP_MEM_ALIGN_SIZE(sizeof(struct memp_malloc_helper)); http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f52033e9/net/ip/lwip_base/src/core/memp.c ---------------------------------------------------------------------- diff --git a/net/ip/lwip_base/src/core/memp.c b/net/ip/lwip_base/src/core/memp.c index 19198eb..58fab1a 100644 --- a/net/ip/lwip_base/src/core/memp.c +++ b/net/ip/lwip_base/src/core/memp.c @@ -71,11 +71,10 @@ #include "netif/ppp/ppp_opts.h" #include "lwip/netdb.h" #include "lwip/dns.h" -#include "lwip/nd6.h" +#include "lwip/priv/nd6_priv.h" #include "lwip/ip6_frag.h" #include "lwip/mld6.h" - #define LWIP_MEMPOOL(name,num,size,desc) LWIP_MEMPOOL_DECLARE(name,num,size,desc) #include "lwip/priv/memp_std.h" @@ -84,6 +83,10 @@ const struct memp_desc* const memp_pools[MEMP_MAX] = { #include "lwip/priv/memp_std.h" }; +#ifdef LWIP_HOOK_FILENAME +#include LWIP_HOOK_FILENAME +#endif + #if MEMP_MEM_MALLOC && MEMP_OVERFLOW_CHECK >= 2 #undef MEMP_OVERFLOW_CHECK /* MEMP_OVERFLOW_CHECK >= 2 does not work with MEMP_MEM_MALLOC, use 1 instead */ @@ -205,11 +208,11 @@ memp_overflow_check_all(void) SYS_ARCH_PROTECT(old_level); for (i = 0; i < MEMP_MAX; ++i) { - p = (struct memp *)(size_t)(memp_pools[i]->base); + p = (struct memp*)LWIP_MEM_ALIGN(memp_pools[i]->base); for (j = 0; j < memp_pools[i]->num; ++j) { memp_overflow_check_element_overflow(p, memp_pools[i]); memp_overflow_check_element_underflow(p, memp_pools[i]); - p = (struct memp*)(size_t)((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED); + p = LWIP_ALIGNMENT_CAST(struct memp*, ((u8_t*)p + MEMP_SIZE + memp_pools[i]->size + MEMP_SANITY_REGION_AFTER_ALIGNED)); } } SYS_ARCH_UNPROTECT(old_level); @@ -301,15 +304,15 @@ do_memp_malloc_pool_fn(const struct memp_desc *desc, const char* file, const int SYS_ARCH_PROTECT(old_level); memp = *desc->tab; - -#if MEMP_OVERFLOW_CHECK == 1 - memp_overflow_check_element_overflow(memp, desc); - memp_overflow_check_element_underflow(memp, desc); -#endif /* MEMP_OVERFLOW_CHECK */ #endif /* MEMP_MEM_MALLOC */ if (memp != NULL) { #if !MEMP_MEM_MALLOC +#if MEMP_OVERFLOW_CHECK == 1 + memp_overflow_check_element_overflow(memp, desc); + memp_overflow_check_element_underflow(memp, desc); +#endif /* MEMP_OVERFLOW_CHECK */ + *desc->tab = memp->next; #if MEMP_OVERFLOW_CHECK memp->next = NULL; @@ -471,6 +474,10 @@ memp_free(memp_t type, void *mem) LWIP_ERROR("memp_free: type < MEMP_MAX", (type < MEMP_MAX), return;); + if (mem == NULL) { + return; + } + #if MEMP_OVERFLOW_CHECK >= 2 memp_overflow_check_all(); #endif /* MEMP_OVERFLOW_CHECK >= 2 */