diff --git a/bpf/bpf_network.c b/bpf/bpf_network.c index 98d41222d822..41fca641ea63 100644 --- a/bpf/bpf_network.c +++ b/bpf/bpf_network.c @@ -8,93 +8,18 @@ #include #include "lib/common.h" -#include "lib/maps.h" -#include "lib/ipv6.h" #include "lib/eth.h" #include "lib/dbg.h" #include "lib/trace.h" -#include "lib/l3.h" -#include "lib/drop.h" - -#ifdef ENABLE_IPV6 -static __always_inline int handle_ipv6(struct __ctx_buff *ctx) -{ -#ifdef ENABLE_IPSEC - void *data_end, *data; - struct ipv6hdr *ip6; - bool decrypted; - - decrypted = ((ctx->mark & MARK_MAGIC_HOST_MASK) == MARK_MAGIC_DECRYPT); - if (!revalidate_data_pull(ctx, &data, &data_end, &ip6)) - return DROP_INVALID; - - if (!decrypted) { - /* IPSec is not currently enforce (feature coming soon) - * so for now just handle normally - */ - if (ip6->nexthdr != IPPROTO_ESP) - return 0; - - /* Decrypt "key" is determined by SPI */ - ctx->mark = MARK_MAGIC_DECRYPT; - - /* We are going to pass this up the stack for IPsec decryption - * but eth_type_trans may already have labeled this as an - * OTHERHOST type packet. To avoid being dropped by IP stack - * before IPSec can be processed mark as a HOST packet. - */ - ctx_change_type(ctx, PACKET_HOST); - return CTX_ACT_OK; - } - - ctx->mark = 0; - return redirect(CILIUM_IFINDEX, 0); -#endif - return 0; -} -#endif /* ENABLE_IPV6 */ - -#ifdef ENABLE_IPV4 -static __always_inline int handle_ipv4(struct __ctx_buff *ctx) -{ -#ifdef ENABLE_IPSEC - void *data_end, *data; - struct iphdr *ip4; - bool decrypted; - - decrypted = ((ctx->mark & MARK_MAGIC_HOST_MASK) == MARK_MAGIC_DECRYPT); - if (!revalidate_data_pull(ctx, &data, &data_end, &ip4)) - return DROP_INVALID; - - if (!decrypted) { - /* IPSec is not currently enforce (feature coming soon) - * so for now just handle normally - */ - if (ip4->protocol != IPPROTO_ESP) - goto out; - /* Decrypt "key" is determined by SPI */ - ctx->mark = MARK_MAGIC_DECRYPT; - ctx_change_type(ctx, PACKET_HOST); - return CTX_ACT_OK; - } - - ctx->mark = 0; - return redirect(CILIUM_IFINDEX, 0); -out: -#endif - return 0; -} -#endif +#include "lib/encrypt.h" __section("from-network") int from_network(struct __ctx_buff *ctx) { +#ifdef ENABLE_IPSEC __u16 proto; - int ret = 0; + int ret; - bpf_clear_meta(ctx); - -#ifdef ENABLE_IPSEC if ((ctx->mark & MARK_MAGIC_HOST_MASK) == MARK_MAGIC_DECRYPT) { send_trace_notify(ctx, TRACE_FROM_NETWORK, get_identity(ctx), 0, 0, ctx->ingress_ifindex, @@ -106,30 +31,21 @@ int from_network(struct __ctx_buff *ctx) ctx->ingress_ifindex, 0, TRACE_PAYLOAD_LEN); } - if (!validate_ethertype(ctx, &proto)) { - /* Pass unknown traffic to the stack */ - ret = CTX_ACT_OK; - return ret; - } + bpf_clear_meta(ctx); - switch (proto) { - case bpf_htons(ETH_P_IPV6): -#ifdef ENABLE_IPV6 - ret = handle_ipv6(ctx); -#endif - break; +#ifdef ENABLE_IPSEC + /* Pass unknown protocols to the stack */ + if (!validate_ethertype(ctx, &proto)) + return CTX_ACT_OK; - case bpf_htons(ETH_P_IP): -#ifdef ENABLE_IPV4 - ret = handle_ipv4(ctx); + ret = do_decrypt(ctx, proto); + if (!ret) + return CTX_ACT_OK; + ctx->mark = 0; + return redirect(CILIUM_IFINDEX, 0); #endif - break; - - default: - /* Pass unknown traffic to the stack */ - ret = CTX_ACT_OK; - } - return ret; + /* Pass unknown traffic to the stack */ + return CTX_ACT_OK; } BPF_LICENSE("GPL"); diff --git a/bpf/lib/encrypt.h b/bpf/lib/encrypt.h new file mode 100644 index 000000000000..df74b663c1b1 --- /dev/null +++ b/bpf/lib/encrypt.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2020 Authors of Cilium */ + +#ifndef __LIB_ENCRYPT_H_ +#define __LIB_ENCRYPT_H_ + +#include +#include + +#include "lib/common.h" +#include "lib/ipv6.h" +#include "lib/l3.h" +#include "lib/eth.h" + +#ifdef ENABLE_IPSEC +static __always_inline int +do_decrypt(struct __ctx_buff *ctx, __u16 proto) +{ + bool decrypted; + + decrypted = ((ctx->mark & MARK_MAGIC_HOST_MASK) == MARK_MAGIC_DECRYPT); + if (!decrypted) { + void *data, *data_end; + __u8 protocol = 0; +#ifdef ENABLE_IPV6 + struct ipv6hdr *ip6; +#endif +#ifdef ENABLE_IPV4 + struct iphdr *ip4; +#endif + + switch (proto) { +#ifdef ENABLE_IPV6 + case bpf_htons(ETH_P_IPV6): + if (!revalidate_data_pull(ctx, &data, &data_end, &ip6)) + break; + protocol = ip6->nexthdr; + break; +#endif +#ifdef ENABLE_IPV4 + case bpf_htons(ETH_P_IP): + if (!revalidate_data(ctx, &data, &data_end, &ip4)) + break; + + protocol = ip4->protocol; + break; +#endif + } + + if (protocol == IPPROTO_ESP) { + /* Decrypt "key" is determined by SPI */ + ctx->mark = MARK_MAGIC_DECRYPT; + /* We are going to pass this up the stack for IPsec decryption + * but eth_type_trans may already have labeled this as an + * OTHERHOST type packet. To avoid being dropped by IP stack + * before IPSec can be processed mark as a HOST packet. + */ + ctx_change_type(ctx, PACKET_HOST); + return 0; + } + } + return -ENOENT; +} +#else +static __always_inline int +do_decrypt(struct __ctx_buff __maybe_unused *ctx, __u16 __maybe_unused proto) +{ + return -ENOENT; +} +#endif /* ENABLE_IPSEC */ +#endif /* __LIB_ENCRYPT_H_ */ +