Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 111 additions & 11 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,13 @@
#define FIELD_BYTE_RATE "byte_rate"
#define FIELD_BYTE_BURST "byte_burst"

#define FIELD_PORT "port"
#define FIELD_IP "ip"
#define FIELD_IPV6 "ipv6"
#define FIELD_IP_PUBLIC "ip_public"
#define FIELD_IP_PRIVATE "ip_private"
#define FIELD_ETHER "ether"
#define FIELD_PORT "port"
#define FIELD_IP "ip"
#define FIELD_IPV6 "ipv6"
#define FIELD_IP_PREFIXES "ip_prefixes"
#define FIELD_IP_PUBLIC "ip_public"
#define FIELD_IP_PRIVATE "ip_private"
#define FIELD_ETHER "ether"

#define FIELD_AUTH_PEERS "auth_peers"
#define FIELD_BEST_EFFORT "best_effort"
Expand Down Expand Up @@ -90,7 +91,7 @@ peer_init(struct lf_config_peer *config_peer)
{
*config_peer = (struct lf_config_peer){
.drkey_protocol = rte_cpu_to_be_16(LF_DRKEY_PROTOCOL),
.ip = 0,
.ip_prefixes = NULL,
.isd_as = 1,
.next = NULL,

Expand Down Expand Up @@ -300,6 +301,105 @@ parse_shared_secret_list(json_value *json_val,
return length;
}

static int
parse_ipv4_prefix(json_value *json_val,
struct lf_config_peer_ipv4_prefix *ip_prefix)
{
return lf_json_parse_ipv4_prefix(json_val, &ip_prefix->ip,
&ip_prefix->length);
}

static int
parse_peer_ipv4_prefixes(json_value *json_val, struct lf_config_peer *peer)
{
int res;
unsigned int length;
unsigned int i;
json_value *prefix_json_val;
struct lf_config_peer_ipv4_prefix *prefix;
struct lf_config_peer_ipv4_prefix *previous_prefix = NULL;
struct lf_config_peer_ipv4_prefix *next_prefix = NULL;

if (json_val == NULL) {
return -1;
}

if (json_val->type != json_array) {
return -1;
}

length = json_val->u.array.length;
if (length > LF_CONFIG_PEERS_PREFIX_MAX) {
LF_LOG(ERR, "Exceed peer's IP prefix limit (%d:%d)\n", json_val->line,
json_val->col);
return -1;
}

assert(peer->ip_prefixes == NULL);

res = 0;
for (i = 0; i < length; ++i) {
prefix_json_val = json_val->u.array.values[i];

prefix = malloc(sizeof(struct lf_config_peer_ipv4_prefix));
if (prefix == NULL) {
LF_LOG(ERR, "Failed to allocate memory for prefix (%d:%d)\n",
json_val->line, json_val->col);
res = -1;
break;
}

res = parse_ipv4_prefix(prefix_json_val, prefix);
if (res != 0) {
free(prefix);
LF_LOG(ERR, "Failed to parse IP prefix %d", i);
break;
}

/*
* Extend peer list with new peer.
*/
if (previous_prefix != NULL) {
previous_prefix->next = prefix;
} else {
peer->ip_prefixes = prefix;
}
previous_prefix = prefix;
}

if (res != 0) {
/* Something went wrong. Remove all parsed ip_prefixes. */
prefix = peer->ip_prefixes;
while (prefix != NULL) {
next_prefix = prefix->next;
free(prefix);
prefix = next_prefix;
}
return -1;
}

return 0;
}

struct lf_config_peer *
new_peer()
{
return calloc(1, sizeof(struct lf_config_peer));
}

void
free_peer(struct lf_config_peer *peer)
{
struct lf_config_peer_ipv4_prefix *prefix = peer->ip_prefixes;
struct lf_config_peer_ipv4_prefix *next_prefix;
while (prefix != NULL) {
next_prefix = prefix->next;
free(prefix);
prefix = next_prefix;
}
free(peer);
}

static int
parse_peer(json_value *json_val, struct lf_config_peer *peer)
{
Expand Down Expand Up @@ -340,10 +440,10 @@ parse_peer(json_value *json_val, struct lf_config_peer *peer)
}
/* set to network byte order */
peer->drkey_protocol = rte_cpu_to_be_16(peer->drkey_protocol);
} else if (strcmp(field_name, FIELD_IP) == 0) {
res = lf_json_parse_ipv4(field_value, &peer->ip);
} else if (strcmp(field_name, FIELD_IP_PREFIXES) == 0) {
res = parse_peer_ipv4_prefixes(field_value, peer);
if (res != 0) {
LF_LOG(ERR, "Invalid IP address (%d:%d)\n", field_value->line,
LF_LOG(ERR, "Invalid IP prefix (%d:%d)\n", field_value->line,
field_value->col);
error_count++;
}
Expand Down Expand Up @@ -1057,7 +1157,7 @@ lf_config_free(struct lf_config *config)
current_peer = config->peers;
while (current_peer != NULL) {
next_peer = current_peer->next;
free(current_peer);
free_peer(current_peer);
current_peer = next_peer;
}

Expand Down
14 changes: 11 additions & 3 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
* configuration file, default values are set.
*/

#define LF_CONFIG_PEERS_MAX 1000000 /* 1'000'000 */
#define LF_CONFIG_PEERS_MAX 1000000 /* 1'000'000 */
#define LF_CONFIG_PEERS_PREFIX_MAX 1000

/*
* Maximum number of SV that can be configured per peer
Expand All @@ -40,6 +41,13 @@ struct lf_config_shared_secret {
uint64_t not_before;
};

struct lf_config_peer_ipv4_prefix {
uint32_t ip; /* in host byte order with the least significant bits beyond
the length set to 0 */
uint8_t length;
struct lf_config_peer_ipv4_prefix *next;
};

struct lf_config_peer {
/* peer identifier */
uint64_t isd_as; /* in network byte order */
Expand All @@ -53,8 +61,8 @@ struct lf_config_peer {
bool shared_secrets_configured_option; /* if shared secrets are defined*/
struct lf_config_shared_secret shared_secrets[LF_CONFIG_SV_MAX];

/* LF-IP: ip -> isd_as map (TODO: move this to a separate map) */
uint32_t ip; /* in network byte order */
/* LF-IP: ip -> isd_as map */
struct lf_config_peer_ipv4_prefix *ip_prefixes;

/*
* Pointer to the next peer (for the linked list represenation).
Expand Down
9 changes: 7 additions & 2 deletions src/configmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,18 @@ lf_configmanager_worker_get_peer_from_ip(
const struct lf_configmanager_worker *config_ctx, uint32_t ip)
{
struct lf_config_peer *peer;
struct lf_config_peer_ipv4_prefix *prefix;
struct lf_config *config =
atomic_load_explicit(&config_ctx->config, memory_order_relaxed);

peer = config->peers;
while (peer != NULL) {
if (peer->ip == ip) {
return peer;
prefix = peer->ip_prefixes;
while (prefix != NULL) {
uint32_t mask = ~(1 << (32 - prefix->length)) - 1;
if (prefix->ip == (rte_be_to_cpu_32(ip) & mask)) {
return peer;
}
}
peer = peer->next;
}
Expand Down
43 changes: 43 additions & 0 deletions src/lib/json-parser/lf_json_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,49 @@ lf_json_parse_ipv6(const json_value *json_val, uint8_t val[16])
return 0;
}

static inline int
lf_json_parse_ipv4_prefix(const json_value *json_val, uint32_t *ip,
uint8_t *length)
{
char *ip_string, *length_string;
char *saveptr;
uint64_t parsed_length;
if (json_val->type != json_string) {
return -1;
}
assert(sizeof *ip == sizeof(struct in_addr));

ip_string = strtok_r(json_val->u.string.ptr, "/", &saveptr);
if (ip_string == NULL) {
return -1;
}
length_string = strtok_r(NULL, "/", &saveptr);
if (length_string == NULL) {
return -1;
}
if (strtok_r(NULL, "/", &saveptr) != NULL) {
return -1;
}

if (inet_pton(AF_INET, ip_string, ip) != 1) {
return -1;
}
*ip = ntohl(*ip);
if (lf_parse_unum(length_string, &parsed_length)) {
return -1;
}
if (parsed_length > 32) {
return -1;
}
*length = (uint8_t)parsed_length;

/* set least significant bits beyong the length to 0 */
uint32_t mask = ~(1 << (32 - *length)) - 1;
*ip &= mask;

return 0;
}

/**
* Parse UDP/TCP port number.
* @param val result port number (newtork byte order).
Expand Down
Loading