net: tcp2: Fix reading TCP options
This patch fixes an issue with TCP options reading. Previous approach was accessing the options with pointers (th + 1). This does not work if TCP options span multiple net_pkt buffer fragments. Instead net_pkt functions must be used. Signed-off-by: Ruslan Mstoi <ruslan.mstoi@intel.com>
This commit is contained in:
parent
45a014a883
commit
59c21ad3cf
1 changed files with 20 additions and 5 deletions
|
@ -361,10 +361,26 @@ static const char *tcp_conn_state(struct tcp *conn, struct net_pkt *pkt)
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool tcp_options_check(void *buf, ssize_t len)
|
static u8_t *tcp_options_get(struct net_pkt *pkt, int tcp_options_len)
|
||||||
|
{
|
||||||
|
static u8_t options[40]; /* TCP header max options size is 40 */
|
||||||
|
struct net_pkt_cursor backup;
|
||||||
|
|
||||||
|
net_pkt_cursor_backup(pkt, &backup);
|
||||||
|
net_pkt_cursor_init(pkt);
|
||||||
|
net_pkt_skip(pkt, net_pkt_ip_hdr_len(pkt) + net_pkt_ip_opts_len(pkt) +
|
||||||
|
sizeof(struct tcphdr));
|
||||||
|
net_pkt_read(pkt, options, tcp_options_len);
|
||||||
|
net_pkt_cursor_restore(pkt, &backup);
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tcp_options_check(struct net_pkt *pkt, ssize_t len)
|
||||||
{
|
{
|
||||||
bool result = len > 0 && ((len % 4) == 0) ? true : false;
|
bool result = len > 0 && ((len % 4) == 0) ? true : false;
|
||||||
u8_t *options = buf, opt, opt_len;
|
u8_t *options = tcp_options_get(pkt, len);
|
||||||
|
u8_t opt, opt_len;
|
||||||
|
|
||||||
NET_DBG("len=%zd", len);
|
NET_DBG("len=%zd", len);
|
||||||
|
|
||||||
|
@ -424,8 +440,7 @@ static size_t tcp_data_len(struct net_pkt *pkt)
|
||||||
ssize_t len = net_pkt_get_len(pkt) - net_pkt_ip_hdr_len(pkt) -
|
ssize_t len = net_pkt_get_len(pkt) - net_pkt_ip_hdr_len(pkt) -
|
||||||
net_pkt_ip_opts_len(pkt) - sizeof(*th) - tcp_options_len;
|
net_pkt_ip_opts_len(pkt) - sizeof(*th) - tcp_options_len;
|
||||||
|
|
||||||
if (tcp_options_len && tcp_options_check((th + 1), tcp_options_len)
|
if (tcp_options_len && !tcp_options_check(pkt, tcp_options_len)) {
|
||||||
== false) {
|
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -846,7 +861,7 @@ static void tcp_in(struct tcp *conn, struct net_pkt *pkt)
|
||||||
goto next_state;
|
goto next_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tcp_options_len && !tcp_options_check((th + 1), tcp_options_len)) {
|
if (tcp_options_len && !tcp_options_check(pkt, tcp_options_len)) {
|
||||||
NET_DBG("DROP: Invalid TCP option list");
|
NET_DBG("DROP: Invalid TCP option list");
|
||||||
tcp_out(conn, RST);
|
tcp_out(conn, RST);
|
||||||
conn_state(conn, TCP_CLOSED);
|
conn_state(conn, TCP_CLOSED);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue