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;