#include #include #include #include #include #include #include #include #include #define DEAD_IP "127.16.0.1" #define fail_if(arg) if (0 != (arg)) { \ fprintf(stderr, "Failed at %d: %s\n", __LINE__, #arg);\ return 1; }; void handler(int sig) { // printf("Got signal %d\n", sig); } int _test(int proto, int timeo, int blocking) { struct sockaddr_in addr4 = { .sin_family = AF_INET, .sin_port = htons(5555) }; struct sockaddr *deadaddr = (struct sockaddr *)&addr4; struct sigaction sa = { .sa_handler = handler, .sa_flags = SA_RESTART }; struct timeval tv = { .tv_sec = 300 }; int sk, rtn; fail_if(1 != inet_pton(AF_INET, DEAD_IP, &addr4.sin_addr)); fail_if(0 > (sk = socket(PF_INET, SOCK_STREAM | (blocking ? 0 : SOCK_NONBLOCK), proto))); if (timeo) { fail_if(setsockopt(sk, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof tv)); } fail_if(sigaction(SIGALRM, &sa, NULL)); fail_if(alarm(3) < 0); rtn = connect(sk, deadaddr, sizeof *deadaddr); printf(" 1st connect - rtn: %d errno: %d (%s)\n", rtn, errno, strerror(errno)); rtn = connect(sk, deadaddr, sizeof *deadaddr); printf(" 2nd connect - rtn: %d errno: %d (%s)\n", rtn, errno, strerror(errno)); close(sk); return 0; } #define test(proto, timeo, blocking) \ (printf("Testing " #proto " on a %s%sblocking socket\n", \ timeo ? "timeo " : "", blocking ? "" : "non-"), \ _test(proto, timeo, blocking)) int main(int argc, char *argv[]) { setlinebuf(stdout); fail_if(system("iptables -I OUTPUT -d " DEAD_IP "/32 -j DROP")); test(IPPROTO_SCTP, 0, 1); test(IPPROTO_TCP, 0, 1); test(IPPROTO_SCTP, 1, 1); test(IPPROTO_TCP, 1, 1); test(IPPROTO_SCTP, 0, 0); test(IPPROTO_TCP, 0, 0); test(IPPROTO_SCTP, 1, 1); test(IPPROTO_TCP, 1, 1); fail_if(system("iptables -D OUTPUT -d " DEAD_IP "/32 -j DROP")); }