xref: /netbsd-src/external/bsd/openldap/dist/libraries/liblutil/sockpair.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: sockpair.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $	*/
2 
3 /* OpenLDAP: pkg/ldap/libraries/liblutil/sockpair.c,v 1.17.2.4 2009/01/22 00:00:58 kurt Exp */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1998-2009 The OpenLDAP Foundation.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted only as authorized by the OpenLDAP
11  * Public License.
12  *
13  * A copy of this license is available in the file LICENSE in the
14  * top-level directory of the distribution or, alternatively, at
15  * <http://www.OpenLDAP.org/license.html>.
16  */
17 
18 #include "portable.h"
19 #include <ac/socket.h>
20 #include <ac/unistd.h>
21 
22 #include <lutil.h>
23 
24 /* Return a pair of socket descriptors that are connected to each other.
25  * The returned descriptors are suitable for use with select(). The two
26  * descriptors may or may not be identical; the function may return
27  * the same descriptor number in both slots. It is guaranteed that
28  * data written on sds[1] will be readable on sds[0]. The returned
29  * descriptors may be datagram oriented, so data should be written
30  * in reasonably small pieces and read all at once. On Unix systems
31  * this function is best implemented using a single pipe() call.
32  */
33 
34 int lutil_pair( ber_socket_t sds[2] )
35 {
36 #ifdef USE_PIPE
37 	return pipe( sds );
38 #else
39 	struct sockaddr_in si;
40 	int rc;
41 	ber_socklen_t len = sizeof(si);
42 	ber_socket_t sd;
43 
44 	sd = socket( AF_INET, SOCK_DGRAM, 0 );
45 	if ( sd == AC_SOCKET_INVALID ) {
46 		return sd;
47 	}
48 
49 	(void) memset( (void*) &si, '\0', len );
50 	si.sin_family = AF_INET;
51 	si.sin_port = 0;
52 	si.sin_addr.s_addr = htonl( INADDR_LOOPBACK );
53 
54 	rc = bind( sd, (struct sockaddr *)&si, len );
55 	if ( rc == AC_SOCKET_ERROR ) {
56 		tcp_close(sd);
57 		return rc;
58 	}
59 
60 	rc = getsockname( sd, (struct sockaddr *)&si, &len );
61 	if ( rc == AC_SOCKET_ERROR ) {
62 		tcp_close(sd);
63 		return rc;
64 	}
65 
66 	rc = connect( sd, (struct sockaddr *)&si, len );
67 	if ( rc == AC_SOCKET_ERROR ) {
68 		tcp_close(sd);
69 		return rc;
70 	}
71 
72 	sds[0] = sd;
73 #if !HAVE_WINSOCK
74 	sds[1] = dup( sds[0] );
75 #else
76 	sds[1] = sds[0];
77 #endif
78 	return 0;
79 #endif
80 }
81