From owner-svn-src-head@freebsd.org Sat Sep 12 17:08:53 2015 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 31773A0364B; Sat, 12 Sep 2015 17:08:53 +0000 (UTC) (envelope-from tuexen@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1E1DC1598; Sat, 12 Sep 2015 17:08:53 +0000 (UTC) (envelope-from tuexen@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.70]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id t8CH8rrY048716; Sat, 12 Sep 2015 17:08:53 GMT (envelope-from tuexen@FreeBSD.org) Received: (from tuexen@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id t8CH8pXU048651; Sat, 12 Sep 2015 17:08:51 GMT (envelope-from tuexen@FreeBSD.org) Message-Id: <201509121708.t8CH8pXU048651@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: tuexen set sender to tuexen@FreeBSD.org using -f From: Michael Tuexen Date: Sat, 12 Sep 2015 17:08:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r287717 - head/sys/netinet X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 12 Sep 2015 17:08:53 -0000 Author: tuexen Date: Sat Sep 12 17:08:51 2015 New Revision: 287717 URL: https://svnweb.freebsd.org/changeset/base/287717 Log: Cleanup the handling of error causes for ERROR chunks. This fixes an inconsistency of the padding handling. The final padding is now considered to be a chunk padding. MFC after: 1 week Modified: head/sys/netinet/sctp.h head/sys/netinet/sctp_auth.c head/sys/netinet/sctp_header.h head/sys/netinet/sctp_indata.c head/sys/netinet/sctp_input.c Modified: head/sys/netinet/sctp.h ============================================================================== --- head/sys/netinet/sctp.h Sat Sep 12 16:46:41 2015 (r287716) +++ head/sys/netinet/sctp.h Sat Sep 12 17:08:51 2015 (r287717) @@ -388,33 +388,32 @@ struct sctp_error_cause { } SCTP_PACKED; struct sctp_error_invalid_stream { - struct sctp_error_cause cause; /* code=SCTP_ERROR_INVALID_STREAM */ + struct sctp_error_cause cause; /* code=SCTP_CAUSE_INVALID_STREAM */ uint16_t stream_id; /* stream id of the DATA in error */ uint16_t reserved; } SCTP_PACKED; struct sctp_error_missing_param { - struct sctp_error_cause cause; /* code=SCTP_ERROR_MISSING_PARAM */ + struct sctp_error_cause cause; /* code=SCTP_CAUSE_MISSING_PARAM */ uint32_t num_missing_params; /* number of missing parameters */ - /* uint16_t param_type's follow */ + uint16_t type[]; } SCTP_PACKED; struct sctp_error_stale_cookie { - struct sctp_error_cause cause; /* code=SCTP_ERROR_STALE_COOKIE */ + struct sctp_error_cause cause; /* code=SCTP_CAUSE_STALE_COOKIE */ uint32_t stale_time; /* time in usec of staleness */ } SCTP_PACKED; struct sctp_error_out_of_resource { - struct sctp_error_cause cause; /* code=SCTP_ERROR_OUT_OF_RESOURCES */ + struct sctp_error_cause cause; /* code=SCTP_CAUSE_OUT_OF_RESOURCES */ } SCTP_PACKED; struct sctp_error_unresolv_addr { - struct sctp_error_cause cause; /* code=SCTP_ERROR_UNRESOLVABLE_ADDR */ - + struct sctp_error_cause cause; /* code=SCTP_CAUSE_UNRESOLVABLE_ADDR */ } SCTP_PACKED; struct sctp_error_unrecognized_chunk { - struct sctp_error_cause cause; /* code=SCTP_ERROR_UNRECOG_CHUNK */ + struct sctp_error_cause cause; /* code=SCTP_CAUSE_UNRECOG_CHUNK */ struct sctp_chunkhdr ch;/* header from chunk in error */ } SCTP_PACKED; @@ -423,6 +422,11 @@ struct sctp_error_no_user_data { uint32_t tsn; /* TSN of the empty data chunk */ } SCTP_PACKED; +struct sctp_error_auth_invalid_hmac { + struct sctp_error_cause cause; /* code=SCTP_CAUSE_UNSUPPORTED_HMACID */ + uint16_t hmac_id; +} SCTP_PACKED; + /* * Main SCTP chunk types we place these here so natd and f/w's in user land * can find them. Modified: head/sys/netinet/sctp_auth.c ============================================================================== --- head/sys/netinet/sctp_auth.c Sat Sep 12 16:46:41 2015 (r287716) +++ head/sys/netinet/sctp_auth.c Sat Sep 12 17:08:51 2015 (r287717) @@ -1651,8 +1651,8 @@ sctp_handle_auth(struct sctp_tcb *stcb, /* is the indicated HMAC supported? */ if (!sctp_auth_is_supported_hmac(stcb->asoc.local_hmacs, hmac_id)) { - struct mbuf *m_err; - struct sctp_auth_invalid_hmac *err; + struct mbuf *op_err; + struct sctp_error_auth_invalid_hmac *cause; SCTP_STAT_INCR(sctps_recvivalhmacid); SCTPDBG(SCTP_DEBUG_AUTH1, @@ -1662,20 +1662,19 @@ sctp_handle_auth(struct sctp_tcb *stcb, * report this in an Error Chunk: Unsupported HMAC * Identifier */ - m_err = sctp_get_mbuf_for_msg(sizeof(*err), 0, M_NOWAIT, - 1, MT_HEADER); - if (m_err != NULL) { + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_auth_invalid_hmac), + 0, M_NOWAIT, 1, MT_HEADER); + if (op_err != NULL) { /* pre-reserve some space */ - SCTP_BUF_RESV_UF(m_err, sizeof(struct sctp_chunkhdr)); + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); /* fill in the error */ - err = mtod(m_err, struct sctp_auth_invalid_hmac *); - bzero(err, sizeof(*err)); - err->ph.param_type = htons(SCTP_CAUSE_UNSUPPORTED_HMACID); - err->ph.param_length = htons(sizeof(*err)); - err->hmac_id = ntohs(hmac_id); - SCTP_BUF_LEN(m_err) = sizeof(*err); + cause = mtod(op_err, struct sctp_error_auth_invalid_hmac *); + cause->cause.code = htons(SCTP_CAUSE_UNSUPPORTED_HMACID); + cause->cause.length = htons(sizeof(struct sctp_error_auth_invalid_hmac)); + cause->hmac_id = ntohs(hmac_id); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_auth_invalid_hmac); /* queue it */ - sctp_queue_op_err(stcb, m_err); + sctp_queue_op_err(stcb, op_err); } return (-1); } Modified: head/sys/netinet/sctp_header.h ============================================================================== --- head/sys/netinet/sctp_header.h Sat Sep 12 16:46:41 2015 (r287716) +++ head/sys/netinet/sctp_header.h Sat Sep 12 17:08:51 2015 (r287717) @@ -202,34 +202,6 @@ struct sctp_state_cookie { /* this is ou */ } SCTP_PACKED; - -/* Used for NAT state error cause */ -struct sctp_missing_nat_state { - uint16_t cause; - uint16_t length; - uint8_t data[]; -} SCTP_PACKED; - - -struct sctp_inv_mandatory_param { - uint16_t cause; - uint16_t length; - uint32_t num_param; - uint16_t param; - /* - * We include this to 0 it since only a missing cookie will cause - * this error. - */ - uint16_t resv; -} SCTP_PACKED; - -struct sctp_unresolv_addr { - uint16_t cause; - uint16_t length; - uint16_t addr_type; - uint16_t reserved; /* Only one invalid addr type */ -} SCTP_PACKED; - /* state cookie parameter */ struct sctp_state_cookie_param { struct sctp_paramhdr ph; @@ -370,28 +342,11 @@ struct sctp_shutdown_complete_chunk { struct sctp_chunkhdr ch; } SCTP_PACKED; -/* Oper error holding a stale cookie */ -struct sctp_stale_cookie_msg { - struct sctp_paramhdr ph;/* really an error cause */ - uint32_t time_usec; -} SCTP_PACKED; - struct sctp_adaptation_layer_indication { struct sctp_paramhdr ph; uint32_t indication; } SCTP_PACKED; -struct sctp_cookie_while_shutting_down { - struct sctphdr sh; - struct sctp_chunkhdr ch; - struct sctp_paramhdr ph;/* really an error cause */ -} SCTP_PACKED; - -struct sctp_shutdown_complete_msg { - struct sctphdr sh; - struct sctp_shutdown_complete_chunk shut_cmp; -} SCTP_PACKED; - /* * draft-ietf-tsvwg-addip-sctp */ @@ -554,12 +509,6 @@ struct sctp_auth_chunk { uint8_t hmac[]; } SCTP_PACKED; -struct sctp_auth_invalid_hmac { - struct sctp_paramhdr ph; - uint16_t hmac_id; - uint16_t padding; -} SCTP_PACKED; - /* * we pre-reserve enough room for a ECNE or CWR AND a SACK with no missing * pieces. If ENCE is missing we could have a couple of blocks. This way we Modified: head/sys/netinet/sctp_indata.c ============================================================================== --- head/sys/netinet/sctp_indata.c Sat Sep 12 16:46:41 2015 (r287716) +++ head/sys/netinet/sctp_indata.c Sat Sep 12 17:08:51 2015 (r287717) @@ -1426,30 +1426,25 @@ sctp_process_a_data_chunk(struct sctp_tc } strmno = ntohs(ch->dp.stream_id); if (strmno >= asoc->streamincnt) { - struct sctp_paramhdr *phdr; - struct mbuf *mb; + struct sctp_error_invalid_stream *cause; - mb = sctp_get_mbuf_for_msg((sizeof(struct sctp_paramhdr) * 2), + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_invalid_stream), 0, M_NOWAIT, 1, MT_DATA); - if (mb != NULL) { + if (op_err != NULL) { /* add some space up front so prepend will work well */ - SCTP_BUF_RESV_UF(mb, sizeof(struct sctp_chunkhdr)); - phdr = mtod(mb, struct sctp_paramhdr *); + SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); + cause = mtod(op_err, struct sctp_error_invalid_stream *); /* * Error causes are just param's and this one has * two back to back phdr, one with the error type * and size, the other with the streamid and a rsvd */ - SCTP_BUF_LEN(mb) = (sizeof(struct sctp_paramhdr) * 2); - phdr->param_type = htons(SCTP_CAUSE_INVALID_STREAM); - phdr->param_length = - htons(sizeof(struct sctp_paramhdr) * 2); - phdr++; - /* We insert the stream in the type field */ - phdr->param_type = ch->dp.stream_id; - /* And set the length to 0 for the rsvd field */ - phdr->param_length = 0; - sctp_queue_op_err(stcb, mb); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_invalid_stream); + cause->cause.code = htons(SCTP_CAUSE_INVALID_STREAM); + cause->cause.length = htons(sizeof(struct sctp_error_invalid_stream)); + cause->stream_id = ch->dp.stream_id; + cause->reserved = htons(0); + sctp_queue_op_err(stcb, op_err); } SCTP_STAT_INCR(sctps_badsid); SCTP_TCB_LOCK_ASSERT(stcb); @@ -2492,30 +2487,21 @@ sctp_process_data(struct mbuf **mm, int /* unknown chunk type, use bit rules */ if (ch->ch.chunk_type & 0x40) { /* Add a error report to the queue */ - struct mbuf *merr; - struct sctp_paramhdr *phd; + struct mbuf *op_err; + struct sctp_gen_error_cause *cause; - merr = sctp_get_mbuf_for_msg(sizeof(*phd), 0, M_NOWAIT, 1, MT_DATA); - if (merr) { - phd = mtod(merr, struct sctp_paramhdr *); - /* - * We cheat and use param - * type since we did not - * bother to define a error - * cause struct. They are - * the same basic format - * with different names. - */ - phd->param_type = - htons(SCTP_CAUSE_UNRECOG_CHUNK); - phd->param_length = - htons(chk_length + sizeof(*phd)); - SCTP_BUF_LEN(merr) = sizeof(*phd); - SCTP_BUF_NEXT(merr) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT); - if (SCTP_BUF_NEXT(merr)) { - sctp_queue_op_err(stcb, merr); + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_gen_error_cause), + 0, M_NOWAIT, 1, MT_DATA); + if (op_err != NULL) { + cause = mtod(op_err, struct sctp_gen_error_cause *); + cause->code = htons(SCTP_CAUSE_UNRECOG_CHUNK); + cause->length = htons(chk_length + sizeof(struct sctp_gen_error_cause)); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause); + SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT); + if (SCTP_BUF_NEXT(op_err) != NULL) { + sctp_queue_op_err(stcb, op_err); } else { - sctp_m_freem(merr); + sctp_m_freem(op_err); } } } Modified: head/sys/netinet/sctp_input.c ============================================================================== --- head/sys/netinet/sctp_input.c Sat Sep 12 16:46:41 2015 (r287716) +++ head/sys/netinet/sctp_input.c Sat Sep 12 17:08:51 2015 (r287717) @@ -530,25 +530,21 @@ sctp_process_init_ack(struct mbuf *m, in * abandon the peer, its broke. */ if (retval == -3) { + size_t len; + + len = sizeof(struct sctp_error_missing_param) + sizeof(uint16_t); /* We abort with an error of missing mandatory param */ - op_err = sctp_generate_cause(SCTP_CAUSE_MISSING_PARAM, ""); - if (op_err) { - /* - * Expand beyond to include the mandatory - * param cookie - */ - struct sctp_inv_mandatory_param *mp; + op_err = sctp_get_mbuf_for_msg(len, 0, M_NOWAIT, 1, MT_DATA); + if (op_err != NULL) { + struct sctp_error_missing_param *cause; - SCTP_BUF_LEN(op_err) = - sizeof(struct sctp_inv_mandatory_param); - mp = mtod(op_err, - struct sctp_inv_mandatory_param *); + SCTP_BUF_LEN(op_err) = len; + cause = mtod(op_err, struct sctp_error_missing_param *); /* Subtract the reserved param */ - mp->length = - htons(sizeof(struct sctp_inv_mandatory_param) - 2); - mp->num_param = htonl(1); - mp->param = htons(SCTP_STATE_COOKIE); - mp->resv = 0; + cause->cause.code = htons(SCTP_CAUSE_MISSING_PARAM); + cause->cause.length = htons(len); + cause->num_missing_params = htonl(1); + cause->type[0] = htons(SCTP_STATE_COOKIE); } sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, src, dst, sh, op_err, @@ -781,10 +777,10 @@ sctp_handle_abort(struct sctp_abort_chun * Need to check the cause codes for our two magic nat * aborts which don't kill the assoc necessarily. */ - struct sctp_missing_nat_state *natc; + struct sctp_gen_error_cause *cause; - natc = (struct sctp_missing_nat_state *)(abort + 1); - error = ntohs(natc->cause); + cause = (struct sctp_gen_error_cause *)(abort + 1); + error = ntohs(cause->code); if (error == SCTP_CAUSE_NAT_COLLIDING_STATE) { SCTPDBG(SCTP_DEBUG_INPUT2, "Received Colliding state abort flags:%x\n", abort->ch.chunk_flags); @@ -2558,27 +2554,27 @@ sctp_handle_cookie_echo(struct mbuf *m, if (timevalcmp(&now, &time_expires, >)) { /* cookie is stale! */ struct mbuf *op_err; - struct sctp_stale_cookie_msg *scm; + struct sctp_error_stale_cookie *cause; uint32_t tim; - op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_stale_cookie_msg), + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_error_stale_cookie), 0, M_NOWAIT, 1, MT_DATA); if (op_err == NULL) { /* FOOBAR */ return (NULL); } /* Set the len */ - SCTP_BUF_LEN(op_err) = sizeof(struct sctp_stale_cookie_msg); - scm = mtod(op_err, struct sctp_stale_cookie_msg *); - scm->ph.param_type = htons(SCTP_CAUSE_STALE_COOKIE); - scm->ph.param_length = htons((sizeof(struct sctp_paramhdr) + + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_error_stale_cookie); + cause = mtod(op_err, struct sctp_error_stale_cookie *); + cause->cause.code = htons(SCTP_CAUSE_STALE_COOKIE); + cause->cause.length = htons((sizeof(struct sctp_paramhdr) + (sizeof(uint32_t)))); /* seconds to usec */ tim = (now.tv_sec - time_expires.tv_sec) * 1000000; /* add in usec */ if (tim == 0) tim = now.tv_usec - cookie->time_entered.tv_usec; - scm->time_usec = htonl(tim); + cause->stale_time = htonl(tim); sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, mflowtype, mflowid, l_inp->fibnum, vrf_id, port); @@ -5581,35 +5577,27 @@ process_control_chunks: unknown_chunk: /* it's an unknown chunk! */ if ((ch->chunk_type & 0x40) && (stcb != NULL)) { - struct mbuf *mm; - struct sctp_paramhdr *phd; + struct sctp_gen_error_cause *cause; int len; - mm = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), + op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_gen_error_cause), 0, M_NOWAIT, 1, MT_DATA); - if (mm) { + if (op_err != NULL) { len = min(SCTP_SIZE32(chk_length), (uint32_t) (length - *offset)); - phd = mtod(mm, struct sctp_paramhdr *); - /* - * We cheat and use param type since - * we did not bother to define a - * error cause struct. They are the - * same basic format with different - * names. - */ - phd->param_type = htons(SCTP_CAUSE_UNRECOG_CHUNK); - phd->param_length = htons(len + sizeof(*phd)); - SCTP_BUF_LEN(mm) = sizeof(*phd); - SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, len, M_NOWAIT); - if (SCTP_BUF_NEXT(mm)) { + cause = mtod(op_err, struct sctp_gen_error_cause *); + cause->code = htons(SCTP_CAUSE_UNRECOG_CHUNK); + cause->length = htons(len + sizeof(struct sctp_gen_error_cause)); + SCTP_BUF_LEN(op_err) = sizeof(struct sctp_gen_error_cause); + SCTP_BUF_NEXT(op_err) = SCTP_M_COPYM(m, *offset, len, M_NOWAIT); + if (SCTP_BUF_NEXT(op_err) != NULL) { #ifdef SCTP_MBUF_LOGGING if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) { sctp_log_mbc(SCTP_BUF_NEXT(mm), SCTP_MBUF_ICOPY); } #endif - sctp_queue_op_err(stcb, mm); + sctp_queue_op_err(stcb, op_err); } else { - sctp_m_freem(mm); + sctp_m_freem(op_err); } } }