1 /* $NetBSD: timed_connect.c,v 1.1.1.2 2017/02/14 01:13:44 christos Exp $ */ 2 3 /*++ 4 /* NAME 5 /* timed_connect 3 6 /* SUMMARY 7 /* connect operation with timeout 8 /* SYNOPSIS 9 /* #include <sys/socket.h> 10 /* #include <timed_connect.h> 11 /* 12 /* int timed_connect(fd, buf, buf_len, timeout) 13 /* int fd; 14 /* struct sockaddr *buf; 15 /* int buf_len; 16 /* int timeout; 17 /* DESCRIPTION 18 /* timed_connect() implement a BSD socket connect() operation that is 19 /* bounded in time. 20 /* 21 /* Arguments: 22 /* .IP fd 23 /* File descriptor in the range 0..FD_SETSIZE. This descriptor 24 /* must be set to non-blocking mode prior to calling timed_connect(). 25 /* .IP buf 26 /* Socket address buffer pointer. 27 /* .IP buf_len 28 /* Size of socket address buffer. 29 /* .IP timeout 30 /* The deadline in seconds. This must be a number > 0. 31 /* DIAGNOSTICS 32 /* Panic: interface violations. 33 /* When the operation does not complete within the deadline, the 34 /* result value is -1, and errno is set to ETIMEDOUT. 35 /* All other returns are identical to those of a blocking connect(2) 36 /* operation. 37 /* WARNINGS 38 /* .ad 39 /* .fi 40 /* A common error is to call timed_connect() without enabling 41 /* non-blocking I/O on the socket. In that case, the \fItimeout\fR 42 /* parameter takes no effect. 43 /* LICENSE 44 /* .ad 45 /* .fi 46 /* The Secure Mailer license must be distributed with this software. 47 /* AUTHOR(S) 48 /* Wietse Venema 49 /* IBM T.J. Watson Research 50 /* P.O. Box 704 51 /* Yorktown Heights, NY 10598, USA 52 /*--*/ 53 54 /* System library. */ 55 56 #include <sys_defs.h> 57 #include <sys/socket.h> 58 #include <errno.h> 59 60 /* Utility library. */ 61 62 #include "msg.h" 63 #include "iostuff.h" 64 #include "sane_connect.h" 65 #include "timed_connect.h" 66 67 /* timed_connect - connect with deadline */ 68 69 int timed_connect(int sock, struct sockaddr *sa, int len, int timeout) 70 { 71 int error; 72 SOCKOPT_SIZE error_len; 73 74 /* 75 * Sanity check. Just like with timed_wait(), the timeout must be a 76 * positive number. 77 */ 78 if (timeout <= 0) 79 msg_panic("timed_connect: bad timeout: %d", timeout); 80 81 /* 82 * Start the connection, and handle all possible results. 83 */ 84 if (sane_connect(sock, sa, len) == 0) 85 return (0); 86 if (errno != EINPROGRESS) 87 return (-1); 88 89 /* 90 * A connection is in progress. Wait for a limited amount of time for 91 * something to happen. If nothing happens, report an error. 92 */ 93 if (write_wait(sock, timeout) < 0) 94 return (-1); 95 96 /* 97 * Something happened. Some Solaris 2 versions have getsockopt() itself 98 * return the error, instead of returning it via the parameter list. 99 */ 100 error = 0; 101 error_len = sizeof(error); 102 if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void *) &error, &error_len) < 0) 103 return (-1); 104 if (error) { 105 errno = error; 106 return (-1); 107 } 108 109 /* 110 * No problems. 111 */ 112 return (0); 113 } 114