1 // SPDX-License-Identifier: GPL-2.0 2 #include <stddef.h> 3 #include <string.h> 4 #include <linux/bpf.h> 5 #include <linux/ip.h> 6 #include <linux/ipv6.h> 7 #include "bpf_helpers.h" 8 #include "bpf_endian.h" 9 10 struct grehdr { 11 __be16 flags; 12 __be16 protocol; 13 }; 14 15 SEC("encap_gre") 16 int bpf_lwt_encap_gre(struct __sk_buff *skb) 17 { 18 struct encap_hdr { 19 struct iphdr iph; 20 struct grehdr greh; 21 } hdr; 22 int err; 23 24 memset(&hdr, 0, sizeof(struct encap_hdr)); 25 26 hdr.iph.ihl = 5; 27 hdr.iph.version = 4; 28 hdr.iph.ttl = 0x40; 29 hdr.iph.protocol = 47; /* IPPROTO_GRE */ 30 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 31 hdr.iph.saddr = 0x640110ac; /* 172.16.1.100 */ 32 hdr.iph.daddr = 0x641010ac; /* 172.16.16.100 */ 33 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 34 hdr.iph.saddr = 0xac100164; /* 172.16.1.100 */ 35 hdr.iph.daddr = 0xac101064; /* 172.16.16.100 */ 36 #else 37 #error "Fix your compiler's __BYTE_ORDER__?!" 38 #endif 39 hdr.iph.tot_len = bpf_htons(skb->len + sizeof(struct encap_hdr)); 40 41 hdr.greh.protocol = skb->protocol; 42 43 err = bpf_lwt_push_encap(skb, BPF_LWT_ENCAP_IP, &hdr, 44 sizeof(struct encap_hdr)); 45 if (err) 46 return BPF_DROP; 47 48 return BPF_LWT_REROUTE; 49 } 50 51 SEC("encap_gre6") 52 int bpf_lwt_encap_gre6(struct __sk_buff *skb) 53 { 54 struct encap_hdr { 55 struct ipv6hdr ip6hdr; 56 struct grehdr greh; 57 } hdr; 58 int err; 59 60 memset(&hdr, 0, sizeof(struct encap_hdr)); 61 62 hdr.ip6hdr.version = 6; 63 hdr.ip6hdr.payload_len = bpf_htons(skb->len + sizeof(struct grehdr)); 64 hdr.ip6hdr.nexthdr = 47; /* IPPROTO_GRE */ 65 hdr.ip6hdr.hop_limit = 0x40; 66 /* fb01::1 */ 67 hdr.ip6hdr.saddr.s6_addr[0] = 0xfb; 68 hdr.ip6hdr.saddr.s6_addr[1] = 1; 69 hdr.ip6hdr.saddr.s6_addr[15] = 1; 70 /* fb10::1 */ 71 hdr.ip6hdr.daddr.s6_addr[0] = 0xfb; 72 hdr.ip6hdr.daddr.s6_addr[1] = 0x10; 73 hdr.ip6hdr.daddr.s6_addr[15] = 1; 74 75 hdr.greh.protocol = skb->protocol; 76 77 err = bpf_lwt_push_encap(skb, BPF_LWT_ENCAP_IP, &hdr, 78 sizeof(struct encap_hdr)); 79 if (err) 80 return BPF_DROP; 81 82 return BPF_LWT_REROUTE; 83 } 84 85 char _license[] SEC("license") = "GPL"; 86