1 /* $NetBSD: sockpair.c,v 1.2 2020/08/11 13:15:39 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2020 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 <sys/cdefs.h> 19 __RCSID("$NetBSD: sockpair.c,v 1.2 2020/08/11 13:15:39 christos Exp $"); 20 21 #include "portable.h" 22 #include <ac/socket.h> 23 #include <ac/unistd.h> 24 25 #include <lutil.h> 26 27 /* Return a pair of socket descriptors that are connected to each other. 28 * The returned descriptors are suitable for use with select(). The two 29 * descriptors may or may not be identical; the function may return 30 * the same descriptor number in both slots. It is guaranteed that 31 * data written on sds[1] will be readable on sds[0]. The returned 32 * descriptors may be datagram oriented, so data should be written 33 * in reasonably small pieces and read all at once. On Unix systems 34 * this function is best implemented using a single pipe() call. 35 */ 36 37 int lutil_pair( ber_socket_t sds[2] ) 38 { 39 #ifdef USE_PIPE 40 return pipe( sds ); 41 #else 42 struct sockaddr_in si; 43 int rc; 44 ber_socklen_t len = sizeof(si); 45 ber_socket_t sd; 46 47 sd = socket( AF_INET, SOCK_DGRAM, 0 ); 48 if ( sd == AC_SOCKET_INVALID ) { 49 return sd; 50 } 51 52 (void) memset( (void*) &si, '\0', len ); 53 si.sin_family = AF_INET; 54 si.sin_port = 0; 55 si.sin_addr.s_addr = htonl( INADDR_LOOPBACK ); 56 57 rc = bind( sd, (struct sockaddr *)&si, len ); 58 if ( rc == AC_SOCKET_ERROR ) { 59 tcp_close(sd); 60 return rc; 61 } 62 63 rc = getsockname( sd, (struct sockaddr *)&si, &len ); 64 if ( rc == AC_SOCKET_ERROR ) { 65 tcp_close(sd); 66 return rc; 67 } 68 69 rc = connect( sd, (struct sockaddr *)&si, len ); 70 if ( rc == AC_SOCKET_ERROR ) { 71 tcp_close(sd); 72 return rc; 73 } 74 75 sds[0] = sd; 76 #if !HAVE_WINSOCK 77 sds[1] = dup( sds[0] ); 78 #else 79 sds[1] = sds[0]; 80 #endif 81 return 0; 82 #endif 83 } 84