Skip to content

Instantly share code, notes, and snippets.

@anfernee
Created July 9, 2020 18:42
Show Gist options
  • Save anfernee/423a78fca4e8bc27dfcf981bfd88730b to your computer and use it in GitHub Desktop.
Save anfernee/423a78fca4e8bc27dfcf981bfd88730b to your computer and use it in GitHub Desktop.
diff --git a/bpf/lib/icmp6.h b/bpf/lib/icmp6.h
index 3446b727e..4fa0aa57e 100644
--- a/bpf/lib/icmp6.h
+++ b/bpf/lib/icmp6.h
@@ -9,6 +9,8 @@
#include "common.h"
#include "eth.h"
#include "drop.h"
+#include "eps.h"
+#include "dbg.h"
#define ICMP6_TYPE_OFFSET (sizeof(struct ipv6hdr) + offsetof(struct icmp6hdr, icmp6_type))
#define ICMP6_CSUM_OFFSET (sizeof(struct ipv6hdr) + offsetof(struct icmp6hdr, icmp6_cksum))
@@ -153,8 +155,17 @@ static __always_inline int icmp6_send_echo_reply(struct __ctx_buff *ctx,
return DROP_MISSED_TAIL_CALL;
}
+/*
+ * send_icmp6_ndisc_adv
+ * @ctx: socket buffer
+ * @nh_off: offset to the IPv6 header
+ * @mac: device mac address
+ * @to_router: ndisc is sent to router, otherwise ndisc is sent to an endpoint.
+ *
+ * Send an ICMPv6 nadv reply in return to an ICMPv6 ndisc.
+ */
static __always_inline int send_icmp6_ndisc_adv(struct __ctx_buff *ctx,
- int nh_off, union macaddr *mac)
+ int nh_off, union macaddr *mac, bool to_router)
{
struct icmp6hdr icmp6hdr __align_stack_8 = {}, icmp6hdr_old __align_stack_8;
__u8 opts[8], opts_old[8];
@@ -170,9 +181,16 @@ static __always_inline int send_icmp6_ndisc_adv(struct __ctx_buff *ctx,
icmp6hdr.icmp6_code = 0;
icmp6hdr.icmp6_cksum = icmp6hdr_old.icmp6_cksum;
icmp6hdr.icmp6_dataun.un_data32[0] = 0;
- icmp6hdr.icmp6_router = 1;
- icmp6hdr.icmp6_solicited = 1;
- icmp6hdr.icmp6_override = 0;
+
+ if (to_router) {
+ icmp6hdr.icmp6_router = 1;
+ icmp6hdr.icmp6_solicited = 1;
+ icmp6hdr.icmp6_override = 0;
+ } else {
+ icmp6hdr.icmp6_router = 0;
+ icmp6hdr.icmp6_solicited = 0;
+ icmp6hdr.icmp6_override = 1;
+ }
if (ctx_store_bytes(ctx, nh_off + sizeof(struct ipv6hdr), &icmp6hdr, sizeof(icmp6hdr), 0) < 0)
return DROP_WRITE_ERROR;
@@ -345,6 +363,7 @@ static __always_inline int icmp6_send_time_exceeded(struct __ctx_buff *ctx,
static __always_inline int __icmp6_handle_ns(struct __ctx_buff *ctx, int nh_off)
{
union v6addr target, router;
+ struct endpoint_info *ep;
if (ctx_load_bytes(ctx, nh_off + ICMP6_ND_TARGET_OFFSET, target.addr,
sizeof(((struct ipv6hdr *)NULL)->saddr)) < 0)
@@ -352,11 +371,17 @@ static __always_inline int __icmp6_handle_ns(struct __ctx_buff *ctx, int nh_off)
cilium_dbg(ctx, DBG_ICMP6_NS, target.p3, target.p4);
+ ep = __lookup_ip6_endpoint(&target);
+
BPF_V6(router, ROUTER_IP);
if (ipv6_addrcmp(&target, &router) == 0) {
union macaddr router_mac = NODE_MAC;
- return send_icmp6_ndisc_adv(ctx, nh_off, &router_mac);
+ return send_icmp6_ndisc_adv(ctx, nh_off, &router_mac, true);
+ } else if (ep != NULL) {
+ union macaddr node_mac = NODE_MAC;
+
+ return send_icmp6_ndisc_adv(ctx, nh_off, &node_mac, false);
} else {
/* Unknown target address, drop */
return ACTION_UNKNOWN_ICMP6_NS;
@@ -426,6 +451,11 @@ icmp6_host_handle(struct __ctx_buff *ctx __maybe_unused)
{
__u8 type __maybe_unused;
+ type = icmp6_load_type(ctx, ETH_HLEN);
+ if (type == ICMP6_NS_MSG_TYPE) {
+ return __icmp6_handle_ns(ctx, ETH_HLEN);
+ }
+
#ifdef ENABLE_HOST_FIREWALL
/* When the host firewall is enabled, we drop and allow ICMPv6 messages
* according to RFC4890, except for echo request and reply messages which
@@ -473,7 +503,7 @@ icmp6_host_handle(struct __ctx_buff *ctx __maybe_unused)
* | ICMPv6-unallocated | CTX_ACT_DROP | |
* | ICMPv6-unassigned | CTX_ACT_DROP | |
*/
- type = icmp6_load_type(ctx, ETH_HLEN);
+
if (type == ICMP6_ECHO_REQUEST_MSG_TYPE || type == ICMP6_ECHO_REPLY_MSG_TYPE)
return CTX_ACT_OK;
diff --git a/bpf/lib/overloadable_skb.h b/bpf/lib/overloadable_skb.h
index 26e0cca07..67e1192d7 100644
--- a/bpf/lib/overloadable_skb.h
+++ b/bpf/lib/overloadable_skb.h
@@ -73,9 +73,17 @@ redirect_self(const struct __sk_buff *ctx)
*/
#ifdef ENABLE_HOST_REDIRECT
return redirect(ctx->ifindex, 0);
+#else
+#ifdef NATIVE_IFINDEX
+ if (ctx->ifindex == NATIVE_IFINDEX) {
+ return redirect(ctx->ifindex, 0);
+ } else {
+ return redirect(ctx->ifindex, BPF_F_INGRESS);
+ }
#else
return redirect(ctx->ifindex, BPF_F_INGRESS);
-#endif
+#endif /* NATIVE_IFINDEX */
+#endif /* ENABLE_HOST_REDIRECT */
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment