lib/tst_checksum: add crc32c checksum
PATCH v2 1/2 lib/tst_checksum: add crc32c checksum
It will be used to make a SCTP packet in the test.
---
v2: As suggested by Cyril:
* updated the docs, added section 2.2.25
* added 'tst_' prefix
* changed type 'int' to 'size_t' for the buffer length
doc/test-writing-guidelines.txt | 6 +++ include/tst_checksum.h | 29 ++++++++++++ lib/tst_checksum.c | 95 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 130 insertions(+), 0 deletions(-) create mode 100644 include/tst_checksum.h create mode 100644 lib/tst_checksum.c
doc/test-writing-guidelines.txt +6 -0
@@ -1366,6 +1366,12 @@ For reference to tainted kernels, see kernel documentation: Documentation/admin-guide/tainted-kernels.rst or https://www.kernel.org/doc/html/latest/admin-guide/tainted-kernels.html +2.2.25 Checksums +^^^^^^^^^^^^^^^^ + +CRC32c checksum generation is supported by LTP. In order to use it, the +test should include "tst_checksum.h" header, then can call tst_crc32c(). + 2.3 Writing a testcase in shell ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/tst_checksum.h new file +29 -0
@@ -0,0 +1,29 @@ +/* +* Copyright (c) 2018 Oracle and/or its affiliates. All Rights Reserved. +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef TST_CHECKSUM_H__ +#define TST_CHECKSUM_H__ + +#include <stdint.h> +#include <stddef.h> + +/* +* Generates CRC32c checksum. +*/ +uint32_t tst_crc32c (uint8_t *buf,size_t buf_len); + +#endif
lib/tst_checksum.c new file +95 -0
95 lines not on this page · raw message
Signature · 1 line
1.7.1
PATCH v2 2/2 sctp_big_chunk: make INIT packet in the test
Since creating many different IP addresses and binding them to the same SCTP socket is a time consuming process, prepare SCTP INIT chunk in the test.
---
v2: * the test doesn't support IPv6 fragmentation, TCONF in that case
* add needs_root since we use a raw socket
runtest/cve | 1 - testcases/network/sctp/sctp_big_chunk.c | 105 +++++++++++++++++++++++++++---- 2 files changed, 93 insertions(+), 13 deletions(-)
runtest/cve +0 -1
@@ -33,4 +33,3 @@ cve-2017-17052 cve-2017-17052 cve-2017-16939 cve-2017-16939 cve-2017-17053 cve-2017-17053 cve-2018-5803 sctp_big_chunk -cve-2018-5803_2 sctp_big_chunk -a 10000
testcases/network/sctp/sctp_big_chunk.c +93 -12
166 lines not on this page · raw message
Signature · 1 line
1.7.1
PATCH v2 2/2 sctp_big_chunk: make INIT packet in the test
Hi Alexey,
This patch set works well on my environment, and it looks good to me.
Thanks,
Xiao Yang
Quoted 198 lines · Alexey Kodanev
Since creating many different IP addresses and binding them to the same SCTP socket is a time consuming process, prepare SCTP INIT chunk in the test.
Signed-off-by Alexey Kodanev <[email protected]>---
v2: * the test doesn't support IPv6 fragmentation, TCONF in that case
* addneeds_rootsince we use a raw socketruntest/cve | 1 - testcases/network/sctp/sctp_big_chunk.c | 105 +++++++++++++++++++++++++++---- 2 files changed, 93 insertions(+), 13 deletions(-)runtest/cve +0
-1@@ -33,4 +33,3 @@ cve-2017-17052 cve-2017-17052 cve-2017-16939 cve-2017-16939 cve-2017-17053 cve-2017-17053 cve-2018-5803 sctp_big_chunk -cve-2018-5803_2 sctp_big_chunk -a 10000testcases/network/sctp/sctp_big_chunk.c +93
-12@@ -24,12 +24,14 @@#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> +#include <netinet/ip.h> +#include <netinet/ip6.h> #include <netdb.h> #include <sys/syscall.h> -#include <fcntl.h> #include "tst_test.h" #include "tst_safe_stdio.h" +#include "tst_checksum.h" #include "lapi/netinet_in.h" #include "lapi/socket.h" #include "lapi/sctp.h" @@ -38,6 +40,8 @@ static int port;static int sfd, cfd;static struct sockaddr_in6 rmt, loc; +static uint8_t packet[IP_MAXPACKET ]; +static int pkt_len;static char *addr_param;static int addr_num =3273 ;@@ -53,35 +57,108 @@ static void setup_server(void)tst_res (TINFO ,"sctp server listen on %d" , port);SAFE_LISTEN (sfd,1 ); + +srand (port); +} + +static void update_packet_field (size_t *off,void *buf,size_t buf_len) +{ +memcpy (packet + *off, buf, buf_len); + *off += buf_len; }static void setup_client (void ) { -struct sockaddr_in6 addr_buf[addr_num]; +struct ip6_hdr ip6; +const size_t ip6_hdr_len =sizeof (ip6); +size_t cmn_hdr_off; +size_t off;int i; - cfd =SAFE_SOCKET (AF_INET6 ,SOCK_STREAM ,IPPROTO_SCTP ); +memset (&ip6,0 ,sizeof (ip6)); + ip6.ip6_flow =htonl (6 <<28 |2 <<20 ); + ip6.ip6_hops =64 ; + ip6.ip6_nxt =IPPROTO_SCTP ; + ip6.ip6_src.s6_addr[15 ] =1 ; + ip6.ip6_dst.s6_addr[15 ] =1 ; rmt.sin6_family =AF_INET6 ; rmt.sin6_addr = in6addr_loopback; - rmt.sin6_port =htons (port); -tst_res (TINFO ,"bind %d additional IP addresses" , addr_num); +/* SCTP common header */ + off = ip6_hdr_len; + +uint16_t src_port =htons (port -1 ); +uint16_t dst_port =htons (port); +uint32_t vtag =0 ; +uint32_t checksum =0 ; + +update_packet_field (&off, &src_port,2 ); +update_packet_field (&off, &dst_port,2 ); +update_packet_field (&off, &vtag,4 ); +update_packet_field (&off, &checksum,4 ); + cmn_hdr_off = off; + +/* SCTP INIT chunk */ +uint16_t chunk_len; + + packet[off++] =1 ; + packet[off++] =0 ; + off +=2 ;/* chunk length, will be set in the end */ + +uint32_t init_tag =rand (); +uint32_t rwnd =htonl (106496 ); +uint16_t outs =htons (10 ); +uint16_t ins =htons (65535 ); +uint32_t init_tsn =rand (); + +update_packet_field (&off, &init_tag,4 ); +update_packet_field (&off, &rwnd,4 ); +update_packet_field (&off, &outs,2 ); +update_packet_field (&off, &ins,2 ); +update_packet_field (&off, &init_tsn,4 ); -memset (addr_buf,0 ,sizeof (addr_buf)); +/* SCTP optional parameter for IPv6 addresses */ +uint16_t param_type =htons (6 ); +uint16_t param_len =htons (20 ); + +/* IPv6(40) + SCTP_COMMON(12) + SCTP_CHUNK(20) + SCTP_OPT(65460)) */ for (i =0 ; i < addr_num; ++i) { - addr_buf[i].sin6_family =AF_INET6 ; - addr_buf[i].sin6_addr = in6addr_loopback; +update_packet_field (&off, ¶m_type,2 ); +update_packet_field (&off, ¶m_len,2 ); + packet[off +15 ] =1 ; + off +=16 ; } + pkt_len = off; + +tst_res (TINFO ,"set chunk length %zu" , pkt_len - cmn_hdr_off); + chunk_len =htons (pkt_len - cmn_hdr_off); +memcpy (packet + cmn_hdr_off +2 , &chunk_len,2 ); + +/* set checksum for SCTP: common header + INIT chunk */ +uint32_t csum =tst_crc32c (packet + ip6_hdr_len, pkt_len - ip6_hdr_len); + +memcpy (packet + ip6_hdr_len +8 , &csum,4 ); + + ip6.ip6_plen =htons (pkt_len - ip6_hdr_len); +memcpy (packet, &ip6, ip6_hdr_len); -SAFE_SETSOCKOPT (cfd,SOL_SCTP ,SCTP_SOCKOPT_BINDX_ADD , addr_buf, -sizeof (addr_buf)); + cfd =SAFE_SOCKET (AF_INET6 ,SOCK_RAW ,IPPROTO_RAW ); } +static const char mtu_path[] ="/sys/class/net/lo/mtu" ; +static const unsigned int max_mtu =65535 ; +static unsigned int mtu; +static void setup (void ) {if (tst_parse_int (addr_param, &addr_num,1 ,INT_MAX ))tst_brk (TBROK ,"wrong address number '%s'" , addr_param); +/* We don't fragment IPv6 packet here yet, check that MTU is 65535 */ +SAFE_FILE_SCANF (mtu_path,"%d" , &mtu); +if (mtu < max_mtu) +tst_brk (TCONF ,"Test needs that 'lo' MTU has %d" , max_mtu); +setup_server ();setup_client (); }@@ -89,6 +166,7 @@ static void setup(void)static void run (void ) {int pid =SAFE_FORK (); +int i;if (!pid) {struct sockaddr_in6 addr6;@@ -99,8 +177,10 @@ static void run(void)exit (0 ); } -fcntl (cfd,F_SETFL ,O_NONBLOCK ); -connect (cfd, (struct sockaddr *)&rmt,sizeof (rmt)); +for (i =0 ; i <3 ; ++i) { +SAFE_SENDTO (1 , cfd, packet, pkt_len,0 , + (struct sockaddr *)&rmt,sizeof (rmt)); + }SAFE_KILL (pid,SIGKILL );SAFE_WAITPID (pid,NULL ,0 );@@ -114,6 +194,7 @@ static struct tst_option options[] = { };static struct tst_test test = { + .needs_root =1 , .setup = setup, .forks_child =1 , .test_all = run,