int connect_v4_prog(struct bpf_sock_addr *ctx) { struct sockaddr_in sa; /* Rewrite destination. */ ctx->user_ip4 = bpf_htonl(DST_REWRITE_IP4); ctx->user_port = bpf_htons(DST_REWRITE_PORT4); if (ctx->type == SOCK_DGRAM || ctx->type == SOCK_STREAM) { ///* Rewrite source. */ memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = bpf_htons(0); sa.sin_addr.s_addr = bpf_htonl(SRC_REWRITE_IP4); if (bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa)) != 0) return 0; } return 1; }
#include <bpf/libbpf.h> #include "test_iptunnel_common.h" #include "bpf_util.h" #include "bpf_endian.h" static int error_cnt, pass_cnt; #define MAGIC_BYTES 123 /* ipv4 test vector */ static struct { struct ethhdr eth; struct iphdr iph; struct tcphdr tcp; } __packed pkt_v4 = { .eth.h_proto = bpf_htons(ETH_P_IP), .iph.ihl = 5, .iph.protocol = 6, .iph.tot_len = bpf_htons(MAGIC_BYTES), .tcp.urg_ptr = 123, }; /* ipv6 test vector */ static struct { struct ethhdr eth; struct ipv6hdr iph; struct tcphdr tcp; } __packed pkt_v6 = { .eth.h_proto = bpf_htons(ETH_P_IPV6), .iph.nexthdr = 6, .iph.payload_len = bpf_htons(MAGIC_BYTES),
static int handle_rx(void *skb, struct metadata *md) { struct __sk_buff *skb2 = (struct __sk_buff *)skb; void *data = (void *)(long)skb2->data; void *data_end = (void *)(long)skb2->data_end; struct eth_hdr *eth = data; if (data + sizeof(*eth) > data_end) return RX_DROP; u32 in_ifc = md->in_ifc; #ifdef BPF_TRACE bpf_trace_printk("[switch-%d]: in_ifc=%d\n", md->module_id, in_ifc); #endif // port security on source mac #ifdef MAC_SECURITY_INGRESS __be64 *mac_lookup = securitymac.lookup(&in_ifc); if (mac_lookup) if (eth->src != *mac_lookup) { #ifdef BPF_TRACE bpf_trace_printk("[switch-%d]: mac INGRESS %lx mismatch %lx -> DROP\n", md->module_id, PRINT_MAC(eth->src), PRINT_MAC(*mac_lookup)); #endif return RX_DROP; } #endif // port security on source ip #ifdef IP_SECURITY_INGRESS if (eth->proto == bpf_htons(ETH_P_IP)) { __be32 *ip_lookup = securityip.lookup(&in_ifc); if (ip_lookup) { struct ip_t *ip = data + sizeof(*eth); if (data + sizeof(*eth) + sizeof(*ip) > data_end) return RX_DROP; if (ip->src != *ip_lookup) { #ifdef BPF_TRACE bpf_trace_printk("[switch-%d]: IP INGRESS %x mismatch %x -> DROP\n", md->module_id, bpf_htonl(ip->src), bpf_htonl(*ip_lookup)); #endif return RX_DROP; } } } #endif #ifdef BPF_TRACE bpf_trace_printk("[switch-%d]: mac src:%lx dst:%lx\n", md->module_id, PRINT_MAC(eth->src), PRINT_MAC(eth->dst)); #endif //LEARNING PHASE: mapping in_ifc with src_interface __be64 src_key = eth->src; //lookup in fwdtable. if no key present initialize with interface u32 *interface_lookup = fwdtable.lookup_or_init(&src_key, &in_ifc); //if the same mac has changed interface, update it if (*interface_lookup != in_ifc) *interface_lookup = in_ifc; //FORWARDING PHASE: select interface(s) to send the packet __be64 dst_mac = eth->dst; //lookup in forwarding table fwdtable u32 *dst_interface = fwdtable.lookup(&dst_mac); if (dst_interface) { //HIT in forwarding table //redirect packet to dst_interface #ifdef MAC_SECURITY_EGRESS u32 out_iface = *dst_interface; __be64 *mac_lookup = securitymac.lookup(&out_iface); if (mac_lookup) if (eth->dst != *mac_lookup){ #ifdef BPF_TRACE bpf_trace_printk("[switch-%d]: mac EGRESS %lx mismatch %lx -> DROP\n", md->module_id, PRINT_MAC(eth->dst), PRINT_MAC(*mac_lookup)); #endif return RX_DROP; } #endif /* do not send packet back on the ingress interface */ if (*dst_interface == in_ifc) return RX_DROP; pkt_redirect(skb, md, *dst_interface); #ifdef BPF_TRACE bpf_trace_printk("[switch-%d]: redirect out_ifc=%d\n", md->module_id, *dst_interface); #endif return RX_REDIRECT; } else { #ifdef BPF_TRACE bpf_trace_printk("[switch-%d]: Broadcast\n", md->module_id); #endif pkt_controller(skb, md, PKT_BROADCAST); return RX_CONTROLLER; } }