0001
0002 #include <string.h>
0003 #include <linux/tcp.h>
0004 #include <linux/bpf.h>
0005 #include <netinet/in.h>
0006 #include <bpf/bpf_helpers.h>
0007
0008 char _license[] SEC("license") = "GPL";
0009
0010 int page_size = 0;
0011
0012 #ifndef SOL_TCP
0013 #define SOL_TCP IPPROTO_TCP
0014 #endif
0015
0016 #define SOL_CUSTOM 0xdeadbeef
0017
0018 struct sockopt_sk {
0019 __u8 val;
0020 };
0021
0022 struct {
0023 __uint(type, BPF_MAP_TYPE_SK_STORAGE);
0024 __uint(map_flags, BPF_F_NO_PREALLOC);
0025 __type(key, int);
0026 __type(value, struct sockopt_sk);
0027 } socket_storage_map SEC(".maps");
0028
0029 SEC("cgroup/getsockopt")
0030 int _getsockopt(struct bpf_sockopt *ctx)
0031 {
0032 __u8 *optval_end = ctx->optval_end;
0033 __u8 *optval = ctx->optval;
0034 struct sockopt_sk *storage;
0035
0036
0037
0038 if (bpf_get_netns_cookie(NULL) == 0)
0039 return 0;
0040
0041 if (bpf_get_netns_cookie(ctx) == 0)
0042 return 0;
0043
0044 if (ctx->level == SOL_IP && ctx->optname == IP_TOS) {
0045
0046
0047
0048
0049 ctx->optlen = 0;
0050 return 1;
0051 }
0052
0053 if (ctx->level == SOL_SOCKET && ctx->optname == SO_SNDBUF) {
0054
0055
0056
0057
0058 return 1;
0059 }
0060
0061 if (ctx->level == SOL_TCP && ctx->optname == TCP_CONGESTION) {
0062
0063
0064
0065
0066 return 1;
0067 }
0068
0069 if (ctx->level == SOL_TCP && ctx->optname == TCP_ZEROCOPY_RECEIVE) {
0070
0071
0072
0073
0074
0075
0076 if (optval + sizeof(__u64) > optval_end)
0077 return 0;
0078
0079 if (((struct tcp_zerocopy_receive *)optval)->address != 0)
0080 return 0;
0081
0082 return 1;
0083 }
0084
0085 if (ctx->level == SOL_IP && ctx->optname == IP_FREEBIND) {
0086 if (optval + 1 > optval_end)
0087 return 0;
0088
0089 ctx->retval = 0;
0090
0091
0092 optval[0] = 0x55;
0093 ctx->optlen = 1;
0094
0095
0096
0097
0098
0099 if (optval_end - optval != page_size)
0100 return 0;
0101
0102 return 1;
0103 }
0104
0105 if (ctx->level != SOL_CUSTOM)
0106 return 0;
0107
0108 if (optval + 1 > optval_end)
0109 return 0;
0110
0111 storage = bpf_sk_storage_get(&socket_storage_map, ctx->sk, 0,
0112 BPF_SK_STORAGE_GET_F_CREATE);
0113 if (!storage)
0114 return 0;
0115
0116 if (!ctx->retval)
0117 return 0;
0118
0119
0120 ctx->retval = 0;
0121
0122 optval[0] = storage->val;
0123 ctx->optlen = 1;
0124
0125 return 1;
0126 }
0127
0128 SEC("cgroup/setsockopt")
0129 int _setsockopt(struct bpf_sockopt *ctx)
0130 {
0131 __u8 *optval_end = ctx->optval_end;
0132 __u8 *optval = ctx->optval;
0133 struct sockopt_sk *storage;
0134
0135
0136
0137 if (bpf_get_netns_cookie(NULL) == 0)
0138 return 0;
0139
0140 if (bpf_get_netns_cookie(ctx) == 0)
0141 return 0;
0142
0143 if (ctx->level == SOL_IP && ctx->optname == IP_TOS) {
0144
0145
0146
0147
0148 ctx->optlen = 0;
0149 return 1;
0150 }
0151
0152 if (ctx->level == SOL_SOCKET && ctx->optname == SO_SNDBUF) {
0153
0154
0155 if (optval + sizeof(__u32) > optval_end)
0156 return 0;
0157
0158 *(__u32 *)optval = 0x55AA;
0159 ctx->optlen = 4;
0160
0161 return 1;
0162 }
0163
0164 if (ctx->level == SOL_TCP && ctx->optname == TCP_CONGESTION) {
0165
0166
0167 if (optval + 5 > optval_end)
0168 return 0;
0169
0170 memcpy(optval, "cubic", 5);
0171 ctx->optlen = 5;
0172
0173 return 1;
0174 }
0175
0176 if (ctx->level == SOL_IP && ctx->optname == IP_FREEBIND) {
0177
0178 if (ctx->optlen != page_size * 2)
0179 return 0;
0180
0181 if (optval + 1 > optval_end)
0182 return 0;
0183
0184
0185 optval[0] = 0;
0186 ctx->optlen = 1;
0187
0188
0189
0190
0191
0192 if (optval_end - optval != page_size)
0193 return 0;
0194
0195 return 1;
0196 }
0197
0198 if (ctx->level != SOL_CUSTOM)
0199 return 0;
0200
0201 if (optval + 1 > optval_end)
0202 return 0;
0203
0204 storage = bpf_sk_storage_get(&socket_storage_map, ctx->sk, 0,
0205 BPF_SK_STORAGE_GET_F_CREATE);
0206 if (!storage)
0207 return 0;
0208
0209 storage->val = optval[0];
0210 ctx->optlen = -1;
0211
0212
0213
0214 return 1;
0215 }