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