From cd1d99611e445c9fe2452d05627ccfc624f35c39 Mon Sep 17 00:00:00 2001 From: "Ondrej Zajicek (work)" Date: Tue, 19 Sep 2017 19:55:37 +0200 Subject: BGP: Shutdown communication (RFC 8203) The patch implements BGP Administrative Shutdown Communication (RFC 8203) allowing BGP operators to pass messages related to BGP session administrative shutdown/restart. It handles both transmit and receive of shutdown messages. Messages are logged and may be displayed by show protocol all command. Thanks to Job Snijders for the basic patch. --- nest/proto.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 11 deletions(-) (limited to 'nest/proto.c') diff --git a/nest/proto.c b/nest/proto.c index 64422ee3..552d53ae 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -610,6 +610,7 @@ proto_rethink_goal(struct proto *p) config_del_obstacle(p->cf->global); rem_node(&p->n); rem_node(&p->glob_node); + mb_free(p->message); mb_free(p); if (!nc) return; @@ -1096,6 +1097,39 @@ proto_schedule_down(struct proto *p, byte restart, byte code) tm_start_max(proto_shutdown_timer, restart ? 2 : 0); } +/** + * proto_set_message - set administrative message to protocol + * @p: protocol + * @msg: message + * @len: message length (-1 for NULL-terminated string) + * + * The function sets administrative message (string) related to protocol state + * change. It is called by the nest code for manual enable/disable/restart + * commands all routes to the protocol, and by protocol-specific code when the + * protocol state change is initiated by the protocol. Using NULL message clears + * the last message. The message string may be either NULL-terminated or with an + * explicit length. + */ +void +proto_set_message(struct proto *p, char *msg, int len) +{ + mb_free(p->message); + p->message = NULL; + + if (!msg || !len) + return; + + if (len < 0) + len = strlen(msg); + + if (!len) + return; + + p->message = mb_alloc(proto_pool, len + 1); + memcpy(p->message, msg, len); + p->message[len] = 0; +} + /** * proto_request_feeding - request feeding routes to the protocol @@ -1497,7 +1531,7 @@ proto_show_basic_info(struct proto *p) } void -proto_cmd_show(struct proto *p, uint verbose, int cnt) +proto_cmd_show(struct proto *p, uintptr_t verbose, int cnt) { byte buf[256], tbuf[TM_DATETIME_BUFFER_SIZE]; @@ -1520,6 +1554,10 @@ proto_cmd_show(struct proto *p, uint verbose, int cnt) { if (p->cf->dsc) cli_msg(-1006, " Description: %s", p->cf->dsc); + + if (p->message) + cli_msg(-1006, " Message: %s", p->message); + if (p->cf->router_id) cli_msg(-1006, " Router ID: %R", p->cf->router_id); @@ -1533,7 +1571,7 @@ proto_cmd_show(struct proto *p, uint verbose, int cnt) } void -proto_cmd_disable(struct proto *p, uint arg UNUSED, int cnt UNUSED) +proto_cmd_disable(struct proto *p, uintptr_t arg, int cnt UNUSED) { if (p->disabled) { @@ -1544,12 +1582,13 @@ proto_cmd_disable(struct proto *p, uint arg UNUSED, int cnt UNUSED) log(L_INFO "Disabling protocol %s", p->name); p->disabled = 1; p->down_code = PDC_CMD_DISABLE; + proto_set_message(p, (char *) arg, -1); proto_rethink_goal(p); cli_msg(-9, "%s: disabled", p->name); } void -proto_cmd_enable(struct proto *p, uint arg UNUSED, int cnt UNUSED) +proto_cmd_enable(struct proto *p, uintptr_t arg, int cnt UNUSED) { if (!p->disabled) { @@ -1559,12 +1598,13 @@ proto_cmd_enable(struct proto *p, uint arg UNUSED, int cnt UNUSED) log(L_INFO "Enabling protocol %s", p->name); p->disabled = 0; + proto_set_message(p, (char *) arg, -1); proto_rethink_goal(p); cli_msg(-11, "%s: enabled", p->name); } void -proto_cmd_restart(struct proto *p, uint arg UNUSED, int cnt UNUSED) +proto_cmd_restart(struct proto *p, uintptr_t arg, int cnt UNUSED) { if (p->disabled) { @@ -1575,6 +1615,7 @@ proto_cmd_restart(struct proto *p, uint arg UNUSED, int cnt UNUSED) log(L_INFO "Restarting protocol %s", p->name); p->disabled = 1; p->down_code = PDC_CMD_RESTART; + proto_set_message(p, (char *) arg, -1); proto_rethink_goal(p); p->disabled = 0; proto_rethink_goal(p); @@ -1582,7 +1623,7 @@ proto_cmd_restart(struct proto *p, uint arg UNUSED, int cnt UNUSED) } void -proto_cmd_reload(struct proto *p, uint dir, int cnt UNUSED) +proto_cmd_reload(struct proto *p, uintptr_t dir, int cnt UNUSED) { if (p->disabled) { @@ -1624,19 +1665,19 @@ proto_cmd_reload(struct proto *p, uint dir, int cnt UNUSED) } void -proto_cmd_debug(struct proto *p, uint mask, int cnt UNUSED) +proto_cmd_debug(struct proto *p, uintptr_t mask, int cnt UNUSED) { p->debug = mask; } void -proto_cmd_mrtdump(struct proto *p, uint mask, int cnt UNUSED) +proto_cmd_mrtdump(struct proto *p, uintptr_t mask, int cnt UNUSED) { p->mrtdump = mask; } static void -proto_apply_cmd_symbol(struct symbol *s, void (* cmd)(struct proto *, uint, int), uint arg) +proto_apply_cmd_symbol(struct symbol *s, void (* cmd)(struct proto *, uintptr_t, int), uintptr_t arg) { if (s->class != SYM_PROTO) { @@ -1649,7 +1690,7 @@ proto_apply_cmd_symbol(struct symbol *s, void (* cmd)(struct proto *, uint, int) } static void -proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, uint, int), uint arg) +proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, uintptr_t, int), uintptr_t arg) { int cnt = 0; @@ -1669,8 +1710,8 @@ proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, uint, int), uint a } void -proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, uint, int), - int restricted, uint arg) +proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, uintptr_t, int), + int restricted, uintptr_t arg) { if (restricted && cli_access_restricted()) return; -- cgit v1.2.3