0001
0002
0003
0004
0005
0006
0007 #define KBUILD_MODNAME "foo"
0008 #include <uapi/linux/bpf.h>
0009 #include <uapi/linux/if_ether.h>
0010 #include <uapi/linux/if_packet.h>
0011 #include <uapi/linux/ip.h>
0012 #include <uapi/linux/ipv6.h>
0013 #include <uapi/linux/in.h>
0014 #include <uapi/linux/tcp.h>
0015 #include <uapi/linux/filter.h>
0016 #include <uapi/linux/pkt_cls.h>
0017 #include <net/ipv6.h>
0018 #include <bpf/bpf_helpers.h>
0019
0020 #define _htonl __builtin_bswap32
0021
0022 #define PIN_GLOBAL_NS 2
0023 struct bpf_elf_map {
0024 __u32 type;
0025 __u32 size_key;
0026 __u32 size_value;
0027 __u32 max_elem;
0028 __u32 flags;
0029 __u32 id;
0030 __u32 pinning;
0031 };
0032
0033
0034 struct eth_hdr {
0035 unsigned char h_dest[ETH_ALEN];
0036 unsigned char h_source[ETH_ALEN];
0037 unsigned short h_proto;
0038 };
0039
0040 struct bpf_elf_map SEC("maps") tun_iface = {
0041 .type = BPF_MAP_TYPE_ARRAY,
0042 .size_key = sizeof(int),
0043 .size_value = sizeof(int),
0044 .pinning = PIN_GLOBAL_NS,
0045 .max_elem = 1,
0046 };
0047
0048 static __always_inline bool is_vip_addr(__be16 eth_proto, __be32 daddr)
0049 {
0050 if (eth_proto == htons(ETH_P_IP))
0051 return (_htonl(0xffffff00) & daddr) == _htonl(0x0a0a0100);
0052 else if (eth_proto == htons(ETH_P_IPV6))
0053 return (daddr == _htonl(0x2401face));
0054
0055 return false;
0056 }
0057
0058 SEC("l2_to_iptun_ingress_forward")
0059 int _l2_to_iptun_ingress_forward(struct __sk_buff *skb)
0060 {
0061 struct bpf_tunnel_key tkey = {};
0062 void *data = (void *)(long)skb->data;
0063 struct eth_hdr *eth = data;
0064 void *data_end = (void *)(long)skb->data_end;
0065 int key = 0, *ifindex;
0066
0067 int ret;
0068
0069 if (data + sizeof(*eth) > data_end)
0070 return TC_ACT_OK;
0071
0072 ifindex = bpf_map_lookup_elem(&tun_iface, &key);
0073 if (!ifindex)
0074 return TC_ACT_OK;
0075
0076 if (eth->h_proto == htons(ETH_P_IP)) {
0077 char fmt4[] = "ingress forward to ifindex:%d daddr4:%x\n";
0078 struct iphdr *iph = data + sizeof(*eth);
0079
0080 if (data + sizeof(*eth) + sizeof(*iph) > data_end)
0081 return TC_ACT_OK;
0082
0083 if (iph->protocol != IPPROTO_IPIP)
0084 return TC_ACT_OK;
0085
0086 bpf_trace_printk(fmt4, sizeof(fmt4), *ifindex,
0087 _htonl(iph->daddr));
0088 return bpf_redirect(*ifindex, BPF_F_INGRESS);
0089 } else if (eth->h_proto == htons(ETH_P_IPV6)) {
0090 char fmt6[] = "ingress forward to ifindex:%d daddr6:%x::%x\n";
0091 struct ipv6hdr *ip6h = data + sizeof(*eth);
0092
0093 if (data + sizeof(*eth) + sizeof(*ip6h) > data_end)
0094 return TC_ACT_OK;
0095
0096 if (ip6h->nexthdr != IPPROTO_IPIP &&
0097 ip6h->nexthdr != IPPROTO_IPV6)
0098 return TC_ACT_OK;
0099
0100 bpf_trace_printk(fmt6, sizeof(fmt6), *ifindex,
0101 _htonl(ip6h->daddr.s6_addr32[0]),
0102 _htonl(ip6h->daddr.s6_addr32[3]));
0103 return bpf_redirect(*ifindex, BPF_F_INGRESS);
0104 }
0105
0106 return TC_ACT_OK;
0107 }
0108
0109 SEC("l2_to_iptun_ingress_redirect")
0110 int _l2_to_iptun_ingress_redirect(struct __sk_buff *skb)
0111 {
0112 struct bpf_tunnel_key tkey = {};
0113 void *data = (void *)(long)skb->data;
0114 struct eth_hdr *eth = data;
0115 void *data_end = (void *)(long)skb->data_end;
0116 int key = 0, *ifindex;
0117
0118 int ret;
0119
0120 if (data + sizeof(*eth) > data_end)
0121 return TC_ACT_OK;
0122
0123 ifindex = bpf_map_lookup_elem(&tun_iface, &key);
0124 if (!ifindex)
0125 return TC_ACT_OK;
0126
0127 if (eth->h_proto == htons(ETH_P_IP)) {
0128 char fmt4[] = "e/ingress redirect daddr4:%x to ifindex:%d\n";
0129 struct iphdr *iph = data + sizeof(*eth);
0130 __be32 daddr = iph->daddr;
0131
0132 if (data + sizeof(*eth) + sizeof(*iph) > data_end)
0133 return TC_ACT_OK;
0134
0135 if (!is_vip_addr(eth->h_proto, daddr))
0136 return TC_ACT_OK;
0137
0138 bpf_trace_printk(fmt4, sizeof(fmt4), _htonl(daddr), *ifindex);
0139 } else {
0140 return TC_ACT_OK;
0141 }
0142
0143 tkey.tunnel_id = 10000;
0144 tkey.tunnel_ttl = 64;
0145 tkey.remote_ipv4 = 0x0a020166;
0146 bpf_skb_set_tunnel_key(skb, &tkey, sizeof(tkey), 0);
0147 return bpf_redirect(*ifindex, 0);
0148 }
0149
0150 SEC("l2_to_ip6tun_ingress_redirect")
0151 int _l2_to_ip6tun_ingress_redirect(struct __sk_buff *skb)
0152 {
0153 struct bpf_tunnel_key tkey = {};
0154 void *data = (void *)(long)skb->data;
0155 struct eth_hdr *eth = data;
0156 void *data_end = (void *)(long)skb->data_end;
0157 int key = 0, *ifindex;
0158
0159 if (data + sizeof(*eth) > data_end)
0160 return TC_ACT_OK;
0161
0162 ifindex = bpf_map_lookup_elem(&tun_iface, &key);
0163 if (!ifindex)
0164 return TC_ACT_OK;
0165
0166 if (eth->h_proto == htons(ETH_P_IP)) {
0167 char fmt4[] = "e/ingress redirect daddr4:%x to ifindex:%d\n";
0168 struct iphdr *iph = data + sizeof(*eth);
0169
0170 if (data + sizeof(*eth) + sizeof(*iph) > data_end)
0171 return TC_ACT_OK;
0172
0173 if (!is_vip_addr(eth->h_proto, iph->daddr))
0174 return TC_ACT_OK;
0175
0176 bpf_trace_printk(fmt4, sizeof(fmt4), _htonl(iph->daddr),
0177 *ifindex);
0178 } else if (eth->h_proto == htons(ETH_P_IPV6)) {
0179 char fmt6[] = "e/ingress redirect daddr6:%x to ifindex:%d\n";
0180 struct ipv6hdr *ip6h = data + sizeof(*eth);
0181
0182 if (data + sizeof(*eth) + sizeof(*ip6h) > data_end)
0183 return TC_ACT_OK;
0184
0185 if (!is_vip_addr(eth->h_proto, ip6h->daddr.s6_addr32[0]))
0186 return TC_ACT_OK;
0187
0188 bpf_trace_printk(fmt6, sizeof(fmt6),
0189 _htonl(ip6h->daddr.s6_addr32[0]), *ifindex);
0190 } else {
0191 return TC_ACT_OK;
0192 }
0193
0194 tkey.tunnel_id = 10000;
0195 tkey.tunnel_ttl = 64;
0196
0197 tkey.remote_ipv6[0] = _htonl(0x2401db02);
0198 tkey.remote_ipv6[1] = 0;
0199 tkey.remote_ipv6[2] = 0;
0200 tkey.remote_ipv6[3] = _htonl(0x00000066);
0201 bpf_skb_set_tunnel_key(skb, &tkey, sizeof(tkey), BPF_F_TUNINFO_IPV6);
0202 return bpf_redirect(*ifindex, 0);
0203 }
0204
0205 SEC("drop_non_tun_vip")
0206 int _drop_non_tun_vip(struct __sk_buff *skb)
0207 {
0208 struct bpf_tunnel_key tkey = {};
0209 void *data = (void *)(long)skb->data;
0210 struct eth_hdr *eth = data;
0211 void *data_end = (void *)(long)skb->data_end;
0212
0213 if (data + sizeof(*eth) > data_end)
0214 return TC_ACT_OK;
0215
0216 if (eth->h_proto == htons(ETH_P_IP)) {
0217 struct iphdr *iph = data + sizeof(*eth);
0218
0219 if (data + sizeof(*eth) + sizeof(*iph) > data_end)
0220 return TC_ACT_OK;
0221
0222 if (is_vip_addr(eth->h_proto, iph->daddr))
0223 return TC_ACT_SHOT;
0224 } else if (eth->h_proto == htons(ETH_P_IPV6)) {
0225 struct ipv6hdr *ip6h = data + sizeof(*eth);
0226
0227 if (data + sizeof(*eth) + sizeof(*ip6h) > data_end)
0228 return TC_ACT_OK;
0229
0230 if (is_vip_addr(eth->h_proto, ip6h->daddr.s6_addr32[0]))
0231 return TC_ACT_SHOT;
0232 }
0233
0234 return TC_ACT_OK;
0235 }
0236
0237 char _license[] SEC("license") = "GPL";