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