diff options
author | tuexen <tuexen@FreeBSD.org> | 2014-06-22 16:28:52 +0000 |
---|---|---|
committer | tuexen <tuexen@FreeBSD.org> | 2014-06-22 16:28:52 +0000 |
commit | bfa185cf87a08086dbf1c5a1511f85f3c71ffba7 (patch) | |
tree | 82bfc760cb279faed99e0faa9190ad31973ea089 /sys/netinet/sctp_input.c | |
parent | 23098a703ac8e491721697eacf342e5e61144188 (diff) | |
download | FreeBSD-src-bfa185cf87a08086dbf1c5a1511f85f3c71ffba7.zip FreeBSD-src-bfa185cf87a08086dbf1c5a1511f85f3c71ffba7.tar.gz |
MFC r263237:
* Provide information in error causes in ASCII instead of
proprietary binary format.
* Add support for a diagnostic information error cause.
The code is sysctlable and the default is 0, which
means it is not sent.
This is joint work with rrs@.
Diffstat (limited to 'sys/netinet/sctp_input.c')
-rw-r--r-- | sys/netinet/sctp_input.c | 122 |
1 files changed, 57 insertions, 65 deletions
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c index 6ea85f5..2be2b87 100644 --- a/sys/netinet/sctp_input.c +++ b/sys/netinet/sctp_input.c @@ -97,7 +97,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, } /* validate length */ if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_chunk)) { - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, vrf_id, port); @@ -109,7 +109,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, init = &cp->init; if (init->initiate_tag == 0) { /* protocol error... send abort */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, vrf_id, port); @@ -119,7 +119,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, } if (ntohl(init->a_rwnd) < SCTP_MIN_RWND) { /* invalid parameter... send abort */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, vrf_id, port); @@ -129,7 +129,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, } if (init->num_inbound_streams == 0) { /* protocol error... send abort */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, vrf_id, port); @@ -139,7 +139,7 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, } if (init->num_outbound_streams == 0) { /* protocol error... send abort */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, vrf_id, port); @@ -150,7 +150,9 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, if (sctp_validate_init_auth_params(m, offset + sizeof(*cp), offset + ntohs(cp->ch.chunk_length))) { /* auth parameter(s) error... send abort */ - sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, NULL, + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + "Problem with AUTH parameters"); + sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, vrf_id, port); if (stcb) @@ -179,7 +181,9 @@ sctp_handle_init(struct mbuf *m, int iphlen, int offset, * state :-) */ if (SCTP_BASE_SYSCTL(sctp_blackhole) == 0) { - sctp_send_abort(m, iphlen, src, dst, sh, 0, NULL, + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + "No listener"); + sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, use_mflowid, mflowid, vrf_id, port); } @@ -461,12 +465,13 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset, if ((retval = sctp_load_addresses_from_init(stcb, m, (offset + sizeof(struct sctp_init_chunk)), initack_limit, src, dst, NULL))) { - /* Huh, we should abort */ + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + "Problem with address parameters"); SCTPDBG(SCTP_DEBUG_INPUT1, "Load addresses from INIT causes an abort %d\n", retval); sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, - src, dst, sh, NULL, + src, dst, sh, op_err, use_mflowid, mflowid, vrf_id, net->port); *abort_no_unlock = 1; @@ -521,8 +526,7 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset, */ if (retval == -3) { /* We abort with an error of missing mandatory param */ - op_err = - sctp_generate_invmanparam(SCTP_CAUSE_MISSING_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_MISSING_PARAM, ""); if (op_err) { /* * Expand beyond to include the mandatory @@ -1305,7 +1309,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, } if (ntohs(cp->ch.chunk_length) < sizeof(struct sctp_init_ack_chunk)) { /* Invalid length */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -1317,7 +1321,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, /* validate parameters */ if (init_ack->initiate_tag == 0) { /* protocol error... send an abort */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -1327,7 +1331,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, } if (ntohl(init_ack->a_rwnd) < SCTP_MIN_RWND) { /* protocol error... send an abort */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -1337,7 +1341,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, } if (init_ack->num_inbound_streams == 0) { /* protocol error... send an abort */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -1347,7 +1351,7 @@ sctp_handle_init_ack(struct mbuf *m, int iphlen, int offset, } if (init_ack->num_outbound_streams == 0) { /* protocol error... send an abort */ - op_err = sctp_generate_invmanparam(SCTP_CAUSE_INVALID_PARAM); + op_err = sctp_generate_cause(SCTP_CAUSE_INVALID_PARAM, ""); sctp_abort_association(stcb->sctp_ep, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -1457,7 +1461,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, struct sctp_init_ack_chunk *initack_cp, initack_buf; struct sctp_nets *net; struct mbuf *op_err; - struct sctp_paramhdr *ph; int init_offset, initack_offset, i; int retval; int spec_flag = 0; @@ -1476,17 +1479,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, if (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_ACK_SENT) { /* SHUTDOWN came in after sending INIT-ACK */ sctp_send_shutdown_ack(stcb, stcb->asoc.primary_destination); - op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), - 0, M_NOWAIT, 1, MT_DATA); - if (op_err == NULL) { - /* FOOBAR */ - return (NULL); - } - /* Set the len */ - SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); - ph = mtod(op_err, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_COOKIE_IN_SHUTDOWN); - ph->param_length = htons(sizeof(struct sctp_paramhdr)); + op_err = sctp_generate_cause(SCTP_CAUSE_COOKIE_IN_SHUTDOWN, ""); sctp_send_operr_to(src, dst, sh, cookie->peers_vtag, op_err, use_mflowid, mflowid, vrf_id, net->port); @@ -1693,25 +1686,7 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset, * Now we have colliding state. We must send an abort here * with colliding state indication. */ - op_err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), - 0, M_NOWAIT, 1, MT_DATA); - if (op_err == NULL) { - /* FOOBAR */ - return (NULL); - } - /* pre-reserve some space */ -#ifdef INET6 - SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr)); -#else - SCTP_BUF_RESV_UF(op_err, sizeof(struct ip)); -#endif - SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr)); - SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr)); - /* Set the len */ - SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr); - ph = mtod(op_err, struct sctp_paramhdr *); - ph->param_type = htons(SCTP_CAUSE_NAT_COLLIDING_STATE); - ph->param_length = htons(sizeof(struct sctp_paramhdr)); + op_err = sctp_generate_cause(SCTP_CAUSE_NAT_COLLIDING_STATE, ""); sctp_send_abort(m, iphlen, src, dst, sh, 0, op_err, use_mflowid, mflowid, vrf_id, port); @@ -2124,8 +2099,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, /* memory problem? */ SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: no room for another TCB!\n"); - op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); - + op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -2153,7 +2127,7 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset, * association. */ atomic_add_int(&stcb->asoc.refcnt, 1); - op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); + op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); sctp_abort_association(inp, (struct sctp_tcb *)NULL, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -2772,7 +2746,7 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset, #endif /* Too many sockets */ SCTPDBG(SCTP_DEBUG_INPUT1, "process_cookie_new: no room for another socket!\n"); - op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); + op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); sctp_abort_association(*inp_p, NULL, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -4394,6 +4368,8 @@ __attribute__((noinline)) uint32_t vrf_id, uint16_t port) { struct sctp_association *asoc; + struct mbuf *op_err; + char msg[SCTP_DIAG_INFO_LEN]; uint32_t vtag_in; int num_chunks = 0; /* number of control chunks processed */ uint32_t chk_length; @@ -4547,8 +4523,11 @@ __attribute__((noinline)) } } if (stcb == NULL) { + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); /* no association, so it's out of the blue... */ - sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp, + sctp_handle_ootb(m, iphlen, *offset, src, dst, sh, inp, op_err, use_mflowid, mflowid, vrf_id, port); *offset = length; @@ -4588,8 +4567,11 @@ __attribute__((noinline)) if (locked_tcb) { SCTP_TCB_UNLOCK(locked_tcb); } + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); sctp_handle_ootb(m, iphlen, *offset, src, dst, - sh, inp, + sh, inp, op_err, use_mflowid, mflowid, vrf_id, port); return (NULL); @@ -4731,8 +4713,10 @@ process_control_chunks: /* The INIT chunk must be the only chunk. */ if ((num_chunks > 1) || (length - *offset > (int)SCTP_SIZE32(chk_length))) { + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + "INIT not the only chunk"); sctp_abort_association(inp, stcb, m, iphlen, - src, dst, sh, NULL, + src, dst, sh, op_err, use_mflowid, mflowid, vrf_id, port); *offset = length; @@ -4740,9 +4724,7 @@ process_control_chunks: } /* Honor our resource limit. */ if (chk_length > SCTP_LARGEST_INIT_ACCEPTED) { - struct mbuf *op_err; - - op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); + op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -5110,9 +5092,7 @@ process_control_chunks: if ((stcb == NULL) && (inp->sctp_socket->so_qlen >= inp->sctp_socket->so_qlimit)) { if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && (SCTP_BASE_SYSCTL(sctp_abort_if_one_2_one_hits_limit))) { - struct mbuf *op_err; - - op_err = sctp_generate_invmanparam(SCTP_CAUSE_OUT_OF_RESC); + op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, ""); sctp_abort_association(inp, stcb, m, iphlen, src, dst, sh, op_err, use_mflowid, mflowid, @@ -5597,7 +5577,8 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt { uint32_t high_tsn; int fwd_tsn_seen = 0, data_processed = 0; - struct mbuf *m = *mm; + struct mbuf *m = *mm, *op_err; + char msg[SCTP_DIAG_INFO_LEN]; int un_sent; int cnt_ctrl_ready = 0; struct sctp_inpcb *inp = NULL, *inp_decr = NULL; @@ -5683,8 +5664,10 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt if ((SCTP_BASE_SYSCTL(sctp_blackhole) == 0) || ((SCTP_BASE_SYSCTL(sctp_blackhole) == 1) && (ch->chunk_type != SCTP_INIT))) { + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + "Out of the blue"); sctp_send_abort(m, iphlen, src, dst, - sh, 0, NULL, + sh, 0, op_err, use_mflowid, mflowid, vrf_id, port); } @@ -5742,7 +5725,10 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt */ SCTP_TCB_UNLOCK(stcb); stcb = NULL; - sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); + sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, use_mflowid, mflowid, vrf_id, port); goto out; @@ -5789,7 +5775,10 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt } if (stcb == NULL) { /* out of the blue DATA chunk */ - sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); + sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, use_mflowid, mflowid, vrf_id, port); goto out; @@ -5858,7 +5847,10 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt /* * We consider OOTB any data sent during asoc setup. */ - sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, + snprintf(msg, sizeof(msg), "OOTB, %s:%d at %s\n", __FILE__, __LINE__, __FUNCTION__); + op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code), + msg); + sctp_handle_ootb(m, iphlen, offset, src, dst, sh, inp, op_err, use_mflowid, mflowid, vrf_id, port); goto out; |