Use initializers instead of memset

This commit is contained in:
Daniel Adolfsson 2019-12-15 18:05:17 +01:00
parent 724fa74974
commit 565c6dd404
12 changed files with 245 additions and 281 deletions

View File

@ -5,5 +5,5 @@ set(CMAKE_C_STANDARD 99)
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC)
add_executable(ndppd ${SRC})
target_compile_options(ndppd PRIVATE -Werror -Wall -Wextra)
target_compile_options(ndppd PRIVATE -Werror -Wall -Wextra -Wno-missing-braces -Wno-missing-field-initializers)

View File

@ -1,17 +1,19 @@
ifdef DEBUG
CCFLAGS ?= -g -DDEBUG
CFLAGS ?= -g -DDEBUG
else
CCFLAGS ?= -Os
CFLAGS ?= -Os
LDFLAGS ?= -s -w
endif
PREFIX ?= /usr/local
CCC ?= gcc
CC ?= gcc
GZIP ?= /bin/gzip
MANDIR ?= ${DESTDIR}${PREFIX}/share/man
SBINDIR ?= ${DESTDIR}${PREFIX}/sbin
ASCIIDOCTOR ?= /usr/bin/asciidoctor
CFLAGS := ${CFLAGS} -Werror -Wall -Wextra -Wno-missing-braces -Wno-missing-field-initializers
OBJS = $(patsubst %.c,%.o,$(wildcard src/*.c))
all: ndppd ndppd.8.gz ndppd.conf.5.gz
@ -30,7 +32,7 @@ ndppd: ${OBJS}
${CC} -o ndppd ${LDFLAGS} ${OBJS} ${LIBS}
%.o: %.c
${CC} -c ${CPPFLAGS} $(CCFLAGS) -o $@ $<
${CC} -c ${CPPFLAGS} $(CFLAGS) -o $@ $<
clean:
rm -f ndppd ndppd.conf.5.gz ndppd.8.gz ${OBJS}

View File

@ -143,18 +143,12 @@ int nd_mask_to_pflen(nd_addr_t *netmask)
void nd_mask_from_pflen(unsigned pflen, nd_addr_t *netmask)
{
if (pflen == 0) {
netmask->s6_addr32[0] = 0;
netmask->s6_addr32[1] = 0;
netmask->s6_addr32[2] = 0;
netmask->s6_addr32[3] = 0;
*netmask = (nd_addr_t){ 0 };
return;
}
if (pflen >= 128) {
netmask->s6_addr32[0] = 0xffffffff;
netmask->s6_addr32[1] = 0xffffffff;
netmask->s6_addr32[2] = 0xffffffff;
netmask->s6_addr32[3] = 0xffffffff;
memset(netmask, 0xff, sizeof(nd_addr_t));
return;
}

View File

@ -59,16 +59,18 @@ void *nd_alloc(size_t size)
}
}
ndL_chunk_t *chunk = (ndL_chunk_t *)calloc(1, ndL_alloc_size);
ndL_chunk_t *chunk = (ndL_chunk_t *)malloc(ndL_alloc_size);
// This should never happen.
if (chunk == NULL) {
abort();
}
chunk->next = ndL_chunks;
chunk->size = ndL_alloc_size;
chunk->free = ndL_alloc_size - ((sizeof(ndL_chunk_t) + 7U) & ~7U);
*chunk = (ndL_chunk_t){
.next = ndL_chunks,
.size = ndL_alloc_size,
.free = ndL_alloc_size - ((sizeof(ndL_chunk_t) + 7U) & ~7U),
};
ndL_chunks = chunk;

View File

@ -320,7 +320,7 @@ static bool ndL_accept_addr(ndL_state_t *state, nd_addr_t *addr)
return false;
}
// Make sure we don't have a trailing [A-Za-z0-9-_]
// [A-Za-z0-9_-] must not directly follow the address.
if (ndL_accept_one(&tmp, NDL_EALNM)) {
return false;
}

View File

@ -145,16 +145,14 @@ static uint16_t ndL_calculate_icmp6_checksum(ndL_icmp6_msg_t *msg, size_t size)
uint8_t unused[3];
uint8_t type;
struct icmp6_hdr icmp6_hdr;
} hdr;
} hdr = {
.src = msg->ip6_hdr.ip6_src,
.dst = msg->ip6_hdr.ip6_dst,
.len = htonl(size - sizeof(struct ip6_hdr)),
.type = IPPROTO_ICMPV6,
.icmp6_hdr = msg->icmp6_hdr,
};
hdr.src = msg->ip6_hdr.ip6_src;
hdr.dst = msg->ip6_hdr.ip6_dst;
hdr.len = htonl(size - sizeof(struct ip6_hdr));
hdr.unused[0] = 0;
hdr.unused[1] = 0;
hdr.unused[2] = 0;
hdr.type = IPPROTO_ICMPV6;
hdr.icmp6_hdr = msg->icmp6_hdr;
hdr.icmp6_hdr.icmp6_cksum = 0;
uint16_t sum;
@ -195,29 +193,33 @@ static void ndL_handle_packet(nd_iface_t *iface, uint8_t *buf, size_t buflen)
// Called from nd_io_poll() when there are pending events on the nd_io_t.
static void ndL_io_handler(nd_io_t *io, __attribute__((unused)) int events)
{
struct sockaddr_ll lladdr;
memset(&lladdr, 0, sizeof(struct sockaddr_ll));
lladdr.sll_family = AF_PACKET;
lladdr.sll_protocol = htons(ETH_P_IPV6);
struct sockaddr_ll lladdr = {
.sll_family = AF_PACKET,
.sll_protocol = htons(ETH_P_IPV6),
};
uint8_t buf[1024];
for (;;) {
ssize_t len = nd_io_recv(io, (struct sockaddr *)&lladdr, sizeof(lladdr), buf, sizeof(buf));
if (len == 0)
if (len == 0) {
return;
}
if (len < 0)
if (len < 0) {
return;
}
if ((size_t)len < sizeof(struct ether_header) + sizeof(struct ip6_hdr))
if ((size_t)len < sizeof(struct ether_header) + sizeof(struct ip6_hdr)) {
continue;
}
struct ether_header *eh = (struct ether_header *)(buf);
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);
@ -225,8 +227,9 @@ static void ndL_io_handler(nd_io_t *io, __attribute__((unused)) int events)
ND_LL_SEARCH(ndL_first_iface, iface, next, iface->index == (unsigned int)lladdr.sll_ifindex);
if (iface)
if (iface) {
ndL_handle_packet(iface, (uint8_t *)ip6_hdr, len - sizeof(struct ether_header));
}
}
}
#else
@ -271,13 +274,11 @@ static void ndL_io_handler(nd_io_t *io, __attribute__((unused)) int events)
static bool ndL_configure_filter(nd_io_t *io)
{
#ifndef __linux__
# define sock_filter bpf_insn
# define sock_fprog bpf_program
#endif
// Set up filter, so we only get NS and NA messages.
#ifdef __linux__
static struct sock_filter filter[] = {
#else
static struct bpf_insn filter[] = {
#endif
/* Load ether_type. */
BPF_STMT(BPF_LD | BPF_H | BPF_ABS, offsetof(struct ether_header, ether_type)),
/* Drop packet if not ETHERTYPE_IPV6. */
@ -296,17 +297,17 @@ static bool ndL_configure_filter(nd_io_t *io)
/* Drop packet. */
BPF_STMT(BPF_RET | BPF_K, 0),
/* Keep packet. */
BPF_STMT(BPF_RET | BPF_K, (u_int32_t)-1)
BPF_STMT(BPF_RET | BPF_K, (u_int32_t)-1),
};
static struct sock_fprog fprog = { 9, filter };
#ifdef __linux__
if (setsockopt(io->fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)) == -1)
static struct sock_fprog fprog = { .len = 9, .filter = filter };
if (setsockopt(io->fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)) == -1) {
return false;
}
#else
# undef sock_filter
# undef sock_fprog
static struct bpf_program fprog = { .bf_len = 9, .bf_insns = filter };
if (ioctl(io->fd, BIOCSETF, &fprog) == -1) {
return false;
@ -348,8 +349,7 @@ nd_iface_t *nd_iface_open(const char *name, unsigned index)
#ifdef __linux__
// Determine link-layer address.
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
struct ifreq ifr = { 0 };
strcpy(ifr.ifr_name, name);
if (ioctl(ndL_io->fd, SIOCGIFHWADDR, &ifr) < 0) {
@ -426,24 +426,25 @@ nd_iface_t *nd_iface_open(const char *name, unsigned index)
iface = ND_ALLOC(nd_iface_t);
}
memset(iface, 0, sizeof(nd_iface_t));
*iface = (nd_iface_t){
.index = index,
.refcount = 1,
.old_allmulti = -1,
.old_promisc = -1,
};
ND_LL_PREPEND(ndL_first_iface, iface, next);
iface->index = index;
iface->refcount = 1;
iface->old_allmulti = -1;
iface->old_promisc = -1;
strcpy(iface->name, name);
memcpy(iface->lladdr, lladdr, 6);
ND_LL_PREPEND(ndL_first_iface, iface, next);
#ifndef __linux__
io->data = (uintptr_t)iface;
iface->bpf_io = io;
#endif
nd_log_info("New interface %s [%02x:%02x:%02x:%02x:%02x:%02x]", iface->name, lladdr[0], lladdr[1], lladdr[2],
lladdr[3], lladdr[4], lladdr[5]);
nd_log_info("New interface %s [%02x:%02x:%02x:%02x:%02x:%02x]", //
iface->name, lladdr[0], lladdr[1], lladdr[2], lladdr[3], lladdr[4], lladdr[5]);
return iface;
}
@ -485,7 +486,7 @@ static void ndL_get_local_addr(nd_iface_t *iface, nd_addr_t *addr)
addr->s6_addr[15] = iface->lladdr[5];
}
static ssize_t ndL_send_icmp6(nd_iface_t *ifa, ndL_icmp6_msg_t *msg, size_t size, const uint8_t *hwaddr)
static ssize_t ndL_send_icmp6(nd_iface_t *iface, ndL_icmp6_msg_t *msg, size_t size, const uint8_t *hwaddr)
{
assert(size >= sizeof(ndL_icmp6_msg_t));
@ -501,39 +502,38 @@ static ssize_t ndL_send_icmp6(nd_iface_t *ifa, ndL_icmp6_msg_t *msg, size_t size
struct ether_header *eh = (struct ether_header *)buf;
eh->ether_type = htons(ETHERTYPE_IPV6);
memcpy(eh->ether_shost, ifa->lladdr, ETHER_ADDR_LEN);
memcpy(eh->ether_shost, iface->lladdr, ETHER_ADDR_LEN);
memcpy(eh->ether_dhost, hwaddr, ETHER_ADDR_LEN);
memcpy(eh + 1, msg, size);
#ifdef __linux__
struct sockaddr_ll ll;
memset(&ll, 0, sizeof(ll));
ll.sll_family = AF_PACKET;
ll.sll_ifindex = (int)ifa->index;
struct sockaddr_ll ll = {
.sll_family = AF_PACKET,
.sll_ifindex = (int)iface->index,
};
return nd_io_send(ndL_io, (struct sockaddr *)&ll, sizeof(ll), buf, sizeof(struct ether_header) + size);
#else
return nd_io_write(ifa->bpf_io, buf, sizeof(struct ether_header) + size);
return nd_io_write(iface->bpf_io, buf, sizeof(struct ether_header) + size);
#endif
}
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 __attribute__((packed)) {
struct ip6_hdr ip;
struct nd_neighbor_advert na;
struct nd_opt_hdr opt;
uint8_t lladdr[6];
} msg;
memset(&msg, 0, sizeof(msg));
msg.ip.ip6_src = *tgt;
msg.ip.ip6_dst = *dst;
msg.na.nd_na_type = ND_NEIGHBOR_ADVERT;
msg.na.nd_na_target = *tgt;
} msg = {
.ip.ip6_src = *tgt,
.ip.ip6_dst = *dst,
.na.nd_na_type = ND_NEIGHBOR_ADVERT,
.na.nd_na_target = *tgt,
.opt.nd_opt_type = ND_OPT_TARGET_LINKADDR,
.opt.nd_opt_len = 1,
};
if (nd_addr_is_multicast(dst)) {
msg.na.nd_na_flags_reserved |= ND_NA_FLAG_SOLICITED;
@ -543,9 +543,6 @@ ssize_t nd_iface_write_na(nd_iface_t *iface, nd_addr_t *dst, uint8_t *dst_ll, nd
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;
memcpy(msg.lladdr, iface->lladdr, sizeof(msg.lladdr));
nd_log_info("Write NA tgt=%s, dst=%s [%x:%x:%x:%x:%x:%x dev %s]", //
@ -556,24 +553,21 @@ ssize_t nd_iface_write_na(nd_iface_t *iface, nd_addr_t *dst, uint8_t *dst_ll, nd
return ndL_send_icmp6(iface, (ndL_icmp6_msg_t *)&msg, sizeof(msg), dst_ll);
}
ssize_t nd_iface_write_ns(nd_iface_t *ifa, nd_addr_t *tgt)
ssize_t nd_iface_write_ns(nd_iface_t *iface, nd_addr_t *tgt)
{
struct {
struct __attribute__((packed)) {
struct ip6_hdr ip;
struct nd_neighbor_solicit ns;
struct nd_opt_hdr opt;
uint8_t lladdr[6];
} msg;
} msg = {
.ns.nd_ns_type = ND_NEIGHBOR_SOLICIT,
.ns.nd_ns_target = *tgt,
.opt.nd_opt_type = ND_OPT_SOURCE_LINKADDR,
.opt.nd_opt_len = 1,
};
memset(&msg, 0, sizeof(msg));
msg.ns.nd_ns_type = ND_NEIGHBOR_SOLICIT;
msg.ns.nd_ns_target = *tgt;
msg.opt.nd_opt_type = ND_OPT_SOURCE_LINKADDR;
msg.opt.nd_opt_len = 1;
ndL_get_local_addr(ifa, &msg.ip.ip6_src);
ndL_get_local_addr(iface, &msg.ip.ip6_src);
const uint8_t multicast[] = { 255, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 255, 0, 0, 0 };
memcpy(&msg.ip.ip6_dst, multicast, sizeof(struct in6_addr));
@ -581,21 +575,22 @@ ssize_t nd_iface_write_ns(nd_iface_t *ifa, nd_addr_t *tgt)
msg.ip.ip6_dst.s6_addr[14] = tgt->s6_addr[14];
msg.ip.ip6_dst.s6_addr[15] = tgt->s6_addr[15];
memcpy(msg.lladdr, ifa->lladdr, sizeof(msg.lladdr));
memcpy(msg.lladdr, iface->lladdr, sizeof(msg.lladdr));
uint8_t ll_mcast[6] = { 0x33, 0x33 };
*(uint32_t *)&ll_mcast[2] = tgt->s6_addr32[3];
nd_log_trace("Write NS iface=%s, tgt=%s", ifa->name, nd_aton(tgt));
nd_log_trace("Write NS iface=%s, tgt=%s", iface->name, nd_aton(tgt));
return ndL_send_icmp6(ifa, (ndL_icmp6_msg_t *)&msg, sizeof(msg), ll_mcast);
return ndL_send_icmp6(iface, (ndL_icmp6_msg_t *)&msg, sizeof(msg), ll_mcast);
}
bool nd_iface_startup()
{
#ifdef __linux__
if (!(ndL_io = nd_io_socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IPV6))))
if (!(ndL_io = nd_io_socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IPV6)))) {
return false;
}
if (!ndL_configure_filter(ndL_io)) {
nd_io_close(ndL_io);
@ -614,7 +609,7 @@ bool nd_iface_set_allmulti(nd_iface_t *iface, bool on)
{
nd_log_debug("%s all multicast mode for interface %s", on ? "Enabling" : "Disabling", iface->name);
struct ifreq ifr;
struct ifreq ifr = { 0 };
memcpy(ifr.ifr_name, iface->name, IFNAMSIZ);
if (ioctl(ndL_io->fd, SIOCGIFFLAGS, &ifr) < 0) {
@ -648,7 +643,7 @@ bool nd_iface_set_promisc(nd_iface_t *iface, bool on)
{
nd_log_debug("%s promiscuous mode for interface %s", on ? "Enabling" : "Disabling", iface->name);
struct ifreq ifr;
struct ifreq ifr = { 0 };
memcpy(ifr.ifr_name, iface->name, IFNAMSIZ);
if (ioctl(ndL_io->fd, SIOCGIFFLAGS, &ifr) < 0) {

View File

@ -45,7 +45,7 @@ extern bool nd_iface_no_restore_flags;
nd_iface_t *nd_iface_open(const char *if_name, unsigned int if_index);
void nd_iface_close(nd_iface_t *iface);
ssize_t nd_iface_write_ns(nd_iface_t *ifa, nd_addr_t *tgt);
ssize_t nd_iface_write_ns(nd_iface_t *iface, nd_addr_t *tgt);
ssize_t nd_iface_write_na(nd_iface_t *iface, nd_addr_t *dst, uint8_t *dst_ll, nd_addr_t *tgt, bool router);
void nd_iface_get_local_addr(nd_iface_t *iface, nd_addr_t *addr);
bool nd_iface_set_allmulti(nd_iface_t *iface, bool on);

View File

@ -72,10 +72,7 @@ static void ndL_refresh_pollfds()
int index = 0;
ND_LL_FOREACH (ndL_first_io, io, next) {
ndL_pollfds[index].fd = io->fd;
ndL_pollfds[index].revents = 0;
ndL_pollfds[index].events = POLLIN;
index++;
ndL_pollfds[index++] = (struct pollfd){ .fd = io->fd, .events = POLLIN };
}
ndL_pollfds_count = index;
@ -106,11 +103,9 @@ static nd_io_t *ndL_create(int fd)
io = ND_ALLOC(nd_io_t);
}
ND_LL_PREPEND(ndL_first_io, io, next);
*io = (nd_io_t){ .fd = fd };
io->fd = fd;
io->data = 0;
io->handler = NULL;
ND_LL_PREPEND(ndL_first_io, io, next);
#ifndef NDPPD_NO_USE_EPOLL
if (ndL_epoll_fd <= 0 && (ndL_epoll_fd = epoll_create(1)) < 0) {
@ -169,15 +164,17 @@ void nd_io_close(nd_io_t *io)
ssize_t nd_io_send(nd_io_t *io, const struct sockaddr *addr, size_t addrlen, const void *msg, size_t msglen)
{
struct iovec iov;
iov.iov_len = msglen;
iov.iov_base = (caddr_t)msg;
struct iovec iov = {
.iov_len = msglen,
.iov_base = (caddr_t)msg,
};
struct msghdr mhdr;
memset(&mhdr, 0, sizeof(mhdr));
mhdr.msg_name = (caddr_t)addr, mhdr.msg_namelen = addrlen;
mhdr.msg_iov = &iov;
mhdr.msg_iovlen = 1;
struct msghdr mhdr = {
.msg_name = (caddr_t)addr,
mhdr.msg_namelen = addrlen,
.msg_iov = &iov,
.msg_iovlen = 1,
};
ssize_t len;
@ -191,16 +188,17 @@ ssize_t nd_io_send(nd_io_t *io, const struct sockaddr *addr, size_t addrlen, con
ssize_t nd_io_recv(nd_io_t *io, struct sockaddr *addr, size_t addrlen, void *msg, size_t msglen)
{
struct iovec iov;
iov.iov_len = msglen;
iov.iov_base = (caddr_t)msg;
struct iovec iov = {
.iov_len = msglen,
.iov_base = (caddr_t)msg,
};
struct msghdr mhdr;
memset(&mhdr, 0, sizeof(mhdr));
mhdr.msg_name = (caddr_t)addr;
mhdr.msg_namelen = addrlen;
mhdr.msg_iov = &iov;
mhdr.msg_iovlen = 1;
struct msghdr mhdr = {
.msg_name = (caddr_t)addr,
.msg_namelen = addrlen,
.msg_iov = &iov,
.msg_iovlen = 1,
};
int len;
@ -223,9 +221,11 @@ 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) {
nd_log_error("err: %s", strerror(errno));
}
return len;
}

View File

@ -46,12 +46,11 @@ nd_proxy_t *nd_proxy_create(const char *ifname)
proxy = ND_ALLOC(nd_proxy_t);
ND_LL_PREPEND(ndL_proxies, proxy, next);
memset(proxy, 0, sizeof(nd_proxy_t));
*proxy = (nd_proxy_t){ 0 };
strcpy(proxy->ifname, ifname);
ND_LL_PREPEND(ndL_proxies, proxy, next);
return proxy;
}

258
src/rt.c
View File

@ -180,12 +180,14 @@ 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)) {
if (rta->rta_type == IFA_ADDRESS)
if (rta->rta_type == IFA_ADDRESS) {
addr = (nd_addr_t *)RTA_DATA(rta);
}
}
if (!addr)
if (!addr) {
return;
}
ndL_new_addr(msg->ifa_index, addr, msg->ifa_prefixlen);
}
@ -195,12 +197,14 @@ 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)) {
if (rta->rta_type == IFA_ADDRESS)
if (rta->rta_type == IFA_ADDRESS) {
addr = (nd_addr_t *)RTA_DATA(rta);
}
}
if (!addr)
if (!addr) {
return;
}
ndL_delete_addr(msg->ifa_index, addr, msg->ifa_prefixlen);
}
@ -211,14 +215,16 @@ static void ndL_handle_newroute(struct rtmsg *msg, int rtl)
int oif = 0;
for (struct rtattr *rta = RTM_RTA(msg); RTA_OK(rta, rtl); rta = RTA_NEXT(rta, rtl)) {
if (rta->rta_type == RTA_OIF)
if (rta->rta_type == RTA_OIF) {
oif = *(int *)RTA_DATA(rta);
else if (rta->rta_type == RTA_DST)
} else if (rta->rta_type == RTA_DST) {
dst = (nd_addr_t *)RTA_DATA(rta);
}
}
if (!dst || !oif)
if (!dst || !oif) {
return;
}
nd_rt_route_t route = {
.table = msg->rtm_table,
@ -237,14 +243,16 @@ static void ndL_handle_delroute(struct rtmsg *msg, int rtl)
int oif = 0;
for (struct rtattr *rta = RTM_RTA(msg); RTA_OK(rta, rtl); rta = RTA_NEXT(rta, rtl)) {
if (rta->rta_type == RTA_OIF)
if (rta->rta_type == RTA_OIF) {
oif = *(int *)RTA_DATA(rta);
else if (rta->rta_type == RTA_DST)
} else if (rta->rta_type == RTA_DST) {
dst = (nd_addr_t *)RTA_DATA(rta);
}
}
if (!dst || !oif)
if (!dst || !oif) {
return;
}
nd_rt_route_t route = {
.table = msg->rtm_table,
@ -263,8 +271,9 @@ static void ndL_io_handler(__attribute__((unused)) nd_io_t *unused1, __attribute
for (;;) {
ssize_t len = nd_io_recv(ndL_io, NULL, 0, buf, sizeof(buf));
if (len < 0)
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) {
@ -278,14 +287,15 @@ static void ndL_io_handler(__attribute__((unused)) nd_io_t *unused1, __attribute
continue;
}
if (hdr->nlmsg_type == RTM_NEWROUTE)
if (hdr->nlmsg_type == RTM_NEWROUTE) {
ndL_handle_newroute((struct rtmsg *)NLMSG_DATA(hdr), RTM_PAYLOAD(hdr));
else if (hdr->nlmsg_type == RTM_DELROUTE)
} else if (hdr->nlmsg_type == RTM_DELROUTE) {
ndL_handle_delroute((struct rtmsg *)NLMSG_DATA(hdr), RTM_PAYLOAD(hdr));
else if (hdr->nlmsg_type == RTM_NEWADDR)
} else if (hdr->nlmsg_type == RTM_NEWADDR) {
ndL_handle_newaddr((struct ifaddrmsg *)NLMSG_DATA(hdr), IFA_PAYLOAD(hdr));
else if (hdr->nlmsg_type == RTM_DELADDR)
} else if (hdr->nlmsg_type == RTM_DELADDR) {
ndL_handle_deladdr((struct ifaddrmsg *)NLMSG_DATA(hdr), IFA_PAYLOAD(hdr));
}
}
}
}
@ -439,10 +449,10 @@ bool nd_rt_open()
return false;
}
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
addr.nl_groups = (1 << (RTNLGRP_IPV6_IFADDR - 1)) | (1 << (RTNLGRP_IPV6_ROUTE - 1));
struct sockaddr_nl addr = {
.nl_family = AF_NETLINK,
.nl_groups = (1 << (RTNLGRP_IPV6_IFADDR - 1)) | (1 << (RTNLGRP_IPV6_ROUTE - 1)),
};
if (!nd_io_bind(ndL_io, (struct sockaddr *)&addr, sizeof(addr))) {
nd_log_error("Failed to bind netlink socket: %s", strerror(errno));
@ -472,27 +482,23 @@ void nd_rt_cleanup()
bool nd_rt_query_routes()
{
#ifdef __linux__
if (nd_rt_dump_timeout)
if (nd_rt_dump_timeout) {
return false;
}
struct {
struct nlmsghdr hdr;
struct rtmsg msg;
} req;
} req = {
.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)),
.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
.hdr.nlmsg_type = RTM_GETROUTE,
.msg.rtm_protocol = RTPROT_UNSPEC,
.msg.rtm_table = RT_TABLE_UNSPEC,
.msg.rtm_family = AF_INET6,
};
memset(&req, 0, sizeof(req));
req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
req.hdr.nlmsg_type = RTM_GETROUTE;
req.msg.rtm_protocol = RTPROT_UNSPEC;
req.msg.rtm_table = RT_TABLE_UNSPEC;
req.msg.rtm_family = AF_INET6;
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
struct sockaddr_nl addr = { .nl_family = AF_NETLINK };
nd_rt_dump_timeout = nd_current_time + 5000;
@ -506,26 +512,22 @@ bool nd_rt_query_routes()
bool nd_rt_query_addresses()
{
#ifdef __linux__
if (nd_rt_dump_timeout)
if (nd_rt_dump_timeout) {
return false;
}
struct {
struct nlmsghdr hdr;
struct ifaddrmsg msg;
} req;
} req = {
.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)),
.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP,
.hdr.nlmsg_type = RTM_GETADDR,
.hdr.nlmsg_seq = 1,
.msg.ifa_family = AF_INET6,
};
memset(&req, 0, sizeof(req));
req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
req.hdr.nlmsg_type = RTM_GETADDR;
req.hdr.nlmsg_seq = 1;
req.msg.ifa_family = AF_INET6;
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
struct sockaddr_nl addr = { .nl_family = AF_NETLINK };
nd_rt_dump_timeout = nd_current_time + 5000;
@ -559,35 +561,27 @@ bool nd_rt_add_route(nd_addr_t *dst, unsigned pflen, unsigned oif, unsigned tabl
nd_addr_t dst;
// struct rtattr exp_attr __attribute__((aligned(RTA_ALIGNTO)));
// uint32_t exp;
} req;
} req = {
.msg.rtm_protocol = RTPROT_NDPPD,
.msg.rtm_family = AF_INET6,
.msg.rtm_dst_len = pflen,
.msg.rtm_table = table,
.msg.rtm_scope = RT_SCOPE_UNIVERSE,
.oif_attr.rta_type = RTA_OIF,
.oif_attr.rta_len = RTA_LENGTH(sizeof(req.oif)),
.oif = oif,
.dst_attr.rta_type = RTA_DST,
.dst_attr.rta_len = RTA_LENGTH(sizeof(req.dst)),
.dst = *dst,
.hdr.nlmsg_type = RTM_NEWROUTE,
.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE,
.hdr.nlmsg_len = sizeof(req),
// .exp_attr.rta_type = RTA_EXPIRES,
// .exp_attr.rta_len = RTA_LENGTH(sizeof(req.exp)),
// .exp = 60,
};
memset(&req, 0, sizeof(req));
req.msg.rtm_protocol = RTPROT_NDPPD;
req.msg.rtm_family = AF_INET6;
req.msg.rtm_dst_len = pflen;
req.msg.rtm_table = table;
req.msg.rtm_scope = RT_SCOPE_UNIVERSE;
req.oif_attr.rta_type = RTA_OIF;
req.oif_attr.rta_len = RTA_LENGTH(sizeof(req.oif));
req.oif = oif;
req.dst_attr.rta_type = RTA_DST;
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.hdr.nlmsg_type = RTM_NEWROUTE;
req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
req.hdr.nlmsg_len = sizeof(req);
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
struct sockaddr_nl addr = { .nl_family = AF_NETLINK };
return nd_io_send(ndL_io, (struct sockaddr *)&addr, sizeof(addr), &req, sizeof(req)) >= 0;
#else
@ -596,34 +590,27 @@ bool nd_rt_add_route(nd_addr_t *dst, unsigned pflen, unsigned oif, unsigned tabl
struct sockaddr_in6 dst;
struct sockaddr_dl dl __aligned(sizeof(u_long));
struct sockaddr_in6 mask __aligned(sizeof(u_long));
} msg;
memset(&msg, 0, sizeof(msg));
msg.hdr.rtm_type = RTM_ADD;
msg.hdr.rtm_version = RTM_VERSION;
msg.hdr.rtm_pid = getpid();
msg.hdr.rtm_flags = RTF_UP | RTF_PROTO3;
msg.hdr.rtm_msglen = sizeof(msg);
msg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
msg.hdr.rtm_index = oif;
# ifdef __FreeBSD__
(void)table;
# else
msg.hdr->rtm_tableid = table;
} msg = {
.hdr.rtm_type = RTM_ADD,
.hdr.rtm_version = RTM_VERSION,
.hdr.rtm_pid = getpid(),
.hdr.rtm_flags = RTF_UP | RTF_PROTO3,
.hdr.rtm_msglen = sizeof(msg),
.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK,
.hdr.rtm_index = oif,
# ifndef __FreeBSD__
msg.hdr->rtm_tableid = table,
# endif
.dst.sin6_family = AF_INET6,
.dst.sin6_len = sizeof(msg.dst),
.dst.sin6_addr = *dst,
.dl.sdl_family = AF_LINK,
.dl.sdl_index = oif,
.dl.sdl_len = sizeof(msg.dl),
.mask.sin6_family = AF_INET6,
.mask.sin6_len = sizeof(msg.mask),
};
msg.dst.sin6_family = AF_INET6;
msg.dst.sin6_len = sizeof(msg.dst);
msg.dst.sin6_addr = *dst;
msg.dl.sdl_family = AF_LINK;
msg.dl.sdl_index = oif;
msg.dl.sdl_len = sizeof(msg.dl);
msg.mask.sin6_family = AF_INET6;
msg.mask.sin6_len = sizeof(msg.mask);
nd_mask_from_pflen(pflen, &msg.mask.sin6_addr);
nd_log_info("rt: Adding route %s/%d table %d", nd_aton(dst), pflen, table);
@ -640,27 +627,21 @@ bool nd_rt_remove_route(nd_addr_t *dst, unsigned pflen, unsigned table)
struct rtmsg msg;
struct rtattr dst_attr __attribute__((aligned(NLMSG_ALIGNTO)));
nd_addr_t dst;
} req;
} req = {
.msg.rtm_protocol = RTPROT_NDPPD,
.msg.rtm_family = AF_INET6,
.msg.rtm_dst_len = pflen,
.msg.rtm_table = table,
.msg.rtm_scope = RT_SCOPE_UNIVERSE,
.dst_attr.rta_type = RTA_DST,
.dst_attr.rta_len = RTA_LENGTH(sizeof(req.dst)),
.dst = *dst,
.hdr.nlmsg_type = RTM_DELROUTE,
.hdr.nlmsg_flags = NLM_F_REQUEST,
.hdr.nlmsg_len = sizeof(req),
};
memset(&req, 0, sizeof(req));
req.msg.rtm_protocol = RTPROT_NDPPD;
req.msg.rtm_family = AF_INET6;
req.msg.rtm_dst_len = pflen;
req.msg.rtm_table = table;
req.msg.rtm_scope = RT_SCOPE_UNIVERSE;
req.dst_attr.rta_type = RTA_DST;
req.dst_attr.rta_len = RTA_LENGTH(sizeof(req.dst));
req.dst = *dst;
req.hdr.nlmsg_type = RTM_DELROUTE;
req.hdr.nlmsg_flags = NLM_F_REQUEST;
req.hdr.nlmsg_len = sizeof(req);
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
struct sockaddr_nl addr = { .nl_family = AF_NETLINK };
return nd_io_send(ndL_io, (struct sockaddr *)&addr, sizeof(addr), &req, sizeof(req)) >= 0;
#else
@ -668,27 +649,22 @@ bool nd_rt_remove_route(nd_addr_t *dst, unsigned pflen, unsigned table)
struct rt_msghdr hdr;
struct sockaddr_in6 dst;
struct sockaddr_in6 mask __aligned(sizeof(u_long));
} req;
memset(&req, 0, sizeof(req));
req.hdr.rtm_type = RTM_DELETE;
req.hdr.rtm_version = RTM_VERSION;
req.hdr.rtm_pid = getpid();
req.hdr.rtm_msglen = sizeof(req);
req.hdr.rtm_addrs = RTA_DST | RTA_NETMASK;
# ifdef __FreeBSD__
(void)table;
# else
msg.hdr->rtm_tableid = table;
} req = {
.hdr.rtm_type = RTM_DELETE,
.hdr.rtm_version = RTM_VERSION,
.hdr.rtm_pid = getpid(),
.hdr.rtm_msglen = sizeof(req),
.hdr.rtm_addrs = RTA_DST | RTA_NETMASK,
# ifndef __FreeBSD__
.hdr.rtm_tableid = table,
# endif
.dst.sin6_family = AF_INET6,
.dst.sin6_len = sizeof(req.dst),
.dst.sin6_addr = *dst,
.mask.sin6_family = AF_INET6,
.mask.sin6_len = sizeof(req.mask),
};
req.dst.sin6_family = AF_INET6;
req.dst.sin6_len = sizeof(req.dst);
req.dst.sin6_addr = *dst;
req.mask.sin6_family = AF_INET6;
req.mask.sin6_len = sizeof(req.mask);
nd_mask_from_pflen(pflen, &req.mask.sin6_addr);
nd_log_info("rt: Removing route %s/%d table %d", nd_aton(dst), pflen, table);

View File

@ -14,21 +14,17 @@
//
// You should have received a copy of the GNU General Public License
// 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)
{
nd_rule_t *rule = ND_ALLOC(nd_rule_t);
memset(rule, 0, sizeof(nd_rule_t));
*rule = (nd_rule_t){ .proxy = proxy };
ND_LL_PREPEND(proxy->rules, rule, next);
rule->proxy = proxy;
return rule;
}

View File

@ -81,16 +81,16 @@ nd_session_t *nd_session_create(nd_rule_t *rule, nd_addr_t *tgt)
session = ND_ALLOC(nd_session_t);
}
ND_LL_PREPEND(rule->proxy->sessions, session, next_in_proxy);
memset(session, 0, sizeof(nd_session_t));
session->rule = rule;
session->state_time = nd_current_time;
session->tgt = *tgt;
*session = (nd_session_t){
.rule = rule,
.state_time = nd_current_time,
.tgt = *tgt,
};
nd_addr_combine(&rule->rewrite_tgt, tgt, rule->rewrite_pflen, &session->real_tgt);
ND_LL_PREPEND(rule->proxy->sessions, session, next_in_proxy);
if (rule->mode == ND_MODE_AUTO) {
nd_rt_route_t *route = nd_rt_find_route(tgt, rule->table);