|
Packit Service |
dff8e4 |
/*
|
|
Packit Service |
dff8e4 |
* eBPF filter for IPv4 Address Conflict Detection
|
|
Packit Service |
dff8e4 |
*
|
|
Packit Service |
dff8e4 |
* An eBPF map and an eBPF program are provided. The map contains all the
|
|
Packit Service |
dff8e4 |
* addresses address conflict detection is performed on, and the program
|
|
Packit Service |
dff8e4 |
* filters out all packets except exactly the packets relevant to the ACD
|
|
Packit Service |
dff8e4 |
* protocol on the addresses currently in the map.
|
|
Packit Service |
dff8e4 |
*
|
|
Packit Service |
dff8e4 |
* Note that userspace still has to filter the incoming packets, as filter
|
|
Packit Service |
dff8e4 |
* are applied when packets are queued on the socket, not when userspace
|
|
Packit Service |
dff8e4 |
* receives them. It is therefore possible to receive packets about addresses
|
|
Packit Service |
dff8e4 |
* that have already been removed.
|
|
Packit Service |
dff8e4 |
*/
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
#include <c-stdaux.h>
|
|
Packit Service |
dff8e4 |
#include <errno.h>
|
|
Packit Service |
dff8e4 |
#include <inttypes.h>
|
|
Packit Service |
dff8e4 |
#include <linux/bpf.h>
|
|
Packit Service |
dff8e4 |
#include <netinet/if_ether.h>
|
|
Packit Service |
dff8e4 |
#include <netinet/in.h>
|
|
Packit Service |
dff8e4 |
#include <stdlib.h>
|
|
Packit Service |
dff8e4 |
#include <string.h>
|
|
Packit Service |
dff8e4 |
#include <sys/resource.h>
|
|
Packit Service |
dff8e4 |
#include <sys/syscall.h>
|
|
Packit Service |
dff8e4 |
#include <unistd.h>
|
|
Packit Service |
dff8e4 |
#include "n-acd-private.h"
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
#define BPF_LD_ABS(SIZE, IMM) \
|
|
Packit Service |
dff8e4 |
((struct bpf_insn) { \
|
|
Packit Service |
dff8e4 |
.code = BPF_LD | BPF_SIZE(SIZE) | BPF_ABS, \
|
|
Packit Service |
dff8e4 |
.dst_reg = 0, \
|
|
Packit Service |
dff8e4 |
.src_reg = 0, \
|
|
Packit Service |
dff8e4 |
.off = 0, \
|
|
Packit Service |
dff8e4 |
.imm = IMM, \
|
|
Packit Service |
dff8e4 |
})
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
#define BPF_LDX_MEM(SIZE, DST, SRC, OFF) \
|
|
Packit Service |
dff8e4 |
((struct bpf_insn) { \
|
|
Packit Service |
dff8e4 |
.code = BPF_LDX | BPF_SIZE(SIZE) | BPF_MEM, \
|
|
Packit Service |
dff8e4 |
.dst_reg = DST, \
|
|
Packit Service |
dff8e4 |
.src_reg = SRC, \
|
|
Packit Service |
dff8e4 |
.off = OFF, \
|
|
Packit Service |
dff8e4 |
.imm = 0, \
|
|
Packit Service |
dff8e4 |
})
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
#define BPF_LD_MAP_FD(DST, MAP_FD) \
|
|
Packit Service |
dff8e4 |
((struct bpf_insn) { \
|
|
Packit Service |
dff8e4 |
.code = BPF_LD | BPF_DW | BPF_IMM, \
|
|
Packit Service |
dff8e4 |
.dst_reg = DST, \
|
|
Packit Service |
dff8e4 |
.src_reg = BPF_PSEUDO_MAP_FD, \
|
|
Packit Service |
dff8e4 |
.off = 0, \
|
|
Packit Service |
dff8e4 |
.imm = (__u32) (MAP_FD), \
|
|
Packit Service |
dff8e4 |
}), \
|
|
Packit Service |
dff8e4 |
((struct bpf_insn) { \
|
|
Packit Service |
dff8e4 |
.code = 0, /* zero is reserved opcode */ \
|
|
Packit Service |
dff8e4 |
.dst_reg = 0, \
|
|
Packit Service |
dff8e4 |
.src_reg = 0, \
|
|
Packit Service |
dff8e4 |
.off = 0, \
|
|
Packit Service |
dff8e4 |
.imm = ((__u64) (MAP_FD)) >> 32, \
|
|
Packit Service |
dff8e4 |
})
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
#define BPF_ALU_REG(OP, DST, SRC) \
|
|
Packit Service |
dff8e4 |
((struct bpf_insn) { \
|
|
Packit Service |
dff8e4 |
.code = BPF_ALU64 | BPF_OP(OP) | BPF_X, \
|
|
Packit Service |
dff8e4 |
.dst_reg = DST, \
|
|
Packit Service |
dff8e4 |
.src_reg = SRC, \
|
|
Packit Service |
dff8e4 |
.off = 0, \
|
|
Packit Service |
dff8e4 |
.imm = 0, \
|
|
Packit Service |
dff8e4 |
})
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
#define BPF_ALU_IMM(OP, DST, IMM) \
|
|
Packit Service |
dff8e4 |
((struct bpf_insn) { \
|
|
Packit Service |
dff8e4 |
.code = BPF_ALU64 | BPF_OP(OP) | BPF_K, \
|
|
Packit Service |
dff8e4 |
.dst_reg = DST, \
|
|
Packit Service |
dff8e4 |
.src_reg = 0, \
|
|
Packit Service |
dff8e4 |
.off = 0, \
|
|
Packit Service |
dff8e4 |
.imm = IMM, \
|
|
Packit Service |
dff8e4 |
})
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
#define BPF_MOV_REG(DST, SRC) \
|
|
Packit Service |
dff8e4 |
((struct bpf_insn) { \
|
|
Packit Service |
dff8e4 |
.code = BPF_ALU64 | BPF_MOV | BPF_X, \
|
|
Packit Service |
dff8e4 |
.dst_reg = DST, \
|
|
Packit Service |
dff8e4 |
.src_reg = SRC, \
|
|
Packit Service |
dff8e4 |
.off = 0, \
|
|
Packit Service |
dff8e4 |
.imm = 0, \
|
|
Packit Service |
dff8e4 |
})
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
#define BPF_MOV_IMM(DST, IMM) \
|
|
Packit Service |
dff8e4 |
((struct bpf_insn) { \
|
|
Packit Service |
dff8e4 |
.code = BPF_ALU64 | BPF_MOV | BPF_K, \
|
|
Packit Service |
dff8e4 |
.dst_reg = DST, \
|
|
Packit Service |
dff8e4 |
.src_reg = 0, \
|
|
Packit Service |
dff8e4 |
.off = 0, \
|
|
Packit Service |
dff8e4 |
.imm = IMM, \
|
|
Packit Service |
dff8e4 |
})
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
#define BPF_STX_MEM(SIZE, DST, SRC, OFF) \
|
|
Packit Service |
dff8e4 |
((struct bpf_insn) { \
|
|
Packit Service |
dff8e4 |
.code = BPF_STX | BPF_SIZE(SIZE) | BPF_MEM, \
|
|
Packit Service |
dff8e4 |
.dst_reg = DST, \
|
|
Packit Service |
dff8e4 |
.src_reg = SRC, \
|
|
Packit Service |
dff8e4 |
.off = OFF, \
|
|
Packit Service |
dff8e4 |
.imm = 0, \
|
|
Packit Service |
dff8e4 |
})
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
#define BPF_JMP_REG(OP, DST, SRC, OFF) \
|
|
Packit Service |
dff8e4 |
((struct bpf_insn) { \
|
|
Packit Service |
dff8e4 |
.code = BPF_JMP | BPF_OP(OP) | BPF_X, \
|
|
Packit Service |
dff8e4 |
.dst_reg = DST, \
|
|
Packit Service |
dff8e4 |
.src_reg = SRC, \
|
|
Packit Service |
dff8e4 |
.off = OFF, \
|
|
Packit Service |
dff8e4 |
.imm = 0, \
|
|
Packit Service |
dff8e4 |
})
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
#define BPF_JMP_IMM(OP, DST, IMM, OFF) \
|
|
Packit Service |
dff8e4 |
((struct bpf_insn) { \
|
|
Packit Service |
dff8e4 |
.code = BPF_JMP | BPF_OP(OP) | BPF_K, \
|
|
Packit Service |
dff8e4 |
.dst_reg = DST, \
|
|
Packit Service |
dff8e4 |
.src_reg = 0, \
|
|
Packit Service |
dff8e4 |
.off = OFF, \
|
|
Packit Service |
dff8e4 |
.imm = IMM, \
|
|
Packit Service |
dff8e4 |
})
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
#define BPF_EMIT_CALL(FUNC) \
|
|
Packit Service |
dff8e4 |
((struct bpf_insn) { \
|
|
Packit Service |
dff8e4 |
.code = BPF_JMP | BPF_CALL, \
|
|
Packit Service |
dff8e4 |
.dst_reg = 0, \
|
|
Packit Service |
dff8e4 |
.src_reg = 0, \
|
|
Packit Service |
dff8e4 |
.off = 0, \
|
|
Packit Service |
dff8e4 |
.imm = FUNC, \
|
|
Packit Service |
dff8e4 |
})
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
#define BPF_EXIT_INSN() \
|
|
Packit Service |
dff8e4 |
((struct bpf_insn) { \
|
|
Packit Service |
dff8e4 |
.code = BPF_JMP | BPF_EXIT, \
|
|
Packit Service |
dff8e4 |
.dst_reg = 0, \
|
|
Packit Service |
dff8e4 |
.src_reg = 0, \
|
|
Packit Service |
dff8e4 |
.off = 0, \
|
|
Packit Service |
dff8e4 |
.imm = 0, \
|
|
Packit Service |
dff8e4 |
})
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
static int n_acd_syscall_bpf(int cmd, union bpf_attr *attr, unsigned int size) {
|
|
Packit Service |
dff8e4 |
return (int)syscall(__NR_bpf, cmd, attr, size);
|
|
Packit Service |
dff8e4 |
}
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
int n_acd_bpf_map_create(int *mapfdp, size_t max_entries) {
|
|
Packit Service |
dff8e4 |
union bpf_attr attr;
|
|
Packit Service |
dff8e4 |
int mapfd;
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
memset(&attr, 0, sizeof(attr));
|
|
Packit Service |
dff8e4 |
attr = (union bpf_attr){
|
|
Packit Service |
dff8e4 |
.map_type = BPF_MAP_TYPE_HASH,
|
|
Packit Service |
dff8e4 |
.key_size = sizeof(uint32_t),
|
|
Packit Service |
dff8e4 |
.value_size = sizeof(uint8_t), /* values are never used, but must be set */
|
|
Packit Service |
dff8e4 |
.max_entries = max_entries,
|
|
Packit Service |
dff8e4 |
};
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
mapfd = n_acd_syscall_bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
|
|
Packit Service |
dff8e4 |
if (mapfd < 0)
|
|
Packit Service |
dff8e4 |
return -errno;
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
*mapfdp = mapfd;
|
|
Packit Service |
dff8e4 |
return 0;
|
|
Packit Service |
dff8e4 |
}
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
int n_acd_bpf_map_add(int mapfd, struct in_addr *addrp) {
|
|
Packit Service |
dff8e4 |
union bpf_attr attr;
|
|
Packit Service |
dff8e4 |
uint32_t addr = be32toh(addrp->s_addr);
|
|
Packit Service |
dff8e4 |
uint8_t _dummy = 0;
|
|
Packit Service |
dff8e4 |
int r;
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
memset(&attr, 0, sizeof(attr));
|
|
Packit Service |
dff8e4 |
attr = (union bpf_attr){
|
|
Packit Service |
dff8e4 |
.map_fd = mapfd,
|
|
Packit Service |
dff8e4 |
.key = (uint64_t)(unsigned long)&addr,
|
|
Packit Service |
dff8e4 |
.value = (uint64_t)(unsigned long)&_dummy,
|
|
Packit Service |
dff8e4 |
.flags = BPF_NOEXIST,
|
|
Packit Service |
dff8e4 |
};
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
r = n_acd_syscall_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
|
|
Packit Service |
dff8e4 |
if (r < 0)
|
|
Packit Service |
dff8e4 |
return -errno;
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
return 0;
|
|
Packit Service |
dff8e4 |
}
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
int n_acd_bpf_map_remove(int mapfd, struct in_addr *addrp) {
|
|
Packit Service |
dff8e4 |
uint32_t addr = be32toh(addrp->s_addr);
|
|
Packit Service |
dff8e4 |
union bpf_attr attr;
|
|
Packit Service |
dff8e4 |
int r;
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
memset(&attr, 0, sizeof(attr));
|
|
Packit Service |
dff8e4 |
attr = (union bpf_attr){
|
|
Packit Service |
dff8e4 |
.map_fd = mapfd,
|
|
Packit Service |
dff8e4 |
.key = (uint64_t)(unsigned long)&addr,
|
|
Packit Service |
dff8e4 |
};
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
r = n_acd_syscall_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
|
|
Packit Service |
dff8e4 |
if (r < 0)
|
|
Packit Service |
dff8e4 |
return -errno;
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
return 0;
|
|
Packit Service |
dff8e4 |
}
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
int n_acd_bpf_compile(int *progfdp, int mapfd, struct ether_addr *macp) {
|
|
Packit Service |
dff8e4 |
const union {
|
|
Packit Service |
dff8e4 |
uint8_t u8[6];
|
|
Packit Service |
dff8e4 |
uint16_t u16[3];
|
|
Packit Service |
dff8e4 |
uint32_t u32[1];
|
|
Packit Service |
dff8e4 |
} mac = {
|
|
Packit Service |
dff8e4 |
.u8 = {
|
|
Packit Service |
dff8e4 |
macp->ether_addr_octet[0],
|
|
Packit Service |
dff8e4 |
macp->ether_addr_octet[1],
|
|
Packit Service |
dff8e4 |
macp->ether_addr_octet[2],
|
|
Packit Service |
dff8e4 |
macp->ether_addr_octet[3],
|
|
Packit Service |
dff8e4 |
macp->ether_addr_octet[4],
|
|
Packit Service |
dff8e4 |
macp->ether_addr_octet[5],
|
|
Packit Service |
dff8e4 |
},
|
|
Packit Service |
dff8e4 |
};
|
|
Packit Service |
dff8e4 |
struct bpf_insn prog[] = {
|
|
Packit Service |
dff8e4 |
/* for using BPF_LD_ABS r6 must point to the skb, currently in r1 */
|
|
Packit Service |
dff8e4 |
BPF_MOV_REG(6, 1), /* r6 = r1 */
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
/* drop the packet if it is too short */
|
|
Packit Service |
dff8e4 |
BPF_LDX_MEM(BPF_W, 0, 6, offsetof(struct __sk_buff, len)), /* r0 = skb->len */
|
|
Packit Service |
dff8e4 |
BPF_JMP_IMM(BPF_JGE, 0, sizeof(struct ether_arp), 2), /* if (r0 >= sizeof(ether_arp)) skip 2 */
|
|
Packit Service |
dff8e4 |
BPF_MOV_IMM(0, 0), /* r0 = 0 */
|
|
Packit Service |
dff8e4 |
BPF_EXIT_INSN(), /* return */
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
/* drop the packet if the header is not as expected */
|
|
Packit Service |
dff8e4 |
BPF_LD_ABS(BPF_H, offsetof(struct ether_arp, arp_hrd)), /* r0 = header type */
|
|
Packit Service |
dff8e4 |
BPF_JMP_IMM(BPF_JEQ, 0, ARPHRD_ETHER, 2), /* if (r0 == ethernet) skip 2 */
|
|
Packit Service |
dff8e4 |
BPF_MOV_IMM(0, 0), /* r0 = 0 */
|
|
Packit Service |
dff8e4 |
BPF_EXIT_INSN(), /* return */
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
BPF_LD_ABS(BPF_H, offsetof(struct ether_arp, arp_pro)), /* r0 = protocol */
|
|
Packit Service |
dff8e4 |
BPF_JMP_IMM(BPF_JEQ, 0, ETHERTYPE_IP, 2), /* if (r0 == IP) skip 2 */
|
|
Packit Service |
dff8e4 |
BPF_MOV_IMM(0, 0), /* r0 = 0 */
|
|
Packit Service |
dff8e4 |
BPF_EXIT_INSN(), /* return */
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
BPF_LD_ABS(BPF_B, offsetof(struct ether_arp, arp_hln)), /* r0 = hw addr length */
|
|
Packit Service |
dff8e4 |
BPF_JMP_IMM(BPF_JEQ, 0, sizeof(struct ether_addr), 2), /* if (r0 == sizeof(ether_addr)) skip 2 */
|
|
Packit Service |
dff8e4 |
BPF_MOV_IMM(0, 0), /* r0 = 0 */
|
|
Packit Service |
dff8e4 |
BPF_EXIT_INSN(), /* return */
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
BPF_LD_ABS(BPF_B, offsetof(struct ether_arp, arp_pln)), /* r0 = protocol addr length */
|
|
Packit Service |
dff8e4 |
BPF_JMP_IMM(BPF_JEQ, 0, sizeof(struct in_addr), 2), /* if (r0 == sizeof(in_addr)) skip 2 */
|
|
Packit Service |
dff8e4 |
BPF_MOV_IMM(0, 0), /* r0 = 0 */
|
|
Packit Service |
dff8e4 |
BPF_EXIT_INSN(), /* return */
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
/* drop packets from our own mac address */
|
|
Packit Service |
dff8e4 |
BPF_LD_ABS(BPF_W, offsetof(struct ether_arp, arp_sha)), /* r0 = first four bytes of packet mac address */
|
|
Packit Service |
dff8e4 |
BPF_JMP_IMM(BPF_JNE, 0, be32toh(mac.u32[0]), 4), /* if (r0 != first four bytes of our mac address) skip 4 */
|
|
Packit Service |
dff8e4 |
BPF_LD_ABS(BPF_H, offsetof(struct ether_arp, arp_sha) + 4), /* r0 = last two bytes of packet mac address */
|
|
Packit Service |
dff8e4 |
BPF_JMP_IMM(BPF_JNE, 0, be16toh(mac.u16[2]), 2), /* if (r0 != last two bytes of our mac address) skip 2 */
|
|
Packit Service |
dff8e4 |
BPF_MOV_IMM(0, 0), /* r0 = 0 */
|
|
Packit Service |
dff8e4 |
BPF_EXIT_INSN(), /* return */
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
/*
|
|
Packit Service |
dff8e4 |
* We listen for two kinds of packets:
|
|
Packit Service |
dff8e4 |
* Conflicts)
|
|
Packit Service |
dff8e4 |
* These are requests or replies with the sender address not set to INADDR_ANY. The
|
|
Packit Service |
dff8e4 |
* conflicted address is the sender address, remember this in r7.
|
|
Packit Service |
dff8e4 |
* Probes)
|
|
Packit Service |
dff8e4 |
* These are requests with the sender address set to INADDR_ANY. The probed address
|
|
Packit Service |
dff8e4 |
* is the target address, remember this in r7.
|
|
Packit Service |
dff8e4 |
* Any other packets are dropped.
|
|
Packit Service |
dff8e4 |
*/
|
|
Packit Service |
dff8e4 |
BPF_LD_ABS(BPF_W, offsetof(struct ether_arp, arp_spa)), /* r0 = sender ip address */
|
|
Packit Service |
dff8e4 |
BPF_JMP_IMM(BPF_JEQ, 0, 0, 7), /* if (r0 == 0) skip 7 */
|
|
Packit Service |
dff8e4 |
BPF_MOV_REG(7, 0), /* r7 = r0 */
|
|
Packit Service |
dff8e4 |
BPF_LD_ABS(BPF_H, offsetof(struct ether_arp, arp_op)), /* r0 = operation */
|
|
Packit Service |
dff8e4 |
BPF_JMP_IMM(BPF_JEQ, 0, ARPOP_REQUEST, 3), /* if (r0 == request) skip 3 */
|
|
Packit Service |
dff8e4 |
BPF_JMP_IMM(BPF_JEQ, 0, ARPOP_REPLY, 2), /* if (r0 == reply) skip 2 */
|
|
Packit Service |
dff8e4 |
BPF_MOV_IMM(0, 0), /* r0 = 0 */
|
|
Packit Service |
dff8e4 |
BPF_EXIT_INSN(), /* return */
|
|
Packit Service |
dff8e4 |
BPF_JMP_IMM(BPF_JA, 0, 0, 6), /* skip 6 */
|
|
Packit Service |
dff8e4 |
BPF_LD_ABS(BPF_W, offsetof(struct ether_arp, arp_tpa)), /* r0 = target ip address */
|
|
Packit Service |
dff8e4 |
BPF_MOV_REG(7, 0), /* r7 = r0 */
|
|
Packit Service |
dff8e4 |
BPF_LD_ABS(BPF_H, offsetof(struct ether_arp, arp_op)), /* r0 = operation */
|
|
Packit Service |
dff8e4 |
BPF_JMP_IMM(BPF_JEQ, 0, ARPOP_REQUEST, 2), /* if (r0 == request) skip 2 */
|
|
Packit Service |
dff8e4 |
BPF_MOV_IMM(0, 0), /* r0 = 0 */
|
|
Packit Service |
dff8e4 |
BPF_EXIT_INSN(), /* return */
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
/* check if the probe or conflict is for an address we are monitoring */
|
|
Packit Service |
dff8e4 |
BPF_STX_MEM(BPF_W, 10, 7, -4), /* *(uint32_t*)fp - 4 = r7 */
|
|
Packit Service |
dff8e4 |
BPF_MOV_REG(2, 10), /* r2 = fp */
|
|
Packit Service |
dff8e4 |
BPF_ALU_IMM(BPF_ADD, 2, -4), /* r2 -= 4 */
|
|
Packit Service |
dff8e4 |
BPF_LD_MAP_FD(1, mapfd), /* r1 = mapfd */
|
|
Packit Service |
dff8e4 |
BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), /* r0 = map_lookup_elem(r1, r2) */
|
|
Packit Service |
dff8e4 |
BPF_JMP_IMM(BPF_JNE, 0, 0, 2), /* if (r0 != NULL) skip 2 */
|
|
Packit Service |
dff8e4 |
BPF_MOV_IMM(0, 0), /* r0 = 0 */
|
|
Packit Service |
dff8e4 |
BPF_EXIT_INSN(), /* return */
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
/* return exactly the packet length*/
|
|
Packit Service |
dff8e4 |
BPF_MOV_IMM(0, sizeof(struct ether_arp)), /* r0 = sizeof(struct ether_arp) */
|
|
Packit Service |
dff8e4 |
BPF_EXIT_INSN(), /* return */
|
|
Packit Service |
dff8e4 |
};
|
|
Packit Service |
dff8e4 |
union bpf_attr attr;
|
|
Packit Service |
dff8e4 |
int progfd;
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
memset(&attr, 0, sizeof(attr));
|
|
Packit Service |
dff8e4 |
attr = (union bpf_attr){
|
|
Packit Service |
dff8e4 |
.prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
|
|
Packit Service |
dff8e4 |
.insns = (uint64_t)(unsigned long)prog,
|
|
Packit Service |
dff8e4 |
.insn_cnt = sizeof(prog) / sizeof(*prog),
|
|
Packit Service |
dff8e4 |
.license = (uint64_t)(unsigned long)"ASL",
|
|
Packit Service |
dff8e4 |
};
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
progfd = n_acd_syscall_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
|
|
Packit Service |
dff8e4 |
if (progfd < 0)
|
|
Packit Service |
dff8e4 |
return -errno;
|
|
Packit Service |
dff8e4 |
|
|
Packit Service |
dff8e4 |
*progfdp = progfd;
|
|
Packit Service |
dff8e4 |
return 0;
|
|
Packit Service |
dff8e4 |
}
|