sctp6_usrreq.c revision 169420
1/*-
2 * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * a) Redistributions of source code must retain the above copyright notice,
8 *   this list of conditions and the following disclaimer.
9 *
10 * b) Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in
12 *   the documentation and/or other materials provided with the distribution.
13 *
14 * c) Neither the name of Cisco Systems, Inc. nor the names of its
15 *    contributors may be used to endorse or promote products derived
16 *    from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
29 */
30/*	$KAME: sctp6_usrreq.c,v 1.38 2005/08/24 08:08:56 suz Exp $	*/
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: head/sys/netinet6/sctp6_usrreq.c 169420 2007-05-09 13:30:06Z rrs $");
33
34
35#include <netinet/sctp_os.h>
36#include <sys/proc.h>
37#include <netinet/sctp_pcb.h>
38#include <netinet/sctp_header.h>
39#include <netinet/sctp_var.h>
40#if defined(INET6)
41#include <netinet6/sctp6_var.h>
42#endif
43#include <netinet/sctp_sysctl.h>
44#include <netinet/sctp_output.h>
45#include <netinet/sctp_uio.h>
46#include <netinet/sctp_asconf.h>
47#include <netinet/sctputil.h>
48#include <netinet/sctp_indata.h>
49#include <netinet/sctp_timer.h>
50#include <netinet/sctp_auth.h>
51#include <netinet/sctp_input.h>
52#include <netinet/sctp_output.h>
53
54
55extern struct protosw inetsw[];
56
57
58
59
60int
61sctp6_input(i_pak, offp, proto)
62	struct mbuf **i_pak;
63	int *offp;
64	int proto;
65{
66	struct mbuf *m;
67	struct ip6_hdr *ip6;
68	struct sctphdr *sh;
69	struct sctp_inpcb *in6p = NULL;
70	struct sctp_nets *net;
71	int refcount_up = 0;
72	uint32_t check, calc_check;
73	uint32_t vrf_id = 0, table_id = 0;
74	struct inpcb *in6p_ip;
75	struct sctp_chunkhdr *ch;
76	int length, mlen, offset, iphlen;
77	uint8_t ecn_bits;
78	struct sctp_tcb *stcb = NULL;
79	int off = *offp;
80
81	/* get the VRF and table id's */
82	if (SCTP_GET_PKT_VRFID(*i_pak, vrf_id)) {
83		SCTP_RELEASE_PKT(*i_pak);
84		return (-1);
85	}
86	if (SCTP_GET_PKT_TABLEID(*i_pak, table_id)) {
87		SCTP_RELEASE_PKT(*i_pak);
88		return (-1);
89	}
90	m = SCTP_HEADER_TO_CHAIN(*i_pak);
91
92	ip6 = mtod(m, struct ip6_hdr *);
93	/* Ensure that (sctphdr + sctp_chunkhdr) in a row. */
94	IP6_EXTHDR_GET(sh, struct sctphdr *, m, off, sizeof(*sh) + sizeof(*ch));
95	if (sh == NULL) {
96		SCTP_STAT_INCR(sctps_hdrops);
97		return IPPROTO_DONE;
98	}
99	ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
100	iphlen = off;
101	offset = iphlen + sizeof(*sh) + sizeof(*ch);
102
103#if defined(NFAITH) && NFAITH > 0
104
105	if (faithprefix_p != NULL && (*faithprefix_p) (&ip6->ip6_dst)) {
106		/* XXX send icmp6 host/port unreach? */
107		goto bad;
108	}
109#endif				/* NFAITH defined and > 0 */
110	SCTP_STAT_INCR(sctps_recvpackets);
111	SCTP_STAT_INCR_COUNTER64(sctps_inpackets);
112	SCTPDBG(SCTP_DEBUG_INPUT1, "V6 input gets a packet iphlen:%d pktlen:%d\n",
113	    iphlen, SCTP_HEADER_LEN((*i_pak)));
114	if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
115		/* No multi-cast support in SCTP */
116		goto bad;
117	}
118	/* destination port of 0 is illegal, based on RFC2960. */
119	if (sh->dest_port == 0)
120		goto bad;
121	if ((sctp_no_csum_on_loopback == 0) ||
122	    (!SCTP_IS_IT_LOOPBACK(m))) {
123		/*
124		 * we do NOT validate things from the loopback if the sysctl
125		 * is set to 1.
126		 */
127		check = sh->checksum;	/* save incoming checksum */
128		if ((check == 0) && (sctp_no_csum_on_loopback)) {
129			/*
130			 * special hook for where we got a local address
131			 * somehow routed across a non IFT_LOOP type
132			 * interface
133			 */
134			if (IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, &ip6->ip6_dst))
135				goto sctp_skip_csum;
136		}
137		sh->checksum = 0;	/* prepare for calc */
138		calc_check = sctp_calculate_sum(m, &mlen, iphlen);
139		if (calc_check != check) {
140			SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x  m:%p mlen:%d iphlen:%d\n",
141			    calc_check, check, m, mlen, iphlen);
142			stcb = sctp_findassociation_addr(m, iphlen, offset - sizeof(*ch),
143			    sh, ch, &in6p, &net, vrf_id);
144			/* in6p's ref-count increased && stcb locked */
145			if ((in6p) && (stcb)) {
146				sctp_send_packet_dropped(stcb, net, m, iphlen, 1);
147				sctp_chunk_output((struct sctp_inpcb *)in6p, stcb, 2);
148			} else if ((in6p != NULL) && (stcb == NULL)) {
149				refcount_up = 1;
150			}
151			SCTP_STAT_INCR(sctps_badsum);
152			SCTP_STAT_INCR_COUNTER32(sctps_checksumerrors);
153			goto bad;
154		}
155		sh->checksum = calc_check;
156	}
157sctp_skip_csum:
158	net = NULL;
159	/*
160	 * Locate pcb and tcb for datagram sctp_findassociation_addr() wants
161	 * IP/SCTP/first chunk header...
162	 */
163	stcb = sctp_findassociation_addr(m, iphlen, offset - sizeof(*ch),
164	    sh, ch, &in6p, &net, vrf_id);
165	/* in6p's ref-count increased */
166	if (in6p == NULL) {
167		struct sctp_init_chunk *init_chk, chunk_buf;
168
169		SCTP_STAT_INCR(sctps_noport);
170		if (ch->chunk_type == SCTP_INITIATION) {
171			/*
172			 * we do a trick here to get the INIT tag, dig in
173			 * and get the tag from the INIT and put it in the
174			 * common header.
175			 */
176			init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
177			    iphlen + sizeof(*sh), sizeof(*init_chk),
178			    (uint8_t *) & chunk_buf);
179			if (init_chk)
180				sh->v_tag = init_chk->init.initiate_tag;
181			else
182				sh->v_tag = 0;
183		}
184		if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
185			sctp_send_shutdown_complete2(m, iphlen, sh, vrf_id,
186			    table_id);
187			goto bad;
188		}
189		if (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) {
190			goto bad;
191		}
192		if (ch->chunk_type != SCTP_ABORT_ASSOCIATION)
193			sctp_send_abort(m, iphlen, sh, 0, NULL, vrf_id,
194			    table_id);
195		goto bad;
196	} else if (stcb == NULL) {
197		refcount_up = 1;
198	}
199	in6p_ip = (struct inpcb *)in6p;
200#ifdef IPSEC
201	/*
202	 * Check AH/ESP integrity.
203	 */
204	if (in6p_ip && (ipsec6_in_reject(m, in6p_ip))) {
205/* XXX */
206		ipsec6stat.in_polvio++;
207		goto bad;
208	}
209#endif				/* IPSEC */
210
211	/*
212	 * CONTROL chunk processing
213	 */
214	offset -= sizeof(*ch);
215	ecn_bits = ((ntohl(ip6->ip6_flow) >> 20) & 0x000000ff);
216
217	/* Length now holds the total packet length payload + iphlen */
218	length = ntohs(ip6->ip6_plen) + iphlen;
219
220	sctp_common_input_processing(&m, iphlen, offset, length, sh, ch,
221	    in6p, stcb, net, ecn_bits, vrf_id, table_id);
222	/* inp's ref-count reduced && stcb unlocked */
223	/* XXX this stuff below gets moved to appropriate parts later... */
224	if (m)
225		sctp_m_freem(m);
226	if ((in6p) && refcount_up) {
227		/* reduce ref-count */
228		SCTP_INP_WLOCK(in6p);
229		SCTP_INP_DECR_REF(in6p);
230		SCTP_INP_WUNLOCK(in6p);
231	}
232	return IPPROTO_DONE;
233
234bad:
235	if (stcb) {
236		SCTP_TCB_UNLOCK(stcb);
237	}
238	if ((in6p) && refcount_up) {
239		/* reduce ref-count */
240		SCTP_INP_WLOCK(in6p);
241		SCTP_INP_DECR_REF(in6p);
242		SCTP_INP_WUNLOCK(in6p);
243	}
244	if (m)
245		sctp_m_freem(m);
246	return IPPROTO_DONE;
247}
248
249
250static void
251sctp6_notify_mbuf(struct sctp_inpcb *inp,
252    struct icmp6_hdr *icmp6,
253    struct sctphdr *sh,
254    struct sctp_tcb *stcb,
255    struct sctp_nets *net)
256{
257	uint32_t nxtsz;
258
259	if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
260	    (icmp6 == NULL) || (sh == NULL)) {
261		goto out;
262	}
263	/* First do we even look at it? */
264	if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag))
265		goto out;
266
267	if (icmp6->icmp6_type != ICMP6_PACKET_TOO_BIG) {
268		/* not PACKET TO BIG */
269		goto out;
270	}
271	/*
272	 * ok we need to look closely. We could even get smarter and look at
273	 * anyone that we sent to in case we get a different ICMP that tells
274	 * us there is no way to reach a host, but for this impl, all we
275	 * care about is MTU discovery.
276	 */
277	nxtsz = ntohl(icmp6->icmp6_mtu);
278	/* Stop any PMTU timer */
279	sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, NULL, SCTP_FROM_SCTP6_USRREQ + SCTP_LOC_1);
280
281	/* Adjust destination size limit */
282	if (net->mtu > nxtsz) {
283		net->mtu = nxtsz;
284	}
285	/* now what about the ep? */
286	if (stcb->asoc.smallest_mtu > nxtsz) {
287		struct sctp_tmit_chunk *chk;
288
289		/* Adjust that too */
290		stcb->asoc.smallest_mtu = nxtsz;
291		/* now off to subtract IP_DF flag if needed */
292
293		TAILQ_FOREACH(chk, &stcb->asoc.send_queue, sctp_next) {
294			if ((uint32_t) (chk->send_size + IP_HDR_SIZE) > nxtsz) {
295				chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
296			}
297		}
298		TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
299			if ((uint32_t) (chk->send_size + IP_HDR_SIZE) > nxtsz) {
300				/*
301				 * For this guy we also mark for immediate
302				 * resend since we sent to big of chunk
303				 */
304				chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
305				if (chk->sent != SCTP_DATAGRAM_RESEND)
306					stcb->asoc.sent_queue_retran_cnt++;
307				chk->sent = SCTP_DATAGRAM_RESEND;
308				chk->rec.data.doing_fast_retransmit = 0;
309
310				chk->sent = SCTP_DATAGRAM_RESEND;
311				/* Clear any time so NO RTT is being done */
312				chk->sent_rcv_time.tv_sec = 0;
313				chk->sent_rcv_time.tv_usec = 0;
314				stcb->asoc.total_flight -= chk->send_size;
315				net->flight_size -= chk->send_size;
316			}
317		}
318	}
319	sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, NULL);
320out:
321	if (stcb) {
322		SCTP_TCB_UNLOCK(stcb);
323	}
324}
325
326
327void
328sctp6_ctlinput(cmd, pktdst, d)
329	int cmd;
330	struct sockaddr *pktdst;
331	void *d;
332{
333	struct sctphdr sh;
334	struct ip6ctlparam *ip6cp = NULL;
335	uint32_t vrf_id;
336	int cm;
337
338	vrf_id = SCTP_DEFAULT_VRFID;
339
340	if (pktdst->sa_family != AF_INET6 ||
341	    pktdst->sa_len != sizeof(struct sockaddr_in6))
342		return;
343
344	if ((unsigned)cmd >= PRC_NCMDS)
345		return;
346	if (PRC_IS_REDIRECT(cmd)) {
347		d = NULL;
348	} else if (inet6ctlerrmap[cmd] == 0) {
349		return;
350	}
351	/* if the parameter is from icmp6, decode it. */
352	if (d != NULL) {
353		ip6cp = (struct ip6ctlparam *)d;
354	} else {
355		ip6cp = (struct ip6ctlparam *)NULL;
356	}
357
358	if (ip6cp) {
359		/*
360		 * XXX: We assume that when IPV6 is non NULL, M and OFF are
361		 * valid.
362		 */
363		/* check if we can safely examine src and dst ports */
364		struct sctp_inpcb *inp = NULL;
365		struct sctp_tcb *stcb = NULL;
366		struct sctp_nets *net = NULL;
367		struct sockaddr_in6 final;
368
369		if (ip6cp->ip6c_m == NULL)
370			return;
371
372		bzero(&sh, sizeof(sh));
373		bzero(&final, sizeof(final));
374		inp = NULL;
375		net = NULL;
376		m_copydata(ip6cp->ip6c_m, ip6cp->ip6c_off, sizeof(sh),
377		    (caddr_t)&sh);
378		ip6cp->ip6c_src->sin6_port = sh.src_port;
379		final.sin6_len = sizeof(final);
380		final.sin6_family = AF_INET6;
381		final.sin6_addr = ((struct sockaddr_in6 *)pktdst)->sin6_addr;
382		final.sin6_port = sh.dest_port;
383		stcb = sctp_findassociation_addr_sa((struct sockaddr *)ip6cp->ip6c_src,
384		    (struct sockaddr *)&final,
385		    &inp, &net, 1, vrf_id);
386		/* inp's ref-count increased && stcb locked */
387		if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
388			if (cmd == PRC_MSGSIZE) {
389				sctp6_notify_mbuf(inp,
390				    ip6cp->ip6c_icmp6,
391				    &sh,
392				    stcb,
393				    net);
394				/* inp's ref-count reduced && stcb unlocked */
395			} else {
396				if (cmd == PRC_HOSTDEAD) {
397					cm = EHOSTUNREACH;
398				} else {
399					cm = inet6ctlerrmap[cmd];
400				}
401				sctp_notify(inp, cm, &sh,
402				    (struct sockaddr *)&final,
403				    stcb, net);
404				/* inp's ref-count reduced && stcb unlocked */
405			}
406		} else {
407			if (PRC_IS_REDIRECT(cmd) && inp) {
408				in6_rtchange((struct in6pcb *)inp,
409				    inet6ctlerrmap[cmd]);
410			}
411			if (inp) {
412				/* reduce inp's ref-count */
413				SCTP_INP_WLOCK(inp);
414				SCTP_INP_DECR_REF(inp);
415				SCTP_INP_WUNLOCK(inp);
416			}
417			if (stcb)
418				SCTP_TCB_UNLOCK(stcb);
419		}
420	}
421}
422
423/*
424 * this routine can probably be collasped into the one in sctp_userreq.c
425 * since they do the same thing and now we lookup with a sockaddr
426 */
427static int
428sctp6_getcred(SYSCTL_HANDLER_ARGS)
429{
430	struct xucred xuc;
431	struct sockaddr_in6 addrs[2];
432	struct sctp_inpcb *inp;
433	struct sctp_nets *net;
434	struct sctp_tcb *stcb;
435	int error;
436	uint32_t vrf_id;
437
438	vrf_id = SCTP_DEFAULT_VRFID;
439
440	/*
441	 * XXXRW: Other instances of getcred use SUSER_ALLOWJAIL, as socket
442	 * visibility is scoped using cr_canseesocket(), which it is not
443	 * here.
444	 */
445	error = priv_check_cred(req->td->td_ucred, PRIV_NETINET_RESERVEDPORT,
446	    0);
447	if (error)
448		return (error);
449
450	if (req->newlen != sizeof(addrs))
451		return (EINVAL);
452	if (req->oldlen != sizeof(struct ucred))
453		return (EINVAL);
454	error = SYSCTL_IN(req, addrs, sizeof(addrs));
455	if (error)
456		return (error);
457
458	stcb = sctp_findassociation_addr_sa(sin6tosa(&addrs[0]),
459	    sin6tosa(&addrs[1]),
460	    &inp, &net, 1, vrf_id);
461	if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
462		if ((inp != NULL) && (stcb == NULL)) {
463			/* reduce ref-count */
464			SCTP_INP_WLOCK(inp);
465			SCTP_INP_DECR_REF(inp);
466			goto cred_can_cont;
467		}
468		error = ENOENT;
469		goto out;
470	}
471	SCTP_TCB_UNLOCK(stcb);
472	/*
473	 * We use the write lock here, only since in the error leg we need
474	 * it. If we used RLOCK, then we would have to
475	 * wlock/decr/unlock/rlock. Which in theory could create a hole.
476	 * Better to use higher wlock.
477	 */
478	SCTP_INP_WLOCK(inp);
479cred_can_cont:
480	error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
481	if (error) {
482		SCTP_INP_WUNLOCK(inp);
483		goto out;
484	}
485	cru2x(inp->sctp_socket->so_cred, &xuc);
486	SCTP_INP_WUNLOCK(inp);
487	error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
488out:
489	return (error);
490}
491
492SYSCTL_PROC(_net_inet6_sctp6, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
493    0, 0,
494    sctp6_getcred, "S,ucred", "Get the ucred of a SCTP6 connection");
495
496
497/* This is the same as the sctp_abort() could be made common */
498static void
499sctp6_abort(struct socket *so)
500{
501	struct sctp_inpcb *inp;
502	uint32_t flags;
503
504	inp = (struct sctp_inpcb *)so->so_pcb;
505	if (inp == 0)
506		return;
507sctp_must_try_again:
508	flags = inp->sctp_flags;
509#ifdef SCTP_LOG_CLOSING
510	sctp_log_closing(inp, NULL, 17);
511#endif
512	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
513	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
514#ifdef SCTP_LOG_CLOSING
515		sctp_log_closing(inp, NULL, 16);
516#endif
517		sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
518		    SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
519		SOCK_LOCK(so);
520		SCTP_SB_CLEAR(so->so_snd);
521		/*
522		 * same for the rcv ones, they are only here for the
523		 * accounting/select.
524		 */
525		SCTP_SB_CLEAR(so->so_rcv);
526		/* Now null out the reference, we are completely detached. */
527		so->so_pcb = NULL;
528		SOCK_UNLOCK(so);
529	} else {
530		flags = inp->sctp_flags;
531		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
532			goto sctp_must_try_again;
533		}
534	}
535	return;
536}
537
538static int
539sctp6_attach(struct socket *so, int proto, struct thread *p)
540{
541	struct in6pcb *inp6;
542	int error;
543	struct sctp_inpcb *inp;
544
545	inp = (struct sctp_inpcb *)so->so_pcb;
546	if (inp != NULL)
547		return EINVAL;
548
549	if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
550		error = SCTP_SORESERVE(so, sctp_sendspace, sctp_recvspace);
551		if (error)
552			return error;
553	}
554	error = sctp_inpcb_alloc(so);
555	if (error)
556		return error;
557	inp = (struct sctp_inpcb *)so->so_pcb;
558	inp->sctp_flags |= SCTP_PCB_FLAGS_BOUND_V6;	/* I'm v6! */
559	inp6 = (struct in6pcb *)inp;
560
561	inp6->inp_vflag |= INP_IPV6;
562	inp6->in6p_hops = -1;	/* use kernel default */
563	inp6->in6p_cksum = -1;	/* just to be sure */
564#ifdef INET
565	/*
566	 * XXX: ugly!! IPv4 TTL initialization is necessary for an IPv6
567	 * socket as well, because the socket may be bound to an IPv6
568	 * wildcard address, which may match an IPv4-mapped IPv6 address.
569	 */
570	inp6->inp_ip_ttl = ip_defttl;
571#endif
572	/*
573	 * Hmm what about the IPSEC stuff that is missing here but in
574	 * sctp_attach()?
575	 */
576	return 0;
577}
578
579static int
580sctp6_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
581{
582	struct sctp_inpcb *inp;
583	struct in6pcb *inp6;
584	int error;
585
586	inp = (struct sctp_inpcb *)so->so_pcb;
587	if (inp == 0)
588		return EINVAL;
589
590	inp6 = (struct in6pcb *)inp;
591	inp6->inp_vflag &= ~INP_IPV4;
592	inp6->inp_vflag |= INP_IPV6;
593	if ((addr != NULL) && (SCTP_IPV6_V6ONLY(inp6) == 0)) {
594		if (addr->sa_family == AF_INET) {
595			/* binding v4 addr to v6 socket, so reset flags */
596			inp6->inp_vflag |= INP_IPV4;
597			inp6->inp_vflag &= ~INP_IPV6;
598		} else {
599			struct sockaddr_in6 *sin6_p;
600
601			sin6_p = (struct sockaddr_in6 *)addr;
602
603			if (IN6_IS_ADDR_UNSPECIFIED(&sin6_p->sin6_addr)) {
604				inp6->inp_vflag |= INP_IPV4;
605			} else if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr)) {
606				struct sockaddr_in sin;
607
608				in6_sin6_2_sin(&sin, sin6_p);
609				inp6->inp_vflag |= INP_IPV4;
610				inp6->inp_vflag &= ~INP_IPV6;
611				error = sctp_inpcb_bind(so, (struct sockaddr *)&sin, p);
612				return error;
613			}
614		}
615	} else if (addr != NULL) {
616		/* IPV6_V6ONLY socket */
617		if (addr->sa_family == AF_INET) {
618			/* can't bind v4 addr to v6 only socket! */
619			return EINVAL;
620		} else {
621			struct sockaddr_in6 *sin6_p;
622
623			sin6_p = (struct sockaddr_in6 *)addr;
624
625			if (IN6_IS_ADDR_V4MAPPED(&sin6_p->sin6_addr))
626				/* can't bind v4-mapped addrs either! */
627				/* NOTE: we don't support SIIT */
628				return EINVAL;
629		}
630	}
631	error = sctp_inpcb_bind(so, addr, p);
632	return error;
633}
634
635
636static void
637sctp6_close(struct socket *so)
638{
639	struct sctp_inpcb *inp;
640	uint32_t flags;
641
642	inp = (struct sctp_inpcb *)so->so_pcb;
643	if (inp == 0)
644		return;
645
646	/*
647	 * Inform all the lower layer assoc that we are done.
648	 */
649sctp_must_try_again:
650	flags = inp->sctp_flags;
651#ifdef SCTP_LOG_CLOSING
652	sctp_log_closing(inp, NULL, 17);
653#endif
654	if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
655	    (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
656		if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
657		    (so->so_rcv.sb_cc > 0)) {
658#ifdef SCTP_LOG_CLOSING
659			sctp_log_closing(inp, NULL, 13);
660#endif
661			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT
662			    ,SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
663		} else {
664#ifdef SCTP_LOG_CLOSING
665			sctp_log_closing(inp, NULL, 14);
666#endif
667			sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
668			    SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
669		}
670		/*
671		 * The socket is now detached, no matter what the state of
672		 * the SCTP association.
673		 */
674		SOCK_LOCK(so);
675		SCTP_SB_CLEAR(so->so_snd);
676		/*
677		 * same for the rcv ones, they are only here for the
678		 * accounting/select.
679		 */
680		SCTP_SB_CLEAR(so->so_rcv);
681		/* Now null out the reference, we are completely detached. */
682		so->so_pcb = NULL;
683		SOCK_UNLOCK(so);
684	} else {
685		flags = inp->sctp_flags;
686		if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
687			goto sctp_must_try_again;
688		}
689	}
690	return;
691
692}
693
694/* This could be made common with sctp_detach() since they are identical */
695
696static
697int
698sctp6_disconnect(struct socket *so)
699{
700	struct sctp_inpcb *inp;
701
702	inp = (struct sctp_inpcb *)so->so_pcb;
703	if (inp == NULL) {
704		return (ENOTCONN);
705	}
706	SCTP_INP_RLOCK(inp);
707	if (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
708		if (SCTP_LIST_EMPTY(&inp->sctp_asoc_list)) {
709			/* No connection */
710			SCTP_INP_RUNLOCK(inp);
711			return (ENOTCONN);
712		} else {
713			int some_on_streamwheel = 0;
714			struct sctp_association *asoc;
715			struct sctp_tcb *stcb;
716
717			stcb = LIST_FIRST(&inp->sctp_asoc_list);
718			if (stcb == NULL) {
719				SCTP_INP_RUNLOCK(inp);
720				return (EINVAL);
721			}
722			SCTP_TCB_LOCK(stcb);
723			asoc = &stcb->asoc;
724			if (((so->so_options & SO_LINGER) &&
725			    (so->so_linger == 0)) ||
726			    (so->so_rcv.sb_cc > 0)) {
727				if (SCTP_GET_STATE(asoc) !=
728				    SCTP_STATE_COOKIE_WAIT) {
729					/* Left with Data unread */
730					struct mbuf *op_err;
731
732					op_err = sctp_generate_invmanparam(SCTP_CAUSE_USER_INITIATED_ABT);
733					sctp_send_abort_tcb(stcb, op_err);
734					SCTP_STAT_INCR_COUNTER32(sctps_aborted);
735				}
736				SCTP_INP_RUNLOCK(inp);
737				if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
738				    (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
739					SCTP_STAT_DECR_GAUGE32(sctps_currestab);
740				}
741				sctp_free_assoc(inp, stcb, SCTP_DONOT_SETSCOPE,
742				    SCTP_FROM_SCTP6_USRREQ + SCTP_LOC_2);
743				/* No unlock tcb assoc is gone */
744				return (0);
745			}
746			if (!TAILQ_EMPTY(&asoc->out_wheel)) {
747				/* Check to see if some data queued */
748				struct sctp_stream_out *outs;
749
750				TAILQ_FOREACH(outs, &asoc->out_wheel,
751				    next_spoke) {
752					if (!TAILQ_EMPTY(&outs->outqueue)) {
753						some_on_streamwheel = 1;
754						break;
755					}
756				}
757			}
758			if (TAILQ_EMPTY(&asoc->send_queue) &&
759			    TAILQ_EMPTY(&asoc->sent_queue) &&
760			    (some_on_streamwheel == 0)) {
761				/* nothing queued to send, so I'm done... */
762				if ((SCTP_GET_STATE(asoc) !=
763				    SCTP_STATE_SHUTDOWN_SENT) &&
764				    (SCTP_GET_STATE(asoc) !=
765				    SCTP_STATE_SHUTDOWN_ACK_SENT)) {
766					/* only send SHUTDOWN the first time */
767					sctp_send_shutdown(stcb, stcb->asoc.primary_destination);
768					sctp_chunk_output(stcb->sctp_ep, stcb, 1);
769					if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
770					    (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
771						SCTP_STAT_DECR_GAUGE32(sctps_currestab);
772					}
773					asoc->state = SCTP_STATE_SHUTDOWN_SENT;
774					sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
775					    stcb->sctp_ep, stcb,
776					    asoc->primary_destination);
777					sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
778					    stcb->sctp_ep, stcb,
779					    asoc->primary_destination);
780				}
781			} else {
782				/*
783				 * we still got (or just got) data to send,
784				 * so set SHUTDOWN_PENDING
785				 */
786				/*
787				 * XXX sockets draft says that MSG_EOF
788				 * should be sent with no data.  currently,
789				 * we will allow user data to be sent first
790				 * and move to SHUTDOWN-PENDING
791				 */
792				asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
793			}
794			SCTP_TCB_UNLOCK(stcb);
795			SCTP_INP_RUNLOCK(inp);
796			return (0);
797		}
798	} else {
799		/* UDP model does not support this */
800		SCTP_INP_RUNLOCK(inp);
801		return EOPNOTSUPP;
802	}
803}
804
805
806int
807sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
808    struct mbuf *control, struct thread *p);
809
810
811static int
812sctp6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
813    struct mbuf *control, struct thread *p)
814{
815	struct sctp_inpcb *inp;
816	struct inpcb *in_inp;
817	struct in6pcb *inp6;
818
819#ifdef INET
820	struct sockaddr_in6 *sin6;
821
822#endif				/* INET */
823	/* No SPL needed since sctp_output does this */
824
825	inp = (struct sctp_inpcb *)so->so_pcb;
826	if (inp == NULL) {
827		if (control) {
828			SCTP_RELEASE_PKT(control);
829			control = NULL;
830		}
831		SCTP_RELEASE_PKT(m);
832		return EINVAL;
833	}
834	in_inp = (struct inpcb *)inp;
835	inp6 = (struct in6pcb *)inp;
836	/*
837	 * For the TCP model we may get a NULL addr, if we are a connected
838	 * socket thats ok.
839	 */
840	if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) &&
841	    (addr == NULL)) {
842		goto connected_type;
843	}
844	if (addr == NULL) {
845		SCTP_RELEASE_PKT(m);
846		if (control) {
847			SCTP_RELEASE_PKT(control);
848			control = NULL;
849		}
850		return (EDESTADDRREQ);
851	}
852#ifdef INET
853	sin6 = (struct sockaddr_in6 *)addr;
854	if (SCTP_IPV6_V6ONLY(inp6)) {
855		/*
856		 * if IPV6_V6ONLY flag, we discard datagrams destined to a
857		 * v4 addr or v4-mapped addr
858		 */
859		if (addr->sa_family == AF_INET) {
860			return EINVAL;
861		}
862		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
863			return EINVAL;
864		}
865	}
866	if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
867		if (!ip6_v6only) {
868			struct sockaddr_in sin;
869
870			/* convert v4-mapped into v4 addr and send */
871			in6_sin6_2_sin(&sin, sin6);
872			return sctp_sendm(so, flags, m, (struct sockaddr *)&sin,
873			    control, p);
874		} else {
875			/* mapped addresses aren't enabled */
876			return EINVAL;
877		}
878	}
879#endif				/* INET */
880connected_type:
881	/* now what about control */
882	if (control) {
883		if (inp->control) {
884			SCTP_PRINTF("huh? control set?\n");
885			SCTP_RELEASE_PKT(inp->control);
886			inp->control = NULL;
887		}
888		inp->control = control;
889	}
890	/* Place the data */
891	if (inp->pkt) {
892		SCTP_BUF_NEXT(inp->pkt_last) = m;
893		inp->pkt_last = m;
894	} else {
895		inp->pkt_last = inp->pkt = m;
896	}
897	if (
898	/* FreeBSD and MacOSX uses a flag passed */
899	    ((flags & PRUS_MORETOCOME) == 0)
900	    ) {
901		/*
902		 * note with the current version this code will only be used
903		 * by OpenBSD, NetBSD and FreeBSD have methods for
904		 * re-defining sosend() to use sctp_sosend().  One can
905		 * optionaly switch back to this code (by changing back the
906		 * defininitions but this is not advisable.
907		 */
908		int ret;
909
910		ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
911		inp->pkt = NULL;
912		inp->control = NULL;
913		return (ret);
914	} else {
915		return (0);
916	}
917}
918
919static int
920sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
921{
922	uint32_t vrf_id;
923	int error = 0;
924	struct sctp_inpcb *inp;
925	struct in6pcb *inp6;
926	struct sctp_tcb *stcb;
927
928#ifdef INET
929	struct sockaddr_in6 *sin6;
930	struct sockaddr_storage ss;
931
932#endif				/* INET */
933
934	inp6 = (struct in6pcb *)so->so_pcb;
935	inp = (struct sctp_inpcb *)so->so_pcb;
936	if (inp == 0) {
937		return (ECONNRESET);	/* I made the same as TCP since we are
938					 * not setup? */
939	}
940	vrf_id = inp->def_vrf_id;
941	SCTP_ASOC_CREATE_LOCK(inp);
942	SCTP_INP_RLOCK(inp);
943	if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
944	    SCTP_PCB_FLAGS_UNBOUND) {
945		/* Bind a ephemeral port */
946		SCTP_INP_RUNLOCK(inp);
947		error = sctp6_bind(so, NULL, p);
948		if (error) {
949			SCTP_ASOC_CREATE_UNLOCK(inp);
950
951			return (error);
952		}
953		SCTP_INP_RLOCK(inp);
954	}
955	if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
956	    (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
957		/* We are already connected AND the TCP model */
958		SCTP_INP_RUNLOCK(inp);
959		SCTP_ASOC_CREATE_UNLOCK(inp);
960		return (EADDRINUSE);
961	}
962#ifdef INET
963	sin6 = (struct sockaddr_in6 *)addr;
964	if (SCTP_IPV6_V6ONLY(inp6)) {
965		/*
966		 * if IPV6_V6ONLY flag, ignore connections destined to a v4
967		 * addr or v4-mapped addr
968		 */
969		if (addr->sa_family == AF_INET) {
970			SCTP_INP_RUNLOCK(inp);
971			SCTP_ASOC_CREATE_UNLOCK(inp);
972			return EINVAL;
973		}
974		if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
975			SCTP_INP_RUNLOCK(inp);
976			SCTP_ASOC_CREATE_UNLOCK(inp);
977			return EINVAL;
978		}
979	}
980	if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
981		if (!ip6_v6only) {
982			/* convert v4-mapped into v4 addr */
983			in6_sin6_2_sin((struct sockaddr_in *)&ss, sin6);
984			addr = (struct sockaddr *)&ss;
985		} else {
986			/* mapped addresses aren't enabled */
987			SCTP_INP_RUNLOCK(inp);
988			SCTP_ASOC_CREATE_UNLOCK(inp);
989			return EINVAL;
990		}
991	} else
992#endif				/* INET */
993		addr = addr;	/* for true v6 address case */
994
995	/* Now do we connect? */
996	if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
997		stcb = LIST_FIRST(&inp->sctp_asoc_list);
998		if (stcb) {
999			SCTP_TCB_UNLOCK(stcb);
1000		}
1001		SCTP_INP_RUNLOCK(inp);
1002	} else {
1003		SCTP_INP_RUNLOCK(inp);
1004		SCTP_INP_WLOCK(inp);
1005		SCTP_INP_INCR_REF(inp);
1006		SCTP_INP_WUNLOCK(inp);
1007		stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
1008		if (stcb == NULL) {
1009			SCTP_INP_WLOCK(inp);
1010			SCTP_INP_DECR_REF(inp);
1011			SCTP_INP_WUNLOCK(inp);
1012		}
1013	}
1014
1015	if (stcb != NULL) {
1016		/* Already have or am bring up an association */
1017		SCTP_ASOC_CREATE_UNLOCK(inp);
1018		SCTP_TCB_UNLOCK(stcb);
1019		return (EALREADY);
1020	}
1021	/* We are GOOD to go */
1022	stcb = sctp_aloc_assoc(inp, addr, 1, &error, 0, vrf_id);
1023	SCTP_ASOC_CREATE_UNLOCK(inp);
1024	if (stcb == NULL) {
1025		/* Gak! no memory */
1026		return (error);
1027	}
1028	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
1029		stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
1030		/* Set the connected flag so we can queue data */
1031		soisconnecting(so);
1032	}
1033	stcb->asoc.state = SCTP_STATE_COOKIE_WAIT;
1034	(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
1035
1036	/* initialize authentication parameters for the assoc */
1037	sctp_initialize_auth_params(inp, stcb);
1038
1039	sctp_send_initiate(inp, stcb);
1040	SCTP_TCB_UNLOCK(stcb);
1041	return error;
1042}
1043
1044static int
1045sctp6_getaddr(struct socket *so, struct sockaddr **addr)
1046{
1047	struct sockaddr_in6 *sin6;
1048	struct sctp_inpcb *inp;
1049	uint32_t vrf_id;
1050	struct sctp_ifa *sctp_ifa;
1051
1052	int error;
1053
1054	/*
1055	 * Do the malloc first in case it blocks.
1056	 */
1057	SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
1058	sin6->sin6_family = AF_INET6;
1059	sin6->sin6_len = sizeof(*sin6);
1060
1061	inp = (struct sctp_inpcb *)so->so_pcb;
1062	if (inp == NULL) {
1063		SCTP_FREE_SONAME(sin6);
1064		return ECONNRESET;
1065	}
1066	SCTP_INP_RLOCK(inp);
1067	sin6->sin6_port = inp->sctp_lport;
1068	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1069		/* For the bound all case you get back 0 */
1070		if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
1071			struct sctp_tcb *stcb;
1072			struct sockaddr_in6 *sin_a6;
1073			struct sctp_nets *net;
1074			int fnd;
1075
1076			stcb = LIST_FIRST(&inp->sctp_asoc_list);
1077			if (stcb == NULL) {
1078				goto notConn6;
1079			}
1080			fnd = 0;
1081			sin_a6 = NULL;
1082			TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1083				sin_a6 = (struct sockaddr_in6 *)&net->ro._l_addr;
1084				if (sin_a6 == NULL)
1085					/* this will make coverity happy */
1086					continue;
1087
1088				if (sin_a6->sin6_family == AF_INET6) {
1089					fnd = 1;
1090					break;
1091				}
1092			}
1093			if ((!fnd) || (sin_a6 == NULL)) {
1094				/* punt */
1095				goto notConn6;
1096			}
1097			vrf_id = inp->def_vrf_id;
1098			sctp_ifa = sctp_source_address_selection(inp, stcb, (sctp_route_t *) & net->ro, net, 0, vrf_id);
1099			if (sctp_ifa) {
1100				sin6->sin6_addr = sctp_ifa->address.sin6.sin6_addr;
1101			}
1102		} else {
1103			/* For the bound all case you get back 0 */
1104	notConn6:
1105			memset(&sin6->sin6_addr, 0, sizeof(sin6->sin6_addr));
1106		}
1107	} else {
1108		/* Take the first IPv6 address in the list */
1109		struct sctp_laddr *laddr;
1110		int fnd = 0;
1111
1112		LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1113			if (laddr->ifa->address.sa.sa_family == AF_INET6) {
1114				struct sockaddr_in6 *sin_a;
1115
1116				sin_a = (struct sockaddr_in6 *)&laddr->ifa->address.sin6;
1117				sin6->sin6_addr = sin_a->sin6_addr;
1118				fnd = 1;
1119				break;
1120			}
1121		}
1122		if (!fnd) {
1123			SCTP_FREE_SONAME(sin6);
1124			SCTP_INP_RUNLOCK(inp);
1125			return ENOENT;
1126		}
1127	}
1128	SCTP_INP_RUNLOCK(inp);
1129	/* Scoping things for v6 */
1130	if ((error = sa6_recoverscope(sin6)) != 0) {
1131		SCTP_FREE_SONAME(sin6);
1132		return (error);
1133	}
1134	(*addr) = (struct sockaddr *)sin6;
1135	return (0);
1136}
1137
1138static int
1139sctp6_peeraddr(struct socket *so, struct sockaddr **addr)
1140{
1141	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)*addr;
1142	int fnd;
1143	struct sockaddr_in6 *sin_a6;
1144	struct sctp_inpcb *inp;
1145	struct sctp_tcb *stcb;
1146	struct sctp_nets *net;
1147
1148	int error;
1149
1150	/*
1151	 * Do the malloc first in case it blocks.
1152	 */
1153	inp = (struct sctp_inpcb *)so->so_pcb;
1154	if ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0) {
1155		/* UDP type and listeners will drop out here */
1156		return (ENOTCONN);
1157	}
1158	SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
1159	sin6->sin6_family = AF_INET6;
1160	sin6->sin6_len = sizeof(*sin6);
1161
1162	/* We must recapture incase we blocked */
1163	inp = (struct sctp_inpcb *)so->so_pcb;
1164	if (inp == NULL) {
1165		SCTP_FREE_SONAME(sin6);
1166		return ECONNRESET;
1167	}
1168	SCTP_INP_RLOCK(inp);
1169	stcb = LIST_FIRST(&inp->sctp_asoc_list);
1170	if (stcb) {
1171		SCTP_TCB_LOCK(stcb);
1172	}
1173	SCTP_INP_RUNLOCK(inp);
1174	if (stcb == NULL) {
1175		SCTP_FREE_SONAME(sin6);
1176		return ECONNRESET;
1177	}
1178	fnd = 0;
1179	TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
1180		sin_a6 = (struct sockaddr_in6 *)&net->ro._l_addr;
1181		if (sin_a6->sin6_family == AF_INET6) {
1182			fnd = 1;
1183			sin6->sin6_port = stcb->rport;
1184			sin6->sin6_addr = sin_a6->sin6_addr;
1185			break;
1186		}
1187	}
1188	SCTP_TCB_UNLOCK(stcb);
1189	if (!fnd) {
1190		/* No IPv4 address */
1191		SCTP_FREE_SONAME(sin6);
1192		return ENOENT;
1193	}
1194	if ((error = sa6_recoverscope(sin6)) != 0)
1195		return (error);
1196	*addr = (struct sockaddr *)sin6;
1197	return (0);
1198}
1199
1200static int
1201sctp6_in6getaddr(struct socket *so, struct sockaddr **nam)
1202{
1203	struct sockaddr *addr;
1204	struct in6pcb *inp6 = sotoin6pcb(so);
1205	int error;
1206
1207	if (inp6 == NULL)
1208		return EINVAL;
1209
1210	/* allow v6 addresses precedence */
1211	error = sctp6_getaddr(so, nam);
1212	if (error) {
1213		/* try v4 next if v6 failed */
1214		error = sctp_ingetaddr(so, nam);
1215		if (error) {
1216			return (error);
1217		}
1218		addr = *nam;
1219		/* if I'm V6ONLY, convert it to v4-mapped */
1220		if (SCTP_IPV6_V6ONLY(inp6)) {
1221			struct sockaddr_in6 sin6;
1222
1223			in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6);
1224			memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
1225
1226		}
1227	}
1228	return (error);
1229}
1230
1231
1232static int
1233sctp6_getpeeraddr(struct socket *so, struct sockaddr **nam)
1234{
1235	struct sockaddr *addr = *nam;
1236	struct in6pcb *inp6 = sotoin6pcb(so);
1237	int error;
1238
1239	if (inp6 == NULL)
1240		return EINVAL;
1241
1242	/* allow v6 addresses precedence */
1243	error = sctp6_peeraddr(so, nam);
1244	if (error) {
1245		/* try v4 next if v6 failed */
1246		error = sctp_peeraddr(so, nam);
1247		if (error) {
1248			return (error);
1249		}
1250		/* if I'm V6ONLY, convert it to v4-mapped */
1251		if (SCTP_IPV6_V6ONLY(inp6)) {
1252			struct sockaddr_in6 sin6;
1253
1254			in6_sin_2_v4mapsin6((struct sockaddr_in *)addr, &sin6);
1255			memcpy(addr, &sin6, sizeof(struct sockaddr_in6));
1256		}
1257	}
1258	return error;
1259}
1260
1261struct pr_usrreqs sctp6_usrreqs = {
1262	.pru_abort = sctp6_abort,
1263	.pru_accept = sctp_accept,
1264	.pru_attach = sctp6_attach,
1265	.pru_bind = sctp6_bind,
1266	.pru_connect = sctp6_connect,
1267	.pru_control = in6_control,
1268	.pru_close = sctp6_close,
1269	.pru_detach = sctp6_close,
1270	.pru_sopoll = sopoll_generic,
1271	.pru_disconnect = sctp6_disconnect,
1272	.pru_listen = sctp_listen,
1273	.pru_peeraddr = sctp6_getpeeraddr,
1274	.pru_send = sctp6_send,
1275	.pru_shutdown = sctp_shutdown,
1276	.pru_sockaddr = sctp6_in6getaddr,
1277	.pru_sosend = sctp_sosend,
1278	.pru_soreceive = sctp_soreceive
1279};
1280