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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 26 /* All Rights Reserved */ 27 28 /* 29 * University Copyright- Copyright (c) 1982, 1986, 1988 30 * The Regents of the University of California 31 * All Rights Reserved 32 * 33 * University Acknowledgment- Portions of this document are derived from 34 * software developed by the University of California, Berkeley, and its 35 * contributors. 36 */ 37 38 #include <sys/types.h> 39 #include <sys/socket.h> 40 #include <sys/stropts.h> 41 #include <sys/stream.h> 42 #include <sys/socketvar.h> 43 #include <errno.h> 44 #include <unistd.h> 45 #include <stdlib.h> 46 47 extern int _so_socket(); 48 extern int _s_netconfig_path(); 49 extern int _setsockopt(); 50 51 int _socket_create(int, int, int, int); 52 53 #pragma weak socket = _socket 54 55 int 56 _socket(int family, int type, int protocol) 57 { 58 return (_socket_create(family, type, protocol, SOV_DEFAULT)); 59 } 60 61 /* 62 * Used by the BCP library. 63 */ 64 int 65 _socket_bsd(int family, int type, int protocol) 66 { 67 return (_socket_create(family, type, protocol, SOV_SOCKBSD)); 68 } 69 70 int 71 _socket_svr4(int family, int type, int protocol) 72 { 73 return (_socket_create(family, type, protocol, SOV_SOCKSTREAM)); 74 } 75 76 int 77 __xnet_socket(int family, int type, int protocol) 78 { 79 return (_socket_create(family, type, protocol, SOV_XPG4_2)); 80 } 81 82 /* 83 * Create a socket endpoint for socket() and socketpair(). 84 * In SunOS 4.X and in SunOS 5.X prior to XPG 4.2 the only error 85 * that could be returned due to invalid <family, type, protocol> 86 * was EPROTONOSUPPORT. (While the SunOS 4.X source contains EPROTOTYPE 87 * error as well that error can only be generated if the kernel is 88 * incorrectly configured.) 89 * For backwards compatibility only applications that request XPG 4.2 90 * (through c89 or XOPEN_SOURCE) will get EPROTOTYPE or EAFNOSUPPORT errors. 91 */ 92 int 93 _socket_create(int family, int type, int protocol, int version) 94 { 95 int fd; 96 97 /* 98 * Try creating without knowing the device assuming that 99 * the transport provider is registered in /etc/sock2path.d. 100 * If none found fall back to using /etc/netconfig to look 101 * up the name of the transport device name. This provides 102 * backwards compatibility for transport providers that have not 103 * yet been converted to using /etc/sock2path.d. 104 * XXX When all transport providers use /etc/sock2path.d. this 105 * part of the code can be removed. 106 */ 107 fd = _so_socket(family, type, protocol, NULL, version); 108 if (fd == -1) { 109 char *devpath; 110 int saved_errno = errno; 111 int prototype = 0; 112 113 switch (saved_errno) { 114 case EAFNOSUPPORT: 115 case EPROTOTYPE: 116 if (version != SOV_XPG4_2) 117 saved_errno = EPROTONOSUPPORT; 118 break; 119 case EPROTONOSUPPORT: 120 break; 121 122 default: 123 errno = saved_errno; 124 return (-1); 125 } 126 if (_s_netconfig_path(family, type, protocol, 127 &devpath, &prototype) == -1) { 128 errno = saved_errno; 129 return (-1); 130 } 131 fd = _so_socket(family, type, protocol, devpath, version); 132 free(devpath); 133 if (fd == -1) { 134 errno = saved_errno; 135 return (-1); 136 } 137 if (prototype != 0) { 138 if (_setsockopt(fd, SOL_SOCKET, SO_PROTOTYPE, 139 (caddr_t)&prototype, (int)sizeof (prototype)) < 0) { 140 (void) close(fd); 141 /* 142 * setsockopt often fails with ENOPROTOOPT 143 * but socket() should fail with 144 * EPROTONOSUPPORT. 145 */ 146 errno = EPROTONOSUPPORT; 147 return (-1); 148 } 149 } 150 } 151 return (fd); 152 } 153