xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/sane_connect.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
1 /*	$NetBSD: sane_connect.c,v 1.2 2017/02/14 01:16:49 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	sane_connect 3
6 /* SUMMARY
7 /*	sanitize connect() results
8 /* SYNOPSIS
9 /*	#include <sane_connect.h>
10 /*
11 /*	int	sane_connect(sock, buf, len)
12 /*	int	sock;
13 /*	struct sockaddr	*buf;
14 /*	SOCKADDR_SIZE *len;
15 /* DESCRIPTION
16 /*	sane_connect() implements the connect(2) socket call, and maps
17 /*	known harmless error results to EAGAIN.
18 /* BUGS
19 /*	Bizarre systems may have other harmless error results. Such
20 /*	systems encourage programmers to ignore error results, and
21 /*	penalize programmers who code defensively.
22 /* LICENSE
23 /* .ad
24 /* .fi
25 /*	The Secure Mailer license must be distributed with this software.
26 /* AUTHOR(S)
27 /*	Wietse Venema
28 /*	IBM T.J. Watson Research
29 /*	P.O. Box 704
30 /*	Yorktown Heights, NY 10598, USA
31 /*--*/
32 
33 /* System library. */
34 
35 #include "sys_defs.h"
36 #include <sys/socket.h>
37 #include <errno.h>
38 
39 /* Utility library. */
40 
41 #include "msg.h"
42 #include "sane_connect.h"
43 
44 /* sane_connect - sanitize connect() results */
45 
sane_connect(int sock,struct sockaddr * sa,SOCKADDR_SIZE len)46 int     sane_connect(int sock, struct sockaddr *sa, SOCKADDR_SIZE len)
47 {
48 
49     /*
50      * XXX Solaris select() produces false read events, so that read() blocks
51      * forever on a blocking socket, and fails with EAGAIN on a non-blocking
52      * socket. Turning on keepalives will fix a blocking socket provided that
53      * the kernel's keepalive timer expires before the Postfix watchdog
54      * timer.
55      *
56      * XXX Work around NAT induced damage by sending a keepalive before an idle
57      * connection is expired. This requires that the kernel keepalive timer
58      * is set to a short time, like 100s.
59      */
60     if (sa->sa_family == AF_INET) {
61 	int     on = 1;
62 
63 	(void) setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
64 			  (void *) &on, sizeof(on));
65     }
66     return (connect(sock, sa, len));
67 }
68