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 (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 /*
  27  * Copyright (c) 2018, Joyent, Inc.
  28  */
  29 
  30 #include <sys/types.h>
  31 #include <sys/stream.h>
  32 #define _SUN_TPI_VERSION 2
  33 #include <sys/tihdr.h>
  34 #include <sys/socket.h>
  35 #include <sys/xti_inet.h>
  36 #include <sys/systm.h>
  37 #include <sys/ddi.h>
  38 #include <sys/sunddi.h>
  39 #include <sys/kmem.h>
  40 #include <sys/strsubr.h>
  41 #include <sys/strsun.h>
  42 #include <sys/policy.h>
  43 
  44 #include <inet/common.h>
  45 #include <netinet/ip6.h>
  46 #include <inet/ip.h>
  47 #include <inet/ip_ire.h>
  48 #include <inet/ip_if.h>
  49 #include <inet/proto_set.h>
  50 #include <inet/ipclassifier.h>
  51 #include <inet/ipsec_impl.h>
  52 
  53 #include <netinet/in.h>
  54 #include <netinet/ip.h>
  55 #include <netinet/tcp.h>
  56 
  57 #include <inet/common.h>
  58 #include <inet/ip.h>
  59 #include <inet/ip6.h>
  60 #include <inet/sctp_itf.h>
  61 #include "sctp_impl.h"
  62 #include "sctp_asconf.h"
  63 #include "sctp_addr.h"
  64 
  65 static int      sctp_getpeeraddrs(sctp_t *, void *, int *);
  66 
  67 static int
  68 sctp_get_status(sctp_t *sctp, void *ptr)
  69 {
  70         struct sctp_status *sstat = ptr;
  71         sctp_faddr_t *fp;
  72         struct sockaddr_in *sin;
  73         struct sockaddr_in6 *sin6;
  74         struct sctp_paddrinfo *sp;
  75         mblk_t *meta, *mp;
  76         int i;
  77         conn_t  *connp = sctp->sctp_connp;
  78 
  79         sstat->sstat_state = sctp->sctp_state;
  80         sstat->sstat_rwnd = sctp->sctp_frwnd;
  81 
  82         sp = &sstat->sstat_primary;
  83         if (!sctp->sctp_primary) {
  84                 bzero(sp, sizeof (*sp));
  85                 goto noprim;
  86         }
  87         fp = sctp->sctp_primary;
  88 
  89         if (fp->sf_isv4) {
  90                 sin = (struct sockaddr_in *)&sp->spinfo_address;
  91                 sin->sin_family = AF_INET;
  92                 sin->sin_port = connp->conn_fport;
  93                 IN6_V4MAPPED_TO_INADDR(&fp->sf_faddr, &sin->sin_addr);
  94                 sp->spinfo_mtu = sctp->sctp_hdr_len;
  95         } else {
  96                 sin6 = (struct sockaddr_in6 *)&sp->spinfo_address;
  97                 sin6->sin6_family = AF_INET6;
  98                 sin6->sin6_port = connp->conn_fport;
  99                 sin6->sin6_addr = fp->sf_faddr;
 100                 sp->spinfo_mtu = sctp->sctp_hdr6_len;
 101         }
 102         sp->spinfo_state = fp->sf_state == SCTP_FADDRS_ALIVE ? SCTP_ACTIVE :
 103             SCTP_INACTIVE;
 104         sp->spinfo_cwnd = fp->sf_cwnd;
 105         sp->spinfo_srtt = fp->sf_srtt;
 106         sp->spinfo_rto = fp->sf_rto;
 107         sp->spinfo_mtu += fp->sf_pmss;
 108 
 109 noprim:
 110         sstat->sstat_unackdata = 0;
 111         sstat->sstat_penddata = 0;
 112         sstat->sstat_instrms = sctp->sctp_num_istr;
 113         sstat->sstat_outstrms = sctp->sctp_num_ostr;
 114         sstat->sstat_fragmentation_point = sctp->sctp_mss -
 115             sizeof (sctp_data_hdr_t);
 116 
 117         /* count unack'd */
 118         for (meta = sctp->sctp_xmit_head; meta; meta = meta->b_next) {
 119                 for (mp = meta->b_cont; mp; mp = mp->b_next) {
 120                         if (!SCTP_CHUNK_ISSENT(mp)) {
 121                                 break;
 122                         }
 123                         if (!SCTP_CHUNK_ISACKED(mp)) {
 124                                 sstat->sstat_unackdata++;
 125                         }
 126                 }
 127         }
 128 
 129         /*
 130          * Count penddata chunks. We can only count chunks in SCTP (not
 131          * data already delivered to socket layer).
 132          */
 133         if (sctp->sctp_instr != NULL) {
 134                 for (i = 0; i < sctp->sctp_num_istr; i++) {
 135                         for (meta = sctp->sctp_instr[i].istr_reass;
 136                             meta != NULL; meta = meta->b_next) {
 137                                 for (mp = meta->b_cont; mp; mp = mp->b_cont) {
 138                                         if (DB_TYPE(mp) != M_CTL) {
 139                                                 sstat->sstat_penddata++;
 140                                         }
 141                                 }
 142                         }
 143                 }
 144         }
 145         /* Un-Ordered Frag list */
 146         for (meta = sctp->sctp_uo_frags; meta != NULL; meta = meta->b_next)
 147                 sstat->sstat_penddata++;
 148 
 149         return (sizeof (*sstat));
 150 }
 151 
 152 /*
 153  * SCTP_GET_PEER_ADDR_INFO
 154  */
 155 static int
 156 sctp_get_paddrinfo(sctp_t *sctp, void *ptr, socklen_t *optlen)
 157 {
 158         struct sctp_paddrinfo   *infop = ptr;
 159         struct sockaddr_in      *sin4;
 160         struct sockaddr_in6     *sin6;
 161         in6_addr_t              faddr;
 162         sctp_faddr_t            *fp;
 163 
 164         switch (infop->spinfo_address.ss_family) {
 165         case AF_INET:
 166                 sin4 = (struct sockaddr_in *)&infop->spinfo_address;
 167                 IN6_INADDR_TO_V4MAPPED(&sin4->sin_addr, &faddr);
 168                 break;
 169         case AF_INET6:
 170                 sin6 = (struct sockaddr_in6 *)&infop->spinfo_address;
 171                 faddr = sin6->sin6_addr;
 172                 break;
 173         default:
 174                 return (EAFNOSUPPORT);
 175         }
 176 
 177         if ((fp = sctp_lookup_faddr(sctp, &faddr)) == NULL)
 178                 return (EINVAL);
 179 
 180         infop->spinfo_state = (fp->sf_state == SCTP_FADDRS_ALIVE) ?
 181             SCTP_ACTIVE : SCTP_INACTIVE;
 182         infop->spinfo_cwnd = fp->sf_cwnd;
 183         infop->spinfo_srtt = TICK_TO_MSEC(fp->sf_srtt);
 184         infop->spinfo_rto = TICK_TO_MSEC(fp->sf_rto);
 185         infop->spinfo_mtu = fp->sf_pmss;
 186 
 187         *optlen = sizeof (struct sctp_paddrinfo);
 188         return (0);
 189 }
 190 
 191 /*
 192  * SCTP_RTOINFO
 193  */
 194 static int
 195 sctp_get_rtoinfo(sctp_t *sctp, void *ptr)
 196 {
 197         struct sctp_rtoinfo *srto = ptr;
 198 
 199         srto->srto_initial = TICK_TO_MSEC(sctp->sctp_rto_initial);
 200         srto->srto_max = TICK_TO_MSEC(sctp->sctp_rto_max);
 201         srto->srto_min = TICK_TO_MSEC(sctp->sctp_rto_min);
 202 
 203         return (sizeof (*srto));
 204 }
 205 
 206 static int
 207 sctp_set_rtoinfo(sctp_t *sctp, const void *invalp)
 208 {
 209         const struct sctp_rtoinfo *srto;
 210         boolean_t ispriv;
 211         sctp_stack_t    *sctps = sctp->sctp_sctps;
 212         conn_t          *connp = sctp->sctp_connp;
 213         uint32_t        new_min, new_max;
 214 
 215         srto = invalp;
 216 
 217         ispriv = secpolicy_ip_config(connp->conn_cred, B_TRUE) == 0;
 218 
 219         /*
 220          * Bounds checking.  Priviledged user can set the RTO initial
 221          * outside the ndd boundary.
 222          */
 223         if (srto->srto_initial != 0 &&
 224             (!ispriv && (srto->srto_initial < sctps->sctps_rto_initialg_low ||
 225             srto->srto_initial > sctps->sctps_rto_initialg_high))) {
 226                 return (EINVAL);
 227         }
 228         if (srto->srto_max != 0 &&
 229             (!ispriv && (srto->srto_max < sctps->sctps_rto_maxg_low ||
 230             srto->srto_max > sctps->sctps_rto_maxg_high))) {
 231                 return (EINVAL);
 232         }
 233         if (srto->srto_min != 0 &&
 234             (!ispriv && (srto->srto_min < sctps->sctps_rto_ming_low ||
 235             srto->srto_min > sctps->sctps_rto_ming_high))) {
 236                 return (EINVAL);
 237         }
 238 
 239         new_min = (srto->srto_min != 0) ? srto->srto_min : sctp->sctp_rto_min;
 240         new_max = (srto->srto_max != 0) ? srto->srto_max : sctp->sctp_rto_max;
 241         if (new_max < new_min) {
 242                 return (EINVAL);
 243         }
 244 
 245         if (srto->srto_initial != 0) {
 246                 sctp->sctp_rto_initial = MSEC_TO_TICK(srto->srto_initial);
 247         }
 248 
 249         /* Ensure that sctp_rto_max will never be zero. */
 250         if (srto->srto_max != 0) {
 251                 sctp->sctp_rto_max = MAX(MSEC_TO_TICK(srto->srto_max), 1);
 252         }
 253         if (srto->srto_min != 0) {
 254                 sctp->sctp_rto_min = MSEC_TO_TICK(srto->srto_min);
 255         }
 256 
 257         return (0);
 258 }
 259 
 260 /*
 261  * SCTP_ASSOCINFO
 262  */
 263 static int
 264 sctp_get_assocparams(sctp_t *sctp, void *ptr)
 265 {
 266         struct sctp_assocparams *sap = ptr;
 267         sctp_faddr_t *fp;
 268         uint16_t i;
 269 
 270         sap->sasoc_asocmaxrxt = sctp->sctp_pa_max_rxt;
 271 
 272         /*
 273          * Count the number of peer addresses
 274          */
 275         for (i = 0, fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) {
 276                 i++;
 277         }
 278         sap->sasoc_number_peer_destinations = i;
 279         sap->sasoc_peer_rwnd = sctp->sctp_frwnd;
 280         sap->sasoc_local_rwnd = sctp->sctp_rwnd;
 281         sap->sasoc_cookie_life = TICK_TO_MSEC(sctp->sctp_cookie_lifetime);
 282 
 283         return (sizeof (*sap));
 284 }
 285 
 286 static int
 287 sctp_set_assocparams(sctp_t *sctp, const void *invalp)
 288 {
 289         const struct sctp_assocparams *sap = invalp;
 290         uint32_t sum = 0;
 291         sctp_faddr_t *fp;
 292         sctp_stack_t    *sctps = sctp->sctp_sctps;
 293 
 294         if (sap->sasoc_asocmaxrxt) {
 295                 if (sctp->sctp_faddrs) {
 296                         /*
 297                          * Bounds check: as per rfc2960, assoc max retr cannot
 298                          * exceed the sum of all individual path max retr's.
 299                          */
 300                         for (fp = sctp->sctp_faddrs; fp; fp = fp->sf_next) {
 301                                 sum += fp->sf_max_retr;
 302                         }
 303                         if (sap->sasoc_asocmaxrxt > sum) {
 304                                 return (EINVAL);
 305                         }
 306                 }
 307                 if (sap->sasoc_asocmaxrxt < sctps->sctps_pa_max_retr_low ||
 308                     sap->sasoc_asocmaxrxt > sctps->sctps_pa_max_retr_high) {
 309                         /*
 310                          * Out of bounds.
 311                          */
 312                         return (EINVAL);
 313                 }
 314         }
 315         if (sap->sasoc_cookie_life != 0 &&
 316             (sap->sasoc_cookie_life < sctps->sctps_cookie_life_low ||
 317             sap->sasoc_cookie_life > sctps->sctps_cookie_life_high)) {
 318                 return (EINVAL);
 319         }
 320 
 321         if (sap->sasoc_asocmaxrxt > 0) {
 322                 sctp->sctp_pa_max_rxt = sap->sasoc_asocmaxrxt;
 323         }
 324         if (sap->sasoc_cookie_life > 0) {
 325                 sctp->sctp_cookie_lifetime = MSEC_TO_TICK(
 326                     sap->sasoc_cookie_life);
 327         }
 328         return (0);
 329 }
 330 
 331 /*
 332  * SCTP_INITMSG
 333  */
 334 static int
 335 sctp_get_initmsg(sctp_t *sctp, void *ptr)
 336 {
 337         struct sctp_initmsg *si = ptr;
 338 
 339         si->sinit_num_ostreams = sctp->sctp_num_ostr;
 340         si->sinit_max_instreams = sctp->sctp_num_istr;
 341         si->sinit_max_attempts = sctp->sctp_max_init_rxt;
 342         si->sinit_max_init_timeo = TICK_TO_MSEC(sctp->sctp_rto_max_init);
 343 
 344         return (sizeof (*si));
 345 }
 346 
 347 static int
 348 sctp_set_initmsg(sctp_t *sctp, const void *invalp, uint_t inlen)
 349 {
 350         const struct sctp_initmsg *si = invalp;
 351         sctp_stack_t    *sctps = sctp->sctp_sctps;
 352         conn_t          *connp = sctp->sctp_connp;
 353 
 354         if (sctp->sctp_state > SCTPS_LISTEN) {
 355                 return (EINVAL);
 356         }
 357         if (inlen < sizeof (*si)) {
 358                 return (EINVAL);
 359         }
 360         if (si->sinit_num_ostreams != 0 &&
 361             (si->sinit_num_ostreams < sctps->sctps_initial_out_streams_low ||
 362             si->sinit_num_ostreams >
 363             sctps->sctps_initial_out_streams_high)) {
 364                 /*
 365                  * Out of bounds.
 366                  */
 367                 return (EINVAL);
 368         }
 369         if (si->sinit_max_instreams != 0 &&
 370             (si->sinit_max_instreams < sctps->sctps_max_in_streams_low ||
 371             si->sinit_max_instreams > sctps->sctps_max_in_streams_high)) {
 372                 return (EINVAL);
 373         }
 374         if (si->sinit_max_attempts != 0 &&
 375             (si->sinit_max_attempts < sctps->sctps_max_init_retr_low ||
 376             si->sinit_max_attempts > sctps->sctps_max_init_retr_high)) {
 377                 return (EINVAL);
 378         }
 379         if (si->sinit_max_init_timeo != 0 &&
 380             (secpolicy_ip_config(connp->conn_cred, B_TRUE) != 0 &&
 381             (si->sinit_max_init_timeo < sctps->sctps_rto_maxg_low ||
 382             si->sinit_max_init_timeo > sctps->sctps_rto_maxg_high))) {
 383                 return (EINVAL);
 384         }
 385         if (si->sinit_num_ostreams != 0)
 386                 sctp->sctp_num_ostr = si->sinit_num_ostreams;
 387 
 388         if (si->sinit_max_instreams != 0)
 389                 sctp->sctp_num_istr = si->sinit_max_instreams;
 390 
 391         if (si->sinit_max_attempts != 0)
 392                 sctp->sctp_max_init_rxt = si->sinit_max_attempts;
 393 
 394         if (si->sinit_max_init_timeo != 0) {
 395                 sctp->sctp_rto_max_init =
 396                     MSEC_TO_TICK(si->sinit_max_init_timeo);
 397         }
 398         return (0);
 399 }
 400 
 401 /*
 402  * SCTP_PEER_ADDR_PARAMS
 403  */
 404 static int
 405 sctp_find_peer_fp(sctp_t *sctp, const struct sockaddr_storage *ss,
 406     sctp_faddr_t **fpp)
 407 {
 408         struct sockaddr_in *sin;
 409         struct sockaddr_in6 *sin6;
 410         in6_addr_t addr;
 411 
 412         if (ss->ss_family == AF_INET) {
 413                 sin = (struct sockaddr_in *)ss;
 414                 IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &addr);
 415         } else if (ss->ss_family == AF_INET6) {
 416                 sin6 = (struct sockaddr_in6 *)ss;
 417                 addr = sin6->sin6_addr;
 418         } else if (ss->ss_family) {
 419                 return (EAFNOSUPPORT);
 420         }
 421 
 422         if (!ss->ss_family ||
 423             SCTP_IS_ADDR_UNSPEC(IN6_IS_ADDR_V4MAPPED(&addr), addr)) {
 424                 *fpp = NULL;
 425         } else {
 426                 *fpp = sctp_lookup_faddr(sctp, &addr);
 427                 if (*fpp == NULL) {
 428                         return (EINVAL);
 429                 }
 430         }
 431         return (0);
 432 }
 433 
 434 static int
 435 sctp_get_peer_addr_params(sctp_t *sctp, void *ptr)
 436 {
 437         struct sctp_paddrparams *spp = ptr;
 438         sctp_faddr_t *fp;
 439         int retval;
 440 
 441         retval = sctp_find_peer_fp(sctp, &spp->spp_address, &fp);
 442         if (retval) {
 443                 return (retval);
 444         }
 445         if (fp) {
 446                 spp->spp_hbinterval = TICK_TO_MSEC(fp->sf_hb_interval);
 447                 spp->spp_pathmaxrxt = fp->sf_max_retr;
 448         } else {
 449                 spp->spp_hbinterval = TICK_TO_MSEC(sctp->sctp_hb_interval);
 450                 spp->spp_pathmaxrxt = sctp->sctp_pp_max_rxt;
 451         }
 452         return (sizeof (*spp));
 453 }
 454 
 455 static int
 456 sctp_set_peer_addr_params(sctp_t *sctp, const void *invalp)
 457 {
 458         const struct sctp_paddrparams *spp = invalp;
 459         sctp_faddr_t *fp, *fp2;
 460         int retval;
 461         uint32_t sum = 0;
 462         int64_t now;
 463         sctp_stack_t    *sctps = sctp->sctp_sctps;
 464 
 465         retval = sctp_find_peer_fp(sctp, &spp->spp_address, &fp);
 466         if (retval != 0) {
 467                 return (retval);
 468         }
 469 
 470         if (spp->spp_hbinterval && spp->spp_hbinterval != UINT32_MAX &&
 471             (spp->spp_hbinterval < sctps->sctps_heartbeat_interval_low ||
 472             spp->spp_hbinterval > sctps->sctps_heartbeat_interval_high)) {
 473                 return (EINVAL);
 474         }
 475         if (spp->spp_pathmaxrxt &&
 476             (spp->spp_pathmaxrxt < sctps->sctps_pp_max_retr_low ||
 477             spp->spp_pathmaxrxt > sctps->sctps_pp_max_retr_high)) {
 478                 return (EINVAL);
 479         }
 480         if (spp->spp_pathmaxrxt && sctp->sctp_faddrs) {
 481                 for (fp2 = sctp->sctp_faddrs; fp2; fp2 = fp2->sf_next) {
 482                         if (!fp || fp2 == fp) {
 483                                 sum += spp->spp_pathmaxrxt;
 484                         } else {
 485                                 sum += fp2->sf_max_retr;
 486                         }
 487                 }
 488                 if (sctp->sctp_pa_max_rxt > sum) {
 489                         return (EINVAL);
 490                 }
 491         }
 492 
 493         now = ddi_get_lbolt64();
 494         if (fp != NULL) {
 495                 if (spp->spp_hbinterval == UINT32_MAX) {
 496                         /*
 497                          * Send heartbeat immediatelly, don't modify the
 498                          * current setting.
 499                          */
 500                         sctp_send_heartbeat(sctp, fp);
 501                 } else {
 502                         fp->sf_hb_interval = MSEC_TO_TICK(spp->spp_hbinterval);
 503                         fp->sf_hb_expiry = now + SET_HB_INTVL(fp);
 504                         /*
 505                          * Restart the heartbeat timer using the new intrvl.
 506                          * We need to call sctp_heartbeat_timer() to set
 507                          * the earliest heartbeat expiry time.
 508                          */
 509                         sctp_heartbeat_timer(sctp);
 510                 }
 511                 if (spp->spp_pathmaxrxt) {
 512                         fp->sf_max_retr = spp->spp_pathmaxrxt;
 513                 }
 514         } else {
 515                 for (fp2 = sctp->sctp_faddrs; fp2 != NULL; fp2 = fp2->sf_next) {
 516                         if (spp->spp_hbinterval == UINT32_MAX) {
 517                                 /*
 518                                  * Send heartbeat immediatelly, don't modify
 519                                  * the current setting.
 520                                  */
 521                                 sctp_send_heartbeat(sctp, fp2);
 522                         } else {
 523                                 fp2->sf_hb_interval = MSEC_TO_TICK(
 524                                     spp->spp_hbinterval);
 525                                 fp2->sf_hb_expiry = now + SET_HB_INTVL(fp2);
 526                         }
 527                         if (spp->spp_pathmaxrxt) {
 528                                 fp2->sf_max_retr = spp->spp_pathmaxrxt;
 529                         }
 530                 }
 531                 if (spp->spp_hbinterval != UINT32_MAX) {
 532                         sctp->sctp_hb_interval = MSEC_TO_TICK(
 533                             spp->spp_hbinterval);
 534                         /* Restart the heartbeat timer using the new intrvl. */
 535                         sctp_timer(sctp, sctp->sctp_heartbeat_mp,
 536                             sctp->sctp_hb_interval);
 537                 }
 538                 if (spp->spp_pathmaxrxt) {
 539                         sctp->sctp_pp_max_rxt = spp->spp_pathmaxrxt;
 540                 }
 541         }
 542         return (0);
 543 }
 544 
 545 /*
 546  * SCTP_DEFAULT_SEND_PARAM
 547  */
 548 static int
 549 sctp_get_def_send_params(sctp_t *sctp, void *ptr)
 550 {
 551         struct sctp_sndrcvinfo *sinfo = ptr;
 552 
 553         sinfo->sinfo_stream = sctp->sctp_def_stream;
 554         sinfo->sinfo_ssn = 0;
 555         sinfo->sinfo_flags = sctp->sctp_def_flags;
 556         sinfo->sinfo_ppid = sctp->sctp_def_ppid;
 557         sinfo->sinfo_context = sctp->sctp_def_context;
 558         sinfo->sinfo_timetolive = sctp->sctp_def_timetolive;
 559         sinfo->sinfo_tsn = 0;
 560         sinfo->sinfo_cumtsn = 0;
 561 
 562         return (sizeof (*sinfo));
 563 }
 564 
 565 static int
 566 sctp_set_def_send_params(sctp_t *sctp, const void *invalp)
 567 {
 568         const struct sctp_sndrcvinfo *sinfo = invalp;
 569 
 570         if (sinfo->sinfo_stream >= sctp->sctp_num_ostr) {
 571                 return (EINVAL);
 572         }
 573 
 574         sctp->sctp_def_stream = sinfo->sinfo_stream;
 575         sctp->sctp_def_flags = sinfo->sinfo_flags;
 576         sctp->sctp_def_ppid = sinfo->sinfo_ppid;
 577         sctp->sctp_def_context = sinfo->sinfo_context;
 578         sctp->sctp_def_timetolive = sinfo->sinfo_timetolive;
 579 
 580         return (0);
 581 }
 582 
 583 static int
 584 sctp_set_prim(sctp_t *sctp, const void *invalp)
 585 {
 586         const struct    sctp_setpeerprim *pp = invalp;
 587         int             retval;
 588         sctp_faddr_t    *fp;
 589 
 590         retval = sctp_find_peer_fp(sctp, &pp->sspp_addr, &fp);
 591         if (retval)
 592                 return (retval);
 593 
 594         if (fp == NULL)
 595                 return (EINVAL);
 596         if (fp == sctp->sctp_primary)
 597                 return (0);
 598         sctp->sctp_primary = fp;
 599 
 600         /* Only switch current if fp is alive */
 601         if (fp->sf_state != SCTP_FADDRS_ALIVE || fp == sctp->sctp_current) {
 602                 return (0);
 603         }
 604         sctp_set_faddr_current(sctp, fp);
 605 
 606         return (0);
 607 }
 608 
 609 /*
 610  * Table of all known options handled on a SCTP protocol stack.
 611  *
 612  * Note: This table contains options processed by both SCTP and IP levels
 613  *       and is the superset of options that can be performed on a SCTP and IP
 614  *       stack.
 615  */
 616 opdes_t sctp_opt_arr[] = {
 617 
 618 { SO_LINGER,    SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0,
 619         sizeof (struct linger), 0 },
 620 
 621 { SO_DEBUG,     SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 622 { SO_KEEPALIVE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 623 { SO_DONTROUTE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 624 { SO_USELOOPBACK, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
 625         },
 626 { SO_BROADCAST, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 627 { SO_REUSEADDR, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 628 { SO_OOBINLINE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 629 { SO_TYPE,      SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
 630 { SO_SNDBUF,    SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 631 { SO_RCVBUF,    SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 632 { SO_DGRAM_ERRIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
 633         },
 634 { SO_SND_COPYAVOID, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 635 { SO_ANON_MLP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
 636         0 },
 637 { SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
 638         0 },
 639 { SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, 0, sizeof (int),
 640         0 },
 641 { SO_EXCLBIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 642 
 643 { SO_DOMAIN,    SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
 644 
 645 { SO_PROTOTYPE, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
 646 
 647 { SCTP_ADAPTATION_LAYER, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
 648         sizeof (struct sctp_setadaptation), 0 },
 649 { SCTP_ADD_ADDR, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, OP_VARLEN,
 650         sizeof (int), 0 },
 651 { SCTP_ASSOCINFO, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
 652         sizeof (struct sctp_assocparams), 0 },
 653 { SCTP_AUTOCLOSE, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 654 { SCTP_DEFAULT_SEND_PARAM, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
 655         sizeof (struct sctp_sndrcvinfo), 0 },
 656 { SCTP_DISABLE_FRAGMENTS, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
 657         sizeof (int), 0 },
 658 { SCTP_EVENTS, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
 659         sizeof (struct sctp_event_subscribe), 0 },
 660 { SCTP_GET_LADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, OP_VARLEN,
 661         sizeof (int), 0 },
 662 { SCTP_GET_NLADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
 663 { SCTP_GET_NPADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
 664 { SCTP_GET_PADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, OP_VARLEN,
 665         sizeof (int), 0 },
 666 { SCTP_GET_PEER_ADDR_INFO, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0,
 667         sizeof (struct sctp_paddrinfo), 0 },
 668 { SCTP_INITMSG, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
 669         sizeof (struct sctp_initmsg), 0 },
 670 { SCTP_I_WANT_MAPPED_V4_ADDR, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
 671         sizeof (int), 0 },
 672 { SCTP_MAXSEG, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 673 { SCTP_NODELAY, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 674 { SCTP_PEER_ADDR_PARAMS, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
 675         sizeof (struct sctp_paddrparams), 0 },
 676 { SCTP_PRIMARY_ADDR, IPPROTO_SCTP, OA_W, OA_W, OP_NP, 0,
 677         sizeof (struct sctp_setpeerprim), 0 },
 678 { SCTP_PRSCTP, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 679 { SCTP_GET_ASSOC_STATS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0,
 680         sizeof (sctp_assoc_stats_t), 0 },
 681 { SCTP_REM_ADDR, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, OP_VARLEN,
 682         sizeof (int), 0 },
 683 { SCTP_RTOINFO, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
 684         sizeof (struct sctp_rtoinfo), 0 },
 685 { SCTP_SET_PEER_PRIMARY_ADDR, IPPROTO_SCTP, OA_W, OA_W, OP_NP, 0,
 686         sizeof (struct sctp_setprim), 0 },
 687 { SCTP_STATUS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0,
 688         sizeof (struct sctp_status), 0 },
 689 { SCTP_UC_SWAP, IPPROTO_SCTP, OA_W, OA_W, OP_NP, 0,
 690         sizeof (struct sctp_uc_swap), 0 },
 691 
 692 { IP_OPTIONS,   IPPROTO_IP, OA_RW, OA_RW, OP_NP,
 693         (OP_VARLEN|OP_NODEFAULT),
 694         40, -1 /* not initialized */ },
 695 { T_IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP,
 696         (OP_VARLEN|OP_NODEFAULT),
 697         40, -1 /* not initialized */ },
 698 
 699 { IP_TOS,       IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 700 { T_IP_TOS,     IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 701 { IP_TTL,       IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_DEF_FN,
 702         sizeof (int), -1 /* not initialized */ },
 703 
 704 { IP_SEC_OPT, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_NODEFAULT,
 705         sizeof (ipsec_req_t), -1 /* not initialized */ },
 706 
 707 { IP_BOUND_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0,
 708         sizeof (int),   0 /* no ifindex */ },
 709 
 710 { IP_UNSPEC_SRC, IPPROTO_IP, OA_R, OA_RW, OP_RAW, 0,
 711         sizeof (int), 0 },
 712 
 713 { IPV6_UNICAST_HOPS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, OP_DEF_FN,
 714         sizeof (int), -1 /* not initialized */ },
 715 
 716 { IPV6_BOUND_IF, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 717         sizeof (int),   0 /* no ifindex */ },
 718 
 719 { IP_DONTFRAG, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
 720 
 721 { IP_NEXTHOP, IPPROTO_IP, OA_R, OA_RW, OP_CONFIG, 0,
 722         sizeof (in_addr_t),     -1 /* not initialized  */ },
 723 
 724 { IPV6_UNSPEC_SRC, IPPROTO_IPV6, OA_R, OA_RW, OP_RAW, 0,
 725         sizeof (int), 0 },
 726 
 727 { IPV6_PKTINFO, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 728         (OP_NODEFAULT|OP_VARLEN),
 729         sizeof (struct in6_pktinfo), -1 /* not initialized */ },
 730 { IPV6_NEXTHOP, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 731         OP_NODEFAULT,
 732         sizeof (sin6_t), -1 /* not initialized */ },
 733 { IPV6_HOPOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 734         (OP_VARLEN|OP_NODEFAULT), 255*8,
 735         -1 /* not initialized */ },
 736 { IPV6_DSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 737         (OP_VARLEN|OP_NODEFAULT), 255*8,
 738         -1 /* not initialized */ },
 739 { IPV6_RTHDRDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 740         (OP_VARLEN|OP_NODEFAULT), 255*8,
 741         -1 /* not initialized */ },
 742 { IPV6_RTHDR, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 743         (OP_VARLEN|OP_NODEFAULT), 255*8,
 744         -1 /* not initialized */ },
 745 { IPV6_TCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 746         OP_NODEFAULT,
 747         sizeof (int), -1 /* not initialized */ },
 748 { IPV6_PATHMTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
 749         OP_NODEFAULT,
 750         sizeof (struct ip6_mtuinfo), -1 /* not initialized */ },
 751 { IPV6_DONTFRAG, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 752         sizeof (int), 0 },
 753 { IPV6_USE_MIN_MTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 754         sizeof (int), 0 },
 755 { IPV6_V6ONLY, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 756         sizeof (int), 0 },
 757 
 758 /* Enable receipt of ancillary data */
 759 { IPV6_RECVPKTINFO, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 760         sizeof (int), 0 },
 761 { IPV6_RECVHOPLIMIT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 762         sizeof (int), 0 },
 763 { IPV6_RECVTCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 764         sizeof (int), 0 },
 765 { IPV6_RECVHOPOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 766         sizeof (int), 0 },
 767 { _OLD_IPV6_RECVDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 768         sizeof (int), 0 },
 769 { IPV6_RECVDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 770         sizeof (int), 0 },
 771 { IPV6_RECVRTHDR, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 772         sizeof (int), 0 },
 773 { IPV6_RECVRTHDRDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 774         sizeof (int), 0 },
 775 { IPV6_RECVTCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 776         sizeof (int), 0 },
 777 
 778 { IPV6_SEC_OPT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, OP_NODEFAULT,
 779         sizeof (ipsec_req_t), -1 /* not initialized */ },
 780 { IPV6_SRC_PREFERENCES, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
 781         sizeof (uint32_t), IPV6_PREFER_SRC_DEFAULT },
 782 };
 783 
 784 uint_t sctp_opt_arr_size = A_CNT(sctp_opt_arr);
 785 
 786 /* Handy on off switch for socket option processing. */
 787 #define ONOFF(x)        ((x) == 0 ? 0 : 1)
 788 
 789 /*
 790  * SCTP routine to get the values of options.
 791  */
 792 int
 793 sctp_get_opt(sctp_t *sctp, int level, int name, void *ptr, socklen_t *optlen)
 794 {
 795         int     *i1 = (int *)ptr;
 796         int     retval = 0;
 797         int     buflen = *optlen;
 798         conn_t  *connp = sctp->sctp_connp;
 799         conn_opt_arg_t  coas;
 800 
 801         coas.coa_connp = connp;
 802         coas.coa_ixa = connp->conn_ixa;
 803         coas.coa_ipp = &connp->conn_xmit_ipp;
 804 
 805         /* In most cases, the return buffer is just an int */
 806         *optlen = sizeof (int32_t);
 807 
 808         RUN_SCTP(sctp);
 809 
 810         if (connp->conn_state_flags & CONN_CLOSING) {
 811                 WAKE_SCTP(sctp);
 812                 return (EINVAL);
 813         }
 814 
 815         /*
 816          * Check that the level and name are supported by SCTP, and that
 817          * the length and credentials are ok.
 818          */
 819         retval = proto_opt_check(level, name, buflen, NULL, sctp_opt_arr,
 820             sctp_opt_arr_size, B_FALSE, B_TRUE, connp->conn_cred);
 821         if (retval != 0) {
 822                 WAKE_SCTP(sctp);
 823                 if (retval < 0) {
 824                         retval = proto_tlitosyserr(-retval);
 825                 }
 826                 return (retval);
 827         }
 828 
 829         switch (level) {
 830         case IPPROTO_SCTP:
 831                 switch (name) {
 832                 case SCTP_RTOINFO:
 833                         *optlen = sctp_get_rtoinfo(sctp, ptr);
 834                         break;
 835                 case SCTP_ASSOCINFO:
 836                         *optlen = sctp_get_assocparams(sctp, ptr);
 837                         break;
 838                 case SCTP_INITMSG:
 839                         *optlen = sctp_get_initmsg(sctp, ptr);
 840                         break;
 841                 case SCTP_NODELAY:
 842                         *i1 = sctp->sctp_ndelay;
 843                         break;
 844                 case SCTP_AUTOCLOSE:
 845                         *i1 = TICK_TO_SEC(sctp->sctp_autoclose);
 846                         break;
 847                 case SCTP_ADAPTATION_LAYER:
 848                         ((struct sctp_setadaptation *)ptr)->ssb_adaptation_ind =
 849                             sctp->sctp_tx_adaptation_code;
 850                         break;
 851                 case SCTP_PEER_ADDR_PARAMS:
 852                         *optlen = sctp_get_peer_addr_params(sctp, ptr);
 853                         break;
 854                 case SCTP_DEFAULT_SEND_PARAM:
 855                         *optlen = sctp_get_def_send_params(sctp, ptr);
 856                         break;
 857                 case SCTP_EVENTS: {
 858                         struct sctp_event_subscribe *ev;
 859 
 860                         ev = (struct sctp_event_subscribe *)ptr;
 861                         ev->sctp_data_io_event =
 862                             ONOFF(sctp->sctp_recvsndrcvinfo);
 863                         ev->sctp_association_event =
 864                             ONOFF(sctp->sctp_recvassocevnt);
 865                         ev->sctp_address_event =
 866                             ONOFF(sctp->sctp_recvpathevnt);
 867                         ev->sctp_send_failure_event =
 868                             ONOFF(sctp->sctp_recvsendfailevnt);
 869                         ev->sctp_peer_error_event =
 870                             ONOFF(sctp->sctp_recvpeererr);
 871                         ev->sctp_shutdown_event =
 872                             ONOFF(sctp->sctp_recvshutdownevnt);
 873                         ev->sctp_partial_delivery_event =
 874                             ONOFF(sctp->sctp_recvpdevnt);
 875                         ev->sctp_adaptation_layer_event =
 876                             ONOFF(sctp->sctp_recvalevnt);
 877                         *optlen = sizeof (struct sctp_event_subscribe);
 878                         break;
 879                 }
 880                 case SCTP_STATUS:
 881                         *optlen = sctp_get_status(sctp, ptr);
 882                         break;
 883                 case SCTP_GET_PEER_ADDR_INFO:
 884                         retval = sctp_get_paddrinfo(sctp, ptr, optlen);
 885                         break;
 886                 case SCTP_GET_NLADDRS:
 887                         *(int32_t *)ptr = sctp->sctp_nsaddrs;
 888                         break;
 889                 case SCTP_GET_LADDRS: {
 890                         int addr_cnt;
 891                         int addr_size;
 892 
 893                         if (connp->conn_family == AF_INET)
 894                                 addr_size = sizeof (struct sockaddr_in);
 895                         else
 896                                 addr_size = sizeof (struct sockaddr_in6);
 897                         addr_cnt = buflen / addr_size;
 898                         retval = sctp_getmyaddrs(sctp, ptr, &addr_cnt);
 899                         if (retval == 0)
 900                                 *optlen = addr_cnt * addr_size;
 901                         break;
 902                 }
 903                 case SCTP_GET_NPADDRS: {
 904                         int i;
 905                         sctp_faddr_t *fp;
 906 
 907                         for (i = 0, fp = sctp->sctp_faddrs; fp != NULL;
 908                             i++, fp = fp->sf_next)
 909                                 ;
 910                         *(int32_t *)ptr = i;
 911                         break;
 912                 }
 913                 case SCTP_GET_PADDRS: {
 914                         int addr_cnt;
 915                         int addr_size;
 916 
 917                         if (connp->conn_family == AF_INET)
 918                                 addr_size = sizeof (struct sockaddr_in);
 919                         else
 920                                 addr_size = sizeof (struct sockaddr_in6);
 921                         addr_cnt = buflen / addr_size;
 922                         retval = sctp_getpeeraddrs(sctp, ptr, &addr_cnt);
 923                         if (retval == 0)
 924                                 *optlen = addr_cnt * addr_size;
 925                         break;
 926                 }
 927                 case SCTP_PRSCTP:
 928                         *i1 = sctp->sctp_prsctp_aware ? 1 : 0;
 929                         break;
 930 
 931                 case SCTP_GET_ASSOC_STATS: {
 932                         sctp_assoc_stats_t *sas;
 933 
 934                         sas = (sctp_assoc_stats_t *)ptr;
 935 
 936                         /*
 937                          * Copy the current stats to the stats struct.
 938                          * For stats which can be reset by snmp users
 939                          * add the cumulative and current stats for
 940                          * the raw totals to output to the user.
 941                          */
 942                         sas->sas_gapcnt = sctp->sctp_gapcnt;
 943                         sas->sas_outseqtsns = sctp->sctp_outseqtsns;
 944                         sas->sas_osacks = sctp->sctp_osacks;
 945                         sas->sas_isacks = sctp->sctp_isacks;
 946                         sas->sas_idupchunks = sctp->sctp_idupchunks;
 947                         sas->sas_rtxchunks =  sctp->sctp_rxtchunks +
 948                             sctp->sctp_cum_rxtchunks;
 949                         sas->sas_octrlchunks = sctp->sctp_obchunks +
 950                             sctp->sctp_cum_obchunks;
 951                         sas->sas_ictrlchunks = sctp->sctp_ibchunks +
 952                             sctp->sctp_cum_ibchunks;
 953                         sas->sas_oodchunks = sctp->sctp_odchunks +
 954                             sctp->sctp_cum_odchunks;
 955                         sas->sas_iodchunks = sctp->sctp_idchunks +
 956                             sctp->sctp_cum_idchunks;
 957                         sas->sas_ouodchunks = sctp->sctp_oudchunks +
 958                             sctp->sctp_cum_oudchunks;
 959                         sas->sas_iuodchunks = sctp->sctp_iudchunks +
 960                             sctp->sctp_cum_iudchunks;
 961 
 962                         /*
 963                          * Copy out the maximum observed RTO since the
 964                          * time this data was last requested
 965                          */
 966                         if (sctp->sctp_maxrto == 0) {
 967                                 /* unchanged during obervation period */
 968                                 sas->sas_maxrto = sctp->sctp_prev_maxrto;
 969                         } else {
 970                                 /* record new period maximum */
 971                                 sas->sas_maxrto = sctp->sctp_maxrto;
 972                         }
 973                         /* Record the value sent to the user this period */
 974                         sctp->sctp_prev_maxrto = sas->sas_maxrto;
 975 
 976                         /* Mark beginning of a new observation period */
 977                         sctp->sctp_maxrto = 0;
 978 
 979                         *optlen = sizeof (sctp_assoc_stats_t);
 980                         break;
 981                 }
 982                 case SCTP_I_WANT_MAPPED_V4_ADDR:
 983                 case SCTP_MAXSEG:
 984                 case SCTP_DISABLE_FRAGMENTS:
 985                 default:
 986                         /* Not yet supported. */
 987                         retval = ENOPROTOOPT;
 988                         break;
 989                 }
 990                 WAKE_SCTP(sctp);
 991                 return (retval);
 992         case IPPROTO_IP:
 993                 if (connp->conn_family != AF_INET) {
 994                         retval = EINVAL;
 995                         break;
 996                 }
 997                 switch (name) {
 998                 case IP_OPTIONS:
 999                 case T_IP_OPTIONS: {
1000                         /*
1001                          * This is compatible with BSD in that in only return
1002                          * the reverse source route with the final destination
1003                          * as the last entry. The first 4 bytes of the option
1004                          * will contain the final destination. Allocate a
1005                          * buffer large enough to hold all the options, we
1006                          * add IP_ADDR_LEN to SCTP_MAX_IP_OPTIONS_LENGTH since
1007                          * ip_opt_get_user() adds the final destination
1008                          * at the start.
1009                          */
1010                         int     opt_len;
1011                         uchar_t obuf[SCTP_MAX_IP_OPTIONS_LENGTH + IP_ADDR_LEN];
1012 
1013                         opt_len = ip_opt_get_user(connp, obuf);
1014                         ASSERT(opt_len <= sizeof (obuf));
1015 
1016                         if (buflen < opt_len) {
1017                                 /* Silently truncate */
1018                                 opt_len = buflen;
1019                         }
1020                         *optlen = opt_len;
1021                         bcopy(obuf, ptr, opt_len);
1022                         WAKE_SCTP(sctp);
1023                         return (0);
1024                 }
1025                 default:
1026                         break;
1027                 }
1028                 break;
1029         }
1030         mutex_enter(&connp->conn_lock);
1031         retval = conn_opt_get(&coas, level, name, ptr);
1032         mutex_exit(&connp->conn_lock);
1033         WAKE_SCTP(sctp);
1034         if (retval == -1)
1035                 return (EINVAL);
1036         *optlen = retval;
1037         return (0);
1038 }
1039 
1040 int
1041 sctp_set_opt(sctp_t *sctp, int level, int name, const void *invalp,
1042     socklen_t inlen)
1043 {
1044         int             *i1 = (int *)invalp;
1045         boolean_t       onoff;
1046         int             retval = 0, addrcnt;
1047         conn_t          *connp = sctp->sctp_connp;
1048         sctp_stack_t    *sctps = sctp->sctp_sctps;
1049         conn_opt_arg_t  coas;
1050 
1051         coas.coa_connp = connp;
1052         coas.coa_ixa = connp->conn_ixa;
1053         coas.coa_ipp = &connp->conn_xmit_ipp;
1054         coas.coa_ancillary = B_FALSE;
1055         coas.coa_changed = 0;
1056 
1057         /* In all cases, the size of the option must be bigger than int */
1058         if (inlen >= sizeof (int32_t)) {
1059                 onoff = ONOFF(*i1);
1060         }
1061         retval = 0;
1062 
1063         RUN_SCTP(sctp);
1064 
1065         if (connp->conn_state_flags & CONN_CLOSING) {
1066                 WAKE_SCTP(sctp);
1067                 return (EINVAL);
1068         }
1069 
1070         /*
1071          * Check that the level and name are supported by SCTP, and that
1072          * the length an credentials are ok.
1073          */
1074         retval = proto_opt_check(level, name, inlen, NULL, sctp_opt_arr,
1075             sctp_opt_arr_size, B_TRUE, B_FALSE, connp->conn_cred);
1076         if (retval != 0) {
1077                 if (retval < 0) {
1078                         retval = proto_tlitosyserr(-retval);
1079                 }
1080                 goto done;
1081         }
1082 
1083         /* Note: both SCTP and TCP interpret l_linger as being in seconds */
1084         switch (level) {
1085         case SOL_SOCKET:
1086                 switch (name) {
1087                 case SO_SNDBUF:
1088                         if (*i1 > sctps->sctps_max_buf) {
1089                                 retval = ENOBUFS;
1090                                 goto done;
1091                         }
1092                         if (*i1 < 0) {
1093                                 retval = EINVAL;
1094                                 goto done;
1095                         }
1096                         connp->conn_sndbuf = *i1;
1097                         if (sctps->sctps_snd_lowat_fraction != 0) {
1098                                 connp->conn_sndlowat = connp->conn_sndbuf /
1099                                     sctps->sctps_snd_lowat_fraction;
1100                         }
1101                         goto done;
1102                 case SO_RCVBUF:
1103                         if (*i1 > sctps->sctps_max_buf) {
1104                                 retval = ENOBUFS;
1105                                 goto done;
1106                         }
1107                         /* Silently ignore zero */
1108                         if (*i1 != 0) {
1109                                 struct sock_proto_props sopp;
1110 
1111                                 /*
1112                                  * Insist on a receive window that is at least
1113                                  * sctp_recv_hiwat_minmss * MSS (default 4*MSS)
1114                                  * to avoid funny interactions of Nagle
1115                                  * algorithm, SWS avoidance and delayed
1116                                  * acknowledgement.
1117                                  */
1118                                 *i1 = MAX(*i1,
1119                                     sctps->sctps_recv_hiwat_minmss *
1120                                     sctp->sctp_mss);
1121                                 /*
1122                                  * Note that sctp_rwnd is modified by the
1123                                  * protocol and here we just whack it.
1124                                  */
1125                                 connp->conn_rcvbuf = sctp->sctp_rwnd = *i1;
1126                                 sctp->sctp_arwnd = sctp->sctp_rwnd;
1127                                 sctp->sctp_pd_point = sctp->sctp_rwnd;
1128 
1129                                 sopp.sopp_flags = SOCKOPT_RCVHIWAT;
1130                                 sopp.sopp_rxhiwat = connp->conn_rcvbuf;
1131                                 sctp->sctp_ulp_prop(sctp->sctp_ulpd, &sopp);
1132 
1133                         }
1134                         /*
1135                          * XXX should we return the rwnd here
1136                          * and sctp_opt_get ?
1137                          */
1138                         goto done;
1139                 case SO_ALLZONES:
1140                         if (sctp->sctp_state >= SCTPS_BOUND) {
1141                                 retval = EINVAL;
1142                                 goto done;
1143                         }
1144                         break;
1145                 case SO_MAC_EXEMPT:
1146                         if (sctp->sctp_state >= SCTPS_BOUND) {
1147                                 retval = EINVAL;
1148                                 goto done;
1149                         }
1150                         break;
1151                 }
1152                 break;
1153 
1154         case IPPROTO_SCTP:
1155                 switch (name) {
1156                 case SCTP_RTOINFO:
1157                         retval = sctp_set_rtoinfo(sctp, invalp);
1158                         break;
1159                 case SCTP_ASSOCINFO:
1160                         retval = sctp_set_assocparams(sctp, invalp);
1161                         break;
1162                 case SCTP_INITMSG:
1163                         retval = sctp_set_initmsg(sctp, invalp, inlen);
1164                         break;
1165                 case SCTP_NODELAY:
1166                         sctp->sctp_ndelay = ONOFF(*i1);
1167                         break;
1168                 case SCTP_AUTOCLOSE:
1169                         if (SEC_TO_TICK(*i1) < 0) {
1170                                 retval = EINVAL;
1171                                 break;
1172                         }
1173                         /* Convert the number of seconds to ticks. */
1174                         sctp->sctp_autoclose = SEC_TO_TICK(*i1);
1175                         sctp_heartbeat_timer(sctp);
1176                         break;
1177                 case SCTP_SET_PEER_PRIMARY_ADDR:
1178                         retval = sctp_set_peerprim(sctp, invalp);
1179                         break;
1180                 case SCTP_PRIMARY_ADDR:
1181                         retval = sctp_set_prim(sctp, invalp);
1182                         break;
1183                 case SCTP_ADAPTATION_LAYER: {
1184                         struct sctp_setadaptation *ssb;
1185 
1186                         ssb = (struct sctp_setadaptation *)invalp;
1187                         sctp->sctp_send_adaptation = 1;
1188                         sctp->sctp_tx_adaptation_code = ssb->ssb_adaptation_ind;
1189                         break;
1190                 }
1191                 case SCTP_PEER_ADDR_PARAMS:
1192                         retval = sctp_set_peer_addr_params(sctp, invalp);
1193                         break;
1194                 case SCTP_DEFAULT_SEND_PARAM:
1195                         retval = sctp_set_def_send_params(sctp, invalp);
1196                         break;
1197                 case SCTP_EVENTS: {
1198                         struct sctp_event_subscribe *ev;
1199 
1200                         ev = (struct sctp_event_subscribe *)invalp;
1201                         sctp->sctp_recvsndrcvinfo =
1202                             ONOFF(ev->sctp_data_io_event);
1203                         sctp->sctp_recvassocevnt =
1204                             ONOFF(ev->sctp_association_event);
1205                         sctp->sctp_recvpathevnt =
1206                             ONOFF(ev->sctp_address_event);
1207                         sctp->sctp_recvsendfailevnt =
1208                             ONOFF(ev->sctp_send_failure_event);
1209                         sctp->sctp_recvpeererr =
1210                             ONOFF(ev->sctp_peer_error_event);
1211                         sctp->sctp_recvshutdownevnt =
1212                             ONOFF(ev->sctp_shutdown_event);
1213                         sctp->sctp_recvpdevnt =
1214                             ONOFF(ev->sctp_partial_delivery_event);
1215                         sctp->sctp_recvalevnt =
1216                             ONOFF(ev->sctp_adaptation_layer_event);
1217                         break;
1218                 }
1219                 case SCTP_ADD_ADDR:
1220                 case SCTP_REM_ADDR:
1221                         /*
1222                          * The sctp_t has to be bound first before
1223                          * the address list can be changed.
1224                          */
1225                         if (sctp->sctp_state < SCTPS_BOUND) {
1226                                 retval = EINVAL;
1227                                 break;
1228                         }
1229                         if (connp->conn_family == AF_INET) {
1230                                 addrcnt = inlen / sizeof (struct sockaddr_in);
1231                         } else {
1232                                 ASSERT(connp->conn_family == AF_INET6);
1233                                 addrcnt = inlen / sizeof (struct sockaddr_in6);
1234                         }
1235                         if (name == SCTP_ADD_ADDR) {
1236                                 retval = sctp_bind_add(sctp, invalp, addrcnt,
1237                                     B_TRUE, connp->conn_lport);
1238                         } else {
1239                                 retval = sctp_bind_del(sctp, invalp, addrcnt,
1240                                     B_TRUE);
1241                         }
1242                         break;
1243                 case SCTP_UC_SWAP: {
1244                         struct sctp_uc_swap *us;
1245 
1246                         /*
1247                          * Change handle & upcalls.
1248                          */
1249                         us = (struct sctp_uc_swap *)invalp;
1250                         sctp->sctp_ulpd = us->sus_handle;
1251                         sctp->sctp_upcalls = us->sus_upcalls;
1252                         break;
1253                 }
1254                 case SCTP_PRSCTP:
1255                         sctp->sctp_prsctp_aware = onoff;
1256                         break;
1257                 case SCTP_I_WANT_MAPPED_V4_ADDR:
1258                 case SCTP_MAXSEG:
1259                 case SCTP_DISABLE_FRAGMENTS:
1260                         /* Not yet supported. */
1261                         retval = ENOPROTOOPT;
1262                         break;
1263                 }
1264                 goto done;
1265 
1266         case IPPROTO_IP:
1267                 if (connp->conn_family != AF_INET) {
1268                         retval = ENOPROTOOPT;
1269                         goto done;
1270                 }
1271                 switch (name) {
1272                 case IP_SEC_OPT:
1273                         /*
1274                          * We should not allow policy setting after
1275                          * we start listening for connections.
1276                          */
1277                         if (sctp->sctp_state >= SCTPS_LISTEN) {
1278                                 retval = EINVAL;
1279                                 goto done;
1280                         }
1281                         break;
1282                 }
1283                 break;
1284         case IPPROTO_IPV6:
1285                 if (connp->conn_family != AF_INET6) {
1286                         retval = EINVAL;
1287                         goto done;
1288                 }
1289 
1290                 switch (name) {
1291                 case IPV6_RECVPKTINFO:
1292                         /* Send it with the next msg */
1293                         sctp->sctp_recvifindex = 0;
1294                         break;
1295                 case IPV6_RECVTCLASS:
1296                         /* Force it to be sent up with the next msg */
1297                         sctp->sctp_recvtclass = 0xffffffffU;
1298                         break;
1299                 case IPV6_RECVHOPLIMIT:
1300                         /* Force it to be sent up with the next msg */
1301                         sctp->sctp_recvhops = 0xffffffffU;
1302                         break;
1303                 case IPV6_SEC_OPT:
1304                         /*
1305                          * We should not allow policy setting after
1306                          * we start listening for connections.
1307                          */
1308                         if (sctp->sctp_state >= SCTPS_LISTEN) {
1309                                 retval = EINVAL;
1310                                 goto done;
1311                         }
1312                         break;
1313                 case IPV6_V6ONLY:
1314                         /*
1315                          * After the bound state, setting the v6only option
1316                          * is too late.
1317                          */
1318                         if (sctp->sctp_state >= SCTPS_BOUND) {
1319                                 retval = EINVAL;
1320                                 goto done;
1321                         }
1322                         break;
1323                 }
1324                 break;
1325         }
1326 
1327         retval = conn_opt_set(&coas, level, name, inlen, (uchar_t *)invalp,
1328             B_FALSE, connp->conn_cred);
1329         if (retval != 0)
1330                 goto done;
1331 
1332         if (coas.coa_changed & COA_ROUTE_CHANGED) {
1333                 sctp_faddr_t *fp;
1334                 /*
1335                  * We recache the information which might pick a different
1336                  * source and redo IPsec as a result.
1337                  */
1338                 for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next)
1339                         sctp_get_dest(sctp, fp);
1340         }
1341         if (coas.coa_changed & COA_HEADER_CHANGED) {
1342                 retval = sctp_build_hdrs(sctp, KM_NOSLEEP);
1343                 if (retval != 0)
1344                         goto done;
1345         }
1346         if (coas.coa_changed & COA_WROFF_CHANGED) {
1347                 connp->conn_wroff = connp->conn_ht_iphc_allocated +
1348                     sctps->sctps_wroff_xtra;
1349                 if (sctp->sctp_current != NULL) {
1350                         /*
1351                          * Could be setting options before setting up
1352                          * connection.
1353                          */
1354                         sctp_set_ulp_prop(sctp);
1355                 }
1356         }
1357 done:
1358         WAKE_SCTP(sctp);
1359         return (retval);
1360 }
1361 
1362 /*
1363  * SCTP exported kernel interface for geting the first source address of
1364  * a sctp_t.  The parameter addr is assumed to have enough space to hold
1365  * one socket address.
1366  */
1367 int
1368 sctp_getsockname(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen)
1369 {
1370         int     err = 0;
1371         int     addrcnt = 1;
1372         sin_t   *sin4;
1373         sin6_t  *sin6;
1374         conn_t  *connp = sctp->sctp_connp;
1375 
1376         ASSERT(sctp != NULL);
1377 
1378         RUN_SCTP(sctp);
1379         addr->sa_family = connp->conn_family;
1380         switch (connp->conn_family) {
1381         case AF_INET:
1382                 sin4 = (sin_t *)addr;
1383                 if ((sctp->sctp_state <= SCTPS_LISTEN) &&
1384                     sctp->sctp_bound_to_all) {
1385                         sin4->sin_addr.s_addr = INADDR_ANY;
1386                         sin4->sin_port = connp->conn_lport;
1387                 } else {
1388                         err = sctp_getmyaddrs(sctp, sin4, &addrcnt);
1389                         if (err != 0) {
1390                                 *addrlen = 0;
1391                                 break;
1392                         }
1393                 }
1394                 *addrlen = sizeof (struct sockaddr_in);
1395                 break;
1396         case AF_INET6:
1397                 sin6 = (sin6_t *)addr;
1398                 if ((sctp->sctp_state <= SCTPS_LISTEN) &&
1399                     sctp->sctp_bound_to_all) {
1400                         bzero(&sin6->sin6_addr, sizeof (sin6->sin6_addr));
1401                         sin6->sin6_port = connp->conn_lport;
1402                 } else {
1403                         err = sctp_getmyaddrs(sctp, sin6, &addrcnt);
1404                         if (err != 0) {
1405                                 *addrlen = 0;
1406                                 break;
1407                         }
1408                 }
1409                 *addrlen = sizeof (struct sockaddr_in6);
1410                 /* Note that flowinfo is only returned for getpeername */
1411                 break;
1412         }
1413         WAKE_SCTP(sctp);
1414         return (err);
1415 }
1416 
1417 /*
1418  * SCTP exported kernel interface for geting the primary peer address of
1419  * a sctp_t.  The parameter addr is assumed to have enough space to hold
1420  * one socket address.
1421  */
1422 int
1423 sctp_getpeername(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen)
1424 {
1425         int     err = 0;
1426         int     addrcnt = 1;
1427         sin6_t  *sin6;
1428         conn_t  *connp = sctp->sctp_connp;
1429 
1430         ASSERT(sctp != NULL);
1431 
1432         RUN_SCTP(sctp);
1433         addr->sa_family = connp->conn_family;
1434         switch (connp->conn_family) {
1435         case AF_INET:
1436                 err = sctp_getpeeraddrs(sctp, addr, &addrcnt);
1437                 if (err != 0) {
1438                         *addrlen = 0;
1439                         break;
1440                 }
1441                 *addrlen = sizeof (struct sockaddr_in);
1442                 break;
1443         case AF_INET6:
1444                 sin6 = (sin6_t *)addr;
1445                 err = sctp_getpeeraddrs(sctp, sin6, &addrcnt);
1446                 if (err != 0) {
1447                         *addrlen = 0;
1448                         break;
1449                 }
1450                 *addrlen = sizeof (struct sockaddr_in6);
1451                 break;
1452         }
1453         WAKE_SCTP(sctp);
1454         return (err);
1455 }
1456 
1457 /*
1458  * Return a list of IP addresses of the peer endpoint of this sctp_t.
1459  * The parameter paddrs is supposed to be either (struct sockaddr_in *) or
1460  * (struct sockaddr_in6 *) depending on the address family of the sctp_t.
1461  */
1462 int
1463 sctp_getpeeraddrs(sctp_t *sctp, void *paddrs, int *addrcnt)
1464 {
1465         int                     family;
1466         struct sockaddr_in      *sin4;
1467         struct sockaddr_in6     *sin6;
1468         int                     max;
1469         int                     cnt;
1470         sctp_faddr_t            *fp = sctp->sctp_faddrs;
1471         in6_addr_t              addr;
1472         conn_t                  *connp = sctp->sctp_connp;
1473 
1474         ASSERT(sctp != NULL);
1475 
1476         if (sctp->sctp_faddrs == NULL)
1477                 return (ENOTCONN);
1478 
1479         family = connp->conn_family;
1480         max = *addrcnt;
1481 
1482         /* If we want only one, give the primary */
1483         if (max == 1) {
1484                 addr = sctp->sctp_primary->sf_faddr;
1485                 switch (family) {
1486                 case AF_INET:
1487                         sin4 = paddrs;
1488                         IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr);
1489                         sin4->sin_port = connp->conn_fport;
1490                         sin4->sin_family = AF_INET;
1491                         break;
1492 
1493                 case AF_INET6:
1494                         sin6 = paddrs;
1495                         sin6->sin6_addr = addr;
1496                         sin6->sin6_port = connp->conn_fport;
1497                         sin6->sin6_family = AF_INET6;
1498                         sin6->sin6_flowinfo = connp->conn_flowinfo;
1499                         if (IN6_IS_ADDR_LINKSCOPE(&addr) &&
1500                             (sctp->sctp_primary->sf_ixa->ixa_flags &
1501                             IXAF_SCOPEID_SET)) {
1502                                 sin6->sin6_scope_id =
1503                                     sctp->sctp_primary->sf_ixa->ixa_scopeid;
1504                         } else {
1505                                 sin6->sin6_scope_id = 0;
1506                         }
1507                         sin6->__sin6_src_id = 0;
1508                         break;
1509                 }
1510                 return (0);
1511         }
1512 
1513         for (cnt = 0; cnt < max && fp != NULL; cnt++, fp = fp->sf_next) {
1514                 addr = fp->sf_faddr;
1515                 switch (family) {
1516                 case AF_INET:
1517                         ASSERT(IN6_IS_ADDR_V4MAPPED(&addr));
1518                         sin4 = (struct sockaddr_in *)paddrs + cnt;
1519                         IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr);
1520                         sin4->sin_port = connp->conn_fport;
1521                         sin4->sin_family = AF_INET;
1522                         break;
1523                 case AF_INET6:
1524                         sin6 = (struct sockaddr_in6 *)paddrs + cnt;
1525                         sin6->sin6_addr = addr;
1526                         sin6->sin6_port = connp->conn_fport;
1527                         sin6->sin6_family = AF_INET6;
1528                         sin6->sin6_flowinfo = connp->conn_flowinfo;
1529                         if (IN6_IS_ADDR_LINKSCOPE(&addr) &&
1530                             (fp->sf_ixa->ixa_flags & IXAF_SCOPEID_SET))
1531                                 sin6->sin6_scope_id = fp->sf_ixa->ixa_scopeid;
1532                         else
1533                                 sin6->sin6_scope_id = 0;
1534                         sin6->__sin6_src_id = 0;
1535                         break;
1536                 }
1537         }
1538         *addrcnt = cnt;
1539         return (0);
1540 }