Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Kui-Feng Lee | 1164 | 99.23% | 1 | 25.00% |
Sargun Dhillon | 4 | 0.34% | 1 | 25.00% |
Roman Gushchin | 4 | 0.34% | 1 | 25.00% |
Greg Kroah-Hartman | 1 | 0.09% | 1 | 25.00% |
Total | 1173 | 4 |
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
// SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */ #include <linux/bpf.h> #include <bpf/bpf_endian.h> #include <bpf/bpf_helpers.h> #include <linux/if_ether.h> #include <linux/in.h> #include <linux/in6.h> #include <linux/ipv6.h> #include <linux/tcp.h> #include <sys/types.h> #include <sys/socket.h> #include "cgroup_tcp_skb.h" char _license[] SEC("license") = "GPL"; __u16 g_sock_port = 0; __u32 g_sock_state = 0; int g_unexpected = 0; __u32 g_packet_count = 0; int needed_tcp_pkt(struct __sk_buff *skb, struct tcphdr *tcph) { struct ipv6hdr ip6h; if (skb->protocol != bpf_htons(ETH_P_IPV6)) return 0; if (bpf_skb_load_bytes(skb, 0, &ip6h, sizeof(ip6h))) return 0; if (ip6h.nexthdr != IPPROTO_TCP) return 0; if (bpf_skb_load_bytes(skb, sizeof(ip6h), tcph, sizeof(*tcph))) return 0; if (tcph->source != bpf_htons(g_sock_port) && tcph->dest != bpf_htons(g_sock_port)) return 0; return 1; } /* Run accept() on a socket in the cgroup to receive a new connection. */ static int egress_accept(struct tcphdr *tcph) { if (g_sock_state == SYN_RECV_SENDING_SYN_ACK) { if (tcph->fin || !tcph->syn || !tcph->ack) g_unexpected++; else g_sock_state = SYN_RECV; return 1; } return 0; } static int ingress_accept(struct tcphdr *tcph) { switch (g_sock_state) { case INIT: if (!tcph->syn || tcph->fin || tcph->ack) g_unexpected++; else g_sock_state = SYN_RECV_SENDING_SYN_ACK; break; case SYN_RECV: if (tcph->fin || tcph->syn || !tcph->ack) g_unexpected++; else g_sock_state = ESTABLISHED; break; default: return 0; } return 1; } /* Run connect() on a socket in the cgroup to start a new connection. */ static int egress_connect(struct tcphdr *tcph) { if (g_sock_state == INIT) { if (!tcph->syn || tcph->fin || tcph->ack) g_unexpected++; else g_sock_state = SYN_SENT; return 1; } return 0; } static int ingress_connect(struct tcphdr *tcph) { if (g_sock_state == SYN_SENT) { if (tcph->fin || !tcph->syn || !tcph->ack) g_unexpected++; else g_sock_state = ESTABLISHED; return 1; } return 0; } /* The connection is closed by the peer outside the cgroup. */ static int egress_close_remote(struct tcphdr *tcph) { switch (g_sock_state) { case ESTABLISHED: break; case CLOSE_WAIT_SENDING_ACK: if (tcph->fin || tcph->syn || !tcph->ack) g_unexpected++; else g_sock_state = CLOSE_WAIT; break; case CLOSE_WAIT: if (!tcph->fin) g_unexpected++; else g_sock_state = LAST_ACK; break; default: return 0; } return 1; } static int ingress_close_remote(struct tcphdr *tcph) { switch (g_sock_state) { case ESTABLISHED: if (tcph->fin) g_sock_state = CLOSE_WAIT_SENDING_ACK; break; case LAST_ACK: if (tcph->fin || tcph->syn || !tcph->ack) g_unexpected++; else g_sock_state = CLOSED; break; default: return 0; } return 1; } /* The connection is closed by the endpoint inside the cgroup. */ static int egress_close_local(struct tcphdr *tcph) { switch (g_sock_state) { case ESTABLISHED: if (tcph->fin) g_sock_state = FIN_WAIT1; break; case TIME_WAIT_SENDING_ACK: if (tcph->fin || tcph->syn || !tcph->ack) g_unexpected++; else g_sock_state = TIME_WAIT; break; default: return 0; } return 1; } static int ingress_close_local(struct tcphdr *tcph) { switch (g_sock_state) { case ESTABLISHED: break; case FIN_WAIT1: if (tcph->fin || tcph->syn || !tcph->ack) g_unexpected++; else g_sock_state = FIN_WAIT2; break; case FIN_WAIT2: if (!tcph->fin || tcph->syn || !tcph->ack) g_unexpected++; else g_sock_state = TIME_WAIT_SENDING_ACK; break; default: return 0; } return 1; } /* Check the types of outgoing packets of a server socket to make sure they * are consistent with the state of the server socket. * * The connection is closed by the client side. */ SEC("cgroup_skb/egress") int server_egress(struct __sk_buff *skb) { struct tcphdr tcph; if (!needed_tcp_pkt(skb, &tcph)) return 1; g_packet_count++; /* Egress of the server socket. */ if (egress_accept(&tcph) || egress_close_remote(&tcph)) return 1; g_unexpected++; return 1; } /* Check the types of incoming packets of a server socket to make sure they * are consistent with the state of the server socket. * * The connection is closed by the client side. */ SEC("cgroup_skb/ingress") int server_ingress(struct __sk_buff *skb) { struct tcphdr tcph; if (!needed_tcp_pkt(skb, &tcph)) return 1; g_packet_count++; /* Ingress of the server socket. */ if (ingress_accept(&tcph) || ingress_close_remote(&tcph)) return 1; g_unexpected++; return 1; } /* Check the types of outgoing packets of a server socket to make sure they * are consistent with the state of the server socket. * * The connection is closed by the server side. */ SEC("cgroup_skb/egress") int server_egress_srv(struct __sk_buff *skb) { struct tcphdr tcph; if (!needed_tcp_pkt(skb, &tcph)) return 1; g_packet_count++; /* Egress of the server socket. */ if (egress_accept(&tcph) || egress_close_local(&tcph)) return 1; g_unexpected++; return 1; } /* Check the types of incoming packets of a server socket to make sure they * are consistent with the state of the server socket. * * The connection is closed by the server side. */ SEC("cgroup_skb/ingress") int server_ingress_srv(struct __sk_buff *skb) { struct tcphdr tcph; if (!needed_tcp_pkt(skb, &tcph)) return 1; g_packet_count++; /* Ingress of the server socket. */ if (ingress_accept(&tcph) || ingress_close_local(&tcph)) return 1; g_unexpected++; return 1; } /* Check the types of outgoing packets of a client socket to make sure they * are consistent with the state of the client socket. * * The connection is closed by the server side. */ SEC("cgroup_skb/egress") int client_egress_srv(struct __sk_buff *skb) { struct tcphdr tcph; if (!needed_tcp_pkt(skb, &tcph)) return 1; g_packet_count++; /* Egress of the server socket. */ if (egress_connect(&tcph) || egress_close_remote(&tcph)) return 1; g_unexpected++; return 1; } /* Check the types of incoming packets of a client socket to make sure they * are consistent with the state of the client socket. * * The connection is closed by the server side. */ SEC("cgroup_skb/ingress") int client_ingress_srv(struct __sk_buff *skb) { struct tcphdr tcph; if (!needed_tcp_pkt(skb, &tcph)) return 1; g_packet_count++; /* Ingress of the server socket. */ if (ingress_connect(&tcph) || ingress_close_remote(&tcph)) return 1; g_unexpected++; return 1; } /* Check the types of outgoing packets of a client socket to make sure they * are consistent with the state of the client socket. * * The connection is closed by the client side. */ SEC("cgroup_skb/egress") int client_egress(struct __sk_buff *skb) { struct tcphdr tcph; if (!needed_tcp_pkt(skb, &tcph)) return 1; g_packet_count++; /* Egress of the server socket. */ if (egress_connect(&tcph) || egress_close_local(&tcph)) return 1; g_unexpected++; return 1; } /* Check the types of incoming packets of a client socket to make sure they * are consistent with the state of the client socket. * * The connection is closed by the client side. */ SEC("cgroup_skb/ingress") int client_ingress(struct __sk_buff *skb) { struct tcphdr tcph; if (!needed_tcp_pkt(skb, &tcph)) return 1; g_packet_count++; /* Ingress of the server socket. */ if (ingress_connect(&tcph) || ingress_close_local(&tcph)) return 1; g_unexpected++; return 1; }
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1