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