github.com/datadog/cilium@v1.6.12/bpf/sockops/bpf_sockops.c (about) 1 /* 2 * Copyright (C) 2018-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 #define SOCKMAP 1 19 20 #include <node_config.h> 21 #include <bpf/api.h> 22 23 #include <stdint.h> 24 #include <stdio.h> 25 26 #include <linux/bpf.h> 27 #include <linux/if_ether.h> 28 29 #include "../lib/utils.h" 30 #include "../lib/common.h" 31 #include "../lib/maps.h" 32 #include "../lib/lb.h" 33 #include "../lib/eps.h" 34 #include "../lib/events.h" 35 #include "../lib/policy.h" 36 37 #include "bpf_sockops.h" 38 39 static inline void bpf_sock_ops_ipv4(struct bpf_sock_ops *skops) 40 { 41 struct lb4_key_v2 lb4_key = {}; 42 __u32 dip4, dport, dstID = 0; 43 struct endpoint_info *exists; 44 struct lb4_service_v2 *svc; 45 struct sock_key key = {}; 46 int verdict; 47 48 sk_extract4_key(skops, &key); 49 50 /* If endpoint a service use L4/L3 stack for now. These can be 51 * pulled in as needed. 52 */ 53 sk_lb4_key_v2(&lb4_key, &key); 54 svc = __lb4_lookup_service_v2(&lb4_key); 55 if (svc) 56 return; 57 58 /* Policy lookup required to learn proxy port */ 59 if (1) { 60 struct remote_endpoint_info *info; 61 62 info = lookup_ip4_remote_endpoint(key.dip4); 63 if (info != NULL && info->sec_label) 64 dstID = info->sec_label; 65 else 66 dstID = WORLD_ID; 67 } 68 69 verdict = policy_sk_egress(dstID, key.sip4, key.dport); 70 if (redirect_to_proxy(verdict)) { 71 __be32 host_ip = IPV4_GATEWAY; 72 73 key.dip4 = key.sip4; 74 key.dport = key.sport; 75 key.sip4 = host_ip; 76 key.sport = verdict; 77 78 sock_hash_update(skops, &SOCK_OPS_MAP, &key, BPF_NOEXIST); 79 return; 80 } 81 82 /* Lookup IPv4 address, this will return a match if: 83 * - The destination IP address belongs to the local endpoint manage 84 * by Cilium. 85 * - The destination IP address is an IP address associated with the 86 * host itself. 87 * Then because these are local IPs that have passed LB/Policy/NAT 88 * blocks redirect directly to socket. 89 */ 90 exists = __lookup_ip4_endpoint(key.dip4); 91 if (!exists) 92 return; 93 94 dip4 = key.dip4; 95 dport = key.dport; 96 key.dip4 = key.sip4; 97 key.dport = key.sport; 98 key.sip4 = dip4; 99 key.sport = dport; 100 101 sock_hash_update(skops, &SOCK_OPS_MAP, &key, BPF_NOEXIST); 102 } 103 104 static inline void bpf_sock_ops_ipv6(struct bpf_sock_ops *skops) 105 { 106 if (skops->remote_ip4) 107 bpf_sock_ops_ipv4(skops); 108 } 109 110 __section("sockops") 111 int bpf_sockmap(struct bpf_sock_ops *skops) 112 { 113 __u32 family, op; 114 115 family = skops->family; 116 op = skops->op; 117 118 switch (op) { 119 case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: 120 case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: 121 if (family == AF_INET6) 122 bpf_sock_ops_ipv6(skops); 123 else if (family == AF_INET) 124 bpf_sock_ops_ipv4(skops); 125 break; 126 default: 127 break; 128 } 129 130 return 0; 131 } 132 133 BPF_LICENSE("GPL"); 134 int _version __section("version") = 1;