xref: /freebsd/sys/netinet6/sctp6_usrreq.c (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
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 #include <sys/cdefs.h>
36 #include <netinet/sctp_os.h>
37 #ifdef INET6
38 #include <sys/proc.h>
39 #include <netinet/sctp_pcb.h>
40 #include <netinet/sctp_header.h>
41 #include <netinet/sctp_var.h>
42 #include <netinet6/sctp6_var.h>
43 #include <netinet/sctp_sysctl.h>
44 #include <netinet/sctp_output.h>
45 #include <netinet/sctp_uio.h>
46 #include <netinet/sctp_asconf.h>
47 #include <netinet/sctputil.h>
48 #include <netinet/sctp_indata.h>
49 #include <netinet/sctp_timer.h>
50 #include <netinet/sctp_auth.h>
51 #include <netinet/sctp_input.h>
52 #include <netinet/sctp_output.h>
53 #include <netinet/sctp_bsd_addr.h>
54 #include <netinet/sctp_crc32.h>
55 #include <netinet/icmp6.h>
56 #include <netinet/udp.h>
57 
58 int
59 sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port)
60 {
61 	struct mbuf *m;
62 	int iphlen;
63 	uint32_t vrf_id;
64 	uint8_t ecn_bits;
65 	struct sockaddr_in6 src, dst;
66 	struct ip6_hdr *ip6;
67 	struct sctphdr *sh;
68 	struct sctp_chunkhdr *ch;
69 	int length, offset;
70 	uint8_t compute_crc;
71 	uint32_t mflowid;
72 	uint8_t mflowtype;
73 	uint16_t fibnum;
74 
75 	iphlen = *offp;
76 	if (SCTP_GET_PKT_VRFID(*i_pak, vrf_id)) {
77 		SCTP_RELEASE_PKT(*i_pak);
78 		return (IPPROTO_DONE);
79 	}
80 	m = SCTP_HEADER_TO_CHAIN(*i_pak);
81 #ifdef SCTP_MBUF_LOGGING
82 	/* Log in any input mbufs */
83 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
84 		sctp_log_mbc(m, SCTP_MBUF_INPUT);
85 	}
86 #endif
87 #ifdef SCTP_PACKET_LOGGING
88 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) {
89 		sctp_packet_log(m);
90 	}
91 #endif
92 	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
93 	    "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%b.\n",
94 	    m->m_pkthdr.len,
95 	    if_name(m->m_pkthdr.rcvif),
96 	    (int)m->m_pkthdr.csum_flags, CSUM_BITS);
97 	mflowid = m->m_pkthdr.flowid;
98 	mflowtype = M_HASHTYPE_GET(m);
99 	fibnum = M_GETFIB(m);
100 	SCTP_STAT_INCR(sctps_recvpackets);
101 	SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
102 	/* Get IP, SCTP, and first chunk header together in the first mbuf. */
103 	offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
104 	if (m->m_len < offset) {
105 		m = m_pullup(m, offset);
106 		if (m == NULL) {
107 			SCTP_STAT_INCR(sctps_hdrops);
108 			return (IPPROTO_DONE);
109 		}
110 	}
111 	ip6 = mtod(m, struct ip6_hdr *);
112 	sh = (struct sctphdr *)(mtod(m, caddr_t)+iphlen);
113 	ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
114 	offset -= sizeof(struct sctp_chunkhdr);
115 	memset(&src, 0, sizeof(struct sockaddr_in6));
116 	src.sin6_family = AF_INET6;
117 	src.sin6_len = sizeof(struct sockaddr_in6);
118 	src.sin6_port = sh->src_port;
119 	src.sin6_addr = ip6->ip6_src;
120 	if (in6_setscope(&src.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
121 		goto out;
122 	}
123 	memset(&dst, 0, sizeof(struct sockaddr_in6));
124 	dst.sin6_family = AF_INET6;
125 	dst.sin6_len = sizeof(struct sockaddr_in6);
126 	dst.sin6_port = sh->dest_port;
127 	dst.sin6_addr = ip6->ip6_dst;
128 	if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
129 		goto out;
130 	}
131 	length = ntohs(ip6->ip6_plen) + iphlen;
132 	/* Validate mbuf chain length with IP payload length. */
133 	if (SCTP_HEADER_LEN(m) != length) {
134 		SCTPDBG(SCTP_DEBUG_INPUT1,
135 		    "sctp6_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m));
136 		SCTP_STAT_INCR(sctps_hdrops);
137 		goto out;
138 	}
139 	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
140 		goto out;
141 	}
142 	ecn_bits = IPV6_TRAFFIC_CLASS(ip6);
143 	if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
144 		SCTP_STAT_INCR(sctps_recvhwcrc);
145 		compute_crc = 0;
146 	} else {
147 		SCTP_STAT_INCR(sctps_recvswcrc);
148 		compute_crc = 1;
149 	}
150 	sctp_common_input_processing(&m, iphlen, offset, length,
151 	    (struct sockaddr *)&src,
152 	    (struct sockaddr *)&dst,
153 	    sh, ch,
154 	    compute_crc,
155 	    ecn_bits,
156 	    mflowtype, mflowid, fibnum,
157 	    vrf_id, port);
158 out:
159 	if (m) {
160 		sctp_m_freem(m);
161 	}
162 	return (IPPROTO_DONE);
163 }
164 
165 int
166 sctp6_input(struct mbuf **i_pak, int *offp, int proto SCTP_UNUSED)
167 {
168 	return (sctp6_input_with_port(i_pak, offp, 0));
169 }
170 
171 void
172 sctp6_notify(struct sctp_inpcb *inp,
173     struct sctp_tcb *stcb,
174     struct sctp_nets *net,
175     uint8_t icmp6_type,
176     uint8_t icmp6_code,
177     uint32_t next_mtu)
178 {
179 	int timer_stopped;
180 
181 	switch (icmp6_type) {
182 	case ICMP6_DST_UNREACH:
183 		if ((icmp6_code == ICMP6_DST_UNREACH_NOROUTE) ||
184 		    (icmp6_code == ICMP6_DST_UNREACH_ADMIN) ||
185 		    (icmp6_code == ICMP6_DST_UNREACH_BEYONDSCOPE) ||
186 		    (icmp6_code == ICMP6_DST_UNREACH_ADDR)) {
187 			/* Mark the net unreachable. */
188 			if (net->dest_state & SCTP_ADDR_REACHABLE) {
189 				/* Ok that destination is not reachable */
190 				net->dest_state &= ~SCTP_ADDR_REACHABLE;
191 				net->dest_state &= ~SCTP_ADDR_PF;
192 				sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
193 				    stcb, 0, (void *)net, SCTP_SO_NOT_LOCKED);
194 			}
195 		}
196 		SCTP_TCB_UNLOCK(stcb);
197 		break;
198 	case ICMP6_PARAM_PROB:
199 		/* Treat it like an ABORT. */
200 		if (icmp6_code == ICMP6_PARAMPROB_NEXTHEADER) {
201 			sctp_abort_notification(stcb, true, false, 0, NULL, SCTP_SO_NOT_LOCKED);
202 			(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
203 			    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
204 		} else {
205 			SCTP_TCB_UNLOCK(stcb);
206 		}
207 		break;
208 	case ICMP6_PACKET_TOO_BIG:
209 		if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
210 			SCTP_TCB_UNLOCK(stcb);
211 			break;
212 		}
213 		if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
214 			timer_stopped = 1;
215 			sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
216 			    SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1);
217 		} else {
218 			timer_stopped = 0;
219 		}
220 		/* Update the path MTU. */
221 		if (net->port) {
222 			next_mtu -= sizeof(struct udphdr);
223 		}
224 		if (net->mtu > next_mtu) {
225 			net->mtu = next_mtu;
226 			if (net->port) {
227 				sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu + sizeof(struct udphdr));
228 			} else {
229 				sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu);
230 			}
231 		}
232 		/* Update the association MTU */
233 		if (stcb->asoc.smallest_mtu > next_mtu) {
234 			sctp_pathmtu_adjustment(stcb, next_mtu, true);
235 		}
236 		/* Finally, start the PMTU timer if it was running before. */
237 		if (timer_stopped) {
238 			sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
239 		}
240 		SCTP_TCB_UNLOCK(stcb);
241 		break;
242 	default:
243 		SCTP_TCB_UNLOCK(stcb);
244 		break;
245 	}
246 }
247 
248 void
249 sctp6_ctlinput(struct ip6ctlparam *ip6cp)
250 {
251 	struct sctp_inpcb *inp;
252 	struct sctp_tcb *stcb;
253 	struct sctp_nets *net;
254 	struct sctphdr sh;
255 	struct sockaddr_in6 src, dst;
256 
257 	if (icmp6_errmap(ip6cp->ip6c_icmp6) == 0) {
258 		return;
259 	}
260 
261 	/*
262 	 * Check if we can safely examine the ports and the verification tag
263 	 * of the SCTP common header.
264 	 */
265 	if (ip6cp->ip6c_m->m_pkthdr.len <
266 	    (int32_t)(ip6cp->ip6c_off + offsetof(struct sctphdr, checksum))) {
267 		return;
268 	}
269 
270 	/* Copy out the port numbers and the verification tag. */
271 	memset(&sh, 0, sizeof(sh));
272 	m_copydata(ip6cp->ip6c_m,
273 	    ip6cp->ip6c_off,
274 	    sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t),
275 	    (caddr_t)&sh);
276 	memset(&src, 0, sizeof(struct sockaddr_in6));
277 	src.sin6_family = AF_INET6;
278 	src.sin6_len = sizeof(struct sockaddr_in6);
279 	src.sin6_port = sh.src_port;
280 	src.sin6_addr = ip6cp->ip6c_ip6->ip6_src;
281 	if (in6_setscope(&src.sin6_addr, ip6cp->ip6c_m->m_pkthdr.rcvif, NULL) != 0) {
282 		return;
283 	}
284 	memset(&dst, 0, sizeof(struct sockaddr_in6));
285 	dst.sin6_family = AF_INET6;
286 	dst.sin6_len = sizeof(struct sockaddr_in6);
287 	dst.sin6_port = sh.dest_port;
288 	dst.sin6_addr = ip6cp->ip6c_ip6->ip6_dst;
289 	if (in6_setscope(&dst.sin6_addr, ip6cp->ip6c_m->m_pkthdr.rcvif, NULL) != 0) {
290 		return;
291 	}
292 	inp = NULL;
293 	net = NULL;
294 	stcb = sctp_findassociation_addr_sa((struct sockaddr *)&dst,
295 	    (struct sockaddr *)&src,
296 	    &inp, &net, 1, SCTP_DEFAULT_VRFID);
297 	if ((stcb != NULL) &&
298 	    (net != NULL) &&
299 	    (inp != NULL)) {
300 		/* Check the verification tag */
301 		if (ntohl(sh.v_tag) != 0) {
302 			/*
303 			 * This must be the verification tag used for
304 			 * sending out packets. We don't consider packets
305 			 * reflecting the verification tag.
306 			 */
307 			if (ntohl(sh.v_tag) != stcb->asoc.peer_vtag) {
308 				SCTP_TCB_UNLOCK(stcb);
309 				return;
310 			}
311 		} else {
312 			if (ip6cp->ip6c_m->m_pkthdr.len >=
313 			    ip6cp->ip6c_off + sizeof(struct sctphdr) +
314 			    sizeof(struct sctp_chunkhdr) +
315 			    offsetof(struct sctp_init, a_rwnd)) {
316 				/*
317 				 * In this case we can check if we got an
318 				 * INIT chunk and if the initiate tag
319 				 * matches.
320 				 */
321 				uint32_t initiate_tag;
322 				uint8_t chunk_type;
323 
324 				m_copydata(ip6cp->ip6c_m,
325 				    ip6cp->ip6c_off +
326 				    sizeof(struct sctphdr),
327 				    sizeof(uint8_t),
328 				    (caddr_t)&chunk_type);
329 				m_copydata(ip6cp->ip6c_m,
330 				    ip6cp->ip6c_off +
331 				    sizeof(struct sctphdr) +
332 				    sizeof(struct sctp_chunkhdr),
333 				    sizeof(uint32_t),
334 				    (caddr_t)&initiate_tag);
335 				if ((chunk_type != SCTP_INITIATION) ||
336 				    (ntohl(initiate_tag) != stcb->asoc.my_vtag)) {
337 					SCTP_TCB_UNLOCK(stcb);
338 					return;
339 				}
340 			} else {
341 				SCTP_TCB_UNLOCK(stcb);
342 				return;
343 			}
344 		}
345 		sctp6_notify(inp, stcb, net,
346 		    ip6cp->ip6c_icmp6->icmp6_type,
347 		    ip6cp->ip6c_icmp6->icmp6_code,
348 		    ntohl(ip6cp->ip6c_icmp6->icmp6_mtu));
349 	} else {
350 		if ((stcb == NULL) && (inp != NULL)) {
351 			/* reduce inp's ref-count */
352 			SCTP_INP_WLOCK(inp);
353 			SCTP_INP_DECR_REF(inp);
354 			SCTP_INP_WUNLOCK(inp);
355 		}
356 		if (stcb) {
357 			SCTP_TCB_UNLOCK(stcb);
358 		}
359 	}
360 }
361 
362 /*
363  * this routine can probably be collasped into the one in sctp_userreq.c
364  * since they do the same thing and now we lookup with a sockaddr
365  */
366 static int
367 sctp6_getcred(SYSCTL_HANDLER_ARGS)
368 {
369 	struct xucred xuc;
370 	struct sockaddr_in6 addrs[2];
371 	struct sctp_inpcb *inp;
372 	struct sctp_nets *net;
373 	struct sctp_tcb *stcb;
374 	int error;
375 	uint32_t vrf_id;
376 
377 	vrf_id = SCTP_DEFAULT_VRFID;
378 
379 	error = priv_check(req->td, PRIV_NETINET_GETCRED);
380 	if (error)
381 		return (error);
382 
383 	if (req->newlen != sizeof(addrs)) {
384 		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
385 		return (EINVAL);
386 	}
387 	if (req->oldlen != sizeof(struct ucred)) {
388 		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
389 		return (EINVAL);
390 	}
391 	error = SYSCTL_IN(req, addrs, sizeof(addrs));
392 	if (error)
393 		return (error);
394 
395 	stcb = sctp_findassociation_addr_sa(sin6tosa(&addrs[1]),
396 	    sin6tosa(&addrs[0]),
397 	    &inp, &net, 1, vrf_id);
398 	if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
399 		if ((inp != NULL) && (stcb == NULL)) {
400 			/* reduce ref-count */
401 			SCTP_INP_WLOCK(inp);
402 			SCTP_INP_DECR_REF(inp);
403 			goto cred_can_cont;
404 		}
405 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
406 		error = ENOENT;
407 		goto out;
408 	}
409 	SCTP_TCB_UNLOCK(stcb);
410 	/*
411 	 * We use the write lock here, only since in the error leg we need
412 	 * it. If we used RLOCK, then we would have to
413 	 * wlock/decr/unlock/rlock. Which in theory could create a hole.
414 	 * Better to use higher wlock.
415 	 */
416 	SCTP_INP_WLOCK(inp);
417 cred_can_cont:
418 	error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
419 	if (error) {
420 		SCTP_INP_WUNLOCK(inp);
421 		goto out;
422 	}
423 	cru2x(inp->sctp_socket->so_cred, &xuc);
424 	SCTP_INP_WUNLOCK(inp);
425 	error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
426 out:
427 	return (error);
428 }
429 
430 SYSCTL_PROC(_net_inet6_sctp6, OID_AUTO, getcred,
431     CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
432     0, 0, sctp6_getcred, "S,ucred",
433     "Get the ucred of a SCTP6 connection");
434 
435 static int
436 sctp6_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
437 {
438 	int error;
439 	struct sctp_inpcb *inp;
440 	uint32_t vrf_id = SCTP_DEFAULT_VRFID;
441 
442 	inp = (struct sctp_inpcb *)so->so_pcb;
443 	if (inp != NULL) {
444 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
445 		return (EINVAL);
446 	}
447 
448 	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
449 		error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
450 		if (error)
451 			return (error);
452 	}
453 	error = sctp_inpcb_alloc(so, vrf_id);
454 	if (error)
455 		return (error);
456 	inp = (struct sctp_inpcb *)so->so_pcb;
457 	SCTP_INP_WLOCK(inp);
458 	inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_V6;	/* I'm v6! */
459 
460 	inp->ip_inp.inp.inp_vflag |= INP_IPV6;
461 	inp->ip_inp.inp.in6p_hops = -1;	/* use kernel default */
462 	inp->ip_inp.inp.in6p_cksum = -1;	/* just to be sure */
463 #ifdef INET
464 	/*
465 	 * XXX: ugly!! IPv4 TTL initialization is necessary for an IPv6
466 	 * socket as well, because the socket may be bound to an IPv6
467 	 * wildcard address, which may match an IPv4-mapped IPv6 address.
468 	 */
469 	inp->ip_inp.inp.inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
470 #endif
471 	SCTP_INP_WUNLOCK(inp);
472 	return (0);
473 }
474 
475 static int
476 sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
477 {
478 	struct sctp_inpcb *inp;
479 	int error;
480 	u_char vflagsav;
481 
482 	inp = (struct sctp_inpcb *)so->so_pcb;
483 	if (inp == NULL) {
484 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
485 		return (EINVAL);
486 	}
487 
488 	if (addr) {
489 		switch (addr->sa_family) {
490 #ifdef INET
491 		case AF_INET:
492 			if (addr->sa_len != sizeof(struct sockaddr_in)) {
493 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
494 				return (EINVAL);
495 			}
496 			break;
497 #endif
498 #ifdef INET6
499 		case AF_INET6:
500 			if (addr->sa_len != sizeof(struct sockaddr_in6)) {
501 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
502 				return (EINVAL);
503 			}
504 			break;
505 #endif
506 		default:
507 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
508 			return (EINVAL);
509 		}
510 	}
511 	vflagsav = inp->ip_inp.inp.inp_vflag;
512 	inp->ip_inp.inp.inp_vflag &= ~INP_IPV4;
513 	inp->ip_inp.inp.inp_vflag |= INP_IPV6;
514 	if ((addr != NULL) && (SCTP_IPV6_V6ONLY(inp) == 0)) {
515 		switch (addr->sa_family) {
516 #ifdef INET
517 		case AF_INET:
518 			/* binding v4 addr to v6 socket, so reset flags */
519 			inp->ip_inp.inp.inp_vflag |= INP_IPV4;
520 			inp->ip_inp.inp.inp_vflag &= ~INP_IPV6;
521 			break;
522 #endif
523 #ifdef INET6
524 		case AF_INET6:
525 			{
526 				struct sockaddr_in6 *sin6_p;
527 
528 				sin6_p = (struct sockaddr_in6 *)addr;
529 
530 				if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) {
531 					inp->ip_inp.inp.inp_vflag |= INP_IPV4;
532 				}
533 #ifdef INET
534 				if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
535 					struct sockaddr_in sin;
536 
537 					in6_sin6_2_sin(&sin, sin6_p);
538 					inp->ip_inp.inp.inp_vflag |= INP_IPV4;
539 					inp->ip_inp.inp.inp_vflag &= ~INP_IPV6;
540 					error = sctp_inpcb_bind(so, (struct sockaddr *)&sin, NULL, p);
541 					goto out;
542 				}
543 #endif
544 				break;
545 			}
546 #endif
547 		default:
548 			break;
549 		}
550 	} else if (addr != NULL) {
551 		struct sockaddr_in6 *sin6_p;
552 
553 		/* IPV6_V6ONLY socket */
554 #ifdef INET
555 		if (addr->sa_family == AF_INET) {
556 			/* can't bind v4 addr to v6 only socket! */
557 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
558 			error = EINVAL;
559 			goto out;
560 		}
561 #endif
562 		sin6_p = (struct sockaddr_in6 *)addr;
563 
564 		if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
565 			/* can't bind v4-mapped addrs either! */
566 			/* NOTE: we don't support SIIT */
567 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
568 			error = EINVAL;
569 			goto out;
570 		}
571 	}
572 	error = sctp_inpcb_bind(so, addr, NULL, p);
573 out:
574 	if (error != 0)
575 		inp->ip_inp.inp.inp_vflag = vflagsav;
576 	return (error);
577 }
578 
579 static void
580 sctp6_close(struct socket *so)
581 {
582 	sctp_close(so);
583 }
584 
585 /* This could be made common with sctp_detach() since they are identical */
586 
587 int
588 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
589     struct mbuf *control, struct thread *p);
590 
591 static int
592 sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
593     struct mbuf *control, struct thread *p)
594 {
595 	struct sctp_inpcb *inp;
596 
597 #ifdef INET
598 	struct sockaddr_in6 *sin6;
599 #endif				/* INET */
600 	/* No SPL needed since sctp_output does this */
601 
602 	inp = (struct sctp_inpcb *)so->so_pcb;
603 	if (inp == NULL) {
604 		if (control) {
605 			SCTP_RELEASE_PKT(control);
606 			control = NULL;
607 		}
608 		SCTP_RELEASE_PKT(m);
609 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
610 		return (EINVAL);
611 	}
612 	/*
613 	 * For the TCP model we may get a NULL addr, if we are a connected
614 	 * socket thats ok.
615 	 */
616 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) &&
617 	    (addr == NULL)) {
618 		goto connected_type;
619 	}
620 	if (addr == NULL) {
621 		SCTP_RELEASE_PKT(m);
622 		if (control) {
623 			SCTP_RELEASE_PKT(control);
624 			control = NULL;
625 		}
626 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EDESTADDRREQ);
627 		return (EDESTADDRREQ);
628 	}
629 	switch (addr->sa_family) {
630 #ifdef INET
631 	case AF_INET:
632 		if (addr->sa_len != sizeof(struct sockaddr_in)) {
633 			if (control) {
634 				SCTP_RELEASE_PKT(control);
635 				control = NULL;
636 			}
637 			SCTP_RELEASE_PKT(m);
638 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
639 			return (EINVAL);
640 		}
641 		break;
642 #endif
643 #ifdef INET6
644 	case AF_INET6:
645 		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
646 			if (control) {
647 				SCTP_RELEASE_PKT(control);
648 				control = NULL;
649 			}
650 			SCTP_RELEASE_PKT(m);
651 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
652 			return (EINVAL);
653 		}
654 		break;
655 #endif
656 	default:
657 		if (control) {
658 			SCTP_RELEASE_PKT(control);
659 			control = NULL;
660 		}
661 		SCTP_RELEASE_PKT(m);
662 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
663 		return (EINVAL);
664 	}
665 #ifdef INET
666 	sin6 = (struct sockaddr_in6 *)addr;
667 	if (SCTP_IPV6_V6ONLY(inp)) {
668 		/*
669 		 * if IPV6_V6ONLY flag, we discard datagrams destined to a
670 		 * v4 addr or v4-mapped addr
671 		 */
672 		if (addr->sa_family == AF_INET) {
673 			if (control) {
674 				SCTP_RELEASE_PKT(control);
675 				control = NULL;
676 			}
677 			SCTP_RELEASE_PKT(m);
678 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
679 			return (EINVAL);
680 		}
681 		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
682 			if (control) {
683 				SCTP_RELEASE_PKT(control);
684 				control = NULL;
685 			}
686 			SCTP_RELEASE_PKT(m);
687 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
688 			return (EINVAL);
689 		}
690 	}
691 	if ((addr->sa_family == AF_INET6) &&
692 	    IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
693 		struct sockaddr_in sin;
694 
695 		/* convert v4-mapped into v4 addr and send */
696 		in6_sin6_2_sin(&sin, sin6);
697 		return (sctp_sendm(so, flags, m, (struct sockaddr *)&sin, control, p));
698 	}
699 #endif				/* INET */
700 connected_type:
701 	/* now what about control */
702 	if (control) {
703 		if (inp->control) {
704 			SCTP_PRINTF("huh? control set?\n");
705 			SCTP_RELEASE_PKT(inp->control);
706 			inp->control = NULL;
707 		}
708 		inp->control = control;
709 	}
710 	/* Place the data */
711 	if (inp->pkt) {
712 		SCTP_BUF_NEXT(inp->pkt_last) = m;
713 		inp->pkt_last = m;
714 	} else {
715 		inp->pkt_last = inp->pkt = m;
716 	}
717 	if (
718 	/* FreeBSD and MacOSX uses a flag passed */
719 	    ((flags & PRUS_MORETOCOME) == 0)
720 	    ) {
721 		/*
722 		 * note with the current version this code will only be used
723 		 * by OpenBSD, NetBSD and FreeBSD have methods for
724 		 * re-defining sosend() to use sctp_sosend().  One can
725 		 * optionaly switch back to this code (by changing back the
726 		 * defininitions but this is not advisable.
727 		 */
728 		struct epoch_tracker et;
729 		int ret;
730 
731 		NET_EPOCH_ENTER(et);
732 		ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
733 		NET_EPOCH_EXIT(et);
734 		inp->pkt = NULL;
735 		inp->control = NULL;
736 		return (ret);
737 	} else {
738 		return (0);
739 	}
740 }
741 
742 static int
743 sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
744 {
745 	struct epoch_tracker et;
746 	uint32_t vrf_id;
747 	int error = 0;
748 	struct sctp_inpcb *inp;
749 	struct sctp_tcb *stcb;
750 #ifdef INET
751 	struct sockaddr_in6 *sin6;
752 	union sctp_sockstore store;
753 #endif
754 
755 	inp = (struct sctp_inpcb *)so->so_pcb;
756 	if (inp == NULL) {
757 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
758 		return (ECONNRESET);	/* I made the same as TCP since we are
759 					 * not setup? */
760 	}
761 	if (addr == NULL) {
762 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
763 		return (EINVAL);
764 	}
765 	switch (addr->sa_family) {
766 #ifdef INET
767 	case AF_INET:
768 		if (addr->sa_len != sizeof(struct sockaddr_in)) {
769 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
770 			return (EINVAL);
771 		}
772 		break;
773 #endif
774 #ifdef INET6
775 	case AF_INET6:
776 		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
777 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
778 			return (EINVAL);
779 		}
780 		break;
781 #endif
782 	default:
783 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
784 		return (EINVAL);
785 	}
786 
787 	vrf_id = inp->def_vrf_id;
788 	SCTP_ASOC_CREATE_LOCK(inp);
789 	SCTP_INP_RLOCK(inp);
790 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
791 	    SCTP_PCB_FLAGS_UNBOUND) {
792 		/* Bind a ephemeral port */
793 		SCTP_INP_RUNLOCK(inp);
794 		error = sctp6_bind(so, NULL, p);
795 		if (error) {
796 			SCTP_ASOC_CREATE_UNLOCK(inp);
797 
798 			return (error);
799 		}
800 		SCTP_INP_RLOCK(inp);
801 	}
802 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
803 	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
804 		/* We are already connected AND the TCP model */
805 		SCTP_INP_RUNLOCK(inp);
806 		SCTP_ASOC_CREATE_UNLOCK(inp);
807 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EADDRINUSE);
808 		return (EADDRINUSE);
809 	}
810 #ifdef INET
811 	sin6 = (struct sockaddr_in6 *)addr;
812 	if (SCTP_IPV6_V6ONLY(inp)) {
813 		/*
814 		 * if IPV6_V6ONLY flag, ignore connections destined to a v4
815 		 * addr or v4-mapped addr
816 		 */
817 		if (addr->sa_family == AF_INET) {
818 			SCTP_INP_RUNLOCK(inp);
819 			SCTP_ASOC_CREATE_UNLOCK(inp);
820 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
821 			return (EINVAL);
822 		}
823 		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
824 			SCTP_INP_RUNLOCK(inp);
825 			SCTP_ASOC_CREATE_UNLOCK(inp);
826 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
827 			return (EINVAL);
828 		}
829 	}
830 	if ((addr->sa_family == AF_INET6) &&
831 	    IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
832 		/* convert v4-mapped into v4 addr */
833 		in6_sin6_2_sin(&store.sin, sin6);
834 		addr = &store.sa;
835 	}
836 #endif				/* INET */
837 	/* Now do we connect? */
838 	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
839 		stcb = LIST_FIRST(&inp->sctp_asoc_list);
840 		if (stcb) {
841 			SCTP_TCB_LOCK(stcb);
842 		}
843 		SCTP_INP_RUNLOCK(inp);
844 	} else {
845 		SCTP_INP_RUNLOCK(inp);
846 		SCTP_INP_WLOCK(inp);
847 		SCTP_INP_INCR_REF(inp);
848 		SCTP_INP_WUNLOCK(inp);
849 		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
850 		if (stcb == NULL) {
851 			SCTP_INP_WLOCK(inp);
852 			SCTP_INP_DECR_REF(inp);
853 			SCTP_INP_WUNLOCK(inp);
854 		}
855 	}
856 
857 	if (stcb != NULL) {
858 		/* Already have or am bring up an association */
859 		SCTP_ASOC_CREATE_UNLOCK(inp);
860 		SCTP_TCB_UNLOCK(stcb);
861 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EALREADY);
862 		return (EALREADY);
863 	}
864 	/* We are GOOD to go */
865 	stcb = sctp_aloc_assoc_connected(inp, addr, &error, 0, 0, vrf_id,
866 	    inp->sctp_ep.pre_open_stream_count,
867 	    inp->sctp_ep.port, p,
868 	    SCTP_INITIALIZE_AUTH_PARAMS);
869 	SCTP_ASOC_CREATE_UNLOCK(inp);
870 	if (stcb == NULL) {
871 		/* Gak! no memory */
872 		return (error);
873 	}
874 	SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
875 	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
876 	NET_EPOCH_ENTER(et);
877 	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
878 	SCTP_TCB_UNLOCK(stcb);
879 	NET_EPOCH_EXIT(et);
880 	return (error);
881 }
882 
883 static int
884 sctp6_getaddr(struct socket *so, struct sockaddr **addr)
885 {
886 	struct sockaddr_in6 *sin6;
887 	struct sctp_inpcb *inp;
888 	uint32_t vrf_id;
889 	struct sctp_ifa *sctp_ifa;
890 
891 	int error;
892 
893 	/*
894 	 * Do the malloc first in case it blocks.
895 	 */
896 	SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof(*sin6));
897 	if (sin6 == NULL)
898 		return (ENOMEM);
899 	sin6->sin6_family = AF_INET6;
900 	sin6->sin6_len = sizeof(*sin6);
901 
902 	inp = (struct sctp_inpcb *)so->so_pcb;
903 	if (inp == NULL) {
904 		SCTP_FREE_SONAME(sin6);
905 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
906 		return (ECONNRESET);
907 	}
908 	SCTP_INP_RLOCK(inp);
909 	sin6->sin6_port = inp->sctp_lport;
910 	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
911 		/* For the bound all case you get back 0 */
912 		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
913 			struct sctp_tcb *stcb;
914 			struct sockaddr_in6 *sin_a6;
915 			struct sctp_nets *net;
916 			int fnd;
917 
918 			stcb = LIST_FIRST(&inp->sctp_asoc_list);
919 			if (stcb == NULL) {
920 				SCTP_INP_RUNLOCK(inp);
921 				SCTP_FREE_SONAME(sin6);
922 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
923 				return (ENOENT);
924 			}
925 			fnd = 0;
926 			sin_a6 = NULL;
927 			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
928 				sin_a6 = (struct sockaddr_in6 *)&net->ro._l_addr;
929 				if (sin_a6 == NULL)
930 					/* this will make coverity happy */
931 					continue;
932 
933 				if (sin_a6->sin6_family == AF_INET6) {
934 					fnd = 1;
935 					break;
936 				}
937 			}
938 			if ((!fnd) || (sin_a6 == NULL)) {
939 				/* punt */
940 				SCTP_INP_RUNLOCK(inp);
941 				SCTP_FREE_SONAME(sin6);
942 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
943 				return (ENOENT);
944 			}
945 			vrf_id = inp->def_vrf_id;
946 			sctp_ifa = sctp_source_address_selection(inp, stcb, (sctp_route_t *)&net->ro, net, 0, vrf_id);
947 			if (sctp_ifa) {
948 				sin6->sin6_addr = sctp_ifa->address.sin6.sin6_addr;
949 			}
950 		} else {
951 			/* For the bound all case you get back 0 */
952 			memset(&sin6->sin6_addr, 0, sizeof(sin6->sin6_addr));
953 		}
954 	} else {
955 		/* Take the first IPv6 address in the list */
956 		struct sctp_laddr *laddr;
957 		int fnd = 0;
958 
959 		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
960 			if (laddr->ifa->address.sa.sa_family == AF_INET6) {
961 				struct sockaddr_in6 *sin_a;
962 
963 				sin_a = &laddr->ifa->address.sin6;
964 				sin6->sin6_addr = sin_a->sin6_addr;
965 				fnd = 1;
966 				break;
967 			}
968 		}
969 		if (!fnd) {
970 			SCTP_FREE_SONAME(sin6);
971 			SCTP_INP_RUNLOCK(inp);
972 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
973 			return (ENOENT);
974 		}
975 	}
976 	SCTP_INP_RUNLOCK(inp);
977 	/* Scoping things for v6 */
978 	if ((error = sa6_recoverscope(sin6)) != 0) {
979 		SCTP_FREE_SONAME(sin6);
980 		return (error);
981 	}
982 	(*addr) = (struct sockaddr *)sin6;
983 	return (0);
984 }
985 
986 static int
987 sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
988 {
989 	struct sockaddr_in6 *sin6;
990 	int fnd;
991 	struct sockaddr_in6 *sin_a6;
992 	struct sctp_inpcb *inp;
993 	struct sctp_tcb *stcb;
994 	struct sctp_nets *net;
995 	int error;
996 
997 	/* Do the malloc first in case it blocks. */
998 	SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
999 	if (sin6 == NULL)
1000 		return (ENOMEM);
1001 	sin6->sin6_family = AF_INET6;
1002 	sin6->sin6_len = sizeof(*sin6);
1003 
1004 	inp = (struct sctp_inpcb *)so->so_pcb;
1005 	if ((inp == NULL) ||
1006 	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
1007 		/* UDP type and listeners will drop out here */
1008 		SCTP_FREE_SONAME(sin6);
1009 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOTCONN);
1010 		return (ENOTCONN);
1011 	}
1012 	SCTP_INP_RLOCK(inp);
1013 	stcb = LIST_FIRST(&inp->sctp_asoc_list);
1014 	if (stcb) {
1015 		SCTP_TCB_LOCK(stcb);
1016 	}
1017 	SCTP_INP_RUNLOCK(inp);
1018 	if (stcb == NULL) {
1019 		SCTP_FREE_SONAME(sin6);
1020 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
1021 		return (ECONNRESET);
1022 	}
1023 	fnd = 0;
1024 	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1025 		sin_a6 = (struct sockaddr_in6 *)&net->ro._l_addr;
1026 		if (sin_a6->sin6_family == AF_INET6) {
1027 			fnd = 1;
1028 			sin6->sin6_port = stcb->rport;
1029 			sin6->sin6_addr = sin_a6->sin6_addr;
1030 			break;
1031 		}
1032 	}
1033 	SCTP_TCB_UNLOCK(stcb);
1034 	if (!fnd) {
1035 		/* No IPv4 address */
1036 		SCTP_FREE_SONAME(sin6);
1037 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
1038 		return (ENOENT);
1039 	}
1040 	if ((error = sa6_recoverscope(sin6)) != 0) {
1041 		SCTP_FREE_SONAME(sin6);
1042 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, error);
1043 		return (error);
1044 	}
1045 	*addr = (struct sockaddr *)sin6;
1046 	return (0);
1047 }
1048 
1049 static int
1050 sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
1051 {
1052 	struct inpcb *inp = sotoinpcb(so);
1053 	int error;
1054 
1055 	if (inp == NULL) {
1056 		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1057 		return (EINVAL);
1058 	}
1059 
1060 	/* allow v6 addresses precedence */
1061 	error = sctp6_getaddr(so, nam);
1062 #ifdef INET
1063 	if (error) {
1064 		struct sockaddr_in6 *sin6;
1065 
1066 		/* try v4 next if v6 failed */
1067 		error = sctp_ingetaddr(so, nam);
1068 		if (error) {
1069 			return (error);
1070 		}
1071 		SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
1072 		if (sin6 == NULL) {
1073 			SCTP_FREE_SONAME(*nam);
1074 			return (ENOMEM);
1075 		}
1076 		in6_sin_2_v4mapsin6((struct sockaddr_in *)*nam, sin6);
1077 		SCTP_FREE_SONAME(*nam);
1078 		*nam = (struct sockaddr *)sin6;
1079 	}
1080 #endif
1081 	return (error);
1082 }
1083 
1084 static int
1085 sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
1086 {
1087 	struct inpcb *inp = sotoinpcb(so);
1088 	int error;
1089 
1090 	if (inp == NULL) {
1091 		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1092 		return (EINVAL);
1093 	}
1094 
1095 	/* allow v6 addresses precedence */
1096 	error = sctp6_peeraddr(so, nam);
1097 #ifdef INET
1098 	if (error) {
1099 		struct sockaddr_in6 *sin6;
1100 
1101 		/* try v4 next if v6 failed */
1102 		error = sctp_peeraddr(so, nam);
1103 		if (error) {
1104 			return (error);
1105 		}
1106 		SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
1107 		if (sin6 == NULL) {
1108 			SCTP_FREE_SONAME(*nam);
1109 			return (ENOMEM);
1110 		}
1111 		in6_sin_2_v4mapsin6((struct sockaddr_in *)*nam, sin6);
1112 		SCTP_FREE_SONAME(*nam);
1113 		*nam = (struct sockaddr *)sin6;
1114 	}
1115 #endif
1116 	return (error);
1117 }
1118 
1119 #define	SCTP6_PROTOSW							\
1120 	.pr_protocol =	IPPROTO_SCTP,					\
1121 	.pr_ctloutput =	sctp_ctloutput,					\
1122 	.pr_abort =	sctp_abort,					\
1123 	.pr_accept =	sctp_accept,					\
1124 	.pr_attach =	sctp6_attach,					\
1125 	.pr_bind =	sctp6_bind,					\
1126 	.pr_connect =	sctp6_connect,					\
1127 	.pr_control =	in6_control,					\
1128 	.pr_close =	sctp6_close,					\
1129 	.pr_detach =	sctp6_close,					\
1130 	.pr_sopoll =	sopoll_generic,					\
1131 	.pr_flush =	sctp_flush,					\
1132 	.pr_disconnect = sctp_disconnect,				\
1133 	.pr_listen =	sctp_listen,					\
1134 	.pr_peeraddr =	sctp6_getpeeraddr,				\
1135 	.pr_send =	sctp6_send,					\
1136 	.pr_shutdown =	sctp_shutdown,					\
1137 	.pr_sockaddr =	sctp6_in6getaddr,				\
1138 	.pr_sosend =	sctp_sosend,					\
1139 	.pr_soreceive =	sctp_soreceive
1140 
1141 struct protosw sctp6_seqpacket_protosw = {
1142 	.pr_type = SOCK_SEQPACKET,
1143 	.pr_flags = PR_WANTRCVD,
1144 	SCTP6_PROTOSW
1145 };
1146 
1147 struct protosw sctp6_stream_protosw = {
1148 	.pr_type = SOCK_STREAM,
1149 	.pr_flags = PR_CONNREQUIRED | PR_WANTRCVD,
1150 	SCTP6_PROTOSW
1151 };
1152 #endif
1153