github.com/datadog/cilium@v1.6.12/bpf/lib/lxc.h (about) 1 /* 2 * Copyright (C) 2016-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 #ifndef __LIB_LXC_H_ 19 #define __LIB_LXC_H_ 20 21 #include "common.h" 22 #include "utils.h" 23 #include "ipv6.h" 24 #include "ipv4.h" 25 #include "eth.h" 26 #include "dbg.h" 27 #include "trace.h" 28 #include "csum.h" 29 #include "l4.h" 30 31 #define TEMPLATE_LXC_ID 0xffff 32 33 #ifndef DISABLE_SIP_VERIFICATION 34 static inline int is_valid_lxc_src_ip(struct ipv6hdr *ip6) 35 { 36 #ifdef ENABLE_IPV6 37 union v6addr valid = {}; 38 39 BPF_V6(valid, LXC_IP); 40 41 return !ipv6_addrcmp((union v6addr *) &ip6->saddr, &valid); 42 #else 43 return 0; 44 #endif 45 } 46 47 static inline int is_valid_lxc_src_ipv4(struct iphdr *ip4) 48 { 49 #ifdef ENABLE_IPV4 50 return ip4->saddr == LXC_IPV4; 51 #else 52 /* Can't send IPv4 if no IPv4 address is configured */ 53 return 0; 54 #endif 55 } 56 #else 57 static inline int is_valid_lxc_src_ip(struct ipv6hdr *ip6) 58 { 59 return 1; 60 } 61 62 static inline int is_valid_lxc_src_ipv4(struct iphdr *ip4) 63 { 64 return 1; 65 } 66 #endif 67 68 /** 69 * skb_redirect_to_proxy configures the skb with the proxy mark and proxy port 70 * number to ensure that the stack redirects the packet into the proxy. 71 * 72 * It is called from both ingress and egress side of endpoint devices. 73 * 74 * In regular veth mode: 75 * * To apply egress policy, the egressing endpoint configures the mark, 76 * which returns TC_ACT_OK to pass the packet to the stack in the context 77 * of the source device (stack ingress). 78 * * To apply ingress policy, the egressing endpoint or netdev program tail 79 * calls into the policy program which configures the mark here, which 80 * returns TC_ACT_OK to pass the packet to the stack in the context of the 81 * source device (netdev or egress endpoint device, stack ingress). 82 * 83 * In chaining mode with bridged endpoint devices: 84 * * To apply egress policy, the egressing endpoint configures the mark, 85 * which is propagated to skb->cb[] in the caller. The redirect() call here 86 * redirects the packet to the ingress TC filter configured on the bridge 87 * master device. 88 * * To apply ingress policy, the stack transmits the packet into the bridge 89 * master device which tail calls into the policy program for the ingress 90 * endpoint, which configures mark and cb[] as described for the egress path. 91 * The redirect() call here redirects the packet to the ingress TC filter 92 * configured on the bridge master device. 93 * * In both cases for bridged endpoint devices, the bridge master device has 94 * a BPF program configured upon ingress to transfer the cb[] to the mark 95 * before passing the traffic up to the stack towards the proxy. 96 */ 97 static inline int __inline__ 98 skb_redirect_to_proxy(struct __sk_buff *skb, __be16 proxy_port) 99 { 100 skb->mark = MARK_MAGIC_TO_PROXY | proxy_port << 16; 101 102 #ifdef HOST_REDIRECT_TO_INGRESS 103 cilium_dbg_capture(skb, DBG_CAPTURE_PROXY_PRE, proxy_port); 104 /* In this case, the DBG_CAPTURE_PROXY_POST will be sent from the 105 * programm attached to HOST_IFINDEX. */ 106 return redirect(HOST_IFINDEX, BPF_F_INGRESS); 107 #else 108 cilium_dbg_capture(skb, DBG_CAPTURE_PROXY_POST, proxy_port); 109 skb_change_type(skb, PACKET_HOST); // Required for ingress packets from overlay 110 return TC_ACT_OK; 111 #endif 112 } 113 114 /** 115 * skb_redirect_to_proxy_hairpin redirects to the proxy by hairpining the 116 * packet out the incoming interface 117 */ 118 static inline int __inline__ 119 skb_redirect_to_proxy_hairpin(struct __sk_buff *skb, __be16 proxy_port) 120 { 121 union macaddr host_mac = HOST_IFINDEX_MAC; 122 union macaddr router_mac = NODE_MAC; 123 void *data_end = (void *) (long) skb->data_end; 124 void *data = (void *) (long) skb->data; 125 struct iphdr *ip4; 126 int ret; 127 128 skb->cb[0] = MARK_MAGIC_TO_PROXY | (proxy_port << 16); 129 bpf_barrier(); /* verifier workaround */ 130 131 if (!revalidate_data(skb, &data, &data_end, &ip4)) 132 return DROP_INVALID; 133 134 ret = ipv4_l3(skb, ETH_HLEN, (__u8 *) &router_mac, (__u8 *) &host_mac, ip4); 135 if (IS_ERR(ret)) 136 return ret; 137 138 cilium_dbg_capture(skb, DBG_CAPTURE_PROXY_POST, proxy_port); 139 140 return redirect(HOST_IFINDEX, 0); 141 } 142 143 /** 144 * tc_index_skip_ingress_proxy - returns true if packet originates from ingress proxy 145 */ 146 static inline bool __inline__ tc_index_skip_ingress_proxy(struct __sk_buff *skb) 147 { 148 volatile __u32 tc_index = skb->tc_index; 149 #ifdef DEBUG 150 if (tc_index & TC_INDEX_F_SKIP_INGRESS_PROXY) 151 cilium_dbg(skb, DBG_SKIP_PROXY, tc_index, 0); 152 #endif 153 154 return tc_index & TC_INDEX_F_SKIP_INGRESS_PROXY; 155 } 156 157 /** 158 * tc_index_skip_egress_proxy - returns true if packet originates from egress proxy 159 */ 160 static inline bool __inline__ tc_index_skip_egress_proxy(struct __sk_buff *skb) 161 { 162 volatile __u32 tc_index = skb->tc_index; 163 #ifdef DEBUG 164 if (tc_index & TC_INDEX_F_SKIP_EGRESS_PROXY) 165 cilium_dbg(skb, DBG_SKIP_PROXY, tc_index, 0); 166 #endif 167 168 return tc_index & TC_INDEX_F_SKIP_EGRESS_PROXY; 169 } 170 #endif /* __LIB_LXC_H_ */