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