1138269Snik/* 2138269SnikCopyright 2004 Michiel Boland. All rights reserved. 3138269Snik 4138269SnikRedistribution and use in source and binary forms, with or without 5138269Snikmodification, are permitted provided that the following conditions 6138269Snikare met: 7138269Snik 8138269Snik1. Redistributions of source code must retain the above copyright 9138269Sniknotice, this list of conditions and the following disclaimer. 10138269Snik 11138269Snik2. Redistributions in binary form must reproduce the above copyright 12138269Sniknotice, this list of conditions and the following disclaimer in the 13138269Snikdocumentation and/or other materials provided with the distribution. 14138269Snik 15138269SnikTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16138269SnikOR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17138269SnikWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18138269SnikARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE 19138269SnikLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 20138269SnikOR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 21138269SnikOF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 22138269SnikBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23138269SnikWHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 24138269SnikOR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 25138269SnikEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26138269Snik 27138269Snik$FreeBSD$ 28138269Snik 29138269Snik*/ 30138269Snik 31138269Snik#include <sys/types.h> 32138269Snik#include <sys/socket.h> 33138269Snik#include <netinet/in.h> 34138269Snik#include <fcntl.h> 35138269Snik#include <poll.h> 36138269Snik#include <unistd.h> 37138269Snik#include <signal.h> 38222485Srwatson#include <stdio.h> 39138269Snik#include <stdlib.h> 40138269Snik#include <string.h> 41138269Snik 42138269Snik/* 43138269Snik * The following code sets up two connected TCP sockets that send data to each 44138269Snik * other until the window is closed. Then one of the sockets is closed, which 45138269Snik * will generate a RST once the TCP at the other socket does a window probe. 46138269Snik * 47138269Snik * All versions of FreeBSD prior to 11/26/2004 will ignore this RST into a 0 48138269Snik * window, causing the connection (and application) to hang indefinitely. 49138269Snik * On patched versions of FreeBSD (and other operating systems), the RST 50138269Snik * will be accepted and the program will exit in a few seconds. 51138269Snik */ 52138269Snik 53138269Snik/* 54138269Snik * If the alarm fired then we've hung and the test failed. 55138269Snik */ 56138269Snikvoid 57138269Snikdo_alrm(int s) 58138269Snik{ 59138269Snik printf("not ok 1 - tcpfullwindowrst\n"); 60138269Snik exit(0); 61138269Snik} 62138269Snik 63138269Snikint 64138269Snikmain(void) 65138269Snik{ 66138269Snik int o, s, t, u, do_t, do_u; 67138269Snik struct pollfd pfd[2]; 68138269Snik struct sockaddr_in sa; 69138269Snik char buf[4096]; 70138269Snik 71138269Snik printf("1..1\n"); 72138269Snik signal(SIGALRM, do_alrm); 73138269Snik alarm(20); 74138269Snik 75138269Snik s = socket(AF_INET, SOCK_STREAM, 0); 76138269Snik if (s == -1) 77138269Snik return 1; 78138269Snik o = 1; 79138269Snik setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &o, sizeof o); 80138269Snik memset(&sa, 0, sizeof sa); 81138269Snik sa.sin_family = AF_INET; 82138269Snik sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 83138269Snik sa.sin_port = htons(3737); 84138269Snik if (bind(s, (struct sockaddr *) &sa, sizeof sa) == -1) 85138269Snik return 1; 86138269Snik if (listen(s, 1) == -1) 87138269Snik return 1; 88138269Snik t = socket(AF_INET, SOCK_STREAM, 0); 89138269Snik if (t == -1) 90138269Snik return 1; 91138269Snik if (connect(t, (struct sockaddr *) &sa, sizeof sa) == -1) 92138269Snik return 1; 93138269Snik u = accept(s, 0, 0); 94138269Snik if (u == -1) 95138269Snik return 1; 96138269Snik close(s); 97138269Snik fcntl(t, F_SETFL, fcntl(t, F_GETFL) | O_NONBLOCK); 98138269Snik fcntl(u, F_SETFL, fcntl(t, F_GETFL) | O_NONBLOCK); 99138269Snik do_t = 1; 100138269Snik do_u = 1; 101138269Snik pfd[0].fd = t; 102138269Snik pfd[0].events = POLLOUT; 103138269Snik pfd[1].fd = u; 104138269Snik pfd[1].events = POLLOUT; 105138269Snik while (do_t || do_u) { 106138269Snik if (poll(pfd, 2, 1000) == 0) { 107138269Snik if (do_t) { 108138269Snik close(t); 109138269Snik pfd[0].fd = -1; 110138269Snik do_t = 0; 111138269Snik } 112138269Snik continue; 113138269Snik } 114138269Snik if (pfd[0].revents & POLLOUT) { 115138269Snik if (write(t, buf, sizeof buf) == -1) { 116138269Snik close(t); 117138269Snik pfd[0].fd = -1; 118138269Snik do_t = 0; 119138269Snik } 120138269Snik } 121138269Snik if (pfd[1].revents & POLLOUT) { 122138269Snik if (write(u, buf, sizeof buf) == -1) { 123138269Snik close(u); 124138269Snik pfd[1].fd = -1; 125138269Snik do_u = 0; 126138269Snik } 127138269Snik } 128138269Snik } 129138269Snik 130138269Snik printf("ok 1 - tcpfullwindowrst\n"); 131138269Snik return 0; 132138269Snik} 133