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 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <sys/stropts.h>
32 #include <sys/stream.h>
33 #include <sys/socketvar.h>
34 #include <sys/sockio.h>
35 
36 #include <errno.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <stropts.h>
40 #include <stdio.h>
41 #include <strings.h>
42 #include <netinet/sctp.h>
43 
44 #pragma weak bind = _bind
45 #pragma weak listen = _listen
46 #pragma weak accept = _accept
47 #pragma weak connect = _connect
48 #pragma weak shutdown = _shutdown
49 #pragma weak recv = _recv
50 #pragma weak recvfrom = _recvfrom
51 #pragma weak recvmsg = _recvmsg
52 #pragma weak send = _send
53 #pragma weak sendmsg = _sendmsg
54 #pragma weak sendto = _sendto
55 #pragma weak getpeername = _getpeername
56 #pragma weak getsockname = _getsockname
57 #pragma weak getsockopt = _getsockopt
58 #pragma weak setsockopt = _setsockopt
59 
60 extern int _so_bind();
61 extern int _so_listen();
62 extern int _so_accept();
63 extern int _so_connect();
64 extern int _so_shutdown();
65 extern int _so_recv();
66 extern int _so_recvfrom();
67 extern int _so_recvmsg();
68 extern int _so_send();
69 extern int _so_sendmsg();
70 extern int _so_sendto();
71 extern int _so_getpeername();
72 extern int _so_getsockopt();
73 extern int _so_setsockopt();
74 extern int _so_getsockname();
75 
76 /*
77  * Note that regular sockets use SOV_SOCKBSD here to not allow a rebind of an
78  * already bound socket.
79  */
80 int
81 _bind(int sock, struct sockaddr *addr, int addrlen)
82 {
83 	return (_so_bind(sock, addr, addrlen, SOV_SOCKBSD));
84 }
85 
86 int
87 _listen(int sock, int backlog)
88 {
89 	return (_so_listen(sock, backlog, SOV_DEFAULT));
90 }
91 
92 int
93 _accept(int sock, struct sockaddr *addr, int *addrlen)
94 {
95 	return (_so_accept(sock, addr, addrlen, SOV_DEFAULT));
96 }
97 
98 int
99 _connect(int sock, struct sockaddr *addr, int addrlen)
100 {
101 	return (_so_connect(sock, addr, addrlen, SOV_DEFAULT));
102 }
103 
104 int
105 _shutdown(int sock, int how)
106 {
107 	return (_so_shutdown(sock, how, SOV_DEFAULT));
108 }
109 
110 int
111 _recv(int sock, char *buf, int len, int flags)
112 {
113 	return (_so_recv(sock, buf, len, flags & ~MSG_XPG4_2));
114 }
115 
116 int
117 _recvfrom(int sock, char *buf, int len, int flags,
118 	struct sockaddr *addr, int *addrlen)
119 {
120 	return (_so_recvfrom(sock, buf, len, flags & ~MSG_XPG4_2,
121 	    addr, addrlen));
122 }
123 
124 int
125 _recvmsg(int sock, struct msghdr *msg, int flags)
126 {
127 	return (_so_recvmsg(sock, msg, flags & ~MSG_XPG4_2));
128 }
129 
130 int
131 _send(int sock, char *buf, int len, int flags)
132 {
133 	return (_so_send(sock, buf, len, flags & ~MSG_XPG4_2));
134 }
135 
136 int
137 _sendmsg(int sock, struct msghdr *msg, int flags)
138 {
139 	return (_so_sendmsg(sock, msg, flags & ~MSG_XPG4_2));
140 }
141 
142 int
143 _sendto(int sock, char *buf, int len, int flags,
144 	struct sockaddr *addr, int *addrlen)
145 {
146 	return (_so_sendto(sock, buf, len, flags & ~MSG_XPG4_2,
147 	    addr, addrlen));
148 }
149 
150 int
151 _getpeername(int sock, struct sockaddr *name, int *namelen)
152 {
153 	return (_so_getpeername(sock, name, namelen, SOV_DEFAULT));
154 }
155 
156 int
157 _getsockname(int sock, struct sockaddr *name, int *namelen)
158 {
159 	return (_so_getsockname(sock, name, namelen, SOV_DEFAULT));
160 }
161 
162 int
163 _getsockopt(int sock, int level, int optname, char *optval, int *optlen)
164 {
165 	if (level == IPPROTO_SCTP) {
166 		sctp_assoc_t id = 0;
167 		socklen_t len = *optlen;
168 		int err = 0;
169 		struct sctpopt sopt;
170 
171 		switch (optname) {
172 		case SCTP_RTOINFO:
173 		case SCTP_ASSOCINFO:
174 		case SCTP_SET_PEER_PRIMARY_ADDR:
175 		case SCTP_PRIMARY_ADDR:
176 		case SCTP_PEER_ADDR_PARAMS:
177 		case SCTP_STATUS:
178 		case SCTP_GET_PEER_ADDR_INFO:
179 			/*
180 			 * Association ID is the first element params struct
181 			 */
182 			bcopy(optval, &id, sizeof (id));
183 			break;
184 		case SCTP_DEFAULT_SEND_PARAM:
185 			bcopy(&((struct sctp_sndrcvinfo *)
186 			    optval)->sinfo_assoc_id, &id, sizeof (id));
187 			break;
188 		}
189 
190 		sopt.sopt_aid = id;
191 		sopt.sopt_name = optname;
192 		sopt.sopt_val = optval;
193 		sopt.sopt_len = len;
194 		if (ioctl(sock, SIOCSCTPGOPT, &sopt) == -1) {
195 			err = -1;
196 		} else {
197 			*optlen = sopt.sopt_len;
198 		}
199 		return (err);
200 	} else {
201 		return (_so_getsockopt(sock, level, optname, optval, optlen,
202 		    SOV_DEFAULT));
203 	}
204 }
205 
206 int
207 _setsockopt(int sock, int level, int optname, char *optval, int optlen)
208 {
209 	return (_so_setsockopt(sock, level, optname, optval, optlen,
210 	    SOV_DEFAULT));
211 }
212 
213 int
214 __xnet_bind(int sock, const struct sockaddr *addr, socklen_t addrlen)
215 {
216 	return (_so_bind(sock, addr, addrlen, SOV_XPG4_2));
217 }
218 
219 
220 int
221 __xnet_listen(int sock, int backlog)
222 {
223 	return (_so_listen(sock, backlog, SOV_XPG4_2));
224 }
225 
226 int
227 __xnet_connect(int sock, const struct sockaddr *addr, socklen_t addrlen)
228 {
229 	return (_so_connect(sock, addr, addrlen, SOV_XPG4_2));
230 }
231 
232 int
233 __xnet_recvmsg(int sock, struct msghdr *msg, int flags)
234 {
235 	return (_so_recvmsg(sock, msg, flags | MSG_XPG4_2));
236 }
237 
238 int
239 __xnet_sendmsg(int sock, const struct msghdr *msg, int flags)
240 {
241 	return (_so_sendmsg(sock, msg, flags | MSG_XPG4_2));
242 }
243 
244 int
245 __xnet_sendto(int sock, const void *buf, size_t len, int flags,
246 	const struct sockaddr *addr, socklen_t addrlen)
247 {
248 	return (_so_sendto(sock, buf, len, flags | MSG_XPG4_2,
249 	    addr, addrlen));
250 }
251 
252 int
253 __xnet_getsockopt(int sock, int level, int option_name,
254 	void *option_value, socklen_t *option_lenp)
255 {
256 	if (level == IPPROTO_SCTP) {
257 		return (_getsockopt(sock, level, option_name, option_value,
258 		    (int *)option_lenp));
259 	} else {
260 		return (_so_getsockopt(sock, level, option_name, option_value,
261 		    option_lenp, SOV_XPG4_2));
262 	}
263 }
264