parent
87cd8abe9e
commit
4db6b7f7a5
79
src/addr.c
79
src/addr.c
@ -18,6 +18,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#ifndef __linux__
|
||||
# include <netinet/in.h>
|
||||
# include <sys/socket.h>
|
||||
# define s6_addr32 __u6_addr.__u6_addr32
|
||||
#endif
|
||||
@ -86,9 +87,9 @@ bool nd_addr_match(nd_addr_t *first, nd_addr_t *second, unsigned pflen)
|
||||
else if (pflen == 128)
|
||||
return nd_addr_eq(first, second);
|
||||
|
||||
for (unsigned i = 0, top = (pflen - 1) >> 5U; i <= top; i++)
|
||||
for (unsigned i = 0, top = (pflen - 1) >> 5; i <= top; i++)
|
||||
{
|
||||
uint32_t mask = i < top ? 0xffffffff : ndL_masks[(pflen - 1) & 31U];
|
||||
uint32_t mask = i < top ? 0xffffffff : ndL_masks[(pflen - 1) & 31];
|
||||
|
||||
if ((first->s6_addr32[i] ^ second->s6_addr32[i]) & mask)
|
||||
return false;
|
||||
@ -97,6 +98,34 @@ bool nd_addr_match(nd_addr_t *first, nd_addr_t *second, unsigned pflen)
|
||||
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)
|
||||
{
|
||||
*result = *second;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pflen >= 128)
|
||||
{
|
||||
*result = *first;
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
result->s6_addr32[i] = first->s6_addr32[i];
|
||||
else
|
||||
result->s6_addr32[i] = second->s6_addr32[i];
|
||||
}
|
||||
}
|
||||
|
||||
static int ndL_count_bits(uint32_t n)
|
||||
{
|
||||
n = (n & 0x55555555) + ((n >> 1) & 0x55555555);
|
||||
@ -115,39 +144,31 @@ int nd_mask_to_pflen(nd_addr_t *netmask)
|
||||
|
||||
void nd_mask_from_pflen(unsigned pflen, nd_addr_t *netmask)
|
||||
{
|
||||
if (pflen >= 97)
|
||||
if (pflen == 0)
|
||||
{
|
||||
netmask->s6_addr32[0] = 0;
|
||||
netmask->s6_addr32[1] = 0;
|
||||
netmask->s6_addr32[2] = 0;
|
||||
netmask->s6_addr32[3] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (pflen >= 128)
|
||||
{
|
||||
netmask->s6_addr32[0] = 0xffffffff;
|
||||
netmask->s6_addr32[1] = 0xffffffff;
|
||||
netmask->s6_addr32[2] = 0xffffffff;
|
||||
netmask->s6_addr32[3] = ndL_masks[pflen - 97];
|
||||
netmask->s6_addr32[3] = 0xffffffff;
|
||||
return;
|
||||
}
|
||||
else if (pflen >= 65)
|
||||
|
||||
for (unsigned i = 0, top = (pflen - 1) >> 5; i < 4; i++)
|
||||
{
|
||||
netmask->s6_addr32[0] = 0xffffffff;
|
||||
netmask->s6_addr32[1] = 0xffffffff;
|
||||
netmask->s6_addr32[2] = ndL_masks[pflen - 65];
|
||||
netmask->s6_addr32[3] = 0x00000000;
|
||||
}
|
||||
else if (pflen >= 33)
|
||||
{
|
||||
netmask->s6_addr32[0] = 0xffffffff;
|
||||
netmask->s6_addr32[1] = ndL_masks[pflen - 33];
|
||||
netmask->s6_addr32[2] = 0x00000000;
|
||||
netmask->s6_addr32[3] = 0x00000000;
|
||||
}
|
||||
else if (pflen >= 1)
|
||||
{
|
||||
netmask->s6_addr32[0] = ndL_masks[pflen - 1];
|
||||
netmask->s6_addr32[1] = 0x00000000;
|
||||
netmask->s6_addr32[2] = 0x00000000;
|
||||
netmask->s6_addr32[3] = 0x00000000;
|
||||
}
|
||||
if (i == top)
|
||||
netmask->s6_addr32[i] = ndL_masks[(pflen - 1) & 31];
|
||||
else if (i < top)
|
||||
netmask->s6_addr32[i] = 0xffffffff;
|
||||
else
|
||||
{
|
||||
netmask->s6_addr32[0] = 0x00000000;
|
||||
netmask->s6_addr32[1] = 0x00000000;
|
||||
netmask->s6_addr32[2] = 0x00000000;
|
||||
netmask->s6_addr32[3] = 0x00000000;
|
||||
netmask->s6_addr32[i] = 0;
|
||||
}
|
||||
}
|
||||
|
@ -27,5 +27,6 @@ bool nd_addr_match(nd_addr_t *first, nd_addr_t *second, unsigned pflen);
|
||||
bool nd_addr_eq(nd_addr_t *first, nd_addr_t *second);
|
||||
int nd_mask_to_pflen(nd_addr_t *netmask);
|
||||
void nd_mask_from_pflen(unsigned pflen, nd_addr_t *netmask);
|
||||
void nd_addr_combine(const nd_addr_t *first, const nd_addr_t *second, unsigned pflen, nd_addr_t *result);
|
||||
|
||||
#endif // NDPPD_ADDR_H
|
||||
|
48
src/conf.c
48
src/conf.c
@ -98,11 +98,13 @@ enum
|
||||
};
|
||||
|
||||
static bool ndL_parse_rule(ndL_state_t *state, nd_proxy_t *proxy);
|
||||
static bool ndL_parse_rewrite(ndL_state_t *state, nd_rule_t *rule);
|
||||
static bool ndL_parse_proxy(ndL_state_t *state, void *unused);
|
||||
|
||||
static const ndL_cfinfo_t ndL_cfinfo_table[] = {
|
||||
{ "proxy", NDL_DEFAULT, NDL_NONE, 0, 0, 0, (ndL_cfcb_t)ndL_parse_proxy },
|
||||
{ "rule", NDL_PROXY, NDL_NONE, 0, 0, 0, (ndL_cfcb_t)ndL_parse_rule },
|
||||
{ "rewrite", NDL_RULE, NDL_NONE, 0, 0, 0, (ndL_cfcb_t)ndL_parse_rewrite },
|
||||
{ "invalid-ttl", NDL_DEFAULT, NDL_INT, (uintptr_t)&nd_conf_invalid_ttl, 1000, 3600000, NULL },
|
||||
{ "valid-ttl", NDL_DEFAULT, NDL_INT, (uintptr_t)&nd_conf_valid_ttl, 10000, 3600000, NULL },
|
||||
{ "renew", NDL_DEFAULT, NDL_INT, (uintptr_t)&nd_conf_renew, 0, 0, NULL },
|
||||
@ -264,7 +266,7 @@ static bool ndL_accept_bool(ndL_state_t *state, bool *value)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ndL_accept_int(ndL_state_t *state, int *value)
|
||||
static bool ndL_accept_int(ndL_state_t *state, int *value, int min, int max)
|
||||
{
|
||||
ndL_state_t tmp = *state;
|
||||
|
||||
@ -281,8 +283,11 @@ static bool ndL_accept_int(ndL_state_t *state, int *value)
|
||||
|
||||
long longval = strtoll(buf, NULL, 10) * n;
|
||||
|
||||
if (longval < INT_MIN || longval > INT_MAX)
|
||||
if (longval < min || longval > max)
|
||||
{
|
||||
ndL_error(state, "Expected a number between %d and %d", min, max);
|
||||
return false;
|
||||
}
|
||||
|
||||
*value = (int)longval;
|
||||
*state = tmp;
|
||||
@ -375,20 +380,11 @@ static bool ndL_parse_rule(ndL_state_t *state, nd_proxy_t *proxy)
|
||||
|
||||
if (ndL_accept(state, "/", 0))
|
||||
{
|
||||
// Just for accurate logging if there is an error.
|
||||
ndL_state_t tmp = *state;
|
||||
|
||||
if (!ndL_accept_int(state, &rule->prefix))
|
||||
if (!ndL_accept_int(state, &rule->prefix, 0, 128))
|
||||
{
|
||||
ndL_error(state, "Expected prefix");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rule->prefix < 0 || rule->prefix > 128)
|
||||
{
|
||||
ndL_error(&tmp, "Invalid prefix (%d)", rule->prefix);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -404,6 +400,27 @@ static bool ndL_parse_rule(ndL_state_t *state, nd_proxy_t *proxy)
|
||||
return ndL_parse_block(state, NDL_RULE, rule);
|
||||
}
|
||||
|
||||
static bool ndL_parse_rewrite(ndL_state_t *state, nd_rule_t *rule)
|
||||
{
|
||||
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))
|
||||
{
|
||||
ndL_error(state, "Expected prefix");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rule->rewrite_pflen = 128;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ndL_parse_proxy(ndL_state_t *state, __attribute__((unused)) void *unused)
|
||||
{
|
||||
char ifname[IF_NAMESIZE];
|
||||
@ -481,16 +498,11 @@ static bool ndL_parse_block(ndL_state_t *state, int scope, void *ptr)
|
||||
break;
|
||||
|
||||
case NDL_INT:
|
||||
if (!ndL_accept_int(state, (int *)(ptr + t->offset)))
|
||||
if (!ndL_accept_int(state, (int *)(ptr + t->offset), t->min, t->max))
|
||||
{
|
||||
ndL_error(&saved_state, "Expected an integer");
|
||||
return false;
|
||||
}
|
||||
if (*(int *)(ptr + t->offset) < t->min || *(int *)(ptr + t->offset) > t->max)
|
||||
{
|
||||
ndL_error(&saved_state, "Invalid range; must be between %d and %d", t->min, t->max);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case NDL_ADDR:
|
||||
|
@ -103,7 +103,7 @@ static void ndL_handle_na(nd_iface_t *iface, ndL_icmp6_msg_t *msg)
|
||||
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->tgt, &na->nd_na_target));
|
||||
ND_LL_SEARCH(iface->sessions, session, next_in_iface, nd_addr_eq(&session->real_tgt, &na->nd_na_target));
|
||||
|
||||
if (!session)
|
||||
return;
|
||||
|
@ -19,17 +19,16 @@
|
||||
#include <getopt.h>
|
||||
#include <stdint.h>
|
||||
/**/
|
||||
#include <netinet/in.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "addr.h"
|
||||
#include "conf.h"
|
||||
#include "iface.h"
|
||||
#include "io.h"
|
||||
|
@ -118,6 +118,9 @@ bool nd_proxy_startup()
|
||||
{
|
||||
if (rule->ifname[0] && !(rule->iface = nd_iface_open(rule->ifname, 0)))
|
||||
return false;
|
||||
|
||||
nd_log_error("RULE REWRITE %s/%d", nd_aton(&rule->rewrite_tgt), rule->rewrite_pflen);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,9 @@ struct nd_rule
|
||||
nd_addr_t addr;
|
||||
int prefix;
|
||||
|
||||
nd_addr_t rewrite_tgt;
|
||||
int rewrite_pflen;
|
||||
|
||||
nd_iface_t *iface;
|
||||
bool is_auto;
|
||||
bool autowire;
|
||||
|
@ -90,11 +90,13 @@ nd_session_t *nd_session_create(nd_rule_t *rule, nd_addr_t *tgt)
|
||||
session->state_time = nd_current_time;
|
||||
session->tgt = *tgt;
|
||||
|
||||
nd_addr_combine(&rule->rewrite_tgt, tgt, rule->rewrite_pflen, &session->real_tgt);
|
||||
|
||||
if (rule->is_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;
|
||||
@ -112,8 +114,7 @@ nd_session_t *nd_session_create(nd_rule_t *rule, nd_addr_t *tgt)
|
||||
session->state = ND_STATE_INCOMPLETE;
|
||||
session->ons_count = 1;
|
||||
session->ons_time = nd_current_time;
|
||||
nd_iface_write_ns(session->iface, tgt);
|
||||
|
||||
nd_iface_write_ns(session->iface, &session->real_tgt);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -135,11 +136,12 @@ void nd_session_update(nd_session_t *session)
|
||||
{
|
||||
session->state = ND_STATE_INVALID;
|
||||
session->state_time = nd_current_time;
|
||||
nd_log_debug("session [%s] %s INCOMPLETE -> INVALID", session->rule->proxy->ifname, nd_aton(&session->tgt));
|
||||
nd_log_debug("session [%s] %s INCOMPLETE -> INVALID", //
|
||||
session->rule->proxy->ifname, nd_aton(&session->tgt));
|
||||
break;
|
||||
}
|
||||
|
||||
nd_iface_write_ns(session->iface, &session->tgt);
|
||||
nd_iface_write_ns(session->iface, &session->real_tgt);
|
||||
break;
|
||||
|
||||
case ND_STATE_INVALID:
|
||||
@ -157,7 +159,8 @@ void nd_session_update(nd_session_t *session)
|
||||
ND_LL_DELETE(session->rule->proxy->sessions, session, next_in_proxy);
|
||||
ND_LL_PREPEND(ndL_free_sessions, session, next_in_proxy);
|
||||
|
||||
nd_log_debug("session [%s] %s INVALID -> (deleted)", session->rule->proxy->ifname, nd_aton(&session->tgt));
|
||||
nd_log_debug("session [%s] %s INVALID -> (deleted)", //
|
||||
session->rule->proxy->ifname, nd_aton(&session->tgt));
|
||||
break;
|
||||
|
||||
case ND_STATE_VALID:
|
||||
@ -168,12 +171,13 @@ void nd_session_update(nd_session_t *session)
|
||||
session->state_time = nd_current_time;
|
||||
session->ons_time = nd_current_time;
|
||||
|
||||
nd_log_debug("session [%s] %s VALID -> STALE", session->rule->proxy->ifname, nd_aton(&session->tgt));
|
||||
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)
|
||||
{
|
||||
session->ons_count = 1;
|
||||
nd_iface_write_ns(session->iface, &session->tgt);
|
||||
nd_iface_write_ns(session->iface, &session->real_tgt);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -187,7 +191,9 @@ void nd_session_update(nd_session_t *session)
|
||||
{
|
||||
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));
|
||||
|
||||
nd_log_debug("session [%s] %s STALE -> INVALID", //
|
||||
session->rule->proxy->ifname, nd_aton(&session->tgt));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -206,7 +212,7 @@ void nd_session_update(nd_session_t *session)
|
||||
|
||||
session->ons_count++;
|
||||
session->ons_time = nd_current_time;
|
||||
nd_iface_write_ns(session->iface, &session->tgt);
|
||||
nd_iface_write_ns(session->iface, &session->real_tgt);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ struct nd_session
|
||||
nd_session_t *next_in_iface;
|
||||
nd_rule_t *rule;
|
||||
nd_addr_t tgt;
|
||||
nd_addr_t real_tgt;
|
||||
int ons_count; // Number of outgoing NS messages.
|
||||
long ons_time; // Last time we sent a NS message.
|
||||
long ins_time; // Last time this session was the target of an incoming NS.
|
||||
|
Loading…
x
Reference in New Issue
Block a user