Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /* Copyright (c) 2017-2018 Covalent IO, Inc. http://covalent.io */
0003 #include <stddef.h>
0004 #include <string.h>
0005 #include <linux/bpf.h>
0006 #include <linux/if_ether.h>
0007 #include <linux/if_packet.h>
0008 #include <linux/ip.h>
0009 #include <linux/ipv6.h>
0010 #include <linux/in.h>
0011 #include <linux/udp.h>
0012 #include <linux/tcp.h>
0013 #include <linux/pkt_cls.h>
0014 #include <sys/socket.h>
0015 #include <bpf/bpf_helpers.h>
0016 #include <bpf/bpf_endian.h>
0017 
0018 /* Sockmap sample program connects a client and a backend together
0019  * using cgroups.
0020  *
0021  *    client:X <---> frontend:80 client:X <---> backend:80
0022  *
0023  * For simplicity we hard code values here and bind 1:1. The hard
0024  * coded values are part of the setup in sockmap.sh script that
0025  * is associated with this BPF program.
0026  *
0027  * The bpf_printk is verbose and prints information as connections
0028  * are established and verdicts are decided.
0029  */
0030 
0031 struct {
0032     __uint(type, TEST_MAP_TYPE);
0033     __uint(max_entries, 20);
0034     __uint(key_size, sizeof(int));
0035     __uint(value_size, sizeof(int));
0036 } sock_map SEC(".maps");
0037 
0038 struct {
0039     __uint(type, TEST_MAP_TYPE);
0040     __uint(max_entries, 20);
0041     __uint(key_size, sizeof(int));
0042     __uint(value_size, sizeof(int));
0043 } sock_map_txmsg SEC(".maps");
0044 
0045 struct {
0046     __uint(type, TEST_MAP_TYPE);
0047     __uint(max_entries, 20);
0048     __uint(key_size, sizeof(int));
0049     __uint(value_size, sizeof(int));
0050 } sock_map_redir SEC(".maps");
0051 
0052 struct {
0053     __uint(type, BPF_MAP_TYPE_ARRAY);
0054     __uint(max_entries, 1);
0055     __type(key, int);
0056     __type(value, int);
0057 } sock_apply_bytes SEC(".maps");
0058 
0059 struct {
0060     __uint(type, BPF_MAP_TYPE_ARRAY);
0061     __uint(max_entries, 1);
0062     __type(key, int);
0063     __type(value, int);
0064 } sock_cork_bytes SEC(".maps");
0065 
0066 struct {
0067     __uint(type, BPF_MAP_TYPE_ARRAY);
0068     __uint(max_entries, 6);
0069     __type(key, int);
0070     __type(value, int);
0071 } sock_bytes SEC(".maps");
0072 
0073 struct {
0074     __uint(type, BPF_MAP_TYPE_ARRAY);
0075     __uint(max_entries, 1);
0076     __type(key, int);
0077     __type(value, int);
0078 } sock_redir_flags SEC(".maps");
0079 
0080 struct {
0081     __uint(type, BPF_MAP_TYPE_ARRAY);
0082     __uint(max_entries, 3);
0083     __type(key, int);
0084     __type(value, int);
0085 } sock_skb_opts SEC(".maps");
0086 
0087 struct {
0088     __uint(type, TEST_MAP_TYPE);
0089     __uint(max_entries, 20);
0090     __uint(key_size, sizeof(int));
0091     __uint(value_size, sizeof(int));
0092 } tls_sock_map SEC(".maps");
0093 
0094 SEC("sk_skb1")
0095 int bpf_prog1(struct __sk_buff *skb)
0096 {
0097     int *f, two = 2;
0098 
0099     f = bpf_map_lookup_elem(&sock_skb_opts, &two);
0100     if (f && *f) {
0101         return *f;
0102     }
0103     return skb->len;
0104 }
0105 
0106 SEC("sk_skb2")
0107 int bpf_prog2(struct __sk_buff *skb)
0108 {
0109     __u32 lport = skb->local_port;
0110     __u32 rport = skb->remote_port;
0111     int len, *f, ret, zero = 0;
0112     __u64 flags = 0;
0113 
0114     if (lport == 10000)
0115         ret = 10;
0116     else
0117         ret = 1;
0118 
0119     len = (__u32)skb->data_end - (__u32)skb->data;
0120     f = bpf_map_lookup_elem(&sock_skb_opts, &zero);
0121     if (f && *f) {
0122         ret = 3;
0123         flags = *f;
0124     }
0125 
0126 #ifdef SOCKMAP
0127     return bpf_sk_redirect_map(skb, &sock_map, ret, flags);
0128 #else
0129     return bpf_sk_redirect_hash(skb, &sock_map, &ret, flags);
0130 #endif
0131 
0132 }
0133 
0134 static inline void bpf_write_pass(struct __sk_buff *skb, int offset)
0135 {
0136     int err = bpf_skb_pull_data(skb, 6 + offset);
0137     void *data_end;
0138     char *c;
0139 
0140     if (err)
0141         return;
0142 
0143     c = (char *)(long)skb->data;
0144     data_end = (void *)(long)skb->data_end;
0145 
0146     if (c + 5 + offset < data_end)
0147         memcpy(c + offset, "PASS", 4);
0148 }
0149 
0150 SEC("sk_skb3")
0151 int bpf_prog3(struct __sk_buff *skb)
0152 {
0153     int err, *f, ret = SK_PASS;
0154     const int one = 1;
0155 
0156     f = bpf_map_lookup_elem(&sock_skb_opts, &one);
0157     if (f && *f) {
0158         __u64 flags = 0;
0159 
0160         ret = 0;
0161         flags = *f;
0162 
0163         err = bpf_skb_adjust_room(skb, -13, 0, 0);
0164         if (err)
0165             return SK_DROP;
0166         err = bpf_skb_adjust_room(skb, 4, 0, 0);
0167         if (err)
0168             return SK_DROP;
0169         bpf_write_pass(skb, 0);
0170 #ifdef SOCKMAP
0171         return bpf_sk_redirect_map(skb, &tls_sock_map, ret, flags);
0172 #else
0173         return bpf_sk_redirect_hash(skb, &tls_sock_map, &ret, flags);
0174 #endif
0175     }
0176     f = bpf_map_lookup_elem(&sock_skb_opts, &one);
0177     if (f && *f)
0178         ret = SK_DROP;
0179     err = bpf_skb_adjust_room(skb, 4, 0, 0);
0180     if (err)
0181         return SK_DROP;
0182     bpf_write_pass(skb, 13);
0183 tls_out:
0184     return ret;
0185 }
0186 
0187 SEC("sockops")
0188 int bpf_sockmap(struct bpf_sock_ops *skops)
0189 {
0190     __u32 lport, rport;
0191     int op, err = 0, index, key, ret;
0192 
0193 
0194     op = (int) skops->op;
0195 
0196     switch (op) {
0197     case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
0198         lport = skops->local_port;
0199         rport = skops->remote_port;
0200 
0201         if (lport == 10000) {
0202             ret = 1;
0203 #ifdef SOCKMAP
0204             err = bpf_sock_map_update(skops, &sock_map, &ret,
0205                           BPF_NOEXIST);
0206 #else
0207             err = bpf_sock_hash_update(skops, &sock_map, &ret,
0208                            BPF_NOEXIST);
0209 #endif
0210         }
0211         break;
0212     case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
0213         lport = skops->local_port;
0214         rport = skops->remote_port;
0215 
0216         if (bpf_ntohl(rport) == 10001) {
0217             ret = 10;
0218 #ifdef SOCKMAP
0219             err = bpf_sock_map_update(skops, &sock_map, &ret,
0220                           BPF_NOEXIST);
0221 #else
0222             err = bpf_sock_hash_update(skops, &sock_map, &ret,
0223                            BPF_NOEXIST);
0224 #endif
0225         }
0226         break;
0227     default:
0228         break;
0229     }
0230 
0231     return 0;
0232 }
0233 
0234 SEC("sk_msg1")
0235 int bpf_prog4(struct sk_msg_md *msg)
0236 {
0237     int *bytes, zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5;
0238     int *start, *end, *start_push, *end_push, *start_pop, *pop, err = 0;
0239 
0240     bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
0241     if (bytes)
0242         bpf_msg_apply_bytes(msg, *bytes);
0243     bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
0244     if (bytes)
0245         bpf_msg_cork_bytes(msg, *bytes);
0246     start = bpf_map_lookup_elem(&sock_bytes, &zero);
0247     end = bpf_map_lookup_elem(&sock_bytes, &one);
0248     if (start && end)
0249         bpf_msg_pull_data(msg, *start, *end, 0);
0250     start_push = bpf_map_lookup_elem(&sock_bytes, &two);
0251     end_push = bpf_map_lookup_elem(&sock_bytes, &three);
0252     if (start_push && end_push) {
0253         err = bpf_msg_push_data(msg, *start_push, *end_push, 0);
0254         if (err)
0255             return SK_DROP;
0256     }
0257     start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
0258     pop = bpf_map_lookup_elem(&sock_bytes, &five);
0259     if (start_pop && pop)
0260         bpf_msg_pop_data(msg, *start_pop, *pop, 0);
0261     return SK_PASS;
0262 }
0263 
0264 SEC("sk_msg2")
0265 int bpf_prog6(struct sk_msg_md *msg)
0266 {
0267     int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5, key = 0;
0268     int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop, *f;
0269     int err = 0;
0270     __u64 flags = 0;
0271 
0272     bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
0273     if (bytes)
0274         bpf_msg_apply_bytes(msg, *bytes);
0275     bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
0276     if (bytes)
0277         bpf_msg_cork_bytes(msg, *bytes);
0278 
0279     start = bpf_map_lookup_elem(&sock_bytes, &zero);
0280     end = bpf_map_lookup_elem(&sock_bytes, &one);
0281     if (start && end)
0282         bpf_msg_pull_data(msg, *start, *end, 0);
0283 
0284     start_push = bpf_map_lookup_elem(&sock_bytes, &two);
0285     end_push = bpf_map_lookup_elem(&sock_bytes, &three);
0286     if (start_push && end_push) {
0287         err = bpf_msg_push_data(msg, *start_push, *end_push, 0);
0288         if (err)
0289             return SK_DROP;
0290     }
0291 
0292     start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
0293     pop = bpf_map_lookup_elem(&sock_bytes, &five);
0294     if (start_pop && pop)
0295         bpf_msg_pop_data(msg, *start_pop, *pop, 0);
0296 
0297     f = bpf_map_lookup_elem(&sock_redir_flags, &zero);
0298     if (f && *f) {
0299         key = 2;
0300         flags = *f;
0301     }
0302 #ifdef SOCKMAP
0303     return bpf_msg_redirect_map(msg, &sock_map_redir, key, flags);
0304 #else
0305     return bpf_msg_redirect_hash(msg, &sock_map_redir, &key, flags);
0306 #endif
0307 }
0308 
0309 SEC("sk_msg3")
0310 int bpf_prog8(struct sk_msg_md *msg)
0311 {
0312     void *data_end = (void *)(long) msg->data_end;
0313     void *data = (void *)(long) msg->data;
0314     int ret = 0, *bytes, zero = 0;
0315 
0316     bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
0317     if (bytes) {
0318         ret = bpf_msg_apply_bytes(msg, *bytes);
0319         if (ret)
0320             return SK_DROP;
0321     } else {
0322         return SK_DROP;
0323     }
0324     return SK_PASS;
0325 }
0326 SEC("sk_msg4")
0327 int bpf_prog9(struct sk_msg_md *msg)
0328 {
0329     void *data_end = (void *)(long) msg->data_end;
0330     void *data = (void *)(long) msg->data;
0331     int ret = 0, *bytes, zero = 0;
0332 
0333     bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
0334     if (bytes) {
0335         if (((__u64)data_end - (__u64)data) >= *bytes)
0336             return SK_PASS;
0337         ret = bpf_msg_cork_bytes(msg, *bytes);
0338         if (ret)
0339             return SK_DROP;
0340     }
0341     return SK_PASS;
0342 }
0343 
0344 SEC("sk_msg5")
0345 int bpf_prog10(struct sk_msg_md *msg)
0346 {
0347     int *bytes, *start, *end, *start_push, *end_push, *start_pop, *pop;
0348     int zero = 0, one = 1, two = 2, three = 3, four = 4, five = 5, err = 0;
0349 
0350     bytes = bpf_map_lookup_elem(&sock_apply_bytes, &zero);
0351     if (bytes)
0352         bpf_msg_apply_bytes(msg, *bytes);
0353     bytes = bpf_map_lookup_elem(&sock_cork_bytes, &zero);
0354     if (bytes)
0355         bpf_msg_cork_bytes(msg, *bytes);
0356     start = bpf_map_lookup_elem(&sock_bytes, &zero);
0357     end = bpf_map_lookup_elem(&sock_bytes, &one);
0358     if (start && end)
0359         bpf_msg_pull_data(msg, *start, *end, 0);
0360     start_push = bpf_map_lookup_elem(&sock_bytes, &two);
0361     end_push = bpf_map_lookup_elem(&sock_bytes, &three);
0362     if (start_push && end_push) {
0363         err = bpf_msg_push_data(msg, *start_push, *end_push, 0);
0364         if (err)
0365             return SK_PASS;
0366     }
0367     start_pop = bpf_map_lookup_elem(&sock_bytes, &four);
0368     pop = bpf_map_lookup_elem(&sock_bytes, &five);
0369     if (start_pop && pop)
0370         bpf_msg_pop_data(msg, *start_pop, *pop, 0);
0371     return SK_DROP;
0372 }
0373 
0374 char _license[] SEC("license") = "GPL";