1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 1997 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  28 /*        All Rights Reserved   */
  29 
  30 /*
  31  * University Copyright- Copyright (c) 1982, 1986, 1988
  32  * The Regents of the University of California
  33  * All Rights Reserved
  34  *
  35  * University Acknowledgment- Portions of this document are derived from
  36  * software developed by the University of California, Berkeley, and its
  37  * contributors.
  38  */
  39 
  40 #pragma ident   "%Z%%M% %I%     %E% SMI"
  41 
  42 #include <sys/types.h>
  43 #include <sys/socket.h>
  44 #include <sys/stropts.h>
  45 #include <sys/stream.h>
  46 #include <sys/socketvar.h>
  47 #include <errno.h>
  48 #include <unistd.h>
  49 #include <stdlib.h>
  50 
  51 extern int _socket_create(int, int, int, int);
  52 extern int _so_socketpair(int*);
  53 
  54 int _socketpair_create(int, int, int, int*, int);
  55 
  56 #pragma weak socketpair = _socketpair
  57 
  58 int
  59 _socketpair(int family, int type, int protocol, int sv[2])
  60 {
  61         return (_socketpair_create(family, type, protocol, sv, SOV_DEFAULT));
  62 }
  63 
  64 /*
  65  * Used by the BCP library.
  66  */
  67 int
  68 _socketpair_bsd(int family, int type, int protocol, int sv[2])
  69 {
  70         return (_socketpair_create(family, type, protocol, sv, SOV_SOCKBSD));
  71 }
  72 
  73 int
  74 _socketpair_svr4(int family, int type, int protocol, int sv[2])
  75 {
  76         return (_socketpair_create(family, type, protocol, sv,
  77                                 SOV_SOCKSTREAM));
  78 }
  79 
  80 int
  81 __xnet_socketpair(int family, int type, int protocol, int sv[2])
  82 {
  83         return (_socketpair_create(family, type, protocol, sv,
  84                                 SOV_XPG4_2));
  85 }
  86 
  87 int
  88 _socketpair_create(int family, int type, int protocol, int sv[2], int version)
  89 {
  90         int res;
  91         int fd1, fd2;
  92 
  93         /*
  94          * Create the two sockets and pass them to _so_socketpair, which
  95          * will connect them together.
  96          */
  97         fd1 = _socket_create(family, type, protocol, version);
  98         if (fd1 < 0)
  99                 return (-1);
 100         fd2 = _socket_create(family, type, protocol, version);
 101         if (fd2 < 0) {
 102                 int error = errno;
 103 
 104                 (void) close(fd1);
 105                 errno = error;
 106                 return (-1);
 107         }
 108         sv[0] = fd1;
 109         sv[1] = fd2;
 110         res = _so_socketpair(sv);
 111         if (res < 0) {
 112                 int error = errno;
 113 
 114                 (void) close(fd1);
 115                 (void) close(fd2);
 116                 errno = error;
 117                 return (-1);
 118         }
 119         /*
 120          * Check if kernel returned different fds in which case we close
 121          * the original ones. This is the case for SOCK_STREAM where
 122          * one of the original sockets is used as a listener and
 123          * _so_socketpair passes out the newly accepted socket.
 124          */
 125         if (sv[0] != fd1)
 126                 (void) close(fd1);
 127         if (sv[1] != fd2)
 128                 (void) close(fd2);
 129         return (res);
 130 }