1/* $NetBSD: timed_connect.c,v 1.2 2017/02/14 01:16:49 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 69int 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