Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0
  2/* 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 ENOENT
  9#define ENOENT 2
 10#endif
 11
 12struct sockaddr_in6 srv_sa6 = {};
 13struct sockaddr_in srv_sa4 = {};
 14__u16 listen_tp_sport = 0;
 15__u16 req_sk_sport = 0;
 16__u32 recv_cookie = 0;
 17__u32 gen_cookie = 0;
 18__u32 mss = 0;
 19__u32 linum = 0;
 20
 21#define LOG() ({ if (!linum) linum = __LINE__; })
 22
 23static void test_syncookie_helper(void *iphdr, int iphdr_size,
 24				  struct tcphdr *th, struct tcp_sock *tp,
 25				  struct __sk_buff *skb)
 26{
 27	if (th->syn) {
 28		__s64 mss_cookie;
 29		void *data_end;
 30
 31		data_end = (void *)(long)(skb->data_end);
 32
 33		if (th->doff * 4 != 40) {
 34			LOG();
 35			return;
 36		}
 37
 38		if ((void *)th + 40 > data_end) {
 39			LOG();
 40			return;
 41		}
 42
 43		mss_cookie = bpf_tcp_gen_syncookie(tp, iphdr, iphdr_size,
 44						   th, 40);
 45		if (mss_cookie < 0) {
 46			if (mss_cookie != -ENOENT)
 47				LOG();
 48		} else {
 49			gen_cookie = (__u32)mss_cookie;
 50			mss = mss_cookie >> 32;
 51		}
 52	} else if (gen_cookie) {
 53		/* It was in cookie mode */
 54		int ret = bpf_tcp_check_syncookie(tp, iphdr, iphdr_size,
 55						  th, sizeof(*th));
 56
 57		if (ret < 0) {
 58			if (ret != -ENOENT)
 59				LOG();
 60		} else {
 61			recv_cookie = bpf_ntohl(th->ack_seq) - 1;
 62		}
 63	}
 64}
 65
 66static int handle_ip_tcp(struct ethhdr *eth, struct __sk_buff *skb)
 67{
 68	struct bpf_sock_tuple *tuple = NULL;
 69	unsigned int tuple_len = 0;
 70	struct bpf_sock *bpf_skc;
 71	void *data_end, *iphdr;
 72	struct ipv6hdr *ip6h;
 73	struct iphdr *ip4h;
 74	struct tcphdr *th;
 75	int iphdr_size;
 76
 77	data_end = (void *)(long)(skb->data_end);
 78
 79	switch (eth->h_proto) {
 80	case bpf_htons(ETH_P_IP):
 81		ip4h = (struct iphdr *)(eth + 1);
 82		if (ip4h + 1 > data_end)
 83			return TC_ACT_OK;
 84		if (ip4h->protocol != IPPROTO_TCP)
 85			return TC_ACT_OK;
 86		th = (struct tcphdr *)(ip4h + 1);
 87		if (th + 1 > data_end)
 88			return TC_ACT_OK;
 89		/* Is it the testing traffic? */
 90		if (th->dest != srv_sa4.sin_port)
 91			return TC_ACT_OK;
 92		tuple_len = sizeof(tuple->ipv4);
 93		tuple = (struct bpf_sock_tuple *)&ip4h->saddr;
 94		iphdr = ip4h;
 95		iphdr_size = sizeof(*ip4h);
 96		break;
 97	case bpf_htons(ETH_P_IPV6):
 98		ip6h = (struct ipv6hdr *)(eth + 1);
 99		if (ip6h + 1 > data_end)
100			return TC_ACT_OK;
101		if (ip6h->nexthdr != IPPROTO_TCP)
102			return TC_ACT_OK;
103		th = (struct tcphdr *)(ip6h + 1);
104		if (th + 1 > data_end)
105			return TC_ACT_OK;
106		/* Is it the testing traffic? */
107		if (th->dest != srv_sa6.sin6_port)
108			return TC_ACT_OK;
109		tuple_len = sizeof(tuple->ipv6);
110		tuple = (struct bpf_sock_tuple *)&ip6h->saddr;
111		iphdr = ip6h;
112		iphdr_size = sizeof(*ip6h);
113		break;
114	default:
115		return TC_ACT_OK;
116	}
117
 
 
118	if ((void *)tuple + tuple_len > data_end) {
119		LOG();
120		return TC_ACT_OK;
121	}
122
123	bpf_skc = bpf_skc_lookup_tcp(skb, tuple, tuple_len,
124				     BPF_F_CURRENT_NETNS, 0);
125	if (!bpf_skc) {
126		LOG();
127		return TC_ACT_OK;
128	}
129
130	if (bpf_skc->state == BPF_TCP_NEW_SYN_RECV) {
131		struct request_sock *req_sk;
132
133		req_sk = (struct request_sock *)bpf_skc_to_tcp_request_sock(bpf_skc);
134		if (!req_sk) {
135			LOG();
136			goto release;
137		}
138
139		if (bpf_sk_assign(skb, req_sk, 0)) {
140			LOG();
141			goto release;
142		}
143
144		req_sk_sport = req_sk->__req_common.skc_num;
145
146		bpf_sk_release(req_sk);
147		return TC_ACT_OK;
148	} else if (bpf_skc->state == BPF_TCP_LISTEN) {
149		struct tcp_sock *tp;
150
151		tp = bpf_skc_to_tcp_sock(bpf_skc);
152		if (!tp) {
153			LOG();
154			goto release;
155		}
156
157		if (bpf_sk_assign(skb, tp, 0)) {
158			LOG();
159			goto release;
160		}
161
162		listen_tp_sport = tp->inet_conn.icsk_inet.sk.__sk_common.skc_num;
163
164		test_syncookie_helper(iphdr, iphdr_size, th, tp, skb);
165		bpf_sk_release(tp);
166		return TC_ACT_OK;
167	}
168
169	if (bpf_sk_assign(skb, bpf_skc, 0))
170		LOG();
171
172release:
173	bpf_sk_release(bpf_skc);
174	return TC_ACT_OK;
175}
176
177SEC("tc")
178int cls_ingress(struct __sk_buff *skb)
179{
 
180	struct ethhdr *eth;
181	void *data_end;
182
183	data_end = (void *)(long)(skb->data_end);
184
185	eth = (struct ethhdr *)(long)(skb->data);
186	if (eth + 1 > data_end)
187		return TC_ACT_OK;
188
189	if (eth->h_proto != bpf_htons(ETH_P_IP) &&
190	    eth->h_proto != bpf_htons(ETH_P_IPV6))
 
 
 
191		return TC_ACT_OK;
192
193	return handle_ip_tcp(eth, skb);
 
 
 
194}
195
196char _license[] SEC("license") = "GPL";
v6.9.4
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2020 Facebook */
  3
  4#include <string.h>
  5#include <errno.h>
  6#include <netinet/in.h>
  7#include <linux/stddef.h>
  8#include <linux/bpf.h>
  9#include <linux/ipv6.h>
 10#include <linux/tcp.h>
 11#include <linux/if_ether.h>
 12#include <linux/pkt_cls.h>
 13
 14#include <bpf/bpf_helpers.h>
 15#include <bpf/bpf_endian.h>
 16#include "bpf_tcp_helpers.h"
 
 
 
 17
 18struct sockaddr_in6 srv_sa6 = {};
 
 19__u16 listen_tp_sport = 0;
 20__u16 req_sk_sport = 0;
 21__u32 recv_cookie = 0;
 22__u32 gen_cookie = 0;
 
 23__u32 linum = 0;
 24
 25#define LOG() ({ if (!linum) linum = __LINE__; })
 26
 27static void test_syncookie_helper(struct ipv6hdr *ip6h, struct tcphdr *th,
 28				  struct tcp_sock *tp,
 29				  struct __sk_buff *skb)
 30{
 31	if (th->syn) {
 32		__s64 mss_cookie;
 33		void *data_end;
 34
 35		data_end = (void *)(long)(skb->data_end);
 36
 37		if (th->doff * 4 != 40) {
 38			LOG();
 39			return;
 40		}
 41
 42		if ((void *)th + 40 > data_end) {
 43			LOG();
 44			return;
 45		}
 46
 47		mss_cookie = bpf_tcp_gen_syncookie(tp, ip6h, sizeof(*ip6h),
 48						   th, 40);
 49		if (mss_cookie < 0) {
 50			if (mss_cookie != -ENOENT)
 51				LOG();
 52		} else {
 53			gen_cookie = (__u32)mss_cookie;
 
 54		}
 55	} else if (gen_cookie) {
 56		/* It was in cookie mode */
 57		int ret = bpf_tcp_check_syncookie(tp, ip6h, sizeof(*ip6h),
 58						  th, sizeof(*th));
 59
 60		if (ret < 0) {
 61			if (ret != -ENOENT)
 62				LOG();
 63		} else {
 64			recv_cookie = bpf_ntohl(th->ack_seq) - 1;
 65		}
 66	}
 67}
 68
 69static int handle_ip6_tcp(struct ipv6hdr *ip6h, struct __sk_buff *skb)
 70{
 71	struct bpf_sock_tuple *tuple;
 
 72	struct bpf_sock *bpf_skc;
 73	unsigned int tuple_len;
 
 
 74	struct tcphdr *th;
 75	void *data_end;
 76
 77	data_end = (void *)(long)(skb->data_end);
 78
 79	th = (struct tcphdr *)(ip6h + 1);
 80	if (th + 1 > data_end)
 81		return TC_ACT_OK;
 82
 83	/* Is it the testing traffic? */
 84	if (th->dest != srv_sa6.sin6_port)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 85		return TC_ACT_OK;
 
 86
 87	tuple_len = sizeof(tuple->ipv6);
 88	tuple = (struct bpf_sock_tuple *)&ip6h->saddr;
 89	if ((void *)tuple + tuple_len > data_end) {
 90		LOG();
 91		return TC_ACT_OK;
 92	}
 93
 94	bpf_skc = bpf_skc_lookup_tcp(skb, tuple, tuple_len,
 95				     BPF_F_CURRENT_NETNS, 0);
 96	if (!bpf_skc) {
 97		LOG();
 98		return TC_ACT_OK;
 99	}
100
101	if (bpf_skc->state == BPF_TCP_NEW_SYN_RECV) {
102		struct request_sock *req_sk;
103
104		req_sk = (struct request_sock *)bpf_skc_to_tcp_request_sock(bpf_skc);
105		if (!req_sk) {
106			LOG();
107			goto release;
108		}
109
110		if (bpf_sk_assign(skb, req_sk, 0)) {
111			LOG();
112			goto release;
113		}
114
115		req_sk_sport = req_sk->__req_common.skc_num;
116
117		bpf_sk_release(req_sk);
118		return TC_ACT_OK;
119	} else if (bpf_skc->state == BPF_TCP_LISTEN) {
120		struct tcp_sock *tp;
121
122		tp = bpf_skc_to_tcp_sock(bpf_skc);
123		if (!tp) {
124			LOG();
125			goto release;
126		}
127
128		if (bpf_sk_assign(skb, tp, 0)) {
129			LOG();
130			goto release;
131		}
132
133		listen_tp_sport = tp->inet_conn.icsk_inet.sk.__sk_common.skc_num;
134
135		test_syncookie_helper(ip6h, th, tp, skb);
136		bpf_sk_release(tp);
137		return TC_ACT_OK;
138	}
139
140	if (bpf_sk_assign(skb, bpf_skc, 0))
141		LOG();
142
143release:
144	bpf_sk_release(bpf_skc);
145	return TC_ACT_OK;
146}
147
148SEC("tc")
149int cls_ingress(struct __sk_buff *skb)
150{
151	struct ipv6hdr *ip6h;
152	struct ethhdr *eth;
153	void *data_end;
154
155	data_end = (void *)(long)(skb->data_end);
156
157	eth = (struct ethhdr *)(long)(skb->data);
158	if (eth + 1 > data_end)
159		return TC_ACT_OK;
160
161	if (eth->h_proto != bpf_htons(ETH_P_IPV6))
162		return TC_ACT_OK;
163
164	ip6h = (struct ipv6hdr *)(eth + 1);
165	if (ip6h + 1 > data_end)
166		return TC_ACT_OK;
167
168	if (ip6h->nexthdr == IPPROTO_TCP)
169		return handle_ip6_tcp(ip6h, skb);
170
171	return TC_ACT_OK;
172}
173
174char _license[] SEC("license") = "GPL";