1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
5  * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
6  * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * a) Redistributions of source code must retain the above copyright notice,
12  *    this list of conditions and the following disclaimer.
13  *
14  * b) Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the distribution.
17  *
18  * c) Neither the name of Cisco Systems, Inc. nor the names of its
19  *    contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32  * THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #if defined(__FreeBSD__) && !defined(__Userspace__)
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 361895 2020-06-07 14:39:20Z tuexen $");
38 #endif
39 
40 #include <netinet/sctp_os.h>
41 #ifdef INET6
42 #if defined(__FreeBSD__) && !defined(__Userspace__)
43 #include <sys/proc.h>
44 #endif
45 #include <netinet/sctp_pcb.h>
46 #include <netinet/sctp_header.h>
47 #include <netinet/sctp_var.h>
48 #include <netinet6/sctp6_var.h>
49 #include <netinet/sctp_sysctl.h>
50 #include <netinet/sctp_output.h>
51 #include <netinet/sctp_uio.h>
52 #include <netinet/sctp_asconf.h>
53 #include <netinet/sctputil.h>
54 #include <netinet/sctp_indata.h>
55 #include <netinet/sctp_timer.h>
56 #include <netinet/sctp_auth.h>
57 #include <netinet/sctp_input.h>
58 #include <netinet/sctp_output.h>
59 #include <netinet/sctp_bsd_addr.h>
60 #include <netinet/sctp_crc32.h>
61 #if !defined(_WIN32)
62 #include <netinet/icmp6.h>
63 #include <netinet/udp.h>
64 #endif
65 #if defined(__Userspace__)
66 int ip6_v6only=0;
67 #endif
68 #if defined(__Userspace__)
69 #ifdef INET
70 void
in6_sin6_2_sin(struct sockaddr_in * sin,struct sockaddr_in6 * sin6)71 in6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
72 {
73 #if defined(_WIN32)
74 	uint32_t temp;
75 #endif
76 	memset(sin, 0, sizeof(*sin));
77 #ifdef HAVE_SIN_LEN
78 	sin->sin_len = sizeof(struct sockaddr_in);
79 #endif
80 	sin->sin_family = AF_INET;
81 	sin->sin_port = sin6->sin6_port;
82 #if defined(_WIN32)
83 	temp = sin6->sin6_addr.s6_addr16[7];
84 	temp = temp << 16;
85 	temp = temp | sin6->sin6_addr.s6_addr16[6];
86 	sin->sin_addr.s_addr = temp;
87 #else
88 	sin->sin_addr.s_addr = sin6->sin6_addr.s6_addr32[3];
89 #endif
90 }
91 
92 void
in6_sin6_2_sin_in_sock(struct sockaddr * nam)93 in6_sin6_2_sin_in_sock(struct sockaddr *nam)
94 {
95 	struct sockaddr_in *sin_p;
96 	struct sockaddr_in6 sin6;
97 
98 	/* save original sockaddr_in6 addr and convert it to sockaddr_in  */
99 	sin6 = *(struct sockaddr_in6 *)nam;
100 	sin_p = (struct sockaddr_in *)nam;
101 	in6_sin6_2_sin(sin_p, &sin6);
102 }
103 
104 void
in6_sin_2_v4mapsin6(const struct sockaddr_in * sin,struct sockaddr_in6 * sin6)105 in6_sin_2_v4mapsin6(const struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
106 {
107 	memset(sin6, 0, sizeof(struct sockaddr_in6));
108  	sin6->sin6_family = AF_INET6;
109 #ifdef HAVE_SIN6_LEN
110 	sin6->sin6_len = sizeof(struct sockaddr_in6);
111 #endif
112 	sin6->sin6_port = sin->sin_port;
113 #if defined(_WIN32)
114 	((uint32_t *)&sin6->sin6_addr)[0] = 0;
115 	((uint32_t *)&sin6->sin6_addr)[1] = 0;
116 	((uint32_t *)&sin6->sin6_addr)[2] = htonl(0xffff);
117 	((uint32_t *)&sin6->sin6_addr)[3] = sin->sin_addr.s_addr;
118 #else
119  	sin6->sin6_addr.s6_addr32[0] = 0;
120 	sin6->sin6_addr.s6_addr32[1] = 0;
121  	sin6->sin6_addr.s6_addr32[2] = htonl(0xffff);
122 	sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
123 #endif
124 }
125 #endif
126 #endif
127 
128 #if !defined(__Userspace__)
129 int
130 #if defined(__APPLE__) || defined(__FreeBSD__)
sctp6_input_with_port(struct mbuf ** i_pak,int * offp,uint16_t port)131 sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port)
132 #else
133 sctp6_input(struct mbuf **i_pak, int *offp, int proto)
134 #endif
135 {
136 	struct mbuf *m;
137 	int iphlen;
138 	uint32_t vrf_id;
139 	uint8_t ecn_bits;
140 	struct sockaddr_in6 src, dst;
141 	struct ip6_hdr *ip6;
142 	struct sctphdr *sh;
143 	struct sctp_chunkhdr *ch;
144 	int length, offset;
145 	uint8_t compute_crc;
146 #if defined(__FreeBSD__)
147 	uint32_t mflowid;
148 	uint8_t mflowtype;
149 	uint16_t fibnum;
150 #endif
151 #if !(defined(__APPLE__) || defined(__FreeBSD__))
152 	uint16_t port = 0;
153 #endif
154 
155 	iphlen = *offp;
156 	if (SCTP_GET_PKT_VRFID(*i_pak, vrf_id)) {
157 		SCTP_RELEASE_PKT(*i_pak);
158 		return (IPPROTO_DONE);
159 	}
160 	m = SCTP_HEADER_TO_CHAIN(*i_pak);
161 #ifdef SCTP_MBUF_LOGGING
162 	/* Log in any input mbufs */
163 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
164 		sctp_log_mbc(m, SCTP_MBUF_INPUT);
165 	}
166 #endif
167 #ifdef SCTP_PACKET_LOGGING
168 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) {
169 		sctp_packet_log(m);
170 	}
171 #endif
172 #if defined(__FreeBSD__)
173 	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
174 	        "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%b.\n",
175 	        m->m_pkthdr.len,
176 	        if_name(m->m_pkthdr.rcvif),
177 	        (int)m->m_pkthdr.csum_flags, CSUM_BITS);
178 #endif
179 #if defined(__APPLE__)
180 	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
181 	        "sctp6_input(): Packet of length %d received on %s%d with csum_flags 0x%x.\n",
182 	        m->m_pkthdr.len,
183 	        m->m_pkthdr.rcvif->if_name,
184 	        m->m_pkthdr.rcvif->if_unit,
185 	        m->m_pkthdr.csum_flags);
186 #endif
187 #if defined(_WIN32) && !defined(__Userspace__)
188 	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
189 	        "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
190 	        m->m_pkthdr.len,
191 	        m->m_pkthdr.rcvif->if_xname,
192 	        m->m_pkthdr.csum_flags);
193 #endif
194 #if defined(__FreeBSD__)
195 	mflowid = m->m_pkthdr.flowid;
196 	mflowtype = M_HASHTYPE_GET(m);
197 	fibnum = M_GETFIB(m);
198 #endif
199 	SCTP_STAT_INCR(sctps_recvpackets);
200 	SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
201 	/* Get IP, SCTP, and first chunk header together in the first mbuf. */
202 	offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
203 	if (m->m_len < offset) {
204 		m = m_pullup(m, offset);
205 		if (m == NULL) {
206 			SCTP_STAT_INCR(sctps_hdrops);
207 			return (IPPROTO_DONE);
208 		}
209 	}
210 	ip6 = mtod(m, struct ip6_hdr *);
211 	sh = (struct sctphdr *)(mtod(m, caddr_t) + iphlen);
212 	ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
213 	offset -= sizeof(struct sctp_chunkhdr);
214 	memset(&src, 0, sizeof(struct sockaddr_in6));
215 	src.sin6_family = AF_INET6;
216 #ifdef HAVE_SIN6_LEN
217 	src.sin6_len = sizeof(struct sockaddr_in6);
218 #endif
219 	src.sin6_port = sh->src_port;
220 	src.sin6_addr = ip6->ip6_src;
221 #if defined(__FreeBSD__)
222 #if defined(__APPLE__)
223 	/* XXX: This code should also be used on Apple */
224 #endif
225 	if (in6_setscope(&src.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
226 		goto out;
227 	}
228 #endif
229 	memset(&dst, 0, sizeof(struct sockaddr_in6));
230 	dst.sin6_family = AF_INET6;
231 #ifdef HAVE_SIN6_LEN
232 	dst.sin6_len = sizeof(struct sockaddr_in6);
233 #endif
234 	dst.sin6_port = sh->dest_port;
235 	dst.sin6_addr = ip6->ip6_dst;
236 #if defined(__FreeBSD__)
237 #if defined(__APPLE__)
238 	/* XXX: This code should also be used on Apple */
239 #endif
240 	if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
241 		goto out;
242 	}
243 #endif
244 #if defined(__APPLE__)
245 #if defined(NFAITH) && 0 < NFAITH
246 	if (faithprefix(&dst.sin6_addr)) {
247 		goto out;
248 	}
249 #endif
250 #endif
251 	length = ntohs(ip6->ip6_plen) + iphlen;
252 	/* Validate mbuf chain length with IP payload length. */
253 	if (SCTP_HEADER_LEN(m) != length) {
254 		SCTPDBG(SCTP_DEBUG_INPUT1,
255 		        "sctp6_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m));
256 		SCTP_STAT_INCR(sctps_hdrops);
257 		goto out;
258 	}
259 	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
260 		goto out;
261 	}
262 	ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff);
263 #if defined(__FreeBSD__)
264 	if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
265 		SCTP_STAT_INCR(sctps_recvhwcrc);
266 		compute_crc = 0;
267 	} else {
268 #else
269 	if (SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) &&
270 	    (IN6_ARE_ADDR_EQUAL(&src.sin6_addr, &dst.sin6_addr))) {
271 		SCTP_STAT_INCR(sctps_recvhwcrc);
272 		compute_crc = 0;
273 	} else {
274 #endif
275 		SCTP_STAT_INCR(sctps_recvswcrc);
276 		compute_crc = 1;
277 	}
278 	sctp_common_input_processing(&m, iphlen, offset, length,
279 	                             (struct sockaddr *)&src,
280 	                             (struct sockaddr *)&dst,
281 	                             sh, ch,
282 	                             compute_crc,
283 	                             ecn_bits,
284 #if defined(__FreeBSD__)
285 	                             mflowtype, mflowid, fibnum,
286 #endif
287 	                             vrf_id, port);
288  out:
289 	if (m) {
290 		sctp_m_freem(m);
291 	}
292 	return (IPPROTO_DONE);
293 }
294 
295 #if defined(__APPLE__)
296 int
297 sctp6_input(struct mbuf **i_pak, int *offp)
298 {
299 	return (sctp6_input_with_port(i_pak, offp, 0));
300 }
301 #endif
302 
303 #if defined(__FreeBSD__)
304 int
305 sctp6_input(struct mbuf **i_pak, int *offp, int proto SCTP_UNUSED)
306 {
307 	return (sctp6_input_with_port(i_pak, offp, 0));
308 }
309 #endif
310 
311 void
312 sctp6_notify(struct sctp_inpcb *inp,
313              struct sctp_tcb *stcb,
314              struct sctp_nets *net,
315              uint8_t icmp6_type,
316              uint8_t icmp6_code,
317              uint32_t next_mtu)
318 {
319 #if defined(__APPLE__)
320 	struct socket *so;
321 #endif
322 	int timer_stopped;
323 
324 	switch (icmp6_type) {
325 	case ICMP6_DST_UNREACH:
326 		if ((icmp6_code == ICMP6_DST_UNREACH_NOROUTE) ||
327 		    (icmp6_code == ICMP6_DST_UNREACH_ADMIN) ||
328 		    (icmp6_code == ICMP6_DST_UNREACH_BEYONDSCOPE) ||
329 		    (icmp6_code == ICMP6_DST_UNREACH_ADDR)) {
330 			/* Mark the net unreachable. */
331 			if (net->dest_state & SCTP_ADDR_REACHABLE) {
332 				/* Ok that destination is not reachable */
333 				net->dest_state &= ~SCTP_ADDR_REACHABLE;
334 				net->dest_state &= ~SCTP_ADDR_PF;
335 				sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
336 				                stcb, 0, (void *)net, SCTP_SO_NOT_LOCKED);
337 			}
338 		}
339 		SCTP_TCB_UNLOCK(stcb);
340 		break;
341 	case ICMP6_PARAM_PROB:
342 		/* Treat it like an ABORT. */
343 		if (icmp6_code == ICMP6_PARAMPROB_NEXTHEADER) {
344 			sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
345 #if defined(__APPLE__)
346 			so = SCTP_INP_SO(inp);
347 			atomic_add_int(&stcb->asoc.refcnt, 1);
348 			SCTP_TCB_UNLOCK(stcb);
349 			SCTP_SOCKET_LOCK(so, 1);
350 			SCTP_TCB_LOCK(stcb);
351 			atomic_subtract_int(&stcb->asoc.refcnt, 1);
352 #endif
353 			(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
354 					      SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
355 #if defined(__APPLE__)
356 			SCTP_SOCKET_UNLOCK(so, 1);
357 #endif
358 		} else {
359 			SCTP_TCB_UNLOCK(stcb);
360 		}
361 		break;
362 	case ICMP6_PACKET_TOO_BIG:
363 		if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
364 			SCTP_TCB_UNLOCK(stcb);
365 			break;
366 		}
367 		if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
368 			timer_stopped = 1;
369 			sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
370 			                SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1);
371 		} else {
372 			timer_stopped = 0;
373 		}
374 		/* Update the path MTU. */
375 		if (net->port) {
376 			next_mtu -= sizeof(struct udphdr);
377 		}
378 		if (net->mtu > next_mtu) {
379 			net->mtu = next_mtu;
380 #if defined(__FreeBSD__)
381 			if (net->port) {
382 				sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu + sizeof(struct udphdr));
383 			} else {
384 				sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu);
385 			}
386 #endif
387 		}
388 		/* Update the association MTU */
389 		if (stcb->asoc.smallest_mtu > next_mtu) {
390 			sctp_pathmtu_adjustment(stcb, next_mtu);
391 		}
392 		/* Finally, start the PMTU timer if it was running before. */
393 		if (timer_stopped) {
394 			sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
395 		}
396 		SCTP_TCB_UNLOCK(stcb);
397 		break;
398 	default:
399 		SCTP_TCB_UNLOCK(stcb);
400 		break;
401 	}
402 }
403 
404 void
405 #if defined(__APPLE__) && !defined(APPLE_LEOPARD) && !defined(APPLE_SNOWLEOPARD) && !defined(APPLE_LION) && !defined(APPLE_MOUNTAINLION) && !defined(APPLE_ELCAPITAN)
406 sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d, struct ifnet *ifp SCTP_UNUSED)
407 #else
408 sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
409 #endif
410 {
411 	struct ip6ctlparam *ip6cp;
412 	struct sctp_inpcb *inp;
413 	struct sctp_tcb *stcb;
414 	struct sctp_nets *net;
415 	struct sctphdr sh;
416 	struct sockaddr_in6 src, dst;
417 
418 #ifdef HAVE_SA_LEN
419 	if (pktdst->sa_family != AF_INET6 ||
420 	    pktdst->sa_len != sizeof(struct sockaddr_in6)) {
421 #else
422 	if (pktdst->sa_family != AF_INET6) {
423 #endif
424 		return;
425 	}
426 
427 	if ((unsigned)cmd >= PRC_NCMDS) {
428 		return;
429 	}
430 	if (PRC_IS_REDIRECT(cmd)) {
431 		d = NULL;
432 	} else if (inet6ctlerrmap[cmd] == 0) {
433 		return;
434 	}
435 	/* If the parameter is from icmp6, decode it. */
436 	if (d != NULL) {
437 		ip6cp = (struct ip6ctlparam *)d;
438 	} else {
439 		ip6cp = (struct ip6ctlparam *)NULL;
440 	}
441 
442 	if (ip6cp != NULL) {
443 		/*
444 		 * XXX: We assume that when IPV6 is non NULL, M and OFF are
445 		 * valid.
446 		 */
447 		if (ip6cp->ip6c_m == NULL) {
448 			return;
449 		}
450 
451 		/* Check if we can safely examine the ports and the
452 		 * verification tag of the SCTP common header.
453 		 */
454 		if (ip6cp->ip6c_m->m_pkthdr.len <
455 		    (int32_t)(ip6cp->ip6c_off + offsetof(struct sctphdr, checksum))) {
456 			return;
457 		}
458 
459 		/* Copy out the port numbers and the verification tag. */
460 		memset(&sh, 0, sizeof(sh));
461 		m_copydata(ip6cp->ip6c_m,
462 		           ip6cp->ip6c_off,
463 		           sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t),
464 		           (caddr_t)&sh);
465 		memset(&src, 0, sizeof(struct sockaddr_in6));
466 		src.sin6_family = AF_INET6;
467 #ifdef HAVE_SIN6_LEN
468 		src.sin6_len = sizeof(struct sockaddr_in6);
469 #endif
470 		src.sin6_port = sh.src_port;
471 		src.sin6_addr = ip6cp->ip6c_ip6->ip6_src;
472 #if defined(__FreeBSD__)
473 		if (in6_setscope(&src.sin6_addr, ip6cp->ip6c_m->m_pkthdr.rcvif, NULL) != 0) {
474 			return;
475 		}
476 #endif
477 		memset(&dst, 0, sizeof(struct sockaddr_in6));
478 		dst.sin6_family = AF_INET6;
479 #ifdef HAVE_SIN6_LEN
480 		dst.sin6_len = sizeof(struct sockaddr_in6);
481 #endif
482 		dst.sin6_port = sh.dest_port;
483 		dst.sin6_addr = ip6cp->ip6c_ip6->ip6_dst;
484 #if defined(__FreeBSD__)
485 		if (in6_setscope(&dst.sin6_addr, ip6cp->ip6c_m->m_pkthdr.rcvif, NULL) != 0) {
486 			return;
487 		}
488 #endif
489 		inp = NULL;
490 		net = NULL;
491 		stcb = sctp_findassociation_addr_sa((struct sockaddr *)&dst,
492 		                                    (struct sockaddr *)&src,
493 		                                    &inp, &net, 1, SCTP_DEFAULT_VRFID);
494 		if ((stcb != NULL) &&
495 		    (net != NULL) &&
496 		    (inp != NULL)) {
497 			/* Check the verification tag */
498 			if (ntohl(sh.v_tag) != 0) {
499 				/*
500 				 * This must be the verification tag used for
501 				 * sending out packets. We don't consider
502 				 * packets reflecting the verification tag.
503 				 */
504 				if (ntohl(sh.v_tag) != stcb->asoc.peer_vtag) {
505 					SCTP_TCB_UNLOCK(stcb);
506 					return;
507 				}
508 			} else {
509 #if defined(__FreeBSD__)
510 				if (ip6cp->ip6c_m->m_pkthdr.len >=
511 				    ip6cp->ip6c_off + sizeof(struct sctphdr) +
512 				                      sizeof(struct sctp_chunkhdr) +
513 				                      offsetof(struct sctp_init, a_rwnd)) {
514 					/*
515 					 * In this case we can check if we
516 					 * got an INIT chunk and if the
517 					 * initiate tag matches.
518 					 */
519 					uint32_t initiate_tag;
520 					uint8_t chunk_type;
521 
522 					m_copydata(ip6cp->ip6c_m,
523 					           ip6cp->ip6c_off +
524 					           sizeof(struct sctphdr),
525 					           sizeof(uint8_t),
526 					           (caddr_t)&chunk_type);
527 					m_copydata(ip6cp->ip6c_m,
528 					           ip6cp->ip6c_off +
529 					           sizeof(struct sctphdr) +
530 					           sizeof(struct sctp_chunkhdr),
531 					           sizeof(uint32_t),
532 					           (caddr_t)&initiate_tag);
533 					if ((chunk_type != SCTP_INITIATION) ||
534 					    (ntohl(initiate_tag) != stcb->asoc.my_vtag)) {
535 						SCTP_TCB_UNLOCK(stcb);
536 						return;
537 					}
538 				} else {
539 					SCTP_TCB_UNLOCK(stcb);
540 					return;
541 				}
542 #else
543 				SCTP_TCB_UNLOCK(stcb);
544 				return;
545 #endif
546 			}
547 			sctp6_notify(inp, stcb, net,
548 			             ip6cp->ip6c_icmp6->icmp6_type,
549 			             ip6cp->ip6c_icmp6->icmp6_code,
550 			             ntohl(ip6cp->ip6c_icmp6->icmp6_mtu));
551 #if defined(__Userspace__)
552 			if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) &&
553 			    (stcb->sctp_socket != NULL) {
554 				struct socket *upcall_socket;
555 
556 				upcall_socket = stcb->sctp_socket;
557 				SOCK_LOCK(upcall_socket);
558 				soref(upcall_socket);
559 				SOCK_UNLOCK(upcall_socket);
560 				if ((upcall_socket->so_upcall != NULL) &&
561 				    (upcall_socket->so_error != 0)) {
562 					(*upcall_socket->so_upcall)(upcall_socket, upcall_socket->so_upcallarg, M_NOWAIT);
563 				}
564 				ACCEPT_LOCK();
565 				SOCK_LOCK(upcall_socket);
566 				sorele(upcall_socket);
567 			}
568 #endif
569 		} else {
570 			if ((stcb == NULL) && (inp != NULL)) {
571 				/* reduce inp's ref-count */
572 				SCTP_INP_WLOCK(inp);
573 				SCTP_INP_DECR_REF(inp);
574 				SCTP_INP_WUNLOCK(inp);
575 			}
576 			if (stcb) {
577 				SCTP_TCB_UNLOCK(stcb);
578 			}
579 		}
580 	}
581 }
582 #endif
583 
584 /*
585  * this routine can probably be collasped into the one in sctp_userreq.c
586  * since they do the same thing and now we lookup with a sockaddr
587  */
588 #if defined(__FreeBSD__) && !defined(__Userspace__)
589 static int
590 sctp6_getcred(SYSCTL_HANDLER_ARGS)
591 {
592 	struct xucred xuc;
593 	struct sockaddr_in6 addrs[2];
594 	struct sctp_inpcb *inp;
595 	struct sctp_nets *net;
596 	struct sctp_tcb *stcb;
597 	int error;
598 	uint32_t vrf_id;
599 
600 	vrf_id = SCTP_DEFAULT_VRFID;
601 
602 #if defined(__FreeBSD__) && !defined(__Userspace__)
603 	error = priv_check(req->td, PRIV_NETINET_GETCRED);
604 #else
605 	error = suser(req->p);
606 #endif
607 	if (error)
608 		return (error);
609 
610 	if (req->newlen != sizeof(addrs)) {
611 		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
612 		return (EINVAL);
613 	}
614 	if (req->oldlen != sizeof(struct ucred)) {
615 		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
616 		return (EINVAL);
617 	}
618 	error = SYSCTL_IN(req, addrs, sizeof(addrs));
619 	if (error)
620 		return (error);
621 
622 	stcb = sctp_findassociation_addr_sa(sin6tosa(&addrs[1]),
623 	    sin6tosa(&addrs[0]),
624 	    &inp, &net, 1, vrf_id);
625 	if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
626 		if ((inp != NULL) && (stcb == NULL)) {
627 			/* reduce ref-count */
628 			SCTP_INP_WLOCK(inp);
629 			SCTP_INP_DECR_REF(inp);
630 			goto cred_can_cont;
631 		}
632 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
633 		error = ENOENT;
634 		goto out;
635 	}
636 	SCTP_TCB_UNLOCK(stcb);
637 	/* We use the write lock here, only
638 	 * since in the error leg we need it.
639 	 * If we used RLOCK, then we would have
640 	 * to wlock/decr/unlock/rlock. Which
641 	 * in theory could create a hole. Better
642 	 * to use higher wlock.
643 	 */
644 	SCTP_INP_WLOCK(inp);
645  cred_can_cont:
646 	error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
647 	if (error) {
648 		SCTP_INP_WUNLOCK(inp);
649 		goto out;
650 	}
651 	cru2x(inp->sctp_socket->so_cred, &xuc);
652 	SCTP_INP_WUNLOCK(inp);
653 	error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
654 out:
655 	return (error);
656 }
657 
658 SYSCTL_PROC(_net_inet6_sctp6, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
659     0, 0,
660     sctp6_getcred, "S,ucred", "Get the ucred of a SCTP6 connection");
661 
662 #endif
663 
664 /* This is the same as the sctp_abort() could be made common */
665 #if defined(__Userspace__)
666 int
667 #elif defined(__FreeBSD__) || defined(_WIN32)
668 static void
669 #else
670 static int
671 #endif
672 sctp6_abort(struct socket *so)
673 {
674 #if defined(__FreeBSD__) && !defined(__Userspace__)
675 	struct epoch_tracker et;
676 #endif
677 	struct sctp_inpcb *inp;
678 	uint32_t flags;
679 
680 	inp = (struct sctp_inpcb *)so->so_pcb;
681 	if (inp == NULL) {
682 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
683 #if (defined(__FreeBSD__) || defined(_WIN32)) && !defined(__Userspace__)
684 		return;
685 #else
686 		return (EINVAL);
687 #endif
688 	}
689 #if defined(__FreeBSD__) && !defined(__Userspace__)
690 	NET_EPOCH_ENTER(et);
691 #endif
692  sctp_must_try_again:
693 	flags = inp->sctp_flags;
694 #ifdef SCTP_LOG_CLOSING
695 	sctp_log_closing(inp, NULL, 17);
696 #endif
697 	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
698 	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
699 #ifdef SCTP_LOG_CLOSING
700 		sctp_log_closing(inp, NULL, 16);
701 #endif
702 		sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
703 				SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
704 		SOCK_LOCK(so);
705 		SCTP_SB_CLEAR(so->so_snd);
706 		/* same for the rcv ones, they are only
707 		 * here for the accounting/select.
708 		 */
709 		SCTP_SB_CLEAR(so->so_rcv);
710 #if defined(__APPLE__) && !defined(__Userspace__)
711 		so->so_usecount--;
712 #else
713 		/* Now null out the reference, we are completely detached. */
714 		so->so_pcb = NULL;
715 #endif
716 		SOCK_UNLOCK(so);
717 	} else {
718 		flags = inp->sctp_flags;
719 		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
720 			goto sctp_must_try_again;
721 		}
722 	}
723 #if defined(__FreeBSD__) && !defined(__Userspace__)
724 	NET_EPOCH_EXIT(et);
725 	return;
726 #else
727 	return (0);
728 #endif
729 }
730 
731 #if defined(__Userspace__)
732 int
733 sctp6_attach(struct socket *so, int proto SCTP_UNUSED, uint32_t vrf_id)
734 #elif defined(__FreeBSD__)
735 static int
736 sctp6_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
737 #elif defined(_WIN32)
738 static int
739 sctp6_attach(struct socket *so, int proto SCTP_UNUSED, PKTHREAD p SCTP_UNUSED)
740 #else
741 static int
742 sctp6_attach(struct socket *so, int proto SCTP_UNUSED, struct proc *p SCTP_UNUSED)
743 #endif
744 {
745 	int error;
746 	struct sctp_inpcb *inp;
747 #if !defined(__Userspace__)
748 	uint32_t vrf_id = SCTP_DEFAULT_VRFID;
749 #endif
750 
751 	inp = (struct sctp_inpcb *)so->so_pcb;
752 	if (inp != NULL) {
753 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
754 		return (EINVAL);
755 	}
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 	error = sctp_inpcb_alloc(so, vrf_id);
763 	if (error)
764 		return (error);
765 	inp = (struct sctp_inpcb *)so->so_pcb;
766 	SCTP_INP_WLOCK(inp);
767 	inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_V6;	/* I'm v6! */
768 
769 	inp->ip_inp.inp.inp_vflag |= INP_IPV6;
770 	inp->ip_inp.inp.in6p_hops = -1;	/* use kernel default */
771 	inp->ip_inp.inp.in6p_cksum = -1;	/* just to be sure */
772 #ifdef INET
773 	/*
774 	 * XXX: ugly!! IPv4 TTL initialization is necessary for an IPv6
775 	 * socket as well, because the socket may be bound to an IPv6
776 	 * wildcard address, which may match an IPv4-mapped IPv6 address.
777 	 */
778 	inp->ip_inp.inp.inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
779 #endif
780 	SCTP_INP_WUNLOCK(inp);
781 	return (0);
782 }
783 
784 #if defined(__Userspace__)
785 int
786 sctp6_bind(struct socket *so, struct sockaddr *addr, void * p)
787 {
788 #elif defined(__FreeBSD__)
789 static int
790 sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
791 {
792 #elif defined(__APPLE__)
793 static int
794 sctp6_bind(struct socket *so, struct sockaddr *addr, struct proc *p)
795 {
796 #elif defined(_WIN32)
797 static int
798 sctp6_bind(struct socket *so, struct sockaddr *addr, PKTHREAD p)
799 {
800 #else
801 static int
802 sctp6_bind(struct socket *so, struct mbuf *nam, struct proc *p)
803 {
804 	struct sockaddr *addr = nam ? mtod(nam, struct sockaddr *): NULL;
805 
806 #endif
807 	struct sctp_inpcb *inp;
808 	int error;
809 	u_char vflagsav;
810 
811 	inp = (struct sctp_inpcb *)so->so_pcb;
812 	if (inp == NULL) {
813 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
814 		return (EINVAL);
815 	}
816 
817 #if !(defined(_WIN32) && !defined(__Userspace__))
818 	if (addr) {
819 		switch (addr->sa_family) {
820 #ifdef INET
821 		case AF_INET:
822 #ifdef HAVE_SA_LEN
823 			if (addr->sa_len != sizeof(struct sockaddr_in)) {
824 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
825 				return (EINVAL);
826 			}
827 #endif
828 			break;
829 #endif
830 #ifdef INET6
831 		case AF_INET6:
832 #ifdef HAVE_SA_LEN
833 			if (addr->sa_len != sizeof(struct sockaddr_in6)) {
834 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
835 				return (EINVAL);
836 			}
837 #endif
838 			break;
839 #endif
840 		default:
841 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
842 			return (EINVAL);
843 		}
844 	}
845 #endif
846 	vflagsav = inp->ip_inp.inp.inp_vflag;
847 	inp->ip_inp.inp.inp_vflag &= ~INP_IPV4;
848 	inp->ip_inp.inp.inp_vflag |= INP_IPV6;
849 	if ((addr != NULL) && (SCTP_IPV6_V6ONLY(inp) == 0)) {
850 		switch (addr->sa_family) {
851 #ifdef INET
852 		case AF_INET:
853 			/* binding v4 addr to v6 socket, so reset flags */
854 			inp->ip_inp.inp.inp_vflag |= INP_IPV4;
855 			inp->ip_inp.inp.inp_vflag &= ~INP_IPV6;
856 			break;
857 #endif
858 #ifdef INET6
859 		case AF_INET6:
860 		{
861 			struct sockaddr_in6 *sin6_p;
862 
863 			sin6_p = (struct sockaddr_in6 *)addr;
864 
865 			if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) {
866 				inp->ip_inp.inp.inp_vflag |= INP_IPV4;
867 			}
868 #ifdef INET
869 			if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
870 				struct sockaddr_in sin;
871 
872 				in6_sin6_2_sin(&sin, sin6_p);
873 				inp->ip_inp.inp.inp_vflag |= INP_IPV4;
874 				inp->ip_inp.inp.inp_vflag &= ~INP_IPV6;
875 				error = sctp_inpcb_bind(so, (struct sockaddr *)&sin, NULL, p);
876 				goto out;
877 			}
878 #endif
879 			break;
880 		}
881 #endif
882 		default:
883 			break;
884 		}
885 	} else if (addr != NULL) {
886 		struct sockaddr_in6 *sin6_p;
887 
888 		/* IPV6_V6ONLY socket */
889 #ifdef INET
890 		if (addr->sa_family == AF_INET) {
891 			/* can't bind v4 addr to v6 only socket! */
892 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
893 			error = EINVAL;
894 			goto out;
895 		}
896 #endif
897 		sin6_p = (struct sockaddr_in6 *)addr;
898 
899 		if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
900 			/* can't bind v4-mapped addrs either! */
901 			/* NOTE: we don't support SIIT */
902 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
903 			error = EINVAL;
904 			goto out;
905 		}
906 	}
907 	error = sctp_inpcb_bind(so, addr, NULL, p);
908 out:
909 	if (error != 0)
910 		inp->ip_inp.inp.inp_vflag = vflagsav;
911 	return (error);
912 }
913 
914 
915 #if defined(__FreeBSD__) || defined(_WIN32) || defined(__Userspace__)
916 #if !defined(__Userspace__)
917 static void
918 #else
919 void
920 #endif
921 sctp6_close(struct socket *so)
922 {
923 	sctp_close(so);
924 }
925 
926 /* This could be made common with sctp_detach() since they are identical */
927 #else
928 
929 static
930 int
931 sctp6_detach(struct socket *so)
932 {
933 #if defined(__Userspace__)
934 	sctp_close(so);
935 	return (0);
936 #else
937 	return (sctp_detach(so));
938 #endif
939 }
940 
941 #endif
942 
943 #if !defined(__Userspace__)
944 static
945 #endif
946 int
947 sctp6_disconnect(struct socket *so)
948 {
949 	return (sctp_disconnect(so));
950 }
951 
952 
953 int
954 #if defined(__FreeBSD__) && !defined(__Userspace__)
955 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
956     struct mbuf *control, struct thread *p);
957 
958 #else
959 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
960     struct mbuf *control, struct proc *p);
961 
962 #endif
963 
964 #if !defined(_WIN32) && !defined(__Userspace__)
965 #if defined(__FreeBSD__)
966 static int
967 sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
968     struct mbuf *control, struct thread *p)
969 {
970 #elif defined(__APPLE__)
971 static int
972 sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
973     struct mbuf *control, struct proc *p)
974 {
975 #else
976 static int
977 sctp6_send(struct socket *so, int flags, struct mbuf *m, struct mbuf *nam,
978     struct mbuf *control, struct proc *p)
979 {
980 	struct sockaddr *addr = nam ? mtod(nam, struct sockaddr *): NULL;
981 #endif
982 	struct sctp_inpcb *inp;
983 
984 #ifdef INET
985 	struct sockaddr_in6 *sin6;
986 #endif /* INET */
987 	/* No SPL needed since sctp_output does this */
988 
989 	inp = (struct sctp_inpcb *)so->so_pcb;
990 	if (inp == NULL) {
991 		if (control) {
992 			SCTP_RELEASE_PKT(control);
993 			control = NULL;
994 		}
995 		SCTP_RELEASE_PKT(m);
996 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
997 		return (EINVAL);
998 	}
999 	/*
1000 	 * For the TCP model we may get a NULL addr, if we are a connected
1001 	 * socket thats ok.
1002 	 */
1003 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) &&
1004 	    (addr == NULL)) {
1005 		goto connected_type;
1006 	}
1007 	if (addr == NULL) {
1008 		SCTP_RELEASE_PKT(m);
1009 		if (control) {
1010 			SCTP_RELEASE_PKT(control);
1011 			control = NULL;
1012 		}
1013 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EDESTADDRREQ);
1014 		return (EDESTADDRREQ);
1015 	}
1016 #ifdef INET
1017 	sin6 = (struct sockaddr_in6 *)addr;
1018 	if (SCTP_IPV6_V6ONLY(inp)) {
1019 		/*
1020 		 * if IPV6_V6ONLY flag, we discard datagrams destined to a
1021 		 * v4 addr or v4-mapped addr
1022 		 */
1023 		if (addr->sa_family == AF_INET) {
1024 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1025 			return (EINVAL);
1026 		}
1027 		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1028 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1029 			return (EINVAL);
1030 		}
1031 	}
1032 	if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1033 		struct sockaddr_in sin;
1034 
1035 		/* convert v4-mapped into v4 addr and send */
1036 		in6_sin6_2_sin(&sin, sin6);
1037 		return (sctp_sendm(so, flags, m, (struct sockaddr *)&sin, control, p));
1038 	}
1039 #endif				/* INET */
1040 connected_type:
1041 	/* now what about control */
1042 	if (control) {
1043 		if (inp->control) {
1044 			SCTP_PRINTF("huh? control set?\n");
1045 			SCTP_RELEASE_PKT(inp->control);
1046 			inp->control = NULL;
1047 		}
1048 		inp->control = control;
1049 	}
1050 	/* Place the data */
1051 	if (inp->pkt) {
1052 		SCTP_BUF_NEXT(inp->pkt_last) = m;
1053 		inp->pkt_last = m;
1054 	} else {
1055 		inp->pkt_last = inp->pkt = m;
1056 	}
1057 	if (
1058 #if (defined(__FreeBSD__) || defined(__APPLE__)) && !defined(__Userspace__)
1059 	/* FreeBSD and MacOSX uses a flag passed */
1060 	    ((flags & PRUS_MORETOCOME) == 0)
1061 #else
1062 	    1			/* Open BSD does not have any "more to come"
1063 				 * indication */
1064 #endif
1065 	    ) {
1066 		/*
1067 		 * note with the current version this code will only be used
1068 		 * by OpenBSD, NetBSD and FreeBSD have methods for
1069 		 * re-defining sosend() to use sctp_sosend().  One can
1070 		 * optionaly switch back to this code (by changing back the
1071 		 * defininitions but this is not advisable.
1072 		 */
1073 #if defined(__FreeBSD__) && !defined(__Userspace__)
1074 		struct epoch_tracker et;
1075 #endif
1076 		int ret;
1077 
1078 #if defined(__FreeBSD__) && !defined(__Userspace__)
1079 	NET_EPOCH_ENTER(et);
1080 #endif
1081 		ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
1082 #if defined(__FreeBSD__) && !defined(__Userspace__)
1083 	NET_EPOCH_EXIT(et);
1084 #endif
1085 		inp->pkt = NULL;
1086 		inp->control = NULL;
1087 		return (ret);
1088 	} else {
1089 		return (0);
1090 	}
1091 }
1092 #endif
1093 
1094 #if defined(__Userspace__)
1095 int
1096 sctp6_connect(struct socket *so, struct sockaddr *addr)
1097 {
1098 	void *p = NULL;
1099 #elif defined(__FreeBSD__)
1100 static int
1101 sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
1102 {
1103 #elif defined(__APPLE__)
1104 static int
1105 sctp6_connect(struct socket *so, struct sockaddr *addr, struct proc *p)
1106 {
1107 #elif defined(_WIN32)
1108 static int
1109 sctp6_connect(struct socket *so, struct sockaddr *addr, PKTHREAD p)
1110 {
1111 #else
1112 static int
1113 sctp6_connect(struct socket *so, struct mbuf *nam, struct proc *p)
1114 {
1115 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1116 #endif
1117 #if defined(__FreeBSD__) && !defined(__Userspace__)
1118 	struct epoch_tracker et;
1119 #endif
1120 	uint32_t vrf_id;
1121 	int error = 0;
1122 	struct sctp_inpcb *inp;
1123 	struct sctp_tcb *stcb;
1124 #ifdef INET
1125 	struct sockaddr_in6 *sin6;
1126 	union sctp_sockstore store;
1127 #endif
1128 
1129 	inp = (struct sctp_inpcb *)so->so_pcb;
1130 	if (inp == NULL) {
1131 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
1132 		return (ECONNRESET);	/* I made the same as TCP since we are
1133 					 * not setup? */
1134 	}
1135 	if (addr == NULL) {
1136 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1137 		return (EINVAL);
1138 	}
1139 #if !(defined(_WIN32) && !defined(__Userspace__))
1140 	switch (addr->sa_family) {
1141 #ifdef INET
1142 	case AF_INET:
1143 #ifdef HAVE_SA_LEN
1144 		if (addr->sa_len != sizeof(struct sockaddr_in)) {
1145 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1146 			return (EINVAL);
1147 		}
1148 #endif
1149 		break;
1150 #endif
1151 #ifdef INET6
1152 	case AF_INET6:
1153 #ifdef HAVE_SA_LEN
1154 		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
1155 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1156 			return (EINVAL);
1157 		}
1158 #endif
1159 		break;
1160 #endif
1161 	default:
1162 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1163 		return (EINVAL);
1164 	}
1165 #endif
1166 
1167 	vrf_id = inp->def_vrf_id;
1168 	SCTP_ASOC_CREATE_LOCK(inp);
1169 	SCTP_INP_RLOCK(inp);
1170 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
1171 	    SCTP_PCB_FLAGS_UNBOUND) {
1172 		/* Bind a ephemeral port */
1173 		SCTP_INP_RUNLOCK(inp);
1174 		error = sctp6_bind(so, NULL, p);
1175 		if (error) {
1176 			SCTP_ASOC_CREATE_UNLOCK(inp);
1177 
1178 			return (error);
1179 		}
1180 		SCTP_INP_RLOCK(inp);
1181 	}
1182 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
1183 	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
1184 		/* We are already connected AND the TCP model */
1185 		SCTP_INP_RUNLOCK(inp);
1186 		SCTP_ASOC_CREATE_UNLOCK(inp);
1187 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EADDRINUSE);
1188 		return (EADDRINUSE);
1189 	}
1190 #ifdef INET
1191 	sin6 = (struct sockaddr_in6 *)addr;
1192 	if (SCTP_IPV6_V6ONLY(inp)) {
1193 		/*
1194 		 * if IPV6_V6ONLY flag, ignore connections destined to a v4
1195 		 * addr or v4-mapped addr
1196 		 */
1197 		if (addr->sa_family == AF_INET) {
1198 			SCTP_INP_RUNLOCK(inp);
1199 			SCTP_ASOC_CREATE_UNLOCK(inp);
1200 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1201 			return (EINVAL);
1202 		}
1203 		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1204 			SCTP_INP_RUNLOCK(inp);
1205 			SCTP_ASOC_CREATE_UNLOCK(inp);
1206 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1207 			return (EINVAL);
1208 		}
1209 	}
1210 	if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1211 		/* convert v4-mapped into v4 addr */
1212 		in6_sin6_2_sin(&store.sin, sin6);
1213 		addr = &store.sa;
1214 	}
1215 #endif				/* INET */
1216 	/* Now do we connect? */
1217 	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
1218 		stcb = LIST_FIRST(&inp->sctp_asoc_list);
1219 		if (stcb) {
1220 			SCTP_TCB_LOCK(stcb);
1221 		}
1222 		SCTP_INP_RUNLOCK(inp);
1223 	} else {
1224 		SCTP_INP_RUNLOCK(inp);
1225 		SCTP_INP_WLOCK(inp);
1226 		SCTP_INP_INCR_REF(inp);
1227 		SCTP_INP_WUNLOCK(inp);
1228 		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
1229 		if (stcb == NULL) {
1230 			SCTP_INP_WLOCK(inp);
1231 			SCTP_INP_DECR_REF(inp);
1232 			SCTP_INP_WUNLOCK(inp);
1233 		}
1234 	}
1235 
1236 	if (stcb != NULL) {
1237 		/* Already have or am bring up an association */
1238 		SCTP_ASOC_CREATE_UNLOCK(inp);
1239 		SCTP_TCB_UNLOCK(stcb);
1240 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EALREADY);
1241 		return (EALREADY);
1242 	}
1243 	/* We are GOOD to go */
1244 	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id,
1245 	                       inp->sctp_ep.pre_open_stream_count,
1246 	                       inp->sctp_ep.port, p,
1247 	                       SCTP_INITIALIZE_AUTH_PARAMS);
1248 	SCTP_ASOC_CREATE_UNLOCK(inp);
1249 	if (stcb == NULL) {
1250 		/* Gak! no memory */
1251 		return (error);
1252 	}
1253 	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
1254 		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
1255 		/* Set the connected flag so we can queue data */
1256 		soisconnecting(so);
1257 	}
1258 	SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
1259 	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
1260 #if defined(__FreeBSD__) && !defined(__Userspace__)
1261 	NET_EPOCH_ENTER(et);
1262 #endif
1263 	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
1264 	SCTP_TCB_UNLOCK(stcb);
1265 #if defined(__FreeBSD__) && !defined(__Userspace__)
1266 	NET_EPOCH_EXIT(et);
1267 #endif
1268 	return (error);
1269 }
1270 
1271 static int
1272 #if !defined(__Userspace__)
1273 sctp6_getaddr(struct socket *so, struct sockaddr **addr)
1274 {
1275 	struct sockaddr_in6 *sin6;
1276 #else
1277 sctp6_getaddr(struct socket *so, struct mbuf *nam)
1278 {
1279 	struct sockaddr_in6 *sin6 = mtod(nam, struct sockaddr_in6 *);
1280 #endif
1281 	struct sctp_inpcb *inp;
1282 	uint32_t vrf_id;
1283 	struct sctp_ifa *sctp_ifa;
1284 
1285 #if defined(SCTP_KAME) && defined(SCTP_EMBEDDED_V6_SCOPE)
1286 	int error;
1287 #endif
1288 
1289 	/*
1290 	 * Do the malloc first in case it blocks.
1291 	 */
1292 #if !defined(__Userspace__)
1293 	SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof(*sin6));
1294 	if (sin6 == NULL)
1295 		return (ENOMEM);
1296 #else
1297 	SCTP_BUF_LEN(nam) = sizeof(*sin6);
1298 	memset(sin6, 0, sizeof(*sin6));
1299 #endif
1300 	sin6->sin6_family = AF_INET6;
1301 #ifdef HAVE_SIN6_LEN
1302 	sin6->sin6_len = sizeof(*sin6);
1303 #endif
1304 
1305 	inp = (struct sctp_inpcb *)so->so_pcb;
1306 	if (inp == NULL) {
1307 #if !defined(__Userspace__)
1308 		SCTP_FREE_SONAME(sin6);
1309 #endif
1310 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
1311 		return (ECONNRESET);
1312 	}
1313 	SCTP_INP_RLOCK(inp);
1314 	sin6->sin6_port = inp->sctp_lport;
1315 	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1316 		/* For the bound all case you get back 0 */
1317 		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
1318 			struct sctp_tcb *stcb;
1319 			struct sockaddr_in6 *sin_a6;
1320 			struct sctp_nets *net;
1321 			int fnd;
1322 			stcb = LIST_FIRST(&inp->sctp_asoc_list);
1323 			if (stcb == NULL) {
1324 				SCTP_INP_RUNLOCK(inp);
1325 #if !defined(__Userspace__)
1326 				SCTP_FREE_SONAME(sin6);
1327 #endif
1328 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
1329 				return (ENOENT);
1330 			}
1331 			fnd = 0;
1332 			sin_a6 = NULL;
1333 			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1334 				sin_a6 = (struct sockaddr_in6 *)&net->ro._l_addr;
1335 				if (sin_a6 == NULL)
1336 					/* this will make coverity happy */
1337 					continue;
1338 
1339 				if (sin_a6->sin6_family == AF_INET6) {
1340 					fnd = 1;
1341 					break;
1342 				}
1343 			}
1344 			if ((!fnd) || (sin_a6 == NULL)) {
1345 				/* punt */
1346 				SCTP_INP_RUNLOCK(inp);
1347 #if !defined(__Userspace__)
1348 				SCTP_FREE_SONAME(sin6);
1349 #endif
1350 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
1351 				return (ENOENT);
1352 			}
1353 			vrf_id = inp->def_vrf_id;
1354 			sctp_ifa = sctp_source_address_selection(inp, stcb, (sctp_route_t *)&net->ro, net, 0, vrf_id);
1355 			if (sctp_ifa) {
1356 				sin6->sin6_addr = sctp_ifa->address.sin6.sin6_addr;
1357 			}
1358 		} else {
1359 			/* For the bound all case you get back 0 */
1360 			memset(&sin6->sin6_addr, 0, sizeof(sin6->sin6_addr));
1361 		}
1362 	} else {
1363 		/* Take the first IPv6 address in the list */
1364 		struct sctp_laddr *laddr;
1365 		int fnd = 0;
1366 
1367 		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1368 			if (laddr->ifa->address.sa.sa_family == AF_INET6) {
1369 				struct sockaddr_in6 *sin_a;
1370 
1371 				sin_a = &laddr->ifa->address.sin6;
1372 				sin6->sin6_addr = sin_a->sin6_addr;
1373 				fnd = 1;
1374 				break;
1375 			}
1376 		}
1377 		if (!fnd) {
1378 #if !defined(__Userspace__)
1379 			SCTP_FREE_SONAME(sin6);
1380 #endif
1381 			SCTP_INP_RUNLOCK(inp);
1382 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
1383 			return (ENOENT);
1384 		}
1385 	}
1386 	SCTP_INP_RUNLOCK(inp);
1387 	/* Scoping things for v6 */
1388 #ifdef SCTP_EMBEDDED_V6_SCOPE
1389 #ifdef SCTP_KAME
1390 	if ((error = sa6_recoverscope(sin6)) != 0) {
1391 		SCTP_FREE_SONAME(sin6);
1392 		return (error);
1393 	}
1394 #else
1395 	if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
1396 		/* skip ifp check below */
1397 		in6_recoverscope(sin6, &sin6->sin6_addr, NULL);
1398 	else
1399 		sin6->sin6_scope_id = 0;	/* XXX */
1400 #endif /* SCTP_KAME */
1401 #endif /* SCTP_EMBEDDED_V6_SCOPE */
1402 #if !defined(__Userspace__)
1403 	(*addr) = (struct sockaddr *)sin6;
1404 #endif
1405 	return (0);
1406 }
1407 
1408 static int
1409 #if !defined(__Userspace__)
1410 sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
1411 {
1412 	struct sockaddr_in6 *sin6;
1413 #else
1414 sctp6_peeraddr(struct socket *so, struct mbuf *nam)
1415 {
1416 	struct sockaddr_in6 *sin6 = mtod(nam, struct sockaddr_in6 *);
1417 #endif
1418 	int fnd;
1419 	struct sockaddr_in6 *sin_a6;
1420 	struct sctp_inpcb *inp;
1421 	struct sctp_tcb *stcb;
1422 	struct sctp_nets *net;
1423 #ifdef SCTP_KAME
1424 	int error;
1425 #endif
1426 
1427 	/* Do the malloc first in case it blocks. */
1428 #if !defined(__Userspace__)
1429 	SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
1430 	if (sin6 == NULL)
1431 		return (ENOMEM);
1432 #else
1433 	SCTP_BUF_LEN(nam) = sizeof(*sin6);
1434 	memset(sin6, 0, sizeof(*sin6));
1435 #endif
1436 	sin6->sin6_family = AF_INET6;
1437 #ifdef HAVE_SIN6_LEN
1438 	sin6->sin6_len = sizeof(*sin6);
1439 #endif
1440 
1441 	inp = (struct sctp_inpcb *)so->so_pcb;
1442 	if ((inp == NULL) ||
1443 	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
1444 		/* UDP type and listeners will drop out here */
1445 #if !defined(__Userspace__)
1446 		SCTP_FREE_SONAME(sin6);
1447 #endif
1448 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOTCONN);
1449 		return (ENOTCONN);
1450 	}
1451 	SCTP_INP_RLOCK(inp);
1452 	stcb = LIST_FIRST(&inp->sctp_asoc_list);
1453 	if (stcb) {
1454 		SCTP_TCB_LOCK(stcb);
1455 	}
1456 	SCTP_INP_RUNLOCK(inp);
1457 	if (stcb == NULL) {
1458 #if !defined(__Userspace__)
1459 		SCTP_FREE_SONAME(sin6);
1460 #endif
1461 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
1462 		return (ECONNRESET);
1463 	}
1464 	fnd = 0;
1465 	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1466 		sin_a6 = (struct sockaddr_in6 *)&net->ro._l_addr;
1467 		if (sin_a6->sin6_family == AF_INET6) {
1468 			fnd = 1;
1469 			sin6->sin6_port = stcb->rport;
1470 			sin6->sin6_addr = sin_a6->sin6_addr;
1471 			break;
1472 		}
1473 	}
1474 	SCTP_TCB_UNLOCK(stcb);
1475 	if (!fnd) {
1476 		/* No IPv4 address */
1477 #if !defined(__Userspace__)
1478 		SCTP_FREE_SONAME(sin6);
1479 #endif
1480 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
1481 		return (ENOENT);
1482 	}
1483 #ifdef SCTP_EMBEDDED_V6_SCOPE
1484 #ifdef SCTP_KAME
1485 	if ((error = sa6_recoverscope(sin6)) != 0) {
1486 #if !defined(__Userspace__)
1487 		SCTP_FREE_SONAME(sin6);
1488 #endif
1489 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, error);
1490 		return (error);
1491 	}
1492 #else
1493 	in6_recoverscope(sin6, &sin6->sin6_addr, NULL);
1494 #endif /* SCTP_KAME */
1495 #endif /* SCTP_EMBEDDED_V6_SCOPE */
1496 #if !defined(__Userspace__)
1497 	*addr = (struct sockaddr *)sin6;
1498 #endif
1499 	return (0);
1500 }
1501 
1502 #if !defined(__Userspace__)
1503 static int
1504 sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
1505 {
1506 #elif defined(__Userspace__)
1507 int
1508 sctp6_in6getaddr(struct socket *so, struct mbuf *nam)
1509 {
1510 #ifdef INET
1511 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1512 #endif
1513 #else
1514 static int
1515 sctp6_in6getaddr(struct socket *so, struct mbuf *nam)
1516 {
1517 #ifdef INET
1518 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1519 #endif
1520 #endif
1521 	struct inpcb *inp = sotoinpcb(so);
1522 	int error;
1523 
1524 	if (inp == NULL) {
1525 		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1526 		return (EINVAL);
1527 	}
1528 
1529 	/* allow v6 addresses precedence */
1530 	error = sctp6_getaddr(so, nam);
1531 #ifdef INET
1532 	if (error) {
1533 #if !defined(__Userspace__)
1534 		struct sockaddr_in6 *sin6;
1535 #else
1536 		struct sockaddr_in6 sin6;
1537 #endif
1538 
1539 		/* try v4 next if v6 failed */
1540 		error = sctp_ingetaddr(so, nam);
1541 		if (error) {
1542 			return (error);
1543 		}
1544 #if !defined(__Userspace__)
1545 		SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
1546 		if (sin6 == NULL) {
1547 			SCTP_FREE_SONAME(*nam);
1548 			return (ENOMEM);
1549 		}
1550 		in6_sin_2_v4mapsin6((struct sockaddr_in *)*nam, sin6);
1551 		SCTP_FREE_SONAME(*nam);
1552 		*nam = (struct sockaddr *)sin6;
1553 #else
1554 		in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6);
1555 		SCTP_BUF_LEN(nam) = sizeof(struct sockaddr_in6);
1556 		memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
1557 #endif
1558 	}
1559 #endif
1560 	return (error);
1561 }
1562 
1563 
1564 #if !defined(__Userspace__)
1565 static int
1566 sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
1567 {
1568 #elif defined(__Userspace__)
1569 int
1570 sctp6_getpeeraddr(struct socket *so, struct mbuf *nam)
1571 {
1572 #ifdef INET
1573 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1574 #endif
1575 #else
1576 static
1577 int
1578 sctp6_getpeeraddr(struct socket *so, struct mbuf *nam)
1579 {
1580 #ifdef INET
1581 	struct sockaddr *addr = mtod(nam, struct sockaddr *);
1582 #endif
1583 
1584 #endif
1585 	struct inpcb *inp = sotoinpcb(so);
1586 	int error;
1587 
1588 	if (inp == NULL) {
1589 		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1590 		return (EINVAL);
1591 	}
1592 
1593 	/* allow v6 addresses precedence */
1594 	error = sctp6_peeraddr(so, nam);
1595 #ifdef INET
1596 	if (error) {
1597 #if !defined(__Userspace__)
1598 		struct sockaddr_in6 *sin6;
1599 #else
1600 		struct sockaddr_in6 sin6;
1601 #endif
1602 
1603 		/* try v4 next if v6 failed */
1604 		error = sctp_peeraddr(so, nam);
1605 		if (error) {
1606 			return (error);
1607 		}
1608 #if !defined(__Userspace__)
1609 		SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
1610 		if (sin6 == NULL) {
1611 			SCTP_FREE_SONAME(*nam);
1612 			return (ENOMEM);
1613 		}
1614 		in6_sin_2_v4mapsin6((struct sockaddr_in *)*nam, sin6);
1615 		SCTP_FREE_SONAME(*nam);
1616 		*nam = (struct sockaddr *)sin6;
1617 #else
1618 		in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6);
1619 		SCTP_BUF_LEN(nam) = sizeof(struct sockaddr_in6);
1620 		memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
1621 #endif
1622 	}
1623 #endif
1624 	return (error);
1625 }
1626 
1627 #if !defined(__Userspace__)
1628 struct pr_usrreqs sctp6_usrreqs = {
1629 #if defined(__FreeBSD__)
1630 	.pru_abort = sctp6_abort,
1631 	.pru_accept = sctp_accept,
1632 	.pru_attach = sctp6_attach,
1633 	.pru_bind = sctp6_bind,
1634 	.pru_connect = sctp6_connect,
1635 	.pru_control = in6_control,
1636 	.pru_close = sctp6_close,
1637 	.pru_detach = sctp6_close,
1638 	.pru_sopoll = sopoll_generic,
1639 	.pru_flush = sctp_flush,
1640 	.pru_disconnect = sctp6_disconnect,
1641 	.pru_listen = sctp_listen,
1642 	.pru_peeraddr = sctp6_getpeeraddr,
1643 	.pru_send = sctp6_send,
1644 	.pru_shutdown = sctp_shutdown,
1645 	.pru_sockaddr = sctp6_in6getaddr,
1646 	.pru_sosend = sctp_sosend,
1647 	.pru_soreceive = sctp_soreceive
1648 #elif defined(__APPLE__) && !defined(__Userspace__)
1649 	.pru_abort = sctp6_abort,
1650 	.pru_accept = sctp_accept,
1651 	.pru_attach = sctp6_attach,
1652 	.pru_bind = sctp6_bind,
1653 	.pru_connect = sctp6_connect,
1654 	.pru_connect2 = pru_connect2_notsupp,
1655 	.pru_control = in6_control,
1656 	.pru_detach = sctp6_detach,
1657 	.pru_disconnect = sctp6_disconnect,
1658 	.pru_listen = sctp_listen,
1659 	.pru_peeraddr = sctp6_getpeeraddr,
1660 	.pru_rcvd = NULL,
1661 	.pru_rcvoob = pru_rcvoob_notsupp,
1662 	.pru_send = sctp6_send,
1663 	.pru_sense = pru_sense_null,
1664 	.pru_shutdown = sctp_shutdown,
1665 	.pru_sockaddr = sctp6_in6getaddr,
1666 	.pru_sosend = sctp_sosend,
1667 	.pru_soreceive = sctp_soreceive,
1668 	.pru_sopoll = sopoll
1669 #elif defined(_WIN32) && !defined(__Userspace__)
1670 	sctp6_abort,
1671 	sctp_accept,
1672 	sctp6_attach,
1673 	sctp6_bind,
1674 	sctp6_connect,
1675 	pru_connect2_notsupp,
1676 	NULL,
1677 	NULL,
1678 	sctp6_disconnect,
1679 	sctp_listen,
1680 	sctp6_getpeeraddr,
1681 	NULL,
1682 	pru_rcvoob_notsupp,
1683 	NULL,
1684 	pru_sense_null,
1685 	sctp_shutdown,
1686 	sctp_flush,
1687 	sctp6_in6getaddr,
1688 	sctp_sosend,
1689 	sctp_soreceive,
1690 	sopoll_generic,
1691 	NULL,
1692 	sctp6_close
1693 #endif
1694 };
1695 
1696 #elif !defined(__Userspace__)
1697 int
1698 sctp6_usrreq(so, req, m, nam, control, p)
1699 	struct socket *so;
1700 	int req;
1701 	struct mbuf *m, *nam, *control;
1702 	struct proc *p;
1703 {
1704 	int error;
1705 	int family;
1706 
1707 	family = so->so_proto->pr_domain->dom_family;
1708 
1709 	if (req == PRU_CONTROL) {
1710 		switch (family) {
1711 		case PF_INET:
1712 			error = in_control(so, (long)m, (caddr_t)nam,
1713 			    (struct ifnet *)control );
1714 			break;
1715 #ifdef INET6
1716 		case PF_INET6:
1717 			error = in6_control(so, (long)m, (caddr_t)nam,
1718 			    (struct ifnet *)control, p);
1719 			break;
1720 #endif
1721 		default:
1722 			SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EAFNOSUPPORT);
1723 			error = EAFNOSUPPORT;
1724 		}
1725 		return (error);
1726 	}
1727 	switch (req) {
1728 	case PRU_ATTACH:
1729 		error = sctp6_attach(so, family, p);
1730 		break;
1731 	case PRU_DETACH:
1732 		error = sctp6_detach(so);
1733 		break;
1734 	case PRU_BIND:
1735 		if (nam == NULL) {
1736 			SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1737 			return (EINVAL);
1738 		}
1739 		error = sctp6_bind(so, nam, p);
1740 		break;
1741 	case PRU_LISTEN:
1742 		error = sctp_listen(so, p);
1743 		break;
1744 	case PRU_CONNECT:
1745 		if (nam == NULL) {
1746 			SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1747 			return (EINVAL);
1748 		}
1749 		error = sctp6_connect(so, nam, p);
1750 		break;
1751 	case PRU_DISCONNECT:
1752 		error = sctp6_disconnect(so);
1753 		break;
1754 	case PRU_ACCEPT:
1755 		if (nam == NULL) {
1756 			SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1757 			return (EINVAL);
1758 		}
1759 		error = sctp_accept(so, nam);
1760 		break;
1761 	case PRU_SHUTDOWN:
1762 		error = sctp_shutdown(so);
1763 		break;
1764 
1765 	case PRU_RCVD:
1766 		/*
1767 		 * For OpenBSD and NetBSD, this is real ugly. The (mbuf *)
1768 		 * nam that is passed (by soreceive()) is the int flags cast
1769 		 * as a (mbuf *) yuck!
1770 		 */
1771 		error = sctp_usr_recvd(so, (int)((long)nam));
1772 		break;
1773 
1774 	case PRU_SEND:
1775 		/* Flags are ignored */
1776 		error = sctp6_send(so, 0, m, nam, control, p);
1777 		break;
1778 	case PRU_ABORT:
1779 		error = sctp6_abort(so);
1780 		break;
1781 
1782 	case PRU_SENSE:
1783 		error = 0;
1784 		break;
1785 	case PRU_RCVOOB:
1786 		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EAFNOSUPPORT);
1787 		error = EAFNOSUPPORT;
1788 		break;
1789 	case PRU_SENDOOB:
1790 		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EAFNOSUPPORT);
1791 		error = EAFNOSUPPORT;
1792 		break;
1793 	case PRU_PEERADDR:
1794 		error = sctp6_getpeeraddr(so, nam);
1795 		break;
1796 	case PRU_SOCKADDR:
1797 		error = sctp6_in6getaddr(so, nam);
1798 		break;
1799 	case PRU_SLOWTIMO:
1800 		error = 0;
1801 		break;
1802 	default:
1803 		error = 0;
1804 		break;
1805 	}
1806 	return (error);
1807 }
1808 #endif
1809 #endif
1810