| xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 1 | #define KBUILD_MODNAME "foo" | 
 | 2 | #include <uapi/linux/bpf.h> | 
 | 3 | #include <uapi/linux/if_ether.h> | 
 | 4 | #include <uapi/linux/if_packet.h> | 
 | 5 | #include <uapi/linux/ip.h> | 
 | 6 | #include <uapi/linux/in.h> | 
 | 7 | #include <uapi/linux/tcp.h> | 
 | 8 | #include <uapi/linux/filter.h> | 
 | 9 | #include <uapi/linux/pkt_cls.h> | 
 | 10 | #include "bpf_helpers.h" | 
 | 11 |  | 
 | 12 | /* compiler workaround */ | 
 | 13 | #define _htonl __builtin_bswap32 | 
 | 14 |  | 
 | 15 | static inline void set_dst_mac(struct __sk_buff *skb, char *mac) | 
 | 16 | { | 
 | 17 | 	bpf_skb_store_bytes(skb, 0, mac, ETH_ALEN, 1); | 
 | 18 | } | 
 | 19 |  | 
 | 20 | #define IP_CSUM_OFF (ETH_HLEN + offsetof(struct iphdr, check)) | 
 | 21 | #define TOS_OFF (ETH_HLEN + offsetof(struct iphdr, tos)) | 
 | 22 |  | 
 | 23 | static inline void set_ip_tos(struct __sk_buff *skb, __u8 new_tos) | 
 | 24 | { | 
 | 25 | 	__u8 old_tos = load_byte(skb, TOS_OFF); | 
 | 26 |  | 
 | 27 | 	bpf_l3_csum_replace(skb, IP_CSUM_OFF, htons(old_tos), htons(new_tos), 2); | 
 | 28 | 	bpf_skb_store_bytes(skb, TOS_OFF, &new_tos, sizeof(new_tos), 0); | 
 | 29 | } | 
 | 30 |  | 
 | 31 | #define TCP_CSUM_OFF (ETH_HLEN + sizeof(struct iphdr) + offsetof(struct tcphdr, check)) | 
 | 32 | #define IP_SRC_OFF (ETH_HLEN + offsetof(struct iphdr, saddr)) | 
 | 33 |  | 
 | 34 | #define IS_PSEUDO 0x10 | 
 | 35 |  | 
 | 36 | static inline void set_tcp_ip_src(struct __sk_buff *skb, __u32 new_ip) | 
 | 37 | { | 
 | 38 | 	__u32 old_ip = _htonl(load_word(skb, IP_SRC_OFF)); | 
 | 39 |  | 
 | 40 | 	bpf_l4_csum_replace(skb, TCP_CSUM_OFF, old_ip, new_ip, IS_PSEUDO | sizeof(new_ip)); | 
 | 41 | 	bpf_l3_csum_replace(skb, IP_CSUM_OFF, old_ip, new_ip, sizeof(new_ip)); | 
 | 42 | 	bpf_skb_store_bytes(skb, IP_SRC_OFF, &new_ip, sizeof(new_ip), 0); | 
 | 43 | } | 
 | 44 |  | 
 | 45 | #define TCP_DPORT_OFF (ETH_HLEN + sizeof(struct iphdr) + offsetof(struct tcphdr, dest)) | 
 | 46 | static inline void set_tcp_dest_port(struct __sk_buff *skb, __u16 new_port) | 
 | 47 | { | 
 | 48 | 	__u16 old_port = htons(load_half(skb, TCP_DPORT_OFF)); | 
 | 49 |  | 
 | 50 | 	bpf_l4_csum_replace(skb, TCP_CSUM_OFF, old_port, new_port, sizeof(new_port)); | 
 | 51 | 	bpf_skb_store_bytes(skb, TCP_DPORT_OFF, &new_port, sizeof(new_port), 0); | 
 | 52 | } | 
 | 53 |  | 
 | 54 | SEC("classifier") | 
 | 55 | int bpf_prog1(struct __sk_buff *skb) | 
 | 56 | { | 
 | 57 | 	__u8 proto = load_byte(skb, ETH_HLEN + offsetof(struct iphdr, protocol)); | 
 | 58 | 	long *value; | 
 | 59 |  | 
 | 60 | 	if (proto == IPPROTO_TCP) { | 
 | 61 | 		set_ip_tos(skb, 8); | 
 | 62 | 		set_tcp_ip_src(skb, 0xA010101); | 
 | 63 | 		set_tcp_dest_port(skb, 5001); | 
 | 64 | 	} | 
 | 65 |  | 
 | 66 | 	return 0; | 
 | 67 | } | 
 | 68 | SEC("redirect_xmit") | 
 | 69 | int _redirect_xmit(struct __sk_buff *skb) | 
 | 70 | { | 
 | 71 | 	return bpf_redirect(skb->ifindex + 1, 0); | 
 | 72 | } | 
 | 73 | SEC("redirect_recv") | 
 | 74 | int _redirect_recv(struct __sk_buff *skb) | 
 | 75 | { | 
 | 76 | 	return bpf_redirect(skb->ifindex + 1, 1); | 
 | 77 | } | 
 | 78 | SEC("clone_redirect_xmit") | 
 | 79 | int _clone_redirect_xmit(struct __sk_buff *skb) | 
 | 80 | { | 
 | 81 | 	bpf_clone_redirect(skb, skb->ifindex + 1, 0); | 
 | 82 | 	return TC_ACT_SHOT; | 
 | 83 | } | 
 | 84 | SEC("clone_redirect_recv") | 
 | 85 | int _clone_redirect_recv(struct __sk_buff *skb) | 
 | 86 | { | 
 | 87 | 	bpf_clone_redirect(skb, skb->ifindex + 1, 1); | 
 | 88 | 	return TC_ACT_SHOT; | 
 | 89 | } | 
 | 90 | char _license[] SEC("license") = "GPL"; |