brintos

brintos / linux-shallow public Read only

0
0
Text · 3.2 KiB · f0759ef Raw
169 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2020 Facebook */3 4#include "bpf_tracing_net.h"5#include <bpf/bpf_helpers.h>6#include <bpf/bpf_endian.h>7 8#ifndef ENOENT9#define ENOENT 210#endif11 12struct sockaddr_in6 srv_sa6 = {};13__u16 listen_tp_sport = 0;14__u16 req_sk_sport = 0;15__u32 recv_cookie = 0;16__u32 gen_cookie = 0;17__u32 linum = 0;18 19#define LOG() ({ if (!linum) linum = __LINE__; })20 21static void test_syncookie_helper(struct ipv6hdr *ip6h, struct tcphdr *th,22				  struct tcp_sock *tp,23				  struct __sk_buff *skb)24{25	if (th->syn) {26		__s64 mss_cookie;27		void *data_end;28 29		data_end = (void *)(long)(skb->data_end);30 31		if (th->doff * 4 != 40) {32			LOG();33			return;34		}35 36		if ((void *)th + 40 > data_end) {37			LOG();38			return;39		}40 41		mss_cookie = bpf_tcp_gen_syncookie(tp, ip6h, sizeof(*ip6h),42						   th, 40);43		if (mss_cookie < 0) {44			if (mss_cookie != -ENOENT)45				LOG();46		} else {47			gen_cookie = (__u32)mss_cookie;48		}49	} else if (gen_cookie) {50		/* It was in cookie mode */51		int ret = bpf_tcp_check_syncookie(tp, ip6h, sizeof(*ip6h),52						  th, sizeof(*th));53 54		if (ret < 0) {55			if (ret != -ENOENT)56				LOG();57		} else {58			recv_cookie = bpf_ntohl(th->ack_seq) - 1;59		}60	}61}62 63static int handle_ip6_tcp(struct ipv6hdr *ip6h, struct __sk_buff *skb)64{65	struct bpf_sock_tuple *tuple;66	struct bpf_sock *bpf_skc;67	unsigned int tuple_len;68	struct tcphdr *th;69	void *data_end;70 71	data_end = (void *)(long)(skb->data_end);72 73	th = (struct tcphdr *)(ip6h + 1);74	if (th + 1 > data_end)75		return TC_ACT_OK;76 77	/* Is it the testing traffic? */78	if (th->dest != srv_sa6.sin6_port)79		return TC_ACT_OK;80 81	tuple_len = sizeof(tuple->ipv6);82	tuple = (struct bpf_sock_tuple *)&ip6h->saddr;83	if ((void *)tuple + tuple_len > data_end) {84		LOG();85		return TC_ACT_OK;86	}87 88	bpf_skc = bpf_skc_lookup_tcp(skb, tuple, tuple_len,89				     BPF_F_CURRENT_NETNS, 0);90	if (!bpf_skc) {91		LOG();92		return TC_ACT_OK;93	}94 95	if (bpf_skc->state == BPF_TCP_NEW_SYN_RECV) {96		struct request_sock *req_sk;97 98		req_sk = (struct request_sock *)bpf_skc_to_tcp_request_sock(bpf_skc);99		if (!req_sk) {100			LOG();101			goto release;102		}103 104		if (bpf_sk_assign(skb, req_sk, 0)) {105			LOG();106			goto release;107		}108 109		req_sk_sport = req_sk->__req_common.skc_num;110 111		bpf_sk_release(req_sk);112		return TC_ACT_OK;113	} else if (bpf_skc->state == BPF_TCP_LISTEN) {114		struct tcp_sock *tp;115 116		tp = bpf_skc_to_tcp_sock(bpf_skc);117		if (!tp) {118			LOG();119			goto release;120		}121 122		if (bpf_sk_assign(skb, tp, 0)) {123			LOG();124			goto release;125		}126 127		listen_tp_sport = tp->inet_conn.icsk_inet.sk.__sk_common.skc_num;128 129		test_syncookie_helper(ip6h, th, tp, skb);130		bpf_sk_release(tp);131		return TC_ACT_OK;132	}133 134	if (bpf_sk_assign(skb, bpf_skc, 0))135		LOG();136 137release:138	bpf_sk_release(bpf_skc);139	return TC_ACT_OK;140}141 142SEC("tc")143int cls_ingress(struct __sk_buff *skb)144{145	struct ipv6hdr *ip6h;146	struct ethhdr *eth;147	void *data_end;148 149	data_end = (void *)(long)(skb->data_end);150 151	eth = (struct ethhdr *)(long)(skb->data);152	if (eth + 1 > data_end)153		return TC_ACT_OK;154 155	if (eth->h_proto != bpf_htons(ETH_P_IPV6))156		return TC_ACT_OK;157 158	ip6h = (struct ipv6hdr *)(eth + 1);159	if (ip6h + 1 > data_end)160		return TC_ACT_OK;161 162	if (ip6h->nexthdr == IPPROTO_TCP)163		return handle_ip6_tcp(ip6h, skb);164 165	return TC_ACT_OK;166}167 168char _license[] SEC("license") = "GPL";169