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