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