Coverage Report

Created: 2025-08-28 06:37

/src/usrsctp/usrsctplib/netinet/sctp_usrreq.c
Line
Count
Source (jump to first uncovered line)
1
/*-
2
 * SPDX-License-Identifier: BSD-3-Clause
3
 *
4
 * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
5
 * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
6
 * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions are met:
10
 *
11
 * a) Redistributions of source code must retain the above copyright notice,
12
 *    this list of conditions and the following disclaimer.
13
 *
14
 * b) Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in
16
 *    the documentation and/or other materials provided with the distribution.
17
 *
18
 * c) Neither the name of Cisco Systems, Inc. nor the names of its
19
 *    contributors may be used to endorse or promote products derived
20
 *    from this software without specific prior written permission.
21
 *
22
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32
 * THE POSSIBILITY OF SUCH DAMAGE.
33
 */
34
35
#include <netinet/sctp_os.h>
36
#if defined(__FreeBSD__) && !defined(__Userspace__)
37
#include <sys/proc.h>
38
#endif
39
#include <netinet/sctp_pcb.h>
40
#include <netinet/sctp_header.h>
41
#include <netinet/sctp_var.h>
42
#ifdef INET6
43
#include <netinet6/sctp6_var.h>
44
#endif
45
#include <netinet/sctp_sysctl.h>
46
#include <netinet/sctp_output.h>
47
#include <netinet/sctp_uio.h>
48
#include <netinet/sctp_asconf.h>
49
#include <netinet/sctputil.h>
50
#include <netinet/sctp_indata.h>
51
#include <netinet/sctp_timer.h>
52
#include <netinet/sctp_auth.h>
53
#include <netinet/sctp_bsd_addr.h>
54
#if defined(__Userspace__)
55
#include <netinet/sctp_callout.h>
56
#else
57
#include <netinet/udp.h>
58
#endif
59
#if defined(__FreeBSD__) && !defined(__Userspace__)
60
#include <sys/eventhandler.h>
61
#endif
62
#if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
63
#include <netinet/sctp_peeloff.h>
64
#endif        /* HAVE_SCTP_PEELOFF_SOCKOPT */
65
66
extern const struct sctp_cc_functions sctp_cc_functions[];
67
extern const struct sctp_ss_functions sctp_ss_functions[];
68
69
#if defined(__Userspace__)
70
void
71
sctp_init(uint16_t port,
72
          int (*conn_output)(void *addr, void *buffer, size_t length, uint8_t tos, uint8_t set_df),
73
          void (*debug_printf)(const char *format, ...), int start_threads)
74
#elif defined(__APPLE__) && (!defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) &&!defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION))
75
void
76
sctp_init(struct protosw *pp SCTP_UNUSED, struct domain *dp SCTP_UNUSED)
77
#elif defined(__FreeBSD__)
78
static void
79
sctp_init(void *arg SCTP_UNUSED)
80
#else
81
void
82
sctp_init(void)
83
#endif
84
3
{
85
#if !defined(__Userspace__)
86
  u_long sb_max_adj;
87
88
#else
89
3
  init_random();
90
3
#endif
91
  /* Initialize and modify the sysctled variables */
92
3
  sctp_init_sysctls();
93
3
#if defined(__Userspace__)
94
3
  SCTP_BASE_SYSCTL(sctp_udp_tunneling_port) = port;
95
#else
96
#if defined(__APPLE__) && !defined(__Userspace__)
97
  sb_max_adj = (u_long)((u_quad_t) (sb_max) * MCLBYTES / (MSIZE + MCLBYTES));
98
  SCTP_BASE_SYSCTL(sctp_sendspace) = sb_max_adj;
99
#else
100
  if ((nmbclusters / 8) > SCTP_ASOC_MAX_CHUNKS_ON_QUEUE)
101
    SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue) = (nmbclusters / 8);
102
  /*
103
   * Allow a user to take no more than 1/2 the number of clusters or
104
   * the SB_MAX, whichever is smaller, for the send window.
105
   */
106
  sb_max_adj = (u_long)((u_quad_t) (SB_MAX) * MCLBYTES / (MSIZE + MCLBYTES));
107
  SCTP_BASE_SYSCTL(sctp_sendspace) = min(sb_max_adj,
108
      (((uint32_t)nmbclusters / 2) * MCLBYTES));
109
#endif
110
  /*
111
   * Now for the recv window, should we take the same amount? or
112
   * should I do 1/2 the SB_MAX instead in the SB_MAX min above. For
113
   * now I will just copy.
114
   */
115
  SCTP_BASE_SYSCTL(sctp_recvspace) = SCTP_BASE_SYSCTL(sctp_sendspace);
116
#endif
117
3
  SCTP_BASE_VAR(first_time) = 0;
118
3
  SCTP_BASE_VAR(sctp_pcb_initialized) = 0;
119
3
#if defined(__Userspace__)
120
3
#if !defined(_WIN32)
121
3
#if defined(INET) || defined(INET6)
122
3
  SCTP_BASE_VAR(userspace_route) = -1;
123
3
#endif
124
3
#endif
125
3
#ifdef INET
126
3
  SCTP_BASE_VAR(userspace_rawsctp) = -1;
127
3
  SCTP_BASE_VAR(userspace_udpsctp) = -1;
128
3
#endif
129
3
#ifdef INET6
130
3
  SCTP_BASE_VAR(userspace_rawsctp6) = -1;
131
3
  SCTP_BASE_VAR(userspace_udpsctp6) = -1;
132
3
#endif
133
3
  SCTP_BASE_VAR(timer_thread_should_exit) = 0;
134
3
  SCTP_BASE_VAR(conn_output) = conn_output;
135
3
  SCTP_BASE_VAR(debug_printf) = debug_printf;
136
3
  SCTP_BASE_VAR(crc32c_offloaded) = 0;
137
3
  SCTP_BASE_VAR(iterator_thread_started) = 0;
138
3
  SCTP_BASE_VAR(timer_thread_started) = 0;
139
3
#endif
140
3
#if defined(__Userspace__)
141
3
  sctp_pcb_init(start_threads);
142
3
  if (start_threads) {
143
3
    sctp_start_timer_thread();
144
3
  }
145
#else
146
  sctp_pcb_init();
147
#endif
148
#if defined(SCTP_PACKET_LOGGING)
149
  SCTP_BASE_VAR(packet_log_writers) = 0;
150
  SCTP_BASE_VAR(packet_log_end) = 0;
151
  memset(&SCTP_BASE_VAR(packet_log_buffer), 0, SCTP_PACKET_LOG_SIZE);
152
#endif
153
#if defined(__APPLE__) && !defined(__Userspace__)
154
  SCTP_BASE_VAR(sctp_main_timer_ticks) = 0;
155
  sctp_start_main_timer();
156
  timeout(sctp_delayed_startup, NULL, 1);
157
#endif
158
#if defined(__FreeBSD__) && !defined(__Userspace__)
159
  SCTP_BASE_VAR(eh_tag) = EVENTHANDLER_REGISTER(rt_addrmsg,
160
      sctp_addr_change_event_handler, NULL, EVENTHANDLER_PRI_FIRST);
161
#endif
162
3
}
163
#if defined(__FreeBSD__) && !defined(__Userspace__)
164
VNET_SYSINIT(sctp_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_THIRD, sctp_init, NULL);
165
166
#ifdef VIMAGE
167
static void
168
sctp_finish(void *unused __unused)
169
{
170
  EVENTHANDLER_DEREGISTER(rt_addrmsg, SCTP_BASE_VAR(eh_tag));
171
  sctp_pcb_finish();
172
}
173
VNET_SYSUNINIT(sctp, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, sctp_finish, NULL);
174
#endif
175
#else
176
void
177
sctp_finish(void)
178
0
{
179
#if defined(__APPLE__) && !defined(__Userspace__)
180
  untimeout(sctp_delayed_startup, NULL);
181
  sctp_over_udp_stop();
182
  sctp_address_monitor_stop();
183
  sctp_stop_main_timer();
184
#endif
185
0
#if defined(__Userspace__)
186
0
#if defined(INET) || defined(INET6)
187
0
  recv_thread_destroy();
188
0
#endif
189
0
  sctp_stop_timer_thread();
190
0
#endif
191
0
  sctp_pcb_finish();
192
#if defined(_WIN32) && !defined(__Userspace__)
193
  sctp_finish_sysctls();
194
#endif
195
0
#if defined(__Userspace__)
196
0
  finish_random();
197
0
#endif
198
0
}
199
#endif
200
201
void
202
sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint32_t mtu, bool resend)
203
0
{
204
0
  struct sctp_association *asoc;
205
0
  struct sctp_tmit_chunk *chk;
206
0
  uint32_t overhead;
207
208
0
  asoc = &stcb->asoc;
209
0
  KASSERT(mtu < asoc->smallest_mtu,
210
0
          ("Currently only reducing association MTU %u supported (MTU %u)",
211
0
          asoc->smallest_mtu, mtu));
212
0
  asoc->smallest_mtu = mtu;
213
0
  if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
214
0
    overhead = SCTP_MIN_OVERHEAD;
215
0
  } else {
216
0
#if defined(__Userspace__)
217
0
    if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) {
218
0
      overhead = sizeof(struct sctphdr);
219
0
    } else {
220
0
      overhead = SCTP_MIN_V4_OVERHEAD;
221
0
    }
222
#else
223
    overhead = SCTP_MIN_V4_OVERHEAD;
224
#endif
225
0
  }
226
0
  if (asoc->idata_supported) {
227
0
    if (sctp_auth_is_required_chunk(SCTP_IDATA, asoc->peer_auth_chunks)) {
228
0
      overhead += sctp_get_auth_chunk_len(asoc->peer_hmac_id);
229
0
    }
230
0
  } else {
231
0
    if (sctp_auth_is_required_chunk(SCTP_DATA, asoc->peer_auth_chunks)) {
232
0
      overhead += sctp_get_auth_chunk_len(asoc->peer_hmac_id);
233
0
    }
234
0
  }
235
0
  KASSERT(overhead % 4 == 0,
236
0
          ("overhead (%u) not a multiple of 4", overhead));
237
0
  TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
238
0
    if (((uint32_t)chk->send_size + overhead) > mtu) {
239
0
      chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
240
0
    }
241
0
  }
242
0
  TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
243
0
    if (((uint32_t)chk->send_size + overhead) > mtu) {
244
0
      chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
245
0
      if (resend && chk->sent < SCTP_DATAGRAM_RESEND) {
246
        /*
247
         * If requested, mark the chunk for immediate
248
         * resend, since we sent it being too big.
249
         */
250
0
        sctp_flight_size_decrease(chk);
251
0
        sctp_total_flight_decrease(stcb, chk);
252
0
        chk->sent = SCTP_DATAGRAM_RESEND;
253
0
        sctp_ucount_incr(asoc->sent_queue_retran_cnt);
254
0
        chk->rec.data.doing_fast_retransmit = 0;
255
0
        if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
256
0
          sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
257
0
                         chk->whoTo->flight_size,
258
0
                         chk->book_size,
259
0
                         (uint32_t)(uintptr_t)chk->whoTo,
260
0
                         chk->rec.data.tsn);
261
0
        }
262
        /* Clear any time, so NO RTT is being done. */
263
0
        if (chk->do_rtt == 1) {
264
0
          chk->do_rtt = 0;
265
0
          chk->whoTo->rto_needed = 1;
266
0
        }
267
0
      }
268
0
    }
269
0
  }
270
0
}
271
272
#ifdef INET
273
#if !defined(__Userspace__)
274
void
275
sctp_notify(struct sctp_inpcb *inp,
276
            struct sctp_tcb *stcb,
277
            struct sctp_nets *net,
278
            uint8_t icmp_type,
279
            uint8_t icmp_code,
280
            uint16_t ip_len,
281
            uint32_t next_mtu)
282
{
283
#if defined(__APPLE__) && !defined(__Userspace__)
284
  struct socket *so;
285
#endif
286
  int timer_stopped;
287
288
  if (icmp_type != ICMP_UNREACH) {
289
    /* We only care about unreachable */
290
    SCTP_TCB_UNLOCK(stcb);
291
    return;
292
  }
293
  if ((icmp_code == ICMP_UNREACH_NET) ||
294
      (icmp_code == ICMP_UNREACH_HOST) ||
295
      (icmp_code == ICMP_UNREACH_NET_UNKNOWN) ||
296
      (icmp_code == ICMP_UNREACH_HOST_UNKNOWN) ||
297
      (icmp_code == ICMP_UNREACH_ISOLATED) ||
298
      (icmp_code == ICMP_UNREACH_NET_PROHIB) ||
299
      (icmp_code == ICMP_UNREACH_HOST_PROHIB) ||
300
#if defined(__NetBSD__)
301
      (icmp_code == ICMP_UNREACH_ADMIN_PROHIBIT)) {
302
#else
303
      (icmp_code == ICMP_UNREACH_FILTER_PROHIB)) {
304
#endif
305
    /* Mark the net unreachable. */
306
    if (net->dest_state & SCTP_ADDR_REACHABLE) {
307
      /* OK, that destination is NOT reachable. */
308
      net->dest_state &= ~SCTP_ADDR_REACHABLE;
309
      net->dest_state &= ~SCTP_ADDR_PF;
310
      sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
311
                      stcb, 0,
312
                      (void *)net, SCTP_SO_NOT_LOCKED);
313
    }
314
    SCTP_TCB_UNLOCK(stcb);
315
  } else  if ((icmp_code == ICMP_UNREACH_PROTOCOL) ||
316
        (icmp_code == ICMP_UNREACH_PORT)) {
317
    /* Treat it like an ABORT. */
318
    sctp_abort_notification(stcb, true, false, 0, NULL, SCTP_SO_NOT_LOCKED);
319
#if defined(__APPLE__) && !defined(__Userspace__)
320
    so = SCTP_INP_SO(inp);
321
    atomic_add_int(&stcb->asoc.refcnt, 1);
322
    SCTP_TCB_UNLOCK(stcb);
323
    SCTP_SOCKET_LOCK(so, 1);
324
    SCTP_TCB_LOCK(stcb);
325
    atomic_subtract_int(&stcb->asoc.refcnt, 1);
326
#endif
327
    (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
328
                          SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
329
#if defined(__APPLE__) && !defined(__Userspace__)
330
    SCTP_SOCKET_UNLOCK(so, 1);
331
    /* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed.*/
332
#endif
333
    /* no need to unlock here, since the TCB is gone */
334
  } else if (icmp_code == ICMP_UNREACH_NEEDFRAG) {
335
    if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
336
      SCTP_TCB_UNLOCK(stcb);
337
      return;
338
    }
339
    /* Find the next (smaller) MTU */
340
    if (next_mtu == 0) {
341
      /*
342
       * Old type router that does not tell us what the next
343
       * MTU is.
344
       * Rats we will have to guess (in a educated fashion
345
       * of course).
346
       */
347
      next_mtu = sctp_get_prev_mtu(ip_len);
348
    }
349
    /* Stop the PMTU timer. */
350
    if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
351
      timer_stopped = 1;
352
      sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
353
                      SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1);
354
    } else {
355
      timer_stopped = 0;
356
    }
357
    /* Update the path MTU. */
358
    if (net->port) {
359
      next_mtu -= sizeof(struct udphdr);
360
    }
361
    if (net->mtu > next_mtu) {
362
      net->mtu = next_mtu;
363
#if defined(__FreeBSD__) && !defined(__Userspace__)
364
      if (net->port) {
365
        sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu + sizeof(struct udphdr));
366
      } else {
367
        sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu);
368
      }
369
#endif
370
    }
371
    /* Update the association MTU */
372
    if (stcb->asoc.smallest_mtu > next_mtu) {
373
      sctp_pathmtu_adjustment(stcb, next_mtu, true);
374
    }
375
    /* Finally, start the PMTU timer if it was running before. */
376
    if (timer_stopped) {
377
      sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
378
    }
379
    SCTP_TCB_UNLOCK(stcb);
380
  } else {
381
    SCTP_TCB_UNLOCK(stcb);
382
  }
383
}
384
#endif
385
386
#if !defined(__Userspace__)
387
#if defined(__FreeBSD__)
388
void sctp_ctlinput(struct icmp *icmp)
389
{
390
  struct ip *inner_ip, *outer_ip;
391
  struct sctphdr *sh;
392
  struct sctp_inpcb *inp;
393
  struct sctp_tcb *stcb;
394
  struct sctp_nets *net;
395
  struct sctp_init_chunk *ch;
396
  struct sockaddr_in src, dst;
397
398
  if (icmp_errmap(icmp) == 0)
399
    return;
400
401
  outer_ip = (struct ip *)((caddr_t)icmp - sizeof(struct ip));
402
  inner_ip = &icmp->icmp_ip;
403
  sh = (struct sctphdr *)((caddr_t)inner_ip + (inner_ip->ip_hl << 2));
404
  memset(&src, 0, sizeof(struct sockaddr_in));
405
  src.sin_family = AF_INET;
406
  src.sin_len = sizeof(struct sockaddr_in);
407
  src.sin_port = sh->src_port;
408
  src.sin_addr = inner_ip->ip_src;
409
  memset(&dst, 0, sizeof(struct sockaddr_in));
410
  dst.sin_family = AF_INET;
411
  dst.sin_len = sizeof(struct sockaddr_in);
412
  dst.sin_port = sh->dest_port;
413
  dst.sin_addr = inner_ip->ip_dst;
414
  /*
415
   * 'dst' holds the dest of the packet that failed to be sent.
416
   * 'src' holds our local endpoint address. Thus we reverse
417
   * the dst and the src in the lookup.
418
   */
419
  inp = NULL;
420
  net = NULL;
421
  stcb = sctp_findassociation_addr_sa((struct sockaddr *)&dst,
422
                                      (struct sockaddr *)&src,
423
                                      &inp, &net, 1,
424
                                      SCTP_DEFAULT_VRFID);
425
  if ((stcb != NULL) &&
426
      (net != NULL) &&
427
      (inp != NULL)) {
428
    /* Check the verification tag */
429
    if (ntohl(sh->v_tag) != 0) {
430
      /*
431
       * This must be the verification tag used for
432
       * sending out packets. We don't consider
433
       * packets reflecting the verification tag.
434
       */
435
      if (ntohl(sh->v_tag) != stcb->asoc.peer_vtag) {
436
        SCTP_TCB_UNLOCK(stcb);
437
        return;
438
      }
439
    } else {
440
      if (ntohs(outer_ip->ip_len) >=
441
          sizeof(struct ip) +
442
          8 + (inner_ip->ip_hl << 2) + 20) {
443
        /*
444
         * In this case we can check if we
445
         * got an INIT chunk and if the
446
         * initiate tag matches.
447
         */
448
        ch = (struct sctp_init_chunk *)(sh + 1);
449
        if ((ch->ch.chunk_type != SCTP_INITIATION) ||
450
            (ntohl(ch->init.initiate_tag) != stcb->asoc.my_vtag)) {
451
          SCTP_TCB_UNLOCK(stcb);
452
          return;
453
        }
454
      } else {
455
        SCTP_TCB_UNLOCK(stcb);
456
        return;
457
      }
458
    }
459
    sctp_notify(inp, stcb, net,
460
                icmp->icmp_type,
461
                icmp->icmp_code,
462
                ntohs(inner_ip->ip_len),
463
                (uint32_t)ntohs(icmp->icmp_nextmtu));
464
  } else {
465
    if ((stcb == NULL) && (inp != NULL)) {
466
      /* reduce ref-count */
467
      SCTP_INP_WLOCK(inp);
468
      SCTP_INP_DECR_REF(inp);
469
      SCTP_INP_WUNLOCK(inp);
470
    }
471
    if (stcb) {
472
      SCTP_TCB_UNLOCK(stcb);
473
    }
474
  }
475
}
476
#else
477
void
478
#if defined(__APPLE__) && !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION) && !defined(APPLE_ELCAPITAN)
479
sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip, struct ifnet *ifp SCTP_UNUSED)
480
#else
481
sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
482
#endif
483
{
484
  struct ip *inner_ip;
485
  struct sctphdr *sh;
486
  struct icmp *icmp;
487
  struct sctp_inpcb *inp;
488
  struct sctp_tcb *stcb;
489
  struct sctp_nets *net;
490
  struct sockaddr_in src, dst;
491
492
#if !defined(__FreeBSD__) && !defined(__Userspace__)
493
  if (sa->sa_family != AF_INET ||
494
      ((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) {
495
    return;
496
  }
497
#endif
498
  if (PRC_IS_REDIRECT(cmd)) {
499
    vip = NULL;
500
  } else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) {
501
    return;
502
  }
503
  if (vip != NULL) {
504
    inner_ip = (struct ip *)vip;
505
    icmp = (struct icmp *)((caddr_t)inner_ip -
506
        (sizeof(struct icmp) - sizeof(struct ip)));
507
    sh = (struct sctphdr *)((caddr_t)inner_ip + (inner_ip->ip_hl << 2));
508
    memset(&src, 0, sizeof(struct sockaddr_in));
509
    src.sin_family = AF_INET;
510
#ifdef HAVE_SIN_LEN
511
    src.sin_len = sizeof(struct sockaddr_in);
512
#endif
513
    src.sin_port = sh->src_port;
514
    src.sin_addr = inner_ip->ip_src;
515
    memset(&dst, 0, sizeof(struct sockaddr_in));
516
    dst.sin_family = AF_INET;
517
#ifdef HAVE_SIN_LEN
518
    dst.sin_len = sizeof(struct sockaddr_in);
519
#endif
520
    dst.sin_port = sh->dest_port;
521
    dst.sin_addr = inner_ip->ip_dst;
522
    /*
523
     * 'dst' holds the dest of the packet that failed to be sent.
524
     * 'src' holds our local endpoint address. Thus we reverse
525
     * the dst and the src in the lookup.
526
     */
527
    inp = NULL;
528
    net = NULL;
529
    stcb = sctp_findassociation_addr_sa((struct sockaddr *)&dst,
530
                                        (struct sockaddr *)&src,
531
                                        &inp, &net, 1,
532
                                        SCTP_DEFAULT_VRFID);
533
    if ((stcb != NULL) &&
534
        (net != NULL) &&
535
        (inp != NULL)) {
536
      /* Check the verification tag */
537
      if (ntohl(sh->v_tag) != 0) {
538
        /*
539
         * This must be the verification tag used for
540
         * sending out packets. We don't consider
541
         * packets reflecting the verification tag.
542
         */
543
        if (ntohl(sh->v_tag) != stcb->asoc.peer_vtag) {
544
          SCTP_TCB_UNLOCK(stcb);
545
          return;
546
        }
547
      } else {
548
        SCTP_TCB_UNLOCK(stcb);
549
        return;
550
      }
551
      sctp_notify(inp, stcb, net,
552
                  icmp->icmp_type,
553
                  icmp->icmp_code,
554
                  inner_ip->ip_len,
555
                  (uint32_t)ntohs(icmp->icmp_nextmtu));
556
#if defined(__Userspace__)
557
      if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
558
          (stcb->sctp_socket != NULL)) {
559
        struct socket *upcall_socket;
560
561
        upcall_socket = stcb->sctp_socket;
562
        SOCK_LOCK(upcall_socket);
563
        soref(upcall_socket);
564
        SOCK_UNLOCK(upcall_socket);
565
        if ((upcall_socket->so_upcall != NULL) &&
566
            (upcall_socket->so_error != 0)) {
567
          (*upcall_socket->so_upcall)(upcall_socket, upcall_socket->so_upcallarg, M_NOWAIT);
568
        }
569
        ACCEPT_LOCK();
570
        SOCK_LOCK(upcall_socket);
571
        sorele(upcall_socket);
572
      }
573
#endif
574
    } else {
575
      if ((stcb == NULL) && (inp != NULL)) {
576
        /* reduce ref-count */
577
        SCTP_INP_WLOCK(inp);
578
        SCTP_INP_DECR_REF(inp);
579
        SCTP_INP_WUNLOCK(inp);
580
      }
581
      if (stcb) {
582
        SCTP_TCB_UNLOCK(stcb);
583
      }
584
    }
585
  }
586
  return;
587
}
588
#endif
589
#endif
590
#endif
591
592
#if defined(__FreeBSD__) && !defined(__Userspace__)
593
static int
594
sctp_getcred(SYSCTL_HANDLER_ARGS)
595
{
596
  struct xucred xuc;
597
  struct sockaddr_in addrs[2];
598
  struct sctp_inpcb *inp;
599
  struct sctp_nets *net;
600
  struct sctp_tcb *stcb;
601
  int error;
602
  uint32_t vrf_id;
603
604
  /* FIX, for non-bsd is this right? */
605
  vrf_id = SCTP_DEFAULT_VRFID;
606
607
  if (req->newptr == NULL)
608
    return (EINVAL);
609
  error = priv_check(req->td, PRIV_NETINET_GETCRED);
610
  if (error)
611
    return (error);
612
613
  error = SYSCTL_IN(req, addrs, sizeof(addrs));
614
  if (error)
615
    return (error);
616
617
  stcb = sctp_findassociation_addr_sa(sintosa(&addrs[1]),
618
      sintosa(&addrs[0]),
619
      &inp, &net, 1, vrf_id);
620
  if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
621
    if ((inp != NULL) && (stcb == NULL)) {
622
      /* reduce ref-count */
623
      SCTP_INP_WLOCK(inp);
624
      SCTP_INP_DECR_REF(inp);
625
      goto cred_can_cont;
626
    }
627
628
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
629
    error = ENOENT;
630
    goto out;
631
  }
632
  SCTP_TCB_UNLOCK(stcb);
633
  /* We use the write lock here, only
634
   * since in the error leg we need it.
635
   * If we used RLOCK, then we would have
636
   * to wlock/decr/unlock/rlock. Which
637
   * in theory could create a hole. Better
638
   * to use higher wlock.
639
   */
640
  SCTP_INP_WLOCK(inp);
641
 cred_can_cont:
642
  error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
643
  if (error) {
644
    SCTP_INP_WUNLOCK(inp);
645
    goto out;
646
  }
647
  cru2x(inp->sctp_socket->so_cred, &xuc);
648
  SCTP_INP_WUNLOCK(inp);
649
  error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
650
out:
651
  return (error);
652
}
653
654
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred,
655
    CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
656
    0, 0, sctp_getcred, "S,ucred",
657
    "Get the ucred of a SCTP connection");
658
#endif
659
660
#if defined(__FreeBSD__) && !defined(__Userspace__)
661
void
662
#else
663
int
664
#endif
665
sctp_abort(struct socket *so)
666
0
{
667
#if defined(__FreeBSD__) && !defined(__Userspace__)
668
  struct epoch_tracker et;
669
#endif
670
0
  struct sctp_inpcb *inp;
671
672
0
  inp = (struct sctp_inpcb *)so->so_pcb;
673
0
  if (inp == NULL) {
674
#if defined(__FreeBSD__) && !defined(__Userspace__)
675
    return;
676
#else
677
0
    SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
678
0
    return (EINVAL);
679
0
#endif
680
0
  }
681
682
0
  SCTP_INP_WLOCK(inp);
683
#if defined(__FreeBSD__) && !defined(__Userspace__)
684
  NET_EPOCH_ENTER(et);
685
#endif
686
#ifdef SCTP_LOG_CLOSING
687
  sctp_log_closing(inp, NULL, 17);
688
#endif
689
0
  if (((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0)) {
690
0
    inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP;
691
#ifdef SCTP_LOG_CLOSING
692
    sctp_log_closing(inp, NULL, 16);
693
#endif
694
0
    SCTP_INP_WUNLOCK(inp);
695
0
    sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
696
0
                    SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
697
0
    SOCK_LOCK(so);
698
#if defined(__FreeBSD__) && !defined(__Userspace__)
699
    KASSERT(!SOLISTENING(so),
700
            ("sctp_abort: called on listening socket %p", so));
701
#endif
702
0
    SCTP_SB_CLEAR(so->so_snd);
703
0
    SCTP_SB_CLEAR(so->so_rcv);
704
#if defined(__APPLE__) && !defined(__Userspace__)
705
    so->so_usecount--;
706
#else
707
    /* Now null out the reference, we are completely detached. */
708
0
    so->so_pcb = NULL;
709
0
#endif
710
0
    SOCK_UNLOCK(so);
711
0
  } else {
712
0
    SCTP_INP_WUNLOCK(inp);
713
0
  }
714
#if defined(__FreeBSD__) && !defined(__Userspace__)
715
  NET_EPOCH_EXIT(et);
716
#else
717
0
  return (0);
718
0
#endif
719
0
}
720
721
#ifdef INET
722
#if defined(__Userspace__)
723
int
724
#else
725
static int
726
#endif
727
#if defined(__Userspace__)
728
sctp_attach(struct socket *so, int proto SCTP_UNUSED, uint32_t vrf_id)
729
#elif defined(__FreeBSD__)
730
sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
731
#elif defined(_WIN32)
732
sctp_attach(struct socket *so, int proto SCTP_UNUSED, PKTHREAD p SCTP_UNUSED)
733
#else
734
sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct proc *p SCTP_UNUSED)
735
#endif
736
0
{
737
0
  struct sctp_inpcb *inp;
738
0
  struct inpcb *ip_inp;
739
0
  int error;
740
#if !defined(__Userspace__)
741
  uint32_t vrf_id = SCTP_DEFAULT_VRFID;
742
#endif
743
744
0
  inp = (struct sctp_inpcb *)so->so_pcb;
745
0
  if (inp != NULL) {
746
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
747
0
    return (EINVAL);
748
0
  }
749
0
  if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
750
0
    error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
751
0
    if (error) {
752
0
      return (error);
753
0
    }
754
0
  }
755
0
  error = sctp_inpcb_alloc(so, vrf_id);
756
0
  if (error) {
757
0
    return (error);
758
0
  }
759
0
  inp = (struct sctp_inpcb *)so->so_pcb;
760
0
  SCTP_INP_WLOCK(inp);
761
0
  inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6; /* I'm not v6! */
762
0
  ip_inp = &inp->ip_inp.inp;
763
0
  ip_inp->inp_vflag |= INP_IPV4;
764
0
  ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
765
0
  SCTP_INP_WUNLOCK(inp);
766
0
  return (0);
767
0
}
768
769
#if defined(__Userspace__)
770
int
771
0
sctp_bind(struct socket *so, struct sockaddr *addr) {
772
0
  void *p = NULL;
773
#elif defined(__FreeBSD__)
774
static int
775
sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
776
{
777
#elif defined(__APPLE__)
778
static int
779
sctp_bind(struct socket *so, struct sockaddr *addr, struct proc *p) {
780
#elif defined(_WIN32)
781
static int
782
sctp_bind(struct socket *so, struct sockaddr *addr, PKTHREAD p) {
783
#else
784
static int
785
sctp_bind(struct socket *so, struct mbuf *nam, struct proc *p)
786
{
787
  struct sockaddr *addr = nam ? mtod(nam, struct sockaddr *): NULL;
788
789
#endif
790
0
  struct sctp_inpcb *inp;
791
792
0
  inp = (struct sctp_inpcb *)so->so_pcb;
793
0
  if (inp == NULL) {
794
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
795
0
    return (EINVAL);
796
0
  }
797
0
  if (addr != NULL) {
798
#ifdef HAVE_SA_LEN
799
    if ((addr->sa_family != AF_INET) ||
800
        (addr->sa_len != sizeof(struct sockaddr_in))) {
801
#else
802
0
    if (addr->sa_family != AF_INET) {
803
0
#endif
804
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
805
0
      return (EINVAL);
806
0
    }
807
0
  }
808
0
  return (sctp_inpcb_bind(so, addr, NULL, p));
809
0
}
810
811
#endif
812
#if defined(__Userspace__)
813
814
int
815
sctpconn_attach(struct socket *so, int proto SCTP_UNUSED, uint32_t vrf_id)
816
11.5k
{
817
11.5k
  struct sctp_inpcb *inp;
818
11.5k
  struct inpcb *ip_inp;
819
11.5k
  int error;
820
821
11.5k
  inp = (struct sctp_inpcb *)so->so_pcb;
822
11.5k
  if (inp != NULL) {
823
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
824
0
    return (EINVAL);
825
0
  }
826
11.5k
  if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
827
11.5k
    error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
828
11.5k
    if (error) {
829
0
      return (error);
830
0
    }
831
11.5k
  }
832
11.5k
  error = sctp_inpcb_alloc(so, vrf_id);
833
11.5k
  if (error) {
834
0
    return (error);
835
0
  }
836
11.5k
  inp = (struct sctp_inpcb *)so->so_pcb;
837
11.5k
  SCTP_INP_WLOCK(inp);
838
11.5k
  inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6;
839
11.5k
  inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_CONN;
840
11.5k
  ip_inp = &inp->ip_inp.inp;
841
11.5k
  ip_inp->inp_vflag |= INP_CONN;
842
11.5k
  ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
843
11.5k
  SCTP_INP_WUNLOCK(inp);
844
11.5k
  return (0);
845
11.5k
}
846
847
int
848
sctpconn_bind(struct socket *so, struct sockaddr *addr)
849
11.5k
{
850
11.5k
  struct sctp_inpcb *inp;
851
852
11.5k
  inp = (struct sctp_inpcb *)so->so_pcb;
853
11.5k
  if (inp == NULL) {
854
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
855
0
    return (EINVAL);
856
0
  }
857
11.5k
  if (addr != NULL) {
858
#ifdef HAVE_SA_LEN
859
    if ((addr->sa_family != AF_CONN) ||
860
        (addr->sa_len != sizeof(struct sockaddr_conn))) {
861
#else
862
11.5k
    if (addr->sa_family != AF_CONN) {
863
0
#endif
864
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
865
0
      return (EINVAL);
866
0
    }
867
11.5k
  }
868
11.5k
  return (sctp_inpcb_bind(so, addr, NULL, NULL));
869
11.5k
}
870
871
#endif
872
#if defined(__FreeBSD__) || defined(_WIN32) || defined(__Userspace__)
873
void
874
sctp_close(struct socket *so)
875
11.5k
{
876
#if defined(__FreeBSD__) && !defined(__Userspace__)
877
  struct epoch_tracker et;
878
#endif
879
11.5k
  struct sctp_inpcb *inp;
880
881
11.5k
  inp = (struct sctp_inpcb *)so->so_pcb;
882
11.5k
  if (inp == NULL)
883
0
    return;
884
885
  /* Inform all the lower layer assoc that we
886
   * are done.
887
   */
888
11.5k
  SCTP_INP_WLOCK(inp);
889
#if defined(__FreeBSD__) && !defined(__Userspace__)
890
  NET_EPOCH_ENTER(et);
891
#endif
892
#ifdef SCTP_LOG_CLOSING
893
  sctp_log_closing(inp, NULL, 17);
894
#endif
895
11.5k
  if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
896
11.5k
    inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP;
897
11.5k
#if defined(__Userspace__)
898
11.5k
    if (((so->so_options & SCTP_SO_LINGER) && (so->so_linger == 0)) ||
899
#else
900
    if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
901
#endif
902
11.5k
        (SCTP_SBAVAIL(&so->so_rcv) > 0)) {
903
#ifdef SCTP_LOG_CLOSING
904
      sctp_log_closing(inp, NULL, 13);
905
#endif
906
11.5k
      SCTP_INP_WUNLOCK(inp);
907
11.5k
      sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
908
11.5k
                      SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
909
11.5k
    } else {
910
#ifdef SCTP_LOG_CLOSING
911
      sctp_log_closing(inp, NULL, 14);
912
#endif
913
0
      SCTP_INP_WUNLOCK(inp);
914
0
      sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
915
0
                      SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
916
0
    }
917
    /* The socket is now detached, no matter what
918
     * the state of the SCTP association.
919
     */
920
11.5k
    SOCK_LOCK(so);
921
#if defined(__FreeBSD__) && !defined(__Userspace__)
922
    if (!SOLISTENING(so)) {
923
      SCTP_SB_CLEAR(so->so_snd);
924
      SCTP_SB_CLEAR(so->so_rcv);
925
    }
926
#else
927
11.5k
    SCTP_SB_CLEAR(so->so_snd);
928
11.5k
    SCTP_SB_CLEAR(so->so_rcv);
929
11.5k
#endif
930
11.5k
#if !(defined(__APPLE__) && !defined(__Userspace__))
931
    /* Now null out the reference, we are completely detached. */
932
11.5k
    so->so_pcb = NULL;
933
11.5k
#endif
934
11.5k
    SOCK_UNLOCK(so);
935
11.5k
  } else {
936
0
    SCTP_INP_WUNLOCK(inp);
937
0
  }
938
#if defined(__FreeBSD__) && !defined(__Userspace__)
939
  NET_EPOCH_EXIT(et);
940
#endif
941
11.5k
}
942
#else
943
int
944
sctp_detach(struct socket *so)
945
{
946
  struct sctp_inpcb *inp;
947
  uint32_t flags;
948
949
  inp = (struct sctp_inpcb *)so->so_pcb;
950
  if (inp == NULL) {
951
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
952
    return (EINVAL);
953
  }
954
 sctp_must_try_again:
955
  flags = inp->sctp_flags;
956
#ifdef SCTP_LOG_CLOSING
957
  sctp_log_closing(inp, NULL, 17);
958
#endif
959
  if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
960
      (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
961
    if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
962
        (SCTP_SBAVAIL(&so->so_rcv) > 0)) {
963
#ifdef SCTP_LOG_CLOSING
964
      sctp_log_closing(inp, NULL, 13);
965
#endif
966
      sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
967
                      SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
968
    } else {
969
#ifdef SCTP_LOG_CLOSING
970
      sctp_log_closing(inp, NULL, 13);
971
#endif
972
      sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
973
                      SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
974
    }
975
    /* The socket is now detached, no matter what
976
     * the state of the SCTP association.
977
     */
978
    SCTP_SB_CLEAR(so->so_snd);
979
    /* same for the rcv ones, they are only
980
     * here for the accounting/select.
981
     */
982
    SCTP_SB_CLEAR(so->so_rcv);
983
#if !(defined(__APPLE__) && !defined(__Userspace__))
984
    /* Now disconnect */
985
    so->so_pcb = NULL;
986
#endif
987
  } else {
988
    flags = inp->sctp_flags;
989
    if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
990
      goto sctp_must_try_again;
991
    }
992
  }
993
  return (0);
994
}
995
#endif
996
997
#if defined(__Userspace__)
998
/* __Userspace__ is not calling sctp_sendm */
999
#endif
1000
#if !(defined(_WIN32) && !defined(__Userspace__))
1001
int
1002
#if defined(__FreeBSD__) && !defined(__Userspace__)
1003
sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
1004
    struct mbuf *control, struct thread *p);
1005
1006
#else
1007
sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
1008
    struct mbuf *control, struct proc *p);
1009
1010
#endif
1011
int
1012
#if defined(__FreeBSD__) && !defined(__Userspace__)
1013
sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
1014
    struct mbuf *control, struct thread *p)
1015
{
1016
#else
1017
sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
1018
    struct mbuf *control, struct proc *p)
1019
0
{
1020
0
#endif
1021
0
  struct sctp_inpcb *inp;
1022
0
  int error;
1023
1024
0
  inp = (struct sctp_inpcb *)so->so_pcb;
1025
0
  if (inp == NULL) {
1026
0
    if (control) {
1027
0
      sctp_m_freem(control);
1028
0
      control = NULL;
1029
0
    }
1030
0
    SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1031
0
    sctp_m_freem(m);
1032
0
    return (EINVAL);
1033
0
  }
1034
  /* Got to have an to address if we are NOT a connected socket */
1035
0
  if ((addr == NULL) &&
1036
0
      ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) ||
1037
0
      (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE))) {
1038
0
    goto connected_type;
1039
0
  }
1040
1041
0
  error = 0;
1042
0
  if (addr == NULL) {
1043
0
    SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
1044
0
    error = EDESTADDRREQ;
1045
0
  } else if (addr->sa_family != AF_INET) {
1046
0
    SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
1047
0
    error = EAFNOSUPPORT;
1048
#if defined(HAVE_SA_LEN)
1049
  } else if (addr->sa_len != sizeof(struct sockaddr_in)) {
1050
    SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1051
    error = EINVAL;
1052
#endif
1053
0
  }
1054
0
  if (error != 0) {
1055
0
    sctp_m_freem(m);
1056
0
    if (control) {
1057
0
      sctp_m_freem(control);
1058
0
      control = NULL;
1059
0
    }
1060
0
    return (error);
1061
0
  }
1062
0
connected_type:
1063
  /* now what about control */
1064
0
  if (control) {
1065
0
    if (inp->control) {
1066
0
      sctp_m_freem(inp->control);
1067
0
      inp->control = NULL;
1068
0
    }
1069
0
    inp->control = control;
1070
0
  }
1071
  /* Place the data */
1072
0
  if (inp->pkt) {
1073
0
    SCTP_BUF_NEXT(inp->pkt_last) = m;
1074
0
    inp->pkt_last = m;
1075
0
  } else {
1076
0
    inp->pkt_last = inp->pkt = m;
1077
0
  }
1078
0
  if (
1079
#if (defined(__FreeBSD__) || defined(__APPLE__)) && !defined(__Userspace__)
1080
  /* FreeBSD uses a flag passed */
1081
      ((flags & PRUS_MORETOCOME) == 0)
1082
#else
1083
0
      1      /* Open BSD does not have any "more to come"
1084
         * indication */
1085
0
#endif
1086
0
      ) {
1087
    /*
1088
     * note with the current version this code will only be used
1089
     * by OpenBSD-- NetBSD, FreeBSD, and MacOS have methods for
1090
     * re-defining sosend to use the sctp_sosend. One can
1091
     * optionally switch back to this code (by changing back the
1092
     * definitions) but this is not advisable. This code is used
1093
     * by FreeBSD when sending a file with sendfile() though.
1094
     */
1095
#if defined(__FreeBSD__) && !defined(__Userspace__)
1096
    struct epoch_tracker et;
1097
#endif
1098
0
    int ret;
1099
1100
#if defined(__FreeBSD__) && !defined(__Userspace__)
1101
  NET_EPOCH_ENTER(et);
1102
#endif
1103
0
    ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
1104
#if defined(__FreeBSD__) && !defined(__Userspace__)
1105
  NET_EPOCH_EXIT(et);
1106
#endif
1107
0
    inp->pkt = NULL;
1108
0
    inp->control = NULL;
1109
0
    return (ret);
1110
0
  } else {
1111
0
    return (0);
1112
0
  }
1113
0
}
1114
#endif
1115
1116
int
1117
sctp_disconnect(struct socket *so)
1118
0
{
1119
#if defined(__FreeBSD__) && !defined(__Userspace__)
1120
  struct epoch_tracker et;
1121
#endif
1122
0
  struct sctp_inpcb *inp;
1123
0
  struct sctp_association *asoc;
1124
0
  struct sctp_tcb *stcb;
1125
1126
0
  inp = (struct sctp_inpcb *)so->so_pcb;
1127
0
  if (inp == NULL) {
1128
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
1129
0
    return (ENOTCONN);
1130
0
  }
1131
0
  SCTP_INP_RLOCK(inp);
1132
0
  KASSERT(inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE ||
1133
0
          inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL,
1134
0
          ("Not a one-to-one style socket"));
1135
0
  stcb = LIST_FIRST(&inp->sctp_asoc_list);
1136
0
  if (stcb == NULL) {
1137
0
    SCTP_INP_RUNLOCK(inp);
1138
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
1139
0
    return (ENOTCONN);
1140
0
  }
1141
0
  SCTP_TCB_LOCK(stcb);
1142
0
  asoc = &stcb->asoc;
1143
0
  if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) {
1144
    /* We are about to be freed, out of here */
1145
0
    SCTP_TCB_UNLOCK(stcb);
1146
0
    SCTP_INP_RUNLOCK(inp);
1147
0
    return (0);
1148
0
  }
1149
#if defined(__FreeBSD__) && !defined(__Userspace__)
1150
  NET_EPOCH_ENTER(et);
1151
#endif
1152
0
#if defined(__Userspace__)
1153
0
  if (((so->so_options & SCTP_SO_LINGER) && (so->so_linger == 0)) ||
1154
0
      (SCTP_SBAVAIL(&so->so_rcv) > 0)) {
1155
#else
1156
  if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
1157
      (SCTP_SBAVAIL(&so->so_rcv) > 0)) {
1158
#endif
1159
0
    if (SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_WAIT) {
1160
      /* Left with Data unread */
1161
0
      struct mbuf *op_err;
1162
1163
0
      op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
1164
0
      sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
1165
0
      SCTP_STAT_INCR_COUNTER32(sctps_aborted);
1166
0
    }
1167
0
    SCTP_INP_RUNLOCK(inp);
1168
0
    if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
1169
0
        (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1170
0
      SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1171
0
    }
1172
0
    (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
1173
0
                          SCTP_FROM_SCTP_USRREQ + SCTP_LOC_3);
1174
    /* No unlock tcb assoc is gone */
1175
#if defined(__FreeBSD__) && !defined(__Userspace__)
1176
    NET_EPOCH_EXIT(et);
1177
#endif
1178
0
    return (0);
1179
0
  }
1180
0
  if (TAILQ_EMPTY(&asoc->send_queue) &&
1181
0
      TAILQ_EMPTY(&asoc->sent_queue) &&
1182
0
      (asoc->stream_queue_cnt == 0)) {
1183
    /* there is nothing queued to send, so done */
1184
0
    if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete)(stcb, asoc)) {
1185
0
      goto abort_anyway;
1186
0
    }
1187
0
    if ((SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT) &&
1188
0
        (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
1189
      /* only send SHUTDOWN 1st time thru */
1190
0
      struct sctp_nets *netp;
1191
1192
0
      if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
1193
0
          (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1194
0
        SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1195
0
      }
1196
0
      SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
1197
0
      sctp_stop_timers_for_shutdown(stcb);
1198
0
      if (stcb->asoc.alternate) {
1199
0
        netp = stcb->asoc.alternate;
1200
0
      } else {
1201
0
        netp = stcb->asoc.primary_destination;
1202
0
      }
1203
0
      sctp_send_shutdown(stcb,netp);
1204
0
      sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
1205
0
                       stcb->sctp_ep, stcb, netp);
1206
0
      sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1207
0
                       stcb->sctp_ep, stcb, NULL);
1208
0
      sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
1209
0
    }
1210
0
  } else {
1211
    /*
1212
     * we still got (or just got) data to send,
1213
     * so set SHUTDOWN_PENDING
1214
     */
1215
    /*
1216
     * XXX sockets draft says that SCTP_EOF
1217
     * should be sent with no data. currently,
1218
     * we will allow user data to be sent first
1219
     * and move to SHUTDOWN-PENDING
1220
     */
1221
0
    SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING);
1222
0
    if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete)(stcb, asoc)) {
1223
0
      SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT);
1224
0
    }
1225
0
    if (TAILQ_EMPTY(&asoc->send_queue) &&
1226
0
        TAILQ_EMPTY(&asoc->sent_queue) &&
1227
0
        (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
1228
0
      struct mbuf *op_err;
1229
0
    abort_anyway:
1230
0
      op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
1231
0
      stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4;
1232
0
      sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
1233
0
      SCTP_STAT_INCR_COUNTER32(sctps_aborted);
1234
0
      if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
1235
0
          (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
1236
0
        SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1237
0
      }
1238
0
      SCTP_INP_RUNLOCK(inp);
1239
0
      (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
1240
0
                            SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5);
1241
#if defined(__FreeBSD__) && !defined(__Userspace__)
1242
      NET_EPOCH_EXIT(et);
1243
#endif
1244
0
      return (0);
1245
0
    } else {
1246
0
      sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
1247
0
    }
1248
0
  }
1249
0
  soisdisconnecting(so);
1250
#if defined(__FreeBSD__) && !defined(__Userspace__)
1251
  NET_EPOCH_EXIT(et);
1252
#endif
1253
0
  SCTP_TCB_UNLOCK(stcb);
1254
0
  SCTP_INP_RUNLOCK(inp);
1255
0
  return (0);
1256
0
}
1257
1258
#if defined(__FreeBSD__) || defined(_WIN32) || defined(__Userspace__)
1259
int
1260
sctp_flush(struct socket *so, int how)
1261
0
{
1262
#if defined(__FreeBSD__) && !defined(__Userspace__)
1263
  struct epoch_tracker et;
1264
#endif
1265
0
  struct sctp_tcb *stcb;
1266
0
  struct sctp_queued_to_read *control, *ncontrol;
1267
0
  struct sctp_inpcb *inp;
1268
0
  struct mbuf *m, *op_err;
1269
0
  bool need_to_abort = false;
1270
1271
  /*
1272
   * For 1-to-1 style sockets, flush the read queue and trigger an
1273
   * ungraceful shutdown of the association, if and only if user messages
1274
   * are lost. Loosing notifications does not need to be signalled to the
1275
   * peer.
1276
   */
1277
0
  if (how == PRU_FLUSH_WR) {
1278
    /* This function is only relevant for the read directions. */
1279
0
    return (0);
1280
0
  }
1281
0
  inp = (struct sctp_inpcb *)so->so_pcb;
1282
0
  if (inp == NULL) {
1283
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1284
0
    return (EINVAL);
1285
0
  }
1286
0
  SCTP_INP_WLOCK(inp);
1287
0
  if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
1288
    /* For 1-to-many style sockets this function does nothing. */
1289
0
    SCTP_INP_WUNLOCK(inp);
1290
0
    return (0);
1291
0
  }
1292
0
  stcb = LIST_FIRST(&inp->sctp_asoc_list);
1293
0
  if (stcb != NULL) {
1294
0
    SCTP_TCB_LOCK(stcb);
1295
0
  }
1296
0
  SCTP_INP_READ_LOCK(inp);
1297
0
  inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_CANT_READ;
1298
0
  SOCK_LOCK(so);
1299
0
  TAILQ_FOREACH_SAFE(control, &inp->read_queue, next, ncontrol) {
1300
0
    if ((control->spec_flags & M_NOTIFICATION) == 0) {
1301
0
      need_to_abort = true;
1302
0
    }
1303
0
    TAILQ_REMOVE(&inp->read_queue, control, next);
1304
0
    control->on_read_q = 0;
1305
0
    for (m = control->data; m; m = SCTP_BUF_NEXT(m)) {
1306
0
      sctp_sbfree(control, control->stcb, &so->so_rcv, m);
1307
0
    }
1308
0
    if (control->on_strm_q == 0) {
1309
0
      sctp_free_remote_addr(control->whoFrom);
1310
0
      if (control->data) {
1311
0
        sctp_m_freem(control->data);
1312
0
        control->data = NULL;
1313
0
      }
1314
0
      sctp_free_a_readq(stcb, control);
1315
0
    } else {
1316
0
      if (stcb != NULL) {
1317
0
        stcb->asoc.size_on_all_streams += control->length;
1318
0
      }
1319
0
    }
1320
0
  }
1321
0
  SOCK_UNLOCK(so);
1322
0
  SCTP_INP_READ_UNLOCK(inp);
1323
0
  if (need_to_abort && (stcb != NULL)) {
1324
0
    inp->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6;
1325
0
    SCTP_INP_WUNLOCK(inp);
1326
0
    op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
1327
#if defined(__FreeBSD__) && !defined(__Userspace__)
1328
    NET_EPOCH_ENTER(et);
1329
#endif
1330
0
    sctp_abort_an_association(inp, stcb, op_err, false, SCTP_SO_LOCKED);
1331
#if defined(__FreeBSD__) && !defined(__Userspace__)
1332
    NET_EPOCH_EXIT(et);
1333
#endif
1334
0
    return (ECONNABORTED);
1335
0
  }
1336
0
  if (stcb != NULL) {
1337
0
    SCTP_TCB_UNLOCK(stcb);
1338
0
  }
1339
0
  SCTP_INP_WUNLOCK(inp);
1340
0
  return (0);
1341
0
}
1342
#endif
1343
1344
int
1345
sctp_shutdown(struct socket *so)
1346
0
{
1347
0
  struct sctp_inpcb *inp;
1348
1349
0
  inp = (struct sctp_inpcb *)so->so_pcb;
1350
0
  if (inp == NULL) {
1351
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1352
0
    return (EINVAL);
1353
0
  }
1354
0
  SCTP_INP_RLOCK(inp);
1355
  /* For UDP model this is a invalid call */
1356
0
  if (!((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1357
0
        (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
1358
    /* Restore the flags that the soshutdown took away. */
1359
#if (defined(__FreeBSD__) || defined(_WIN32)) && !defined(__Userspace__)
1360
    SOCKBUF_LOCK(&so->so_rcv);
1361
    so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
1362
    SOCKBUF_UNLOCK(&so->so_rcv);
1363
#else
1364
0
    SOCK_LOCK(so);
1365
0
    so->so_state &= ~SS_CANTRCVMORE;
1366
0
    SOCK_UNLOCK(so);
1367
0
#endif
1368
    /* This proc will wakeup for read and do nothing (I hope) */
1369
0
    SCTP_INP_RUNLOCK(inp);
1370
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1371
0
    return (EOPNOTSUPP);
1372
0
  } else {
1373
    /*
1374
     * Ok, if we reach here its the TCP model and it is either
1375
     * a SHUT_WR or SHUT_RDWR.
1376
     * This means we put the shutdown flag against it.
1377
     */
1378
#if defined(__FreeBSD__) && !defined(__Userspace__)
1379
    struct epoch_tracker et;
1380
#endif
1381
0
    struct sctp_tcb *stcb;
1382
0
    struct sctp_association *asoc;
1383
0
    struct sctp_nets *netp;
1384
1385
0
    if ((so->so_state &
1386
0
         (SS_ISCONNECTED|SS_ISCONNECTING|SS_ISDISCONNECTING)) == 0) {
1387
0
      SCTP_INP_RUNLOCK(inp);
1388
0
      return (ENOTCONN);
1389
0
    }
1390
0
    socantsendmore(so);
1391
1392
0
    stcb = LIST_FIRST(&inp->sctp_asoc_list);
1393
0
    if (stcb == NULL) {
1394
      /*
1395
       * Ok, we hit the case that the shutdown call was
1396
       * made after an abort or something. Nothing to do
1397
       * now.
1398
       */
1399
0
      SCTP_INP_RUNLOCK(inp);
1400
0
      return (0);
1401
0
    }
1402
0
    SCTP_TCB_LOCK(stcb);
1403
0
    asoc = &stcb->asoc;
1404
0
    if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) {
1405
0
      SCTP_TCB_UNLOCK(stcb);
1406
0
      SCTP_INP_RUNLOCK(inp);
1407
0
      return (0);
1408
0
    }
1409
0
    if ((SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_WAIT) &&
1410
0
        (SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_ECHOED) &&
1411
0
        (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN)) {
1412
      /* If we are not in or before ESTABLISHED, there is
1413
       * no protocol action required.
1414
       */
1415
0
      SCTP_TCB_UNLOCK(stcb);
1416
0
      SCTP_INP_RUNLOCK(inp);
1417
0
      return (0);
1418
0
    }
1419
#if defined(__FreeBSD__) && !defined(__Userspace__)
1420
    NET_EPOCH_ENTER(et);
1421
#endif
1422
0
    if (stcb->asoc.alternate) {
1423
0
      netp = stcb->asoc.alternate;
1424
0
    } else {
1425
0
      netp = stcb->asoc.primary_destination;
1426
0
    }
1427
0
    if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) &&
1428
0
        TAILQ_EMPTY(&asoc->send_queue) &&
1429
0
        TAILQ_EMPTY(&asoc->sent_queue) &&
1430
0
        (asoc->stream_queue_cnt == 0)) {
1431
0
      if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete)(stcb, asoc)) {
1432
0
        goto abort_anyway;
1433
0
      }
1434
      /* there is nothing queued to send, so I'm done... */
1435
0
      SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1436
0
      SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
1437
0
      sctp_stop_timers_for_shutdown(stcb);
1438
0
      sctp_send_shutdown(stcb, netp);
1439
0
      sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
1440
0
                       stcb->sctp_ep, stcb, netp);
1441
0
      sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1442
0
                       stcb->sctp_ep, stcb, NULL);
1443
0
    } else {
1444
      /*
1445
       * We still got (or just got) data to send, so set
1446
       * SHUTDOWN_PENDING.
1447
       */
1448
0
      SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING);
1449
0
      if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete)(stcb, asoc)) {
1450
0
        SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT);
1451
0
      }
1452
0
      if (TAILQ_EMPTY(&asoc->send_queue) &&
1453
0
          TAILQ_EMPTY(&asoc->sent_queue) &&
1454
0
          (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
1455
0
        struct mbuf *op_err;
1456
0
      abort_anyway:
1457
0
        op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
1458
0
        stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6;
1459
0
        SCTP_INP_RUNLOCK(inp);
1460
0
        sctp_abort_an_association(stcb->sctp_ep, stcb,
1461
0
                                  op_err, false, SCTP_SO_LOCKED);
1462
#if defined(__FreeBSD__) && !defined(__Userspace__)
1463
        NET_EPOCH_EXIT(et);
1464
#endif
1465
0
        return (0);
1466
0
      }
1467
0
    }
1468
    /* XXX: Why do this in the case where we have still data queued? */
1469
0
    sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
1470
0
    SCTP_TCB_UNLOCK(stcb);
1471
0
    SCTP_INP_RUNLOCK(inp);
1472
#if defined(__FreeBSD__) && !defined(__Userspace__)
1473
    NET_EPOCH_EXIT(et);
1474
#endif
1475
0
    return (0);
1476
0
  }
1477
0
}
1478
1479
/*
1480
 * copies a "user" presentable address and removes embedded scope, etc.
1481
 * returns 0 on success, 1 on error
1482
 */
1483
static uint32_t
1484
sctp_fill_user_address(struct sockaddr *dst, struct sockaddr *src)
1485
0
{
1486
0
#ifdef INET6
1487
#if defined(SCTP_EMBEDDED_V6_SCOPE)
1488
  struct sockaddr_in6 lsa6;
1489
1490
  src = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)src,
1491
      &lsa6);
1492
#endif
1493
0
#endif
1494
#ifdef HAVE_SA_LEN
1495
  memcpy(dst, src, src->sa_len);
1496
#else
1497
0
  switch (src->sa_family) {
1498
0
#ifdef INET
1499
0
  case AF_INET:
1500
0
    memcpy(dst, src, sizeof(struct sockaddr_in));
1501
0
    break;
1502
0
#endif
1503
0
#ifdef INET6
1504
0
  case AF_INET6:
1505
0
    memcpy(dst, src, sizeof(struct sockaddr_in6));
1506
0
    break;
1507
0
#endif
1508
0
#if defined(__Userspace__)
1509
0
  case AF_CONN:
1510
0
    memcpy(dst, src, sizeof(struct sockaddr_conn));
1511
0
    break;
1512
0
#endif
1513
0
  default:
1514
    /* TSNH */
1515
0
    break;
1516
0
  }
1517
0
#endif
1518
0
  return (0);
1519
0
}
1520
1521
static size_t
1522
sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
1523
                           struct sctp_tcb *stcb,
1524
                           size_t limit,
1525
                           struct sockaddr *addr,
1526
                           uint32_t vrf_id)
1527
0
{
1528
0
  struct sctp_ifn *sctp_ifn;
1529
0
  struct sctp_ifa *sctp_ifa;
1530
0
  size_t actual;
1531
0
  int loopback_scope;
1532
0
#if defined(INET)
1533
0
  int ipv4_local_scope, ipv4_addr_legal;
1534
0
#endif
1535
0
#if defined(INET6)
1536
0
  int local_scope, site_scope, ipv6_addr_legal;
1537
0
#endif
1538
0
#if defined(__Userspace__)
1539
0
  int conn_addr_legal;
1540
0
#endif
1541
0
  struct sctp_vrf *vrf;
1542
1543
0
  SCTP_IPI_ADDR_LOCK_ASSERT();
1544
0
  actual = 0;
1545
0
  if (limit == 0)
1546
0
    return (actual);
1547
1548
0
  if (stcb) {
1549
    /* Turn on all the appropriate scope */
1550
0
    loopback_scope = stcb->asoc.scope.loopback_scope;
1551
0
#if defined(INET)
1552
0
    ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
1553
0
    ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
1554
0
#endif
1555
0
#if defined(INET6)
1556
0
    local_scope = stcb->asoc.scope.local_scope;
1557
0
    site_scope = stcb->asoc.scope.site_scope;
1558
0
    ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
1559
0
#endif
1560
0
#if defined(__Userspace__)
1561
0
    conn_addr_legal = stcb->asoc.scope.conn_addr_legal;
1562
0
#endif
1563
0
  } else {
1564
    /* Use generic values for endpoints. */
1565
0
    loopback_scope = 1;
1566
0
#if defined(INET)
1567
0
    ipv4_local_scope = 1;
1568
0
#endif
1569
0
#if defined(INET6)
1570
0
    local_scope = 1;
1571
0
    site_scope = 1;
1572
0
#endif
1573
0
    if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1574
0
#if defined(INET6)
1575
0
      ipv6_addr_legal = 1;
1576
0
#endif
1577
0
#if defined(INET)
1578
0
      if (SCTP_IPV6_V6ONLY(inp)) {
1579
0
        ipv4_addr_legal = 0;
1580
0
      } else {
1581
0
        ipv4_addr_legal = 1;
1582
0
      }
1583
0
#endif
1584
0
#if defined(__Userspace__)
1585
0
      conn_addr_legal = 0;
1586
0
#endif
1587
0
    } else {
1588
0
#if defined(INET6)
1589
0
      ipv6_addr_legal = 0;
1590
0
#endif
1591
0
#if defined(__Userspace__)
1592
0
      if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) {
1593
0
        conn_addr_legal = 1;
1594
0
#if defined(INET)
1595
0
        ipv4_addr_legal = 0;
1596
0
#endif
1597
0
      } else {
1598
0
        conn_addr_legal = 0;
1599
0
#if defined(INET)
1600
0
        ipv4_addr_legal = 1;
1601
0
#endif
1602
0
      }
1603
#else
1604
#if defined(INET)
1605
      ipv4_addr_legal = 1;
1606
#endif
1607
#endif
1608
0
    }
1609
0
  }
1610
0
  vrf = sctp_find_vrf(vrf_id);
1611
0
  if (vrf == NULL) {
1612
0
    return (0);
1613
0
  }
1614
0
  if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1615
0
    LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1616
0
      if ((loopback_scope == 0) &&
1617
0
          SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
1618
        /* Skip loopback if loopback_scope not set */
1619
0
        continue;
1620
0
      }
1621
0
      LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1622
0
        if (stcb) {
1623
          /*
1624
           * For the BOUND-ALL case, the list
1625
           * associated with a TCB is Always
1626
           * considered a reverse list.. i.e.
1627
           * it lists addresses that are NOT
1628
           * part of the association. If this
1629
           * is one of those we must skip it.
1630
           */
1631
0
          if (sctp_is_addr_restricted(stcb,
1632
0
                                      sctp_ifa)) {
1633
0
            continue;
1634
0
          }
1635
0
        }
1636
0
        switch (sctp_ifa->address.sa.sa_family) {
1637
0
#ifdef INET
1638
0
        case AF_INET:
1639
0
          if (ipv4_addr_legal) {
1640
0
            struct sockaddr_in *sin;
1641
1642
0
            sin = &sctp_ifa->address.sin;
1643
0
            if (sin->sin_addr.s_addr == 0) {
1644
              /*
1645
               * we skip unspecified
1646
               * addresses
1647
               */
1648
0
              continue;
1649
0
            }
1650
#if defined(__FreeBSD__) && !defined(__Userspace__)
1651
            if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
1652
                                 &sin->sin_addr) != 0) {
1653
              continue;
1654
            }
1655
#endif
1656
0
            if ((ipv4_local_scope == 0) &&
1657
0
                (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
1658
0
              continue;
1659
0
            }
1660
0
#ifdef INET6
1661
0
            if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
1662
0
              if (actual + sizeof(struct sockaddr_in6) > limit) {
1663
0
                return (actual);
1664
0
              }
1665
0
              in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)addr);
1666
0
              ((struct sockaddr_in6 *)addr)->sin6_port = inp->sctp_lport;
1667
0
              addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in6));
1668
0
              actual += sizeof(struct sockaddr_in6);
1669
0
            } else {
1670
0
#endif
1671
0
              if (actual + sizeof(struct sockaddr_in) > limit) {
1672
0
                return (actual);
1673
0
              }
1674
0
              memcpy(addr, sin, sizeof(struct sockaddr_in));
1675
0
              ((struct sockaddr_in *)addr)->sin_port = inp->sctp_lport;
1676
0
              addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in));
1677
0
              actual += sizeof(struct sockaddr_in);
1678
0
#ifdef INET6
1679
0
            }
1680
0
#endif
1681
0
          } else {
1682
0
            continue;
1683
0
          }
1684
0
          break;
1685
0
#endif
1686
0
#ifdef INET6
1687
0
        case AF_INET6:
1688
0
          if (ipv6_addr_legal) {
1689
0
            struct sockaddr_in6 *sin6;
1690
1691
#if defined(SCTP_EMBEDDED_V6_SCOPE) && !defined(SCTP_KAME)
1692
            struct sockaddr_in6 lsa6;
1693
#endif
1694
0
            sin6 = &sctp_ifa->address.sin6;
1695
0
            if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1696
              /*
1697
               * we skip unspecified
1698
               * addresses
1699
               */
1700
0
              continue;
1701
0
            }
1702
#if defined(__FreeBSD__) && !defined(__Userspace__)
1703
            if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
1704
                                 &sin6->sin6_addr) != 0) {
1705
              continue;
1706
            }
1707
#endif
1708
0
            if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1709
0
              if (local_scope == 0)
1710
0
                continue;
1711
#if defined(SCTP_EMBEDDED_V6_SCOPE)
1712
              if (sin6->sin6_scope_id == 0) {
1713
#ifdef SCTP_KAME
1714
                if (sa6_recoverscope(sin6) != 0)
1715
                  /*
1716
                   * bad link
1717
                   * local
1718
                   * address
1719
                   */
1720
                  continue;
1721
#else
1722
                lsa6 = *sin6;
1723
                if (in6_recoverscope(&lsa6,
1724
                         &lsa6.sin6_addr,
1725
                         NULL))
1726
                  /*
1727
                   * bad link
1728
                   * local
1729
                   * address
1730
                   */
1731
                continue;
1732
                sin6 = &lsa6;
1733
#endif        /* SCTP_KAME */
1734
              }
1735
#endif /* SCTP_EMBEDDED_V6_SCOPE */
1736
0
            }
1737
0
            if ((site_scope == 0) &&
1738
0
                (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
1739
0
              continue;
1740
0
            }
1741
0
            if (actual + sizeof(struct sockaddr_in6) > limit) {
1742
0
              return (actual);
1743
0
            }
1744
0
            memcpy(addr, sin6, sizeof(struct sockaddr_in6));
1745
0
            ((struct sockaddr_in6 *)addr)->sin6_port = inp->sctp_lport;
1746
0
            addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in6));
1747
0
            actual += sizeof(struct sockaddr_in6);
1748
0
          } else {
1749
0
            continue;
1750
0
          }
1751
0
          break;
1752
0
#endif
1753
0
#if defined(__Userspace__)
1754
0
        case AF_CONN:
1755
0
          if (conn_addr_legal) {
1756
0
            if (actual + sizeof(struct sockaddr_conn) > limit) {
1757
0
              return (actual);
1758
0
            }
1759
0
            memcpy(addr, &sctp_ifa->address.sconn, sizeof(struct sockaddr_conn));
1760
0
            ((struct sockaddr_conn *)addr)->sconn_port = inp->sctp_lport;
1761
0
            addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_conn));
1762
0
            actual += sizeof(struct sockaddr_conn);
1763
0
          } else {
1764
0
            continue;
1765
0
          }
1766
0
#endif
1767
0
        default:
1768
          /* TSNH */
1769
0
          break;
1770
0
        }
1771
0
      }
1772
0
    }
1773
0
  } else {
1774
0
    struct sctp_laddr *laddr;
1775
0
    size_t sa_len;
1776
1777
0
    LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1778
0
      if (stcb) {
1779
0
        if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
1780
0
          continue;
1781
0
        }
1782
0
      }
1783
#ifdef HAVE_SA_LEN
1784
      sa_len = laddr->ifa->address.sa.sa_len;
1785
#else
1786
0
      switch (laddr->ifa->address.sa.sa_family) {
1787
0
#ifdef INET
1788
0
      case AF_INET:
1789
0
        sa_len = sizeof(struct sockaddr_in);
1790
0
        break;
1791
0
#endif
1792
0
#ifdef INET6
1793
0
      case AF_INET6:
1794
0
        sa_len = sizeof(struct sockaddr_in6);
1795
0
        break;
1796
0
#endif
1797
0
#if defined(__Userspace__)
1798
0
      case AF_CONN:
1799
0
        sa_len = sizeof(struct sockaddr_conn);
1800
0
        break;
1801
0
#endif
1802
0
      default:
1803
        /* TSNH */
1804
0
        sa_len = 0;
1805
0
        break;
1806
0
      }
1807
0
#endif
1808
0
      if (actual + sa_len > limit) {
1809
0
        return (actual);
1810
0
      }
1811
0
      if (sctp_fill_user_address(addr, &laddr->ifa->address.sa))
1812
0
        continue;
1813
0
      switch (laddr->ifa->address.sa.sa_family) {
1814
0
#ifdef INET
1815
0
      case AF_INET:
1816
0
        ((struct sockaddr_in *)addr)->sin_port = inp->sctp_lport;
1817
0
        break;
1818
0
#endif
1819
0
#ifdef INET6
1820
0
      case AF_INET6:
1821
0
        ((struct sockaddr_in6 *)addr)->sin6_port = inp->sctp_lport;
1822
0
        break;
1823
0
#endif
1824
0
#if defined(__Userspace__)
1825
0
      case AF_CONN:
1826
0
        ((struct sockaddr_conn *)addr)->sconn_port = inp->sctp_lport;
1827
0
        break;
1828
0
#endif
1829
0
      default:
1830
        /* TSNH */
1831
0
        break;
1832
0
      }
1833
0
      addr = (struct sockaddr *)((caddr_t)addr + sa_len);
1834
0
      actual += sa_len;
1835
0
    }
1836
0
  }
1837
0
  return (actual);
1838
0
}
1839
1840
static size_t
1841
sctp_fill_up_addresses(struct sctp_inpcb *inp,
1842
                       struct sctp_tcb *stcb,
1843
                       size_t limit,
1844
                       struct sockaddr *addr)
1845
0
{
1846
0
  size_t size;
1847
#ifdef SCTP_MVRF
1848
  uint32_t id;
1849
#endif
1850
1851
0
  SCTP_IPI_ADDR_RLOCK();
1852
#ifdef SCTP_MVRF
1853
/*
1854
 * FIX ME: ?? this WILL report duplicate addresses if they appear
1855
 * in more than one VRF.
1856
 */
1857
  /* fill up addresses for all VRFs on the endpoint */
1858
  size = 0;
1859
  for (id = 0; (id < inp->num_vrfs) && (size < limit); id++) {
1860
    size += sctp_fill_up_addresses_vrf(inp, stcb, limit, addr,
1861
                                       inp->m_vrf_ids[id]);
1862
    addr = (struct sockaddr *)((caddr_t)addr + size);
1863
  }
1864
#else
1865
  /* fill up addresses for the endpoint's default vrf */
1866
0
  size = sctp_fill_up_addresses_vrf(inp, stcb, limit, addr,
1867
0
                                    inp->def_vrf_id);
1868
0
#endif
1869
0
  SCTP_IPI_ADDR_RUNLOCK();
1870
0
  return (size);
1871
0
}
1872
1873
static size_t
1874
sctp_max_size_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
1875
0
{
1876
0
  struct sctp_vrf *vrf;
1877
0
  size_t size;
1878
1879
  /*
1880
   * In both sub-set bound an bound_all cases we return the size of
1881
   * the maximum number of addresses that you could get. In reality
1882
   * the sub-set bound may have an exclusion list for a given TCB or
1883
   * in the bound-all case a TCB may NOT include the loopback or other
1884
   * addresses as well.
1885
   */
1886
0
  SCTP_IPI_ADDR_LOCK_ASSERT();
1887
0
  vrf = sctp_find_vrf(vrf_id);
1888
0
  if (vrf == NULL) {
1889
0
    return (0);
1890
0
  }
1891
0
  size = 0;
1892
0
  if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1893
0
    struct sctp_ifn *sctp_ifn;
1894
0
    struct sctp_ifa *sctp_ifa;
1895
1896
0
    LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1897
0
      LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1898
        /* Count them if they are the right type */
1899
0
        switch (sctp_ifa->address.sa.sa_family) {
1900
0
#ifdef INET
1901
0
        case AF_INET:
1902
0
#ifdef INET6
1903
0
          if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1904
0
            size += sizeof(struct sockaddr_in6);
1905
0
          else
1906
0
            size += sizeof(struct sockaddr_in);
1907
#else
1908
          size += sizeof(struct sockaddr_in);
1909
#endif
1910
0
          break;
1911
0
#endif
1912
0
#ifdef INET6
1913
0
        case AF_INET6:
1914
0
          size += sizeof(struct sockaddr_in6);
1915
0
          break;
1916
0
#endif
1917
0
#if defined(__Userspace__)
1918
0
        case AF_CONN:
1919
0
          size += sizeof(struct sockaddr_conn);
1920
0
          break;
1921
0
#endif
1922
0
        default:
1923
0
          break;
1924
0
        }
1925
0
      }
1926
0
    }
1927
0
  } else {
1928
0
    struct sctp_laddr *laddr;
1929
1930
0
    LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1931
0
      switch (laddr->ifa->address.sa.sa_family) {
1932
0
#ifdef INET
1933
0
      case AF_INET:
1934
0
#ifdef INET6
1935
0
        if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1936
0
          size += sizeof(struct sockaddr_in6);
1937
0
        else
1938
0
          size += sizeof(struct sockaddr_in);
1939
#else
1940
        size += sizeof(struct sockaddr_in);
1941
#endif
1942
0
        break;
1943
0
#endif
1944
0
#ifdef INET6
1945
0
      case AF_INET6:
1946
0
        size += sizeof(struct sockaddr_in6);
1947
0
        break;
1948
0
#endif
1949
0
#if defined(__Userspace__)
1950
0
      case AF_CONN:
1951
0
        size += sizeof(struct sockaddr_conn);
1952
0
        break;
1953
0
#endif
1954
0
      default:
1955
0
        break;
1956
0
      }
1957
0
    }
1958
0
  }
1959
0
  return (size);
1960
0
}
1961
1962
static size_t
1963
sctp_max_size_addresses(struct sctp_inpcb *inp)
1964
0
{
1965
0
  size_t size;
1966
#ifdef SCTP_MVRF
1967
  int id;
1968
#endif
1969
1970
0
  SCTP_IPI_ADDR_RLOCK();
1971
#ifdef SCTP_MVRF
1972
/*
1973
 * FIX ME: ?? this WILL count duplicate addresses if they appear
1974
 * in more than one VRF.
1975
 */
1976
  /* Maximum size of all addresses for all VRFs on the endpoint */
1977
  size = 0;
1978
  for (id = 0; id < inp->num_vrfs; id++) {
1979
    size += sctp_max_size_addresses_vrf(inp, inp->m_vrf_ids[id]);
1980
  }
1981
#else
1982
  /* Maximum size of all addresses for the endpoint's default VRF */
1983
0
  size = sctp_max_size_addresses_vrf(inp, inp->def_vrf_id);
1984
0
#endif
1985
0
  SCTP_IPI_ADDR_RUNLOCK();
1986
0
  return (size);
1987
0
}
1988
1989
static int
1990
sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
1991
      size_t optsize, void *p, int delay)
1992
0
{
1993
0
  int error;
1994
0
  int creat_lock_on = 0;
1995
0
  struct sctp_tcb *stcb = NULL;
1996
0
  struct sockaddr *sa;
1997
0
  unsigned int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
1998
0
  uint32_t vrf_id;
1999
0
  sctp_assoc_t *a_id;
2000
2001
0
  SCTPDBG(SCTP_DEBUG_PCB1, "Connectx called\n");
2002
2003
0
  if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
2004
0
      (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
2005
    /* We are already connected AND the TCP model */
2006
0
    SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
2007
0
    return (EADDRINUSE);
2008
0
  }
2009
2010
0
  if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
2011
0
      (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
2012
0
    SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2013
0
    return (EINVAL);
2014
0
  }
2015
2016
0
  if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
2017
0
    SCTP_INP_RLOCK(inp);
2018
0
    stcb = LIST_FIRST(&inp->sctp_asoc_list);
2019
0
    SCTP_INP_RUNLOCK(inp);
2020
0
  }
2021
0
  if (stcb) {
2022
0
    SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
2023
0
    return (EALREADY);
2024
0
  }
2025
0
  SCTP_INP_INCR_REF(inp);
2026
0
  SCTP_ASOC_CREATE_LOCK(inp);
2027
0
  creat_lock_on = 1;
2028
0
  if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
2029
0
      (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
2030
0
    SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
2031
0
    error = EFAULT;
2032
0
    goto out_now;
2033
0
  }
2034
0
  totaddrp = (unsigned int *)optval;
2035
0
  totaddr = *totaddrp;
2036
0
  sa = (struct sockaddr *)(totaddrp + 1);
2037
0
  error = sctp_connectx_helper_find(inp, sa, totaddr, &num_v4, &num_v6, (unsigned int)(optsize - sizeof(int)));
2038
0
  if (error != 0) {
2039
    /* Already have or am bring up an association */
2040
0
    SCTP_ASOC_CREATE_UNLOCK(inp);
2041
0
    creat_lock_on = 0;
2042
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2043
0
    goto out_now;
2044
0
  }
2045
0
#ifdef INET6
2046
0
  if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
2047
0
      (num_v6 > 0)) {
2048
0
    error = EINVAL;
2049
0
    goto out_now;
2050
0
  }
2051
0
  if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
2052
0
      (num_v4 > 0)) {
2053
0
    if (SCTP_IPV6_V6ONLY(inp)) {
2054
      /*
2055
       * if IPV6_V6ONLY flag, ignore connections destined
2056
       * to a v4 addr or v4-mapped addr
2057
       */
2058
0
      SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2059
0
      error = EINVAL;
2060
0
      goto out_now;
2061
0
    }
2062
0
  }
2063
0
#endif        /* INET6 */
2064
0
  if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
2065
    /* Bind a ephemeral port */
2066
0
    error = sctp_inpcb_bind(so, NULL, NULL, p);
2067
0
    if (error) {
2068
0
      goto out_now;
2069
0
    }
2070
0
  }
2071
2072
  /* FIX ME: do we want to pass in a vrf on the connect call? */
2073
0
  vrf_id = inp->def_vrf_id;
2074
2075
  /* We are GOOD to go */
2076
0
  stcb = sctp_aloc_assoc_connected(inp, sa, &error, 0, 0, vrf_id,
2077
0
                                   inp->sctp_ep.pre_open_stream_count,
2078
0
                                   inp->sctp_ep.port,
2079
#if defined(__FreeBSD__) && !defined(__Userspace__)
2080
                                   (struct thread *)p,
2081
#elif defined(_WIN32) && !defined(__Userspace__)
2082
                                   (PKTHREAD)p,
2083
#else
2084
0
                                   (struct proc *)p,
2085
0
#endif
2086
0
                                   SCTP_INITIALIZE_AUTH_PARAMS);
2087
0
  if (stcb == NULL) {
2088
    /* Gak! no memory */
2089
0
    goto out_now;
2090
0
  }
2091
0
  SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
2092
  /* move to second address */
2093
0
  switch (sa->sa_family) {
2094
0
#ifdef INET
2095
0
  case AF_INET:
2096
0
    sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
2097
0
    break;
2098
0
#endif
2099
0
#ifdef INET6
2100
0
  case AF_INET6:
2101
0
    sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
2102
0
    break;
2103
0
#endif
2104
0
  default:
2105
0
    break;
2106
0
  }
2107
2108
0
  error = 0;
2109
0
  sctp_connectx_helper_add(stcb, sa, (totaddr-1), &error);
2110
  /* Fill in the return id */
2111
0
  if (error) {
2112
0
    goto out_now;
2113
0
  }
2114
0
  a_id = (sctp_assoc_t *)optval;
2115
0
  *a_id = sctp_get_associd(stcb);
2116
2117
0
  if (delay) {
2118
    /* doing delayed connection */
2119
0
    stcb->asoc.delayed_connection = 1;
2120
0
    sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
2121
0
  } else {
2122
0
    (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
2123
0
    sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
2124
0
  }
2125
0
  SCTP_TCB_UNLOCK(stcb);
2126
0
 out_now:
2127
0
  if (creat_lock_on) {
2128
0
    SCTP_ASOC_CREATE_UNLOCK(inp);
2129
0
  }
2130
0
  SCTP_INP_DECR_REF(inp);
2131
0
  return (error);
2132
0
}
2133
2134
167k
#define SCTP_FIND_STCB(inp, stcb, assoc_id) { \
2135
167k
  if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||\
2136
167k
      (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { \
2137
167k
    SCTP_INP_RLOCK(inp); \
2138
167k
    stcb = LIST_FIRST(&inp->sctp_asoc_list); \
2139
167k
    if (stcb) { \
2140
2.19k
      SCTP_TCB_LOCK(stcb); \
2141
2.19k
    } \
2142
167k
    SCTP_INP_RUNLOCK(inp); \
2143
167k
  } else if (assoc_id > SCTP_ALL_ASSOC) { \
2144
0
    stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
2145
0
    if (stcb == NULL) { \
2146
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \
2147
0
      error = ENOENT; \
2148
0
      break; \
2149
0
    } \
2150
0
  } else { \
2151
0
    stcb = NULL; \
2152
0
  } \
2153
167k
}
2154
2155
230k
#define SCTP_CHECK_AND_CAST(destp, srcp, type, size) {\
2156
230k
  if (size < sizeof(type)) { \
2157
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); \
2158
0
    error = EINVAL; \
2159
0
    break; \
2160
230k
  } else { \
2161
230k
    destp = (type *)srcp; \
2162
230k
  } \
2163
230k
}
2164
2165
#if defined(__Userspace__)
2166
int
2167
#else
2168
static int
2169
#endif
2170
sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
2171
0
      void *p) {
2172
0
  struct sctp_inpcb *inp = NULL;
2173
0
  int error, val = 0;
2174
0
  struct sctp_tcb *stcb = NULL;
2175
2176
0
  if (optval == NULL) {
2177
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2178
0
    return (EINVAL);
2179
0
  }
2180
2181
0
  inp = (struct sctp_inpcb *)so->so_pcb;
2182
0
  if (inp == NULL) {
2183
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2184
0
    return EINVAL;
2185
0
  }
2186
0
  error = 0;
2187
2188
0
  switch (optname) {
2189
0
  case SCTP_NODELAY:
2190
0
  case SCTP_AUTOCLOSE:
2191
0
  case SCTP_EXPLICIT_EOR:
2192
0
  case SCTP_AUTO_ASCONF:
2193
0
  case SCTP_DISABLE_FRAGMENTS:
2194
0
  case SCTP_I_WANT_MAPPED_V4_ADDR:
2195
0
  case SCTP_USE_EXT_RCVINFO:
2196
0
    SCTP_INP_RLOCK(inp);
2197
0
    switch (optname) {
2198
0
    case SCTP_DISABLE_FRAGMENTS:
2199
0
      val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT);
2200
0
      break;
2201
0
    case SCTP_I_WANT_MAPPED_V4_ADDR:
2202
0
      val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4);
2203
0
      break;
2204
0
    case SCTP_AUTO_ASCONF:
2205
0
      if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
2206
        /* only valid for bound all sockets */
2207
0
        val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
2208
0
      } else {
2209
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2210
0
        error = EINVAL;
2211
0
        goto flags_out;
2212
0
      }
2213
0
      break;
2214
0
    case SCTP_EXPLICIT_EOR:
2215
0
      val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
2216
0
      break;
2217
0
    case SCTP_NODELAY:
2218
0
      val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY);
2219
0
      break;
2220
0
    case SCTP_USE_EXT_RCVINFO:
2221
0
      val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO);
2222
0
      break;
2223
0
    case SCTP_AUTOCLOSE:
2224
0
      if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))
2225
0
        val = sctp_ticks_to_secs(inp->sctp_ep.auto_close_time);
2226
0
      else
2227
0
        val = 0;
2228
0
      break;
2229
2230
0
    default:
2231
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
2232
0
      error = ENOPROTOOPT;
2233
0
    } /* end switch (sopt->sopt_name) */
2234
0
    if (*optsize < sizeof(val)) {
2235
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2236
0
      error = EINVAL;
2237
0
    }
2238
0
  flags_out:
2239
0
    SCTP_INP_RUNLOCK(inp);
2240
0
    if (error == 0) {
2241
      /* return the option value */
2242
0
      *(int *)optval = val;
2243
0
      *optsize = sizeof(val);
2244
0
    }
2245
0
    break;
2246
0
        case SCTP_GET_PACKET_LOG:
2247
0
  {
2248
#ifdef  SCTP_PACKET_LOGGING
2249
    uint8_t *target;
2250
    int ret;
2251
2252
    SCTP_CHECK_AND_CAST(target, optval, uint8_t, *optsize);
2253
    ret = sctp_copy_out_packet_log(target , (int)*optsize);
2254
    *optsize = ret;
2255
#else
2256
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
2257
0
    error = EOPNOTSUPP;
2258
0
#endif
2259
0
    break;
2260
0
  }
2261
0
  case SCTP_REUSE_PORT:
2262
0
  {
2263
0
    uint32_t *value;
2264
2265
0
    if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
2266
      /* Can't do this for a 1-m socket */
2267
0
      error = EINVAL;
2268
0
      break;
2269
0
    }
2270
0
    SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2271
0
    *value = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
2272
0
    *optsize = sizeof(uint32_t);
2273
0
    break;
2274
0
  }
2275
0
  case SCTP_PARTIAL_DELIVERY_POINT:
2276
0
  {
2277
0
    uint32_t *value;
2278
2279
0
    SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2280
0
    *value = inp->partial_delivery_point;
2281
0
    *optsize = sizeof(uint32_t);
2282
0
    break;
2283
0
  }
2284
0
  case SCTP_FRAGMENT_INTERLEAVE:
2285
0
  {
2286
0
    uint32_t *value;
2287
2288
0
    SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2289
0
    if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) {
2290
0
      if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) {
2291
0
        *value = SCTP_FRAG_LEVEL_2;
2292
0
      } else {
2293
0
        *value = SCTP_FRAG_LEVEL_1;
2294
0
      }
2295
0
    } else {
2296
0
      *value = SCTP_FRAG_LEVEL_0;
2297
0
    }
2298
0
    *optsize = sizeof(uint32_t);
2299
0
    break;
2300
0
  }
2301
0
  case SCTP_INTERLEAVING_SUPPORTED:
2302
0
  {
2303
0
    struct sctp_assoc_value *av;
2304
2305
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2306
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2307
2308
0
    if (stcb) {
2309
0
      av->assoc_value = stcb->asoc.idata_supported;
2310
0
      SCTP_TCB_UNLOCK(stcb);
2311
0
    } else {
2312
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2313
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2314
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2315
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
2316
0
        SCTP_INP_RLOCK(inp);
2317
0
        if (inp->idata_supported) {
2318
0
          av->assoc_value = 1;
2319
0
        } else {
2320
0
          av->assoc_value = 0;
2321
0
        }
2322
0
        SCTP_INP_RUNLOCK(inp);
2323
0
      } else {
2324
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2325
0
        error = EINVAL;
2326
0
      }
2327
0
    }
2328
0
    if (error == 0) {
2329
0
      *optsize = sizeof(struct sctp_assoc_value);
2330
0
    }
2331
0
    break;
2332
0
  }
2333
0
  case SCTP_CMT_ON_OFF:
2334
0
  {
2335
0
    struct sctp_assoc_value *av;
2336
2337
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2338
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2339
0
    if (stcb) {
2340
0
      av->assoc_value = stcb->asoc.sctp_cmt_on_off;
2341
0
      SCTP_TCB_UNLOCK(stcb);
2342
0
    } else {
2343
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2344
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2345
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2346
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
2347
0
        SCTP_INP_RLOCK(inp);
2348
0
        av->assoc_value = inp->sctp_cmt_on_off;
2349
0
        SCTP_INP_RUNLOCK(inp);
2350
0
      } else {
2351
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2352
0
        error = EINVAL;
2353
0
      }
2354
0
    }
2355
0
    if (error == 0) {
2356
0
      *optsize = sizeof(struct sctp_assoc_value);
2357
0
    }
2358
0
    break;
2359
0
  }
2360
0
  case SCTP_PLUGGABLE_CC:
2361
0
  {
2362
0
    struct sctp_assoc_value *av;
2363
2364
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2365
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2366
0
    if (stcb) {
2367
0
      av->assoc_value = stcb->asoc.congestion_control_module;
2368
0
      SCTP_TCB_UNLOCK(stcb);
2369
0
    } else {
2370
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2371
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2372
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2373
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
2374
0
        SCTP_INP_RLOCK(inp);
2375
0
        av->assoc_value = inp->sctp_ep.sctp_default_cc_module;
2376
0
        SCTP_INP_RUNLOCK(inp);
2377
0
      } else {
2378
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2379
0
        error = EINVAL;
2380
0
      }
2381
0
    }
2382
0
    if (error == 0) {
2383
0
      *optsize = sizeof(struct sctp_assoc_value);
2384
0
    }
2385
0
    break;
2386
0
  }
2387
0
  case SCTP_CC_OPTION:
2388
0
  {
2389
0
    struct sctp_cc_option *cc_opt;
2390
2391
0
    SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, *optsize);
2392
0
    SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
2393
0
    if (stcb == NULL) {
2394
0
      error = EINVAL;
2395
0
    } else {
2396
0
      if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
2397
0
        error = ENOTSUP;
2398
0
      } else {
2399
0
        error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 0, cc_opt);
2400
0
        *optsize = sizeof(struct sctp_cc_option);
2401
0
      }
2402
0
      SCTP_TCB_UNLOCK(stcb);
2403
0
    }
2404
0
    break;
2405
0
  }
2406
0
  case SCTP_STREAM_SCHEDULER:
2407
0
  {
2408
0
    struct sctp_assoc_value *av;
2409
2410
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2411
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2412
0
    if (stcb) {
2413
0
      av->assoc_value = stcb->asoc.stream_scheduling_module;
2414
0
      SCTP_TCB_UNLOCK(stcb);
2415
0
    } else {
2416
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2417
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2418
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2419
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
2420
0
        SCTP_INP_RLOCK(inp);
2421
0
        av->assoc_value = inp->sctp_ep.sctp_default_ss_module;
2422
0
        SCTP_INP_RUNLOCK(inp);
2423
0
      } else {
2424
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2425
0
        error = EINVAL;
2426
0
      }
2427
0
    }
2428
0
    if (error == 0) {
2429
0
      *optsize = sizeof(struct sctp_assoc_value);
2430
0
    }
2431
0
    break;
2432
0
  }
2433
0
  case SCTP_STREAM_SCHEDULER_VALUE:
2434
0
  {
2435
0
    struct sctp_stream_value *av;
2436
2437
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, *optsize);
2438
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2439
0
    if (stcb) {
2440
0
      if ((av->stream_id >= stcb->asoc.streamoutcnt) ||
2441
0
          (stcb->asoc.ss_functions.sctp_ss_get_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
2442
0
                                                     &av->stream_value) < 0)) {
2443
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2444
0
        error = EINVAL;
2445
0
      } else {
2446
0
        *optsize = sizeof(struct sctp_stream_value);
2447
0
      }
2448
0
      SCTP_TCB_UNLOCK(stcb);
2449
0
    } else {
2450
      /* Can't get stream value without association */
2451
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2452
0
      error = EINVAL;
2453
0
    }
2454
0
    break;
2455
0
  }
2456
0
  case SCTP_GET_ADDR_LEN:
2457
0
  {
2458
0
    struct sctp_assoc_value *av;
2459
2460
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2461
0
    error = EINVAL;
2462
0
#ifdef INET
2463
0
    if (av->assoc_value == AF_INET) {
2464
0
      av->assoc_value = sizeof(struct sockaddr_in);
2465
0
      error = 0;
2466
0
    }
2467
0
#endif
2468
0
#ifdef INET6
2469
0
    if (av->assoc_value == AF_INET6) {
2470
0
      av->assoc_value = sizeof(struct sockaddr_in6);
2471
0
      error = 0;
2472
0
    }
2473
0
#endif
2474
0
#if defined(__Userspace__)
2475
0
    if (av->assoc_value == AF_CONN) {
2476
0
      av->assoc_value = sizeof(struct sockaddr_conn);
2477
0
      error = 0;
2478
0
    }
2479
0
#endif
2480
0
    if (error) {
2481
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2482
0
    } else {
2483
0
      *optsize = sizeof(struct sctp_assoc_value);
2484
0
    }
2485
0
    break;
2486
0
  }
2487
0
  case SCTP_GET_ASSOC_NUMBER:
2488
0
  {
2489
0
    uint32_t *value, cnt;
2490
2491
0
    SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2492
0
    SCTP_INP_RLOCK(inp);
2493
0
    if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2494
0
        (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
2495
      /* Can't do this for a 1-1 socket */
2496
0
      error = EINVAL;
2497
0
      SCTP_INP_RUNLOCK(inp);
2498
0
      break;
2499
0
    }
2500
0
    cnt = 0;
2501
0
    LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
2502
0
      cnt++;
2503
0
    }
2504
0
    SCTP_INP_RUNLOCK(inp);
2505
0
    *value = cnt;
2506
0
    *optsize = sizeof(uint32_t);
2507
0
    break;
2508
0
  }
2509
0
  case SCTP_GET_ASSOC_ID_LIST:
2510
0
  {
2511
0
    struct sctp_assoc_ids *ids;
2512
0
    uint32_t at;
2513
0
    size_t limit;
2514
2515
0
    SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
2516
0
    SCTP_INP_RLOCK(inp);
2517
0
    if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2518
0
        (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
2519
      /* Can't do this for a 1-1 socket */
2520
0
      error = EINVAL;
2521
0
      SCTP_INP_RUNLOCK(inp);
2522
0
      break;
2523
0
    }
2524
0
    at = 0;
2525
0
    limit = (*optsize - sizeof(uint32_t)) / sizeof(sctp_assoc_t);
2526
0
    LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
2527
0
      if (at < limit) {
2528
0
        ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
2529
0
        if (at == 0) {
2530
0
          error = EINVAL;
2531
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2532
0
          break;
2533
0
        }
2534
0
      } else {
2535
0
        error = EINVAL;
2536
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2537
0
        break;
2538
0
      }
2539
0
    }
2540
0
    SCTP_INP_RUNLOCK(inp);
2541
0
    if (error == 0) {
2542
0
      ids->gaids_number_of_ids = at;
2543
0
      *optsize = ((at * sizeof(sctp_assoc_t)) + sizeof(uint32_t));
2544
0
    }
2545
0
    break;
2546
0
  }
2547
0
  case SCTP_CONTEXT:
2548
0
  {
2549
0
    struct sctp_assoc_value *av;
2550
2551
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2552
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2553
2554
0
    if (stcb) {
2555
0
      av->assoc_value = stcb->asoc.context;
2556
0
      SCTP_TCB_UNLOCK(stcb);
2557
0
    } else {
2558
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2559
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2560
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2561
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
2562
0
        SCTP_INP_RLOCK(inp);
2563
0
        av->assoc_value = inp->sctp_context;
2564
0
        SCTP_INP_RUNLOCK(inp);
2565
0
      } else {
2566
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2567
0
        error = EINVAL;
2568
0
      }
2569
0
    }
2570
0
    if (error == 0) {
2571
0
      *optsize = sizeof(struct sctp_assoc_value);
2572
0
    }
2573
0
    break;
2574
0
  }
2575
0
  case SCTP_VRF_ID:
2576
0
  {
2577
0
    uint32_t *default_vrfid;
2578
2579
0
    SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, *optsize);
2580
0
    *default_vrfid = inp->def_vrf_id;
2581
0
    *optsize = sizeof(uint32_t);
2582
0
    break;
2583
0
  }
2584
0
  case SCTP_GET_ASOC_VRF:
2585
0
  {
2586
0
    struct sctp_assoc_value *id;
2587
2588
0
    SCTP_CHECK_AND_CAST(id, optval, struct sctp_assoc_value, *optsize);
2589
0
    SCTP_FIND_STCB(inp, stcb, id->assoc_id);
2590
0
    if (stcb == NULL) {
2591
0
      error = EINVAL;
2592
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2593
0
    } else {
2594
0
      id->assoc_value = stcb->asoc.vrf_id;
2595
0
      SCTP_TCB_UNLOCK(stcb);
2596
0
      *optsize = sizeof(struct sctp_assoc_value);
2597
0
    }
2598
0
    break;
2599
0
  }
2600
0
  case SCTP_GET_VRF_IDS:
2601
0
  {
2602
#ifdef SCTP_MVRF
2603
    int siz_needed;
2604
    uint32_t *vrf_ids;
2605
2606
    SCTP_CHECK_AND_CAST(vrf_ids, optval, uint32_t, *optsize);
2607
    siz_needed = inp->num_vrfs * sizeof(uint32_t);
2608
    if (*optsize < siz_needed) {
2609
      error = EINVAL;
2610
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2611
    } else {
2612
      memcpy(vrf_ids, inp->m_vrf_ids, siz_needed);
2613
      *optsize = siz_needed;
2614
    }
2615
#else
2616
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
2617
0
    error = EOPNOTSUPP;
2618
0
#endif
2619
0
    break;
2620
0
  }
2621
0
  case SCTP_GET_NONCE_VALUES:
2622
0
  {
2623
0
    struct sctp_get_nonce_values *gnv;
2624
2625
0
    SCTP_CHECK_AND_CAST(gnv, optval, struct sctp_get_nonce_values, *optsize);
2626
0
    SCTP_FIND_STCB(inp, stcb, gnv->gn_assoc_id);
2627
2628
0
    if (stcb) {
2629
0
      gnv->gn_peers_tag = stcb->asoc.peer_vtag;
2630
0
      gnv->gn_local_tag = stcb->asoc.my_vtag;
2631
0
      SCTP_TCB_UNLOCK(stcb);
2632
0
      *optsize = sizeof(struct sctp_get_nonce_values);
2633
0
    } else {
2634
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2635
0
      error = ENOTCONN;
2636
0
    }
2637
0
    break;
2638
0
  }
2639
0
  case SCTP_DELAYED_SACK:
2640
0
  {
2641
0
    struct sctp_sack_info *sack;
2642
2643
0
    SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, *optsize);
2644
0
    SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
2645
0
    if (stcb) {
2646
0
      sack->sack_delay = stcb->asoc.delayed_ack;
2647
0
      sack->sack_freq = stcb->asoc.sack_freq;
2648
0
      SCTP_TCB_UNLOCK(stcb);
2649
0
    } else {
2650
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2651
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2652
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2653
0
           (sack->sack_assoc_id == SCTP_FUTURE_ASSOC))) {
2654
0
        SCTP_INP_RLOCK(inp);
2655
0
        sack->sack_delay = sctp_ticks_to_msecs(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
2656
0
        sack->sack_freq = inp->sctp_ep.sctp_sack_freq;
2657
0
        SCTP_INP_RUNLOCK(inp);
2658
0
      } else {
2659
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2660
0
        error = EINVAL;
2661
0
      }
2662
0
    }
2663
0
    if (error == 0) {
2664
0
      *optsize = sizeof(struct sctp_sack_info);
2665
0
    }
2666
0
    break;
2667
0
  }
2668
0
  case SCTP_GET_SNDBUF_USE:
2669
0
  {
2670
0
    struct sctp_sockstat *ss;
2671
2672
0
    SCTP_CHECK_AND_CAST(ss, optval, struct sctp_sockstat, *optsize);
2673
0
    SCTP_FIND_STCB(inp, stcb, ss->ss_assoc_id);
2674
2675
0
    if (stcb) {
2676
0
      ss->ss_total_sndbuf = stcb->asoc.total_output_queue_size;
2677
0
      ss->ss_total_recv_buf = (stcb->asoc.size_on_reasm_queue +
2678
0
             stcb->asoc.size_on_all_streams);
2679
0
      SCTP_TCB_UNLOCK(stcb);
2680
0
      *optsize = sizeof(struct sctp_sockstat);
2681
0
    } else {
2682
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2683
0
      error = ENOTCONN;
2684
0
    }
2685
0
    break;
2686
0
  }
2687
0
  case SCTP_MAX_BURST:
2688
0
  {
2689
0
    struct sctp_assoc_value *av;
2690
2691
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2692
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2693
2694
0
    if (stcb) {
2695
0
      av->assoc_value = stcb->asoc.max_burst;
2696
0
      SCTP_TCB_UNLOCK(stcb);
2697
0
    } else {
2698
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2699
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2700
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2701
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
2702
0
        SCTP_INP_RLOCK(inp);
2703
0
        av->assoc_value = inp->sctp_ep.max_burst;
2704
0
        SCTP_INP_RUNLOCK(inp);
2705
0
      } else {
2706
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2707
0
        error = EINVAL;
2708
0
      }
2709
0
    }
2710
0
    if (error == 0) {
2711
0
      *optsize = sizeof(struct sctp_assoc_value);
2712
0
    }
2713
0
    break;
2714
0
  }
2715
0
  case SCTP_MAXSEG:
2716
0
  {
2717
0
    struct sctp_assoc_value *av;
2718
2719
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2720
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2721
2722
0
    if (stcb) {
2723
0
      av->assoc_value = stcb->asoc.sctp_frag_point;
2724
0
      SCTP_TCB_UNLOCK(stcb);
2725
0
    } else {
2726
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2727
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2728
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2729
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
2730
0
        SCTP_INP_RLOCK(inp);
2731
0
        av->assoc_value = inp->sctp_frag_point;
2732
0
        SCTP_INP_RUNLOCK(inp);
2733
0
      } else {
2734
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2735
0
        error = EINVAL;
2736
0
      }
2737
0
    }
2738
0
    if (error == 0) {
2739
0
      *optsize = sizeof(struct sctp_assoc_value);
2740
0
    }
2741
0
    break;
2742
0
  }
2743
0
  case SCTP_GET_STAT_LOG:
2744
0
    error = sctp_fill_stat_log(optval, optsize);
2745
0
    break;
2746
0
  case SCTP_EVENTS:
2747
0
  {
2748
0
    struct sctp_event_subscribe *events;
2749
2750
0
    SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, *optsize);
2751
0
    memset(events, 0, sizeof(struct sctp_event_subscribe));
2752
0
    SCTP_INP_RLOCK(inp);
2753
0
    if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT))
2754
0
      events->sctp_data_io_event = 1;
2755
2756
0
    if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT))
2757
0
      events->sctp_association_event = 1;
2758
2759
0
    if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT))
2760
0
      events->sctp_address_event = 1;
2761
2762
0
    if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
2763
0
      events->sctp_send_failure_event = 1;
2764
2765
0
    if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR))
2766
0
      events->sctp_peer_error_event = 1;
2767
2768
0
    if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
2769
0
      events->sctp_shutdown_event = 1;
2770
2771
0
    if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT))
2772
0
      events->sctp_partial_delivery_event = 1;
2773
2774
0
    if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT))
2775
0
      events->sctp_adaptation_layer_event = 1;
2776
2777
0
    if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT))
2778
0
      events->sctp_authentication_event = 1;
2779
2780
0
    if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT))
2781
0
      events->sctp_sender_dry_event = 1;
2782
2783
0
    if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT))
2784
0
      events->sctp_stream_reset_event = 1;
2785
0
    SCTP_INP_RUNLOCK(inp);
2786
0
    *optsize = sizeof(struct sctp_event_subscribe);
2787
0
    break;
2788
0
  }
2789
0
  case SCTP_ADAPTATION_LAYER:
2790
0
  {
2791
0
    uint32_t *value;
2792
2793
0
    SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2794
2795
0
    SCTP_INP_RLOCK(inp);
2796
0
    *value = inp->sctp_ep.adaptation_layer_indicator;
2797
0
    SCTP_INP_RUNLOCK(inp);
2798
0
    *optsize = sizeof(uint32_t);
2799
0
    break;
2800
0
  }
2801
0
  case SCTP_SET_INITIAL_DBG_SEQ:
2802
0
  {
2803
0
    uint32_t *value;
2804
2805
0
    SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2806
0
    SCTP_INP_RLOCK(inp);
2807
0
    *value = inp->sctp_ep.initial_sequence_debug;
2808
0
    SCTP_INP_RUNLOCK(inp);
2809
0
    *optsize = sizeof(uint32_t);
2810
0
    break;
2811
0
  }
2812
0
  case SCTP_GET_LOCAL_ADDR_SIZE:
2813
0
  {
2814
0
    uint32_t *value;
2815
2816
0
    SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2817
0
    SCTP_INP_RLOCK(inp);
2818
0
    *value = (uint32_t)sctp_max_size_addresses(inp);
2819
0
    SCTP_INP_RUNLOCK(inp);
2820
0
    *optsize = sizeof(uint32_t);
2821
0
    break;
2822
0
  }
2823
0
  case SCTP_GET_REMOTE_ADDR_SIZE:
2824
0
  {
2825
0
    uint32_t *value;
2826
0
    struct sctp_nets *net;
2827
0
    size_t size;
2828
2829
0
    SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2830
    /* FIXME MT: change to sctp_assoc_value? */
2831
0
    SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t)*value);
2832
2833
0
    if (stcb != NULL) {
2834
0
      size = 0;
2835
      /* Count the sizes */
2836
0
      TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2837
0
        switch (net->ro._l_addr.sa.sa_family) {
2838
0
#ifdef INET
2839
0
        case AF_INET:
2840
0
#ifdef INET6
2841
0
          if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2842
0
            size += sizeof(struct sockaddr_in6);
2843
0
          } else {
2844
0
            size += sizeof(struct sockaddr_in);
2845
0
          }
2846
#else
2847
          size += sizeof(struct sockaddr_in);
2848
#endif
2849
0
          break;
2850
0
#endif
2851
0
#ifdef INET6
2852
0
        case AF_INET6:
2853
0
          size += sizeof(struct sockaddr_in6);
2854
0
          break;
2855
0
#endif
2856
0
#if defined(__Userspace__)
2857
0
        case AF_CONN:
2858
0
          size += sizeof(struct sockaddr_conn);
2859
0
          break;
2860
0
#endif
2861
0
        default:
2862
0
          break;
2863
0
        }
2864
0
      }
2865
0
      SCTP_TCB_UNLOCK(stcb);
2866
0
      *value = (uint32_t)size;
2867
0
      *optsize = sizeof(uint32_t);
2868
0
    } else {
2869
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2870
0
          ((sctp_assoc_t)*value <= SCTP_ALL_ASSOC)) {
2871
0
        error = EINVAL;
2872
0
      } else {
2873
0
        error = ENOENT;
2874
0
      }
2875
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2876
0
    }
2877
0
    break;
2878
0
  }
2879
0
  case SCTP_GET_PEER_ADDRESSES:
2880
    /*
2881
     * Get the address information, an array is passed in to
2882
     * fill up we pack it.
2883
     */
2884
0
  {
2885
0
    size_t cpsz, left;
2886
0
    struct sockaddr *addr;
2887
0
    struct sctp_nets *net;
2888
0
    struct sctp_getaddresses *saddr;
2889
2890
0
    SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2891
0
    SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2892
2893
0
    if (stcb != NULL) {
2894
0
      left = *optsize - offsetof(struct sctp_getaddresses, addr);
2895
0
      *optsize = offsetof(struct sctp_getaddresses, addr);
2896
0
      addr = &saddr->addr[0].sa;
2897
2898
0
      TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2899
0
        switch (net->ro._l_addr.sa.sa_family) {
2900
0
#ifdef INET
2901
0
        case AF_INET:
2902
0
#ifdef INET6
2903
0
          if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2904
0
            cpsz = sizeof(struct sockaddr_in6);
2905
0
          } else {
2906
0
            cpsz = sizeof(struct sockaddr_in);
2907
0
          }
2908
#else
2909
          cpsz = sizeof(struct sockaddr_in);
2910
#endif
2911
0
          break;
2912
0
#endif
2913
0
#ifdef INET6
2914
0
        case AF_INET6:
2915
0
          cpsz = sizeof(struct sockaddr_in6);
2916
0
          break;
2917
0
#endif
2918
0
#if defined(__Userspace__)
2919
0
        case AF_CONN:
2920
0
          cpsz = sizeof(struct sockaddr_conn);
2921
0
          break;
2922
0
#endif
2923
0
        default:
2924
0
          cpsz = 0;
2925
0
          break;
2926
0
        }
2927
0
        if (cpsz == 0) {
2928
0
          break;
2929
0
        }
2930
0
        if (left < cpsz) {
2931
          /* not enough room. */
2932
0
          break;
2933
0
        }
2934
0
#if defined(INET) && defined(INET6)
2935
0
        if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
2936
0
            (net->ro._l_addr.sa.sa_family == AF_INET)) {
2937
          /* Must map the address */
2938
0
          in6_sin_2_v4mapsin6(&net->ro._l_addr.sin,
2939
0
                              (struct sockaddr_in6 *)addr);
2940
0
        } else {
2941
0
          memcpy(addr, &net->ro._l_addr, cpsz);
2942
0
        }
2943
#else
2944
        memcpy(addr, &net->ro._l_addr, cpsz);
2945
#endif
2946
0
        ((struct sockaddr_in *)addr)->sin_port = stcb->rport;
2947
2948
0
        addr = (struct sockaddr *)((caddr_t)addr + cpsz);
2949
0
        left -= cpsz;
2950
0
        *optsize += cpsz;
2951
0
      }
2952
0
      SCTP_TCB_UNLOCK(stcb);
2953
0
    } else {
2954
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2955
0
          (saddr->sget_assoc_id <= SCTP_ALL_ASSOC)) {
2956
0
        error = EINVAL;
2957
0
      } else {
2958
0
        error = ENOENT;
2959
0
      }
2960
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2961
0
    }
2962
0
    break;
2963
0
  }
2964
0
  case SCTP_GET_LOCAL_ADDRESSES:
2965
0
  {
2966
0
    size_t limit, actual;
2967
0
    struct sctp_getaddresses *saddr;
2968
2969
0
    SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2970
0
    SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2971
2972
0
    if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2973
0
        ((saddr->sget_assoc_id == SCTP_CURRENT_ASSOC) ||
2974
0
         (saddr->sget_assoc_id == SCTP_ALL_ASSOC))) {
2975
0
      error = EINVAL;
2976
0
    } else {
2977
0
      limit = *optsize - offsetof(struct sctp_getaddresses, addr);
2978
0
      actual = sctp_fill_up_addresses(inp, stcb, limit, &saddr->addr[0].sa);
2979
0
      *optsize = offsetof(struct sctp_getaddresses, addr) + actual;
2980
0
    }
2981
0
    if (stcb != NULL) {
2982
0
      SCTP_TCB_UNLOCK(stcb);
2983
0
    }
2984
0
    break;
2985
0
  }
2986
0
  case SCTP_PEER_ADDR_PARAMS:
2987
0
  {
2988
0
    struct sctp_paddrparams *paddrp;
2989
0
    struct sctp_nets *net;
2990
0
    struct sockaddr *addr;
2991
0
#if defined(INET) && defined(INET6)
2992
0
    struct sockaddr_in sin_store;
2993
0
#endif
2994
2995
0
    SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, *optsize);
2996
0
    SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
2997
2998
0
#if defined(INET) && defined(INET6)
2999
0
    if (paddrp->spp_address.ss_family == AF_INET6) {
3000
0
      struct sockaddr_in6 *sin6;
3001
3002
0
      sin6 = (struct sockaddr_in6 *)&paddrp->spp_address;
3003
0
      if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
3004
0
        in6_sin6_2_sin(&sin_store, sin6);
3005
0
        addr = (struct sockaddr *)&sin_store;
3006
0
      } else {
3007
0
        addr = (struct sockaddr *)&paddrp->spp_address;
3008
0
      }
3009
0
    } else {
3010
0
      addr = (struct sockaddr *)&paddrp->spp_address;
3011
0
    }
3012
#else
3013
    addr = (struct sockaddr *)&paddrp->spp_address;
3014
#endif
3015
0
    if (stcb != NULL) {
3016
0
      net = sctp_findnet(stcb, addr);
3017
0
    } else {
3018
      /* We increment here since sctp_findassociation_ep_addr() wil
3019
       * do a decrement if it finds the stcb as long as the locked
3020
       * tcb (last argument) is NOT a TCB.. aka NULL.
3021
       */
3022
0
      net = NULL;
3023
0
      SCTP_INP_INCR_REF(inp);
3024
0
      stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
3025
0
      if (stcb == NULL) {
3026
0
        SCTP_INP_DECR_REF(inp);
3027
0
      }
3028
0
    }
3029
0
    if ((stcb != NULL) && (net == NULL)) {
3030
0
#ifdef INET
3031
0
      if (addr->sa_family == AF_INET) {
3032
0
        struct sockaddr_in *sin;
3033
3034
0
        sin = (struct sockaddr_in *)addr;
3035
0
        if (sin->sin_addr.s_addr != INADDR_ANY) {
3036
0
          error = EINVAL;
3037
0
          SCTP_TCB_UNLOCK(stcb);
3038
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3039
0
          break;
3040
0
        }
3041
0
      } else
3042
0
#endif
3043
0
#ifdef INET6
3044
0
      if (addr->sa_family == AF_INET6) {
3045
0
        struct sockaddr_in6 *sin6;
3046
3047
0
        sin6 = (struct sockaddr_in6 *)addr;
3048
0
        if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3049
0
          error = EINVAL;
3050
0
          SCTP_TCB_UNLOCK(stcb);
3051
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3052
0
          break;
3053
0
        }
3054
0
      } else
3055
0
#endif
3056
0
#if defined(__Userspace__)
3057
0
      if (addr->sa_family == AF_CONN) {
3058
0
        struct sockaddr_conn *sconn;
3059
3060
0
        sconn = (struct sockaddr_conn *)addr;
3061
0
        if (sconn->sconn_addr != NULL) {
3062
0
          error = EINVAL;
3063
0
          SCTP_TCB_UNLOCK(stcb);
3064
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3065
0
          break;
3066
0
        }
3067
0
      } else
3068
0
#endif
3069
0
      {
3070
0
        error = EAFNOSUPPORT;
3071
0
        SCTP_TCB_UNLOCK(stcb);
3072
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3073
0
        break;
3074
0
      }
3075
0
    }
3076
3077
0
    if (stcb != NULL) {
3078
      /* Applies to the specific association */
3079
0
      paddrp->spp_flags = 0;
3080
0
      if (net != NULL) {
3081
0
        paddrp->spp_hbinterval = net->heart_beat_delay;
3082
0
        paddrp->spp_pathmaxrxt = net->failure_threshold;
3083
0
        paddrp->spp_pathmtu = net->mtu;
3084
0
        switch (net->ro._l_addr.sa.sa_family) {
3085
0
#ifdef INET
3086
0
        case AF_INET:
3087
0
          paddrp->spp_pathmtu -= SCTP_MIN_V4_OVERHEAD;
3088
0
          break;
3089
0
#endif
3090
0
#ifdef INET6
3091
0
        case AF_INET6:
3092
0
          paddrp->spp_pathmtu -= SCTP_MIN_OVERHEAD;
3093
0
          break;
3094
0
#endif
3095
0
#if defined(__Userspace__)
3096
0
        case AF_CONN:
3097
0
          paddrp->spp_pathmtu -= sizeof(struct sctphdr);
3098
0
          break;
3099
0
#endif
3100
0
        default:
3101
0
          break;
3102
0
        }
3103
        /* get flags for HB */
3104
0
        if (net->dest_state & SCTP_ADDR_NOHB) {
3105
0
          paddrp->spp_flags |= SPP_HB_DISABLE;
3106
0
        } else {
3107
0
          paddrp->spp_flags |= SPP_HB_ENABLE;
3108
0
        }
3109
        /* get flags for PMTU */
3110
0
        if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
3111
0
          paddrp->spp_flags |= SPP_PMTUD_DISABLE;
3112
0
        } else {
3113
0
          paddrp->spp_flags |= SPP_PMTUD_ENABLE;
3114
0
        }
3115
0
        if (net->dscp & 0x01) {
3116
0
          paddrp->spp_dscp = net->dscp & 0xfc;
3117
0
          paddrp->spp_flags |= SPP_DSCP;
3118
0
        }
3119
0
#ifdef INET6
3120
0
        if ((net->ro._l_addr.sa.sa_family == AF_INET6) &&
3121
0
            (net->flowlabel & 0x80000000)) {
3122
0
          paddrp->spp_ipv6_flowlabel = net->flowlabel & 0x000fffff;
3123
0
          paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
3124
0
        }
3125
0
#endif
3126
0
      } else {
3127
        /*
3128
         * No destination so return default
3129
         * value
3130
         */
3131
0
        paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
3132
0
        paddrp->spp_pathmtu = stcb->asoc.default_mtu;
3133
0
        if (stcb->asoc.default_dscp & 0x01) {
3134
0
          paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc;
3135
0
          paddrp->spp_flags |= SPP_DSCP;
3136
0
        }
3137
0
#ifdef INET6
3138
0
        if (stcb->asoc.default_flowlabel & 0x80000000) {
3139
0
          paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel & 0x000fffff;
3140
0
          paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
3141
0
        }
3142
0
#endif
3143
        /* default settings should be these */
3144
0
        if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
3145
0
          paddrp->spp_flags |= SPP_HB_DISABLE;
3146
0
        } else {
3147
0
          paddrp->spp_flags |= SPP_HB_ENABLE;
3148
0
        }
3149
0
        if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
3150
0
          paddrp->spp_flags |= SPP_PMTUD_DISABLE;
3151
0
        } else {
3152
0
          paddrp->spp_flags |= SPP_PMTUD_ENABLE;
3153
0
        }
3154
0
        paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
3155
0
      }
3156
0
      paddrp->spp_assoc_id = sctp_get_associd(stcb);
3157
0
      SCTP_TCB_UNLOCK(stcb);
3158
0
    } else {
3159
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3160
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3161
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3162
0
           (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC))) {
3163
        /* Use endpoint defaults */
3164
0
        SCTP_INP_RLOCK(inp);
3165
0
        paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
3166
0
        paddrp->spp_hbinterval = sctp_ticks_to_msecs(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
3167
0
        paddrp->spp_assoc_id = SCTP_FUTURE_ASSOC;
3168
        /* get inp's default */
3169
0
        if (inp->sctp_ep.default_dscp & 0x01) {
3170
0
          paddrp->spp_dscp = inp->sctp_ep.default_dscp & 0xfc;
3171
0
          paddrp->spp_flags |= SPP_DSCP;
3172
0
        }
3173
0
#ifdef INET6
3174
0
        if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
3175
0
            (inp->sctp_ep.default_flowlabel & 0x80000000)) {
3176
0
          paddrp->spp_ipv6_flowlabel = inp->sctp_ep.default_flowlabel & 0x000fffff;
3177
0
          paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
3178
0
        }
3179
0
#endif
3180
0
        paddrp->spp_pathmtu = inp->sctp_ep.default_mtu;
3181
3182
0
        if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
3183
0
          paddrp->spp_flags |= SPP_HB_ENABLE;
3184
0
        } else {
3185
0
          paddrp->spp_flags |= SPP_HB_DISABLE;
3186
0
        }
3187
0
        if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
3188
0
          paddrp->spp_flags |= SPP_PMTUD_ENABLE;
3189
0
        } else {
3190
0
          paddrp->spp_flags |= SPP_PMTUD_DISABLE;
3191
0
        }
3192
0
        SCTP_INP_RUNLOCK(inp);
3193
0
      } else {
3194
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3195
0
        error = EINVAL;
3196
0
      }
3197
0
    }
3198
0
    if (error == 0) {
3199
0
      *optsize = sizeof(struct sctp_paddrparams);
3200
0
    }
3201
0
    break;
3202
0
  }
3203
0
  case SCTP_GET_PEER_ADDR_INFO:
3204
0
  {
3205
0
    struct sctp_paddrinfo *paddri;
3206
0
    struct sctp_nets *net;
3207
0
    struct sockaddr *addr;
3208
0
#if defined(INET) && defined(INET6)
3209
0
    struct sockaddr_in sin_store;
3210
0
#endif
3211
3212
0
    SCTP_CHECK_AND_CAST(paddri, optval, struct sctp_paddrinfo, *optsize);
3213
0
    SCTP_FIND_STCB(inp, stcb, paddri->spinfo_assoc_id);
3214
3215
0
#if defined(INET) && defined(INET6)
3216
0
    if (paddri->spinfo_address.ss_family == AF_INET6) {
3217
0
      struct sockaddr_in6 *sin6;
3218
3219
0
      sin6 = (struct sockaddr_in6 *)&paddri->spinfo_address;
3220
0
      if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
3221
0
        in6_sin6_2_sin(&sin_store, sin6);
3222
0
        addr = (struct sockaddr *)&sin_store;
3223
0
      } else {
3224
0
        addr = (struct sockaddr *)&paddri->spinfo_address;
3225
0
      }
3226
0
    } else {
3227
0
      addr = (struct sockaddr *)&paddri->spinfo_address;
3228
0
    }
3229
#else
3230
    addr = (struct sockaddr *)&paddri->spinfo_address;
3231
#endif
3232
0
    if (stcb != NULL) {
3233
0
      net = sctp_findnet(stcb, addr);
3234
0
    } else {
3235
      /* We increment here since sctp_findassociation_ep_addr() wil
3236
       * do a decrement if it finds the stcb as long as the locked
3237
       * tcb (last argument) is NOT a TCB.. aka NULL.
3238
       */
3239
0
      net = NULL;
3240
0
      SCTP_INP_INCR_REF(inp);
3241
0
      stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
3242
0
      if (stcb == NULL) {
3243
0
        SCTP_INP_DECR_REF(inp);
3244
0
      }
3245
0
    }
3246
3247
0
    if ((stcb != NULL) && (net != NULL)) {
3248
0
      if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
3249
        /* It's unconfirmed */
3250
0
        paddri->spinfo_state = SCTP_UNCONFIRMED;
3251
0
      } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
3252
        /* It's active */
3253
0
        paddri->spinfo_state = SCTP_ACTIVE;
3254
0
      } else {
3255
        /* It's inactive */
3256
0
        paddri->spinfo_state = SCTP_INACTIVE;
3257
0
      }
3258
0
      paddri->spinfo_cwnd = net->cwnd;
3259
0
      paddri->spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
3260
0
      paddri->spinfo_rto = net->RTO;
3261
0
      paddri->spinfo_assoc_id = sctp_get_associd(stcb);
3262
0
      paddri->spinfo_mtu = net->mtu;
3263
0
      switch (addr->sa_family) {
3264
0
#if defined(INET)
3265
0
      case AF_INET:
3266
0
        paddri->spinfo_mtu -= SCTP_MIN_V4_OVERHEAD;
3267
0
        break;
3268
0
#endif
3269
0
#if defined(INET6)
3270
0
      case AF_INET6:
3271
0
        paddri->spinfo_mtu -= SCTP_MIN_OVERHEAD;
3272
0
        break;
3273
0
#endif
3274
0
#if defined(__Userspace__)
3275
0
      case AF_CONN:
3276
0
        paddri->spinfo_mtu -= sizeof(struct sctphdr);
3277
0
        break;
3278
0
#endif
3279
0
      default:
3280
0
        break;
3281
0
      }
3282
0
      SCTP_TCB_UNLOCK(stcb);
3283
0
      *optsize = sizeof(struct sctp_paddrinfo);
3284
0
    } else {
3285
0
      if (stcb != NULL) {
3286
0
        SCTP_TCB_UNLOCK(stcb);
3287
0
      }
3288
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
3289
0
      error = ENOENT;
3290
0
    }
3291
0
    break;
3292
0
  }
3293
0
  case SCTP_PCB_STATUS:
3294
0
  {
3295
0
    struct sctp_pcbinfo *spcb;
3296
3297
0
    SCTP_CHECK_AND_CAST(spcb, optval, struct sctp_pcbinfo, *optsize);
3298
0
    sctp_fill_pcbinfo(spcb);
3299
0
    *optsize = sizeof(struct sctp_pcbinfo);
3300
0
    break;
3301
0
  }
3302
0
  case SCTP_STATUS:
3303
0
  {
3304
0
    struct sctp_nets *net;
3305
0
    struct sctp_status *sstat;
3306
3307
0
    SCTP_CHECK_AND_CAST(sstat, optval, struct sctp_status, *optsize);
3308
0
    SCTP_FIND_STCB(inp, stcb, sstat->sstat_assoc_id);
3309
3310
0
    if (stcb == NULL) {
3311
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3312
0
      error = EINVAL;
3313
0
      break;
3314
0
    }
3315
0
    sstat->sstat_state = sctp_map_assoc_state(stcb->asoc.state);
3316
0
    sstat->sstat_assoc_id = sctp_get_associd(stcb);
3317
0
    sstat->sstat_rwnd = stcb->asoc.peers_rwnd;
3318
0
    sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt;
3319
    /*
3320
     * We can't include chunks that have been passed to
3321
     * the socket layer. Only things in queue.
3322
     */
3323
0
    sstat->sstat_penddata = (stcb->asoc.cnt_on_reasm_queue +
3324
0
           stcb->asoc.cnt_on_all_streams);
3325
0
    sstat->sstat_instrms = stcb->asoc.streamincnt;
3326
0
    sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
3327
0
    sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb);
3328
0
    net = stcb->asoc.primary_destination;
3329
0
    if (net != NULL) {
3330
#ifdef HAVE_SA_LEN
3331
      memcpy(&sstat->sstat_primary.spinfo_address,
3332
             &net->ro._l_addr,
3333
             ((struct sockaddr *)(&net->ro._l_addr))->sa_len);
3334
#else
3335
0
      switch (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family) {
3336
0
#if defined(INET)
3337
0
      case AF_INET:
3338
0
        memcpy(&sstat->sstat_primary.spinfo_address,
3339
0
               &net->ro._l_addr,
3340
0
               sizeof(struct sockaddr_in));
3341
0
        break;
3342
0
#endif
3343
0
#if defined(INET6)
3344
0
      case AF_INET6:
3345
0
        memcpy(&sstat->sstat_primary.spinfo_address,
3346
0
               &net->ro._l_addr,
3347
0
               sizeof(struct sockaddr_in6));
3348
0
        break;
3349
0
#endif
3350
0
#if defined(__Userspace__)
3351
0
      case AF_CONN:
3352
0
        memcpy(&sstat->sstat_primary.spinfo_address,
3353
0
               &net->ro._l_addr,
3354
0
               sizeof(struct sockaddr_conn));
3355
0
        break;
3356
0
#endif
3357
0
      default:
3358
0
        break;
3359
0
      }
3360
0
#endif
3361
0
      ((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
3362
      /*
3363
       * Again the user can get info from sctp_constants.h
3364
       * for what the state of the network is.
3365
       */
3366
0
      if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
3367
        /* It's unconfirmed */
3368
0
        sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
3369
0
      } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
3370
        /* It's active */
3371
0
        sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
3372
0
      } else {
3373
        /* It's inactive */
3374
0
        sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
3375
0
      }
3376
0
      sstat->sstat_primary.spinfo_cwnd = net->cwnd;
3377
0
      sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
3378
0
      sstat->sstat_primary.spinfo_rto = net->RTO;
3379
0
      sstat->sstat_primary.spinfo_mtu = net->mtu;
3380
0
      switch (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family) {
3381
0
#if defined(INET)
3382
0
      case AF_INET:
3383
0
        sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_V4_OVERHEAD;
3384
0
        break;
3385
0
#endif
3386
0
#if defined(INET6)
3387
0
      case AF_INET6:
3388
0
        sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_OVERHEAD;
3389
0
        break;
3390
0
#endif
3391
0
#if defined(__Userspace__)
3392
0
      case AF_CONN:
3393
0
        sstat->sstat_primary.spinfo_mtu -= sizeof(struct sctphdr);
3394
0
        break;
3395
0
#endif
3396
0
      default:
3397
0
        break;
3398
0
      }
3399
0
    } else {
3400
0
      memset(&sstat->sstat_primary, 0, sizeof(struct sctp_paddrinfo));
3401
0
    }
3402
0
    sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
3403
0
    SCTP_TCB_UNLOCK(stcb);
3404
0
    *optsize = sizeof(struct sctp_status);
3405
0
    break;
3406
0
  }
3407
0
  case SCTP_RTOINFO:
3408
0
  {
3409
0
    struct sctp_rtoinfo *srto;
3410
3411
0
    SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, *optsize);
3412
0
    SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
3413
3414
0
    if (stcb) {
3415
0
      srto->srto_initial = stcb->asoc.initial_rto;
3416
0
      srto->srto_max = stcb->asoc.maxrto;
3417
0
      srto->srto_min = stcb->asoc.minrto;
3418
0
      SCTP_TCB_UNLOCK(stcb);
3419
0
    } else {
3420
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3421
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3422
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3423
0
           (srto->srto_assoc_id == SCTP_FUTURE_ASSOC))) {
3424
0
        SCTP_INP_RLOCK(inp);
3425
0
        srto->srto_initial = inp->sctp_ep.initial_rto;
3426
0
        srto->srto_max = inp->sctp_ep.sctp_maxrto;
3427
0
        srto->srto_min = inp->sctp_ep.sctp_minrto;
3428
0
        SCTP_INP_RUNLOCK(inp);
3429
0
      } else {
3430
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3431
0
        error = EINVAL;
3432
0
      }
3433
0
    }
3434
0
    if (error == 0) {
3435
0
      *optsize = sizeof(struct sctp_rtoinfo);
3436
0
    }
3437
0
    break;
3438
0
  }
3439
0
  case SCTP_TIMEOUTS:
3440
0
  {
3441
0
    struct sctp_timeouts *stimo;
3442
3443
0
    SCTP_CHECK_AND_CAST(stimo, optval, struct sctp_timeouts, *optsize);
3444
0
    SCTP_FIND_STCB(inp, stcb, stimo->stimo_assoc_id);
3445
3446
0
    if (stcb) {
3447
0
      stimo->stimo_init= stcb->asoc.timoinit;
3448
0
      stimo->stimo_data= stcb->asoc.timodata;
3449
0
      stimo->stimo_sack= stcb->asoc.timosack;
3450
0
      stimo->stimo_shutdown= stcb->asoc.timoshutdown;
3451
0
      stimo->stimo_heartbeat= stcb->asoc.timoheartbeat;
3452
0
      stimo->stimo_cookie= stcb->asoc.timocookie;
3453
0
      stimo->stimo_shutdownack= stcb->asoc.timoshutdownack;
3454
0
      SCTP_TCB_UNLOCK(stcb);
3455
0
      *optsize = sizeof(struct sctp_timeouts);
3456
0
    } else {
3457
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3458
0
      error = EINVAL;
3459
0
    }
3460
0
    break;
3461
0
  }
3462
0
  case SCTP_ASSOCINFO:
3463
0
  {
3464
0
    struct sctp_assocparams *sasoc;
3465
3466
0
    SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, *optsize);
3467
0
    SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
3468
3469
0
    if (stcb) {
3470
0
      sasoc->sasoc_cookie_life = sctp_ticks_to_msecs(stcb->asoc.cookie_life);
3471
0
      sasoc->sasoc_asocmaxrxt = stcb->asoc.max_send_times;
3472
0
      sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
3473
0
      sasoc->sasoc_peer_rwnd = stcb->asoc.peers_rwnd;
3474
0
      sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
3475
0
      SCTP_TCB_UNLOCK(stcb);
3476
0
    } else {
3477
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3478
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3479
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3480
0
           (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC))) {
3481
0
        SCTP_INP_RLOCK(inp);
3482
0
        sasoc->sasoc_cookie_life = sctp_ticks_to_msecs(inp->sctp_ep.def_cookie_life);
3483
0
        sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
3484
0
        sasoc->sasoc_number_peer_destinations = 0;
3485
0
        sasoc->sasoc_peer_rwnd = 0;
3486
0
        sasoc->sasoc_local_rwnd = (uint32_t)sbspace(&inp->sctp_socket->so_rcv);
3487
0
        SCTP_INP_RUNLOCK(inp);
3488
0
      } else {
3489
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3490
0
        error = EINVAL;
3491
0
      }
3492
0
    }
3493
0
    if (error == 0) {
3494
0
      *optsize = sizeof(struct sctp_assocparams);
3495
0
    }
3496
0
    break;
3497
0
  }
3498
0
  case SCTP_DEFAULT_SEND_PARAM:
3499
0
  {
3500
0
    struct sctp_sndrcvinfo *s_info;
3501
3502
0
    SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, *optsize);
3503
0
    SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
3504
3505
0
    if (stcb) {
3506
0
      memcpy(s_info, &stcb->asoc.def_send, sizeof(stcb->asoc.def_send));
3507
0
      SCTP_TCB_UNLOCK(stcb);
3508
0
    } else {
3509
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3510
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3511
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3512
0
           (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC))) {
3513
0
        SCTP_INP_RLOCK(inp);
3514
0
        memcpy(s_info, &inp->def_send, sizeof(inp->def_send));
3515
0
        SCTP_INP_RUNLOCK(inp);
3516
0
      } else {
3517
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3518
0
        error = EINVAL;
3519
0
      }
3520
0
    }
3521
0
    if (error == 0) {
3522
0
      *optsize = sizeof(struct sctp_sndrcvinfo);
3523
0
    }
3524
0
    break;
3525
0
  }
3526
0
  case SCTP_INITMSG:
3527
0
  {
3528
0
    struct sctp_initmsg *sinit;
3529
3530
0
    SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, *optsize);
3531
0
    SCTP_INP_RLOCK(inp);
3532
0
    sinit->sinit_num_ostreams = inp->sctp_ep.pre_open_stream_count;
3533
0
    sinit->sinit_max_instreams = inp->sctp_ep.max_open_streams_intome;
3534
0
    sinit->sinit_max_attempts = inp->sctp_ep.max_init_times;
3535
0
    sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max;
3536
0
    SCTP_INP_RUNLOCK(inp);
3537
0
    *optsize = sizeof(struct sctp_initmsg);
3538
0
    break;
3539
0
  }
3540
0
  case SCTP_PRIMARY_ADDR:
3541
    /* we allow a "get" operation on this */
3542
0
  {
3543
0
    struct sctp_setprim *ssp;
3544
3545
0
    SCTP_CHECK_AND_CAST(ssp, optval, struct sctp_setprim, *optsize);
3546
0
    SCTP_FIND_STCB(inp, stcb, ssp->ssp_assoc_id);
3547
3548
0
    if (stcb) {
3549
0
      union sctp_sockstore *addr;
3550
3551
0
      addr = &stcb->asoc.primary_destination->ro._l_addr;
3552
0
      switch (addr->sa.sa_family) {
3553
0
#ifdef INET
3554
0
      case AF_INET:
3555
0
#ifdef INET6
3556
0
        if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
3557
0
          in6_sin_2_v4mapsin6(&addr->sin,
3558
0
                              (struct sockaddr_in6 *)&ssp->ssp_addr);
3559
0
        } else {
3560
0
          memcpy(&ssp->ssp_addr, &addr->sin, sizeof(struct sockaddr_in));
3561
0
        }
3562
#else
3563
        memcpy(&ssp->ssp_addr, &addr->sin, sizeof(struct sockaddr_in));
3564
#endif
3565
0
        break;
3566
0
#endif
3567
0
#ifdef INET6
3568
0
      case AF_INET6:
3569
0
        memcpy(&ssp->ssp_addr, &addr->sin6, sizeof(struct sockaddr_in6));
3570
0
        break;
3571
0
#endif
3572
0
#if defined(__Userspace__)
3573
0
      case AF_CONN:
3574
0
        memcpy(&ssp->ssp_addr, &addr->sconn, sizeof(struct sockaddr_conn));
3575
0
        break;
3576
0
#endif
3577
0
      default:
3578
0
        break;
3579
0
      }
3580
0
      SCTP_TCB_UNLOCK(stcb);
3581
0
      *optsize = sizeof(struct sctp_setprim);
3582
0
    } else {
3583
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3584
0
      error = EINVAL;
3585
0
    }
3586
0
    break;
3587
0
  }
3588
0
  case SCTP_HMAC_IDENT:
3589
0
  {
3590
0
    struct sctp_hmacalgo *shmac;
3591
0
    sctp_hmaclist_t *hmaclist;
3592
0
    size_t size;
3593
0
    int i;
3594
3595
0
    SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, *optsize);
3596
3597
0
    SCTP_INP_RLOCK(inp);
3598
0
    hmaclist = inp->sctp_ep.local_hmacs;
3599
0
    if (hmaclist == NULL) {
3600
      /* no HMACs to return */
3601
0
      *optsize = sizeof(*shmac);
3602
0
      SCTP_INP_RUNLOCK(inp);
3603
0
      break;
3604
0
    }
3605
    /* is there room for all of the hmac ids? */
3606
0
    size = sizeof(*shmac) + (hmaclist->num_algo *
3607
0
                             sizeof(shmac->shmac_idents[0]));
3608
0
    if (*optsize < size) {
3609
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3610
0
      error = EINVAL;
3611
0
      SCTP_INP_RUNLOCK(inp);
3612
0
      break;
3613
0
    }
3614
    /* copy in the list */
3615
0
    shmac->shmac_number_of_idents = hmaclist->num_algo;
3616
0
    for (i = 0; i < hmaclist->num_algo; i++) {
3617
0
      shmac->shmac_idents[i] = hmaclist->hmac[i];
3618
0
    }
3619
0
    SCTP_INP_RUNLOCK(inp);
3620
0
    *optsize = size;
3621
0
    break;
3622
0
  }
3623
0
  case SCTP_AUTH_ACTIVE_KEY:
3624
0
  {
3625
0
    struct sctp_authkeyid *scact;
3626
3627
0
    SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, *optsize);
3628
0
    SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
3629
3630
0
    if (stcb) {
3631
      /* get the active key on the assoc */
3632
0
      scact->scact_keynumber = stcb->asoc.authinfo.active_keyid;
3633
0
      SCTP_TCB_UNLOCK(stcb);
3634
0
    } else {
3635
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3636
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3637
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3638
0
           (scact->scact_assoc_id == SCTP_FUTURE_ASSOC))) {
3639
        /* get the endpoint active key */
3640
0
        SCTP_INP_RLOCK(inp);
3641
0
        scact->scact_keynumber = inp->sctp_ep.default_keyid;
3642
0
        SCTP_INP_RUNLOCK(inp);
3643
0
      } else {
3644
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3645
0
        error = EINVAL;
3646
0
      }
3647
0
    }
3648
0
    if (error == 0) {
3649
0
      *optsize = sizeof(struct sctp_authkeyid);
3650
0
    }
3651
0
    break;
3652
0
  }
3653
0
  case SCTP_LOCAL_AUTH_CHUNKS:
3654
0
  {
3655
0
    struct sctp_authchunks *sac;
3656
0
    sctp_auth_chklist_t *chklist = NULL;
3657
0
    size_t size = 0;
3658
3659
0
    SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
3660
0
    SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
3661
3662
0
    if (stcb) {
3663
      /* get off the assoc */
3664
0
      chklist = stcb->asoc.local_auth_chunks;
3665
      /* is there enough space? */
3666
0
      size = sctp_auth_get_chklist_size(chklist);
3667
0
      if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
3668
0
        error = EINVAL;
3669
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3670
0
      } else {
3671
        /* copy in the chunks */
3672
0
        (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
3673
0
        sac->gauth_number_of_chunks = (uint32_t)size;
3674
0
        *optsize = sizeof(struct sctp_authchunks) + size;
3675
0
      }
3676
0
      SCTP_TCB_UNLOCK(stcb);
3677
0
    } else {
3678
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3679
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3680
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3681
0
           (sac->gauth_assoc_id == SCTP_FUTURE_ASSOC))) {
3682
        /* get off the endpoint */
3683
0
        SCTP_INP_RLOCK(inp);
3684
0
        chklist = inp->sctp_ep.local_auth_chunks;
3685
        /* is there enough space? */
3686
0
        size = sctp_auth_get_chklist_size(chklist);
3687
0
        if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
3688
0
          error = EINVAL;
3689
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3690
0
        } else {
3691
          /* copy in the chunks */
3692
0
          (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
3693
0
          sac->gauth_number_of_chunks = (uint32_t)size;
3694
0
          *optsize = sizeof(struct sctp_authchunks) + size;
3695
0
        }
3696
0
        SCTP_INP_RUNLOCK(inp);
3697
0
      } else {
3698
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3699
0
        error = EINVAL;
3700
0
      }
3701
0
    }
3702
0
    break;
3703
0
  }
3704
0
  case SCTP_PEER_AUTH_CHUNKS:
3705
0
  {
3706
0
    struct sctp_authchunks *sac;
3707
0
    sctp_auth_chklist_t *chklist = NULL;
3708
0
    size_t size = 0;
3709
3710
0
    SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
3711
0
    SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
3712
3713
0
    if (stcb) {
3714
      /* get off the assoc */
3715
0
      chklist = stcb->asoc.peer_auth_chunks;
3716
      /* is there enough space? */
3717
0
      size = sctp_auth_get_chklist_size(chklist);
3718
0
      if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
3719
0
        error = EINVAL;
3720
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3721
0
      } else {
3722
        /* copy in the chunks */
3723
0
        (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
3724
0
        sac->gauth_number_of_chunks = (uint32_t)size;
3725
0
        *optsize = sizeof(struct sctp_authchunks) + size;
3726
0
      }
3727
0
      SCTP_TCB_UNLOCK(stcb);
3728
0
    } else {
3729
0
            SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
3730
0
      error = ENOENT;
3731
0
    }
3732
0
    break;
3733
0
  }
3734
#if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
3735
  case SCTP_PEELOFF:
3736
  {
3737
    struct sctp_peeloff_opt *peeloff;
3738
3739
    SCTP_CHECK_AND_CAST(peeloff, optval, struct sctp_peeloff_opt, *optsize);
3740
    /* do the peeloff */
3741
    error = sctp_peeloff_option(p, peeloff);
3742
    if (error == 0) {
3743
      *optsize = sizeof(struct sctp_peeloff_opt);
3744
    }
3745
  }
3746
  break;
3747
#endif /* HAVE_SCTP_PEELOFF_SOCKOPT */
3748
0
  case SCTP_EVENT:
3749
0
  {
3750
0
    struct sctp_event *event;
3751
0
    uint32_t event_type;
3752
3753
0
    SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, *optsize);
3754
0
    SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
3755
3756
0
    switch (event->se_type) {
3757
0
    case SCTP_ASSOC_CHANGE:
3758
0
      event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
3759
0
      break;
3760
0
    case SCTP_PEER_ADDR_CHANGE:
3761
0
      event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
3762
0
      break;
3763
0
    case SCTP_REMOTE_ERROR:
3764
0
      event_type = SCTP_PCB_FLAGS_RECVPEERERR;
3765
0
      break;
3766
0
    case SCTP_SEND_FAILED:
3767
0
      event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
3768
0
      break;
3769
0
    case SCTP_SHUTDOWN_EVENT:
3770
0
      event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
3771
0
      break;
3772
0
    case SCTP_ADAPTATION_INDICATION:
3773
0
      event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
3774
0
      break;
3775
0
    case SCTP_PARTIAL_DELIVERY_EVENT:
3776
0
      event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
3777
0
      break;
3778
0
    case SCTP_AUTHENTICATION_EVENT:
3779
0
      event_type = SCTP_PCB_FLAGS_AUTHEVNT;
3780
0
      break;
3781
0
    case SCTP_STREAM_RESET_EVENT:
3782
0
      event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
3783
0
      break;
3784
0
    case SCTP_SENDER_DRY_EVENT:
3785
0
      event_type = SCTP_PCB_FLAGS_DRYEVNT;
3786
0
      break;
3787
0
    case SCTP_NOTIFICATIONS_STOPPED_EVENT:
3788
0
      event_type = 0;
3789
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
3790
0
      error = ENOTSUP;
3791
0
      break;
3792
0
    case SCTP_ASSOC_RESET_EVENT:
3793
0
      event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
3794
0
      break;
3795
0
    case SCTP_STREAM_CHANGE_EVENT:
3796
0
      event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
3797
0
      break;
3798
0
    case SCTP_SEND_FAILED_EVENT:
3799
0
      event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
3800
0
      break;
3801
0
    default:
3802
0
      event_type = 0;
3803
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3804
0
      error = EINVAL;
3805
0
      break;
3806
0
    }
3807
0
    if (event_type > 0) {
3808
0
      if (stcb) {
3809
0
        event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
3810
0
      } else {
3811
0
        if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3812
0
            (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3813
0
            ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3814
0
             (event->se_assoc_id == SCTP_FUTURE_ASSOC))) {
3815
0
          SCTP_INP_RLOCK(inp);
3816
0
          event->se_on = sctp_is_feature_on(inp, event_type);
3817
0
          SCTP_INP_RUNLOCK(inp);
3818
0
        } else {
3819
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3820
0
          error = EINVAL;
3821
0
        }
3822
0
      }
3823
0
    }
3824
0
    if (stcb != NULL) {
3825
0
      SCTP_TCB_UNLOCK(stcb);
3826
0
    }
3827
0
    if (error == 0) {
3828
0
      *optsize = sizeof(struct sctp_event);
3829
0
    }
3830
0
    break;
3831
0
  }
3832
0
  case SCTP_RECVRCVINFO:
3833
0
    if (*optsize < sizeof(int)) {
3834
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3835
0
      error = EINVAL;
3836
0
    } else {
3837
0
      SCTP_INP_RLOCK(inp);
3838
0
      *(int *)optval = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
3839
0
      SCTP_INP_RUNLOCK(inp);
3840
0
      *optsize = sizeof(int);
3841
0
    }
3842
0
    break;
3843
0
  case SCTP_RECVNXTINFO:
3844
0
    if (*optsize < sizeof(int)) {
3845
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3846
0
      error = EINVAL;
3847
0
    } else {
3848
0
      SCTP_INP_RLOCK(inp);
3849
0
      *(int *)optval = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
3850
0
      SCTP_INP_RUNLOCK(inp);
3851
0
      *optsize = sizeof(int);
3852
0
    }
3853
0
    break;
3854
0
  case SCTP_DEFAULT_SNDINFO:
3855
0
  {
3856
0
    struct sctp_sndinfo *info;
3857
3858
0
    SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, *optsize);
3859
0
    SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
3860
3861
0
    if (stcb) {
3862
0
      info->snd_sid = stcb->asoc.def_send.sinfo_stream;
3863
0
      info->snd_flags = stcb->asoc.def_send.sinfo_flags;
3864
0
      info->snd_flags &= 0xfff0;
3865
0
      info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
3866
0
      info->snd_context = stcb->asoc.def_send.sinfo_context;
3867
0
      SCTP_TCB_UNLOCK(stcb);
3868
0
    } else {
3869
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3870
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3871
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3872
0
           (info->snd_assoc_id == SCTP_FUTURE_ASSOC))) {
3873
0
        SCTP_INP_RLOCK(inp);
3874
0
        info->snd_sid = inp->def_send.sinfo_stream;
3875
0
        info->snd_flags = inp->def_send.sinfo_flags;
3876
0
        info->snd_flags &= 0xfff0;
3877
0
        info->snd_ppid = inp->def_send.sinfo_ppid;
3878
0
        info->snd_context = inp->def_send.sinfo_context;
3879
0
        SCTP_INP_RUNLOCK(inp);
3880
0
      } else {
3881
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3882
0
        error = EINVAL;
3883
0
      }
3884
0
    }
3885
0
    if (error == 0) {
3886
0
      *optsize = sizeof(struct sctp_sndinfo);
3887
0
    }
3888
0
    break;
3889
0
  }
3890
0
  case SCTP_DEFAULT_PRINFO:
3891
0
  {
3892
0
    struct sctp_default_prinfo *info;
3893
3894
0
    SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize);
3895
0
    SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
3896
3897
0
    if (stcb) {
3898
0
      info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
3899
0
      info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
3900
0
      SCTP_TCB_UNLOCK(stcb);
3901
0
    } else {
3902
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3903
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3904
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3905
0
           (info->pr_assoc_id == SCTP_FUTURE_ASSOC))) {
3906
0
        SCTP_INP_RLOCK(inp);
3907
0
        info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
3908
0
        info->pr_value = inp->def_send.sinfo_timetolive;
3909
0
        SCTP_INP_RUNLOCK(inp);
3910
0
      } else {
3911
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3912
0
        error = EINVAL;
3913
0
      }
3914
0
    }
3915
0
    if (error == 0) {
3916
0
      *optsize = sizeof(struct sctp_default_prinfo);
3917
0
    }
3918
0
    break;
3919
0
  }
3920
0
  case SCTP_PEER_ADDR_THLDS:
3921
0
  {
3922
0
    struct sctp_paddrthlds *thlds;
3923
0
    struct sctp_nets *net;
3924
0
    struct sockaddr *addr;
3925
0
#if defined(INET) && defined(INET6)
3926
0
    struct sockaddr_in sin_store;
3927
0
#endif
3928
3929
0
    SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize);
3930
0
    SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
3931
3932
0
#if defined(INET) && defined(INET6)
3933
0
    if (thlds->spt_address.ss_family == AF_INET6) {
3934
0
      struct sockaddr_in6 *sin6;
3935
3936
0
      sin6 = (struct sockaddr_in6 *)&thlds->spt_address;
3937
0
      if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
3938
0
        in6_sin6_2_sin(&sin_store, sin6);
3939
0
        addr = (struct sockaddr *)&sin_store;
3940
0
      } else {
3941
0
        addr = (struct sockaddr *)&thlds->spt_address;
3942
0
      }
3943
0
    } else {
3944
0
      addr = (struct sockaddr *)&thlds->spt_address;
3945
0
    }
3946
#else
3947
    addr = (struct sockaddr *)&thlds->spt_address;
3948
#endif
3949
0
    if (stcb != NULL) {
3950
0
      net = sctp_findnet(stcb, addr);
3951
0
    } else {
3952
      /* We increment here since sctp_findassociation_ep_addr() wil
3953
       * do a decrement if it finds the stcb as long as the locked
3954
       * tcb (last argument) is NOT a TCB.. aka NULL.
3955
       */
3956
0
      net = NULL;
3957
0
      SCTP_INP_INCR_REF(inp);
3958
0
      stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
3959
0
      if (stcb == NULL) {
3960
0
        SCTP_INP_DECR_REF(inp);
3961
0
      }
3962
0
    }
3963
0
    if ((stcb != NULL) && (net == NULL)) {
3964
0
#ifdef INET
3965
0
      if (addr->sa_family == AF_INET) {
3966
0
        struct sockaddr_in *sin;
3967
3968
0
        sin = (struct sockaddr_in *)addr;
3969
0
        if (sin->sin_addr.s_addr != INADDR_ANY) {
3970
0
          error = EINVAL;
3971
0
          SCTP_TCB_UNLOCK(stcb);
3972
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3973
0
          break;
3974
0
        }
3975
0
      } else
3976
0
#endif
3977
0
#ifdef INET6
3978
0
      if (addr->sa_family == AF_INET6) {
3979
0
        struct sockaddr_in6 *sin6;
3980
3981
0
        sin6 = (struct sockaddr_in6 *)addr;
3982
0
        if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3983
0
          error = EINVAL;
3984
0
          SCTP_TCB_UNLOCK(stcb);
3985
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3986
0
          break;
3987
0
        }
3988
0
      } else
3989
0
#endif
3990
0
#if defined(__Userspace__)
3991
0
      if (addr->sa_family == AF_CONN) {
3992
0
        struct sockaddr_conn *sconn;
3993
3994
0
        sconn = (struct sockaddr_conn *)addr;
3995
0
        if (sconn->sconn_addr != NULL) {
3996
0
          error = EINVAL;
3997
0
          SCTP_TCB_UNLOCK(stcb);
3998
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3999
0
          break;
4000
0
        }
4001
0
      } else
4002
0
#endif
4003
0
      {
4004
0
        error = EAFNOSUPPORT;
4005
0
        SCTP_TCB_UNLOCK(stcb);
4006
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4007
0
        break;
4008
0
      }
4009
0
    }
4010
4011
0
    if (stcb != NULL) {
4012
0
      if (net != NULL) {
4013
0
        thlds->spt_pathmaxrxt = net->failure_threshold;
4014
0
        thlds->spt_pathpfthld = net->pf_threshold;
4015
0
        thlds->spt_pathcpthld = 0xffff;
4016
0
      } else {
4017
0
        thlds->spt_pathmaxrxt = stcb->asoc.def_net_failure;
4018
0
        thlds->spt_pathpfthld = stcb->asoc.def_net_pf_threshold;
4019
0
        thlds->spt_pathcpthld = 0xffff;
4020
0
      }
4021
0
      thlds->spt_assoc_id = sctp_get_associd(stcb);
4022
0
      SCTP_TCB_UNLOCK(stcb);
4023
0
    } else {
4024
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4025
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4026
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4027
0
           (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC))) {
4028
        /* Use endpoint defaults */
4029
0
        SCTP_INP_RLOCK(inp);
4030
0
        thlds->spt_pathmaxrxt = inp->sctp_ep.def_net_failure;
4031
0
        thlds->spt_pathpfthld = inp->sctp_ep.def_net_pf_threshold;
4032
0
        thlds->spt_pathcpthld = 0xffff;
4033
0
        SCTP_INP_RUNLOCK(inp);
4034
0
      } else {
4035
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4036
0
        error = EINVAL;
4037
0
      }
4038
0
    }
4039
0
    if (error == 0) {
4040
0
      *optsize = sizeof(struct sctp_paddrthlds);
4041
0
    }
4042
0
    break;
4043
0
  }
4044
0
  case SCTP_REMOTE_UDP_ENCAPS_PORT:
4045
0
  {
4046
0
    struct sctp_udpencaps *encaps;
4047
0
    struct sctp_nets *net;
4048
0
    struct sockaddr *addr;
4049
0
#if defined(INET) && defined(INET6)
4050
0
    struct sockaddr_in sin_store;
4051
0
#endif
4052
4053
0
    SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize);
4054
0
    SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
4055
4056
0
#if defined(INET) && defined(INET6)
4057
0
    if (encaps->sue_address.ss_family == AF_INET6) {
4058
0
      struct sockaddr_in6 *sin6;
4059
4060
0
      sin6 = (struct sockaddr_in6 *)&encaps->sue_address;
4061
0
      if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
4062
0
        in6_sin6_2_sin(&sin_store, sin6);
4063
0
        addr = (struct sockaddr *)&sin_store;
4064
0
      } else {
4065
0
        addr = (struct sockaddr *)&encaps->sue_address;
4066
0
      }
4067
0
    } else {
4068
0
      addr = (struct sockaddr *)&encaps->sue_address;
4069
0
    }
4070
#else
4071
    addr = (struct sockaddr *)&encaps->sue_address;
4072
#endif
4073
0
    if (stcb) {
4074
0
      net = sctp_findnet(stcb, addr);
4075
0
    } else {
4076
      /* We increment here since sctp_findassociation_ep_addr() wil
4077
       * do a decrement if it finds the stcb as long as the locked
4078
       * tcb (last argument) is NOT a TCB.. aka NULL.
4079
       */
4080
0
      net = NULL;
4081
0
      SCTP_INP_INCR_REF(inp);
4082
0
      stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
4083
0
      if (stcb == NULL) {
4084
0
        SCTP_INP_DECR_REF(inp);
4085
0
      }
4086
0
    }
4087
0
    if ((stcb != NULL) && (net == NULL)) {
4088
0
#ifdef INET
4089
0
      if (addr->sa_family == AF_INET) {
4090
0
        struct sockaddr_in *sin;
4091
4092
0
        sin = (struct sockaddr_in *)addr;
4093
0
        if (sin->sin_addr.s_addr != INADDR_ANY) {
4094
0
          error = EINVAL;
4095
0
          SCTP_TCB_UNLOCK(stcb);
4096
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4097
0
          break;
4098
0
        }
4099
0
      } else
4100
0
#endif
4101
0
#ifdef INET6
4102
0
      if (addr->sa_family == AF_INET6) {
4103
0
        struct sockaddr_in6 *sin6;
4104
4105
0
        sin6 = (struct sockaddr_in6 *)addr;
4106
0
        if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
4107
0
          error = EINVAL;
4108
0
          SCTP_TCB_UNLOCK(stcb);
4109
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4110
0
          break;
4111
0
        }
4112
0
      } else
4113
0
#endif
4114
0
#if defined(__Userspace__)
4115
0
      if (addr->sa_family == AF_CONN) {
4116
0
        struct sockaddr_conn *sconn;
4117
4118
0
        sconn = (struct sockaddr_conn *)addr;
4119
0
        if (sconn->sconn_addr != NULL) {
4120
0
          error = EINVAL;
4121
0
          SCTP_TCB_UNLOCK(stcb);
4122
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4123
0
          break;
4124
0
        }
4125
0
      } else
4126
0
#endif
4127
0
      {
4128
0
        error = EAFNOSUPPORT;
4129
0
        SCTP_TCB_UNLOCK(stcb);
4130
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4131
0
        break;
4132
0
      }
4133
0
    }
4134
4135
0
    if (stcb != NULL) {
4136
0
      if (net) {
4137
0
        encaps->sue_port = net->port;
4138
0
      } else {
4139
0
        encaps->sue_port = stcb->asoc.port;
4140
0
      }
4141
0
      SCTP_TCB_UNLOCK(stcb);
4142
0
    } else {
4143
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4144
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4145
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4146
0
           (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC))) {
4147
0
        SCTP_INP_RLOCK(inp);
4148
0
        encaps->sue_port = inp->sctp_ep.port;
4149
0
        SCTP_INP_RUNLOCK(inp);
4150
0
      } else {
4151
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4152
0
        error = EINVAL;
4153
0
      }
4154
0
    }
4155
0
    if (error == 0) {
4156
0
      *optsize = sizeof(struct sctp_udpencaps);
4157
0
    }
4158
0
    break;
4159
0
  }
4160
0
  case SCTP_ECN_SUPPORTED:
4161
0
  {
4162
0
    struct sctp_assoc_value *av;
4163
4164
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4165
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4166
4167
0
    if (stcb) {
4168
0
      av->assoc_value = stcb->asoc.ecn_supported;
4169
0
      SCTP_TCB_UNLOCK(stcb);
4170
0
    } else {
4171
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4172
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4173
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4174
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4175
0
        SCTP_INP_RLOCK(inp);
4176
0
        av->assoc_value = inp->ecn_supported;
4177
0
        SCTP_INP_RUNLOCK(inp);
4178
0
      } else {
4179
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4180
0
        error = EINVAL;
4181
0
      }
4182
0
    }
4183
0
    if (error == 0) {
4184
0
      *optsize = sizeof(struct sctp_assoc_value);
4185
0
    }
4186
0
    break;
4187
0
  }
4188
0
  case SCTP_PR_SUPPORTED:
4189
0
  {
4190
0
    struct sctp_assoc_value *av;
4191
4192
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4193
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4194
4195
0
    if (stcb) {
4196
0
      av->assoc_value = stcb->asoc.prsctp_supported;
4197
0
      SCTP_TCB_UNLOCK(stcb);
4198
0
    } else {
4199
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4200
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4201
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4202
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4203
0
        SCTP_INP_RLOCK(inp);
4204
0
        av->assoc_value = inp->prsctp_supported;
4205
0
        SCTP_INP_RUNLOCK(inp);
4206
0
      } else {
4207
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4208
0
        error = EINVAL;
4209
0
      }
4210
0
    }
4211
0
    if (error == 0) {
4212
0
      *optsize = sizeof(struct sctp_assoc_value);
4213
0
    }
4214
0
    break;
4215
0
  }
4216
0
  case SCTP_AUTH_SUPPORTED:
4217
0
  {
4218
0
    struct sctp_assoc_value *av;
4219
4220
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4221
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4222
4223
0
    if (stcb) {
4224
0
      av->assoc_value = stcb->asoc.auth_supported;
4225
0
      SCTP_TCB_UNLOCK(stcb);
4226
0
    } else {
4227
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4228
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4229
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4230
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4231
0
        SCTP_INP_RLOCK(inp);
4232
0
        av->assoc_value = inp->auth_supported;
4233
0
        SCTP_INP_RUNLOCK(inp);
4234
0
      } else {
4235
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4236
0
        error = EINVAL;
4237
0
      }
4238
0
    }
4239
0
    if (error == 0) {
4240
0
      *optsize = sizeof(struct sctp_assoc_value);
4241
0
    }
4242
0
    break;
4243
0
  }
4244
0
  case SCTP_ASCONF_SUPPORTED:
4245
0
  {
4246
0
    struct sctp_assoc_value *av;
4247
4248
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4249
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4250
4251
0
    if (stcb) {
4252
0
      av->assoc_value = stcb->asoc.asconf_supported;
4253
0
      SCTP_TCB_UNLOCK(stcb);
4254
0
    } else {
4255
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4256
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4257
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4258
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4259
0
        SCTP_INP_RLOCK(inp);
4260
0
        av->assoc_value = inp->asconf_supported;
4261
0
        SCTP_INP_RUNLOCK(inp);
4262
0
      } else {
4263
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4264
0
        error = EINVAL;
4265
0
      }
4266
0
    }
4267
0
    if (error == 0) {
4268
0
      *optsize = sizeof(struct sctp_assoc_value);
4269
0
    }
4270
0
    break;
4271
0
  }
4272
0
  case SCTP_RECONFIG_SUPPORTED:
4273
0
  {
4274
0
    struct sctp_assoc_value *av;
4275
4276
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4277
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4278
4279
0
    if (stcb) {
4280
0
      av->assoc_value = stcb->asoc.reconfig_supported;
4281
0
      SCTP_TCB_UNLOCK(stcb);
4282
0
    } else {
4283
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4284
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4285
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4286
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4287
0
        SCTP_INP_RLOCK(inp);
4288
0
        av->assoc_value = inp->reconfig_supported;
4289
0
        SCTP_INP_RUNLOCK(inp);
4290
0
      } else {
4291
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4292
0
        error = EINVAL;
4293
0
      }
4294
0
    }
4295
0
    if (error == 0) {
4296
0
      *optsize = sizeof(struct sctp_assoc_value);
4297
0
    }
4298
0
    break;
4299
0
  }
4300
0
  case SCTP_NRSACK_SUPPORTED:
4301
0
  {
4302
0
    struct sctp_assoc_value *av;
4303
4304
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4305
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4306
4307
0
    if (stcb) {
4308
0
      av->assoc_value = stcb->asoc.nrsack_supported;
4309
0
      SCTP_TCB_UNLOCK(stcb);
4310
0
    } else {
4311
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4312
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4313
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4314
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4315
0
        SCTP_INP_RLOCK(inp);
4316
0
        av->assoc_value = inp->nrsack_supported;
4317
0
        SCTP_INP_RUNLOCK(inp);
4318
0
      } else {
4319
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4320
0
        error = EINVAL;
4321
0
      }
4322
0
    }
4323
0
    if (error == 0) {
4324
0
      *optsize = sizeof(struct sctp_assoc_value);
4325
0
    }
4326
0
    break;
4327
0
  }
4328
0
  case SCTP_PKTDROP_SUPPORTED:
4329
0
  {
4330
0
    struct sctp_assoc_value *av;
4331
4332
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4333
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4334
4335
0
    if (stcb) {
4336
0
      av->assoc_value = stcb->asoc.pktdrop_supported;
4337
0
      SCTP_TCB_UNLOCK(stcb);
4338
0
    } else {
4339
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4340
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4341
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4342
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4343
0
        SCTP_INP_RLOCK(inp);
4344
0
        av->assoc_value = inp->pktdrop_supported;
4345
0
        SCTP_INP_RUNLOCK(inp);
4346
0
      } else {
4347
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4348
0
        error = EINVAL;
4349
0
      }
4350
0
    }
4351
0
    if (error == 0) {
4352
0
      *optsize = sizeof(struct sctp_assoc_value);
4353
0
    }
4354
0
    break;
4355
0
  }
4356
0
  case SCTP_ENABLE_STREAM_RESET:
4357
0
  {
4358
0
    struct sctp_assoc_value *av;
4359
4360
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4361
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4362
4363
0
    if (stcb) {
4364
0
      av->assoc_value = (uint32_t)stcb->asoc.local_strreset_support;
4365
0
      SCTP_TCB_UNLOCK(stcb);
4366
0
    } else {
4367
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4368
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4369
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4370
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4371
0
        SCTP_INP_RLOCK(inp);
4372
0
        av->assoc_value = (uint32_t)inp->local_strreset_support;
4373
0
        SCTP_INP_RUNLOCK(inp);
4374
0
      } else {
4375
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4376
0
        error = EINVAL;
4377
0
      }
4378
0
    }
4379
0
    if (error == 0) {
4380
0
      *optsize = sizeof(struct sctp_assoc_value);
4381
0
    }
4382
0
    break;
4383
0
  }
4384
0
  case SCTP_PR_STREAM_STATUS:
4385
0
  {
4386
0
    struct sctp_prstatus *sprstat;
4387
0
    uint16_t sid;
4388
0
    uint16_t policy;
4389
4390
0
    SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize);
4391
0
    SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
4392
4393
0
    sid = sprstat->sprstat_sid;
4394
0
    policy = sprstat->sprstat_policy;
4395
#if defined(SCTP_DETAILED_STR_STATS)
4396
    if ((stcb != NULL) &&
4397
        (sid < stcb->asoc.streamoutcnt) &&
4398
        (policy != SCTP_PR_SCTP_NONE) &&
4399
        ((policy <= SCTP_PR_SCTP_MAX) ||
4400
         (policy == SCTP_PR_SCTP_ALL))) {
4401
      if (policy == SCTP_PR_SCTP_ALL) {
4402
        sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0];
4403
        sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0];
4404
      } else {
4405
        sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[policy];
4406
        sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[policy];
4407
      }
4408
#else
4409
0
    if ((stcb != NULL) &&
4410
0
        (sid < stcb->asoc.streamoutcnt) &&
4411
0
        (policy == SCTP_PR_SCTP_ALL)) {
4412
0
      sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0];
4413
0
      sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0];
4414
0
#endif
4415
0
    } else {
4416
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4417
0
      error = EINVAL;
4418
0
    }
4419
0
    if (stcb != NULL) {
4420
0
      SCTP_TCB_UNLOCK(stcb);
4421
0
    }
4422
0
    if (error == 0) {
4423
0
      *optsize = sizeof(struct sctp_prstatus);
4424
0
    }
4425
0
    break;
4426
0
  }
4427
0
  case SCTP_PR_ASSOC_STATUS:
4428
0
  {
4429
0
    struct sctp_prstatus *sprstat;
4430
0
    uint16_t policy;
4431
4432
0
    SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize);
4433
0
    SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
4434
4435
0
    policy = sprstat->sprstat_policy;
4436
0
    if ((stcb != NULL) &&
4437
0
        (policy != SCTP_PR_SCTP_NONE) &&
4438
0
        ((policy <= SCTP_PR_SCTP_MAX) ||
4439
0
         (policy == SCTP_PR_SCTP_ALL))) {
4440
0
      if (policy == SCTP_PR_SCTP_ALL) {
4441
0
        sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[0];
4442
0
        sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[0];
4443
0
      } else {
4444
0
        sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[policy];
4445
0
        sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[policy];
4446
0
      }
4447
0
    } else {
4448
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4449
0
      error = EINVAL;
4450
0
    }
4451
0
    if (stcb != NULL) {
4452
0
      SCTP_TCB_UNLOCK(stcb);
4453
0
    }
4454
0
    if (error == 0) {
4455
0
      *optsize = sizeof(struct sctp_prstatus);
4456
0
    }
4457
0
    break;
4458
0
  }
4459
0
  case SCTP_MAX_CWND:
4460
0
  {
4461
0
    struct sctp_assoc_value *av;
4462
4463
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
4464
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4465
4466
0
    if (stcb) {
4467
0
      av->assoc_value = stcb->asoc.max_cwnd;
4468
0
      SCTP_TCB_UNLOCK(stcb);
4469
0
    } else {
4470
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4471
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4472
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4473
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4474
0
        SCTP_INP_RLOCK(inp);
4475
0
        av->assoc_value = inp->max_cwnd;
4476
0
        SCTP_INP_RUNLOCK(inp);
4477
0
      } else {
4478
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4479
0
        error = EINVAL;
4480
0
      }
4481
0
    }
4482
0
    if (error == 0) {
4483
0
      *optsize = sizeof(struct sctp_assoc_value);
4484
0
    }
4485
0
    break;
4486
0
  }
4487
0
  default:
4488
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
4489
0
    error = ENOPROTOOPT;
4490
0
    break;
4491
0
  } /* end switch (sopt->sopt_name) */
4492
0
  if (error) {
4493
0
    *optsize = 0;
4494
0
  }
4495
0
  return (error);
4496
0
}
4497
4498
#if defined(__Userspace__)
4499
int
4500
#else
4501
static int
4502
#endif
4503
sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
4504
      void *p)
4505
230k
{
4506
230k
  int error, set_opt;
4507
230k
  uint32_t *mopt;
4508
230k
  struct sctp_tcb *stcb = NULL;
4509
230k
  struct sctp_inpcb *inp = NULL;
4510
230k
  uint32_t vrf_id;
4511
4512
230k
  if (optval == NULL) {
4513
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4514
0
    return (EINVAL);
4515
0
  }
4516
230k
  inp = (struct sctp_inpcb *)so->so_pcb;
4517
230k
  if (inp == NULL) {
4518
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4519
0
    return (EINVAL);
4520
0
  }
4521
230k
  vrf_id = inp->def_vrf_id;
4522
4523
230k
  error = 0;
4524
230k
  switch (optname) {
4525
11.5k
  case SCTP_NODELAY:
4526
11.5k
  case SCTP_AUTOCLOSE:
4527
11.5k
  case SCTP_AUTO_ASCONF:
4528
11.5k
  case SCTP_EXPLICIT_EOR:
4529
11.5k
  case SCTP_DISABLE_FRAGMENTS:
4530
11.5k
  case SCTP_USE_EXT_RCVINFO:
4531
11.5k
  case SCTP_I_WANT_MAPPED_V4_ADDR:
4532
    /* copy in the option value */
4533
11.5k
    SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
4534
11.5k
    set_opt = 0;
4535
11.5k
    if (error)
4536
0
      break;
4537
11.5k
    switch (optname) {
4538
0
    case SCTP_DISABLE_FRAGMENTS:
4539
0
      set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
4540
0
      break;
4541
0
    case SCTP_AUTO_ASCONF:
4542
      /*
4543
       * NOTE: we don't really support this flag
4544
       */
4545
0
      if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
4546
        /* only valid for bound all sockets */
4547
0
        if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
4548
0
            (*mopt != 0)) {
4549
          /* forbidden by admin */
4550
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
4551
0
          return (EPERM);
4552
0
        }
4553
0
        set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
4554
0
      } else {
4555
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4556
0
        return (EINVAL);
4557
0
      }
4558
0
      break;
4559
0
    case SCTP_EXPLICIT_EOR:
4560
0
      set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
4561
0
      break;
4562
0
    case SCTP_USE_EXT_RCVINFO:
4563
0
      set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO;
4564
0
      break;
4565
0
    case SCTP_I_WANT_MAPPED_V4_ADDR:
4566
0
      if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4567
0
        set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
4568
0
      } else {
4569
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4570
0
        return (EINVAL);
4571
0
      }
4572
0
      break;
4573
11.5k
    case SCTP_NODELAY:
4574
11.5k
      set_opt = SCTP_PCB_FLAGS_NODELAY;
4575
11.5k
      break;
4576
0
    case SCTP_AUTOCLOSE:
4577
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4578
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
4579
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4580
0
        return (EINVAL);
4581
0
      }
4582
0
      set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
4583
      /*
4584
       * The value is in ticks. Note this does not effect
4585
       * old associations, only new ones.
4586
       */
4587
0
      inp->sctp_ep.auto_close_time = sctp_secs_to_ticks(*mopt);
4588
0
      break;
4589
11.5k
    }
4590
11.5k
    SCTP_INP_WLOCK(inp);
4591
11.5k
    if (*mopt != 0) {
4592
11.5k
      sctp_feature_on(inp, set_opt);
4593
11.5k
    } else {
4594
0
      sctp_feature_off(inp, set_opt);
4595
0
    }
4596
11.5k
    SCTP_INP_WUNLOCK(inp);
4597
11.5k
    break;
4598
11.5k
  case SCTP_REUSE_PORT:
4599
11.5k
  {
4600
11.5k
    SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
4601
11.5k
    if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
4602
      /* Can't set it after we are bound */
4603
0
      error = EINVAL;
4604
0
      break;
4605
0
    }
4606
11.5k
    if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
4607
      /* Can't do this for a 1-m socket */
4608
0
      error = EINVAL;
4609
0
      break;
4610
0
    }
4611
11.5k
    if (optval)
4612
11.5k
      sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
4613
0
    else
4614
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
4615
11.5k
    break;
4616
11.5k
  }
4617
0
  case SCTP_PARTIAL_DELIVERY_POINT:
4618
0
  {
4619
0
    uint32_t *value;
4620
4621
0
    SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
4622
0
    if (*value > SCTP_SB_LIMIT_RCV(so)) {
4623
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4624
0
      error = EINVAL;
4625
0
      break;
4626
0
    }
4627
0
    inp->partial_delivery_point = *value;
4628
0
    break;
4629
0
  }
4630
5.65k
  case SCTP_FRAGMENT_INTERLEAVE:
4631
    /* not yet until we re-write sctp_recvmsg() */
4632
5.65k
  {
4633
5.65k
    uint32_t *level;
4634
4635
5.65k
    SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize);
4636
5.65k
    if (*level == SCTP_FRAG_LEVEL_2) {
4637
5.65k
      sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
4638
5.65k
      sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
4639
5.65k
    } else if (*level == SCTP_FRAG_LEVEL_1) {
4640
0
      sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
4641
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
4642
0
    } else if (*level == SCTP_FRAG_LEVEL_0) {
4643
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
4644
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
4645
4646
0
    } else {
4647
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4648
0
      error = EINVAL;
4649
0
    }
4650
5.65k
    break;
4651
5.65k
  }
4652
5.65k
  case SCTP_INTERLEAVING_SUPPORTED:
4653
5.65k
  {
4654
5.65k
    struct sctp_assoc_value *av;
4655
4656
5.65k
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4657
5.65k
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4658
4659
5.65k
    if (stcb) {
4660
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4661
0
      error = EINVAL;
4662
0
      SCTP_TCB_UNLOCK(stcb);
4663
5.65k
    } else {
4664
5.65k
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4665
5.65k
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4666
5.65k
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4667
5.65k
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4668
5.65k
        SCTP_INP_WLOCK(inp);
4669
5.65k
        if (av->assoc_value == 0) {
4670
0
          inp->idata_supported = 0;
4671
5.65k
        } else {
4672
5.65k
          if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) &&
4673
5.65k
              (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS))) {
4674
5.65k
            inp->idata_supported = 1;
4675
5.65k
          } else {
4676
            /* Must have Frag interleave and stream interleave on */
4677
0
            SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4678
0
            error = EINVAL;
4679
0
          }
4680
5.65k
        }
4681
5.65k
        SCTP_INP_WUNLOCK(inp);
4682
5.65k
      } else {
4683
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4684
0
        error = EINVAL;
4685
0
      }
4686
5.65k
    }
4687
5.65k
    break;
4688
5.65k
  }
4689
5.65k
  case SCTP_CMT_ON_OFF:
4690
0
    if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
4691
0
      struct sctp_assoc_value *av;
4692
4693
0
      SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4694
0
      if (av->assoc_value > SCTP_CMT_MAX) {
4695
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4696
0
        error = EINVAL;
4697
0
        break;
4698
0
      }
4699
0
      SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4700
0
      if (stcb) {
4701
0
        stcb->asoc.sctp_cmt_on_off = av->assoc_value;
4702
0
        SCTP_TCB_UNLOCK(stcb);
4703
0
      } else {
4704
0
        if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4705
0
            (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4706
0
            ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4707
0
             ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
4708
0
              (av->assoc_id == SCTP_ALL_ASSOC)))) {
4709
0
          SCTP_INP_WLOCK(inp);
4710
0
          inp->sctp_cmt_on_off = av->assoc_value;
4711
0
          SCTP_INP_WUNLOCK(inp);
4712
0
        }
4713
0
        if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4714
0
            ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4715
0
             (av->assoc_id == SCTP_ALL_ASSOC))) {
4716
0
          SCTP_INP_RLOCK(inp);
4717
0
          LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4718
0
            SCTP_TCB_LOCK(stcb);
4719
0
            stcb->asoc.sctp_cmt_on_off = av->assoc_value;
4720
0
            SCTP_TCB_UNLOCK(stcb);
4721
0
          }
4722
0
          SCTP_INP_RUNLOCK(inp);
4723
0
        }
4724
0
      }
4725
0
    } else {
4726
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
4727
0
      error = ENOPROTOOPT;
4728
0
    }
4729
0
    break;
4730
0
  case SCTP_PLUGGABLE_CC:
4731
0
  {
4732
0
    struct sctp_assoc_value *av;
4733
0
    struct sctp_nets *net;
4734
4735
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4736
0
    if ((av->assoc_value != SCTP_CC_RFC2581) &&
4737
0
        (av->assoc_value != SCTP_CC_HSTCP) &&
4738
0
        (av->assoc_value != SCTP_CC_HTCP) &&
4739
0
        (av->assoc_value != SCTP_CC_RTCC)) {
4740
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4741
0
      error = EINVAL;
4742
0
      break;
4743
0
    }
4744
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4745
0
    if (stcb) {
4746
0
      stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
4747
0
      stcb->asoc.congestion_control_module = av->assoc_value;
4748
0
      if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
4749
0
        TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4750
0
          stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
4751
0
        }
4752
0
      }
4753
0
      SCTP_TCB_UNLOCK(stcb);
4754
0
    } else {
4755
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4756
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4757
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4758
0
           ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
4759
0
            (av->assoc_id == SCTP_ALL_ASSOC)))) {
4760
0
        SCTP_INP_WLOCK(inp);
4761
0
        inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
4762
0
        SCTP_INP_WUNLOCK(inp);
4763
0
      }
4764
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4765
0
          ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4766
0
           (av->assoc_id == SCTP_ALL_ASSOC))) {
4767
0
        SCTP_INP_RLOCK(inp);
4768
0
        LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4769
0
          SCTP_TCB_LOCK(stcb);
4770
0
          stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
4771
0
          stcb->asoc.congestion_control_module = av->assoc_value;
4772
0
          if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
4773
0
            TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4774
0
              stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
4775
0
            }
4776
0
          }
4777
0
          SCTP_TCB_UNLOCK(stcb);
4778
0
        }
4779
0
        SCTP_INP_RUNLOCK(inp);
4780
0
      }
4781
0
    }
4782
0
    break;
4783
0
  }
4784
0
  case SCTP_CC_OPTION:
4785
0
  {
4786
0
    struct sctp_cc_option *cc_opt;
4787
4788
0
    SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
4789
0
    SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
4790
0
    if (stcb == NULL) {
4791
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4792
0
          (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC)) {
4793
0
        SCTP_INP_RLOCK(inp);
4794
0
        LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4795
0
          SCTP_TCB_LOCK(stcb);
4796
0
          if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
4797
0
            (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 1, cc_opt);
4798
0
          }
4799
0
          SCTP_TCB_UNLOCK(stcb);
4800
0
        }
4801
0
        SCTP_INP_RUNLOCK(inp);
4802
0
      } else {
4803
0
        error = EINVAL;
4804
0
      }
4805
0
    } else {
4806
0
      if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
4807
0
        error = ENOTSUP;
4808
0
      } else {
4809
0
        error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option)(stcb, 1,
4810
0
                         cc_opt);
4811
0
      }
4812
0
      SCTP_TCB_UNLOCK(stcb);
4813
0
    }
4814
0
    break;
4815
0
  }
4816
0
  case SCTP_STREAM_SCHEDULER:
4817
0
  {
4818
0
    struct sctp_assoc_value *av;
4819
4820
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4821
0
    if ((av->assoc_value != SCTP_SS_DEFAULT) &&
4822
0
        (av->assoc_value != SCTP_SS_RR) &&
4823
0
        (av->assoc_value != SCTP_SS_RR_PKT) &&
4824
0
        (av->assoc_value != SCTP_SS_PRIO) &&
4825
0
        (av->assoc_value != SCTP_SS_FB) &&
4826
0
        (av->assoc_value != SCTP_SS_FCFS)) {
4827
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4828
0
      error = EINVAL;
4829
0
      break;
4830
0
    }
4831
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4832
0
    if (stcb) {
4833
0
      stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, true);
4834
0
      stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
4835
0
      stcb->asoc.stream_scheduling_module = av->assoc_value;
4836
0
      stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc);
4837
0
      SCTP_TCB_UNLOCK(stcb);
4838
0
    } else {
4839
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4840
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4841
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4842
0
           ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
4843
0
            (av->assoc_id == SCTP_ALL_ASSOC)))) {
4844
0
        SCTP_INP_WLOCK(inp);
4845
0
        inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
4846
0
        SCTP_INP_WUNLOCK(inp);
4847
0
      }
4848
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4849
0
          ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4850
0
           (av->assoc_id == SCTP_ALL_ASSOC))) {
4851
0
        SCTP_INP_RLOCK(inp);
4852
0
        LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4853
0
          SCTP_TCB_LOCK(stcb);
4854
0
          stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, true);
4855
0
          stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
4856
0
          stcb->asoc.stream_scheduling_module = av->assoc_value;
4857
0
          stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc);
4858
0
          SCTP_TCB_UNLOCK(stcb);
4859
0
        }
4860
0
        SCTP_INP_RUNLOCK(inp);
4861
0
      }
4862
0
    }
4863
0
    break;
4864
0
  }
4865
0
  case SCTP_STREAM_SCHEDULER_VALUE:
4866
0
  {
4867
0
    struct sctp_stream_value *av;
4868
4869
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
4870
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4871
0
    if (stcb) {
4872
0
      if ((av->stream_id >= stcb->asoc.streamoutcnt) ||
4873
0
          (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
4874
0
                                                     av->stream_value) < 0)) {
4875
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4876
0
        error = EINVAL;
4877
0
      }
4878
0
      SCTP_TCB_UNLOCK(stcb);
4879
0
    } else {
4880
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4881
0
          (av->assoc_id == SCTP_CURRENT_ASSOC)) {
4882
0
        SCTP_INP_RLOCK(inp);
4883
0
        LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4884
0
          SCTP_TCB_LOCK(stcb);
4885
0
          if (av->stream_id < stcb->asoc.streamoutcnt) {
4886
0
            stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
4887
0
                                                      &stcb->asoc,
4888
0
                                                      &stcb->asoc.strmout[av->stream_id],
4889
0
                                                      av->stream_value);
4890
0
          }
4891
0
          SCTP_TCB_UNLOCK(stcb);
4892
0
        }
4893
0
        SCTP_INP_RUNLOCK(inp);
4894
0
      } else {
4895
        /* Can't set stream value without association */
4896
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4897
0
        error = EINVAL;
4898
0
      }
4899
0
    }
4900
0
    break;
4901
0
  }
4902
0
  case SCTP_CLR_STAT_LOG:
4903
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4904
0
    error = EOPNOTSUPP;
4905
0
    break;
4906
0
  case SCTP_CONTEXT:
4907
0
  {
4908
0
    struct sctp_assoc_value *av;
4909
4910
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4911
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4912
4913
0
    if (stcb) {
4914
0
      stcb->asoc.context = av->assoc_value;
4915
0
      SCTP_TCB_UNLOCK(stcb);
4916
0
    } else {
4917
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4918
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4919
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4920
0
           ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
4921
0
            (av->assoc_id == SCTP_ALL_ASSOC)))) {
4922
0
        SCTP_INP_WLOCK(inp);
4923
0
        inp->sctp_context = av->assoc_value;
4924
0
        SCTP_INP_WUNLOCK(inp);
4925
0
      }
4926
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4927
0
          ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4928
0
           (av->assoc_id == SCTP_ALL_ASSOC))) {
4929
0
        SCTP_INP_RLOCK(inp);
4930
0
        LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4931
0
          SCTP_TCB_LOCK(stcb);
4932
0
          stcb->asoc.context = av->assoc_value;
4933
0
          SCTP_TCB_UNLOCK(stcb);
4934
0
        }
4935
0
        SCTP_INP_RUNLOCK(inp);
4936
0
      }
4937
0
    }
4938
0
    break;
4939
0
  }
4940
0
  case SCTP_VRF_ID:
4941
0
  {
4942
0
    uint32_t *default_vrfid;
4943
#ifdef SCTP_MVRF
4944
    int i;
4945
#endif
4946
0
    SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
4947
0
    if (*default_vrfid > SCTP_MAX_VRF_ID) {
4948
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4949
0
      error = EINVAL;
4950
0
      break;
4951
0
    }
4952
#ifdef SCTP_MVRF
4953
    for (i = 0; i < inp->num_vrfs; i++) {
4954
      /* The VRF must be in the VRF list */
4955
      if (*default_vrfid == inp->m_vrf_ids[i]) {
4956
        SCTP_INP_WLOCK(inp);
4957
        inp->def_vrf_id = *default_vrfid;
4958
        SCTP_INP_WUNLOCK(inp);
4959
        goto sctp_done;
4960
      }
4961
    }
4962
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4963
    error = EINVAL;
4964
#else
4965
0
    inp->def_vrf_id = *default_vrfid;
4966
0
#endif
4967
#ifdef SCTP_MVRF
4968
  sctp_done:
4969
#endif
4970
0
    break;
4971
0
  }
4972
0
  case SCTP_DEL_VRF_ID:
4973
0
  {
4974
#ifdef SCTP_MVRF
4975
    uint32_t *del_vrfid;
4976
    int i, fnd = 0;
4977
4978
    SCTP_CHECK_AND_CAST(del_vrfid, optval, uint32_t, optsize);
4979
    if (*del_vrfid > SCTP_MAX_VRF_ID) {
4980
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4981
      error = EINVAL;
4982
      break;
4983
    }
4984
    if (inp->num_vrfs == 1) {
4985
      /* Can't delete last one */
4986
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4987
      error = EINVAL;
4988
      break;
4989
    }
4990
    if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
4991
      /* Can't add more once you are bound */
4992
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4993
      error = EINVAL;
4994
      break;
4995
    }
4996
    SCTP_INP_WLOCK(inp);
4997
    for (i = 0; i < inp->num_vrfs; i++) {
4998
      if (*del_vrfid == inp->m_vrf_ids[i]) {
4999
        fnd = 1;
5000
        break;
5001
      }
5002
    }
5003
    if (!fnd) {
5004
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5005
      error = EINVAL;
5006
      break;
5007
    }
5008
    if (i != (inp->num_vrfs - 1)) {
5009
      /* Take bottom one and move to this slot */
5010
      inp->m_vrf_ids[i] = inp->m_vrf_ids[(inp->num_vrfs-1)];
5011
    }
5012
    if (*del_vrfid == inp->def_vrf_id) {
5013
      /* Take the first one as the new default */
5014
      inp->def_vrf_id = inp->m_vrf_ids[0];
5015
    }
5016
    /* Drop the number by one killing last one */
5017
    inp->num_vrfs--;
5018
#else
5019
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5020
0
    error = EOPNOTSUPP;
5021
0
#endif
5022
0
    break;
5023
0
  }
5024
0
  case SCTP_ADD_VRF_ID:
5025
0
  {
5026
#ifdef SCTP_MVRF
5027
    uint32_t *add_vrfid;
5028
    int i;
5029
5030
    SCTP_CHECK_AND_CAST(add_vrfid, optval, uint32_t, optsize);
5031
    if (*add_vrfid > SCTP_MAX_VRF_ID) {
5032
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5033
      error = EINVAL;
5034
      break;
5035
    }
5036
    if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
5037
      /* Can't add more once you are bound */
5038
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5039
      error = EINVAL;
5040
      break;
5041
    }
5042
    SCTP_INP_WLOCK(inp);
5043
    /* Verify its not already here */
5044
    for (i = 0; i < inp->num_vrfs; i++) {
5045
      if (*add_vrfid == inp->m_vrf_ids[i]) {
5046
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5047
        error = EALREADY;
5048
        SCTP_INP_WUNLOCK(inp);
5049
        break;
5050
      }
5051
    }
5052
    if ((inp->num_vrfs + 1) > inp->vrf_size) {
5053
      /* need to grow array */
5054
      uint32_t *tarray;
5055
      SCTP_MALLOC(tarray, uint32_t *,
5056
            (sizeof(uint32_t) * (inp->vrf_size + SCTP_DEFAULT_VRF_SIZE)),
5057
            SCTP_M_MVRF);
5058
      if (tarray == NULL) {
5059
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
5060
        error = ENOMEM;
5061
        SCTP_INP_WUNLOCK(inp);
5062
        break;
5063
      }
5064
      memcpy(tarray, inp->m_vrf_ids, (sizeof(uint32_t) * inp->vrf_size));
5065
      SCTP_FREE(inp->m_vrf_ids, SCTP_M_MVRF);
5066
      inp->m_vrf_ids = tarray;
5067
      inp->vrf_size += SCTP_DEFAULT_VRF_SIZE;
5068
    }
5069
    inp->m_vrf_ids[inp->num_vrfs] = *add_vrfid;
5070
    inp->num_vrfs++;
5071
    SCTP_INP_WUNLOCK(inp);
5072
#else
5073
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5074
0
    error = EOPNOTSUPP;
5075
0
#endif
5076
0
    break;
5077
0
  }
5078
0
  case SCTP_DELAYED_SACK:
5079
0
  {
5080
0
    struct sctp_sack_info *sack;
5081
5082
0
    SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize);
5083
0
    SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
5084
0
    if (sack->sack_delay) {
5085
0
      if (sack->sack_delay > SCTP_MAX_SACK_DELAY) {
5086
0
        error = EINVAL;
5087
0
        if (stcb != NULL) {
5088
0
          SCTP_TCB_UNLOCK(stcb);
5089
0
        }
5090
0
        break;
5091
0
      }
5092
0
    }
5093
0
    if (stcb) {
5094
0
      if (sack->sack_delay) {
5095
0
        stcb->asoc.delayed_ack = sack->sack_delay;
5096
0
      }
5097
0
      if (sack->sack_freq) {
5098
0
        stcb->asoc.sack_freq = sack->sack_freq;
5099
0
      }
5100
0
      SCTP_TCB_UNLOCK(stcb);
5101
0
    } else {
5102
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5103
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5104
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5105
0
           ((sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
5106
0
            (sack->sack_assoc_id == SCTP_ALL_ASSOC)))) {
5107
0
        SCTP_INP_WLOCK(inp);
5108
0
        if (sack->sack_delay) {
5109
0
          inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = sctp_msecs_to_ticks(sack->sack_delay);
5110
0
        }
5111
0
        if (sack->sack_freq) {
5112
0
          inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
5113
0
        }
5114
0
        SCTP_INP_WUNLOCK(inp);
5115
0
      }
5116
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5117
0
          ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
5118
0
           (sack->sack_assoc_id == SCTP_ALL_ASSOC))) {
5119
0
        SCTP_INP_RLOCK(inp);
5120
0
        LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5121
0
          SCTP_TCB_LOCK(stcb);
5122
0
          if (sack->sack_delay) {
5123
0
            stcb->asoc.delayed_ack = sack->sack_delay;
5124
0
          }
5125
0
          if (sack->sack_freq) {
5126
0
            stcb->asoc.sack_freq = sack->sack_freq;
5127
0
          }
5128
0
          SCTP_TCB_UNLOCK(stcb);
5129
0
        }
5130
0
        SCTP_INP_RUNLOCK(inp);
5131
0
      }
5132
0
    }
5133
0
    break;
5134
0
  }
5135
0
  case SCTP_AUTH_CHUNK:
5136
0
  {
5137
0
    struct sctp_authchunk *sauth;
5138
5139
0
    SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
5140
5141
0
    SCTP_INP_WLOCK(inp);
5142
0
    if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
5143
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5144
0
      error = EINVAL;
5145
0
    } else {
5146
0
      inp->auth_supported = 1;
5147
0
    }
5148
0
    SCTP_INP_WUNLOCK(inp);
5149
0
    break;
5150
0
  }
5151
0
  case SCTP_AUTH_KEY:
5152
0
  {
5153
0
    struct sctp_authkey *sca;
5154
0
    struct sctp_keyhead *shared_keys;
5155
0
    sctp_sharedkey_t *shared_key;
5156
0
    sctp_key_t *key = NULL;
5157
0
    size_t size;
5158
5159
0
    SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
5160
0
    if (sca->sca_keylength == 0) {
5161
0
      size = optsize - sizeof(struct sctp_authkey);
5162
0
    } else {
5163
0
      if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
5164
0
        size = sca->sca_keylength;
5165
0
      } else {
5166
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5167
0
        error = EINVAL;
5168
0
        break;
5169
0
      }
5170
0
    }
5171
0
    SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
5172
5173
0
    if (stcb) {
5174
0
      shared_keys = &stcb->asoc.shared_keys;
5175
      /* clear the cached keys for this key id */
5176
0
      sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
5177
      /*
5178
       * create the new shared key and
5179
       * insert/replace it
5180
       */
5181
0
      if (size > 0) {
5182
0
        key = sctp_set_key(sca->sca_key, (uint32_t) size);
5183
0
        if (key == NULL) {
5184
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
5185
0
          error = ENOMEM;
5186
0
          SCTP_TCB_UNLOCK(stcb);
5187
0
          break;
5188
0
        }
5189
0
      }
5190
0
      shared_key = sctp_alloc_sharedkey();
5191
0
      if (shared_key == NULL) {
5192
0
        sctp_free_key(key);
5193
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
5194
0
        error = ENOMEM;
5195
0
        SCTP_TCB_UNLOCK(stcb);
5196
0
        break;
5197
0
      }
5198
0
      shared_key->key = key;
5199
0
      shared_key->keyid = sca->sca_keynumber;
5200
0
      error = sctp_insert_sharedkey(shared_keys, shared_key);
5201
0
      SCTP_TCB_UNLOCK(stcb);
5202
0
    } else {
5203
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5204
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5205
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5206
0
           ((sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
5207
0
            (sca->sca_assoc_id == SCTP_ALL_ASSOC)))) {
5208
0
        SCTP_INP_WLOCK(inp);
5209
0
        shared_keys = &inp->sctp_ep.shared_keys;
5210
        /*
5211
         * clear the cached keys on all assocs for
5212
         * this key id
5213
         */
5214
0
        sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
5215
        /*
5216
         * create the new shared key and
5217
         * insert/replace it
5218
         */
5219
0
        if (size > 0) {
5220
0
          key = sctp_set_key(sca->sca_key, (uint32_t) size);
5221
0
          if (key == NULL) {
5222
0
            SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
5223
0
            error = ENOMEM;
5224
0
            SCTP_INP_WUNLOCK(inp);
5225
0
            break;
5226
0
          }
5227
0
        }
5228
0
        shared_key = sctp_alloc_sharedkey();
5229
0
        if (shared_key == NULL) {
5230
0
          sctp_free_key(key);
5231
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
5232
0
          error = ENOMEM;
5233
0
          SCTP_INP_WUNLOCK(inp);
5234
0
          break;
5235
0
        }
5236
0
        shared_key->key = key;
5237
0
        shared_key->keyid = sca->sca_keynumber;
5238
0
        error = sctp_insert_sharedkey(shared_keys, shared_key);
5239
0
        SCTP_INP_WUNLOCK(inp);
5240
0
      }
5241
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5242
0
          ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
5243
0
           (sca->sca_assoc_id == SCTP_ALL_ASSOC))) {
5244
0
        SCTP_INP_RLOCK(inp);
5245
0
        LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5246
0
          SCTP_TCB_LOCK(stcb);
5247
0
          shared_keys = &stcb->asoc.shared_keys;
5248
          /* clear the cached keys for this key id */
5249
0
          sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
5250
          /*
5251
           * create the new shared key and
5252
           * insert/replace it
5253
           */
5254
0
          if (size > 0) {
5255
0
            key = sctp_set_key(sca->sca_key, (uint32_t) size);
5256
0
            if (key == NULL) {
5257
0
              SCTP_TCB_UNLOCK(stcb);
5258
0
              continue;
5259
0
            }
5260
0
          }
5261
0
          shared_key = sctp_alloc_sharedkey();
5262
0
          if (shared_key == NULL) {
5263
0
            sctp_free_key(key);
5264
0
            SCTP_TCB_UNLOCK(stcb);
5265
0
            continue;
5266
0
          }
5267
0
          shared_key->key = key;
5268
0
          shared_key->keyid = sca->sca_keynumber;
5269
0
          error = sctp_insert_sharedkey(shared_keys, shared_key);
5270
0
          SCTP_TCB_UNLOCK(stcb);
5271
0
        }
5272
0
        SCTP_INP_RUNLOCK(inp);
5273
0
      }
5274
0
    }
5275
0
    break;
5276
0
  }
5277
0
  case SCTP_HMAC_IDENT:
5278
0
  {
5279
0
    struct sctp_hmacalgo *shmac;
5280
0
    sctp_hmaclist_t *hmaclist;
5281
0
    uint16_t hmacid;
5282
0
    uint32_t i;
5283
5284
0
    SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
5285
0
    if ((optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) ||
5286
0
        (shmac->shmac_number_of_idents > 0xffff)) {
5287
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5288
0
      error = EINVAL;
5289
0
      break;
5290
0
    }
5291
5292
0
    hmaclist = sctp_alloc_hmaclist((uint16_t)shmac->shmac_number_of_idents);
5293
0
    if (hmaclist == NULL) {
5294
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
5295
0
      error = ENOMEM;
5296
0
      break;
5297
0
    }
5298
0
    for (i = 0; i < shmac->shmac_number_of_idents; i++) {
5299
0
      hmacid = shmac->shmac_idents[i];
5300
0
      if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
5301
0
        /* invalid HMACs were found */;
5302
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5303
0
        error = EINVAL;
5304
0
        sctp_free_hmaclist(hmaclist);
5305
0
        goto sctp_set_hmac_done;
5306
0
      }
5307
0
    }
5308
0
    for (i = 0; i < hmaclist->num_algo; i++) {
5309
0
      if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
5310
        /* already in list */
5311
0
        break;
5312
0
      }
5313
0
    }
5314
0
    if (i == hmaclist->num_algo) {
5315
      /* not found in list */
5316
0
      sctp_free_hmaclist(hmaclist);
5317
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5318
0
      error = EINVAL;
5319
0
      break;
5320
0
    }
5321
    /* set it on the endpoint */
5322
0
    SCTP_INP_WLOCK(inp);
5323
0
    if (inp->sctp_ep.local_hmacs)
5324
0
      sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
5325
0
    inp->sctp_ep.local_hmacs = hmaclist;
5326
0
    SCTP_INP_WUNLOCK(inp);
5327
0
  sctp_set_hmac_done:
5328
0
    break;
5329
0
  }
5330
0
  case SCTP_AUTH_ACTIVE_KEY:
5331
0
  {
5332
0
    struct sctp_authkeyid *scact;
5333
5334
0
    SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
5335
0
    SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
5336
5337
    /* set the active key on the right place */
5338
0
    if (stcb) {
5339
      /* set the active key on the assoc */
5340
0
      if (sctp_auth_setactivekey(stcb,
5341
0
               scact->scact_keynumber)) {
5342
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
5343
0
                SCTP_FROM_SCTP_USRREQ,
5344
0
                EINVAL);
5345
0
        error = EINVAL;
5346
0
      }
5347
0
      SCTP_TCB_UNLOCK(stcb);
5348
0
    } else {
5349
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5350
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5351
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5352
0
           ((scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
5353
0
            (scact->scact_assoc_id == SCTP_ALL_ASSOC)))) {
5354
0
        SCTP_INP_WLOCK(inp);
5355
0
        if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
5356
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5357
0
          error = EINVAL;
5358
0
        }
5359
0
        SCTP_INP_WUNLOCK(inp);
5360
0
      }
5361
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5362
0
          ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
5363
0
           (scact->scact_assoc_id == SCTP_ALL_ASSOC))) {
5364
0
        SCTP_INP_RLOCK(inp);
5365
0
        LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5366
0
          SCTP_TCB_LOCK(stcb);
5367
0
          sctp_auth_setactivekey(stcb, scact->scact_keynumber);
5368
0
          SCTP_TCB_UNLOCK(stcb);
5369
0
        }
5370
0
        SCTP_INP_RUNLOCK(inp);
5371
0
      }
5372
0
    }
5373
0
    break;
5374
0
  }
5375
0
  case SCTP_AUTH_DELETE_KEY:
5376
0
  {
5377
0
    struct sctp_authkeyid *scdel;
5378
5379
0
    SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
5380
0
    SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
5381
5382
    /* delete the key from the right place */
5383
0
    if (stcb) {
5384
0
      if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
5385
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5386
0
        error = EINVAL;
5387
0
      }
5388
0
      SCTP_TCB_UNLOCK(stcb);
5389
0
    } else {
5390
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5391
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5392
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5393
0
           ((scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
5394
0
            (scdel->scact_assoc_id == SCTP_ALL_ASSOC)))) {
5395
0
        SCTP_INP_WLOCK(inp);
5396
0
        if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
5397
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5398
0
          error = EINVAL;
5399
0
        }
5400
0
        SCTP_INP_WUNLOCK(inp);
5401
0
      }
5402
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5403
0
          ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
5404
0
           (scdel->scact_assoc_id == SCTP_ALL_ASSOC))) {
5405
0
        SCTP_INP_RLOCK(inp);
5406
0
        LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5407
0
          SCTP_TCB_LOCK(stcb);
5408
0
          sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
5409
0
          SCTP_TCB_UNLOCK(stcb);
5410
0
        }
5411
0
        SCTP_INP_RUNLOCK(inp);
5412
0
      }
5413
0
    }
5414
0
    break;
5415
0
  }
5416
0
  case SCTP_AUTH_DEACTIVATE_KEY:
5417
0
  {
5418
0
    struct sctp_authkeyid *keyid;
5419
5420
0
    SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
5421
0
    SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
5422
5423
    /* deactivate the key from the right place */
5424
0
    if (stcb) {
5425
0
      if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
5426
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5427
0
        error = EINVAL;
5428
0
      }
5429
0
      SCTP_TCB_UNLOCK(stcb);
5430
0
    } else {
5431
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5432
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5433
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5434
0
           ((keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
5435
0
            (keyid->scact_assoc_id == SCTP_ALL_ASSOC)))) {
5436
0
        SCTP_INP_WLOCK(inp);
5437
0
        if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
5438
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5439
0
          error = EINVAL;
5440
0
        }
5441
0
        SCTP_INP_WUNLOCK(inp);
5442
0
      }
5443
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5444
0
          ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
5445
0
           (keyid->scact_assoc_id == SCTP_ALL_ASSOC))) {
5446
0
        SCTP_INP_RLOCK(inp);
5447
0
        LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5448
0
          SCTP_TCB_LOCK(stcb);
5449
0
          sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
5450
0
          SCTP_TCB_UNLOCK(stcb);
5451
0
        }
5452
0
        SCTP_INP_RUNLOCK(inp);
5453
0
      }
5454
0
    }
5455
0
    break;
5456
0
  }
5457
9.87k
  case SCTP_ENABLE_STREAM_RESET:
5458
9.87k
  {
5459
9.87k
    struct sctp_assoc_value *av;
5460
5461
9.87k
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
5462
9.87k
    if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) {
5463
0
            SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5464
0
      error = EINVAL;
5465
0
      break;
5466
0
    }
5467
9.87k
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
5468
9.87k
    if (stcb) {
5469
0
      stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
5470
0
      SCTP_TCB_UNLOCK(stcb);
5471
9.87k
    } else {
5472
9.87k
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5473
9.87k
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5474
9.87k
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5475
0
           ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
5476
9.87k
            (av->assoc_id == SCTP_ALL_ASSOC)))) {
5477
9.87k
        SCTP_INP_WLOCK(inp);
5478
9.87k
        inp->local_strreset_support = (uint8_t)av->assoc_value;
5479
9.87k
        SCTP_INP_WUNLOCK(inp);
5480
9.87k
      }
5481
9.87k
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5482
9.87k
          ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
5483
0
           (av->assoc_id == SCTP_ALL_ASSOC))) {
5484
0
        SCTP_INP_RLOCK(inp);
5485
0
        LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5486
0
          SCTP_TCB_LOCK(stcb);
5487
0
          stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
5488
0
          SCTP_TCB_UNLOCK(stcb);
5489
0
        }
5490
0
        SCTP_INP_RUNLOCK(inp);
5491
0
      }
5492
9.87k
    }
5493
9.87k
    break;
5494
9.87k
  }
5495
9.87k
  case SCTP_RESET_STREAMS:
5496
2.19k
  {
5497
2.19k
    struct sctp_reset_streams *strrst;
5498
2.19k
    int i, send_out = 0;
5499
2.19k
    int send_in = 0;
5500
5501
2.19k
    SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize);
5502
2.19k
    SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id);
5503
2.19k
    if (stcb == NULL) {
5504
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5505
0
      error = ENOENT;
5506
0
      break;
5507
0
    }
5508
2.19k
    if (stcb->asoc.reconfig_supported == 0) {
5509
      /*
5510
       * Peer does not support the chunk type.
5511
       */
5512
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5513
0
      error = EOPNOTSUPP;
5514
0
      SCTP_TCB_UNLOCK(stcb);
5515
0
      break;
5516
0
    }
5517
2.19k
    if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) {
5518
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5519
0
      error = EINVAL;
5520
0
      SCTP_TCB_UNLOCK(stcb);
5521
0
      break;
5522
0
    }
5523
2.19k
    if (sizeof(struct sctp_reset_streams) +
5524
2.19k
        strrst->srs_number_streams * sizeof(uint16_t) > optsize) {
5525
0
      error = EINVAL;
5526
0
      SCTP_TCB_UNLOCK(stcb);
5527
0
      break;
5528
0
    }
5529
2.19k
    if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
5530
2.19k
      send_in = 1;
5531
2.19k
      if (stcb->asoc.stream_reset_outstanding) {
5532
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5533
0
        error = EALREADY;
5534
0
        SCTP_TCB_UNLOCK(stcb);
5535
0
        break;
5536
0
      }
5537
2.19k
    }
5538
2.19k
    if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
5539
2.19k
      send_out = 1;
5540
2.19k
    }
5541
2.19k
    if ((strrst->srs_number_streams > SCTP_MAX_STREAMS_AT_ONCE_RESET) && send_in) {
5542
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
5543
0
      error = ENOMEM;
5544
0
      SCTP_TCB_UNLOCK(stcb);
5545
0
      break;
5546
0
    }
5547
2.19k
    if ((send_in == 0) && (send_out == 0)) {
5548
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5549
0
      error = EINVAL;
5550
0
      SCTP_TCB_UNLOCK(stcb);
5551
0
      break;
5552
0
    }
5553
2.19k
    for (i = 0; i < strrst->srs_number_streams; i++) {
5554
0
      if ((send_in) &&
5555
0
          (strrst->srs_stream_list[i] >= stcb->asoc.streamincnt)) {
5556
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5557
0
        error = EINVAL;
5558
0
        break;
5559
0
      }
5560
0
      if ((send_out) &&
5561
0
          (strrst->srs_stream_list[i] >= stcb->asoc.streamoutcnt)) {
5562
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5563
0
        error = EINVAL;
5564
0
        break;
5565
0
      }
5566
0
    }
5567
2.19k
    if (error) {
5568
0
      SCTP_TCB_UNLOCK(stcb);
5569
0
      break;
5570
0
    }
5571
2.19k
    if (send_out) {
5572
2.19k
      int cnt;
5573
2.19k
      uint16_t strm;
5574
2.19k
      if (strrst->srs_number_streams) {
5575
0
        for (i = 0, cnt = 0; i < strrst->srs_number_streams; i++) {
5576
0
          strm = strrst->srs_stream_list[i];
5577
0
          if (stcb->asoc.strmout[strm].state == SCTP_STREAM_OPEN) {
5578
0
            stcb->asoc.strmout[strm].state = SCTP_STREAM_RESET_PENDING;
5579
0
            cnt++;
5580
0
          }
5581
0
        }
5582
2.19k
      } else {
5583
        /* Its all */
5584
567k
        for (i = 0, cnt = 0; i < stcb->asoc.streamoutcnt; i++) {
5585
565k
          if (stcb->asoc.strmout[i].state == SCTP_STREAM_OPEN) {
5586
565k
            stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_PENDING;
5587
565k
            cnt++;
5588
565k
          }
5589
565k
        }
5590
2.19k
      }
5591
2.19k
    }
5592
2.19k
    if (send_in) {
5593
2.19k
      error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
5594
2.19k
              strrst->srs_stream_list,
5595
2.19k
              send_in, 0, 0, 0, 0, 0);
5596
2.19k
    } else {
5597
0
      error = sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_LOCKED);
5598
0
    }
5599
2.19k
    if (error == 0) {
5600
2.19k
      sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
5601
2.19k
    } else {
5602
       /*
5603
        * For outgoing streams don't report any problems in
5604
        * sending the request to the application.
5605
        * XXX: Double check resetting incoming streams.
5606
        */
5607
0
      error = 0;
5608
0
    }
5609
2.19k
    SCTP_TCB_UNLOCK(stcb);
5610
2.19k
    break;
5611
2.19k
  }
5612
2.19k
  case SCTP_ADD_STREAMS:
5613
0
  {
5614
0
    struct sctp_add_streams *stradd;
5615
0
    uint8_t addstream = 0;
5616
0
    uint16_t add_o_strmcnt = 0;
5617
0
    uint16_t add_i_strmcnt = 0;
5618
5619
0
    SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
5620
0
    SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
5621
0
    if (stcb == NULL) {
5622
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5623
0
      error = ENOENT;
5624
0
      break;
5625
0
    }
5626
0
    if (stcb->asoc.reconfig_supported == 0) {
5627
      /*
5628
       * Peer does not support the chunk type.
5629
       */
5630
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5631
0
      error = EOPNOTSUPP;
5632
0
      SCTP_TCB_UNLOCK(stcb);
5633
0
      break;
5634
0
    }
5635
0
    if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) {
5636
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5637
0
      error = EINVAL;
5638
0
      SCTP_TCB_UNLOCK(stcb);
5639
0
      break;
5640
0
    }
5641
0
    if (stcb->asoc.stream_reset_outstanding) {
5642
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5643
0
      error = EALREADY;
5644
0
      SCTP_TCB_UNLOCK(stcb);
5645
0
      break;
5646
0
    }
5647
0
    if ((stradd->sas_outstrms == 0) &&
5648
0
        (stradd->sas_instrms == 0)) {
5649
0
      error = EINVAL;
5650
0
      goto skip_stuff;
5651
0
    }
5652
0
    if (stradd->sas_outstrms) {
5653
0
      addstream = 1;
5654
      /* We allocate here */
5655
0
      add_o_strmcnt = stradd->sas_outstrms;
5656
0
      if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
5657
        /* You can't have more than 64k */
5658
0
        error = EINVAL;
5659
0
        goto skip_stuff;
5660
0
      }
5661
0
    }
5662
0
    if (stradd->sas_instrms) {
5663
0
      int cnt;
5664
5665
0
      addstream |= 2;
5666
      /* We allocate inside sctp_send_str_reset_req() */
5667
0
      add_i_strmcnt = stradd->sas_instrms;
5668
0
      cnt = add_i_strmcnt;
5669
0
      cnt += stcb->asoc.streamincnt;
5670
0
      if (cnt > 0x0000ffff) {
5671
        /* You can't have more than 64k */
5672
0
        error = EINVAL;
5673
0
        goto skip_stuff;
5674
0
      }
5675
0
      if (cnt > (int)stcb->asoc.max_inbound_streams) {
5676
        /* More than you are allowed */
5677
0
        error = EINVAL;
5678
0
        goto skip_stuff;
5679
0
      }
5680
0
    }
5681
0
    error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
5682
0
    sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
5683
0
  skip_stuff:
5684
0
    SCTP_TCB_UNLOCK(stcb);
5685
0
    break;
5686
0
  }
5687
0
  case SCTP_RESET_ASSOC:
5688
0
  {
5689
0
    int i;
5690
0
    uint32_t *value;
5691
5692
0
    SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
5693
0
    SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) *value);
5694
0
    if (stcb == NULL) {
5695
0
            SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5696
0
      error = ENOENT;
5697
0
      break;
5698
0
    }
5699
0
    if (stcb->asoc.reconfig_supported == 0) {
5700
      /*
5701
       * Peer does not support the chunk type.
5702
       */
5703
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
5704
0
      error = EOPNOTSUPP;
5705
0
      SCTP_TCB_UNLOCK(stcb);
5706
0
      break;
5707
0
    }
5708
0
    if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) {
5709
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5710
0
      error = EINVAL;
5711
0
      SCTP_TCB_UNLOCK(stcb);
5712
0
      break;
5713
0
    }
5714
0
    if (stcb->asoc.stream_reset_outstanding) {
5715
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5716
0
      error = EALREADY;
5717
0
      SCTP_TCB_UNLOCK(stcb);
5718
0
      break;
5719
0
    }
5720
    /* Is there any data pending in the send or sent queues? */
5721
0
    if (!TAILQ_EMPTY(&stcb->asoc.send_queue) ||
5722
0
        !TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
5723
0
    busy_out:
5724
0
      error = EBUSY;
5725
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5726
0
      SCTP_TCB_UNLOCK(stcb);
5727
0
      break;
5728
0
    }
5729
    /* Do any streams have data queued? */
5730
0
    for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
5731
0
      if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) {
5732
0
        goto busy_out;
5733
0
      }
5734
0
    }
5735
0
    error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 1, 0, 0, 0, 0);
5736
0
    sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
5737
0
    SCTP_TCB_UNLOCK(stcb);
5738
0
    break;
5739
0
  }
5740
0
  case SCTP_CONNECT_X:
5741
0
    if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
5742
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5743
0
      error = EINVAL;
5744
0
      break;
5745
0
    }
5746
0
    error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
5747
0
    break;
5748
0
  case SCTP_CONNECT_X_DELAYED:
5749
0
    if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
5750
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5751
0
      error = EINVAL;
5752
0
      break;
5753
0
    }
5754
0
    error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
5755
0
    break;
5756
0
  case SCTP_CONNECT_X_COMPLETE:
5757
0
  {
5758
0
    struct sockaddr *sa;
5759
5760
    /* FIXME MT: check correct? */
5761
0
    SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
5762
5763
    /* find tcb */
5764
0
    if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
5765
0
      SCTP_INP_RLOCK(inp);
5766
0
      stcb = LIST_FIRST(&inp->sctp_asoc_list);
5767
0
      if (stcb) {
5768
0
        SCTP_TCB_LOCK(stcb);
5769
0
      }
5770
0
      SCTP_INP_RUNLOCK(inp);
5771
0
    } else {
5772
      /* We increment here since sctp_findassociation_ep_addr() wil
5773
       * do a decrement if it finds the stcb as long as the locked
5774
       * tcb (last argument) is NOT a TCB.. aka NULL.
5775
       */
5776
0
      SCTP_INP_INCR_REF(inp);
5777
0
      stcb = sctp_findassociation_ep_addr(&inp, sa, NULL, NULL, NULL);
5778
0
      if (stcb == NULL) {
5779
0
        SCTP_INP_DECR_REF(inp);
5780
0
      }
5781
0
    }
5782
5783
0
    if (stcb == NULL) {
5784
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
5785
0
      error = ENOENT;
5786
0
      break;
5787
0
    }
5788
0
    if (stcb->asoc.delayed_connection == 1) {
5789
0
      stcb->asoc.delayed_connection = 0;
5790
0
      (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
5791
0
      sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
5792
0
          stcb->asoc.primary_destination,
5793
0
          SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8);
5794
0
      sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
5795
0
    } else {
5796
      /*
5797
       * already expired or did not use delayed
5798
       * connectx
5799
       */
5800
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
5801
0
      error = EALREADY;
5802
0
    }
5803
0
    SCTP_TCB_UNLOCK(stcb);
5804
0
    break;
5805
0
  }
5806
0
  case SCTP_MAX_BURST:
5807
0
  {
5808
0
    struct sctp_assoc_value *av;
5809
5810
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
5811
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
5812
5813
0
    if (stcb) {
5814
0
      stcb->asoc.max_burst = av->assoc_value;
5815
0
      SCTP_TCB_UNLOCK(stcb);
5816
0
    } else {
5817
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5818
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5819
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5820
0
           ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
5821
0
            (av->assoc_id == SCTP_ALL_ASSOC)))) {
5822
0
        SCTP_INP_WLOCK(inp);
5823
0
        inp->sctp_ep.max_burst = av->assoc_value;
5824
0
        SCTP_INP_WUNLOCK(inp);
5825
0
      }
5826
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5827
0
          ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
5828
0
           (av->assoc_id == SCTP_ALL_ASSOC))) {
5829
0
        SCTP_INP_RLOCK(inp);
5830
0
        LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5831
0
          SCTP_TCB_LOCK(stcb);
5832
0
          stcb->asoc.max_burst = av->assoc_value;
5833
0
          SCTP_TCB_UNLOCK(stcb);
5834
0
        }
5835
0
        SCTP_INP_RUNLOCK(inp);
5836
0
      }
5837
0
    }
5838
0
    break;
5839
0
  }
5840
0
  case SCTP_MAXSEG:
5841
0
  {
5842
0
    struct sctp_assoc_value *av;
5843
5844
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
5845
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
5846
5847
0
    if (stcb) {
5848
0
      stcb->asoc.sctp_frag_point = av->assoc_value;
5849
0
      SCTP_TCB_UNLOCK(stcb);
5850
0
    } else {
5851
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5852
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5853
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5854
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
5855
0
        SCTP_INP_WLOCK(inp);
5856
0
        inp->sctp_frag_point = av->assoc_value;
5857
0
        SCTP_INP_WUNLOCK(inp);
5858
0
      } else {
5859
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5860
0
        error = EINVAL;
5861
0
      }
5862
0
    }
5863
0
    break;
5864
0
  }
5865
0
  case SCTP_EVENTS:
5866
0
  {
5867
0
    struct sctp_event_subscribe *events;
5868
5869
0
    SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
5870
5871
0
    SCTP_INP_WLOCK(inp);
5872
0
    if (events->sctp_data_io_event) {
5873
0
      sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
5874
0
    } else {
5875
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
5876
0
    }
5877
5878
0
    if (events->sctp_association_event) {
5879
0
      sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5880
0
    } else {
5881
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5882
0
    }
5883
5884
0
    if (events->sctp_address_event) {
5885
0
      sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
5886
0
    } else {
5887
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
5888
0
    }
5889
5890
0
    if (events->sctp_send_failure_event) {
5891
0
      sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5892
0
    } else {
5893
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5894
0
    }
5895
5896
0
    if (events->sctp_peer_error_event) {
5897
0
      sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
5898
0
    } else {
5899
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
5900
0
    }
5901
5902
0
    if (events->sctp_shutdown_event) {
5903
0
      sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5904
0
    } else {
5905
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5906
0
    }
5907
5908
0
    if (events->sctp_partial_delivery_event) {
5909
0
      sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
5910
0
    } else {
5911
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
5912
0
    }
5913
5914
0
    if (events->sctp_adaptation_layer_event) {
5915
0
      sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5916
0
    } else {
5917
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5918
0
    }
5919
5920
0
    if (events->sctp_authentication_event) {
5921
0
      sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
5922
0
    } else {
5923
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
5924
0
    }
5925
5926
0
    if (events->sctp_sender_dry_event) {
5927
0
      sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
5928
0
    } else {
5929
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
5930
0
    }
5931
5932
0
    if (events->sctp_stream_reset_event) {
5933
0
      sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5934
0
    } else {
5935
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5936
0
    }
5937
5938
0
    LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5939
0
      SCTP_TCB_LOCK(stcb);
5940
0
      if (events->sctp_association_event) {
5941
0
        sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5942
0
      } else {
5943
0
        sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5944
0
      }
5945
0
      if (events->sctp_address_event) {
5946
0
        sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
5947
0
      } else {
5948
0
        sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
5949
0
      }
5950
0
      if (events->sctp_send_failure_event) {
5951
0
        sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5952
0
      } else {
5953
0
        sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5954
0
      }
5955
0
      if (events->sctp_peer_error_event) {
5956
0
        sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
5957
0
      } else {
5958
0
        sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
5959
0
      }
5960
0
      if (events->sctp_shutdown_event) {
5961
0
        sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5962
0
      } else {
5963
0
        sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5964
0
      }
5965
0
      if (events->sctp_partial_delivery_event) {
5966
0
        sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
5967
0
      } else {
5968
0
        sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
5969
0
      }
5970
0
      if (events->sctp_adaptation_layer_event) {
5971
0
        sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5972
0
      } else {
5973
0
        sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5974
0
      }
5975
0
      if (events->sctp_authentication_event) {
5976
0
        sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
5977
0
      } else {
5978
0
        sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
5979
0
      }
5980
0
      if (events->sctp_sender_dry_event) {
5981
0
        sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
5982
0
      } else {
5983
0
        sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
5984
0
      }
5985
0
      if (events->sctp_stream_reset_event) {
5986
0
        sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5987
0
      } else {
5988
0
        sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5989
0
      }
5990
0
      SCTP_TCB_UNLOCK(stcb);
5991
0
    }
5992
    /* Send up the sender dry event only for 1-to-1 style sockets. */
5993
0
    if (events->sctp_sender_dry_event) {
5994
0
      if (((inp->sctp_flags & (SCTP_PCB_FLAGS_TCPTYPE | SCTP_PCB_FLAGS_IN_TCPPOOL)) != 0) &&
5995
0
          !SCTP_IS_LISTENING(inp)) {
5996
0
        stcb = LIST_FIRST(&inp->sctp_asoc_list);
5997
0
        if (stcb != NULL) {
5998
0
          SCTP_TCB_LOCK(stcb);
5999
0
          if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
6000
0
              TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
6001
0
              (stcb->asoc.stream_queue_cnt == 0)) {
6002
0
            sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
6003
0
          }
6004
0
          SCTP_TCB_UNLOCK(stcb);
6005
0
        }
6006
0
      }
6007
0
    }
6008
0
    SCTP_INP_WUNLOCK(inp);
6009
0
    break;
6010
0
  }
6011
0
  case SCTP_ADAPTATION_LAYER:
6012
0
  {
6013
0
    struct sctp_setadaptation *adap_bits;
6014
6015
0
    SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
6016
0
    SCTP_INP_WLOCK(inp);
6017
0
    inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
6018
0
    inp->sctp_ep.adaptation_layer_indicator_provided = 1;
6019
0
    SCTP_INP_WUNLOCK(inp);
6020
0
    break;
6021
0
  }
6022
#ifdef SCTP_DEBUG
6023
  case SCTP_SET_INITIAL_DBG_SEQ:
6024
  {
6025
    uint32_t *vvv;
6026
6027
    SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
6028
    SCTP_INP_WLOCK(inp);
6029
    inp->sctp_ep.initial_sequence_debug = *vvv;
6030
    SCTP_INP_WUNLOCK(inp);
6031
    break;
6032
  }
6033
#endif
6034
0
  case SCTP_DEFAULT_SEND_PARAM:
6035
0
  {
6036
0
    struct sctp_sndrcvinfo *s_info;
6037
6038
0
    SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
6039
0
    SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
6040
6041
0
    if (stcb) {
6042
0
      if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
6043
0
        memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
6044
0
      } else {
6045
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6046
0
        error = EINVAL;
6047
0
      }
6048
0
      SCTP_TCB_UNLOCK(stcb);
6049
0
    } else {
6050
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6051
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6052
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6053
0
           ((s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
6054
0
            (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)))) {
6055
0
        SCTP_INP_WLOCK(inp);
6056
0
        memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
6057
0
        SCTP_INP_WUNLOCK(inp);
6058
0
      }
6059
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6060
0
          ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
6061
0
           (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC))) {
6062
0
        SCTP_INP_RLOCK(inp);
6063
0
        LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6064
0
          SCTP_TCB_LOCK(stcb);
6065
0
          if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
6066
0
            memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
6067
0
          }
6068
0
          SCTP_TCB_UNLOCK(stcb);
6069
0
        }
6070
0
        SCTP_INP_RUNLOCK(inp);
6071
0
      }
6072
0
    }
6073
0
    break;
6074
0
  }
6075
0
  case SCTP_PEER_ADDR_PARAMS:
6076
0
  {
6077
0
    struct sctp_paddrparams *paddrp;
6078
0
    struct sctp_nets *net;
6079
0
    struct sockaddr *addr;
6080
0
#if defined(INET) && defined(INET6)
6081
0
    struct sockaddr_in sin_store;
6082
0
#endif
6083
6084
0
    SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
6085
0
    SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
6086
6087
0
#if defined(INET) && defined(INET6)
6088
0
    if (paddrp->spp_address.ss_family == AF_INET6) {
6089
0
      struct sockaddr_in6 *sin6;
6090
6091
0
      sin6 = (struct sockaddr_in6 *)&paddrp->spp_address;
6092
0
      if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
6093
0
        in6_sin6_2_sin(&sin_store, sin6);
6094
0
        addr = (struct sockaddr *)&sin_store;
6095
0
      } else {
6096
0
        addr = (struct sockaddr *)&paddrp->spp_address;
6097
0
      }
6098
0
    } else {
6099
0
      addr = (struct sockaddr *)&paddrp->spp_address;
6100
0
    }
6101
#else
6102
    addr = (struct sockaddr *)&paddrp->spp_address;
6103
#endif
6104
0
    if (stcb != NULL) {
6105
0
      net = sctp_findnet(stcb, addr);
6106
0
    } else {
6107
      /* We increment here since sctp_findassociation_ep_addr() wil
6108
       * do a decrement if it finds the stcb as long as the locked
6109
       * tcb (last argument) is NOT a TCB.. aka NULL.
6110
       */
6111
0
      net = NULL;
6112
0
      SCTP_INP_INCR_REF(inp);
6113
0
      stcb = sctp_findassociation_ep_addr(&inp, addr,
6114
0
                                          &net, NULL, NULL);
6115
0
      if (stcb == NULL) {
6116
0
        SCTP_INP_DECR_REF(inp);
6117
0
      }
6118
0
    }
6119
0
    if ((stcb != NULL) && (net == NULL)) {
6120
0
#ifdef INET
6121
0
      if (addr->sa_family == AF_INET) {
6122
0
        struct sockaddr_in *sin;
6123
6124
0
        sin = (struct sockaddr_in *)addr;
6125
0
        if (sin->sin_addr.s_addr != INADDR_ANY) {
6126
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6127
0
          SCTP_TCB_UNLOCK(stcb);
6128
0
          error = EINVAL;
6129
0
          break;
6130
0
        }
6131
0
      } else
6132
0
#endif
6133
0
#ifdef INET6
6134
0
      if (addr->sa_family == AF_INET6) {
6135
0
        struct sockaddr_in6 *sin6;
6136
6137
0
        sin6 = (struct sockaddr_in6 *)addr;
6138
0
        if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6139
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6140
0
          SCTP_TCB_UNLOCK(stcb);
6141
0
          error = EINVAL;
6142
0
          break;
6143
0
        }
6144
0
      } else
6145
0
#endif
6146
0
#if defined(__Userspace__)
6147
0
      if (addr->sa_family == AF_CONN) {
6148
0
        struct sockaddr_conn *sconn;
6149
6150
0
        sconn = (struct sockaddr_conn *)addr;
6151
0
        if (sconn->sconn_addr != NULL) {
6152
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6153
0
          SCTP_TCB_UNLOCK(stcb);
6154
0
          error = EINVAL;
6155
0
          break;
6156
0
        }
6157
0
      } else
6158
0
#endif
6159
0
      {
6160
0
        error = EAFNOSUPPORT;
6161
0
        SCTP_TCB_UNLOCK(stcb);
6162
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6163
0
        break;
6164
0
      }
6165
0
    }
6166
    /* sanity checks */
6167
0
    if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
6168
0
      if (stcb)
6169
0
        SCTP_TCB_UNLOCK(stcb);
6170
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6171
0
      return (EINVAL);
6172
0
    }
6173
6174
0
    if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
6175
0
      if (stcb)
6176
0
        SCTP_TCB_UNLOCK(stcb);
6177
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6178
0
      return (EINVAL);
6179
0
    }
6180
0
    if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) &&
6181
0
        (paddrp->spp_pathmtu > 0) &&
6182
0
        ((paddrp->spp_pathmtu < SCTP_SMALLEST_PMTU) ||
6183
0
         (paddrp->spp_pathmtu > SCTP_LARGEST_PMTU))) {
6184
0
      if (stcb)
6185
0
        SCTP_TCB_UNLOCK(stcb);
6186
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6187
0
      return (EINVAL);
6188
0
    }
6189
6190
0
    if (stcb != NULL) {
6191
      /************************TCB SPECIFIC SET ******************/
6192
0
      if (net != NULL) {
6193
        /************************NET SPECIFIC SET ******************/
6194
0
        if (paddrp->spp_flags & SPP_HB_DISABLE) {
6195
0
          if (((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) &&
6196
0
              ((net->dest_state & SCTP_ADDR_NOHB) == 0)) {
6197
0
            sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
6198
0
                            SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9);
6199
0
          }
6200
0
          net->dest_state |= SCTP_ADDR_NOHB;
6201
0
        }
6202
0
        if (paddrp->spp_flags & SPP_HB_ENABLE) {
6203
0
          if (paddrp->spp_hbinterval) {
6204
0
            net->heart_beat_delay = paddrp->spp_hbinterval;
6205
0
          } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
6206
0
            net->heart_beat_delay = 0;
6207
0
          }
6208
0
          sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
6209
0
                          SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
6210
0
          sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
6211
0
          net->dest_state &= ~SCTP_ADDR_NOHB;
6212
0
        }
6213
0
        if (paddrp->spp_flags & SPP_HB_DEMAND) {
6214
0
          if (SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) {
6215
0
            sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6216
0
            sctp_chunk_output(inp, stcb,  SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
6217
0
            sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
6218
0
          }
6219
0
        }
6220
0
        if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
6221
0
          if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
6222
0
            sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
6223
0
                            SCTP_FROM_SCTP_USRREQ + SCTP_LOC_11);
6224
0
          }
6225
0
          net->dest_state |= SCTP_ADDR_NO_PMTUD;
6226
0
          if (paddrp->spp_pathmtu > 0) {
6227
0
            net->mtu = paddrp->spp_pathmtu;
6228
0
            switch (net->ro._l_addr.sa.sa_family) {
6229
0
#ifdef INET
6230
0
            case AF_INET:
6231
0
              net->mtu += SCTP_MIN_V4_OVERHEAD;
6232
0
              break;
6233
0
#endif
6234
0
#ifdef INET6
6235
0
            case AF_INET6:
6236
0
              net->mtu += SCTP_MIN_OVERHEAD;
6237
0
              break;
6238
0
#endif
6239
0
#if defined(__Userspace__)
6240
0
            case AF_CONN:
6241
0
              net->mtu += sizeof(struct sctphdr);
6242
0
              break;
6243
0
#endif
6244
0
            default:
6245
0
              break;
6246
0
            }
6247
0
            if (net->mtu < stcb->asoc.smallest_mtu) {
6248
0
              sctp_pathmtu_adjustment(stcb, net->mtu, true);
6249
0
            }
6250
0
          }
6251
0
        }
6252
0
        if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
6253
0
          if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
6254
0
            sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
6255
0
          }
6256
0
          net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
6257
0
        }
6258
0
        if (paddrp->spp_pathmaxrxt > 0) {
6259
0
          if (net->dest_state & SCTP_ADDR_PF) {
6260
0
            if (net->error_count > paddrp->spp_pathmaxrxt) {
6261
0
              net->dest_state &= ~SCTP_ADDR_PF;
6262
0
            }
6263
0
          } else {
6264
0
            if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
6265
0
                (net->error_count > net->pf_threshold)) {
6266
0
              net->dest_state |= SCTP_ADDR_PF;
6267
0
              sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6268
0
              sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
6269
0
                              stcb->sctp_ep, stcb, net,
6270
0
                              SCTP_FROM_SCTP_USRREQ + SCTP_LOC_12);
6271
0
              sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
6272
0
            }
6273
0
          }
6274
0
          if (net->dest_state & SCTP_ADDR_REACHABLE) {
6275
0
            if (net->error_count > paddrp->spp_pathmaxrxt) {
6276
0
              net->dest_state &= ~SCTP_ADDR_REACHABLE;
6277
0
              sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
6278
0
            }
6279
0
          } else {
6280
0
            if (net->error_count <= paddrp->spp_pathmaxrxt) {
6281
0
              net->dest_state |= SCTP_ADDR_REACHABLE;
6282
0
              sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
6283
0
            }
6284
0
          }
6285
0
          net->failure_threshold = paddrp->spp_pathmaxrxt;
6286
0
        }
6287
0
        if (paddrp->spp_flags & SPP_DSCP) {
6288
0
          net->dscp = paddrp->spp_dscp & 0xfc;
6289
0
          net->dscp |= 0x01;
6290
0
        }
6291
0
#ifdef INET6
6292
0
        if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
6293
0
          if (net->ro._l_addr.sa.sa_family == AF_INET6) {
6294
0
            net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
6295
0
            net->flowlabel |= 0x80000000;
6296
0
          }
6297
0
        }
6298
0
#endif
6299
0
      } else {
6300
        /************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
6301
0
        if (paddrp->spp_pathmaxrxt > 0) {
6302
0
          stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
6303
0
          TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6304
0
            if (net->dest_state & SCTP_ADDR_PF) {
6305
0
              if (net->error_count > paddrp->spp_pathmaxrxt) {
6306
0
                net->dest_state &= ~SCTP_ADDR_PF;
6307
0
              }
6308
0
            } else {
6309
0
              if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
6310
0
                  (net->error_count > net->pf_threshold)) {
6311
0
                net->dest_state |= SCTP_ADDR_PF;
6312
0
                sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6313
0
                sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
6314
0
                                stcb->sctp_ep, stcb, net,
6315
0
                                SCTP_FROM_SCTP_USRREQ + SCTP_LOC_13);
6316
0
                sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
6317
0
              }
6318
0
            }
6319
0
            if (net->dest_state & SCTP_ADDR_REACHABLE) {
6320
0
              if (net->error_count > paddrp->spp_pathmaxrxt) {
6321
0
                net->dest_state &= ~SCTP_ADDR_REACHABLE;
6322
0
                sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
6323
0
              }
6324
0
            } else {
6325
0
              if (net->error_count <= paddrp->spp_pathmaxrxt) {
6326
0
                net->dest_state |= SCTP_ADDR_REACHABLE;
6327
0
                sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
6328
0
              }
6329
0
            }
6330
0
            net->failure_threshold = paddrp->spp_pathmaxrxt;
6331
0
          }
6332
0
        }
6333
0
        if (paddrp->spp_flags & SPP_HB_ENABLE) {
6334
0
          if (paddrp->spp_hbinterval != 0) {
6335
0
            stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
6336
0
          } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
6337
0
            stcb->asoc.heart_beat_delay = 0;
6338
0
          }
6339
          /* Turn back on the timer */
6340
0
          TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6341
0
            if (paddrp->spp_hbinterval != 0) {
6342
0
              net->heart_beat_delay = paddrp->spp_hbinterval;
6343
0
            } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
6344
0
              net->heart_beat_delay = 0;
6345
0
            }
6346
0
            if (net->dest_state & SCTP_ADDR_NOHB) {
6347
0
              net->dest_state &= ~SCTP_ADDR_NOHB;
6348
0
            }
6349
0
            sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
6350
0
                SCTP_FROM_SCTP_USRREQ + SCTP_LOC_14);
6351
0
            sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
6352
0
          }
6353
0
          sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
6354
0
        }
6355
0
        if (paddrp->spp_flags & SPP_HB_DISABLE) {
6356
0
          TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6357
0
            if ((net->dest_state & SCTP_ADDR_NOHB) == 0) {
6358
0
              net->dest_state |= SCTP_ADDR_NOHB;
6359
0
              if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) {
6360
0
                sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
6361
0
                                inp, stcb, net,
6362
0
                                SCTP_FROM_SCTP_USRREQ + SCTP_LOC_15);
6363
0
              }
6364
0
            }
6365
0
          }
6366
0
          sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
6367
0
        }
6368
0
        if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
6369
0
          TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6370
0
            if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
6371
0
              sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
6372
0
                              SCTP_FROM_SCTP_USRREQ + SCTP_LOC_16);
6373
0
            }
6374
0
            net->dest_state |= SCTP_ADDR_NO_PMTUD;
6375
0
            if (paddrp->spp_pathmtu > 0) {
6376
0
              net->mtu = paddrp->spp_pathmtu;
6377
0
              switch (net->ro._l_addr.sa.sa_family) {
6378
0
#ifdef INET
6379
0
              case AF_INET:
6380
0
                net->mtu += SCTP_MIN_V4_OVERHEAD;
6381
0
                break;
6382
0
#endif
6383
0
#ifdef INET6
6384
0
              case AF_INET6:
6385
0
                net->mtu += SCTP_MIN_OVERHEAD;
6386
0
                break;
6387
0
#endif
6388
0
#if defined(__Userspace__)
6389
0
              case AF_CONN:
6390
0
                net->mtu += sizeof(struct sctphdr);
6391
0
                break;
6392
0
#endif
6393
0
              default:
6394
0
                break;
6395
0
              }
6396
0
              if (net->mtu < stcb->asoc.smallest_mtu) {
6397
0
                sctp_pathmtu_adjustment(stcb, net->mtu, true);
6398
0
              }
6399
0
            }
6400
0
          }
6401
0
          if (paddrp->spp_pathmtu > 0) {
6402
0
            stcb->asoc.default_mtu = paddrp->spp_pathmtu;
6403
0
          }
6404
0
          sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
6405
0
        }
6406
0
        if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
6407
0
          TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6408
0
            if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
6409
0
              sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
6410
0
            }
6411
0
            net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
6412
0
          }
6413
0
          stcb->asoc.default_mtu = 0;
6414
0
          sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
6415
0
        }
6416
0
        if (paddrp->spp_flags & SPP_DSCP) {
6417
0
          TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6418
0
            net->dscp = paddrp->spp_dscp & 0xfc;
6419
0
            net->dscp |= 0x01;
6420
0
          }
6421
0
          stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
6422
0
          stcb->asoc.default_dscp |= 0x01;
6423
0
        }
6424
0
#ifdef INET6
6425
0
        if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
6426
0
          TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6427
0
            if (net->ro._l_addr.sa.sa_family == AF_INET6) {
6428
0
              net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
6429
0
              net->flowlabel |= 0x80000000;
6430
0
            }
6431
0
          }
6432
0
          stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
6433
0
          stcb->asoc.default_flowlabel |= 0x80000000;
6434
0
        }
6435
0
#endif
6436
0
      }
6437
0
      SCTP_TCB_UNLOCK(stcb);
6438
0
    } else {
6439
      /************************NO TCB, SET TO default stuff ******************/
6440
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6441
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6442
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6443
0
           (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC))) {
6444
0
        SCTP_INP_WLOCK(inp);
6445
        /*
6446
         * For the TOS/FLOWLABEL stuff you set it
6447
         * with the options on the socket
6448
         */
6449
0
        if (paddrp->spp_pathmaxrxt > 0) {
6450
0
          inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
6451
0
        }
6452
6453
0
        if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
6454
0
          inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
6455
0
        else if (paddrp->spp_hbinterval != 0) {
6456
0
          if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
6457
0
            paddrp->spp_hbinterval= SCTP_MAX_HB_INTERVAL;
6458
0
          inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = sctp_msecs_to_ticks(paddrp->spp_hbinterval);
6459
0
        }
6460
6461
0
        if (paddrp->spp_flags & SPP_HB_ENABLE) {
6462
0
          if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
6463
0
            inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
6464
0
          } else if (paddrp->spp_hbinterval) {
6465
0
            inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = sctp_msecs_to_ticks(paddrp->spp_hbinterval);
6466
0
          }
6467
0
          sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
6468
0
        } else if (paddrp->spp_flags & SPP_HB_DISABLE) {
6469
0
          sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
6470
0
        }
6471
0
        if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
6472
0
          inp->sctp_ep.default_mtu = 0;
6473
0
          sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
6474
0
        } else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
6475
0
          if (paddrp->spp_pathmtu > 0) {
6476
0
            inp->sctp_ep.default_mtu = paddrp->spp_pathmtu;
6477
0
          }
6478
0
          sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
6479
0
        }
6480
0
        if (paddrp->spp_flags & SPP_DSCP) {
6481
0
          inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
6482
0
          inp->sctp_ep.default_dscp |= 0x01;
6483
0
        }
6484
0
#ifdef INET6
6485
0
        if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
6486
0
          if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
6487
0
            inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
6488
0
            inp->sctp_ep.default_flowlabel |= 0x80000000;
6489
0
          }
6490
0
        }
6491
0
#endif
6492
0
        SCTP_INP_WUNLOCK(inp);
6493
0
      } else {
6494
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6495
0
        error = EINVAL;
6496
0
      }
6497
0
    }
6498
0
    break;
6499
0
  }
6500
0
  case SCTP_RTOINFO:
6501
0
  {
6502
0
    struct sctp_rtoinfo *srto;
6503
0
    uint32_t new_init, new_min, new_max;
6504
6505
0
    SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
6506
0
    SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
6507
6508
0
    if (stcb) {
6509
0
      if (srto->srto_initial)
6510
0
        new_init = srto->srto_initial;
6511
0
      else
6512
0
        new_init = stcb->asoc.initial_rto;
6513
0
      if (srto->srto_max)
6514
0
        new_max = srto->srto_max;
6515
0
      else
6516
0
        new_max = stcb->asoc.maxrto;
6517
0
      if (srto->srto_min)
6518
0
        new_min = srto->srto_min;
6519
0
      else
6520
0
        new_min = stcb->asoc.minrto;
6521
0
      if ((new_min <= new_init) && (new_init <= new_max)) {
6522
0
        stcb->asoc.initial_rto = new_init;
6523
0
        stcb->asoc.maxrto = new_max;
6524
0
        stcb->asoc.minrto = new_min;
6525
0
      } else {
6526
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6527
0
        error = EINVAL;
6528
0
      }
6529
0
      SCTP_TCB_UNLOCK(stcb);
6530
0
    } else {
6531
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6532
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6533
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6534
0
           (srto->srto_assoc_id == SCTP_FUTURE_ASSOC))) {
6535
0
        SCTP_INP_WLOCK(inp);
6536
0
        if (srto->srto_initial)
6537
0
          new_init = srto->srto_initial;
6538
0
        else
6539
0
          new_init = inp->sctp_ep.initial_rto;
6540
0
        if (srto->srto_max)
6541
0
          new_max = srto->srto_max;
6542
0
        else
6543
0
          new_max = inp->sctp_ep.sctp_maxrto;
6544
0
        if (srto->srto_min)
6545
0
          new_min = srto->srto_min;
6546
0
        else
6547
0
          new_min = inp->sctp_ep.sctp_minrto;
6548
0
        if ((new_min <= new_init) && (new_init <= new_max)) {
6549
0
          inp->sctp_ep.initial_rto = new_init;
6550
0
          inp->sctp_ep.sctp_maxrto = new_max;
6551
0
          inp->sctp_ep.sctp_minrto = new_min;
6552
0
        } else {
6553
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6554
0
          error = EINVAL;
6555
0
        }
6556
0
        SCTP_INP_WUNLOCK(inp);
6557
0
      } else {
6558
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6559
0
        error = EINVAL;
6560
0
      }
6561
0
    }
6562
0
    break;
6563
0
  }
6564
0
  case SCTP_ASSOCINFO:
6565
0
  {
6566
0
    struct sctp_assocparams *sasoc;
6567
6568
0
    SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
6569
0
    SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
6570
0
    if (sasoc->sasoc_cookie_life > 0) {
6571
      /* boundary check the cookie life */
6572
0
      if (sasoc->sasoc_cookie_life < SCTP_MIN_COOKIE_LIFE) {
6573
0
        sasoc->sasoc_cookie_life = SCTP_MIN_COOKIE_LIFE;
6574
0
      }
6575
0
      if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
6576
0
        sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
6577
0
      }
6578
0
    }
6579
0
    if (stcb) {
6580
0
      if (sasoc->sasoc_asocmaxrxt > 0) {
6581
0
        stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
6582
0
      }
6583
0
      if (sasoc->sasoc_cookie_life > 0) {
6584
0
        stcb->asoc.cookie_life = sctp_msecs_to_ticks(sasoc->sasoc_cookie_life);
6585
0
      }
6586
0
      SCTP_TCB_UNLOCK(stcb);
6587
0
    } else {
6588
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6589
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6590
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6591
0
           (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC))) {
6592
0
        SCTP_INP_WLOCK(inp);
6593
0
        if (sasoc->sasoc_asocmaxrxt > 0) {
6594
0
          inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
6595
0
        }
6596
0
        if (sasoc->sasoc_cookie_life > 0) {
6597
0
          inp->sctp_ep.def_cookie_life = sctp_msecs_to_ticks(sasoc->sasoc_cookie_life);
6598
0
        }
6599
0
        SCTP_INP_WUNLOCK(inp);
6600
0
      } else {
6601
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6602
0
        error = EINVAL;
6603
0
      }
6604
0
    }
6605
0
    break;
6606
0
  }
6607
11.5k
  case SCTP_INITMSG:
6608
11.5k
  {
6609
11.5k
    struct sctp_initmsg *sinit;
6610
6611
11.5k
    SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
6612
11.5k
    SCTP_INP_WLOCK(inp);
6613
11.5k
    if (sinit->sinit_num_ostreams)
6614
11.5k
      inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
6615
6616
11.5k
    if (sinit->sinit_max_instreams)
6617
11.5k
      inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
6618
6619
11.5k
    if (sinit->sinit_max_attempts)
6620
11.5k
      inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
6621
6622
11.5k
    if (sinit->sinit_max_init_timeo)
6623
11.5k
      inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
6624
11.5k
    SCTP_INP_WUNLOCK(inp);
6625
11.5k
    break;
6626
11.5k
  }
6627
11.5k
  case SCTP_PRIMARY_ADDR:
6628
0
  {
6629
0
    struct sctp_setprim *spa;
6630
0
    struct sctp_nets *net;
6631
0
    struct sockaddr *addr;
6632
0
#if defined(INET) && defined(INET6)
6633
0
    struct sockaddr_in sin_store;
6634
0
#endif
6635
6636
0
    SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
6637
0
    SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
6638
6639
0
#if defined(INET) && defined(INET6)
6640
0
    if (spa->ssp_addr.ss_family == AF_INET6) {
6641
0
      struct sockaddr_in6 *sin6;
6642
6643
0
      sin6 = (struct sockaddr_in6 *)&spa->ssp_addr;
6644
0
      if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
6645
0
        in6_sin6_2_sin(&sin_store, sin6);
6646
0
        addr = (struct sockaddr *)&sin_store;
6647
0
      } else {
6648
0
        addr = (struct sockaddr *)&spa->ssp_addr;
6649
0
      }
6650
0
    } else {
6651
0
      addr = (struct sockaddr *)&spa->ssp_addr;
6652
0
    }
6653
#else
6654
    addr = (struct sockaddr *)&spa->ssp_addr;
6655
#endif
6656
0
    if (stcb != NULL) {
6657
0
      net = sctp_findnet(stcb, addr);
6658
0
    } else {
6659
      /* We increment here since sctp_findassociation_ep_addr() wil
6660
       * do a decrement if it finds the stcb as long as the locked
6661
       * tcb (last argument) is NOT a TCB.. aka NULL.
6662
       */
6663
0
      net = NULL;
6664
0
      SCTP_INP_INCR_REF(inp);
6665
0
      stcb = sctp_findassociation_ep_addr(&inp, addr,
6666
0
                                          &net, NULL, NULL);
6667
0
      if (stcb == NULL) {
6668
0
        SCTP_INP_DECR_REF(inp);
6669
0
      }
6670
0
    }
6671
6672
0
    if ((stcb != NULL) && (net != NULL)) {
6673
0
      if (net != stcb->asoc.primary_destination) {
6674
0
        if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) {
6675
          /* Ok we need to set it */
6676
0
          if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
6677
0
            if ((stcb->asoc.alternate) &&
6678
0
                ((net->dest_state & SCTP_ADDR_PF) == 0) &&
6679
0
                (net->dest_state & SCTP_ADDR_REACHABLE)) {
6680
0
              sctp_free_remote_addr(stcb->asoc.alternate);
6681
0
              stcb->asoc.alternate = NULL;
6682
0
            }
6683
0
          } else {
6684
0
            SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6685
0
            error = EINVAL;
6686
0
          }
6687
0
        } else {
6688
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6689
0
          error = EINVAL;
6690
0
        }
6691
0
      }
6692
0
    } else {
6693
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6694
0
      error = EINVAL;
6695
0
    }
6696
0
    if (stcb != NULL) {
6697
0
      SCTP_TCB_UNLOCK(stcb);
6698
0
    }
6699
0
    break;
6700
0
  }
6701
0
  case SCTP_SET_DYNAMIC_PRIMARY:
6702
0
  {
6703
0
    union sctp_sockstore *ss;
6704
#ifdef SCTP_MVRF
6705
    int i, fnd = 0;
6706
#endif
6707
#if !defined(_WIN32) && !defined(__Userspace__)
6708
#if defined(__APPLE__)
6709
    struct proc *proc;
6710
#endif
6711
#if defined(__FreeBSD__)
6712
    error = priv_check(curthread,
6713
           PRIV_NETINET_RESERVEDPORT);
6714
#elif defined(__APPLE__)
6715
    proc = (struct proc *)p;
6716
    if (p) {
6717
      error = suser(proc->p_ucred, &proc->p_acflag);
6718
    } else {
6719
      break;
6720
    }
6721
#else
6722
    error = suser(p, 0);
6723
#endif
6724
    if (error)
6725
      break;
6726
#endif
6727
6728
0
    SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
6729
    /* SUPER USER CHECK? */
6730
#ifdef SCTP_MVRF
6731
    for (i = 0; i < inp->num_vrfs; i++) {
6732
      if (vrf_id == inp->m_vrf_ids[i]) {
6733
        fnd = 1;
6734
        break;
6735
      }
6736
    }
6737
    if (!fnd) {
6738
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6739
      error = EINVAL;
6740
      break;
6741
    }
6742
#endif
6743
0
    error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
6744
0
    break;
6745
0
  }
6746
0
  case SCTP_SET_PEER_PRIMARY_ADDR:
6747
0
  {
6748
0
    struct sctp_setpeerprim *sspp;
6749
0
    struct sockaddr *addr;
6750
0
#if defined(INET) && defined(INET6)
6751
0
    struct sockaddr_in sin_store;
6752
0
#endif
6753
6754
0
    SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
6755
0
    SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
6756
0
    if (stcb != NULL) {
6757
0
      struct sctp_ifa *ifa;
6758
6759
0
#if defined(INET) && defined(INET6)
6760
0
      if (sspp->sspp_addr.ss_family == AF_INET6) {
6761
0
        struct sockaddr_in6 *sin6;
6762
6763
0
        sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr;
6764
0
        if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
6765
0
          in6_sin6_2_sin(&sin_store, sin6);
6766
0
          addr = (struct sockaddr *)&sin_store;
6767
0
        } else {
6768
0
          addr = (struct sockaddr *)&sspp->sspp_addr;
6769
0
        }
6770
0
      } else {
6771
0
        addr = (struct sockaddr *)&sspp->sspp_addr;
6772
0
      }
6773
#else
6774
      addr = (struct sockaddr *)&sspp->sspp_addr;
6775
#endif
6776
0
      ifa = sctp_find_ifa_by_addr(addr, stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
6777
0
      if (ifa == NULL) {
6778
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6779
0
        error = EINVAL;
6780
0
        goto out_of_it;
6781
0
      }
6782
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
6783
        /* Must validate the ifa found is in our ep */
6784
0
        struct sctp_laddr *laddr;
6785
0
        int found = 0;
6786
6787
0
        LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
6788
0
          if (laddr->ifa == NULL) {
6789
0
            SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
6790
0
              __func__);
6791
0
            continue;
6792
0
          }
6793
0
          if ((sctp_is_addr_restricted(stcb, laddr->ifa)) &&
6794
0
              (!sctp_is_addr_pending(stcb, laddr->ifa))) {
6795
0
            continue;
6796
0
          }
6797
0
          if (laddr->ifa == ifa) {
6798
0
            found = 1;
6799
0
            break;
6800
0
          }
6801
0
        }
6802
0
        if (!found) {
6803
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6804
0
          error = EINVAL;
6805
0
          goto out_of_it;
6806
0
        }
6807
#if defined(__FreeBSD__) && !defined(__Userspace__)
6808
      } else {
6809
        switch (addr->sa_family) {
6810
#ifdef INET
6811
        case AF_INET:
6812
        {
6813
          struct sockaddr_in *sin;
6814
6815
          sin = (struct sockaddr_in *)addr;
6816
          if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
6817
                               &sin->sin_addr) != 0) {
6818
            SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6819
            error = EINVAL;
6820
            goto out_of_it;
6821
          }
6822
          break;
6823
        }
6824
#endif
6825
#ifdef INET6
6826
        case AF_INET6:
6827
        {
6828
          struct sockaddr_in6 *sin6;
6829
6830
          sin6 = (struct sockaddr_in6 *)addr;
6831
          if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
6832
                               &sin6->sin6_addr) != 0) {
6833
            SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6834
            error = EINVAL;
6835
            goto out_of_it;
6836
          }
6837
          break;
6838
        }
6839
#endif
6840
        default:
6841
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6842
          error = EINVAL;
6843
          goto out_of_it;
6844
        }
6845
#endif
6846
0
      }
6847
0
      if (sctp_set_primary_ip_address_sa(stcb, addr) != 0) {
6848
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6849
0
        error = EINVAL;
6850
0
      }
6851
0
      sctp_chunk_output(inp, stcb,  SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
6852
0
    out_of_it:
6853
0
      SCTP_TCB_UNLOCK(stcb);
6854
0
    } else {
6855
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6856
0
      error = EINVAL;
6857
0
    }
6858
0
    break;
6859
0
  }
6860
0
  case SCTP_BINDX_ADD_ADDR:
6861
0
  {
6862
0
    struct sockaddr *sa;
6863
#if defined(__FreeBSD__) && !defined(__Userspace__)
6864
    struct thread *td;
6865
6866
    td = (struct thread *)p;
6867
#endif
6868
0
    SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
6869
0
#ifdef INET
6870
0
    if (sa->sa_family == AF_INET) {
6871
0
      if (optsize < sizeof(struct sockaddr_in)) {
6872
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6873
0
        error = EINVAL;
6874
0
        break;
6875
0
      }
6876
#if defined(__FreeBSD__) && !defined(__Userspace__)
6877
      if (td != NULL &&
6878
          (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)sa)->sin_addr)))) {
6879
        SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6880
        break;
6881
      }
6882
#endif
6883
0
    } else
6884
0
#endif
6885
0
#ifdef INET6
6886
0
    if (sa->sa_family == AF_INET6) {
6887
0
      if (optsize < sizeof(struct sockaddr_in6)) {
6888
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6889
0
        error = EINVAL;
6890
0
        break;
6891
0
      }
6892
#if defined(__FreeBSD__) && !defined(__Userspace__)
6893
      if (td != NULL &&
6894
          (error = prison_local_ip6(td->td_ucred,
6895
                                    &(((struct sockaddr_in6 *)sa)->sin6_addr),
6896
                                    (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
6897
        SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6898
        break;
6899
      }
6900
#endif
6901
0
    } else
6902
0
#endif
6903
0
    {
6904
0
      error = EAFNOSUPPORT;
6905
0
      break;
6906
0
    }
6907
0
    sctp_bindx_add_address(so, inp, sa, vrf_id, &error, p);
6908
0
    break;
6909
0
  }
6910
0
  case SCTP_BINDX_REM_ADDR:
6911
0
  {
6912
0
    struct sockaddr *sa;
6913
#if defined(__FreeBSD__) && !defined(__Userspace__)
6914
    struct thread *td;
6915
    td = (struct thread *)p;
6916
6917
#endif
6918
0
    SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
6919
0
#ifdef INET
6920
0
    if (sa->sa_family == AF_INET) {
6921
0
      if (optsize < sizeof(struct sockaddr_in)) {
6922
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6923
0
        error = EINVAL;
6924
0
        break;
6925
0
      }
6926
#if defined(__FreeBSD__) && !defined(__Userspace__)
6927
      if (td != NULL &&
6928
          (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)sa)->sin_addr)))) {
6929
        SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6930
        break;
6931
      }
6932
#endif
6933
0
    } else
6934
0
#endif
6935
0
#ifdef INET6
6936
0
    if (sa->sa_family == AF_INET6) {
6937
0
      if (optsize < sizeof(struct sockaddr_in6)) {
6938
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6939
0
        error = EINVAL;
6940
0
        break;
6941
0
      }
6942
#if defined(__FreeBSD__) && !defined(__Userspace__)
6943
      if (td != NULL &&
6944
          (error = prison_local_ip6(td->td_ucred,
6945
                                    &(((struct sockaddr_in6 *)sa)->sin6_addr),
6946
                                    (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
6947
        SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6948
        break;
6949
      }
6950
#endif
6951
0
    } else
6952
0
#endif
6953
0
    {
6954
0
      error = EAFNOSUPPORT;
6955
0
      break;
6956
0
    }
6957
0
    sctp_bindx_delete_address(inp, sa, vrf_id, &error);
6958
0
    break;
6959
0
  }
6960
#if defined(__APPLE__) && !defined(__Userspace__)
6961
  case SCTP_LISTEN_FIX:
6962
    /* only applies to one-to-many sockets */
6963
    if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
6964
      /* make sure the ACCEPTCONN flag is OFF */
6965
      so->so_options &= ~SO_ACCEPTCONN;
6966
    } else {
6967
      /* otherwise, not allowed */
6968
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6969
      error = EINVAL;
6970
    }
6971
    break;
6972
#endif
6973
149k
  case SCTP_EVENT:
6974
149k
  {
6975
149k
    struct sctp_event *event;
6976
149k
    uint32_t event_type;
6977
6978
149k
    SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
6979
149k
    SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
6980
149k
    switch (event->se_type) {
6981
11.5k
    case SCTP_ASSOC_CHANGE:
6982
11.5k
      event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
6983
11.5k
      break;
6984
11.5k
    case SCTP_PEER_ADDR_CHANGE:
6985
11.5k
      event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
6986
11.5k
      break;
6987
11.5k
    case SCTP_REMOTE_ERROR:
6988
11.5k
      event_type = SCTP_PCB_FLAGS_RECVPEERERR;
6989
11.5k
      break;
6990
11.5k
    case SCTP_SEND_FAILED:
6991
11.5k
      event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
6992
11.5k
      break;
6993
11.5k
    case SCTP_SHUTDOWN_EVENT:
6994
11.5k
      event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
6995
11.5k
      break;
6996
11.5k
    case SCTP_ADAPTATION_INDICATION:
6997
11.5k
      event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
6998
11.5k
      break;
6999
11.5k
    case SCTP_PARTIAL_DELIVERY_EVENT:
7000
11.5k
      event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
7001
11.5k
      break;
7002
11.5k
    case SCTP_AUTHENTICATION_EVENT:
7003
11.5k
      event_type = SCTP_PCB_FLAGS_AUTHEVNT;
7004
11.5k
      break;
7005
11.5k
    case SCTP_STREAM_RESET_EVENT:
7006
11.5k
      event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
7007
11.5k
      break;
7008
11.5k
    case SCTP_SENDER_DRY_EVENT:
7009
11.5k
      event_type = SCTP_PCB_FLAGS_DRYEVNT;
7010
11.5k
      break;
7011
0
    case SCTP_NOTIFICATIONS_STOPPED_EVENT:
7012
0
      event_type = 0;
7013
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
7014
0
      error = ENOTSUP;
7015
0
      break;
7016
11.5k
    case SCTP_ASSOC_RESET_EVENT:
7017
11.5k
      event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
7018
11.5k
      break;
7019
11.5k
    case SCTP_STREAM_CHANGE_EVENT:
7020
11.5k
      event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
7021
11.5k
      break;
7022
11.5k
    case SCTP_SEND_FAILED_EVENT:
7023
11.5k
      event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
7024
11.5k
      break;
7025
0
    default:
7026
0
      event_type = 0;
7027
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7028
0
      error = EINVAL;
7029
0
      break;
7030
149k
    }
7031
149k
    if (event_type > 0) {
7032
149k
      if (stcb) {
7033
0
        if (event->se_on) {
7034
0
          sctp_stcb_feature_on(inp, stcb, event_type);
7035
0
          if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
7036
0
            if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
7037
0
                TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
7038
0
                (stcb->asoc.stream_queue_cnt == 0)) {
7039
0
              sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb,  0, NULL, SCTP_SO_LOCKED);
7040
0
            }
7041
0
          }
7042
0
        } else {
7043
0
          sctp_stcb_feature_off(inp, stcb, event_type);
7044
0
        }
7045
0
        SCTP_TCB_UNLOCK(stcb);
7046
149k
      } else {
7047
        /*
7048
         * We don't want to send up a storm of events,
7049
         * so return an error for sender dry events
7050
         */
7051
149k
        if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
7052
149k
            (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7053
149k
            ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
7054
0
             (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
7055
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
7056
0
          error = ENOTSUP;
7057
0
          break;
7058
0
        }
7059
149k
        if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7060
149k
            (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7061
149k
            ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7062
0
             ((event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
7063
149k
              (event->se_assoc_id == SCTP_ALL_ASSOC)))) {
7064
149k
          SCTP_INP_WLOCK(inp);
7065
149k
          if (event->se_on) {
7066
149k
            sctp_feature_on(inp, event_type);
7067
149k
          } else {
7068
0
            sctp_feature_off(inp, event_type);
7069
0
          }
7070
149k
          SCTP_INP_WUNLOCK(inp);
7071
149k
        }
7072
149k
        if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7073
149k
            ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
7074
0
             (event->se_assoc_id == SCTP_ALL_ASSOC))) {
7075
0
          SCTP_INP_RLOCK(inp);
7076
0
          LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
7077
0
            SCTP_TCB_LOCK(stcb);
7078
0
            if (event->se_on) {
7079
0
              sctp_stcb_feature_on(inp, stcb, event_type);
7080
0
            } else {
7081
0
              sctp_stcb_feature_off(inp, stcb, event_type);
7082
0
            }
7083
0
            SCTP_TCB_UNLOCK(stcb);
7084
0
          }
7085
0
          SCTP_INP_RUNLOCK(inp);
7086
0
        }
7087
149k
      }
7088
149k
    } else {
7089
0
      if (stcb) {
7090
0
        SCTP_TCB_UNLOCK(stcb);
7091
0
      }
7092
0
    }
7093
149k
    break;
7094
149k
  }
7095
149k
  case SCTP_RECVRCVINFO:
7096
11.5k
  {
7097
11.5k
    int *onoff;
7098
7099
11.5k
    SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
7100
11.5k
    SCTP_INP_WLOCK(inp);
7101
11.5k
    if (*onoff != 0) {
7102
11.5k
      sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
7103
11.5k
    } else {
7104
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
7105
0
    }
7106
11.5k
    SCTP_INP_WUNLOCK(inp);
7107
11.5k
    break;
7108
11.5k
  }
7109
11.5k
  case SCTP_RECVNXTINFO:
7110
11.5k
  {
7111
11.5k
    int *onoff;
7112
7113
11.5k
    SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
7114
11.5k
    SCTP_INP_WLOCK(inp);
7115
11.5k
    if (*onoff != 0) {
7116
11.5k
      sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
7117
11.5k
    } else {
7118
0
      sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
7119
0
    }
7120
11.5k
    SCTP_INP_WUNLOCK(inp);
7121
11.5k
    break;
7122
11.5k
  }
7123
11.5k
  case SCTP_DEFAULT_SNDINFO:
7124
0
  {
7125
0
    struct sctp_sndinfo *info;
7126
0
    uint16_t policy;
7127
7128
0
    SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
7129
0
    SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
7130
7131
0
    if (stcb) {
7132
0
      if (info->snd_sid < stcb->asoc.streamoutcnt) {
7133
0
        stcb->asoc.def_send.sinfo_stream = info->snd_sid;
7134
0
        policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
7135
0
        stcb->asoc.def_send.sinfo_flags = info->snd_flags;
7136
0
        stcb->asoc.def_send.sinfo_flags |= policy;
7137
0
        stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
7138
0
        stcb->asoc.def_send.sinfo_context = info->snd_context;
7139
0
      } else {
7140
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7141
0
        error = EINVAL;
7142
0
      }
7143
0
      SCTP_TCB_UNLOCK(stcb);
7144
0
    } else {
7145
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7146
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7147
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7148
0
           ((info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
7149
0
            (info->snd_assoc_id == SCTP_ALL_ASSOC)))) {
7150
0
        SCTP_INP_WLOCK(inp);
7151
0
        inp->def_send.sinfo_stream = info->snd_sid;
7152
0
        policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
7153
0
        inp->def_send.sinfo_flags = info->snd_flags;
7154
0
        inp->def_send.sinfo_flags |= policy;
7155
0
        inp->def_send.sinfo_ppid = info->snd_ppid;
7156
0
        inp->def_send.sinfo_context = info->snd_context;
7157
0
        SCTP_INP_WUNLOCK(inp);
7158
0
      }
7159
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7160
0
          ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
7161
0
           (info->snd_assoc_id == SCTP_ALL_ASSOC))) {
7162
0
        SCTP_INP_RLOCK(inp);
7163
0
        LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
7164
0
          SCTP_TCB_LOCK(stcb);
7165
0
          if (info->snd_sid < stcb->asoc.streamoutcnt) {
7166
0
            stcb->asoc.def_send.sinfo_stream = info->snd_sid;
7167
0
            policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
7168
0
            stcb->asoc.def_send.sinfo_flags = info->snd_flags;
7169
0
            stcb->asoc.def_send.sinfo_flags |= policy;
7170
0
            stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
7171
0
            stcb->asoc.def_send.sinfo_context = info->snd_context;
7172
0
          }
7173
0
          SCTP_TCB_UNLOCK(stcb);
7174
0
        }
7175
0
        SCTP_INP_RUNLOCK(inp);
7176
0
      }
7177
0
    }
7178
0
    break;
7179
0
  }
7180
0
  case SCTP_DEFAULT_PRINFO:
7181
0
  {
7182
0
    struct sctp_default_prinfo *info;
7183
7184
0
    SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
7185
0
    SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
7186
7187
0
    if (info->pr_policy > SCTP_PR_SCTP_MAX) {
7188
0
      if (stcb) {
7189
0
        SCTP_TCB_UNLOCK(stcb);
7190
0
      }
7191
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7192
0
      error = EINVAL;
7193
0
      break;
7194
0
    }
7195
0
    if (stcb) {
7196
0
      stcb->asoc.def_send.sinfo_flags &= 0xfff0;
7197
0
      stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
7198
0
      stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
7199
0
      SCTP_TCB_UNLOCK(stcb);
7200
0
    } else {
7201
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7202
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7203
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7204
0
           ((info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
7205
0
            (info->pr_assoc_id == SCTP_ALL_ASSOC)))) {
7206
0
        SCTP_INP_WLOCK(inp);
7207
0
        inp->def_send.sinfo_flags &= 0xfff0;
7208
0
        inp->def_send.sinfo_flags |= info->pr_policy;
7209
0
        inp->def_send.sinfo_timetolive = info->pr_value;
7210
0
        SCTP_INP_WUNLOCK(inp);
7211
0
      }
7212
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7213
0
          ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
7214
0
           (info->pr_assoc_id == SCTP_ALL_ASSOC))) {
7215
0
        SCTP_INP_RLOCK(inp);
7216
0
        LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
7217
0
          SCTP_TCB_LOCK(stcb);
7218
0
          stcb->asoc.def_send.sinfo_flags &= 0xfff0;
7219
0
          stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
7220
0
          stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
7221
0
          SCTP_TCB_UNLOCK(stcb);
7222
0
        }
7223
0
        SCTP_INP_RUNLOCK(inp);
7224
0
      }
7225
0
    }
7226
0
    break;
7227
0
  }
7228
0
  case SCTP_PEER_ADDR_THLDS:
7229
    /* Applies to the specific association */
7230
0
  {
7231
0
    struct sctp_paddrthlds *thlds;
7232
0
    struct sctp_nets *net;
7233
0
    struct sockaddr *addr;
7234
0
#if defined(INET) && defined(INET6)
7235
0
    struct sockaddr_in sin_store;
7236
0
#endif
7237
7238
0
    SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
7239
0
    SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
7240
7241
0
#if defined(INET) && defined(INET6)
7242
0
    if (thlds->spt_address.ss_family == AF_INET6) {
7243
0
      struct sockaddr_in6 *sin6;
7244
7245
0
      sin6 = (struct sockaddr_in6 *)&thlds->spt_address;
7246
0
      if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
7247
0
        in6_sin6_2_sin(&sin_store, sin6);
7248
0
        addr = (struct sockaddr *)&sin_store;
7249
0
      } else {
7250
0
        addr = (struct sockaddr *)&thlds->spt_address;
7251
0
      }
7252
0
    } else {
7253
0
      addr = (struct sockaddr *)&thlds->spt_address;
7254
0
    }
7255
#else
7256
    addr = (struct sockaddr *)&thlds->spt_address;
7257
#endif
7258
0
    if (stcb != NULL) {
7259
0
      net = sctp_findnet(stcb, addr);
7260
0
    } else {
7261
      /* We increment here since sctp_findassociation_ep_addr() wil
7262
       * do a decrement if it finds the stcb as long as the locked
7263
       * tcb (last argument) is NOT a TCB.. aka NULL.
7264
       */
7265
0
      net = NULL;
7266
0
      SCTP_INP_INCR_REF(inp);
7267
0
      stcb = sctp_findassociation_ep_addr(&inp, addr,
7268
0
                                          &net, NULL, NULL);
7269
0
      if (stcb == NULL) {
7270
0
        SCTP_INP_DECR_REF(inp);
7271
0
      }
7272
0
    }
7273
0
    if ((stcb != NULL) && (net == NULL)) {
7274
0
#ifdef INET
7275
0
      if (addr->sa_family == AF_INET) {
7276
0
        struct sockaddr_in *sin;
7277
7278
0
        sin = (struct sockaddr_in *)addr;
7279
0
        if (sin->sin_addr.s_addr != INADDR_ANY) {
7280
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7281
0
          SCTP_TCB_UNLOCK(stcb);
7282
0
          error = EINVAL;
7283
0
          break;
7284
0
        }
7285
0
      } else
7286
0
#endif
7287
0
#ifdef INET6
7288
0
      if (addr->sa_family == AF_INET6) {
7289
0
        struct sockaddr_in6 *sin6;
7290
7291
0
        sin6 = (struct sockaddr_in6 *)addr;
7292
0
        if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
7293
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7294
0
          SCTP_TCB_UNLOCK(stcb);
7295
0
          error = EINVAL;
7296
0
          break;
7297
0
        }
7298
0
      } else
7299
0
#endif
7300
0
#if defined(__Userspace__)
7301
0
      if (addr->sa_family == AF_CONN) {
7302
0
        struct sockaddr_conn *sconn;
7303
7304
0
        sconn = (struct sockaddr_conn *)addr;
7305
0
        if (sconn->sconn_addr != NULL) {
7306
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7307
0
          SCTP_TCB_UNLOCK(stcb);
7308
0
          error = EINVAL;
7309
0
          break;
7310
0
        }
7311
0
      } else
7312
0
#endif
7313
0
      {
7314
0
        error = EAFNOSUPPORT;
7315
0
        SCTP_TCB_UNLOCK(stcb);
7316
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
7317
0
        break;
7318
0
      }
7319
0
    }
7320
0
    if (thlds->spt_pathcpthld != 0xffff) {
7321
0
      if (stcb != NULL) {
7322
0
        SCTP_TCB_UNLOCK(stcb);
7323
0
      }
7324
0
      error = EINVAL;
7325
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
7326
0
      break;
7327
0
    }
7328
0
    if (stcb != NULL) {
7329
0
      if (net != NULL) {
7330
0
        net->failure_threshold = thlds->spt_pathmaxrxt;
7331
0
        net->pf_threshold = thlds->spt_pathpfthld;
7332
0
        if (net->dest_state & SCTP_ADDR_PF) {
7333
0
          if ((net->error_count > net->failure_threshold) ||
7334
0
              (net->error_count <= net->pf_threshold)) {
7335
0
            net->dest_state &= ~SCTP_ADDR_PF;
7336
0
          }
7337
0
        } else {
7338
0
          if ((net->error_count > net->pf_threshold) &&
7339
0
              (net->error_count <= net->failure_threshold)) {
7340
0
            net->dest_state |= SCTP_ADDR_PF;
7341
0
            sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
7342
0
            sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
7343
0
                            stcb->sctp_ep, stcb, net,
7344
0
                            SCTP_FROM_SCTP_USRREQ + SCTP_LOC_17);
7345
0
            sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
7346
0
          }
7347
0
        }
7348
0
        if (net->dest_state & SCTP_ADDR_REACHABLE) {
7349
0
          if (net->error_count > net->failure_threshold) {
7350
0
            net->dest_state &= ~SCTP_ADDR_REACHABLE;
7351
0
            sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
7352
0
          }
7353
0
        } else {
7354
0
          if (net->error_count <= net->failure_threshold) {
7355
0
            net->dest_state |= SCTP_ADDR_REACHABLE;
7356
0
            sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
7357
0
          }
7358
0
        }
7359
0
      } else {
7360
0
        TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
7361
0
          net->failure_threshold = thlds->spt_pathmaxrxt;
7362
0
          net->pf_threshold = thlds->spt_pathpfthld;
7363
0
          if (net->dest_state & SCTP_ADDR_PF) {
7364
0
            if ((net->error_count > net->failure_threshold) ||
7365
0
                (net->error_count <= net->pf_threshold)) {
7366
0
              net->dest_state &= ~SCTP_ADDR_PF;
7367
0
            }
7368
0
          } else {
7369
0
            if ((net->error_count > net->pf_threshold) &&
7370
0
                (net->error_count <= net->failure_threshold)) {
7371
0
              net->dest_state |= SCTP_ADDR_PF;
7372
0
              sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
7373
0
              sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
7374
0
                              stcb->sctp_ep, stcb, net,
7375
0
                              SCTP_FROM_SCTP_USRREQ + SCTP_LOC_18);
7376
0
              sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
7377
0
            }
7378
0
          }
7379
0
          if (net->dest_state & SCTP_ADDR_REACHABLE) {
7380
0
            if (net->error_count > net->failure_threshold) {
7381
0
              net->dest_state &= ~SCTP_ADDR_REACHABLE;
7382
0
              sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
7383
0
            }
7384
0
          } else {
7385
0
            if (net->error_count <= net->failure_threshold) {
7386
0
              net->dest_state |= SCTP_ADDR_REACHABLE;
7387
0
              sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
7388
0
            }
7389
0
          }
7390
0
        }
7391
0
        stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
7392
0
        stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
7393
0
      }
7394
0
      SCTP_TCB_UNLOCK(stcb);
7395
0
    } else {
7396
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7397
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7398
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7399
0
           (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC))) {
7400
0
        SCTP_INP_WLOCK(inp);
7401
0
        inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
7402
0
        inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
7403
0
        SCTP_INP_WUNLOCK(inp);
7404
0
      } else {
7405
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7406
0
        error = EINVAL;
7407
0
      }
7408
0
    }
7409
0
    break;
7410
0
  }
7411
0
  case SCTP_REMOTE_UDP_ENCAPS_PORT:
7412
0
  {
7413
0
    struct sctp_udpencaps *encaps;
7414
0
    struct sctp_nets *net;
7415
0
    struct sockaddr *addr;
7416
0
#if defined(INET) && defined(INET6)
7417
0
    struct sockaddr_in sin_store;
7418
0
#endif
7419
7420
0
    SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
7421
0
    SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
7422
7423
0
#if defined(INET) && defined(INET6)
7424
0
    if (encaps->sue_address.ss_family == AF_INET6) {
7425
0
      struct sockaddr_in6 *sin6;
7426
7427
0
      sin6 = (struct sockaddr_in6 *)&encaps->sue_address;
7428
0
      if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
7429
0
        in6_sin6_2_sin(&sin_store, sin6);
7430
0
        addr = (struct sockaddr *)&sin_store;
7431
0
      } else {
7432
0
        addr = (struct sockaddr *)&encaps->sue_address;
7433
0
      }
7434
0
    } else {
7435
0
      addr = (struct sockaddr *)&encaps->sue_address;
7436
0
    }
7437
#else
7438
    addr = (struct sockaddr *)&encaps->sue_address;
7439
#endif
7440
0
    if (stcb != NULL) {
7441
0
      net = sctp_findnet(stcb, addr);
7442
0
    } else {
7443
      /* We increment here since sctp_findassociation_ep_addr() wil
7444
       * do a decrement if it finds the stcb as long as the locked
7445
       * tcb (last argument) is NOT a TCB.. aka NULL.
7446
       */
7447
0
      net = NULL;
7448
0
      SCTP_INP_INCR_REF(inp);
7449
0
      stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
7450
0
      if (stcb == NULL) {
7451
0
        SCTP_INP_DECR_REF(inp);
7452
0
      }
7453
0
    }
7454
0
    if ((stcb != NULL) && (net == NULL)) {
7455
0
#ifdef INET
7456
0
      if (addr->sa_family == AF_INET) {
7457
0
        struct sockaddr_in *sin;
7458
7459
0
        sin = (struct sockaddr_in *)addr;
7460
0
        if (sin->sin_addr.s_addr != INADDR_ANY) {
7461
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7462
0
          SCTP_TCB_UNLOCK(stcb);
7463
0
          error = EINVAL;
7464
0
          break;
7465
0
        }
7466
0
      } else
7467
0
#endif
7468
0
#ifdef INET6
7469
0
      if (addr->sa_family == AF_INET6) {
7470
0
        struct sockaddr_in6 *sin6;
7471
7472
0
        sin6 = (struct sockaddr_in6 *)addr;
7473
0
        if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
7474
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7475
0
          SCTP_TCB_UNLOCK(stcb);
7476
0
          error = EINVAL;
7477
0
          break;
7478
0
        }
7479
0
      } else
7480
0
#endif
7481
0
#if defined(__Userspace__)
7482
0
      if (addr->sa_family == AF_CONN) {
7483
0
        struct sockaddr_conn *sconn;
7484
7485
0
        sconn = (struct sockaddr_conn *)addr;
7486
0
        if (sconn->sconn_addr != NULL) {
7487
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7488
0
          SCTP_TCB_UNLOCK(stcb);
7489
0
          error = EINVAL;
7490
0
          break;
7491
0
        }
7492
0
      } else
7493
0
#endif
7494
0
      {
7495
0
          error = EAFNOSUPPORT;
7496
0
          SCTP_TCB_UNLOCK(stcb);
7497
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
7498
0
          break;
7499
0
        }
7500
0
    }
7501
7502
0
    if (stcb != NULL) {
7503
0
      if (net != NULL) {
7504
0
        net->port = encaps->sue_port;
7505
0
      } else {
7506
0
        stcb->asoc.port = encaps->sue_port;
7507
0
      }
7508
0
      SCTP_TCB_UNLOCK(stcb);
7509
0
    } else {
7510
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7511
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7512
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7513
0
           (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC))) {
7514
0
        SCTP_INP_WLOCK(inp);
7515
0
        inp->sctp_ep.port = encaps->sue_port;
7516
0
        SCTP_INP_WUNLOCK(inp);
7517
0
      } else {
7518
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7519
0
        error = EINVAL;
7520
0
      }
7521
0
    }
7522
0
    break;
7523
0
  }
7524
0
  case SCTP_ECN_SUPPORTED:
7525
0
  {
7526
0
    struct sctp_assoc_value *av;
7527
7528
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7529
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7530
7531
0
    if (stcb) {
7532
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7533
0
      error = EINVAL;
7534
0
      SCTP_TCB_UNLOCK(stcb);
7535
0
    } else {
7536
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7537
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7538
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7539
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
7540
0
        SCTP_INP_WLOCK(inp);
7541
0
        if (av->assoc_value == 0) {
7542
0
          inp->ecn_supported = 0;
7543
0
        } else {
7544
0
          inp->ecn_supported = 1;
7545
0
        }
7546
0
        SCTP_INP_WUNLOCK(inp);
7547
0
      } else {
7548
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7549
0
        error = EINVAL;
7550
0
      }
7551
0
    }
7552
0
    break;
7553
0
  }
7554
0
  case SCTP_PR_SUPPORTED:
7555
0
  {
7556
0
    struct sctp_assoc_value *av;
7557
7558
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7559
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7560
7561
0
    if (stcb) {
7562
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7563
0
      error = EINVAL;
7564
0
      SCTP_TCB_UNLOCK(stcb);
7565
0
    } else {
7566
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7567
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7568
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7569
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
7570
0
        SCTP_INP_WLOCK(inp);
7571
0
        if (av->assoc_value == 0) {
7572
0
          inp->prsctp_supported = 0;
7573
0
        } else {
7574
0
          inp->prsctp_supported = 1;
7575
0
        }
7576
0
        SCTP_INP_WUNLOCK(inp);
7577
0
      } else {
7578
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7579
0
        error = EINVAL;
7580
0
      }
7581
0
    }
7582
0
    break;
7583
0
  }
7584
0
  case SCTP_AUTH_SUPPORTED:
7585
0
  {
7586
0
    struct sctp_assoc_value *av;
7587
7588
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7589
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7590
7591
0
    if (stcb) {
7592
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7593
0
      error = EINVAL;
7594
0
      SCTP_TCB_UNLOCK(stcb);
7595
0
    } else {
7596
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7597
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7598
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7599
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
7600
0
        if ((av->assoc_value == 0) &&
7601
0
            (inp->asconf_supported == 1)) {
7602
              /* AUTH is required for ASCONF */
7603
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7604
0
          error = EINVAL;
7605
0
        } else {
7606
0
          SCTP_INP_WLOCK(inp);
7607
0
          if (av->assoc_value == 0) {
7608
0
            inp->auth_supported = 0;
7609
0
          } else {
7610
0
            inp->auth_supported = 1;
7611
0
          }
7612
0
          SCTP_INP_WUNLOCK(inp);
7613
0
        }
7614
0
      } else {
7615
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7616
0
        error = EINVAL;
7617
0
      }
7618
0
    }
7619
0
    break;
7620
0
  }
7621
0
  case SCTP_ASCONF_SUPPORTED:
7622
0
  {
7623
0
    struct sctp_assoc_value *av;
7624
7625
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7626
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7627
7628
0
    if (stcb) {
7629
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7630
0
      error = EINVAL;
7631
0
      SCTP_TCB_UNLOCK(stcb);
7632
0
    } else {
7633
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7634
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7635
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7636
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
7637
0
        if ((av->assoc_value != 0) &&
7638
0
            (inp->auth_supported == 0)) {
7639
              /* AUTH is required for ASCONF */
7640
0
          SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7641
0
          error = EINVAL;
7642
0
        } else {
7643
0
          SCTP_INP_WLOCK(inp);
7644
0
          if (av->assoc_value == 0) {
7645
0
            inp->asconf_supported = 0;
7646
0
            sctp_auth_delete_chunk(SCTP_ASCONF,
7647
0
                                   inp->sctp_ep.local_auth_chunks);
7648
0
            sctp_auth_delete_chunk(SCTP_ASCONF_ACK,
7649
0
                                   inp->sctp_ep.local_auth_chunks);
7650
0
          } else {
7651
0
            inp->asconf_supported = 1;
7652
0
            sctp_auth_add_chunk(SCTP_ASCONF,
7653
0
                                inp->sctp_ep.local_auth_chunks);
7654
0
            sctp_auth_add_chunk(SCTP_ASCONF_ACK,
7655
0
                                inp->sctp_ep.local_auth_chunks);
7656
0
          }
7657
0
          SCTP_INP_WUNLOCK(inp);
7658
0
        }
7659
0
      } else {
7660
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7661
0
        error = EINVAL;
7662
0
      }
7663
0
    }
7664
0
    break;
7665
0
  }
7666
0
  case SCTP_RECONFIG_SUPPORTED:
7667
0
  {
7668
0
    struct sctp_assoc_value *av;
7669
7670
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7671
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7672
7673
0
    if (stcb) {
7674
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7675
0
      error = EINVAL;
7676
0
      SCTP_TCB_UNLOCK(stcb);
7677
0
    } else {
7678
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7679
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7680
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7681
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
7682
0
        SCTP_INP_WLOCK(inp);
7683
0
        if (av->assoc_value == 0) {
7684
0
          inp->reconfig_supported = 0;
7685
0
        } else {
7686
0
          inp->reconfig_supported = 1;
7687
0
        }
7688
0
        SCTP_INP_WUNLOCK(inp);
7689
0
      } else {
7690
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7691
0
        error = EINVAL;
7692
0
      }
7693
0
    }
7694
0
    break;
7695
0
  }
7696
0
  case SCTP_NRSACK_SUPPORTED:
7697
0
  {
7698
0
    struct sctp_assoc_value *av;
7699
7700
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7701
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7702
7703
0
    if (stcb) {
7704
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7705
0
      error = EINVAL;
7706
0
      SCTP_TCB_UNLOCK(stcb);
7707
0
    } else {
7708
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7709
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7710
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7711
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
7712
0
        SCTP_INP_WLOCK(inp);
7713
0
        if (av->assoc_value == 0) {
7714
0
          inp->nrsack_supported = 0;
7715
0
        } else {
7716
0
          inp->nrsack_supported = 1;
7717
0
        }
7718
0
        SCTP_INP_WUNLOCK(inp);
7719
0
      } else {
7720
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7721
0
        error = EINVAL;
7722
0
      }
7723
0
    }
7724
0
    break;
7725
0
  }
7726
0
  case SCTP_PKTDROP_SUPPORTED:
7727
0
  {
7728
0
    struct sctp_assoc_value *av;
7729
7730
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7731
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7732
7733
0
    if (stcb) {
7734
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7735
0
      error = EINVAL;
7736
0
      SCTP_TCB_UNLOCK(stcb);
7737
0
    } else {
7738
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7739
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7740
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7741
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
7742
0
        SCTP_INP_WLOCK(inp);
7743
0
        if (av->assoc_value == 0) {
7744
0
          inp->pktdrop_supported = 0;
7745
0
        } else {
7746
0
          inp->pktdrop_supported = 1;
7747
0
        }
7748
0
        SCTP_INP_WUNLOCK(inp);
7749
0
      } else {
7750
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7751
0
        error = EINVAL;
7752
0
      }
7753
0
    }
7754
0
    break;
7755
0
  }
7756
0
  case SCTP_MAX_CWND:
7757
0
  {
7758
0
    struct sctp_assoc_value *av;
7759
0
    struct sctp_nets *net;
7760
7761
0
    SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
7762
0
    SCTP_FIND_STCB(inp, stcb, av->assoc_id);
7763
7764
0
    if (stcb) {
7765
0
      stcb->asoc.max_cwnd = av->assoc_value;
7766
0
      if (stcb->asoc.max_cwnd > 0) {
7767
0
        TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
7768
0
          if ((net->cwnd > stcb->asoc.max_cwnd) &&
7769
0
              (net->cwnd > (net->mtu - sizeof(struct sctphdr)))) {
7770
0
            net->cwnd = stcb->asoc.max_cwnd;
7771
0
            if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
7772
0
              net->cwnd = net->mtu - sizeof(struct sctphdr);
7773
0
            }
7774
0
          }
7775
0
        }
7776
0
      }
7777
0
      SCTP_TCB_UNLOCK(stcb);
7778
0
    } else {
7779
0
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
7780
0
          (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
7781
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
7782
0
           (av->assoc_id == SCTP_FUTURE_ASSOC))) {
7783
0
        SCTP_INP_WLOCK(inp);
7784
0
        inp->max_cwnd = av->assoc_value;
7785
0
        SCTP_INP_WUNLOCK(inp);
7786
0
      } else {
7787
0
        SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7788
0
        error = EINVAL;
7789
0
      }
7790
0
    }
7791
0
    break;
7792
0
  }
7793
0
  case SCTP_ACCEPT_ZERO_CHECKSUM:
7794
0
  {
7795
0
    uint32_t *value;
7796
7797
0
    SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
7798
0
    if ((*value == SCTP_EDMID_NONE) ||
7799
0
        (*value == SCTP_EDMID_LOWER_LAYER_DTLS)) {
7800
0
      SCTP_INP_WLOCK(inp);
7801
0
      inp->rcv_edmid = *value;
7802
0
      SCTP_INP_WUNLOCK(inp);
7803
0
    } else {
7804
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7805
0
      error = EINVAL;
7806
0
    }
7807
0
    break;
7808
0
  }
7809
7810
0
  default:
7811
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
7812
0
    error = ENOPROTOOPT;
7813
0
    break;
7814
230k
  } /* end switch (opt) */
7815
230k
  return (error);
7816
230k
}
7817
7818
#if !defined(__Userspace__)
7819
int
7820
sctp_ctloutput(struct socket *so, struct sockopt *sopt)
7821
{
7822
#if defined(__FreeBSD__)
7823
  struct epoch_tracker et;
7824
  struct sctp_inpcb *inp;
7825
#endif
7826
  void *optval = NULL;
7827
  void *p;
7828
  size_t optsize = 0;
7829
  int error = 0;
7830
7831
#if defined(__FreeBSD__)
7832
  if ((sopt->sopt_level == SOL_SOCKET) &&
7833
      (sopt->sopt_name == SO_SETFIB)) {
7834
    inp = (struct sctp_inpcb *)so->so_pcb;
7835
    if (inp == NULL) {
7836
      SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
7837
      return (EINVAL);
7838
    }
7839
    SCTP_INP_WLOCK(inp);
7840
    inp->fibnum = so->so_fibnum;
7841
    SCTP_INP_WUNLOCK(inp);
7842
    return (0);
7843
  }
7844
#endif
7845
  if (sopt->sopt_level != IPPROTO_SCTP) {
7846
    /* wrong proto level... send back up to IP */
7847
#ifdef INET6
7848
    if (INP_CHECK_SOCKAF(so, AF_INET6))
7849
      error = ip6_ctloutput(so, sopt);
7850
#endif        /* INET6 */
7851
#if defined(INET) && defined(INET6)
7852
    else
7853
#endif
7854
#ifdef INET
7855
      error = ip_ctloutput(so, sopt);
7856
#endif
7857
    return (error);
7858
  }
7859
  optsize = sopt->sopt_valsize;
7860
  if (optsize > SCTP_SOCKET_OPTION_LIMIT) {
7861
    SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
7862
    return (ENOBUFS);
7863
  }
7864
  if (optsize) {
7865
    SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
7866
    if (optval == NULL) {
7867
      SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
7868
      return (ENOBUFS);
7869
    }
7870
    error = sooptcopyin(sopt, optval, optsize, optsize);
7871
    if (error) {
7872
      SCTP_FREE(optval, SCTP_M_SOCKOPT);
7873
      goto out;
7874
    }
7875
  }
7876
#if defined(__FreeBSD__) || defined(_WIN32)
7877
  p = (void *)sopt->sopt_td;
7878
#else
7879
  p = (void *)sopt->sopt_p;
7880
#endif
7881
  if (sopt->sopt_dir == SOPT_SET) {
7882
#if defined(__FreeBSD__)
7883
    NET_EPOCH_ENTER(et);
7884
#endif
7885
    error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
7886
#if defined(__FreeBSD__)
7887
    NET_EPOCH_EXIT(et);
7888
#endif
7889
  } else if (sopt->sopt_dir == SOPT_GET) {
7890
    error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
7891
  } else {
7892
    SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7893
    error = EINVAL;
7894
  }
7895
  if ((error == 0) && (optval != NULL)) {
7896
    error = sooptcopyout(sopt, optval, optsize);
7897
    SCTP_FREE(optval, SCTP_M_SOCKOPT);
7898
  } else if (optval != NULL) {
7899
    SCTP_FREE(optval, SCTP_M_SOCKOPT);
7900
  }
7901
out:
7902
  return (error);
7903
}
7904
#endif
7905
7906
#ifdef INET
7907
#if defined(__Userspace__)
7908
int
7909
sctp_connect(struct socket *so, struct sockaddr *addr)
7910
0
{
7911
0
  void *p = NULL;
7912
#elif defined(__FreeBSD__)
7913
static int
7914
sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
7915
{
7916
#elif defined(__APPLE__)
7917
static int
7918
sctp_connect(struct socket *so, struct sockaddr *addr, struct proc *p)
7919
{
7920
#elif defined(_WIN32)
7921
static int
7922
sctp_connect(struct socket *so, struct sockaddr *addr, PKTHREAD p)
7923
{
7924
#else
7925
static int
7926
sctp_connect(struct socket *so, struct mbuf *nam, struct proc *p)
7927
{
7928
  struct sockaddr *addr = mtod(nam, struct sockaddr *);
7929
7930
#endif
7931
#if defined(__FreeBSD__) && !defined(__Userspace__)
7932
  struct epoch_tracker et;
7933
#endif
7934
#ifdef SCTP_MVRF
7935
  int i, fnd = 0;
7936
#endif
7937
0
  int error = 0;
7938
0
  int create_lock_on = 0;
7939
0
  uint32_t vrf_id;
7940
0
  struct sctp_inpcb *inp;
7941
0
  struct sctp_tcb *stcb = NULL;
7942
7943
0
  inp = (struct sctp_inpcb *)so->so_pcb;
7944
0
  if (inp == NULL) {
7945
    /* I made the same as TCP since we are not setup? */
7946
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7947
0
    return (ECONNRESET);
7948
0
  }
7949
0
  if (addr == NULL) {
7950
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7951
0
    return EINVAL;
7952
0
  }
7953
7954
0
#if defined(__Userspace__)
7955
  /* TODO __Userspace__ falls into this code for IPv6 stuff at the moment... */
7956
0
#endif
7957
#if !defined(_WIN32) && !defined(__linux__) && !defined(__EMSCRIPTEN__)
7958
  switch (addr->sa_family) {
7959
#ifdef INET6
7960
  case AF_INET6:
7961
  {
7962
#if defined(__FreeBSD__) && !defined(__Userspace__)
7963
    struct sockaddr_in6 *sin6;
7964
7965
#endif
7966
    if (addr->sa_len != sizeof(struct sockaddr_in6)) {
7967
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7968
      return (EINVAL);
7969
    }
7970
#if defined(__FreeBSD__) && !defined(__Userspace__)
7971
    sin6 = (struct sockaddr_in6 *)addr;
7972
    if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6->sin6_addr)) != 0) {
7973
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
7974
      return (error);
7975
    }
7976
#endif
7977
    break;
7978
  }
7979
#endif
7980
#ifdef INET
7981
  case AF_INET:
7982
  {
7983
#if defined(__FreeBSD__) && !defined(__Userspace__)
7984
    struct sockaddr_in *sin;
7985
7986
#endif
7987
#if !defined(_WIN32)
7988
    if (addr->sa_len != sizeof(struct sockaddr_in)) {
7989
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7990
      return (EINVAL);
7991
    }
7992
#endif
7993
#if defined(__FreeBSD__) && !defined(__Userspace__)
7994
    sin = (struct sockaddr_in *)addr;
7995
    if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sin->sin_addr)) != 0) {
7996
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
7997
      return (error);
7998
    }
7999
#endif
8000
    break;
8001
  }
8002
#endif
8003
  default:
8004
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
8005
    return (EAFNOSUPPORT);
8006
  }
8007
#endif
8008
0
  SCTP_INP_INCR_REF(inp);
8009
0
  SCTP_ASOC_CREATE_LOCK(inp);
8010
0
  create_lock_on = 1;
8011
#if defined(__FreeBSD__) && !defined(__Userspace__)
8012
  NET_EPOCH_ENTER(et);
8013
#endif
8014
8015
0
  if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
8016
0
      (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
8017
    /* Should I really unlock ? */
8018
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
8019
0
    error = EFAULT;
8020
0
    goto out_now;
8021
0
  }
8022
0
#ifdef INET6
8023
0
  if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
8024
0
      (addr->sa_family == AF_INET6)) {
8025
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8026
0
    error = EINVAL;
8027
0
    goto out_now;
8028
0
  }
8029
0
#endif
8030
0
#if defined(__Userspace__)
8031
0
  if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) &&
8032
0
      (addr->sa_family != AF_CONN)) {
8033
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8034
0
    error = EINVAL;
8035
0
    goto out_now;
8036
0
  }
8037
0
#endif
8038
0
  if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
8039
    /* Bind a ephemeral port */
8040
0
    error = sctp_inpcb_bind(so, NULL, NULL, p);
8041
0
    if (error) {
8042
0
      goto out_now;
8043
0
    }
8044
0
  }
8045
  /* Now do we connect? */
8046
0
  if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
8047
0
      (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
8048
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8049
0
    error = EINVAL;
8050
0
    goto out_now;
8051
0
  }
8052
0
  if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
8053
0
      (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
8054
    /* We are already connected AND the TCP model */
8055
0
    SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
8056
0
    error = EADDRINUSE;
8057
0
    goto out_now;
8058
0
  }
8059
0
  if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
8060
0
    SCTP_INP_RLOCK(inp);
8061
0
    stcb = LIST_FIRST(&inp->sctp_asoc_list);
8062
0
    SCTP_INP_RUNLOCK(inp);
8063
0
  } else {
8064
    /* We increment here since sctp_findassociation_ep_addr() will
8065
     * do a decrement if it finds the stcb as long as the locked
8066
     * tcb (last argument) is NOT a TCB.. aka NULL.
8067
     */
8068
0
    SCTP_INP_INCR_REF(inp);
8069
0
    stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
8070
0
    if (stcb == NULL) {
8071
0
      SCTP_INP_DECR_REF(inp);
8072
0
    } else {
8073
0
      SCTP_TCB_UNLOCK(stcb);
8074
0
    }
8075
0
  }
8076
0
  if (stcb != NULL) {
8077
    /* Already have or am bring up an association */
8078
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
8079
0
    error = EALREADY;
8080
0
    goto out_now;
8081
0
  }
8082
8083
0
  vrf_id = inp->def_vrf_id;
8084
#ifdef SCTP_MVRF
8085
  for (i = 0; i < inp->num_vrfs; i++) {
8086
    if (vrf_id == inp->m_vrf_ids[i]) {
8087
      fnd = 1;
8088
      break;
8089
    }
8090
  }
8091
  if (!fnd) {
8092
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8093
    error = EINVAL;
8094
    goto out_now;
8095
  }
8096
#endif
8097
  /* We are GOOD to go */
8098
0
  stcb = sctp_aloc_assoc_connected(inp, addr, &error, 0, 0, vrf_id,
8099
0
                                   inp->sctp_ep.pre_open_stream_count,
8100
0
                                   inp->sctp_ep.port, p,
8101
0
                                   SCTP_INITIALIZE_AUTH_PARAMS);
8102
0
  if (stcb == NULL) {
8103
    /* Gak! no memory */
8104
0
    goto out_now;
8105
0
  }
8106
0
  SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
8107
0
  (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
8108
8109
0
  sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
8110
0
  SCTP_TCB_UNLOCK(stcb);
8111
0
 out_now:
8112
#if defined(__FreeBSD__) && !defined(__Userspace__)
8113
  NET_EPOCH_EXIT(et);
8114
#endif
8115
0
  if (create_lock_on) {
8116
0
    SCTP_ASOC_CREATE_UNLOCK(inp);
8117
0
  }
8118
0
  SCTP_INP_DECR_REF(inp);
8119
0
  return (error);
8120
0
}
8121
#endif
8122
8123
#if defined(__Userspace__)
8124
int
8125
sctpconn_connect(struct socket *so, struct sockaddr *addr)
8126
11.5k
{
8127
#ifdef SCTP_MVRF
8128
  int i, fnd = 0;
8129
#endif
8130
11.5k
  void *p = NULL;
8131
11.5k
  int error = 0;
8132
11.5k
  int create_lock_on = 0;
8133
11.5k
  uint32_t vrf_id;
8134
11.5k
  struct sctp_inpcb *inp;
8135
11.5k
  struct sctp_tcb *stcb = NULL;
8136
8137
11.5k
  inp = (struct sctp_inpcb *)so->so_pcb;
8138
11.5k
  if (inp == NULL) {
8139
    /* I made the same as TCP since we are not setup? */
8140
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8141
0
    return (ECONNRESET);
8142
0
  }
8143
11.5k
  if (addr == NULL) {
8144
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8145
0
    return EINVAL;
8146
0
  }
8147
11.5k
  switch (addr->sa_family) {
8148
0
#ifdef INET
8149
0
  case AF_INET:
8150
#ifdef HAVE_SA_LEN
8151
    if (addr->sa_len != sizeof(struct sockaddr_in)) {
8152
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8153
      return (EINVAL);
8154
    }
8155
#endif
8156
0
    break;
8157
0
#endif
8158
0
#ifdef INET6
8159
0
  case AF_INET6:
8160
#ifdef HAVE_SA_LEN
8161
    if (addr->sa_len != sizeof(struct sockaddr_in6)) {
8162
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8163
      return (EINVAL);
8164
    }
8165
#endif
8166
0
    break;
8167
0
#endif
8168
11.5k
  case AF_CONN:
8169
#ifdef HAVE_SA_LEN
8170
    if (addr->sa_len != sizeof(struct sockaddr_conn)) {
8171
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8172
      return (EINVAL);
8173
    }
8174
#endif
8175
11.5k
    break;
8176
0
  default:
8177
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
8178
0
    return (EAFNOSUPPORT);
8179
11.5k
  }
8180
11.5k
  SCTP_INP_INCR_REF(inp);
8181
11.5k
  SCTP_ASOC_CREATE_LOCK(inp);
8182
11.5k
  create_lock_on = 1;
8183
8184
8185
11.5k
  if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
8186
11.5k
      (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
8187
    /* Should I really unlock ? */
8188
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
8189
0
          error = EFAULT;
8190
0
    goto out_now;
8191
0
  }
8192
11.5k
#ifdef INET6
8193
11.5k
  if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
8194
11.5k
      (addr->sa_family == AF_INET6)) {
8195
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8196
0
    error = EINVAL;
8197
0
    goto out_now;
8198
0
  }
8199
11.5k
#endif
8200
11.5k
  if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
8201
    /* Bind a ephemeral port */
8202
0
    error = sctp_inpcb_bind(so, NULL, NULL, p);
8203
0
    if (error) {
8204
0
      goto out_now;
8205
0
    }
8206
0
  }
8207
  /* Now do we connect? */
8208
11.5k
  if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
8209
11.5k
      (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
8210
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8211
0
    error = EINVAL;
8212
0
    goto out_now;
8213
0
  }
8214
11.5k
  if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
8215
11.5k
      (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
8216
    /* We are already connected AND the TCP model */
8217
0
    SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
8218
0
    error = EADDRINUSE;
8219
0
    goto out_now;
8220
0
  }
8221
11.5k
  if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
8222
0
    SCTP_INP_RLOCK(inp);
8223
0
    stcb = LIST_FIRST(&inp->sctp_asoc_list);
8224
0
    SCTP_INP_RUNLOCK(inp);
8225
11.5k
  } else {
8226
    /* We increment here since sctp_findassociation_ep_addr() will
8227
     * do a decrement if it finds the stcb as long as the locked
8228
     * tcb (last argument) is NOT a TCB.. aka NULL.
8229
     */
8230
11.5k
    SCTP_INP_INCR_REF(inp);
8231
11.5k
    stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
8232
11.5k
    if (stcb == NULL) {
8233
11.5k
      SCTP_INP_DECR_REF(inp);
8234
11.5k
    } else {
8235
0
      SCTP_TCB_UNLOCK(stcb);
8236
0
    }
8237
11.5k
  }
8238
11.5k
  if (stcb != NULL) {
8239
    /* Already have or am bring up an association */
8240
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
8241
0
    error = EALREADY;
8242
0
    goto out_now;
8243
0
  }
8244
8245
11.5k
  vrf_id = inp->def_vrf_id;
8246
#ifdef SCTP_MVRF
8247
  for (i = 0; i < inp->num_vrfs; i++) {
8248
    if (vrf_id == inp->m_vrf_ids[i]) {
8249
      fnd = 1;
8250
      break;
8251
    }
8252
  }
8253
  if (!fnd) {
8254
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8255
    error = EINVAL;
8256
    goto out_now;
8257
  }
8258
#endif
8259
  /* We are GOOD to go */
8260
11.5k
  stcb = sctp_aloc_assoc_connected(inp, addr, &error, 0, 0, vrf_id,
8261
11.5k
                                   inp->sctp_ep.pre_open_stream_count,
8262
11.5k
                                   inp->sctp_ep.port, p,
8263
11.5k
                                   SCTP_INITIALIZE_AUTH_PARAMS);
8264
11.5k
  if (stcb == NULL) {
8265
    /* Gak! no memory */
8266
0
    goto out_now;
8267
0
  }
8268
11.5k
  SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
8269
11.5k
  (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
8270
8271
11.5k
  sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
8272
11.5k
  SCTP_TCB_UNLOCK(stcb);
8273
11.5k
 out_now:
8274
11.5k
  if (create_lock_on) {
8275
11.5k
    SCTP_ASOC_CREATE_UNLOCK(inp);
8276
11.5k
  }
8277
8278
11.5k
  SCTP_INP_DECR_REF(inp);
8279
11.5k
  return (error);
8280
11.5k
}
8281
#endif
8282
int
8283
#if defined(__Userspace__)
8284
sctp_listen(struct socket *so, int backlog, struct proc *p)
8285
#elif defined(__FreeBSD__)
8286
sctp_listen(struct socket *so, int backlog, struct thread *p)
8287
#elif defined(_WIN32)
8288
sctp_listen(struct socket *so, int backlog, PKTHREAD p)
8289
#else
8290
sctp_listen(struct socket *so, struct proc *p)
8291
#endif
8292
1
{
8293
  /*
8294
   * Note this module depends on the protocol processing being called
8295
   * AFTER any socket level flags and backlog are applied to the
8296
   * socket. The traditional way that the socket flags are applied is
8297
   * AFTER protocol processing. We have made a change to the
8298
   * sys/kern/uipc_socket.c module to reverse this but this MUST be in
8299
   * place if the socket API for SCTP is to work properly.
8300
   */
8301
8302
1
  int error = 0;
8303
1
  struct sctp_inpcb *inp;
8304
8305
1
  inp = (struct sctp_inpcb *)so->so_pcb;
8306
1
  if (inp == NULL) {
8307
    /* I made the same as TCP since we are not setup? */
8308
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8309
0
    return (ECONNRESET);
8310
0
  }
8311
1
  if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
8312
    /* See if we have a listener */
8313
0
    struct sctp_inpcb *tinp;
8314
0
    union sctp_sockstore store;
8315
8316
0
    if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
8317
      /* not bound all */
8318
0
      struct sctp_laddr *laddr;
8319
8320
0
      LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
8321
0
        memcpy(&store, &laddr->ifa->address, sizeof(store));
8322
0
        switch (store.sa.sa_family) {
8323
0
#ifdef INET
8324
0
        case AF_INET:
8325
0
          store.sin.sin_port = inp->sctp_lport;
8326
0
          break;
8327
0
#endif
8328
0
#ifdef INET6
8329
0
        case AF_INET6:
8330
0
          store.sin6.sin6_port = inp->sctp_lport;
8331
0
          break;
8332
0
#endif
8333
0
#if defined(__Userspace__)
8334
0
        case AF_CONN:
8335
0
          store.sconn.sconn_port = inp->sctp_lport;
8336
0
          break;
8337
0
#endif
8338
0
        default:
8339
0
          break;
8340
0
        }
8341
0
        tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
8342
0
        if (tinp && (tinp != inp) &&
8343
0
            ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
8344
0
            ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
8345
0
            (SCTP_IS_LISTENING(tinp))) {
8346
          /* we have a listener already and its not this inp. */
8347
0
          SCTP_INP_DECR_REF(tinp);
8348
0
          return (EADDRINUSE);
8349
0
        } else if (tinp) {
8350
0
          SCTP_INP_DECR_REF(tinp);
8351
0
        }
8352
0
      }
8353
0
    } else {
8354
      /* Setup a local addr bound all */
8355
0
      memset(&store, 0, sizeof(store));
8356
0
#ifdef INET6
8357
0
      if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
8358
0
        store.sa.sa_family = AF_INET6;
8359
#ifdef HAVE_SA_LEN
8360
        store.sa.sa_len = sizeof(struct sockaddr_in6);
8361
#endif
8362
0
      }
8363
0
#endif
8364
0
#if defined(__Userspace__)
8365
0
      if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) {
8366
0
        store.sa.sa_family = AF_CONN;
8367
#ifdef HAVE_SA_LEN
8368
        store.sa.sa_len = sizeof(struct sockaddr_conn);
8369
#endif
8370
0
      }
8371
0
#endif
8372
0
#ifdef INET
8373
0
#if defined(__Userspace__)
8374
0
      if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
8375
0
          ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_CONN) == 0)) {
8376
#else
8377
      if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
8378
#endif
8379
0
        store.sa.sa_family = AF_INET;
8380
#ifdef HAVE_SA_LEN
8381
        store.sa.sa_len = sizeof(struct sockaddr_in);
8382
#endif
8383
0
      }
8384
0
#endif
8385
0
      switch (store.sa.sa_family) {
8386
0
#ifdef INET
8387
0
      case AF_INET:
8388
0
        store.sin.sin_port = inp->sctp_lport;
8389
0
        break;
8390
0
#endif
8391
0
#ifdef INET6
8392
0
      case AF_INET6:
8393
0
        store.sin6.sin6_port = inp->sctp_lport;
8394
0
        break;
8395
0
#endif
8396
0
#if defined(__Userspace__)
8397
0
      case AF_CONN:
8398
0
        store.sconn.sconn_port = inp->sctp_lport;
8399
0
        break;
8400
0
#endif
8401
0
      default:
8402
0
        break;
8403
0
      }
8404
0
      tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
8405
0
      if (tinp && (tinp != inp) &&
8406
0
          ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
8407
0
          ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
8408
0
          (SCTP_IS_LISTENING(tinp))) {
8409
        /* we have a listener already and its not this inp. */
8410
0
        SCTP_INP_DECR_REF(tinp);
8411
0
        return (EADDRINUSE);
8412
0
      } else if (tinp) {
8413
0
        SCTP_INP_DECR_REF(tinp);
8414
0
      }
8415
0
    }
8416
0
  }
8417
1
  SCTP_INP_INFO_WLOCK();
8418
1
  SCTP_INP_WLOCK(inp);
8419
#ifdef SCTP_LOCK_LOGGING
8420
  if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
8421
    sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
8422
  }
8423
#endif
8424
1
  if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
8425
1
      (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
8426
    /* The unlucky case
8427
     * - We are in the tcp pool with this guy.
8428
     * - Someone else is in the main inp slot.
8429
     * - We must move this guy (the listener) to the main slot
8430
     * - We must then move the guy that was listener to the TCP Pool.
8431
     */
8432
0
    if (sctp_swap_inpcb_for_listen(inp)) {
8433
0
      error = EADDRINUSE;
8434
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
8435
0
      goto out;
8436
0
    }
8437
0
  }
8438
1
#if defined(__FreeBSD__) || defined(__Userspace__)
8439
1
  SOCK_LOCK(so);
8440
1
  error = solisten_proto_check(so);
8441
1
  if (error) {
8442
0
    SOCK_UNLOCK(so);
8443
0
    goto out;
8444
0
  }
8445
1
#endif
8446
1
  if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
8447
1
      (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
8448
0
    SOCK_UNLOCK(so);
8449
#if defined(__FreeBSD__) && !defined(__Userspace__)
8450
    solisten_proto_abort(so);
8451
#endif
8452
0
    error = EADDRINUSE;
8453
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
8454
0
    goto out;
8455
0
  }
8456
1
  if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
8457
1
      ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) ||
8458
1
       (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED))) {
8459
0
    SOCK_UNLOCK(so);
8460
#if defined(__FreeBSD__) && !defined(__Userspace__)
8461
    solisten_proto_abort(so);
8462
#endif
8463
0
    error = EINVAL;
8464
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
8465
0
    goto out;
8466
0
  }
8467
1
  if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
8468
0
    if ((error = sctp_inpcb_bind_locked(inp, NULL, NULL, p))) {
8469
0
      SOCK_UNLOCK(so);
8470
#if defined(__FreeBSD__) && !defined(__Userspace__)
8471
      solisten_proto_abort(so);
8472
#endif
8473
      /* bind error, probably perm */
8474
0
      goto out;
8475
0
    }
8476
0
  }
8477
#if defined(__FreeBSD__) && !defined(__Userspace__)
8478
  if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) == 0) {
8479
    solisten_proto(so, backlog);
8480
    SOCK_UNLOCK(so);
8481
    inp->sctp_flags |= SCTP_PCB_FLAGS_ACCEPTING;
8482
  } else {
8483
    solisten_proto_abort(so);
8484
    SOCK_UNLOCK(so);
8485
    if (backlog > 0) {
8486
      inp->sctp_flags |= SCTP_PCB_FLAGS_ACCEPTING;
8487
    } else {
8488
      inp->sctp_flags &= ~SCTP_PCB_FLAGS_ACCEPTING;
8489
    }
8490
  }
8491
#elif defined(_WIN32) || defined(__Userspace__)
8492
1
  solisten_proto(so, backlog);
8493
1
#endif
8494
1
#if !(defined(__FreeBSD__) && !defined(__Userspace__))
8495
1
  if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
8496
    /* remove the ACCEPTCONN flag for one-to-many sockets */
8497
0
#if defined(__Userspace__)
8498
0
    so->so_options &= ~SCTP_SO_ACCEPTCONN;
8499
#else
8500
    so->so_options &= ~SO_ACCEPTCONN;
8501
#endif
8502
0
  }
8503
1
  SOCK_UNLOCK(so);
8504
1
  if (backlog > 0) {
8505
1
    inp->sctp_flags |= SCTP_PCB_FLAGS_ACCEPTING;
8506
1
  } else {
8507
0
    inp->sctp_flags &= ~SCTP_PCB_FLAGS_ACCEPTING;
8508
0
  }
8509
1
#endif
8510
1
out:
8511
1
  SCTP_INP_WUNLOCK(inp);
8512
1
  SCTP_INP_INFO_WUNLOCK();
8513
1
  return (error);
8514
1
}
8515
8516
static int sctp_defered_wakeup_cnt = 0;
8517
8518
int
8519
sctp_accept(struct socket *so, struct sockaddr **addr)
8520
0
{
8521
0
  struct sctp_tcb *stcb;
8522
0
  struct sctp_inpcb *inp;
8523
0
  union sctp_sockstore store;
8524
0
#ifdef INET6
8525
#if defined(SCTP_KAME) && defined(SCTP_EMBEDDED_V6_SCOPE)
8526
  int error;
8527
#endif
8528
0
#endif
8529
0
  inp = (struct sctp_inpcb *)so->so_pcb;
8530
8531
0
  if (inp == NULL) {
8532
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8533
0
    return (ECONNRESET);
8534
0
  }
8535
0
  SCTP_INP_WLOCK(inp);
8536
0
  if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
8537
0
    SCTP_INP_WUNLOCK(inp);
8538
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
8539
0
    return (EOPNOTSUPP);
8540
0
  }
8541
0
  if (so->so_state & SS_ISDISCONNECTED) {
8542
0
    SCTP_INP_WUNLOCK(inp);
8543
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
8544
0
    return (ECONNABORTED);
8545
0
  }
8546
0
  stcb = LIST_FIRST(&inp->sctp_asoc_list);
8547
0
  if (stcb == NULL) {
8548
0
    SCTP_INP_WUNLOCK(inp);
8549
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8550
0
    return (ECONNRESET);
8551
0
  }
8552
0
  SCTP_TCB_LOCK(stcb);
8553
0
  store = stcb->asoc.primary_destination->ro._l_addr;
8554
0
  SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_IN_ACCEPT_QUEUE);
8555
  /* Wake any delayed sleep action */
8556
0
  if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
8557
0
    inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
8558
0
    if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
8559
0
      inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
8560
0
      SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
8561
0
      if (sowriteable(inp->sctp_socket)) {
8562
0
#if defined(__Userspace__)
8563
        /*__Userspace__ calling sowwakup_locked because of SOCKBUF_LOCK above. */
8564
0
#endif
8565
0
#if defined(__FreeBSD__) || defined(_WIN32) || defined(__Userspace__)
8566
0
        sowwakeup_locked(inp->sctp_socket);
8567
#else
8568
#if defined(__APPLE__)
8569
        /* socket is locked */
8570
#endif
8571
        sowwakeup(inp->sctp_socket);
8572
#endif
8573
0
      } else {
8574
0
        SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
8575
0
      }
8576
0
    }
8577
0
    if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
8578
0
      inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
8579
0
      SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
8580
0
      if (soreadable(inp->sctp_socket)) {
8581
0
        sctp_defered_wakeup_cnt++;
8582
0
#if defined(__Userspace__)
8583
        /*__Userspace__ calling sorwakup_locked because of SOCKBUF_LOCK above */
8584
0
#endif
8585
0
#if defined(__FreeBSD__) || defined(_WIN32) || defined(__Userspace__)
8586
0
        sorwakeup_locked(inp->sctp_socket);
8587
#else
8588
#if defined(__APPLE__)
8589
        /* socket is locked */
8590
#endif
8591
        sorwakeup(inp->sctp_socket);
8592
#endif
8593
0
      } else {
8594
0
        SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
8595
0
      }
8596
0
    }
8597
0
  }
8598
0
  SCTP_INP_WUNLOCK(inp);
8599
0
  if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
8600
0
    sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
8601
0
                    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_19);
8602
0
  } else {
8603
0
    SCTP_TCB_UNLOCK(stcb);
8604
0
  }
8605
0
  switch (store.sa.sa_family) {
8606
0
#ifdef INET
8607
0
  case AF_INET:
8608
0
  {
8609
0
    struct sockaddr_in *sin;
8610
8611
0
    SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
8612
0
    if (sin == NULL)
8613
0
      return (ENOMEM);
8614
0
    sin->sin_family = AF_INET;
8615
#ifdef HAVE_SIN_LEN
8616
    sin->sin_len = sizeof(*sin);
8617
#endif
8618
0
    sin->sin_port = store.sin.sin_port;
8619
0
    sin->sin_addr = store.sin.sin_addr;
8620
0
    *addr = (struct sockaddr *)sin;
8621
0
    break;
8622
0
  }
8623
0
#endif
8624
0
#ifdef INET6
8625
0
  case AF_INET6:
8626
0
  {
8627
0
    struct sockaddr_in6 *sin6;
8628
8629
0
    SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
8630
0
    if (sin6 == NULL)
8631
0
      return (ENOMEM);
8632
0
    sin6->sin6_family = AF_INET6;
8633
#ifdef HAVE_SIN6_LEN
8634
    sin6->sin6_len = sizeof(*sin6);
8635
#endif
8636
0
    sin6->sin6_port = store.sin6.sin6_port;
8637
0
    sin6->sin6_addr = store.sin6.sin6_addr;
8638
#if defined(SCTP_EMBEDDED_V6_SCOPE)
8639
#ifdef SCTP_KAME
8640
    if ((error = sa6_recoverscope(sin6)) != 0) {
8641
      SCTP_FREE_SONAME(sin6);
8642
      return (error);
8643
    }
8644
#else
8645
    if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
8646
      /*
8647
       * sin6->sin6_scope_id =
8648
       * ntohs(sin6->sin6_addr.s6_addr16[1]);
8649
       */
8650
      in6_recoverscope(sin6, &sin6->sin6_addr, NULL); /* skip ifp check */
8651
    else
8652
      sin6->sin6_scope_id = 0;  /* XXX */
8653
#endif /* SCTP_KAME */
8654
#endif /* SCTP_EMBEDDED_V6_SCOPE */
8655
0
    *addr = (struct sockaddr *)sin6;
8656
0
    break;
8657
0
  }
8658
0
#endif
8659
0
#if defined(__Userspace__)
8660
0
  case AF_CONN:
8661
0
  {
8662
0
    struct sockaddr_conn *sconn;
8663
8664
0
    SCTP_MALLOC_SONAME(sconn, struct sockaddr_conn *, sizeof(struct sockaddr_conn));
8665
0
    if (sconn == NULL) {
8666
0
      return (ENOMEM);
8667
0
    }
8668
0
    sconn->sconn_family = AF_CONN;
8669
#ifdef HAVE_SCONN_LEN
8670
    sconn->sconn_len = sizeof(struct sockaddr_conn);
8671
#endif
8672
0
    sconn->sconn_port = store.sconn.sconn_port;
8673
0
    sconn->sconn_addr = store.sconn.sconn_addr;
8674
0
    *addr = (struct sockaddr *)sconn;
8675
0
    break;
8676
0
  }
8677
0
#endif
8678
0
  default:
8679
    /* TSNH */
8680
0
    break;
8681
0
  }
8682
0
  return (0);
8683
0
}
8684
8685
#ifdef INET
8686
int
8687
#if !defined(__Userspace__)
8688
sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
8689
{
8690
  struct sockaddr_in *sin;
8691
#else
8692
sctp_ingetaddr(struct socket *so, struct mbuf *nam)
8693
0
{
8694
0
  struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
8695
0
#endif
8696
0
  uint32_t vrf_id;
8697
0
  struct sctp_inpcb *inp;
8698
0
  struct sctp_ifa *sctp_ifa;
8699
8700
  /*
8701
   * Do the malloc first in case it blocks.
8702
   */
8703
#if !defined(__Userspace__)
8704
  SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
8705
  if (sin == NULL)
8706
    return (ENOMEM);
8707
#else
8708
0
  SCTP_BUF_LEN(nam) = sizeof(*sin);
8709
0
  memset(sin, 0, sizeof(*sin));
8710
0
#endif
8711
0
  sin->sin_family = AF_INET;
8712
#ifdef HAVE_SIN_LEN
8713
  sin->sin_len = sizeof(*sin);
8714
#endif
8715
0
  inp = (struct sctp_inpcb *)so->so_pcb;
8716
0
  if (!inp) {
8717
#if !defined(__Userspace__)
8718
    SCTP_FREE_SONAME(sin);
8719
#endif
8720
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8721
0
    return (ECONNRESET);
8722
0
  }
8723
0
  SCTP_INP_RLOCK(inp);
8724
0
  sin->sin_port = inp->sctp_lport;
8725
0
  if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
8726
0
    if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
8727
0
      struct sctp_tcb *stcb;
8728
0
      struct sockaddr_in *sin_a;
8729
0
      struct sctp_nets *net;
8730
0
      int fnd;
8731
8732
0
      stcb = LIST_FIRST(&inp->sctp_asoc_list);
8733
0
      if (stcb == NULL) {
8734
0
        goto notConn;
8735
0
      }
8736
0
      fnd = 0;
8737
0
      sin_a = NULL;
8738
0
      SCTP_TCB_LOCK(stcb);
8739
0
      TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
8740
0
        sin_a = (struct sockaddr_in *)&net->ro._l_addr;
8741
0
        if (sin_a == NULL)
8742
          /* this will make coverity happy */
8743
0
          continue;
8744
8745
0
        if (sin_a->sin_family == AF_INET) {
8746
0
          fnd = 1;
8747
0
          break;
8748
0
        }
8749
0
      }
8750
0
      if ((!fnd) || (sin_a == NULL)) {
8751
        /* punt */
8752
0
        SCTP_TCB_UNLOCK(stcb);
8753
0
        goto notConn;
8754
0
      }
8755
8756
0
      vrf_id = inp->def_vrf_id;
8757
0
      sctp_ifa = sctp_source_address_selection(inp,
8758
0
                 stcb,
8759
0
                 (sctp_route_t *)&net->ro,
8760
0
                 net, 0, vrf_id);
8761
0
      if (sctp_ifa) {
8762
0
        sin->sin_addr = sctp_ifa->address.sin.sin_addr;
8763
0
        sctp_free_ifa(sctp_ifa);
8764
0
      }
8765
0
      SCTP_TCB_UNLOCK(stcb);
8766
0
    } else {
8767
      /* For the bound all case you get back 0 */
8768
0
  notConn:
8769
0
      sin->sin_addr.s_addr = 0;
8770
0
    }
8771
8772
0
  } else {
8773
    /* Take the first IPv4 address in the list */
8774
0
    struct sctp_laddr *laddr;
8775
0
    int fnd = 0;
8776
8777
0
    LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
8778
0
      if (laddr->ifa->address.sa.sa_family == AF_INET) {
8779
0
        struct sockaddr_in *sin_a;
8780
8781
0
        sin_a = &laddr->ifa->address.sin;
8782
0
        sin->sin_addr = sin_a->sin_addr;
8783
0
        fnd = 1;
8784
0
        break;
8785
0
      }
8786
0
    }
8787
0
    if (!fnd) {
8788
#if !defined(__Userspace__)
8789
      SCTP_FREE_SONAME(sin);
8790
#endif
8791
0
      SCTP_INP_RUNLOCK(inp);
8792
0
      SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
8793
0
      return (ENOENT);
8794
0
    }
8795
0
  }
8796
0
  SCTP_INP_RUNLOCK(inp);
8797
#if !defined(__Userspace__)
8798
  (*addr) = (struct sockaddr *)sin;
8799
#endif
8800
0
  return (0);
8801
0
}
8802
8803
int
8804
#if !defined(__Userspace__)
8805
sctp_peeraddr(struct socket *so, struct sockaddr **addr)
8806
{
8807
  struct sockaddr_in *sin;
8808
#else
8809
sctp_peeraddr(struct socket *so, struct mbuf *nam)
8810
0
{
8811
0
  struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
8812
8813
0
#endif
8814
0
  int fnd;
8815
0
  struct sockaddr_in *sin_a;
8816
0
  struct sctp_inpcb *inp;
8817
0
  struct sctp_tcb *stcb;
8818
0
  struct sctp_nets *net;
8819
8820
  /* Do the malloc first in case it blocks. */
8821
#if !defined(__Userspace__)
8822
  SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
8823
  if (sin == NULL)
8824
    return (ENOMEM);
8825
#else
8826
0
  SCTP_BUF_LEN(nam) = sizeof(*sin);
8827
0
  memset(sin, 0, sizeof(*sin));
8828
0
#endif
8829
0
  sin->sin_family = AF_INET;
8830
#ifdef HAVE_SIN_LEN
8831
  sin->sin_len = sizeof(*sin);
8832
#endif
8833
8834
0
  inp = (struct sctp_inpcb *)so->so_pcb;
8835
0
  if ((inp == NULL) ||
8836
0
      ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
8837
    /* UDP type and listeners will drop out here */
8838
#if !defined(__Userspace__)
8839
    SCTP_FREE_SONAME(sin);
8840
#endif
8841
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
8842
0
    return (ENOTCONN);
8843
0
  }
8844
0
  SCTP_INP_RLOCK(inp);
8845
0
  stcb = LIST_FIRST(&inp->sctp_asoc_list);
8846
0
  if (stcb) {
8847
0
    SCTP_TCB_LOCK(stcb);
8848
0
  }
8849
0
  SCTP_INP_RUNLOCK(inp);
8850
0
  if (stcb == NULL) {
8851
#if !defined(__Userspace__)
8852
    SCTP_FREE_SONAME(sin);
8853
#endif
8854
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
8855
0
    return (ECONNRESET);
8856
0
  }
8857
0
  fnd = 0;
8858
0
  TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
8859
0
    sin_a = (struct sockaddr_in *)&net->ro._l_addr;
8860
0
    if (sin_a->sin_family == AF_INET) {
8861
0
      fnd = 1;
8862
0
      sin->sin_port = stcb->rport;
8863
0
      sin->sin_addr = sin_a->sin_addr;
8864
0
      break;
8865
0
    }
8866
0
  }
8867
0
  SCTP_TCB_UNLOCK(stcb);
8868
0
  if (!fnd) {
8869
    /* No IPv4 address */
8870
#if !defined(__Userspace__)
8871
    SCTP_FREE_SONAME(sin);
8872
#endif
8873
0
    SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
8874
0
    return (ENOENT);
8875
0
  }
8876
#if !defined(__Userspace__)
8877
  (*addr) = (struct sockaddr *)sin;
8878
#endif
8879
0
  return (0);
8880
0
}
8881
8882
#if !defined(__Userspace__)
8883
#if defined(__FreeBSD__)
8884
#define SCTP_PROTOSW            \
8885
  .pr_protocol =  IPPROTO_SCTP,       \
8886
  .pr_ctloutput = sctp_ctloutput,       \
8887
  .pr_abort = sctp_abort,       \
8888
  .pr_accept =  sctp_accept,        \
8889
  .pr_attach =  sctp_attach,        \
8890
  .pr_bind =  sctp_bind,        \
8891
  .pr_connect = sctp_connect,       \
8892
  .pr_control = in_control,       \
8893
  .pr_close = sctp_close,       \
8894
  .pr_detach =  sctp_close,       \
8895
  .pr_flush = sctp_flush,       \
8896
  .pr_disconnect = sctp_disconnect,     \
8897
  .pr_listen =  sctp_listen,        \
8898
  .pr_peeraddr =  sctp_peeraddr,        \
8899
  .pr_send =  sctp_sendm,       \
8900
  .pr_shutdown =  sctp_shutdown,        \
8901
  .pr_sockaddr =  sctp_ingetaddr,       \
8902
  .pr_sosend =  sctp_sosend,        \
8903
  .pr_soreceive = sctp_soreceive        \
8904
8905
struct protosw sctp_seqpacket_protosw = {
8906
  .pr_type =  SOCK_SEQPACKET,
8907
  .pr_flags = PR_WANTRCVD,
8908
  SCTP_PROTOSW
8909
};
8910
8911
struct protosw sctp_stream_protosw = {
8912
  .pr_type =      SOCK_STREAM,
8913
  .pr_flags = PR_CONNREQUIRED | PR_WANTRCVD,
8914
  SCTP_PROTOSW
8915
};
8916
#else
8917
struct pr_usrreqs sctp_usrreqs = {
8918
#if defined(__APPLE__)
8919
  .pru_abort = sctp_abort,
8920
  .pru_accept = sctp_accept,
8921
  .pru_attach = sctp_attach,
8922
  .pru_bind = sctp_bind,
8923
  .pru_connect = sctp_connect,
8924
  .pru_connect2 = pru_connect2_notsupp,
8925
  .pru_control = in_control,
8926
  .pru_detach = sctp_detach,
8927
  .pru_disconnect = sctp_disconnect,
8928
  .pru_listen = sctp_listen,
8929
  .pru_peeraddr = sctp_peeraddr,
8930
  .pru_rcvd = NULL,
8931
  .pru_rcvoob = pru_rcvoob_notsupp,
8932
  .pru_send = sctp_sendm,
8933
  .pru_sense = pru_sense_null,
8934
  .pru_shutdown = sctp_shutdown,
8935
  .pru_sockaddr = sctp_ingetaddr,
8936
  .pru_sosend = sctp_sosend,
8937
  .pru_soreceive = sctp_soreceive,
8938
  .pru_sopoll = sopoll
8939
#elif defined(_WIN32) && !defined(__Userspace__)
8940
  sctp_abort,
8941
  sctp_accept,
8942
  sctp_attach,
8943
  sctp_bind,
8944
  sctp_connect,
8945
  pru_connect2_notsupp,
8946
  NULL,
8947
  NULL,
8948
  sctp_disconnect,
8949
  sctp_listen,
8950
  sctp_peeraddr,
8951
  NULL,
8952
  pru_rcvoob_notsupp,
8953
  NULL,
8954
  pru_sense_null,
8955
  sctp_shutdown,
8956
  sctp_flush,
8957
  sctp_ingetaddr,
8958
  sctp_sosend,
8959
  sctp_soreceive,
8960
  sopoll_generic,
8961
  NULL,
8962
  sctp_close
8963
#endif
8964
};
8965
#endif
8966
#endif
8967
#endif
8968
8969
#if defined(__Userspace__)
8970
int
8971
register_recv_cb(struct socket *so,
8972
                 int (*receive_cb)(struct socket *sock, union sctp_sockstore addr, void *data,
8973
                 size_t datalen, struct sctp_rcvinfo, int flags, void *ulp_info))
8974
11.5k
{
8975
11.5k
  struct sctp_inpcb *inp;
8976
8977
11.5k
  inp = (struct sctp_inpcb *) so->so_pcb;
8978
11.5k
  if (inp == NULL) {
8979
0
    return (0);
8980
0
  }
8981
11.5k
  SCTP_INP_WLOCK(inp);
8982
11.5k
  inp->recv_callback = receive_cb;
8983
11.5k
  SCTP_INP_WUNLOCK(inp);
8984
11.5k
  return (1);
8985
11.5k
}
8986
8987
int
8988
register_send_cb(struct socket *so, uint32_t sb_threshold, int (*send_cb)(struct socket *sock, uint32_t sb_free, void *ulp_info))
8989
11.5k
{
8990
11.5k
  struct sctp_inpcb *inp;
8991
8992
11.5k
  inp = (struct sctp_inpcb *) so->so_pcb;
8993
11.5k
  if (inp == NULL) {
8994
0
    return (0);
8995
0
  }
8996
11.5k
  SCTP_INP_WLOCK(inp);
8997
11.5k
  inp->send_callback = send_cb;
8998
11.5k
  inp->send_sb_threshold = sb_threshold;
8999
11.5k
  SCTP_INP_WUNLOCK(inp);
9000
  /* FIXME change to current amount free. This will be the full buffer
9001
   * the first time this is registered but it could be only a portion
9002
   * of the send buffer if this is called a second time e.g. if the
9003
   * threshold changes.
9004
   */
9005
11.5k
  return (1);
9006
11.5k
}
9007
9008
int
9009
register_ulp_info (struct socket *so, void *ulp_info)
9010
11.5k
{
9011
11.5k
  struct sctp_inpcb *inp;
9012
9013
11.5k
  inp = (struct sctp_inpcb *) so->so_pcb;
9014
11.5k
  if (inp == NULL) {
9015
0
    return (0);
9016
0
  }
9017
11.5k
  SCTP_INP_WLOCK(inp);
9018
11.5k
  inp->ulp_info = ulp_info;
9019
11.5k
  SCTP_INP_WUNLOCK(inp);
9020
11.5k
  return (1);
9021
11.5k
}
9022
9023
int
9024
retrieve_ulp_info (struct socket *so, void **pulp_info)
9025
0
{
9026
0
  struct sctp_inpcb *inp;
9027
9028
0
  if (pulp_info == NULL) {
9029
0
    return (0);
9030
0
  }
9031
9032
0
  inp = (struct sctp_inpcb *) so->so_pcb;
9033
0
  if (inp == NULL) {
9034
0
    return (0);
9035
0
  }
9036
0
  SCTP_INP_RLOCK(inp);
9037
0
  *pulp_info = inp->ulp_info;
9038
0
  SCTP_INP_RUNLOCK(inp);
9039
0
  return (1);
9040
0
}
9041
#endif