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