github.com/datadog/cilium@v1.6.12/bpf/bpf_network.c (about) 1 /* 2 * Copyright (C) 2019 Authors of Cilium 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 #include <node_config.h> 19 #include <netdev_config.h> 20 21 #include <bpf/api.h> 22 23 #include <stdint.h> 24 #include <stdio.h> 25 26 #include <linux/if_packet.h> 27 28 #include "lib/utils.h" 29 #include "lib/common.h" 30 #include "lib/maps.h" 31 #include "lib/ipv6.h" 32 #include "lib/eth.h" 33 #include "lib/dbg.h" 34 #include "lib/trace.h" 35 #include "lib/l3.h" 36 #include "lib/drop.h" 37 38 #ifdef ENABLE_IPV6 39 static inline int handle_ipv6(struct __sk_buff *skb) 40 { 41 #ifdef ENABLE_IPSEC 42 void *data_end, *data; 43 struct ipv6hdr *ip6; 44 bool decrypted; 45 46 decrypted = ((skb->mark & MARK_MAGIC_HOST_MASK) == MARK_MAGIC_DECRYPT); 47 if (!revalidate_data_first(skb, &data, &data_end, &ip6)) 48 return DROP_INVALID; 49 50 if (!decrypted) { 51 /* IPSec is not currently enforce (feature coming soon) 52 * so for now just handle normally 53 */ 54 if (ip6->nexthdr != IPPROTO_ESP) 55 return 0; 56 57 /* Decrypt "key" is determined by SPI */ 58 skb->mark = MARK_MAGIC_DECRYPT; 59 60 /* We are going to pass this up the stack for IPsec decryption 61 * but eth_type_trans may already have labeled this as an 62 * OTHERHOST type packet. To avoid being dropped by IP stack 63 * before IPSec can be processed mark as a HOST packet. 64 */ 65 skb_change_type(skb, PACKET_HOST); 66 return TC_ACT_OK; 67 } else{ 68 skb->mark = 0; 69 return redirect(CILIUM_IFINDEX, 0); 70 } 71 #endif 72 return 0; 73 } 74 #endif /* ENABLE_IPV6 */ 75 76 #ifdef ENABLE_IPV4 77 static inline int handle_ipv4(struct __sk_buff *skb) 78 { 79 #ifdef ENABLE_IPSEC 80 void *data_end, *data; 81 struct iphdr *ip4; 82 bool decrypted; 83 84 decrypted = ((skb->mark & MARK_MAGIC_HOST_MASK) == MARK_MAGIC_DECRYPT); 85 if (!revalidate_data_first(skb, &data, &data_end, &ip4)) 86 return DROP_INVALID; 87 88 if (!decrypted) { 89 /* IPSec is not currently enforce (feature coming soon) 90 * so for now just handle normally 91 */ 92 if (ip4->protocol != IPPROTO_ESP) 93 goto out; 94 /* Decrypt "key" is determined by SPI */ 95 skb->mark = MARK_MAGIC_DECRYPT; 96 skb_change_type(skb, PACKET_HOST); 97 return TC_ACT_OK; 98 } else { 99 skb->mark = 0; 100 return redirect(CILIUM_IFINDEX, 0); 101 } 102 out: 103 #endif 104 return 0; 105 } 106 #endif 107 108 __section("from-network") 109 int from_network(struct __sk_buff *skb) 110 { 111 __u16 proto; 112 int ret = 0; 113 114 bpf_clear_cb(skb); 115 116 #ifdef ENABLE_IPSEC 117 if ((skb->mark & MARK_MAGIC_HOST_MASK) == MARK_MAGIC_DECRYPT) { 118 send_trace_notify(skb, TRACE_FROM_NETWORK, get_identity(skb), 0, 0, 119 skb->ingress_ifindex, 120 TRACE_REASON_ENCRYPTED, TRACE_PAYLOAD_LEN); 121 } else 122 #endif 123 { 124 send_trace_notify(skb, TRACE_FROM_NETWORK, 0, 0, 0, 125 skb->ingress_ifindex, 0, TRACE_PAYLOAD_LEN); 126 } 127 128 if (!validate_ethertype(skb, &proto)) { 129 /* Pass unknown traffic to the stack */ 130 ret = TC_ACT_OK; 131 return ret; 132 } 133 134 switch (proto) { 135 case bpf_htons(ETH_P_IPV6): 136 #ifdef ENABLE_IPV6 137 ret = handle_ipv6(skb); 138 #endif 139 break; 140 141 case bpf_htons(ETH_P_IP): 142 #ifdef ENABLE_IPV4 143 ret = handle_ipv4(skb); 144 #endif 145 break; 146 147 default: 148 /* Pass unknown traffic to the stack */ 149 ret = TC_ACT_OK; 150 } 151 return ret; 152 } 153 154 BPF_LICENSE("GPL");