## RTR Configuration
-> TODO Move this
+> TODO Update this
The RTR server reads the configuration from a JSON file, learn about it at FORT's site [RTR Server arguments](https://nicmx.github.io/FORT-validator/doc/rtr-server.html).
## Execution
+> TODO Update this
+
The executable needs only one argument: the location of the configuration file. So, assuming that the configuration file is located at `/home/fort/rtr.conf`, use the flag `-f` to indicate such location and run the server:
```
make
sudo make install
{% endhighlight %}
+
+## OpenBSD
+
+{% highlight bash %}
+# pkg_add libexecinfo jansson rsync
+$
+$ ftp <libcmscodec tar url>
+$ tar xvzf libcmscodec-<version>.tar.gz
+$ cd libcmscodec
+$ ./configure
+$ make
+# make install
+$ cd ..
+$ ftp <fort tar url>
+$ tar xvzf fort-<version>.tar.gz
+$ cd fort
+$ # clang is needed because of gnu11.
+$ env CC=clang CFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/lib ./configure
+$ make
+# make install
+{% endhighlight %}
#include <string.h>
#include <errno.h>
#include <arpa/inet.h> /* inet_ntop */
+#include <sys/types.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
+#include <sys/socket.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
#include "log.h"
#include "thread_var.h"
+static void
+init_quadrant(struct in6_addr *addr, unsigned int slot, uint32_t value)
+{
+ addr->s6_addr[slot ] = (value >> 24) ;
+ addr->s6_addr[slot + 1] = (value >> 16) & 0xFF;
+ addr->s6_addr[slot + 2] = (value >> 8) & 0xFF;
+ addr->s6_addr[slot + 3] = (value ) & 0xFF;
+}
+
+void
+in6_addr_init(struct in6_addr *addr, uint32_t quadrant0, uint32_t quadrant1,
+ uint32_t quadrant2, uint32_t quadrant3)
+{
+ init_quadrant(addr, 0, quadrant0);
+ init_quadrant(addr, 4, quadrant1);
+ init_quadrant(addr, 8, quadrant2);
+ init_quadrant(addr, 12, quadrant3);
+}
+
/*
* Returns a mask you can use to extract the suffix bits of a 32-bit unsigned
* number whose prefix lengths @prefix_len.
{
struct in6_addr suffix;
char buffer[INET6_ADDRSTRLEN];
+ unsigned int i;
memset(&suffix, 0, sizeof(suffix));
ipv6_suffix_mask(prefix->len, &suffix);
- if ((prefix->addr.s6_addr32[0] & suffix.s6_addr32[0])
- || (prefix->addr.s6_addr32[1] & suffix.s6_addr32[1])
- || (prefix->addr.s6_addr32[2] & suffix.s6_addr32[2])
- || (prefix->addr.s6_addr32[3] & suffix.s6_addr32[3]))
- return pr_err("IPv6 prefix %s/%u has enabled suffix bits.",
- addr2str6(&prefix->addr, buffer), prefix->len);
+
+ for (i = 0; i < 16; i++)
+ if (prefix->addr.s6_addr[i] & suffix.s6_addr[i])
+ return pr_err("IPv6 prefix %s/%u has enabled suffix bits.",
+ addr2str6(&prefix->addr, buffer), prefix->len);
return 0;
}
struct in6_addr max;
};
+void in6_addr_init(struct in6_addr *, uint32_t, uint32_t, uint32_t, uint32_t);
+
uint32_t u32_suffix_mask(unsigned int);
uint32_t be32_suffix_mask(unsigned int);
void ipv6_suffix_mask(unsigned int, struct in6_addr *);
#include <stdint.h> /* SIZE_MAX */
#include <libcmscodec/SubjectPublicKeyInfo.h>
#include <libcmscodec/IPAddrBlocks.h>
+#include <sys/socket.h>
#include "algorithm.h"
#include "config.h"
#include "crypto/hash.h"
#include "object/name.h"
#include "rsync/rsync.h"
-#include <sys/socket.h>
/* Just to prevent some line breaking. */
#define GN_URI uniformResourceIdentifier
}
static int
-spki_validate_algorithm(OBJECT_IDENTIFIER_t *tal_alg,
- X509_PUBKEY *cert_public_key)
+spki_cmp(X509_PUBKEY *tal_spki, X509_PUBKEY *cert_spki)
{
+ ASN1_OBJECT *tal_alg;
ASN1_OBJECT *cert_alg;
- int ok;
- ok = X509_PUBKEY_get0_param(&cert_alg, NULL, NULL, NULL,
- cert_public_key);
- if (!ok)
- return crypto_err("X509_PUBKEY_get0_param() returned %d", ok);
-
- if (tal_alg->size != OBJ_length(cert_alg))
- goto fail;
- if (memcmp(tal_alg->buf, OBJ_get0_data(cert_alg), tal_alg->size) != 0)
- goto fail;
+ unsigned char const *tal_spk, *cert_spk;
+ int tal_spk_len, cert_spk_len;
- return 0;
-
-fail:
- return pr_err("TAL's public key algorithm is different than the root certificate's public key algorithm.");
-}
-
-static int
-spki_validate_key(BIT_STRING_t *tal_key, X509_PUBKEY *cert_public_key)
-{
- unsigned char const *cert_spk;
- int cert_spk_len;
int ok;
- ok = X509_PUBKEY_get0_param(NULL, &cert_spk, &cert_spk_len, NULL,
- cert_public_key);
+ ok = X509_PUBKEY_get0_param(&tal_alg, &tal_spk, &tal_spk_len, NULL,
+ tal_spki);
if (!ok)
- return crypto_err("X509_PUBKEY_get0_param() returned %d", ok);
+ return crypto_err("X509_PUBKEY_get0_param() 1 returned %d", ok);
+ ok = X509_PUBKEY_get0_param(&cert_alg, &cert_spk, &cert_spk_len, NULL,
+ cert_spki);
+ if (!ok)
+ return crypto_err("X509_PUBKEY_get0_param() 2 returned %d", ok);
- if (tal_key->size != cert_spk_len)
- goto fail;
- if (memcmp(tal_key->buf, cert_spk, cert_spk_len) != 0)
- goto fail;
+ if (OBJ_cmp(tal_alg, cert_alg) != 0)
+ goto different_alg;
+ if (tal_spk_len != cert_spk_len)
+ goto different_pk;
+ if (memcmp(tal_spk, cert_spk, cert_spk_len) != 0)
+ goto different_pk;
return 0;
-fail:
+different_alg:
+ return pr_err("TAL's public key algorithm is different than the root certificate's public key algorithm.");
+different_pk:
return pr_err("TAL's public key is different than the root certificate's public key.");
}
static int
-validate_spki(X509_PUBKEY *cert_public_key)
+validate_spki(X509_PUBKEY *cert_spki)
{
struct validation *state;
struct tal *tal;
- int error;
- struct SubjectPublicKeyInfo *tal_spki;
+ X509_PUBKEY *tal_spki;
unsigned char const *_tal_spki;
size_t _tal_spki_len;
* Luckily, the only other component of the SPKI is the algorithm
* identifier. So doing a field-by-field comparison is not too much
* trouble. We'll have to decode the TAL's SPKI though.
+ *
+ * Reminder: "X509_PUBKEY" and "Subject Public Key Info" are synonyms.
*/
fnstack_push(tal_get_file_name(tal));
tal_get_spki(tal, &_tal_spki, &_tal_spki_len);
- error = asn1_decode(_tal_spki, _tal_spki_len,
- &asn_DEF_SubjectPublicKeyInfo, (void **) &tal_spki);
+ tal_spki = d2i_X509_PUBKEY(NULL, &_tal_spki, _tal_spki_len);
fnstack_pop();
- if (error)
+ if (tal_spki == NULL) {
+ crypto_err("The TAL's public key cannot be decoded");
goto fail1;
+ }
- error = spki_validate_algorithm(&tal_spki->algorithm.algorithm,
- cert_public_key);
- if (error)
- goto fail2;
- error = spki_validate_key(&tal_spki->subjectPublicKey, cert_public_key);
- if (error)
+ if (spki_cmp(tal_spki, cert_spki) != 0)
goto fail2;
- ASN_STRUCT_FREE(asn_DEF_SubjectPublicKeyInfo, tal_spki);
+ X509_PUBKEY_free(tal_spki);
validation_pubkey_valid(state);
return 0;
fail2:
- ASN_STRUCT_FREE(asn_DEF_SubjectPublicKeyInfo, tal_spki);
+ X509_PUBKEY_free(tal_spki);
fail1:
validation_pubkey_invalid(state);
- return error;
+ return -EINVAL;
}
static int
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
+#include <signal.h> /* SIGINT, SIGQUIT, etc */
#include <sys/cdefs.h>
#include <sys/queue.h>
#include <sys/stat.h>
#include "rtr/db/delta.h"
#include <stdatomic.h>
+#include <sys/types.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
+#include <sys/socket.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
#include "data_structure/array_list.h"
struct delta_v4 {
#include "rtr/db/roa_table.h"
+#include <sys/types.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
+#include <sys/socket.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
#include "data_structure/uthash_nonfatal.h"
struct hashable_roa {
#ifndef RTR_PDU_H_
#define RTR_PDU_H_
+#include <sys/socket.h>
#include <netinet/in.h>
#include "common.h"
&& ((left->addr_fam == AF_INET
&& left->prefix.v4.s_addr == right->prefix.v4.s_addr)
|| (left->addr_fam == AF_INET6
- && IN6_ARE_ADDR_EQUAL(left->prefix.v6.s6_addr32,
- right->prefix.v6.s6_addr32)));
+ && IN6_ARE_ADDR_EQUAL(&left->prefix.v6, &right->prefix.v6)));
}
static int
int
read_in6_addr(struct pdu_reader *reader, struct in6_addr *result)
{
- return read_int32(reader, &result->s6_addr32[0])
- || read_int32(reader, &result->s6_addr32[1])
- || read_int32(reader, &result->s6_addr32[2])
- || read_int32(reader, &result->s6_addr32[3]);
+ unsigned int i;
+ int error;
+
+ for (i = 0; i < 16; i++) {
+ error = read_int8(reader, &result->s6_addr[i]);
+ if (error)
+ return error;
+ }
+
+ return 0;
}
#define EINVALID_UTF8 -0xFFFF
#define RTR_PRIMITIVE_READER_H_
#include <stdbool.h>
-#include <netinet/ip.h>
+#include <netinet/in.h> /* in_addr, in6_addr */
#include "common.h"
*/
/*
- * TODO this `if` is a Linux quirk and should probably not exist in the
- * BSDs. See `man 2 accept`.
+ * TODO (whatever) print error messages?
+ * "Connection acceptor thread interrupted" sounds pretty unhelpful.
+ */
+
+#if __linux__
+ /*
+ * man 2 accept (on Linux):
+ * Linux accept() (...) passes already-pending network errors on the
+ * new socket as an error code from accept(). This behavior differs from
+ * other BSD socket implementations. For reliable operation the
+ * application should detect the network errors defined for the protocol
+ * after accept() and treat them like EAGAIN by retrying. In the case of
+ * TCP/IP, these are (...)
*/
if (err == ENETDOWN || err == EPROTO || err == ENOPROTOOPT
|| err == EHOSTDOWN || err == ENONET || err == EHOSTUNREACH
|| err == EOPNOTSUPP || err == ENETUNREACH)
return VERDICT_RETRY;
+#endif
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wlogical-op"
#include "slurm_db.h"
#include <string.h>
+#include <sys/types.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
+#include <sys/socket.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
#include "data_structure/array_list.h"
return ((filter_vrp->addr_fam == AF_INET &&
filter_vrp->prefix.v4.s_addr == prefix_vrp->prefix.v4.s_addr) ||
(filter_vrp->addr_fam == AF_INET6 &&
- IN6_ARE_ADDR_EQUAL(filter_vrp->prefix.v6.s6_addr32,
- prefix_vrp->prefix.v6.s6_addr32)));
+ IN6_ARE_ADDR_EQUAL(&filter_vrp->prefix.v6, &prefix_vrp->prefix.v6)));
return false;
}
&& ((left_vrp->addr_fam == AF_INET
&& left_vrp->prefix.v4.s_addr == right_vrp->prefix.v4.s_addr)
|| (left_vrp->addr_fam == AF_INET6
- && IN6_ARE_ADDR_EQUAL(left_vrp->prefix.v6.s6_addr32,
- right_vrp->prefix.v6.s6_addr32)));
+ && IN6_ARE_ADDR_EQUAL(&left_vrp->prefix.v6, &right_vrp->prefix.v6)));
if ((left->data_flag & SLURM_PFX_FLAG_MAX_LENGTH) > 0)
equal = equal &&
#include <stdlib.h>
#include <stdbool.h>
+#include <sys/types.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
+#include <sys/socket.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
#include "log.h"
#include "config.h"
#include <stdint.h>
#include <string.h>
#include <openssl/evp.h>
+#include <sys/types.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
+#include <sys/socket.h> /* AF_INET, AF_INET6 (needed in OpenBSD) */
#include "crypto/base64.h"
#include "log.h"
pdu_handler_test_LDADD = ${MY_LDADD} ${JANSSON_LIBS}
roa_table_test_SOURCES = ${BASIC_MODULES}
+roa_table_test_SOURCES += ../src/address.c
roa_table_test_SOURCES += ../src/rtr/db/delta.c
roa_table_test_SOURCES += ../src/rtr/db/roa_table.c
roa_table_test_SOURCES += rtr/db/roa_table_test.c
add_v6(struct validation_handler *handler, uint32_t as)
{
struct ipv6_prefix prefix;
- prefix.addr.s6_addr32[0] = htonl(0x20010DB8);
- prefix.addr.s6_addr32[1] = 0;
- prefix.addr.s6_addr32[2] = 0;
- prefix.addr.s6_addr32[3] = 0;
+ in6_addr_init(&prefix.addr, 0x20010DB8u, 0, 0, 0);
prefix.len = 96;
ck_assert_int_eq(0, handler->handle_roa_v6(as, &prefix, 120,
handler->arg));
vrp_equals_v6(struct vrp const *vrp, uint8_t as, uint32_t addr,
uint8_t prefix_len, uint8_t max_prefix_len)
{
+ struct in6_addr tmp;
+ in6_addr_init(&tmp, 0x20010DB8u, 0, 0, addr);
+
return (AF_INET6 == vrp->addr_fam)
&& (as == vrp->asn)
- && (htonl(0x20010DB8) == vrp->prefix.v6.s6_addr32[0])
- && (0 == vrp->prefix.v6.s6_addr32[1])
- && (0 == vrp->prefix.v6.s6_addr32[2])
- && (htonl(addr) == vrp->prefix.v6.s6_addr32[3])
+ && IN6_ARE_ADDR_EQUAL(&tmp, &vrp->prefix.v6)
&& (prefix_len == vrp->prefix_length)
&& (max_prefix_len == vrp->max_prefix_length);
}
prefix4.addr.s_addr = ADDR1;
prefix4.len = 24;
- prefix6.addr.s6_addr32[0] = htonl(0x20010DB8);
- prefix6.addr.s6_addr32[1] = 0;
- prefix6.addr.s6_addr32[2] = 0;
- prefix6.addr.s6_addr32[3] = htonl(0x00000001);
+ in6_addr_init(&prefix6.addr, 0x20010DB8u, 0, 0, 1);
prefix6.len = 120;
/* Duplicates should be transparently not re-added. */
ck_assert_int_eq(0, rtrhandler_handle_roa_v6(table, 11, &prefix6, 128));
ck_assert_int_eq(0, rtrhandler_handle_roa_v6(table, 11, &prefix6, 128));
- prefix6.addr.s6_addr32[3] = htonl(0x00000002);
+ in6_addr_init(&prefix6.addr, 0x20010DB8u, 0, 0, 2);
ck_assert_int_eq(0, rtrhandler_handle_roa_v6(table, 10, &prefix6, 128));
ck_assert_int_eq(0, rtrhandler_handle_roa_v6(table, 10, &prefix6, 128));
- prefix6.addr.s6_addr32[3] = htonl(0x00000001);
+ in6_addr_init(&prefix6.addr, 0x20010DB8u, 0, 0, 1);
prefix6.len = 121;
ck_assert_int_eq(0, rtrhandler_handle_roa_v6(table, 10, &prefix6, 128));
ck_assert_int_eq(0, rtrhandler_handle_roa_v6(table, 10, &prefix6, 128));
prefix4.addr.s_addr = ADDR1;
prefix4.len = 24;
- prefix6.addr.s6_addr32[0] = htonl(0x20010DB8);
- prefix6.addr.s6_addr32[1] = 0;
- prefix6.addr.s6_addr32[2] = 0;
- prefix6.addr.s6_addr32[3] = htonl(0x00000001);
+ in6_addr_init(&prefix6.addr, 0x20010DB8u, 0, 0, 1);
prefix6.len = 120;
left_count = 0;
ck_assert_int_eq(0, rtrhandler_handle_roa_v6(left, 11, &prefix6, 128));
left_count++;
- prefix6.addr.s6_addr32[3] = htonl(0x00000002);
+ in6_addr_init(&prefix6.addr, 0x20010DB8u, 0, 0, 2);
ck_assert_int_eq(0, rtrhandler_handle_roa_v6(right, 10, &prefix6, 128));
right_count++;
- prefix6.addr.s6_addr32[3] = htonl(0x00000001);
+ in6_addr_init(&prefix6.addr, 0x20010DB8u, 0, 0, 1);
prefix6.len = 121;
ck_assert_int_eq(0, rtrhandler_handle_roa_v6(left, 10, &prefix6, 128));
left_count++;
static array_index
get_vrp_index(struct vrp const *vrp)
{
+ struct in6_addr tmp;
array_index family_bit;
switch (vrp->addr_fam) {
break;
case AF_INET6:
- ck_assert_uint_eq(htonl(0x20010DB8), vrp->prefix.v6.s6_addr32[0]);
- ck_assert_uint_eq(0, vrp->prefix.v6.s6_addr32[1]);
- ck_assert_uint_eq(0, vrp->prefix.v6.s6_addr32[2]);
- ck_assert_uint_eq(0, vrp->prefix.v6.s6_addr32[3]);
+ in6_addr_init(&tmp, 0x20010DB8u, 0, 0, 0);
+ ck_assert(IN6_ARE_ADDR_EQUAL(&tmp, &vrp->prefix.v6));
ck_assert_uint_eq(96, vrp->prefix_length);
ck_assert_uint_eq(120, vrp->max_prefix_length);
family_bit = 1;
44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
58, 59, 60 };
struct ipv6_prefix_pdu pdu;
+ struct in6_addr tmp;
BUFFER2FD(input, ipv6_prefix_from_stream, &pdu);
ck_assert_uint_eq(pdu.flags, 33);
ck_assert_uint_eq(pdu.prefix_length, 34);
ck_assert_uint_eq(pdu.max_length, 35);
ck_assert_uint_eq(pdu.zero, 36);
- ck_assert_uint_eq(pdu.ipv6_prefix.s6_addr32[0], 0x25262728);
- ck_assert_uint_eq(pdu.ipv6_prefix.s6_addr32[1], 0x292a2b2c);
- ck_assert_uint_eq(pdu.ipv6_prefix.s6_addr32[2], 0x2d2e2f30);
- ck_assert_uint_eq(pdu.ipv6_prefix.s6_addr32[3], 0x31323334);
+ in6_addr_init(&tmp, 0x25262728, 0x292a2b2c, 0x2d2e2f30, 0x31323334);
+ ck_assert(IN6_ARE_ADDR_EQUAL(&tmp, &pdu.ipv6_prefix));
ck_assert_uint_eq(pdu.asn, 0x35363738);
}
END_TEST