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