Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -1707,8 +1707,8 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr

if ((c = tb[IFACE_ATTR_PREFIX_FILTER]))
odhcpd_parse_addr6_prefix(blobmsg_get_string(c),
&iface->pio_filter_addr,
&iface->pio_filter_length);
&iface->prefix_filter_addr,
&iface->prefix_filter_length);

if (overwrite && (c = tb[IFACE_ATTR_NTP])) {
struct blob_attr *cur;
Expand Down
10 changes: 5 additions & 5 deletions src/dhcpv6-ia.c
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ static void __apply_lease(struct dhcpv6_lease *a,
for (ssize_t i = 0; i < addr_len; ++i) {
struct in6_addr prefix;

if (ADDR_MATCH_PIO_FILTER(&addrs[i], a->iface))
if (ADDR_MATCH_PREFIX_FILTER(&addrs[i], a->iface))
continue;

prefix = addrs[i].addr.in6;
Expand Down Expand Up @@ -324,7 +324,7 @@ static void set_border_assignment_size(struct interface *iface, struct dhcpv6_le
for (size_t i = 0; i < iface->addr6_len; ++i) {
struct odhcpd_ipaddr *addr = &iface->addr6[i];

if (ADDR_MATCH_PIO_FILTER(addr, iface))
if (ADDR_MATCH_PREFIX_FILTER(addr, iface))
continue;

if (addr->preferred_lt > (uint32_t)now &&
Expand Down Expand Up @@ -634,7 +634,7 @@ static size_t build_ia(uint8_t *buf, size_t buflen, uint16_t status,
continue;

/* Filter Out Prefixes */
if (ADDR_MATCH_PIO_FILTER(&addrs[i], iface)) {
if (ADDR_MATCH_PREFIX_FILTER(&addrs[i], iface)) {
char addrbuf[INET6_ADDRSTRLEN];
info("Address %s filtered out on %s",
inet_ntop(AF_INET6, &addrs[i].addr.in6, addrbuf, sizeof(addrbuf)),
Expand Down Expand Up @@ -761,7 +761,7 @@ static size_t build_ia(uint8_t *buf, size_t buflen, uint16_t status,
if (!valid_prefix_length(a, addrs[i].prefix_len))
continue;

if (ADDR_MATCH_PIO_FILTER(&addrs[i], iface))
if (ADDR_MATCH_PREFIX_FILTER(&addrs[i], iface))
continue;

if (ia->type == htons(DHCPV6_OPT_IA_PD)) {
Expand Down Expand Up @@ -934,7 +934,7 @@ static bool dhcpv6_ia_on_link(const struct dhcpv6_ia_hdr *ia, struct dhcpv6_leas
if (!valid_addr(&addrs[i], now))
continue;

if (ADDR_MATCH_PIO_FILTER(&addrs[i], iface))
if (ADDR_MATCH_PREFIX_FILTER(&addrs[i], iface))
continue;

if (ia->type == htons(DHCPV6_OPT_IA_PD)) {
Expand Down
11 changes: 10 additions & 1 deletion src/ndp.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,12 +278,18 @@ static void ndp_netevent_cb(unsigned long event, struct netevent_handler_info *i
netlink_dump_neigh_table(false);
_o_fallthrough;
case NETEV_ADDR6_ADD:
if (IN6_MATCH_PREFIX_FILTER(info->addr.in6, iface))
break; /* Address filtered out */

setup_addr_for_relaying(&info->addr.in6, iface, add);
break;
case NETEV_NEIGH6_DEL:
add = false;
_o_fallthrough;
case NETEV_NEIGH6_ADD:
if (IN6_MATCH_PREFIX_FILTER(info->neigh.dst.in6, iface))
break; /* Address filtered out */

if (info->neigh.flags & NTF_PROXY) {
if (add) {
netlink_setup_proxy_neigh(&info->neigh.dst.in6, iface->ifindex, false);
Expand Down Expand Up @@ -380,13 +386,16 @@ static void handle_solicit(void *addr, void *data, size_t len,
return;

if (len < sizeof(*ip6) + sizeof(*req))
return; // Invalid total length
return; /* Invalid total length */

if (IN6_IS_ADDR_LINKLOCAL(&req->nd_ns_target) ||
IN6_IS_ADDR_LOOPBACK(&req->nd_ns_target) ||
IN6_IS_ADDR_MULTICAST(&req->nd_ns_target))
return; /* Invalid target */

if (IN6_MATCH_PREFIX_FILTER(req->nd_ns_target, iface))
return; /* Address filtered out */

inet_ntop(AF_INET6, &req->nd_ns_target, ipbuf, sizeof(ipbuf));
debug("Got a NS for %s on %s", ipbuf, iface->name);

Expand Down
51 changes: 50 additions & 1 deletion src/odhcpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ void odhcpd_enum_addr6(struct interface *iface, struct dhcpv6_lease *lease,
continue;

/* Filter Out Prefixes */
if (ADDR_MATCH_PIO_FILTER(&addrs[i], iface)) {
if (ADDR_MATCH_PREFIX_FILTER(&addrs[i], iface)) {
char addrbuf[INET6_ADDRSTRLEN];
info("Address %s filtered out on %s",
inet_ntop(AF_INET6, &addrs[i].addr.in6, addrbuf, sizeof(addrbuf)),
Expand Down Expand Up @@ -789,3 +789,52 @@ bool odhcpd_hostname_valid(const char *name)

return (label_sz && label_sz <= DNS_MAX_LABEL_LEN ? true : false);
}

void odhcpd_iov_builder_init(struct iov_builder *builder, uint8_t *data, struct iovec* iov_buf, size_t iov_capacity) {
builder->iov_count = 0;
builder->current_iov_base = data;
builder->current_iov_len = 0;
builder->include_iov = false;

if (iov_buf) {
builder->iov_buf = iov_buf;
builder->iov_capacity = iov_capacity;
}
}

int odhcpd_iov_builder_advance(struct iov_builder *builder, size_t chunk_len, bool include_chunk) {
if (include_chunk ^ builder->include_iov) {
if (builder->include_iov) {
int error = odhcpd_iov_builder_append(builder, builder->current_iov_base, builder->current_iov_len);
if (error)
return error;
}

builder->current_iov_base += builder->current_iov_len;
builder->current_iov_len = chunk_len;
builder->include_iov = include_chunk;
} else {
builder->current_iov_len += chunk_len;
}

return 0;
}

int odhcpd_iov_builder_append(struct iov_builder *builder, uint8_t *iov_base, size_t iov_len) {
if (iov_len == 0)
return 0;
if (builder->iov_count >= builder->iov_capacity)
return 1;

builder->iov_buf[builder->iov_count] = (struct iovec) {
.iov_base = iov_base,
.iov_len = iov_len
};
builder->iov_count++;

return 0;
}

int odhcpd_iov_builder_finalize(struct iov_builder *builder) {
return odhcpd_iov_builder_advance(builder, 0, false);
}
28 changes: 22 additions & 6 deletions src/odhcpd.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,12 @@

#define IN6_IS_ADDR_ULA(a) (((a)->s6_addr32[0] & htonl(0xfe000000)) == htonl(0xfc000000))

#define ADDR_MATCH_PIO_FILTER(_addr, iface) (odhcpd_bmemcmp(&(_addr)->addr, \
&(iface)->pio_filter_addr, \
(iface)->pio_filter_length) != 0 || \
(_addr)->prefix_len < (iface)->pio_filter_length)
#define IN6_MATCH_PREFIX_FILTER(_addr, iface) (odhcpd_bmemcmp(&(_addr), \
&(iface)->prefix_filter_addr, \
(iface)->prefix_filter_length) != 0)

#define ADDR_MATCH_PREFIX_FILTER(_addr, iface) (IN6_MATCH_PREFIX_FILTER((_addr)->addr, iface) || \
(_addr)->prefix_len < (iface)->prefix_filter_length)

struct interface;
struct nl_sock;
Expand Down Expand Up @@ -423,8 +425,8 @@ struct interface {
uint32_t pref64_prefix[3];
bool no_dynamic_dhcp;
bool have_link_local;
uint8_t pio_filter_length;
struct in6_addr pio_filter_addr;
uint8_t prefix_filter_length;
struct in6_addr prefix_filter_addr;
int default_router;
int route_preference;
uint32_t ra_maxinterval;
Expand Down Expand Up @@ -666,4 +668,18 @@ void reload_services(struct interface *iface);

void odhcpd_reload(void);

struct iov_builder {
struct iovec *iov_buf;
size_t iov_capacity;
size_t iov_count;
uint8_t *current_iov_base;
size_t current_iov_len;
bool include_iov;
};

void odhcpd_iov_builder_init(struct iov_builder *builder, uint8_t *data, struct iovec* iov_buf, size_t iov_capacity);
int odhcpd_iov_builder_advance(struct iov_builder *builder, size_t chunk_len, bool include_chunk);
int odhcpd_iov_builder_append(struct iov_builder *builder, uint8_t *iov_base, size_t iov_len);
int odhcpd_iov_builder_finalize(struct iov_builder *builder);

#endif /* _ODHCPD_H_ */
Loading
Loading