196a8eb1eSDaniel Borkmann #define KBUILD_MODNAME "foo"
291bc4822SAlexei Starovoitov #include <uapi/linux/bpf.h>
391bc4822SAlexei Starovoitov #include <uapi/linux/if_ether.h>
491bc4822SAlexei Starovoitov #include <uapi/linux/if_packet.h>
591bc4822SAlexei Starovoitov #include <uapi/linux/ip.h>
691bc4822SAlexei Starovoitov #include <uapi/linux/in.h>
791bc4822SAlexei Starovoitov #include <uapi/linux/tcp.h>
8a166151cSAlexei Starovoitov #include <uapi/linux/filter.h>
927b29f63SAlexei Starovoitov #include <uapi/linux/pkt_cls.h>
10*7cf245a3SToke Høiland-Jørgensen #include <bpf/bpf_helpers.h>
1136b5d471SAndrii Nakryiko #include "bpf_legacy.h"
1291bc4822SAlexei Starovoitov
1391bc4822SAlexei Starovoitov /* compiler workaround */
1491bc4822SAlexei Starovoitov #define _htonl __builtin_bswap32
1591bc4822SAlexei Starovoitov
set_dst_mac(struct __sk_buff * skb,char * mac)1691bc4822SAlexei Starovoitov static inline void set_dst_mac(struct __sk_buff *skb, char *mac)
1791bc4822SAlexei Starovoitov {
1891bc4822SAlexei Starovoitov bpf_skb_store_bytes(skb, 0, mac, ETH_ALEN, 1);
1991bc4822SAlexei Starovoitov }
2091bc4822SAlexei Starovoitov
2191bc4822SAlexei Starovoitov #define IP_CSUM_OFF (ETH_HLEN + offsetof(struct iphdr, check))
2291bc4822SAlexei Starovoitov #define TOS_OFF (ETH_HLEN + offsetof(struct iphdr, tos))
2391bc4822SAlexei Starovoitov
set_ip_tos(struct __sk_buff * skb,__u8 new_tos)2491bc4822SAlexei Starovoitov static inline void set_ip_tos(struct __sk_buff *skb, __u8 new_tos)
2591bc4822SAlexei Starovoitov {
263431205eSAlexei Starovoitov __u8 old_tos = load_byte(skb, TOS_OFF);
2791bc4822SAlexei Starovoitov
2891bc4822SAlexei Starovoitov bpf_l3_csum_replace(skb, IP_CSUM_OFF, htons(old_tos), htons(new_tos), 2);
2991bc4822SAlexei Starovoitov bpf_skb_store_bytes(skb, TOS_OFF, &new_tos, sizeof(new_tos), 0);
3091bc4822SAlexei Starovoitov }
3191bc4822SAlexei Starovoitov
3291bc4822SAlexei Starovoitov #define TCP_CSUM_OFF (ETH_HLEN + sizeof(struct iphdr) + offsetof(struct tcphdr, check))
3391bc4822SAlexei Starovoitov #define IP_SRC_OFF (ETH_HLEN + offsetof(struct iphdr, saddr))
3491bc4822SAlexei Starovoitov
3591bc4822SAlexei Starovoitov #define IS_PSEUDO 0x10
3691bc4822SAlexei Starovoitov
set_tcp_ip_src(struct __sk_buff * skb,__u32 new_ip)3791bc4822SAlexei Starovoitov static inline void set_tcp_ip_src(struct __sk_buff *skb, __u32 new_ip)
3891bc4822SAlexei Starovoitov {
393431205eSAlexei Starovoitov __u32 old_ip = _htonl(load_word(skb, IP_SRC_OFF));
4091bc4822SAlexei Starovoitov
4191bc4822SAlexei Starovoitov bpf_l4_csum_replace(skb, TCP_CSUM_OFF, old_ip, new_ip, IS_PSEUDO | sizeof(new_ip));
4291bc4822SAlexei Starovoitov bpf_l3_csum_replace(skb, IP_CSUM_OFF, old_ip, new_ip, sizeof(new_ip));
4391bc4822SAlexei Starovoitov bpf_skb_store_bytes(skb, IP_SRC_OFF, &new_ip, sizeof(new_ip), 0);
4491bc4822SAlexei Starovoitov }
4591bc4822SAlexei Starovoitov
4691bc4822SAlexei Starovoitov #define TCP_DPORT_OFF (ETH_HLEN + sizeof(struct iphdr) + offsetof(struct tcphdr, dest))
set_tcp_dest_port(struct __sk_buff * skb,__u16 new_port)4791bc4822SAlexei Starovoitov static inline void set_tcp_dest_port(struct __sk_buff *skb, __u16 new_port)
4891bc4822SAlexei Starovoitov {
493431205eSAlexei Starovoitov __u16 old_port = htons(load_half(skb, TCP_DPORT_OFF));
5091bc4822SAlexei Starovoitov
5191bc4822SAlexei Starovoitov bpf_l4_csum_replace(skb, TCP_CSUM_OFF, old_port, new_port, sizeof(new_port));
5291bc4822SAlexei Starovoitov bpf_skb_store_bytes(skb, TCP_DPORT_OFF, &new_port, sizeof(new_port), 0);
5391bc4822SAlexei Starovoitov }
5491bc4822SAlexei Starovoitov
5591bc4822SAlexei Starovoitov SEC("classifier")
bpf_prog1(struct __sk_buff * skb)5691bc4822SAlexei Starovoitov int bpf_prog1(struct __sk_buff *skb)
5791bc4822SAlexei Starovoitov {
583431205eSAlexei Starovoitov __u8 proto = load_byte(skb, ETH_HLEN + offsetof(struct iphdr, protocol));
5991bc4822SAlexei Starovoitov long *value;
6091bc4822SAlexei Starovoitov
6191bc4822SAlexei Starovoitov if (proto == IPPROTO_TCP) {
6291bc4822SAlexei Starovoitov set_ip_tos(skb, 8);
6391bc4822SAlexei Starovoitov set_tcp_ip_src(skb, 0xA010101);
6491bc4822SAlexei Starovoitov set_tcp_dest_port(skb, 5001);
6591bc4822SAlexei Starovoitov }
6691bc4822SAlexei Starovoitov
6791bc4822SAlexei Starovoitov return 0;
6891bc4822SAlexei Starovoitov }
6927b29f63SAlexei Starovoitov SEC("redirect_xmit")
_redirect_xmit(struct __sk_buff * skb)7027b29f63SAlexei Starovoitov int _redirect_xmit(struct __sk_buff *skb)
7127b29f63SAlexei Starovoitov {
7227b29f63SAlexei Starovoitov return bpf_redirect(skb->ifindex + 1, 0);
7327b29f63SAlexei Starovoitov }
7427b29f63SAlexei Starovoitov SEC("redirect_recv")
_redirect_recv(struct __sk_buff * skb)7527b29f63SAlexei Starovoitov int _redirect_recv(struct __sk_buff *skb)
7627b29f63SAlexei Starovoitov {
7727b29f63SAlexei Starovoitov return bpf_redirect(skb->ifindex + 1, 1);
7827b29f63SAlexei Starovoitov }
7927b29f63SAlexei Starovoitov SEC("clone_redirect_xmit")
_clone_redirect_xmit(struct __sk_buff * skb)8027b29f63SAlexei Starovoitov int _clone_redirect_xmit(struct __sk_buff *skb)
8127b29f63SAlexei Starovoitov {
8227b29f63SAlexei Starovoitov bpf_clone_redirect(skb, skb->ifindex + 1, 0);
8327b29f63SAlexei Starovoitov return TC_ACT_SHOT;
8427b29f63SAlexei Starovoitov }
8527b29f63SAlexei Starovoitov SEC("clone_redirect_recv")
_clone_redirect_recv(struct __sk_buff * skb)8627b29f63SAlexei Starovoitov int _clone_redirect_recv(struct __sk_buff *skb)
8727b29f63SAlexei Starovoitov {
8827b29f63SAlexei Starovoitov bpf_clone_redirect(skb, skb->ifindex + 1, 1);
8927b29f63SAlexei Starovoitov return TC_ACT_SHOT;
9027b29f63SAlexei Starovoitov }
9191bc4822SAlexei Starovoitov char _license[] SEC("license") = "GPL";
92