Continue work on handling TTLs
This commit is contained in:
parent
141f39f20a
commit
8028e2d487
@ -40,7 +40,8 @@
|
||||
#include "rule.h"
|
||||
|
||||
int nd_conf_invalid_ttl = 10000;
|
||||
int nd_conf_valid_ttl = 10000;
|
||||
int nd_conf_valid_ttl = 30000;
|
||||
int nd_conf_stale_ttl = 30000;
|
||||
int nd_conf_renew = 5000;
|
||||
int nd_conf_retrans_limit = 3;
|
||||
int nd_conf_retrans_time = 1000;
|
||||
|
20
src/iface.c
20
src/iface.c
@ -34,8 +34,8 @@
|
||||
#include "addr.h"
|
||||
#include "iface.h"
|
||||
#include "ndppd.h"
|
||||
#include "neigh.h"
|
||||
#include "proxy.h"
|
||||
#include "session.h"
|
||||
#include "sio.h"
|
||||
|
||||
extern int nd_conf_invalid_ttl;
|
||||
@ -55,7 +55,7 @@ typedef struct
|
||||
struct icmp6_hdr icmp6_hdr;
|
||||
} ndL_icmp6_msg_t;
|
||||
|
||||
static void ndL_handle_ns(nd_iface_t *ifa, ndL_icmp6_msg_t *msg)
|
||||
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;
|
||||
|
||||
@ -76,8 +76,8 @@ static void ndL_handle_ns(nd_iface_t *ifa, ndL_icmp6_msg_t *msg)
|
||||
|
||||
uint8_t *lladdr = (uint8_t *)((void *)opt + 2);
|
||||
|
||||
if (ifa->proxy)
|
||||
nd_proxy_handle_ns(ifa->proxy, &msg->ip6_hdr.ip6_src, &msg->ip6_hdr.ip6_dst, &ns->nd_ns_target, lladdr);
|
||||
if (iface->proxy)
|
||||
nd_proxy_handle_ns(iface->proxy, &msg->ip6_hdr.ip6_src, &msg->ip6_hdr.ip6_dst, &ns->nd_ns_target, lladdr);
|
||||
}
|
||||
|
||||
static void ndL_handle_na(nd_iface_t *iface, ndL_icmp6_msg_t *msg)
|
||||
@ -87,15 +87,15 @@ 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_neigh_t *neigh;
|
||||
ND_LL_SEARCH(iface->neighs, neigh, next_in_iface, nd_addr_eq(&neigh->tgt, &na->nd_na_target));
|
||||
nd_session_t *session;
|
||||
ND_LL_SEARCH(iface->sessions, session, next_in_iface, nd_addr_eq(&session->tgt, &na->nd_na_target));
|
||||
|
||||
if (!neigh)
|
||||
if (!session)
|
||||
return;
|
||||
|
||||
neigh->state = ND_STATE_VALID;
|
||||
neigh->ttl = nd_conf_valid_ttl;
|
||||
neigh->touched_at = nd_current_time;
|
||||
session->state = ND_STATE_VALID;
|
||||
session->mtime = nd_current_time;
|
||||
nd_log_debug("session [%s] %s INVALID -> (deleted)", "?", nd_addr_to_string(&session->tgt));
|
||||
}
|
||||
|
||||
static uint16_t ndL_calculate_checksum(uint32_t sum, const void *data, size_t length)
|
||||
|
@ -36,7 +36,7 @@ struct nd_iface
|
||||
int old_promisc;
|
||||
|
||||
nd_proxy_t *proxy;
|
||||
nd_neigh_t *neighs; /* All sessions expecting NA messages to arrive here. */
|
||||
nd_session_t *sessions; /* All sessions expecting NA messages to arrive here. */
|
||||
nd_sio_t *sio;
|
||||
};
|
||||
|
||||
|
@ -225,9 +225,12 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (!nd_sio_poll())
|
||||
{
|
||||
/* TODO: Error */
|
||||
break;
|
||||
}
|
||||
|
||||
nd_proxy_update_all();
|
||||
|
||||
gettimeofday(&t1, 0);
|
||||
nd_current_time = t1.tv_sec * 1000 + t1.tv_usec / 1000;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ typedef struct in6_addr nd_addr_t;
|
||||
typedef struct nd_conf_rule nd_conf_rule_t;
|
||||
typedef struct nd_conf_proxy nd_conf_proxy_t;
|
||||
typedef struct nd_rule nd_rule_t;
|
||||
typedef struct nd_neigh nd_neigh_t;
|
||||
typedef struct nd_session nd_session_t;
|
||||
|
||||
extern long nd_current_time;
|
||||
extern bool nd_daemonized;
|
||||
|
148
src/proxy.c
148
src/proxy.c
@ -22,15 +22,16 @@
|
||||
#include "addr.h"
|
||||
#include "iface.h"
|
||||
#include "ndppd.h"
|
||||
#include "neigh.h"
|
||||
#include "proxy.h"
|
||||
#include "rtnl.h"
|
||||
#include "rule.h"
|
||||
#include "session.h"
|
||||
|
||||
static nd_proxy_t *ndL_proxies;
|
||||
|
||||
extern int nd_conf_invalid_ttl;
|
||||
extern int nd_conf_valid_ttl;
|
||||
extern int nd_conf_stale_ttl;
|
||||
extern int nd_conf_renew;
|
||||
extern int nd_conf_retrans_limit;
|
||||
extern int nd_conf_retrans_time;
|
||||
@ -54,7 +55,7 @@ nd_proxy_t *nd_proxy_create(const char *ifname)
|
||||
|
||||
proxy->iface = NULL;
|
||||
proxy->rules = NULL;
|
||||
proxy->neighs = NULL;
|
||||
proxy->sessions = NULL;
|
||||
proxy->router = false;
|
||||
|
||||
strcpy(proxy->ifname, ifname);
|
||||
@ -68,16 +69,15 @@ void nd_proxy_handle_ns(nd_proxy_t *proxy, nd_addr_t *src, __attribute__((unused
|
||||
nd_log_trace("Handle NA src=%s [%x:%x:%x:%x:%x:%x], dst=%s, tgt=%s", nd_addr_to_string(src), src_ll[0], src_ll[1],
|
||||
src_ll[2], src_ll[3], src_ll[4], src_ll[5], nd_addr_to_string(dst), nd_addr_to_string(tgt));
|
||||
|
||||
nd_neigh_t *neigh;
|
||||
nd_session_t *session;
|
||||
|
||||
ND_LL_FOREACH_NODEF(proxy->neighs, neigh, next_in_proxy)
|
||||
ND_LL_FOREACH_NODEF(proxy->sessions, session, next_in_proxy)
|
||||
{
|
||||
if (!nd_addr_eq(&neigh->tgt, tgt))
|
||||
if (!nd_addr_eq(&session->tgt, tgt))
|
||||
continue;
|
||||
|
||||
if (neigh->state == ND_STATE_VALID || neigh->state == ND_STATE_VALID_REFRESH)
|
||||
if (session->state == ND_STATE_VALID || session->state == ND_STATE_STALE)
|
||||
{
|
||||
neigh->used_at = nd_current_time;
|
||||
nd_iface_write_na(proxy->iface, src, src_ll, tgt, proxy->router);
|
||||
return;
|
||||
}
|
||||
@ -94,11 +94,11 @@ void nd_proxy_handle_ns(nd_proxy_t *proxy, nd_addr_t *src, __attribute__((unused
|
||||
if (!rule)
|
||||
return;
|
||||
|
||||
neigh = nd_alloc_neigh();
|
||||
neigh->touched_at = nd_current_time;
|
||||
neigh->tgt = *tgt;
|
||||
session = nd_alloc_session();
|
||||
session->mtime = nd_current_time;
|
||||
session->tgt = *tgt;
|
||||
|
||||
ND_LL_PREPEND(proxy->neighs, neigh, next_in_proxy);
|
||||
ND_LL_PREPEND(proxy->sessions, session, next_in_proxy);
|
||||
|
||||
if (rule->is_auto)
|
||||
{
|
||||
@ -109,92 +109,112 @@ void nd_proxy_handle_ns(nd_proxy_t *proxy, nd_addr_t *src, __attribute__((unused
|
||||
if (!route || route->oif == proxy->iface->index)
|
||||
{
|
||||
/* Could not find a matching route. */
|
||||
neigh->state = ND_STATE_INVALID;
|
||||
session->state = ND_STATE_INVALID;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(neigh->iface = nd_iface_open(NULL, route->oif)))
|
||||
if (!(session->iface = nd_iface_open(NULL, route->oif)))
|
||||
{
|
||||
/* Could not open interface. */
|
||||
neigh->state = ND_STATE_INVALID;
|
||||
session->state = ND_STATE_INVALID;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if ((neigh->iface = rule->iface))
|
||||
else if ((session->iface = rule->iface))
|
||||
{
|
||||
neigh->iface->refs++;
|
||||
session->iface->refs++;
|
||||
}
|
||||
|
||||
if (neigh->iface)
|
||||
if (session->iface)
|
||||
{
|
||||
neigh->state = ND_STATE_INCOMPLETE;
|
||||
nd_iface_write_ns(neigh->iface, tgt);
|
||||
session->state = ND_STATE_INCOMPLETE;
|
||||
nd_iface_write_ns(session->iface, tgt);
|
||||
|
||||
ND_LL_PREPEND(neigh->iface->neighs, neigh, next_in_iface);
|
||||
ND_LL_PREPEND(session->iface->sessions, session, next_in_iface);
|
||||
}
|
||||
else
|
||||
{
|
||||
neigh->state = ND_STATE_VALID;
|
||||
session->state = ND_STATE_VALID;
|
||||
nd_iface_write_na(proxy->iface, src, src_ll, tgt, proxy->router);
|
||||
}
|
||||
}
|
||||
|
||||
void nd_proxy_update_neighs(nd_proxy_t *proxy)
|
||||
static void ndL_update_session(nd_proxy_t *proxy, nd_session_t *session)
|
||||
{
|
||||
ND_LL_FOREACH_S(proxy->neighs, neigh, tmp, next_in_proxy)
|
||||
switch (session->state)
|
||||
{
|
||||
switch (neigh->state)
|
||||
case ND_STATE_INCOMPLETE:
|
||||
if (nd_current_time - session->mtime < nd_conf_retrans_time)
|
||||
break;
|
||||
|
||||
session->mtime = nd_current_time;
|
||||
|
||||
if (++session->rcount > nd_conf_retrans_limit)
|
||||
{
|
||||
case ND_STATE_INCOMPLETE:
|
||||
if ((nd_current_time - neigh->touched_at) < nd_conf_retrans_time)
|
||||
break;
|
||||
session->state = ND_STATE_INVALID;
|
||||
nd_log_debug("session [%s] %s INCOMPLETE -> INVALID", proxy->ifname, nd_addr_to_string(&session->tgt));
|
||||
break;
|
||||
}
|
||||
|
||||
neigh->touched_at = nd_current_time;
|
||||
nd_iface_write_ns(session->iface, &session->tgt);
|
||||
break;
|
||||
|
||||
if (++neigh->attempt > 3)
|
||||
{
|
||||
neigh->state = ND_STATE_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
nd_iface_write_ns(neigh->iface, &neigh->tgt);
|
||||
case ND_STATE_INVALID:
|
||||
if (nd_current_time - session->mtime < nd_conf_invalid_ttl)
|
||||
break;
|
||||
|
||||
case ND_STATE_INVALID:
|
||||
if ((nd_current_time - neigh->touched_at) < nd_conf_invalid_ttl)
|
||||
break;
|
||||
ND_LL_DELETE(session->iface->sessions, session, next_in_iface);
|
||||
ND_LL_DELETE(proxy->sessions, session, next_in_proxy);
|
||||
|
||||
ND_LL_DELETE(neigh->iface->neighs, neigh, next_in_iface);
|
||||
ND_LL_DELETE(proxy->neighs, neigh, next_in_proxy);
|
||||
nd_iface_close(session->iface);
|
||||
nd_free_session(session);
|
||||
nd_log_debug("session [%s] %s INVALID -> (deleted)", proxy->ifname, nd_addr_to_string(&session->tgt));
|
||||
break;
|
||||
|
||||
nd_iface_close(neigh->iface);
|
||||
nd_free_neigh(neigh);
|
||||
case ND_STATE_VALID:
|
||||
if (nd_current_time - session->mtime < nd_conf_valid_ttl)
|
||||
break;
|
||||
|
||||
case ND_STATE_VALID:
|
||||
if (nd_current_time - neigh->touched_at < nd_conf_valid_ttl - nd_conf_renew)
|
||||
session->mtime = nd_current_time;
|
||||
session->rtime = nd_current_time;
|
||||
session->state = ND_STATE_STALE;
|
||||
session->rcount = 0;
|
||||
|
||||
nd_log_debug("session [%s] %s VALID -> STALE", proxy->ifname, nd_addr_to_string(&session->tgt));
|
||||
nd_iface_write_ns(session->iface, &session->tgt);
|
||||
break;
|
||||
|
||||
case ND_STATE_STALE:
|
||||
if (nd_current_time - session->mtime >= nd_conf_stale_ttl)
|
||||
{
|
||||
session->mtime = nd_current_time;
|
||||
session->state = ND_STATE_INVALID;
|
||||
nd_log_debug("session [%s] %s STALE -> INVALID", proxy->ifname, nd_addr_to_string(&session->tgt));
|
||||
}
|
||||
else
|
||||
{
|
||||
long t = session->rcount && !(session->rcount % nd_conf_retrans_limit)
|
||||
? ((1 << session->rcount / 3) * nd_conf_retrans_time)
|
||||
: nd_conf_retrans_time;
|
||||
|
||||
if (nd_current_time - session->rtime < t)
|
||||
break;
|
||||
|
||||
session->rcount++;
|
||||
session->rtime = nd_current_time;
|
||||
nd_iface_write_ns(session->iface, &session->tgt);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* TODO: Send solicit. */
|
||||
break;
|
||||
|
||||
case ND_STATE_VALID_REFRESH:
|
||||
if ((nd_current_time - neigh->touched_at) < nd_conf_retrans_time)
|
||||
break;
|
||||
|
||||
if (++neigh->attempt > 3)
|
||||
{
|
||||
neigh->state = ND_STATE_INVALID;
|
||||
neigh->touched_at = nd_current_time;
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO: Send solicit. */
|
||||
break;
|
||||
void nd_proxy_update_all()
|
||||
{
|
||||
ND_LL_FOREACH(ndL_proxies, proxy, next)
|
||||
{
|
||||
ND_LL_FOREACH_S(proxy->sessions, session, tmp, next_in_proxy)
|
||||
{
|
||||
ndL_update_session(proxy, session);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -206,6 +226,8 @@ bool nd_proxy_startup()
|
||||
if (!(proxy->iface = nd_iface_open(proxy->ifname, 0)))
|
||||
return false;
|
||||
|
||||
proxy->iface->proxy = proxy;
|
||||
|
||||
if (proxy->promisc)
|
||||
nd_iface_set_promisc(proxy->iface, true);
|
||||
else
|
||||
|
@ -30,15 +30,15 @@ struct nd_proxy
|
||||
|
||||
nd_iface_t *iface;
|
||||
nd_rule_t *rules;
|
||||
nd_neigh_t *neighs;
|
||||
nd_session_t *sessions;
|
||||
bool router;
|
||||
bool promisc;
|
||||
};
|
||||
|
||||
/* proxy.c */
|
||||
nd_proxy_t *nd_proxy_create(const char *ifname);
|
||||
void nd_proxy_handle_na(nd_proxy_t *proxy, nd_addr_t *src, nd_addr_t *tgt);
|
||||
void nd_proxy_handle_ns(nd_proxy_t *proxy, nd_addr_t *src, nd_addr_t *dst, nd_addr_t *tgt, uint8_t *src_ll);
|
||||
bool nd_proxy_startup();
|
||||
void nd_proxy_update_all();
|
||||
|
||||
#endif // NDPPD_PROXY_H
|
||||
|
@ -18,28 +18,26 @@
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
#include "neigh.h"
|
||||
#include "ndppd.h"
|
||||
#include "session.h"
|
||||
|
||||
static nd_neigh_t *ndL_free_neighs;
|
||||
static nd_session_t *ndL_free_sessions;
|
||||
|
||||
nd_neigh_t *nd_alloc_neigh()
|
||||
nd_session_t *nd_alloc_session()
|
||||
{
|
||||
nd_neigh_t *neigh = ndL_free_neighs;
|
||||
nd_session_t *session = ndL_free_sessions;
|
||||
|
||||
if (neigh)
|
||||
ND_LL_DELETE(ndL_free_neighs, neigh, next_in_proxy);
|
||||
if (session)
|
||||
ND_LL_DELETE(ndL_free_sessions, session, next_in_proxy);
|
||||
else
|
||||
neigh = ND_ALLOC(nd_neigh_t);
|
||||
session = ND_ALLOC(nd_session_t);
|
||||
|
||||
memset(neigh, 0, sizeof(nd_neigh_t));
|
||||
memset(session, 0, sizeof(nd_session_t));
|
||||
|
||||
return neigh;
|
||||
return session;
|
||||
}
|
||||
|
||||
void nd_free_neigh(nd_neigh_t *session)
|
||||
void nd_free_session(nd_session_t *session)
|
||||
{
|
||||
ND_LL_PREPEND(ndL_free_neighs, session, next_in_proxy);
|
||||
ND_LL_PREPEND(ndL_free_sessions, session, next_in_proxy);
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,8 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ndppd. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef NDPPD_NEIGH_H
|
||||
#define NDPPD_NEIGH_H
|
||||
#ifndef NDPPD_SESSION_H
|
||||
#define NDPPD_SESSION_H
|
||||
|
||||
#include "ndppd.h"
|
||||
|
||||
@ -34,9 +34,9 @@ typedef enum
|
||||
ND_STATE_VALID,
|
||||
|
||||
/*
|
||||
* Resolution was successful, but this entry is getting old.
|
||||
*
|
||||
*/
|
||||
ND_STATE_VALID_REFRESH,
|
||||
ND_STATE_STALE,
|
||||
|
||||
/*
|
||||
* Resolution failed, and further Neighbor Solicitation messages will be ignored until
|
||||
@ -46,20 +46,19 @@ typedef enum
|
||||
|
||||
} nd_state_t;
|
||||
|
||||
struct nd_neigh
|
||||
struct nd_session
|
||||
{
|
||||
nd_neigh_t *next_in_proxy;
|
||||
nd_neigh_t *next_in_iface;
|
||||
nd_session_t *next_in_proxy;
|
||||
nd_session_t *next_in_iface;
|
||||
nd_addr_t tgt;
|
||||
int attempt;
|
||||
long touched_at;
|
||||
long used_at;
|
||||
int rcount;
|
||||
long rtime;
|
||||
long mtime;
|
||||
nd_state_t state;
|
||||
nd_iface_t *iface;
|
||||
};
|
||||
|
||||
nd_neigh_t *nd_alloc_neigh();
|
||||
void nd_free_neigh(nd_neigh_t *session);
|
||||
void nd_session_send_ns(nd_neigh_t *session);
|
||||
nd_session_t *nd_alloc_session();
|
||||
void nd_free_session(nd_session_t *session);
|
||||
|
||||
#endif /* NDPPD_NEIGH_H */
|
||||
#endif /*NDPPD_SESSION_H*/
|
Loading…
x
Reference in New Issue
Block a user