diff options
Diffstat (limited to 'sys/netinet/sctp_input.c')
-rw-r--r-- | sys/netinet/sctp_input.c | 84 |
1 files changed, 73 insertions, 11 deletions
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 8674713..5287423 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -1102,10 +1102,17 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, int init_offset, initack_offset, i; int retval; int spec_flag = 0; + int how_indx; /* I know that the TCB is non-NULL from the caller */ asoc = &stcb->asoc; - + for (how_indx = 0; how_indx < sizeof(asoc->cookie_how); i++) { + if (asoc->cookie_how[how_indx] == 0) + break; + } + if (how_indx < sizeof(asoc->cookie_how)) { + asoc->cookie_how[how_indx] = 1; + } if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { /* SHUTDOWN came in after sending INIT-ACK */ struct mbuf *op_err; @@ -1128,6 +1135,8 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, ph->param_type = htons(SCTP_CAUSE_COOKIE_IN_SHUTDOWN); ph->param_length = htons(sizeof(struct sctp_paramhdr)); sctp_send_operr_to(m, iphlen, op_err, cookie->peers_vtag); + if (how_indx < sizeof(asoc->cookie_how)) + asoc->cookie_how[how_indx] = 2; return (NULL); } /* @@ -1170,22 +1179,26 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, * case D in Section 5.2.4 Table 2: MMAA process accordingly * to get into the OPEN state */ + if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) { + panic("Case D and non-match seq?"); + } switch SCTP_GET_STATE (asoc) { case SCTP_STATE_COOKIE_WAIT: + case SCTP_STATE_COOKIE_ECHOED: /* * INIT was sent, but got got a COOKIE_ECHO with the - * correct tags... just accept it... + * correct tags... just accept it...but we must + * process the init so that we can make sure we have + * the right seq no's. */ /* First we must process the INIT !! */ retval = sctp_process_init(init_cp, stcb, net); if (retval < 0) { + if (how_indx < sizeof(asoc->cookie_how)) + asoc->cookie_how[how_indx] = 3; return (NULL); } - /* intentional fall through to below... */ - - case SCTP_STATE_COOKIE_ECHOED: - /* Duplicate INIT case */ /* we have already processed the INIT so no problem */ sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_11); @@ -1246,11 +1259,15 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, if (sctp_load_addresses_from_init(stcb, m, iphlen, init_offset + sizeof(struct sctp_init_chunk), initack_offset, sh, init_src)) { + if (how_indx < sizeof(asoc->cookie_how)) + asoc->cookie_how[how_indx] = 4; return (NULL); } /* respond with a COOKIE-ACK */ sctp_toss_old_cookies(stcb, asoc); sctp_send_cookie_ack(stcb); + if (how_indx < sizeof(asoc->cookie_how)) + asoc->cookie_how[how_indx] = 5; return (stcb); } /* end if */ if (ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag && @@ -1260,6 +1277,8 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, /* * case C in Section 5.2.4 Table 2: XMOO silently discard */ + if (how_indx < sizeof(asoc->cookie_how)) + asoc->cookie_how[how_indx] = 6; return (NULL); } if (ntohl(initack_cp->init.initiate_tag) == asoc->my_vtag && @@ -1269,6 +1288,31 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, * case B in Section 5.2.4 Table 2: MXAA or MOAA my info * should be ok, re-accept peer info */ + if (ntohl(initack_cp->init.initial_tsn) != asoc->init_seq_number) { + /* + * Extension of case C. If we hit this, then the + * random number generator returned the same vtag + * when we first sent our INIT-ACK and when we later + * sent our INIT. The side with the seq numbers that + * are different will be the one that normnally + * would have hit case C. This in effect "extends" + * our vtags in this collision case to be 64 bits. + * The same collision could occur aka you get both + * vtag and seq number the same twice in a row.. but + * is much less likely. If it did happen then we + * would proceed through and bring up the assoc.. we + * may end up with the wrong stream setup however.. + * which would be bad.. but there is no way to + * tell.. until we send on a stream that does not + * exist :-) + */ + if (how_indx < sizeof(asoc->cookie_how)) + asoc->cookie_how[how_indx] = 7; + + return (NULL); + } + if (how_indx < sizeof(asoc->cookie_how)) + asoc->cookie_how[how_indx] = 8; sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_13); sctp_stop_all_cookie_timers(stcb); /* @@ -1309,11 +1353,15 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, /* process the INIT info (peer's info) */ retval = sctp_process_init(init_cp, stcb, net); if (retval < 0) { + if (how_indx < sizeof(asoc->cookie_how)) + asoc->cookie_how[how_indx] = 9; return (NULL); } if (sctp_load_addresses_from_init(stcb, m, iphlen, init_offset + sizeof(struct sctp_init_chunk), initack_offset, sh, init_src)) { + if (how_indx < sizeof(asoc->cookie_how)) + asoc->cookie_how[how_indx] = 10; return (NULL); } if ((asoc->state & SCTP_STATE_COOKIE_WAIT) || @@ -1350,6 +1398,9 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, */ sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_COOKIE_ACK); } + if (how_indx < sizeof(asoc->cookie_how)) + asoc->cookie_how[how_indx] = 11; + return (stcb); } if ((ntohl(initack_cp->init.initiate_tag) != asoc->my_vtag && @@ -1363,6 +1414,8 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, * case A in Section 5.2.4 Table 2: XXMM (peer restarted) */ /* temp code */ + if (how_indx < sizeof(asoc->cookie_how)) + asoc->cookie_how[how_indx] = 12; sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_14); sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_INPUT + SCTP_LOC_15); @@ -1438,6 +1491,9 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, retval = sctp_process_init(init_cp, stcb, net); if (retval < 0) { + if (how_indx < sizeof(asoc->cookie_how)) + asoc->cookie_how[how_indx] = 13; + return (NULL); } /* @@ -1449,18 +1505,24 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, if (sctp_load_addresses_from_init(stcb, m, iphlen, init_offset + sizeof(struct sctp_init_chunk), initack_offset, sh, init_src)) { + if (how_indx < sizeof(asoc->cookie_how)) + asoc->cookie_how[how_indx] = 14; + return (NULL); } /* respond with a COOKIE-ACK */ sctp_stop_all_cookie_timers(stcb); sctp_toss_old_cookies(stcb, asoc); sctp_send_cookie_ack(stcb); + if (how_indx < sizeof(asoc->cookie_how)) + asoc->cookie_how[how_indx] = 15; return (stcb); } /* if we are not a restart we need the assoc_id field pop'd */ asoc->assoc_id = ntohl(initack_cp->init.initiate_tag); - + if (how_indx < sizeof(asoc->cookie_how)) + asoc->cookie_how[how_indx] = 16; /* all other cases... */ return (NULL); } @@ -3076,6 +3138,7 @@ sctp_handle_stream_reset(struct sctp_tcb *stcb, struct sctp_stream_reset_out_req chk->asoc = &stcb->asoc; chk->no_fr_allowed = 0; chk->book_size = chk->send_size = sizeof(struct sctp_chunkhdr); + chk->book_size_scale = 0; chk->data = sctp_get_mbuf_for_msg(MCLBYTES, 0, M_DONTWAIT, 1, MT_DATA); if (chk->data == NULL) { strres_nochunk: @@ -4266,7 +4329,7 @@ process_control_chunks: phd->param_type = htons(SCTP_CAUSE_UNRECOG_CHUNK); phd->param_length = htons(chk_length + sizeof(*phd)); SCTP_BUF_LEN(mm) = sizeof(*phd); - SCTP_BUF_NEXT(mm) = sctp_m_copym(m, *offset, SCTP_SIZE32(chk_length), + SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, SCTP_SIZE32(chk_length), M_DONTWAIT); if (SCTP_BUF_NEXT(mm)) { sctp_queue_op_err(stcb, mm); @@ -4687,8 +4750,7 @@ sctp_input(i_pak, off) goto bad; } /* validate SCTP checksum */ - if ((sctp_no_csum_on_loopback == 0) || - SCTP_IS_IT_LOOPBACK(i_pak)) { + if ((sctp_no_csum_on_loopback == 0) || !SCTP_IS_IT_LOOPBACK(i_pak)) { /* * we do NOT validate things from the loopback if the sysctl * is set to 1. @@ -4740,7 +4802,7 @@ sctp_skip_csum_4: int x; x = atomic_fetchadd_int(&sctp_buf_index, 1); - if (x > 30000) { + if (x >= 30000) { sctp_buf_index = 1; x = 0;; } |