sync with OpenBSD -current

This commit is contained in:
purplerain 2024-04-23 01:36:57 +00:00
parent 62f1a75fe4
commit 01dd575d45
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
36 changed files with 399 additions and 217 deletions

View file

@ -1,4 +1,4 @@
/* $OpenBSD: session.c,v 1.470 2024/04/11 08:33:15 claudio Exp $ */
/* $OpenBSD: session.c,v 1.473 2024/04/22 09:43:11 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@ -87,7 +87,7 @@ int parse_header(struct peer *, u_char *, uint16_t *, uint8_t *);
int parse_open(struct peer *);
int parse_update(struct peer *);
int parse_rrefresh(struct peer *);
int parse_notification(struct peer *);
void parse_notification(struct peer *);
int parse_capabilities(struct peer *, u_char *, uint16_t, uint32_t *);
int capa_neg_calc(struct peer *);
void session_dispatch_imsg(struct imsgbuf *, int, u_int *);
@ -266,11 +266,12 @@ session_main(int debug, int verbose)
if (p->demoted)
session_demote(p, -1);
p->conf.demote_group[0] = 0;
session_stop(p, ERR_CEASE_PEER_UNCONF);
session_stop(p, ERR_CEASE_PEER_UNCONF,
NULL);
timer_remove_all(&p->timers);
tcp_md5_del_listener(conf, p);
log_peer_warnx(&p->conf, "removed");
RB_REMOVE(peer_head, &conf->peers, p);
log_peer_warnx(&p->conf, "removed");
free(p);
peer_cnt--;
continue;
@ -513,12 +514,10 @@ session_main(int debug, int verbose)
}
RB_FOREACH_SAFE(p, peer_head, &conf->peers, next) {
RB_REMOVE(peer_head, &conf->peers, p);
strlcpy(p->conf.reason,
"bgpd shutting down",
sizeof(p->conf.reason));
session_stop(p, ERR_CEASE_ADMIN_DOWN);
session_stop(p, ERR_CEASE_ADMIN_DOWN, "bgpd shutting down");
timer_remove_all(&p->timers);
tcp_md5_del_listener(conf, p);
RB_REMOVE(peer_head, &conf->peers, p);
free(p);
}
@ -624,6 +623,9 @@ bgp_fsm(struct peer *peer, enum session_events event)
}
peer->passive = 0;
break;
case EVNT_STOP:
timer_stop(&peer->timers, Timer_IdleHold);
break;
default:
/* ignore */
break;
@ -723,13 +725,7 @@ bgp_fsm(struct peer *peer, enum session_events event)
change_state(peer, STATE_OPENCONFIRM, event);
break;
case EVNT_RCVD_NOTIFICATION:
if (parse_notification(peer)) {
change_state(peer, STATE_IDLE, event);
/* don't punish, capa negotiation */
timer_set(&peer->timers, Timer_IdleHold, 0);
peer->IdleHoldTime /= 2;
} else
change_state(peer, STATE_IDLE, event);
parse_notification(peer);
break;
default:
session_notification(peer,
@ -769,7 +765,6 @@ bgp_fsm(struct peer *peer, enum session_events event)
break;
case EVNT_RCVD_NOTIFICATION:
parse_notification(peer);
change_state(peer, STATE_IDLE, event);
break;
default:
session_notification(peer,
@ -815,7 +810,6 @@ bgp_fsm(struct peer *peer, enum session_events event)
break;
case EVNT_RCVD_NOTIFICATION:
parse_notification(peer);
change_state(peer, STATE_IDLE, event);
break;
default:
session_notification(peer,
@ -2326,9 +2320,6 @@ bad_len:
session_notification(peer, ERR_OPEN, ERR_OPEN_OPT,
NULL);
change_state(peer, STATE_IDLE, EVNT_RCVD_OPEN);
/* no punish */
timer_set(&peer->timers, Timer_IdleHold, 0);
peer->IdleHoldTime /= 2;
return (-1);
}
}
@ -2493,7 +2484,7 @@ parse_rrefresh(struct peer *peer)
return (0);
}
int
void
parse_notification(struct peer *peer)
{
struct ibuf ibuf;
@ -2518,7 +2509,7 @@ parse_notification(struct peer *peer)
if (ibuf_get_n8(&ibuf, &errcode) == -1 ||
ibuf_get_n8(&ibuf, &subcode) == -1) {
log_peer_warnx(&peer->conf, "received bad notification");
return (-1);
goto done;
}
peer->errcnt++;
@ -2541,12 +2532,8 @@ parse_notification(struct peer *peer)
}
}
if (errcode == ERR_OPEN && subcode == ERR_OPEN_OPT) {
session_capa_ann_none(peer);
return (1);
}
return (0);
done:
change_state(peer, STATE_IDLE, EVNT_RCVD_NOTIFICATION);
}
int
@ -3165,7 +3152,8 @@ session_dispatch_imsg(struct imsgbuf *imsgbuf, int idx, u_int *listener_cnt)
} else if (!depend_ok && p->depend_ok) {
p->depend_ok = depend_ok;
session_stop(p,
ERR_CEASE_OTHER_CHANGE);
ERR_CEASE_OTHER_CHANGE,
NULL);
}
}
break;
@ -3631,21 +3619,21 @@ session_demote(struct peer *p, int level)
}
void
session_stop(struct peer *peer, uint8_t subcode)
session_stop(struct peer *peer, uint8_t subcode, const char *reason)
{
struct ibuf *ibuf;
char *communication;
communication = peer->conf.reason;
if (reason != NULL)
strlcpy(peer->conf.reason, reason, sizeof(peer->conf.reason));
ibuf = ibuf_dynamic(0, REASON_LEN);
if ((subcode == ERR_CEASE_ADMIN_DOWN ||
subcode == ERR_CEASE_ADMIN_RESET) &&
communication != NULL && *communication != '\0' &&
reason != NULL && *reason != '\0' &&
ibuf != NULL) {
if (ibuf_add_n8(ibuf, strlen(communication)) == -1 ||
ibuf_add(ibuf, communication, strlen(communication))) {
if (ibuf_add_n8(ibuf, strlen(reason)) == -1 ||
ibuf_add(ibuf, reason, strlen(reason))) {
log_peer_warnx(&peer->conf,
"trying to send overly long shutdown reason");
ibuf_free(ibuf);
@ -3660,6 +3648,13 @@ session_stop(struct peer *peer, uint8_t subcode)
break;
default:
/* session not open, no need to send notification */
if (subcode >= sizeof(suberr_cease_names) / sizeof(char *) ||
suberr_cease_names[subcode] == NULL)
log_peer_warnx(&peer->conf, "session stop: %s, "
"unknown subcode %u", errnames[ERR_CEASE], subcode);
else
log_peer_warnx(&peer->conf, "session stop: %s, %s",
errnames[ERR_CEASE], suberr_cease_names[subcode]);
break;
}
ibuf_free(ibuf);