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