1 /* $OpenBSD: setsockopt2.c,v 1.1 2009/12/26 01:34:18 fgsch Exp $ */ 2 /* 3 * Federico G. Schwindt <fgsch@openbsd.org>, 2009. Public Domain. 4 */ 5 6 #include <sys/types.h> 7 #include <sys/socket.h> 8 #include <sys/wait.h> 9 #include <netinet/in.h> 10 #include <err.h> 11 #include <fcntl.h> 12 #include <netdb.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <unistd.h> 16 #include "test.h" 17 18 static void 19 alarm_handler(int sig) 20 { 21 _exit(NOTOK); 22 } 23 24 int 25 check_timeout(int s, int sec, struct timeval *to) 26 { 27 struct timeval t1, t2; 28 struct timeval e, d; 29 char buf[BUFSIZ]; 30 31 ASSERT(signal(SIGALRM, alarm_handler) != SIG_ERR); 32 CHECKe(alarm(sec)); 33 CHECKe(gettimeofday(&t1, NULL)); 34 ASSERT(read(s, &buf, sizeof(buf)) == -1); 35 CHECKe(gettimeofday(&t2, NULL)); 36 ASSERT(errno == EAGAIN); 37 timersub(&t2, &t1, &e); 38 timersub(&e, to, &d); 39 return ((d.tv_sec > 1 || (d.tv_usec / 1000) > 100) ? 1 : 0); 40 } 41 42 static void * 43 sock_connect(void *arg) 44 { 45 struct sockaddr_in sin; 46 struct timeval to; 47 pid_t child_pid; 48 int status; 49 int s, s2, s3; 50 51 CHECKe(s = socket(AF_INET, SOCK_STREAM, 0)); 52 CHECKe(s2 = dup(s)); 53 CHECKe(s3 = fcntl(s, F_DUPFD, s)); 54 bzero(&sin, sizeof(sin)); 55 sin.sin_family = AF_INET; 56 sin.sin_len = sizeof(sin); 57 sin.sin_port = htons(6543); 58 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 59 CHECKe(connect(s, (struct sockaddr *)&sin, sizeof(sin))); 60 to.tv_sec = 2; 61 to.tv_usec = 0.5 * 1e6; 62 CHECKe(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to))); 63 CHECKe(child_pid = fork()); 64 if (child_pid == 0) { 65 to.tv_sec = 1; 66 to.tv_usec = 0.5 * 1e6; 67 CHECKe(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to))); 68 CHECKr(check_timeout(s, 2, &to)); 69 CHECKr(check_timeout(s2, 2, &to)); 70 CHECKr(check_timeout(s3, 2, &to)); 71 return (NULL); 72 } 73 sleep(2); 74 CHECKr(check_timeout(s, 2, &to)); 75 CHECKr(check_timeout(s2, 2, &to)); 76 CHECKr(check_timeout(s3, 2, &to)); 77 CHECKe(s2 = dup(s)); 78 CHECKe(s3 = fcntl(s, F_DUPFD, s)); 79 CHECKr(check_timeout(s2, 2, &to)); 80 CHECKr(check_timeout(s3, 2, &to)); 81 CHECKe(close(s)); 82 CHECKe(close(s2)); 83 CHECKe(close(s3)); 84 ASSERTe(wait(&status), == child_pid); 85 ASSERT(WIFEXITED(status)); 86 CHECKr(WEXITSTATUS(status)); 87 return (NULL); 88 } 89 90 static void * 91 sock_accept(void *arg) 92 { 93 pthread_t connect_thread; 94 struct sockaddr_in sin; 95 int s; 96 97 CHECKe(s = socket(AF_INET, SOCK_STREAM, 0)); 98 bzero(&sin, sizeof(sin)); 99 sin.sin_family = AF_INET; 100 sin.sin_len = sizeof(sin); 101 sin.sin_port = htons(6543); 102 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 103 CHECKe(bind(s, (struct sockaddr *)&sin, sizeof(sin))); 104 CHECKe(listen(s, 2)); 105 106 CHECKr(pthread_create(&connect_thread, NULL, sock_connect, NULL)); 107 CHECKr(pthread_join(connect_thread, NULL)); 108 return (NULL); 109 } 110 111 int 112 main(int argc, char **argv) 113 { 114 pthread_t accept_thread; 115 116 CHECKr(pthread_create(&accept_thread, NULL, sock_accept, NULL)); 117 CHECKr(pthread_join(accept_thread, NULL)); 118 SUCCEED; 119 } 120