diff --git a/modules/pico_icmp6.c b/modules/pico_icmp6.c index 9ca6129c6..eb769ba86 100644 --- a/modules/pico_icmp6.c +++ b/modules/pico_icmp6.c @@ -205,26 +205,41 @@ static int pico_icmp6_notify(struct pico_frame *f, uint8_t type, uint8_t code, u int pico_icmp6_port_unreachable(struct pico_frame *f) { + struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->net_hdr; + if (pico_ipv6_is_multicast(hdr->dst.addr)) + return 0; return pico_icmp6_notify(f, PICO_ICMP6_DEST_UNREACH, PICO_ICMP6_UNREACH_PORT, 0); } int pico_icmp6_proto_unreachable(struct pico_frame *f) { + struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->net_hdr; + if (pico_ipv6_is_multicast(hdr->dst.addr)) + return 0; return pico_icmp6_notify(f, PICO_ICMP6_DEST_UNREACH, PICO_ICMP6_UNREACH_ADDR, 0); } int pico_icmp6_dest_unreachable(struct pico_frame *f) { + struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->net_hdr; + if (pico_ipv6_is_multicast(hdr->dst.addr)) + return 0; return pico_icmp6_notify(f, PICO_ICMP6_DEST_UNREACH, PICO_ICMP6_UNREACH_ADDR, 0); } int pico_icmp6_ttl_expired(struct pico_frame *f) { + struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->net_hdr; + if (pico_ipv6_is_multicast(hdr->dst.addr)) + return 0; return pico_icmp6_notify(f, PICO_ICMP6_TIME_EXCEEDED, PICO_ICMP6_TIMXCEED_INTRANS, 0); } int pico_icmp6_pkt_too_big(struct pico_frame *f) { + struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->net_hdr; + if (pico_ipv6_is_multicast(hdr->dst.addr)) + return 0; return pico_icmp6_notify(f, PICO_ICMP6_PKT_TOO_BIG, 0, 0); } @@ -242,6 +257,9 @@ int pico_icmp6_parameter_problem(struct pico_frame *f, uint8_t problem, uint32_t int pico_icmp6_frag_expired(struct pico_frame *f) { + struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)f->net_hdr; + if (pico_ipv6_is_multicast(hdr->dst.addr)) + return 0; return pico_icmp6_notify(f, PICO_ICMP6_TIME_EXCEEDED, PICO_ICMP6_TIMXCEED_REASS, 0); } @@ -461,6 +479,7 @@ struct pico_icmp6_ping_cookie int timeout; pico_time timestamp; struct pico_ip6 dst; + struct pico_device *dev; void (*cb)(struct pico_icmp6_stats*); }; @@ -499,6 +518,7 @@ static int pico_icmp6_send_echo(struct pico_icmp6_ping_cookie *cookie) /* XXX: Fill payload */ hdr->crc = 0; hdr->crc = short_be(pico_icmp6_checksum(echo)); + echo->dev = cookie->dev; pico_ipv6_frame_push(echo, &cookie->dst, PICO_PROTO_ICMP6); return 0; } @@ -599,7 +619,7 @@ static void pico_icmp6_ping_recv_reply(struct pico_frame *f) } } -int pico_icmp6_ping(char *dst, int count, int interval, int timeout, int size, void (*cb)(struct pico_icmp6_stats *)) +int pico_icmp6_ping(char *dst, int count, int interval, int timeout, int size, void (*cb)(struct pico_icmp6_stats *), struct pico_device *dev) { static uint16_t next_id = 0x91c0; struct pico_icmp6_ping_cookie *cookie = NULL; @@ -629,6 +649,7 @@ int pico_icmp6_ping(char *dst, int count, int interval, int timeout, int size, v cookie->timeout = timeout; cookie->cb = cb; cookie->count = count; + cookie->dev = dev; pico_tree_insert(&IPV6Pings, cookie); pico_icmp6_send_ping(cookie); diff --git a/modules/pico_icmp6.h b/modules/pico_icmp6.h index 0e5ce5d5a..e74e23d12 100644 --- a/modules/pico_icmp6.h +++ b/modules/pico_icmp6.h @@ -237,7 +237,7 @@ struct pico_icmp6_stats struct pico_ip6 dst; }; -int pico_icmp6_ping(char *dst, int count, int interval, int timeout, int size, void (*cb)(struct pico_icmp6_stats *)); +int pico_icmp6_ping(char *dst, int count, int interval, int timeout, int size, void (*cb)(struct pico_icmp6_stats *), struct pico_device *dev); int pico_icmp6_ping_abort(int id); int pico_icmp6_neighbor_solicitation(struct pico_device *dev, struct pico_ip6 *dst, uint8_t type); diff --git a/modules/pico_ipv6.c b/modules/pico_ipv6.c index 15ed37873..8fd773701 100644 --- a/modules/pico_ipv6.c +++ b/modules/pico_ipv6.c @@ -610,6 +610,7 @@ static void pico_ipv6_frag_expire(pico_time now, void *arg) struct pico_tree_node *index, *tmp; struct pico_frame *f; struct pico_frame *first = pico_tree_first(&ipv6_fragments); + struct pico_ipv6_hdr *hdr = (struct pico_ipv6_hdr *)first->net_hdr; (void)arg; (void)now; if (!first) { @@ -623,7 +624,7 @@ static void pico_ipv6_frag_expire(pico_time now, void *arg) if (f != first) pico_frame_discard(f); /* Later, after ICMP notification...*/ } - if (IP6FRAG_OFF(first->frag) == 0) + if ((IP6FRAG_OFF(first->frag) == 0) && (!pico_ipv6_is_multicast(hdr->dst.addr))) pico_icmp6_frag_expired(first); pico_frame_discard(first); } @@ -1049,7 +1050,11 @@ int pico_ipv6_frame_push(struct pico_frame *f, struct pico_ip6 *dst, uint8_t pro pico_frame_discard(f); return -1; } - link = pico_ipv6_linklocal_get(f->dev); + + if (pico_ipv6_is_sitelocal(dst->addr)) + link = pico_ipv6_sitelocal_get(f->dev); + else + link = pico_ipv6_linklocal_get(f->dev); if (link) goto push_final; } @@ -1519,6 +1524,15 @@ struct pico_ipv6_link *pico_ipv6_linklocal_get(struct pico_device *dev) return link; } +struct pico_ipv6_link *pico_ipv6_sitelocal_get(struct pico_device *dev) +{ + struct pico_ipv6_link *link = pico_ipv6_link_by_dev(dev); + while (link && !pico_ipv6_is_sitelocal(link->address.addr)) { + link = pico_ipv6_link_by_dev_next(dev, link); + } + return link; +} + struct pico_ipv6_link *pico_ipv6_global_get(struct pico_device *dev) { struct pico_ipv6_link *link = pico_ipv6_link_by_dev(dev); diff --git a/modules/pico_ipv6.h b/modules/pico_ipv6.h index d1f3d74a2..3dda1e19a 100644 --- a/modules/pico_ipv6.h +++ b/modules/pico_ipv6.h @@ -124,6 +124,7 @@ struct pico_ipv6_link *pico_ipv6_link_by_dev(struct pico_device *dev); struct pico_ipv6_link *pico_ipv6_link_by_dev_next(struct pico_device *dev, struct pico_ipv6_link *last); struct pico_ipv6_link *pico_ipv6_global_get(struct pico_device *dev); struct pico_ipv6_link *pico_ipv6_linklocal_get(struct pico_device *dev); +struct pico_ipv6_link *pico_ipv6_sitelocal_get(struct pico_device *dev); int pico_ipv6_dev_routing_enable(struct pico_device *dev); int pico_ipv6_dev_routing_disable(struct pico_device *dev); #endif diff --git a/test/examples/ping.c b/test/examples/ping.c index 4608e8de4..13f015b91 100644 --- a/test/examples/ping.c +++ b/test/examples/ping.c @@ -81,7 +81,7 @@ void app_ping(char *arg) #ifdef PICO_SUPPORT_IPV6 else - id = pico_icmp6_ping(dest, NUM_PING, 1000, 10000, 64, cb_ping6); + id = pico_icmp6_ping(dest, NUM_PING, 1000, 10000, 64, cb_ping6, NULL); #endif if (timeout > 0) { printf("Adding abort timer after %d seconds for id %d\n", timeout, id);