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