diff --git a/modules/pico_ipfilter.c b/modules/pico_ipfilter.c index 1bb4621c..a97114af 100644 --- a/modules/pico_ipfilter.c +++ b/modules/pico_ipfilter.c @@ -461,18 +461,18 @@ int ipfilter(struct pico_frame *f) temp.fdev = f->dev; temp.out_addr = ipv4_hdr->dst.addr; temp.in_addr = ipv4_hdr->src.addr; - if ((ipv4_hdr->proto == PICO_PROTO_TCP) || (ipv4_hdr->proto == PICO_PROTO_UDP)) { - trans = (struct pico_trans *) f->transport_hdr; - temp.out_port = short_be(trans->dport); - temp.in_port = short_be(trans->sport); - } - else if(ipv4_hdr->proto == PICO_PROTO_ICMP4) { - icmp_hdr = (struct pico_icmp4_hdr *) f->transport_hdr; - if(icmp_hdr->type == PICO_ICMP_UNREACH && icmp_hdr->code == PICO_ICMP_UNREACH_FILTER_PROHIB) - return 0; + if ((f->transport_hdr + sizeof(struct pico_trans)) <= (f->buffer + f->buffer_len)) { + if ((ipv4_hdr->proto == PICO_PROTO_TCP) || (ipv4_hdr->proto == PICO_PROTO_UDP)) { + trans = (struct pico_trans *) f->transport_hdr; + temp.out_port = short_be(trans->dport); + temp.in_port = short_be(trans->sport); + } else if(ipv4_hdr->proto == PICO_PROTO_ICMP4) { + icmp_hdr = (struct pico_icmp4_hdr *) f->transport_hdr; + if(icmp_hdr->type == PICO_ICMP_UNREACH && icmp_hdr->code == PICO_ICMP_UNREACH_FILTER_PROHIB) + return 0; + } + temp.proto = ipv4_hdr->proto; } - - temp.proto = ipv4_hdr->proto; temp.priority = f->priority; temp.tos = ipv4_hdr->tos; return ipfilter_apply_filter(f, &temp); diff --git a/modules/pico_ipv4.c b/modules/pico_ipv4.c index bdbaabad..ddbf029c 100644 --- a/modules/pico_ipv4.c +++ b/modules/pico_ipv4.c @@ -668,6 +668,11 @@ static int pico_ipv4_process_in(struct pico_stack *S, struct pico_protocol *self f->transport_hdr = ((uint8_t *)f->net_hdr) + PICO_SIZE_IP4HDR + option_len; f->transport_len = (uint16_t)(short_be(hdr->len) - PICO_SIZE_IP4HDR - option_len); f->net_len = (uint16_t)(PICO_SIZE_IP4HDR + option_len); + + if ((f->net_hdr + f->net_len) > (f->buffer + f->buffer_len)) { + pico_frame_discard(f); + return 0; + } #if defined(PICO_SUPPORT_IPV4FRAG) || defined(PICO_SUPPORT_IPV6FRAG) f->frag = short_be(hdr->frag); #endif diff --git a/modules/pico_tcp.c b/modules/pico_tcp.c index d2ca607b..423d6966 100644 --- a/modules/pico_tcp.c +++ b/modules/pico_tcp.c @@ -868,6 +868,9 @@ static inline void tcp_parse_option_mss(struct pico_socket_tcp *t, uint8_t len, if (tcpopt_len_check(idx, len, PICO_TCPOPTLEN_MSS) < 0) return; + if ((*idx + PICO_TCPOPTLEN_MSS) > len) + return; + t->mss_ok = 1; mss = short_from(opt + *idx); *idx += (uint32_t)sizeof(uint16_t); @@ -896,6 +899,10 @@ static int tcp_parse_options(struct pico_frame *f) uint8_t *opt = f->transport_hdr + PICO_SIZE_TCPHDR; uint32_t i = 0; f->timestamp = 0; + + if (f->buffer + f->buffer_len > f->transport_hdr + f->transport_len) + return -1; + while (i < (f->transport_len - PICO_SIZE_TCPHDR)) { uint8_t type = opt[i++]; uint8_t len; @@ -1085,7 +1092,11 @@ struct pico_socket *pico_tcp_open(struct pico_stack *S, uint16_t family) t->sock.stack = S; t->sock.timestamp = TCP_TIME; pico_socket_set_family(&t->sock, family); - t->mss = (uint16_t)(pico_socket_get_mss(&t->sock) - PICO_SIZE_TCPHDR); + t->mss = (uint16_t)(pico_socket_get_mss(&t->sock)); + if (t->mss > PICO_SIZE_TCPHDR + PICO_TCP_MIN_MSS) + t->mss -= (uint16_t)PICO_SIZE_TCPHDR; + else + t->mss = PICO_TCP_MIN_MSS; t->tcpq_in.pool.root = t->tcpq_hold.pool.root = t->tcpq_out.pool.root = &LEAF; t->tcpq_hold.pool.compare = t->tcpq_out.pool.compare = segment_compare; t->tcpq_in.pool.compare = input_segment_compare; @@ -1254,7 +1265,10 @@ int pico_tcp_initconn(struct pico_socket *s) ts->snd_last = ts->snd_nxt; ts->cwnd = PICO_TCP_IW; mtu = (uint16_t)pico_socket_get_mss(s); - ts->mss = (uint16_t)(mtu - PICO_SIZE_TCPHDR); + if (mtu > PICO_SIZE_TCPHDR + PICO_TCP_MIN_MSS) + ts->mss = (uint16_t)(mtu - PICO_SIZE_TCPHDR); + else + ts->mss = PICO_TCP_MIN_MSS; ts->ssthresh = (uint16_t)((uint16_t)(PICO_DEFAULT_SOCKETQ / ts->mss) - (((uint16_t)(PICO_DEFAULT_SOCKETQ / ts->mss)) >> 3u)); syn->sock = s; hdr->seq = long_be(ts->snd_nxt); @@ -2446,7 +2460,10 @@ static int tcp_syn(struct pico_socket *s, struct pico_frame *f) #endif f->sock = &new->sock; mtu = (uint16_t)pico_socket_get_mss(&new->sock); - new->mss = (uint16_t)(mtu - PICO_SIZE_TCPHDR); + if (mtu > PICO_SIZE_TCPHDR + PICO_TCP_MIN_MSS) + new->mss = (uint16_t)(mtu - PICO_SIZE_TCPHDR); + else + new->mss = PICO_TCP_MIN_MSS; if (tcp_parse_options(f) < 0) return -1; new->sock.stack = s->stack; diff --git a/modules/pico_tcp.h b/modules/pico_tcp.h index 3bd1a11e..f598be84 100644 --- a/modules/pico_tcp.h +++ b/modules/pico_tcp.h @@ -55,6 +55,7 @@ PACKED_STRUCT_DEF tcp_pseudo_hdr_ipv4 #define PICO_TCPHDR_SIZE 20 #define PICO_SIZE_TCPOPT_SYN 20 #define PICO_SIZE_TCPHDR (uint32_t)(sizeof(struct pico_tcp_hdr)) +#define PICO_TCP_MIN_MSS (64 - PICO_SIZE_TCPHDR) /* TCP options */ #define PICO_TCP_OPTION_END 0x00