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