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");