This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit c581cc5f9b8c3bbd622895f3eff4e6a7f1342774 Author: chao an <anc...@xiaomi.com> AuthorDate: Mon Jan 9 19:44:23 2023 +0800 net/tcp: parse tcp options in common function Signed-off-by: chao an <anc...@xiaomi.com> --- net/tcp/tcp_input.c | 212 ++++++++++++++++++++++++---------------------------- 1 file changed, 96 insertions(+), 116 deletions(-) diff --git a/net/tcp/tcp_input.c b/net/tcp/tcp_input.c index 552f6b1d37..b4b7b05292 100644 --- a/net/tcp/tcp_input.c +++ b/net/tcp/tcp_input.c @@ -564,6 +564,100 @@ clear: } #endif /* CONFIG_NET_TCP_OUT_OF_ORDER */ +/**************************************************************************** + * Name: tcp_parse_option + * + * Description: + * Parse incoming TCP options + * + * Input Parameters: + * dev - The device driver structure containing the received TCP packet. + * conn - The TCP connection of interest + * iplen - Length of the IP header (IPv4_HDRLEN or IPv6_HDRLEN). + * + * Returned Value: + * None + * + * Assumptions: + * The network is locked. + * + ****************************************************************************/ + +static void tcp_parse_option(FAR struct net_driver_s *dev, + FAR struct tcp_conn_s *conn, + unsigned int iplen) +{ + FAR struct tcp_hdr_s *tcp; + unsigned int tcpiplen; + uint16_t tmp16; + uint8_t opt; + int i; + + tcp = IPBUF(iplen); + + if ((tcp->tcpoffset & 0xf0) <= 0x50) + { + return; + } + + tcpiplen = iplen + TCP_HDRLEN; + + for (i = 0; i < ((tcp->tcpoffset >> 4) - 5) << 2 ; ) + { + opt = IPDATA(tcpiplen + i); + if (opt == TCP_OPT_END) + { + /* End of options. */ + + break; + } + else if (opt == TCP_OPT_NOOP) + { + /* NOP option. */ + + ++i; + continue; + } + else if (opt == TCP_OPT_MSS && + IPDATA(tcpiplen + 1 + i) == TCP_OPT_MSS_LEN) + { + uint16_t tcp_mss = TCP_MSS(dev, iplen); + + /* An MSS option with the right option length. */ + + tmp16 = ((uint16_t)IPDATA(tcpiplen + 2 + i) << 8) | + (uint16_t)IPDATA(tcpiplen + 3 + i); + conn->mss = tmp16 > tcp_mss ? tcp_mss : tmp16; + } +#ifdef CONFIG_NET_TCP_WINDOW_SCALE + else if (opt == TCP_OPT_WS && + IPDATA(tcpiplen + 1 + i) == TCP_OPT_WS_LEN) + { + conn->snd_scale = IPDATA(tcpiplen + 2 + i); + conn->rcv_scale = CONFIG_NET_TCP_WINDOW_SCALE_FACTOR; + conn->flags |= TCP_WSCALE; + } +#endif + else + { + /* All other options have a length field, so that we + * easily can skip past them. + */ + + if (IPDATA(tcpiplen + 1 + i) == 0) + { + /* If the length field is zero, the options are + * malformed and we don't process them further. + */ + + break; + } + } + + i += IPDATA(tcpiplen + 1 + i); + } +} + /**************************************************************************** * Name: tcp_input * @@ -593,9 +687,7 @@ static void tcp_input(FAR struct net_driver_s *dev, uint8_t domain, uint16_t tmp16; uint16_t flags; uint16_t result; - uint8_t opt; int len; - int i; #ifdef CONFIG_NET_STATISTICS /* Bump up the count of TCP packets received */ @@ -748,63 +840,7 @@ static void tcp_input(FAR struct net_driver_s *dev, uint8_t domain, /* Parse the TCP MSS option, if present. */ - if ((tcp->tcpoffset & 0xf0) > 0x50) - { - for (i = 0; i < ((tcp->tcpoffset >> 4) - 5) << 2 ; ) - { - opt = IPDATA(tcpiplen + i); - if (opt == TCP_OPT_END) - { - /* End of options. */ - - break; - } - else if (opt == TCP_OPT_NOOP) - { - /* NOP option. */ - - ++i; - continue; - } - else if (opt == TCP_OPT_MSS && - IPDATA(tcpiplen + 1 + i) == TCP_OPT_MSS_LEN) - { - uint16_t tcp_mss = TCP_MSS(dev, iplen); - - /* An MSS option with the right option length. */ - - tmp16 = ((uint16_t)IPDATA(tcpiplen + 2 + i) << 8) | - (uint16_t)IPDATA(tcpiplen + 3 + i); - conn->mss = tmp16 > tcp_mss ? tcp_mss : tmp16; - } -#ifdef CONFIG_NET_TCP_WINDOW_SCALE - else if (opt == TCP_OPT_WS && - IPDATA(tcpiplen + 1 + i) == TCP_OPT_WS_LEN) - { - conn->snd_scale = IPDATA(tcpiplen + 2 + i); - conn->rcv_scale = CONFIG_NET_TCP_WINDOW_SCALE_FACTOR; - conn->flags |= TCP_WSCALE; - } -#endif - else - { - /* All other options have a length field, so that we - * easily can skip past them. - */ - - if (IPDATA(tcpiplen + 1 + i) == 0) - { - /* If the length field is zero, the options are - * malformed and we don't process them further. - */ - - break; - } - } - - i += IPDATA(tcpiplen + 1 + i); - } - } + tcp_parse_option(dev, conn, iplen); /* Our response will be a SYNACK. */ @@ -1245,63 +1281,7 @@ found: { /* Parse the TCP MSS option, if present. */ - if ((tcp->tcpoffset & 0xf0) > 0x50) - { - for (i = 0; i < ((tcp->tcpoffset >> 4) - 5) << 2 ; ) - { - opt = IPDATA(tcpiplen + i); - if (opt == TCP_OPT_END) - { - /* End of options. */ - - break; - } - else if (opt == TCP_OPT_NOOP) - { - /* NOP option. */ - - ++i; - continue; - } - else if (opt == TCP_OPT_MSS && - IPDATA(tcpiplen + 1 + i) == TCP_OPT_MSS_LEN) - { - uint16_t tcp_mss = TCP_MSS(dev, iplen); - - /* An MSS option with the right option length. */ - - tmp16 = (IPDATA(tcpiplen + 2 + i) << 8) | - IPDATA(tcpiplen + 3 + i); - conn->mss = tmp16 > tcp_mss ? tcp_mss : tmp16; - } -#ifdef CONFIG_NET_TCP_WINDOW_SCALE - else if (opt == TCP_OPT_WS && - IPDATA(tcpiplen + 1 + i) == TCP_OPT_WS_LEN) - { - conn->snd_scale = IPDATA(tcpiplen + 2 + i); - conn->rcv_scale = CONFIG_NET_TCP_WINDOW_SCALE_FACTOR; - conn->flags |= TCP_WSCALE; - } -#endif - else - { - /* All other options have a length field, so that we - * easily can skip past them. - */ - - if (IPDATA(tcpiplen + 1 + i) == 0) - { - /* If the length field is zero, the options are - * malformed and we don't process them further. - */ - - break; - } - } - - i += IPDATA(tcpiplen + 1 + i); - } - } + tcp_parse_option(dev, conn, iplen); conn->tcpstateflags = TCP_ESTABLISHED; memcpy(conn->rcvseq, tcp->seqno, 4);