From b93b083a46bee889df5614c7f938008775943638 Mon Sep 17 00:00:00 2001 From: Hannes Gredler Date: Tue, 5 Sep 2023 11:49:07 +0000 Subject: [PATCH 01/12] Pad OSPF2 RI LSA subTLVs --- code/lspgen/src/lspgen_packet.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/lspgen/src/lspgen_packet.c b/code/lspgen/src/lspgen_packet.c index a5f059af..db0f49c6 100644 --- a/code/lspgen/src/lspgen_packet.c +++ b/code/lspgen/src/lspgen_packet.c @@ -950,8 +950,9 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t push_be_uint(buf2, 1, 0); /* Reserved */ push_be_uint(buf2, 2, 1); /* SID Type Label */ - push_be_uint(buf2, 2, 3); /* SID Type Length */ - push_be_uint(buf2, 3, attr->key.cap.srgb_base); + push_be_uint(buf2, 2, 3); /* SID Type Length */ + push_be_uint(buf2, 3, attr->key.cap.srgb_base); + push_pad4(buf2); write_be_uint(buf2->data+2, 2, buf2->idx-4); /* Update length */ push_pad4(buf2); From 42850bca77a617ac14d5e2feaa3d11a322a43ad0 Mon Sep 17 00:00:00 2001 From: Hannes Gredler Date: Tue, 12 Sep 2023 08:24:36 +0000 Subject: [PATCH 02/12] correctly pad SID Index subTLV --- code/lspgen/src/lspgen_packet.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/lspgen/src/lspgen_packet.c b/code/lspgen/src/lspgen_packet.c index db0f49c6..9a4fbfa2 100644 --- a/code/lspgen/src/lspgen_packet.c +++ b/code/lspgen/src/lspgen_packet.c @@ -971,10 +971,11 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t /* Prefix SID - XXX Move this to Level 4*/ push_be_uint(buf2, 2, 2); /* Type */ - push_be_uint(buf2, 2, 7); /* Length */ + push_be_uint(buf2, 2, 8); /* Length */ push_be_uint(buf2, 3, 0); /* Flags, Reserved, MT-ID */ push_be_uint(buf2, 1, attr->key.prefix.sid_algo); /* Algorithm */ - push_be_uint(buf2, 3, attr->key.prefix.sid); /* SID Index */ + push_be_uint(buf2, 4, attr->key.prefix.sid); /* SID Index */ + push_pad4(buf2); write_be_uint(buf2->data+2, 2, buf2->idx-4); /* Update length */ push_pad4(buf2); From aaacc395e61c56784e5dac71854ad774be7b6fda Mon Sep 17 00:00:00 2001 From: Hannes Gredler Date: Tue, 12 Sep 2023 14:13:12 +0000 Subject: [PATCH 03/12] Use correct json tag on blaster socket. Omit the IP header on the blaster socket. --- code/lspgen/src/lspgen_ctrl.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/code/lspgen/src/lspgen_ctrl.c b/code/lspgen/src/lspgen_ctrl.c index ab6fd6c3..f3daf6eb 100644 --- a/code/lspgen/src/lspgen_ctrl.c +++ b/code/lspgen/src/lspgen_ctrl.c @@ -175,7 +175,17 @@ lspgen_ctrl_encode_packet(lsdb_ctx_t *ctx, lsdb_packet_t *packet) push_be_uint(buf, 1, '\n'); } push_be_uint(buf, 1, '"'); - for (idx = 0; idx < packet->buf.idx; idx++) { + + idx = 0; + if (ctx->protocol_id == PROTO_OSPF2) { + + /* + * Omit the IP header (=the first 20 bytes). + */ + idx = 20; + } + + for (; idx < packet->buf.idx; idx++) { hi_byte = packet->buf.data[idx] >> 4; lo_byte = packet->buf.data[idx] & 0xf; @@ -254,7 +264,7 @@ lspgen_ctrl_write_cb(timer_s *timer) json_header = "{\n\"command\": \"isis-lsp-update\",\n" "\"arguments\": {\n\"instance\": 1,\n\"pdu\": ["; } else if (ctx->protocol_id == PROTO_OSPF2 || ctx->protocol_id == PROTO_OSPF3) { - json_header = "{\n\"command\": \"ospf-ls-update\",\n" + json_header = "{\n\"command\": \"ospf-pdu-update\",\n" "\"arguments\": {\n\"instance\": 1,\n\"pdu\": ["; } if (!json_header) { From f2c01c6d6909747728241daa7c96fbc77f025646 Mon Sep 17 00:00:00 2001 From: Hannes Gredler Date: Wed, 13 Sep 2023 07:37:20 +0000 Subject: [PATCH 04/12] add support for --purge option --- code/lspgen/src/lspgen.c | 10 ++++++-- code/lspgen/src/lspgen_lsdb.h | 1 + code/lspgen/src/lspgen_packet.c | 44 ++++++++++++++++++++++++++------- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/code/lspgen/src/lspgen.c b/code/lspgen/src/lspgen.c index 46fec503..693cc718 100644 --- a/code/lspgen/src/lspgen.c +++ b/code/lspgen/src/lspgen.c @@ -63,6 +63,7 @@ static struct option long_options[] = { {"mrt-file", required_argument, NULL, 'm'}, {"node-count", required_argument, NULL, 'c'}, {"pcap-file", required_argument, NULL, 'p'}, + {"purge", no_argument, NULL, 'G'}, {"stream-file", required_argument, NULL, 'f'}, {"seed", required_argument, NULL, 's'}, {"sequence", required_argument, NULL, 'q'}, @@ -819,7 +820,9 @@ lspgen_log_ctx(struct lsdb_ctx_ *ctx) } else if (ctx->protocol_id == PROTO_OSPF2 || ctx->protocol_id == PROTO_OSPF3) { LOG(NORMAL, " Area %s\n", format_ipv4_address(&ctx->topology_id.area)); } - LOG(NORMAL, " Sequence 0x%x, lsp-lifetime %u\n", ctx->sequence, ctx->lsp_lifetime); + LOG(NORMAL, " Sequence 0x%x, lsp-lifetime %u%s\n", + ctx->sequence, ctx->lsp_lifetime, + ctx->purge ? ", Purge" : ""); if (ctx->authentication_key) { LOG(NORMAL, " Authentication-key %s, Authentication-type %s\n", @@ -1027,12 +1030,15 @@ main(int argc, char *argv[]) * Parse options. */ idx = 0; - while ((opt = getopt_long(argc, argv, "vha:c:C:e:f:g:l:L:m:M:n:K:N:p:P:q:Qr:s:S:t:T:V:w:x:X:yzZ", + while ((opt = getopt_long(argc, argv, "vha:c:C:e:f:g:Gl:L:m:M:n:K:N:p:P:q:Qr:s:S:t:T:V:w:x:X:yzZ", long_options, &idx)) != -1) { switch (opt) { case 'v': lspgen_print_version(); exit(0); + case 'G': + ctx->purge = true; + break; case 'P': ctx->protocol_id = key2val(proto_names, optarg); if (ctx->protocol_id == PROTO_OSPF2) { diff --git a/code/lspgen/src/lspgen_lsdb.h b/code/lspgen/src/lspgen_lsdb.h index 8988d5c2..0c0cb922 100644 --- a/code/lspgen/src/lspgen_lsdb.h +++ b/code/lspgen/src/lspgen_lsdb.h @@ -83,6 +83,7 @@ typedef struct lsdb_ctx_ bool no_sr; bool no_ipv4; bool no_ipv6; + bool purge; uint16_t lsp_lifetime; uint32_t node_index; diff --git a/code/lspgen/src/lspgen_packet.c b/code/lspgen/src/lspgen_packet.c index 9a4fbfa2..3a6b84a5 100644 --- a/code/lspgen/src/lspgen_packet.c +++ b/code/lspgen/src/lspgen_packet.c @@ -226,7 +226,7 @@ lspgen_calculate_isis_auth_len(lsdb_ctx_t *ctx) void lspgen_finalize_isis_packet(lsdb_ctx_t *ctx, lsdb_node_t *node, lsdb_packet_t *packet) { - uint16_t checksum; + uint16_t checksum, lsp_lifetime; uint8_t auth_len; /* @@ -262,10 +262,14 @@ lspgen_finalize_isis_packet(lsdb_ctx_t *ctx, lsdb_node_t *node, lsdb_packet_t *p * Set remaining lifetime */ if (node->lsp_lifetime) { - write_be_uint(packet->data+10, 2, node->lsp_lifetime); + lsp_lifetime = node->lsp_lifetime; } else { - write_be_uint(packet->data+10, 2, ctx->lsp_lifetime); + lsp_lifetime = ctx->lsp_lifetime; } + if (ctx->purge) { + lsp_lifetime = 0; + } + write_be_uint(packet->data+10, 2, lsp_lifetime); /* * Update PDU length field. @@ -706,6 +710,20 @@ lspgen_format_serializer_state (uint16_t state) return buf; } +uint16_t +lspgen_get_ospf_age(lsdb_node_t *node) +{ + lsdb_ctx_t *ctx; + + ctx = node->ctx; + + if (ctx->purge) { + return 3600; + } + + return 1; +} + /* * Fill a buffer with zeros up to the next 32bit boundary. */ @@ -835,7 +853,7 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t switch(attr->key.attr_cp[1]) { case OSPF_LSA_ROUTER: - push_be_uint(buf1, 2, 1); /* LS-age */ + push_be_uint(buf1, 2, lspgen_get_ospf_age(node)); /* LS-age */ push_be_uint(buf1, 1, 0); /* Options */ push_be_uint(buf1, 1, OSPF_LSA_ROUTER); /* LS-Type */ router_id = read_be_uint(node->key.node_id, 4); @@ -851,7 +869,7 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t break; case OSPF_LSA_EXTERNAL: - push_be_uint(buf1, 2, 1); /* LS-age */ + push_be_uint(buf1, 2, lspgen_get_ospf_age(node)); /* LS-age */ push_be_uint(buf1, 1, 0); /* Options */ push_be_uint(buf1, 1, 5); /* LS-Type */ push_data(buf1, (uint8_t*)&attr->key.prefix.ipv4_prefix.address, 4); /* Link State ID */ @@ -873,7 +891,7 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t break; case OSPF_LSA_OPAQUE_AREA_RI: - push_be_uint(buf1, 2, 1); /* LS-age */ + push_be_uint(buf1, 2, lspgen_get_ospf_age(node)); /* LS-age */ push_be_uint(buf1, 1, 0); /* Options */ push_be_uint(buf1, 1, 10); /* LS-Type */ push_be_uint(buf1, 1, 4); /* Opaque Type: Router-Information */ @@ -886,7 +904,7 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t break; case OSPF_LSA_OPAQUE_AREA_EP: - push_be_uint(buf1, 2, 1); /* LS-age */ + push_be_uint(buf1, 2, lspgen_get_ospf_age(node)); /* LS-age */ push_be_uint(buf1, 1, 0); /* Options */ push_be_uint(buf1, 1, 10); /* LS-Type */ push_be_uint(buf1, 1, 7); /* Opaque Type: Extended Prefix */ @@ -906,6 +924,13 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t lspgen_propagate_buffer_down(packet, 1); } + /* + * If users wants to generate purges encoding stops at level 1. + */ + if (ctx->purge) { + return; + } + /* open Level 2 */ if (state & OPEN_LEVEL2) { switch(attr->key.attr_cp[2]) { @@ -1311,9 +1336,10 @@ lspgen_gen_isis_packet_node(lsdb_node_t *node) */ dict_clear(node->packet_dict, lsdb_free_packet); - if (!node->attr_dict) { + if (!node->attr_dict || ctx->purge) { + /* - * No attributes. This is a purge. + * Purge if no attributes or explicit purge. */ packet = lspgen_add_packet(ctx, node, id); lspgen_finalize_packet(ctx, node, packet); From 8ec420dbbc20f83a776dfb5044dc01d951b8eca6 Mon Sep 17 00:00:00 2001 From: Hannes Gredler Date: Wed, 13 Sep 2023 14:08:11 +0000 Subject: [PATCH 05/12] zero change: consolidate single and hierarchical buffer management --- code/lspgen/src/lspgen_ctrl.c | 11 +-- code/lspgen/src/lspgen_lsdb.c | 6 +- code/lspgen/src/lspgen_lsdb.h | 3 +- code/lspgen/src/lspgen_mrt.c | 10 +-- code/lspgen/src/lspgen_packet.c | 152 ++++++++++++++------------------ code/lspgen/src/lspgen_pcap.c | 20 ++--- 6 files changed, 89 insertions(+), 113 deletions(-) diff --git a/code/lspgen/src/lspgen_ctrl.c b/code/lspgen/src/lspgen_ctrl.c index f3daf6eb..bba5c1f0 100644 --- a/code/lspgen/src/lspgen_ctrl.c +++ b/code/lspgen/src/lspgen_ctrl.c @@ -161,7 +161,7 @@ lspgen_write_ctrl_buffer(lsdb_ctx_t *ctx) static void lspgen_ctrl_encode_packet(lsdb_ctx_t *ctx, lsdb_packet_t *packet) { - struct io_buffer_ *buf; + struct io_buffer_ *buf, *src_buf; char hextable[] = "0123456789abcdef"; uint8_t hi_byte, lo_byte; uint32_t idx, val; @@ -185,9 +185,10 @@ lspgen_ctrl_encode_packet(lsdb_ctx_t *ctx, lsdb_packet_t *packet) idx = 20; } - for (; idx < packet->buf.idx; idx++) { - hi_byte = packet->buf.data[idx] >> 4; - lo_byte = packet->buf.data[idx] & 0xf; + src_buf = &packet->buf[0]; + for (; idx < src_buf->idx; idx++) { + hi_byte = src_buf->data[idx] >> 4; + lo_byte = src_buf->data[idx] & 0xf; val = (hextable[hi_byte] << 8) | hextable[lo_byte]; push_be_uint(buf, 2, val); @@ -285,7 +286,7 @@ lspgen_ctrl_write_cb(timer_s *timer) /* * Hexdumping doubles the data plus 4 bytes for two quotation marks, comma and whitespace. */ - if (buffer_left < ((packet->buf.idx * 2) + 4)) { + if (buffer_left < ((packet->buf[0].idx * 2) + 4)) { /* no space, release buffer and try later */ lspgen_write_ctrl_buffer(ctx); diff --git a/code/lspgen/src/lspgen_lsdb.c b/code/lspgen/src/lspgen_lsdb.c index 9d24d15d..2e094a58 100644 --- a/code/lspgen/src/lspgen_lsdb.c +++ b/code/lspgen/src/lspgen_lsdb.c @@ -962,14 +962,14 @@ lsdb_add_node_attr(lsdb_node_t *node, lsdb_attr_t *attr_template) */ lspgen_reset_packet_buffer(&packet); lspgen_serialize_attr(ctx, attr, &packet); - attr->size = packet.buf.idx; + attr->size = packet.buf[0].idx; /* * Find lowest level size. */ for (idx = MAX_MSG_LEVEL-1; idx; idx--) { - if (packet.bufX[idx].idx) { - attr->size += packet.bufX[idx].idx; + if (packet.buf[idx].idx) { + attr->size += packet.buf[idx].idx; break; } } diff --git a/code/lspgen/src/lspgen_lsdb.h b/code/lspgen/src/lspgen_lsdb.h index 0c0cb922..76551584 100644 --- a/code/lspgen/src/lspgen_lsdb.h +++ b/code/lspgen/src/lspgen_lsdb.h @@ -316,8 +316,7 @@ typedef struct lsdb_packet_ { uint32_t id; /* Fragment # for IS-IS, LS-Update Packet # for OSPF */ } key; - struct io_buffer_ buf; - struct io_buffer_ bufX[MAX_MSG_LEVEL]; + struct io_buffer_ buf[MAX_MSG_LEVEL]; uint8_t data[1500]; /* fixed buffer */ uint8_t redzone[8]; /* Overwrite detection */ diff --git a/code/lspgen/src/lspgen_mrt.c b/code/lspgen/src/lspgen_mrt.c index aaa38389..d7990b7b 100644 --- a/code/lspgen/src/lspgen_mrt.c +++ b/code/lspgen/src/lspgen_mrt.c @@ -62,8 +62,8 @@ lspgen_dump_mrt_node(lsdb_ctx_t *ctx, lsdb_node_t *node) /* * Copy packet */ - memcpy(&mrt_record[buf.idx], packet->data, packet->buf.idx); - buf.idx += packet->buf.idx; + memcpy(&mrt_record[buf.idx], packet->data, packet->buf[0].idx); + buf.idx += packet->buf[0].idx; break; case PROTO_OSPF2: @@ -77,13 +77,13 @@ lspgen_dump_mrt_node(lsdb_ctx_t *ctx, lsdb_node_t *node) /* * Copy packet */ - if (packet->buf.idx > 20) { + if (packet->buf[0].idx > 20) { /* * Skip 20 bytes of IPv4 header. */ - memcpy(&mrt_record[buf.idx], packet->data+20, packet->buf.idx-20); - buf.idx += packet->buf.idx-20; + memcpy(&mrt_record[buf.idx], packet->data+20, packet->buf[0].idx-20); + buf.idx += packet->buf[0].idx-20; } break; diff --git a/code/lspgen/src/lspgen_packet.c b/code/lspgen/src/lspgen_packet.c index 3a6b84a5..9b26787d 100644 --- a/code/lspgen/src/lspgen_packet.c +++ b/code/lspgen/src/lspgen_packet.c @@ -22,45 +22,47 @@ void lspgen_serialize_ospf2_state(lsdb_attr_t *, lsdb_packet_t *, uint16_t); void lspgen_gen_isis_packet_header(lsdb_ctx_t *ctx, lsdb_node_t *node, lsdb_packet_t *packet) { + struct io_buffer_ *buf; unsigned long long sysid; uint8_t lsattr; /* * Reset buffer. */ - packet->buf.data = packet->data; - packet->buf.start_idx = 0; - packet->buf.idx = 0; - packet->buf.size = sizeof(packet->data); + buf = &packet->buf[0]; + buf->data = packet->data; + buf->start_idx = 0; + buf->idx = 0; + buf->size = sizeof(packet->data); - push_be_uint(&packet->buf, 1, 0x83); /* Intradomain Routeing Protocol Discriminator */ - push_be_uint(&packet->buf, 1, 27); /* Length Indicator always 27 for LSPs */ - push_be_uint(&packet->buf, 1, 1); /* Version/Protocol ID Extension */ - push_be_uint(&packet->buf, 1, 0); /* ID Length */ + push_be_uint(buf, 1, 0x83); /* Intradomain Routeing Protocol Discriminator */ + push_be_uint(buf, 1, 27); /* Length Indicator always 27 for LSPs */ + push_be_uint(buf, 1, 1); /* Version/Protocol ID Extension */ + push_be_uint(buf, 1, 0); /* ID Length */ /* PDU Type */ if (ctx->topology_id.level == 1) { - push_be_uint(&packet->buf, 1, ISIS_PDU_L1_LSP); + push_be_uint(buf, 1, ISIS_PDU_L1_LSP); } if (ctx->topology_id.level == 2) { - push_be_uint(&packet->buf, 1, ISIS_PDU_L2_LSP); + push_be_uint(buf, 1, ISIS_PDU_L2_LSP); } - push_be_uint(&packet->buf, 1, 1); /* Version */ - push_be_uint(&packet->buf, 1, 0); /* Reserved */ - push_be_uint(&packet->buf, 1, 0); /* Maximum Area Addresses */ + push_be_uint(buf, 1, 1); /* Version */ + push_be_uint(buf, 1, 0); /* Reserved */ + push_be_uint(buf, 1, 0); /* Maximum Area Addresses */ - push_be_uint(&packet->buf, 2, 0); /* PDU length */ - push_be_uint(&packet->buf, 2, 0); /* Remaining Lifetime - will be overwritten during checksum calc */ + push_be_uint(buf, 2, 0); /* PDU length */ + push_be_uint(buf, 2, 0); /* Remaining Lifetime - will be overwritten during checksum calc */ /* LSP ID */ sysid = read_be_uint(node->key.node_id, 6); - push_be_uint(&packet->buf, 6, sysid); /* System ID */ - push_be_uint(&packet->buf, 1, 0); /* PSN # */ - push_be_uint(&packet->buf, 1, packet->key.id); /* Fragment # */ + push_be_uint(buf, 6, sysid); /* System ID */ + push_be_uint(buf, 1, 0); /* PSN # */ + push_be_uint(buf, 1, packet->key.id); /* Fragment # */ - push_be_uint(&packet->buf, 4, node->sequence); /* Sequence */ - push_be_uint(&packet->buf, 2, 0); /* Checksum */ + push_be_uint(buf, 4, node->sequence); /* Sequence */ + push_be_uint(buf, 2, 0); /* Checksum */ lsattr = 0; if (ctx->topology_id.level == 1) { @@ -75,36 +77,7 @@ lspgen_gen_isis_packet_header(lsdb_ctx_t *ctx, lsdb_node_t *node, lsdb_packet_t if (node->attach) { lsattr |= 0x08; } - push_be_uint(&packet->buf, 1, lsattr); /* LSP Attributes */ -} - -void -lspgen_gen_ospf2_packet_header(lsdb_ctx_t *ctx, lsdb_node_t *node, lsdb_packet_t *packet) -{ - uint32_t router_id; - - /* - * Reset buffer. - */ - packet->buf.data = packet->data; - packet->buf.start_idx = 0; - packet->buf.idx = 0; - packet->buf.size = sizeof(packet->data); - - push_be_uint(&packet->buf, 1, 2); /* Version */ - push_be_uint(&packet->buf, 1, 4); /* Message Type: Link State Update */ - push_be_uint(&packet->buf, 2, 0); /* Packet length - will be overwritten later */ - - router_id = read_be_uint(node->key.node_id, 4); - push_be_uint(&packet->buf, 4, router_id); /* Router ID */ - push_be_uint(&packet->buf, 4, ctx->topology_id.area); /* Area ID */ - - push_be_uint(&packet->buf, 2, 0); /* Checksum - will be overwritten later */ - - push_be_uint(&packet->buf, 2, 0); /* Authentication Type */ - push_be_uint(&packet->buf, 8, 0); /* Authentication */ - - push_be_uint(&packet->buf, 4, 0); /* # LSAs - will be overwritten later */ + push_be_uint(buf, 1, lsattr); /* LSP Attributes */ } void @@ -115,7 +88,6 @@ lspgen_gen_packet_header(lsdb_ctx_t *ctx, lsdb_node_t *node, lsdb_packet_t *pack lspgen_gen_isis_packet_header(ctx, node, packet); break; case PROTO_OSPF2: - //lspgen_gen_ospf2_packet_header(ctx, node, packet); break; default: LOG_NOARG(ERROR, "Unknown protocol\n"); @@ -226,9 +198,12 @@ lspgen_calculate_isis_auth_len(lsdb_ctx_t *ctx) void lspgen_finalize_isis_packet(lsdb_ctx_t *ctx, lsdb_node_t *node, lsdb_packet_t *packet) { + struct io_buffer_ *buf; uint16_t checksum, lsp_lifetime; uint8_t auth_len; + buf = &packet->buf[0]; + /* * Generate Authentication TLV */ @@ -240,21 +215,21 @@ lspgen_finalize_isis_packet(lsdb_ctx_t *ctx, lsdb_node_t *node, lsdb_packet_t *p auth_len = 16; } - push_be_uint(&packet->buf, 1, ISIS_TLV_AUTH); /* Type */ - push_be_uint(&packet->buf, 1, auth_len+1); /* Length */ - push_be_uint(&packet->buf, 1, ctx->authentication_type); + push_be_uint(buf, 1, ISIS_TLV_AUTH); /* Type */ + push_be_uint(buf, 1, auth_len+1); /* Length */ + push_be_uint(buf, 1, ctx->authentication_type); if (ctx->authentication_type == ISIS_AUTH_SIMPLE) { - push_data(&packet->buf, (uint8_t *)ctx->authentication_key, auth_len); + push_data(buf, (uint8_t *)ctx->authentication_key, auth_len); } if (ctx->authentication_type == ISIS_AUTH_MD5) { - push_be_uint(&packet->buf, 8, 0); - push_be_uint(&packet->buf, 8, 0); + push_be_uint(buf, 8, 0); + push_be_uint(buf, 8, 0); /* Update PDU length field. */ - write_be_uint(packet->data+8, 2, packet->buf.idx); - hmac_md5(packet->buf.data, packet->buf.idx, + write_be_uint(packet->data+8, 2, buf->idx); + hmac_md5(buf->data, buf->idx, (unsigned char *)ctx->authentication_key, strlen(ctx->authentication_key), - packet->buf.data+packet->buf.idx-16); + buf->data+buf->idx-16); } } @@ -274,14 +249,14 @@ lspgen_finalize_isis_packet(lsdb_ctx_t *ctx, lsdb_node_t *node, lsdb_packet_t *p /* * Update PDU length field. */ - write_be_uint(packet->data+8, 2, packet->buf.idx); + write_be_uint(packet->data+8, 2, buf->idx); /* * Calculate Checksum */ - write_be_uint(packet->data+24, 2, 0); /* reset checksum field */ - checksum = calculate_fletcher_cksum(packet->data+12, 12, packet->buf.idx-12); - write_be_uint(packet->data+24, 2, checksum); + write_be_uint(buf->data+24, 2, 0); /* reset checksum field */ + checksum = calculate_fletcher_cksum(buf->data+12, 12, buf->idx-12); + write_be_uint(buf->data+24, 2, checksum); } void @@ -305,8 +280,6 @@ lspgen_finalize_ospf2_packet(__attribute__((unused))lsdb_ctx_t *ctx, state |= CLOSE_LEVEL2; } lspgen_serialize_ospf2_state(NULL, packet, state); - memcpy(&packet->buf, &packet->bufX[0], sizeof(struct io_buffer_)); /* XXX rework */ - } void @@ -449,7 +422,7 @@ lspgen_serialize_isis_attr(lsdb_attr_t *attr, lsdb_packet_t *packet) bool subtlv_present; io_buffer_t *buf; - buf = &packet->buf; + buf = &packet->buf[0]; subtlv_present = lsdb_attr_subtlvs_present(attr); @@ -620,8 +593,8 @@ lspgen_propagate_buffer_down (lsdb_packet_t *packet, uint level) return; } - cur = &packet->bufX[level]; - next = &packet->bufX[level+1]; + cur = &packet->buf[level]; + next = &packet->buf[level+1]; next->data = cur->data + cur->idx; next->size = cur->size - cur->idx; @@ -642,8 +615,8 @@ lspgen_propagate_buffer_up (lsdb_packet_t *packet, uint level) return; } - cur = &packet->bufX[level]; - prev = &packet->bufX[level-1]; + cur = &packet->buf[level]; + prev = &packet->buf[level-1]; prev->idx += cur->idx; cur->data += cur->idx; @@ -748,9 +721,9 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t node = packet->parent; ctx = node->ctx; - buf0 = &packet->bufX[0]; - buf1 = &packet->bufX[1]; - buf2 = &packet->bufX[2]; + buf0 = &packet->buf[0]; + buf1 = &packet->buf[1]; + buf2 = &packet->buf[2]; LOG(PACKET, " %s\n", lspgen_format_serializer_state(state)); @@ -1189,14 +1162,17 @@ lspgen_calculate_tlv_space(io_buffer_t *buf, uint32_t tlv_start_idx) void lspgen_reset_packet_buffer (struct lsdb_packet_ *packet) { + struct io_buffer_ *buf; uint idx; - packet->buf.data = packet->data; - packet->buf.start_idx = 0; - packet->buf.idx = 0; - packet->buf.size = sizeof(packet->data); - for (idx = 0; idx < MAX_MSG_LEVEL; idx++) { - memcpy(&packet->bufX[idx], &packet->buf, sizeof(struct io_buffer_)); + buf = &packet->buf[0]; + + buf->data = packet->data; + buf->start_idx = 0; + buf->idx = 0; + buf->size = sizeof(packet->data); + for (idx = 1; idx < MAX_MSG_LEVEL; idx++) { + memcpy(&packet->buf[idx], buf, sizeof(struct io_buffer_)); } /* @@ -1379,7 +1355,7 @@ lspgen_gen_isis_packet_node(lsdb_node_t *node) */ min_len = lspgen_calculate_isis_auth_len(ctx); min_len += attr->size + TLV_OVERHEAD; - if (packet && packet->buf.idx > (1465-min_len)) { + if (packet && packet->buf[0].idx > (1465-min_len)) { /* * No space left. Finalize this packet. @@ -1400,7 +1376,7 @@ lspgen_gen_isis_packet_node(lsdb_node_t *node) */ if (!packet) { packet = lspgen_add_packet(ctx, node, id); - tlv_start_idx = packet->buf.idx; + tlv_start_idx = packet->buf[0].idx; } /* @@ -1411,15 +1387,15 @@ lspgen_gen_isis_packet_node(lsdb_node_t *node) * Start a fresh TLV ? */ if ((last_attr != attr->key.attr_type) || - (lspgen_calculate_tlv_space(&packet->buf, tlv_start_idx) < attr->size) || + (lspgen_calculate_tlv_space(&packet->buf[0], tlv_start_idx) < attr->size) || attr->key.start_tlv) { - tlv_start_idx = packet->buf.idx; - push_be_uint(&packet->buf, 1, attr->key.attr_type); /* Type */ - push_be_uint(&packet->buf, 1, 0); /* Length */ + tlv_start_idx = packet->buf[0].idx; + push_be_uint(&packet->buf[0], 1, attr->key.attr_type); /* Type */ + push_be_uint(&packet->buf[0], 1, 0); /* Length */ } lspgen_serialize_attr(ctx, attr, packet); - lspgen_update_tlv_length(&packet->buf, tlv_start_idx); + lspgen_update_tlv_length(&packet->buf[0], tlv_start_idx); last_attr = attr->key.attr_type; @@ -1493,7 +1469,7 @@ lspgen_gen_ospf2_packet_node(lsdb_node_t *node) */ min_len = lspgen_calculate_isis_auth_len(ctx); min_len += attr->size; - if (packet && packet->bufX[0].idx > (1440-min_len)) { + if (packet && packet->buf[0].idx > (1440-min_len)) { /* * No space left. Finalize this packet. diff --git a/code/lspgen/src/lspgen_pcap.c b/code/lspgen/src/lspgen_pcap.c index 69716591..49e52e7b 100644 --- a/code/lspgen/src/lspgen_pcap.c +++ b/code/lspgen/src/lspgen_pcap.c @@ -161,13 +161,13 @@ lspgen_dump_pcap_node (struct lsdb_ctx_ *ctx, struct lsdb_node_ *node) /* Account for the the faked ethernet & LLC header */ eth_header_length = 17; - push_le_uint(&buf, 4, packet->buf.idx+eth_header_length); /* captured packet length */ - push_le_uint(&buf, 4, packet->buf.idx+eth_header_length); /* original packet length */ + push_le_uint(&buf, 4, packet->buf[0].idx+eth_header_length); /* captured packet length */ + push_le_uint(&buf, 4, packet->buf[0].idx+eth_header_length); /* original packet length */ /* Fake an Ethernet & LLC header */ push_be_uint(&buf, 6, 0x0180c2000014); /* Destination MAC */ push_be_uint(&buf, 6, 0xf41e5e000000); /* Source MAC MAC */ - push_be_uint(&buf, 2, packet->buf.idx+3); /* Length + DSAP, SSAP, Mode */ + push_be_uint(&buf, 2, packet->buf[0].idx+3); /* Length + DSAP, SSAP, Mode */ push_be_uint(&buf, 3, 0xfefe03); /* OSI DSAP, SSAP, Mode */ } else if (ctx->protocol_id == PROTO_OSPF2) { @@ -176,8 +176,8 @@ lspgen_dump_pcap_node (struct lsdb_ctx_ *ctx, struct lsdb_node_ *node) /* Account for the faked Ethernet header */ eth_header_length = 14; - push_le_uint(&buf, 4, packet->buf.idx+eth_header_length); /* captured packet length */ - push_le_uint(&buf, 4, packet->buf.idx+eth_header_length); /* original packet length */ + push_le_uint(&buf, 4, packet->buf[0].idx+eth_header_length); /* captured packet length */ + push_le_uint(&buf, 4, packet->buf[0].idx+eth_header_length); /* original packet length */ /* Fake an Ethernet header */ push_be_uint(&buf, 6, 0x01005e000005); /* Destination MAC */ @@ -190,8 +190,8 @@ lspgen_dump_pcap_node (struct lsdb_ctx_ *ctx, struct lsdb_node_ *node) /* Account for the faked Ethernet header */ eth_header_length = 14; - push_le_uint(&buf, 4, packet->buf.idx+eth_header_length); /* captured packet length */ - push_le_uint(&buf, 4, packet->buf.idx+eth_header_length); /* original packet length */ + push_le_uint(&buf, 4, packet->buf[0].idx+eth_header_length); /* captured packet length */ + push_le_uint(&buf, 4, packet->buf[0].idx+eth_header_length); /* original packet length */ /* Fake an Ethernet header */ push_be_uint(&buf, 6, 0x333300000005); /* Destination MAC */ @@ -202,9 +202,9 @@ lspgen_dump_pcap_node (struct lsdb_ctx_ *ctx, struct lsdb_node_ *node) /* * Copy packet */ - memcpy(&pcap_packet[buf.idx], packet->data, packet->buf.idx); - buf.idx += packet->buf.idx; - push_le_uint(&buf, calc_pad(packet->buf.idx+eth_header_length), 0); /* write pad bytes */ + memcpy(&pcap_packet[buf.idx], packet->data, packet->buf[0].idx); + buf.idx += packet->buf[0].idx; + push_le_uint(&buf, calc_pad(packet->buf[0].idx+eth_header_length), 0); /* write pad bytes */ /* * Calculate total length field. It occurs twice. Overwrite and append. From f85f36c3403bd094452c9cf55fc01c80383cf75f Mon Sep 17 00:00:00 2001 From: Hannes Gredler Date: Thu, 14 Sep 2023 13:45:51 +0000 Subject: [PATCH 06/12] Add lsdb attributes for OSPF3 --- code/lspgen/src/lspgen.c | 183 ++++++++++++++++++++++++++++++++-- code/lspgen/src/lspgen_lsdb.c | 4 +- 2 files changed, 179 insertions(+), 8 deletions(-) diff --git a/code/lspgen/src/lspgen.c b/code/lspgen/src/lspgen.c index 693cc718..b3092f53 100644 --- a/code/lspgen/src/lspgen.c +++ b/code/lspgen/src/lspgen.c @@ -97,7 +97,7 @@ struct keyval_ log_names[] = { struct keyval_ proto_names[] = { { PROTO_ISIS, "isis" }, { PROTO_OSPF2, "ospf2" }, - //{ PROTO_OSPF3, "ospf3" }, + { PROTO_OSPF3, "ospf3" }, { 0, NULL} }; @@ -462,7 +462,7 @@ lspgen_gen_isis_attr(struct lsdb_ctx_ *ctx) /* ipv6 external prefix */ lsdb_reset_attr_template(&attr_template); - lspgen_store_addr(ext_addr6, attr_template.key.prefix.ipv6_prefix.address, 16); + lspgen_store_addr(ext_addr6, attr_template.key.prefix.ipv6_prefix.address, IPV6_ADDR_LEN); attr_template.key.prefix.ipv6_prefix.len = ctx->ipv6_ext_prefix.len; attr_template.key.prefix.metric = 100; attr_template.key.attr_type = ISIS_TLV_EXTD_IPV6_REACH; @@ -640,7 +640,7 @@ lspgen_gen_ospf2_attr(struct lsdb_ctx_ *ctx) CIRCLEQ_FOREACH(link, &node->link_qhead, link_qnode) { /* - * Is this a conncetor link ? + * Is this a connector link ? */ if (link->key.remote_node_id[7] == CONNECTOR_MARKER) { lsdb_reset_attr_template(&attr_template); @@ -700,6 +700,176 @@ lspgen_gen_ospf2_attr(struct lsdb_ctx_ *ctx) dict_itor_free(itor); } +/* + * Walk the graph of the LSDB and add the required node/link attributes for OSPFv3 LSP generation. + */ +void +lspgen_gen_ospf3_attr(struct lsdb_ctx_ *ctx) +{ + struct lsdb_node_ *node; + struct lsdb_link_ *link; + struct lsdb_attr_ attr_template; + dict_itor *itor; + __uint128_t addr, inc, ext_addr6, ext_incr6, addr_offset; + uint32_t ext_per_node, metric; + + /* + * Walk the node DB. + */ + itor = dict_itor_new(ctx->node_dict); + if (!itor) { + return; + } + + /* + * Node DB empty ? + */ + if (!dict_itor_first(itor)) { + dict_itor_free(itor); + LOG_NOARG(ERROR, "Empty LSDB.\n"); + return; + } + + /* + * For external routes load the first address of the pool. + */ + ext_addr6 = lspgen_load_addr((uint8_t*)&ctx->ipv6_ext_prefix.address, IPV6_ADDR_LEN); + ext_incr6 = lspgen_get_prefix_inc(AF_INET6, ctx->ipv6_ext_prefix.len); + + do { + node = *dict_itor_datum(itor); + + /* Host name */ + if (node->node_name) { + lsdb_reset_attr_template(&attr_template); + attr_template.key.ordinal = 1; + attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE; + attr_template.key.attr_cp[1] = OSPF_LSA_OPAQUE_AREA_RI; + attr_template.key.attr_cp[2] = OSPF_TLV_HOSTNAME; + strncpy(attr_template.key.hostname, node->node_name, sizeof(attr_template.key.hostname)-1); + lsdb_add_node_attr(node, &attr_template); + } + + /* IPv6 loopback prefix */ + lsdb_reset_attr_template(&attr_template); + addr = lspgen_load_addr((uint8_t*)&ctx->ipv6_node_prefix.address, IPV6_ADDR_LEN); + lspgen_store_addr(addr, attr_template.key.prefix.ipv6_prefix.address, IPV6_ADDR_LEN); + attr_template.key.prefix.ipv6_prefix.len = ctx->ipv6_node_prefix.len; + attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE; + attr_template.key.attr_cp[1] = OSPF_LSA_ROUTER; + attr_template.key.attr_cp[2] = OSPF_ROUTER_LSA_LINK_STUB; + lsdb_add_node_attr(node, &attr_template); + + if (!ctx->no_sr) { + lsdb_reset_attr_template(&attr_template); + lspgen_store_addr(addr, (uint8_t*)&attr_template.key.prefix.ipv6_prefix.address, IPV6_ADDR_LEN); + attr_template.key.prefix.ipv6_prefix.len = ctx->ipv6_node_prefix.len; + attr_template.key.prefix.sid = node->node_index; + + attr_template.key.ordinal = 1; + attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE; + attr_template.key.attr_cp[1] = OSPF_LSA_OPAQUE_AREA_EP; + attr_template.key.attr_cp[2] = OSPF_TLV_EXTENDED_PREFIX_RANGE; + lsdb_add_node_attr(node, &attr_template); + } + addr += node->node_index; + + /* external prefixes */ + ext_per_node = ctx->num_ext / ctx->num_nodes; + while (ext_per_node--) { + /* ipv6 external prefix */ + lsdb_reset_attr_template(&attr_template); + lspgen_store_addr(ext_addr6, attr_template.key.prefix.ipv6_prefix.address, IPV6_ADDR_LEN); + attr_template.key.prefix.ipv6_prefix.len = ctx->ipv6_ext_prefix.len; + attr_template.key.prefix.metric = 100; + attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE; + attr_template.key.attr_cp[1] = OSPF_LSA_EXTERNAL; + attr_template.key.start_tlv = true; + lsdb_add_node_attr(node, &attr_template); + ext_addr6 += ext_incr6; + } + + if (!ctx->no_sr) { + /* SR capability */ + lsdb_reset_attr_template(&attr_template); + addr = lspgen_load_addr((uint8_t*)&ctx->ipv4_node_prefix.address, sizeof(ipv4addr_t)); + addr += node->node_index; + lspgen_store_addr(addr, attr_template.key.cap.router_id, sizeof(ipv4addr_t)); + attr_template.key.cap.srgb_base = ctx->srgb_base; + attr_template.key.cap.srgb_range = ctx->srgb_range; + attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE; + attr_template.key.attr_cp[1] = OSPF_LSA_OPAQUE_AREA_RI; + attr_template.key.attr_cp[2] = OSPF_TLV_SID_LABEL_RANGE; + attr_template.key.ordinal = 1; + lsdb_add_node_attr(node, &attr_template); + } + + /* + * Walk all of our neighbors. + */ + CIRCLEQ_FOREACH(link, &node->link_qhead, link_qnode) { + + /* + * Is this a connector link ? + */ + if (link->key.remote_node_id[7] == CONNECTOR_MARKER) { + lsdb_reset_attr_template(&attr_template); + + attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE; + attr_template.key.attr_cp[1] = OSPF_LSA_ROUTER; + attr_template.key.attr_cp[2] = OSPF_ROUTER_LSA_LINK_PTP; + + memcpy(attr_template.key.link.remote_node_id, link->key.remote_node_id, 4); + memcpy(attr_template.key.link.local_node_id, link->key.local_link_id, 4); + attr_template.key.link.metric = link->link_metric; + lsdb_add_node_attr(node, &attr_template); + continue; + } + + /* + * Generate a ptp neighbor for each link + * TODO Type-2 LSA handling. + */ + lsdb_reset_attr_template(&attr_template); + + addr = lspgen_load_addr((uint8_t*)&ctx->ipv4_link_prefix.address, sizeof(ipv4addr_t)); + inc = lspgen_get_prefix_inc(AF_INET, ctx->ipv4_link_prefix.len); + addr += link->link_index * inc; + addr_offset = 0; + if (lspgen_load_addr(link->key.remote_node_id, 4) < lspgen_load_addr(link->key.local_node_id, 4)) { + addr_offset = 1; + } + + lspgen_store_addr(addr + addr_offset, attr_template.key.link.local_node_id, 4); + + attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE; + attr_template.key.attr_cp[1] = OSPF_LSA_ROUTER; + attr_template.key.attr_cp[2] = OSPF_ROUTER_LSA_LINK_PTP; + memcpy(attr_template.key.link.remote_node_id, link->key.remote_node_id, 4); + metric = link->link_metric; + if (metric > 65535) { + metric = 65535; + } + attr_template.key.link.metric = metric; + lsdb_add_node_attr(node, &attr_template); + + /* Generate an IPv6 prefix for each link */ + lsdb_reset_attr_template(&attr_template); + lspgen_store_addr(addr, (uint8_t*)&attr_template.key.prefix.ipv6_prefix.address, IPV6_ADDR_LEN); + attr_template.key.prefix.ipv6_prefix.len = ctx->ipv6_link_prefix.len; + attr_template.key.prefix.metric = metric; + + attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE; + attr_template.key.attr_cp[1] = OSPF_LSA_ROUTER; + attr_template.key.attr_cp[2] = OSPF_ROUTER_LSA_LINK_STUB; + lsdb_add_node_attr(node, &attr_template); + } + + } while (dict_itor_next(itor)); + + dict_itor_free(itor); +} + void lspgen_init_ctx(struct lsdb_ctx_ *ctx) { @@ -787,9 +957,9 @@ lspgen_compute_end_prefix6(struct ipv6_prefix_ *start_prefix, unsigned int num_p } prefix_inc = lspgen_get_prefix_inc(AF_INET6, start_prefix->len); - addr = lspgen_load_addr((uint8_t *)&start_prefix->address, 16); + addr = lspgen_load_addr((uint8_t *)&start_prefix->address, IPV6_ADDR_LEN); addr += prefix_inc * (num_prefixes-1); - lspgen_store_addr(addr, (uint8_t *)&end_prefix.address, 16); + lspgen_store_addr(addr, (uint8_t *)&end_prefix.address, IPV6_ADDR_LEN); return &end_prefix; } @@ -1232,8 +1402,9 @@ main(int argc, char *argv[]) lspgen_gen_isis_attr(ctx); } else if (ctx->protocol_id == PROTO_OSPF2) { lspgen_gen_ospf2_attr(ctx); + } else if (ctx->protocol_id == PROTO_OSPF3) { + lspgen_gen_ospf3_attr(ctx); } - } /* diff --git a/code/lspgen/src/lspgen_lsdb.c b/code/lspgen/src/lspgen_lsdb.c index 2e094a58..493334ef 100644 --- a/code/lspgen/src/lspgen_lsdb.c +++ b/code/lspgen/src/lspgen_lsdb.c @@ -181,10 +181,10 @@ lsdb_format_node(lsdb_node_t *node) if (ctx->protocol_id == PROTO_ISIS) { if (node->node_name) { - snprintf(buffer, sizeof(buffer), "%s (%s)", + snprintf(buffer, sizeof(buffer), "%s (%s)", lsdb_format_node_id(node->key.node_id), node->node_name); } else { - snprintf(buffer, sizeof(buffer), "%s", + snprintf(buffer, sizeof(buffer), "%s", lsdb_format_node_id(node->key.node_id)); } } else if (ctx->protocol_id == PROTO_OSPF2 || ctx->protocol_id == PROTO_OSPF3) { From 331db2b0943893098c3f381f589b350e3200aab9 Mon Sep 17 00:00:00 2001 From: Hannes Gredler Date: Fri, 15 Sep 2023 13:43:12 +0000 Subject: [PATCH 07/12] Add MRT support for OSPFv3 --- code/lspgen/src/lspgen_mrt.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/code/lspgen/src/lspgen_mrt.c b/code/lspgen/src/lspgen_mrt.c index d7990b7b..7f847f03 100644 --- a/code/lspgen/src/lspgen_mrt.c +++ b/code/lspgen/src/lspgen_mrt.c @@ -14,6 +14,7 @@ /* https://datatracker.ietf.org/doc/html/rfc6396#section-4 */ #define MRT_TYPE_OSPFV2 11 +#define MRT_TYPE_OSPFV3 48 #define MRT_TYPE_ISIS 32 /* @@ -87,6 +88,30 @@ lspgen_dump_mrt_node(lsdb_ctx_t *ctx, lsdb_node_t *node) } break; + case PROTO_OSPF3: + push_be_uint(&buf, 2, MRT_TYPE_OSPFV3); /* type */ + push_be_uint(&buf, 2, 0); /* subtype */ + push_be_uint(&buf, 4, 0); /* length, will be overwritten */ + + push_be_uint(&buf, 2, 2); /* address family: ipv6 */ + push_be_uint(&buf, 8, 0); /* remote IP address */ + push_be_uint(&buf, 8, 0); /* remote IP address */ + push_be_uint(&buf, 8, 0); /* local IP address */ + push_be_uint(&buf, 8, 0); /* local IP address */ + + /* + * Copy packet + */ + if (packet->buf[0].idx > 40) { + + /* + * Skip 40 bytes of IPv6 header. + */ + memcpy(&mrt_record[buf.idx], packet->data+40, packet->buf[0].idx-40); + buf.idx += packet->buf[0].idx-40; + } + break; + default: LOG(ERROR, "No MRT writer for protocol %u\n", ctx->protocol_id); return; From cfcbfac24b98b9ee378a236c12b33464e76ac756 Mon Sep 17 00:00:00 2001 From: Hannes Gredler Date: Fri, 15 Sep 2023 15:38:30 +0000 Subject: [PATCH 08/12] Add ospf3 support for router and external LSA --- code/lspgen/src/lspgen_packet.c | 379 ++++++++++++++++++++++++++++---- 1 file changed, 337 insertions(+), 42 deletions(-) diff --git a/code/lspgen/src/lspgen_packet.c b/code/lspgen/src/lspgen_packet.c index 9b26787d..7d2215d0 100644 --- a/code/lspgen/src/lspgen_packet.c +++ b/code/lspgen/src/lspgen_packet.c @@ -18,6 +18,7 @@ */ void lspgen_gen_packet_node(lsdb_node_t *); void lspgen_serialize_ospf2_state(lsdb_attr_t *, lsdb_packet_t *, uint16_t); +void lspgen_serialize_ospf3_state(lsdb_attr_t *, lsdb_packet_t *, uint16_t); void lspgen_gen_isis_packet_header(lsdb_ctx_t *ctx, lsdb_node_t *node, lsdb_packet_t *packet) @@ -89,6 +90,8 @@ lspgen_gen_packet_header(lsdb_ctx_t *ctx, lsdb_node_t *node, lsdb_packet_t *pack break; case PROTO_OSPF2: break; + case PROTO_OSPF3: + break; default: LOG_NOARG(ERROR, "Unknown protocol\n"); } @@ -175,23 +178,34 @@ calculate_cksum(uint8_t *buf, uint16_t len) } /* - * Calculate the size of the authentication TLV to be inserted. + * Calculate the size of the authentication data to be inserted. * Helper for calculating when to start a new packet. */ uint32_t -lspgen_calculate_isis_auth_len(lsdb_ctx_t *ctx) +lspgen_calculate_auth_len(lsdb_ctx_t *ctx) { uint8_t auth_len; auth_len = 0; - if (ctx->authentication_key && ctx->authentication_type) { - if (ctx->authentication_type == ISIS_AUTH_SIMPLE) { - auth_len = strlen(ctx->authentication_key) + 1 + TLV_OVERHEAD; - } if (ctx->authentication_type == ISIS_AUTH_MD5) { - auth_len = 16 + 1 + TLV_OVERHEAD; + switch (ctx->protocol_id) { + case PROTO_ISIS: + if (ctx->authentication_key && ctx->authentication_type) { + if (ctx->authentication_type == ISIS_AUTH_SIMPLE) { + auth_len = strlen(ctx->authentication_key) + 1 + TLV_OVERHEAD; + } if (ctx->authentication_type == ISIS_AUTH_MD5) { + auth_len = 16 + 1 + TLV_OVERHEAD; + } } - } + break; + /* + * BNG Blaster computes the authentication trailer for OSPF2 and OSPF3 + */ + case PROTO_OSPF2: /* fall through */ + case PROTO_OSPF3: /* fall through */ + default: + break; + } return auth_len; } @@ -259,16 +273,14 @@ lspgen_finalize_isis_packet(lsdb_ctx_t *ctx, lsdb_node_t *node, lsdb_packet_t *p write_be_uint(buf->data+24, 2, checksum); } -void -lspgen_finalize_ospf2_packet(__attribute__((unused))lsdb_ctx_t *ctx, - __attribute__((unused))lsdb_node_t *node, - lsdb_packet_t *packet) +/* + * Close all Message levels that the serializer may have left open. + */ +uint16_t +lspgen_close_all_message_levels (lsdb_packet_t *packet) { uint16_t state; - /* - * Close all Message levels that the serializer may have left open. - */ state = 0; if (packet->prev_attr_cp[0]) { state |= CLOSE_LEVEL0; @@ -279,7 +291,11 @@ lspgen_finalize_ospf2_packet(__attribute__((unused))lsdb_ctx_t *ctx, if (packet->prev_attr_cp[2]) { state |= CLOSE_LEVEL2; } - lspgen_serialize_ospf2_state(NULL, packet, state); + if (packet->prev_attr_cp[3]) { + state |= CLOSE_LEVEL3; + } + + return state; } void @@ -290,7 +306,10 @@ lspgen_finalize_packet(lsdb_ctx_t *ctx, lsdb_node_t *node, lsdb_packet_t *packet lspgen_finalize_isis_packet(ctx, node, packet); break; case PROTO_OSPF2: - lspgen_finalize_ospf2_packet(ctx, node, packet); + lspgen_serialize_ospf2_state(NULL, packet, lspgen_close_all_message_levels(packet)); + break; + case PROTO_OSPF3: + lspgen_serialize_ospf3_state(NULL, packet, lspgen_close_all_message_levels(packet)); break; default: LOG_NOARG(ERROR, "Unknown protocol\n"); @@ -729,14 +748,6 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t /* close Level 2 */ if (state & CLOSE_LEVEL2) { - switch (packet->prev_attr_cp[2]) { - case OSPF_ROUTER_LSA_LINK_PTP: - case OSPF_ROUTER_LSA_LINK_STUB: - break; - default: - break; - } - lspgen_propagate_buffer_up(packet, 2); } @@ -764,7 +775,6 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t /* close Level 0 */ if (state & CLOSE_LEVEL0) { - switch (packet->prev_attr_cp[0]) { case OSPF_MSG_LSUPDATE: write_be_uint(buf0->data+20+2, 2, buf0->idx - 20); /* Packet length */ @@ -811,7 +821,6 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t push_be_uint(buf0, 8, 0); /* Authentication */ push_be_uint(buf0, 4, 0); /* # LSAs - will be overwritten later */ - break; default: LOG(ERROR, "No Level 0 open packet serializer for attr %d\n", attr->key.attr_cp[0]); @@ -988,11 +997,258 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t } } +void +lspgen_serialize_ospf3_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t state) +{ + lsdb_ctx_t *ctx; + lsdb_node_t *node; + io_buffer_t *buf0, *buf1, *buf2; + uint16_t attr_len, checksum; + uint32_t router_id; + + node = packet->parent; + ctx = node->ctx; + + buf0 = &packet->buf[0]; + buf1 = &packet->buf[1]; + buf2 = &packet->buf[2]; + + LOG(PACKET, " %s\n", lspgen_format_serializer_state(state)); + + /* close Level 2 */ + if (state & CLOSE_LEVEL2) { + lspgen_propagate_buffer_up(packet, 2); + } + + /* close Level 1 */ + if (state & CLOSE_LEVEL1) { + switch (packet->prev_attr_cp[1]) { + case OSPF_LSA_ROUTER: + case OSPF_LSA_EXTERNAL: + case OSPF_LSA_OPAQUE_AREA_RI: + case OSPF_LSA_OPAQUE_AREA_EP: + inc_be_uint(buf0->data+40+16, 4); /* Update #LSAs */ + write_be_uint(buf1->data+18, 2, buf1->idx); /* Update Packet length */ + write_be_uint(buf1->data+16, 2, 0); /* reset checksum field */ + checksum = calculate_fletcher_cksum(buf1->data+2, 14, buf1->idx-2); + write_be_uint(buf1->data+16, 2, checksum); /* Update LSA Checksum */ + break; + default: + break; + } + + lspgen_propagate_buffer_up(packet, 1); + } + + /* close Level 0 */ + if (state & CLOSE_LEVEL0) { + switch (packet->prev_attr_cp[0]) { + case OSPF_MSG_LSUPDATE: + write_be_uint(buf0->data+40+2, 2, buf0->idx - 40); /* Packet length */ + write_be_uint(buf0->data+40+12, 2, calculate_cksum(buf0->data+40, buf0->idx-40)); /* Checksum */ + write_be_uint(buf0->data+4, 2, buf0->idx - 40); /* Payload length */ + break; + default: + break; + } + } + + /* open Level 0 */ + if (state & OPEN_LEVEL0) { + + switch(attr->key.attr_cp[0]) { + case OSPF_MSG_LSUPDATE: + + /* IPv6 header */ + push_be_uint(buf0, 1, 0x6c); /* Version, Traffic Class MSB */ + push_be_uint(buf0, 3, 0); /* Flow label */ + push_be_uint(buf0, 2, 0); /* Payload length - will be overwritten later */ + push_be_uint(buf0, 1, 89); /* Next Header */ + push_be_uint(buf0, 1, 255); /* Hop limit */ + push_data(buf0, (uint8_t *)&ctx->ipv6_node_prefix, IPV6_ADDR_LEN); /* Source Address */ + push_be_uint(buf0, 8, 0xff02000000000000); /* Destination Address */ + push_be_uint(buf0, 8, 5); /* Destination Address */ + + /* OSPFv3 header */ + push_be_uint(buf0, 1, 3); /* Version */ + push_be_uint(buf0, 1, OSPF_MSG_LSUPDATE); /* Msg */ + push_be_uint(buf0, 2, 0); /* Packet length - will be overwritten later */ + + router_id = read_be_uint(node->key.node_id, 4); + push_be_uint(buf0, 4, router_id); /* Router ID */ + push_be_uint(buf0, 4, ctx->topology_id.area); /* Area ID */ + + push_be_uint(buf0, 2, 0); /* Checksum - will be overwritten later */ + + push_be_uint(buf0, 1, 0); /* Instance ID */ + push_be_uint(buf0, 1, 0); /* Reserved */ + + push_be_uint(buf0, 4, 0); /* # LSAs - will be overwritten later */ + break; + default: + LOG(ERROR, "No Level 0 open packet serializer for attr %d\n", attr->key.attr_cp[0]); + return; + } + + lspgen_propagate_buffer_down(packet, 0); + } + + /* open Level 1 */ + if (state & OPEN_LEVEL1) { + + switch(attr->key.attr_cp[1]) { + case OSPF_LSA_ROUTER: + push_be_uint(buf1, 2, lspgen_get_ospf_age(node)); /* LS-age */ + push_be_uint(buf1, 2, 0x2001); /* LS-Type */ + router_id = read_be_uint(node->key.node_id, 4); + push_be_uint(buf1, 4, router_id); /* Link State ID */ + push_be_uint(buf1, 4, router_id); /* Advertising Router */ + push_be_uint(buf1, 4, node->sequence); /* Sequence */ + push_be_uint(buf1, 2, 0xffff); /* Checksum - will be overwritten later */ + push_be_uint(buf1, 2, 0); /* Length - will be overwritten later */ + + push_be_uint(buf1, 1, 0x02); /* Flags, E */ + push_be_uint(buf1, 3, 0); /* Options */ + break; + + case OSPF_LSA_EXTERNAL: + push_be_uint(buf1, 2, lspgen_get_ospf_age(node)); /* LS-age */ + push_be_uint(buf1, 2, 0x4005); /* LS-Type */ + push_data(buf1, (uint8_t*)&attr->key.prefix.ipv4_prefix.address, 4); /* Link State ID */ + router_id = read_be_uint(node->key.node_id, 4); + push_be_uint(buf1, 4, router_id); /* Advertising Router */ + push_be_uint(buf1, 4, node->sequence); /* Sequence */ + push_be_uint(buf1, 2, 0); /* Checksum - will be overwritten later */ + push_be_uint(buf1, 2, 0); /* Length - will be overwritten later */ + + push_be_uint(buf1, 1, 0x04); /* E2 */ + push_be_uint(buf1, 3, attr->key.prefix.metric); /* Metric */ + push_be_uint(buf1, 1, attr->key.prefix.ipv6_prefix.len); /* Prefix Length */ + push_be_uint(buf1, 1, 0x00); /* Prefix Options */ + push_be_uint(buf1, 2, 0); /* Referenced LS Type */ + attr_len = (attr->key.prefix.ipv6_prefix.len+7)/8; + push_data(buf1, attr->key.prefix.ipv6_prefix.address, attr_len); /* Prefix */ + push_pad4(buf1); + break; + + case OSPF_LSA_OPAQUE_AREA_RI: + push_be_uint(buf1, 2, lspgen_get_ospf_age(node)); /* LS-age */ + push_be_uint(buf1, 1, 0); /* Options */ + push_be_uint(buf1, 1, 10); /* LS-Type */ + push_be_uint(buf1, 1, 4); /* Opaque Type: Router-Information */ + push_be_uint(buf1, 3, 0); /* Opaque subtype */ + router_id = read_be_uint(node->key.node_id, 4); + push_be_uint(buf1, 4, router_id); /* Advertising Router */ + push_be_uint(buf1, 4, node->sequence); /* Sequence */ + push_be_uint(buf1, 2, 0); /* Checksum - will be overwritten later */ + push_be_uint(buf1, 2, 0); /* Length - will be overwritten later */ + break; + + case OSPF_LSA_OPAQUE_AREA_EP: + push_be_uint(buf1, 2, lspgen_get_ospf_age(node)); /* LS-age */ + push_be_uint(buf1, 1, 0); /* Options */ + push_be_uint(buf1, 1, 10); /* LS-Type */ + push_be_uint(buf1, 1, 7); /* Opaque Type: Extended Prefix */ + push_be_uint(buf1, 3, 0); /* Opaque subtype */ + router_id = read_be_uint(node->key.node_id, 4); + push_be_uint(buf1, 4, router_id); /* Advertising Router */ + push_be_uint(buf1, 4, node->sequence); /* Sequence */ + push_be_uint(buf1, 2, 0); /* Checksum - will be overwritten later */ + push_be_uint(buf1, 2, 0); /* Length - will be overwritten later */ + break; + + default: + LOG(ERROR, "No Level 1 open packet serializer for attr %d\n", attr->key.attr_cp[1]); + return; + } + + lspgen_propagate_buffer_down(packet, 1); + } + + /* + * If users wants to generate purges encoding stops at level 1. + */ + if (ctx->purge) { + return; + } + + /* open Level 2 */ + if (state & OPEN_LEVEL2) { + switch(attr->key.attr_cp[2]) { + case OSPF_ROUTER_LSA_LINK_PTP: + push_be_uint(buf2, 1, 1); /* Type ptp */ + push_be_uint(buf2, 1, 0); /* #TOS */ + push_be_uint(buf2, 2, attr->key.link.metric); /* metric */ + push_be_uint(buf2, 4, read_be_uint(attr->key.link.local_node_id, 4)); /* Interface ID */ + push_be_uint(buf2, 4, 0); /* Neighbor Interface ID */ + push_be_uint(buf2, 4, read_be_uint(attr->key.link.remote_node_id, 4)); /* Neighbor Router ID */ + break; + + case OSPF_TLV_HOSTNAME: + attr_len = strnlen(attr->key.hostname, sizeof(attr->key.hostname)); + if (attr_len) { + push_be_uint(buf2, 2, 7); /* Type */ + push_be_uint(buf2, 2, attr_len); /* Length */ + push_data(buf2, (uint8_t *)attr->key.hostname, attr_len); + push_pad4(buf2); + } + break; + + case OSPF_TLV_SID_LABEL_RANGE: + if (attr->key.cap.srgb_base && attr->key.cap.srgb_range) { + push_be_uint(buf2, 2, 9); /* Type */ + push_be_uint(buf2, 2, 0); /* Length - will be overwritten later */ + push_be_uint(buf2, 3, attr->key.cap.srgb_range); /* Range size */ + push_be_uint(buf2, 1, 0); /* Reserved */ + + push_be_uint(buf2, 2, 1); /* SID Type Label */ + push_be_uint(buf2, 2, 3); /* SID Type Length */ + push_be_uint(buf2, 3, attr->key.cap.srgb_base); + push_pad4(buf2); + + //write_be_uint(buf2->data+2, 2, buf2->idx-4); /* Update length */ + push_pad4(buf2); + } + break; + + case OSPF_TLV_EXTENDED_PREFIX_RANGE: + push_be_uint(buf2, 2, 2); /* Type */ + push_be_uint(buf2, 2, 0); /* Length - will be overwritten later */ + push_be_uint(buf2, 1, attr->key.prefix.ipv4_prefix.len); + push_be_uint(buf2, 1, 0); /* AF ipv4 */ + push_be_uint(buf2, 2, 1); /* Range size */ + push_be_uint(buf2, 1, 0); /* Flags */ + push_be_uint(buf2, 3, 0); /* Reserved */ + push_data(buf2, (uint8_t*)&attr->key.prefix.ipv4_prefix.address, 4); /* Prefix */ + + /* Prefix SID - XXX Move this to Level 4*/ + push_be_uint(buf2, 2, 2); /* Type */ + push_be_uint(buf2, 2, 8); /* Length */ + push_be_uint(buf2, 3, 0); /* Flags, Reserved, MT-ID */ + push_be_uint(buf2, 1, attr->key.prefix.sid_algo); /* Algorithm */ + push_be_uint(buf2, 4, attr->key.prefix.sid); /* SID Index */ + push_pad4(buf2); + + //write_be_uint(buf2->data+2, 2, buf2->idx-4); /* Update length */ + push_pad4(buf2); + break; + + default: + LOG(ERROR, "No Level 2 open packet serializer for attr %d\n", attr->key.attr_cp[2]); + return; + } + + lspgen_propagate_buffer_down(packet, 2); + } +} + /* - * Serialize an OSPFv2 attribute into a packet buffer. + * Serialize an OSPF attribute into a packet buffer. + * Pass a custom serialization callback function. */ void -lspgen_serialize_ospf2_attr(lsdb_attr_t *attr, lsdb_packet_t *packet) +lspgen_serialize_ospf_attr(lsdb_attr_t *attr, lsdb_packet_t *packet, + void (*serialize_cb)(lsdb_attr_t *, lsdb_packet_t *, uint16_t)) { uint16_t state; @@ -1016,9 +1272,12 @@ lspgen_serialize_ospf2_attr(lsdb_attr_t *attr, lsdb_packet_t *packet) state |= OPEN_LEVEL1; if (attr->key.attr_cp[2] && packet->prev_attr_cp[2] == 0) { state |= OPEN_LEVEL2; + if (attr->key.attr_cp[3] && packet->prev_attr_cp[3] == 0) { + state |= OPEN_LEVEL3; + } } } - lspgen_serialize_ospf2_state(attr, packet, state); + (*serialize_cb)(attr, packet, state); return; } @@ -1030,6 +1289,12 @@ lspgen_serialize_ospf2_attr(lsdb_attr_t *attr, lsdb_packet_t *packet) if (attr->key.attr_cp[0]) { state |= OPEN_LEVEL0; } + if (packet->prev_attr_cp[3]) { + state |= CLOSE_LEVEL3; + } + if (attr->key.attr_cp[3]) { + state |= OPEN_LEVEL3; + } if (packet->prev_attr_cp[2]) { state |= CLOSE_LEVEL2; } @@ -1042,7 +1307,7 @@ lspgen_serialize_ospf2_attr(lsdb_attr_t *attr, lsdb_packet_t *packet) if (attr->key.attr_cp[1]) { state |= OPEN_LEVEL1; } - lspgen_serialize_ospf2_state(attr, packet, state); + (*serialize_cb)(attr, packet, state); return; } @@ -1060,7 +1325,13 @@ lspgen_serialize_ospf2_attr(lsdb_attr_t *attr, lsdb_packet_t *packet) if (attr->key.attr_cp[2]) { state |= OPEN_LEVEL2; } - lspgen_serialize_ospf2_state(attr, packet, state); + if (packet->prev_attr_cp[3]) { + state |= CLOSE_LEVEL3; + } + if (attr->key.attr_cp[3]) { + state |= OPEN_LEVEL3; + } + (*serialize_cb)(attr, packet, state); return; } @@ -1072,7 +1343,25 @@ lspgen_serialize_ospf2_attr(lsdb_attr_t *attr, lsdb_packet_t *packet) if (attr->key.attr_cp[2]) { state |= OPEN_LEVEL2; } - lspgen_serialize_ospf2_state(attr, packet, state); + if (packet->prev_attr_cp[3]) { + state |= CLOSE_LEVEL3; + } + if (attr->key.attr_cp[3]) { + state |= OPEN_LEVEL3; + } + (*serialize_cb)(attr, packet, state); + return; + } + + /* + * Different L3 message ? + */ + if (packet->prev_attr_cp[3] != attr->key.attr_cp[3]) { + state |= CLOSE_LEVEL3; + if (attr->key.attr_cp[3]) { + state |= OPEN_LEVEL3; + } + (*serialize_cb)(attr, packet, state); return; } @@ -1084,7 +1373,9 @@ lspgen_serialize_ospf2_attr(lsdb_attr_t *attr, lsdb_packet_t *packet) /* * Figure out max level. */ - if (attr->key.attr_cp[2]) { + if (attr->key.attr_cp[3]) { + state |= OPEN_LEVEL3; + } else if (attr->key.attr_cp[2]) { state |= OPEN_LEVEL2; } else if (attr->key.attr_cp[1]) { state |= OPEN_LEVEL1; @@ -1099,7 +1390,7 @@ lspgen_serialize_ospf2_attr(lsdb_attr_t *attr, lsdb_packet_t *packet) state |= state << 8; } - lspgen_serialize_ospf2_state(attr, packet, state); + (*serialize_cb)(attr, packet, state); return; } } @@ -1119,7 +1410,10 @@ lspgen_serialize_attr(lsdb_ctx_t *ctx, lsdb_attr_t *attr, lsdb_packet_t *packet) lspgen_serialize_isis_attr(attr, packet); break; case PROTO_OSPF2: - lspgen_serialize_ospf2_attr(attr, packet); + lspgen_serialize_ospf_attr(attr, packet, lspgen_serialize_ospf2_state); + break; + case PROTO_OSPF3: + lspgen_serialize_ospf_attr(attr, packet, lspgen_serialize_ospf3_state); break; default: LOG_NOARG(ERROR, "Unknown protocol\n"); @@ -1353,7 +1647,7 @@ lspgen_gen_isis_packet_node(lsdb_node_t *node) /* * Space left in this packet ? */ - min_len = lspgen_calculate_isis_auth_len(ctx); + min_len = lspgen_calculate_auth_len(ctx); min_len += attr->size + TLV_OVERHEAD; if (packet && packet->buf[0].idx > (1465-min_len)) { @@ -1406,10 +1700,10 @@ lspgen_gen_isis_packet_node(lsdb_node_t *node) } /* - * Walk the graph of the LSDB and serialize OSPFv2 packets. + * Walk the graph of the LSDB and serialize OSPF2 and OSPF3 packets. */ void -lspgen_gen_ospf2_packet_node(lsdb_node_t *node) +lspgen_gen_ospf_packet_node(lsdb_node_t *node) { lsdb_ctx_t *ctx; struct lsdb_packet_ *packet; @@ -1467,7 +1761,7 @@ lspgen_gen_ospf2_packet_node(lsdb_node_t *node) /* * Space left in this packet ? */ - min_len = lspgen_calculate_isis_auth_len(ctx); + min_len = lspgen_calculate_auth_len(ctx); min_len += attr->size; if (packet && packet->buf[0].idx > (1440-min_len)) { @@ -1513,8 +1807,9 @@ lspgen_gen_packet_node(lsdb_node_t *node) case PROTO_ISIS: lspgen_gen_isis_packet_node(node); break; - case PROTO_OSPF2: - lspgen_gen_ospf2_packet_node(node); + case PROTO_OSPF2: /* fall through */ + case PROTO_OSPF3: + lspgen_gen_ospf_packet_node(node); break; default: LOG_NOARG(ERROR, "Unknown protocol\n"); From b741018093d4fc342437c7dc5255b6874a446864 Mon Sep 17 00:00:00 2001 From: Hannes Gredler Date: Fri, 15 Sep 2023 16:52:18 +0000 Subject: [PATCH 09/12] add ospf3 support for intra-area-prefix LSA --- code/lspgen/src/lspgen.c | 16 ++++++++------ code/lspgen/src/lspgen_ospf.h | 5 ++++- code/lspgen/src/lspgen_packet.c | 38 ++++++++++++++++++++++++++++----- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/code/lspgen/src/lspgen.c b/code/lspgen/src/lspgen.c index b3092f53..54c3ed15 100644 --- a/code/lspgen/src/lspgen.c +++ b/code/lspgen/src/lspgen.c @@ -742,7 +742,7 @@ lspgen_gen_ospf3_attr(struct lsdb_ctx_ *ctx) /* Host name */ if (node->node_name) { lsdb_reset_attr_template(&attr_template); - attr_template.key.ordinal = 1; + //attr_template.key.ordinal = 1; attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE; attr_template.key.attr_cp[1] = OSPF_LSA_OPAQUE_AREA_RI; attr_template.key.attr_cp[2] = OSPF_TLV_HOSTNAME; @@ -756,10 +756,11 @@ lspgen_gen_ospf3_attr(struct lsdb_ctx_ *ctx) lspgen_store_addr(addr, attr_template.key.prefix.ipv6_prefix.address, IPV6_ADDR_LEN); attr_template.key.prefix.ipv6_prefix.len = ctx->ipv6_node_prefix.len; attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE; - attr_template.key.attr_cp[1] = OSPF_LSA_ROUTER; - attr_template.key.attr_cp[2] = OSPF_ROUTER_LSA_LINK_STUB; + attr_template.key.attr_cp[1] = OSPF_LSA_INTRA_AREA_PREFIX; + attr_template.key.attr_cp[2] = OSPF_IA_PREFIX_LSA_PREFIX; lsdb_add_node_attr(node, &attr_template); +#if 0 if (!ctx->no_sr) { lsdb_reset_attr_template(&attr_template); lspgen_store_addr(addr, (uint8_t*)&attr_template.key.prefix.ipv6_prefix.address, IPV6_ADDR_LEN); @@ -773,6 +774,7 @@ lspgen_gen_ospf3_attr(struct lsdb_ctx_ *ctx) lsdb_add_node_attr(node, &attr_template); } addr += node->node_index; +#endif /* external prefixes */ ext_per_node = ctx->num_ext / ctx->num_nodes; @@ -800,7 +802,7 @@ lspgen_gen_ospf3_attr(struct lsdb_ctx_ *ctx) attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE; attr_template.key.attr_cp[1] = OSPF_LSA_OPAQUE_AREA_RI; attr_template.key.attr_cp[2] = OSPF_TLV_SID_LABEL_RANGE; - attr_template.key.ordinal = 1; + //attr_template.key.ordinal = 1; lsdb_add_node_attr(node, &attr_template); } @@ -853,6 +855,7 @@ lspgen_gen_ospf3_attr(struct lsdb_ctx_ *ctx) attr_template.key.link.metric = metric; lsdb_add_node_attr(node, &attr_template); +#if 0 /* Generate an IPv6 prefix for each link */ lsdb_reset_attr_template(&attr_template); lspgen_store_addr(addr, (uint8_t*)&attr_template.key.prefix.ipv6_prefix.address, IPV6_ADDR_LEN); @@ -860,9 +863,10 @@ lspgen_gen_ospf3_attr(struct lsdb_ctx_ *ctx) attr_template.key.prefix.metric = metric; attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE; - attr_template.key.attr_cp[1] = OSPF_LSA_ROUTER; - attr_template.key.attr_cp[2] = OSPF_ROUTER_LSA_LINK_STUB; + attr_template.key.attr_cp[1] = OSPF_LSA_INTRA_AREA_PREFIX; + attr_template.key.attr_cp[2] = OSPF_IA_PREFIX_LSA_PREFIX; lsdb_add_node_attr(node, &attr_template); +#endif } } while (dict_itor_next(itor)); diff --git a/code/lspgen/src/lspgen_ospf.h b/code/lspgen/src/lspgen_ospf.h index 8de381b0..46d1d809 100644 --- a/code/lspgen/src/lspgen_ospf.h +++ b/code/lspgen/src/lspgen_ospf.h @@ -15,8 +15,8 @@ #define OSPF_LSA_SUMMARY 3 #define OSPF_LSA_ASBR_SUMMARY 4 #define OSPF_LSA_EXTERNAL 5 - #define OSPF_LSA_OPAQUE_LINK 9 +#define OSPF_LSA_INTRA_AREA_PREFIX 39 /* OSPFv3 LSA Type 9*/ #define OSPF_LSA_OPAQUE_AREA_RI 104 #define OSPF_LSA_OPAQUE_AREA_EP 107 /* rfc 7684 */ #define OSPF_LSA_OPAQUE_DOMAIN 11 @@ -31,3 +31,6 @@ /* Opaque LSA Extended Prefix TLVs */ #define OSPF_TLV_EXTENDED_PREFIX_RANGE 2 + +/* Inter Area Prefix LSA */ +#define OSPF_IA_PREFIX_LSA_PREFIX 31 diff --git a/code/lspgen/src/lspgen_packet.c b/code/lspgen/src/lspgen_packet.c index 7d2215d0..bcf72ceb 100644 --- a/code/lspgen/src/lspgen_packet.c +++ b/code/lspgen/src/lspgen_packet.c @@ -1027,6 +1027,7 @@ lspgen_serialize_ospf3_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t case OSPF_LSA_EXTERNAL: case OSPF_LSA_OPAQUE_AREA_RI: case OSPF_LSA_OPAQUE_AREA_EP: + case OSPF_LSA_INTRA_AREA_PREFIX: inc_be_uint(buf0->data+40+16, 4); /* Update #LSAs */ write_be_uint(buf1->data+18, 2, buf1->idx); /* Update Packet length */ write_be_uint(buf1->data+16, 2, 0); /* reset checksum field */ @@ -1131,12 +1132,28 @@ lspgen_serialize_ospf3_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t push_pad4(buf1); break; + case OSPF_LSA_INTRA_AREA_PREFIX: + push_be_uint(buf1, 2, lspgen_get_ospf_age(node)); /* LS-age */ + push_be_uint(buf1, 2, 0x2009); /* LS-Type */ + push_data(buf1, (uint8_t*)&attr->key.prefix.ipv4_prefix.address, 4); /* Link State ID */ + router_id = read_be_uint(node->key.node_id, 4); + push_be_uint(buf1, 4, router_id); /* Advertising Router */ + push_be_uint(buf1, 4, node->sequence); /* Sequence */ + push_be_uint(buf1, 2, 0); /* Checksum - will be overwritten later */ + push_be_uint(buf1, 2, 0); /* Length - will be overwritten later */ + + push_be_uint(buf1, 2, 0); /* # Prefixes - will be overwritten later */ + push_be_uint(buf1, 2, 0x2001); /* # Referenced LS Type */ + + push_be_uint(buf1, 4, 0); /* Referenced Link State ID */ + push_be_uint(buf1, 4, router_id); /* Referenced Advertising Router */ + + break; + case OSPF_LSA_OPAQUE_AREA_RI: push_be_uint(buf1, 2, lspgen_get_ospf_age(node)); /* LS-age */ - push_be_uint(buf1, 1, 0); /* Options */ - push_be_uint(buf1, 1, 10); /* LS-Type */ - push_be_uint(buf1, 1, 4); /* Opaque Type: Router-Information */ - push_be_uint(buf1, 3, 0); /* Opaque subtype */ + push_be_uint(buf1, 2, 0x800c); /* LS-Type */ + push_be_uint(buf1, 4, 0); /* Link State ID (Instance ID) */ router_id = read_be_uint(node->key.node_id, 4); push_be_uint(buf1, 4, router_id); /* Advertising Router */ push_be_uint(buf1, 4, node->sequence); /* Sequence */ @@ -1184,6 +1201,17 @@ lspgen_serialize_ospf3_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t push_be_uint(buf2, 4, read_be_uint(attr->key.link.remote_node_id, 4)); /* Neighbor Router ID */ break; + case OSPF_IA_PREFIX_LSA_PREFIX: + push_be_uint(buf2, 1, attr->key.prefix.ipv6_prefix.len); /* Prefix Length */ + push_be_uint(buf2, 1, 0x00); /* Prefix Options */ + push_be_uint(buf2, 2, attr->key.prefix.metric); /* Metric */ + attr_len = (attr->key.prefix.ipv6_prefix.len+7)/8; + push_data(buf2, attr->key.prefix.ipv6_prefix.address, attr_len); /* Prefix */ + push_pad4(buf2); + + inc_be_uint(buf1->data+20, 2); /* Update #prefixes */ + break; + case OSPF_TLV_HOSTNAME: attr_len = strnlen(attr->key.hostname, sizeof(attr->key.hostname)); if (attr_len) { @@ -1206,7 +1234,7 @@ lspgen_serialize_ospf3_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t push_be_uint(buf2, 3, attr->key.cap.srgb_base); push_pad4(buf2); - //write_be_uint(buf2->data+2, 2, buf2->idx-4); /* Update length */ + write_be_uint(buf2->data+2, 2, buf2->idx-4); /* Update length */ push_pad4(buf2); } break; From 6d18e28605fa3c85764b36058826521d42473508 Mon Sep 17 00:00:00 2001 From: Hannes Gredler Date: Fri, 15 Sep 2023 17:01:04 +0000 Subject: [PATCH 10/12] copy the correct ospfv3 source address --- code/lspgen/src/lspgen_packet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/lspgen/src/lspgen_packet.c b/code/lspgen/src/lspgen_packet.c index bcf72ceb..c51236c6 100644 --- a/code/lspgen/src/lspgen_packet.c +++ b/code/lspgen/src/lspgen_packet.c @@ -1066,7 +1066,7 @@ lspgen_serialize_ospf3_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t push_be_uint(buf0, 2, 0); /* Payload length - will be overwritten later */ push_be_uint(buf0, 1, 89); /* Next Header */ push_be_uint(buf0, 1, 255); /* Hop limit */ - push_data(buf0, (uint8_t *)&ctx->ipv6_node_prefix, IPV6_ADDR_LEN); /* Source Address */ + push_data(buf0, (uint8_t *)&ctx->ipv6_node_prefix.address, IPV6_ADDR_LEN); /* Source Address */ push_be_uint(buf0, 8, 0xff02000000000000); /* Destination Address */ push_be_uint(buf0, 8, 5); /* Destination Address */ From c93c0284df9c3a5016fe1209feceb6fceef25119 Mon Sep 17 00:00:00 2001 From: Hannes Gredler Date: Wed, 20 Sep 2023 14:32:25 +0000 Subject: [PATCH 11/12] Fix external packing calculation for ospf3 --- code/lspgen/src/lspgen.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/code/lspgen/src/lspgen.c b/code/lspgen/src/lspgen.c index f367a1f4..121c5e6a 100644 --- a/code/lspgen/src/lspgen.c +++ b/code/lspgen/src/lspgen.c @@ -721,7 +721,7 @@ lspgen_gen_ospf3_attr(struct lsdb_ctx_ *ctx) struct lsdb_attr_ attr_template; dict_itor *itor; __uint128_t addr, inc, ext_addr6, ext_incr6, addr_offset; - uint32_t ext_per_node, metric; + uint32_t ext_per_node, metric, nodes_left, ext_left; /* * Walk the node DB. @@ -746,6 +746,9 @@ lspgen_gen_ospf3_attr(struct lsdb_ctx_ *ctx) ext_addr6 = lspgen_load_addr((uint8_t*)&ctx->ipv6_ext_prefix.address, IPV6_ADDR_LEN); ext_incr6 = lspgen_get_prefix_inc(AF_INET6, ctx->ipv6_ext_prefix.len); + nodes_left = ctx->num_nodes; + ext_left = ctx->num_ext; + do { node = *dict_itor_datum(itor); @@ -787,7 +790,8 @@ lspgen_gen_ospf3_attr(struct lsdb_ctx_ *ctx) #endif /* external prefixes */ - ext_per_node = ctx->num_ext / ctx->num_nodes; + ext_per_node = ext_left / nodes_left; + ext_left -= ext_per_node; while (ext_per_node--) { /* ipv6 external prefix */ lsdb_reset_attr_template(&attr_template); @@ -879,6 +883,7 @@ lspgen_gen_ospf3_attr(struct lsdb_ctx_ *ctx) #endif } + nodes_left--; } while (dict_itor_next(itor)); dict_itor_free(itor); From 6c62b2c5048bd38d9f1bbe0be60f565d03d9349c Mon Sep 17 00:00:00 2001 From: Hannes Gredler Date: Fri, 22 Sep 2023 08:54:47 +0000 Subject: [PATCH 12/12] Encode the Prefix-SID Index using an Extended Prefix and not an Extended Prefix Range --- code/lspgen/src/lspgen.c | 3 +- code/lspgen/src/lspgen_ospf.h | 4 ++ code/lspgen/src/lspgen_packet.c | 71 ++++++++++++++++++++++++++------- 3 files changed, 63 insertions(+), 15 deletions(-) diff --git a/code/lspgen/src/lspgen.c b/code/lspgen/src/lspgen.c index 121c5e6a..bd935460 100644 --- a/code/lspgen/src/lspgen.c +++ b/code/lspgen/src/lspgen.c @@ -606,7 +606,8 @@ lspgen_gen_ospf2_attr(struct lsdb_ctx_ *ctx) attr_template.key.ordinal = 1; attr_template.key.attr_cp[0] = OSPF_MSG_LSUPDATE; attr_template.key.attr_cp[1] = OSPF_LSA_OPAQUE_AREA_EP; - attr_template.key.attr_cp[2] = OSPF_TLV_EXTENDED_PREFIX_RANGE; + attr_template.key.attr_cp[2] = OSPF_TLV_EXTENDED_PREFIX; + attr_template.key.attr_cp[3] = OSPF_SUBTLV_EXTENDED_PREFIX_SID;; lsdb_add_node_attr(node, &attr_template); } addr += node->node_index; diff --git a/code/lspgen/src/lspgen_ospf.h b/code/lspgen/src/lspgen_ospf.h index 46d1d809..c5708ccb 100644 --- a/code/lspgen/src/lspgen_ospf.h +++ b/code/lspgen/src/lspgen_ospf.h @@ -30,7 +30,11 @@ #define OSPF_TLV_SID_LABEL_RANGE 9 /* Opaque LSA Extended Prefix TLVs */ +#define OSPF_TLV_EXTENDED_PREFIX 12 #define OSPF_TLV_EXTENDED_PREFIX_RANGE 2 +/* Extended Prefix & Extended Prefix range subTLVs */ +#define OSPF_SUBTLV_EXTENDED_PREFIX_SID 1 + /* Inter Area Prefix LSA */ #define OSPF_IA_PREFIX_LSA_PREFIX 31 diff --git a/code/lspgen/src/lspgen_packet.c b/code/lspgen/src/lspgen_packet.c index c51236c6..e1e16e9c 100644 --- a/code/lspgen/src/lspgen_packet.c +++ b/code/lspgen/src/lspgen_packet.c @@ -733,7 +733,7 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t { lsdb_ctx_t *ctx; lsdb_node_t *node; - io_buffer_t *buf0, *buf1, *buf2; + io_buffer_t *buf0, *buf1, *buf2, *buf3; uint16_t attr_len, checksum; uint32_t router_id, mask; @@ -743,11 +743,37 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t buf0 = &packet->buf[0]; buf1 = &packet->buf[1]; buf2 = &packet->buf[2]; + buf3 = &packet->buf[3]; LOG(PACKET, " %s\n", lspgen_format_serializer_state(state)); + /* close Level 3 */ + if (state & CLOSE_LEVEL3) { + switch (packet->prev_attr_cp[3]) { + case OSPF_SUBTLV_EXTENDED_PREFIX_SID: + write_be_uint(buf3->data+2, 2, buf3->idx-4); /* Update length */ + push_pad4(buf3); + break; + default: + break; + } + + lspgen_propagate_buffer_up(packet, 3); + } + /* close Level 2 */ if (state & CLOSE_LEVEL2) { + switch (packet->prev_attr_cp[2]) { + case OSPF_TLV_EXTENDED_PREFIX_RANGE: /* fall through */ + case OSPF_TLV_EXTENDED_PREFIX: + case OSPF_TLV_SID_LABEL_RANGE: + write_be_uint(buf2->data+2, 2, buf2->idx-4); /* Update length */ + push_pad4(buf2); + default: + break; + } + + lspgen_propagate_buffer_up(packet, 2); } @@ -956,13 +982,11 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t push_be_uint(buf2, 3, attr->key.cap.srgb_range); /* Range size */ push_be_uint(buf2, 1, 0); /* Reserved */ + /* XXX Move this to level 3 */ push_be_uint(buf2, 2, 1); /* SID Type Label */ push_be_uint(buf2, 2, 3); /* SID Type Length */ push_be_uint(buf2, 3, attr->key.cap.srgb_base); push_pad4(buf2); - - write_be_uint(buf2->data+2, 2, buf2->idx-4); /* Update length */ - push_pad4(buf2); } break; @@ -975,17 +999,16 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t push_be_uint(buf2, 1, 0); /* Flags */ push_be_uint(buf2, 3, 0); /* Reserved */ push_data(buf2, (uint8_t*)&attr->key.prefix.ipv4_prefix.address, 4); /* Prefix */ + break; - /* Prefix SID - XXX Move this to Level 4*/ - push_be_uint(buf2, 2, 2); /* Type */ - push_be_uint(buf2, 2, 8); /* Length */ - push_be_uint(buf2, 3, 0); /* Flags, Reserved, MT-ID */ - push_be_uint(buf2, 1, attr->key.prefix.sid_algo); /* Algorithm */ - push_be_uint(buf2, 4, attr->key.prefix.sid); /* SID Index */ - push_pad4(buf2); - - write_be_uint(buf2->data+2, 2, buf2->idx-4); /* Update length */ - push_pad4(buf2); + case OSPF_TLV_EXTENDED_PREFIX: + push_be_uint(buf2, 2, 1); /* Type */ + push_be_uint(buf2, 2, 0); /* Length - will be overwritten later */ + push_be_uint(buf2, 1, 1); /* Route Type: Intra Area */ + push_be_uint(buf2, 1, attr->key.prefix.ipv4_prefix.len); + push_be_uint(buf2, 1, 0); /* AF ipv4 */ + push_be_uint(buf2, 1, 0); /* Flags */ + push_data(buf2, (uint8_t*)&attr->key.prefix.ipv4_prefix.address, 4); /* Prefix */ break; default: @@ -995,6 +1018,26 @@ lspgen_serialize_ospf2_state(lsdb_attr_t *attr, lsdb_packet_t *packet, uint16_t lspgen_propagate_buffer_down(packet, 2); } + + /* open Level 3 */ + if (state & OPEN_LEVEL3) { + switch(attr->key.attr_cp[3]) { + case OSPF_SUBTLV_EXTENDED_PREFIX_SID: + push_be_uint(buf3, 2, 2); /* Type */ + push_be_uint(buf3, 2, 0); /* Length - will be overwritten later */ + push_be_uint(buf3, 3, 0); /* Flags, Reserved, MT-ID */ + push_be_uint(buf3, 1, attr->key.prefix.sid_algo); /* Algorithm */ + push_be_uint(buf3, 4, attr->key.prefix.sid); /* SID Index */ + break; + + default: + LOG(ERROR, "No Level 3 open packet serializer for attr %d\n", attr->key.attr_cp[3]); + return; + } + + lspgen_propagate_buffer_down(packet, 3); + } + } void