mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 02:53:55 +00:00
isisd: implement the authentication failure notifications
the original isisd code did not distinguish between authentication_failure and authentication_type_failure, so additional code had to be added to differentiate between the two and to return the raw_pdu as requested by the IETF YANG model. Signed-off-by: Emanuele Di Pascale <emanuele@voltanet.io>
This commit is contained in:
parent
2ab5a2d155
commit
3380c990a3
@ -2614,6 +2614,50 @@ void isis_notif_max_area_addr_mismatch(const struct isis_circuit *circuit,
|
|||||||
nb_notification_send(xpath, arguments);
|
nb_notification_send(xpath, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath:
|
||||||
|
* /frr-isisd:authentication-type-failure
|
||||||
|
*/
|
||||||
|
void isis_notif_authentication_type_failure(const struct isis_circuit *circuit,
|
||||||
|
const char *raw_pdu)
|
||||||
|
{
|
||||||
|
const char *xpath = "/frr-isisd:authentication-type-failure";
|
||||||
|
struct list *arguments = yang_data_list_new();
|
||||||
|
char xpath_arg[XPATH_MAXLEN];
|
||||||
|
struct yang_data *data;
|
||||||
|
struct isis_area *area = circuit->area;
|
||||||
|
|
||||||
|
notif_prep_instance_hdr(xpath, area, "default", arguments);
|
||||||
|
notif_prepr_iface_hdr(xpath, circuit, arguments);
|
||||||
|
snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath);
|
||||||
|
data = yang_data_new(xpath_arg, raw_pdu);
|
||||||
|
listnode_add(arguments, data);
|
||||||
|
|
||||||
|
nb_notification_send(xpath, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XPath:
|
||||||
|
* /frr-isisd:authentication-failure
|
||||||
|
*/
|
||||||
|
void isis_notif_authentication_failure(const struct isis_circuit *circuit,
|
||||||
|
const char *raw_pdu)
|
||||||
|
{
|
||||||
|
const char *xpath = "/frr-isisd:authentication-failure";
|
||||||
|
struct list *arguments = yang_data_list_new();
|
||||||
|
char xpath_arg[XPATH_MAXLEN];
|
||||||
|
struct yang_data *data;
|
||||||
|
struct isis_area *area = circuit->area;
|
||||||
|
|
||||||
|
notif_prep_instance_hdr(xpath, area, "default", arguments);
|
||||||
|
notif_prepr_iface_hdr(xpath, circuit, arguments);
|
||||||
|
snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath);
|
||||||
|
data = yang_data_new(xpath_arg, raw_pdu);
|
||||||
|
listnode_add(arguments, data);
|
||||||
|
|
||||||
|
nb_notification_send(xpath, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
const struct frr_yang_module_info frr_isisd_info = {
|
const struct frr_yang_module_info frr_isisd_info = {
|
||||||
.name = "frr-isisd",
|
.name = "frr-isisd",
|
||||||
|
@ -553,6 +553,10 @@ static int pdu_len_validate(uint16_t pdu_len, struct isis_circuit *circuit)
|
|||||||
static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
|
static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
|
||||||
uint8_t *ssnpa)
|
uint8_t *ssnpa)
|
||||||
{
|
{
|
||||||
|
/* keep a copy of the raw pdu for NB notifications */
|
||||||
|
size_t pdu_start = stream_get_getp(circuit->rcv_stream);
|
||||||
|
size_t pdu_end = stream_get_endp(circuit->rcv_stream);
|
||||||
|
char raw_pdu[pdu_end - pdu_start];
|
||||||
bool p2p_hello = (pdu_type == P2P_HELLO);
|
bool p2p_hello = (pdu_type == P2P_HELLO);
|
||||||
int level = p2p_hello ? 0
|
int level = p2p_hello ? 0
|
||||||
: (pdu_type == L1_LAN_HELLO) ? ISIS_LEVEL1
|
: (pdu_type == L1_LAN_HELLO) ? ISIS_LEVEL1
|
||||||
@ -562,6 +566,9 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
|
|||||||
? "P2P IIH"
|
? "P2P IIH"
|
||||||
: (level == ISIS_LEVEL1) ? "L1 LAN IIH" : "L2 LAN IIH";
|
: (level == ISIS_LEVEL1) ? "L1 LAN IIH" : "L2 LAN IIH";
|
||||||
|
|
||||||
|
|
||||||
|
stream_get_from(raw_pdu, circuit->rcv_stream, pdu_start,
|
||||||
|
pdu_end - pdu_start);
|
||||||
if (isis->debugs & DEBUG_ADJ_PACKETS) {
|
if (isis->debugs & DEBUG_ADJ_PACKETS) {
|
||||||
zlog_debug("ISIS-Adj (%s): Rcvd %s on %s, cirType %s, cirID %u",
|
zlog_debug("ISIS-Adj (%s): Rcvd %s on %s, cirType %s, cirID %u",
|
||||||
circuit->area->area_tag, pdu_name,
|
circuit->area->area_tag, pdu_name,
|
||||||
@ -652,11 +659,22 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isis_tlvs_auth_is_valid(iih.tlvs, &circuit->passwd,
|
int auth_code = isis_tlvs_auth_is_valid(iih.tlvs, &circuit->passwd,
|
||||||
circuit->rcv_stream, false)) {
|
circuit->rcv_stream, false);
|
||||||
|
if (auth_code != ISIS_AUTH_OK) {
|
||||||
isis_event_auth_failure(circuit->area->area_tag,
|
isis_event_auth_failure(circuit->area->area_tag,
|
||||||
"IIH authentication failure",
|
"IIH authentication failure",
|
||||||
iih.sys_id);
|
iih.sys_id);
|
||||||
|
#ifndef FABRICD
|
||||||
|
/* send northbound notification */
|
||||||
|
stream_get_from(raw_pdu, circuit->rcv_stream, pdu_start,
|
||||||
|
pdu_end - pdu_start);
|
||||||
|
if (auth_code == ISIS_AUTH_FAILURE)
|
||||||
|
isis_notif_authentication_failure(circuit, raw_pdu);
|
||||||
|
else /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
|
||||||
|
isis_notif_authentication_type_failure(circuit,
|
||||||
|
raw_pdu);
|
||||||
|
#endif /* ifndef FABRICD */
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -724,6 +742,12 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit,
|
|||||||
{
|
{
|
||||||
int level;
|
int level;
|
||||||
bool circuit_scoped;
|
bool circuit_scoped;
|
||||||
|
size_t pdu_start = stream_get_getp(circuit->rcv_stream);
|
||||||
|
size_t pdu_end = stream_get_endp(circuit->rcv_stream);
|
||||||
|
char raw_pdu[pdu_end - pdu_start];
|
||||||
|
|
||||||
|
stream_get_from(raw_pdu, circuit->rcv_stream, pdu_start,
|
||||||
|
pdu_end - pdu_start);
|
||||||
|
|
||||||
if (pdu_type == FS_LINK_STATE) {
|
if (pdu_type == FS_LINK_STATE) {
|
||||||
if (!fabricd)
|
if (!fabricd)
|
||||||
@ -846,10 +870,20 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit,
|
|||||||
struct isis_passwd *passwd = (level == ISIS_LEVEL1)
|
struct isis_passwd *passwd = (level == ISIS_LEVEL1)
|
||||||
? &circuit->area->area_passwd
|
? &circuit->area->area_passwd
|
||||||
: &circuit->area->domain_passwd;
|
: &circuit->area->domain_passwd;
|
||||||
if (!isis_tlvs_auth_is_valid(tlvs, passwd, circuit->rcv_stream, true)) {
|
int auth_code = isis_tlvs_auth_is_valid(tlvs, passwd,
|
||||||
|
circuit->rcv_stream, true);
|
||||||
|
if (auth_code != ISIS_AUTH_OK) {
|
||||||
isis_event_auth_failure(circuit->area->area_tag,
|
isis_event_auth_failure(circuit->area->area_tag,
|
||||||
"LSP authentication failure",
|
"LSP authentication failure",
|
||||||
hdr.lsp_id);
|
hdr.lsp_id);
|
||||||
|
#ifndef FABRICD
|
||||||
|
/* send northbound notification */
|
||||||
|
if (auth_code == ISIS_AUTH_FAILURE)
|
||||||
|
isis_notif_authentication_failure(circuit, raw_pdu);
|
||||||
|
else /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
|
||||||
|
isis_notif_authentication_type_failure(circuit,
|
||||||
|
raw_pdu);
|
||||||
|
#endif /* ifndef FABRICD */
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1124,6 +1158,12 @@ out:
|
|||||||
static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
|
static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
|
||||||
const uint8_t *ssnpa)
|
const uint8_t *ssnpa)
|
||||||
{
|
{
|
||||||
|
#ifndef FABRICD
|
||||||
|
size_t pdu_start = stream_get_getp(circuit->rcv_stream);
|
||||||
|
size_t pdu_end = stream_get_endp(circuit->rcv_stream);
|
||||||
|
char raw_pdu[pdu_end - pdu_start];
|
||||||
|
#endif /* ifndef FABRICD */
|
||||||
|
|
||||||
bool is_csnp = (pdu_type == L1_COMPLETE_SEQ_NUM
|
bool is_csnp = (pdu_type == L1_COMPLETE_SEQ_NUM
|
||||||
|| pdu_type == L2_COMPLETE_SEQ_NUM);
|
|| pdu_type == L2_COMPLETE_SEQ_NUM);
|
||||||
char typechar = is_csnp ? 'C' : 'P';
|
char typechar = is_csnp ? 'C' : 'P';
|
||||||
@ -1134,6 +1174,7 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
|
|||||||
|
|
||||||
uint16_t pdu_len = stream_getw(circuit->rcv_stream);
|
uint16_t pdu_len = stream_getw(circuit->rcv_stream);
|
||||||
uint8_t rem_sys_id[ISIS_SYS_ID_LEN];
|
uint8_t rem_sys_id[ISIS_SYS_ID_LEN];
|
||||||
|
|
||||||
stream_get(rem_sys_id, circuit->rcv_stream, ISIS_SYS_ID_LEN);
|
stream_get(rem_sys_id, circuit->rcv_stream, ISIS_SYS_ID_LEN);
|
||||||
stream_forward_getp(circuit->rcv_stream, 1); /* Circuit ID - unused */
|
stream_forward_getp(circuit->rcv_stream, 1); /* Circuit ID - unused */
|
||||||
|
|
||||||
@ -1237,13 +1278,26 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
|
|||||||
struct isis_passwd *passwd = (level == IS_LEVEL_1)
|
struct isis_passwd *passwd = (level == IS_LEVEL_1)
|
||||||
? &circuit->area->area_passwd
|
? &circuit->area->area_passwd
|
||||||
: &circuit->area->domain_passwd;
|
: &circuit->area->domain_passwd;
|
||||||
if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV)
|
if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV)) {
|
||||||
&& !isis_tlvs_auth_is_valid(tlvs, passwd, circuit->rcv_stream,
|
int auth_code = isis_tlvs_auth_is_valid(
|
||||||
false)) {
|
tlvs, passwd, circuit->rcv_stream, false);
|
||||||
isis_event_auth_failure(circuit->area->area_tag,
|
if (auth_code != ISIS_AUTH_OK) {
|
||||||
"SNP authentication failure",
|
isis_event_auth_failure(circuit->area->area_tag,
|
||||||
rem_sys_id);
|
"SNP authentication failure",
|
||||||
goto out;
|
rem_sys_id);
|
||||||
|
#ifndef FABRICD
|
||||||
|
/* send northbound notification */
|
||||||
|
stream_get_from(raw_pdu, circuit->rcv_stream, pdu_start,
|
||||||
|
pdu_end - pdu_start);
|
||||||
|
if (auth_code == ISIS_AUTH_FAILURE)
|
||||||
|
isis_notif_authentication_failure(circuit,
|
||||||
|
raw_pdu);
|
||||||
|
else /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
|
||||||
|
isis_notif_authentication_type_failure(circuit,
|
||||||
|
raw_pdu);
|
||||||
|
#endif /* ifndef FABRICD */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct isis_lsp_entry *entry_head =
|
struct isis_lsp_entry *entry_head =
|
||||||
|
@ -3304,17 +3304,17 @@ static const auth_validator_func auth_validators[] = {
|
|||||||
[ISIS_PASSWD_TYPE_HMAC_MD5] = auth_validator_hmac_md5,
|
[ISIS_PASSWD_TYPE_HMAC_MD5] = auth_validator_hmac_md5,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool isis_tlvs_auth_is_valid(struct isis_tlvs *tlvs, struct isis_passwd *passwd,
|
int isis_tlvs_auth_is_valid(struct isis_tlvs *tlvs, struct isis_passwd *passwd,
|
||||||
struct stream *stream, bool is_lsp)
|
struct stream *stream, bool is_lsp)
|
||||||
{
|
{
|
||||||
/* If no auth is set, always pass authentication */
|
/* If no auth is set, always pass authentication */
|
||||||
if (!passwd->type)
|
if (!passwd->type)
|
||||||
return true;
|
return ISIS_AUTH_OK;
|
||||||
|
|
||||||
/* If we don't known how to validate the auth, return invalid */
|
/* If we don't known how to validate the auth, return invalid */
|
||||||
if (passwd->type >= array_size(auth_validators)
|
if (passwd->type >= array_size(auth_validators)
|
||||||
|| !auth_validators[passwd->type])
|
|| !auth_validators[passwd->type])
|
||||||
return false;
|
return ISIS_AUTH_NO_VALIDATOR;
|
||||||
|
|
||||||
struct isis_auth *auth_head = (struct isis_auth *)tlvs->isis_auth.head;
|
struct isis_auth *auth_head = (struct isis_auth *)tlvs->isis_auth.head;
|
||||||
struct isis_auth *auth;
|
struct isis_auth *auth;
|
||||||
@ -3325,10 +3325,14 @@ bool isis_tlvs_auth_is_valid(struct isis_tlvs *tlvs, struct isis_passwd *passwd,
|
|||||||
|
|
||||||
/* If matching auth TLV could not be found, return invalid */
|
/* If matching auth TLV could not be found, return invalid */
|
||||||
if (!auth)
|
if (!auth)
|
||||||
return false;
|
return ISIS_AUTH_TYPE_FAILURE;
|
||||||
|
|
||||||
|
|
||||||
/* Perform validation and return result */
|
/* Perform validation and return result */
|
||||||
return auth_validators[passwd->type](passwd, stream, auth, is_lsp);
|
if (auth_validators[passwd->type](passwd, stream, auth, is_lsp))
|
||||||
|
return ISIS_AUTH_OK;
|
||||||
|
else
|
||||||
|
return ISIS_AUTH_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isis_tlvs_area_addresses_match(struct isis_tlvs *tlvs,
|
bool isis_tlvs_area_addresses_match(struct isis_tlvs *tlvs,
|
||||||
|
@ -196,6 +196,13 @@ struct isis_purge_originator {
|
|||||||
uint8_t sender[6];
|
uint8_t sender[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum isis_auth_result {
|
||||||
|
ISIS_AUTH_OK = 0,
|
||||||
|
ISIS_AUTH_TYPE_FAILURE,
|
||||||
|
ISIS_AUTH_FAILURE,
|
||||||
|
ISIS_AUTH_NO_VALIDATOR,
|
||||||
|
};
|
||||||
|
|
||||||
RB_HEAD(isis_mt_item_list, isis_item_list);
|
RB_HEAD(isis_mt_item_list, isis_item_list);
|
||||||
|
|
||||||
struct isis_item_list *isis_get_mt_items(struct isis_mt_item_list *m,
|
struct isis_item_list *isis_get_mt_items(struct isis_mt_item_list *m,
|
||||||
@ -337,8 +344,8 @@ void isis_tlvs_add_ipv4_addresses(struct isis_tlvs *tlvs,
|
|||||||
struct list *addresses);
|
struct list *addresses);
|
||||||
void isis_tlvs_add_ipv6_addresses(struct isis_tlvs *tlvs,
|
void isis_tlvs_add_ipv6_addresses(struct isis_tlvs *tlvs,
|
||||||
struct list *addresses);
|
struct list *addresses);
|
||||||
bool isis_tlvs_auth_is_valid(struct isis_tlvs *tlvs, struct isis_passwd *passwd,
|
int isis_tlvs_auth_is_valid(struct isis_tlvs *tlvs, struct isis_passwd *passwd,
|
||||||
struct stream *stream, bool is_lsp);
|
struct stream *stream, bool is_lsp);
|
||||||
bool isis_tlvs_area_addresses_match(struct isis_tlvs *tlvs,
|
bool isis_tlvs_area_addresses_match(struct isis_tlvs *tlvs,
|
||||||
struct list *addresses);
|
struct list *addresses);
|
||||||
struct isis_adjacency;
|
struct isis_adjacency;
|
||||||
|
@ -234,6 +234,12 @@ extern void isis_notif_lsp_exceed_max(const struct isis_area *area,
|
|||||||
extern void
|
extern void
|
||||||
isis_notif_max_area_addr_mismatch(const struct isis_circuit *circuit,
|
isis_notif_max_area_addr_mismatch(const struct isis_circuit *circuit,
|
||||||
uint8_t max_area_addrs, const char *raw_pdu);
|
uint8_t max_area_addrs, const char *raw_pdu);
|
||||||
|
extern void
|
||||||
|
isis_notif_authentication_type_failure(const struct isis_circuit *circuit,
|
||||||
|
const char *raw_pdu);
|
||||||
|
extern void
|
||||||
|
isis_notif_authentication_failure(const struct isis_circuit *circuit,
|
||||||
|
const char *raw_pdu);
|
||||||
/* Master of threads. */
|
/* Master of threads. */
|
||||||
extern struct thread_master *master;
|
extern struct thread_master *master;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user