]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Apply PDU ordering from 8210bis-25#section-11.2 aspa
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Fri, 5 Jun 2026 00:14:56 +0000 (18:14 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Fri, 5 Jun 2026 00:14:56 +0000 (18:14 -0600)
src/rtr/db/db_table.c
src/rtr/pdu_handler.c
test/rtr/pdu_handler_test.c

index 5b51983a52573fb1ef1da369e33acb1459632d2f..1764cdef073383d63f217d6e6db44b474190d3eb 100644 (file)
@@ -266,18 +266,20 @@ cmp_vrp(struct hashable_roa *_a, struct hashable_roa *_b)
 
        cmp = cmp_u8(a->addr_fam, b->addr_fam);
        if (cmp) return cmp;
-       cmp = cmp_u32(a->asn, b->asn);
-       if (cmp) return cmp;
 
        switch (a->addr_fam) {
-       case AF_INET:  cmp = memcmp(&a->prefix.v4, &b->prefix.v4, 4);  break;
-       case AF_INET6: cmp = memcmp(&a->prefix.v6, &b->prefix.v6, 16); break;
+       case AF_INET:  cmp = memcmp(&b->prefix.v4, &a->prefix.v4, 4);  break;
+       case AF_INET6: cmp = memcmp(&b->prefix.v6, &a->prefix.v6, 16); break;
        }
        if (cmp) return cmp;
 
-       cmp = cmp_u8(a->prefix_length, b->prefix_length);
+       cmp = cmp_u8(b->max_prefix_length, a->max_prefix_length);
+       if (cmp) return cmp;
+
+       cmp = cmp_u8(b->prefix_length, a->prefix_length);
        if (cmp) return cmp;
-       return cmp_u8(a->max_prefix_length, b->max_prefix_length);
+
+       return cmp_u32(b->asn, a->asn);
 }
 
 static int
@@ -287,11 +289,11 @@ cmp_rk(struct hashable_key *_a, struct hashable_key *_b)
        struct router_key *b = &_b->data;
        int cmp;
 
-       cmp = cmp_u32(a->as, b->as);
-       if (cmp) return cmp;
        cmp = memcmp(a->ski, b->ski, RK_SKI_LEN);
        if (cmp) return cmp;
-       return memcmp(a->spk, b->spk, RK_SPKI_LEN);
+       cmp = memcmp(a->spk, b->spk, RK_SPKI_LEN);
+       if (cmp) return cmp;
+       return cmp_u32(a->as, b->as);
 }
 
 static int
index ad3ed4eb062840c5d1e0fdeae23877d6b91a474d..8646ee861359e8b1c56f49e764c20b8960fad9df 100644 (file)
@@ -312,8 +312,28 @@ internal_error:
        return err_pdu_send_internal_error(stream.fd, stream.ver);
 }
 
+struct withdrawal {
+       unsigned char raw[22];
+};
+
+struct withdrawal_array {
+       struct withdrawal *a; /* array */
+       size_t n; /* array length */
+       size_t c; /* array capacity */
+};
+
+static void
+add_withdrawal(struct withdrawal_array *wds, unsigned char const *chunk, size_t size)
+{
+       if (wds->n >= wds->c) {
+               wds->c <<= 1;
+               wds->a = prealloc(wds->a, wds->c * sizeof(struct withdrawal));
+       }
+       memcpy(wds->a[wds->n++].raw, chunk, size);
+}
+
 static int
-send_delta(struct rtr_stream *rs, serial_t oserial, serial_t nserial)
+send_pfx_delta(struct rtr_stream *rs, serial_t oserial, serial_t nserial)
 {
        FILE *ofile = NULL;
        FILE *nfile = NULL;
@@ -321,12 +341,18 @@ send_delta(struct rtr_stream *rs, serial_t oserial, serial_t nserial)
        unsigned char *buf2;
        unsigned char const *ochunk;
        unsigned char const *nchunk;
+       struct withdrawal_array wds;
+       ssize_t w;
        int cmp;
        int error;
 
        buf1 = pmalloc(rs->rawlen);
        buf2 = pmalloc(rs->rawlen);
 
+       wds.n = 0;
+       wds.c = 128;
+       wds.a = pmalloc(wds.c * sizeof(struct withdrawal));
+
        error = rtr_open_file(oserial, rs->type, "r", &ofile);
        if (error)
                goto end;
@@ -343,15 +369,13 @@ send_delta(struct rtr_stream *rs, serial_t oserial, serial_t nserial)
 
        while (ochunk && nchunk) {
                cmp = memcmp(ochunk, nchunk, rs->rawlen);
-               if (cmp < 0) {
-                       error = rs->send(rs, ochunk, FLAG_WITHDRAWAL);
-                       if (error)
-                               goto end;
+               if (cmp > 0) {
+                       add_withdrawal(&wds, ochunk, rs->rawlen);
                        ochunk = next_chunk(ofile, buf1, rs->rawlen, &error);
                        if (error)
                                goto end;
 
-               } else if (cmp > 0) {
+               } else if (cmp < 0) {
                        error = rs->send(rs, nchunk, FLAG_ANNOUNCEMENT);
                        if (error)
                                goto end;
@@ -369,33 +393,39 @@ send_delta(struct rtr_stream *rs, serial_t oserial, serial_t nserial)
                }
        }
 
-       while (ochunk) {
-               error = rs->send(rs, ochunk, FLAG_WITHDRAWAL);
+       while (nchunk) {
+               error = rs->send(rs, nchunk, FLAG_ANNOUNCEMENT);
                if (error)
                        goto end;
-               ochunk = next_chunk(ofile, buf1, rs->rawlen, &error);
+               nchunk = next_chunk(nfile, buf2, rs->rawlen, &error);
                if (error)
                        goto end;
        }
 
-       while (nchunk) {
-               error = rs->send(rs, nchunk, FLAG_ANNOUNCEMENT);
+       while (ochunk) {
+               add_withdrawal(&wds, ochunk, rs->rawlen);
+               ochunk = next_chunk(ofile, buf1, rs->rawlen, &error);
                if (error)
                        goto end;
-               nchunk = next_chunk(nfile, buf2, rs->rawlen, &error);
+       }
+
+       for (w = wds.n - 1; w >= 0; w--) {
+               error = rs->send(rs, wds.a[w].raw, FLAG_WITHDRAWAL);
                if (error)
                        goto end;
        }
 
 end:   if (nfile) fclose(nfile);
        if (ofile) fclose(ofile);
+       free(wds.a);
        free(buf2);
        free(buf1);
        return error;
 }
 
 static int
-send_aspa_delta(int fd, uint8_t ver, serial_t oserial, serial_t nserial)
+send_aspa_delta(int fd, uint8_t ver, serial_t oserial, serial_t nserial,
+    bool announce)
 {
        FILE *ofile = NULL;
        FILE *nfile = NULL;
@@ -426,14 +456,18 @@ send_aspa_delta(int fd, uint8_t ver, serial_t oserial, serial_t nserial)
        while (ochunk && nchunk) {
                cmp = memcmp(ochunk, nchunk, 4); /* AS only */
                if (cmp < 0) {
-                       error = send_aspa_withdraw(fd, ver, ochunk, ofile);
+                       error = announce
+                           ? skip_providers(ochunk, ofile)
+                           : send_aspa_withdraw(fd, ver, ochunk, ofile);
                        if (error)
                                goto end;
                        ochunk = next_chunk(ofile, buf1, 8, &error);
                        if (error)
                                goto end;
                } else if (cmp > 0) {
-                       error = send_aspa_announce(fd, ver, nchunk, nfile);
+                       error = announce
+                           ? send_aspa_announce(fd, ver, nchunk, nfile)
+                           : skip_providers(nchunk, nfile);
                        if (error)
                                goto end;
                        nchunk = next_chunk(nfile, buf2, 8, &error);
@@ -449,7 +483,7 @@ send_aspa_delta(int fd, uint8_t ver, serial_t oserial, serial_t nserial)
                                goto end;
                        }
 
-                       if (!providers_equal(&oprovs, &nprovs)) {
+                       if (announce && !providers_equal(&oprovs, &nprovs)) {
                                aspa.customer = read_u32(nchunk);
                                aspa.providers = nprovs;
                                error = send_aspa_announce_pdu(fd, ver, &aspa);
@@ -472,22 +506,24 @@ send_aspa_delta(int fd, uint8_t ver, serial_t oserial, serial_t nserial)
                }
        }
 
-       while (ochunk) {
-               error = send_aspa_withdraw(fd, ver, ochunk, ofile);
-               if (error)
-                       goto end;
-               ochunk = next_chunk(ofile, buf1, 8, &error);
-               if (error)
-                       goto end;
-       }
-
-       while (nchunk) {
-               error = send_aspa_announce(fd, ver, nchunk, nfile);
-               if (error)
-                       goto end;
-               nchunk = next_chunk(nfile, buf2, 8, &error);
-               if (error)
-                       goto end;
+       if (announce) {
+               while (nchunk) {
+                       error = send_aspa_announce(fd, ver, nchunk, nfile);
+                       if (error)
+                               goto end;
+                       nchunk = next_chunk(nfile, buf2, 8, &error);
+                       if (error)
+                               goto end;
+               }
+       } else {
+               while (ochunk) {
+                       error = send_aspa_withdraw(fd, ver, ochunk, ofile);
+                       if (error)
+                               goto end;
+                       ochunk = next_chunk(ofile, buf1, 8, &error);
+                       if (error)
+                               goto end;
+               }
        }
 
 end:   if (ofile) fclose(ofile);
@@ -540,17 +576,18 @@ handle_serial_query_pdu(struct rtr_request *request)
        stream.type = "vrp4";
        stream.rawlen = 10;
        stream.send = send_vrp4;
-       error = send_delta(&stream, oserial, nserial);
+       error = send_pfx_delta(&stream, oserial, nserial);
        if (error)
                goto internal_error;
 
        stream.type = "vrp6";
        stream.rawlen = 22;
        stream.send = send_vrp6;
-       error = send_delta(&stream, oserial, nserial);
+       error = send_pfx_delta(&stream, oserial, nserial);
        if (error)
                goto internal_error;
 
+       /*
        if (stream.ver >= RTR_V1) {
                stream.type = "rk";
                stream.rawlen = 4 + RK_SKI_LEN + RK_SPKI_LEN;
@@ -559,9 +596,15 @@ handle_serial_query_pdu(struct rtr_request *request)
                if (error)
                        goto internal_error;
        }
+       */
 
        if (stream.ver >= RTR_V2) {
-               error = send_aspa_delta(stream.fd, stream.ver, oserial, nserial);
+               error = send_aspa_delta(stream.fd, stream.ver, oserial, nserial,
+                   true);
+               if (error)
+                       goto internal_error;
+               error = send_aspa_delta(stream.fd, stream.ver, oserial, nserial,
+                   false);
                if (error)
                        goto internal_error;
        }
index 6d54a2404bb1fae8a16da780826bbf2421b8c218..73d46a7b658d606e474409e0af65a592f0f336db 100644 (file)
@@ -230,12 +230,12 @@ check_response(void)
 
        pr_op_debug("Expected:");
        for (i = 0; i < e; i++)
-               pr_op_debug("- %s %u %u", pdutype2str(expected[i].type),
-                   expected[i].as, expected[i].flags);
+               pr_op_debug("%s %s as:%u", expected[i].flags ? "+" : "-",
+                   pdutype2str(expected[i].type), expected[i].as);
        pr_op_debug("Actual:");
        for (i = 0; i < a; i++)
-               pr_op_debug("- %s %u %u", pdutype2str(actual[i].type),
-                   actual[i].as, actual[i].flags);
+               pr_op_debug("%s %s as:%u", expected[i].flags ? "+" : "-",
+                   pdutype2str(actual[i].type), actual[i].as);
 
        ck_assert_uint_eq(e, a);
        for (i = 0; i < e; i++) {
@@ -348,10 +348,10 @@ START_TEST(test_natural_flows)
 
        e = 0;
        expected_pdu_add(PDU_TYPE_CACHE_RESPONSE, 0, 0);
-       expected_pdu_add(PDU_TYPE_IPV4_PREFIX, 1, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_IPV4_PREFIX, 2, FLAG_ANNOUNCEMENT);
-       expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 1, FLAG_ANNOUNCEMENT);
+       expected_pdu_add(PDU_TYPE_IPV4_PREFIX, 1, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 2, FLAG_ANNOUNCEMENT);
+       expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 1, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_ROUTER_KEY, 1, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_ROUTER_KEY, 2, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_ASPA, 1, FLAG_ANNOUNCEMENT);
@@ -363,7 +363,7 @@ START_TEST(test_natural_flows)
        expected_pdu_add(PDU_TYPE_CACHE_RESPONSE, 0, 0);
        expected_pdu_add(PDU_TYPE_IPV4_PREFIX, 2, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 2, FLAG_ANNOUNCEMENT);
-       expected_pdu_add(PDU_TYPE_ROUTER_KEY, 2, FLAG_ANNOUNCEMENT);
+//     expected_pdu_add(PDU_TYPE_ROUTER_KEY, 2, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_ASPA, 2, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_END_OF_DATA, 0, 0);
        rcv_serial_query(session, 1);
@@ -387,14 +387,14 @@ START_TEST(test_natural_flows)
 
        e = 0;
        expected_pdu_add(PDU_TYPE_CACHE_RESPONSE, 0, 0);
-       expected_pdu_add(PDU_TYPE_IPV4_PREFIX, 1, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_IPV4_PREFIX, 2, FLAG_ANNOUNCEMENT);
-       expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 1, FLAG_WITHDRAWAL);
+       expected_pdu_add(PDU_TYPE_IPV4_PREFIX, 1, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 2, FLAG_ANNOUNCEMENT);
-       expected_pdu_add(PDU_TYPE_ROUTER_KEY, 1, FLAG_WITHDRAWAL);
-       expected_pdu_add(PDU_TYPE_ROUTER_KEY, 2, FLAG_ANNOUNCEMENT);
-       expected_pdu_add(PDU_TYPE_ASPA, 1, FLAG_WITHDRAWAL);
+       expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 1, FLAG_WITHDRAWAL);
+//     expected_pdu_add(PDU_TYPE_ROUTER_KEY, 2, FLAG_ANNOUNCEMENT);
+//     expected_pdu_add(PDU_TYPE_ROUTER_KEY, 1, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_ASPA, 2, FLAG_ANNOUNCEMENT);
+       expected_pdu_add(PDU_TYPE_ASPA, 1, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_END_OF_DATA, 0, 0);
        rcv_serial_query(session, 1);
 
@@ -402,7 +402,7 @@ START_TEST(test_natural_flows)
        expected_pdu_add(PDU_TYPE_CACHE_RESPONSE, 0, 0);
        expected_pdu_add(PDU_TYPE_IPV4_PREFIX, 1, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 1, FLAG_WITHDRAWAL);
-       expected_pdu_add(PDU_TYPE_ROUTER_KEY, 1, FLAG_WITHDRAWAL);
+//     expected_pdu_add(PDU_TYPE_ROUTER_KEY, 1, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_ASPA, 1, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_END_OF_DATA, 0, 0);
        rcv_serial_query(session, 2);
@@ -433,7 +433,7 @@ START_TEST(test_natural_flows)
        expected_pdu_add(PDU_TYPE_CACHE_RESPONSE, 0, 0);
        expected_pdu_add(PDU_TYPE_IPV4_PREFIX, 2, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 2, FLAG_WITHDRAWAL);
-       expected_pdu_add(PDU_TYPE_ROUTER_KEY, 2, FLAG_WITHDRAWAL);
+//     expected_pdu_add(PDU_TYPE_ROUTER_KEY, 2, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_ASPA, 2, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_END_OF_DATA, 0, 0);
        rcv_serial_query(session, 2);
@@ -444,8 +444,8 @@ START_TEST(test_natural_flows)
        expected_pdu_add(PDU_TYPE_IPV4_PREFIX, 2, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 1, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 2, FLAG_WITHDRAWAL);
-       expected_pdu_add(PDU_TYPE_ROUTER_KEY, 1, FLAG_ANNOUNCEMENT);
-       expected_pdu_add(PDU_TYPE_ROUTER_KEY, 2, FLAG_WITHDRAWAL);
+//     expected_pdu_add(PDU_TYPE_ROUTER_KEY, 1, FLAG_ANNOUNCEMENT);
+//     expected_pdu_add(PDU_TYPE_ROUTER_KEY, 2, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_ASPA, 1, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_ASPA, 2, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_END_OF_DATA, 0, 0);
@@ -496,10 +496,10 @@ START_TEST(test_delta_forget)
 
        e = 0;
        expected_pdu_add(PDU_TYPE_CACHE_RESPONSE, 0, 0);
-       expected_pdu_add(PDU_TYPE_IPV4_PREFIX, 1, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_IPV4_PREFIX, 2, FLAG_ANNOUNCEMENT);
-       expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 1, FLAG_ANNOUNCEMENT);
+       expected_pdu_add(PDU_TYPE_IPV4_PREFIX, 1, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 2, FLAG_ANNOUNCEMENT);
+       expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 1, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_ROUTER_KEY, 1, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_ROUTER_KEY, 2, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_ASPA, 1, FLAG_ANNOUNCEMENT);
@@ -511,7 +511,7 @@ START_TEST(test_delta_forget)
        expected_pdu_add(PDU_TYPE_CACHE_RESPONSE, 0, 0);
        expected_pdu_add(PDU_TYPE_IPV4_PREFIX, 2, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 2, FLAG_ANNOUNCEMENT);
-       expected_pdu_add(PDU_TYPE_ROUTER_KEY, 2, FLAG_ANNOUNCEMENT);
+//     expected_pdu_add(PDU_TYPE_ROUTER_KEY, 2, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_ASPA, 2, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_END_OF_DATA, 0, 0);
        rcv_serial_query(session, 1);
@@ -541,7 +541,7 @@ START_TEST(test_delta_forget)
        expected_pdu_add(PDU_TYPE_CACHE_RESPONSE, 0, 0);
        expected_pdu_add(PDU_TYPE_IPV4_PREFIX, 1, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 1, FLAG_WITHDRAWAL);
-       expected_pdu_add(PDU_TYPE_ROUTER_KEY, 1, FLAG_WITHDRAWAL);
+//     expected_pdu_add(PDU_TYPE_ROUTER_KEY, 1, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_ASPA, 1, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_END_OF_DATA, 0, 0);
        rcv_serial_query(session, 2);
@@ -577,8 +577,8 @@ START_TEST(test_delta_forget)
        expected_pdu_add(PDU_TYPE_IPV4_PREFIX, 2, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 1, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_IPV6_PREFIX, 2, FLAG_WITHDRAWAL);
-       expected_pdu_add(PDU_TYPE_ROUTER_KEY, 1, FLAG_ANNOUNCEMENT);
-       expected_pdu_add(PDU_TYPE_ROUTER_KEY, 2, FLAG_WITHDRAWAL);
+//     expected_pdu_add(PDU_TYPE_ROUTER_KEY, 1, FLAG_ANNOUNCEMENT);
+//     expected_pdu_add(PDU_TYPE_ROUTER_KEY, 2, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_ASPA, 1, FLAG_ANNOUNCEMENT);
        expected_pdu_add(PDU_TYPE_ASPA, 2, FLAG_WITHDRAWAL);
        expected_pdu_add(PDU_TYPE_END_OF_DATA, 0, 0);