1*539c7e67SKui-Feng Lee // SPDX-License-Identifier: GPL-2.0
2*539c7e67SKui-Feng Lee /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
3*539c7e67SKui-Feng Lee #include <linux/bpf.h>
4*539c7e67SKui-Feng Lee #include <bpf/bpf_endian.h>
5*539c7e67SKui-Feng Lee #include <bpf/bpf_helpers.h>
6*539c7e67SKui-Feng Lee 
7*539c7e67SKui-Feng Lee #include <linux/if_ether.h>
8*539c7e67SKui-Feng Lee #include <linux/in.h>
9*539c7e67SKui-Feng Lee #include <linux/in6.h>
10*539c7e67SKui-Feng Lee #include <linux/ipv6.h>
11*539c7e67SKui-Feng Lee #include <linux/tcp.h>
12*539c7e67SKui-Feng Lee 
13*539c7e67SKui-Feng Lee #include <sys/types.h>
14*539c7e67SKui-Feng Lee #include <sys/socket.h>
15*539c7e67SKui-Feng Lee 
16*539c7e67SKui-Feng Lee #include "cgroup_tcp_skb.h"
17*539c7e67SKui-Feng Lee 
18*539c7e67SKui-Feng Lee char _license[] SEC("license") = "GPL";
19*539c7e67SKui-Feng Lee 
20*539c7e67SKui-Feng Lee __u16 g_sock_port = 0;
21*539c7e67SKui-Feng Lee __u32 g_sock_state = 0;
22*539c7e67SKui-Feng Lee int g_unexpected = 0;
23*539c7e67SKui-Feng Lee __u32 g_packet_count = 0;
24*539c7e67SKui-Feng Lee 
needed_tcp_pkt(struct __sk_buff * skb,struct tcphdr * tcph)25*539c7e67SKui-Feng Lee int needed_tcp_pkt(struct __sk_buff *skb, struct tcphdr *tcph)
26*539c7e67SKui-Feng Lee {
27*539c7e67SKui-Feng Lee 	struct ipv6hdr ip6h;
28*539c7e67SKui-Feng Lee 
29*539c7e67SKui-Feng Lee 	if (skb->protocol != bpf_htons(ETH_P_IPV6))
30*539c7e67SKui-Feng Lee 		return 0;
31*539c7e67SKui-Feng Lee 	if (bpf_skb_load_bytes(skb, 0, &ip6h, sizeof(ip6h)))
32*539c7e67SKui-Feng Lee 		return 0;
33*539c7e67SKui-Feng Lee 
34*539c7e67SKui-Feng Lee 	if (ip6h.nexthdr != IPPROTO_TCP)
35*539c7e67SKui-Feng Lee 		return 0;
36*539c7e67SKui-Feng Lee 
37*539c7e67SKui-Feng Lee 	if (bpf_skb_load_bytes(skb, sizeof(ip6h), tcph, sizeof(*tcph)))
38*539c7e67SKui-Feng Lee 		return 0;
39*539c7e67SKui-Feng Lee 
40*539c7e67SKui-Feng Lee 	if (tcph->source != bpf_htons(g_sock_port) &&
41*539c7e67SKui-Feng Lee 	    tcph->dest != bpf_htons(g_sock_port))
42*539c7e67SKui-Feng Lee 		return 0;
43*539c7e67SKui-Feng Lee 
44*539c7e67SKui-Feng Lee 	return 1;
45*539c7e67SKui-Feng Lee }
46*539c7e67SKui-Feng Lee 
47*539c7e67SKui-Feng Lee /* Run accept() on a socket in the cgroup to receive a new connection. */
egress_accept(struct tcphdr * tcph)48*539c7e67SKui-Feng Lee static int egress_accept(struct tcphdr *tcph)
49*539c7e67SKui-Feng Lee {
50*539c7e67SKui-Feng Lee 	if (g_sock_state ==  SYN_RECV_SENDING_SYN_ACK) {
51*539c7e67SKui-Feng Lee 		if (tcph->fin || !tcph->syn || !tcph->ack)
52*539c7e67SKui-Feng Lee 			g_unexpected++;
53*539c7e67SKui-Feng Lee 		else
54*539c7e67SKui-Feng Lee 			g_sock_state = SYN_RECV;
55*539c7e67SKui-Feng Lee 		return 1;
56*539c7e67SKui-Feng Lee 	}
57*539c7e67SKui-Feng Lee 
58*539c7e67SKui-Feng Lee 	return 0;
59*539c7e67SKui-Feng Lee }
60*539c7e67SKui-Feng Lee 
ingress_accept(struct tcphdr * tcph)61*539c7e67SKui-Feng Lee static int ingress_accept(struct tcphdr *tcph)
62*539c7e67SKui-Feng Lee {
63*539c7e67SKui-Feng Lee 	switch (g_sock_state) {
64*539c7e67SKui-Feng Lee 	case INIT:
65*539c7e67SKui-Feng Lee 		if (!tcph->syn || tcph->fin || tcph->ack)
66*539c7e67SKui-Feng Lee 			g_unexpected++;
67*539c7e67SKui-Feng Lee 		else
68*539c7e67SKui-Feng Lee 			g_sock_state = SYN_RECV_SENDING_SYN_ACK;
69*539c7e67SKui-Feng Lee 		break;
70*539c7e67SKui-Feng Lee 	case SYN_RECV:
71*539c7e67SKui-Feng Lee 		if (tcph->fin || tcph->syn || !tcph->ack)
72*539c7e67SKui-Feng Lee 			g_unexpected++;
73*539c7e67SKui-Feng Lee 		else
74*539c7e67SKui-Feng Lee 			g_sock_state = ESTABLISHED;
75*539c7e67SKui-Feng Lee 		break;
76*539c7e67SKui-Feng Lee 	default:
77*539c7e67SKui-Feng Lee 		return 0;
78*539c7e67SKui-Feng Lee 	}
79*539c7e67SKui-Feng Lee 
80*539c7e67SKui-Feng Lee 	return 1;
81*539c7e67SKui-Feng Lee }
82*539c7e67SKui-Feng Lee 
83*539c7e67SKui-Feng Lee /* Run connect() on a socket in the cgroup to start a new connection. */
egress_connect(struct tcphdr * tcph)84*539c7e67SKui-Feng Lee static int egress_connect(struct tcphdr *tcph)
85*539c7e67SKui-Feng Lee {
86*539c7e67SKui-Feng Lee 	if (g_sock_state == INIT) {
87*539c7e67SKui-Feng Lee 		if (!tcph->syn || tcph->fin || tcph->ack)
88*539c7e67SKui-Feng Lee 			g_unexpected++;
89*539c7e67SKui-Feng Lee 		else
90*539c7e67SKui-Feng Lee 			g_sock_state = SYN_SENT;
91*539c7e67SKui-Feng Lee 		return 1;
92*539c7e67SKui-Feng Lee 	}
93*539c7e67SKui-Feng Lee 
94*539c7e67SKui-Feng Lee 	return 0;
95*539c7e67SKui-Feng Lee }
96*539c7e67SKui-Feng Lee 
ingress_connect(struct tcphdr * tcph)97*539c7e67SKui-Feng Lee static int ingress_connect(struct tcphdr *tcph)
98*539c7e67SKui-Feng Lee {
99*539c7e67SKui-Feng Lee 	if (g_sock_state == SYN_SENT) {
100*539c7e67SKui-Feng Lee 		if (tcph->fin || !tcph->syn || !tcph->ack)
101*539c7e67SKui-Feng Lee 			g_unexpected++;
102*539c7e67SKui-Feng Lee 		else
103*539c7e67SKui-Feng Lee 			g_sock_state = ESTABLISHED;
104*539c7e67SKui-Feng Lee 		return 1;
105*539c7e67SKui-Feng Lee 	}
106*539c7e67SKui-Feng Lee 
107*539c7e67SKui-Feng Lee 	return 0;
108*539c7e67SKui-Feng Lee }
109*539c7e67SKui-Feng Lee 
110*539c7e67SKui-Feng Lee /* The connection is closed by the peer outside the cgroup. */
egress_close_remote(struct tcphdr * tcph)111*539c7e67SKui-Feng Lee static int egress_close_remote(struct tcphdr *tcph)
112*539c7e67SKui-Feng Lee {
113*539c7e67SKui-Feng Lee 	switch (g_sock_state) {
114*539c7e67SKui-Feng Lee 	case ESTABLISHED:
115*539c7e67SKui-Feng Lee 		break;
116*539c7e67SKui-Feng Lee 	case CLOSE_WAIT_SENDING_ACK:
117*539c7e67SKui-Feng Lee 		if (tcph->fin || tcph->syn || !tcph->ack)
118*539c7e67SKui-Feng Lee 			g_unexpected++;
119*539c7e67SKui-Feng Lee 		else
120*539c7e67SKui-Feng Lee 			g_sock_state = CLOSE_WAIT;
121*539c7e67SKui-Feng Lee 		break;
122*539c7e67SKui-Feng Lee 	case CLOSE_WAIT:
123*539c7e67SKui-Feng Lee 		if (!tcph->fin)
124*539c7e67SKui-Feng Lee 			g_unexpected++;
125*539c7e67SKui-Feng Lee 		else
126*539c7e67SKui-Feng Lee 			g_sock_state = LAST_ACK;
127*539c7e67SKui-Feng Lee 		break;
128*539c7e67SKui-Feng Lee 	default:
129*539c7e67SKui-Feng Lee 		return 0;
130*539c7e67SKui-Feng Lee 	}
131*539c7e67SKui-Feng Lee 
132*539c7e67SKui-Feng Lee 	return 1;
133*539c7e67SKui-Feng Lee }
134*539c7e67SKui-Feng Lee 
ingress_close_remote(struct tcphdr * tcph)135*539c7e67SKui-Feng Lee static int ingress_close_remote(struct tcphdr *tcph)
136*539c7e67SKui-Feng Lee {
137*539c7e67SKui-Feng Lee 	switch (g_sock_state) {
138*539c7e67SKui-Feng Lee 	case ESTABLISHED:
139*539c7e67SKui-Feng Lee 		if (tcph->fin)
140*539c7e67SKui-Feng Lee 			g_sock_state = CLOSE_WAIT_SENDING_ACK;
141*539c7e67SKui-Feng Lee 		break;
142*539c7e67SKui-Feng Lee 	case LAST_ACK:
143*539c7e67SKui-Feng Lee 		if (tcph->fin || tcph->syn || !tcph->ack)
144*539c7e67SKui-Feng Lee 			g_unexpected++;
145*539c7e67SKui-Feng Lee 		else
146*539c7e67SKui-Feng Lee 			g_sock_state = CLOSED;
147*539c7e67SKui-Feng Lee 		break;
148*539c7e67SKui-Feng Lee 	default:
149*539c7e67SKui-Feng Lee 		return 0;
150*539c7e67SKui-Feng Lee 	}
151*539c7e67SKui-Feng Lee 
152*539c7e67SKui-Feng Lee 	return 1;
153*539c7e67SKui-Feng Lee }
154*539c7e67SKui-Feng Lee 
155*539c7e67SKui-Feng Lee /* The connection is closed by the endpoint inside the cgroup. */
egress_close_local(struct tcphdr * tcph)156*539c7e67SKui-Feng Lee static int egress_close_local(struct tcphdr *tcph)
157*539c7e67SKui-Feng Lee {
158*539c7e67SKui-Feng Lee 	switch (g_sock_state) {
159*539c7e67SKui-Feng Lee 	case ESTABLISHED:
160*539c7e67SKui-Feng Lee 		if (tcph->fin)
161*539c7e67SKui-Feng Lee 			g_sock_state = FIN_WAIT1;
162*539c7e67SKui-Feng Lee 		break;
163*539c7e67SKui-Feng Lee 	case TIME_WAIT_SENDING_ACK:
164*539c7e67SKui-Feng Lee 		if (tcph->fin || tcph->syn || !tcph->ack)
165*539c7e67SKui-Feng Lee 			g_unexpected++;
166*539c7e67SKui-Feng Lee 		else
167*539c7e67SKui-Feng Lee 			g_sock_state = TIME_WAIT;
168*539c7e67SKui-Feng Lee 		break;
169*539c7e67SKui-Feng Lee 	default:
170*539c7e67SKui-Feng Lee 		return 0;
171*539c7e67SKui-Feng Lee 	}
172*539c7e67SKui-Feng Lee 
173*539c7e67SKui-Feng Lee 	return 1;
174*539c7e67SKui-Feng Lee }
175*539c7e67SKui-Feng Lee 
ingress_close_local(struct tcphdr * tcph)176*539c7e67SKui-Feng Lee static int ingress_close_local(struct tcphdr *tcph)
177*539c7e67SKui-Feng Lee {
178*539c7e67SKui-Feng Lee 	switch (g_sock_state) {
179*539c7e67SKui-Feng Lee 	case ESTABLISHED:
180*539c7e67SKui-Feng Lee 		break;
181*539c7e67SKui-Feng Lee 	case FIN_WAIT1:
182*539c7e67SKui-Feng Lee 		if (tcph->fin || tcph->syn || !tcph->ack)
183*539c7e67SKui-Feng Lee 			g_unexpected++;
184*539c7e67SKui-Feng Lee 		else
185*539c7e67SKui-Feng Lee 			g_sock_state = FIN_WAIT2;
186*539c7e67SKui-Feng Lee 		break;
187*539c7e67SKui-Feng Lee 	case FIN_WAIT2:
188*539c7e67SKui-Feng Lee 		if (!tcph->fin || tcph->syn || !tcph->ack)
189*539c7e67SKui-Feng Lee 			g_unexpected++;
190*539c7e67SKui-Feng Lee 		else
191*539c7e67SKui-Feng Lee 			g_sock_state = TIME_WAIT_SENDING_ACK;
192*539c7e67SKui-Feng Lee 		break;
193*539c7e67SKui-Feng Lee 	default:
194*539c7e67SKui-Feng Lee 		return 0;
195*539c7e67SKui-Feng Lee 	}
196*539c7e67SKui-Feng Lee 
197*539c7e67SKui-Feng Lee 	return 1;
198*539c7e67SKui-Feng Lee }
199*539c7e67SKui-Feng Lee 
200*539c7e67SKui-Feng Lee /* Check the types of outgoing packets of a server socket to make sure they
201*539c7e67SKui-Feng Lee  * are consistent with the state of the server socket.
202*539c7e67SKui-Feng Lee  *
203*539c7e67SKui-Feng Lee  * The connection is closed by the client side.
204*539c7e67SKui-Feng Lee  */
205*539c7e67SKui-Feng Lee SEC("cgroup_skb/egress")
server_egress(struct __sk_buff * skb)206*539c7e67SKui-Feng Lee int server_egress(struct __sk_buff *skb)
207*539c7e67SKui-Feng Lee {
208*539c7e67SKui-Feng Lee 	struct tcphdr tcph;
209*539c7e67SKui-Feng Lee 
210*539c7e67SKui-Feng Lee 	if (!needed_tcp_pkt(skb, &tcph))
211*539c7e67SKui-Feng Lee 		return 1;
212*539c7e67SKui-Feng Lee 
213*539c7e67SKui-Feng Lee 	g_packet_count++;
214*539c7e67SKui-Feng Lee 
215*539c7e67SKui-Feng Lee 	/* Egress of the server socket. */
216*539c7e67SKui-Feng Lee 	if (egress_accept(&tcph) || egress_close_remote(&tcph))
217*539c7e67SKui-Feng Lee 		return 1;
218*539c7e67SKui-Feng Lee 
219*539c7e67SKui-Feng Lee 	g_unexpected++;
220*539c7e67SKui-Feng Lee 	return 1;
221*539c7e67SKui-Feng Lee }
222*539c7e67SKui-Feng Lee 
223*539c7e67SKui-Feng Lee /* Check the types of incoming packets of a server socket to make sure they
224*539c7e67SKui-Feng Lee  * are consistent with the state of the server socket.
225*539c7e67SKui-Feng Lee  *
226*539c7e67SKui-Feng Lee  * The connection is closed by the client side.
227*539c7e67SKui-Feng Lee  */
228*539c7e67SKui-Feng Lee SEC("cgroup_skb/ingress")
server_ingress(struct __sk_buff * skb)229*539c7e67SKui-Feng Lee int server_ingress(struct __sk_buff *skb)
230*539c7e67SKui-Feng Lee {
231*539c7e67SKui-Feng Lee 	struct tcphdr tcph;
232*539c7e67SKui-Feng Lee 
233*539c7e67SKui-Feng Lee 	if (!needed_tcp_pkt(skb, &tcph))
234*539c7e67SKui-Feng Lee 		return 1;
235*539c7e67SKui-Feng Lee 
236*539c7e67SKui-Feng Lee 	g_packet_count++;
237*539c7e67SKui-Feng Lee 
238*539c7e67SKui-Feng Lee 	/* Ingress of the server socket. */
239*539c7e67SKui-Feng Lee 	if (ingress_accept(&tcph) || ingress_close_remote(&tcph))
240*539c7e67SKui-Feng Lee 		return 1;
241*539c7e67SKui-Feng Lee 
242*539c7e67SKui-Feng Lee 	g_unexpected++;
243*539c7e67SKui-Feng Lee 	return 1;
244*539c7e67SKui-Feng Lee }
245*539c7e67SKui-Feng Lee 
246*539c7e67SKui-Feng Lee /* Check the types of outgoing packets of a server socket to make sure they
247*539c7e67SKui-Feng Lee  * are consistent with the state of the server socket.
248*539c7e67SKui-Feng Lee  *
249*539c7e67SKui-Feng Lee  * The connection is closed by the server side.
250*539c7e67SKui-Feng Lee  */
251*539c7e67SKui-Feng Lee SEC("cgroup_skb/egress")
server_egress_srv(struct __sk_buff * skb)252*539c7e67SKui-Feng Lee int server_egress_srv(struct __sk_buff *skb)
253*539c7e67SKui-Feng Lee {
254*539c7e67SKui-Feng Lee 	struct tcphdr tcph;
255*539c7e67SKui-Feng Lee 
256*539c7e67SKui-Feng Lee 	if (!needed_tcp_pkt(skb, &tcph))
257*539c7e67SKui-Feng Lee 		return 1;
258*539c7e67SKui-Feng Lee 
259*539c7e67SKui-Feng Lee 	g_packet_count++;
260*539c7e67SKui-Feng Lee 
261*539c7e67SKui-Feng Lee 	/* Egress of the server socket. */
262*539c7e67SKui-Feng Lee 	if (egress_accept(&tcph) || egress_close_local(&tcph))
263*539c7e67SKui-Feng Lee 		return 1;
264*539c7e67SKui-Feng Lee 
265*539c7e67SKui-Feng Lee 	g_unexpected++;
266*539c7e67SKui-Feng Lee 	return 1;
267*539c7e67SKui-Feng Lee }
268*539c7e67SKui-Feng Lee 
269*539c7e67SKui-Feng Lee /* Check the types of incoming packets of a server socket to make sure they
270*539c7e67SKui-Feng Lee  * are consistent with the state of the server socket.
271*539c7e67SKui-Feng Lee  *
272*539c7e67SKui-Feng Lee  * The connection is closed by the server side.
273*539c7e67SKui-Feng Lee  */
274*539c7e67SKui-Feng Lee SEC("cgroup_skb/ingress")
server_ingress_srv(struct __sk_buff * skb)275*539c7e67SKui-Feng Lee int server_ingress_srv(struct __sk_buff *skb)
276*539c7e67SKui-Feng Lee {
277*539c7e67SKui-Feng Lee 	struct tcphdr tcph;
278*539c7e67SKui-Feng Lee 
279*539c7e67SKui-Feng Lee 	if (!needed_tcp_pkt(skb, &tcph))
280*539c7e67SKui-Feng Lee 		return 1;
281*539c7e67SKui-Feng Lee 
282*539c7e67SKui-Feng Lee 	g_packet_count++;
283*539c7e67SKui-Feng Lee 
284*539c7e67SKui-Feng Lee 	/* Ingress of the server socket. */
285*539c7e67SKui-Feng Lee 	if (ingress_accept(&tcph) || ingress_close_local(&tcph))
286*539c7e67SKui-Feng Lee 		return 1;
287*539c7e67SKui-Feng Lee 
288*539c7e67SKui-Feng Lee 	g_unexpected++;
289*539c7e67SKui-Feng Lee 	return 1;
290*539c7e67SKui-Feng Lee }
291*539c7e67SKui-Feng Lee 
292*539c7e67SKui-Feng Lee /* Check the types of outgoing packets of a client socket to make sure they
293*539c7e67SKui-Feng Lee  * are consistent with the state of the client socket.
294*539c7e67SKui-Feng Lee  *
295*539c7e67SKui-Feng Lee  * The connection is closed by the server side.
296*539c7e67SKui-Feng Lee  */
297*539c7e67SKui-Feng Lee SEC("cgroup_skb/egress")
client_egress_srv(struct __sk_buff * skb)298*539c7e67SKui-Feng Lee int client_egress_srv(struct __sk_buff *skb)
299*539c7e67SKui-Feng Lee {
300*539c7e67SKui-Feng Lee 	struct tcphdr tcph;
301*539c7e67SKui-Feng Lee 
302*539c7e67SKui-Feng Lee 	if (!needed_tcp_pkt(skb, &tcph))
303*539c7e67SKui-Feng Lee 		return 1;
304*539c7e67SKui-Feng Lee 
305*539c7e67SKui-Feng Lee 	g_packet_count++;
306*539c7e67SKui-Feng Lee 
307*539c7e67SKui-Feng Lee 	/* Egress of the server socket. */
308*539c7e67SKui-Feng Lee 	if (egress_connect(&tcph) || egress_close_remote(&tcph))
309*539c7e67SKui-Feng Lee 		return 1;
310*539c7e67SKui-Feng Lee 
311*539c7e67SKui-Feng Lee 	g_unexpected++;
312*539c7e67SKui-Feng Lee 	return 1;
313*539c7e67SKui-Feng Lee }
314*539c7e67SKui-Feng Lee 
315*539c7e67SKui-Feng Lee /* Check the types of incoming packets of a client socket to make sure they
316*539c7e67SKui-Feng Lee  * are consistent with the state of the client socket.
317*539c7e67SKui-Feng Lee  *
318*539c7e67SKui-Feng Lee  * The connection is closed by the server side.
319*539c7e67SKui-Feng Lee  */
320*539c7e67SKui-Feng Lee SEC("cgroup_skb/ingress")
client_ingress_srv(struct __sk_buff * skb)321*539c7e67SKui-Feng Lee int client_ingress_srv(struct __sk_buff *skb)
322*539c7e67SKui-Feng Lee {
323*539c7e67SKui-Feng Lee 	struct tcphdr tcph;
324*539c7e67SKui-Feng Lee 
325*539c7e67SKui-Feng Lee 	if (!needed_tcp_pkt(skb, &tcph))
326*539c7e67SKui-Feng Lee 		return 1;
327*539c7e67SKui-Feng Lee 
328*539c7e67SKui-Feng Lee 	g_packet_count++;
329*539c7e67SKui-Feng Lee 
330*539c7e67SKui-Feng Lee 	/* Ingress of the server socket. */
331*539c7e67SKui-Feng Lee 	if (ingress_connect(&tcph) || ingress_close_remote(&tcph))
332*539c7e67SKui-Feng Lee 		return 1;
333*539c7e67SKui-Feng Lee 
334*539c7e67SKui-Feng Lee 	g_unexpected++;
335*539c7e67SKui-Feng Lee 	return 1;
336*539c7e67SKui-Feng Lee }
337*539c7e67SKui-Feng Lee 
338*539c7e67SKui-Feng Lee /* Check the types of outgoing packets of a client socket to make sure they
339*539c7e67SKui-Feng Lee  * are consistent with the state of the client socket.
340*539c7e67SKui-Feng Lee  *
341*539c7e67SKui-Feng Lee  * The connection is closed by the client side.
342*539c7e67SKui-Feng Lee  */
343*539c7e67SKui-Feng Lee SEC("cgroup_skb/egress")
client_egress(struct __sk_buff * skb)344*539c7e67SKui-Feng Lee int client_egress(struct __sk_buff *skb)
345*539c7e67SKui-Feng Lee {
346*539c7e67SKui-Feng Lee 	struct tcphdr tcph;
347*539c7e67SKui-Feng Lee 
348*539c7e67SKui-Feng Lee 	if (!needed_tcp_pkt(skb, &tcph))
349*539c7e67SKui-Feng Lee 		return 1;
350*539c7e67SKui-Feng Lee 
351*539c7e67SKui-Feng Lee 	g_packet_count++;
352*539c7e67SKui-Feng Lee 
353*539c7e67SKui-Feng Lee 	/* Egress of the server socket. */
354*539c7e67SKui-Feng Lee 	if (egress_connect(&tcph) || egress_close_local(&tcph))
355*539c7e67SKui-Feng Lee 		return 1;
356*539c7e67SKui-Feng Lee 
357*539c7e67SKui-Feng Lee 	g_unexpected++;
358*539c7e67SKui-Feng Lee 	return 1;
359*539c7e67SKui-Feng Lee }
360*539c7e67SKui-Feng Lee 
361*539c7e67SKui-Feng Lee /* Check the types of incoming packets of a client socket to make sure they
362*539c7e67SKui-Feng Lee  * are consistent with the state of the client socket.
363*539c7e67SKui-Feng Lee  *
364*539c7e67SKui-Feng Lee  * The connection is closed by the client side.
365*539c7e67SKui-Feng Lee  */
366*539c7e67SKui-Feng Lee SEC("cgroup_skb/ingress")
client_ingress(struct __sk_buff * skb)367*539c7e67SKui-Feng Lee int client_ingress(struct __sk_buff *skb)
368*539c7e67SKui-Feng Lee {
369*539c7e67SKui-Feng Lee 	struct tcphdr tcph;
370*539c7e67SKui-Feng Lee 
371*539c7e67SKui-Feng Lee 	if (!needed_tcp_pkt(skb, &tcph))
372*539c7e67SKui-Feng Lee 		return 1;
373*539c7e67SKui-Feng Lee 
374*539c7e67SKui-Feng Lee 	g_packet_count++;
375*539c7e67SKui-Feng Lee 
376*539c7e67SKui-Feng Lee 	/* Ingress of the server socket. */
377*539c7e67SKui-Feng Lee 	if (ingress_connect(&tcph) || ingress_close_local(&tcph))
378*539c7e67SKui-Feng Lee 		return 1;
379*539c7e67SKui-Feng Lee 
380*539c7e67SKui-Feng Lee 	g_unexpected++;
381*539c7e67SKui-Feng Lee 	return 1;
382*539c7e67SKui-Feng Lee }
383