#include <stdint.h> #include "bpf-sql.h" /* SELECT TGVENDOR,FREQ(UNIPFAGT) WHERE TGVENDOR IN (1,2,3,4) */ static struct bpf_insn bpf_insns[] = { /* C[0] IN (1,2,3,4) */ BPF_STMT(BPF_LD+BPF_ABS, 0), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 1, 0, 4), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 2, 0, 3), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 3, 0, 2), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 4, 0, 1), BPF_STMT(BPF_RET+BPF_K, 0), /* R[0] = C[0] */ BPF_STMT(BPF_ST+BPF_REC, 0), BPF_STMT(BPF_LD+BPF_ABS, 1), BPF_STMT(BPF_ST+BPF_REC, 1), /* R <- G */ BPF_STMT(BPF_MISC+BPF_LDR, 0), /* R[2]++ */ BPF_STMT(BPF_LD+BPF_REC, 2), BPF_STMT(BPF_ALU+BPF_ADD+BPF_K, 1), BPF_STMT(BPF_ST+BPF_REC, 2), /* G <- R */
BPF_STMT(BPF_ALU | BPF_LSH | BPF_K, 8), /* or with X */ BPF_STMT(BPF_ALU | BPF_OR | BPF_X, 0), /* put result into X */ BPF_STMT(BPF_MISC| BPF_TAX, 0), /* * Allow management frames through, this also gives us those * management frames that we sent ourselves with status */ /* load the lower byte of the IEEE 802.11 frame control field */ BPF_STMT(BPF_LD | BPF_B | BPF_IND, 0), /* mask off frame type and version */ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0xF), /* accept frame if it's both 0, fall through otherwise */ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, PASS, 0), /* * TODO: add a bit to radiotap RX flags that indicates * that the sending station is not associated, then * add a filter here that filters on our DA and that flag * to allow us to deauth frames to that bad station. * * For now allow all To DS data frames through. */ /* load the IEEE 802.11 frame control field */ BPF_STMT(BPF_LD | BPF_H | BPF_IND, 0), /* mask off frame type, version and DS status */ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, 0x0F03), /* accept frame if version 0, type 2 and To DS, fall through otherwise */
int lldp_network_bind_raw_socket(int ifindex) { static const struct sock_filter filter[] = { BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ethhdr, h_dest)), /* A <- 4 bytes of destination MAC */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0180c200, 1, 0), /* A != 01:80:c2:00 */ BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ethhdr, h_dest) + 4), /* A <- remaining 2 bytes of destination MAC */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0000, 3, 0), /* A != 00:00 */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x0003, 2, 0), /* A != 00:03 */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x000e, 1, 0), /* A != 00:0e */ BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ethhdr, h_proto)), /* A <- protocol */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_LLDP, 1, 0), /* A != ETHERTYPE_LLDP */ BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */ BPF_STMT(BPF_RET + BPF_K, (uint32_t) -1), /* accept packet */ }; static const struct sock_fprog fprog = { .len = ELEMENTSOF(filter), .filter = (struct sock_filter*) filter, }; struct packet_mreq mreq = { .mr_ifindex = ifindex, .mr_type = PACKET_MR_MULTICAST, .mr_alen = ETH_ALEN, .mr_address = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x00 } }; union sockaddr_union saddrll = { .ll.sll_family = AF_PACKET, .ll.sll_ifindex = ifindex, }; _cleanup_close_ int fd = -1; int r; assert(ifindex > 0); fd = socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC|SOCK_NONBLOCK, htobe16(ETHERTYPE_LLDP)); if (fd < 0) return -errno; r = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); if (r < 0) return -errno; r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); if (r < 0) return -errno; mreq.mr_address[ETH_ALEN - 1] = 0x03; r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); if (r < 0) return -errno; mreq.mr_address[ETH_ALEN - 1] = 0x0E; r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); if (r < 0) return -errno; r = bind(fd, &saddrll.sa, sizeof(saddrll.ll)); if (r < 0) return -errno; r = fd; fd = -1; return r; }
// Since the fake SNP is based on a real NIC, to avoid conflict with the host NIC // network stack, we use a different MAC address. // So just change the last byte of the MAC address for the real NIC. // Mode->CurrentAddress.Addr[NET_ETHER_ADDR_LEN - 1]++; return EFI_SUCCESS; } static struct bpf_insn mFilterInstructionTemplate[] = { // Load 4 bytes from the destination MAC address. BPF_STMT (BPF_LD + BPF_W + BPF_ABS, OFFSET_OF (ETHERNET_HEADER, DstAddr[0])), // Compare to first 4 bytes of fake MAC address. BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0x12345678, 0, 3 ), // Load remaining 2 bytes from the destination MAC address. BPF_STMT (BPF_LD + BPF_H + BPF_ABS, OFFSET_OF( ETHERNET_HEADER, DstAddr[4])), // Compare to remaining 2 bytes of fake MAC address. BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0x9ABC, 5, 0 ), // Load 4 bytes from the destination MAC address. BPF_STMT (BPF_LD + BPF_W + BPF_ABS, OFFSET_OF (ETHERNET_HEADER, DstAddr[0])), // Compare to first 4 bytes of broadcast MAC address. BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0xFFFFFFFF, 0, 2), // Load remaining 2 bytes from the destination MAC address. BPF_STMT (BPF_LD + BPF_H + BPF_ABS, OFFSET_OF( ETHERNET_HEADER, DstAddr[4])),
static int install_filter(void) { struct sock_filter filter[] = { /* Grab the system call number */ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_nr), /* Jump table for the allowed syscalls */ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_rt_sigreturn, 0, 1), BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), #ifdef __NR_sigreturn BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_sigreturn, 0, 1), BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), #endif BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_exit_group, 0, 1), BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_exit, 0, 1), BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_read, 1, 0), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_write, 3, 2), /* Check that read is only using stdin. */ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_arg(0)), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, STDIN_FILENO, 4, 0), BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL), /* Check that write is only using stdout */ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_arg(0)), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, STDOUT_FILENO, 1, 0), /* Trap attempts to write to stderr */ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, STDERR_FILENO, 1, 2), BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP), BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL), }; struct sock_fprog prog = { .len = (unsigned short)(sizeof(filter)/sizeof(filter[0])), .filter = filter, }; if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { perror("prctl(NO_NEW_PRIVS)"); return 1; } if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { perror("prctl"); return 1; } return 0; } #define payload(_c) (_c), sizeof((_c)) int main(int argc, char **argv) { char buf[4096]; ssize_t bytes = 0; if (install_emulator()) return 1; if (install_filter()) return 1; syscall(__NR_write, STDOUT_FILENO, payload("OHAI! WHAT IS YOUR NAME? ")); bytes = syscall(__NR_read, STDIN_FILENO, buf, sizeof(buf)); syscall(__NR_write, STDOUT_FILENO, payload("HELLO, ")); syscall(__NR_write, STDOUT_FILENO, buf, bytes); syscall(__NR_write, STDERR_FILENO, payload("Error message going to STDERR\n")); return 0; }
/* * npfctl_bpf_cidr: code block to match IPv4 or IPv6 CIDR. * * => IP address shall be in the network byte order. */ void npfctl_bpf_cidr(npf_bpf_t *ctx, u_int opts, sa_family_t af, const npf_addr_t *addr, const npf_netmask_t mask) { const uint32_t *awords = (const uint32_t *)addr; u_int nwords, length, maxmask, off; assert(((opts & MATCH_SRC) != 0) ^ ((opts & MATCH_DST) != 0)); assert((mask && mask <= NPF_MAX_NETMASK) || mask == NPF_NO_NETMASK); switch (af) { case AF_INET: maxmask = 32; off = (opts & MATCH_SRC) ? offsetof(struct ip, ip_src) : offsetof(struct ip, ip_dst); nwords = sizeof(struct in_addr) / sizeof(uint32_t); break; case AF_INET6: maxmask = 128; off = (opts & MATCH_SRC) ? offsetof(struct ip6_hdr, ip6_src) : offsetof(struct ip6_hdr, ip6_dst); nwords = sizeof(struct in6_addr) / sizeof(uint32_t); break; default: abort(); } /* Ensure address family. */ fetch_l3(ctx, af, 0); length = (mask == NPF_NO_NETMASK) ? maxmask : mask; /* CAUTION: BPF operates in host byte-order. */ for (u_int i = 0; i < nwords; i++) { const u_int woff = i * sizeof(uint32_t); uint32_t word = ntohl(awords[i]); uint32_t wordmask; if (length >= 32) { /* The mask is a full word - do not apply it. */ wordmask = 0; length -= 32; } else if (length) { wordmask = 0xffffffff << (32 - length); length = 0; } else { /* The mask became zero - skip the rest. */ break; } /* A <- IP address (or one word of it) */ struct bpf_insn insns_ip[] = { BPF_STMT(BPF_LD+BPF_W+BPF_ABS, off + woff), }; add_insns(ctx, insns_ip, __arraycount(insns_ip)); /* A <- (A & MASK) */ if (wordmask) { struct bpf_insn insns_mask[] = { BPF_STMT(BPF_ALU+BPF_AND+BPF_K, wordmask), }; add_insns(ctx, insns_mask, __arraycount(insns_mask)); } /* A == expected-IP-word ? */ struct bpf_insn insns_cmp[] = { BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, word, 0, JUMP_MAGIC), }; add_insns(ctx, insns_cmp, __arraycount(insns_cmp)); } uint32_t mwords[] = { (opts & MATCH_SRC) ? BM_SRC_CIDR: BM_DST_CIDR, 6, af, mask, awords[0], awords[1], awords[2], awords[3], }; done_block(ctx, mwords, sizeof(mwords)); }
static void fetch_l3(npf_bpf_t *ctx, sa_family_t af, u_int flags) { u_int ver; switch (af) { case AF_INET: ver = IPVERSION; break; case AF_INET6: ver = IPV6_VERSION >> 4; break; case AF_UNSPEC: ver = 0; break; default: abort(); } /* * The memory store is populated with: * - BPF_MW_IPVER: IP version (4 or 6). * - BPF_MW_L4OFF: L4 header offset. * - BPF_MW_L4PROTO: L4 protocol. */ if ((ctx->flags & FETCHED_L3) == 0 || (af && ctx->af == 0)) { const uint8_t jt = ver ? 0 : JUMP_MAGIC; const uint8_t jf = ver ? JUMP_MAGIC : 0; bool ingroup = ctx->ingroup; /* * L3 block cannot be inserted in the middle of a group. * In fact, it never is. Check and start the group after. */ if (ingroup) { assert(ctx->nblocks == ctx->gblock); npfctl_bpf_endgroup(ctx); } /* * A <- IP version; A == expected-version? * If no particular version specified, check for non-zero. */ struct bpf_insn insns_af[] = { BPF_STMT(BPF_LD+BPF_W+BPF_MEM, BPF_MW_IPVER), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ver, jt, jf), }; add_insns(ctx, insns_af, __arraycount(insns_af)); ctx->flags |= FETCHED_L3; ctx->af = af; if (af) { uint32_t mwords[] = { BM_IPVER, 1, af }; done_raw_block(ctx, mwords, sizeof(mwords)); } if (ingroup) { npfctl_bpf_group(ctx); } } else if (af && af != ctx->af) { errx(EXIT_FAILURE, "address family mismatch"); } if ((flags & X_EQ_L4OFF) != 0 && (ctx->flags & X_EQ_L4OFF) == 0) { /* X <- IP header length */ struct bpf_insn insns_hlen[] = { BPF_STMT(BPF_LDX+BPF_MEM, BPF_MW_L4OFF), }; add_insns(ctx, insns_hlen, __arraycount(insns_hlen)); ctx->flags |= X_EQ_L4OFF; } }
int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_addr *eth_mac) { struct sock_filter filter[] = { BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), /* A <- packet length */ BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct ether_arp), 1, 0), /* packet >= arp packet ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_hrd)), /* A <- header */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPHRD_ETHER, 1, 0), /* header == ethernet ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_pro)), /* A <- protocol */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 1, 0), /* protocol == IP ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_hln)), /* A <- hardware address length */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, sizeof(struct ether_addr), 1, 0), /* length == sizeof(ether_addr)? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_pln)), /* A <- protocol address length */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, sizeof(struct in_addr), 1, 0), /* length == sizeof(in_addr) ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, ea_hdr.ar_op)), /* A <- operation */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REQUEST, 2, 0), /* protocol == request ? */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ARPOP_REPLY, 1, 0), /* protocol == reply ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ /* Sender Hardware Address must be different from our own */ BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_ne32(ð_mac->ether_addr_octet[0])),/* A <- 4 bytes of client's MAC */ BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_sha)), /* A <- 4 bytes of SHA */ BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 6), /* A == 0 ? */ BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_ne16(ð_mac->ether_addr_octet[4])),/* A <- remainder of client's MAC */ BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(struct ether_arp, arp_sha) + 4), /* A <- remainder of SHA */ BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 1), /* A == 0 ? */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ /* Sender Protocol Address or Target Protocol Address must be equal to the one we care about */ BPF_STMT(BPF_LD + BPF_IMM, htobe32(address)), /* A <- clients IP */ BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_spa)), /* A <- SPA */ BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* X xor A */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 1), /* A == 0 ? */ BPF_STMT(BPF_RET + BPF_K, 65535), /* return all */ BPF_STMT(BPF_LD + BPF_IMM, htobe32(address)), /* A <- clients IP */ BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct ether_arp, arp_tpa)), /* A <- TPA */ BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* X xor A */ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 0, 1), /* A == 0 ? */ BPF_STMT(BPF_RET + BPF_K, 65535), /* return all */ BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */ }; struct sock_fprog fprog = { .len = ELEMENTSOF(filter), .filter = (struct sock_filter*) filter }; union sockaddr_union link = { .ll.sll_family = AF_PACKET, .ll.sll_protocol = htobe16(ETH_P_ARP), .ll.sll_ifindex = ifindex, .ll.sll_halen = ETH_ALEN, .ll.sll_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, }; _cleanup_close_ int s = -1; int r; assert(ifindex > 0); s = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); if (s < 0) return -errno; r = setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); if (r < 0) return -errno; r = bind(s, &link.sa, sizeof(link.ll)); if (r < 0) return -errno; r = s; s = -1; return r; } static int arp_send_packet(int fd, int ifindex, be32_t pa, const struct ether_addr *ha, bool announce) { union sockaddr_union link = { .ll.sll_family = AF_PACKET, .ll.sll_protocol = htobe16(ETH_P_ARP), .ll.sll_ifindex = ifindex, .ll.sll_halen = ETH_ALEN, .ll.sll_addr = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, }; struct ether_arp arp = { .ea_hdr.ar_hrd = htobe16(ARPHRD_ETHER), /* HTYPE */ .ea_hdr.ar_pro = htobe16(ETHERTYPE_IP), /* PTYPE */ .ea_hdr.ar_hln = ETH_ALEN, /* HLEN */ .ea_hdr.ar_pln = sizeof(be32_t), /* PLEN */ .ea_hdr.ar_op = htobe16(ARPOP_REQUEST), /* REQUEST */ }; int r; assert(fd >= 0); assert(pa != 0); assert(ha); memcpy(&arp.arp_sha, ha, ETH_ALEN); memcpy(&arp.arp_tpa, &pa, sizeof(pa)); if (announce) memcpy(&arp.arp_spa, &pa, sizeof(pa)); r = sendto(fd, &arp, sizeof(struct ether_arp), 0, &link.sa, sizeof(link.ll)); if (r < 0) return -errno; return 0; } int arp_send_probe(int fd, int ifindex, be32_t pa, const struct ether_addr *ha) { return arp_send_packet(fd, ifindex, pa, ha, false); } int arp_send_announcement(int fd, int ifindex, be32_t pa, const struct ether_addr *ha) { return arp_send_packet(fd, ifindex, pa, ha, true); }
#include "isisd/isis_constants.h" #include "isisd/isis_common.h" #include "isisd/isis_circuit.h" #include "isisd/isis_flags.h" #include "isisd/isisd.h" #include "isisd/isis_constants.h" #include "isisd/isis_circuit.h" #include "isisd/isis_network.h" #include "privs.h" extern struct zebra_privs_t isisd_privs; struct bpf_insn llcfilter[] = { BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN), /* check first byte */ BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 5), BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 1), BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, ISO_SAP, 0, 3), /* check second byte */ BPF_STMT (BPF_LD + BPF_B + BPF_ABS, ETHER_HDR_LEN + 2), BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0x03, 0, 1), /* check third byte */ BPF_STMT (BPF_RET + BPF_K, (u_int) - 1), BPF_STMT (BPF_RET + BPF_K, 0) }; u_int readblen = 0; u_char *readbuff = NULL; /* * Table 9 - Architectural constants for use with ISO 8802 subnetworks * ISO 10589 - 8.4.8 */
int CapsH_createBPF(char* ifname) { int bpf = 0; int i; char filename[11] = {0}; seteuid(CapsH_euid); for ( i = 0; i < 99; i++ ) { /* make sure we test every bpf file */ sprintf(filename, "/dev/bpf%i", i); bpf = open(filename, O_RDWR); if ( bpf >= 0 ) { printf("opened file: %s\n", filename); struct ifreq bound_if; strcpy(bound_if.ifr_name, ifname); /* attach to given interface */ if ( ioctl(bpf, BIOCSETIF, &bound_if) > 0 ) { printf("Error binding bpf device to %s\n", ifname); perror("interface error"); return -1; } printf("bound bpf to %s\n", ifname); int opt = 1; /* set device to nonblocking */ if( ioctl(bpf, FIONBIO, &opt) == -1 ) { perror("error setting nonblockig BPF\n"); return -1; } /* return immediately when a packet is received */ if( ioctl( bpf, BIOCIMMEDIATE, &opt ) == -1 ) { perror("error setting BIOCIMMEDIATE mode\n"); return -1; } /* get mac address of ifname */ struct ifaddrs *ifap, *ifaptr; uint8_t thishwaddr[6]; uint8_t* ptr; if ( getifaddrs(&ifap) == 0 ) { for ( ifaptr = ifap; ifaptr != NULL; ifaptr = ifaptr->ifa_next ) { if( ((ifaptr)->ifa_addr)->sa_family == AF_LINK ) { if ( strcmp(ifname, ifaptr->ifa_name) == 0 ) { ptr = (uint8_t*)LLADDR((struct sockaddr_dl *)(ifaptr)->ifa_addr); thishwaddr[0] = *ptr; thishwaddr[1] = *(ptr+1); thishwaddr[2] = *(ptr+2); thishwaddr[3] = *(ptr+3); thishwaddr[4] = *(ptr+4); thishwaddr[5] = *(ptr+5); } } } freeifaddrs(ifap); } else { printf("enable to get MAC address of %s\n", ifname); return -1; } /* filter by destination address, then by ether type */ struct bpf_program fcode = {0}; struct bpf_insn insns[] = { BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 0), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, thishwaddr[0], 0, 13), BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 1), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, thishwaddr[1], 0, 11), BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 2), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, thishwaddr[2], 0, 9), BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 3), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, thishwaddr[3], 0, 7), BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 4), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, thishwaddr[4], 0, 5), BPF_STMT(BPF_LD+BPF_B+BPF_ABS, 5), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, thishwaddr[5], 0, 3), /* copy protocol value (byte offset 12 of ether frame) into accumulator register */ BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12), /* If accumulator register is equal to LinkC_eth_proto, execute following return STMT */ /* If not, jump to STMT that returns 0 (drop packet) */ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, LinkC_eth_proto, 0, 1), BPF_STMT(BPF_RET+BPF_K, (u_int)-1), BPF_STMT(BPF_RET+BPF_K, 0), }; /* Set the filter */ fcode.bf_len = sizeof(insns) / sizeof(struct bpf_insn); fcode.bf_insns = &insns[0]; if( ioctl( bpf, BIOCSETF, &fcode ) < 0) { printf("error setting BPF filter\n"); return ( -1 ); } seteuid(CapsH_ruid); printf("bpf = %d\n", bpf); return bpf; } } seteuid(CapsH_ruid); fprintf(stderr, "Error: no bpf files could be opened\n"); return -1; }