Coverage Report

Created: 2025-08-03 06:44

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