diff --git a/src/addr.c b/src/addr.c
index bd6ae49..6360cf1 100644
--- a/src/addr.c
+++ b/src/addr.c
@@ -35,11 +35,7 @@ const char *nd_ntoa(const nd_addr_t *addr)
static int index;
static char buf[3][64];
- if (addr == NULL) {
- return "(null)";
- }
-
- return inet_ntop(AF_INET6, addr, buf[index++ % 3], 64);
+ return addr ? inet_ntop(AF_INET6, addr, buf[index++ % 3], 64) : "(null)";
}
bool nd_addr_is_multicast(const nd_addr_t *addr)
@@ -175,11 +171,7 @@ const char *nd_ll_ntoa(const nd_lladdr_t *addr)
static int index;
static char buf[3][64];
- if (addr == NULL) {
- return "(null)";
- }
-
- return ether_ntoa_r((struct ether_addr *)addr, buf[index++ % 3]);
+ return addr ? ether_ntoa_r((struct ether_addr *)addr, buf[index++ % 3]) : "(null)";
}
bool nd_ll_addr_is_unspecified(const nd_lladdr_t *lladdr)
diff --git a/src/alloc.c b/src/alloc.c
index aeecaeb..463f427 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -16,7 +16,6 @@
* You should have received a copy of the GNU General Public License
* along with ndppd. If not, see .
*/
-#include
#include
#include
@@ -24,9 +23,14 @@
# define NDPPD_ALLOC_SIZE 16384
#endif
+#ifndef NDPPD_MAX_ALLOC
+# define NDPPD_MAX_ALLOC 128
+#endif
+
#include "ndppd.h"
typedef struct ndL_chunk ndL_chunk_t;
+typedef struct ndL_obj ndL_obj_t;
struct ndL_chunk {
ndL_chunk_t *next;
@@ -34,8 +38,13 @@ struct ndL_chunk {
size_t size;
};
+struct ndL_obj {
+ ndL_obj_t *next;
+};
+
static ndL_chunk_t *ndL_chunks;
static size_t ndL_alloc_size = NDPPD_ALLOC_SIZE;
+static ndL_obj_t *ndL_free_objects[NDPPD_MAX_ALLOC >> 3];
char *nd_strdup(const char *str)
{
@@ -45,13 +54,39 @@ char *nd_strdup(const char *str)
return buf;
}
+void nd_free(void *ptr, size_t size)
+{
+ if (size == 0 || size > NDPPD_MAX_ALLOC) {
+ abort();
+ }
+
+ size = (size + 7U) & ~7U;
+
+ unsigned int bucket = (size >> 3) - 1;
+ ND_LL_PREPEND(ndL_free_objects[bucket], (ndL_obj_t *)ptr, next);
+}
+
void *nd_alloc(size_t size)
{
- assert(size > 0 && size < 512);
+ if (size == 0 || size > NDPPD_MAX_ALLOC) {
+ abort();
+ }
- // To keep everything properly aligned, we'll make sure it's multiple of 8.
+ /* To keep everything properly aligned, we'll make sure it's multiple of 8. */
size = (size + 7U) & ~7U;
+ /* See if we can reuse an object. */
+
+ unsigned int bucket = (size >> 3) - 1;
+ ndL_obj_t *obj = ndL_free_objects[bucket];
+
+ if (obj) {
+ ND_LL_DELETE(ndL_free_objects[bucket], obj, next);
+ return obj;
+ }
+
+ /* See if we have any chunks with enough space left. */
+
for (ndL_chunk_t *chunk = ndL_chunks; chunk; chunk = chunk->next) {
if (chunk->free >= size) {
void *ptr = (void *)chunk + chunk->size - chunk->free;
diff --git a/src/iface.c b/src/iface.c
index fd26f95..7ac9fea 100644
--- a/src/iface.c
+++ b/src/iface.c
@@ -54,7 +54,7 @@ extern int nd_conf_retrans_limit;
extern int nd_conf_retrans_time;
extern bool nd_conf_keepalive;
-static nd_iface_t *ndL_first_iface, *ndL_first_free_iface;
+static nd_iface_t *ndL_first_iface;
static nd_io_t *ndL_io;
//! Used when daemonizing to make sure the parent process does not restore these flags upon exit.
@@ -506,13 +506,7 @@ nd_iface_t *nd_iface_open(const char *name, unsigned index)
nd_lladdr_t *lladdr = (nd_lladdr_t *)LLADDR((struct sockaddr_dl *)(sysctl_buf + sizeof(struct if_msghdr)));
#endif
- iface = ndL_first_free_iface;
-
- if (iface) {
- ND_LL_DELETE(ndL_first_free_iface, iface, next);
- } else {
- iface = ND_ALLOC(nd_iface_t);
- }
+ iface = ND_NEW(nd_iface_t);
*iface = (nd_iface_t){
.index = index,
@@ -553,7 +547,7 @@ void nd_iface_close(nd_iface_t *iface)
#endif
ND_LL_DELETE(ndL_first_iface, iface, next);
- ND_LL_PREPEND(ndL_first_free_iface, iface, next);
+ ND_DELETE(iface);
}
static void ndL_get_local_addr(nd_iface_t *iface, nd_addr_t *addr)
diff --git a/src/io.c b/src/io.c
index 7ce1032..695596d 100644
--- a/src/io.c
+++ b/src/io.c
@@ -40,7 +40,7 @@
#include "ndppd.h"
-static nd_io_t *ndL_first_io, *ndL_first_free_io;
+static nd_io_t *ndL_first_io;
#ifndef NDPPD_NO_USE_EPOLL
static int ndL_epoll_fd;
@@ -96,13 +96,7 @@ static nd_io_t *ndL_create(int fd)
return false;
}
- nd_io_t *io = ndL_first_free_io;
-
- if (io) {
- ND_LL_DELETE(ndL_first_free_io, io, next);
- } else {
- io = ND_ALLOC(nd_io_t);
- }
+ nd_io_t *io = ND_NEW(nd_io_t);
*io = (nd_io_t){ .fd = fd };
@@ -160,7 +154,7 @@ void nd_io_close(nd_io_t *io)
#endif
ND_LL_DELETE(ndL_first_io, io, next);
- ND_LL_PREPEND(ndL_first_free_io, io, next);
+ ND_DELETE(io);
}
ssize_t nd_io_send(nd_io_t *io, const struct sockaddr *addr, size_t addrlen, const void *msg, size_t msglen)
diff --git a/src/ndppd.h b/src/ndppd.h
index b1b80a7..ab28db2 100644
--- a/src/ndppd.h
+++ b/src/ndppd.h
@@ -40,6 +40,7 @@ typedef struct nd_lladdr nd_lladdr_t;
typedef struct nd_rt_route nd_rt_route_t;
typedef struct nd_rt_addr nd_rt_addr_t;
typedef struct nd_ml nd_ml_t;
+typedef struct nd_sub nd_sub_t;
typedef void(nd_io_handler_t)(nd_io_t *io, int events);
@@ -100,20 +101,27 @@ struct nd_proxy {
};
struct nd_session {
- nd_session_t *next;
- nd_session_t *next_r;
- nd_rule_t *rule;
- nd_addr_t tgt;
- nd_addr_t tgt_r;
- 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. */
- long state_time; /* Time when session entered it's current state. */
+ nd_session_t *next; /* Next session in ndL_sessions. */
+ nd_session_t *next_r; /* Next session in ndL_sessions_r. */
+ nd_rule_t *rule; /* */
+ nd_addr_t tgt; /* Target address. */
+ nd_addr_t tgt_r; /* Rewritten target address. */
+ 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. */
+ long state_time; /* Time when session entered it's current state. */
nd_state_t state;
nd_iface_t *iface;
+ nd_sub_t *subs;
bool autowired; /* If this session had a route set up. */
};
+struct nd_sub {
+ nd_sub_t *next;
+ nd_addr_t addr;
+ nd_lladdr_t lladdr;
+};
+
struct nd_rule {
nd_rule_t *next;
nd_proxy_t *proxy;
@@ -227,7 +235,8 @@ struct nd_io {
; \
} while (0)
-#define ND_ALLOC(type) (type *)nd_alloc(sizeof(type))
+#define ND_NEW(type) (type *)nd_alloc(sizeof(type))
+#define ND_DELETE(ptr) nd_free((ptr), sizeof((ptr)[0]))
/*
* ndppd.c
@@ -309,6 +318,7 @@ nd_rule_t *nd_rule_create(nd_proxy_t *proxy);
*/
void *nd_alloc(size_t size);
+void nd_free(void *ptr, size_t size);
char *nd_strdup(const char *str);
void nd_alloc_cleanup();
diff --git a/src/proxy.c b/src/proxy.c
index b51ddb0..5a13077 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -41,7 +41,7 @@ nd_proxy_t *nd_proxy_create(const char *ifname)
return NULL;
}
- proxy = ND_ALLOC(nd_proxy_t);
+ proxy = ND_NEW(nd_proxy_t);
*proxy = (nd_proxy_t){ 0 };
strcpy(proxy->ifname, ifname);
diff --git a/src/rt.c b/src/rt.c
index 2576c72..6c41693 100644
--- a/src/rt.c
+++ b/src/rt.c
@@ -70,7 +70,7 @@ static void ndL_new_route(nd_rt_route_t *route)
if ((new_route = ndL_free_routes)) {
ND_LL_DELETE(ndL_free_routes, new_route, next);
} else {
- new_route = ND_ALLOC(nd_rt_route_t);
+ new_route = ND_NEW(nd_rt_route_t);
}
*new_route = *route;
@@ -140,7 +140,7 @@ static void ndL_new_addr(unsigned index, nd_addr_t *addr, unsigned pflen)
if ((rt_addr = ndL_free_addrs)) {
ND_LL_DELETE(ndL_free_addrs, rt_addr, next);
} else {
- rt_addr = ND_ALLOC(nd_rt_addr_t);
+ rt_addr = ND_NEW(nd_rt_addr_t);
}
ND_LL_PREPEND(ndL_addrs, rt_addr, next);
diff --git a/src/rule.c b/src/rule.c
index 66fc147..66361ea 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -20,7 +20,7 @@
nd_rule_t *nd_rule_create(nd_proxy_t *proxy)
{
- nd_rule_t *rule = ND_ALLOC(nd_rule_t);
+ nd_rule_t *rule = ND_NEW(nd_rule_t);
*rule = (nd_rule_t){ .proxy = proxy, .target = proxy->target };
diff --git a/src/session.c b/src/session.c
index 2180088..bbcb577 100644
--- a/src/session.c
+++ b/src/session.c
@@ -34,7 +34,6 @@ extern bool nd_conf_keepalive;
#define NDL_BUCKET(a) (nd_addr_hash(a) % NDPPD_SESSION_BUCKETS)
-static nd_session_t *ndL_free_sessions;
static nd_session_t *ndL_sessions[NDPPD_SESSION_BUCKETS];
static nd_session_t *ndL_sessions_r[NDPPD_SESSION_BUCKETS];
@@ -59,6 +58,7 @@ void nd_session_handle_ns(nd_session_t *session, const nd_addr_t *src, const nd_
session->ins_time = nd_current_time;
if (session->state != ND_STATE_VALID && session->state != ND_STATE_STALE) {
+ /* Register sub */
return;
}
@@ -77,6 +77,20 @@ void nd_session_handle_ns(nd_session_t *session, const nd_addr_t *src, const nd_
void nd_session_handle_na(nd_session_t *session)
{
+ if (session->state == ND_STATE_VALID) {
+ return;
+ }
+
+ /*if (!nd_addr_is_unspecified(&q)) {
+ nd_log_error("testing quickness.. ");
+ nd_lladdr_t *tgt_ll = !nd_ll_addr_is_unspecified(&session->rule->target) ? &session->rule->target : NULL;
+
+ nd_iface_send_na(session->rule->proxy->iface, &q, &z, //
+ &session->tgt, tgt_ll, session->rule->proxy->router);
+
+ memset(&q, 0, sizeof(q));
+ }*/
+
if (session->state != ND_STATE_VALID) {
nd_log_debug("Session [%s] %s -> VALID", session->rule->proxy->ifname, nd_ntoa(&session->tgt));
@@ -88,13 +102,7 @@ void nd_session_handle_na(nd_session_t *session)
nd_session_t *nd_session_create(nd_rule_t *rule, const nd_addr_t *tgt)
{
- nd_session_t *session = ndL_free_sessions;
-
- if (session) {
- ND_LL_DELETE(ndL_free_sessions, session, next);
- } else {
- session = ND_ALLOC(nd_session_t);
- }
+ nd_session_t *session = ND_NEW(nd_session_t);
*session = (nd_session_t){
.rule = rule,
@@ -162,10 +170,11 @@ void nd_session_update(nd_session_t *session)
ND_LL_DELETE(ndL_sessions[NDL_BUCKET(&session->tgt)], session, next);
ND_LL_DELETE(ndL_sessions_r[NDL_BUCKET(&session->tgt_r)], session, next_r);
- ND_LL_PREPEND(ndL_free_sessions, session, next);
nd_log_debug("session [%s] %s INVALID -> (deleted)", //
session->rule->proxy->ifname, nd_ntoa(&session->tgt));
+
+ ND_DELETE(session);
break;
case ND_STATE_VALID:
@@ -239,7 +248,7 @@ nd_session_t *nd_session_find_r(const nd_addr_t *tgt, const nd_iface_t *iface)
void nd_session_update_all()
{
for (int i = 0; i < NDPPD_SESSION_BUCKETS; i++) {
- ND_LL_FOREACH(ndL_sessions[i], session, next) {
+ ND_LL_FOREACH_S(ndL_sessions[i], session, tmp, next) {
nd_session_update(session);
}
}