Skip to content

Commit c1eb6a9

Browse files
committed
Extended prefix_filter to work in relay mode for RA and NDP
1 parent 13cec01 commit c1eb6a9

6 files changed

Lines changed: 225 additions & 100 deletions

File tree

src/config.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,8 +1707,8 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr
17071707

17081708
if ((c = tb[IFACE_ATTR_PREFIX_FILTER]))
17091709
odhcpd_parse_addr6_prefix(blobmsg_get_string(c),
1710-
&iface->pio_filter_addr,
1711-
&iface->pio_filter_length);
1710+
&iface->prefix_filter_addr,
1711+
&iface->prefix_filter_length);
17121712

17131713
if (overwrite && (c = tb[IFACE_ATTR_NTP])) {
17141714
struct blob_attr *cur;

src/dhcpv6-ia.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ static void __apply_lease(struct dhcpv6_lease *a,
295295
for (ssize_t i = 0; i < addr_len; ++i) {
296296
struct in6_addr prefix;
297297

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

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

327-
if (ADDR_MATCH_PIO_FILTER(addr, iface))
327+
if (ADDR_MATCH_PREFIX_FILTER(addr, iface))
328328
continue;
329329

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

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

764-
if (ADDR_MATCH_PIO_FILTER(&addrs[i], iface))
764+
if (ADDR_MATCH_PREFIX_FILTER(&addrs[i], iface))
765765
continue;
766766

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

937-
if (ADDR_MATCH_PIO_FILTER(&addrs[i], iface))
937+
if (ADDR_MATCH_PREFIX_FILTER(&addrs[i], iface))
938938
continue;
939939

940940
if (ia->type == htons(DHCPV6_OPT_IA_PD)) {

src/ndp.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,12 +278,18 @@ static void ndp_netevent_cb(unsigned long event, struct netevent_handler_info *i
278278
netlink_dump_neigh_table(false);
279279
_o_fallthrough;
280280
case NETEV_ADDR6_ADD:
281+
if (IN6_MATCH_PREFIX_FILTER(info->addr.in6, iface))
282+
break; /* Address filtered out */
283+
281284
setup_addr_for_relaying(&info->addr.in6, iface, add);
282285
break;
283286
case NETEV_NEIGH6_DEL:
284287
add = false;
285288
_o_fallthrough;
286289
case NETEV_NEIGH6_ADD:
290+
if (IN6_MATCH_PREFIX_FILTER(info->neigh.dst.in6, iface))
291+
break; /* Address filtered out */
292+
287293
if (info->neigh.flags & NTF_PROXY) {
288294
if (add) {
289295
netlink_setup_proxy_neigh(&info->neigh.dst.in6, iface->ifindex, false);
@@ -380,13 +386,16 @@ static void handle_solicit(void *addr, void *data, size_t len,
380386
return;
381387

382388
if (len < sizeof(*ip6) + sizeof(*req))
383-
return; // Invalid total length
389+
return; /* Invalid total length */
384390

385391
if (IN6_IS_ADDR_LINKLOCAL(&req->nd_ns_target) ||
386392
IN6_IS_ADDR_LOOPBACK(&req->nd_ns_target) ||
387393
IN6_IS_ADDR_MULTICAST(&req->nd_ns_target))
388394
return; /* Invalid target */
389395

396+
if (IN6_MATCH_PREFIX_FILTER(req->nd_ns_target, iface))
397+
return; /* Address filtered out */
398+
390399
inet_ntop(AF_INET6, &req->nd_ns_target, ipbuf, sizeof(ipbuf));
391400
debug("Got a NS for %s on %s", ipbuf, iface->name);
392401

src/odhcpd.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,7 @@ void odhcpd_enum_addr6(struct interface *iface, struct dhcpv6_lease *lease,
680680
continue;
681681

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

790790
return (label_sz && label_sz <= DNS_MAX_LABEL_LEN ? true : false);
791791
}
792+
793+
void odhcpd_iov_builder_init(struct iov_builder *builder, uint8_t *data, struct iovec* iov_buf, size_t iov_capacity) {
794+
builder->iov_count = 0;
795+
builder->current_iov_base = data;
796+
builder->current_iov_len = 0;
797+
builder->include_iov = false;
798+
799+
if (iov_buf) {
800+
builder->iov_buf = iov_buf;
801+
builder->iov_capacity = iov_capacity;
802+
}
803+
}
804+
805+
int odhcpd_iov_builder_advance(struct iov_builder *builder, size_t chunk_len, bool include_chunk) {
806+
if (include_chunk ^ builder->include_iov) {
807+
if (builder->include_iov) {
808+
int error = odhcpd_iov_builder_append(builder, builder->current_iov_base, builder->current_iov_len);
809+
if (error)
810+
return error;
811+
}
812+
813+
builder->current_iov_base += builder->current_iov_len;
814+
builder->current_iov_len = chunk_len;
815+
builder->include_iov = include_chunk;
816+
} else {
817+
builder->current_iov_len += chunk_len;
818+
}
819+
820+
return 0;
821+
}
822+
823+
int odhcpd_iov_builder_append(struct iov_builder *builder, uint8_t *iov_base, size_t iov_len) {
824+
if (iov_len == 0)
825+
return 0;
826+
if (builder->iov_count >= builder->iov_capacity)
827+
return 1;
828+
829+
builder->iov_buf[builder->iov_count] = (struct iovec) {
830+
.iov_base = iov_base,
831+
.iov_len = iov_len
832+
};
833+
builder->iov_count++;
834+
835+
return 0;
836+
}
837+
838+
int odhcpd_iov_builder_finalize(struct iov_builder *builder) {
839+
return odhcpd_iov_builder_advance(builder, 0, false);
840+
}

src/odhcpd.h

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,12 @@
8282

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

85-
#define ADDR_MATCH_PIO_FILTER(_addr, iface) (odhcpd_bmemcmp(&(_addr)->addr, \
86-
&(iface)->pio_filter_addr, \
87-
(iface)->pio_filter_length) != 0 || \
88-
(_addr)->prefix_len < (iface)->pio_filter_length)
85+
#define IN6_MATCH_PREFIX_FILTER(_addr, iface) (odhcpd_bmemcmp(&(_addr), \
86+
&(iface)->prefix_filter_addr, \
87+
(iface)->prefix_filter_length) != 0)
88+
89+
#define ADDR_MATCH_PREFIX_FILTER(_addr, iface) (IN6_MATCH_PREFIX_FILTER((_addr)->addr, iface) || \
90+
(_addr)->prefix_len < (iface)->prefix_filter_length)
8991

9092
struct interface;
9193
struct nl_sock;
@@ -423,8 +425,8 @@ struct interface {
423425
uint32_t pref64_prefix[3];
424426
bool no_dynamic_dhcp;
425427
bool have_link_local;
426-
uint8_t pio_filter_length;
427-
struct in6_addr pio_filter_addr;
428+
uint8_t prefix_filter_length;
429+
struct in6_addr prefix_filter_addr;
428430
int default_router;
429431
int route_preference;
430432
uint32_t ra_maxinterval;
@@ -666,4 +668,18 @@ void reload_services(struct interface *iface);
666668

667669
void odhcpd_reload(void);
668670

671+
struct iov_builder {
672+
struct iovec *iov_buf;
673+
size_t iov_capacity;
674+
size_t iov_count;
675+
uint8_t *current_iov_base;
676+
size_t current_iov_len;
677+
bool include_iov;
678+
};
679+
680+
void odhcpd_iov_builder_init(struct iov_builder *builder, uint8_t *data, struct iovec* iov_buf, size_t iov_capacity);
681+
int odhcpd_iov_builder_advance(struct iov_builder *builder, size_t chunk_len, bool include_chunk);
682+
int odhcpd_iov_builder_append(struct iov_builder *builder, uint8_t *iov_base, size_t iov_len);
683+
int odhcpd_iov_builder_finalize(struct iov_builder *builder);
684+
669685
#endif /* _ODHCPD_H_ */

0 commit comments

Comments
 (0)