1 /* $OpenBSD: setsockopt3a.c,v 1.2 2010/01/03 23:02:34 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_accept(void *arg) 43 { 44 struct sockaddr_in sin; 45 struct timeval to; 46 int s, s2, s3; 47 48 CHECKe(s = strtol(arg, NULL, 10)); 49 bzero(&sin, sizeof(sin)); 50 sin.sin_family = AF_INET; 51 sin.sin_len = sizeof(sin); 52 sin.sin_port = htons(6543); 53 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 54 CHECKe(connect(s, (struct sockaddr *)&sin, sizeof(sin))); 55 to.tv_sec = 2; 56 to.tv_usec = 0.5 * 1e6; 57 CHECKr(check_timeout(s, 3, &to)); 58 CHECKe(s2 = dup(s)); 59 CHECKe(s3 = fcntl(s, F_DUPFD, s)); 60 CHECKr(check_timeout(s2, 3, &to)); 61 CHECKr(check_timeout(s3, 3, &to)); 62 return (NULL); 63 } 64 65 int 66 main(int argc, char **argv) 67 { 68 pthread_t accept_thread; 69 70 if (argc != 2) 71 exit(NOTOK); 72 CHECKr(pthread_create(&accept_thread, NULL, sock_accept, argv[1])); 73 CHECKr(pthread_join(accept_thread, NULL)); 74 SUCCEED; 75 } 76