From da77faec06a40f2fce2ea54660bd309a2ec100fb Mon Sep 17 00:00:00 2001 From: Christian Giese Date: Tue, 25 Jul 2023 20:54:55 +0000 Subject: [PATCH] OSPF MRT initial draft --- code/bngblaster/src/ospf/ospf_lsa.c | 2 +- code/bngblaster/src/ospf/ospf_lsa.h | 6 ++ code/bngblaster/src/ospf/ospf_mrt.c | 100 +++++++++++++++++++++++++++- 3 files changed, 104 insertions(+), 4 deletions(-) diff --git a/code/bngblaster/src/ospf/ospf_lsa.c b/code/bngblaster/src/ospf/ospf_lsa.c index f37a43d8..7e1440c0 100644 --- a/code/bngblaster/src/ospf/ospf_lsa.c +++ b/code/bngblaster/src/ospf/ospf_lsa.c @@ -421,7 +421,7 @@ ospf_lsa_refresh_job(timer_s *timer) ospf_lsa_refresh(lsa); } -static ospf_lsa_s * +ospf_lsa_s * ospf_lsa_new(uint8_t type, ospf_lsa_key_s *key, ospf_instance_s *ospf_instance) { ospf_lsa_s *lsa = calloc(1, sizeof(ospf_lsa_s)); diff --git a/code/bngblaster/src/ospf/ospf_lsa.h b/code/bngblaster/src/ospf/ospf_lsa.h index 6a427f7e..55fc69e3 100644 --- a/code/bngblaster/src/ospf/ospf_lsa.h +++ b/code/bngblaster/src/ospf/ospf_lsa.h @@ -24,6 +24,9 @@ ospf_lsa_compare(ospf_lsa_header_s *hdr_a, ospf_lsa_header_s *hdr_b); void ospf_lsa_gc_job(timer_s *timer); +void +ospf_lsa_lifetime(ospf_lsa_s *lsa); + void ospf_lsa_flood(ospf_lsa_s *lsa); @@ -39,6 +42,9 @@ ospf_lsa_self_update(ospf_instance_s *ospf_instance); void ospf_lsa_self_update_request(ospf_instance_s *ospf_instance); +ospf_lsa_s * +ospf_lsa_new(uint8_t type, ospf_lsa_key_s *key, ospf_instance_s *ospf_instance); + protocol_error_t ospf_lsa_update_tx(ospf_interface_s *ospf_interface, ospf_neighbor_s *ospf_neighbor, diff --git a/code/bngblaster/src/ospf/ospf_mrt.c b/code/bngblaster/src/ospf/ospf_mrt.c index 58897733..28889f10 100644 --- a/code/bngblaster/src/ospf/ospf_mrt.c +++ b/code/bngblaster/src/ospf/ospf_mrt.c @@ -11,7 +11,101 @@ bool ospf_mrt_load(ospf_instance_s *instance, char *file_path) { - UNUSED(instance); - UNUSED(file_path); + FILE *mrt_file; + + ospf_mrt_hdr_t mrt = {0}; + uint8_t lsa_buf[UINT16_MAX]; + + ospf_lsa_header_s *hdr; + ospf_lsa_key_s *key; + ospf_lsa_s *lsa; + + void **search = NULL; + dict_insert_result result; + + uint16_t lsa_len; + uint8_t lsa_type; + + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + + LOG(OSPF, "Load OSPF MRT file %s\n", file_path); + + mrt_file = fopen(file_path, "r"); + if(!mrt_file) { + LOG(ERROR, "Failed to open MRT file %s\n", file_path); + return false; + } + + while(fread(&mrt, sizeof(ospf_mrt_hdr_t), 1, mrt_file) == 1) { + mrt.type = be16toh(mrt.type); + mrt.subtype = be16toh(mrt.subtype); + mrt.length = be32toh(mrt.length); + //LOG(DEBUG, "MRT type: %u subtype: %u length: %u\n", mrt.type, mrt.subtype, mrt.length); + if(!(mrt.type == OSPF_MRT_TYPE && + mrt.subtype == 0 && + mrt.length >= OSPF_LSA_HDR_LEN && + mrt.length <= UINT16_MAX)) { + LOG(ERROR, "Invalid MRT file %s\n", file_path); + fclose(mrt_file); + return false; + } + if(fread(lsa_buf, mrt.length, 1, mrt_file) != 1) { + LOG(ERROR, "Invalid MRT file %s\n", file_path); + fclose(mrt_file); + return false; + } + + hdr = (ospf_lsa_header_s*)lsa_buf; + key = (ospf_lsa_key_s*)&hdr->id; + + lsa_type = hdr->type; + if(lsa_type < OSPF_LSA_TYPE_1 || lsa_type > OSPF_LSA_TYPE_11) { + LOG(ERROR, "Failed to load LSA from MRT file %s (invalid LSA type)\n", file_path); + fclose(mrt_file); + return false; + } + lsa_len = be16toh(hdr->length); + if(lsa_len > mrt.length) { + LOG(ERROR, "Failed to load LSA from MRT file %s (invalid LSA len)\n", file_path); + fclose(mrt_file); + return false; + } + + search = hb_tree_search(instance->lsdb[lsa_type], key); + if(search) { + lsa = *search; + } else { + /* NEW LSA */ + lsa = ospf_lsa_new(lsa_type, key, instance); + result = hb_tree_insert(instance->lsdb[lsa_type], &lsa->key); + assert(result.inserted); + if(result.inserted) { + *result.datum_ptr = lsa; + } else { + LOG_NOARG(OSPF, "Failed to add OSPF LSA to LSDB\n"); + return false; + } + } + + if(lsa->lsa_buf_len < lsa_len) { + if(lsa->lsa) free(lsa->lsa); + lsa->lsa = malloc(lsa_len); + lsa->lsa_buf_len = lsa_len; + } + memcpy(lsa->lsa, hdr, lsa_len); + lsa->lsa_len = lsa_len; + lsa->source.type = OSPF_SOURCE_EXTERNAL; + lsa->source.router_id = 0; + lsa->seq = be32toh(hdr->seq); + lsa->age = be16toh(hdr->age)+1; + lsa->timestamp.tv_sec = now.tv_sec; + lsa->timestamp.tv_nsec = now.tv_sec; + ospf_lsa_update_age(lsa, &now); + ospf_lsa_flood(lsa); + ospf_lsa_lifetime(lsa); + } + + fclose(mrt_file); return true; -} +} \ No newline at end of file