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