Skip to content

Commit

Permalink
Fully compliant ICMP6 RFC4333 Implementation
Browse files Browse the repository at this point in the history
Fixed #240
Fixed #241
  • Loading branch information
Daniele Lacamera committed Mar 20, 2015
1 parent 869a6fb commit 67327c4
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 5 deletions.
23 changes: 22 additions & 1 deletion modules/pico_icmp6.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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);
}

Expand Down Expand Up @@ -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*);
};

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion modules/pico_icmp6.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
18 changes: 16 additions & 2 deletions modules/pico_ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions modules/pico_ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion test/examples/ping.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 67327c4

Please sign in to comment.