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 load_sock_ops 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_helpers.h" 19 #include "bpf_endian.h" 20 21 #define DEBUG 1 22 23 #define bpf_printk(fmt, ...) \ 24 ({ \ 25 char ____fmt[] = fmt; \ 26 bpf_trace_printk(____fmt, sizeof(____fmt), \ 27 ##__VA_ARGS__); \ 28 }) 29 30 SEC("sockops") 31 int bpf_basertt(struct bpf_sock_ops *skops) 32 { 33 char header[sizeof(struct ipv6hdr)]; 34 struct ipv6hdr *hdr6; 35 struct iphdr *hdr; 36 int hdr_size = 0; 37 int save_syn = 1; 38 int tos = 0; 39 int rv = 0; 40 int op; 41 42 op = (int) skops->op; 43 44 #ifdef DEBUG 45 bpf_printk("BPF command: %d\n", op); 46 #endif 47 switch (op) { 48 case BPF_SOCK_OPS_TCP_LISTEN_CB: 49 rv = bpf_setsockopt(skops, SOL_TCP, TCP_SAVE_SYN, 50 &save_syn, sizeof(save_syn)); 51 break; 52 case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: 53 if (skops->family == AF_INET) 54 hdr_size = sizeof(struct iphdr); 55 else 56 hdr_size = sizeof(struct ipv6hdr); 57 rv = bpf_getsockopt(skops, SOL_TCP, TCP_SAVED_SYN, 58 header, hdr_size); 59 if (!rv) { 60 if (skops->family == AF_INET) { 61 hdr = (struct iphdr *) header; 62 tos = hdr->tos; 63 if (tos != 0) 64 bpf_setsockopt(skops, SOL_IP, IP_TOS, 65 &tos, sizeof(tos)); 66 } else { 67 hdr6 = (struct ipv6hdr *) header; 68 tos = ((hdr6->priority) << 4 | 69 (hdr6->flow_lbl[0]) >> 4); 70 if (tos) 71 bpf_setsockopt(skops, SOL_IPV6, 72 IPV6_TCLASS, 73 &tos, sizeof(tos)); 74 } 75 rv = 0; 76 } 77 break; 78 default: 79 rv = -1; 80 } 81 #ifdef DEBUG 82 bpf_printk("Returning %d\n", rv); 83 #endif 84 skops->reply = rv; 85 return 1; 86 } 87 char _license[] SEC("license") = "GPL"; 88