setsockopt2.c revision 1.3
1/* $OpenBSD: setsockopt2.c,v 1.3 2012/02/19 23:58:57 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 24void 25check_timeout(int s, int sec, struct timeval *to) 26{ 27 struct timeval t1, t2; 28 struct timeval e, max; 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 max.tv_sec = sec; 39 max.tv_usec = 0; 40 ASSERT(timercmp(&e, &max, <)); 41} 42 43static void * 44sock_connect(void *arg) 45{ 46 struct sockaddr_in sin; 47 struct timeval to; 48 pid_t child_pid; 49 int status; 50 int s, s2, s3; 51 52 CHECKe(s = socket(AF_INET, SOCK_STREAM, 0)); 53 CHECKe(s2 = dup(s)); 54 CHECKe(s3 = fcntl(s, F_DUPFD, s)); 55 bzero(&sin, sizeof(sin)); 56 sin.sin_family = AF_INET; 57 sin.sin_len = sizeof(sin); 58 sin.sin_port = htons(6543); 59 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 60 CHECKe(connect(s, (struct sockaddr *)&sin, sizeof(sin))); 61 to.tv_sec = 2; 62 to.tv_usec = 0.5 * 1e6; 63 CHECKe(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to))); 64 CHECKe(child_pid = fork()); 65 if (child_pid == 0) { 66 to.tv_sec = 1; 67 to.tv_usec = 0.5 * 1e6; 68 CHECKe(setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &to, sizeof(to))); 69 check_timeout(s, 2, &to); 70 check_timeout(s2, 2, &to); 71 check_timeout(s3, 2, &to); 72 return (NULL); 73 } 74 sleep(2); 75 check_timeout(s, 2, &to); 76 check_timeout(s2, 2, &to); 77 check_timeout(s3, 2, &to); 78 CHECKe(s2 = dup(s)); 79 CHECKe(s3 = fcntl(s, F_DUPFD, s)); 80 check_timeout(s2, 2, &to); 81 check_timeout(s3, 2, &to); 82 CHECKe(close(s)); 83 CHECKe(close(s2)); 84 CHECKe(close(s3)); 85 ASSERTe(wait(&status), == child_pid); 86 ASSERT(WIFEXITED(status)); 87 CHECKr(WEXITSTATUS(status)); 88 return (NULL); 89} 90 91static void * 92sock_accept(void *arg) 93{ 94 pthread_t connect_thread; 95 struct sockaddr_in sin; 96 int s; 97 98 CHECKe(s = socket(AF_INET, SOCK_STREAM, 0)); 99 bzero(&sin, sizeof(sin)); 100 sin.sin_family = AF_INET; 101 sin.sin_len = sizeof(sin); 102 sin.sin_port = htons(6543); 103 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 104 CHECKe(bind(s, (struct sockaddr *)&sin, sizeof(sin))); 105 CHECKe(listen(s, 2)); 106 107 CHECKr(pthread_create(&connect_thread, NULL, sock_connect, NULL)); 108 CHECKr(pthread_join(connect_thread, NULL)); 109 return (NULL); 110} 111 112int 113main(int argc, char **argv) 114{ 115 pthread_t accept_thread; 116 117 CHECKr(pthread_create(&accept_thread, NULL, sock_accept, NULL)); 118 CHECKr(pthread_join(accept_thread, NULL)); 119 SUCCEED; 120} 121