18c2654abSrjs /* $KAME: sctp_input.c,v 1.28 2005/04/21 18:36:21 nishida Exp $ */
2*481d3881Srin /* $NetBSD: sctp_input.c,v 1.18 2024/07/05 04:31:54 rin Exp $ */
38c2654abSrjs
48c2654abSrjs /*
58c2654abSrjs * Copyright (C) 2002, 2003, 2004 Cisco Systems Inc,
68c2654abSrjs * All rights reserved.
78c2654abSrjs *
88c2654abSrjs * Redistribution and use in source and binary forms, with or without
98c2654abSrjs * modification, are permitted provided that the following conditions
108c2654abSrjs * are met:
118c2654abSrjs * 1. Redistributions of source code must retain the above copyright
128c2654abSrjs * notice, this list of conditions and the following disclaimer.
138c2654abSrjs * 2. Redistributions in binary form must reproduce the above copyright
148c2654abSrjs * notice, this list of conditions and the following disclaimer in the
158c2654abSrjs * documentation and/or other materials provided with the distribution.
168c2654abSrjs * 3. Neither the name of the project nor the names of its contributors
178c2654abSrjs * may be used to endorse or promote products derived from this software
188c2654abSrjs * without specific prior written permission.
198c2654abSrjs *
208c2654abSrjs * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
218c2654abSrjs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
228c2654abSrjs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
238c2654abSrjs * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
248c2654abSrjs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
258c2654abSrjs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
268c2654abSrjs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
278c2654abSrjs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
288c2654abSrjs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
298c2654abSrjs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
308c2654abSrjs * SUCH DAMAGE.
318c2654abSrjs */
328c2654abSrjs
338c2654abSrjs #include <sys/cdefs.h>
34*481d3881Srin __KERNEL_RCSID(0, "$NetBSD: sctp_input.c,v 1.18 2024/07/05 04:31:54 rin Exp $");
358c2654abSrjs
368c2654abSrjs #ifdef _KERNEL_OPT
378c2654abSrjs #include "opt_ipsec.h"
388c2654abSrjs #include "opt_inet.h"
398c2654abSrjs #include "opt_sctp.h"
408c2654abSrjs #endif /* _KERNEL_OPT */
418c2654abSrjs
428c2654abSrjs #include <sys/param.h>
438c2654abSrjs #include <sys/systm.h>
448c2654abSrjs #include <sys/malloc.h>
458c2654abSrjs #include <sys/mbuf.h>
468c2654abSrjs #include <sys/socket.h>
478c2654abSrjs #include <sys/socketvar.h>
488c2654abSrjs #include <sys/sysctl.h>
498c2654abSrjs #include <sys/domain.h>
508c2654abSrjs #include <sys/protosw.h>
518c2654abSrjs #include <sys/kernel.h>
528c2654abSrjs #include <sys/errno.h>
538c2654abSrjs #include <sys/syslog.h>
548c2654abSrjs
558c2654abSrjs #include <machine/limits.h>
568c2654abSrjs #include <machine/cpu.h>
578c2654abSrjs
588c2654abSrjs #include <net/if.h>
598c2654abSrjs #include <net/route.h>
608c2654abSrjs #include <net/if_types.h>
618c2654abSrjs
628c2654abSrjs #include <netinet/in.h>
638c2654abSrjs #include <netinet/in_systm.h>
648c2654abSrjs #include <netinet/ip.h>
658c2654abSrjs #include <netinet/in_pcb.h>
668c2654abSrjs #include <netinet/in_var.h>
678c2654abSrjs #include <netinet/ip_var.h>
688c2654abSrjs
698c2654abSrjs #ifdef INET6
708c2654abSrjs #include <netinet/ip6.h>
718c2654abSrjs #include <netinet6/ip6_var.h>
728c2654abSrjs #endif /* INET6 */
738c2654abSrjs
748c2654abSrjs #include <netinet/ip_icmp.h>
758c2654abSrjs #include <netinet/icmp_var.h>
768c2654abSrjs #include <netinet/sctp_var.h>
778c2654abSrjs #include <netinet/sctp_pcb.h>
788c2654abSrjs #include <netinet/sctp_header.h>
798c2654abSrjs #include <netinet/sctputil.h>
808c2654abSrjs #include <netinet/sctp_output.h>
818c2654abSrjs #include <netinet/sctp_input.h>
828c2654abSrjs #include <netinet/sctp_hashdriver.h>
838c2654abSrjs #include <netinet/sctp_indata.h>
848c2654abSrjs #include <netinet/sctp_asconf.h>
858c2654abSrjs
868c2654abSrjs #ifdef IPSEC
87505ea976Srjs #include <netipsec/ipsec.h>
88505ea976Srjs #include <netipsec/key.h>
898c2654abSrjs #endif /*IPSEC*/
908c2654abSrjs
918c2654abSrjs #ifdef SCTP_DEBUG
928c2654abSrjs extern u_int32_t sctp_debug_on;
938c2654abSrjs #endif
948c2654abSrjs
958c2654abSrjs /* INIT handler */
968c2654abSrjs static void
sctp_handle_init(struct mbuf * m,int iphlen,int offset,struct sctphdr * sh,struct sctp_init_chunk * cp,struct sctp_inpcb * inp,struct sctp_tcb * stcb,struct sctp_nets * net)978c2654abSrjs sctp_handle_init(struct mbuf *m, int iphlen, int offset,
988c2654abSrjs struct sctphdr *sh, struct sctp_init_chunk *cp, struct sctp_inpcb *inp,
998c2654abSrjs struct sctp_tcb *stcb, struct sctp_nets *net)
1008c2654abSrjs {
1018c2654abSrjs struct sctp_init *init;
1028c2654abSrjs struct mbuf *op_err;
1038c2654abSrjs #ifdef SCTP_DEBUG
1048c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
1058c2654abSrjs printf("sctp_handle_init: handling INIT tcb:%p\n", stcb);
1068c2654abSrjs }
1078c2654abSrjs #endif
1088c2654abSrjs op_err = NULL;
1098c2654abSrjs init = &cp->init;
1108c2654abSrjs /* First are we accepting? */
1118c2654abSrjs if (((inp->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING) == 0) ||
1128c2654abSrjs (inp->sctp_socket->so_qlimit == 0)) {
1138c2654abSrjs sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
1148c2654abSrjs return;
1158c2654abSrjs }
1168c2654abSrjs if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_chunk)) {
1178c2654abSrjs /* Invalid length */
1188c2654abSrjs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
1198c2654abSrjs sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
1208c2654abSrjs return;
1218c2654abSrjs }
1228c2654abSrjs /* validate parameters */
1238c2654abSrjs if (init->initiate_tag == 0) {
1248c2654abSrjs /* protocol error... send abort */
1258c2654abSrjs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
1268c2654abSrjs sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
1278c2654abSrjs return;
1288c2654abSrjs }
1298c2654abSrjs if (ntohl(init->a_rwnd) < SCTP_MIN_RWND) {
1308c2654abSrjs /* invalid parameter... send abort */
1318c2654abSrjs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
1328c2654abSrjs sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
1338c2654abSrjs return;
1348c2654abSrjs }
1358c2654abSrjs if (init->num_inbound_streams == 0) {
1368c2654abSrjs /* protocol error... send abort */
1378c2654abSrjs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
1388c2654abSrjs sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
1398c2654abSrjs return;
1408c2654abSrjs }
1418c2654abSrjs if (init->num_outbound_streams == 0) {
1428c2654abSrjs /* protocol error... send abort */
1438c2654abSrjs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
1448c2654abSrjs sctp_abort_association(inp, stcb, m, iphlen, sh, op_err);
1458c2654abSrjs return;
1468c2654abSrjs }
1478c2654abSrjs
1488c2654abSrjs /* send an INIT-ACK w/cookie */
1498c2654abSrjs #ifdef SCTP_DEBUG
1508c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
1518c2654abSrjs printf("sctp_handle_init: sending INIT-ACK\n");
1528c2654abSrjs }
1538c2654abSrjs #endif
1548c2654abSrjs
1558c2654abSrjs sctp_send_initiate_ack(inp, stcb, m, iphlen, offset, sh, cp);
1568c2654abSrjs }
1578c2654abSrjs
1588c2654abSrjs /*
1598c2654abSrjs * process peer "INIT/INIT-ACK" chunk
1608c2654abSrjs * returns value < 0 on error
1618c2654abSrjs */
1628c2654abSrjs
1638c2654abSrjs static int
sctp_process_init(struct sctp_init_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)1648c2654abSrjs sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb,
1658c2654abSrjs struct sctp_nets *net)
1668c2654abSrjs {
1678c2654abSrjs struct sctp_init *init;
1688c2654abSrjs struct sctp_association *asoc;
1698c2654abSrjs struct sctp_nets *lnet;
1708c2654abSrjs unsigned int i;
1718c2654abSrjs
1728c2654abSrjs init = &cp->init;
1738c2654abSrjs asoc = &stcb->asoc;
1748c2654abSrjs /* save off parameters */
1758c2654abSrjs asoc->peer_vtag = ntohl(init->initiate_tag);
1768c2654abSrjs asoc->peers_rwnd = ntohl(init->a_rwnd);
1778c2654abSrjs
1788c2654abSrjs if (TAILQ_FIRST(&asoc->nets)) {
1798c2654abSrjs /* update any ssthresh's that may have a default */
1808c2654abSrjs TAILQ_FOREACH(lnet, &asoc->nets, sctp_next) {
1818c2654abSrjs lnet->ssthresh = asoc->peers_rwnd;
1828c2654abSrjs }
1838c2654abSrjs }
1848c2654abSrjs if (asoc->pre_open_streams > ntohs(init->num_inbound_streams)) {
1858c2654abSrjs unsigned int newcnt;
1868c2654abSrjs struct sctp_stream_out *outs;
1878c2654abSrjs struct sctp_tmit_chunk *chk;
1888c2654abSrjs
1898c2654abSrjs /* cut back on number of streams */
1908c2654abSrjs newcnt = ntohs(init->num_inbound_streams);
1918c2654abSrjs /* This if is probably not needed but I am cautious */
1928c2654abSrjs if (asoc->strmout) {
1938c2654abSrjs /* First make sure no data chunks are trapped */
1948c2654abSrjs for (i=newcnt; i < asoc->pre_open_streams; i++) {
1958c2654abSrjs outs = &asoc->strmout[i];
1968c2654abSrjs chk = TAILQ_FIRST(&outs->outqueue);
1978c2654abSrjs while (chk) {
1988c2654abSrjs TAILQ_REMOVE(&outs->outqueue, chk,
1998c2654abSrjs sctp_next);
2008c2654abSrjs asoc->stream_queue_cnt--;
2018c2654abSrjs sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL,
2028c2654abSrjs stcb, SCTP_NOTIFY_DATAGRAM_UNSENT,
2038c2654abSrjs chk);
2048c2654abSrjs sctp_m_freem(chk->data);
2058c2654abSrjs chk->data = NULL;
2068c2654abSrjs sctp_free_remote_addr(chk->whoTo);
2078c2654abSrjs chk->whoTo = NULL;
2088c2654abSrjs chk->asoc = NULL;
2098c2654abSrjs /* Free the chunk */
2108c2654abSrjs SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
2118c2654abSrjs sctppcbinfo.ipi_count_chunk--;
2128c2654abSrjs if ((int)sctppcbinfo.ipi_count_chunk < 0) {
2138c2654abSrjs panic("Chunk count is negative");
2148c2654abSrjs }
2158c2654abSrjs sctppcbinfo.ipi_gencnt_chunk++;
2168c2654abSrjs chk = TAILQ_FIRST(&outs->outqueue);
2178c2654abSrjs }
2188c2654abSrjs }
2198c2654abSrjs }
2208c2654abSrjs /* cut back the count and abandon the upper streams */
2218c2654abSrjs asoc->pre_open_streams = newcnt;
2228c2654abSrjs }
2238c2654abSrjs asoc->streamincnt = ntohs(init->num_outbound_streams);
2248c2654abSrjs if (asoc->streamincnt > MAX_SCTP_STREAMS) {
2258c2654abSrjs asoc->streamincnt = MAX_SCTP_STREAMS;
2268c2654abSrjs }
2278c2654abSrjs
2288c2654abSrjs asoc->streamoutcnt = asoc->pre_open_streams;
2298c2654abSrjs /* init tsn's */
2308c2654abSrjs asoc->highest_tsn_inside_map = asoc->asconf_seq_in = ntohl(init->initial_tsn) - 1;
2318c2654abSrjs #ifdef SCTP_MAP_LOGGING
2328c2654abSrjs sctp_log_map(0, 5, asoc->highest_tsn_inside_map, SCTP_MAP_SLIDE_RESULT);
2338c2654abSrjs #endif
2348c2654abSrjs /* This is the next one we expect */
2358c2654abSrjs asoc->str_reset_seq_in = asoc->asconf_seq_in + 1;
2368c2654abSrjs
2378c2654abSrjs asoc->mapping_array_base_tsn = ntohl(init->initial_tsn);
2388c2654abSrjs asoc->cumulative_tsn = asoc->asconf_seq_in;
2398c2654abSrjs asoc->last_echo_tsn = asoc->asconf_seq_in;
2408c2654abSrjs asoc->advanced_peer_ack_point = asoc->last_acked_seq;
2418c2654abSrjs /* open the requested streams */
2428c2654abSrjs if (asoc->strmin != NULL) {
2438c2654abSrjs /* Free the old ones */
2448c2654abSrjs free(asoc->strmin, M_PCB);
2458c2654abSrjs }
2468c2654abSrjs asoc->strmin = malloc(asoc->streamincnt * sizeof(struct sctp_stream_in),
2478c2654abSrjs M_PCB, M_NOWAIT);
2488c2654abSrjs if (asoc->strmin == NULL) {
2498c2654abSrjs /* we didn't get memory for the streams! */
2508c2654abSrjs #ifdef SCTP_DEBUG
2518c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
2528c2654abSrjs printf("process_init: couldn't get memory for the streams!\n");
2538c2654abSrjs }
2548c2654abSrjs #endif
2558c2654abSrjs return (-1);
2568c2654abSrjs }
2578c2654abSrjs for (i = 0; i < asoc->streamincnt; i++) {
2588c2654abSrjs asoc->strmin[i].stream_no = i;
2598c2654abSrjs asoc->strmin[i].last_sequence_delivered = 0xffff;
2608c2654abSrjs /*
2618c2654abSrjs * U-stream ranges will be set when the cookie
2628c2654abSrjs * is unpacked. Or for the INIT sender they
2638c2654abSrjs * are un set (if pr-sctp not supported) when the
2648c2654abSrjs * INIT-ACK arrives.
2658c2654abSrjs */
2668c2654abSrjs TAILQ_INIT(&asoc->strmin[i].inqueue);
2678c2654abSrjs /*
2688c2654abSrjs * we are not on any wheel, pr-sctp streams
2698c2654abSrjs * will go on the wheel when they have data waiting
2708c2654abSrjs * for reorder.
2718c2654abSrjs */
2728c2654abSrjs asoc->strmin[i].next_spoke.tqe_next = 0;
2738c2654abSrjs asoc->strmin[i].next_spoke.tqe_prev = 0;
2748c2654abSrjs }
2758c2654abSrjs
2768c2654abSrjs /*
2778c2654abSrjs * load_address_from_init will put the addresses into the
2788c2654abSrjs * association when the COOKIE is processed or the INIT-ACK
2798c2654abSrjs * is processed. Both types of COOKIE's existing and new
2808c2654abSrjs * call this routine. It will remove addresses that
2818c2654abSrjs * are no longer in the association (for the restarting
2828c2654abSrjs * case where addresses are removed). Up front when the
2838c2654abSrjs * INIT arrives we will discard it if it is a restart
2848c2654abSrjs * and new addresses have been added.
2858c2654abSrjs */
2868c2654abSrjs return (0);
2878c2654abSrjs }
2888c2654abSrjs
2898c2654abSrjs /*
2908c2654abSrjs * INIT-ACK message processing/consumption
2918c2654abSrjs * returns value < 0 on error
2928c2654abSrjs */
2938c2654abSrjs static int
sctp_process_init_ack(struct mbuf * m,int iphlen,int offset,struct sctphdr * sh,struct sctp_init_ack_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)2948c2654abSrjs sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
2958c2654abSrjs struct sctphdr *sh, struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb,
2968c2654abSrjs struct sctp_nets *net)
2978c2654abSrjs {
2988c2654abSrjs struct sctp_association *asoc;
2998c2654abSrjs struct mbuf *op_err;
3008c2654abSrjs int retval, abort_flag;
3018c2654abSrjs uint32_t initack_limit;
3028c2654abSrjs /* First verify that we have no illegal param's */
3038c2654abSrjs abort_flag = 0;
3048c2654abSrjs op_err = NULL;
3058c2654abSrjs
3068c2654abSrjs op_err = sctp_arethere_unrecognized_parameters(m,
3078c2654abSrjs (offset+sizeof(struct sctp_init_chunk)) ,
3088c2654abSrjs &abort_flag, (struct sctp_chunkhdr *)cp);
3098c2654abSrjs if (abort_flag) {
3108c2654abSrjs /* Send an abort and notify peer */
3118c2654abSrjs if (op_err != NULL) {
3128c2654abSrjs sctp_send_operr_to(m, iphlen, op_err, cp->init.initiate_tag);
3138c2654abSrjs } else {
3148c2654abSrjs /*
3158c2654abSrjs * Just notify (abort_assoc does this if
3168c2654abSrjs * we send an abort).
3178c2654abSrjs */
3188c2654abSrjs sctp_abort_notification(stcb, 0);
3198c2654abSrjs /*
3208c2654abSrjs * No sense in further INIT's since
3218c2654abSrjs * we will get the same param back
3228c2654abSrjs */
3238c2654abSrjs sctp_free_assoc(stcb->sctp_ep, stcb);
3248c2654abSrjs }
3258c2654abSrjs return (-1);
3268c2654abSrjs }
3278c2654abSrjs asoc = &stcb->asoc;
3288c2654abSrjs /* process the peer's parameters in the INIT-ACK */
3298c2654abSrjs retval = sctp_process_init((struct sctp_init_chunk *)cp, stcb, net);
3308c2654abSrjs if (retval < 0) {
3318c2654abSrjs return (retval);
3328c2654abSrjs }
3338c2654abSrjs
3348c2654abSrjs initack_limit = offset + ntohs(cp->ch.chunk_length);
3358c2654abSrjs /* load all addresses */
3368c2654abSrjs if (sctp_load_addresses_from_init(stcb, m, iphlen,
3378c2654abSrjs (offset + sizeof(struct sctp_init_chunk)), initack_limit, sh,
3388c2654abSrjs NULL)) {
3398c2654abSrjs /* Huh, we should abort */
3408c2654abSrjs sctp_abort_notification(stcb, 0);
3418c2654abSrjs sctp_free_assoc(stcb->sctp_ep, stcb);
3428c2654abSrjs return (-1);
3438c2654abSrjs }
3448c2654abSrjs if (op_err) {
3458c2654abSrjs sctp_queue_op_err(stcb, op_err);
3468c2654abSrjs /* queuing will steal away the mbuf chain to the out queue */
3478c2654abSrjs op_err = NULL;
3488c2654abSrjs }
3498c2654abSrjs /* extract the cookie and queue it to "echo" it back... */
3508c2654abSrjs stcb->asoc.overall_error_count = 0;
3518c2654abSrjs net->error_count = 0;
3528c2654abSrjs retval = sctp_send_cookie_echo(m, offset, stcb, net);
3538c2654abSrjs if (retval < 0) {
3548c2654abSrjs /*
3558c2654abSrjs * No cookie, we probably should send a op error.
3568c2654abSrjs * But in any case if there is no cookie in the INIT-ACK,
3578c2654abSrjs * we can abandon the peer, its broke.
3588c2654abSrjs */
3598c2654abSrjs if (retval == -3) {
3608c2654abSrjs /* We abort with an error of missing mandatory param */
3618c2654abSrjs op_err =
3628c2654abSrjs sctp_generate_invmanparam(SCTP_CAUSE_MISS_PARAM);
3638c2654abSrjs if (op_err) {
3648c2654abSrjs /*
3658c2654abSrjs * Expand beyond to include the mandatory
3668c2654abSrjs * param cookie
3678c2654abSrjs */
3688c2654abSrjs struct sctp_inv_mandatory_param *mp;
3698c2654abSrjs op_err->m_len =
3708c2654abSrjs sizeof(struct sctp_inv_mandatory_param);
3718c2654abSrjs mp = mtod(op_err,
3728c2654abSrjs struct sctp_inv_mandatory_param *);
3738c2654abSrjs /* Subtract the reserved param */
3748c2654abSrjs mp->length =
3758c2654abSrjs htons(sizeof(struct sctp_inv_mandatory_param) - 2);
3768c2654abSrjs mp->num_param = htonl(1);
3778c2654abSrjs mp->param = htons(SCTP_STATE_COOKIE);
3788c2654abSrjs mp->resv = 0;
3798c2654abSrjs }
3808c2654abSrjs sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen,
3818c2654abSrjs sh, op_err);
3828c2654abSrjs }
3838c2654abSrjs return (retval);
3848c2654abSrjs }
3858c2654abSrjs
3868c2654abSrjs /*
3878c2654abSrjs * Cancel the INIT timer, We do this first before queueing
388a136e22aSandvar * the cookie. We always cancel at the primary to assume that
38934908c48Sandvar * we are cancelling the timer started by the INIT which always
3908c2654abSrjs * goes to the primary.
3918c2654abSrjs */
3928c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep, stcb,
3938c2654abSrjs asoc->primary_destination);
3948c2654abSrjs
3958c2654abSrjs /* calculate the RTO */
3968c2654abSrjs net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered);
3978c2654abSrjs
3988c2654abSrjs return (0);
3998c2654abSrjs }
4008c2654abSrjs
4018c2654abSrjs static void
sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)4028c2654abSrjs sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
4038c2654abSrjs struct sctp_tcb *stcb, struct sctp_nets *net)
4048c2654abSrjs {
4058c2654abSrjs struct sockaddr_storage store;
4068c2654abSrjs struct sockaddr_in *sin;
4078c2654abSrjs struct sockaddr_in6 *sin6;
4088c2654abSrjs struct sctp_nets *r_net;
4098c2654abSrjs struct timeval tv;
4108c2654abSrjs
4118c2654abSrjs if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_heartbeat_chunk)) {
4128c2654abSrjs /* Invalid length */
4138c2654abSrjs return;
4148c2654abSrjs }
4158c2654abSrjs
4168c2654abSrjs sin = (struct sockaddr_in *)&store;
4178c2654abSrjs sin6 = (struct sockaddr_in6 *)&store;
4188c2654abSrjs
4198c2654abSrjs memset(&store, 0, sizeof(store));
4208c2654abSrjs if (cp->heartbeat.hb_info.addr_family == AF_INET &&
4218c2654abSrjs cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in)) {
4228c2654abSrjs sin->sin_family = cp->heartbeat.hb_info.addr_family;
4238c2654abSrjs sin->sin_len = cp->heartbeat.hb_info.addr_len;
4248c2654abSrjs sin->sin_port = stcb->rport;
4258c2654abSrjs memcpy(&sin->sin_addr, cp->heartbeat.hb_info.address,
4268c2654abSrjs sizeof(sin->sin_addr));
4278c2654abSrjs } else if (cp->heartbeat.hb_info.addr_family == AF_INET6 &&
4288c2654abSrjs cp->heartbeat.hb_info.addr_len == sizeof(struct sockaddr_in6)) {
4298c2654abSrjs sin6->sin6_family = cp->heartbeat.hb_info.addr_family;
4308c2654abSrjs sin6->sin6_len = cp->heartbeat.hb_info.addr_len;
4318c2654abSrjs sin6->sin6_port = stcb->rport;
4328c2654abSrjs memcpy(&sin6->sin6_addr, cp->heartbeat.hb_info.address,
4338c2654abSrjs sizeof(sin6->sin6_addr));
4348c2654abSrjs } else {
4358c2654abSrjs #ifdef SCTP_DEBUG
4368c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
4378c2654abSrjs printf("unsupported address family");
4388c2654abSrjs }
4398c2654abSrjs #endif
4408c2654abSrjs return;
4418c2654abSrjs }
4428c2654abSrjs r_net = sctp_findnet(stcb, (struct sockaddr *)sin);
4438c2654abSrjs if (r_net == NULL) {
4448c2654abSrjs #ifdef SCTP_DEBUG
4458c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
4468c2654abSrjs printf("Huh? I can't find the address I sent it to, discard\n");
4478c2654abSrjs }
4488c2654abSrjs #endif
4498c2654abSrjs return;
4508c2654abSrjs }
4518c2654abSrjs if ((r_net && (r_net->dest_state & SCTP_ADDR_UNCONFIRMED)) &&
4528c2654abSrjs (r_net->heartbeat_random1 == cp->heartbeat.hb_info.random_value1) &&
4538c2654abSrjs (r_net->heartbeat_random2 == cp->heartbeat.hb_info.random_value2)) {
4548c2654abSrjs /*
4558c2654abSrjs * If the its a HB and it's random value is correct when
4568c2654abSrjs * can confirm the destination.
4578c2654abSrjs */
4588c2654abSrjs r_net->dest_state &= ~SCTP_ADDR_UNCONFIRMED;
4598c2654abSrjs sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
4608c2654abSrjs stcb, 0, (void *)r_net);
4618c2654abSrjs }
4628c2654abSrjs r_net->error_count = 0;
4638c2654abSrjs r_net->hb_responded = 1;
4648c2654abSrjs tv.tv_sec = cp->heartbeat.hb_info.time_value_1;
4658c2654abSrjs tv.tv_usec = cp->heartbeat.hb_info.time_value_2;
4668c2654abSrjs if (r_net->dest_state & SCTP_ADDR_NOT_REACHABLE) {
4678c2654abSrjs r_net->dest_state = SCTP_ADDR_REACHABLE;
4688c2654abSrjs sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb,
4698c2654abSrjs SCTP_HEARTBEAT_SUCCESS, (void *)r_net);
4708c2654abSrjs
4718c2654abSrjs /* now was it the primary? if so restore */
4728c2654abSrjs if (r_net->dest_state & SCTP_ADDR_WAS_PRIMARY) {
4738c2654abSrjs sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, r_net);
4748c2654abSrjs }
4758c2654abSrjs }
4768c2654abSrjs /* Now lets do a RTO with this */
4778c2654abSrjs r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv);
4788c2654abSrjs }
4798c2654abSrjs
4808c2654abSrjs static void
sctp_handle_abort(struct sctp_abort_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)4818c2654abSrjs sctp_handle_abort(struct sctp_abort_chunk *cp,
4828c2654abSrjs struct sctp_tcb *stcb, struct sctp_nets *net)
4838c2654abSrjs {
4848c2654abSrjs
4858c2654abSrjs #ifdef SCTP_DEBUG
4868c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
4878c2654abSrjs printf("sctp_handle_abort: handling ABORT\n");
4888c2654abSrjs }
4898c2654abSrjs #endif
4908c2654abSrjs if (stcb == NULL)
4918c2654abSrjs return;
4928c2654abSrjs /* verify that the destination addr is in the association */
4938c2654abSrjs /* ignore abort for addresses being deleted */
4948c2654abSrjs
4958c2654abSrjs /* stop any receive timers */
4968c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, net);
4978c2654abSrjs /* notify user of the abort and clean up... */
4988c2654abSrjs sctp_abort_notification(stcb, 0);
4998c2654abSrjs /* free the tcb */
5008c2654abSrjs sctp_free_assoc(stcb->sctp_ep, stcb);
5018c2654abSrjs #ifdef SCTP_DEBUG
5028c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
5038c2654abSrjs printf("sctp_handle_abort: finished\n");
5048c2654abSrjs }
5058c2654abSrjs #endif
5068c2654abSrjs }
5078c2654abSrjs
5088c2654abSrjs static void
sctp_handle_shutdown(struct sctp_shutdown_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net,int * abort_flag)5098c2654abSrjs sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
5108c2654abSrjs struct sctp_tcb *stcb, struct sctp_nets *net, int *abort_flag)
5118c2654abSrjs {
5128c2654abSrjs struct sctp_association *asoc;
5138c2654abSrjs int some_on_streamwheel;
5148c2654abSrjs
5158c2654abSrjs #ifdef SCTP_DEBUG
5168c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
5178c2654abSrjs printf("sctp_handle_shutdown: handling SHUTDOWN\n");
5188c2654abSrjs }
5198c2654abSrjs #endif
5208c2654abSrjs if (stcb == NULL)
5218c2654abSrjs return;
5228c2654abSrjs
5238c2654abSrjs if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_WAIT) ||
5248c2654abSrjs (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
5258c2654abSrjs return;
5268c2654abSrjs }
5278c2654abSrjs
5288c2654abSrjs if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_shutdown_chunk)) {
5298c2654abSrjs /* update current data status */
5308c2654abSrjs #ifdef SCTP_DEBUG
5318c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
5328c2654abSrjs printf("Warning Shutdown NOT the expected size.. skipping (%d:%d)\n",
5338c2654abSrjs ntohs(cp->ch.chunk_length),
5348c2654abSrjs (int)sizeof(struct sctp_shutdown_chunk));
5358c2654abSrjs }
5368c2654abSrjs #endif
5378c2654abSrjs return;
5388c2654abSrjs } else {
5398c2654abSrjs sctp_update_acked(stcb, cp, net, abort_flag);
5408c2654abSrjs }
5418c2654abSrjs asoc = &stcb->asoc;
5428c2654abSrjs /* goto SHUTDOWN_RECEIVED state to block new requests */
5438c2654abSrjs if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
5448c2654abSrjs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT)) {
5458c2654abSrjs asoc->state = SCTP_STATE_SHUTDOWN_RECEIVED;
5468c2654abSrjs #ifdef SCTP_DEBUG
5478c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
5488c2654abSrjs printf("Moving to SHUTDOWN-RECEIVED state\n");
5498c2654abSrjs }
5508c2654abSrjs #endif
5518c2654abSrjs /* notify upper layer that peer has initiated a shutdown */
5528c2654abSrjs sctp_ulp_notify(SCTP_NOTIFY_PEER_SHUTDOWN, stcb, 0, NULL);
5538c2654abSrjs
5548c2654abSrjs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5558c2654abSrjs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
5568c2654abSrjs
5578c2654abSrjs /* Set the flag so we cannot send more, we
5588c2654abSrjs * would call the function but we don't want to
5598c2654abSrjs * wake up the ulp necessarily.
5608c2654abSrjs */
5618c2654abSrjs #if defined(__FreeBSD__) && __FreeBSD_version >= 502115
5628c2654abSrjs stcb->sctp_ep->sctp_socket->so_rcv.sb_state |= SBS_CANTSENDMORE;
5638c2654abSrjs #else
5648c2654abSrjs stcb->sctp_ep->sctp_socket->so_state |= SS_CANTSENDMORE;
5658c2654abSrjs #endif
5668c2654abSrjs }
5678c2654abSrjs /* reset time */
5688c2654abSrjs SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
5698c2654abSrjs }
5708c2654abSrjs if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_SENT) {
5718c2654abSrjs /*
5728c2654abSrjs * stop the shutdown timer, since we WILL move
5738c2654abSrjs * to SHUTDOWN-ACK-SENT.
5748c2654abSrjs */
5758c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net);
5768c2654abSrjs }
5778c2654abSrjs /* Now are we there yet? */
5788c2654abSrjs some_on_streamwheel = 0;
5798c2654abSrjs if (!TAILQ_EMPTY(&asoc->out_wheel)) {
5808c2654abSrjs /* Check to see if some data queued */
5818c2654abSrjs struct sctp_stream_out *outs;
5828c2654abSrjs TAILQ_FOREACH(outs, &asoc->out_wheel, next_spoke) {
5838c2654abSrjs if (!TAILQ_EMPTY(&outs->outqueue)) {
5848c2654abSrjs some_on_streamwheel = 1;
5858c2654abSrjs break;
5868c2654abSrjs }
5878c2654abSrjs }
5888c2654abSrjs }
5898c2654abSrjs #ifdef SCTP_DEBUG
5908c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
5918c2654abSrjs printf("some_on_streamwheel:%d send_q_empty:%d sent_q_empty:%d\n",
5928c2654abSrjs some_on_streamwheel,
5938c2654abSrjs !TAILQ_EMPTY(&asoc->send_queue),
5948c2654abSrjs !TAILQ_EMPTY(&asoc->sent_queue));
5958c2654abSrjs }
5968c2654abSrjs #endif
5978c2654abSrjs if (!TAILQ_EMPTY(&asoc->send_queue) ||
5988c2654abSrjs !TAILQ_EMPTY(&asoc->sent_queue) ||
5998c2654abSrjs some_on_streamwheel) {
6008c2654abSrjs /* By returning we will push more data out */
6018c2654abSrjs return;
6028c2654abSrjs } else {
6038c2654abSrjs /* no outstanding data to send, so move on... */
6048c2654abSrjs /* send SHUTDOWN-ACK */
6058c2654abSrjs sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination);
6068c2654abSrjs /* move to SHUTDOWN-ACK-SENT state */
6078c2654abSrjs asoc->state = SCTP_STATE_SHUTDOWN_ACK_SENT;
6088c2654abSrjs #ifdef SCTP_DEBUG
6098c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
6108c2654abSrjs printf("moving to SHUTDOWN_ACK state\n");
6118c2654abSrjs }
6128c2654abSrjs #endif
6138c2654abSrjs /* start SHUTDOWN timer */
6148c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNACK, stcb->sctp_ep,
6158c2654abSrjs stcb, net);
6168c2654abSrjs }
6178c2654abSrjs }
6188c2654abSrjs
6198c2654abSrjs static void
sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)6208c2654abSrjs sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp,
6218c2654abSrjs struct sctp_tcb *stcb, struct sctp_nets *net)
6228c2654abSrjs {
6238c2654abSrjs struct sctp_association *asoc;
6248c2654abSrjs
6258c2654abSrjs #ifdef SCTP_DEBUG
6268c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
6278c2654abSrjs printf("sctp_handle_shutdown_ack: handling SHUTDOWN ACK\n");
6288c2654abSrjs }
6298c2654abSrjs #endif
6308c2654abSrjs if (stcb == NULL)
6318c2654abSrjs return;
6328c2654abSrjs
6338c2654abSrjs asoc = &stcb->asoc;
6348c2654abSrjs /* process according to association state */
6358c2654abSrjs if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
6368c2654abSrjs (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
6378c2654abSrjs /* unexpected SHUTDOWN-ACK... so ignore... */
6388c2654abSrjs return;
6398c2654abSrjs }
6408c2654abSrjs /* are the queues empty? */
6418c2654abSrjs if (!TAILQ_EMPTY(&asoc->send_queue) ||
6428c2654abSrjs !TAILQ_EMPTY(&asoc->sent_queue) ||
6438c2654abSrjs !TAILQ_EMPTY(&asoc->out_wheel)) {
6448c2654abSrjs sctp_report_all_outbound(stcb);
6458c2654abSrjs }
6468c2654abSrjs /* stop the timer */
6478c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net);
6488c2654abSrjs /* send SHUTDOWN-COMPLETE */
6498c2654abSrjs sctp_send_shutdown_complete(stcb, net);
6508c2654abSrjs /* notify upper layer protocol */
6518c2654abSrjs sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL);
6528c2654abSrjs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6538c2654abSrjs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
6548c2654abSrjs stcb->sctp_ep->sctp_flags &= ~SCTP_PCB_FLAGS_CONNECTED;
6558c2654abSrjs /* Set the connected flag to disconnected */
6568c2654abSrjs stcb->sctp_ep->sctp_socket->so_snd.sb_cc = 0;
6578c2654abSrjs stcb->sctp_ep->sctp_socket->so_snd.sb_mbcnt = 0;
6588c2654abSrjs soisdisconnected(stcb->sctp_ep->sctp_socket);
6598c2654abSrjs }
6608c2654abSrjs /* free the TCB but first save off the ep */
6618c2654abSrjs sctp_free_assoc(stcb->sctp_ep, stcb);
6628c2654abSrjs }
6638c2654abSrjs
6648c2654abSrjs /*
6658c2654abSrjs * Skip past the param header and then we will find the chunk that
6668c2654abSrjs * caused the problem. There are two possiblities ASCONF or FWD-TSN
6678c2654abSrjs * other than that and our peer must be broken.
6688c2654abSrjs */
6698c2654abSrjs static void
sctp_process_unrecog_chunk(struct sctp_tcb * stcb,struct sctp_paramhdr * phdr,struct sctp_nets * net)6708c2654abSrjs sctp_process_unrecog_chunk(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr,
6718c2654abSrjs struct sctp_nets *net)
6728c2654abSrjs {
6738c2654abSrjs struct sctp_chunkhdr *chk;
6748c2654abSrjs
6758c2654abSrjs chk = (struct sctp_chunkhdr *)((vaddr_t)phdr + sizeof(*phdr));
6768c2654abSrjs switch (chk->chunk_type) {
6778c2654abSrjs case SCTP_ASCONF_ACK:
6788c2654abSrjs #ifdef SCTP_DEBUG
6798c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
6808c2654abSrjs printf("Strange peer, snds ASCONF but does not recongnize asconf-ack?\n");
6818c2654abSrjs }
6828c2654abSrjs #endif
683a14ed5aeSkamil /* FALLTHROUGH */
6848c2654abSrjs case SCTP_ASCONF:
6858c2654abSrjs #ifdef SCTP_DEBUG
6868c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
6878c2654abSrjs printf("Peer does not support ASCONF/ASCONF-ACK chunks\n");
6888c2654abSrjs }
6898c2654abSrjs #endif /* SCTP_DEBUG */
6908c2654abSrjs sctp_asconf_cleanup(stcb, net);
6918c2654abSrjs break;
6928c2654abSrjs case SCTP_FORWARD_CUM_TSN:
6938c2654abSrjs stcb->asoc.peer_supports_prsctp = 0;
6948c2654abSrjs break;
6958c2654abSrjs default:
6968c2654abSrjs #ifdef SCTP_DEBUG
6978c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
6988c2654abSrjs printf("Peer does not support chunk type %d(%x)??\n",
6998c2654abSrjs chk->chunk_type, (u_int)chk->chunk_type);
7008c2654abSrjs }
7018c2654abSrjs #endif
7028c2654abSrjs break;
7038c2654abSrjs }
7048c2654abSrjs }
7058c2654abSrjs
7068c2654abSrjs /*
7078c2654abSrjs * Skip past the param header and then we will find the param that
7088c2654abSrjs * caused the problem. There are a number of param's in a ASCONF
7098c2654abSrjs * OR the prsctp param these will turn of specific features.
7108c2654abSrjs */
7118c2654abSrjs static void
sctp_process_unrecog_param(struct sctp_tcb * stcb,struct sctp_paramhdr * phdr)7128c2654abSrjs sctp_process_unrecog_param(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr)
7138c2654abSrjs {
7148c2654abSrjs struct sctp_paramhdr *pbad;
7158c2654abSrjs
7168c2654abSrjs pbad = phdr + 1;
7178c2654abSrjs switch (ntohs(pbad->param_type)) {
7188c2654abSrjs /* pr-sctp draft */
7198c2654abSrjs case SCTP_PRSCTP_SUPPORTED:
7208c2654abSrjs stcb->asoc.peer_supports_prsctp = 0;
7218c2654abSrjs break;
7228c2654abSrjs case SCTP_SUPPORTED_CHUNK_EXT:
7238c2654abSrjs break;
7248c2654abSrjs /* draft-ietf-tsvwg-addip-sctp */
7258c2654abSrjs case SCTP_ECN_NONCE_SUPPORTED:
7268c2654abSrjs stcb->asoc.peer_supports_ecn_nonce = 0;
7278c2654abSrjs stcb->asoc.ecn_nonce_allowed = 0;
7288c2654abSrjs stcb->asoc.ecn_allowed = 0;
7298c2654abSrjs break;
7308c2654abSrjs case SCTP_ADD_IP_ADDRESS:
7318c2654abSrjs case SCTP_DEL_IP_ADDRESS:
7328c2654abSrjs stcb->asoc.peer_supports_asconf = 0;
7338c2654abSrjs break;
7348c2654abSrjs case SCTP_SET_PRIM_ADDR:
7358c2654abSrjs stcb->asoc.peer_supports_asconf_setprim = 0;
7368c2654abSrjs break;
7378c2654abSrjs case SCTP_SUCCESS_REPORT:
7388c2654abSrjs case SCTP_ERROR_CAUSE_IND:
7398c2654abSrjs #ifdef SCTP_DEBUG
7408c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
7418c2654abSrjs printf("Huh, the peer does not support success? or error cause?\n");
7428c2654abSrjs printf("Turning off ASCONF to this strange peer\n");
7438c2654abSrjs }
7448c2654abSrjs #endif
7458c2654abSrjs stcb->asoc.peer_supports_asconf = 0;
7468c2654abSrjs stcb->asoc.peer_supports_asconf_setprim = 0;
7478c2654abSrjs break;
7488c2654abSrjs default:
7498c2654abSrjs #ifdef SCTP_DEBUG
7508c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
7518c2654abSrjs printf("Peer does not support base param type %d(%x)??\n",
7528c2654abSrjs pbad->param_type, (u_int)pbad->param_type);
7538c2654abSrjs }
7548c2654abSrjs #endif
7558c2654abSrjs break;
7568c2654abSrjs }
7578c2654abSrjs }
7588c2654abSrjs
7598c2654abSrjs static int
sctp_handle_error(struct sctp_chunkhdr * ch,struct sctp_tcb * stcb,struct sctp_nets * net)7608c2654abSrjs sctp_handle_error(struct sctp_chunkhdr *ch,
7618c2654abSrjs struct sctp_tcb *stcb, struct sctp_nets *net)
7628c2654abSrjs {
7638c2654abSrjs int chklen;
7648c2654abSrjs struct sctp_paramhdr *phdr;
7658c2654abSrjs uint16_t error_type;
7668c2654abSrjs uint16_t error_len;
7678c2654abSrjs struct sctp_association *asoc;
7688c2654abSrjs
7698c2654abSrjs int adjust;
7708c2654abSrjs /* parse through all of the errors and process */
7718c2654abSrjs asoc = &stcb->asoc;
7728c2654abSrjs phdr = (struct sctp_paramhdr *)((vaddr_t)ch +
7738c2654abSrjs sizeof(struct sctp_chunkhdr));
7748c2654abSrjs chklen = ntohs(ch->chunk_length) - sizeof(struct sctp_chunkhdr);
7758c2654abSrjs while ((size_t)chklen >= sizeof(struct sctp_paramhdr)) {
7768c2654abSrjs /* Process an Error Cause */
7778c2654abSrjs error_type = ntohs(phdr->param_type);
7788c2654abSrjs error_len = ntohs(phdr->param_length);
7798c2654abSrjs if ((error_len > chklen) || (error_len == 0)) {
7808c2654abSrjs /* invalid param length for this param */
7818c2654abSrjs #ifdef SCTP_DEBUG
7828c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
7838c2654abSrjs printf("Bogus length in error param- chunk left:%d errorlen:%d\n",
7848c2654abSrjs chklen, error_len);
7858c2654abSrjs }
7868c2654abSrjs #endif /* SCTP_DEBUG */
7878c2654abSrjs return (0);
7888c2654abSrjs }
7898c2654abSrjs switch (error_type) {
7908c2654abSrjs case SCTP_CAUSE_INV_STRM:
7918c2654abSrjs case SCTP_CAUSE_MISS_PARAM:
7928c2654abSrjs case SCTP_CAUSE_INVALID_PARAM:
7938c2654abSrjs case SCTP_CAUSE_NOUSER_DATA:
7948c2654abSrjs #ifdef SCTP_DEBUG
7958c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
7968c2654abSrjs printf("Software error we got a %d back? We have a bug :/ (or do they?)\n",
7978c2654abSrjs error_type);
7988c2654abSrjs }
7998c2654abSrjs #endif
8008c2654abSrjs break;
8018c2654abSrjs case SCTP_CAUSE_STALE_COOKIE:
8028c2654abSrjs /* We only act if we have echoed a cookie and are waiting. */
8038c2654abSrjs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) {
8048c2654abSrjs int *p;
8058c2654abSrjs p = (int *)((vaddr_t)phdr + sizeof(*phdr));
8068c2654abSrjs /* Save the time doubled */
8078c2654abSrjs asoc->cookie_preserve_req = ntohl(*p) << 1;
8088c2654abSrjs asoc->stale_cookie_count++;
8098c2654abSrjs if (asoc->stale_cookie_count >
8108c2654abSrjs asoc->max_init_times) {
8118c2654abSrjs sctp_abort_notification(stcb, 0);
8128c2654abSrjs /* now free the asoc */
8138c2654abSrjs sctp_free_assoc(stcb->sctp_ep, stcb);
8148c2654abSrjs return (-1);
8158c2654abSrjs }
8168c2654abSrjs /* blast back to INIT state */
8178c2654abSrjs asoc->state &= ~SCTP_STATE_COOKIE_ECHOED;
8188c2654abSrjs asoc->state |= SCTP_STATE_COOKIE_WAIT;
8198c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE,
8208c2654abSrjs stcb->sctp_ep, stcb, net);
8218c2654abSrjs sctp_send_initiate(stcb->sctp_ep, stcb);
8228c2654abSrjs }
8238c2654abSrjs break;
8248c2654abSrjs case SCTP_CAUSE_UNRESOLV_ADDR:
8258c2654abSrjs /*
8268c2654abSrjs * Nothing we can do here, we don't do hostname
8278c2654abSrjs * addresses so if the peer does not like my IPv6 (or
8288c2654abSrjs * IPv4 for that matter) it does not matter. If they
8298c2654abSrjs * don't support that type of address, they can NOT
8308c2654abSrjs * possibly get that packet type... i.e. with no IPv6
83139c3181aSmsaitoh * you can't receive a IPv6 packet. so we can safely
8328c2654abSrjs * ignore this one. If we ever added support for
8338c2654abSrjs * HOSTNAME Addresses, then we would need to do
8348c2654abSrjs * something here.
8358c2654abSrjs */
8368c2654abSrjs break;
8378c2654abSrjs case SCTP_CAUSE_UNRECOG_CHUNK:
8388c2654abSrjs sctp_process_unrecog_chunk(stcb, phdr, net);
8398c2654abSrjs break;
8408c2654abSrjs case SCTP_CAUSE_UNRECOG_PARAM:
8418c2654abSrjs sctp_process_unrecog_param(stcb, phdr);
8428c2654abSrjs break;
8438c2654abSrjs case SCTP_CAUSE_COOKIE_IN_SHUTDOWN:
8448c2654abSrjs /*
8458c2654abSrjs * We ignore this since the timer will drive out a new
8468c2654abSrjs * cookie anyway and there timer will drive us to send
8478c2654abSrjs * a SHUTDOWN_COMPLETE. We can't send one here since
8488c2654abSrjs * we don't have their tag.
8498c2654abSrjs */
8508c2654abSrjs break;
8518c2654abSrjs case SCTP_CAUSE_DELETEING_LAST_ADDR:
8528c2654abSrjs case SCTP_CAUSE_OPERATION_REFUSED:
8538c2654abSrjs case SCTP_CAUSE_DELETING_SRC_ADDR:
8548c2654abSrjs /* We should NOT get these here, but in a ASCONF-ACK. */
8558c2654abSrjs #ifdef SCTP_DEBUG
8568c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
8578c2654abSrjs printf("Peer sends ASCONF errors in a Operational Error?<%d>?\n",
8588c2654abSrjs error_type);
8598c2654abSrjs }
8608c2654abSrjs #endif
8618c2654abSrjs break;
8628c2654abSrjs case SCTP_CAUSE_OUT_OF_RESC:
8638c2654abSrjs /*
8648c2654abSrjs * And what, pray tell do we do with the fact
8658c2654abSrjs * that the peer is out of resources? Not
8668c2654abSrjs * really sure we could do anything but abort.
8678c2654abSrjs * I suspect this should have came WITH an
8688c2654abSrjs * abort instead of in a OP-ERROR.
8698c2654abSrjs */
8708c2654abSrjs break;
8718c2654abSrjs default:
8728c2654abSrjs #ifdef SCTP_DEBUG
8738c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
8748c2654abSrjs /* don't know what this error cause is... */
8758c2654abSrjs printf("sctp_handle_error: unknown error type = 0x%xh\n",
8768c2654abSrjs error_type);
8778c2654abSrjs }
8788c2654abSrjs #endif /* SCTP_DEBUG */
8798c2654abSrjs break;
8808c2654abSrjs }
8818c2654abSrjs adjust = SCTP_SIZE32(error_len);
8828c2654abSrjs chklen -= adjust;
8838c2654abSrjs phdr = (struct sctp_paramhdr *)((vaddr_t)phdr + adjust);
8848c2654abSrjs }
8858c2654abSrjs return (0);
8868c2654abSrjs }
8878c2654abSrjs
8888c2654abSrjs static int
sctp_handle_init_ack(struct mbuf * m,int iphlen,int offset,struct sctphdr * sh,struct sctp_init_ack_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)8898c2654abSrjs sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
8908c2654abSrjs struct sctp_init_ack_chunk *cp, struct sctp_tcb *stcb,
8918c2654abSrjs struct sctp_nets *net)
8928c2654abSrjs {
8938c2654abSrjs struct sctp_init_ack *init_ack;
8948c2654abSrjs int *state;
8958c2654abSrjs struct mbuf *op_err;
8968c2654abSrjs
8978c2654abSrjs #ifdef SCTP_DEBUG
8988c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
8998c2654abSrjs printf("sctp_handle_init_ack: handling INIT-ACK\n");
9008c2654abSrjs }
9018c2654abSrjs #endif
9028c2654abSrjs if (stcb == NULL) {
9038c2654abSrjs #ifdef SCTP_DEBUG
9048c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
9058c2654abSrjs printf("sctp_handle_init_ack: TCB is null\n");
9068c2654abSrjs }
9078c2654abSrjs #endif
9088c2654abSrjs return (-1);
9098c2654abSrjs }
9108c2654abSrjs if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_ack_chunk)) {
9118c2654abSrjs /* Invalid length */
9128c2654abSrjs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
9138c2654abSrjs sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
9148c2654abSrjs op_err);
9158c2654abSrjs return (-1);
9168c2654abSrjs }
9178c2654abSrjs init_ack = &cp->init;
9188c2654abSrjs /* validate parameters */
9198c2654abSrjs if (init_ack->initiate_tag == 0) {
9208c2654abSrjs /* protocol error... send an abort */
9218c2654abSrjs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
9228c2654abSrjs sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
9238c2654abSrjs op_err);
9248c2654abSrjs return (-1);
9258c2654abSrjs }
9268c2654abSrjs if (ntohl(init_ack->a_rwnd) < SCTP_MIN_RWND) {
9278c2654abSrjs /* protocol error... send an abort */
9288c2654abSrjs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
9298c2654abSrjs sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
9308c2654abSrjs op_err);
9318c2654abSrjs return (-1);
9328c2654abSrjs }
9338c2654abSrjs if (init_ack->num_inbound_streams == 0) {
9348c2654abSrjs /* protocol error... send an abort */
9358c2654abSrjs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
9368c2654abSrjs sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
9378c2654abSrjs op_err);
9388c2654abSrjs return (-1);
9398c2654abSrjs }
9408c2654abSrjs if (init_ack->num_outbound_streams == 0) {
9418c2654abSrjs /* protocol error... send an abort */
9428c2654abSrjs op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM);
9438c2654abSrjs sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, sh,
9448c2654abSrjs op_err);
9458c2654abSrjs return (-1);
9468c2654abSrjs }
9478c2654abSrjs
9488c2654abSrjs /* process according to association state... */
9498c2654abSrjs state = &stcb->asoc.state;
9508c2654abSrjs switch (*state & SCTP_STATE_MASK) {
9518c2654abSrjs case SCTP_STATE_COOKIE_WAIT:
9528c2654abSrjs /* this is the expected state for this chunk */
9538c2654abSrjs /* process the INIT-ACK parameters */
9548c2654abSrjs if (stcb->asoc.primary_destination->dest_state &
9558c2654abSrjs SCTP_ADDR_UNCONFIRMED) {
9568c2654abSrjs /*
9578c2654abSrjs * The primary is where we sent the INIT, we can
9588c2654abSrjs * always consider it confirmed when the INIT-ACK
9598c2654abSrjs * is returned. Do this before we load addresses
9608c2654abSrjs * though.
9618c2654abSrjs */
9628c2654abSrjs stcb->asoc.primary_destination->dest_state &=
9638c2654abSrjs ~SCTP_ADDR_UNCONFIRMED;
9648c2654abSrjs sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
9658c2654abSrjs stcb, 0, (void *)stcb->asoc.primary_destination);
9668c2654abSrjs }
9678c2654abSrjs if (sctp_process_init_ack(m, iphlen, offset, sh, cp, stcb, net
9688c2654abSrjs ) < 0) {
9698c2654abSrjs /* error in parsing parameters */
9708c2654abSrjs #ifdef SCTP_DEBUG
9718c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
9728c2654abSrjs printf("sctp_process_init_ack: error in msg, discarding\n");
9738c2654abSrjs }
9748c2654abSrjs #endif
9758c2654abSrjs return (-1);
9768c2654abSrjs }
9778c2654abSrjs /* update our state */
9788c2654abSrjs #ifdef SCTP_DEBUG
9798c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
9808c2654abSrjs printf("moving to COOKIE-ECHOED state\n");
9818c2654abSrjs }
9828c2654abSrjs #endif
9838c2654abSrjs if (*state & SCTP_STATE_SHUTDOWN_PENDING) {
9848c2654abSrjs *state = SCTP_STATE_COOKIE_ECHOED |
9858c2654abSrjs SCTP_STATE_SHUTDOWN_PENDING;
9868c2654abSrjs } else {
9878c2654abSrjs *state = SCTP_STATE_COOKIE_ECHOED;
9888c2654abSrjs }
9898c2654abSrjs
9908c2654abSrjs /* reset the RTO calc */
9918c2654abSrjs stcb->asoc.overall_error_count = 0;
9928c2654abSrjs SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
9938c2654abSrjs /*
9948c2654abSrjs * collapse the init timer back in case of a exponential backoff
9958c2654abSrjs */
9968c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, stcb->sctp_ep,
9978c2654abSrjs stcb, net);
9988c2654abSrjs /*
9998c2654abSrjs * the send at the end of the inbound data processing will
10008c2654abSrjs * cause the cookie to be sent
10018c2654abSrjs */
10028c2654abSrjs break;
10038c2654abSrjs case SCTP_STATE_SHUTDOWN_SENT:
10048c2654abSrjs /* incorrect state... discard */
10058c2654abSrjs break;
10068c2654abSrjs case SCTP_STATE_COOKIE_ECHOED:
10078c2654abSrjs /* incorrect state... discard */
10088c2654abSrjs break;
10098c2654abSrjs case SCTP_STATE_OPEN:
10108c2654abSrjs /* incorrect state... discard */
10118c2654abSrjs break;
10128c2654abSrjs case SCTP_STATE_EMPTY:
10138c2654abSrjs case SCTP_STATE_INUSE:
10148c2654abSrjs default:
10158c2654abSrjs /* incorrect state... discard */
10168c2654abSrjs #ifdef SCTP_DEBUG
10178c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
10188c2654abSrjs printf("Leaving handle-init-ack default\n");
10198c2654abSrjs }
10208c2654abSrjs #endif
10218c2654abSrjs return (-1);
10228c2654abSrjs break;
10238c2654abSrjs } /* end switch asoc state */
10248c2654abSrjs #ifdef SCTP_DEBUG
10258c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
10268c2654abSrjs printf("Leaving handle-init-ack end\n");
10278c2654abSrjs }
10288c2654abSrjs #endif
10298c2654abSrjs return (0);
10308c2654abSrjs }
10318c2654abSrjs
10328c2654abSrjs
10338c2654abSrjs /*
10348c2654abSrjs * handle a state cookie for an existing association
10358c2654abSrjs * m: input packet mbuf chain-- assumes a pullup on IP/SCTP/COOKIE-ECHO chunk
10368c2654abSrjs * note: this is a "split" mbuf and the cookie signature does not exist
10378c2654abSrjs * offset: offset into mbuf to the cookie-echo chunk
10388c2654abSrjs */
10398c2654abSrjs static struct sctp_tcb *
sctp_process_cookie_existing(struct mbuf * m,int iphlen,int offset,struct sctphdr * sh,struct sctp_state_cookie * cookie,int cookie_len,struct sctp_inpcb * inp,struct sctp_tcb * stcb,struct sctp_nets * net,struct sockaddr * init_src,int * notification)10408c2654abSrjs sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
10418c2654abSrjs struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len,
10428c2654abSrjs struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets *net,
10438c2654abSrjs struct sockaddr *init_src, int *notification)
10448c2654abSrjs {
10458c2654abSrjs struct sctp_association *asoc;
10468c2654abSrjs struct sctp_init_chunk *init_cp, init_buf;
10478c2654abSrjs struct sctp_init_ack_chunk *initack_cp, initack_buf;
10488c2654abSrjs int chk_length;
10498c2654abSrjs int init_offset, initack_offset;
10508c2654abSrjs int retval;
10518c2654abSrjs
10528c2654abSrjs /* I know that the TCB is non-NULL from the caller */
10538c2654abSrjs asoc = &stcb->asoc;
10548c2654abSrjs
10558c2654abSrjs if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) {
10568c2654abSrjs /* SHUTDOWN came in after sending INIT-ACK */
10578c2654abSrjs struct mbuf *op_err;
10588c2654abSrjs struct sctp_paramhdr *ph;
10598c2654abSrjs
10608c2654abSrjs sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination);
10618c2654abSrjs #ifdef SCTP_DEBUG
10628c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
10638c2654abSrjs printf("sctp_handle_cookie: got a cookie, while shutting down!\n");
10648c2654abSrjs }
10658c2654abSrjs #endif
10668c2654abSrjs MGETHDR(op_err, M_DONTWAIT, MT_HEADER);
10678c2654abSrjs if (op_err == NULL) {
10688c2654abSrjs /* FOOBAR */
10698c2654abSrjs return (NULL);
10708c2654abSrjs }
10718c2654abSrjs /* pre-reserve some space */
10728c2654abSrjs op_err->m_data += sizeof(struct ip6_hdr);
10738c2654abSrjs op_err->m_data += sizeof(struct sctphdr);
10748c2654abSrjs op_err->m_data += sizeof(struct sctp_chunkhdr);
10758c2654abSrjs /* Set the len */
10768c2654abSrjs op_err->m_len = op_err->m_pkthdr.len = sizeof(struct sctp_paramhdr);
10778c2654abSrjs ph = mtod(op_err, struct sctp_paramhdr *);
10788c2654abSrjs ph->param_type = htons(SCTP_CAUSE_COOKIE_IN_SHUTDOWN);
10798c2654abSrjs ph->param_length = htons(sizeof(struct sctp_paramhdr));
10808c2654abSrjs sctp_send_operr_to(m, iphlen, op_err, cookie->peers_vtag);
10818c2654abSrjs return (NULL);
10828c2654abSrjs }
10838c2654abSrjs /*
10848c2654abSrjs * find and validate the INIT chunk in the cookie (peer's info)
10858c2654abSrjs * the INIT should start after the cookie-echo header struct
10868c2654abSrjs * (chunk header, state cookie header struct)
10878c2654abSrjs */
10888c2654abSrjs init_offset = offset += sizeof(struct sctp_cookie_echo_chunk);
10898c2654abSrjs
10908c2654abSrjs init_cp = (struct sctp_init_chunk *)
10918c2654abSrjs sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk),
10928c2654abSrjs (u_int8_t *)&init_buf);
10938c2654abSrjs if (init_cp == NULL) {
10948c2654abSrjs /* could not pull a INIT chunk in cookie */
10958c2654abSrjs #ifdef SCTP_DEBUG
10968c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
10978c2654abSrjs printf("process_cookie_existing: could not pull INIT chunk hdr\n");
10988c2654abSrjs }
10998c2654abSrjs #endif /* SCTP_DEBUG */
11008c2654abSrjs return (NULL);
11018c2654abSrjs }
11028c2654abSrjs chk_length = ntohs(init_cp->ch.chunk_length);
11038c2654abSrjs if (init_cp->ch.chunk_type != SCTP_INITIATION) {
11048c2654abSrjs #ifdef SCTP_DEBUG
11058c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
11068c2654abSrjs printf("process_cookie_existing: could not find INIT chunk!\n");
11078c2654abSrjs }
11088c2654abSrjs #endif /* SCTP_DEBUG */
11098c2654abSrjs return (NULL);
11108c2654abSrjs }
11118c2654abSrjs
11128c2654abSrjs /*
11138c2654abSrjs * find and validate the INIT-ACK chunk in the cookie (my info)
11148c2654abSrjs * the INIT-ACK follows the INIT chunk
11158c2654abSrjs */
11168c2654abSrjs initack_offset = init_offset + SCTP_SIZE32(chk_length);
11178c2654abSrjs initack_cp = (struct sctp_init_ack_chunk *)
11188c2654abSrjs sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk),
11198c2654abSrjs (u_int8_t *)&initack_buf);
11208c2654abSrjs if (initack_cp == NULL) {
11218c2654abSrjs /* could not pull INIT-ACK chunk in cookie */
11228c2654abSrjs #ifdef SCTP_DEBUG
11238c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
11248c2654abSrjs printf("process_cookie_existing: could not pull INIT-ACK chunk hdr\n");
11258c2654abSrjs }
11268c2654abSrjs #endif /* SCTP_DEBUG */
11278c2654abSrjs return (NULL);
11288c2654abSrjs }
11298c2654abSrjs chk_length = ntohs(initack_cp->ch.chunk_length);
11308c2654abSrjs if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) {
11318c2654abSrjs #ifdef SCTP_DEBUG
11328c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
11338c2654abSrjs printf("process_cookie_existing: could not find INIT-ACK chunk!\n");
11348c2654abSrjs }
11358c2654abSrjs #endif /* SCTP_DEBUG */
11368c2654abSrjs return (NULL);
11378c2654abSrjs }
11388c2654abSrjs if ((ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag) &&
11398c2654abSrjs (ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag)) {
11408c2654abSrjs /*
11418c2654abSrjs * case D in Section 5.2.4 Table 2: MMAA
11428c2654abSrjs * process accordingly to get into the OPEN state
11438c2654abSrjs */
11448c2654abSrjs switch SCTP_GET_STATE(asoc) {
11458c2654abSrjs case SCTP_STATE_COOKIE_WAIT:
11468c2654abSrjs /*
11478c2654abSrjs * INIT was sent, but got got a COOKIE_ECHO with
11488c2654abSrjs * the correct tags... just accept it...
11498c2654abSrjs */
11508c2654abSrjs /* First we must process the INIT !! */
11518c2654abSrjs retval = sctp_process_init(init_cp, stcb, net);
11528c2654abSrjs if (retval < 0) {
11538c2654abSrjs #ifdef SCTP_DEBUG
11548c2654abSrjs printf("process_cookie_existing: INIT processing failed\n");
11558c2654abSrjs #endif
11568c2654abSrjs return (NULL);
11578c2654abSrjs }
1158d642e5f9Srjs /* FALLTHROUGH */
11598c2654abSrjs /* intentional fall through to below... */
11608c2654abSrjs
11618c2654abSrjs case SCTP_STATE_COOKIE_ECHOED:
11628c2654abSrjs /* Duplicate INIT case */
11638c2654abSrjs /* we have already processed the INIT so no problem */
11648c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb,
11658c2654abSrjs net);
11668c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net);
11678c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE, inp, stcb,
11688c2654abSrjs net);
11698c2654abSrjs /* update current state */
11708c2654abSrjs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
11718c2654abSrjs asoc->state = SCTP_STATE_OPEN |
11728c2654abSrjs SCTP_STATE_SHUTDOWN_PENDING;
11738c2654abSrjs } else if ((asoc->state & SCTP_STATE_SHUTDOWN_SENT) == 0) {
11748c2654abSrjs /* if ok, move to OPEN state */
11758c2654abSrjs asoc->state = SCTP_STATE_OPEN;
11768c2654abSrjs }
11778c2654abSrjs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
11788c2654abSrjs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
11798c2654abSrjs (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING))) {
11808c2654abSrjs /*
11818c2654abSrjs * Here is where collision would go if we did a
11828c2654abSrjs * connect() and instead got a
11838c2654abSrjs * init/init-ack/cookie done before the
11848c2654abSrjs * init-ack came back..
11858c2654abSrjs */
11868c2654abSrjs stcb->sctp_ep->sctp_flags |=
11878c2654abSrjs SCTP_PCB_FLAGS_CONNECTED;
11888c2654abSrjs soisconnected(stcb->sctp_ep->sctp_socket);
11898c2654abSrjs }
11908c2654abSrjs /* notify upper layer */
11918c2654abSrjs *notification = SCTP_NOTIFY_ASSOC_UP;
11928c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb,
11938c2654abSrjs net);
11948c2654abSrjs /*
11958c2654abSrjs * since we did not send a HB make sure we don't double
11968c2654abSrjs * things
11978c2654abSrjs */
11988c2654abSrjs net->hb_responded = 1;
11998c2654abSrjs
12008c2654abSrjs if (stcb->asoc.sctp_autoclose_ticks &&
12018c2654abSrjs (inp->sctp_flags & SCTP_PCB_FLAGS_AUTOCLOSE)) {
12028c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE,
12038c2654abSrjs inp, stcb, NULL);
12048c2654abSrjs }
12058c2654abSrjs break;
12068c2654abSrjs default:
12078c2654abSrjs /*
12088c2654abSrjs * we're in the OPEN state (or beyond), so peer
12098c2654abSrjs * must have simply lost the COOKIE-ACK
12108c2654abSrjs */
12118c2654abSrjs break;
12128c2654abSrjs } /* end switch */
12138c2654abSrjs
12148c2654abSrjs /*
12158c2654abSrjs * We ignore the return code here.. not sure if we should
12168c2654abSrjs * somehow abort.. but we do have an existing asoc. This
12178c2654abSrjs * really should not fail.
12188c2654abSrjs */
12198c2654abSrjs if (sctp_load_addresses_from_init(stcb, m, iphlen,
12208c2654abSrjs init_offset + sizeof(struct sctp_init_chunk),
12218c2654abSrjs initack_offset, sh, init_src)) {
12228c2654abSrjs #ifdef SCTP_DEBUG
12238c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
12248c2654abSrjs printf("Weird cookie load_address failure on cookie existing - 1\n");
12258c2654abSrjs }
12268c2654abSrjs #endif
12278c2654abSrjs return (NULL);
12288c2654abSrjs }
12298c2654abSrjs
12308c2654abSrjs /* respond with a COOKIE-ACK */
12318c2654abSrjs sctp_send_cookie_ack(stcb);
12328c2654abSrjs return (stcb);
12338c2654abSrjs } /* end if */
12348c2654abSrjs if (ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag &&
12358c2654abSrjs ntohl(init_cp->init.initiate_tag) == asoc->peer_vtag &&
12368c2654abSrjs cookie->tie_tag_my_vtag == 0 &&
12378c2654abSrjs cookie->tie_tag_peer_vtag == 0) {
12388c2654abSrjs /*
12398c2654abSrjs * case C in Section 5.2.4 Table 2: XMOO
12408c2654abSrjs * silently discard
12418c2654abSrjs */
12428c2654abSrjs return (NULL);
12438c2654abSrjs }
12448c2654abSrjs if (ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag &&
12458c2654abSrjs (ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag ||
12468c2654abSrjs init_cp->init.initiate_tag == 0)) {
12478c2654abSrjs /*
12488c2654abSrjs * case B in Section 5.2.4 Table 2: MXAA or MOAA
12498c2654abSrjs * my info should be ok, re-accept peer info
12508c2654abSrjs */
12518c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
12528c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net);
12538c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE, inp, stcb, net);
12548c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
12558c2654abSrjs /*
12568c2654abSrjs * since we did not send a HB make sure we don't double things
12578c2654abSrjs */
12588c2654abSrjs net->hb_responded = 1;
12598c2654abSrjs if (stcb->asoc.sctp_autoclose_ticks &&
12608c2654abSrjs (inp->sctp_flags & SCTP_PCB_FLAGS_AUTOCLOSE)) {
12618c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb,
12628c2654abSrjs NULL);
12638c2654abSrjs }
12648c2654abSrjs asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
12658c2654abSrjs asoc->pre_open_streams =
12668c2654abSrjs ntohs(initack_cp->init.num_outbound_streams);
12678c2654abSrjs asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn);
12688c2654abSrjs asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out =
12698c2654abSrjs asoc->init_seq_number;
12708c2654abSrjs asoc->t3timeout_highest_marked = asoc->asconf_seq_out;
12718c2654abSrjs asoc->last_cwr_tsn = asoc->init_seq_number - 1;
12728c2654abSrjs asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1;
12738c2654abSrjs asoc->str_reset_seq_in = asoc->init_seq_number;
12748c2654abSrjs asoc->advanced_peer_ack_point = asoc->last_acked_seq;
12758c2654abSrjs
12768c2654abSrjs /* process the INIT info (peer's info) */
12778c2654abSrjs retval = sctp_process_init(init_cp, stcb, net);
12788c2654abSrjs if (retval < 0) {
12798c2654abSrjs #ifdef SCTP_DEBUG
12808c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
12818c2654abSrjs printf("process_cookie_existing: INIT processing failed\n");
12828c2654abSrjs }
12838c2654abSrjs #endif
12848c2654abSrjs return (NULL);
12858c2654abSrjs }
12868c2654abSrjs if (sctp_load_addresses_from_init(stcb, m, iphlen,
12878c2654abSrjs init_offset + sizeof(struct sctp_init_chunk),
12888c2654abSrjs initack_offset, sh, init_src)) {
12898c2654abSrjs #ifdef SCTP_DEBUG
12908c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
12918c2654abSrjs printf("Weird cookie load_address failure on cookie existing - 2\n");
12928c2654abSrjs }
12938c2654abSrjs #endif
12948c2654abSrjs return (NULL);
12958c2654abSrjs }
12968c2654abSrjs
12978c2654abSrjs if ((asoc->state & SCTP_STATE_COOKIE_WAIT) ||
12988c2654abSrjs (asoc->state & SCTP_STATE_COOKIE_ECHOED)) {
12998c2654abSrjs *notification = SCTP_NOTIFY_ASSOC_UP;
13008c2654abSrjs
13018c2654abSrjs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
13028c2654abSrjs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
13038c2654abSrjs !(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING)) {
13048c2654abSrjs stcb->sctp_ep->sctp_flags |=
13058c2654abSrjs SCTP_PCB_FLAGS_CONNECTED;
13068c2654abSrjs soisconnected(stcb->sctp_ep->sctp_socket);
13078c2654abSrjs }
13088c2654abSrjs }
13098c2654abSrjs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
13108c2654abSrjs asoc->state = SCTP_STATE_OPEN |
13118c2654abSrjs SCTP_STATE_SHUTDOWN_PENDING;
13128c2654abSrjs } else {
13138c2654abSrjs asoc->state = SCTP_STATE_OPEN;
13148c2654abSrjs }
13158c2654abSrjs sctp_send_cookie_ack(stcb);
13168c2654abSrjs return (stcb);
13178c2654abSrjs }
13188c2654abSrjs
13198c2654abSrjs if ((ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag &&
13208c2654abSrjs ntohl(init_cp->init.initiate_tag) != asoc->peer_vtag) &&
13218c2654abSrjs cookie->tie_tag_my_vtag == asoc->my_vtag_nonce &&
13228c2654abSrjs cookie->tie_tag_peer_vtag == asoc->peer_vtag_nonce &&
13238c2654abSrjs cookie->tie_tag_peer_vtag != 0) {
13248c2654abSrjs /*
13258c2654abSrjs * case A in Section 5.2.4 Table 2: XXMM (peer restarted)
13268c2654abSrjs */
13278c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net);
13288c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE, inp, stcb, net);
13298c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
13308c2654abSrjs
13318c2654abSrjs /* notify upper layer */
13328c2654abSrjs *notification = SCTP_NOTIFY_ASSOC_RESTART;
13338c2654abSrjs
13348c2654abSrjs /* send up all the data */
13358c2654abSrjs sctp_report_all_outbound(stcb);
13368c2654abSrjs
13378c2654abSrjs /* process the INIT-ACK info (my info) */
13388c2654abSrjs asoc->my_vtag = ntohl(initack_cp->init.initiate_tag);
13398c2654abSrjs asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
13408c2654abSrjs asoc->pre_open_streams =
13418c2654abSrjs ntohs(initack_cp->init.num_outbound_streams);
13428c2654abSrjs asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn);
13438c2654abSrjs asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out =
13448c2654abSrjs asoc->init_seq_number;
13458c2654abSrjs asoc->t3timeout_highest_marked = asoc->asconf_seq_out;
13468c2654abSrjs asoc->last_cwr_tsn = asoc->init_seq_number - 1;
13478c2654abSrjs asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1;
13488c2654abSrjs asoc->str_reset_seq_in = asoc->init_seq_number;
13498c2654abSrjs
13508c2654abSrjs asoc->advanced_peer_ack_point = asoc->last_acked_seq;
13518c2654abSrjs if (asoc->mapping_array)
13528c2654abSrjs memset(asoc->mapping_array, 0,
13538c2654abSrjs asoc->mapping_array_size);
13548c2654abSrjs /* process the INIT info (peer's info) */
13558c2654abSrjs retval = sctp_process_init(init_cp, stcb, net);
13568c2654abSrjs if (retval < 0) {
13578c2654abSrjs #ifdef SCTP_DEBUG
13588c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
13598c2654abSrjs printf("process_cookie_existing: INIT processing failed\n");
13608c2654abSrjs }
13618c2654abSrjs #endif
13628c2654abSrjs return (NULL);
13638c2654abSrjs }
13648c2654abSrjs
13658c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
13668c2654abSrjs /*
13678c2654abSrjs * since we did not send a HB make sure we don't double things
13688c2654abSrjs */
13698c2654abSrjs net->hb_responded = 1;
13708c2654abSrjs
13718c2654abSrjs if (sctp_load_addresses_from_init(stcb, m, iphlen,
13728c2654abSrjs init_offset + sizeof(struct sctp_init_chunk),
13738c2654abSrjs initack_offset, sh, init_src)) {
13748c2654abSrjs #ifdef SCTP_DEBUG
13758c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
13768c2654abSrjs printf("Weird cookie load_address failure on cookie existing - 3\n");
13778c2654abSrjs }
13788c2654abSrjs #endif
13798c2654abSrjs return (NULL);
13808c2654abSrjs }
13818c2654abSrjs
13828c2654abSrjs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
13838c2654abSrjs asoc->state = SCTP_STATE_OPEN |
13848c2654abSrjs SCTP_STATE_SHUTDOWN_PENDING;
13858c2654abSrjs } else if (!(asoc->state & SCTP_STATE_SHUTDOWN_SENT)) {
13868c2654abSrjs /* move to OPEN state, if not in SHUTDOWN_SENT */
13878c2654abSrjs asoc->state = SCTP_STATE_OPEN;
13888c2654abSrjs }
13898c2654abSrjs /* respond with a COOKIE-ACK */
13908c2654abSrjs sctp_send_cookie_ack(stcb);
13918c2654abSrjs
13928c2654abSrjs return (stcb);
13938c2654abSrjs }
13948c2654abSrjs /* all other cases... */
13958c2654abSrjs return (NULL);
13968c2654abSrjs }
13978c2654abSrjs
13988c2654abSrjs /*
13998c2654abSrjs * handle a state cookie for a new association
14008c2654abSrjs * m: input packet mbuf chain-- assumes a pullup on IP/SCTP/COOKIE-ECHO chunk
14018c2654abSrjs * note: this is a "split" mbuf and the cookie signature does not exist
14028c2654abSrjs * offset: offset into mbuf to the cookie-echo chunk
14038c2654abSrjs * length: length of the cookie chunk
14048c2654abSrjs * to: where the init was from
14058c2654abSrjs * returns a new TCB
14068c2654abSrjs */
14078c2654abSrjs static struct sctp_tcb *
sctp_process_cookie_new(struct mbuf * m,int iphlen,int offset,struct sctphdr * sh,struct sctp_state_cookie * cookie,int cookie_len,struct sctp_inpcb * inp,struct sctp_nets ** netp,struct sockaddr * init_src,int * notification)14088c2654abSrjs sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
14098c2654abSrjs struct sctphdr *sh, struct sctp_state_cookie *cookie, int cookie_len,
14108c2654abSrjs struct sctp_inpcb *inp, struct sctp_nets **netp,
14118c2654abSrjs struct sockaddr *init_src, int *notification)
14128c2654abSrjs {
14138c2654abSrjs struct sctp_tcb *stcb;
14148c2654abSrjs struct sctp_init_chunk *init_cp, init_buf;
14158c2654abSrjs struct sctp_init_ack_chunk *initack_cp, initack_buf;
14168c2654abSrjs struct sockaddr_storage sa_store;
14178c2654abSrjs struct sockaddr *initack_src = (struct sockaddr *)&sa_store;
14188c2654abSrjs struct sockaddr_in *sin;
14198c2654abSrjs struct sockaddr_in6 *sin6;
14208c2654abSrjs struct sctp_association *asoc;
14218c2654abSrjs int chk_length;
14228c2654abSrjs int init_offset, initack_offset, initack_limit;
14238c2654abSrjs int retval;
14248c2654abSrjs int error = 0;
14258c2654abSrjs /*
14268c2654abSrjs * find and validate the INIT chunk in the cookie (peer's info)
14278c2654abSrjs * the INIT should start after the cookie-echo header struct
14288c2654abSrjs * (chunk header, state cookie header struct)
14298c2654abSrjs */
14308c2654abSrjs init_offset = offset + sizeof(struct sctp_cookie_echo_chunk);
14318c2654abSrjs init_cp = (struct sctp_init_chunk *)
14328c2654abSrjs sctp_m_getptr(m, init_offset, sizeof(struct sctp_init_chunk),
14338c2654abSrjs (u_int8_t *)&init_buf);
14348c2654abSrjs if (init_cp == NULL) {
14358c2654abSrjs /* could not pull a INIT chunk in cookie */
14368c2654abSrjs #ifdef SCTP_DEBUG
14378c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
14388c2654abSrjs printf("process_cookie_new: could not pull INIT chunk hdr\n");
14398c2654abSrjs }
14408c2654abSrjs #endif /* SCTP_DEBUG */
14418c2654abSrjs return (NULL);
14428c2654abSrjs }
14438c2654abSrjs chk_length = ntohs(init_cp->ch.chunk_length);
14448c2654abSrjs if (init_cp->ch.chunk_type != SCTP_INITIATION) {
14458c2654abSrjs #ifdef SCTP_DEBUG
14468c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
14478c2654abSrjs printf("HUH? process_cookie_new: could not find INIT chunk!\n");
14488c2654abSrjs }
14498c2654abSrjs #endif /* SCTP_DEBUG */
14508c2654abSrjs return (NULL);
14518c2654abSrjs }
14528c2654abSrjs
14538c2654abSrjs initack_offset = init_offset + SCTP_SIZE32(chk_length);
14548c2654abSrjs /*
14558c2654abSrjs * find and validate the INIT-ACK chunk in the cookie (my info)
14568c2654abSrjs * the INIT-ACK follows the INIT chunk
14578c2654abSrjs */
14588c2654abSrjs initack_cp = (struct sctp_init_ack_chunk *)
14598c2654abSrjs sctp_m_getptr(m, initack_offset, sizeof(struct sctp_init_ack_chunk),
14608c2654abSrjs (u_int8_t *)&initack_buf);
14618c2654abSrjs if (initack_cp == NULL) {
14628c2654abSrjs /* could not pull INIT-ACK chunk in cookie */
14638c2654abSrjs #ifdef SCTP_DEBUG
14648c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
14658c2654abSrjs printf("process_cookie_new: could not pull INIT-ACK chunk hdr\n");
14668c2654abSrjs }
14678c2654abSrjs #endif /* SCTP_DEBUG */
14688c2654abSrjs return (NULL);
14698c2654abSrjs }
14708c2654abSrjs chk_length = ntohs(initack_cp->ch.chunk_length);
14718c2654abSrjs if (initack_cp->ch.chunk_type != SCTP_INITIATION_ACK) {
14728c2654abSrjs #ifdef SCTP_DEBUG
14738c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
14748c2654abSrjs u_int8_t *pp;
14758c2654abSrjs pp = (u_int8_t *)initack_cp;
14768c2654abSrjs printf("process_cookie_new: could not find INIT-ACK chunk!\n");
1477146d03e6Sandvar printf("Found bytes %x %x %x %x at position %d\n",
14788c2654abSrjs (u_int)pp[0], (u_int)pp[1], (u_int)pp[2],
14798c2654abSrjs (u_int)pp[3], initack_offset);
14808c2654abSrjs }
14818c2654abSrjs #endif /* SCTP_DEBUG */
14828c2654abSrjs return (NULL);
14838c2654abSrjs }
14848c2654abSrjs initack_limit = initack_offset + SCTP_SIZE32(chk_length);
14858c2654abSrjs
14868c2654abSrjs /*
14878c2654abSrjs * now that we know the INIT/INIT-ACK are in place,
14888c2654abSrjs * create a new TCB and popluate
14898c2654abSrjs */
14908c2654abSrjs stcb = sctp_aloc_assoc(inp, init_src, 0, &error, ntohl(initack_cp->init.initiate_tag));
14918c2654abSrjs if (stcb == NULL) {
14928c2654abSrjs struct mbuf *op_err;
14938c2654abSrjs /* memory problem? */
14948c2654abSrjs #ifdef SCTP_DEBUG
14958c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
14968c2654abSrjs printf("process_cookie_new: no room for another TCB!\n");
14978c2654abSrjs }
14988c2654abSrjs #endif /* SCTP_DEBUG */
14998c2654abSrjs op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
15008c2654abSrjs sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen,
15018c2654abSrjs sh, op_err);
15028c2654abSrjs return (NULL);
15038c2654abSrjs }
15048c2654abSrjs
15058c2654abSrjs /* get the correct sctp_nets */
15068c2654abSrjs *netp = sctp_findnet(stcb, init_src);
15078c2654abSrjs asoc = &stcb->asoc;
15088c2654abSrjs /* get scope variables out of cookie */
15098c2654abSrjs asoc->ipv4_local_scope = cookie->ipv4_scope;
15108c2654abSrjs asoc->site_scope = cookie->site_scope;
15118c2654abSrjs asoc->local_scope = cookie->local_scope;
15128c2654abSrjs asoc->loopback_scope = cookie->loopback_scope;
15138c2654abSrjs
15148c2654abSrjs if ((asoc->ipv4_addr_legal != cookie->ipv4_addr_legal) ||
15158c2654abSrjs (asoc->ipv6_addr_legal != cookie->ipv6_addr_legal)) {
15168c2654abSrjs struct mbuf *op_err;
15178c2654abSrjs /*
15188c2654abSrjs * Houston we have a problem. The EP changed while the cookie
15198c2654abSrjs * was in flight. Only recourse is to abort the association.
15208c2654abSrjs */
15218c2654abSrjs op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
15228c2654abSrjs sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen,
15238c2654abSrjs sh, op_err);
15248c2654abSrjs return (NULL);
15258c2654abSrjs }
15268c2654abSrjs
15278c2654abSrjs /* process the INIT-ACK info (my info) */
15288c2654abSrjs asoc->my_vtag = ntohl(initack_cp->init.initiate_tag);
15298c2654abSrjs asoc->my_rwnd = ntohl(initack_cp->init.a_rwnd);
15308c2654abSrjs asoc->pre_open_streams = ntohs(initack_cp->init.num_outbound_streams);
15318c2654abSrjs asoc->init_seq_number = ntohl(initack_cp->init.initial_tsn);
15328c2654abSrjs asoc->sending_seq = asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number;
15338c2654abSrjs asoc->t3timeout_highest_marked = asoc->asconf_seq_out;
15348c2654abSrjs asoc->last_cwr_tsn = asoc->init_seq_number - 1;
15358c2654abSrjs asoc->asconf_seq_in = asoc->last_acked_seq = asoc->init_seq_number - 1;
15368c2654abSrjs asoc->str_reset_seq_in = asoc->init_seq_number;
15378c2654abSrjs
15388c2654abSrjs asoc->advanced_peer_ack_point = asoc->last_acked_seq;
15398c2654abSrjs
15408c2654abSrjs /* process the INIT info (peer's info) */
15418c2654abSrjs retval = sctp_process_init(init_cp, stcb, *netp);
15428c2654abSrjs if (retval < 0) {
15438c2654abSrjs #ifdef SCTP_DEBUG
15448c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
15458c2654abSrjs printf("process_cookie_new: INIT processing failed\n");
15468c2654abSrjs }
15478c2654abSrjs #endif
15488c2654abSrjs sctp_free_assoc(inp, stcb);
15498c2654abSrjs return (NULL);
15508c2654abSrjs }
15518c2654abSrjs /* load all addresses */
15528c2654abSrjs if (sctp_load_addresses_from_init(stcb, m, iphlen,
15538c2654abSrjs init_offset + sizeof(struct sctp_init_chunk), initack_offset, sh,
15548c2654abSrjs init_src)) {
15558c2654abSrjs sctp_free_assoc(inp, stcb);
15568c2654abSrjs return (NULL);
15578c2654abSrjs }
15588c2654abSrjs
15598c2654abSrjs /* update current state */
15608c2654abSrjs #ifdef SCTP_DEBUG
15618c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
15628c2654abSrjs printf("moving to OPEN state\n");
15638c2654abSrjs }
15648c2654abSrjs #endif
15658c2654abSrjs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
15668c2654abSrjs asoc->state = SCTP_STATE_OPEN | SCTP_STATE_SHUTDOWN_PENDING;
15678c2654abSrjs } else {
15688c2654abSrjs asoc->state = SCTP_STATE_OPEN;
15698c2654abSrjs }
15708c2654abSrjs /* calculate the RTT */
15718c2654abSrjs (*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp,
15728c2654abSrjs &cookie->time_entered);
15738c2654abSrjs
15748c2654abSrjs /*
15758c2654abSrjs * if we're doing ASCONFs, check to see if we have any new
15768c2654abSrjs * local addresses that need to get added to the peer (eg.
15778c2654abSrjs * addresses changed while cookie echo in flight). This needs
15788c2654abSrjs * to be done after we go to the OPEN state to do the correct
15798c2654abSrjs * asconf processing.
15808c2654abSrjs * else, make sure we have the correct addresses in our lists
15818c2654abSrjs */
15828c2654abSrjs
15838c2654abSrjs /* warning, we re-use sin, sin6, sa_store here! */
15848c2654abSrjs /* pull in local_address (our "from" address) */
15858c2654abSrjs if (cookie->laddr_type == SCTP_IPV4_ADDRESS) {
15868c2654abSrjs /* source addr is IPv4 */
15878c2654abSrjs sin = (struct sockaddr_in *)initack_src;
15888c2654abSrjs memset(sin, 0, sizeof(*sin));
15898c2654abSrjs sin->sin_family = AF_INET;
15908c2654abSrjs sin->sin_len = sizeof(struct sockaddr_in);
15918c2654abSrjs sin->sin_addr.s_addr = cookie->laddress[0];
15928c2654abSrjs } else if (cookie->laddr_type == SCTP_IPV6_ADDRESS) {
15938c2654abSrjs /* source addr is IPv6 */
15948c2654abSrjs sin6 = (struct sockaddr_in6 *)initack_src;
15958c2654abSrjs memset(sin6, 0, sizeof(*sin6));
15968c2654abSrjs sin6->sin6_family = AF_INET6;
15978c2654abSrjs sin6->sin6_len = sizeof(struct sockaddr_in6);
15988c2654abSrjs sin6->sin6_scope_id = cookie->scope_id;
15998c2654abSrjs memcpy(&sin6->sin6_addr, cookie->laddress,
16008c2654abSrjs sizeof(sin6->sin6_addr));
16018c2654abSrjs } else {
16028c2654abSrjs sctp_free_assoc(inp, stcb);
16038c2654abSrjs return (NULL);
16048c2654abSrjs }
16058c2654abSrjs
16068c2654abSrjs sctp_check_address_list(stcb, m, initack_offset +
16078c2654abSrjs sizeof(struct sctp_init_ack_chunk), initack_limit,
16088c2654abSrjs initack_src, cookie->local_scope, cookie->site_scope,
16098c2654abSrjs cookie->ipv4_scope, cookie->loopback_scope);
16108c2654abSrjs
16118c2654abSrjs
16128c2654abSrjs /* set up to notify upper layer */
16138c2654abSrjs *notification = SCTP_NOTIFY_ASSOC_UP;
16148c2654abSrjs if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
16158c2654abSrjs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
16168c2654abSrjs !(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING)) {
16178c2654abSrjs /*
16188c2654abSrjs * This is an endpoint that called connect()
16198c2654abSrjs * how it got a cookie that is NEW is a bit of
16208c2654abSrjs * a mystery. It must be that the INIT was sent, but
16218c2654abSrjs * before it got there.. a complete INIT/INIT-ACK/COOKIE
16228c2654abSrjs * arrived. But of course then it should have went to
16238c2654abSrjs * the other code.. not here.. oh well.. a bit of protection
16248c2654abSrjs * is worth having..
16258c2654abSrjs */
16268c2654abSrjs stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
16278c2654abSrjs soisconnected(stcb->sctp_ep->sctp_socket);
16288c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, *netp);
16298c2654abSrjs } else if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
16308c2654abSrjs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING)) {
16318c2654abSrjs /*
16328c2654abSrjs * We don't want to do anything with this
16338c2654abSrjs * one. Since it is the listening guy. The timer will
16348c2654abSrjs * get started for accepted connections in the caller.
16358c2654abSrjs */
16368c2654abSrjs ;
16378c2654abSrjs } else {
16388c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, *netp);
16398c2654abSrjs }
16408c2654abSrjs /* since we did not send a HB make sure we don't double things */
16418c2654abSrjs (*netp)->hb_responded = 1;
16428c2654abSrjs
16438c2654abSrjs if (stcb->asoc.sctp_autoclose_ticks &&
16448c2654abSrjs (inp->sctp_flags & SCTP_PCB_FLAGS_AUTOCLOSE)) {
16458c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE, inp, stcb, NULL);
16468c2654abSrjs }
16478c2654abSrjs
16488c2654abSrjs /* respond with a COOKIE-ACK */
16498c2654abSrjs sctp_send_cookie_ack(stcb);
16508c2654abSrjs
16518c2654abSrjs return (stcb);
16528c2654abSrjs }
16538c2654abSrjs
16548c2654abSrjs
16558c2654abSrjs /*
16568c2654abSrjs * handles a COOKIE-ECHO message
16578c2654abSrjs * stcb: modified to either a new or left as existing (non-NULL) TCB
16588c2654abSrjs */
16598c2654abSrjs static struct mbuf *
sctp_handle_cookie_echo(struct mbuf * m,int iphlen,int offset,struct sctphdr * sh,struct sctp_cookie_echo_chunk * cp,struct sctp_inpcb ** inp_p,struct sctp_tcb ** stcb,struct sctp_nets ** netp)16608c2654abSrjs sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
16618c2654abSrjs struct sctphdr *sh, struct sctp_cookie_echo_chunk *cp,
16628c2654abSrjs struct sctp_inpcb **inp_p, struct sctp_tcb **stcb, struct sctp_nets **netp)
16638c2654abSrjs {
16648c2654abSrjs struct sctp_state_cookie *cookie;
16658c2654abSrjs struct sockaddr_in6 sin6;
16668c2654abSrjs struct sockaddr_in sin;
16678c2654abSrjs struct sctp_tcb *l_stcb=*stcb;
16688c2654abSrjs struct sctp_inpcb *l_inp;
16698c2654abSrjs struct sockaddr *to;
16708c2654abSrjs struct sctp_pcb *ep;
16718c2654abSrjs struct mbuf *m_sig;
16728c2654abSrjs uint8_t calc_sig[SCTP_SIGNATURE_SIZE], tmp_sig[SCTP_SIGNATURE_SIZE];
16738c2654abSrjs uint8_t *sig;
16748c2654abSrjs uint8_t cookie_ok = 0;
16758c2654abSrjs unsigned int size_of_pkt, sig_offset, cookie_offset;
16768c2654abSrjs unsigned int cookie_len;
16778c2654abSrjs struct timeval now;
16788c2654abSrjs struct timeval time_expires;
16798c2654abSrjs struct sockaddr_storage dest_store;
16808c2654abSrjs struct sockaddr *localep_sa = (struct sockaddr *)&dest_store;
16818c2654abSrjs struct ip *iph;
16828c2654abSrjs int notification = 0;
16838c2654abSrjs struct sctp_nets *netl;
16848c2654abSrjs int had_a_existing_tcb = 0;
16858c2654abSrjs
16868c2654abSrjs #ifdef SCTP_DEBUG
16878c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
16888c2654abSrjs printf("sctp_handle_cookie: handling COOKIE-ECHO\n");
16898c2654abSrjs }
16908c2654abSrjs #endif
16918c2654abSrjs
16928c2654abSrjs if (inp_p == NULL) {
16938c2654abSrjs #ifdef SCTP_DEBUG
16948c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
16958c2654abSrjs printf("sctp_handle_cookie: null inp_p!\n");
16968c2654abSrjs }
16978c2654abSrjs #endif
16988c2654abSrjs return (NULL);
16998c2654abSrjs }
17008c2654abSrjs /* First get the destination address setup too. */
17018c2654abSrjs iph = mtod(m, struct ip *);
17028c2654abSrjs if (iph->ip_v == IPVERSION) {
17038c2654abSrjs /* its IPv4 */
17048c2654abSrjs struct sockaddr_in *sin_d;
17058c2654abSrjs sin_d = (struct sockaddr_in *)(localep_sa);
17068c2654abSrjs memset(sin_d, 0, sizeof(*sin_d));
17078c2654abSrjs sin_d->sin_family = AF_INET;
17088c2654abSrjs sin_d->sin_len = sizeof(*sin_d);
17098c2654abSrjs sin_d->sin_port = sh->dest_port;
17108c2654abSrjs sin_d->sin_addr.s_addr = iph->ip_dst.s_addr ;
17118c2654abSrjs } else if (iph->ip_v == (IPV6_VERSION >> 4)) {
17128c2654abSrjs /* its IPv6 */
17138c2654abSrjs struct ip6_hdr *ip6;
17148c2654abSrjs struct sockaddr_in6 *sin6_d;
17158c2654abSrjs sin6_d = (struct sockaddr_in6 *)(localep_sa);
17168c2654abSrjs memset(sin6_d, 0, sizeof(*sin6_d));
17178c2654abSrjs sin6_d->sin6_family = AF_INET6;
17188c2654abSrjs sin6_d->sin6_len = sizeof(struct sockaddr_in6);
17198c2654abSrjs ip6 = mtod(m, struct ip6_hdr *);
17208c2654abSrjs sin6_d->sin6_port = sh->dest_port;
17218c2654abSrjs sin6_d->sin6_addr = ip6->ip6_dst;
17228c2654abSrjs } else {
17238c2654abSrjs return (NULL);
17248c2654abSrjs }
17258c2654abSrjs
17268c2654abSrjs cookie = &cp->cookie;
17278c2654abSrjs cookie_offset = offset + sizeof(struct sctp_chunkhdr);
17288c2654abSrjs cookie_len = ntohs(cp->ch.chunk_length);
17298c2654abSrjs
17308c2654abSrjs /* compute size of packet */
17318c2654abSrjs if (m->m_flags & M_PKTHDR) {
17328c2654abSrjs size_of_pkt = m->m_pkthdr.len;
17338c2654abSrjs } else {
17348c2654abSrjs /* Should have a pkt hdr really */
17358c2654abSrjs struct mbuf *mat;
17368c2654abSrjs mat = m;
17378c2654abSrjs size_of_pkt = 0;
17388c2654abSrjs while (mat != NULL) {
17398c2654abSrjs size_of_pkt += mat->m_len;
17408c2654abSrjs mat = mat->m_next;
17418c2654abSrjs }
17428c2654abSrjs }
17438c2654abSrjs if (cookie_len > size_of_pkt ||
17448c2654abSrjs cookie_len < sizeof(struct sctp_cookie_echo_chunk) +
17458c2654abSrjs sizeof(struct sctp_init_chunk) +
17468c2654abSrjs sizeof(struct sctp_init_ack_chunk) + SCTP_SIGNATURE_SIZE) {
17478c2654abSrjs /* cookie too long! or too small */
17488c2654abSrjs #ifdef SCTP_DEBUG
17498c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
17508c2654abSrjs printf("sctp_handle_cookie: cookie_len=%u, pkt size=%u\n", cookie_len, size_of_pkt);
17518c2654abSrjs }
17528c2654abSrjs #endif /* SCTP_DEBUG */
17538c2654abSrjs return (NULL);
17548c2654abSrjs }
17555c08ce63Srjs
17565c08ce63Srjs if ((cookie->peerport != sh->src_port) &&
17575c08ce63Srjs (cookie->myport != sh->dest_port) &&
17585c08ce63Srjs (cookie->my_vtag != sh->v_tag)) {
17595c08ce63Srjs /*
17605c08ce63Srjs * invalid ports or bad tag. Note that we always leave
17615c08ce63Srjs * the v_tag in the header in network order and when we
17625c08ce63Srjs * stored it in the my_vtag slot we also left it in network
17635c08ce63Srjs * order. This maintians the match even though it may be in
17645c08ce63Srjs * the opposite byte order of the machine :->
17655c08ce63Srjs */
17665c08ce63Srjs return (NULL);
17675c08ce63Srjs }
17685c08ce63Srjs
17698c2654abSrjs /*
17708c2654abSrjs * split off the signature into its own mbuf (since it
17718c2654abSrjs * should not be calculated in the sctp_hash_digest_m() call).
17728c2654abSrjs */
17738c2654abSrjs sig_offset = offset + cookie_len - SCTP_SIGNATURE_SIZE;
17748c2654abSrjs if (sig_offset > size_of_pkt) {
17758c2654abSrjs /* packet not correct size! */
17768c2654abSrjs /* XXX this may already be accounted for earlier... */
17778c2654abSrjs #ifdef SCTP_DEBUG
17788c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
17798c2654abSrjs printf("sctp_handle_cookie: sig offset=%u, pkt size=%u\n", sig_offset, size_of_pkt);
17808c2654abSrjs }
17818c2654abSrjs #endif
17828c2654abSrjs return (NULL);
17838c2654abSrjs }
17848c2654abSrjs
17858c2654abSrjs m_sig = m_split(m, sig_offset, M_DONTWAIT);
17868c2654abSrjs if (m_sig == NULL) {
17878c2654abSrjs /* out of memory or ?? */
17888c2654abSrjs #ifdef SCTP_DEBUG
17898c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
17908c2654abSrjs printf("sctp_handle_cookie: couldn't m_split the signature\n");
17918c2654abSrjs }
17928c2654abSrjs #endif
17938c2654abSrjs return (NULL);
17948c2654abSrjs }
17958c2654abSrjs /*
17968c2654abSrjs * compute the signature/digest for the cookie
17978c2654abSrjs */
17988c2654abSrjs ep = &(*inp_p)->sctp_ep;
17998c2654abSrjs l_inp = *inp_p;
18008c2654abSrjs if (l_stcb) {
18018c2654abSrjs SCTP_TCB_UNLOCK(l_stcb);
18028c2654abSrjs }
18038c2654abSrjs SCTP_INP_RLOCK(l_inp);
18048c2654abSrjs if (l_stcb) {
18058c2654abSrjs SCTP_TCB_LOCK(l_stcb);
18068c2654abSrjs }
18078c2654abSrjs /* which cookie is it? */
18088c2654abSrjs if ((cookie->time_entered.tv_sec < (long)ep->time_of_secret_change) &&
18098c2654abSrjs (ep->current_secret_number != ep->last_secret_number)) {
18108c2654abSrjs /* it's the old cookie */
18118c2654abSrjs #ifdef SCTP_DEBUG
18128c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
18138c2654abSrjs printf("sctp_handle_cookie: old cookie sig\n");
18148c2654abSrjs }
18158c2654abSrjs #endif
18168c2654abSrjs sctp_hash_digest_m((char *)ep->secret_key[(int)ep->last_secret_number],
18178c2654abSrjs SCTP_SECRET_SIZE, m, cookie_offset, calc_sig);
18188c2654abSrjs } else {
18198c2654abSrjs /* it's the current cookie */
18208c2654abSrjs #ifdef SCTP_DEBUG
18218c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
18228c2654abSrjs printf("sctp_handle_cookie: current cookie sig\n");
18238c2654abSrjs }
18248c2654abSrjs #endif
18258c2654abSrjs sctp_hash_digest_m((char *)ep->secret_key[(int)ep->current_secret_number],
18268c2654abSrjs SCTP_SECRET_SIZE, m, cookie_offset, calc_sig);
18278c2654abSrjs }
18288c2654abSrjs /* get the signature */
18298c2654abSrjs SCTP_INP_RUNLOCK(l_inp);
18308c2654abSrjs sig = (u_int8_t *)sctp_m_getptr(m_sig, 0, SCTP_SIGNATURE_SIZE, (u_int8_t *)&tmp_sig);
18318c2654abSrjs if (sig == NULL) {
18328c2654abSrjs /* couldn't find signature */
18338c2654abSrjs #ifdef SCTP_DEBUG
18348c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
18358c2654abSrjs printf("sctp_handle_cookie: couldn't pull the signature\n");
18368c2654abSrjs }
18378c2654abSrjs #endif
18388c2654abSrjs return (NULL);
18398c2654abSrjs }
18408c2654abSrjs /* compare the received digest with the computed digest */
18418c2654abSrjs if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) != 0) {
18428c2654abSrjs /* try the old cookie? */
18438c2654abSrjs if ((cookie->time_entered.tv_sec == (long)ep->time_of_secret_change) &&
18448c2654abSrjs (ep->current_secret_number != ep->last_secret_number)) {
18458c2654abSrjs /* compute digest with old */
18468c2654abSrjs #ifdef SCTP_DEBUG
18478c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
18488c2654abSrjs printf("sctp_handle_cookie: old cookie sig\n");
18498c2654abSrjs }
18508c2654abSrjs #endif
18518c2654abSrjs sctp_hash_digest_m((char *)ep->secret_key[(int)ep->last_secret_number],
18528c2654abSrjs SCTP_SECRET_SIZE, m, cookie_offset, calc_sig);
18538c2654abSrjs /* compare */
18548c2654abSrjs if (memcmp(calc_sig, sig, SCTP_SIGNATURE_SIZE) == 0)
18558c2654abSrjs cookie_ok = 1;
18568c2654abSrjs }
18578c2654abSrjs } else {
18588c2654abSrjs cookie_ok = 1;
18598c2654abSrjs }
18608c2654abSrjs
18618c2654abSrjs /*
18628c2654abSrjs * Now before we continue we must reconstruct our mbuf so
18638c2654abSrjs * that normal processing of any other chunks will work.
18648c2654abSrjs */
18658c2654abSrjs {
18668c2654abSrjs struct mbuf *m_at;
18678c2654abSrjs m_at = m;
18688c2654abSrjs while (m_at->m_next != NULL) {
18698c2654abSrjs m_at = m_at->m_next;
18708c2654abSrjs }
18718c2654abSrjs m_at->m_next = m_sig;
18728c2654abSrjs if (m->m_flags & M_PKTHDR) {
18738c2654abSrjs /*
18748c2654abSrjs * We should only do this if and only if the front
18758c2654abSrjs * mbuf has a m_pkthdr... it should in theory.
18768c2654abSrjs */
18778c2654abSrjs if (m_sig->m_flags & M_PKTHDR) {
18788c2654abSrjs /* Add back to the pkt hdr of main m chain */
18798c2654abSrjs m->m_pkthdr.len += m_sig->m_len;
18808c2654abSrjs } else {
18818c2654abSrjs /*
18828c2654abSrjs * Got a problem, no pkthdr in split chain.
18838c2654abSrjs * TSNH but we will handle it just in case
18848c2654abSrjs */
18858c2654abSrjs int mmlen = 0;
18868c2654abSrjs struct mbuf *lat;
18878c2654abSrjs printf("Warning: Hitting m_split join TSNH code - fixed\n");
18888c2654abSrjs lat = m_sig;
18898c2654abSrjs while (lat) {
18908c2654abSrjs mmlen += lat->m_len;
18918c2654abSrjs lat = lat->m_next;
18928c2654abSrjs }
18938c2654abSrjs m->m_pkthdr.len += mmlen;
18948c2654abSrjs }
18958c2654abSrjs }
18968c2654abSrjs }
18978c2654abSrjs
18988c2654abSrjs if (cookie_ok == 0) {
18998c2654abSrjs #ifdef SCTP_DEBUG
19008c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
19018c2654abSrjs printf("handle_cookie_echo: cookie signature validation failed!\n");
19028c2654abSrjs printf("offset = %u, cookie_offset = %u, sig_offset = %u\n",
19038c2654abSrjs (u_int32_t)offset, cookie_offset, sig_offset);
19048c2654abSrjs }
19058c2654abSrjs #endif
19068c2654abSrjs return (NULL);
19078c2654abSrjs }
19088c2654abSrjs #ifdef SCTP_DEBUG
19098c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
19108c2654abSrjs printf("handle_cookie_echo: cookie signature validation passed\n");
19118c2654abSrjs }
19128c2654abSrjs #endif
19138c2654abSrjs
19148c2654abSrjs /*
19158c2654abSrjs * check the cookie timestamps to be sure it's not stale
19168c2654abSrjs */
19178c2654abSrjs SCTP_GETTIME_TIMEVAL(&now);
19188c2654abSrjs /* Expire time is in Ticks, so we convert to seconds */
19198c2654abSrjs time_expires.tv_sec = cookie->time_entered.tv_sec + cookie->cookie_life;
19208c2654abSrjs time_expires.tv_usec = cookie->time_entered.tv_usec;
19218c2654abSrjs #ifndef __FreeBSD__
19228c2654abSrjs if (timercmp(&now, &time_expires, >))
19238c2654abSrjs #else
19248c2654abSrjs if (timevalcmp(&now, &time_expires, >))
19258c2654abSrjs #endif
19268c2654abSrjs {
19278c2654abSrjs /* cookie is stale! */
19288c2654abSrjs struct mbuf *op_err;
19298c2654abSrjs struct sctp_stale_cookie_msg *scm;
19308c2654abSrjs u_int32_t tim;
19318c2654abSrjs #ifdef SCTP_DEBUG
19328c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
19338c2654abSrjs printf("sctp_handle_cookie: got a STALE cookie!\n");
19348c2654abSrjs }
19358c2654abSrjs #endif
19368c2654abSrjs MGETHDR(op_err, M_DONTWAIT, MT_HEADER);
19378c2654abSrjs if (op_err == NULL) {
19388c2654abSrjs /* FOOBAR */
19398c2654abSrjs return (NULL);
19408c2654abSrjs }
19418c2654abSrjs /* pre-reserve some space */
19428c2654abSrjs op_err->m_data += sizeof(struct ip6_hdr);
19438c2654abSrjs op_err->m_data += sizeof(struct sctphdr);
19448c2654abSrjs op_err->m_data += sizeof(struct sctp_chunkhdr);
19458c2654abSrjs
19468c2654abSrjs /* Set the len */
19478c2654abSrjs op_err->m_len = op_err->m_pkthdr.len = sizeof(struct sctp_stale_cookie_msg);
19488c2654abSrjs scm = mtod(op_err, struct sctp_stale_cookie_msg *);
19498c2654abSrjs scm->ph.param_type = htons(SCTP_CAUSE_STALE_COOKIE);
19508c2654abSrjs scm->ph.param_length = htons((sizeof(struct sctp_paramhdr) +
19518c2654abSrjs (sizeof(u_int32_t))));
19528c2654abSrjs /* seconds to usec */
19538c2654abSrjs tim = (now.tv_sec - time_expires.tv_sec) * 1000000;
19548c2654abSrjs /* add in usec */
19558c2654abSrjs if (tim == 0)
19568c2654abSrjs tim = now.tv_usec - cookie->time_entered.tv_usec;
19578c2654abSrjs scm->time_usec = htonl(tim);
19588c2654abSrjs sctp_send_operr_to(m, iphlen, op_err, cookie->peers_vtag);
19598c2654abSrjs return (NULL);
19608c2654abSrjs }
19618c2654abSrjs /*
19628c2654abSrjs * Now we must see with the lookup address if we have an existing
19638c2654abSrjs * asoc. This will only happen if we were in the COOKIE-WAIT state
19648c2654abSrjs * and a INIT collided with us and somewhere the peer sent the
19658c2654abSrjs * cookie on another address besides the single address our assoc
19668c2654abSrjs * had for him. In this case we will have one of the tie-tags set
19678c2654abSrjs * at least AND the address field in the cookie can be used to
19688c2654abSrjs * look it up.
19698c2654abSrjs */
19708c2654abSrjs to = NULL;
19718c2654abSrjs if (cookie->addr_type == SCTP_IPV6_ADDRESS) {
19728c2654abSrjs memset(&sin6, 0, sizeof(sin6));
19738c2654abSrjs sin6.sin6_family = AF_INET6;
19748c2654abSrjs sin6.sin6_len = sizeof(sin6);
19758c2654abSrjs sin6.sin6_port = sh->src_port;
19768c2654abSrjs sin6.sin6_scope_id = cookie->scope_id;
19778c2654abSrjs memcpy(&sin6.sin6_addr.s6_addr, cookie->address,
19788c2654abSrjs sizeof(sin6.sin6_addr.s6_addr));
19798c2654abSrjs to = (struct sockaddr *)&sin6;
19808c2654abSrjs } else if (cookie->addr_type == SCTP_IPV4_ADDRESS) {
19818c2654abSrjs memset(&sin, 0, sizeof(sin));
19828c2654abSrjs sin.sin_family = AF_INET;
19838c2654abSrjs sin.sin_len = sizeof(sin);
19848c2654abSrjs sin.sin_port = sh->src_port;
19858c2654abSrjs sin.sin_addr.s_addr = cookie->address[0];
19868c2654abSrjs to = (struct sockaddr *)&sin;
19878c2654abSrjs }
19888c2654abSrjs
19898c2654abSrjs if ((*stcb == NULL) && to) {
19908c2654abSrjs /* Yep, lets check */
19918c2654abSrjs *stcb = sctp_findassociation_ep_addr(inp_p, to, netp, localep_sa, NULL);
19928c2654abSrjs if (*stcb == NULL) {
19938c2654abSrjs /* We should have only got back the same inp. If we
19948c2654abSrjs * got back a different ep we have a problem. The original
19958c2654abSrjs * findep got back l_inp and now
19968c2654abSrjs */
19978c2654abSrjs if (l_inp != *inp_p) {
19988c2654abSrjs printf("Bad problem find_ep got a diff inp then special_locate?\n");
19998c2654abSrjs }
20008c2654abSrjs }
20018c2654abSrjs }
20028c2654abSrjs
20038c2654abSrjs cookie_len -= SCTP_SIGNATURE_SIZE;
20048c2654abSrjs if (*stcb == NULL) {
20058c2654abSrjs /* this is the "normal" case... get a new TCB */
20068c2654abSrjs #ifdef SCTP_DEBUG
20078c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
20088c2654abSrjs printf("sctp_handle_cookie: processing NEW cookie\n");
20098c2654abSrjs }
20108c2654abSrjs #endif
20118c2654abSrjs *stcb = sctp_process_cookie_new(m, iphlen, offset, sh, cookie,
20128c2654abSrjs cookie_len, *inp_p, netp, to, ¬ification);
20138c2654abSrjs /* now always decrement, since this is the normal
20148c2654abSrjs * case.. we had no tcb when we entered.
20158c2654abSrjs */
20168c2654abSrjs } else {
20178c2654abSrjs /* this is abnormal... cookie-echo on existing TCB */
20188c2654abSrjs #ifdef SCTP_DEBUG
20198c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
20208c2654abSrjs printf("sctp_handle_cookie: processing EXISTING cookie\n");
20218c2654abSrjs }
20228c2654abSrjs #endif
20238c2654abSrjs had_a_existing_tcb = 1;
20248c2654abSrjs *stcb = sctp_process_cookie_existing(m, iphlen, offset, sh,
20258c2654abSrjs cookie, cookie_len, *inp_p, *stcb, *netp, to, ¬ification);
20268c2654abSrjs }
20278c2654abSrjs
20288c2654abSrjs if (*stcb == NULL) {
20298c2654abSrjs /* still no TCB... must be bad cookie-echo */
20308c2654abSrjs #ifdef SCTP_DEBUG
20318c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
20328c2654abSrjs printf("handle_cookie_echo: ACK! don't have a TCB!\n");
20338c2654abSrjs }
20348c2654abSrjs #endif /* SCTP_DEBUG */
20358c2654abSrjs return (NULL);
20368c2654abSrjs }
20378c2654abSrjs
20388c2654abSrjs /*
20398c2654abSrjs * Ok, we built an association so confirm the address
20408c2654abSrjs * we sent the INIT-ACK to.
20418c2654abSrjs */
20428c2654abSrjs netl = sctp_findnet(*stcb, to);
20438c2654abSrjs /* This code should in theory NOT run but
20448c2654abSrjs */
20458c2654abSrjs if (netl == NULL) {
20468c2654abSrjs #ifdef SCTP_DEBUG
20478c2654abSrjs printf("TSNH! Huh, why do I need to add this address here?\n");
20488c2654abSrjs #endif
20498c2654abSrjs sctp_add_remote_addr(*stcb, to, 0, 100);
20508c2654abSrjs netl = sctp_findnet(*stcb, to);
20518c2654abSrjs }
20528c2654abSrjs if (netl) {
20538c2654abSrjs if (netl->dest_state & SCTP_ADDR_UNCONFIRMED) {
20548c2654abSrjs netl->dest_state &= ~SCTP_ADDR_UNCONFIRMED;
20558c2654abSrjs sctp_set_primary_addr((*stcb), (struct sockaddr *)NULL,
20568c2654abSrjs netl);
20578c2654abSrjs sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_CONFIRMED,
20588c2654abSrjs (*stcb), 0, (void *)netl);
20598c2654abSrjs }
20608c2654abSrjs }
20618c2654abSrjs #ifdef SCTP_DEBUG
20628c2654abSrjs else {
20638c2654abSrjs printf("Could not add source address for some reason\n");
20648c2654abSrjs }
20658c2654abSrjs #endif
20668c2654abSrjs
20678c2654abSrjs if ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
20688c2654abSrjs if (!had_a_existing_tcb ||
20698c2654abSrjs (((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
20708c2654abSrjs /*
20718c2654abSrjs * If we have a NEW cookie or the connect never reached
20728c2654abSrjs * the connected state during collision we must do the
20738c2654abSrjs * TCP accept thing.
20748c2654abSrjs */
20758c2654abSrjs struct socket *so, *oso;
20768c2654abSrjs struct sctp_inpcb *inp;
20778c2654abSrjs if (notification == SCTP_NOTIFY_ASSOC_RESTART) {
20788c2654abSrjs /*
20798c2654abSrjs * For a restart we will keep the same socket,
20808c2654abSrjs * no need to do anything. I THINK!!
20818c2654abSrjs */
20828c2654abSrjs sctp_ulp_notify(notification, *stcb, 0, NULL);
20838c2654abSrjs return (m);
20848c2654abSrjs }
20858c2654abSrjs oso = (*inp_p)->sctp_socket;
20868c2654abSrjs SCTP_TCB_UNLOCK((*stcb));
20878c2654abSrjs so = sonewconn(oso, SS_ISCONNECTED);
20888c2654abSrjs SCTP_INP_WLOCK((*stcb)->sctp_ep);
20898c2654abSrjs SCTP_TCB_LOCK((*stcb));
20908c2654abSrjs SCTP_INP_WUNLOCK((*stcb)->sctp_ep);
20918c2654abSrjs if (so == NULL) {
20928c2654abSrjs struct mbuf *op_err;
20938c2654abSrjs /* Too many sockets */
20948c2654abSrjs #ifdef SCTP_DEBUG
20958c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
20968c2654abSrjs printf("process_cookie_new: no room for another socket!\n");
20978c2654abSrjs }
20988c2654abSrjs #endif /* SCTP_DEBUG */
20998c2654abSrjs op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC);
21008c2654abSrjs sctp_abort_association(*inp_p, NULL, m, iphlen,
21018c2654abSrjs sh, op_err);
21028c2654abSrjs sctp_free_assoc(*inp_p, *stcb);
21038c2654abSrjs return (NULL);
21048c2654abSrjs }
21058c2654abSrjs inp = (struct sctp_inpcb *)so->so_pcb;
21068c2654abSrjs inp->sctp_flags = (SCTP_PCB_FLAGS_TCPTYPE |
21078c2654abSrjs SCTP_PCB_FLAGS_CONNECTED |
21088c2654abSrjs SCTP_PCB_FLAGS_IN_TCPPOOL |
21098c2654abSrjs (SCTP_PCB_COPY_FLAGS & (*inp_p)->sctp_flags) |
21108c2654abSrjs SCTP_PCB_FLAGS_DONT_WAKE);
21118c2654abSrjs inp->sctp_socket = so;
21128c2654abSrjs
21138c2654abSrjs /*
21148c2654abSrjs * Now we must move it from one hash table to another
21158c2654abSrjs * and get the tcb in the right place.
21168c2654abSrjs */
21178c2654abSrjs sctp_move_pcb_and_assoc(*inp_p, inp, *stcb);
21188c2654abSrjs
21198c2654abSrjs /* Switch over to the new guy */
21208c2654abSrjs *inp_p = inp;
21218c2654abSrjs
21228c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp,
21238c2654abSrjs *stcb, *netp);
21248c2654abSrjs
21258c2654abSrjs sctp_ulp_notify(notification, *stcb, 0, NULL);
21268c2654abSrjs return (m);
21278c2654abSrjs }
21288c2654abSrjs }
21298c2654abSrjs if ((notification) && ((*inp_p)->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
21308c2654abSrjs sctp_ulp_notify(notification, *stcb, 0, NULL);
21318c2654abSrjs }
21328c2654abSrjs return (m);
21338c2654abSrjs }
21348c2654abSrjs
21358c2654abSrjs static void
sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)21368c2654abSrjs sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp,
21378c2654abSrjs struct sctp_tcb *stcb, struct sctp_nets *net)
21388c2654abSrjs {
21398c2654abSrjs /* cp must not be used, others call this without a c-ack :-) */
21408c2654abSrjs struct sctp_association *asoc;
21418c2654abSrjs
21428c2654abSrjs #ifdef SCTP_DEBUG
21438c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
21448c2654abSrjs printf("sctp_handle_cookie_ack: handling COOKIE-ACK\n");
21458c2654abSrjs }
21468c2654abSrjs #endif
21478c2654abSrjs if (stcb == NULL)
21488c2654abSrjs return;
21498c2654abSrjs
21508c2654abSrjs asoc = &stcb->asoc;
21518c2654abSrjs
21528c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE, stcb->sctp_ep, stcb, net);
21538c2654abSrjs
21548c2654abSrjs /* process according to association state */
21558c2654abSrjs if (SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED) {
21568c2654abSrjs /* state change only needed when I am in right state */
21578c2654abSrjs #ifdef SCTP_DEBUG
21588c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
21598c2654abSrjs printf("moving to OPEN state\n");
21608c2654abSrjs }
21618c2654abSrjs #endif
21628c2654abSrjs if (asoc->state & SCTP_STATE_SHUTDOWN_PENDING) {
21638c2654abSrjs asoc->state = SCTP_STATE_OPEN | SCTP_STATE_SHUTDOWN_PENDING;
21648c2654abSrjs } else {
21658c2654abSrjs asoc->state = SCTP_STATE_OPEN;
21668c2654abSrjs }
21678c2654abSrjs
21688c2654abSrjs /* update RTO */
21698c2654abSrjs if (asoc->overall_error_count == 0) {
21708c2654abSrjs net->RTO = sctp_calculate_rto(stcb, asoc, net,
21718c2654abSrjs &asoc->time_entered);
21728c2654abSrjs }
21738c2654abSrjs SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
21748c2654abSrjs sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL);
21758c2654abSrjs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
21768c2654abSrjs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
21778c2654abSrjs stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
21788c2654abSrjs soisconnected(stcb->sctp_ep->sctp_socket);
21798c2654abSrjs }
21808c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep,
21818c2654abSrjs stcb, net);
21828c2654abSrjs /* since we did not send a HB make sure we don't double things */
21838c2654abSrjs net->hb_responded = 1;
21848c2654abSrjs
21858c2654abSrjs if (stcb->asoc.sctp_autoclose_ticks &&
21868c2654abSrjs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_AUTOCLOSE)) {
21878c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_AUTOCLOSE,
21888c2654abSrjs stcb->sctp_ep, stcb, NULL);
21898c2654abSrjs }
21908c2654abSrjs
21918c2654abSrjs /*
21928c2654abSrjs * set ASCONF timer if ASCONFs are pending and allowed
21938c2654abSrjs * (eg. addresses changed when init/cookie echo in flight)
21948c2654abSrjs */
21958c2654abSrjs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_DO_ASCONF) &&
21968c2654abSrjs (stcb->asoc.peer_supports_asconf) &&
21978c2654abSrjs (!TAILQ_EMPTY(&stcb->asoc.asconf_queue))) {
21988c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_ASCONF,
21998c2654abSrjs stcb->sctp_ep, stcb,
22008c2654abSrjs stcb->asoc.primary_destination);
22018c2654abSrjs }
22028c2654abSrjs
22038c2654abSrjs }
22048c2654abSrjs /* Toss the cookie if I can */
22058c2654abSrjs sctp_toss_old_cookies(asoc);
22068c2654abSrjs if (!TAILQ_EMPTY(&asoc->sent_queue)) {
22078c2654abSrjs /* Restart the timer if we have pending data */
22088c2654abSrjs struct sctp_tmit_chunk *chk;
22098c2654abSrjs chk = TAILQ_FIRST(&asoc->sent_queue);
22108c2654abSrjs if (chk) {
22118c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
22128c2654abSrjs stcb, chk->whoTo);
22138c2654abSrjs }
22148c2654abSrjs }
22158c2654abSrjs
22168c2654abSrjs }
22178c2654abSrjs
22188c2654abSrjs static void
sctp_handle_ecn_echo(struct sctp_ecne_chunk * cp,struct sctp_tcb * stcb)22198c2654abSrjs sctp_handle_ecn_echo(struct sctp_ecne_chunk *cp,
22208c2654abSrjs struct sctp_tcb *stcb)
22218c2654abSrjs {
22228c2654abSrjs struct sctp_nets *net;
22238c2654abSrjs struct sctp_tmit_chunk *lchk;
22248c2654abSrjs u_int32_t tsn;
22258c2654abSrjs if (ntohs(cp->ch.chunk_length) != sizeof(struct sctp_ecne_chunk)) {
22268c2654abSrjs return;
22278c2654abSrjs }
22288c2654abSrjs sctp_pegs[SCTP_ECNE_RCVD]++;
22298c2654abSrjs tsn = ntohl(cp->tsn);
22308c2654abSrjs /* ECN Nonce stuff: need a resync and disable the nonce sum check */
22318c2654abSrjs /* Also we make sure we disable the nonce_wait */
22328c2654abSrjs lchk = TAILQ_FIRST(&stcb->asoc.send_queue);
22338c2654abSrjs if (lchk == NULL) {
22348c2654abSrjs stcb->asoc.nonce_resync_tsn = stcb->asoc.sending_seq;
22358c2654abSrjs } else {
22368c2654abSrjs stcb->asoc.nonce_resync_tsn = lchk->rec.data.TSN_seq;
22378c2654abSrjs }
22388c2654abSrjs stcb->asoc.nonce_wait_for_ecne = 0;
22398c2654abSrjs stcb->asoc.nonce_sum_check = 0;
22408c2654abSrjs
22418c2654abSrjs /* Find where it was sent, if possible */
22428c2654abSrjs net = NULL;
22438c2654abSrjs lchk = TAILQ_FIRST(&stcb->asoc.sent_queue);
22448c2654abSrjs while (lchk) {
22458c2654abSrjs if (lchk->rec.data.TSN_seq == tsn) {
22468c2654abSrjs net = lchk->whoTo;
22478c2654abSrjs break;
22488c2654abSrjs }
22498c2654abSrjs if (compare_with_wrap(lchk->rec.data.TSN_seq, tsn, MAX_SEQ))
22508c2654abSrjs break;
22518c2654abSrjs lchk = TAILQ_NEXT(lchk, sctp_next);
22528c2654abSrjs }
22538c2654abSrjs if (net == NULL)
22548c2654abSrjs /* default is we use the primary */
22558c2654abSrjs net = stcb->asoc.primary_destination;
22568c2654abSrjs
22578c2654abSrjs if (compare_with_wrap(tsn, stcb->asoc.last_cwr_tsn, MAX_TSN)) {
22588c2654abSrjs #ifdef SCTP_CWND_LOGGING
22598c2654abSrjs int old_cwnd;
22608c2654abSrjs #endif
22618c2654abSrjs #ifdef SCTP_CWND_LOGGING
22628c2654abSrjs old_cwnd = net->cwnd;
22638c2654abSrjs #endif
22648c2654abSrjs sctp_pegs[SCTP_CWR_PERFO]++;
22658c2654abSrjs net->ssthresh = net->cwnd / 2;
22668c2654abSrjs if (net->ssthresh < net->mtu) {
22678c2654abSrjs net->ssthresh = net->mtu;
22688c2654abSrjs /* here back off the timer as well, to slow us down */
22698c2654abSrjs net->RTO <<= 2;
22708c2654abSrjs }
22718c2654abSrjs net->cwnd = net->ssthresh;
22728c2654abSrjs #ifdef SCTP_CWND_LOGGING
22738c2654abSrjs sctp_log_cwnd(net, (net->cwnd-old_cwnd), SCTP_CWND_LOG_FROM_SAT);
22748c2654abSrjs #endif
22758c2654abSrjs /* we reduce once every RTT. So we will only lower
22768c2654abSrjs * cwnd at the next sending seq i.e. the resync_tsn.
22778c2654abSrjs */
22788c2654abSrjs stcb->asoc.last_cwr_tsn = stcb->asoc.nonce_resync_tsn;
22798c2654abSrjs }
22808c2654abSrjs /*
22818c2654abSrjs * We always send a CWR this way if our previous one was lost
22828c2654abSrjs * our peer will get an update, or if it is not time again
22838c2654abSrjs * to reduce we still get the cwr to the peer.
22848c2654abSrjs */
22858c2654abSrjs sctp_send_cwr(stcb, net, tsn);
22868c2654abSrjs }
22878c2654abSrjs
22888c2654abSrjs static void
sctp_handle_ecn_cwr(struct sctp_cwr_chunk * cp,struct sctp_tcb * stcb)22898c2654abSrjs sctp_handle_ecn_cwr(struct sctp_cwr_chunk *cp, struct sctp_tcb *stcb)
22908c2654abSrjs {
22918c2654abSrjs /* Here we get a CWR from the peer. We must look in
22928c2654abSrjs * the outqueue and make sure that we have a covered
22938c2654abSrjs * ECNE in teh control chunk part. If so remove it.
22948c2654abSrjs */
22958c2654abSrjs struct sctp_tmit_chunk *chk;
22968c2654abSrjs struct sctp_ecne_chunk *ecne;
22978c2654abSrjs
22988c2654abSrjs TAILQ_FOREACH(chk, &stcb->asoc.control_send_queue, sctp_next) {
22998c2654abSrjs if (chk->rec.chunk_id != SCTP_ECN_ECHO) {
23008c2654abSrjs continue;
23018c2654abSrjs }
23028c2654abSrjs /* Look for and remove if it is the right TSN. Since
23038c2654abSrjs * there is only ONE ECNE on the control queue at
23048c2654abSrjs * any one time we don't need to worry about more than
23058c2654abSrjs * one!
23068c2654abSrjs */
23078c2654abSrjs ecne = mtod(chk->data, struct sctp_ecne_chunk *);
23088c2654abSrjs if (compare_with_wrap(ntohl(cp->tsn), ntohl(ecne->tsn),
23098c2654abSrjs MAX_TSN) || (cp->tsn == ecne->tsn)) {
23108c2654abSrjs /* this covers this ECNE, we can remove it */
23118c2654abSrjs TAILQ_REMOVE(&stcb->asoc.control_send_queue, chk,
23128c2654abSrjs sctp_next);
23138c2654abSrjs sctp_m_freem(chk->data);
23148c2654abSrjs chk->data = NULL;
23158c2654abSrjs stcb->asoc.ctrl_queue_cnt--;
23168c2654abSrjs sctp_free_remote_addr(chk->whoTo);
23178c2654abSrjs SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
23188c2654abSrjs sctppcbinfo.ipi_count_chunk--;
23198c2654abSrjs if ((int)sctppcbinfo.ipi_count_chunk < 0) {
23208c2654abSrjs panic("Chunk count is negative");
23218c2654abSrjs }
23228c2654abSrjs sctppcbinfo.ipi_gencnt_chunk++;
23238c2654abSrjs break;
23248c2654abSrjs }
23258c2654abSrjs }
23268c2654abSrjs }
23278c2654abSrjs
23288c2654abSrjs static void
sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)23298c2654abSrjs sctp_handle_shutdown_complete(struct sctp_shutdown_complete_chunk *cp,
23308c2654abSrjs struct sctp_tcb *stcb, struct sctp_nets *net)
23318c2654abSrjs {
23328c2654abSrjs struct sctp_association *asoc;
23338c2654abSrjs
23348c2654abSrjs #ifdef SCTP_DEBUG
23358c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
23368c2654abSrjs printf("sctp_handle_shutdown_complete: handling SHUTDOWN-COMPLETE\n");
23378c2654abSrjs }
23388c2654abSrjs #endif
23398c2654abSrjs if (stcb == NULL)
23408c2654abSrjs return;
23418c2654abSrjs
23428c2654abSrjs asoc = &stcb->asoc;
23438c2654abSrjs /* process according to association state */
23448c2654abSrjs if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT) {
23458c2654abSrjs /* unexpected SHUTDOWN-COMPLETE... so ignore... */
23468c2654abSrjs return;
23478c2654abSrjs }
23488c2654abSrjs /* notify upper layer protocol */
23498c2654abSrjs sctp_ulp_notify(SCTP_NOTIFY_ASSOC_DOWN, stcb, 0, NULL);
23508c2654abSrjs if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
23518c2654abSrjs (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
23528c2654abSrjs stcb->sctp_ep->sctp_flags &= ~SCTP_PCB_FLAGS_CONNECTED;
23538c2654abSrjs stcb->sctp_ep->sctp_socket->so_snd.sb_cc = 0;
23548c2654abSrjs stcb->sctp_ep->sctp_socket->so_snd.sb_mbcnt = 0;
23558c2654abSrjs soisdisconnected(stcb->sctp_ep->sctp_socket);
23568c2654abSrjs }
23578c2654abSrjs /* are the queues empty? they should be */
23588c2654abSrjs if (!TAILQ_EMPTY(&asoc->send_queue) ||
23598c2654abSrjs !TAILQ_EMPTY(&asoc->sent_queue) ||
23608c2654abSrjs !TAILQ_EMPTY(&asoc->out_wheel)) {
23618c2654abSrjs sctp_report_all_outbound(stcb);
23628c2654abSrjs }
23638c2654abSrjs /* stop the timer */
23648c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_SHUTDOWN, stcb->sctp_ep, stcb, net);
23658c2654abSrjs /* free the TCB */
23668c2654abSrjs sctp_free_assoc(stcb->sctp_ep, stcb);
23678c2654abSrjs return;
23688c2654abSrjs }
23698c2654abSrjs
23708c2654abSrjs static int
process_chunk_drop(struct sctp_tcb * stcb,struct sctp_chunk_desc * desc,struct sctp_nets * net,u_int8_t flg)23718c2654abSrjs process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
23728c2654abSrjs struct sctp_nets *net, u_int8_t flg)
23738c2654abSrjs {
23748c2654abSrjs switch (desc->chunk_type) {
23758c2654abSrjs case SCTP_DATA:
23768c2654abSrjs /* find the tsn to resend (possibly */
23778c2654abSrjs {
23788c2654abSrjs u_int32_t tsn;
23798c2654abSrjs struct sctp_tmit_chunk *tp1;
23808c2654abSrjs tsn = ntohl(desc->tsn_ifany);
23818c2654abSrjs tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue);
23828c2654abSrjs while (tp1) {
23838c2654abSrjs if (tp1->rec.data.TSN_seq == tsn) {
23848c2654abSrjs /* found it */
23858c2654abSrjs break;
23868c2654abSrjs }
23878c2654abSrjs if (compare_with_wrap(tp1->rec.data.TSN_seq, tsn,
23888c2654abSrjs MAX_TSN)) {
23898c2654abSrjs /* not found */
23908c2654abSrjs tp1 = NULL;
23918c2654abSrjs break;
23928c2654abSrjs }
23938c2654abSrjs tp1 = TAILQ_NEXT(tp1, sctp_next);
23948c2654abSrjs }
23958c2654abSrjs if (tp1 == NULL) {
23968c2654abSrjs /* Do it the other way */
23978c2654abSrjs sctp_pegs[SCTP_PDRP_DNFND]++;
23988c2654abSrjs tp1 = TAILQ_FIRST(&stcb->asoc.sent_queue);
23998c2654abSrjs while (tp1) {
24008c2654abSrjs if (tp1->rec.data.TSN_seq == tsn) {
24018c2654abSrjs /* found it */
24028c2654abSrjs break;
24038c2654abSrjs }
24048c2654abSrjs tp1 = TAILQ_NEXT(tp1, sctp_next);
24058c2654abSrjs }
24068c2654abSrjs }
24078c2654abSrjs if (tp1 == NULL) {
24088c2654abSrjs sctp_pegs[SCTP_PDRP_TSNNF]++;
24098c2654abSrjs }
24108c2654abSrjs if ((tp1) && (tp1->sent < SCTP_DATAGRAM_ACKED)) {
24118c2654abSrjs u_int8_t *ddp;
24128c2654abSrjs if (((tp1->rec.data.state_flags & SCTP_WINDOW_PROBE) == SCTP_WINDOW_PROBE) &&
24138c2654abSrjs ((flg & SCTP_FROM_MIDDLE_BOX) == 0)) {
24148c2654abSrjs sctp_pegs[SCTP_PDRP_DIWNP]++;
24158c2654abSrjs return (0);
24168c2654abSrjs }
24178c2654abSrjs if (stcb->asoc.peers_rwnd == 0 &&
24188c2654abSrjs (flg & SCTP_FROM_MIDDLE_BOX)) {
24198c2654abSrjs sctp_pegs[SCTP_PDRP_DIZRW]++;
24208c2654abSrjs return (0);
24218c2654abSrjs }
24228c2654abSrjs ddp = (u_int8_t *)(mtod(tp1->data, vaddr_t) +
24238c2654abSrjs sizeof(struct sctp_data_chunk));
24248c2654abSrjs {
24258c2654abSrjs unsigned int iii;
24268c2654abSrjs for (iii = 0; iii < sizeof(desc->data_bytes);
24278c2654abSrjs iii++) {
24288c2654abSrjs if (ddp[iii] != desc->data_bytes[iii]) {
24298c2654abSrjs sctp_pegs[SCTP_PDRP_BADD]++;
24308c2654abSrjs return (-1);
24318c2654abSrjs }
24328c2654abSrjs }
24338c2654abSrjs }
24348c2654abSrjs if (tp1->sent != SCTP_DATAGRAM_RESEND) {
24358c2654abSrjs stcb->asoc.sent_queue_retran_cnt++;
24368c2654abSrjs }
24378c2654abSrjs /* We zero out the nonce so resync not needed */
24388c2654abSrjs tp1->rec.data.ect_nonce = 0;
24398c2654abSrjs
24408c2654abSrjs if (tp1->do_rtt) {
24418c2654abSrjs /*
24428c2654abSrjs * this guy had a RTO calculation pending on it,
24438c2654abSrjs * cancel it
24448c2654abSrjs */
24458c2654abSrjs tp1->whoTo->rto_pending = 0;
24468c2654abSrjs tp1->do_rtt = 0;
24478c2654abSrjs }
24488c2654abSrjs sctp_pegs[SCTP_PDRP_MARK]++;
24498c2654abSrjs tp1->sent = SCTP_DATAGRAM_RESEND;
24508c2654abSrjs /*
24518c2654abSrjs * mark it as if we were doing a FR, since we
24528c2654abSrjs * will be getting gap ack reports behind the
24538c2654abSrjs * info from the router.
24548c2654abSrjs */
24558c2654abSrjs tp1->rec.data.doing_fast_retransmit = 1;
24568c2654abSrjs /*
24578c2654abSrjs * mark the tsn with what sequences can cause a new FR.
24588c2654abSrjs */
24598c2654abSrjs if (TAILQ_EMPTY(&stcb->asoc.send_queue) ) {
24608c2654abSrjs tp1->rec.data.fast_retran_tsn = stcb->asoc.sending_seq;
24618c2654abSrjs } else {
24628c2654abSrjs tp1->rec.data.fast_retran_tsn = (TAILQ_FIRST(&stcb->asoc.send_queue))->rec.data.TSN_seq;
24638c2654abSrjs }
24648c2654abSrjs
24658c2654abSrjs /* restart the timer */
24668c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
24678c2654abSrjs stcb, tp1->whoTo);
24688c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_SEND, stcb->sctp_ep,
24698c2654abSrjs stcb, tp1->whoTo);
24708c2654abSrjs
24718c2654abSrjs /* fix counts and things */
24728c2654abSrjs sctp_flight_size_decrease(tp1);
24738c2654abSrjs sctp_total_flight_decrease(stcb, tp1);
24748c2654abSrjs tp1->snd_count--;
24758c2654abSrjs }
24768c2654abSrjs {
24778c2654abSrjs /* audit code */
24788c2654abSrjs unsigned int audit;
24798c2654abSrjs audit = 0;
24808c2654abSrjs TAILQ_FOREACH(tp1, &stcb->asoc.sent_queue, sctp_next) {
24818c2654abSrjs if (tp1->sent == SCTP_DATAGRAM_RESEND)
24828c2654abSrjs audit++;
24838c2654abSrjs }
24848c2654abSrjs TAILQ_FOREACH(tp1, &stcb->asoc.control_send_queue,
24858c2654abSrjs sctp_next) {
24868c2654abSrjs if (tp1->sent == SCTP_DATAGRAM_RESEND)
24878c2654abSrjs audit++;
24888c2654abSrjs }
24898c2654abSrjs if (audit != stcb->asoc.sent_queue_retran_cnt) {
24908c2654abSrjs printf("**Local Audit finds cnt:%d asoc cnt:%d\n",
24918c2654abSrjs audit, stcb->asoc.sent_queue_retran_cnt);
24928c2654abSrjs #ifndef SCTP_AUDITING_ENABLED
24938c2654abSrjs stcb->asoc.sent_queue_retran_cnt = audit;
24948c2654abSrjs #endif
24958c2654abSrjs }
24968c2654abSrjs }
24978c2654abSrjs }
24988c2654abSrjs break;
24998c2654abSrjs case SCTP_ASCONF:
25008c2654abSrjs {
25018c2654abSrjs struct sctp_tmit_chunk *asconf;
25028c2654abSrjs TAILQ_FOREACH(asconf, &stcb->asoc.control_send_queue,
25038c2654abSrjs sctp_next) {
25048c2654abSrjs if (asconf->rec.chunk_id == SCTP_ASCONF) {
25058c2654abSrjs break;
25068c2654abSrjs }
25078c2654abSrjs }
25088c2654abSrjs if (asconf) {
25098c2654abSrjs if (asconf->sent != SCTP_DATAGRAM_RESEND)
25108c2654abSrjs stcb->asoc.sent_queue_retran_cnt++;
25118c2654abSrjs asconf->sent = SCTP_DATAGRAM_RESEND;
25128c2654abSrjs asconf->snd_count--;
25138c2654abSrjs }
25148c2654abSrjs }
25158c2654abSrjs break;
25168c2654abSrjs case SCTP_INITIATION:
25178c2654abSrjs /* resend the INIT */
25188c2654abSrjs stcb->asoc.dropped_special_cnt++;
25198c2654abSrjs if (stcb->asoc.dropped_special_cnt < SCTP_RETRY_DROPPED_THRESH) {
25208c2654abSrjs /*
25218c2654abSrjs * If we can get it in, in a few attempts we do this,
25228c2654abSrjs * otherwise we let the timer fire.
25238c2654abSrjs */
25248c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_INIT, stcb->sctp_ep,
25258c2654abSrjs stcb, net);
25268c2654abSrjs sctp_send_initiate(stcb->sctp_ep, stcb);
25278c2654abSrjs }
25288c2654abSrjs break;
25298c2654abSrjs case SCTP_SELECTIVE_ACK:
25308c2654abSrjs /* resend the sack */
25318c2654abSrjs sctp_send_sack(stcb);
25328c2654abSrjs break;
25338c2654abSrjs case SCTP_HEARTBEAT_REQUEST:
25348c2654abSrjs /* resend a demand HB */
25358c2654abSrjs sctp_send_hb(stcb, 1, net);
25368c2654abSrjs break;
25378c2654abSrjs case SCTP_SHUTDOWN:
25388c2654abSrjs #ifdef SCTP_DEBUG
25398c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_OUTPUT4) {
25408c2654abSrjs printf("%s:%d sends a shutdown\n",
25418c2654abSrjs __FILE__,
25428c2654abSrjs __LINE__
25438c2654abSrjs );
25448c2654abSrjs }
25458c2654abSrjs #endif
25468c2654abSrjs sctp_send_shutdown(stcb, net);
25478c2654abSrjs break;
25488c2654abSrjs case SCTP_SHUTDOWN_ACK:
25498c2654abSrjs sctp_send_shutdown_ack(stcb, net);
25508c2654abSrjs break;
25518c2654abSrjs case SCTP_COOKIE_ECHO:
25528c2654abSrjs {
25538c2654abSrjs struct sctp_tmit_chunk *cookie;
25548c2654abSrjs cookie = NULL;
25558c2654abSrjs TAILQ_FOREACH(cookie, &stcb->asoc.control_send_queue,
25568c2654abSrjs sctp_next) {
25578c2654abSrjs if (cookie->rec.chunk_id == SCTP_COOKIE_ECHO) {
25588c2654abSrjs break;
25598c2654abSrjs }
25608c2654abSrjs }
25618c2654abSrjs if (cookie) {
25628c2654abSrjs if (cookie->sent != SCTP_DATAGRAM_RESEND)
25638c2654abSrjs stcb->asoc.sent_queue_retran_cnt++;
25648c2654abSrjs cookie->sent = SCTP_DATAGRAM_RESEND;
25658c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_COOKIE, stcb->sctp_ep, stcb, net);
25668c2654abSrjs }
25678c2654abSrjs }
25688c2654abSrjs break;
25698c2654abSrjs case SCTP_COOKIE_ACK:
25708c2654abSrjs sctp_send_cookie_ack(stcb);
25718c2654abSrjs break;
25728c2654abSrjs case SCTP_ASCONF_ACK:
25738c2654abSrjs /* resend last asconf ack */
25748c2654abSrjs sctp_send_asconf_ack(stcb, 1);
25758c2654abSrjs break;
25768c2654abSrjs case SCTP_FORWARD_CUM_TSN:
25778c2654abSrjs send_forward_tsn(stcb, &stcb->asoc);
25788c2654abSrjs break;
25798c2654abSrjs /* can't do anything with these */
25808c2654abSrjs case SCTP_PACKET_DROPPED:
25818c2654abSrjs case SCTP_INITIATION_ACK: /* this should not happen */
25828c2654abSrjs case SCTP_HEARTBEAT_ACK:
25838c2654abSrjs case SCTP_ABORT_ASSOCIATION:
25848c2654abSrjs case SCTP_OPERATION_ERROR:
25858c2654abSrjs case SCTP_SHUTDOWN_COMPLETE:
25868c2654abSrjs case SCTP_ECN_ECHO:
25878c2654abSrjs case SCTP_ECN_CWR:
25888c2654abSrjs default:
25898c2654abSrjs break;
25908c2654abSrjs }
25918c2654abSrjs return (0);
25928c2654abSrjs }
25938c2654abSrjs
25948c2654abSrjs static void
sctp_reset_in_stream(struct sctp_tcb * stcb,struct sctp_stream_reset_response * resp,int number_entries)25958c2654abSrjs sctp_reset_in_stream(struct sctp_tcb *stcb,
25968c2654abSrjs struct sctp_stream_reset_response *resp, int number_entries)
25978c2654abSrjs {
25988c2654abSrjs int i;
25998c2654abSrjs uint16_t *list, temp;
26008c2654abSrjs
26018c2654abSrjs /* We set things to 0xffff since this is the last delivered
26028c2654abSrjs * sequence and we will be sending in 0 after the reset.
26038c2654abSrjs */
26048c2654abSrjs
26058c2654abSrjs if (resp->reset_flags & SCTP_RESET_PERFORMED) {
26068c2654abSrjs if (number_entries) {
26078c2654abSrjs list = resp->list_of_streams;
26088c2654abSrjs for (i = 0; i < number_entries; i++) {
26098c2654abSrjs temp = ntohs(list[i]);
26108c2654abSrjs list[i] = temp;
26118c2654abSrjs if (list[i] >= stcb->asoc.streamincnt) {
26128c2654abSrjs printf("Invalid stream in-stream reset %d\n", list[i]);
26138c2654abSrjs continue;
26148c2654abSrjs }
26158c2654abSrjs stcb->asoc.strmin[(list[i])].last_sequence_delivered = 0xffff;
26168c2654abSrjs }
26178c2654abSrjs } else {
26188c2654abSrjs list = NULL;
26198c2654abSrjs for (i = 0; i < stcb->asoc.streamincnt; i++) {
26208c2654abSrjs stcb->asoc.strmin[i].last_sequence_delivered = 0xffff;
26218c2654abSrjs }
26228c2654abSrjs }
26238c2654abSrjs sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_RECV, stcb, number_entries, (void *)list);
26248c2654abSrjs }
26258c2654abSrjs }
26268c2654abSrjs
26278c2654abSrjs static void
sctp_clean_up_stream_reset(struct sctp_tcb * stcb)26288c2654abSrjs sctp_clean_up_stream_reset(struct sctp_tcb *stcb)
26298c2654abSrjs {
26308c2654abSrjs struct sctp_tmit_chunk *chk, *nchk;
26318c2654abSrjs struct sctp_association *asoc;
26328c2654abSrjs
26338c2654abSrjs asoc = &stcb->asoc;
26348c2654abSrjs
26358c2654abSrjs for (chk = TAILQ_FIRST(&asoc->control_send_queue);
26368c2654abSrjs chk; chk = nchk) {
26378c2654abSrjs nchk = TAILQ_NEXT(chk, sctp_next);
26388c2654abSrjs if (chk->rec.chunk_id == SCTP_STREAM_RESET) {
26398c2654abSrjs struct sctp_stream_reset_req *strreq;
26408c2654abSrjs strreq = mtod(chk->data, struct sctp_stream_reset_req *);
26418c2654abSrjs if (strreq->sr_req.ph.param_type == ntohs(SCTP_STR_RESET_RESPONSE)) {
26428c2654abSrjs /* we only clean up the request */
26438c2654abSrjs continue;
26448c2654abSrjs } else if (strreq->sr_req.ph.param_type != ntohs(SCTP_STR_RESET_REQUEST)) {
26458c2654abSrjs printf("TSNH, an unknown stream reset request is in queue %x\n",
26468c2654abSrjs (u_int)ntohs(strreq->sr_req.ph.param_type));
26478c2654abSrjs continue;
26488c2654abSrjs }
26498c2654abSrjs sctp_timer_stop(SCTP_TIMER_TYPE_STRRESET, stcb->sctp_ep, stcb, chk->whoTo);
26508c2654abSrjs TAILQ_REMOVE(&asoc->control_send_queue,
26518c2654abSrjs chk,
26528c2654abSrjs sctp_next);
26538c2654abSrjs sctp_m_freem(chk->data);
26548c2654abSrjs chk->data = NULL;
26558c2654abSrjs asoc->ctrl_queue_cnt--;
26568c2654abSrjs sctp_free_remote_addr(chk->whoTo);
26578c2654abSrjs SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
26588c2654abSrjs sctppcbinfo.ipi_count_chunk--;
26598c2654abSrjs if ((int)sctppcbinfo.ipi_count_chunk < 0) {
26608c2654abSrjs panic("Chunk count is negative");
26618c2654abSrjs }
26628c2654abSrjs sctppcbinfo.ipi_gencnt_chunk++;
26638c2654abSrjs /* we can only have one of these so we break */
26648c2654abSrjs break;
26658c2654abSrjs }
26668c2654abSrjs }
26678c2654abSrjs }
26688c2654abSrjs
26698c2654abSrjs
26708c2654abSrjs void
sctp_handle_stream_reset_response(struct sctp_tcb * stcb,struct sctp_stream_reset_response * resp)26718c2654abSrjs sctp_handle_stream_reset_response(struct sctp_tcb *stcb,
26728c2654abSrjs struct sctp_stream_reset_response *resp)
26738c2654abSrjs {
26748c2654abSrjs uint32_t seq, tsn;
26758c2654abSrjs int number_entries, param_length;
26768c2654abSrjs
26778c2654abSrjs param_length = ntohs(resp->ph.param_length);
26788c2654abSrjs seq = ntohl(resp->reset_req_seq_resp);
26798c2654abSrjs if (seq == stcb->asoc.str_reset_seq_out) {
26808c2654abSrjs sctp_clean_up_stream_reset(stcb);
26818c2654abSrjs stcb->asoc.str_reset_seq_out++;
26828c2654abSrjs stcb->asoc.stream_reset_outstanding = 0;
26838c2654abSrjs tsn = ntohl(resp->reset_at_tsn);
26848c2654abSrjs number_entries = (param_length - sizeof(struct sctp_stream_reset_response))/sizeof(uint16_t);
26858c2654abSrjs tsn--;
26868c2654abSrjs if ((tsn == stcb->asoc.cumulative_tsn) ||
26878c2654abSrjs (compare_with_wrap(stcb->asoc.cumulative_tsn, tsn, MAX_TSN))) {
26888c2654abSrjs /* no problem we are good to go */
26898c2654abSrjs sctp_reset_in_stream(stcb, resp, number_entries);
26908c2654abSrjs } else {
26918c2654abSrjs /* So, we have a stream reset but there
26928c2654abSrjs * is pending data. We need to copy
26938c2654abSrjs * out the stream_reset and then queue
26948c2654abSrjs * any data = or > resp->reset_at_tsn
26958c2654abSrjs */
26968c2654abSrjs if (stcb->asoc.pending_reply != NULL) {
26978c2654abSrjs /* FIX ME FIX ME
26988c2654abSrjs * This IS WRONG. We need
26998c2654abSrjs * to queue each of these up
27008c2654abSrjs * and only release the chunks
27018c2654abSrjs * for each reset that the cum-ack
27028c2654abSrjs * goes by. This is a short cut.
27038c2654abSrjs */
27048c2654abSrjs free(stcb->asoc.pending_reply, M_PCB);
27058c2654abSrjs }
27068c2654abSrjs stcb->asoc.pending_reply = malloc(param_length,
27078c2654abSrjs M_PCB, M_NOWAIT);
27088c2654abSrjs memcpy(stcb->asoc.pending_reply, resp, param_length);
27098c2654abSrjs }
27108c2654abSrjs
27118c2654abSrjs } else {
27128c2654abSrjs /* duplicate */
27138c2654abSrjs #ifdef SCTP_DEBUG
27148c2654abSrjs printf("Duplicate old stream reset resp next:%x this one:%x\n",
27158c2654abSrjs stcb->asoc.str_reset_seq_out, seq);
27168c2654abSrjs #endif
27178c2654abSrjs }
27188c2654abSrjs }
27198c2654abSrjs
27208c2654abSrjs
27218c2654abSrjs static void
sctp_handle_stream_reset(struct sctp_tcb * stcb,struct sctp_stream_reset_req * sr_req)27228c2654abSrjs sctp_handle_stream_reset(struct sctp_tcb *stcb, struct sctp_stream_reset_req *sr_req)
27238c2654abSrjs {
27248c2654abSrjs int chk_length, param_len;
27258c2654abSrjs struct sctp_paramhdr *ph;
27268c2654abSrjs /* now it may be a reset or a reset-response */
27278c2654abSrjs struct sctp_stream_reset_request *req;
27288c2654abSrjs struct sctp_stream_reset_response *resp;
27298c2654abSrjs chk_length = ntohs(sr_req->ch.chunk_length);
27308c2654abSrjs
27318c2654abSrjs ph = (struct sctp_paramhdr *)&sr_req->sr_req;
27328c2654abSrjs while ((size_t)chk_length >= sizeof(struct sctp_stream_reset_request)) {
27338c2654abSrjs param_len = ntohs(ph->param_length);
27348c2654abSrjs if (ntohs(ph->param_type) == SCTP_STR_RESET_REQUEST) {
27358c2654abSrjs /* this will send the ACK and do the reset if needed */
27368c2654abSrjs req = (struct sctp_stream_reset_request *)ph;
27378c2654abSrjs sctp_send_str_reset_ack(stcb, req);
27388c2654abSrjs } else if (ntohs(ph->param_type) == SCTP_STR_RESET_RESPONSE) {
27398c2654abSrjs /* Now here is a tricky one. We reset our receive side
27408c2654abSrjs * of the streams. But what happens if the peers
27418c2654abSrjs * next sending TSN is NOT equal to 1 minus our cumack?
27428c2654abSrjs * And if his cumack is not equal to our next one out - 1
27438c2654abSrjs * we have another problem if this is receprical.
27448c2654abSrjs */
27458c2654abSrjs resp = (struct sctp_stream_reset_response *)ph;
27468c2654abSrjs sctp_handle_stream_reset_response(stcb, resp);
27478c2654abSrjs }
27488c2654abSrjs ph = (struct sctp_paramhdr *)((vaddr_t)ph + SCTP_SIZE32(param_len));
27498c2654abSrjs chk_length -= SCTP_SIZE32(param_len);
27508c2654abSrjs }
27518c2654abSrjs }
27528c2654abSrjs
27538c2654abSrjs /*
27548c2654abSrjs * Handle a router or endpoints report of a packet loss, there
27558c2654abSrjs * are two ways to handle this, either we get the whole packet
27568c2654abSrjs * and must disect it ourselves (possibly with truncation and
27578c2654abSrjs * or corruption) or it is a summary from a middle box that did
27588c2654abSrjs * the disectting for us.
27598c2654abSrjs */
27608c2654abSrjs static void
sctp_handle_packet_dropped(struct sctp_pktdrop_chunk * cp,struct sctp_tcb * stcb,struct sctp_nets * net)27618c2654abSrjs sctp_handle_packet_dropped(struct sctp_pktdrop_chunk *cp,
27628c2654abSrjs struct sctp_tcb *stcb, struct sctp_nets *net)
27638c2654abSrjs {
27648c2654abSrjs u_int32_t bottle_bw, on_queue;
27658c2654abSrjs u_int16_t trunc_len;
27668c2654abSrjs unsigned int chlen;
27678c2654abSrjs unsigned int at;
27688c2654abSrjs struct sctp_chunk_desc desc;
27698c2654abSrjs struct sctp_chunkhdr *ch;
27708c2654abSrjs
27718c2654abSrjs chlen = ntohs(cp->ch.chunk_length);
27728c2654abSrjs chlen -= sizeof(struct sctp_pktdrop_chunk);
27738c2654abSrjs /* XXX possible chlen underflow */
27748c2654abSrjs if (chlen == 0) {
27758c2654abSrjs ch = NULL;
27768c2654abSrjs if (cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX)
27778c2654abSrjs sctp_pegs[SCTP_PDRP_BWRPT]++;
27788c2654abSrjs } else {
27798c2654abSrjs ch = (struct sctp_chunkhdr *)(cp->data + sizeof(struct sctphdr));
27808c2654abSrjs chlen -= sizeof(struct sctphdr);
27818c2654abSrjs /* XXX possible chlen underflow */
27828c2654abSrjs memset(&desc, 0, sizeof(desc));
27838c2654abSrjs }
27848c2654abSrjs
27858c2654abSrjs /* first update a rwnd possibly */
27868c2654abSrjs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) == 0) {
27878c2654abSrjs /* From a peer, we get a rwnd report */
27888c2654abSrjs u_int32_t a_rwnd;
27898c2654abSrjs
27908c2654abSrjs sctp_pegs[SCTP_PDRP_FEHOS]++;
27918c2654abSrjs
27928c2654abSrjs bottle_bw = ntohl(cp->bottle_bw);
27938c2654abSrjs on_queue = ntohl(cp->current_onq);
27948c2654abSrjs if (bottle_bw && on_queue) {
27958c2654abSrjs /* a rwnd report is in here */
27968c2654abSrjs if (bottle_bw > on_queue)
27978c2654abSrjs a_rwnd = bottle_bw - on_queue;
27988c2654abSrjs else
27998c2654abSrjs a_rwnd = 0;
28008c2654abSrjs
28018c2654abSrjs if (a_rwnd <= 0)
28028c2654abSrjs stcb->asoc.peers_rwnd = 0;
28038c2654abSrjs else {
28048c2654abSrjs if (a_rwnd > stcb->asoc.total_flight) {
28058c2654abSrjs stcb->asoc.peers_rwnd =
28068c2654abSrjs a_rwnd - stcb->asoc.total_flight;
28078c2654abSrjs } else {
28088c2654abSrjs stcb->asoc.peers_rwnd = 0;
28098c2654abSrjs }
28108c2654abSrjs if (stcb->asoc.peers_rwnd <
28118c2654abSrjs stcb->sctp_ep->sctp_ep.sctp_sws_sender) {
28128c2654abSrjs /* SWS sender side engages */
28138c2654abSrjs stcb->asoc.peers_rwnd = 0;
28148c2654abSrjs }
28158c2654abSrjs }
28168c2654abSrjs }
28178c2654abSrjs } else {
28188c2654abSrjs sctp_pegs[SCTP_PDRP_FMBOX]++;
28198c2654abSrjs }
28208c2654abSrjs trunc_len = (u_int16_t)ntohs(cp->trunc_len);
28218c2654abSrjs /* now the chunks themselves */
28228c2654abSrjs while ((ch != NULL) && (chlen >= sizeof(struct sctp_chunkhdr))) {
28238c2654abSrjs desc.chunk_type = ch->chunk_type;
28248c2654abSrjs /* get amount we need to move */
28258c2654abSrjs at = ntohs(ch->chunk_length);
28268c2654abSrjs if (at < sizeof(struct sctp_chunkhdr)) {
28278c2654abSrjs /* corrupt chunk, maybe at the end? */
28288c2654abSrjs sctp_pegs[SCTP_PDRP_CRUPT]++;
28298c2654abSrjs break;
28308c2654abSrjs }
28318c2654abSrjs if (trunc_len == 0) {
28328c2654abSrjs /* we are supposed to have all of it */
28338c2654abSrjs if (at > chlen) {
28348c2654abSrjs /* corrupt skip it */
28358c2654abSrjs sctp_pegs[SCTP_PDRP_CRUPT]++;
28368c2654abSrjs break;
28378c2654abSrjs }
28388c2654abSrjs } else {
28398c2654abSrjs /* is there enough of it left ? */
28408c2654abSrjs if (desc.chunk_type == SCTP_DATA) {
28418c2654abSrjs if (chlen < (sizeof(struct sctp_data_chunk) +
28428c2654abSrjs sizeof(desc.data_bytes))) {
28438c2654abSrjs break;
28448c2654abSrjs }
28458c2654abSrjs } else {
28468c2654abSrjs if (chlen < sizeof(struct sctp_chunkhdr)) {
28478c2654abSrjs break;
28488c2654abSrjs }
28498c2654abSrjs }
28508c2654abSrjs }
28518c2654abSrjs if (desc.chunk_type == SCTP_DATA) {
28528c2654abSrjs /* can we get out the tsn? */
28538c2654abSrjs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX))
28548c2654abSrjs sctp_pegs[SCTP_PDRP_MB_DA]++;
28558c2654abSrjs
28568c2654abSrjs if (chlen >= (sizeof(struct sctp_data_chunk) + sizeof(u_int32_t)) ) {
28578c2654abSrjs /* yep */
28588c2654abSrjs struct sctp_data_chunk *dcp;
28598c2654abSrjs u_int8_t *ddp;
28608c2654abSrjs unsigned int iii;
28618c2654abSrjs dcp = (struct sctp_data_chunk *)ch;
28628c2654abSrjs ddp = (u_int8_t *)(dcp + 1);
28638c2654abSrjs for (iii = 0; iii < sizeof(desc.data_bytes); iii++) {
28648c2654abSrjs desc.data_bytes[iii] = ddp[iii];
28658c2654abSrjs }
28668c2654abSrjs desc.tsn_ifany = dcp->dp.tsn;
28678c2654abSrjs } else {
28688c2654abSrjs /* nope we are done. */
28698c2654abSrjs sctp_pegs[SCTP_PDRP_NEDAT]++;
28708c2654abSrjs break;
28718c2654abSrjs }
28728c2654abSrjs } else {
28738c2654abSrjs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX))
28748c2654abSrjs sctp_pegs[SCTP_PDRP_MB_CT]++;
28758c2654abSrjs }
28768c2654abSrjs
28778c2654abSrjs if (process_chunk_drop(stcb, &desc, net, cp->ch.chunk_flags)) {
28788c2654abSrjs sctp_pegs[SCTP_PDRP_PDBRK]++;
28798c2654abSrjs break;
28808c2654abSrjs }
28818c2654abSrjs if (SCTP_SIZE32(at) > chlen) {
28828c2654abSrjs break;
28838c2654abSrjs }
28848c2654abSrjs chlen -= SCTP_SIZE32(at);
28858c2654abSrjs if (chlen < sizeof(struct sctp_chunkhdr)) {
28868c2654abSrjs /* done, none left */
28878c2654abSrjs break;
28888c2654abSrjs }
28898c2654abSrjs ch = (struct sctp_chunkhdr *)((vaddr_t)ch + SCTP_SIZE32(at));
28908c2654abSrjs }
28918c2654abSrjs
28928c2654abSrjs /* now middle boxes in sat networks get a cwnd bump */
28938c2654abSrjs if ((cp->ch.chunk_flags & SCTP_FROM_MIDDLE_BOX) &&
28948c2654abSrjs (stcb->asoc.sat_t3_loss_recovery == 0) &&
28958c2654abSrjs (stcb->asoc.sat_network)) {
28968c2654abSrjs /*
28978c2654abSrjs * This is debateable but for sat networks it makes sense
28988c2654abSrjs * Note if a T3 timer has went off, we will prohibit any
28998c2654abSrjs * changes to cwnd until we exit the t3 loss recovery.
29008c2654abSrjs */
29018c2654abSrjs u_int32_t bw_avail;
29028c2654abSrjs int rtt, incr;
29038c2654abSrjs #ifdef SCTP_CWND_LOGGING
29048c2654abSrjs int old_cwnd=net->cwnd;
29058c2654abSrjs #endif
29068c2654abSrjs /* need real RTT for this calc */
29078c2654abSrjs rtt = ((net->lastsa >> 2) + net->lastsv) >> 1;
29088c2654abSrjs /* get bottle neck bw */
29098c2654abSrjs bottle_bw = ntohl(cp->bottle_bw);
29108c2654abSrjs /* and whats on queue */
29118c2654abSrjs on_queue = ntohl(cp->current_onq);
29128c2654abSrjs /*
29138c2654abSrjs * adjust the on-queue if our flight is more it could be
29148c2654abSrjs * that the router has not yet gotten data "in-flight" to it
29158c2654abSrjs */
29168c2654abSrjs if (on_queue < net->flight_size)
29178c2654abSrjs on_queue = net->flight_size;
29188c2654abSrjs
29198c2654abSrjs /* calculate the available space */
29208c2654abSrjs bw_avail = (bottle_bw*rtt)/1000;
29218c2654abSrjs if (bw_avail > bottle_bw) {
29228c2654abSrjs /*
29238c2654abSrjs * Cap the growth to no more than the bottle neck.
29248c2654abSrjs * This can happen as RTT slides up due to queues.
29258c2654abSrjs * It also means if you have more than a 1 second
29268c2654abSrjs * RTT with a empty queue you will be limited to
29278c2654abSrjs * the bottle_bw per second no matter if
29288c2654abSrjs * other points have 1/2 the RTT and you could
29298c2654abSrjs * get more out...
29308c2654abSrjs */
29318c2654abSrjs bw_avail = bottle_bw;
29328c2654abSrjs }
29338c2654abSrjs
29348c2654abSrjs if (on_queue > bw_avail) {
29358c2654abSrjs /*
29368c2654abSrjs * No room for anything else don't allow anything
29378c2654abSrjs * else to be "added to the fire".
29388c2654abSrjs */
29398c2654abSrjs int seg_inflight, seg_onqueue, my_portion;
29408c2654abSrjs net->partial_bytes_acked = 0;
29418c2654abSrjs
29428c2654abSrjs /* how much are we over queue size? */
29438c2654abSrjs incr = on_queue - bw_avail;
29448c2654abSrjs if (stcb->asoc.seen_a_sack_this_pkt) {
29458c2654abSrjs /* undo any cwnd adjustment that
29468c2654abSrjs * the sack might have made
29478c2654abSrjs */
29488c2654abSrjs net->cwnd = net->prev_cwnd;
29498c2654abSrjs }
29508c2654abSrjs
29518c2654abSrjs /* Now how much of that is mine? */
29528c2654abSrjs seg_inflight = net->flight_size / net->mtu;
29538c2654abSrjs seg_onqueue = on_queue / net->mtu;
29548c2654abSrjs my_portion = (incr * seg_inflight)/seg_onqueue;
29558c2654abSrjs
29568c2654abSrjs /* Have I made an adjustment already */
29578c2654abSrjs if (net->cwnd > net->flight_size) {
29588c2654abSrjs /* for this flight I made an adjustment
29598c2654abSrjs * we need to decrease the portion by a share
29608c2654abSrjs * our previous adjustment.
29618c2654abSrjs */
29628c2654abSrjs int diff_adj;
29638c2654abSrjs diff_adj = net->cwnd - net->flight_size;
29648c2654abSrjs if (diff_adj > my_portion)
29658c2654abSrjs my_portion = 0;
29668c2654abSrjs else
29678c2654abSrjs my_portion -= diff_adj;
29688c2654abSrjs }
29698c2654abSrjs
29708c2654abSrjs /* back down to the previous cwnd (assume
29718c2654abSrjs * we have had a sack before this packet). minus
29728c2654abSrjs * what ever portion of the overage is my fault.
29738c2654abSrjs */
29748c2654abSrjs net->cwnd -= my_portion;
29758c2654abSrjs
29768c2654abSrjs /* we will NOT back down more than 1 MTU */
29778c2654abSrjs if (net->cwnd <= net->mtu) {
29788c2654abSrjs net->cwnd = net->mtu;
29798c2654abSrjs }
29808c2654abSrjs /* force into CA */
29818c2654abSrjs net->ssthresh = net->cwnd - 1;
29828c2654abSrjs } else {
29838c2654abSrjs /*
29848c2654abSrjs * Take 1/4 of the space left or
29858c2654abSrjs * max burst up .. whichever is less.
29868c2654abSrjs */
2987d1579b2dSriastradh incr = uimin((bw_avail - on_queue) >> 2,
29888c2654abSrjs (int)stcb->asoc.max_burst * (int)net->mtu);
29898c2654abSrjs net->cwnd += incr;
29908c2654abSrjs }
29918c2654abSrjs if (net->cwnd > bw_avail) {
29928c2654abSrjs /* We can't exceed the pipe size */
29938c2654abSrjs net->cwnd = bw_avail;
29948c2654abSrjs }
29958c2654abSrjs if (net->cwnd < net->mtu) {
29968c2654abSrjs /* We always have 1 MTU */
29978c2654abSrjs net->cwnd = net->mtu;
29988c2654abSrjs }
29998c2654abSrjs #ifdef SCTP_CWND_LOGGING
30008c2654abSrjs if (net->cwnd - old_cwnd != 0) {
30018c2654abSrjs /* log only changes */
30028c2654abSrjs sctp_log_cwnd(net, (net->cwnd - old_cwnd),
30038c2654abSrjs SCTP_CWND_LOG_FROM_SAT);
30048c2654abSrjs }
30058c2654abSrjs #endif
30068c2654abSrjs }
30078c2654abSrjs }
30088c2654abSrjs
30098c2654abSrjs extern int sctp_strict_init;
30108c2654abSrjs
30118c2654abSrjs /*
30128c2654abSrjs * handles all control chunks in a packet
30138c2654abSrjs * inputs:
30148c2654abSrjs * - m: mbuf chain, assumed to still contain IP/SCTP header
30158c2654abSrjs * - stcb: is the tcb found for this packet
30168c2654abSrjs * - offset: offset into the mbuf chain to first chunkhdr
30178c2654abSrjs * - length: is the length of the complete packet
30188c2654abSrjs * outputs:
30198c2654abSrjs * - length: modified to remaining length after control processing
30208c2654abSrjs * - netp: modified to new sctp_nets after cookie-echo processing
30218c2654abSrjs * - return NULL to discard the packet (ie. no asoc, bad packet,...)
30228c2654abSrjs * otherwise return the tcb for this packet
30238c2654abSrjs */
30248c2654abSrjs static struct sctp_tcb *
sctp_process_control(struct mbuf * m,int iphlen,int * offset,int length,struct sctphdr * sh,struct sctp_chunkhdr * ch,struct sctp_inpcb * inp,struct sctp_tcb * stcb,struct sctp_nets ** netp,int * fwd_tsn_seen)30258c2654abSrjs sctp_process_control(struct mbuf *m, int iphlen, int *offset, int length,
30268c2654abSrjs struct sctphdr *sh, struct sctp_chunkhdr *ch, struct sctp_inpcb *inp,
30278c2654abSrjs struct sctp_tcb *stcb, struct sctp_nets **netp, int *fwd_tsn_seen)
30288c2654abSrjs {
30298c2654abSrjs struct sctp_association *asoc;
30308c2654abSrjs u_int32_t vtag_in;
30318c2654abSrjs int num_chunks = 0; /* number of control chunks processed */
30328c2654abSrjs int chk_length;
30338c2654abSrjs int ret;
30348c2654abSrjs
30358c2654abSrjs /*
30368c2654abSrjs * How big should this be, and should it be alloc'd?
30378c2654abSrjs * Lets try the d-mtu-ceiling for now (2k) and that should
30388c2654abSrjs * hopefully work ... until we get into jumbo grams and such..
30398c2654abSrjs */
30408c2654abSrjs u_int8_t chunk_buf[DEFAULT_CHUNK_BUFFER];
30418c2654abSrjs struct sctp_tcb *locked_tcb = stcb;
30428c2654abSrjs
30438c2654abSrjs #ifdef SCTP_DEBUG
30448c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
30458c2654abSrjs printf("sctp_process_control: iphlen=%u, offset=%u, length=%u stcb:%p\n",
30468c2654abSrjs iphlen, *offset, length, stcb);
30478c2654abSrjs }
30488c2654abSrjs #endif /* SCTP_DEBUG */
30498c2654abSrjs
30508c2654abSrjs /* validate chunk header length... */
30518c2654abSrjs if (ntohs(ch->chunk_length) < sizeof(*ch)) {
30528c2654abSrjs return (NULL);
30538c2654abSrjs }
30548c2654abSrjs
30558c2654abSrjs /*
30568c2654abSrjs * validate the verification tag
30578c2654abSrjs */
30588c2654abSrjs #ifdef SCTP_DEBUG
30598c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
30608c2654abSrjs printf("sctp_process_control: validating vtags\n");
30618c2654abSrjs }
30628c2654abSrjs #endif /* SCTP_DEBUG */
30638c2654abSrjs vtag_in = ntohl(sh->v_tag);
30648c2654abSrjs if (ch->chunk_type == SCTP_INITIATION) {
30658c2654abSrjs if (vtag_in != 0) {
30668c2654abSrjs /* protocol error- silently discard... */
30678c2654abSrjs #ifdef SCTP_DEBUG
30688c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
30698c2654abSrjs printf("sctp_process_control: INIT with vtag != 0\n");
30708c2654abSrjs }
30718c2654abSrjs #endif /* SCTP_DEBUG */
30728c2654abSrjs sctp_pegs[SCTP_BAD_VTAGS]++;
30738c2654abSrjs if (locked_tcb) {
30748c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
30758c2654abSrjs }
30768c2654abSrjs return (NULL);
30778c2654abSrjs }
30788c2654abSrjs } else if (ch->chunk_type != SCTP_COOKIE_ECHO) {
30798c2654abSrjs /*
30808c2654abSrjs * first check if it's an ASCONF with an unknown src addr
30818c2654abSrjs * we need to look inside to find the association
30828c2654abSrjs */
30838c2654abSrjs if (ch->chunk_type == SCTP_ASCONF && stcb == NULL) {
30848c2654abSrjs stcb = sctp_findassociation_ep_asconf(m, iphlen,
30858c2654abSrjs *offset, sh, &inp, netp);
30868c2654abSrjs }
30878c2654abSrjs if (stcb == NULL) {
30888c2654abSrjs /* no association, so it's out of the blue... */
30898c2654abSrjs sctp_handle_ootb(m, iphlen, *offset, sh, inp, NULL);
30908c2654abSrjs #ifdef SCTP_DEBUG
30918c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
30928c2654abSrjs printf("sctp_process_control: handling OOTB packet, chunk type=%xh\n",
30938c2654abSrjs ch->chunk_type);
30948c2654abSrjs }
30958c2654abSrjs #endif /* SCTP_DEBUG */
30968c2654abSrjs *offset = length;
30978c2654abSrjs if (locked_tcb) {
30988c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
30998c2654abSrjs }
31008c2654abSrjs return (NULL);
31018c2654abSrjs }
31028c2654abSrjs asoc = &stcb->asoc;
31038c2654abSrjs /* ABORT and SHUTDOWN can use either v_tag... */
31048c2654abSrjs if ((ch->chunk_type == SCTP_ABORT_ASSOCIATION) ||
31058c2654abSrjs (ch->chunk_type == SCTP_SHUTDOWN_COMPLETE) ||
31068c2654abSrjs (ch->chunk_type == SCTP_PACKET_DROPPED)) {
31078c2654abSrjs if ((vtag_in == asoc->my_vtag) ||
31088c2654abSrjs ((ch->chunk_flags & SCTP_HAD_NO_TCB) &&
31098c2654abSrjs (vtag_in == asoc->peer_vtag))) {
31108c2654abSrjs /* this is valid */
31118c2654abSrjs } else {
31128c2654abSrjs /* drop this packet... */
31138c2654abSrjs sctp_pegs[SCTP_BAD_VTAGS]++;
31148c2654abSrjs if (locked_tcb) {
31158c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
31168c2654abSrjs }
31178c2654abSrjs return (NULL);
31188c2654abSrjs }
31198c2654abSrjs } else if (ch->chunk_type == SCTP_SHUTDOWN_ACK) {
31208c2654abSrjs if (vtag_in != asoc->my_vtag) {
31218c2654abSrjs /*
31228c2654abSrjs * this could be a stale SHUTDOWN-ACK or the
31238c2654abSrjs * peer never got the SHUTDOWN-COMPLETE and
31248c2654abSrjs * is still hung; we have started a new asoc
31258c2654abSrjs * but it won't complete until the shutdown is
31268c2654abSrjs * completed
31278c2654abSrjs */
31288c2654abSrjs if (locked_tcb) {
31298c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
31308c2654abSrjs }
31318c2654abSrjs sctp_handle_ootb(m, iphlen, *offset, sh, inp,
31328c2654abSrjs NULL);
31338c2654abSrjs return (NULL);
31348c2654abSrjs }
31358c2654abSrjs } else {
31368c2654abSrjs /* for all other chunks, vtag must match */
31378c2654abSrjs
31388c2654abSrjs if (vtag_in != asoc->my_vtag) {
31398c2654abSrjs /* invalid vtag... */
31408c2654abSrjs #ifdef SCTP_DEBUG
31418c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
31428c2654abSrjs printf("invalid vtag: %xh, expect %xh\n", vtag_in, asoc->my_vtag);
31438c2654abSrjs }
31448c2654abSrjs #endif /* SCTP_DEBUG */
31458c2654abSrjs sctp_pegs[SCTP_BAD_VTAGS]++;
31468c2654abSrjs if (locked_tcb) {
31478c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
31488c2654abSrjs }
31498c2654abSrjs *offset = length;
31508c2654abSrjs return (NULL);
31518c2654abSrjs }
31528c2654abSrjs }
31538c2654abSrjs } /* end if !SCTP_COOKIE_ECHO */
31548c2654abSrjs
31558c2654abSrjs #ifdef SCTP_DEBUG
31568c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
31578c2654abSrjs printf("sctp_process_control: vtags ok, processing ctrl chunks\n");
31588c2654abSrjs }
31598c2654abSrjs #endif /* SCTP_DEBUG */
31608c2654abSrjs
31618c2654abSrjs /*
31628c2654abSrjs * process all control chunks...
31638c2654abSrjs */
31648c2654abSrjs if (((ch->chunk_type == SCTP_SELECTIVE_ACK) ||
31658c2654abSrjs (ch->chunk_type == SCTP_HEARTBEAT_REQUEST)) &&
31668c2654abSrjs (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
31678c2654abSrjs /* implied cookie-ack.. we must have lost the ack */
31688c2654abSrjs stcb->asoc.overall_error_count = 0;
31698c2654abSrjs sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch, stcb, *netp);
31708c2654abSrjs }
31718c2654abSrjs
31728c2654abSrjs while (IS_SCTP_CONTROL(ch)) {
31738c2654abSrjs /* validate chunk length */
31748c2654abSrjs chk_length = ntohs(ch->chunk_length);
31758c2654abSrjs #ifdef SCTP_DEBUG
31768c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT2) {
31778c2654abSrjs printf("sctp_process_control: processing a chunk type=%u, len=%u\n", ch->chunk_type, chk_length);
31788c2654abSrjs }
31798c2654abSrjs #endif /* SCTP_DEBUG */
31808c2654abSrjs if ((size_t)chk_length < sizeof(*ch) ||
31818c2654abSrjs (*offset + chk_length) > length) {
31828c2654abSrjs #ifdef SCTP_DEBUG
31838c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
31848c2654abSrjs printf("sctp_process_control: chunk length invalid! *offset:%u, chk_length:%u > length:%u\n",
3185753b0e65Srjs *offset, chk_length, length);
31868c2654abSrjs }
31878c2654abSrjs #endif /* SCTP_DEBUG */
31888c2654abSrjs *offset = length;
31898c2654abSrjs if (locked_tcb) {
31908c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
31918c2654abSrjs }
31928c2654abSrjs return (NULL);
31938c2654abSrjs }
31948c2654abSrjs
31958c2654abSrjs /*
31968c2654abSrjs * INIT-ACK only gets the init ack "header" portion only
31978c2654abSrjs * because we don't have to process the peer's COOKIE.
31988c2654abSrjs * All others get a complete chunk.
31998c2654abSrjs */
32008c2654abSrjs if (ch->chunk_type == SCTP_INITIATION_ACK) {
32018c2654abSrjs /* get an init-ack chunk */
32028c2654abSrjs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
32038c2654abSrjs sizeof(struct sctp_init_ack), chunk_buf);
32048c2654abSrjs if (ch == NULL) {
32058c2654abSrjs *offset = length;
32068c2654abSrjs if (locked_tcb) {
32078c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
32088c2654abSrjs }
32098c2654abSrjs return (NULL);
32108c2654abSrjs }
32118c2654abSrjs } else {
32128c2654abSrjs /* get a complete chunk... */
32138c2654abSrjs if ((size_t)chk_length > sizeof(chunk_buf)) {
32148c2654abSrjs struct mbuf *oper;
32158c2654abSrjs struct sctp_paramhdr *phdr;
32168c2654abSrjs oper = NULL;
32178c2654abSrjs MGETHDR(oper, M_DONTWAIT, MT_HEADER);
32188c2654abSrjs if (oper) {
32198c2654abSrjs /* pre-reserve some space */
32208c2654abSrjs oper->m_data +=
32218c2654abSrjs sizeof(struct sctp_chunkhdr);
32228c2654abSrjs phdr =
32238c2654abSrjs mtod(oper, struct sctp_paramhdr *);
32248c2654abSrjs phdr->param_type =
32258c2654abSrjs htons(SCTP_CAUSE_OUT_OF_RESC);
32268c2654abSrjs phdr->param_length =
32278c2654abSrjs htons(sizeof(struct sctp_paramhdr));
32288c2654abSrjs sctp_queue_op_err(stcb, oper);
32298c2654abSrjs }
32308c2654abSrjs if (locked_tcb) {
32318c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
32328c2654abSrjs }
32338c2654abSrjs return (NULL);
32348c2654abSrjs }
32358c2654abSrjs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
32368c2654abSrjs chk_length, chunk_buf);
32378c2654abSrjs if (ch == NULL) {
32388c2654abSrjs printf("sctp_process_control: Can't get the all data....\n");
32398c2654abSrjs *offset = length;
32408c2654abSrjs if (locked_tcb) {
32418c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
32428c2654abSrjs }
32438c2654abSrjs return (NULL);
32448c2654abSrjs }
32458c2654abSrjs
32468c2654abSrjs }
32478c2654abSrjs num_chunks++;
32488c2654abSrjs /* Save off the last place we got a control from */
32498c2654abSrjs if ((*netp) && stcb) {
32508c2654abSrjs stcb->asoc.last_control_chunk_from = *netp;
32518c2654abSrjs }
32528c2654abSrjs #ifdef SCTP_AUDITING_ENABLED
32538c2654abSrjs sctp_audit_log(0xB0, ch->chunk_type);
32548c2654abSrjs #endif
32558c2654abSrjs switch (ch->chunk_type) {
32568c2654abSrjs case SCTP_INITIATION:
32578c2654abSrjs /* must be first and only chunk */
32588c2654abSrjs #ifdef SCTP_DEBUG
32598c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
32608c2654abSrjs printf("SCTP_INIT\n");
32618c2654abSrjs }
32628c2654abSrjs #endif /* SCTP_DEBUG */
32638c2654abSrjs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
32648c2654abSrjs /* We are not interested anymore */
32658c2654abSrjs if (locked_tcb) {
32668c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
32678c2654abSrjs }
32688c2654abSrjs if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
32698c2654abSrjs /* finish the job now */
32708c2654abSrjs sctp_inpcb_free(inp, 1);
32718c2654abSrjs }
32728c2654abSrjs *offset = length;
32738c2654abSrjs return (NULL);
32748c2654abSrjs }
32758c2654abSrjs if ((num_chunks > 1) ||
32768c2654abSrjs (sctp_strict_init && (length - *offset > SCTP_SIZE32(chk_length)))) {
32778c2654abSrjs *offset = length;
32788c2654abSrjs if (locked_tcb) {
32798c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
32808c2654abSrjs }
32818c2654abSrjs return (NULL);
32828c2654abSrjs }
32838c2654abSrjs if ((stcb != NULL) &&
32848c2654abSrjs (SCTP_GET_STATE(&stcb->asoc) ==
32858c2654abSrjs SCTP_STATE_SHUTDOWN_ACK_SENT)) {
32868c2654abSrjs sctp_send_shutdown_ack(stcb,
32878c2654abSrjs stcb->asoc.primary_destination);
32888c2654abSrjs *offset = length;
32898c2654abSrjs if (locked_tcb) {
32908c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
32918c2654abSrjs }
32928c2654abSrjs return (NULL);
32938c2654abSrjs }
32948c2654abSrjs sctp_handle_init(m, iphlen, *offset, sh,
32958c2654abSrjs (struct sctp_init_chunk *)ch, inp, stcb, *netp);
32968c2654abSrjs *offset = length;
32978c2654abSrjs if (locked_tcb) {
32988c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
32998c2654abSrjs }
33008c2654abSrjs return (NULL);
33018c2654abSrjs break;
33028c2654abSrjs case SCTP_INITIATION_ACK:
33038c2654abSrjs /* must be first and only chunk */
33048c2654abSrjs #ifdef SCTP_DEBUG
33058c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
33068c2654abSrjs printf("SCTP_INIT-ACK\n");
33078c2654abSrjs }
33088c2654abSrjs #endif /* SCTP_DEBUG */
33098c2654abSrjs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
33108c2654abSrjs /* We are not interested anymore */
33118c2654abSrjs if (locked_tcb) {
33128c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
33138c2654abSrjs }
33148c2654abSrjs *offset = length;
33158c2654abSrjs if (stcb) {
33168c2654abSrjs sctp_free_assoc(inp, stcb);
33178c2654abSrjs } else {
33188c2654abSrjs if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
33198c2654abSrjs /* finish the job now */
33208c2654abSrjs sctp_inpcb_free(inp, 1);
33218c2654abSrjs }
33228c2654abSrjs }
33238c2654abSrjs return (NULL);
33248c2654abSrjs }
33258c2654abSrjs if ((num_chunks > 1) ||
33268c2654abSrjs (sctp_strict_init && (length - *offset > SCTP_SIZE32(chk_length)))) {
33278c2654abSrjs #ifdef SCTP_DEBUG
33288c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
33298c2654abSrjs printf("Length is %d rounded chk_length:%d .. dropping\n",
33308c2654abSrjs length - *offset,
33318c2654abSrjs SCTP_SIZE32(chk_length));
33328c2654abSrjs }
33338c2654abSrjs #endif
33348c2654abSrjs *offset = length;
33358c2654abSrjs if (locked_tcb) {
33368c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
33378c2654abSrjs }
33388c2654abSrjs return (NULL);
33398c2654abSrjs }
33408c2654abSrjs ret = sctp_handle_init_ack(m, iphlen, *offset, sh,
33418c2654abSrjs (struct sctp_init_ack_chunk *)ch, stcb, *netp);
33428c2654abSrjs /*
33438c2654abSrjs * Special case, I must call the output routine
33448c2654abSrjs * to get the cookie echoed
33458c2654abSrjs */
33468c2654abSrjs if ((stcb) && ret == 0)
33478c2654abSrjs sctp_chunk_output(stcb->sctp_ep, stcb, 2);
33488c2654abSrjs *offset = length;
33498c2654abSrjs #ifdef SCTP_DEBUG
33508c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
33518c2654abSrjs printf("All done INIT-ACK processing\n");
33528c2654abSrjs }
33538c2654abSrjs #endif
33548c2654abSrjs if (locked_tcb) {
33558c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
33568c2654abSrjs }
33578c2654abSrjs return (NULL);
33588c2654abSrjs break;
33598c2654abSrjs case SCTP_SELECTIVE_ACK:
33608c2654abSrjs #ifdef SCTP_DEBUG
33618c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
33628c2654abSrjs printf("SCTP_SACK\n");
33638c2654abSrjs }
33648c2654abSrjs #endif /* SCTP_DEBUG */
33658c2654abSrjs sctp_pegs[SCTP_PEG_SACKS_SEEN]++;
33668c2654abSrjs {
33678c2654abSrjs int abort_now = 0;
33688c2654abSrjs stcb->asoc.seen_a_sack_this_pkt = 1;
33698c2654abSrjs sctp_handle_sack((struct sctp_sack_chunk *)ch,
33708c2654abSrjs stcb, *netp, &abort_now);
33718c2654abSrjs if (abort_now) {
33728c2654abSrjs /* ABORT signal from sack processing */
33738c2654abSrjs *offset = length;
33748c2654abSrjs return (NULL);
33758c2654abSrjs }
33768c2654abSrjs }
33778c2654abSrjs break;
33788c2654abSrjs case SCTP_HEARTBEAT_REQUEST:
33798c2654abSrjs #ifdef SCTP_DEBUG
33808c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
33818c2654abSrjs printf("SCTP_HEARTBEAT\n");
33828c2654abSrjs }
33838c2654abSrjs #endif /* SCTP_DEBUG */
33848c2654abSrjs sctp_pegs[SCTP_HB_RECV]++;
33858c2654abSrjs sctp_send_heartbeat_ack(stcb, m, *offset, chk_length,
33868c2654abSrjs *netp);
33878c2654abSrjs
33888c2654abSrjs /* He's alive so give him credit */
33898c2654abSrjs stcb->asoc.overall_error_count = 0;
33908c2654abSrjs break;
33918c2654abSrjs case SCTP_HEARTBEAT_ACK:
33928c2654abSrjs #ifdef SCTP_DEBUG
33938c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
33948c2654abSrjs printf("SCTP_HEARTBEAT-ACK\n");
33958c2654abSrjs }
33968c2654abSrjs #endif /* SCTP_DEBUG */
33978c2654abSrjs
33988c2654abSrjs /* He's alive so give him credit */
33998c2654abSrjs stcb->asoc.overall_error_count = 0;
34008c2654abSrjs
34018c2654abSrjs sctp_pegs[SCTP_HB_ACK_RECV]++;
34028c2654abSrjs sctp_handle_heartbeat_ack((struct sctp_heartbeat_chunk *)ch,
34038c2654abSrjs stcb, *netp);
34048c2654abSrjs break;
34058c2654abSrjs case SCTP_ABORT_ASSOCIATION:
34068c2654abSrjs #ifdef SCTP_DEBUG
34078c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
34088c2654abSrjs printf("SCTP_ABORT\n");
34098c2654abSrjs }
34108c2654abSrjs #endif /* SCTP_DEBUG */
34118c2654abSrjs sctp_handle_abort((struct sctp_abort_chunk *)ch,
34128c2654abSrjs stcb, *netp);
34138c2654abSrjs *offset = length;
34148c2654abSrjs return (NULL);
34158c2654abSrjs break;
34168c2654abSrjs case SCTP_SHUTDOWN:
34178c2654abSrjs #ifdef SCTP_DEBUG
34188c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
34198c2654abSrjs printf("SCTP_SHUTDOWN\n");
34208c2654abSrjs }
34218c2654abSrjs #endif /* SCTP_DEBUG */
34228c2654abSrjs {
34238c2654abSrjs int abort_flag = 0;
34248c2654abSrjs sctp_handle_shutdown((struct sctp_shutdown_chunk *)ch,
34258c2654abSrjs stcb, *netp, &abort_flag);
34268c2654abSrjs if (abort_flag) {
34278c2654abSrjs *offset = length;
34288c2654abSrjs return (NULL);
34298c2654abSrjs }
34308c2654abSrjs }
34318c2654abSrjs break;
34328c2654abSrjs case SCTP_SHUTDOWN_ACK:
34338c2654abSrjs #ifdef SCTP_DEBUG
34348c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
34358c2654abSrjs printf("SCTP_SHUTDOWN-ACK\n");
34368c2654abSrjs }
34378c2654abSrjs #endif /* SCTP_DEBUG */
34388c2654abSrjs sctp_handle_shutdown_ack((struct sctp_shutdown_ack_chunk *)ch, stcb, *netp);
34398c2654abSrjs *offset = length;
34408c2654abSrjs return (NULL);
34418c2654abSrjs break;
34428c2654abSrjs case SCTP_OPERATION_ERROR:
34438c2654abSrjs #ifdef SCTP_DEBUG
34448c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
34458c2654abSrjs printf("SCTP_OP-ERR\n");
34468c2654abSrjs }
34478c2654abSrjs #endif /* SCTP_DEBUG */
34488c2654abSrjs if (sctp_handle_error(ch, stcb, *netp) < 0) {
34498c2654abSrjs *offset = length;
34508c2654abSrjs return (NULL);
34518c2654abSrjs }
34528c2654abSrjs break;
34538c2654abSrjs case SCTP_COOKIE_ECHO:
34548c2654abSrjs #ifdef SCTP_DEBUG
34558c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
34568c2654abSrjs printf("SCTP_COOKIE-ECHO stcb is %p\n", stcb);
34578c2654abSrjs }
34588c2654abSrjs #endif /* SCTP_DEBUG */
34598c2654abSrjs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
34608c2654abSrjs /* We are not interested anymore */
34618c2654abSrjs *offset = length;
34628c2654abSrjs if (stcb) {
34638c2654abSrjs sctp_free_assoc(inp, stcb);
34648c2654abSrjs } else {
34658c2654abSrjs if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
34668c2654abSrjs /* finish the job now */
34678c2654abSrjs sctp_inpcb_free(inp, 1);
34688c2654abSrjs }
34698c2654abSrjs }
34708c2654abSrjs return (NULL);
34718c2654abSrjs }
34728c2654abSrjs /*
34738c2654abSrjs * First are we accepting?
34748c2654abSrjs * We do this again here since it is possible
34758c2654abSrjs * that a previous endpoint WAS listening responded to
34768c2654abSrjs * a INIT-ACK and then closed. We opened and bound..
34778c2654abSrjs * and are now no longer listening.
34788c2654abSrjs */
34798c2654abSrjs if (((inp->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING) == 0) ||
34808c2654abSrjs (inp->sctp_socket->so_qlimit == 0)) {
34818c2654abSrjs sctp_abort_association(inp, stcb, m, iphlen, sh,
34828c2654abSrjs NULL);
34838c2654abSrjs *offset = length;
34848c2654abSrjs return (NULL);
34858c2654abSrjs } else if (inp->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING) {
34868c2654abSrjs /* we are accepting so check limits like TCP */
34878c2654abSrjs if (inp->sctp_socket->so_qlen >
34888c2654abSrjs inp->sctp_socket->so_qlimit) {
34898c2654abSrjs /* no space */
34908c2654abSrjs struct mbuf *oper;
34918c2654abSrjs struct sctp_paramhdr *phdr;
34928c2654abSrjs oper = NULL;
34938c2654abSrjs MGETHDR(oper, M_DONTWAIT, MT_HEADER);
34948c2654abSrjs if (oper) {
34958c2654abSrjs oper->m_len =
34968c2654abSrjs oper->m_pkthdr.len =
34978c2654abSrjs sizeof(struct sctp_paramhdr);
34988c2654abSrjs phdr = mtod(oper,
34998c2654abSrjs struct sctp_paramhdr *);
35008c2654abSrjs phdr->param_type =
35018c2654abSrjs htons(SCTP_CAUSE_OUT_OF_RESC);
35028c2654abSrjs phdr->param_length =
35038c2654abSrjs htons(sizeof(struct sctp_paramhdr));
35048c2654abSrjs }
35058c2654abSrjs sctp_abort_association(inp, stcb, m,
35068c2654abSrjs iphlen, sh, oper);
35078c2654abSrjs *offset = length;
35088c2654abSrjs return (NULL);
35098c2654abSrjs }
35108c2654abSrjs }
35118c2654abSrjs {
35128c2654abSrjs struct mbuf *ret_buf;
35138c2654abSrjs ret_buf = sctp_handle_cookie_echo(m, iphlen,
35148c2654abSrjs *offset, sh,
35158c2654abSrjs (struct sctp_cookie_echo_chunk *)ch, &inp,
35168c2654abSrjs &stcb, netp);
35178c2654abSrjs #ifdef SCTP_DEBUG
35188c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
35198c2654abSrjs printf("ret_buf:%p length:%d off:%d\n",
35208c2654abSrjs ret_buf, length, *offset);
35218c2654abSrjs }
35228c2654abSrjs #endif /* SCTP_DEBUG */
35238c2654abSrjs
35248c2654abSrjs if (ret_buf == NULL) {
35258c2654abSrjs if (locked_tcb) {
35268c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
35278c2654abSrjs }
35288c2654abSrjs #ifdef SCTP_DEBUG
35298c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
35308c2654abSrjs printf("GAK, null buffer\n");
35318c2654abSrjs }
35328c2654abSrjs #endif /* SCTP_DEBUG */
35338c2654abSrjs *offset = length;
35348c2654abSrjs return (NULL);
35358c2654abSrjs }
35368c2654abSrjs if (!TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
35378c2654abSrjs /*
35388c2654abSrjs * Restart the timer if we have pending
35398c2654abSrjs * data
35408c2654abSrjs */
35418c2654abSrjs struct sctp_tmit_chunk *chk;
35428c2654abSrjs chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
35438c2654abSrjs if (chk) {
35448c2654abSrjs sctp_timer_start(SCTP_TIMER_TYPE_SEND,
35458c2654abSrjs stcb->sctp_ep, stcb,
35468c2654abSrjs chk->whoTo);
35478c2654abSrjs }
35488c2654abSrjs }
35498c2654abSrjs }
35508c2654abSrjs break;
35518c2654abSrjs case SCTP_COOKIE_ACK:
35528c2654abSrjs #ifdef SCTP_DEBUG
35538c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
35548c2654abSrjs printf("SCTP_COOKIE-ACK\n");
35558c2654abSrjs }
35568c2654abSrjs #endif /* SCTP_DEBUG */
35578c2654abSrjs
35588c2654abSrjs if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
35598c2654abSrjs /* We are not interested anymore */
35608c2654abSrjs sctp_free_assoc(inp, stcb);
35618c2654abSrjs *offset = length;
35628c2654abSrjs return (NULL);
35638c2654abSrjs }
35648c2654abSrjs /* He's alive so give him credit */
35658c2654abSrjs stcb->asoc.overall_error_count = 0;
35668c2654abSrjs sctp_handle_cookie_ack((struct sctp_cookie_ack_chunk *)ch,
35678c2654abSrjs stcb, *netp);
35688c2654abSrjs break;
35698c2654abSrjs case SCTP_ECN_ECHO:
35708c2654abSrjs #ifdef SCTP_DEBUG
35718c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
35728c2654abSrjs printf("SCTP_ECN-ECHO\n");
35738c2654abSrjs }
35748c2654abSrjs #endif /* SCTP_DEBUG */
35758c2654abSrjs /* He's alive so give him credit */
35768c2654abSrjs stcb->asoc.overall_error_count = 0;
35778c2654abSrjs sctp_handle_ecn_echo((struct sctp_ecne_chunk *)ch,
35788c2654abSrjs stcb);
35798c2654abSrjs break;
35808c2654abSrjs case SCTP_ECN_CWR:
35818c2654abSrjs #ifdef SCTP_DEBUG
35828c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
35838c2654abSrjs printf("SCTP_ECN-CWR\n");
35848c2654abSrjs }
35858c2654abSrjs #endif /* SCTP_DEBUG */
35868c2654abSrjs /* He's alive so give him credit */
35878c2654abSrjs stcb->asoc.overall_error_count = 0;
35888c2654abSrjs
35898c2654abSrjs sctp_handle_ecn_cwr((struct sctp_cwr_chunk *)ch, stcb);
35908c2654abSrjs break;
35918c2654abSrjs case SCTP_SHUTDOWN_COMPLETE:
35928c2654abSrjs #ifdef SCTP_DEBUG
35938c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
35948c2654abSrjs printf("SCTP_SHUTDOWN-COMPLETE\n");
35958c2654abSrjs }
35968c2654abSrjs #endif /* SCTP_DEBUG */
35978c2654abSrjs /* must be first and only chunk */
35988c2654abSrjs if ((num_chunks > 1) ||
35998c2654abSrjs (length - *offset > SCTP_SIZE32(chk_length))) {
36008c2654abSrjs *offset = length;
36018c2654abSrjs if (locked_tcb) {
36028c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
36038c2654abSrjs }
36048c2654abSrjs return (NULL);
36058c2654abSrjs }
36068c2654abSrjs sctp_handle_shutdown_complete((struct sctp_shutdown_complete_chunk *)ch,
36078c2654abSrjs stcb, *netp);
36088c2654abSrjs *offset = length;
36098c2654abSrjs return (NULL);
36108c2654abSrjs break;
36118c2654abSrjs case SCTP_ASCONF:
36128c2654abSrjs #ifdef SCTP_DEBUG
36138c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
36148c2654abSrjs printf("SCTP_ASCONF\n");
36158c2654abSrjs }
36168c2654abSrjs #endif /* SCTP_DEBUG */
36178c2654abSrjs /* He's alive so give him credit */
36188c2654abSrjs stcb->asoc.overall_error_count = 0;
36198c2654abSrjs
36208c2654abSrjs sctp_handle_asconf(m, *offset,
36218c2654abSrjs (struct sctp_asconf_chunk *)ch, stcb, *netp);
36228c2654abSrjs break;
36238c2654abSrjs case SCTP_ASCONF_ACK:
36248c2654abSrjs #ifdef SCTP_DEBUG
36258c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
36268c2654abSrjs printf("SCTP_ASCONF-ACK\n");
36278c2654abSrjs }
36288c2654abSrjs #endif /* SCTP_DEBUG */
36298c2654abSrjs /* He's alive so give him credit */
36308c2654abSrjs stcb->asoc.overall_error_count = 0;
36318c2654abSrjs
36328c2654abSrjs sctp_handle_asconf_ack(m, *offset,
36338c2654abSrjs (struct sctp_asconf_ack_chunk *)ch, stcb, *netp);
36348c2654abSrjs break;
36358c2654abSrjs case SCTP_FORWARD_CUM_TSN:
36368c2654abSrjs #ifdef SCTP_DEBUG
36378c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
36388c2654abSrjs printf("SCTP_FWD-TSN\n");
36398c2654abSrjs }
36408c2654abSrjs #endif /* SCTP_DEBUG */
36418c2654abSrjs /* He's alive so give him credit */
36428c2654abSrjs {
36438c2654abSrjs int abort_flag = 0;
36448c2654abSrjs stcb->asoc.overall_error_count = 0;
36458c2654abSrjs *fwd_tsn_seen = 1;
36468c2654abSrjs sctp_handle_forward_tsn(stcb,
36478c2654abSrjs (struct sctp_forward_tsn_chunk *)ch, &abort_flag);
36488c2654abSrjs if (abort_flag) {
36498c2654abSrjs *offset = length;
36508c2654abSrjs return (NULL);
36518c2654abSrjs } else {
36528c2654abSrjs stcb->asoc.overall_error_count = 0;
36538c2654abSrjs }
36548c2654abSrjs
36558c2654abSrjs }
36568c2654abSrjs break;
36578c2654abSrjs case SCTP_STREAM_RESET:
36588c2654abSrjs #ifdef SCTP_DEBUG
36598c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
36608c2654abSrjs printf("SCTP_STREAM_RESET\n");
36618c2654abSrjs }
36628c2654abSrjs #endif /* SCTP_DEBUG */
36638c2654abSrjs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
36648c2654abSrjs chk_length, chunk_buf);
36658c2654abSrjs if (stcb->asoc.peer_supports_strreset == 0) {
36668c2654abSrjs /* hmm, peer should have annonced this, but
36678c2654abSrjs * we will turn it on since he is sending us
36688c2654abSrjs * a stream reset.
36698c2654abSrjs */
36708c2654abSrjs stcb->asoc.peer_supports_strreset = 1;
36718c2654abSrjs }
36728c2654abSrjs sctp_handle_stream_reset(stcb, (struct sctp_stream_reset_req *)ch);
36738c2654abSrjs break;
36748c2654abSrjs case SCTP_PACKET_DROPPED:
36758c2654abSrjs #ifdef SCTP_DEBUG
36768c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
36778c2654abSrjs printf("SCTP_PACKET_DROPPED\n");
36788c2654abSrjs }
36798c2654abSrjs #endif /* SCTP_DEBUG */
36808c2654abSrjs /* re-get it all please */
36818c2654abSrjs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
36828c2654abSrjs chk_length, chunk_buf);
36838c2654abSrjs
36848c2654abSrjs sctp_handle_packet_dropped((struct sctp_pktdrop_chunk *)ch,
36858c2654abSrjs stcb, *netp);
36868c2654abSrjs
36878c2654abSrjs
36888c2654abSrjs break;
36898c2654abSrjs default:
36908c2654abSrjs /* it's an unknown chunk! */
36918c2654abSrjs if ((ch->chunk_type & 0x40) && (stcb != NULL)) {
36928c2654abSrjs struct mbuf *mm;
36938c2654abSrjs struct sctp_paramhdr *phd;
36948c2654abSrjs MGETHDR(mm, M_DONTWAIT, MT_HEADER);
36958c2654abSrjs if (mm) {
36968c2654abSrjs phd = mtod(mm, struct sctp_paramhdr *);
36978c2654abSrjs /* We cheat and use param type since we
36988c2654abSrjs * did not bother to define a error
36998c2654abSrjs * cause struct.
37008c2654abSrjs * They are the same basic format with
37018c2654abSrjs * different names.
37028c2654abSrjs */
37038c2654abSrjs phd->param_type =
37048c2654abSrjs htons(SCTP_CAUSE_UNRECOG_CHUNK);
37058c2654abSrjs phd->param_length =
37068c2654abSrjs htons(chk_length + sizeof(*phd));
37078c2654abSrjs mm->m_len = sizeof(*phd);
37088c2654abSrjs mm->m_next = sctp_m_copym(m, *offset,
37098c2654abSrjs SCTP_SIZE32(chk_length),
37108c2654abSrjs M_DONTWAIT);
37118c2654abSrjs if (mm->m_next) {
37128c2654abSrjs mm->m_pkthdr.len =
37138c2654abSrjs SCTP_SIZE32(chk_length) +
37148c2654abSrjs sizeof(*phd);
37158c2654abSrjs sctp_queue_op_err(stcb, mm);
37168c2654abSrjs } else {
37178c2654abSrjs sctp_m_freem(mm);
37188c2654abSrjs #ifdef SCTP_DEBUG
37198c2654abSrjs if (sctp_debug_on &
37208c2654abSrjs SCTP_DEBUG_INPUT1) {
37218c2654abSrjs printf("Gak can't copy the chunk into operr %d bytes\n",
37228c2654abSrjs chk_length);
37238c2654abSrjs }
37248c2654abSrjs #endif
37258c2654abSrjs }
37268c2654abSrjs }
37278c2654abSrjs #ifdef SCTP_DEBUG
37288c2654abSrjs else {
37298c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
37308c2654abSrjs printf("Gak can't mgethdr for op-err of unrec chunk\n");
37318c2654abSrjs }
37328c2654abSrjs }
37338c2654abSrjs #endif
37348c2654abSrjs }
37358c2654abSrjs if ((ch->chunk_type & 0x80) == 0) {
37368c2654abSrjs /* discard this packet */
37378c2654abSrjs *offset = length;
37388c2654abSrjs return (stcb);
37398c2654abSrjs } /* else skip this bad chunk and continue... */
37408c2654abSrjs break;
37418c2654abSrjs } /* switch (ch->chunk_type) */
37428c2654abSrjs /* get the next chunk */
37438c2654abSrjs *offset += SCTP_SIZE32(chk_length);
37448c2654abSrjs if (*offset >= length) {
37458c2654abSrjs /* no more data left in the mbuf chain */
37468c2654abSrjs break;
37478c2654abSrjs }
37488c2654abSrjs ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, *offset,
37498c2654abSrjs sizeof(struct sctp_chunkhdr), chunk_buf);
37508c2654abSrjs if (ch == NULL) {
37518c2654abSrjs if (locked_tcb) {
37528c2654abSrjs SCTP_TCB_UNLOCK(locked_tcb);
37538c2654abSrjs }
37548c2654abSrjs *offset = length;
37558c2654abSrjs return (NULL);
37568c2654abSrjs }
37578c2654abSrjs } /* while */
37588c2654abSrjs return (stcb);
37598c2654abSrjs }
37608c2654abSrjs
37618c2654abSrjs
37628c2654abSrjs /*
37638c2654abSrjs * Process the ECN bits we have something set so
37648c2654abSrjs * we must look to see if it is ECN(0) or ECN(1) or CE
37658c2654abSrjs */
37668c2654abSrjs static void
sctp_process_ecn_marked_a(struct sctp_tcb * stcb,struct sctp_nets * net,u_int8_t ecn_bits)37678c2654abSrjs sctp_process_ecn_marked_a(struct sctp_tcb *stcb, struct sctp_nets *net,
37688c2654abSrjs u_int8_t ecn_bits)
37698c2654abSrjs {
37708c2654abSrjs if ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS) {
37718c2654abSrjs ;
37728c2654abSrjs } else if ((ecn_bits & SCTP_ECT1_BIT) == SCTP_ECT1_BIT) {
37738c2654abSrjs /*
37748c2654abSrjs * we only add to the nonce sum for ECT1, ECT0
37758c2654abSrjs * does not change the NS bit (that we have
37768c2654abSrjs * yet to find a way to send it yet).
37778c2654abSrjs */
37788c2654abSrjs
37798c2654abSrjs /* ECN Nonce stuff */
37808c2654abSrjs stcb->asoc.receiver_nonce_sum++;
37818c2654abSrjs stcb->asoc.receiver_nonce_sum &= SCTP_SACK_NONCE_SUM;
37828c2654abSrjs
37838c2654abSrjs /*
37848c2654abSrjs * Drag up the last_echo point if cumack is larger since we
37858c2654abSrjs * don't want the point falling way behind by more than 2^^31
37868c2654abSrjs * and then having it be incorrect.
37878c2654abSrjs */
37888c2654abSrjs if (compare_with_wrap(stcb->asoc.cumulative_tsn,
37898c2654abSrjs stcb->asoc.last_echo_tsn, MAX_TSN)) {
37908c2654abSrjs stcb->asoc.last_echo_tsn = stcb->asoc.cumulative_tsn;
37918c2654abSrjs }
37928c2654abSrjs } else if ((ecn_bits & SCTP_ECT0_BIT) == SCTP_ECT0_BIT) {
37938c2654abSrjs /*
37948c2654abSrjs * Drag up the last_echo point if cumack is larger since we
37958c2654abSrjs * don't want the point falling way behind by more than 2^^31
37968c2654abSrjs * and then having it be incorrect.
37978c2654abSrjs */
37988c2654abSrjs if (compare_with_wrap(stcb->asoc.cumulative_tsn,
37998c2654abSrjs stcb->asoc.last_echo_tsn, MAX_TSN)) {
38008c2654abSrjs stcb->asoc.last_echo_tsn = stcb->asoc.cumulative_tsn;
38018c2654abSrjs }
38028c2654abSrjs }
38038c2654abSrjs }
38048c2654abSrjs
38058c2654abSrjs static void
sctp_process_ecn_marked_b(struct sctp_tcb * stcb,struct sctp_nets * net,u_int32_t high_tsn,u_int8_t ecn_bits)38068c2654abSrjs sctp_process_ecn_marked_b(struct sctp_tcb *stcb, struct sctp_nets *net,
38078c2654abSrjs u_int32_t high_tsn, u_int8_t ecn_bits)
38088c2654abSrjs {
38098c2654abSrjs if ((ecn_bits & SCTP_CE_BITS) == SCTP_CE_BITS) {
38108c2654abSrjs /*
38118c2654abSrjs * we possibly must notify the sender that a congestion
38128c2654abSrjs * window reduction is in order. We do this
38138c2654abSrjs * by adding a ECNE chunk to the output chunk
38148c2654abSrjs * queue. The incoming CWR will remove this chunk.
38158c2654abSrjs */
38168c2654abSrjs if (compare_with_wrap(high_tsn, stcb->asoc.last_echo_tsn,
38178c2654abSrjs MAX_TSN)) {
38188c2654abSrjs /* Yep, we need to add a ECNE */
38198c2654abSrjs sctp_send_ecn_echo(stcb, net, high_tsn);
38208c2654abSrjs stcb->asoc.last_echo_tsn = high_tsn;
38218c2654abSrjs }
38228c2654abSrjs }
38238c2654abSrjs }
38248c2654abSrjs
38258c2654abSrjs /*
38268c2654abSrjs * common input chunk processing (v4 and v6)
38278c2654abSrjs */
38288c2654abSrjs int
sctp_common_input_processing(struct mbuf ** mm,int iphlen,int offset,int length,struct sctphdr * sh,struct sctp_chunkhdr * ch,struct sctp_inpcb * inp,struct sctp_tcb * stcb,struct sctp_nets * net,u_int8_t ecn_bits)38298c2654abSrjs sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
38308c2654abSrjs int length, struct sctphdr *sh, struct sctp_chunkhdr *ch,
38318c2654abSrjs struct sctp_inpcb *inp, struct sctp_tcb *stcb, struct sctp_nets *net,
38328c2654abSrjs u_int8_t ecn_bits)
38338c2654abSrjs {
38348c2654abSrjs /*
38358c2654abSrjs * Control chunk processing
38368c2654abSrjs */
38378c2654abSrjs u_int32_t high_tsn;
38388c2654abSrjs int fwd_tsn_seen = 0, data_processed = 0;
38398c2654abSrjs struct mbuf *m = *mm;
38408c2654abSrjs int abort_flag = 0;
38418c2654abSrjs
38428c2654abSrjs sctp_pegs[SCTP_DATAGRAMS_RCVD]++;
38438c2654abSrjs #ifdef SCTP_AUDITING_ENABLED
38448c2654abSrjs sctp_audit_log(0xE0, 1);
38458c2654abSrjs sctp_auditing(0, inp, stcb, net);
38468c2654abSrjs #endif
38478c2654abSrjs
38488c2654abSrjs #ifdef SCTP_DEBUG
38498c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
38508c2654abSrjs printf("Ok, Common input processing called, m:%p iphlen:%d offset:%d length:%d\n",
38518c2654abSrjs m, iphlen, offset, length);
38528c2654abSrjs }
38538c2654abSrjs #endif /* SCTP_DEBUG */
38548c2654abSrjs if (IS_SCTP_CONTROL(ch)) {
38558c2654abSrjs /* process the control portion of the SCTP packet */
38568c2654abSrjs #ifdef SCTP_DEBUG
38578c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
38588c2654abSrjs printf("Processing control\n");
38598c2654abSrjs }
38608c2654abSrjs #endif /* SCTP_DEBUG */
38618c2654abSrjs
38628c2654abSrjs stcb = sctp_process_control(m, iphlen, &offset, length, sh, ch,
38638c2654abSrjs inp, stcb, &net, &fwd_tsn_seen);
38648c2654abSrjs } else {
38658c2654abSrjs /*
38668c2654abSrjs * no control chunks, so pre-process DATA chunks
38678c2654abSrjs * (these checks are taken care of by control processing)
38688c2654abSrjs */
38698c2654abSrjs #ifdef SCTP_DEBUG
38708c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
38718c2654abSrjs printf("No control present\n");
38728c2654abSrjs }
38738c2654abSrjs #endif /* SCTP_DEBUG */
38748c2654abSrjs
38758c2654abSrjs if (stcb == NULL) {
38768c2654abSrjs /* out of the blue DATA chunk */
38778c2654abSrjs sctp_handle_ootb(m, iphlen, offset, sh, inp, NULL);
38788c2654abSrjs return (1);
38798c2654abSrjs }
38808c2654abSrjs if (stcb->asoc.my_vtag != ntohl(sh->v_tag)) {
38818c2654abSrjs /* v_tag mismatch! */
38828c2654abSrjs sctp_pegs[SCTP_BAD_VTAGS]++;
38838c2654abSrjs SCTP_TCB_UNLOCK(stcb);
38848c2654abSrjs return (1);
38858c2654abSrjs }
38868c2654abSrjs }
38878c2654abSrjs if (stcb == NULL) {
38888c2654abSrjs /*
38898c2654abSrjs * no valid TCB for this packet,
38908c2654abSrjs * or we found it's a bad packet while processing control,
38918c2654abSrjs * or we're done with this packet (done or skip rest of data),
38928c2654abSrjs * so we drop it...
38938c2654abSrjs */
38948c2654abSrjs return (1);
38958c2654abSrjs }
38968c2654abSrjs #ifdef SCTP_DEBUG
38978c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
38988c2654abSrjs printf("Ok, control finished time to look for data (%d) offset:%d\n",
38998c2654abSrjs length, offset);
39008c2654abSrjs }
39018c2654abSrjs #endif /* SCTP_DEBUG */
39028c2654abSrjs /*
39038c2654abSrjs * DATA chunk processing
39048c2654abSrjs */
39058c2654abSrjs /* plow through the data chunks while length > offset */
39068c2654abSrjs stcb->asoc.seen_a_sack_this_pkt = 0;
39078c2654abSrjs
39088c2654abSrjs if (length > offset) {
39098c2654abSrjs int retval;
39108c2654abSrjs /*
39118c2654abSrjs * First check to make sure our state is correct.
39128c2654abSrjs * We would not get here unless we really did have a
39138c2654abSrjs * tag, so we don't abort if this happens, just
39148c2654abSrjs * dump the chunk silently.
39158c2654abSrjs */
39168c2654abSrjs switch (SCTP_GET_STATE(&stcb->asoc)) {
39178c2654abSrjs case SCTP_STATE_COOKIE_ECHOED:
39188c2654abSrjs /*
39198c2654abSrjs * we consider data with valid tags in
39208c2654abSrjs * this state shows us the cookie-ack was lost.
39218c2654abSrjs * Imply it was there.
39228c2654abSrjs */
39238c2654abSrjs stcb->asoc.overall_error_count = 0;
39248c2654abSrjs sctp_handle_cookie_ack(
39258c2654abSrjs (struct sctp_cookie_ack_chunk *)ch, stcb, net);
39268c2654abSrjs break;
39278c2654abSrjs case SCTP_STATE_COOKIE_WAIT:
39288c2654abSrjs /*
39298c2654abSrjs * We consider OOTB any data sent during asoc setup.
39308c2654abSrjs */
39318c2654abSrjs sctp_handle_ootb(m, iphlen, offset, sh, inp, NULL);
39328c2654abSrjs SCTP_TCB_UNLOCK(stcb);
39338c2654abSrjs return (1);
39348c2654abSrjs break;
39358c2654abSrjs case SCTP_STATE_EMPTY: /* should not happen */
39368c2654abSrjs case SCTP_STATE_INUSE: /* should not happen */
39378c2654abSrjs case SCTP_STATE_SHUTDOWN_RECEIVED: /* This is a peer error */
39388c2654abSrjs case SCTP_STATE_SHUTDOWN_ACK_SENT:
39398c2654abSrjs default:
39408c2654abSrjs #ifdef SCTP_DEBUG
39418c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
39428c2654abSrjs printf("Got data in invalid state %d.. dropping\n", stcb->asoc.state);
39438c2654abSrjs }
39448c2654abSrjs #endif
39458c2654abSrjs SCTP_TCB_UNLOCK(stcb);
39468c2654abSrjs return (1);
39478c2654abSrjs break;
39488c2654abSrjs case SCTP_STATE_OPEN:
39498c2654abSrjs case SCTP_STATE_SHUTDOWN_SENT:
39508c2654abSrjs break;
39518c2654abSrjs }
39528c2654abSrjs /* take care of ECN, part 1. */
39538c2654abSrjs if (stcb->asoc.ecn_allowed &&
39548c2654abSrjs (ecn_bits & (SCTP_ECT0_BIT|SCTP_ECT1_BIT)) ) {
39558c2654abSrjs sctp_process_ecn_marked_a(stcb, net, ecn_bits);
39568c2654abSrjs }
39578c2654abSrjs /* plow through the data chunks while length > offset */
39588c2654abSrjs retval = sctp_process_data(mm, iphlen, &offset, length, sh,
39598c2654abSrjs inp, stcb, net, &high_tsn);
39608c2654abSrjs if (retval == 2) {
39618c2654abSrjs /* The association aborted, NO UNLOCK needed
39628c2654abSrjs * since the association is destroyed.
39638c2654abSrjs */
39648c2654abSrjs return (0);
39658c2654abSrjs }
39668c2654abSrjs
39678c2654abSrjs data_processed = 1;
39688c2654abSrjs if (retval == 0) {
39698c2654abSrjs /* take care of ecn part 2. */
39708c2654abSrjs if (stcb->asoc.ecn_allowed && (ecn_bits & (SCTP_ECT0_BIT|SCTP_ECT1_BIT)) ) {
39718c2654abSrjs sctp_process_ecn_marked_b(stcb, net, high_tsn, ecn_bits);
39728c2654abSrjs
39738c2654abSrjs }
39748c2654abSrjs }
39758c2654abSrjs
39768c2654abSrjs /*
39778c2654abSrjs * Anything important needs to have been m_copy'ed in
39788c2654abSrjs * process_data
39798c2654abSrjs */
39808c2654abSrjs }
39818c2654abSrjs if ((data_processed == 0) && (fwd_tsn_seen)) {
39828c2654abSrjs int was_a_gap = 0;
39838c2654abSrjs if (compare_with_wrap(stcb->asoc.highest_tsn_inside_map,
39848c2654abSrjs stcb->asoc.cumulative_tsn, MAX_TSN)) {
39858c2654abSrjs /* there was a gap before this data was processed */
39868c2654abSrjs was_a_gap = 1;
39878c2654abSrjs }
39888c2654abSrjs sctp_sack_check(stcb, 1, was_a_gap, &abort_flag);
39898c2654abSrjs if (abort_flag) {
39908c2654abSrjs /* Again, we aborted so NO UNLOCK needed */
39918c2654abSrjs return (0);
39928c2654abSrjs }
39938c2654abSrjs }
39948c2654abSrjs /* trigger send of any chunks in queue... */
39958c2654abSrjs #ifdef SCTP_AUDITING_ENABLED
39968c2654abSrjs sctp_audit_log(0xE0, 2);
39978c2654abSrjs sctp_auditing(1, inp, stcb, net);
39988c2654abSrjs #endif
39998c2654abSrjs #ifdef SCTP_DEBUG
40008c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
40018c2654abSrjs printf("Check for chunk output prw:%d tqe:%d tf=%d\n",
40028c2654abSrjs stcb->asoc.peers_rwnd,
40038c2654abSrjs TAILQ_EMPTY(&stcb->asoc.control_send_queue),
40048c2654abSrjs stcb->asoc.total_flight);
40058c2654abSrjs }
40068c2654abSrjs #endif
40078c2654abSrjs if (stcb->asoc.peers_rwnd > 0 ||
40088c2654abSrjs !TAILQ_EMPTY(&stcb->asoc.control_send_queue) ||
40098c2654abSrjs (stcb->asoc.peers_rwnd <= 0 && stcb->asoc.total_flight == 0)) {
40108c2654abSrjs #ifdef SCTP_DEBUG
40118c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
40128c2654abSrjs printf("Calling chunk OUTPUT\n");
40138c2654abSrjs }
40148c2654abSrjs #endif
40158c2654abSrjs sctp_chunk_output(inp, stcb, 3);
40168c2654abSrjs #ifdef SCTP_DEBUG
40178c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT3) {
40188c2654abSrjs printf("chunk OUTPUT returns\n");
40198c2654abSrjs }
40208c2654abSrjs #endif
40218c2654abSrjs }
40228c2654abSrjs
40238c2654abSrjs #ifdef SCTP_AUDITING_ENABLED
40248c2654abSrjs sctp_audit_log(0xE0, 3);
40258c2654abSrjs sctp_auditing(2, inp, stcb, net);
40268c2654abSrjs #endif
40278c2654abSrjs SCTP_TCB_UNLOCK(stcb);
40288c2654abSrjs return (0);
40298c2654abSrjs }
40308c2654abSrjs
40318c2654abSrjs #if defined(__OpenBSD__)
40328c2654abSrjs static void
sctp_saveopt(struct sctp_inpcb * inp,struct mbuf ** mp,struct ip * ip,struct mbuf * m)40338c2654abSrjs sctp_saveopt(struct sctp_inpcb *inp, struct mbuf **mp, struct ip *ip,
40348c2654abSrjs struct mbuf *m)
40358c2654abSrjs {
40368c2654abSrjs if (inp->ip_inp.inp.inp_flags & INP_RECVDSTADDR) {
40378c2654abSrjs *mp = sbcreatecontrol((vaddr_t) &ip->ip_dst,
40388c2654abSrjs sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP);
40398c2654abSrjs if (*mp)
40408c2654abSrjs mp = &(*mp)->m_next;
40418c2654abSrjs }
40428c2654abSrjs }
40438c2654abSrjs #endif
40448c2654abSrjs
40458c2654abSrjs extern int sctp_no_csum_on_loopback;
40468c2654abSrjs
40478c2654abSrjs void
sctp_input(struct mbuf * m,int off,int proto)404815652348Smaxv sctp_input(struct mbuf *m, int off, int proto)
40498c2654abSrjs {
40508c2654abSrjs int iphlen;
40518c2654abSrjs u_int8_t ecn_bits;
40528c2654abSrjs struct ip *ip;
40538c2654abSrjs struct sctphdr *sh;
40548c2654abSrjs struct sctp_inpcb *inp = NULL;
40558c2654abSrjs struct mbuf *opts = 0;
40568c2654abSrjs /*#ifdef INET6*/
40578c2654abSrjs /* Don't think this is needed */
40588c2654abSrjs /* struct ip6_recvpktopts opts6;*/
40598c2654abSrjs /*#endif INET6 */
40608c2654abSrjs
40618c2654abSrjs u_int32_t check, calc_check;
40628c2654abSrjs struct sctp_nets *net;
40638c2654abSrjs struct sctp_tcb *stcb = NULL;
40648c2654abSrjs struct sctp_chunkhdr *ch;
40658c2654abSrjs int refcount_up = 0;
40668c2654abSrjs int length, mlen, offset;
40678c2654abSrjs
406815652348Smaxv iphlen = off;
40698c2654abSrjs
40708c2654abSrjs net = NULL;
40718c2654abSrjs sctp_pegs[SCTP_INPKTS]++;
40728c2654abSrjs #ifdef SCTP_DEBUG
40738c2654abSrjs /*if (sctp_debug_on & SCTP_DEBUG_INPUT1) {*/
40748c2654abSrjs printf("V4 input gets a packet iphlen:%d pktlen:%d\n", iphlen, m->m_pkthdr.len);
40758c2654abSrjs /*}*/
40768c2654abSrjs #endif
40778c2654abSrjs /*#ifdef INET6*/
40788c2654abSrjs /* Don't think this is needed */
40798c2654abSrjs /* bzero(&opts6, sizeof(opts6));*/
40808c2654abSrjs /*#endif INET6 */
40818c2654abSrjs
40828c2654abSrjs /*
40838c2654abSrjs * Strip IP options, we don't allow any in or out.
40848c2654abSrjs */
40858c2654abSrjs if ((size_t)iphlen > sizeof(struct ip)) {
40868c2654abSrjs printf("sctp_input: got options\n");
40878c2654abSrjs #if 0 /* XXX */
40888c2654abSrjs ip_stripoptions(m, (struct mbuf *)0);
40898c2654abSrjs #endif
40908c2654abSrjs iphlen = sizeof(struct ip);
40918c2654abSrjs }
40928c2654abSrjs
40938c2654abSrjs /*
40948c2654abSrjs * Get IP, SCTP, and first chunk header together in first mbuf.
40958c2654abSrjs */
40968c2654abSrjs ip = mtod(m, struct ip *);
40978c2654abSrjs offset = iphlen + sizeof(*sh) + sizeof(*ch);
40988c2654abSrjs if (m->m_len < offset) {
40998c2654abSrjs if ((m = m_pullup(m, offset)) == 0) {
41008c2654abSrjs sctp_pegs[SCTP_HDR_DROPS]++;
41018c2654abSrjs return;
41028c2654abSrjs }
41038c2654abSrjs ip = mtod(m, struct ip *);
41048c2654abSrjs }
41058c2654abSrjs sh = (struct sctphdr *)((vaddr_t)ip + iphlen);
41068c2654abSrjs ch = (struct sctp_chunkhdr *)((vaddr_t)sh + sizeof(*sh));
41078c2654abSrjs
41088c2654abSrjs /* SCTP does not allow broadcasts or multicasts */
41098c2654abSrjs if (IN_MULTICAST(ip->ip_dst.s_addr))
41108c2654abSrjs {
41118c2654abSrjs sctp_pegs[SCTP_IN_MCAST]++;
41128c2654abSrjs goto bad;
41138c2654abSrjs }
4114fe6d4275Sozaki-r if (in_broadcast(ip->ip_dst, m_get_rcvif_NOMPSAFE(m))) {
41158c2654abSrjs sctp_pegs[SCTP_IN_MCAST]++;
41168c2654abSrjs goto bad;
41178c2654abSrjs }
41188c2654abSrjs
41198c2654abSrjs /* destination port of 0 is illegal, based on RFC2960. */
41208c2654abSrjs if (sh->dest_port == 0) {
41218c2654abSrjs sctp_pegs[SCTP_HDR_DROPS]++;
41228c2654abSrjs goto bad;
41238c2654abSrjs }
41248c2654abSrjs
41258c2654abSrjs /* validate SCTP checksum */
41268c2654abSrjs if ((sctp_no_csum_on_loopback == 0) ||
4127fe6d4275Sozaki-r (m_get_rcvif_NOMPSAFE(m) == NULL) ||
4128fe6d4275Sozaki-r (m_get_rcvif_NOMPSAFE(m)->if_type != IFT_LOOP)) {
41298c2654abSrjs /* we do NOT validate things from the loopback if the
41308c2654abSrjs * sysctl is set to 1.
41318c2654abSrjs */
41328c2654abSrjs check = sh->checksum; /* save incoming checksum */
41338c2654abSrjs if ((check == 0) && (sctp_no_csum_on_loopback)) {
41348c2654abSrjs /* special hook for where we got a local address
41358c2654abSrjs * somehow routed across a non IFT_LOOP type interface
41368c2654abSrjs */
41378c2654abSrjs if (ip->ip_src.s_addr == ip->ip_dst.s_addr)
41388c2654abSrjs goto sctp_skip_csum_4;
41398c2654abSrjs }
41408c2654abSrjs sh->checksum = 0; /* prepare for calc */
41418c2654abSrjs calc_check = sctp_calculate_sum(m, &mlen, iphlen);
41428c2654abSrjs if (calc_check != check) {
41438c2654abSrjs #ifdef SCTP_DEBUG
41448c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
41458c2654abSrjs printf("Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n",
41468c2654abSrjs calc_check, check, m, mlen, iphlen);
41478c2654abSrjs }
41488c2654abSrjs #endif
41498c2654abSrjs
41508c2654abSrjs stcb = sctp_findassociation_addr(m, iphlen,
41518c2654abSrjs offset - sizeof(*ch),
41528c2654abSrjs sh, ch, &inp, &net);
41538c2654abSrjs if ((inp) && (stcb)) {
41548c2654abSrjs sctp_send_packet_dropped(stcb, net, m, iphlen,
41558c2654abSrjs 1);
41568c2654abSrjs sctp_chunk_output(inp, stcb, 2);
41578c2654abSrjs } else if ((inp != NULL) && (stcb == NULL)) {
41588c2654abSrjs refcount_up = 1;
41598c2654abSrjs }
41608c2654abSrjs sctp_pegs[SCTP_BAD_CSUM]++;
41618c2654abSrjs goto bad;
41628c2654abSrjs }
41638c2654abSrjs sh->checksum = calc_check;
41648c2654abSrjs } else {
41658c2654abSrjs sctp_skip_csum_4:
41668c2654abSrjs mlen = m->m_pkthdr.len;
41678c2654abSrjs }
41688c2654abSrjs /* validate mbuf chain length with IP payload length */
41698c2654abSrjs #if defined(__NetBSD__) || defined(__OpenBSD__)
41708c2654abSrjs /* Open BSD gives us the len in network order, fix it */
41718c2654abSrjs NTOHS(ip->ip_len);
41728c2654abSrjs #endif
41738c2654abSrjs if (mlen < (ip->ip_len - iphlen)) {
41748c2654abSrjs sctp_pegs[SCTP_HDR_DROPS]++;
41758c2654abSrjs goto bad;
41768c2654abSrjs }
41778c2654abSrjs
41788c2654abSrjs /*
41798c2654abSrjs * Locate pcb and tcb for datagram
41808c2654abSrjs * sctp_findassociation_addr() wants IP/SCTP/first chunk header...
41818c2654abSrjs */
41828c2654abSrjs #ifdef SCTP_DEBUG
41838c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
41848c2654abSrjs printf("V4 find association\n");
41858c2654abSrjs }
41868c2654abSrjs #endif
41878c2654abSrjs
41888c2654abSrjs stcb = sctp_findassociation_addr(m, iphlen, offset - sizeof(*ch),
41898c2654abSrjs sh, ch, &inp, &net);
41908c2654abSrjs /* inp's ref-count increased && stcb locked */
41918c2654abSrjs if (inp == NULL) {
41928c2654abSrjs struct sctp_init_chunk *init_chk, chunk_buf;
41938c2654abSrjs
41948c2654abSrjs sctp_pegs[SCTP_NOPORTS]++;
41958c2654abSrjs #ifdef ICMP_BANDLIM
41968c2654abSrjs /*
41978c2654abSrjs * we use the bandwidth limiting to protect against
41988c2654abSrjs * sending too many ABORTS all at once. In this case
41998c2654abSrjs * these count the same as an ICMP message.
42008c2654abSrjs */
42018c2654abSrjs if (badport_bandlim(0) < 0)
42028c2654abSrjs goto bad;
42038c2654abSrjs #endif /* ICMP_BANDLIM */
42048c2654abSrjs #ifdef SCTP_DEBUG
42058c2654abSrjs if (sctp_debug_on & SCTP_DEBUG_INPUT1) {
42068c2654abSrjs printf("Sending a ABORT from packet entry!\n");
42078c2654abSrjs }
42088c2654abSrjs #endif
42098c2654abSrjs if (ch->chunk_type == SCTP_INITIATION) {
42108c2654abSrjs /* we do a trick here to get the INIT tag,
42118c2654abSrjs * dig in and get the tag from the INIT and
42128c2654abSrjs * put it in the common header.
42138c2654abSrjs */
42148c2654abSrjs init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
42158c2654abSrjs iphlen + sizeof(*sh), sizeof(*init_chk),
42168c2654abSrjs (u_int8_t *)&chunk_buf);
42178c2654abSrjs if (init_chk != NULL)
42188c2654abSrjs sh->v_tag = init_chk->init.initiate_tag;
42198c2654abSrjs }
42208c2654abSrjs sctp_send_abort(m, iphlen, sh, 0, NULL);
42218c2654abSrjs goto bad;
42228c2654abSrjs } else if (stcb == NULL) {
42238c2654abSrjs refcount_up = 1;
42248c2654abSrjs }
42258c2654abSrjs #ifdef IPSEC
42268c2654abSrjs /*
42278c2654abSrjs * I very much doubt any of the IPSEC stuff will work but I have
42288c2654abSrjs * no idea, so I will leave it in place.
42298c2654abSrjs */
4230b39a0dd1Smaxv if (ipsec_used && ipsec_in_reject(m, (struct inpcb *)inp)) {
4231505ea976Srjs #if 0
42328c2654abSrjs ipsecstat.in_polvio++;
4233505ea976Srjs #endif
42348c2654abSrjs sctp_pegs[SCTP_HDR_DROPS]++;
42358c2654abSrjs goto bad;
42368c2654abSrjs }
42378c2654abSrjs #endif /* IPSEC */
42388c2654abSrjs
42398c2654abSrjs /*
42408c2654abSrjs * Construct sockaddr format source address.
42418c2654abSrjs * Stuff source address and datagram in user buffer.
42428c2654abSrjs */
42438c2654abSrjs if ((inp->ip_inp.inp.inp_flags & INP_CONTROLOPTS)
42448c2654abSrjs || (inp->sctp_socket->so_options & SO_TIMESTAMP)
42458c2654abSrjs ) {
42468c2654abSrjs ip_savecontrol((struct inpcb *)inp, &opts, ip, m);
42478c2654abSrjs }
42488c2654abSrjs
42498c2654abSrjs /*
42508c2654abSrjs * common chunk processing
42518c2654abSrjs */
42528c2654abSrjs length = ip->ip_len - (ip->ip_hl << 2) + iphlen;
42538c2654abSrjs offset -= sizeof(struct sctp_chunkhdr);
42548c2654abSrjs
42558c2654abSrjs ecn_bits = ip->ip_tos;
42568c2654abSrjs sctp_common_input_processing(&m, iphlen, offset, length, sh, ch,
42578c2654abSrjs inp, stcb, net, ecn_bits);
42588c2654abSrjs /* inp's ref-count reduced && stcb unlocked */
42598c2654abSrjs sctp_m_freem(m);
42608c2654abSrjs sctp_m_freem(opts);
42618c2654abSrjs
42628c2654abSrjs if ((inp) && (refcount_up)) {
42638c2654abSrjs /* reduce ref-count */
42648c2654abSrjs SCTP_INP_WLOCK(inp);
42658c2654abSrjs SCTP_INP_DECR_REF(inp);
42668c2654abSrjs SCTP_INP_WUNLOCK(inp);
42678c2654abSrjs }
42688c2654abSrjs
42698c2654abSrjs return;
42708c2654abSrjs bad:
42718c2654abSrjs if (stcb) {
42728c2654abSrjs SCTP_TCB_UNLOCK(stcb);
42738c2654abSrjs }
42748c2654abSrjs
42758c2654abSrjs if ((inp) && (refcount_up)) {
42768c2654abSrjs /* reduce ref-count */
42778c2654abSrjs SCTP_INP_WLOCK(inp);
42788c2654abSrjs SCTP_INP_DECR_REF(inp);
42798c2654abSrjs SCTP_INP_WUNLOCK(inp);
42808c2654abSrjs }
42818c2654abSrjs
42828c2654abSrjs sctp_m_freem(m);
42838c2654abSrjs sctp_m_freem(opts);
42848c2654abSrjs return;
42858c2654abSrjs }
4286