Commit e47c678a authored by Daniele Lacamera's avatar Daniele Lacamera

ICMP6 TIME EXCEEDED added for frame reassebly failure.

parent 5df721cc
......@@ -190,7 +190,6 @@ static int pico_icmp6_notify(struct pico_frame *f, uint8_t type, uint8_t code, u
icmp6_hdr->msg.err.param_problem.ptr = long_be(ptr);
break;
default:
return -1;
}
......@@ -241,6 +240,11 @@ int pico_icmp6_parameter_problem(struct pico_frame *f, uint8_t problem, uint32_t
return pico_icmp6_notify(f, PICO_ICMP6_PARAM_PROBLEM, problem, ptr);
}
int pico_icmp6_frag_expired(struct pico_frame *f)
{
return pico_icmp6_notify(f, PICO_ICMP6_TIME_EXCEEDED, PICO_ICMP6_TIMXCEED_REASS, 0);
}
/* RFC 4861 $7.2.2: sending neighbor solicitations */
int pico_icmp6_neighbor_solicitation(struct pico_device *dev, struct pico_ip6 *dst, uint8_t type)
{
......
......@@ -251,6 +251,7 @@ int pico_icmp6_ttl_expired(struct pico_frame *f);
int pico_icmp6_packet_filtered(struct pico_frame *f);
int pico_icmp6_parameter_problem(struct pico_frame *f, uint8_t problem, uint32_t ptr);
int pico_icmp6_pkt_too_big(struct pico_frame *f);
int pico_icmp6_frag_expired(struct pico_frame *f);
uint16_t pico_icmp6_checksum(struct pico_frame *f);
int pico_icmp6_router_advertisement(struct pico_device *dev, struct pico_ip6 *dst);
......
......@@ -549,6 +549,7 @@ static int pico_ipv6_frag_compare(void *ka, void *kb)
return 0;
}
PICO_TREE_DECLARE(ipv6_fragments, pico_ipv6_frag_compare);
struct pico_timer *ipv6_fragments_timer = NULL;
static void pico_ipv6_fragments_complete(unsigned int len, uint8_t proto)
......@@ -575,6 +576,10 @@ static void pico_ipv6_fragments_complete(unsigned int len, uint8_t proto)
pico_frame_discard(f);
}
pico_transport_receive(full, proto);
if (ipv6_fragments_timer) {
pico_timer_cancel(ipv6_fragments_timer);
ipv6_fragments_timer = NULL;
}
}
}
......@@ -594,10 +599,68 @@ static void pico_ipv6_fragments_check_complete(uint8_t proto)
}
}
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);
(void)arg;
(void)now;
if (!first) {
return;
}
/* Empty the tree */
pico_tree_foreach_safe(index, &ipv6_fragments, tmp) {
f = index->keyValue;
pico_tree_delete(&ipv6_fragments, f);
if (f != first)
pico_frame_discard(f); /* Later, after ICMP notification...*/
}
pico_icmp6_frag_expired(first);
pico_frame_discard(first);
}
#define PICO_IPV6_FRAG_TIMEOUT 60000
#define FRAG_ID(x) ((uint32_t)((x->ext.frag.id[0] << 24) + (x->ext.frag.id[1] << 16) + \
(x->ext.frag.id[2] << 8) + x->ext.frag.id[3]))
static void pico_ipv6_frag_timer_on(void)
{
ipv6_fragments_timer = pico_timer_add(PICO_IPV6_FRAG_TIMEOUT, pico_ipv6_frag_expire, NULL);
}
static int pico_ipv6_frag_match(struct pico_frame *a, struct pico_frame *b)
{
struct pico_ipv6_hdr *ha, *hb;
if (!a || !b)
return 0;
ha = (struct pico_ipv6_hdr *)a->net_hdr;
hb = (struct pico_ipv6_hdr *)b->net_hdr;
if (!ha || !hb)
return 0;
if (memcmp(ha->src.addr, hb->src.addr, PICO_SIZE_IP6) != 0)
return 0;
if (memcmp(ha->dst.addr, hb->dst.addr, PICO_SIZE_IP6) != 0)
return 0;
return 1;
}
static void pico_ipv6_process_frag(struct pico_ipv6_exthdr *frag, struct pico_frame *f, uint8_t proto)
{
struct pico_frame *first = pico_tree_first(&ipv6_fragments);
static uint32_t ipv6_cur_frag_id = 0u;
f->frag = (uint16_t)((frag->ext.frag.om[0] << 8) + frag->ext.frag.om[1]);
pico_tree_insert(&ipv6_fragments, pico_frame_copy(f));
if (!first) {
pico_ipv6_frag_timer_on();
ipv6_cur_frag_id = FRAG_ID(frag);
}
if (!first || (pico_ipv6_frag_match(f, first) && (FRAG_ID(frag) == ipv6_cur_frag_id))) {
pico_tree_insert(&ipv6_fragments, pico_frame_copy(f));
}
pico_ipv6_fragments_check_complete(proto);
}
......
......@@ -90,6 +90,7 @@ PACKED_STRUCT_DEF pico_ipv6_exthdr {
PEDANTIC_STRUCT_DEF fragmentation_s {
uint8_t res;
uint8_t om[2];
uint8_t id[4];
} frag;
} ext;
};
......
......@@ -174,7 +174,6 @@ int pico_notify_pkt_too_big(struct pico_frame *f)
}
/* Transport layer */
int32_t pico_transport_receive(struct pico_frame *f, uint8_t proto)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment