xref: /freebsd/sys/netinet6/sctp6_usrreq.c (revision ff0ba87247820afbdfdc1b307c803f7923d0e4d3)
1 /*-
2  * Copyright (c) 2001-2007, 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 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
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 #ifdef INET6
43 #include <netinet6/sctp6_var.h>
44 #endif
45 #include <netinet/sctp_sysctl.h>
46 #include <netinet/sctp_output.h>
47 #include <netinet/sctp_uio.h>
48 #include <netinet/sctp_asconf.h>
49 #include <netinet/sctputil.h>
50 #include <netinet/sctp_indata.h>
51 #include <netinet/sctp_timer.h>
52 #include <netinet/sctp_auth.h>
53 #include <netinet/sctp_input.h>
54 #include <netinet/sctp_output.h>
55 #include <netinet/sctp_bsd_addr.h>
56 #include <netinet/sctp_crc32.h>
57 #include <netinet/udp.h>
58 
59 #ifdef IPSEC
60 #include <netipsec/ipsec.h>
61 #ifdef INET6
62 #include <netipsec/ipsec6.h>
63 #endif				/* INET6 */
64 #endif				/* IPSEC */
65 
66 extern struct protosw inetsw[];
67 
68 int
69 sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port)
70 {
71 	struct mbuf *m;
72 	int iphlen;
73 	uint32_t vrf_id;
74 	uint8_t ecn_bits;
75 	struct sockaddr_in6 src, dst;
76 	struct ip6_hdr *ip6;
77 	struct sctphdr *sh;
78 	struct sctp_chunkhdr *ch;
79 	int length, offset;
80 
81 #if !defined(SCTP_WITH_NO_CSUM)
82 	uint8_t compute_crc;
83 
84 #endif
85 	uint32_t mflowid;
86 	uint8_t use_mflowid;
87 
88 	iphlen = *offp;
89 	if (SCTP_GET_PKT_VRFID(*i_pak, vrf_id)) {
90 		SCTP_RELEASE_PKT(*i_pak);
91 		return (IPPROTO_DONE);
92 	}
93 	m = SCTP_HEADER_TO_CHAIN(*i_pak);
94 #ifdef SCTP_MBUF_LOGGING
95 	/* Log in any input mbufs */
96 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
97 		struct mbuf *mat;
98 
99 		for (mat = m; mat; mat = SCTP_BUF_NEXT(mat)) {
100 			if (SCTP_BUF_IS_EXTENDED(mat)) {
101 				sctp_log_mb(mat, SCTP_MBUF_INPUT);
102 			}
103 		}
104 	}
105 #endif
106 #ifdef SCTP_PACKET_LOGGING
107 	if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING) {
108 		sctp_packet_log(m);
109 	}
110 #endif
111 	SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
112 	    "sctp6_input(): Packet of length %d received on %s with csum_flags 0x%b.\n",
113 	    m->m_pkthdr.len,
114 	    if_name(m->m_pkthdr.rcvif),
115 	    (int)m->m_pkthdr.csum_flags, CSUM_BITS);
116 	if (m->m_flags & M_FLOWID) {
117 		mflowid = m->m_pkthdr.flowid;
118 		use_mflowid = 1;
119 	} else {
120 		mflowid = 0;
121 		use_mflowid = 0;
122 	}
123 	SCTP_STAT_INCR(sctps_recvpackets);
124 	SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
125 	/* Get IP, SCTP, and first chunk header together in the first mbuf. */
126 	offset = iphlen + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr);
127 	ip6 = mtod(m, struct ip6_hdr *);
128 	IP6_EXTHDR_GET(sh, struct sctphdr *, m, iphlen,
129 	    (int)(sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr)));
130 	if (sh == NULL) {
131 		SCTP_STAT_INCR(sctps_hdrops);
132 		return (IPPROTO_DONE);
133 	}
134 	ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
135 	offset -= sizeof(struct sctp_chunkhdr);
136 	memset(&src, 0, sizeof(struct sockaddr_in6));
137 	src.sin6_family = AF_INET6;
138 	src.sin6_len = sizeof(struct sockaddr_in6);
139 	src.sin6_port = sh->src_port;
140 	src.sin6_addr = ip6->ip6_src;
141 	if (in6_setscope(&src.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
142 		goto out;
143 	}
144 	memset(&dst, 0, sizeof(struct sockaddr_in6));
145 	dst.sin6_family = AF_INET6;
146 	dst.sin6_len = sizeof(struct sockaddr_in6);
147 	dst.sin6_port = sh->dest_port;
148 	dst.sin6_addr = ip6->ip6_dst;
149 	if (in6_setscope(&dst.sin6_addr, m->m_pkthdr.rcvif, NULL) != 0) {
150 		goto out;
151 	}
152 	length = ntohs(ip6->ip6_plen) + iphlen;
153 	/* Validate mbuf chain length with IP payload length. */
154 	if (SCTP_HEADER_LEN(m) != length) {
155 		SCTPDBG(SCTP_DEBUG_INPUT1,
156 		    "sctp6_input() length:%d reported length:%d\n", length, SCTP_HEADER_LEN(m));
157 		SCTP_STAT_INCR(sctps_hdrops);
158 		goto out;
159 	}
160 	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
161 		goto out;
162 	}
163 	ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff);
164 #if defined(SCTP_WITH_NO_CSUM)
165 	SCTP_STAT_INCR(sctps_recvnocrc);
166 #else
167 	if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
168 		SCTP_STAT_INCR(sctps_recvhwcrc);
169 		compute_crc = 0;
170 	} else {
171 		SCTP_STAT_INCR(sctps_recvswcrc);
172 		compute_crc = 1;
173 	}
174 #endif
175 	sctp_common_input_processing(&m, iphlen, offset, length,
176 	    (struct sockaddr *)&src,
177 	    (struct sockaddr *)&dst,
178 	    sh, ch,
179 #if !defined(SCTP_WITH_NO_CSUM)
180 	    compute_crc,
181 #endif
182 	    ecn_bits,
183 	    use_mflowid, mflowid,
184 	    vrf_id, port);
185 out:
186 	if (m) {
187 		sctp_m_freem(m);
188 	}
189 	return (IPPROTO_DONE);
190 }
191 
192 
193 int
194 sctp6_input(struct mbuf **i_pak, int *offp, int proto SCTP_UNUSED)
195 {
196 	return (sctp6_input_with_port(i_pak, offp, 0));
197 }
198 
199 static void
200 sctp6_notify_mbuf(struct sctp_inpcb *inp, struct icmp6_hdr *icmp6,
201     struct sctphdr *sh, struct sctp_tcb *stcb, struct sctp_nets *net)
202 {
203 	uint32_t nxtsz;
204 
205 	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
206 	    (icmp6 == NULL) || (sh == NULL)) {
207 		goto out;
208 	}
209 	/* First do we even look at it? */
210 	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag))
211 		goto out;
212 
213 	if (icmp6->icmp6_type != ICMP6_PACKET_TOO_BIG) {
214 		/* not PACKET TO BIG */
215 		goto out;
216 	}
217 	/*
218 	 * ok we need to look closely. We could even get smarter and look at
219 	 * anyone that we sent to in case we get a different ICMP that tells
220 	 * us there is no way to reach a host, but for this impl, all we
221 	 * care about is MTU discovery.
222 	 */
223 	nxtsz = ntohl(icmp6->icmp6_mtu);
224 	/* Stop any PMTU timer */
225 	sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, NULL, SCTP_FROM_SCTP6_USRREQ + SCTP_LOC_1);
226 
227 	/* Adjust destination size limit */
228 	if (net->mtu > nxtsz) {
229 		net->mtu = nxtsz;
230 		if (net->port) {
231 			net->mtu -= sizeof(struct udphdr);
232 		}
233 	}
234 	/* now what about the ep? */
235 	if (stcb->asoc.smallest_mtu > nxtsz) {
236 		struct sctp_tmit_chunk *chk;
237 
238 		/* Adjust that too */
239 		stcb->asoc.smallest_mtu = nxtsz;
240 		/* now off to subtract IP_DF flag if needed */
241 
242 		TAILQ_FOREACH(chk, &stcb->asoc.send_queue, sctp_next) {
243 			if ((uint32_t) (chk->send_size + IP_HDR_SIZE) > nxtsz) {
244 				chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
245 			}
246 		}
247 		TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
248 			if ((uint32_t) (chk->send_size + IP_HDR_SIZE) > nxtsz) {
249 				/*
250 				 * For this guy we also mark for immediate
251 				 * resend since we sent to big of chunk
252 				 */
253 				chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
254 				if (chk->sent != SCTP_DATAGRAM_RESEND)
255 					stcb->asoc.sent_queue_retran_cnt++;
256 				chk->sent = SCTP_DATAGRAM_RESEND;
257 				chk->rec.data.doing_fast_retransmit = 0;
258 
259 				chk->sent = SCTP_DATAGRAM_RESEND;
260 				/* Clear any time so NO RTT is being done */
261 				chk->sent_rcv_time.tv_sec = 0;
262 				chk->sent_rcv_time.tv_usec = 0;
263 				stcb->asoc.total_flight -= chk->send_size;
264 				net->flight_size -= chk->send_size;
265 			}
266 		}
267 	}
268 	sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, NULL);
269 out:
270 	if (stcb) {
271 		SCTP_TCB_UNLOCK(stcb);
272 	}
273 }
274 
275 
276 void
277 sctp6_notify(struct sctp_inpcb *inp,
278     struct icmp6_hdr *icmph,
279     struct sctphdr *sh,
280     struct sockaddr *to,
281     struct sctp_tcb *stcb,
282     struct sctp_nets *net)
283 {
284 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
285 	struct socket *so;
286 
287 #endif
288 
289 	/* protection */
290 	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
291 	    (sh == NULL) || (to == NULL)) {
292 		if (stcb)
293 			SCTP_TCB_UNLOCK(stcb);
294 		return;
295 	}
296 	/* First job is to verify the vtag matches what I would send */
297 	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
298 		SCTP_TCB_UNLOCK(stcb);
299 		return;
300 	}
301 	if (icmph->icmp6_type != ICMP_UNREACH) {
302 		/* We only care about unreachable */
303 		SCTP_TCB_UNLOCK(stcb);
304 		return;
305 	}
306 	if ((icmph->icmp6_code == ICMP_UNREACH_NET) ||
307 	    (icmph->icmp6_code == ICMP_UNREACH_HOST) ||
308 	    (icmph->icmp6_code == ICMP_UNREACH_NET_UNKNOWN) ||
309 	    (icmph->icmp6_code == ICMP_UNREACH_HOST_UNKNOWN) ||
310 	    (icmph->icmp6_code == ICMP_UNREACH_ISOLATED) ||
311 	    (icmph->icmp6_code == ICMP_UNREACH_NET_PROHIB) ||
312 	    (icmph->icmp6_code == ICMP_UNREACH_HOST_PROHIB) ||
313 	    (icmph->icmp6_code == ICMP_UNREACH_FILTER_PROHIB)) {
314 
315 		/*
316 		 * Hmm reachablity problems we must examine closely. If its
317 		 * not reachable, we may have lost a network. Or if there is
318 		 * NO protocol at the other end named SCTP. well we consider
319 		 * it a OOTB abort.
320 		 */
321 		if (net->dest_state & SCTP_ADDR_REACHABLE) {
322 			/* Ok that destination is NOT reachable */
323 			net->dest_state &= ~SCTP_ADDR_REACHABLE;
324 			net->dest_state &= ~SCTP_ADDR_PF;
325 			sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
326 			    stcb, 0, (void *)net, SCTP_SO_NOT_LOCKED);
327 		}
328 		SCTP_TCB_UNLOCK(stcb);
329 	} else if ((icmph->icmp6_code == ICMP_UNREACH_PROTOCOL) ||
330 	    (icmph->icmp6_code == ICMP_UNREACH_PORT)) {
331 		/*
332 		 * Here the peer is either playing tricks on us, including
333 		 * an address that belongs to someone who does not support
334 		 * SCTP OR was a userland implementation that shutdown and
335 		 * now is dead. In either case treat it like a OOTB abort
336 		 * with no TCB
337 		 */
338 		sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
339 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
340 		so = SCTP_INP_SO(inp);
341 		atomic_add_int(&stcb->asoc.refcnt, 1);
342 		SCTP_TCB_UNLOCK(stcb);
343 		SCTP_SOCKET_LOCK(so, 1);
344 		SCTP_TCB_LOCK(stcb);
345 		atomic_subtract_int(&stcb->asoc.refcnt, 1);
346 #endif
347 		(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
348 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
349 		SCTP_SOCKET_UNLOCK(so, 1);
350 		/* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed. */
351 #endif
352 		/* no need to unlock here, since the TCB is gone */
353 	} else {
354 		SCTP_TCB_UNLOCK(stcb);
355 	}
356 }
357 
358 
359 
360 void
361 sctp6_ctlinput(int cmd, struct sockaddr *pktdst, void *d)
362 {
363 	struct sctphdr sh;
364 	struct ip6ctlparam *ip6cp = NULL;
365 	uint32_t vrf_id;
366 
367 	vrf_id = SCTP_DEFAULT_VRFID;
368 
369 	if (pktdst->sa_family != AF_INET6 ||
370 	    pktdst->sa_len != sizeof(struct sockaddr_in6))
371 		return;
372 
373 	if ((unsigned)cmd >= PRC_NCMDS)
374 		return;
375 	if (PRC_IS_REDIRECT(cmd)) {
376 		d = NULL;
377 	} else if (inet6ctlerrmap[cmd] == 0) {
378 		return;
379 	}
380 	/* if the parameter is from icmp6, decode it. */
381 	if (d != NULL) {
382 		ip6cp = (struct ip6ctlparam *)d;
383 	} else {
384 		ip6cp = (struct ip6ctlparam *)NULL;
385 	}
386 
387 	if (ip6cp) {
388 		/*
389 		 * XXX: We assume that when IPV6 is non NULL, M and OFF are
390 		 * valid.
391 		 */
392 		/* check if we can safely examine src and dst ports */
393 		struct sctp_inpcb *inp = NULL;
394 		struct sctp_tcb *stcb = NULL;
395 		struct sctp_nets *net = NULL;
396 		struct sockaddr_in6 final;
397 
398 		if (ip6cp->ip6c_m == NULL)
399 			return;
400 
401 		bzero(&sh, sizeof(sh));
402 		bzero(&final, sizeof(final));
403 		inp = NULL;
404 		net = NULL;
405 		m_copydata(ip6cp->ip6c_m, ip6cp->ip6c_off, sizeof(sh),
406 		    (caddr_t)&sh);
407 		ip6cp->ip6c_src->sin6_port = sh.src_port;
408 		final.sin6_len = sizeof(final);
409 		final.sin6_family = AF_INET6;
410 		final.sin6_addr = ((struct sockaddr_in6 *)pktdst)->sin6_addr;
411 		final.sin6_port = sh.dest_port;
412 		stcb = sctp_findassociation_addr_sa((struct sockaddr *)&final,
413 		    (struct sockaddr *)ip6cp->ip6c_src,
414 		    &inp, &net, 1, vrf_id);
415 		/* inp's ref-count increased && stcb locked */
416 		if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
417 			if (cmd == PRC_MSGSIZE) {
418 				sctp6_notify_mbuf(inp,
419 				    ip6cp->ip6c_icmp6,
420 				    &sh,
421 				    stcb,
422 				    net);
423 				/* inp's ref-count reduced && stcb unlocked */
424 			} else {
425 				sctp6_notify(inp, ip6cp->ip6c_icmp6, &sh,
426 				    (struct sockaddr *)&final,
427 				    stcb, net);
428 				/* inp's ref-count reduced && stcb unlocked */
429 			}
430 		} else {
431 			if (PRC_IS_REDIRECT(cmd) && inp) {
432 				in6_rtchange((struct in6pcb *)inp,
433 				    inet6ctlerrmap[cmd]);
434 			}
435 			if (inp) {
436 				/* reduce inp's ref-count */
437 				SCTP_INP_WLOCK(inp);
438 				SCTP_INP_DECR_REF(inp);
439 				SCTP_INP_WUNLOCK(inp);
440 			}
441 			if (stcb)
442 				SCTP_TCB_UNLOCK(stcb);
443 		}
444 	}
445 }
446 
447 /*
448  * this routine can probably be collasped into the one in sctp_userreq.c
449  * since they do the same thing and now we lookup with a sockaddr
450  */
451 static int
452 sctp6_getcred(SYSCTL_HANDLER_ARGS)
453 {
454 	struct xucred xuc;
455 	struct sockaddr_in6 addrs[2];
456 	struct sctp_inpcb *inp;
457 	struct sctp_nets *net;
458 	struct sctp_tcb *stcb;
459 	int error;
460 	uint32_t vrf_id;
461 
462 	vrf_id = SCTP_DEFAULT_VRFID;
463 
464 	error = priv_check(req->td, PRIV_NETINET_GETCRED);
465 	if (error)
466 		return (error);
467 
468 	if (req->newlen != sizeof(addrs)) {
469 		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
470 		return (EINVAL);
471 	}
472 	if (req->oldlen != sizeof(struct ucred)) {
473 		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
474 		return (EINVAL);
475 	}
476 	error = SYSCTL_IN(req, addrs, sizeof(addrs));
477 	if (error)
478 		return (error);
479 
480 	stcb = sctp_findassociation_addr_sa(sin6tosa(&addrs[1]),
481 	    sin6tosa(&addrs[0]),
482 	    &inp, &net, 1, vrf_id);
483 	if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
484 		if ((inp != NULL) && (stcb == NULL)) {
485 			/* reduce ref-count */
486 			SCTP_INP_WLOCK(inp);
487 			SCTP_INP_DECR_REF(inp);
488 			goto cred_can_cont;
489 		}
490 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
491 		error = ENOENT;
492 		goto out;
493 	}
494 	SCTP_TCB_UNLOCK(stcb);
495 	/*
496 	 * We use the write lock here, only since in the error leg we need
497 	 * it. If we used RLOCK, then we would have to
498 	 * wlock/decr/unlock/rlock. Which in theory could create a hole.
499 	 * Better to use higher wlock.
500 	 */
501 	SCTP_INP_WLOCK(inp);
502 cred_can_cont:
503 	error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
504 	if (error) {
505 		SCTP_INP_WUNLOCK(inp);
506 		goto out;
507 	}
508 	cru2x(inp->sctp_socket->so_cred, &xuc);
509 	SCTP_INP_WUNLOCK(inp);
510 	error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
511 out:
512 	return (error);
513 }
514 
515 SYSCTL_PROC(_net_inet6_sctp6, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
516     0, 0,
517     sctp6_getcred, "S,ucred", "Get the ucred of a SCTP6 connection");
518 
519 
520 /* This is the same as the sctp_abort() could be made common */
521 static void
522 sctp6_abort(struct socket *so)
523 {
524 	struct sctp_inpcb *inp;
525 	uint32_t flags;
526 
527 	inp = (struct sctp_inpcb *)so->so_pcb;
528 	if (inp == NULL) {
529 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
530 		return;
531 	}
532 sctp_must_try_again:
533 	flags = inp->sctp_flags;
534 #ifdef SCTP_LOG_CLOSING
535 	sctp_log_closing(inp, NULL, 17);
536 #endif
537 	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
538 	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
539 #ifdef SCTP_LOG_CLOSING
540 		sctp_log_closing(inp, NULL, 16);
541 #endif
542 		sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
543 		    SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
544 		SOCK_LOCK(so);
545 		SCTP_SB_CLEAR(so->so_snd);
546 		/*
547 		 * same for the rcv ones, they are only here for the
548 		 * accounting/select.
549 		 */
550 		SCTP_SB_CLEAR(so->so_rcv);
551 		/* Now null out the reference, we are completely detached. */
552 		so->so_pcb = NULL;
553 		SOCK_UNLOCK(so);
554 	} else {
555 		flags = inp->sctp_flags;
556 		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
557 			goto sctp_must_try_again;
558 		}
559 	}
560 	return;
561 }
562 
563 static int
564 sctp6_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
565 {
566 	struct in6pcb *inp6;
567 	int error;
568 	struct sctp_inpcb *inp;
569 	uint32_t vrf_id = SCTP_DEFAULT_VRFID;
570 
571 	inp = (struct sctp_inpcb *)so->so_pcb;
572 	if (inp != NULL) {
573 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
574 		return (EINVAL);
575 	}
576 	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
577 		error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
578 		if (error)
579 			return (error);
580 	}
581 	error = sctp_inpcb_alloc(so, vrf_id);
582 	if (error)
583 		return (error);
584 	inp = (struct sctp_inpcb *)so->so_pcb;
585 	SCTP_INP_WLOCK(inp);
586 	inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_V6;	/* I'm v6! */
587 	inp6 = (struct in6pcb *)inp;
588 
589 	inp6->inp_vflag |= INP_IPV6;
590 	inp6->in6p_hops = -1;	/* use kernel default */
591 	inp6->in6p_cksum = -1;	/* just to be sure */
592 #ifdef INET
593 	/*
594 	 * XXX: ugly!! IPv4 TTL initialization is necessary for an IPv6
595 	 * socket as well, because the socket may be bound to an IPv6
596 	 * wildcard address, which may match an IPv4-mapped IPv6 address.
597 	 */
598 	inp6->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
599 #endif
600 	/*
601 	 * Hmm what about the IPSEC stuff that is missing here but in
602 	 * sctp_attach()?
603 	 */
604 	SCTP_INP_WUNLOCK(inp);
605 	return (0);
606 }
607 
608 static int
609 sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
610 {
611 	struct sctp_inpcb *inp;
612 	struct in6pcb *inp6;
613 	int error;
614 
615 	inp = (struct sctp_inpcb *)so->so_pcb;
616 	if (inp == NULL) {
617 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
618 		return (EINVAL);
619 	}
620 	if (addr) {
621 		switch (addr->sa_family) {
622 #ifdef INET
623 		case AF_INET:
624 			if (addr->sa_len != sizeof(struct sockaddr_in)) {
625 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
626 				return (EINVAL);
627 			}
628 			break;
629 #endif
630 #ifdef INET6
631 		case AF_INET6:
632 			if (addr->sa_len != sizeof(struct sockaddr_in6)) {
633 				SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
634 				return (EINVAL);
635 			}
636 			break;
637 #endif
638 		default:
639 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
640 			return (EINVAL);
641 		}
642 	}
643 	inp6 = (struct in6pcb *)inp;
644 	inp6->inp_vflag &= ~INP_IPV4;
645 	inp6->inp_vflag |= INP_IPV6;
646 	if ((addr != NULL) && (SCTP_IPV6_V6ONLY(inp6) == 0)) {
647 		switch (addr->sa_family) {
648 #ifdef INET
649 		case AF_INET:
650 			/* binding v4 addr to v6 socket, so reset flags */
651 			inp6->inp_vflag |= INP_IPV4;
652 			inp6->inp_vflag &= ~INP_IPV6;
653 			break;
654 #endif
655 #ifdef INET6
656 		case AF_INET6:
657 			{
658 				struct sockaddr_in6 *sin6_p;
659 
660 				sin6_p = (struct sockaddr_in6 *)addr;
661 
662 				if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) {
663 					inp6->inp_vflag |= INP_IPV4;
664 				}
665 #ifdef INET
666 				if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
667 					struct sockaddr_in sin;
668 
669 					in6_sin6_2_sin(&sin, sin6_p);
670 					inp6->inp_vflag |= INP_IPV4;
671 					inp6->inp_vflag &= ~INP_IPV6;
672 					error = sctp_inpcb_bind(so, (struct sockaddr *)&sin, NULL, p);
673 					return (error);
674 				}
675 #endif
676 				break;
677 			}
678 #endif
679 		default:
680 			break;
681 		}
682 	} else if (addr != NULL) {
683 		struct sockaddr_in6 *sin6_p;
684 
685 		/* IPV6_V6ONLY socket */
686 #ifdef INET
687 		if (addr->sa_family == AF_INET) {
688 			/* can't bind v4 addr to v6 only socket! */
689 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
690 			return (EINVAL);
691 		}
692 #endif
693 		sin6_p = (struct sockaddr_in6 *)addr;
694 
695 		if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
696 			/* can't bind v4-mapped addrs either! */
697 			/* NOTE: we don't support SIIT */
698 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
699 			return (EINVAL);
700 		}
701 	}
702 	error = sctp_inpcb_bind(so, addr, NULL, p);
703 	return (error);
704 }
705 
706 
707 static void
708 sctp6_close(struct socket *so)
709 {
710 	sctp_close(so);
711 }
712 
713 /* This could be made common with sctp_detach() since they are identical */
714 
715 static
716 int
717 sctp6_disconnect(struct socket *so)
718 {
719 	return (sctp_disconnect(so));
720 }
721 
722 
723 int
724 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
725     struct mbuf *control, struct thread *p);
726 
727 
728 static int
729 sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
730     struct mbuf *control, struct thread *p)
731 {
732 	struct sctp_inpcb *inp;
733 	struct in6pcb *inp6;
734 
735 #ifdef INET
736 	struct sockaddr_in6 *sin6;
737 
738 #endif				/* INET */
739 	/* No SPL needed since sctp_output does this */
740 
741 	inp = (struct sctp_inpcb *)so->so_pcb;
742 	if (inp == NULL) {
743 		if (control) {
744 			SCTP_RELEASE_PKT(control);
745 			control = NULL;
746 		}
747 		SCTP_RELEASE_PKT(m);
748 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
749 		return (EINVAL);
750 	}
751 	inp6 = (struct in6pcb *)inp;
752 	/*
753 	 * For the TCP model we may get a NULL addr, if we are a connected
754 	 * socket thats ok.
755 	 */
756 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) &&
757 	    (addr == NULL)) {
758 		goto connected_type;
759 	}
760 	if (addr == NULL) {
761 		SCTP_RELEASE_PKT(m);
762 		if (control) {
763 			SCTP_RELEASE_PKT(control);
764 			control = NULL;
765 		}
766 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EDESTADDRREQ);
767 		return (EDESTADDRREQ);
768 	}
769 #ifdef INET
770 	sin6 = (struct sockaddr_in6 *)addr;
771 	if (SCTP_IPV6_V6ONLY(inp6)) {
772 		/*
773 		 * if IPV6_V6ONLY flag, we discard datagrams destined to a
774 		 * v4 addr or v4-mapped addr
775 		 */
776 		if (addr->sa_family == AF_INET) {
777 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
778 			return (EINVAL);
779 		}
780 		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
781 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
782 			return (EINVAL);
783 		}
784 	}
785 	if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
786 		struct sockaddr_in sin;
787 
788 		/* convert v4-mapped into v4 addr and send */
789 		in6_sin6_2_sin(&sin, sin6);
790 		return (sctp_sendm(so, flags, m, (struct sockaddr *)&sin, control, p));
791 	}
792 #endif				/* INET */
793 connected_type:
794 	/* now what about control */
795 	if (control) {
796 		if (inp->control) {
797 			SCTP_PRINTF("huh? control set?\n");
798 			SCTP_RELEASE_PKT(inp->control);
799 			inp->control = NULL;
800 		}
801 		inp->control = control;
802 	}
803 	/* Place the data */
804 	if (inp->pkt) {
805 		SCTP_BUF_NEXT(inp->pkt_last) = m;
806 		inp->pkt_last = m;
807 	} else {
808 		inp->pkt_last = inp->pkt = m;
809 	}
810 	if (
811 	/* FreeBSD and MacOSX uses a flag passed */
812 	    ((flags & PRUS_MORETOCOME) == 0)
813 	    ) {
814 		/*
815 		 * note with the current version this code will only be used
816 		 * by OpenBSD, NetBSD and FreeBSD have methods for
817 		 * re-defining sosend() to use sctp_sosend().  One can
818 		 * optionaly switch back to this code (by changing back the
819 		 * defininitions but this is not advisable.
820 		 */
821 		int ret;
822 
823 		ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
824 		inp->pkt = NULL;
825 		inp->control = NULL;
826 		return (ret);
827 	} else {
828 		return (0);
829 	}
830 }
831 
832 static int
833 sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
834 {
835 	uint32_t vrf_id;
836 	int error = 0;
837 	struct sctp_inpcb *inp;
838 	struct sctp_tcb *stcb;
839 
840 #ifdef INET
841 	struct in6pcb *inp6;
842 	struct sockaddr_in6 *sin6;
843 	union sctp_sockstore store;
844 
845 #endif
846 
847 #ifdef INET
848 	inp6 = (struct in6pcb *)so->so_pcb;
849 #endif
850 	inp = (struct sctp_inpcb *)so->so_pcb;
851 	if (inp == NULL) {
852 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
853 		return (ECONNRESET);	/* I made the same as TCP since we are
854 					 * not setup? */
855 	}
856 	if (addr == NULL) {
857 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
858 		return (EINVAL);
859 	}
860 	switch (addr->sa_family) {
861 #ifdef INET
862 	case AF_INET:
863 		if (addr->sa_len != sizeof(struct sockaddr_in)) {
864 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
865 			return (EINVAL);
866 		}
867 		break;
868 #endif
869 #ifdef INET6
870 	case AF_INET6:
871 		if (addr->sa_len != sizeof(struct sockaddr_in6)) {
872 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
873 			return (EINVAL);
874 		}
875 		break;
876 #endif
877 	default:
878 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
879 		return (EINVAL);
880 	}
881 
882 	vrf_id = inp->def_vrf_id;
883 	SCTP_ASOC_CREATE_LOCK(inp);
884 	SCTP_INP_RLOCK(inp);
885 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
886 	    SCTP_PCB_FLAGS_UNBOUND) {
887 		/* Bind a ephemeral port */
888 		SCTP_INP_RUNLOCK(inp);
889 		error = sctp6_bind(so, NULL, p);
890 		if (error) {
891 			SCTP_ASOC_CREATE_UNLOCK(inp);
892 
893 			return (error);
894 		}
895 		SCTP_INP_RLOCK(inp);
896 	}
897 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
898 	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
899 		/* We are already connected AND the TCP model */
900 		SCTP_INP_RUNLOCK(inp);
901 		SCTP_ASOC_CREATE_UNLOCK(inp);
902 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EADDRINUSE);
903 		return (EADDRINUSE);
904 	}
905 #ifdef INET
906 	sin6 = (struct sockaddr_in6 *)addr;
907 	if (SCTP_IPV6_V6ONLY(inp6)) {
908 		/*
909 		 * if IPV6_V6ONLY flag, ignore connections destined to a v4
910 		 * addr or v4-mapped addr
911 		 */
912 		if (addr->sa_family == AF_INET) {
913 			SCTP_INP_RUNLOCK(inp);
914 			SCTP_ASOC_CREATE_UNLOCK(inp);
915 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
916 			return (EINVAL);
917 		}
918 		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
919 			SCTP_INP_RUNLOCK(inp);
920 			SCTP_ASOC_CREATE_UNLOCK(inp);
921 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
922 			return (EINVAL);
923 		}
924 	}
925 	if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
926 		/* convert v4-mapped into v4 addr */
927 		in6_sin6_2_sin(&store.sin, sin6);
928 		addr = &store.sa;
929 	}
930 #endif				/* INET */
931 	/* Now do we connect? */
932 	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
933 		stcb = LIST_FIRST(&inp->sctp_asoc_list);
934 		if (stcb) {
935 			SCTP_TCB_UNLOCK(stcb);
936 		}
937 		SCTP_INP_RUNLOCK(inp);
938 	} else {
939 		SCTP_INP_RUNLOCK(inp);
940 		SCTP_INP_WLOCK(inp);
941 		SCTP_INP_INCR_REF(inp);
942 		SCTP_INP_WUNLOCK(inp);
943 		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
944 		if (stcb == NULL) {
945 			SCTP_INP_WLOCK(inp);
946 			SCTP_INP_DECR_REF(inp);
947 			SCTP_INP_WUNLOCK(inp);
948 		}
949 	}
950 
951 	if (stcb != NULL) {
952 		/* Already have or am bring up an association */
953 		SCTP_ASOC_CREATE_UNLOCK(inp);
954 		SCTP_TCB_UNLOCK(stcb);
955 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EALREADY);
956 		return (EALREADY);
957 	}
958 	/* We are GOOD to go */
959 	stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
960 	SCTP_ASOC_CREATE_UNLOCK(inp);
961 	if (stcb == NULL) {
962 		/* Gak! no memory */
963 		return (error);
964 	}
965 	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
966 		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
967 		/* Set the connected flag so we can queue data */
968 		soisconnecting(so);
969 	}
970 	stcb->asoc.state = SCTP_STATE_COOKIE_WAIT;
971 	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
972 
973 	/* initialize authentication parameters for the assoc */
974 	sctp_initialize_auth_params(inp, stcb);
975 
976 	sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
977 	SCTP_TCB_UNLOCK(stcb);
978 	return (error);
979 }
980 
981 static int
982 sctp6_getaddr(struct socket *so, struct sockaddr **addr)
983 {
984 	struct sockaddr_in6 *sin6;
985 	struct sctp_inpcb *inp;
986 	uint32_t vrf_id;
987 	struct sctp_ifa *sctp_ifa;
988 
989 	int error;
990 
991 	/*
992 	 * Do the malloc first in case it blocks.
993 	 */
994 	SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof(*sin6));
995 	if (sin6 == NULL)
996 		return (ENOMEM);
997 	sin6->sin6_family = AF_INET6;
998 	sin6->sin6_len = sizeof(*sin6);
999 
1000 	inp = (struct sctp_inpcb *)so->so_pcb;
1001 	if (inp == NULL) {
1002 		SCTP_FREE_SONAME(sin6);
1003 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
1004 		return (ECONNRESET);
1005 	}
1006 	SCTP_INP_RLOCK(inp);
1007 	sin6->sin6_port = inp->sctp_lport;
1008 	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1009 		/* For the bound all case you get back 0 */
1010 		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
1011 			struct sctp_tcb *stcb;
1012 			struct sockaddr_in6 *sin_a6;
1013 			struct sctp_nets *net;
1014 			int fnd;
1015 
1016 			stcb = LIST_FIRST(&inp->sctp_asoc_list);
1017 			if (stcb == NULL) {
1018 				goto notConn6;
1019 			}
1020 			fnd = 0;
1021 			sin_a6 = NULL;
1022 			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1023 				sin_a6 = (struct sockaddr_in6 *)&net->ro._l_addr;
1024 				if (sin_a6 == NULL)
1025 					/* this will make coverity happy */
1026 					continue;
1027 
1028 				if (sin_a6->sin6_family == AF_INET6) {
1029 					fnd = 1;
1030 					break;
1031 				}
1032 			}
1033 			if ((!fnd) || (sin_a6 == NULL)) {
1034 				/* punt */
1035 				goto notConn6;
1036 			}
1037 			vrf_id = inp->def_vrf_id;
1038 			sctp_ifa = sctp_source_address_selection(inp, stcb, (sctp_route_t *) & net->ro, net, 0, vrf_id);
1039 			if (sctp_ifa) {
1040 				sin6->sin6_addr = sctp_ifa->address.sin6.sin6_addr;
1041 			}
1042 		} else {
1043 			/* For the bound all case you get back 0 */
1044 	notConn6:
1045 			memset(&sin6->sin6_addr, 0, sizeof(sin6->sin6_addr));
1046 		}
1047 	} else {
1048 		/* Take the first IPv6 address in the list */
1049 		struct sctp_laddr *laddr;
1050 		int fnd = 0;
1051 
1052 		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1053 			if (laddr->ifa->address.sa.sa_family == AF_INET6) {
1054 				struct sockaddr_in6 *sin_a;
1055 
1056 				sin_a = &laddr->ifa->address.sin6;
1057 				sin6->sin6_addr = sin_a->sin6_addr;
1058 				fnd = 1;
1059 				break;
1060 			}
1061 		}
1062 		if (!fnd) {
1063 			SCTP_FREE_SONAME(sin6);
1064 			SCTP_INP_RUNLOCK(inp);
1065 			SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
1066 			return (ENOENT);
1067 		}
1068 	}
1069 	SCTP_INP_RUNLOCK(inp);
1070 	/* Scoping things for v6 */
1071 	if ((error = sa6_recoverscope(sin6)) != 0) {
1072 		SCTP_FREE_SONAME(sin6);
1073 		return (error);
1074 	}
1075 	(*addr) = (struct sockaddr *)sin6;
1076 	return (0);
1077 }
1078 
1079 static int
1080 sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
1081 {
1082 	struct sockaddr_in6 *sin6;
1083 	int fnd;
1084 	struct sockaddr_in6 *sin_a6;
1085 	struct sctp_inpcb *inp;
1086 	struct sctp_tcb *stcb;
1087 	struct sctp_nets *net;
1088 	int error;
1089 
1090 	/* Do the malloc first in case it blocks. */
1091 	SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
1092 	if (sin6 == NULL)
1093 		return (ENOMEM);
1094 	sin6->sin6_family = AF_INET6;
1095 	sin6->sin6_len = sizeof(*sin6);
1096 
1097 	inp = (struct sctp_inpcb *)so->so_pcb;
1098 	if ((inp == NULL) ||
1099 	    ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
1100 		/* UDP type and listeners will drop out here */
1101 		SCTP_FREE_SONAME(sin6);
1102 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOTCONN);
1103 		return (ENOTCONN);
1104 	}
1105 	SCTP_INP_RLOCK(inp);
1106 	stcb = LIST_FIRST(&inp->sctp_asoc_list);
1107 	if (stcb) {
1108 		SCTP_TCB_LOCK(stcb);
1109 	}
1110 	SCTP_INP_RUNLOCK(inp);
1111 	if (stcb == NULL) {
1112 		SCTP_FREE_SONAME(sin6);
1113 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ECONNRESET);
1114 		return (ECONNRESET);
1115 	}
1116 	fnd = 0;
1117 	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1118 		sin_a6 = (struct sockaddr_in6 *)&net->ro._l_addr;
1119 		if (sin_a6->sin6_family == AF_INET6) {
1120 			fnd = 1;
1121 			sin6->sin6_port = stcb->rport;
1122 			sin6->sin6_addr = sin_a6->sin6_addr;
1123 			break;
1124 		}
1125 	}
1126 	SCTP_TCB_UNLOCK(stcb);
1127 	if (!fnd) {
1128 		/* No IPv4 address */
1129 		SCTP_FREE_SONAME(sin6);
1130 		SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, ENOENT);
1131 		return (ENOENT);
1132 	}
1133 	if ((error = sa6_recoverscope(sin6)) != 0)
1134 		return (error);
1135 	*addr = (struct sockaddr *)sin6;
1136 	return (0);
1137 }
1138 
1139 static int
1140 sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
1141 {
1142 #ifdef INET
1143 	struct sockaddr *addr;
1144 
1145 #endif
1146 	struct in6pcb *inp6 = sotoin6pcb(so);
1147 	int error;
1148 
1149 	if (inp6 == NULL) {
1150 		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1151 		return (EINVAL);
1152 	}
1153 	/* allow v6 addresses precedence */
1154 	error = sctp6_getaddr(so, nam);
1155 #ifdef INET
1156 	if (error) {
1157 		/* try v4 next if v6 failed */
1158 		error = sctp_ingetaddr(so, nam);
1159 		if (error) {
1160 			return (error);
1161 		}
1162 		addr = *nam;
1163 		/* if I'm V6ONLY, convert it to v4-mapped */
1164 		if (SCTP_IPV6_V6ONLY(inp6)) {
1165 			struct sockaddr_in6 sin6;
1166 
1167 			in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6);
1168 			memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
1169 		}
1170 	}
1171 #endif
1172 	return (error);
1173 }
1174 
1175 
1176 static int
1177 sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
1178 {
1179 #ifdef INET
1180 	struct sockaddr *addr;
1181 
1182 #endif
1183 	struct in6pcb *inp6 = sotoin6pcb(so);
1184 	int error;
1185 
1186 	if (inp6 == NULL) {
1187 		SCTP_LTRACE_ERR_RET(NULL, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
1188 		return (EINVAL);
1189 	}
1190 	/* allow v6 addresses precedence */
1191 	error = sctp6_peeraddr(so, nam);
1192 #ifdef INET
1193 	if (error) {
1194 		/* try v4 next if v6 failed */
1195 		error = sctp_peeraddr(so, nam);
1196 		if (error) {
1197 			return (error);
1198 		}
1199 		addr = *nam;
1200 		/* if I'm V6ONLY, convert it to v4-mapped */
1201 		if (SCTP_IPV6_V6ONLY(inp6)) {
1202 			struct sockaddr_in6 sin6;
1203 
1204 			in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6);
1205 			memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
1206 		}
1207 	}
1208 #endif
1209 	return (error);
1210 }
1211 
1212 struct pr_usrreqs sctp6_usrreqs = {
1213 	.pru_abort = sctp6_abort,
1214 	.pru_accept = sctp_accept,
1215 	.pru_attach = sctp6_attach,
1216 	.pru_bind = sctp6_bind,
1217 	.pru_connect = sctp6_connect,
1218 	.pru_control = in6_control,
1219 	.pru_close = sctp6_close,
1220 	.pru_detach = sctp6_close,
1221 	.pru_sopoll = sopoll_generic,
1222 	.pru_flush = sctp_flush,
1223 	.pru_disconnect = sctp6_disconnect,
1224 	.pru_listen = sctp_listen,
1225 	.pru_peeraddr = sctp6_getpeeraddr,
1226 	.pru_send = sctp6_send,
1227 	.pru_shutdown = sctp_shutdown,
1228 	.pru_sockaddr = sctp6_in6getaddr,
1229 	.pru_sosend = sctp_sosend,
1230 	.pru_soreceive = sctp_soreceive
1231 };
1232 
1233 #endif
1234