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); } }