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