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 #include <sys/types.h>
  41 #include <sys/socket.h>
  42 #include <sys/stropts.h>
  43 #include <sys/stream.h>
  44 #include <sys/socketvar.h>
  45 #include <errno.h>
  46 #include <unistd.h>
  47 #include <stdlib.h>
  48 
  49 extern int _so_socket(int, int, int, dev_t, int);
  50 extern int _so_socketpair(int *);
  51 
  52 int _socketpair_create(int, int, int, int*, int);
  53 
  54 #pragma weak socketpair = _socketpair
  55 
  56 int
  57 _socketpair(int family, int type, int protocol, int sv[2])
  58 {
  59         return (_socketpair_create(family, type, protocol, sv, SOV_DEFAULT));
  60 }
  61 
  62 /*
  63  * Used by the BCP library.
  64  */
  65 int
  66 _socketpair_bsd(int family, int type, int protocol, int sv[2])
  67 {
  68         return (_socketpair_create(family, type, protocol, sv, SOV_SOCKBSD));
  69 }
  70 
  71 int
  72 _socketpair_svr4(int family, int type, int protocol, int sv[2])
  73 {
  74         return (_socketpair_create(family, type, protocol, sv,
  75                                 SOV_SOCKSTREAM));
  76 }
  77 
  78 int
  79 __xnet_socketpair(int family, int type, int protocol, int sv[2])
  80 {
  81         return (_socketpair_create(family, type, protocol, sv,
  82                                 SOV_XPG4_2));
  83 }
  84 
  85 int
  86 _socketpair_create(int family, int type, int protocol, int sv[2], int version)
  87 {
  88         int res;
  89         int fd1, fd2;
  90 
  91         /*
  92          * Create the two sockets and pass them to _so_socketpair, which
  93          * will connect them together.
  94          */
  95         fd1 = _so_socket(family, type, protocol, NULL, version);
  96         if (fd1 < 0)
  97                 return (-1);
  98         fd2 = _so_socket(family, type, protocol, NULL, version);
  99         if (fd2 < 0) {
 100                 int error = errno;
 101 
 102                 (void) close(fd1);
 103                 errno = error;
 104                 return (-1);
 105         }
 106         sv[0] = fd1;
 107         sv[1] = fd2;
 108         res = _so_socketpair(sv);
 109         if (res < 0) {
 110                 int error = errno;
 111 
 112                 (void) close(fd1);
 113                 (void) close(fd2);
 114                 errno = error;
 115                 return (-1);
 116         }
 117         /*
 118          * Check if kernel returned different fds in which case we close
 119          * the original ones. This is the case for SOCK_STREAM where
 120          * one of the original sockets is used as a listener and
 121          * _so_socketpair passes out the newly accepted socket.
 122          */
 123         if (sv[0] != fd1)
 124                 (void) close(fd1);
 125         if (sv[1] != fd2)
 126                 (void) close(fd2);
 127         return (res);
 128 }