version 1.11, 2019/07/30 10:25:03 |
version 1.11.2.2, 2019/10/12 14:44:32 |
Line 410 bpf_cmp_hwaddr(struct bpf_insn *bpf, siz |
|
Line 410 bpf_cmp_hwaddr(struct bpf_insn *bpf, siz |
|
#endif |
#endif |
|
|
#ifdef ARP |
#ifdef ARP |
|
|
static const struct bpf_insn bpf_arp_ether [] = { |
static const struct bpf_insn bpf_arp_ether [] = { |
/* Ensure packet is at least correct size. */ |
|
BPF_STMT(BPF_LD + BPF_W + BPF_LEN, 0), |
|
BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct ether_arp), 1, 0), |
|
BPF_STMT(BPF_RET + BPF_K, 0), |
|
|
|
/* Check this is an ARP packet. */ |
/* Check this is an ARP packet. */ |
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, |
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, |
offsetof(struct ether_header, ether_type)), |
offsetof(struct ether_header, ether_type)), |
Line 552 bpf_arp(struct interface *ifp, int fd) |
|
Line 546 bpf_arp(struct interface *ifp, int fd) |
|
} |
} |
#endif |
#endif |
|
|
#define BPF_M_FHLEN 0 |
#ifdef ARPHRD_NONE |
#define BPF_M_IPHLEN 1 |
static const struct bpf_insn bpf_bootp_none[] = { |
#define BPF_M_IPLEN 2 |
}; |
#define BPF_M_UDP 3 |
#define BPF_BOOTP_NONE_LEN __arraycount(bpf_bootp_none) |
#define BPF_M_UDPLEN 4 |
#endif |
|
|
static const struct bpf_insn bpf_bootp_ether[] = { |
static const struct bpf_insn bpf_bootp_ether[] = { |
/* Make sure this is an IP packet. */ |
/* Make sure this is an IP packet. */ |
Line 565 static const struct bpf_insn bpf_bootp_e |
|
Line 559 static const struct bpf_insn bpf_bootp_e |
|
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 1, 0), |
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 1, 0), |
BPF_STMT(BPF_RET + BPF_K, 0), |
BPF_STMT(BPF_RET + BPF_K, 0), |
|
|
/* Load frame header length into X. */ |
/* Advance to the IP header. */ |
BPF_STMT(BPF_LDX + BPF_W + BPF_IMM, sizeof(struct ether_header)), |
BPF_STMT(BPF_LDX + BPF_K, sizeof(struct ether_header)), |
/* Copy frame header length to memory */ |
|
BPF_STMT(BPF_STX, BPF_M_FHLEN), |
|
}; |
}; |
#define BPF_BOOTP_ETHER_LEN __arraycount(bpf_bootp_ether) |
#define BPF_BOOTP_ETHER_LEN __arraycount(bpf_bootp_ether) |
|
|
|
#define BOOTP_MIN_SIZE sizeof(struct ip) + sizeof(struct udphdr) + \ |
|
sizeof(struct bootp) |
|
|
static const struct bpf_insn bpf_bootp_filter[] = { |
static const struct bpf_insn bpf_bootp_filter[] = { |
/* Make sure it's an IPv4 packet. */ |
/* Make sure it's an IPv4 packet. */ |
BPF_STMT(BPF_LD + BPF_B + BPF_IND, 0), |
BPF_STMT(BPF_LD + BPF_B + BPF_IND, 0), |
Line 579 static const struct bpf_insn bpf_bootp_f |
|
Line 574 static const struct bpf_insn bpf_bootp_f |
|
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x40, 1, 0), |
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0x40, 1, 0), |
BPF_STMT(BPF_RET + BPF_K, 0), |
BPF_STMT(BPF_RET + BPF_K, 0), |
|
|
/* Ensure IP header length is big enough and |
|
* store the IP header length in memory. */ |
|
BPF_STMT(BPF_LD + BPF_B + BPF_IND, 0), |
|
BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0x0f), |
|
BPF_STMT(BPF_ALU + BPF_MUL + BPF_K, 4), |
|
BPF_JUMP(BPF_JMP + BPF_JGE + BPF_K, sizeof(struct ip), 1, 0), |
|
BPF_STMT(BPF_RET + BPF_K, 0), |
|
BPF_STMT(BPF_ST, BPF_M_IPHLEN), |
|
|
|
/* Make sure it's a UDP packet. */ |
/* Make sure it's a UDP packet. */ |
BPF_STMT(BPF_LD + BPF_B + BPF_IND, offsetof(struct ip, ip_p)), |
BPF_STMT(BPF_LD + BPF_B + BPF_IND, offsetof(struct ip, ip_p)), |
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 1, 0), |
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 1, 0), |
Line 598 static const struct bpf_insn bpf_bootp_f |
|
Line 584 static const struct bpf_insn bpf_bootp_f |
|
BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 0, 1), |
BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 0, 1), |
BPF_STMT(BPF_RET + BPF_K, 0), |
BPF_STMT(BPF_RET + BPF_K, 0), |
|
|
/* Store IP length. */ |
|
BPF_STMT(BPF_LD + BPF_H + BPF_IND, offsetof(struct ip, ip_len)), |
|
BPF_STMT(BPF_ST, BPF_M_IPLEN), |
|
|
|
/* Advance to the UDP header. */ |
/* Advance to the UDP header. */ |
BPF_STMT(BPF_LD + BPF_MEM, BPF_M_IPHLEN), |
BPF_STMT(BPF_LD + BPF_B + BPF_IND, 0), |
|
BPF_STMT(BPF_ALU + BPF_AND + BPF_K, 0x0f), |
|
BPF_STMT(BPF_ALU + BPF_MUL + BPF_K, 4), |
BPF_STMT(BPF_ALU + BPF_ADD + BPF_X, 0), |
BPF_STMT(BPF_ALU + BPF_ADD + BPF_X, 0), |
BPF_STMT(BPF_MISC + BPF_TAX, 0), |
BPF_STMT(BPF_MISC + BPF_TAX, 0), |
|
|
/* Store UDP location */ |
|
BPF_STMT(BPF_STX, BPF_M_UDP), |
|
|
|
/* Make sure it's from and to the right port. */ |
/* Make sure it's from and to the right port. */ |
BPF_STMT(BPF_LD + BPF_W + BPF_IND, 0), |
BPF_STMT(BPF_LD + BPF_W + BPF_IND, 0), |
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (BOOTPS << 16) + BOOTPC, 1, 0), |
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (BOOTPS << 16) + BOOTPC, 1, 0), |
BPF_STMT(BPF_RET + BPF_K, 0), |
BPF_STMT(BPF_RET + BPF_K, 0), |
|
|
/* Store UDP length. */ |
|
BPF_STMT(BPF_LD + BPF_H + BPF_IND, offsetof(struct udphdr, uh_ulen)), |
|
BPF_STMT(BPF_ST, BPF_M_UDPLEN), |
|
|
|
/* Ensure that UDP length + IP header length == IP length */ |
|
/* Copy IP header length to X. */ |
|
BPF_STMT(BPF_LDX + BPF_MEM, BPF_M_IPHLEN), |
|
/* Add UDP length (A) to IP header length (X). */ |
|
BPF_STMT(BPF_ALU + BPF_ADD + BPF_X, 0), |
|
/* Store result in X. */ |
|
BPF_STMT(BPF_MISC + BPF_TAX, 0), |
|
/* Copy IP length to A. */ |
|
BPF_STMT(BPF_LD + BPF_MEM, BPF_M_IPLEN), |
|
/* Ensure X == A. */ |
|
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0), |
|
BPF_STMT(BPF_RET + BPF_K, 0), |
|
|
|
/* Advance to the BOOTP packet. */ |
|
BPF_STMT(BPF_LD + BPF_MEM, BPF_M_UDP), |
|
BPF_STMT(BPF_ALU + BPF_ADD + BPF_K, sizeof(struct udphdr)), |
|
BPF_STMT(BPF_MISC + BPF_TAX, 0), |
|
|
|
/* Make sure it's BOOTREPLY. */ |
|
BPF_STMT(BPF_LD + BPF_B + BPF_IND, offsetof(struct bootp, op)), |
|
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, BOOTREPLY, 1, 0), |
|
BPF_STMT(BPF_RET + BPF_K, 0), |
|
}; |
}; |
|
|
#define BPF_BOOTP_FILTER_LEN __arraycount(bpf_bootp_filter) |
#define BPF_BOOTP_FILTER_LEN __arraycount(bpf_bootp_filter) |
Line 665 bpf_bootp(struct interface *ifp, int fd) |
|
Line 619 bpf_bootp(struct interface *ifp, int fd) |
|
bp = bpf; |
bp = bpf; |
/* Check frame header. */ |
/* Check frame header. */ |
switch(ifp->family) { |
switch(ifp->family) { |
|
#ifdef ARPHRD_NONE |
|
case ARPHRD_NONE: |
|
memcpy(bp, bpf_bootp_none, sizeof(bpf_bootp_none)); |
|
bp += BPF_BOOTP_NONE_LEN; |
|
break; |
|
#endif |
case ARPHRD_ETHER: |
case ARPHRD_ETHER: |
memcpy(bp, bpf_bootp_ether, sizeof(bpf_bootp_ether)); |
memcpy(bp, bpf_bootp_ether, sizeof(bpf_bootp_ether)); |
bp += BPF_BOOTP_ETHER_LEN; |
bp += BPF_BOOTP_ETHER_LEN; |
Line 714 bpf_bootp(struct interface *ifp, int fd) |
|
Line 674 bpf_bootp(struct interface *ifp, int fd) |
|
} |
} |
#endif |
#endif |
|
|
/* All passed, return the packet - frame length + ip length */ |
/* All passed, return the packet. */ |
BPF_SET_STMT(bp, BPF_LD + BPF_MEM, BPF_M_FHLEN); |
BPF_SET_STMT(bp, BPF_RET + BPF_K, BPF_WHOLEPACKET); |
bp++; |
|
BPF_SET_STMT(bp, BPF_LDX + BPF_MEM, BPF_M_IPLEN); |
|
bp++; |
|
BPF_SET_STMT(bp, BPF_ALU + BPF_ADD + BPF_X, 0); |
|
bp++; |
|
BPF_SET_STMT(bp, BPF_RET + BPF_A, 0); |
|
bp++; |
bp++; |
|
|
return bpf_attach(fd, bpf, (unsigned int)(bp - bpf)); |
return bpf_attach(fd, bpf, (unsigned int)(bp - bpf)); |