diff --git a/src/bbl_ctrl.c b/src/bbl_ctrl.c index 8dfdf590..ee040430 100644 --- a/src/bbl_ctrl.c +++ b/src/bbl_ctrl.c @@ -692,9 +692,9 @@ bbl_ctrl_li_flows(int fd, bbl_ctx_s *ctx, session_key_t *key __attribute__((unus } } root = json_pack("{ss si so}", - "status", "ok", - "code", 200, - "li-flows", flows); + "status", "ok", + "code", 200, + "li-flows", flows); if(root) { result = json_dumpfd(root, fd, 0); json_decref(root); diff --git a/src/bbl_l2tp.c b/src/bbl_l2tp.c index c7a8b901..4e13ff7d 100644 --- a/src/bbl_l2tp.c +++ b/src/bbl_l2tp.c @@ -265,6 +265,9 @@ bbl_l2tp_tunnel_tx_job (timer_s *timer) { l2tp_tunnel->stats.control_retry++; interface->stats.l2tp_control_retry++; if(q->retries > l2tp_tunnel->server->max_retry) { + l2tp_tunnel->result_code = 2; + l2tp_tunnel->error_code = 6; + l2tp_tunnel->error_message = "max retry"; bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN); bbl_l2tp_send(l2tp_tunnel, NULL, L2TP_MESSAGE_STOPCCN); } @@ -311,6 +314,9 @@ bbl_l2tp_tunnel_control_job (timer_s *timer) { switch(l2tp_tunnel->state) { case BBL_L2TP_TUNNEL_WAIT_CTR_CONN: if(l2tp_tunnel->state_seconds > 30) { + l2tp_tunnel->result_code = 2; + l2tp_tunnel->error_code = 6; + l2tp_tunnel->error_message = "timeout"; bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN); bbl_l2tp_send(l2tp_tunnel, NULL, L2TP_MESSAGE_STOPCCN); } @@ -600,6 +606,9 @@ bbl_l2tp_sccrq_rx(bbl_ethernet_header_t *eth, bbl_l2tp_t *l2tp, bbl_interface_s LOG(ERROR, "L2TP Error (%s) Missing challenge in SCCRQ from %s\n", l2tp_tunnel->server->host_name, format_ipv4_address(&l2tp_tunnel->peer_ip)); + l2tp_tunnel->result_code = 2; + l2tp_tunnel->error_code = 6; + l2tp_tunnel->error_message = "missing challenge"; l2tp_tunnel->state = BBL_L2TP_TUNNEL_SEND_STOPCCN; } } else { @@ -609,6 +618,9 @@ bbl_l2tp_sccrq_rx(bbl_ethernet_header_t *eth, bbl_l2tp_t *l2tp, bbl_interface_s LOG(ERROR, "L2TP Error (%s) No secret found but challenge received in SCCRQ from %s\n", l2tp_tunnel->server->host_name, format_ipv4_address(&l2tp_tunnel->peer_ip)); + l2tp_tunnel->result_code = 2; + l2tp_tunnel->error_code = 6; + l2tp_tunnel->error_message = "no challenge expected"; l2tp_tunnel->state = BBL_L2TP_TUNNEL_SEND_STOPCCN; } } @@ -648,6 +660,9 @@ bbl_l2tp_scccn_rx(bbl_ethernet_header_t *eth, bbl_l2tp_t *l2tp, bbl_interface_s l2tp_tunnel->server->host_name, format_ipv4_address(&l2tp_tunnel->peer_ip)); bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN); + l2tp_tunnel->result_code = 2; + l2tp_tunnel->error_code = 6; + l2tp_tunnel->error_message = "decode error"; return bbl_l2tp_send(l2tp_tunnel, NULL, L2TP_MESSAGE_STOPCCN); } /* Check challenge response ... */ @@ -663,6 +678,9 @@ bbl_l2tp_scccn_rx(bbl_ethernet_header_t *eth, bbl_l2tp_t *l2tp, bbl_interface_s l2tp_tunnel->server->host_name, format_ipv4_address(&l2tp_tunnel->peer_ip)); bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN); + l2tp_tunnel->result_code = 2; + l2tp_tunnel->error_code = 6; + l2tp_tunnel->error_message = "challenge authentication failed"; return bbl_l2tp_send(l2tp_tunnel, NULL, L2TP_MESSAGE_STOPCCN); } } else { @@ -670,6 +688,9 @@ bbl_l2tp_scccn_rx(bbl_ethernet_header_t *eth, bbl_l2tp_t *l2tp, bbl_interface_s l2tp_tunnel->server->host_name, format_ipv4_address(&l2tp_tunnel->peer_ip)); bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN); + l2tp_tunnel->result_code = 2; + l2tp_tunnel->error_code = 6; + l2tp_tunnel->error_message = "missing challenge response"; return bbl_l2tp_send(l2tp_tunnel, NULL, L2TP_MESSAGE_STOPCCN); } } @@ -759,6 +780,9 @@ bbl_l2tp_iccn_rx(bbl_ethernet_header_t *eth, bbl_l2tp_t *l2tp, bbl_interface_s * } if(!bbl_l2tp_avp_decode_session(l2tp, l2tp_tunnel, l2tp_session)) { + l2tp_session->result_code = 2; + l2tp_session->error_code = 6; + l2tp_session->error_message = "decode error"; bbl_l2tp_send(l2tp_tunnel, l2tp_session, L2TP_MESSAGE_CDN); return bbl_l2tp_session_delete(l2tp_session); } @@ -1118,6 +1142,7 @@ bbl_l2tp_stop_all_tunnel(bbl_ctx_s *ctx) { CIRCLEQ_FOREACH(l2tp_tunnel, &l2tp_server->tunnel_qhead, tunnel_qnode) { if(l2tp_tunnel->state < BBL_L2TP_TUNNEL_SEND_STOPCCN) { bbl_l2tp_tunnel_update_state(l2tp_tunnel, BBL_L2TP_TUNNEL_SEND_STOPCCN); + l2tp_tunnel->result_code = 6; bbl_l2tp_send(l2tp_tunnel, NULL, L2TP_MESSAGE_STOPCCN); } } diff --git a/src/bbl_l2tp.h b/src/bbl_l2tp.h index b44ea654..5a300bbf 100644 --- a/src/bbl_l2tp.h +++ b/src/bbl_l2tp.h @@ -163,6 +163,10 @@ typedef struct bbl_l2tp_tunnel_ uint16_t cwcount; uint32_t send_timestamp; + uint16_t result_code; + uint16_t error_code; + char* error_message; + bool zlb; bbl_l2tp_queue_t *zlb_qnode; @@ -230,6 +234,10 @@ typedef struct bbl_l2tp_session_ uint8_t ipcp_state; uint8_t ip6cp_state; + uint16_t result_code; + uint16_t error_code; + char* error_message; + /* The following members must be freed * if session is destroyed! */ diff --git a/src/bbl_l2tp_avp.c b/src/bbl_l2tp_avp.c index e19facc3..e03fed79 100644 --- a/src/bbl_l2tp_avp.c +++ b/src/bbl_l2tp_avp.c @@ -90,6 +90,41 @@ bbl_l2tp_avp_encode(uint8_t **_buf, uint16_t *len, bbl_l2tp_avp_t *avp) { *_buf = buf; } +static void +bbl_l2tp_avp_encode_result_code(uint8_t **_buf, uint16_t *len, + uint16_t result_code, uint16_t error_code, + char *error_message) { + uint8_t *avp_len_field; + uint16_t avp_len = L2TP_AVP_HDR_LEN; + uint8_t *buf = *_buf; + + avp_len_field = buf; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t)); + *(uint16_t*)buf = 0; + BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t)); + *(uint16_t*)buf = htobe16(L2TP_AVP_RESULT_CODE); + BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t)); + + *(uint16_t*)buf = htobe16(result_code); + BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t)); + avp_len += 2; + + if(error_code) { + *(uint16_t*)buf = htobe16(error_code); + BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t)); + avp_len += 2; + if(error_message) { + memcpy(buf, error_message, strlen(error_message)); + BUMP_WRITE_BUFFER(buf, len, strlen(error_message)); + avp_len += strlen(error_message); + } + } + + avp_len |= L2TP_AVP_M_BIT_MASK; + *(uint16_t*)avp_len_field = htobe16(avp_len); + *_buf = buf; +} + /* bbl_l2tp_avp_unhide */ static bool bbl_l2tp_avp_unhide(bbl_l2tp_tunnel_t *l2tp_tunnel, bbl_l2tp_avp_t *avp, uint8_t @@ -329,6 +364,10 @@ bbl_l2tp_avp_decode_session(bbl_l2tp_t *l2tp, bbl_l2tp_tunnel_t *l2tp_tunnel, bb l2tp_session->proxy_auth_response_len = avp.len; } break; + case L2TP_AVP_RANDOM_VECTOR: + random_vector = avp.value; + random_vector_len = avp.len; + break; case L2TP_AVP_CONNECT_SPEED_UPDATE_ENABLE: /* See RFC5515 */ l2tp_session->connect_speed_update_enabled = true; @@ -515,6 +554,10 @@ bbl_l2tp_avp_decode_tunnel(bbl_l2tp_t *l2tp, bbl_l2tp_tunnel_t *l2tp_tunnel) { memcpy(l2tp_tunnel->peer_challenge_response, avp.value, avp.len); } break; + case L2TP_AVP_RANDOM_VECTOR: + random_vector = avp.value; + random_vector_len = avp.len; + break; default: if(avp.m) { LOG(L2TP, "L2TP Error (%s) Mandatory standard AVP with unknown type %u in %s from %s\n", @@ -739,6 +782,11 @@ bbl_l2tp_avp_encode_attributes(bbl_l2tp_tunnel_t *l2tp_tunnel, bbl_l2tp_session_ avp.value_type = L2TP_AVP_VALUE_UINT16; avp.value = (void*)(&l2tp_tunnel->tunnel_id); bbl_l2tp_avp_encode(&buf, len, &avp); + /* Result Code */ + bbl_l2tp_avp_encode_result_code(&buf, len, + l2tp_tunnel->result_code, + l2tp_tunnel->error_code, + l2tp_tunnel->error_message); break; case L2TP_MESSAGE_ICRP: /* Assigned Session ID */ @@ -760,6 +808,11 @@ bbl_l2tp_avp_encode_attributes(bbl_l2tp_tunnel_t *l2tp_tunnel, bbl_l2tp_session_ avp.value_type = L2TP_AVP_VALUE_UINT16; avp.value = (void*)(&l2tp_session->key.session_id); bbl_l2tp_avp_encode(&buf, len, &avp); + /* Result Code */ + bbl_l2tp_avp_encode_result_code(&buf, len, + l2tp_session->result_code, + l2tp_session->error_code, + l2tp_session->error_message); } break; case L2TP_MESSAGE_CSURQ: