Add Connection-Status-message Support

This commit is contained in:
Christian Giese
2021-09-02 12:19:59 +02:00
parent 3eb40b673f
commit 562e2fe23c
11 changed files with 145 additions and 9 deletions
+2
View File
@@ -449,6 +449,8 @@ Attribute | Description | Default
`keepalive-interval` | LCP echo request interval in seconds (0 means disabled) | 30
`keepalive-retry` | PPP LCP echo request max retry | 3
`start-delay` | PPP LCP initial request delay in milliseconds | 0
`ignore-vendor-specific` | Ignore LCP vendor specific requests | false
`connection-status-message` | Accept LCP connection status messages | false
### PPP IPCP
+3 -1
View File
@@ -58,8 +58,10 @@ The most common case for IPoE is using DHCPv4/v6 as shown below.
}
```
## IPoE Session Information
The control socket command `session-info session-id <id>` provides
detailed information for IPOE sessions.
detailed information for IPoE sessions.
`$ sudo bngblaster-cli run.sock session-info session-id 1 | jq .`
```json
+17 -1
View File
@@ -96,8 +96,24 @@ detailed explained in the configuration section.
}
```
## LCP Vendor Extension
This chapter refers to RFC 2153 PPP vendor extensions.
Per default all LCP vendor specific requests will be rejected sending a
LCP code reject message. With `ppp->lcp->ignore-vendor-specific` enabled,
those messages will be ignored as required to emulate different CPE
behaviors.
The option `ppp->lcp->connection-status-message` allows to accept LCP vendor requests
with any OUI if kind is set to `1` by responding with vendor request of
kind `2`. The OUI from request is copied to response in this case.
The value from request is stored in the session as `connection-status-message`.
## PPPoE Session Information
The control socket command `session-info session-id <id>` provides
detailed information for IPOE sessions.
detailed information for PPPoE sessions.
`$ sudo bngblaster-cli run.sock session-info session-id 1 | jq .`
```json
+5
View File
@@ -630,6 +630,8 @@ typedef struct bbl_ctx_
uint16_t lcp_keepalive_interval;
uint16_t lcp_keepalive_retry;
uint16_t lcp_start_delay;
bool lcp_vendor_ignore;
bool lcp_connection_status_message;
/* Authentication */
uint16_t authentication_timeout;
@@ -885,6 +887,9 @@ typedef struct bbl_session_
uint16_t auth_protocol; /* PAP or CHAP */
uint8_t auth_retries;
char *reply_message;
char *connections_status_message;
/* IPCP */
ppp_state_t ipcp_state;
uint8_t ipcp_response_code;
+8
View File
@@ -872,6 +872,14 @@ json_parse_config (json_t *root, bbl_ctx_s *ctx) {
return false;
}
}
value = json_object_get(sub, "ignore-vendor-specific");
if (json_is_boolean(value)) {
ctx->config.lcp_vendor_ignore = json_boolean_value(value);
}
value = json_object_get(sub, "connection-status-message");
if (json_is_boolean(value)) {
ctx->config.lcp_connection_status_message = json_boolean_value(value);
}
}
sub = json_object_get(section, "ipcp");
if (json_is_object(sub)) {
+3 -1
View File
@@ -504,7 +504,7 @@ bbl_ctrl_session_info(int fd, bbl_ctx_s *ctx, uint32_t session_id, json_t* argum
}
if(session->access_type == ACCESS_TYPE_PPPOE) {
root = json_pack("{ss si s{ss si ss ss si si ss ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* si si si so*}}",
root = json_pack("{ss si s{ss si ss ss si si ss ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* si si si so*}}",
"status", "ok",
"code", 200,
"session-info",
@@ -518,6 +518,8 @@ bbl_ctrl_session_info(int fd, bbl_ctx_s *ctx, uint32_t session_id, json_t* argum
"username", session->username,
"agent-circuit-id", session->agent_circuit_id,
"agent-remote-id", session->agent_remote_id,
"reply-message", session->reply_message,
"connection-status-message", session->connections_status_message,
"lcp-state", ppp_state_string(session->lcp_state),
"ipcp-state", ppp_state_string(session->ipcp_state),
"ip6cp-state", ppp_state_string(session->ip6cp_state),
+15 -6
View File
@@ -20,7 +20,7 @@
typedef enum {
UI_VIEW_DEFAULT = 0,
UI_VIEW_ACCESS_IF_STATS,
UI_VIEW_STREAMS,
UI_VIEW_SESSION,
UI_VIEW_MAX,
} __attribute__ ((__packed__)) bbl_ui_view;
@@ -49,7 +49,7 @@ bbl_init_stats_win()
wclear(stats_win);
wattron(stats_win, COLOR_PAIR(COLOR_GREEN));
wprintw(stats_win, "F1: Select View F7/F8: Start/Stop Traffic F9: Terminate Sessions\n");
if(g_view_selected == UI_VIEW_STREAMS) {
if(g_view_selected == UI_VIEW_SESSION) {
wprintw(stats_win, "Left/Right: Select Session\n");
} else {
wprintw(stats_win, "Left/Right: Select Interface\n");
@@ -93,7 +93,7 @@ bbl_read_key_job (timer_s *timer)
bbl_init_stats_win();
break;
case KEY_LEFT:
if(g_view_selected == UI_VIEW_STREAMS) {
if(g_view_selected == UI_VIEW_SESSION) {
if(g_session_selected > 1) {
g_session_selected--;
} else {
@@ -108,7 +108,7 @@ bbl_read_key_job (timer_s *timer)
bbl_init_stats_win();
break;
case KEY_RIGHT:
if(g_view_selected == UI_VIEW_STREAMS) {
if(g_view_selected == UI_VIEW_SESSION) {
g_session_selected++;
if(g_session_selected > ctx->sessions) {
g_session_selected = 1;
@@ -407,8 +407,8 @@ bbl_stats_job (timer_s *timer)
wprintw(stats_win, "\nAccess Interface Protocol Stats");
}
} else if(g_view_selected == UI_VIEW_STREAMS) {
wprintw(stats_win, "\nSession Stream Stats ( Session-Id: ", g_session_selected);
} else if(g_view_selected == UI_VIEW_SESSION) {
wprintw(stats_win, "\nSession and Streams ( Session-Id: ", g_session_selected);
wattron(stats_win, COLOR_PAIR(COLOR_GREEN));
wprintw(stats_win, "%u", g_session_selected);
wattroff(stats_win, COLOR_PAIR(COLOR_GREEN));
@@ -425,6 +425,15 @@ bbl_stats_job (timer_s *timer)
if(session->agent_remote_id) {
wprintw(stats_win, " ACI: %s \n", session->agent_circuit_id);
}
if(session->connections_status_message || session->reply_message) {
wprintw(stats_win, "\n");
if(session->reply_message) {
wprintw(stats_win, " Reply-Message: %s \n", session->reply_message);
}
if(session->connections_status_message) {
wprintw(stats_win, " Connection-Status-Message: %s \n", session->connections_status_message);
}
}
wprintw(stats_win, "\n Access Client Interface\n");
wprintw(stats_win, " Tx Packets %10lu | %7lu PPS | %10lu Kbps\n",
session->stats.packets_tx, session->stats.rate_packets_tx.avg,
+18
View File
@@ -2964,6 +2964,9 @@ decode_ppp_lcp(uint8_t *buf, uint16_t len,
lcp = (bbl_lcp_t*)sp; BUMP_BUFFER(sp, sp_len, sizeof(bbl_lcp_t));
memset(lcp, 0x0, sizeof(bbl_lcp_t));
lcp->start = buf;
lcp->len = len;
lcp->code = *buf;
BUMP_BUFFER(buf, len, sizeof(uint8_t));
lcp->identifier = *buf;
@@ -2990,6 +2993,21 @@ decode_ppp_lcp(uint8_t *buf, uint16_t len,
lcp->options_len = lcp_len;
switch(lcp->code) {
case PPP_CODE_VENDOR_SPECIFIC:
/* RFC 2153 */
if(lcp_len < 8) {
return DECODE_ERROR;
}
lcp->magic = *(uint32_t*)buf;
BUMP_BUFFER(buf, lcp_len, 3);
lcp->vendor_oui = *(uint32_t*)buf;
lcp->vendor_oui &= 0xffffff;
BUMP_BUFFER(buf, lcp_len, sizeof(uint32_t));
lcp->vendor_kind = *buf;
BUMP_BUFFER(buf, lcp_len, sizeof(uint8_t));
lcp->vendor_value = buf;
lcp->vendor_value_len = lcp_len;
break;
case PPP_CODE_ECHO_REQUEST:
case PPP_CODE_ECHO_REPLY:
if(lcp_len>=4) {
+7
View File
@@ -83,6 +83,7 @@
#define ICMP_TYPE_ECHO_REPLY 0x00
#define ICMP_TYPE_ECHO_REQUEST 0x08
#define PPP_CODE_VENDOR_SPECIFIC 0
#define PPP_CODE_CONF_REQUEST 1
#define PPP_CODE_CONF_ACK 2
#define PPP_CODE_CONF_NAK 3
@@ -533,6 +534,12 @@ typedef struct bbl_lcp_ {
uint16_t mru;
uint16_t auth;
uint32_t magic;
uint32_t vendor_oui;
uint8_t vendor_kind;
uint8_t *vendor_value;
uint16_t vendor_value_len;
uint8_t *start;
uint16_t len;
} bbl_lcp_t;
/*
+58
View File
@@ -756,6 +756,14 @@ bbl_rx_pap(bbl_ethernet_header_t *eth, bbl_interface_s *interface, bbl_session_s
}
}
}
if(pap->reply_message_len) {
if(session->reply_message) {
free(session->reply_message);
}
session->reply_message = malloc(pap->reply_message_len+1);
memcpy(session->reply_message, pap->reply_message, pap->reply_message_len);
session->reply_message[pap->reply_message_len] = 0;
}
bbl_session_update_state(ctx, session, BBL_PPP_NETWORK);
if(ctx->config.ipcp_enable) {
session->ipcp_state = BBL_PPP_INIT;
@@ -841,6 +849,14 @@ bbl_rx_chap(bbl_ethernet_header_t *eth, bbl_interface_s *interface, bbl_session_
}
}
}
if(chap->reply_message_len) {
if(session->reply_message) {
free(session->reply_message);
}
session->reply_message = malloc(chap->reply_message_len+1);
memcpy(session->reply_message, chap->reply_message, chap->reply_message_len);
session->reply_message[chap->reply_message_len] = 0;
}
bbl_session_update_state(ctx, session, BBL_PPP_NETWORK);
if(ctx->config.ipcp_enable) {
session->ipcp_state = BBL_PPP_INIT;
@@ -1132,6 +1148,37 @@ bbl_rx_lcp(bbl_ethernet_header_t *eth, bbl_interface_s *interface, bbl_session_s
lcp = (bbl_lcp_t*)pppoes->next;
switch(lcp->code) {
case PPP_CODE_VENDOR_SPECIFIC:
if(ctx->config.lcp_vendor_ignore) {
return;
}
if(ctx->config.lcp_connection_status_message &&
lcp->vendor_kind == 1 && lcp->vendor_value_len) {
if(session->connections_status_message) {
free(session->connections_status_message);
}
session->connections_status_message = malloc(lcp->vendor_value_len+1);
memcpy(session->connections_status_message, lcp->vendor_value, lcp->vendor_value_len);
session->connections_status_message[lcp->vendor_value_len] = 0;
session->lcp_response_code = PPP_CODE_VENDOR_SPECIFIC;
*(uint32_t*)(session->lcp_options+3) = lcp->vendor_oui;
*(uint32_t*)session->lcp_options = session->magic_number;
session->lcp_options[7] = 2;
session->lcp_options_len = 8;
} else {
session->lcp_response_code = PPP_CODE_CODE_REJECT;
if(lcp->len > PPP_OPTIONS_BUFFER) {
memcpy(session->lcp_options, lcp->start, PPP_OPTIONS_BUFFER);
session->lcp_options_len = PPP_OPTIONS_BUFFER;
} else {
memcpy(session->lcp_options, lcp->start, lcp->len);
session->lcp_options_len = lcp->len;
}
}
session->lcp_peer_identifier = lcp->identifier;
session->send_requests |= BBL_SEND_LCP_RESPONSE;
bbl_session_tx_qnode_insert(session);
break;
case PPP_CODE_CONF_REQUEST:
session->auth_protocol = lcp->auth;
if(session->access_config->authentication_protocol) {
@@ -1253,6 +1300,17 @@ bbl_rx_lcp(bbl_ethernet_header_t *eth, bbl_interface_s *interface, bbl_session_s
bbl_session_tx_qnode_insert(session);
break;
default:
session->lcp_response_code = PPP_CODE_CODE_REJECT;
if(lcp->len > PPP_OPTIONS_BUFFER) {
memcpy(session->lcp_options, lcp->start, PPP_OPTIONS_BUFFER);
session->lcp_options_len = PPP_OPTIONS_BUFFER;
} else {
memcpy(session->lcp_options, lcp->start, lcp->len);
session->lcp_options_len = lcp->len;
}
session->lcp_peer_identifier = lcp->identifier;
session->send_requests |= BBL_SEND_LCP_RESPONSE;
bbl_session_tx_qnode_insert(session);
break;
}
}
+9
View File
@@ -186,6 +186,15 @@ bbl_session_update_state(bbl_ctx_s *ctx, bbl_session_s *session, session_state_t
session->zapping_view_start_time.tv_sec = 0;
session->zapping_view_start_time.tv_nsec = 0;
if(session->reply_message) {
free(session->reply_message);
session->reply_message = NULL;
}
if(session->connections_status_message) {
free(session->connections_status_message);
session->connections_status_message = NULL;
}
/* L2TP */
session->l2tp = false;
session->l2tp_session = NULL;