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
19 changes: 19 additions & 0 deletions files/olsrd.conf.default.txt
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,25 @@

# RtProto 0

# Announce host routes some other software put in the kernel as HNAs, so
# addresses olsr has no other way of learning about become reachable from
# the olsr side. The value is the route protocol identifying that software -
# another routing daemon, a roaming or tunnel manager, anything that
# installs routes under a protocol of its own. 0 (the default) disables it.
# Only host routes are taken, so a default route or an aggregate can never
# turn into an HNA.
#
# ImportPrefix, repeatable, bounds what may be announced. Without any, every
# host route of that protocol is imported - including addresses off transfer
# networks and management interfaces, so a whitelist is usually what you want.
#
# The example imports what protocol 42 installs within one address space:
#
# ImportProto 42
# ImportPrefix 10.12.0.0/16

# ImportProto 0

# Specifies the routing Table olsr uses
# RtTable is for host routes, RtTableDefault for the route to the default
# internet gateway (2 in case of IPv6+NIIT) and RtTableTunnel is for
Expand Down
21 changes: 21 additions & 0 deletions src/cfgparser/cfgfile_gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,27 @@ void olsrd_write_cnf_autobuf_uncached(struct autobuf *out, struct olsrd_config *
cnf->rt_proto == expected ? "# " : "",
cnf->rt_proto == expected ? DEF_RTPROTO : cnf->rt_proto);
}
abuf_appendf(out,
"\n"
"# Route protocol whose host routes are announced as HNAs, so hosts\n"
"# only another routing daemon knows about become reachable over olsr.\n"
"# 0 disables the import. ImportPrefix, repeatable, bounds what may be\n"
"# announced; without any, every host route of that protocol is taken\n"
"\n");
if (cnf->import_proto != DEF_IMPORTPROTO) {
struct ip_prefix_list *hna;

abuf_appendf(out, "ImportProto %u\n", cnf->import_proto);

for (hna = cnf->import_prefixes; hna != NULL; hna = hna->next) {
struct ipaddr_str addrbuf;
abuf_appendf(out, "ImportPrefix %s/%d\n",
olsr_ip_to_string(&addrbuf, &hna->net.prefix), hna->net.prefix_len);
}
} else {
abuf_appendf(out, "# ImportProto %u\n", DEF_IMPORTPROTO);
}

abuf_appendf(out,
"\n"
"# Specifies the routing Table olsr uses\n"
Expand Down
6 changes: 6 additions & 0 deletions src/cfgparser/olsrd_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1049,6 +1049,10 @@ olsrd_free_cnf(struct olsrd_config **cnfVariableAddress)

ip_prefix_list_clear(&cnf->hna_entries);

ip_prefix_list_clear(&cnf->import_prefixes);

ip_prefix_list_clear(&cnf->import_prefixes);

while (cnf->plugins) {
struct plugin_entry *plugin = cnf->plugins;
cnf->plugins = cnf->plugins->next;
Expand Down Expand Up @@ -1095,6 +1099,8 @@ set_default_cnf(struct olsrd_config *cnf, char * configuration_file)
cnf->allow_no_interfaces = DEF_ALLOW_NO_INTS;
cnf->tos = DEF_TOS;
cnf->rt_proto = DEF_RTPROTO;
cnf->import_proto = DEF_IMPORTPROTO;
cnf->import_prefixes = NULL;
cnf->rt_table = DEF_RT_AUTO;
cnf->rt_table_default = DEF_RT_AUTO;
cnf->rt_table_tunnel = DEF_RT_AUTO;
Expand Down
64 changes: 64 additions & 0 deletions src/cfgparser/oparse.y
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ static int add_ipv6_addr(YYSTYPE ipaddr_arg, YYSTYPE prefixlen_arg)
%token TOK_TOS
%token TOK_OLSRPORT
%token TOK_RTPROTO
%token TOK_IMPORTPROTO
%token TOK_IMPORTPREFIX
%token TOK_RTTABLE
%token TOK_RTTABLE_DEFAULT
%token TOK_RTTABLE_TUNNEL
Expand Down Expand Up @@ -296,6 +298,8 @@ stmt: idebug
| atos
| aolsrport
| irtproto
| iimportproto
| iimportprefix
| irttable
| irttable_default
| irttable_tunnel
Expand Down Expand Up @@ -1062,6 +1066,66 @@ aolsrport: TOK_OLSRPORT TOK_INTEGER
}
;

iimportproto: TOK_IMPORTPROTO TOK_INTEGER
{
PARSER_DEBUG_PRINTF("ImportProto: %d\n", $2->integer);
olsr_cnf->import_proto = $2->integer;
free($2);
}
;

iimportprefix: TOK_IMPORTPREFIX TOK_IPV4_ADDR TOK_SLASH TOK_INTEGER
{
union olsr_ip_addr ipaddr;

if (olsr_cnf->ip_version == AF_INET6) {
fprintf(stderr, "IPv4 addresses can only be used if \"IpVersion\" == 4, skipping ImportPrefix.\n");
olsr_startup_sleep(3);
} else {
PARSER_DEBUG_PRINTF("ImportPrefix: %s/%d\n", $2->string, $4->integer);

if (inet_pton(AF_INET, $2->string, &ipaddr.v4) <= 0) {
fprintf(stderr, "iimportprefix: Failed converting IP address %s\n", $2->string);
YYABORT;
}
if ($4->integer > olsr_cnf->maxplen) {
fprintf(stderr, "iimportprefix: Prefix len %u > %d is not allowed!\n", $4->integer, olsr_cnf->maxplen);
YYABORT;
}

ip_prefix_list_add(&olsr_cnf->import_prefixes, &ipaddr, $4->integer);
}
free($2->string);
free($2);
free($4);
}
| TOK_IMPORTPREFIX TOK_IPV6_ADDR TOK_SLASH TOK_INTEGER
{
union olsr_ip_addr ipaddr;

if (olsr_cnf->ip_version == AF_INET) {
fprintf(stderr, "IPv6 addresses can only be used if \"IpVersion\" == 6, skipping ImportPrefix.\n");
olsr_startup_sleep(3);
} else {
PARSER_DEBUG_PRINTF("ImportPrefix: %s/%d\n", $2->string, $4->integer);

if (inet_pton(AF_INET6, $2->string, &ipaddr.v6) <= 0) {
fprintf(stderr, "iimportprefix: Failed converting IP address %s\n", $2->string);
YYABORT;
}
if ($4->integer > olsr_cnf->maxplen) {
fprintf(stderr, "iimportprefix: Prefix len %u > %d is not allowed!\n", $4->integer, olsr_cnf->maxplen);
YYABORT;
}

ip_prefix_list_add(&olsr_cnf->import_prefixes, &ipaddr, $4->integer);
}
free($2->string);
free($2);
free($4);
}
;

irtproto: TOK_RTPROTO TOK_INTEGER
{
PARSER_DEBUG_PRINTF("RtProto: %d\n", $2->integer);
Expand Down
10 changes: 10 additions & 0 deletions src/cfgparser/oscan.lex
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,16 @@ IPV6ADDR {IPV6PAT1}|{IPV6PAT2}|{IPV6PAT3}|{IPV6PAT4}|{IPV6PAT5}|{IPV6PAT6}|{IPV6
return TOK_OLSRPORT;
}

"ImportProto" {
yylval = NULL;
return TOK_IMPORTPROTO;
}

"ImportPrefix" {
yylval = NULL;
return TOK_IMPORTPREFIX;
}

"RtProto" {
olsrd_config_checksum_add(yytext, yyleng);
yylval = NULL;
Expand Down
35 changes: 31 additions & 4 deletions src/linux/kernel_routes_nl.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
#include "log.h"
#include "net_os.h"
#include "ifnet.h"
#include "olsr.h"
#include "route_import.h"

#include <assert.h>
#include <linux/types.h>
Expand Down Expand Up @@ -166,34 +168,59 @@ static void rtnetlink_read(int sock, void *data __attribute__ ((unused)), unsign
.msg_flags = 0,
};

char buffer[4096];
/* route messages carry more attributes than a link message and can
* outgrow a fixed buffer; size each one from a peek first */
int bufsize = 4096;
char *buffer = olsr_malloc(bufsize, "netlink receive buffer");
struct nlmsghdr *nlh = (struct nlmsghdr *)ARM_NOWARN_ALIGN(buffer);
int ret;

iov.iov_base = (void *) buffer;
iov.iov_len = sizeof(buffer);
iov.iov_len = bufsize;

while ((ret = recvmsg(sock, &msg, MSG_DONTWAIT | MSG_TRUNC | MSG_PEEK)) >= 0) {
if (ret > bufsize) {
free(buffer);
buffer = olsr_malloc(ret, "netlink receive buffer expansion");
bufsize = ret;

iov.iov_base = (void *) buffer;
iov.iov_len = bufsize;
nlh = (struct nlmsghdr *)ARM_NOWARN_ALIGN(buffer);
}

ret = recvmsg(sock, &msg, MSG_DONTWAIT);
if (ret < 0) {
goto end;
}

while ((ret = recvmsg(sock, &msg, MSG_DONTWAIT)) >= 0) {
/*check message*/
len = nlh->nlmsg_len;
plen = len - sizeof(nlh);
if (len > ret || plen < 0) {
OLSR_PRINTF(1,"Malformed netlink message: "
"len=%d left=%d plen=%d\n",
len, ret, plen);
return;
goto end;
}

OLSR_PRINTF(3, "Netlink message received: type 0x%x\n", nlh->nlmsg_type);
if ((nlh->nlmsg_type == RTM_NEWLINK) || ( nlh->nlmsg_type == RTM_DELLINK)) {
/* handle ifup/ifdown */
netlink_process_link(nlh);
}

if ((nlh->nlmsg_type == RTM_NEWROUTE) || (nlh->nlmsg_type == RTM_DELROUTE)) {
/* another daemon's route came or went - see ImportProto */
process_import_nlh(nlh, nlh->nlmsg_type == RTM_DELROUTE);
}
}

if (errno != EAGAIN) {
OLSR_PRINTF(1,"netlink listen error %u - %s\n",errno,strerror(errno));
}
end:
free(buffer);
}

static void
Expand Down
16 changes: 15 additions & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
#include <linux/types.h>
#include <linux/rtnetlink.h>
#include "kernel_routes.h"
#include "route_import.h"

#endif /* __linux__ */

Expand Down Expand Up @@ -560,6 +561,9 @@ int main(int argc, char *argv[]) {

/* create a socket for netlink calls */
#ifdef __linux__
{
int rtnetlink_groups = RTMGRP_LINK;

olsr_cnf->rtnl_s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
if (olsr_cnf->rtnl_s < 0) {
char buf2[1024];
Expand All @@ -571,11 +575,18 @@ int main(int argc, char *argv[]) {
olsr_syslog(OLSR_LOG_INFO, "rtnetlink could not be set to nonblocking");
}

if ((olsr_cnf->rt_monitor_socket = rtnetlink_register_socket(RTMGRP_LINK)) < 0) {
/* only ask the kernel for route changes when something wants them: a
* busy table would otherwise wake olsrd on every neighbour's update */
if (olsr_cnf->import_proto != 0) {
rtnetlink_groups |= (olsr_cnf->ip_version == AF_INET) ? RTMGRP_IPV4_ROUTE : RTMGRP_IPV6_ROUTE;
}

if ((olsr_cnf->rt_monitor_socket = rtnetlink_register_socket(rtnetlink_groups)) < 0) {
char buf2[1024];
snprintf(buf2, sizeof(buf2), "rtmonitor socket: %s", strerror(errno));
olsr_exit(buf2, EXIT_FAILURE);
}
}
#endif /* __linux__ */

/* create routing socket */
Expand Down Expand Up @@ -773,6 +784,9 @@ int main(int argc, char *argv[]) {

olsr_shutdown_registered = true;

/* seed the HNA list from what is already in the routing table */
route_import_init();

/* Starting scheduler */
olsr_scheduler();

Expand Down
7 changes: 7 additions & 0 deletions src/olsr_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
#define DEF_CLEAR_SCREEN true
#define DEF_OLSRPORT 698
#define DEF_RTPROTO 0 /* 0 means OS-specific default */
#define DEF_IMPORTPROTO 0 /* 0 disables the route import */
#define DEF_RT_NONE -1
#define DEF_RT_AUTO 0

Expand Down Expand Up @@ -303,6 +304,10 @@ struct olsrd_config {
struct hyst_param hysteresis_param;
struct plugin_entry *plugins;
struct ip_prefix_list *hna_entries;
/* route protocol whose host routes become HNAs, 0 to disable */
uint8_t import_proto;
/* optional whitelist bounding what import_proto may announce */
struct ip_prefix_list *import_prefixes;
struct ip_prefix_list *ipc_nets;
struct if_config_options *interface_defaults;
struct olsr_if *interfaces;
Expand Down Expand Up @@ -417,6 +422,8 @@ extern "C" {

int ip_prefix_list_remove(struct ip_prefix_list **, const union olsr_ip_addr *, uint8_t);

void ip_prefix_list_clear(struct ip_prefix_list **list);

struct ip_prefix_list *ip_prefix_list_find(struct ip_prefix_list *, const union olsr_ip_addr *net, uint8_t prefix_len);

/*
Expand Down
Loading