setsockopt2.c revision 1.1
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 18static void 19alarm_handler(int sig) 20{ 21 _exit(NOTOK); 22} 23 24int 25check_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 42static void * 43sock_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 90static void * 91sock_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 111int 112main(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