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_ */