Refactor how the AF_PACKET socket is used
This commit is contained in:
parent
be97afdf83
commit
f0e0d767f3
122
src/iface.c
122
src/iface.c
@ -33,10 +33,10 @@
|
||||
|
||||
#include "addr.h"
|
||||
#include "iface.h"
|
||||
#include "io.h"
|
||||
#include "ndppd.h"
|
||||
#include "proxy.h"
|
||||
#include "session.h"
|
||||
#include "sio.h"
|
||||
|
||||
extern int nd_conf_invalid_ttl;
|
||||
extern int nd_conf_valid_ttl;
|
||||
@ -46,6 +46,7 @@ extern int nd_conf_retrans_time;
|
||||
extern bool nd_conf_keepalive;
|
||||
|
||||
static nd_iface_t *ndL_first_iface, *ndL_first_free_iface;
|
||||
static nd_io_t *ndL_io;
|
||||
|
||||
/* Used when daemonizing to make sure the parent process does not restore these flags upon exit. */
|
||||
bool nd_iface_no_restore_flags;
|
||||
@ -150,7 +151,7 @@ static uint16_t ndL_calculate_icmp6_checksum(ndL_icmp6_msg_t *msg, size_t size)
|
||||
return htons(~sum);
|
||||
}
|
||||
|
||||
static void ndL_handle_packet(nd_iface_t *iface, uint8_t *buf, size_t buflen)
|
||||
static __attribute__((unused)) void ndL_handle_packet(nd_iface_t *iface, uint8_t *buf, size_t buflen)
|
||||
{
|
||||
ndL_icmp6_msg_t *msg = (ndL_icmp6_msg_t *)buf;
|
||||
|
||||
@ -172,21 +173,18 @@ static void ndL_handle_packet(nd_iface_t *iface, uint8_t *buf, size_t buflen)
|
||||
ndL_handle_na(iface, msg);
|
||||
}
|
||||
|
||||
static void ndL_sio_handler(nd_sio_t *sio, __attribute__((unused)) int events)
|
||||
static void ndL_io_handler(nd_io_t *io, __attribute__((unused)) int events)
|
||||
{
|
||||
nd_iface_t *ifa = (nd_iface_t *)sio->data;
|
||||
|
||||
struct sockaddr_ll lladdr;
|
||||
memset(&lladdr, 0, sizeof(struct sockaddr_ll));
|
||||
lladdr.sll_family = AF_PACKET;
|
||||
lladdr.sll_protocol = htons(ETH_P_IPV6);
|
||||
lladdr.sll_ifindex = (int)ifa->index;
|
||||
|
||||
uint8_t buf[1024];
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ssize_t len = nd_sio_recv(sio, (struct sockaddr *)&lladdr, sizeof(lladdr), buf, sizeof(buf));
|
||||
ssize_t len = nd_io_recv(io, (struct sockaddr *)&lladdr, sizeof(lladdr), buf, sizeof(buf));
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
@ -194,7 +192,12 @@ static void ndL_sio_handler(nd_sio_t *sio, __attribute__((unused)) int events)
|
||||
if (len < 0)
|
||||
return;
|
||||
|
||||
ndL_handle_packet(ifa, buf, len);
|
||||
nd_iface_t *iface;
|
||||
|
||||
ND_LL_SEARCH(ndL_first_iface, iface, next, iface->index == (unsigned int)lladdr.sll_ifindex);
|
||||
|
||||
if (iface)
|
||||
ndL_handle_packet(iface, buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,57 +235,18 @@ nd_iface_t *nd_iface_open(const char *name, unsigned int index)
|
||||
return iface;
|
||||
}
|
||||
|
||||
/* No such interface. */
|
||||
|
||||
nd_sio_t *sio = nd_sio_open(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
|
||||
|
||||
if (!sio)
|
||||
{
|
||||
nd_log_error("Failed to create socket: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Determine link-layer address. */
|
||||
|
||||
struct ifreq ifr;
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strcpy(ifr.ifr_name, name);
|
||||
|
||||
if (ioctl(sio->fd, SIOCGIFHWADDR, &ifr) < 0)
|
||||
if (ioctl(ndL_io->fd, SIOCGIFHWADDR, &ifr) < 0)
|
||||
{
|
||||
nd_sio_close(sio);
|
||||
nd_log_error("Failed to determine link-layer address: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set up filter, so we only get NS and NA messages. */
|
||||
|
||||
static struct sock_filter filter[] = {
|
||||
/* Load next header field. */
|
||||
BPF_STMT(BPF_LD | BPF_B | BPF_ABS, offsetof(struct ip6_hdr, ip6_nxt)),
|
||||
/* Bail if it's not IPPROTO_ICMPV6. */
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_ICMPV6, 0, 3),
|
||||
/* Load the ICMPv6 type. */
|
||||
BPF_STMT(BPF_LD | BPF_B | BPF_ABS, sizeof(struct ip6_hdr) + offsetof(struct icmp6_hdr, icmp6_type)),
|
||||
/* Keep if ND_NEIGHBOR_SOLICIT. */
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ND_NEIGHBOR_SOLICIT, 2, 0),
|
||||
/* Keep if ND_NEIGHBOR_SOLICIT. */
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ND_NEIGHBOR_ADVERT, 1, 0),
|
||||
/* Drop packet. */
|
||||
BPF_STMT(BPF_RET | BPF_K, 0),
|
||||
/* Keep packet. */
|
||||
BPF_STMT(BPF_RET | BPF_K, (u_int32_t)-1)
|
||||
};
|
||||
|
||||
static struct sock_fprog fprog = { 7, filter };
|
||||
|
||||
if (setsockopt(sio->fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)) < 0)
|
||||
{
|
||||
nd_sio_close(sio);
|
||||
nd_log_error("Failed to configure netfilter: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate the nd_ifa_t object. */
|
||||
|
||||
iface = ndL_first_free_iface;
|
||||
@ -296,7 +260,6 @@ nd_iface_t *nd_iface_open(const char *name, unsigned int index)
|
||||
|
||||
ND_LL_PREPEND(ndL_first_iface, iface, next);
|
||||
|
||||
iface->sio = sio;
|
||||
iface->index = index;
|
||||
iface->refcount = 1;
|
||||
iface->old_allmulti = -1;
|
||||
@ -304,9 +267,6 @@ nd_iface_t *nd_iface_open(const char *name, unsigned int index)
|
||||
strcpy(iface->name, name);
|
||||
memcpy(iface->lladdr, ifr.ifr_hwaddr.sa_data, 6);
|
||||
|
||||
sio->data = (intptr_t)iface;
|
||||
sio->handler = ndL_sio_handler;
|
||||
|
||||
nd_log_info("New interface %s (%d)", iface->name, iface->index);
|
||||
|
||||
return iface;
|
||||
@ -325,8 +285,6 @@ void nd_iface_close(nd_iface_t *iface)
|
||||
nd_iface_set_allmulti(iface, iface->old_allmulti);
|
||||
}
|
||||
|
||||
nd_sio_close(iface->sio);
|
||||
|
||||
ND_LL_DELETE(ndL_first_iface, iface, next);
|
||||
ND_LL_PREPEND(ndL_first_free_iface, iface, next);
|
||||
}
|
||||
@ -363,7 +321,7 @@ static ssize_t ndL_send_icmp6(nd_iface_t *ifa, ndL_icmp6_msg_t *msg, size_t size
|
||||
addr.sll_ifindex = (int)ifa->index;
|
||||
memcpy(addr.sll_addr, hwaddr, 6);
|
||||
|
||||
return nd_sio_send(ifa->sio, (struct sockaddr *)&addr, sizeof(addr), msg, size);
|
||||
return nd_io_send(ndL_io, (struct sockaddr *)&addr, sizeof(addr), msg, size);
|
||||
}
|
||||
|
||||
ssize_t nd_iface_write_na(nd_iface_t *iface, nd_addr_t *dst, uint8_t *dst_ll, nd_addr_t *tgt, bool router)
|
||||
@ -395,8 +353,8 @@ ssize_t nd_iface_write_na(nd_iface_t *iface, nd_addr_t *dst, uint8_t *dst_ll, nd
|
||||
|
||||
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]", nd_aton(tgt), nd_aton(dst),
|
||||
dst_ll[0], dst_ll[1], dst_ll[2], dst_ll[3], dst_ll[4], dst_ll[5], iface->name);
|
||||
nd_log_info("Write NA tgt=%s, dst=%s [%x:%x:%x:%x:%x:%x dev %s]", nd_aton(tgt), nd_aton(dst), dst_ll[0], dst_ll[1],
|
||||
dst_ll[2], dst_ll[3], dst_ll[4], dst_ll[5], iface->name);
|
||||
|
||||
return ndL_send_icmp6(iface, (ndL_icmp6_msg_t *)&msg, sizeof(msg), dst_ll);
|
||||
}
|
||||
@ -437,6 +395,45 @@ ssize_t nd_iface_write_ns(nd_iface_t *ifa, nd_addr_t *tgt)
|
||||
return ndL_send_icmp6(ifa, (ndL_icmp6_msg_t *)&msg, sizeof(msg), ll_mcast);
|
||||
}
|
||||
|
||||
bool nd_iface_startup()
|
||||
{
|
||||
if (!(ndL_io = nd_io_socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6))))
|
||||
return false;
|
||||
|
||||
/* Set up filter, so we only get NS and NA messages. */
|
||||
|
||||
static struct sock_filter filter[] = {
|
||||
/* Load next header field. */
|
||||
BPF_STMT(BPF_LD | BPF_B | BPF_ABS, offsetof(struct ip6_hdr, ip6_nxt)),
|
||||
/* Bail if it's not IPPROTO_ICMPV6. */
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, IPPROTO_ICMPV6, 0, 3),
|
||||
/* Load the ICMPv6 type. */
|
||||
BPF_STMT(BPF_LD | BPF_B | BPF_ABS, sizeof(struct ip6_hdr) + offsetof(struct icmp6_hdr, icmp6_type)),
|
||||
/* Keep if ND_NEIGHBOR_SOLICIT. */
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ND_NEIGHBOR_SOLICIT, 2, 0),
|
||||
/* Keep if ND_NEIGHBOR_SOLICIT. */
|
||||
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ND_NEIGHBOR_ADVERT, 1, 0),
|
||||
/* Drop packet. */
|
||||
BPF_STMT(BPF_RET | BPF_K, 0),
|
||||
/* Keep packet. */
|
||||
BPF_STMT(BPF_RET | BPF_K, (u_int32_t)-1)
|
||||
};
|
||||
|
||||
static struct sock_fprog fprog = { 7, filter };
|
||||
|
||||
if (setsockopt(ndL_io->fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)) < 0)
|
||||
{
|
||||
nd_io_close(ndL_io);
|
||||
ndL_io = NULL;
|
||||
nd_log_error("Failed to configure netfilter: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ndL_io->handler = ndL_io_handler;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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);
|
||||
@ -444,7 +441,7 @@ bool nd_iface_set_allmulti(nd_iface_t *iface, bool on)
|
||||
struct ifreq ifr;
|
||||
memcpy(ifr.ifr_name, iface->name, IFNAMSIZ);
|
||||
|
||||
if (ioctl(iface->sio->fd, SIOCGIFFLAGS, &ifr) < 0)
|
||||
if (ioctl(ndL_io->fd, SIOCGIFFLAGS, &ifr) < 0)
|
||||
{
|
||||
nd_log_error("Failed to get interface flags: %s", strerror(errno));
|
||||
return false;
|
||||
@ -461,7 +458,7 @@ bool nd_iface_set_allmulti(nd_iface_t *iface, bool on)
|
||||
else
|
||||
ifr.ifr_flags &= ~IFF_ALLMULTI;
|
||||
|
||||
if (ioctl(iface->sio->fd, SIOCSIFFLAGS, &ifr) < 0)
|
||||
if (ioctl(ndL_io->fd, SIOCSIFFLAGS, &ifr) < 0)
|
||||
{
|
||||
nd_log_error("Failed to set interface flags: %s", strerror(errno));
|
||||
return false;
|
||||
@ -477,7 +474,7 @@ bool nd_iface_set_promisc(nd_iface_t *iface, bool on)
|
||||
struct ifreq ifr;
|
||||
memcpy(ifr.ifr_name, iface->name, IFNAMSIZ);
|
||||
|
||||
if (ioctl(iface->sio->fd, SIOCGIFFLAGS, &ifr) < 0)
|
||||
if (ioctl(ndL_io->fd, SIOCGIFFLAGS, &ifr) < 0)
|
||||
{
|
||||
nd_log_error("Failed to get interface flags: %s", strerror(errno));
|
||||
return false;
|
||||
@ -494,7 +491,7 @@ bool nd_iface_set_promisc(nd_iface_t *iface, bool on)
|
||||
else
|
||||
ifr.ifr_flags &= ~IFF_PROMISC;
|
||||
|
||||
if (ioctl(iface->sio->fd, SIOCSIFFLAGS, &ifr) < 0)
|
||||
if (ioctl(ndL_io->fd, SIOCSIFFLAGS, &ifr) < 0)
|
||||
{
|
||||
nd_log_error("Failed to set interface flags: %s", strerror(errno));
|
||||
return false;
|
||||
@ -507,8 +504,9 @@ void nd_iface_cleanup()
|
||||
{
|
||||
ND_LL_FOREACH_S(ndL_first_iface, iface, tmp, next)
|
||||
{
|
||||
/* We're gonna be bad and just ignore refs here as all memory will soon be invalid anyway. */
|
||||
iface->refcount = 1;
|
||||
nd_iface_close(iface);
|
||||
}
|
||||
|
||||
nd_io_close(ndL_io);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define NDPPD_IFACE_H
|
||||
|
||||
#include "ndppd.h"
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
struct nd_iface
|
||||
@ -37,7 +38,6 @@ struct nd_iface
|
||||
|
||||
nd_proxy_t *proxy;
|
||||
nd_session_t *sessions; /* All sessions expecting NA messages to arrive here. */
|
||||
nd_sio_t *sio;
|
||||
};
|
||||
|
||||
extern bool nd_iface_no_restore_flags;
|
||||
@ -49,6 +49,7 @@ ssize_t nd_iface_write_na(nd_iface_t *iface, nd_addr_t *dst, uint8_t *dst_ll, nd
|
||||
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);
|
||||
bool nd_iface_set_promisc(nd_iface_t *iface, bool on);
|
||||
bool nd_iface_startup();
|
||||
void nd_iface_cleanup();
|
||||
|
||||
#endif /* NDPPD_IFACE_H */
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef NDPPD_NO_USE_EPOLL
|
||||
# include <fcntl.h>
|
||||
# include <sys/epoll.h>
|
||||
#else
|
||||
# include <poll.h>
|
||||
@ -34,16 +35,16 @@
|
||||
# define EPOLLIN POLLIN
|
||||
#endif
|
||||
|
||||
#include "io.h"
|
||||
#include "ndppd.h"
|
||||
#include "sio.h"
|
||||
|
||||
static nd_sio_t *ndL_first_sio, *ndL_first_free_sio;
|
||||
static nd_io_t *ndL_first_io, *ndL_first_free_io;
|
||||
|
||||
#ifndef NDPPD_NO_USE_EPOLL
|
||||
static int ndL_epoll_fd;
|
||||
#else
|
||||
# ifndef NDPPD_STATIC_POLLFDS_SIZE
|
||||
# define NDPPD_STATIC_POLLFDS_SIZE 32
|
||||
# define NDPPD_STATIC_POLLFDS_SIZE 8
|
||||
# endif
|
||||
|
||||
static struct pollfd static_pollfds[NDPPD_STATIC_POLLFDS_SIZE];
|
||||
@ -74,7 +75,7 @@ static void ndL_refresh_pollfds()
|
||||
|
||||
ND_LL_FOREACH(ndL_first_sio, sio, next)
|
||||
{
|
||||
pollfds[index].fd = sio->fd;
|
||||
pollfds[index].fd = io->fd;
|
||||
pollfds[index].revents = 0;
|
||||
pollfds[index].events = POLLIN;
|
||||
index++;
|
||||
@ -84,73 +85,113 @@ static void ndL_refresh_pollfds()
|
||||
}
|
||||
#endif
|
||||
|
||||
nd_sio_t *nd_sio_open(int domain, int type, int protocol)
|
||||
nd_io_t *nd_sio_create(int fd)
|
||||
{
|
||||
int fd = socket(domain, type, protocol);
|
||||
nd_io_t *io = ndL_first_free_io;
|
||||
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
if (io)
|
||||
ND_LL_DELETE(ndL_first_free_io, io, next);
|
||||
else
|
||||
io = ND_ALLOC(nd_io_t);
|
||||
|
||||
/* Non-blocking. */
|
||||
ND_LL_PREPEND(ndL_first_io, io, next);
|
||||
|
||||
int on = 1;
|
||||
if (ioctl(fd, FIONBIO, (char *)&on) < 0)
|
||||
{
|
||||
close(fd);
|
||||
return NULL;
|
||||
io->fd = fd;
|
||||
io->data = 0;
|
||||
io->handler = NULL;
|
||||
|
||||
return io;
|
||||
}
|
||||
|
||||
/* Allocate the nd_sio_t object. */
|
||||
static nd_io_t *ndL_create(int fd)
|
||||
{
|
||||
int flags = fcntl(fd, F_GETFL, 0);
|
||||
|
||||
nd_sio_t *sio = ndL_first_free_sio;
|
||||
if (flags == -1)
|
||||
{
|
||||
nd_log_error("Could not read flags: %s", strerror(errno));
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sio)
|
||||
ND_LL_DELETE(ndL_first_free_sio, sio, next);
|
||||
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
|
||||
{
|
||||
nd_log_error("Could not set flags: %s", strerror(errno));
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
nd_io_t *io = ndL_first_free_io;
|
||||
|
||||
if (io)
|
||||
ND_LL_DELETE(ndL_first_free_io, io, next);
|
||||
else
|
||||
sio = ND_ALLOC(nd_sio_t);
|
||||
io = ND_ALLOC(nd_io_t);
|
||||
|
||||
ND_LL_PREPEND(ndL_first_sio, sio, next);
|
||||
ND_LL_PREPEND(ndL_first_io, io, next);
|
||||
|
||||
sio->fd = fd;
|
||||
io->fd = fd;
|
||||
io->data = 0;
|
||||
io->handler = NULL;
|
||||
|
||||
#ifndef NDPPD_NO_USE_EPOLL
|
||||
if (ndL_epoll_fd <= 0 && (ndL_epoll_fd = epoll_create(1)) < 0)
|
||||
{
|
||||
nd_log_error("epoll_create() failed: %s", strerror(errno));
|
||||
nd_sio_close(sio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct epoll_event event = { .events = EPOLLIN, .data.ptr = sio };
|
||||
struct epoll_event event = { .events = EPOLLIN, .data.ptr = io };
|
||||
|
||||
if (epoll_ctl(ndL_epoll_fd, EPOLL_CTL_ADD, fd, &event) < 0)
|
||||
if (epoll_ctl(ndL_epoll_fd, EPOLL_CTL_ADD, io->fd, &event) < 0)
|
||||
{
|
||||
nd_log_error("epoll_ctl() failed: %s", strerror(errno));
|
||||
nd_sio_close(sio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
/* Make sure our pollfd array is updated. */
|
||||
ndL_dirty = true;
|
||||
#endif
|
||||
|
||||
return sio;
|
||||
return io;
|
||||
}
|
||||
|
||||
void nd_sio_close(nd_sio_t *sio)
|
||||
nd_io_t *nd_io_socket(int domain, int type, int protocol)
|
||||
{
|
||||
close(sio->fd);
|
||||
int fd = socket(domain, type, protocol);
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
nd_log_error("nd_io_socket(): Could not create socket: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ndL_create(fd);
|
||||
}
|
||||
|
||||
nd_io_t *nd_io_open(const char *file, int oflag)
|
||||
{
|
||||
int fd = open(file, oflag);
|
||||
|
||||
if (fd == -1)
|
||||
return NULL;
|
||||
|
||||
return ndL_create(fd);
|
||||
}
|
||||
|
||||
void nd_io_close(nd_io_t *io)
|
||||
{
|
||||
close(io->fd);
|
||||
|
||||
#ifdef NDPPD_NO_USE_EPOLL
|
||||
ndL_dirty = true;
|
||||
#endif
|
||||
|
||||
ND_LL_DELETE(ndL_first_sio, sio, next);
|
||||
ND_LL_PREPEND(ndL_first_free_sio, sio, next);
|
||||
ND_LL_DELETE(ndL_first_io, io, next);
|
||||
ND_LL_PREPEND(ndL_first_free_io, io, next);
|
||||
}
|
||||
|
||||
ssize_t nd_sio_send(nd_sio_t *sio, const struct sockaddr *addr, size_t addrlen, const void *msg, size_t msglen)
|
||||
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;
|
||||
@ -164,7 +205,7 @@ ssize_t nd_sio_send(nd_sio_t *sio, const struct sockaddr *addr, size_t addrlen,
|
||||
|
||||
ssize_t len;
|
||||
|
||||
if ((len = sendmsg(sio->fd, &mhdr, 0)) < 0)
|
||||
if ((len = sendmsg(io->fd, &mhdr, 0)) < 0)
|
||||
{
|
||||
printf("send err %s\n", strerror(errno));
|
||||
return -1;
|
||||
@ -173,7 +214,7 @@ ssize_t nd_sio_send(nd_sio_t *sio, const struct sockaddr *addr, size_t addrlen,
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t nd_sio_recv(nd_sio_t *sio, struct sockaddr *addr, size_t addrlen, void *msg, size_t msglen)
|
||||
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;
|
||||
@ -188,7 +229,7 @@ ssize_t nd_sio_recv(nd_sio_t *sio, struct sockaddr *addr, size_t addrlen, void *
|
||||
|
||||
int len;
|
||||
|
||||
if ((len = recvmsg(sio->fd, &mhdr, 0)) < 0)
|
||||
if ((len = recvmsg(io->fd, &mhdr, 0)) < 0)
|
||||
{
|
||||
if (errno != EAGAIN)
|
||||
nd_log_error("nd_sio_recv() failed: %s", strerror(errno));
|
||||
@ -199,12 +240,12 @@ ssize_t nd_sio_recv(nd_sio_t *sio, struct sockaddr *addr, size_t addrlen, void *
|
||||
return len;
|
||||
}
|
||||
|
||||
bool nd_sio_bind(nd_sio_t *sio, const struct sockaddr *addr, size_t addrlen)
|
||||
bool nd_io_bind(nd_io_t *io, const struct sockaddr *addr, size_t addrlen)
|
||||
{
|
||||
return bind(sio->fd, addr, addrlen) == 0;
|
||||
return bind(io->fd, addr, addrlen) == 0;
|
||||
}
|
||||
|
||||
bool nd_sio_poll()
|
||||
bool nd_io_poll()
|
||||
{
|
||||
#ifndef NDPPD_NO_USE_EPOLL
|
||||
struct epoll_event events[8];
|
||||
@ -219,10 +260,10 @@ bool nd_sio_poll()
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
nd_sio_t *sio = (nd_sio_t *)events[i].data.ptr;
|
||||
nd_io_t *io = (nd_io_t *)events[i].data.ptr;
|
||||
|
||||
if (sio->handler)
|
||||
sio->handler(sio, events[i].events);
|
||||
if (io->handler)
|
||||
io->handler(io, events[i].events);
|
||||
}
|
||||
|
||||
#else
|
||||
@ -245,12 +286,12 @@ bool nd_sio_poll()
|
||||
if (pollfds[i].revents == 0)
|
||||
continue;
|
||||
|
||||
for (nd_sio_t *sio = ndL_first_sio; sio; sio = sio->next)
|
||||
for (nd_sio_t *sio = ndL_first_sio; sio; sio = io->next)
|
||||
{
|
||||
if (sio->fd == pollfds[i].fd)
|
||||
if (io->fd == pollfds[i].fd)
|
||||
{
|
||||
if (sio->handler != NULL)
|
||||
sio->handler(sio, pollfds[i].revents);
|
||||
if (io->handler != NULL)
|
||||
io->handler(sio, pollfds[i].revents);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -261,16 +302,18 @@ bool nd_sio_poll()
|
||||
return true;
|
||||
}
|
||||
|
||||
void nd_sio_cleanup()
|
||||
void nd_io_cleanup()
|
||||
{
|
||||
ND_LL_FOREACH_S(ndL_first_sio, sio, tmp, next)
|
||||
ND_LL_FOREACH_S(ndL_first_io, sio, tmp, next)
|
||||
{
|
||||
nd_sio_close(sio);
|
||||
nd_io_close(sio);
|
||||
}
|
||||
|
||||
#ifndef NDPPD_NO_USE_EPOLL
|
||||
if (ndL_epoll_fd > 0)
|
||||
{
|
||||
close(ndL_epoll_fd);
|
||||
ndL_epoll_fd = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
@ -16,27 +16,30 @@
|
||||
* 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_SIO_H
|
||||
#define NDPPD_SIO_H
|
||||
#ifndef NDPPD_IO_H
|
||||
#define NDPPD_IO_H
|
||||
|
||||
#include "ndppd.h"
|
||||
|
||||
typedef void(nd_sio_handler_t)(nd_sio_t *sio, int events);
|
||||
typedef void(nd_io_handler_t)(nd_io_t *io, int events);
|
||||
|
||||
struct nd_sio
|
||||
struct nd_io
|
||||
{
|
||||
nd_sio_t *next;
|
||||
nd_io_t *next;
|
||||
int fd;
|
||||
uintptr_t data;
|
||||
nd_sio_handler_t *handler;
|
||||
nd_io_handler_t *handler;
|
||||
};
|
||||
|
||||
nd_sio_t *nd_sio_open(int domain, int type, int protocol);
|
||||
void nd_sio_close(nd_sio_t *nio);
|
||||
bool nd_sio_bind(nd_sio_t *sio, const struct sockaddr *addr, size_t addrlen);
|
||||
ssize_t nd_sio_send(nd_sio_t *sio, const struct sockaddr *addr, size_t addrlen, const void *msg, size_t msglen);
|
||||
ssize_t nd_sio_recv(nd_sio_t *sio, struct sockaddr *addr, size_t addrlen, void *msg, size_t msglen);
|
||||
bool nd_sio_poll();
|
||||
void nd_sio_cleanup();
|
||||
nd_io_t *nd_sio_create(int fd);
|
||||
bool nd_sio_set_nonblock(nd_io_t *io, bool value);
|
||||
|
||||
#endif /* NDPPD_SIO_H */
|
||||
nd_io_t *nd_io_socket(int domain, int type, int protocol);
|
||||
void nd_io_close(nd_io_t *io);
|
||||
bool nd_io_bind(nd_io_t *io, const struct sockaddr *addr, size_t addrlen);
|
||||
ssize_t nd_io_send(nd_io_t *io, const struct sockaddr *addr, size_t addrlen, const void *msg, size_t msglen);
|
||||
ssize_t nd_io_recv(nd_io_t *io, struct sockaddr *addr, size_t addrlen, void *msg, size_t msglen);
|
||||
bool nd_io_poll();
|
||||
void nd_io_cleanup();
|
||||
|
||||
#endif /*NDPPD_IO_H*/
|
10
src/ndppd.c
10
src/ndppd.c
@ -28,14 +28,12 @@
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "addr.h"
|
||||
#include "conf.h"
|
||||
#include "iface.h"
|
||||
#include "io.h"
|
||||
#include "ndppd.h"
|
||||
#include "proxy.h"
|
||||
#include "rtnl.h"
|
||||
#include "rule.h"
|
||||
#include "sio.h"
|
||||
|
||||
#ifndef NDPPD_CONFIG_PATH
|
||||
# define NDPPD_CONFIG_PATH "../ndppd.conf"
|
||||
@ -198,6 +196,9 @@ int main(int argc, char *argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!nd_iface_startup())
|
||||
return -1;
|
||||
|
||||
if (!nd_proxy_startup())
|
||||
return -1;
|
||||
|
||||
@ -211,6 +212,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
bool query_addresses = false;
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (nd_current_time >= nd_rtnl_dump_timeout)
|
||||
@ -222,7 +224,7 @@ int main(int argc, char *argv[])
|
||||
nd_rtnl_query_addresses();
|
||||
}
|
||||
|
||||
if (!nd_sio_poll())
|
||||
if (!nd_io_poll())
|
||||
{
|
||||
/* TODO: Error */
|
||||
break;
|
||||
|
@ -27,7 +27,7 @@
|
||||
#define NDPPD_VERSION "1.0-beta1"
|
||||
|
||||
typedef struct nd_iface nd_iface_t;
|
||||
typedef struct nd_sio nd_sio_t;
|
||||
typedef struct nd_io nd_io_t;
|
||||
typedef struct nd_proxy nd_proxy_t;
|
||||
typedef struct nd_conf nd_conf_t;
|
||||
typedef struct in6_addr nd_addr_t;
|
||||
|
28
src/rtnl.c
28
src/rtnl.c
@ -22,11 +22,11 @@
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "addr.h"
|
||||
#include "io.h"
|
||||
#include "ndppd.h"
|
||||
#include "rtnl.h"
|
||||
#include "sio.h"
|
||||
|
||||
static nd_sio_t *ndL_sio;
|
||||
static nd_io_t *ndL_io;
|
||||
static nd_rtnl_route_t *ndL_routes, *ndL_free_routes;
|
||||
static nd_rtnl_addr_t *ndL_addrs, *ndL_free_addrs;
|
||||
|
||||
@ -189,13 +189,13 @@ static void ndL_handle_delroute(struct rtmsg *msg, int rtl)
|
||||
}
|
||||
}
|
||||
|
||||
static void ndL_sio_handler(__attribute__((unused)) nd_sio_t *unused1, __attribute__((unused)) int unused2)
|
||||
static void ndL_io_handler(__attribute__((unused)) nd_io_t *unused1, __attribute__((unused)) int unused2)
|
||||
{
|
||||
uint8_t buf[4096];
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ssize_t len = nd_sio_recv(ndL_sio, NULL, 0, buf, sizeof(buf));
|
||||
ssize_t len = nd_io_recv(ndL_io, NULL, 0, buf, sizeof(buf));
|
||||
|
||||
if (len < 0)
|
||||
/* Failed. */
|
||||
@ -230,10 +230,10 @@ static void ndL_sio_handler(__attribute__((unused)) nd_sio_t *unused1, __attribu
|
||||
|
||||
bool nd_rtnl_open()
|
||||
{
|
||||
if (ndL_sio != NULL)
|
||||
if (ndL_io != NULL)
|
||||
return true;
|
||||
|
||||
if (!(ndL_sio = nd_sio_open(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)))
|
||||
if (!(ndL_io = nd_io_socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)))
|
||||
{
|
||||
nd_log_error("Failed to open netlink socket: %s", strerror(errno));
|
||||
return false;
|
||||
@ -244,23 +244,23 @@ bool nd_rtnl_open()
|
||||
addr.nl_family = AF_NETLINK;
|
||||
addr.nl_groups = (1 << (RTNLGRP_IPV6_IFADDR - 1)) | (1 << (RTNLGRP_IPV6_ROUTE - 1));
|
||||
|
||||
if (!nd_sio_bind(ndL_sio, (struct sockaddr *)&addr, sizeof(addr)))
|
||||
if (!nd_io_bind(ndL_io, (struct sockaddr *)&addr, sizeof(addr)))
|
||||
{
|
||||
nd_log_error("Failed to bind netlink socket: %s", strerror(errno));
|
||||
nd_sio_close(ndL_sio);
|
||||
ndL_sio = NULL;
|
||||
nd_io_close(ndL_io);
|
||||
ndL_io = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
ndL_sio->handler = ndL_sio_handler;
|
||||
ndL_io->handler = ndL_io_handler;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void nd_rtnl_cleanup()
|
||||
{
|
||||
if (ndL_sio)
|
||||
nd_sio_close(ndL_sio);
|
||||
if (ndL_io)
|
||||
nd_io_close(ndL_io);
|
||||
}
|
||||
|
||||
bool nd_rtnl_query_routes()
|
||||
@ -290,7 +290,7 @@ bool nd_rtnl_query_routes()
|
||||
|
||||
nd_rtnl_dump_timeout = nd_current_time + 5000;
|
||||
|
||||
nd_sio_send(ndL_sio, (struct sockaddr *)&addr, sizeof(addr), &req, sizeof(req));
|
||||
nd_io_send(ndL_io, (struct sockaddr *)&addr, sizeof(addr), &req, sizeof(req));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -320,7 +320,7 @@ bool nd_rtnl_query_addresses()
|
||||
|
||||
nd_rtnl_dump_timeout = nd_current_time + 5000;
|
||||
|
||||
nd_sio_send(ndL_sio, (struct sockaddr *)&addr, sizeof(addr), &req, sizeof(req));
|
||||
nd_io_send(ndL_io, (struct sockaddr *)&addr, sizeof(addr), &req, sizeof(req));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user