1TBS
This commit is contained in:
parent
17bb6145e5
commit
724fa74974
@ -1,7 +1,13 @@
|
||||
BreakBeforeBraces: Allman
|
||||
BreakBeforeBraces: Linux
|
||||
IndentWidth: 4
|
||||
ColumnLimit: 120
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
Cpp11BracedListStyle: false
|
||||
IndentPPDirectives: AfterHash
|
||||
MaxEmptyLinesToKeep: 1
|
||||
ForEachMacros:
|
||||
- ND_LL_FOREACH
|
||||
- ND_LL_FOREACH_S
|
||||
- ND_LL_FOREACH_NODEF
|
||||
- ND_LL_FOREACH_S_NODEF
|
||||
|
||||
|
@ -29,7 +29,6 @@ Checks: >
|
||||
-google-*,
|
||||
-hicpp-avoid-c-arrays,
|
||||
-hicpp-avoid-goto,
|
||||
-hicpp-braces-around-statements,
|
||||
-hicpp-function-size,
|
||||
-hicpp-named-parameter,
|
||||
-hicpp-no-array-decay,
|
||||
@ -52,7 +51,6 @@ Checks: >
|
||||
-modernize-use-using,
|
||||
-objc-*,
|
||||
-openmp-exception-escape,
|
||||
-readability-braces-around-statements,
|
||||
-readability-else-after-return,
|
||||
-readability-function-size,
|
||||
-readability-identifier-naming,
|
||||
|
50
src/addr.c
50
src/addr.c
@ -33,8 +33,9 @@ const char *nd_aton(nd_addr_t *addr)
|
||||
static int index;
|
||||
static char buf[3][64];
|
||||
|
||||
if (addr == NULL)
|
||||
if (addr == NULL) {
|
||||
return "(null)";
|
||||
}
|
||||
|
||||
int n = index++ % 3;
|
||||
|
||||
@ -80,50 +81,47 @@ bool nd_addr_eq(nd_addr_t *first, nd_addr_t *second)
|
||||
//! Returns true if the first <tt>pflen</tt> bits are the same in <tt>first</tt> and <tt>second</tt>.
|
||||
bool nd_addr_match(nd_addr_t *first, nd_addr_t *second, unsigned pflen)
|
||||
{
|
||||
if (pflen > 128)
|
||||
if (pflen > 128) {
|
||||
return false;
|
||||
else if (pflen == 0)
|
||||
} else if (pflen == 0) {
|
||||
return true;
|
||||
else if (pflen == 128)
|
||||
} else if (pflen == 128) {
|
||||
return nd_addr_eq(first, second);
|
||||
}
|
||||
|
||||
for (unsigned i = 0, top = (pflen - 1) >> 5; i <= top; i++)
|
||||
{
|
||||
for (unsigned i = 0, top = (pflen - 1) >> 5; i <= top; i++) {
|
||||
uint32_t mask = i < top ? 0xffffffff : ndL_masks[(pflen - 1) & 31];
|
||||
|
||||
if ((first->s6_addr32[i] ^ second->s6_addr32[i]) & mask)
|
||||
if ((first->s6_addr32[i] ^ second->s6_addr32[i]) & mask) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void nd_addr_combine(const nd_addr_t *first, const nd_addr_t *second, unsigned pflen, nd_addr_t *result)
|
||||
{
|
||||
if (pflen == 0)
|
||||
{
|
||||
if (pflen == 0) {
|
||||
*result = *second;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pflen >= 128)
|
||||
{
|
||||
if (pflen >= 128) {
|
||||
*result = *first;
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned i = 0, top = (pflen - 1) >> 5; i < 4; i++)
|
||||
{
|
||||
if (i == top)
|
||||
{
|
||||
for (unsigned i = 0, top = (pflen - 1) >> 5; i < 4; i++) {
|
||||
if (i == top) {
|
||||
uint32_t mask = ndL_masks[(pflen - 1) & 31];
|
||||
result->s6_addr32[i] = (first->s6_addr32[i] & mask) | (second->s6_addr32[i] & ~mask);
|
||||
}
|
||||
else if (i < top)
|
||||
} else if (i < top) {
|
||||
result->s6_addr32[i] = first->s6_addr32[i];
|
||||
else
|
||||
} else {
|
||||
result->s6_addr32[i] = second->s6_addr32[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int ndL_count_bits(uint32_t n)
|
||||
@ -144,8 +142,7 @@ int nd_mask_to_pflen(nd_addr_t *netmask)
|
||||
|
||||
void nd_mask_from_pflen(unsigned pflen, nd_addr_t *netmask)
|
||||
{
|
||||
if (pflen == 0)
|
||||
{
|
||||
if (pflen == 0) {
|
||||
netmask->s6_addr32[0] = 0;
|
||||
netmask->s6_addr32[1] = 0;
|
||||
netmask->s6_addr32[2] = 0;
|
||||
@ -153,8 +150,7 @@ void nd_mask_from_pflen(unsigned pflen, nd_addr_t *netmask)
|
||||
return;
|
||||
}
|
||||
|
||||
if (pflen >= 128)
|
||||
{
|
||||
if (pflen >= 128) {
|
||||
netmask->s6_addr32[0] = 0xffffffff;
|
||||
netmask->s6_addr32[1] = 0xffffffff;
|
||||
netmask->s6_addr32[2] = 0xffffffff;
|
||||
@ -162,13 +158,13 @@ void nd_mask_from_pflen(unsigned pflen, nd_addr_t *netmask)
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned i = 0, top = (pflen - 1) >> 5; i < 4; i++)
|
||||
{
|
||||
if (i == top)
|
||||
for (unsigned i = 0, top = (pflen - 1) >> 5; i < 4; i++) {
|
||||
if (i == top) {
|
||||
netmask->s6_addr32[i] = ndL_masks[(pflen - 1) & 31];
|
||||
else if (i < top)
|
||||
} else if (i < top) {
|
||||
netmask->s6_addr32[i] = 0xffffffff;
|
||||
else
|
||||
} else {
|
||||
netmask->s6_addr32[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
15
src/alloc.c
15
src/alloc.c
@ -27,8 +27,7 @@
|
||||
|
||||
typedef struct ndL_chunk ndL_chunk_t;
|
||||
|
||||
struct ndL_chunk
|
||||
{
|
||||
struct ndL_chunk {
|
||||
ndL_chunk_t *next;
|
||||
size_t free;
|
||||
size_t size;
|
||||
@ -52,10 +51,8 @@ void *nd_alloc(size_t size)
|
||||
// To keep everything properly aligned, we'll make sure it's multiple of 8.
|
||||
size = (size + 7U) & ~7U;
|
||||
|
||||
for (ndL_chunk_t *chunk = ndL_chunks; chunk; chunk = chunk->next)
|
||||
{
|
||||
if (chunk->free >= size)
|
||||
{
|
||||
for (ndL_chunk_t *chunk = ndL_chunks; chunk; chunk = chunk->next) {
|
||||
if (chunk->free >= size) {
|
||||
void *ptr = (void *)chunk + chunk->size - chunk->free;
|
||||
chunk->free -= size;
|
||||
return ptr;
|
||||
@ -65,8 +62,9 @@ void *nd_alloc(size_t size)
|
||||
ndL_chunk_t *chunk = (ndL_chunk_t *)calloc(1, ndL_alloc_size);
|
||||
|
||||
// This should never happen.
|
||||
if (chunk == NULL)
|
||||
if (chunk == NULL) {
|
||||
abort();
|
||||
}
|
||||
|
||||
chunk->next = ndL_chunks;
|
||||
chunk->size = ndL_alloc_size;
|
||||
@ -83,8 +81,7 @@ void *nd_alloc(size_t size)
|
||||
|
||||
void nd_alloc_cleanup()
|
||||
{
|
||||
ND_LL_FOREACH_S(ndL_chunks, chunk, tmp, next)
|
||||
{
|
||||
ND_LL_FOREACH_S (ndL_chunks, chunk, tmp, next) {
|
||||
free(chunk);
|
||||
}
|
||||
}
|
||||
|
245
src/conf.c
245
src/conf.c
@ -36,8 +36,7 @@ int nd_conf_retrans_limit = 3;
|
||||
int nd_conf_retrans_time = 1000;
|
||||
bool nd_conf_keepalive = false;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
const char *data;
|
||||
size_t offset;
|
||||
size_t length;
|
||||
@ -49,8 +48,7 @@ typedef struct ndL_cfinfo ndL_cfinfo_t;
|
||||
|
||||
typedef bool (*ndL_cfcb_t)(ndL_state_t *, const ndL_cfinfo_t *, void *);
|
||||
|
||||
struct ndL_cfinfo
|
||||
{
|
||||
struct ndL_cfinfo {
|
||||
const char *key;
|
||||
int scope;
|
||||
int type;
|
||||
@ -61,26 +59,13 @@ struct ndL_cfinfo
|
||||
};
|
||||
|
||||
//! Scopes.
|
||||
enum
|
||||
{
|
||||
NDL_DEFAULT,
|
||||
NDL_PROXY,
|
||||
NDL_RULE
|
||||
};
|
||||
enum { NDL_DEFAULT, NDL_PROXY, NDL_RULE };
|
||||
|
||||
//! Configuration types.
|
||||
enum
|
||||
{
|
||||
NDL_NONE,
|
||||
NDL_INT,
|
||||
NDL_BOOL,
|
||||
NDL_ADDR,
|
||||
NDL_IDENT
|
||||
};
|
||||
enum { NDL_NONE, NDL_INT, NDL_BOOL, NDL_ADDR, NDL_IDENT };
|
||||
|
||||
//! Character classes.
|
||||
enum
|
||||
{
|
||||
enum {
|
||||
NDL_ALPHA = 256, // [a-zA-Z]
|
||||
NDL_ALNUM, // [a-zA-Z0-9]
|
||||
NDL_DIGIT, // [0-9]
|
||||
@ -93,7 +78,7 @@ enum
|
||||
|
||||
static bool ndL_parse_rule(ndL_state_t *state, ndL_cfinfo_t *info, nd_proxy_t *proxy);
|
||||
static bool ndL_parse_rewrite(ndL_state_t *state, ndL_cfinfo_t *info, nd_rule_t *rule);
|
||||
static bool ndL_parse_proxy(ndL_state_t *state, ndL_cfinfo_t *info, void *unused);
|
||||
static bool ndL_parse_proxy(ndL_state_t *state, ND_UNUSED ndL_cfinfo_t *u1, ND_UNUSED void *u2);
|
||||
static bool ndL_parse_mode(ndL_state_t *state, ndL_cfinfo_t *info, nd_rule_t *rule);
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
@ -136,15 +121,15 @@ static void ndL_error(const ndL_state_t *state, const char *fmt, ...)
|
||||
|
||||
static char ndL_accept_one(ndL_state_t *state, int cl)
|
||||
{
|
||||
if (state->offset >= state->length)
|
||||
if (state->offset >= state->length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char ch = state->data[state->offset];
|
||||
|
||||
bool result;
|
||||
|
||||
switch (cl)
|
||||
{
|
||||
switch (cl) {
|
||||
case 0:
|
||||
result = true;
|
||||
break;
|
||||
@ -186,16 +171,14 @@ static char ndL_accept_one(ndL_state_t *state, int cl)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!result)
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ch == '\n')
|
||||
{
|
||||
if (ch == '\n') {
|
||||
state->line++;
|
||||
state->column = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
state->column++;
|
||||
}
|
||||
|
||||
@ -208,17 +191,15 @@ static bool ndL_accept_all(ndL_state_t *state, int cl, char *buf, size_t buflen)
|
||||
{
|
||||
ndL_state_t tmp = *state;
|
||||
|
||||
for (size_t i = 0; !buf || i < buflen; i++)
|
||||
{
|
||||
for (size_t i = 0; !buf || i < buflen; i++) {
|
||||
char ch = ndL_accept_one(&tmp, cl);
|
||||
|
||||
if (buf)
|
||||
if (buf) {
|
||||
buf[i] = ch;
|
||||
}
|
||||
|
||||
if (!ch)
|
||||
{
|
||||
if (i > 0)
|
||||
{
|
||||
if (!ch) {
|
||||
if (i > 0) {
|
||||
*state = tmp;
|
||||
return true;
|
||||
}
|
||||
@ -234,14 +215,17 @@ static bool ndL_accept(ndL_state_t *state, const char *str, int except_cl)
|
||||
{
|
||||
ndL_state_t tmp = *state;
|
||||
|
||||
while (*str && ndL_accept_one(&tmp, *str))
|
||||
while (*str && ndL_accept_one(&tmp, *str)) {
|
||||
str++;
|
||||
}
|
||||
|
||||
if (*str)
|
||||
if (*str) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (except_cl && ndL_accept_one(&tmp, except_cl))
|
||||
if (except_cl && ndL_accept_one(&tmp, except_cl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*state = tmp;
|
||||
return true;
|
||||
@ -249,16 +233,16 @@ static bool ndL_accept(ndL_state_t *state, const char *str, int except_cl)
|
||||
|
||||
static bool ndL_accept_bool(ndL_state_t *state, bool *value)
|
||||
{
|
||||
if (ndL_accept(state, "yes", NDL_EALNM) || ndL_accept(state, "true", NDL_EALNM))
|
||||
if (ndL_accept(state, "yes", NDL_EALNM) || ndL_accept(state, "true", NDL_EALNM)) {
|
||||
*value = true;
|
||||
else if (ndL_accept(state, "no", NDL_EALNM) || ndL_accept(state, "false", NDL_EALNM))
|
||||
} else if (ndL_accept(state, "no", NDL_EALNM) || ndL_accept(state, "false", NDL_EALNM)) {
|
||||
*value = false;
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// For accurate reporting of location.
|
||||
ndL_state_t tmp = *state;
|
||||
if (ndL_accept_one(&tmp, NDL_XNONL) != 0)
|
||||
if (ndL_accept_one(&tmp, NDL_XNONL) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*value = true;
|
||||
}
|
||||
@ -274,17 +258,18 @@ static bool ndL_accept_int(ndL_state_t *state, int *value, int min, int max)
|
||||
|
||||
char buf[32];
|
||||
|
||||
if (!ndL_accept_all(&tmp, NDL_DIGIT, buf, sizeof(buf)))
|
||||
if (!ndL_accept_all(&tmp, NDL_DIGIT, buf, sizeof(buf))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Trailing [A-Za-z0-9_-] are invalid.
|
||||
if (ndL_accept_one(&tmp, NDL_EALNM))
|
||||
if (ndL_accept_one(&tmp, NDL_EALNM)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long longval = strtoll(buf, NULL, 10) * n;
|
||||
|
||||
if (longval < min || longval > max)
|
||||
{
|
||||
if (longval < min || longval > max) {
|
||||
ndL_error(state, "Expected a number between %d and %d", min, max);
|
||||
return false;
|
||||
}
|
||||
@ -301,32 +286,25 @@ static bool ndL_eof(ndL_state_t *state)
|
||||
|
||||
static void ndL_skip(ndL_state_t *state, bool skip_newline)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
for (;;) {
|
||||
ndL_accept_all(state, skip_newline ? NDL_SPACE : NDL_SNONL, NULL, 0);
|
||||
|
||||
if (ndL_accept(state, "#", 0))
|
||||
{
|
||||
if (ndL_accept(state, "#", 0)) {
|
||||
ndL_accept_all(state, NDL_XNONL, NULL, 0);
|
||||
}
|
||||
else if (ndL_accept(state, "/*", 0))
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (ndL_eof(state))
|
||||
{
|
||||
} else if (ndL_accept(state, "/*", 0)) {
|
||||
for (;;) {
|
||||
if (ndL_eof(state)) {
|
||||
ndL_error(state, "Expected end-of-comment before end-of-file");
|
||||
break;
|
||||
}
|
||||
|
||||
if (ndL_accept(state, "*/", 0))
|
||||
if (ndL_accept(state, "*/", 0)) {
|
||||
break;
|
||||
}
|
||||
|
||||
ndL_accept_one(state, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -338,15 +316,16 @@ static bool ndL_accept_addr(ndL_state_t *state, nd_addr_t *addr)
|
||||
|
||||
char buf[64];
|
||||
|
||||
if (!ndL_accept_all(&tmp, NDL_IPV6X, buf, sizeof(buf)))
|
||||
if (!ndL_accept_all(&tmp, NDL_IPV6X, buf, sizeof(buf))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure we don't have a trailing [A-Za-z0-9-_]
|
||||
if (ndL_accept_one(&tmp, NDL_EALNM))
|
||||
if (ndL_accept_one(&tmp, NDL_EALNM)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET6, buf, addr) != 1)
|
||||
{
|
||||
if (inet_pton(AF_INET6, buf, addr) != 1) {
|
||||
ndL_error(state, "Invalid IPv6 address \"%s\"", buf);
|
||||
return false;
|
||||
}
|
||||
@ -359,8 +338,9 @@ static bool ndL_accept_ident(ndL_state_t *state, char *str, size_t size)
|
||||
{
|
||||
ndL_state_t tmp = *state;
|
||||
|
||||
if (!ndL_accept_all(&tmp, NDL_EALNM, str, size))
|
||||
if (!ndL_accept_all(&tmp, NDL_EALNM, str, size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*state = tmp;
|
||||
return true;
|
||||
@ -372,22 +352,17 @@ static bool ndL_parse_rule(ndL_state_t *state, ND_UNUSED ndL_cfinfo_t *info, nd_
|
||||
{
|
||||
nd_rule_t *rule = nd_rule_create(proxy);
|
||||
|
||||
if (!ndL_accept_addr(state, &rule->addr))
|
||||
{
|
||||
if (!ndL_accept_addr(state, &rule->addr)) {
|
||||
ndL_error(state, "Expected IPv6 address");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ndL_accept(state, "/", 0))
|
||||
{
|
||||
if (!ndL_accept_int(state, &rule->prefix, 0, 128))
|
||||
{
|
||||
if (ndL_accept(state, "/", 0)) {
|
||||
if (!ndL_accept_int(state, &rule->prefix, 0, 128)) {
|
||||
ndL_error(state, "Expected prefix");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
rule->prefix = 128;
|
||||
}
|
||||
|
||||
@ -397,17 +372,16 @@ static bool ndL_parse_rule(ndL_state_t *state, ND_UNUSED ndL_cfinfo_t *info, nd_
|
||||
rule->table = 0;
|
||||
#endif
|
||||
|
||||
if (!ndL_parse_block(state, NDL_RULE, rule))
|
||||
if (!ndL_parse_block(state, NDL_RULE, rule)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rule->mode == ND_MODE_UNKNOWN)
|
||||
{
|
||||
if (rule->mode == ND_MODE_UNKNOWN) {
|
||||
ndL_error(state, "\"static\", \"auto\", or \"iface\" need to be specified");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rule->autowire && rule->mode != ND_MODE_IFACE)
|
||||
{
|
||||
if (rule->autowire && rule->mode != ND_MODE_IFACE) {
|
||||
ndL_error(state, "\"autowire\" may only be used in combination with \"iface\"");
|
||||
return false;
|
||||
}
|
||||
@ -417,19 +391,16 @@ static bool ndL_parse_rule(ndL_state_t *state, ND_UNUSED ndL_cfinfo_t *info, nd_
|
||||
|
||||
static bool ndL_parse_rewrite(ndL_state_t *state, ND_UNUSED ndL_cfinfo_t *info, nd_rule_t *rule)
|
||||
{
|
||||
if (!ndL_accept_addr(state, &rule->rewrite_tgt))
|
||||
if (!ndL_accept_addr(state, &rule->rewrite_tgt)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ndL_accept(state, "/", 0))
|
||||
{
|
||||
if (!ndL_accept_int(state, &rule->rewrite_pflen, 0, 128))
|
||||
{
|
||||
if (ndL_accept(state, "/", 0)) {
|
||||
if (!ndL_accept_int(state, &rule->rewrite_pflen, 0, 128)) {
|
||||
ndL_error(state, "Expected prefix");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
rule->rewrite_pflen = 128;
|
||||
}
|
||||
|
||||
@ -440,36 +411,33 @@ static bool ndL_parse_proxy(ndL_state_t *state, ND_UNUSED ndL_cfinfo_t *u1, ND_U
|
||||
{
|
||||
char ifname[IF_NAMESIZE];
|
||||
|
||||
if (!ndL_accept_all(state, NDL_EALNM, ifname, sizeof(ifname)))
|
||||
{
|
||||
if (!ndL_accept_all(state, NDL_EALNM, ifname, sizeof(ifname))) {
|
||||
ndL_error(state, "Expected interface name");
|
||||
return false;
|
||||
}
|
||||
|
||||
nd_proxy_t *proxy = nd_proxy_create(ifname);
|
||||
|
||||
if (proxy == NULL)
|
||||
if (proxy == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ndL_parse_block(state, NDL_PROXY, proxy);
|
||||
}
|
||||
|
||||
static bool ndL_parse_mode(ndL_state_t *state, ndL_cfinfo_t *info, nd_rule_t *rule)
|
||||
{
|
||||
if (rule->mode != ND_MODE_UNKNOWN)
|
||||
{
|
||||
if (rule->mode != ND_MODE_UNKNOWN) {
|
||||
ndL_error(state, "\"static\", \"auto\" and \"iface\" are mutually exclusive");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!strcmp(info->key, "auto"))
|
||||
if (!strcmp(info->key, "auto")) {
|
||||
rule->mode = ND_MODE_AUTO;
|
||||
else if (!strcmp(info->key, "static"))
|
||||
} else if (!strcmp(info->key, "static")) {
|
||||
rule->mode = ND_MODE_STATIC;
|
||||
else
|
||||
{
|
||||
if (!ndL_accept_ident(state, rule->ifname, sizeof(rule->ifname)))
|
||||
{
|
||||
} else {
|
||||
if (!ndL_accept_ident(state, rule->ifname, sizeof(rule->ifname))) {
|
||||
ndL_error(state, "Expected interface name");
|
||||
return false;
|
||||
}
|
||||
@ -484,25 +452,22 @@ static bool ndL_parse_block(ndL_state_t *state, int scope, void *ptr)
|
||||
{
|
||||
ndL_skip(state, false);
|
||||
|
||||
if (scope != NDL_DEFAULT && !ndL_accept_one(state, '{'))
|
||||
{
|
||||
if (scope != NDL_DEFAULT && !ndL_accept_one(state, '{')) {
|
||||
ndL_error(state, "Expected start-of-block '{'");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t bits = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;) {
|
||||
ndL_skip(state, true);
|
||||
|
||||
if (scope != NDL_DEFAULT && ndL_accept_one(state, '}'))
|
||||
if (scope != NDL_DEFAULT && ndL_accept_one(state, '}')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ndL_eof(state))
|
||||
{
|
||||
if (scope != NDL_DEFAULT)
|
||||
{
|
||||
if (ndL_eof(state)) {
|
||||
if (scope != NDL_DEFAULT) {
|
||||
ndL_error(state, "Expected end-of-block '}'");
|
||||
return false;
|
||||
}
|
||||
@ -515,24 +480,23 @@ static bool ndL_parse_block(ndL_state_t *state, int scope, void *ptr)
|
||||
char key[32];
|
||||
|
||||
const ndL_state_t state_before_key = *state;
|
||||
if (!ndL_accept_ident(state, key, sizeof(key)))
|
||||
{
|
||||
if (!ndL_accept_ident(state, key, sizeof(key))) {
|
||||
nd_log_error("Expected key");
|
||||
return false;
|
||||
}
|
||||
|
||||
ndL_skip(state, false);
|
||||
|
||||
for (int i = 0; !found && ndL_cfinfo_table[i].key; i++)
|
||||
{
|
||||
if (ndL_cfinfo_table[i].scope != scope)
|
||||
for (int i = 0; !found && ndL_cfinfo_table[i].key; i++) {
|
||||
if (ndL_cfinfo_table[i].scope != scope) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(key, ndL_cfinfo_table[i].key) != 0)
|
||||
if (strcmp(key, ndL_cfinfo_table[i].key) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(key, "rule") != 0 && strcmp(key, "proxy") != 0 && bits & (1 << i))
|
||||
{
|
||||
if (strcmp(key, "rule") != 0 && strcmp(key, "proxy") != 0 && bits & (1 << i)) {
|
||||
ndL_error(&state_before_key, "\"%s\" has already been configured earlier in this scope", key);
|
||||
return false;
|
||||
}
|
||||
@ -543,63 +507,56 @@ static bool ndL_parse_block(ndL_state_t *state, int scope, void *ptr)
|
||||
const ndL_cfinfo_t *t = &ndL_cfinfo_table[i];
|
||||
const ndL_state_t state_before_value = *state;
|
||||
|
||||
switch (t->type)
|
||||
{
|
||||
switch (t->type) {
|
||||
case NDL_NONE:
|
||||
break;
|
||||
|
||||
case NDL_BOOL:
|
||||
if (!ndL_accept_bool(state, (bool *)(ptr + t->offset)))
|
||||
{
|
||||
if (!ndL_accept_bool(state, (bool *)(ptr + t->offset))) {
|
||||
ndL_error(&state_before_value, "Expected boolean value");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case NDL_INT:
|
||||
if (!ndL_accept_int(state, (int *)(ptr + t->offset), t->min, t->max))
|
||||
{
|
||||
if (!ndL_accept_int(state, (int *)(ptr + t->offset), t->min, t->max)) {
|
||||
ndL_error(&state_before_value, "Expected an integer");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case NDL_ADDR:
|
||||
if (!ndL_accept_addr(state, (nd_addr_t *)(ptr + t->offset)))
|
||||
{
|
||||
if (!ndL_accept_addr(state, (nd_addr_t *)(ptr + t->offset))) {
|
||||
ndL_error(&state_before_value, "Expected an IPv6 address");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case NDL_IDENT:
|
||||
if (!ndL_accept_ident(state, (char *)(ptr + t->offset), t->max))
|
||||
{
|
||||
if (!ndL_accept_ident(state, (char *)(ptr + t->offset), t->max)) {
|
||||
ndL_error(&state_before_value, "Expected identifier");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (t->cb)
|
||||
{
|
||||
if (t->cb) {
|
||||
ndL_skip(state, false);
|
||||
|
||||
if (!t->cb(state, &ndL_cfinfo_table[i], ptr))
|
||||
if (!t->cb(state, &ndL_cfinfo_table[i], ptr)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ndL_skip(state, false);
|
||||
|
||||
if (!ndL_eof(state) && !ndL_accept_one(state, '\n'))
|
||||
{
|
||||
if (!ndL_eof(state) && !ndL_accept_one(state, '\n')) {
|
||||
ndL_error(state, "Expected newline");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
if (!found) {
|
||||
ndL_error(state, "Invalid configuration");
|
||||
return false;
|
||||
}
|
||||
@ -610,16 +567,14 @@ bool nd_conf_load(const char *path)
|
||||
{
|
||||
FILE *fp = fopen(path, "r");
|
||||
|
||||
if (fp == NULL)
|
||||
{
|
||||
if (fp == NULL) {
|
||||
nd_log_error("Failed to load configuration: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct stat stat;
|
||||
|
||||
if (fstat(fileno(fp), &stat) < 0)
|
||||
{
|
||||
if (fstat(fileno(fp), &stat) < 0) {
|
||||
nd_log_error("Failed to determine size: %s", strerror(errno));
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
@ -627,8 +582,7 @@ bool nd_conf_load(const char *path)
|
||||
|
||||
char *buf = (char *)malloc(stat.st_size);
|
||||
|
||||
if (buf == NULL)
|
||||
{
|
||||
if (buf == NULL) {
|
||||
nd_log_error("Failed to allocate buffer: %s", strerror(errno));
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
@ -636,12 +590,9 @@ bool nd_conf_load(const char *path)
|
||||
|
||||
bool result = false;
|
||||
|
||||
if (fread(buf, stat.st_size, 1, fp) != 1)
|
||||
{
|
||||
if (fread(buf, stat.st_size, 1, fp) != 1) {
|
||||
nd_log_error("Failed to read config: %s", strerror(errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
ndL_state_t state = { .data = buf, .offset = 0, .length = stat.st_size, .column = 0, .line = 1 };
|
||||
|
||||
// FIXME: Validate configuration
|
||||
|
189
src/iface.c
189
src/iface.c
@ -66,8 +66,7 @@ static nd_io_t *ndL_io;
|
||||
//! Used when daemonizing to make sure the parent process does not restore these flags upon exit.
|
||||
bool nd_iface_no_restore_flags;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
struct ip6_hdr ip6_hdr;
|
||||
struct icmp6_hdr icmp6_hdr;
|
||||
} ndL_icmp6_msg_t;
|
||||
@ -76,37 +75,43 @@ static void ndL_handle_ns(nd_iface_t *iface, ndL_icmp6_msg_t *msg)
|
||||
{
|
||||
struct nd_neighbor_solicit *ns = (struct nd_neighbor_solicit *)&msg->icmp6_hdr;
|
||||
|
||||
if (msg->ip6_hdr.ip6_plen < sizeof(struct nd_neighbor_solicit))
|
||||
if (msg->ip6_hdr.ip6_plen < sizeof(struct nd_neighbor_solicit)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We're not doing "proper" parsing of options here.
|
||||
|
||||
if (ntohs(msg->ip6_hdr.ip6_plen) - sizeof(struct nd_neighbor_solicit) < 8)
|
||||
if (ntohs(msg->ip6_hdr.ip6_plen) - sizeof(struct nd_neighbor_solicit) < 8) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct nd_opt_hdr *opt = (struct nd_opt_hdr *)((void *)ns + sizeof(struct nd_neighbor_solicit));
|
||||
|
||||
if (opt->nd_opt_len != 1 || opt->nd_opt_type != ND_OPT_SOURCE_LINKADDR)
|
||||
if (opt->nd_opt_len != 1 || opt->nd_opt_type != ND_OPT_SOURCE_LINKADDR) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t *src_ll = (uint8_t *)((void *)opt + 2);
|
||||
|
||||
if (iface->proxy)
|
||||
if (iface->proxy) {
|
||||
nd_proxy_handle_ns(iface->proxy, &msg->ip6_hdr.ip6_src, &msg->ip6_hdr.ip6_dst, &ns->nd_ns_target, src_ll);
|
||||
}
|
||||
}
|
||||
|
||||
static void ndL_handle_na(nd_iface_t *iface, ndL_icmp6_msg_t *msg)
|
||||
{
|
||||
if (msg->ip6_hdr.ip6_plen < sizeof(struct nd_neighbor_advert))
|
||||
if (msg->ip6_hdr.ip6_plen < sizeof(struct nd_neighbor_advert)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct nd_neighbor_advert *na = (struct nd_neighbor_advert *)&msg->icmp6_hdr;
|
||||
|
||||
nd_session_t *session;
|
||||
ND_LL_SEARCH(iface->sessions, session, next_in_iface, nd_addr_eq(&session->real_tgt, &na->nd_na_target));
|
||||
|
||||
if (!session)
|
||||
if (!session) {
|
||||
return;
|
||||
}
|
||||
|
||||
nd_session_handle_na(session);
|
||||
}
|
||||
@ -115,24 +120,25 @@ static uint16_t ndL_calculate_checksum(uint32_t sum, const void *data, size_t le
|
||||
{
|
||||
uint8_t *p = (uint8_t *)data;
|
||||
|
||||
for (size_t i = 0; i < length; i += 2)
|
||||
{
|
||||
if (i + 1 < length)
|
||||
sum += ntohs(*(uint16_t *)p), p += 2;
|
||||
else
|
||||
for (size_t i = 0; i < length; i += 2) {
|
||||
if (i + 1 < length) {
|
||||
sum += ntohs(*(uint16_t *)p);
|
||||
p += 2;
|
||||
} else {
|
||||
sum += *p++;
|
||||
}
|
||||
|
||||
if (sum > 0xffff)
|
||||
if (sum > 0xffff) {
|
||||
sum -= 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
static uint16_t ndL_calculate_icmp6_checksum(ndL_icmp6_msg_t *msg, size_t size)
|
||||
{
|
||||
struct __attribute__((packed))
|
||||
{
|
||||
struct __attribute__((packed)) {
|
||||
struct in6_addr src;
|
||||
struct in6_addr dst;
|
||||
uint32_t len;
|
||||
@ -162,22 +168,27 @@ static void ndL_handle_packet(nd_iface_t *iface, uint8_t *buf, size_t buflen)
|
||||
{
|
||||
ndL_icmp6_msg_t *msg = (ndL_icmp6_msg_t *)buf;
|
||||
|
||||
if ((size_t)buflen < sizeof(ndL_icmp6_msg_t))
|
||||
if ((size_t)buflen < sizeof(ndL_icmp6_msg_t)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((size_t)buflen != sizeof(struct ip6_hdr) + ntohs(msg->ip6_hdr.ip6_plen))
|
||||
if ((size_t)buflen != sizeof(struct ip6_hdr) + ntohs(msg->ip6_hdr.ip6_plen)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->ip6_hdr.ip6_nxt != IPPROTO_ICMPV6)
|
||||
if (msg->ip6_hdr.ip6_nxt != IPPROTO_ICMPV6) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ndL_calculate_icmp6_checksum(msg, buflen) != msg->icmp6_hdr.icmp6_cksum)
|
||||
if (ndL_calculate_icmp6_checksum(msg, buflen) != msg->icmp6_hdr.icmp6_cksum) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg->icmp6_hdr.icmp6_type == ND_NEIGHBOR_SOLICIT)
|
||||
if (msg->icmp6_hdr.icmp6_type == ND_NEIGHBOR_SOLICIT) {
|
||||
ndL_handle_ns(iface, msg);
|
||||
else if (msg->icmp6_hdr.icmp6_type == ND_NEIGHBOR_ADVERT)
|
||||
} else if (msg->icmp6_hdr.icmp6_type == ND_NEIGHBOR_ADVERT) {
|
||||
ndL_handle_na(iface, msg);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
@ -191,8 +202,7 @@ static void ndL_io_handler(nd_io_t *io, __attribute__((unused)) int events)
|
||||
|
||||
uint8_t buf[1024];
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;) {
|
||||
ssize_t len = nd_io_recv(io, (struct sockaddr *)&lladdr, sizeof(lladdr), buf, sizeof(buf));
|
||||
|
||||
if (len == 0)
|
||||
@ -225,30 +235,30 @@ static void ndL_io_handler(nd_io_t *io, __attribute__((unused)) int events)
|
||||
{
|
||||
__attribute__((aligned(BPF_ALIGNMENT))) uint8_t buf[4096]; /* Depends on BIOCGBLEN */
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;) {
|
||||
ssize_t len = nd_io_read(io, buf, sizeof(buf));
|
||||
|
||||
if (len < 0)
|
||||
{
|
||||
if (errno == EAGAIN)
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN) {
|
||||
return;
|
||||
}
|
||||
|
||||
nd_log_error("%s", strerror(errno));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (size_t)len;)
|
||||
{
|
||||
for (size_t i = 0; i < (size_t)len;) {
|
||||
struct bpf_hdr *bpf_hdr = (struct bpf_hdr *)(buf + i);
|
||||
i += BPF_WORDALIGN(bpf_hdr->bh_hdrlen + bpf_hdr->bh_caplen);
|
||||
|
||||
if (bpf_hdr->bh_caplen < sizeof(struct ether_header) + sizeof(struct ip6_hdr))
|
||||
if (bpf_hdr->bh_caplen < sizeof(struct ether_header) + sizeof(struct ip6_hdr)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct ether_header *eh = (struct ether_header *)((void *)bpf_hdr + bpf_hdr->bh_hdrlen);
|
||||
|
||||
if (eh->ether_type != ntohs(ETHERTYPE_IPV6))
|
||||
if (eh->ether_type != ntohs(ETHERTYPE_IPV6)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct ip6_hdr *ip6_hdr = (struct ip6_hdr *)(eh + 1);
|
||||
|
||||
@ -298,8 +308,9 @@ static bool ndL_configure_filter(nd_io_t *io)
|
||||
# undef sock_filter
|
||||
# undef sock_fprog
|
||||
|
||||
if (ioctl(io->fd, BIOCSETF, &fprog) == -1)
|
||||
if (ioctl(io->fd, BIOCSETF, &fprog) == -1) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@ -309,21 +320,17 @@ nd_iface_t *nd_iface_open(const char *name, unsigned index)
|
||||
{
|
||||
char tmp_name[IF_NAMESIZE];
|
||||
|
||||
if (!name && !index)
|
||||
if (!name && !index) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (name && index && if_nametoindex(name) != index)
|
||||
{
|
||||
if (name && index && if_nametoindex(name) != index) {
|
||||
nd_log_error("Expected interface %s to have index %d", name, index);
|
||||
return NULL;
|
||||
}
|
||||
else if (name && !(index = if_nametoindex(name)))
|
||||
{
|
||||
} else if (name && !(index = if_nametoindex(name))) {
|
||||
nd_log_error("Failed to get index of interface %s: %s", name, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
else if (!(name = if_indextoname(index, tmp_name)))
|
||||
{
|
||||
} else if (!(name = if_indextoname(index, tmp_name))) {
|
||||
nd_log_error("Failed to get name of interface index %d: %s", index, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
@ -333,8 +340,7 @@ nd_iface_t *nd_iface_open(const char *name, unsigned index)
|
||||
nd_iface_t *iface;
|
||||
ND_LL_SEARCH(ndL_first_iface, iface, next, iface->index == index);
|
||||
|
||||
if (iface)
|
||||
{
|
||||
if (iface) {
|
||||
iface->refcount++;
|
||||
return iface;
|
||||
}
|
||||
@ -346,8 +352,7 @@ nd_iface_t *nd_iface_open(const char *name, unsigned index)
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strcpy(ifr.ifr_name, name);
|
||||
|
||||
if (ioctl(ndL_io->fd, SIOCGIFHWADDR, &ifr) < 0)
|
||||
{
|
||||
if (ioctl(ndL_io->fd, SIOCGIFHWADDR, &ifr) < 0) {
|
||||
nd_log_error("Failed to determine link-layer address: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
@ -357,8 +362,7 @@ nd_iface_t *nd_iface_open(const char *name, unsigned index)
|
||||
nd_io_t *io = NULL;
|
||||
|
||||
/* This requires a cloning bpf device, but I hope most sane systems got them. */
|
||||
if (!(io = nd_io_open("/dev/bpf", O_RDWR)))
|
||||
{
|
||||
if (!(io = nd_io_open("/dev/bpf", O_RDWR))) {
|
||||
nd_log_error("Failed to open /dev/bpf");
|
||||
return NULL;
|
||||
}
|
||||
@ -368,8 +372,7 @@ nd_iface_t *nd_iface_open(const char *name, unsigned index)
|
||||
/* Set buffer length. */
|
||||
|
||||
unsigned len = 4096; /* TODO: Configure */
|
||||
if (ioctl(io->fd, BIOCSBLEN, &len) < 0)
|
||||
{
|
||||
if (ioctl(io->fd, BIOCSBLEN, &len) < 0) {
|
||||
nd_log_error("BIOCSBLEN: %s", strerror(errno));
|
||||
nd_io_close(io);
|
||||
return NULL;
|
||||
@ -379,8 +382,7 @@ nd_iface_t *nd_iface_open(const char *name, unsigned index)
|
||||
|
||||
struct ifreq ifr;
|
||||
strcpy(ifr.ifr_name, name);
|
||||
if (ioctl(io->fd, BIOCSETIF, &ifr) < 0)
|
||||
{
|
||||
if (ioctl(io->fd, BIOCSETIF, &ifr) < 0) {
|
||||
nd_log_error("Failed to bind to interface: %s", strerror(errno));
|
||||
nd_io_close(io);
|
||||
return NULL;
|
||||
@ -389,8 +391,7 @@ nd_iface_t *nd_iface_open(const char *name, unsigned index)
|
||||
/* Immediate */
|
||||
|
||||
uint32_t enable = 1;
|
||||
if (ioctl(io->fd, BIOCIMMEDIATE, &enable) < 0)
|
||||
{
|
||||
if (ioctl(io->fd, BIOCIMMEDIATE, &enable) < 0) {
|
||||
nd_log_error("BIOCIMMEDIATE: %s", strerror(errno));
|
||||
nd_io_close(io);
|
||||
return NULL;
|
||||
@ -402,15 +403,13 @@ nd_iface_t *nd_iface_open(const char *name, unsigned index)
|
||||
uint8_t sysctl_buf[512];
|
||||
size_t sysctl_buflen = sizeof(sysctl_buf);
|
||||
|
||||
if (sysctl(mib, 6, sysctl_buf, &sysctl_buflen, NULL, 0) == -1)
|
||||
{
|
||||
if (sysctl(mib, 6, sysctl_buf, &sysctl_buflen, NULL, 0) == -1) {
|
||||
nd_log_error("Failed to determine link-layer address: %s", strerror(errno));
|
||||
nd_io_close(io);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ndL_configure_filter(io))
|
||||
{
|
||||
if (!ndL_configure_filter(io)) {
|
||||
nd_log_error("Could not configure filter: %s", strerror(errno));
|
||||
nd_io_close(io);
|
||||
return NULL;
|
||||
@ -421,10 +420,11 @@ nd_iface_t *nd_iface_open(const char *name, unsigned index)
|
||||
|
||||
iface = ndL_first_free_iface;
|
||||
|
||||
if (iface)
|
||||
if (iface) {
|
||||
ND_LL_DELETE(ndL_first_free_iface, iface, next);
|
||||
else
|
||||
} else {
|
||||
iface = ND_ALLOC(nd_iface_t);
|
||||
}
|
||||
|
||||
memset(iface, 0, sizeof(nd_iface_t));
|
||||
|
||||
@ -450,16 +450,18 @@ nd_iface_t *nd_iface_open(const char *name, unsigned index)
|
||||
|
||||
void nd_iface_close(nd_iface_t *iface)
|
||||
{
|
||||
if (--iface->refcount > 0)
|
||||
if (--iface->refcount > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nd_iface_no_restore_flags)
|
||||
{
|
||||
if (iface->old_promisc >= 0)
|
||||
if (!nd_iface_no_restore_flags) {
|
||||
if (iface->old_promisc >= 0) {
|
||||
nd_iface_set_promisc(iface, iface->old_promisc);
|
||||
if (iface->old_allmulti >= 0)
|
||||
}
|
||||
if (iface->old_allmulti >= 0) {
|
||||
nd_iface_set_allmulti(iface, iface->old_allmulti);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __linux__
|
||||
nd_io_close(iface->bpf_io);
|
||||
@ -518,8 +520,7 @@ static ssize_t ndL_send_icmp6(nd_iface_t *ifa, ndL_icmp6_msg_t *msg, size_t size
|
||||
|
||||
ssize_t nd_iface_write_na(nd_iface_t *iface, nd_addr_t *dst, uint8_t *dst_ll, nd_addr_t *tgt, bool router)
|
||||
{
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
struct ip6_hdr ip;
|
||||
struct nd_neighbor_advert na;
|
||||
struct nd_opt_hdr opt;
|
||||
@ -534,11 +535,13 @@ ssize_t nd_iface_write_na(nd_iface_t *iface, nd_addr_t *dst, uint8_t *dst_ll, nd
|
||||
msg.na.nd_na_type = ND_NEIGHBOR_ADVERT;
|
||||
msg.na.nd_na_target = *tgt;
|
||||
|
||||
if (nd_addr_is_multicast(dst))
|
||||
if (nd_addr_is_multicast(dst)) {
|
||||
msg.na.nd_na_flags_reserved |= ND_NA_FLAG_SOLICITED;
|
||||
}
|
||||
|
||||
if (router)
|
||||
if (router) {
|
||||
msg.na.nd_na_flags_reserved |= ND_NA_FLAG_ROUTER;
|
||||
}
|
||||
|
||||
msg.opt.nd_opt_type = ND_OPT_TARGET_LINKADDR;
|
||||
msg.opt.nd_opt_len = 1;
|
||||
@ -555,8 +558,7 @@ ssize_t nd_iface_write_na(nd_iface_t *iface, nd_addr_t *dst, uint8_t *dst_ll, nd
|
||||
|
||||
ssize_t nd_iface_write_ns(nd_iface_t *ifa, nd_addr_t *tgt)
|
||||
{
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
struct ip6_hdr ip;
|
||||
struct nd_neighbor_solicit ns;
|
||||
struct nd_opt_hdr opt;
|
||||
@ -595,8 +597,7 @@ bool nd_iface_startup()
|
||||
if (!(ndL_io = nd_io_socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IPV6))))
|
||||
return false;
|
||||
|
||||
if (!ndL_configure_filter(ndL_io))
|
||||
{
|
||||
if (!ndL_configure_filter(ndL_io)) {
|
||||
nd_io_close(ndL_io);
|
||||
ndL_io = NULL;
|
||||
nd_log_error("Failed to configure BPF: %s", strerror(errno));
|
||||
@ -616,25 +617,26 @@ bool nd_iface_set_allmulti(nd_iface_t *iface, bool on)
|
||||
struct ifreq ifr;
|
||||
memcpy(ifr.ifr_name, iface->name, IFNAMSIZ);
|
||||
|
||||
if (ioctl(ndL_io->fd, SIOCGIFFLAGS, &ifr) < 0)
|
||||
{
|
||||
if (ioctl(ndL_io->fd, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
nd_log_error("Failed to get interface flags: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (iface->old_allmulti < 0)
|
||||
if (iface->old_allmulti < 0) {
|
||||
iface->old_allmulti = (ifr.ifr_flags & IFF_ALLMULTI) != 0;
|
||||
}
|
||||
|
||||
if (on == ((ifr.ifr_flags & IFF_ALLMULTI) != 0))
|
||||
if (on == ((ifr.ifr_flags & IFF_ALLMULTI) != 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (on)
|
||||
if (on) {
|
||||
ifr.ifr_flags |= IFF_ALLMULTI;
|
||||
else
|
||||
} else {
|
||||
ifr.ifr_flags &= ~IFF_ALLMULTI;
|
||||
}
|
||||
|
||||
if (ioctl(ndL_io->fd, SIOCSIFFLAGS, &ifr) < 0)
|
||||
{
|
||||
if (ioctl(ndL_io->fd, SIOCSIFFLAGS, &ifr) < 0) {
|
||||
nd_log_error("Failed to set interface flags: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
@ -649,25 +651,26 @@ bool nd_iface_set_promisc(nd_iface_t *iface, bool on)
|
||||
struct ifreq ifr;
|
||||
memcpy(ifr.ifr_name, iface->name, IFNAMSIZ);
|
||||
|
||||
if (ioctl(ndL_io->fd, SIOCGIFFLAGS, &ifr) < 0)
|
||||
{
|
||||
if (ioctl(ndL_io->fd, SIOCGIFFLAGS, &ifr) < 0) {
|
||||
nd_log_error("Failed to get interface flags: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (iface->old_promisc < 0)
|
||||
if (iface->old_promisc < 0) {
|
||||
iface->old_promisc = (ifr.ifr_flags & IFF_PROMISC) != 0;
|
||||
}
|
||||
|
||||
if (on == ((ifr.ifr_flags & IFF_PROMISC) != 0))
|
||||
if (on == ((ifr.ifr_flags & IFF_PROMISC) != 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (on)
|
||||
if (on) {
|
||||
ifr.ifr_flags |= IFF_PROMISC;
|
||||
else
|
||||
} else {
|
||||
ifr.ifr_flags &= ~IFF_PROMISC;
|
||||
}
|
||||
|
||||
if (ioctl(ndL_io->fd, SIOCSIFFLAGS, &ifr) < 0)
|
||||
{
|
||||
if (ioctl(ndL_io->fd, SIOCSIFFLAGS, &ifr) < 0) {
|
||||
nd_log_error("Failed to set interface flags: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
@ -677,12 +680,12 @@ bool nd_iface_set_promisc(nd_iface_t *iface, bool on)
|
||||
|
||||
void nd_iface_cleanup()
|
||||
{
|
||||
ND_LL_FOREACH_S(ndL_first_iface, iface, tmp, next)
|
||||
{
|
||||
ND_LL_FOREACH_S (ndL_first_iface, iface, tmp, next) {
|
||||
iface->refcount = 1;
|
||||
nd_iface_close(iface);
|
||||
}
|
||||
|
||||
if (ndL_io)
|
||||
if (ndL_io) {
|
||||
nd_io_close(ndL_io);
|
||||
}
|
||||
}
|
||||
|
@ -21,8 +21,7 @@
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
struct nd_iface
|
||||
{
|
||||
struct nd_iface {
|
||||
nd_iface_t *next;
|
||||
int refcount;
|
||||
|
||||
|
77
src/io.c
77
src/io.c
@ -60,8 +60,7 @@ static void ndL_refresh_pollfds()
|
||||
|
||||
ND_LL_COUNT(ndL_first_io, count, next);
|
||||
|
||||
if (count > ndL_pollfds_size)
|
||||
{
|
||||
if (count > ndL_pollfds_size) {
|
||||
int new_pollfds_size = count * 2;
|
||||
|
||||
ndL_pollfds = (struct pollfd *)realloc(ndL_pollfds == ndL_static_pollfds ? NULL : ndL_pollfds,
|
||||
@ -72,8 +71,7 @@ static void ndL_refresh_pollfds()
|
||||
|
||||
int index = 0;
|
||||
|
||||
ND_LL_FOREACH(ndL_first_io, io, next)
|
||||
{
|
||||
ND_LL_FOREACH (ndL_first_io, io, next) {
|
||||
ndL_pollfds[index].fd = io->fd;
|
||||
ndL_pollfds[index].revents = 0;
|
||||
ndL_pollfds[index].events = POLLIN;
|
||||
@ -88,15 +86,13 @@ static nd_io_t *ndL_create(int fd)
|
||||
{
|
||||
int flags = fcntl(fd, F_GETFL, 0);
|
||||
|
||||
if (flags == -1)
|
||||
{
|
||||
if (flags == -1) {
|
||||
nd_log_error("Could not read flags: %s", strerror(errno));
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
|
||||
{
|
||||
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
|
||||
nd_log_error("Could not set flags: %s", strerror(errno));
|
||||
close(fd);
|
||||
return false;
|
||||
@ -104,10 +100,11 @@ static nd_io_t *ndL_create(int fd)
|
||||
|
||||
nd_io_t *io = ndL_first_free_io;
|
||||
|
||||
if (io)
|
||||
if (io) {
|
||||
ND_LL_DELETE(ndL_first_free_io, io, next);
|
||||
else
|
||||
} else {
|
||||
io = ND_ALLOC(nd_io_t);
|
||||
}
|
||||
|
||||
ND_LL_PREPEND(ndL_first_io, io, next);
|
||||
|
||||
@ -116,16 +113,14 @@ static nd_io_t *ndL_create(int fd)
|
||||
io->handler = NULL;
|
||||
|
||||
#ifndef NDPPD_NO_USE_EPOLL
|
||||
if (ndL_epoll_fd <= 0 && (ndL_epoll_fd = epoll_create(1)) < 0)
|
||||
{
|
||||
if (ndL_epoll_fd <= 0 && (ndL_epoll_fd = epoll_create(1)) < 0) {
|
||||
nd_log_error("epoll_create() failed: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct epoll_event event = { .events = EPOLLIN, .data.ptr = io };
|
||||
|
||||
if (epoll_ctl(ndL_epoll_fd, EPOLL_CTL_ADD, io->fd, &event) < 0)
|
||||
{
|
||||
if (epoll_ctl(ndL_epoll_fd, EPOLL_CTL_ADD, io->fd, &event) < 0) {
|
||||
nd_log_error("epoll_ctl() failed: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
@ -141,8 +136,7 @@ nd_io_t *nd_io_socket(int domain, int type, int protocol)
|
||||
{
|
||||
int fd = socket(domain, type, protocol);
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
if (fd == -1) {
|
||||
nd_log_error("nd_io_socket(): Could not create socket: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
@ -154,8 +148,9 @@ nd_io_t *nd_io_open(const char *file, int oflag)
|
||||
{
|
||||
int fd = open(file, oflag);
|
||||
|
||||
if (fd == -1)
|
||||
if (fd == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ndL_create(fd);
|
||||
}
|
||||
@ -186,8 +181,7 @@ ssize_t nd_io_send(nd_io_t *io, const struct sockaddr *addr, size_t addrlen, con
|
||||
|
||||
ssize_t len;
|
||||
|
||||
if ((len = sendmsg(io->fd, &mhdr, 0)) < 0)
|
||||
{
|
||||
if ((len = sendmsg(io->fd, &mhdr, 0)) < 0) {
|
||||
nd_log_error("nd_sio_send() failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
@ -210,10 +204,10 @@ ssize_t nd_io_recv(nd_io_t *io, struct sockaddr *addr, size_t addrlen, void *msg
|
||||
|
||||
int len;
|
||||
|
||||
if ((len = recvmsg(io->fd, &mhdr, 0)) < 0)
|
||||
{
|
||||
if (errno != EAGAIN)
|
||||
if ((len = recvmsg(io->fd, &mhdr, 0)) < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
nd_log_error("nd_sio_recv() failed: %s", strerror(errno));
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
@ -229,8 +223,9 @@ ssize_t nd_io_read(nd_io_t *io, void *buf, size_t count)
|
||||
ssize_t nd_io_write(nd_io_t *io, void *buf, size_t count)
|
||||
{
|
||||
ssize_t len = write(io->fd, buf, count);
|
||||
if (len < 0)
|
||||
if (len < 0) {
|
||||
nd_log_error("err: %s", strerror(errno));
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
@ -246,45 +241,43 @@ bool nd_io_poll()
|
||||
|
||||
int count = epoll_wait(ndL_epoll_fd, events, 8, 250);
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
if (count < 0) {
|
||||
nd_log_error("epoll() failed: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
for (int i = 0; i < count; i++) {
|
||||
nd_io_t *io = (nd_io_t *)events[i].data.ptr;
|
||||
|
||||
if (io->handler)
|
||||
io->handler(io, events[i].events);
|
||||
}
|
||||
#else
|
||||
if (ndL_dirty)
|
||||
{
|
||||
if (ndL_dirty) {
|
||||
ndL_refresh_pollfds();
|
||||
ndL_dirty = false;
|
||||
}
|
||||
|
||||
int len = poll(ndL_pollfds, ndL_pollfds_count, 250);
|
||||
|
||||
if (len < 0)
|
||||
if (len < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len == 0)
|
||||
if (len == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ndL_pollfds_count; i++)
|
||||
{
|
||||
if (ndL_pollfds[i].revents == 0)
|
||||
for (int i = 0; i < ndL_pollfds_count; i++) {
|
||||
if (ndL_pollfds[i].revents == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ND_LL_FOREACH(ndL_first_io, io, next)
|
||||
{
|
||||
if (io->fd == ndL_pollfds[i].fd)
|
||||
{
|
||||
if (io->handler != NULL)
|
||||
ND_LL_FOREACH (ndL_first_io, io, next) {
|
||||
if (io->fd == ndL_pollfds[i].fd) {
|
||||
if (io->handler != NULL) {
|
||||
io->handler(io, ndL_pollfds[i].revents);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@ -297,14 +290,12 @@ bool nd_io_poll()
|
||||
|
||||
void nd_io_cleanup()
|
||||
{
|
||||
ND_LL_FOREACH_S(ndL_first_io, sio, tmp, next)
|
||||
{
|
||||
ND_LL_FOREACH_S (ndL_first_io, sio, tmp, next) {
|
||||
nd_io_close(sio);
|
||||
}
|
||||
|
||||
#ifndef NDPPD_NO_USE_EPOLL
|
||||
if (ndL_epoll_fd > 0)
|
||||
{
|
||||
if (ndL_epoll_fd > 0) {
|
||||
close(ndL_epoll_fd);
|
||||
ndL_epoll_fd = 0;
|
||||
}
|
||||
|
3
src/io.h
3
src/io.h
@ -21,8 +21,7 @@
|
||||
|
||||
typedef void(nd_io_handler_t)(nd_io_t *io, int events);
|
||||
|
||||
struct nd_io
|
||||
{
|
||||
struct nd_io {
|
||||
nd_io_t *next;
|
||||
int fd;
|
||||
uintptr_t data;
|
||||
|
19
src/log.c
19
src/log.c
@ -31,8 +31,9 @@ bool nd_opt_syslog;
|
||||
|
||||
static void ndL_open_syslog()
|
||||
{
|
||||
if (ndL_syslog_opened)
|
||||
if (ndL_syslog_opened) {
|
||||
return;
|
||||
}
|
||||
|
||||
setlogmask(LOG_UPTO(LOG_DEBUG));
|
||||
openlog("ndppd", LOG_CONS | LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_DAEMON);
|
||||
@ -43,29 +44,29 @@ void nd_log_printf(nd_loglevel_t level, const char *fmt, ...)
|
||||
{
|
||||
assert(level >= 0 && level <= ND_LOG_TRACE);
|
||||
|
||||
if (level > nd_opt_verbosity)
|
||||
if (level > nd_opt_verbosity) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nd_daemonized || nd_opt_syslog)
|
||||
if (nd_daemonized || nd_opt_syslog) {
|
||||
ndL_open_syslog();
|
||||
}
|
||||
|
||||
char buf[512];
|
||||
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
|
||||
if (vsnprintf(buf, sizeof(buf), fmt, va) < 0)
|
||||
if (vsnprintf(buf, sizeof(buf), fmt, va) < 0) {
|
||||
abort();
|
||||
}
|
||||
|
||||
va_end(va);
|
||||
|
||||
if (ndL_syslog_opened)
|
||||
{
|
||||
if (ndL_syslog_opened) {
|
||||
const int pris[] = { LOG_ERR, LOG_INFO, LOG_DEBUG, LOG_DEBUG };
|
||||
syslog(pris[level], "%s", buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
const char *names[] = { "error", "info", "debug", "trace" };
|
||||
|
||||
time_t time = nd_current_time / 1000;
|
||||
|
@ -19,13 +19,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ND_LOG_ERROR,
|
||||
ND_LOG_INFO,
|
||||
ND_LOG_DEBUG,
|
||||
ND_LOG_TRACE
|
||||
} nd_loglevel_t;
|
||||
typedef enum { ND_LOG_ERROR, ND_LOG_INFO, ND_LOG_DEBUG, ND_LOG_TRACE } nd_loglevel_t;
|
||||
|
||||
extern nd_loglevel_t nd_opt_verbosity;
|
||||
extern bool nd_opt_syslog;
|
||||
|
71
src/ndppd.c
71
src/ndppd.c
@ -51,10 +51,10 @@ static bool ndL_check_pidfile()
|
||||
{
|
||||
int fd = open(nd_opt_pidfile_path, O_RDWR);
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
if (fd == -1) {
|
||||
if (errno == ENOENT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -68,32 +68,31 @@ static bool ndL_daemonize()
|
||||
{
|
||||
int fd = open(nd_opt_pidfile_path, O_WRONLY | O_CREAT, 0644);
|
||||
|
||||
if (fd == -1)
|
||||
if (fd == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (flock(fd, LOCK_EX | LOCK_NB) < 0)
|
||||
{
|
||||
if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
pid_t pid = fork();
|
||||
|
||||
if (pid < 0)
|
||||
{
|
||||
if (pid < 0) {
|
||||
// logger::error() << "Failed to fork during daemonize: " << logger::err();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pid > 0)
|
||||
{
|
||||
if (pid > 0) {
|
||||
char buf[21];
|
||||
int len = snprintf(buf, sizeof(buf), "%d", pid);
|
||||
|
||||
if (ftruncate(fd, 0) == -1)
|
||||
if (ftruncate(fd, 0) == -1) {
|
||||
nd_log_error("Failed to write PID file: ftruncate(): %s", strerror(errno));
|
||||
else if (write(fd, buf, len) != 0)
|
||||
} else if (write(fd, buf, len) != 0) {
|
||||
nd_log_error("Failed to write PID file: write(): %s", strerror(errno));
|
||||
}
|
||||
|
||||
nd_iface_no_restore_flags = true;
|
||||
exit(0);
|
||||
@ -102,14 +101,12 @@ static bool ndL_daemonize()
|
||||
umask(0);
|
||||
|
||||
pid_t sid = setsid();
|
||||
if (sid < 0)
|
||||
{
|
||||
if (sid < 0) {
|
||||
// logger::error() << "Failed to setsid during daemonize: " << logger::err();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (chdir("/") < 0)
|
||||
{
|
||||
if (chdir("/") < 0) {
|
||||
// logger::error() << "Failed to change path during daemonize: " << logger::err();
|
||||
return false;
|
||||
}
|
||||
@ -144,10 +141,8 @@ int main(int argc, char *argv[])
|
||||
{ "syslog", 0, 0, 1 }, { "pidfile", 1, 0, 'p' }, { NULL, 0, 0, 0 },
|
||||
};
|
||||
|
||||
for (int ch; (ch = getopt_long(argc, argv, "c:dp:v", long_options, NULL)) != -1;)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
for (int ch; (ch = getopt_long(argc, argv, "c:dp:v", long_options, NULL)) != -1;) {
|
||||
switch (ch) {
|
||||
case 'c':
|
||||
nd_opt_config_path = nd_strdup(optarg);
|
||||
break;
|
||||
@ -157,8 +152,9 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
if (nd_opt_verbosity < ND_LOG_ERROR)
|
||||
if (nd_opt_verbosity < ND_LOG_ERROR) {
|
||||
nd_opt_verbosity++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
@ -180,49 +176,52 @@ int main(int argc, char *argv[])
|
||||
|
||||
nd_log_info("ndppd " NDPPD_VERSION);
|
||||
|
||||
if (nd_opt_pidfile_path && !ndL_check_pidfile())
|
||||
{
|
||||
if (nd_opt_pidfile_path && !ndL_check_pidfile()) {
|
||||
nd_log_error("Failed to lock pidfile. Is ndppd already running?");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nd_opt_config_path == NULL)
|
||||
if (nd_opt_config_path == NULL) {
|
||||
nd_opt_config_path = NDPPD_CONFIG_PATH;
|
||||
}
|
||||
|
||||
nd_log_info("Loading configuration \"%s\"...", nd_opt_config_path);
|
||||
|
||||
if (!nd_conf_load(nd_opt_config_path))
|
||||
if (!nd_conf_load(nd_opt_config_path)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!nd_iface_startup())
|
||||
if (!nd_iface_startup()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!nd_proxy_startup())
|
||||
if (!nd_proxy_startup()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!nd_rt_open())
|
||||
if (!nd_rt_open()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nd_opt_daemonize && !ndL_daemonize())
|
||||
if (nd_opt_daemonize && !ndL_daemonize()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
nd_rt_query_routes();
|
||||
bool querying_routes = true;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (nd_current_time >= nd_rt_dump_timeout)
|
||||
while (1) {
|
||||
if (nd_current_time >= nd_rt_dump_timeout) {
|
||||
nd_rt_dump_timeout = 0;
|
||||
}
|
||||
|
||||
if (querying_routes && !nd_rt_dump_timeout)
|
||||
{
|
||||
if (querying_routes && !nd_rt_dump_timeout) {
|
||||
querying_routes = false;
|
||||
nl_rt_remove_owned_routes();
|
||||
nd_rt_query_addresses();
|
||||
}
|
||||
|
||||
if (!nd_io_poll())
|
||||
{
|
||||
if (!nd_io_poll()) {
|
||||
/* TODO: Error */
|
||||
break;
|
||||
}
|
||||
|
12
src/ndppd.h
12
src/ndppd.h
@ -40,15 +40,13 @@ extern bool nd_opt_daemonize;
|
||||
#define ND_ALIGNED(x) __attribute((aligned(x)))
|
||||
|
||||
#define ND_LL_PREPEND(head, el, next) \
|
||||
do \
|
||||
{ \
|
||||
do { \
|
||||
(el)->next = (head); \
|
||||
(head) = (el); \
|
||||
} while (0)
|
||||
|
||||
#define ND_LL_DELETE(head, el, next) \
|
||||
do \
|
||||
{ \
|
||||
do { \
|
||||
__typeof(el) _last = (head); \
|
||||
while (_last != NULL && _last->next != (el)) \
|
||||
_last = _last->next; \
|
||||
@ -59,8 +57,7 @@ extern bool nd_opt_daemonize;
|
||||
} while (0)
|
||||
|
||||
#define ND_LL_COUNT(head, count, next) \
|
||||
do \
|
||||
{ \
|
||||
do { \
|
||||
(count) = 0; \
|
||||
for (__typeof(head) _el = (head); _el; _el = _el->next) \
|
||||
(count)++; \
|
||||
@ -78,8 +75,7 @@ extern bool nd_opt_daemonize;
|
||||
#define ND_LL_FOREACH_NODEF(head, el, next) for ((el) = (head); (el); (el) = (el)->next)
|
||||
|
||||
#define ND_LL_SEARCH(head, el, next, pred) \
|
||||
do \
|
||||
{ \
|
||||
do { \
|
||||
for (el = (head); el && !(pred); el = el->next) \
|
||||
; \
|
||||
} while (0)
|
||||
|
30
src/proxy.c
30
src/proxy.c
@ -39,8 +39,7 @@ nd_proxy_t *nd_proxy_create(const char *ifname)
|
||||
|
||||
ND_LL_SEARCH(ndL_proxies, proxy, next, !strcmp(proxy->ifname, ifname));
|
||||
|
||||
if (proxy)
|
||||
{
|
||||
if (proxy) {
|
||||
nd_log_error("Proxy already exists for interface \"%s\"", ifname);
|
||||
return NULL;
|
||||
}
|
||||
@ -66,10 +65,8 @@ void nd_proxy_handle_ns(nd_proxy_t *proxy, nd_addr_t *src, nd_addr_t *dst, nd_ad
|
||||
|
||||
nd_session_t *session;
|
||||
|
||||
ND_LL_FOREACH_NODEF(proxy->sessions, session, next_in_proxy)
|
||||
{
|
||||
if (nd_addr_eq(&session->tgt, tgt))
|
||||
{
|
||||
ND_LL_FOREACH_NODEF (proxy->sessions, session, next_in_proxy) {
|
||||
if (nd_addr_eq(&session->tgt, tgt)) {
|
||||
nd_session_handle_ns(session, src, src_ll);
|
||||
return;
|
||||
}
|
||||
@ -81,18 +78,17 @@ void nd_proxy_handle_ns(nd_proxy_t *proxy, nd_addr_t *src, nd_addr_t *dst, nd_ad
|
||||
nd_rule_t *rule;
|
||||
ND_LL_SEARCH(proxy->rules, rule, next, nd_addr_match(&rule->addr, tgt, rule->prefix));
|
||||
|
||||
if (!rule)
|
||||
if (!rule) {
|
||||
return;
|
||||
}
|
||||
|
||||
nd_session_handle_ns(nd_session_create(rule, tgt), src, src_ll);
|
||||
}
|
||||
|
||||
void nd_proxy_update_all()
|
||||
{
|
||||
ND_LL_FOREACH(ndL_proxies, proxy, next)
|
||||
{
|
||||
ND_LL_FOREACH_S(proxy->sessions, session, tmp, next_in_proxy)
|
||||
{
|
||||
ND_LL_FOREACH (ndL_proxies, proxy, next) {
|
||||
ND_LL_FOREACH_S (proxy->sessions, session, tmp, next_in_proxy) {
|
||||
nd_session_update(session);
|
||||
}
|
||||
}
|
||||
@ -100,10 +96,10 @@ void nd_proxy_update_all()
|
||||
|
||||
bool nd_proxy_startup()
|
||||
{
|
||||
ND_LL_FOREACH(ndL_proxies, proxy, next)
|
||||
{
|
||||
if (!(proxy->iface = nd_iface_open(proxy->ifname, 0)))
|
||||
ND_LL_FOREACH (ndL_proxies, proxy, next) {
|
||||
if (!(proxy->iface = nd_iface_open(proxy->ifname, 0))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
proxy->iface->proxy = proxy;
|
||||
|
||||
@ -114,12 +110,12 @@ bool nd_proxy_startup()
|
||||
nd_iface_set_allmulti(proxy->iface, true);
|
||||
#endif
|
||||
|
||||
ND_LL_FOREACH(proxy->rules, rule, next)
|
||||
{
|
||||
if (rule->ifname[0] && !(rule->iface = nd_iface_open(rule->ifname, 0)))
|
||||
ND_LL_FOREACH (proxy->rules, rule, next) {
|
||||
if (rule->ifname[0] && !(rule->iface = nd_iface_open(rule->ifname, 0))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -21,8 +21,7 @@
|
||||
|
||||
#include "ndppd.h"
|
||||
|
||||
struct nd_proxy
|
||||
{
|
||||
struct nd_proxy {
|
||||
nd_proxy_t *next;
|
||||
char ifname[IF_NAMESIZE];
|
||||
|
||||
|
189
src/rt.c
189
src/rt.c
@ -60,17 +60,18 @@ static void ndL_new_route(nd_rt_route_t *route)
|
||||
{
|
||||
nd_rt_route_t *new_route;
|
||||
|
||||
ND_LL_FOREACH_NODEF(ndL_routes, new_route, next)
|
||||
{
|
||||
ND_LL_FOREACH_NODEF (ndL_routes, new_route, next) {
|
||||
if ((nd_addr_eq(&new_route->dst, &route->dst) && new_route->pflen == route->pflen &&
|
||||
new_route->table == route->table))
|
||||
new_route->table == route->table)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((new_route = ndL_free_routes))
|
||||
if ((new_route = ndL_free_routes)) {
|
||||
ND_LL_DELETE(ndL_free_routes, new_route, next);
|
||||
else
|
||||
} else {
|
||||
new_route = ND_ALLOC(nd_rt_route_t);
|
||||
}
|
||||
|
||||
*new_route = *route;
|
||||
|
||||
@ -78,21 +79,18 @@ static void ndL_new_route(nd_rt_route_t *route)
|
||||
|
||||
nd_rt_route_t *prev = NULL;
|
||||
|
||||
ND_LL_FOREACH(ndL_routes, cur, next)
|
||||
{
|
||||
if (new_route->pflen >= cur->pflen)
|
||||
ND_LL_FOREACH (ndL_routes, cur, next) {
|
||||
if (new_route->pflen >= cur->pflen) {
|
||||
break;
|
||||
}
|
||||
|
||||
prev = cur;
|
||||
}
|
||||
|
||||
if (prev)
|
||||
{
|
||||
if (prev) {
|
||||
new_route->next = prev->next;
|
||||
prev->next = new_route;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
ND_LL_PREPEND(ndL_routes, new_route, next);
|
||||
}
|
||||
|
||||
@ -104,22 +102,24 @@ static void ndL_delete_route(nd_rt_route_t *route)
|
||||
{
|
||||
nd_rt_route_t *prev = NULL, *cur;
|
||||
|
||||
ND_LL_FOREACH_NODEF(ndL_routes, cur, next)
|
||||
{
|
||||
ND_LL_FOREACH_NODEF (ndL_routes, cur, next) {
|
||||
if ((nd_addr_eq(&cur->dst, &route->dst) && cur->oif == route->oif && cur->pflen == route->pflen &&
|
||||
cur->table == route->table))
|
||||
cur->table == route->table)) {
|
||||
break;
|
||||
}
|
||||
|
||||
prev = cur;
|
||||
}
|
||||
|
||||
if (!cur)
|
||||
if (!cur) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (prev)
|
||||
if (prev) {
|
||||
prev->next = cur->next;
|
||||
else
|
||||
} else {
|
||||
ndL_routes = cur->next;
|
||||
}
|
||||
|
||||
nd_log_debug("rt: (event) delete route %s/%d dev %d table %d", //
|
||||
nd_aton(&cur->dst), cur->pflen, cur->oif, cur->table);
|
||||
@ -131,16 +131,17 @@ static void ndL_new_addr(unsigned index, nd_addr_t *addr, unsigned pflen)
|
||||
{
|
||||
nd_rt_addr_t *rt_addr;
|
||||
|
||||
ND_LL_FOREACH_NODEF(ndL_addrs, rt_addr, next)
|
||||
{
|
||||
if (rt_addr->iif == index && nd_addr_eq(&rt_addr->addr, addr) && rt_addr->pflen == pflen)
|
||||
ND_LL_FOREACH_NODEF (ndL_addrs, rt_addr, next) {
|
||||
if (rt_addr->iif == index && nd_addr_eq(&rt_addr->addr, addr) && rt_addr->pflen == pflen) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((rt_addr = ndL_free_addrs))
|
||||
if ((rt_addr = ndL_free_addrs)) {
|
||||
ND_LL_DELETE(ndL_free_addrs, rt_addr, next);
|
||||
else
|
||||
} else {
|
||||
rt_addr = ND_ALLOC(nd_rt_addr_t);
|
||||
}
|
||||
|
||||
ND_LL_PREPEND(ndL_addrs, rt_addr, next);
|
||||
|
||||
@ -155,16 +156,15 @@ static void ndL_delete_addr(unsigned int index, nd_addr_t *addr, unsigned pflen)
|
||||
{
|
||||
nd_rt_addr_t *prev = NULL, *rt_addr;
|
||||
|
||||
ND_LL_FOREACH_NODEF(ndL_addrs, rt_addr, next)
|
||||
{
|
||||
if (rt_addr->iif == index && nd_addr_eq(&rt_addr->addr, addr) && rt_addr->pflen == pflen)
|
||||
{
|
||||
ND_LL_FOREACH_NODEF (ndL_addrs, rt_addr, next) {
|
||||
if (rt_addr->iif == index && nd_addr_eq(&rt_addr->addr, addr) && rt_addr->pflen == pflen) {
|
||||
nd_log_debug("rt: (event) delete address %s/%d if %d", nd_aton(addr), pflen, index);
|
||||
|
||||
if (prev)
|
||||
if (prev) {
|
||||
prev->next = rt_addr->next;
|
||||
else
|
||||
} else {
|
||||
ndL_addrs = rt_addr->next;
|
||||
}
|
||||
|
||||
ND_LL_PREPEND(ndL_free_addrs, rt_addr, next);
|
||||
return;
|
||||
@ -179,8 +179,7 @@ static void ndL_handle_newaddr(struct ifaddrmsg *msg, int length)
|
||||
{
|
||||
nd_addr_t *addr = NULL;
|
||||
|
||||
for (struct rtattr *rta = IFA_RTA(msg); RTA_OK(rta, length); rta = RTA_NEXT(rta, length))
|
||||
{
|
||||
for (struct rtattr *rta = IFA_RTA(msg); RTA_OK(rta, length); rta = RTA_NEXT(rta, length)) {
|
||||
if (rta->rta_type == IFA_ADDRESS)
|
||||
addr = (nd_addr_t *)RTA_DATA(rta);
|
||||
}
|
||||
@ -195,8 +194,7 @@ static void ndL_handle_deladdr(struct ifaddrmsg *msg, int length)
|
||||
{
|
||||
nd_addr_t *addr = NULL;
|
||||
|
||||
for (struct rtattr *rta = IFA_RTA(msg); RTA_OK(rta, length); rta = RTA_NEXT(rta, length))
|
||||
{
|
||||
for (struct rtattr *rta = IFA_RTA(msg); RTA_OK(rta, length); rta = RTA_NEXT(rta, length)) {
|
||||
if (rta->rta_type == IFA_ADDRESS)
|
||||
addr = (nd_addr_t *)RTA_DATA(rta);
|
||||
}
|
||||
@ -212,8 +210,7 @@ static void ndL_handle_newroute(struct rtmsg *msg, int rtl)
|
||||
nd_addr_t *dst = NULL;
|
||||
int oif = 0;
|
||||
|
||||
for (struct rtattr *rta = RTM_RTA(msg); RTA_OK(rta, rtl); rta = RTA_NEXT(rta, rtl))
|
||||
{
|
||||
for (struct rtattr *rta = RTM_RTA(msg); RTA_OK(rta, rtl); rta = RTA_NEXT(rta, rtl)) {
|
||||
if (rta->rta_type == RTA_OIF)
|
||||
oif = *(int *)RTA_DATA(rta);
|
||||
else if (rta->rta_type == RTA_DST)
|
||||
@ -239,8 +236,7 @@ static void ndL_handle_delroute(struct rtmsg *msg, int rtl)
|
||||
nd_addr_t *dst = NULL;
|
||||
int oif = 0;
|
||||
|
||||
for (struct rtattr *rta = RTM_RTA(msg); RTA_OK(rta, rtl); rta = RTA_NEXT(rta, rtl))
|
||||
{
|
||||
for (struct rtattr *rta = RTM_RTA(msg); RTA_OK(rta, rtl); rta = RTA_NEXT(rta, rtl)) {
|
||||
if (rta->rta_type == RTA_OIF)
|
||||
oif = *(int *)RTA_DATA(rta);
|
||||
else if (rta->rta_type == RTA_DST)
|
||||
@ -264,23 +260,19 @@ static void ndL_io_handler(__attribute__((unused)) nd_io_t *unused1, __attribute
|
||||
{
|
||||
uint8_t buf[4096];
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;) {
|
||||
ssize_t len = nd_io_recv(ndL_io, NULL, 0, buf, sizeof(buf));
|
||||
|
||||
if (len < 0)
|
||||
return;
|
||||
|
||||
for (struct nlmsghdr *hdr = (struct nlmsghdr *)buf; NLMSG_OK(hdr, len); hdr = NLMSG_NEXT(hdr, len))
|
||||
{
|
||||
if (hdr->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
for (struct nlmsghdr *hdr = (struct nlmsghdr *)buf; NLMSG_OK(hdr, len); hdr = NLMSG_NEXT(hdr, len)) {
|
||||
if (hdr->nlmsg_type == NLMSG_DONE) {
|
||||
nd_rt_dump_timeout = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (hdr->nlmsg_type == NLMSG_ERROR)
|
||||
{
|
||||
if (hdr->nlmsg_type == NLMSG_ERROR) {
|
||||
struct nlmsgerr *e = (struct nlmsgerr *)NLMSG_DATA(hdr);
|
||||
nd_log_error("rt: Netlink: %s (%d)", strerror(-e->error), e->msg.nlmsg_type);
|
||||
continue;
|
||||
@ -300,15 +292,11 @@ static void ndL_io_handler(__attribute__((unused)) nd_io_t *unused1, __attribute
|
||||
#else
|
||||
static void ndL_get_rtas(int addrs, struct sockaddr *sa, struct sockaddr **rtas)
|
||||
{
|
||||
for (int i = 0; i < RTAX_MAX; i++)
|
||||
{
|
||||
if (addrs & (1 << i))
|
||||
{
|
||||
for (int i = 0; i < RTAX_MAX; i++) {
|
||||
if (addrs & (1 << i)) {
|
||||
rtas[i] = sa;
|
||||
sa = (void *)sa + ((sa->sa_len + sizeof(u_long) - 1) & ~(sizeof(u_long) - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
rtas[i] = NULL;
|
||||
}
|
||||
}
|
||||
@ -319,8 +307,9 @@ static void ndL_handle_rt(struct rt_msghdr *hdr)
|
||||
struct sockaddr *rtas[RTAX_MAX];
|
||||
ndL_get_rtas(hdr->rtm_addrs, (struct sockaddr *)(hdr + 1), rtas);
|
||||
|
||||
if (!rtas[RTAX_DST] || rtas[RTAX_DST]->sa_family != AF_INET6)
|
||||
if (!rtas[RTAX_DST] || rtas[RTAX_DST]->sa_family != AF_INET6) {
|
||||
return;
|
||||
}
|
||||
|
||||
int pflen = rtas[RTAX_NETMASK] ? nd_mask_to_pflen(&((struct sockaddr_in6 *)rtas[RTAX_NETMASK])->sin6_addr) : 128;
|
||||
|
||||
@ -338,10 +327,11 @@ static void ndL_handle_rt(struct rt_msghdr *hdr)
|
||||
.owned = (hdr->rtm_flags & RTF_PROTO3) != 0,
|
||||
};
|
||||
|
||||
if (hdr->rtm_type == RTM_GET || hdr->rtm_type == RTM_ADD)
|
||||
if (hdr->rtm_type == RTM_GET || hdr->rtm_type == RTM_ADD) {
|
||||
ndL_new_route(&route);
|
||||
else if (hdr->rtm_type == RTM_DELETE)
|
||||
} else if (hdr->rtm_type == RTM_DELETE) {
|
||||
ndL_delete_route(&route);
|
||||
}
|
||||
}
|
||||
|
||||
static void ndL_handle_ifa(struct ifa_msghdr *hdr)
|
||||
@ -349,21 +339,22 @@ static void ndL_handle_ifa(struct ifa_msghdr *hdr)
|
||||
struct sockaddr *rtas[RTAX_MAX];
|
||||
ndL_get_rtas(hdr->ifam_addrs, (struct sockaddr *)(hdr + 1), rtas);
|
||||
|
||||
if (!rtas[RTAX_IFA] || rtas[RTAX_IFA]->sa_family != AF_INET6)
|
||||
if (!rtas[RTAX_IFA] || rtas[RTAX_IFA]->sa_family != AF_INET6) {
|
||||
return;
|
||||
}
|
||||
|
||||
int pflen = rtas[RTAX_NETMASK] ? nd_mask_to_pflen(&((struct sockaddr_in6 *)rtas[RTAX_NETMASK])->sin6_addr) : 128;
|
||||
|
||||
nd_addr_t *ifa = &((struct sockaddr_in6 *)rtas[RTAX_IFA])->sin6_addr;
|
||||
|
||||
if (hdr->ifam_type == RTM_NEWADDR)
|
||||
if (hdr->ifam_type == RTM_NEWADDR) {
|
||||
ndL_new_addr(hdr->ifam_index, ifa, pflen);
|
||||
else if (hdr->ifam_type == RTM_DELADDR)
|
||||
} else if (hdr->ifam_type == RTM_DELADDR) {
|
||||
ndL_delete_addr(hdr->ifam_index, ifa, pflen);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
u_short msglen;
|
||||
u_char version;
|
||||
u_char type;
|
||||
@ -371,16 +362,15 @@ typedef struct
|
||||
|
||||
static void ndL_handle(void *buf, size_t buflen)
|
||||
{
|
||||
for (size_t i = 0; i < buflen;)
|
||||
{
|
||||
for (size_t i = 0; i < buflen;) {
|
||||
ndL_msghdr_t *hdr = (ndL_msghdr_t *)(buf + i);
|
||||
i += hdr->msglen;
|
||||
|
||||
if (i > buflen)
|
||||
if (i > buflen) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (hdr->type)
|
||||
{
|
||||
switch (hdr->type) {
|
||||
case RTM_ADD:
|
||||
case RTM_GET:
|
||||
case RTM_DELETE:
|
||||
@ -400,8 +390,7 @@ static bool ndL_dump(int type)
|
||||
int mib[] = { CTL_NET, PF_ROUTE, 0, 0, type, 0 };
|
||||
|
||||
size_t size;
|
||||
if (sysctl(mib, 6, NULL, &size, NULL, 0) < 0)
|
||||
{
|
||||
if (sysctl(mib, 6, NULL, &size, NULL, 0) < 0) {
|
||||
nd_log_error("sysctl(): %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
@ -409,8 +398,7 @@ static bool ndL_dump(int type)
|
||||
void *buf = malloc(size);
|
||||
|
||||
// FIXME: Potential race condition as the number of routes might have increased since the previous syscall().
|
||||
if (sysctl(mib, 6, buf, &size, NULL, 0) < 0)
|
||||
{
|
||||
if (sysctl(mib, 6, buf, &size, NULL, 0) < 0) {
|
||||
free(buf);
|
||||
nd_log_error("sysctl(): %s", strerror(errno));
|
||||
return false;
|
||||
@ -426,12 +414,12 @@ static void ndL_io_handler(__attribute__((unused)) nd_io_t *unused1, __attribute
|
||||
{
|
||||
uint8_t buf[4096];
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;) {
|
||||
ssize_t len = nd_io_recv(ndL_io, NULL, 0, buf, sizeof(buf));
|
||||
|
||||
if (len < 0)
|
||||
if (len < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ndL_handle(buf, len);
|
||||
}
|
||||
@ -441,12 +429,12 @@ static void ndL_io_handler(__attribute__((unused)) nd_io_t *unused1, __attribute
|
||||
|
||||
bool nd_rt_open()
|
||||
{
|
||||
if (ndL_io != NULL)
|
||||
if (ndL_io != NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
if (!(ndL_io = nd_io_socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)))
|
||||
{
|
||||
if (!(ndL_io = nd_io_socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE))) {
|
||||
nd_log_error("Failed to open netlink socket: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
@ -456,16 +444,14 @@ bool nd_rt_open()
|
||||
addr.nl_family = AF_NETLINK;
|
||||
addr.nl_groups = (1 << (RTNLGRP_IPV6_IFADDR - 1)) | (1 << (RTNLGRP_IPV6_ROUTE - 1));
|
||||
|
||||
if (!nd_io_bind(ndL_io, (struct sockaddr *)&addr, sizeof(addr)))
|
||||
{
|
||||
if (!nd_io_bind(ndL_io, (struct sockaddr *)&addr, sizeof(addr))) {
|
||||
nd_log_error("Failed to bind netlink socket: %s", strerror(errno));
|
||||
nd_io_close(ndL_io);
|
||||
ndL_io = NULL;
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if (!(ndL_io = nd_io_socket(AF_ROUTE, SOCK_RAW, AF_INET6)))
|
||||
{
|
||||
if (!(ndL_io = nd_io_socket(AF_ROUTE, SOCK_RAW, AF_INET6))) {
|
||||
nd_log_error("Failed to open routing socket: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
@ -478,8 +464,9 @@ bool nd_rt_open()
|
||||
|
||||
void nd_rt_cleanup()
|
||||
{
|
||||
if (ndL_io)
|
||||
if (ndL_io) {
|
||||
nd_io_close(ndL_io);
|
||||
}
|
||||
}
|
||||
|
||||
bool nd_rt_query_routes()
|
||||
@ -488,8 +475,7 @@ bool nd_rt_query_routes()
|
||||
if (nd_rt_dump_timeout)
|
||||
return false;
|
||||
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
struct nlmsghdr hdr;
|
||||
struct rtmsg msg;
|
||||
} req;
|
||||
@ -523,8 +509,7 @@ bool nd_rt_query_addresses()
|
||||
if (nd_rt_dump_timeout)
|
||||
return false;
|
||||
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
struct nlmsghdr hdr;
|
||||
struct ifaddrmsg msg;
|
||||
} req;
|
||||
@ -553,11 +538,11 @@ bool nd_rt_query_addresses()
|
||||
|
||||
nd_rt_route_t *nd_rt_find_route(nd_addr_t *addr, unsigned table)
|
||||
{
|
||||
ND_LL_FOREACH(ndL_routes, route, next)
|
||||
{
|
||||
if (nd_addr_match(&route->dst, addr, route->pflen) && route->table == table)
|
||||
ND_LL_FOREACH (ndL_routes, route, next) {
|
||||
if (nd_addr_match(&route->dst, addr, route->pflen) && route->table == table) {
|
||||
return route;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -565,16 +550,15 @@ nd_rt_route_t *nd_rt_find_route(nd_addr_t *addr, unsigned table)
|
||||
bool nd_rt_add_route(nd_addr_t *dst, unsigned pflen, unsigned oif, unsigned table)
|
||||
{
|
||||
#ifdef __linux__
|
||||
struct __attribute__((packed))
|
||||
{
|
||||
struct __attribute__((packed)) {
|
||||
struct nlmsghdr hdr;
|
||||
struct rtmsg msg;
|
||||
struct rtattr oif_attr __attribute__((aligned(NLMSG_ALIGNTO)));
|
||||
uint32_t oif;
|
||||
struct rtattr dst_attr __attribute__((aligned(RTA_ALIGNTO)));
|
||||
nd_addr_t dst;
|
||||
//struct rtattr exp_attr __attribute__((aligned(RTA_ALIGNTO)));
|
||||
//uint32_t exp;
|
||||
// struct rtattr exp_attr __attribute__((aligned(RTA_ALIGNTO)));
|
||||
// uint32_t exp;
|
||||
} req;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
@ -593,9 +577,9 @@ bool nd_rt_add_route(nd_addr_t *dst, unsigned pflen, unsigned oif, unsigned tabl
|
||||
req.dst_attr.rta_len = RTA_LENGTH(sizeof(req.dst));
|
||||
req.dst = *dst;
|
||||
|
||||
//req.exp_attr.rta_type = RTA_EXPIRES;
|
||||
//req.exp_attr.rta_len = RTA_LENGTH(sizeof(req.exp));
|
||||
//req.exp = 60;
|
||||
// req.exp_attr.rta_type = RTA_EXPIRES;
|
||||
// req.exp_attr.rta_len = RTA_LENGTH(sizeof(req.exp));
|
||||
// req.exp = 60;
|
||||
|
||||
req.hdr.nlmsg_type = RTM_NEWROUTE;
|
||||
req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
|
||||
@ -607,8 +591,7 @@ bool nd_rt_add_route(nd_addr_t *dst, unsigned pflen, unsigned oif, unsigned tabl
|
||||
|
||||
return nd_io_send(ndL_io, (struct sockaddr *)&addr, sizeof(addr), &req, sizeof(req)) >= 0;
|
||||
#else
|
||||
struct
|
||||
{
|
||||
struct {
|
||||
struct rt_msghdr hdr;
|
||||
struct sockaddr_in6 dst;
|
||||
struct sockaddr_dl dl __aligned(sizeof(u_long));
|
||||
@ -652,8 +635,7 @@ bool nd_rt_add_route(nd_addr_t *dst, unsigned pflen, unsigned oif, unsigned tabl
|
||||
bool nd_rt_remove_route(nd_addr_t *dst, unsigned pflen, unsigned table)
|
||||
{
|
||||
#ifdef __linux__
|
||||
struct __attribute__((packed))
|
||||
{
|
||||
struct __attribute__((packed)) {
|
||||
struct nlmsghdr hdr;
|
||||
struct rtmsg msg;
|
||||
struct rtattr dst_attr __attribute__((aligned(NLMSG_ALIGNTO)));
|
||||
@ -682,8 +664,7 @@ bool nd_rt_remove_route(nd_addr_t *dst, unsigned pflen, unsigned table)
|
||||
|
||||
return nd_io_send(ndL_io, (struct sockaddr *)&addr, sizeof(addr), &req, sizeof(req)) >= 0;
|
||||
#else
|
||||
struct __attribute__((packed))
|
||||
{
|
||||
struct __attribute__((packed)) {
|
||||
struct rt_msghdr hdr;
|
||||
struct sockaddr_in6 dst;
|
||||
struct sockaddr_in6 mask __aligned(sizeof(u_long));
|
||||
@ -718,9 +699,9 @@ bool nd_rt_remove_route(nd_addr_t *dst, unsigned pflen, unsigned table)
|
||||
|
||||
void nl_rt_remove_owned_routes()
|
||||
{
|
||||
ND_LL_FOREACH_S(ndL_routes, route, tmp, next)
|
||||
{
|
||||
if (route->owned)
|
||||
ND_LL_FOREACH_S (ndL_routes, route, tmp, next) {
|
||||
if (route->owned) {
|
||||
nd_rt_remove_route(&route->dst, route->pflen, route->table);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
6
src/rt.h
6
src/rt.h
@ -22,8 +22,7 @@
|
||||
typedef struct nd_rt_route nd_rt_route_t;
|
||||
typedef struct nd_rt_addr nd_rt_addr_t;
|
||||
|
||||
struct nd_rt_route
|
||||
{
|
||||
struct nd_rt_route {
|
||||
nd_rt_route_t *next;
|
||||
nd_addr_t dst;
|
||||
unsigned oif;
|
||||
@ -32,8 +31,7 @@ struct nd_rt_route
|
||||
bool owned; // If this route is owned by ndppd.
|
||||
};
|
||||
|
||||
struct nd_rt_addr
|
||||
{
|
||||
struct nd_rt_addr {
|
||||
nd_rt_addr_t *next;
|
||||
unsigned iif;
|
||||
nd_addr_t addr;
|
||||
|
@ -16,9 +16,9 @@
|
||||
// along with ndppd. If not, see <https://www.gnu.org/licenses/>.
|
||||
#include <string.h>
|
||||
|
||||
#include "rule.h"
|
||||
#include "ndppd.h"
|
||||
#include "proxy.h"
|
||||
#include "rule.h"
|
||||
|
||||
nd_rule_t *nd_rule_create(nd_proxy_t *proxy)
|
||||
{
|
||||
|
@ -21,16 +21,14 @@
|
||||
|
||||
#include "ndppd.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
ND_MODE_UNKNOWN,
|
||||
ND_MODE_STATIC,
|
||||
ND_MODE_IFACE, // Use a specific interface
|
||||
ND_MODE_AUTO,
|
||||
} nd_mode_t;
|
||||
|
||||
struct nd_rule
|
||||
{
|
||||
struct nd_rule {
|
||||
nd_rule_t *next;
|
||||
nd_proxy_t *proxy;
|
||||
|
||||
|
@ -35,8 +35,7 @@ static nd_session_t *ndL_free_sessions;
|
||||
|
||||
static void ndL_up(nd_session_t *session)
|
||||
{
|
||||
if (session->iface && !session->autowired && session->rule->autowire)
|
||||
{
|
||||
if (session->iface && !session->autowired && session->rule->autowire) {
|
||||
nd_rt_add_route(&session->tgt, 128, session->iface->index, session->rule->table);
|
||||
session->autowired = true;
|
||||
}
|
||||
@ -44,8 +43,7 @@ static void ndL_up(nd_session_t *session)
|
||||
|
||||
static void ndL_down(nd_session_t *session)
|
||||
{
|
||||
if (session->iface && session->autowired)
|
||||
{
|
||||
if (session->iface && session->autowired) {
|
||||
nd_rt_remove_route(&session->tgt, 128, session->rule->table);
|
||||
session->autowired = false;
|
||||
}
|
||||
@ -55,16 +53,16 @@ void nd_session_handle_ns(nd_session_t *session, nd_addr_t *src, uint8_t *src_ll
|
||||
{
|
||||
session->ins_time = nd_current_time;
|
||||
|
||||
if (session->state != ND_STATE_VALID && session->state != ND_STATE_STALE)
|
||||
if (session->state != ND_STATE_VALID && session->state != ND_STATE_STALE) {
|
||||
return;
|
||||
}
|
||||
|
||||
nd_iface_write_na(session->rule->proxy->iface, src, src_ll, &session->tgt, session->rule->proxy->router);
|
||||
}
|
||||
|
||||
void nd_session_handle_na(nd_session_t *session)
|
||||
{
|
||||
if (session->state != ND_STATE_VALID)
|
||||
{
|
||||
if (session->state != ND_STATE_VALID) {
|
||||
nd_log_debug("session [%s] %s -> VALID", session->rule->proxy->ifname, nd_aton(&session->tgt));
|
||||
|
||||
ndL_up(session);
|
||||
@ -77,10 +75,11 @@ nd_session_t *nd_session_create(nd_rule_t *rule, nd_addr_t *tgt)
|
||||
{
|
||||
nd_session_t *session = ndL_free_sessions;
|
||||
|
||||
if (session)
|
||||
if (session) {
|
||||
ND_LL_DELETE(ndL_free_sessions, session, next_in_proxy);
|
||||
else
|
||||
} else {
|
||||
session = ND_ALLOC(nd_session_t);
|
||||
}
|
||||
|
||||
ND_LL_PREPEND(rule->proxy->sessions, session, next_in_proxy);
|
||||
|
||||
@ -92,32 +91,25 @@ nd_session_t *nd_session_create(nd_rule_t *rule, nd_addr_t *tgt)
|
||||
|
||||
nd_addr_combine(&rule->rewrite_tgt, tgt, rule->rewrite_pflen, &session->real_tgt);
|
||||
|
||||
if (rule->mode == ND_MODE_AUTO)
|
||||
{
|
||||
if (rule->mode == ND_MODE_AUTO) {
|
||||
nd_rt_route_t *route = nd_rt_find_route(tgt, rule->table);
|
||||
|
||||
if (!route || route->oif == rule->proxy->iface->index || !(session->iface = nd_iface_open(NULL, route->oif)))
|
||||
{
|
||||
if (!route || route->oif == rule->proxy->iface->index || !(session->iface = nd_iface_open(NULL, route->oif))) {
|
||||
session->state = ND_STATE_INVALID;
|
||||
return session;
|
||||
}
|
||||
}
|
||||
else if ((session->iface = rule->iface))
|
||||
{
|
||||
} else if ((session->iface = rule->iface)) {
|
||||
session->iface->refcount++;
|
||||
}
|
||||
|
||||
if (session->iface)
|
||||
{
|
||||
if (session->iface) {
|
||||
ND_LL_PREPEND(session->iface->sessions, session, next_in_iface);
|
||||
|
||||
session->state = ND_STATE_INCOMPLETE;
|
||||
session->ons_count = 1;
|
||||
session->ons_time = nd_current_time;
|
||||
nd_iface_write_ns(session->iface, &session->real_tgt);
|
||||
}
|
||||
else if (rule->mode == ND_MODE_STATIC)
|
||||
{
|
||||
} else if (rule->mode == ND_MODE_STATIC) {
|
||||
session->state = ND_STATE_VALID;
|
||||
}
|
||||
|
||||
@ -126,14 +118,13 @@ nd_session_t *nd_session_create(nd_rule_t *rule, nd_addr_t *tgt)
|
||||
|
||||
void nd_session_update(nd_session_t *session)
|
||||
{
|
||||
switch (session->state)
|
||||
{
|
||||
switch (session->state) {
|
||||
case ND_STATE_INCOMPLETE:
|
||||
if (nd_current_time - session->ons_time < nd_conf_retrans_time)
|
||||
if (nd_current_time - session->ons_time < nd_conf_retrans_time) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (++session->ons_count > nd_conf_retrans_limit)
|
||||
{
|
||||
if (++session->ons_count > nd_conf_retrans_limit) {
|
||||
session->state = ND_STATE_INVALID;
|
||||
session->state_time = nd_current_time;
|
||||
nd_log_debug("session [%s] %s INCOMPLETE -> INVALID", //
|
||||
@ -145,13 +136,13 @@ void nd_session_update(nd_session_t *session)
|
||||
break;
|
||||
|
||||
case ND_STATE_INVALID:
|
||||
if (nd_current_time - session->state_time < nd_conf_invalid_ttl)
|
||||
if (nd_current_time - session->state_time < nd_conf_invalid_ttl) {
|
||||
break;
|
||||
}
|
||||
|
||||
ndL_down(session);
|
||||
|
||||
if (session->iface)
|
||||
{
|
||||
if (session->iface) {
|
||||
ND_LL_DELETE(session->iface->sessions, session, next_in_iface);
|
||||
nd_iface_close(session->iface);
|
||||
}
|
||||
@ -164,8 +155,9 @@ void nd_session_update(nd_session_t *session)
|
||||
break;
|
||||
|
||||
case ND_STATE_VALID:
|
||||
if (nd_current_time - session->state_time < nd_conf_valid_ttl)
|
||||
if (nd_current_time - session->state_time < nd_conf_valid_ttl) {
|
||||
break;
|
||||
}
|
||||
|
||||
session->state = ND_STATE_STALE;
|
||||
session->state_time = nd_current_time;
|
||||
@ -174,41 +166,37 @@ void nd_session_update(nd_session_t *session)
|
||||
nd_log_debug("session [%s] %s VALID -> STALE", //
|
||||
session->rule->proxy->ifname, nd_aton(&session->tgt));
|
||||
|
||||
if (nd_conf_keepalive || nd_current_time - session->ins_time < nd_conf_valid_ttl)
|
||||
{
|
||||
if (nd_conf_keepalive || nd_current_time - session->ins_time < nd_conf_valid_ttl) {
|
||||
session->ons_count = 1;
|
||||
nd_iface_write_ns(session->iface, &session->real_tgt);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
session->ons_count = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ND_STATE_STALE:
|
||||
if (nd_current_time - session->state_time >= nd_conf_stale_ttl)
|
||||
{
|
||||
if (nd_current_time - session->state_time >= nd_conf_stale_ttl) {
|
||||
session->state = ND_STATE_INVALID;
|
||||
session->state_time = nd_current_time;
|
||||
|
||||
nd_log_debug("session [%s] %s STALE -> INVALID", //
|
||||
session->rule->proxy->ifname, nd_aton(&session->tgt));
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// We will only retransmit if nd_conf_keepalive is true, or if the last incoming NS
|
||||
// request was made less than nd_conf_valid_ttl milliseconds ago.
|
||||
|
||||
if (!nd_conf_keepalive && nd_current_time - session->ins_time > nd_conf_valid_ttl)
|
||||
if (!nd_conf_keepalive && nd_current_time - session->ins_time > nd_conf_valid_ttl) {
|
||||
break;
|
||||
}
|
||||
|
||||
long time = session->ons_count && !(session->ons_count % nd_conf_retrans_limit)
|
||||
? ((1 << session->ons_count / 3) * nd_conf_retrans_time)
|
||||
: nd_conf_retrans_time;
|
||||
|
||||
if (nd_current_time - session->ons_time < time)
|
||||
if (nd_current_time - session->ons_time < time) {
|
||||
break;
|
||||
}
|
||||
|
||||
session->ons_count++;
|
||||
session->ons_time = nd_current_time;
|
||||
|
@ -20,8 +20,7 @@
|
||||
#include "ndppd.h"
|
||||
#include "rt.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
//! Address resolution is in progress.
|
||||
ND_STATE_INCOMPLETE,
|
||||
|
||||
@ -35,8 +34,7 @@ typedef enum
|
||||
|
||||
} nd_state_t;
|
||||
|
||||
struct nd_session
|
||||
{
|
||||
struct nd_session {
|
||||
nd_session_t *next_in_proxy;
|
||||
nd_session_t *next_in_iface;
|
||||
nd_rule_t *rule;
|
||||
|
Loading…
x
Reference in New Issue
Block a user