Coverage Report

Created: 2025-12-31 07:49

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