summaryrefslogtreecommitdiffstats
path: root/isisd
diff options
context:
space:
mode:
authorEmanuele Di Pascale <emanuele@voltanet.io>2018-11-14 15:20:38 +0100
committerEmanuele Di Pascale <emanuele@voltanet.io>2018-12-18 15:24:46 +0100
commit3380c990a3febdb976d95fcf3b7d7420c75f8c4b (patch)
treeaf57a2c241ba4f5deb62b035d1a11461b1885ba7 /isisd
parentisisd: implement 'max-area-addresses-mismatch' notification (diff)
downloadfrr-3380c990a3febdb976d95fcf3b7d7420c75f8c4b.tar.xz
frr-3380c990a3febdb976d95fcf3b7d7420c75f8c4b.zip
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>
Diffstat (limited to 'isisd')
-rw-r--r--isisd/isis_northbound.c44
-rw-r--r--isisd/isis_pdu.c74
-rw-r--r--isisd/isis_tlvs.c16
-rw-r--r--isisd/isis_tlvs.h11
-rw-r--r--isisd/isisd.h6
5 files changed, 133 insertions, 18 deletions
diff --git a/isisd/isis_northbound.c b/isisd/isis_northbound.c
index 920f3726a..183879cad 100644
--- a/isisd/isis_northbound.c
+++ b/isisd/isis_northbound.c
@@ -2614,6 +2614,50 @@ void isis_notif_max_area_addr_mismatch(const struct isis_circuit *circuit,
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 */
const struct frr_yang_module_info frr_isisd_info = {
.name = "frr-isisd",
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index fc8fe31d5..c4a62a62c 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -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,
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);
int level = p2p_hello ? 0
: (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"
: (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) {
zlog_debug("ISIS-Adj (%s): Rcvd %s on %s, cirType %s, cirID %u",
circuit->area->area_tag, pdu_name,
@@ -652,11 +659,22 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
goto out;
}
- if (!isis_tlvs_auth_is_valid(iih.tlvs, &circuit->passwd,
- circuit->rcv_stream, false)) {
+ int auth_code = isis_tlvs_auth_is_valid(iih.tlvs, &circuit->passwd,
+ circuit->rcv_stream, false);
+ if (auth_code != ISIS_AUTH_OK) {
isis_event_auth_failure(circuit->area->area_tag,
"IIH authentication failure",
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;
}
@@ -724,6 +742,12 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit,
{
int level;
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 (!fabricd)
@@ -846,10 +870,20 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit,
struct isis_passwd *passwd = (level == ISIS_LEVEL1)
? &circuit->area->area_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,
"LSP authentication failure",
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;
}
@@ -1124,6 +1158,12 @@ out:
static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
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
|| pdu_type == L2_COMPLETE_SEQ_NUM);
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);
uint8_t rem_sys_id[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 */
@@ -1237,13 +1278,26 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
struct isis_passwd *passwd = (level == IS_LEVEL_1)
? &circuit->area->area_passwd
: &circuit->area->domain_passwd;
- if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV)
- && !isis_tlvs_auth_is_valid(tlvs, passwd, circuit->rcv_stream,
- false)) {
- isis_event_auth_failure(circuit->area->area_tag,
- "SNP authentication failure",
- rem_sys_id);
- goto out;
+ if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV)) {
+ int auth_code = isis_tlvs_auth_is_valid(
+ tlvs, passwd, circuit->rcv_stream, false);
+ if (auth_code != ISIS_AUTH_OK) {
+ isis_event_auth_failure(circuit->area->area_tag,
+ "SNP authentication failure",
+ 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 =
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
index 87d827335..5a6c7bc30 100644
--- a/isisd/isis_tlvs.c
+++ b/isisd/isis_tlvs.c
@@ -3304,17 +3304,17 @@ static const auth_validator_func auth_validators[] = {
[ISIS_PASSWD_TYPE_HMAC_MD5] = auth_validator_hmac_md5,
};
-bool isis_tlvs_auth_is_valid(struct isis_tlvs *tlvs, struct isis_passwd *passwd,
- struct stream *stream, bool is_lsp)
+int isis_tlvs_auth_is_valid(struct isis_tlvs *tlvs, struct isis_passwd *passwd,
+ struct stream *stream, bool is_lsp)
{
/* If no auth is set, always pass authentication */
if (!passwd->type)
- return true;
+ return ISIS_AUTH_OK;
/* If we don't known how to validate the auth, return invalid */
if (passwd->type >= array_size(auth_validators)
|| !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;
@@ -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 (!auth)
- return false;
+ return ISIS_AUTH_TYPE_FAILURE;
+
/* 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,
diff --git a/isisd/isis_tlvs.h b/isisd/isis_tlvs.h
index 4144809fa..fce30d4ee 100644
--- a/isisd/isis_tlvs.h
+++ b/isisd/isis_tlvs.h
@@ -196,6 +196,13 @@ struct isis_purge_originator {
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);
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);
void isis_tlvs_add_ipv6_addresses(struct isis_tlvs *tlvs,
struct list *addresses);
-bool isis_tlvs_auth_is_valid(struct isis_tlvs *tlvs, struct isis_passwd *passwd,
- struct stream *stream, bool is_lsp);
+int isis_tlvs_auth_is_valid(struct isis_tlvs *tlvs, struct isis_passwd *passwd,
+ struct stream *stream, bool is_lsp);
bool isis_tlvs_area_addresses_match(struct isis_tlvs *tlvs,
struct list *addresses);
struct isis_adjacency;
diff --git a/isisd/isisd.h b/isisd/isisd.h
index d91e8cd54..6d7f0a485 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -234,6 +234,12 @@ extern void isis_notif_lsp_exceed_max(const struct isis_area *area,
extern void
isis_notif_max_area_addr_mismatch(const struct isis_circuit *circuit,
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. */
extern struct thread_master *master;