brintos

brintos / linux-shallow public Read only

0
0
Text · 8.7 KiB · f48f85f Raw
379 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2/* Copyright (c) 2017-2018 Covalent IO, Inc. http://covalent.io */3#include <stddef.h>4#include <string.h>5#include <linux/bpf.h>6#include <linux/if_ether.h>7#include <linux/if_packet.h>8#include <linux/ip.h>9#include <linux/ipv6.h>10#include <linux/in.h>11#include <linux/udp.h>12#include <linux/tcp.h>13#include <linux/pkt_cls.h>14#include <sys/socket.h>15#include <bpf/bpf_helpers.h>16#include <bpf/bpf_endian.h>17#include "bpf_misc.h"18 19/* Sockmap sample program connects a client and a backend together20 * using cgroups.21 *22 *    client:X <---> frontend:80 client:X <---> backend:8023 *24 * For simplicity we hard code values here and bind 1:1. The hard25 * coded values are part of the setup in sockmap.sh script that26 * is associated with this BPF program.27 *28 * The bpf_printk is verbose and prints information as connections29 * are established and verdicts are decided.30 */31 32struct {33	__uint(type, TEST_MAP_TYPE);34	__uint(max_entries, 20);35	__uint(key_size, sizeof(int));36	__uint(value_size, sizeof(int));37} sock_map SEC(".maps");38 39struct {40	__uint(type, TEST_MAP_TYPE);41	__uint(max_entries, 20);42	__uint(key_size, sizeof(int));43	__uint(value_size, sizeof(int));44} sock_map_txmsg SEC(".maps");45 46struct {47	__uint(type, TEST_MAP_TYPE);48	__uint(max_entries, 20);49	__uint(key_size, sizeof(int));50	__uint(value_size, sizeof(int));51} sock_map_redir SEC(".maps");52 53struct {54	__uint(type, BPF_MAP_TYPE_ARRAY);55	__uint(max_entries, 1);56	__type(key, int);57	__type(value, int);58} sock_apply_bytes SEC(".maps");59 60struct {61	__uint(type, BPF_MAP_TYPE_ARRAY);62	__uint(max_entries, 1);63	__type(key, int);64	__type(value, int);65} sock_cork_bytes SEC(".maps");66 67struct {68	__uint(type, BPF_MAP_TYPE_ARRAY);69	__uint(max_entries, 6);70	__type(key, int);71	__type(value, int);72} sock_bytes SEC(".maps");73 74struct {75	__uint(type, BPF_MAP_TYPE_ARRAY);76	__uint(max_entries, 1);77	__type(key, int);78	__type(value, int);79} sock_redir_flags SEC(".maps");80 81struct {82	__uint(type, BPF_MAP_TYPE_ARRAY);83	__uint(max_entries, 3);84	__type(key, int);85	__type(value, int);86} sock_skb_opts SEC(".maps");87 88struct {89	__uint(type, TEST_MAP_TYPE);90	__uint(max_entries, 20);91	__uint(key_size, sizeof(int));92	__uint(value_size, sizeof(int));93} tls_sock_map SEC(".maps");94 95SEC("sk_skb/stream_parser")96int bpf_prog1(struct __sk_buff *skb)97{98	int *f, two = 2;99 100	f = bpf_map_lookup_elem(&sock_skb_opts, &two);101	if (f && *f) {102		return *f;103	}104	return skb->len;105}106 107SEC("sk_skb/stream_verdict")108int bpf_prog2(struct __sk_buff *skb)109{110	__u32 lport = skb->local_port;111	__u32 rport = skb->remote_port;112	int len, *f, ret, zero = 0;113	__u64 flags = 0;114 115	__sink(rport);116	if (lport == 10000)117		ret = 10;118	else119		ret = 1;120 121	len = (__u32)skb->data_end - (__u32)skb->data;122	__sink(len);123 124	f = bpf_map_lookup_elem(&sock_skb_opts, &zero);125	if (f && *f) {126		ret = 3;127		flags = *f;128	}129 130#ifdef SOCKMAP131	return bpf_sk_redirect_map(skb, &sock_map, ret, flags);132#else133	return bpf_sk_redirect_hash(skb, &sock_map, &ret, flags);134#endif135 136}137 138static inline void bpf_write_pass(struct __sk_buff *skb, int offset)139{140	int err = bpf_skb_pull_data(skb, 6 + offset);141	void *data_end;142	char *c;143 144	if (err)145		return;146 147	c = (char *)(long)skb->data;148	data_end = (void *)(long)skb->data_end;149 150	if (c + 5 + offset < data_end)151		memcpy(c + offset, "PASS", 4);152}153 154SEC("sk_skb/stream_verdict")155int bpf_prog3(struct __sk_buff *skb)156{157	int err, *f, ret = SK_PASS;158	const int one = 1;159 160	f = bpf_map_lookup_elem(&sock_skb_opts, &one);161	if (f && *f) {162		__u64 flags = 0;163 164		ret = 0;165		flags = *f;166 167		err = bpf_skb_adjust_room(skb, -13, 0, 0);168		if (err)169			return SK_DROP;170		err = bpf_skb_adjust_room(skb, 4, 0, 0);171		if (err)172			return SK_DROP;173		bpf_write_pass(skb, 0);174#ifdef SOCKMAP175		return bpf_sk_redirect_map(skb, &tls_sock_map, ret, flags);176#else177		return bpf_sk_redirect_hash(skb, &tls_sock_map, &ret, flags);178#endif179	}180	err = bpf_skb_adjust_room(skb, 4, 0, 0);181	if (err)182		return SK_DROP;183	bpf_write_pass(skb, 13);184	return ret;185}186 187SEC("sockops")188int bpf_sockmap(struct bpf_sock_ops *skops)189{190	__u32 lport, rport;191	int op, ret;192 193	op = (int) skops->op;194 195	switch (op) {196	case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:197		lport = skops->local_port;198		rport = skops->remote_port;199 200		if (lport == 10000) {201			ret = 1;202#ifdef SOCKMAP203			bpf_sock_map_update(skops, &sock_map, &ret,204						  BPF_NOEXIST);205#else206			bpf_sock_hash_update(skops, &sock_map, &ret,207						   BPF_NOEXIST);208#endif209		}210		break;211	case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:212		lport = skops->local_port;213		rport = skops->remote_port;214 215		if (bpf_ntohl(rport) == 10001) {216			ret = 10;217#ifdef SOCKMAP218			bpf_sock_map_update(skops, &sock_map, &ret,219						  BPF_NOEXIST);220#else221			bpf_sock_hash_update(skops, &sock_map, &ret,222						   BPF_NOEXIST);223#endif224		}225		break;226	default:227		break;228	}229 230	return 0;231}232 233SEC("sk_msg")234int bpf_prog4(struct sk_msg_md *msg)235{236	int *bytes, zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;237	int *start, *end, *start_push, *end_push, *start_pop, *pop, err = 0;238 239	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);240	if (bytes)241		bpf_msg_apply_bytes(msg, *bytes);242	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);243	if (bytes)244		bpf_msg_cork_bytes(msg, *bytes);245	start = bpf_map_lookup_elem(&sock_bytes, &zero);246	end = bpf_map_lookup_elem(&sock_bytes, &one);247	if (start && end)248		bpf_msg_pull_data(msg, *start, *end, 0);249	start_push = bpf_map_lookup_elem(&sock_bytes, &two);250	end_push = bpf_map_lookup_elem(&sock_bytes, &three);251	if (start_push && end_push) {252		err = bpf_msg_push_data(msg, *start_push, *end_push, 0);253		if (err)254			return SK_DROP;255	}256	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);257	pop = bpf_map_lookup_elem(&sock_bytes, &five);258	if (start_pop && pop)259		bpf_msg_pop_data(msg, *start_pop, *pop, 0);260	return SK_PASS;261}262 263SEC("sk_msg")264int bpf_prog6(struct sk_msg_md *msg)265{266	int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5, key = 0;267	int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop, *f;268	int err = 0;269	__u64 flags = 0;270 271	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);272	if (bytes)273		bpf_msg_apply_bytes(msg, *bytes);274	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);275	if (bytes)276		bpf_msg_cork_bytes(msg, *bytes);277 278	start = bpf_map_lookup_elem(&sock_bytes, &zero);279	end = bpf_map_lookup_elem(&sock_bytes, &one);280	if (start && end)281		bpf_msg_pull_data(msg, *start, *end, 0);282 283	start_push = bpf_map_lookup_elem(&sock_bytes, &two);284	end_push = bpf_map_lookup_elem(&sock_bytes, &three);285	if (start_push && end_push) {286		err = bpf_msg_push_data(msg, *start_push, *end_push, 0);287		if (err)288			return SK_DROP;289	}290 291	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);292	pop = bpf_map_lookup_elem(&sock_bytes, &five);293	if (start_pop && pop)294		bpf_msg_pop_data(msg, *start_pop, *pop, 0);295 296	f = bpf_map_lookup_elem(&sock_redir_flags, &zero);297	if (f && *f) {298		key = 2;299		flags = *f;300	}301#ifdef SOCKMAP302	return bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);303#else304	return bpf_msg_redirect_hash(msg, &sock_map_redir, &key, flags);305#endif306}307 308SEC("sk_msg")309int bpf_prog8(struct sk_msg_md *msg)310{311	void *data_end = (void *)(long) msg->data_end;312	void *data = (void *)(long) msg->data;313	int ret = 0, *bytes, zero = 0;314 315	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);316	if (bytes) {317		ret = bpf_msg_apply_bytes(msg, *bytes);318		if (ret)319			return SK_DROP;320	} else {321		return SK_DROP;322	}323 324	__sink(data_end);325	__sink(data);326 327	return SK_PASS;328}329 330SEC("sk_msg")331int bpf_prog9(struct sk_msg_md *msg)332{333	void *data_end = (void *)(long) msg->data_end;334	void *data = (void *)(long) msg->data;335	int ret = 0, *bytes, zero = 0;336 337	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);338	if (bytes) {339		if (((__u64)data_end - (__u64)data) >= *bytes)340			return SK_PASS;341		ret = bpf_msg_cork_bytes(msg, *bytes);342		if (ret)343			return SK_DROP;344	}345	return SK_PASS;346}347 348SEC("sk_msg")349int bpf_prog10(struct sk_msg_md *msg)350{351	int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop;352	int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5, err = 0;353 354	bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);355	if (bytes)356		bpf_msg_apply_bytes(msg, *bytes);357	bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);358	if (bytes)359		bpf_msg_cork_bytes(msg, *bytes);360	start = bpf_map_lookup_elem(&sock_bytes, &zero);361	end = bpf_map_lookup_elem(&sock_bytes, &one);362	if (start && end)363		bpf_msg_pull_data(msg, *start, *end, 0);364	start_push = bpf_map_lookup_elem(&sock_bytes, &two);365	end_push = bpf_map_lookup_elem(&sock_bytes, &three);366	if (start_push && end_push) {367		err = bpf_msg_push_data(msg, *start_push, *end_push, 0);368		if (err)369			return SK_PASS;370	}371	start_pop = bpf_map_lookup_elem(&sock_bytes, &four);372	pop = bpf_map_lookup_elem(&sock_bytes, &five);373	if (start_pop && pop)374		bpf_msg_pop_data(msg, *start_pop, *pop, 0);375	return SK_DROP;376}377 378char _license[] SEC("license") = "GPL";379