diff options
author | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2017-09-19 19:55:37 +0200 |
---|---|---|
committer | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2017-09-19 19:57:52 +0200 |
commit | cd1d99611e445c9fe2452d05627ccfc624f35c39 (patch) | |
tree | eeae5838682bbc556ebf291423505a77164192e2 /nest/proto.c | |
parent | 7b2c5f3d2826e3175bf31b1c36056c9efc587a2b (diff) |
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.
Diffstat (limited to 'nest/proto.c')
-rw-r--r-- | nest/proto.c | 63 |
1 files changed, 52 insertions, 11 deletions
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; |