1 /* $OpenBSD: setsockopt1.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 <netinet/in.h> 9 #include <err.h> 10 #include <fcntl.h> 11 #include <netdb.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <unistd.h> 15 #include "test.h" 16 17 static void 18 alarm_handler(int sig) 19 { 20 _exit(NOTOK); 21 } 22 23 int 24 check_timeout(int s, int sec, struct timeval *to) 25 { 26 struct timeval t1, t2; 27 struct timeval e, d; 28 char buf[BUFSIZ]; 29 30 ASSERT(signal(SIGALRM, alarm_handler) != SIG_ERR); 31 CHECKe(alarm(sec)); 32 CHECKe(gettimeofday(&t1, NULL)); 33 ASSERT(read(s, &buf, sizeof(buf)) == -1); 34 CHECKe(gettimeofday(&t2, NULL)); 35 ASSERT(errno == EAGAIN); 36 timersub(&t2, &t1, &e); 37 timersub(&e, to, &d); 38 return ((d.tv_sec > 1 || (d.tv_usec / 1000) > 100) ? 1 : 0); 39 } 40 41 static void * 42 sock_connect(void *arg) 43 { 44 struct sockaddr_in sin; 45 struct timeval to; 46 int s, s2, s3; 47 48 CHECKe(s = socket(AF_INET, SOCK_STREAM, 0)); 49 CHECKe(s2 = dup(s)); 50 CHECKe(s3 = fcntl(s, F_DUPFD, s)); 51 bzero(&sin, sizeof(sin)); 52 sin.sin_family = AF_INET; 53 sin.sin_len = sizeof(sin); 54 sin.sin_port = htons(6543); 55 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 56 CHECKe(connect(s, (struct sockaddr *)&sin, sizeof(sin))); 57 to.tv_sec = 2; 58 to.tv_usec = 0.5 * 1e6; 59 CHECKe(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to))); 60 CHECKr(check_timeout(s, 3, &to)); 61 CHECKr(check_timeout(s2, 3, &to)); 62 CHECKr(check_timeout(s3, 3, &to)); 63 to.tv_sec = 1; 64 to.tv_usec = 0.5 * 1e6; 65 CHECKe(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to))); 66 CHECKr(check_timeout(s, 2, &to)); 67 CHECKr(check_timeout(s2, 2, &to)); 68 CHECKr(check_timeout(s3, 2, &to)); 69 return (NULL); 70 } 71 72 static void * 73 sock_accept(void *arg) 74 { 75 pthread_t connect_thread; 76 struct sockaddr_in sin; 77 int s; 78 79 CHECKe(s = socket(AF_INET, SOCK_STREAM, 0)); 80 bzero(&sin, sizeof(sin)); 81 sin.sin_family = AF_INET; 82 sin.sin_len = sizeof(sin); 83 sin.sin_port = htons(6543); 84 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 85 CHECKe(bind(s, (struct sockaddr *)&sin, sizeof(sin))); 86 CHECKe(listen(s, 2)); 87 88 CHECKr(pthread_create(&connect_thread, NULL, sock_connect, NULL)); 89 CHECKr(pthread_join(connect_thread, NULL)); 90 return (NULL); 91 } 92 93 int 94 main(int argc, char **argv) 95 { 96 pthread_t accept_thread; 97 98 CHECKr(pthread_create(&accept_thread, NULL, sock_accept, NULL)); 99 CHECKr(pthread_join(accept_thread, NULL)); 100 SUCCEED; 101 } 102