tcp_tos_reflect_kern.c (1833B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (c) 2018 Facebook 4 * 5 * BPF program to automatically reflect TOS option from received syn packet 6 * 7 * Use "bpftool cgroup attach $cg sock_ops $prog" to load this BPF program. 8 */ 9 10#include <uapi/linux/bpf.h> 11#include <uapi/linux/tcp.h> 12#include <uapi/linux/if_ether.h> 13#include <uapi/linux/if_packet.h> 14#include <uapi/linux/ip.h> 15#include <uapi/linux/ipv6.h> 16#include <uapi/linux/in.h> 17#include <linux/socket.h> 18#include <bpf/bpf_helpers.h> 19#include <bpf/bpf_endian.h> 20 21#define DEBUG 1 22 23SEC("sockops") 24int bpf_basertt(struct bpf_sock_ops *skops) 25{ 26 char header[sizeof(struct ipv6hdr)]; 27 struct ipv6hdr *hdr6; 28 struct iphdr *hdr; 29 int hdr_size = 0; 30 int save_syn = 1; 31 int tos = 0; 32 int rv = 0; 33 int op; 34 35 op = (int) skops->op; 36 37#ifdef DEBUG 38 bpf_printk("BPF command: %d\n", op); 39#endif 40 switch (op) { 41 case BPF_SOCK_OPS_TCP_LISTEN_CB: 42 rv = bpf_setsockopt(skops, SOL_TCP, TCP_SAVE_SYN, 43 &save_syn, sizeof(save_syn)); 44 break; 45 case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: 46 if (skops->family == AF_INET) 47 hdr_size = sizeof(struct iphdr); 48 else 49 hdr_size = sizeof(struct ipv6hdr); 50 rv = bpf_getsockopt(skops, SOL_TCP, TCP_SAVED_SYN, 51 header, hdr_size); 52 if (!rv) { 53 if (skops->family == AF_INET) { 54 hdr = (struct iphdr *) header; 55 tos = hdr->tos; 56 if (tos != 0) 57 bpf_setsockopt(skops, SOL_IP, IP_TOS, 58 &tos, sizeof(tos)); 59 } else { 60 hdr6 = (struct ipv6hdr *) header; 61 tos = ((hdr6->priority) << 4 | 62 (hdr6->flow_lbl[0]) >> 4); 63 if (tos) 64 bpf_setsockopt(skops, SOL_IPV6, 65 IPV6_TCLASS, 66 &tos, sizeof(tos)); 67 } 68 rv = 0; 69 } 70 break; 71 default: 72 rv = -1; 73 } 74#ifdef DEBUG 75 bpf_printk("Returning %d\n", rv); 76#endif 77 skops->reply = rv; 78 return 1; 79} 80char _license[] SEC("license") = "GPL";