mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-08 21:17:47 +03:00
Merge pull request #21050 from yuwata/network-bpf-cleanups
libsystemd-network: cleanup BPF code
This commit is contained in:
commit
a3e33adfb5
@ -14,7 +14,7 @@
|
||||
#include "unaligned.h"
|
||||
#include "util.h"
|
||||
|
||||
int arp_update_filter(int fd, const struct in_addr *a, const struct ether_addr *eth_mac) {
|
||||
int arp_update_filter(int fd, const struct in_addr *a, const struct ether_addr *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 ? */
|
||||
@ -36,30 +36,22 @@ int arp_update_filter(int fd, const struct in_addr *a, const struct ether_addr *
|
||||
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_be32(ð_mac->ether_addr_octet[0])),/* A <- 4 bytes of client's MAC */
|
||||
BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */
|
||||
BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be32(&mac->ether_addr_octet[0])), /* X <- 4 bytes of client's MAC */
|
||||
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_be16(ð_mac->ether_addr_octet[4])),/* A <- remainder of client's MAC */
|
||||
BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 0, 4), /* A == X ? */
|
||||
BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be16(&mac->ether_addr_octet[4])), /* X <- remainder of client's MAC */
|
||||
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_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 0, 1), /* A == X ? */
|
||||
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(a->s_addr)), /* A <- clients IP */
|
||||
BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */
|
||||
BPF_STMT(BPF_LDX + BPF_IMM, htobe32(a->s_addr)), /* X <- clients IP */
|
||||
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(a->s_addr)), /* A <- clients IP */
|
||||
BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 0, 1), /* A == X ? */
|
||||
BPF_STMT(BPF_RET + BPF_K, UINT32_MAX), /* accept */
|
||||
BPF_STMT(BPF_LDX + BPF_IMM, htobe32(a->s_addr)), /* A <- clients IP */
|
||||
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_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 0, 1), /* A == 0 ? */
|
||||
BPF_STMT(BPF_RET + BPF_K, UINT32_MAX), /* accept */
|
||||
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
|
||||
};
|
||||
struct sock_fprog fprog = {
|
||||
@ -75,7 +67,7 @@ int arp_update_filter(int fd, const struct in_addr *a, const struct ether_addr *
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arp_network_bind_raw_socket(int ifindex, const struct in_addr *a, const struct ether_addr *eth_mac) {
|
||||
int arp_network_bind_raw_socket(int ifindex, const struct in_addr *a, const struct ether_addr *mac) {
|
||||
union sockaddr_union link = {
|
||||
.ll.sll_family = AF_PACKET,
|
||||
.ll.sll_protocol = htobe16(ETH_P_ARP),
|
||||
@ -87,12 +79,13 @@ int arp_network_bind_raw_socket(int ifindex, const struct in_addr *a, const stru
|
||||
int r;
|
||||
|
||||
assert(ifindex > 0);
|
||||
assert(mac);
|
||||
|
||||
s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
|
||||
if (s < 0)
|
||||
return -errno;
|
||||
|
||||
r = arp_update_filter(s, a, eth_mac);
|
||||
r = arp_update_filter(s, a, mac);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -11,8 +11,8 @@
|
||||
#include "socket-util.h"
|
||||
#include "sparse-endian.h"
|
||||
|
||||
int arp_update_filter(int fd, const struct in_addr *a, const struct ether_addr *eth_mac);
|
||||
int arp_network_bind_raw_socket(int ifindex, const struct in_addr *a, const struct ether_addr *eth_mac);
|
||||
int arp_update_filter(int fd, const struct in_addr *a, const struct ether_addr *mac);
|
||||
int arp_network_bind_raw_socket(int ifindex, const struct in_addr *a, const struct ether_addr *mac);
|
||||
|
||||
int arp_send_packet(
|
||||
int fd,
|
||||
|
@ -58,24 +58,20 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
|
||||
|
||||
/* We only support MAC address length to be either 0 or 6 (ETH_ALEN). Optionally
|
||||
* compare chaddr for ETH_ALEN bytes. */
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETH_ALEN, 0, 12), /* A (the MAC address length) == ETH_ALEN ? */
|
||||
BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be32(ð_mac->ether_addr_octet[0])), /* A <- 4 bytes of client's MAC */
|
||||
BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETH_ALEN, 0, 8), /* A (the MAC address length) == ETH_ALEN ? */
|
||||
BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be32(ð_mac->ether_addr_octet[0])), /* X <- 4 bytes of client's MAC */
|
||||
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr)), /* A <- 4 bytes of MAC from dhcp.chaddr */
|
||||
BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0), /* A == X ? */
|
||||
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
|
||||
BPF_STMT(BPF_LD + BPF_IMM, unaligned_read_be16(ð_mac->ether_addr_octet[4])), /* A <- remainder of client's MAC */
|
||||
BPF_STMT(BPF_MISC + BPF_TAX, 0), /* X <- A */
|
||||
BPF_STMT(BPF_LDX + BPF_IMM, unaligned_read_be16(ð_mac->ether_addr_octet[4])), /* X <- remainder of client's MAC */
|
||||
BPF_STMT(BPF_LD + BPF_H + BPF_ABS, offsetof(DHCPPacket, dhcp.chaddr) + 4), /* A <- remainder of MAC from dhcp.chaddr */
|
||||
BPF_STMT(BPF_ALU + BPF_XOR + BPF_X, 0), /* A xor X */
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 1, 0), /* A == 0 ? */
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_X, 0, 1, 0), /* A == X ? */
|
||||
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
|
||||
|
||||
BPF_STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(DHCPPacket, dhcp.magic)), /* A <- DHCP magic cookie */
|
||||
BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, DHCP_MAGIC_COOKIE, 1, 0), /* cookie == DHCP magic cookie ? */
|
||||
BPF_STMT(BPF_RET + BPF_K, 0), /* ignore */
|
||||
BPF_STMT(BPF_RET + BPF_K, 65535), /* return all */
|
||||
BPF_STMT(BPF_RET + BPF_K, UINT32_MAX), /* accept */
|
||||
};
|
||||
struct sock_fprog fprog = {
|
||||
.len = ELEMENTSOF(filter),
|
||||
@ -115,10 +111,17 @@ static int _bind_raw_socket(int ifindex, union sockaddr_union *link,
|
||||
return TAKE_FD(s);
|
||||
}
|
||||
|
||||
int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, uint32_t xid,
|
||||
const uint8_t *mac_addr, size_t mac_addr_len,
|
||||
const uint8_t *bcast_addr, size_t bcast_addr_len,
|
||||
uint16_t arp_type, uint16_t port) {
|
||||
int dhcp_network_bind_raw_socket(
|
||||
int ifindex,
|
||||
union sockaddr_union *link,
|
||||
uint32_t xid,
|
||||
const uint8_t *mac_addr,
|
||||
size_t mac_addr_len,
|
||||
const uint8_t *bcast_addr,
|
||||
size_t bcast_addr_len,
|
||||
uint16_t arp_type,
|
||||
uint16_t port) {
|
||||
|
||||
static const uint8_t eth_bcast[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
/* Default broadcast address for IPoIB */
|
||||
static const uint8_t ib_bcast[] = {
|
||||
@ -172,7 +175,6 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int
|
||||
r = setsockopt_int(s, IPPROTO_IP, IP_TOS, ip_service_type);
|
||||
else
|
||||
r = setsockopt_int(s, IPPROTO_IP, IP_TOS, IPTOS_CLASS_CS6);
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -204,43 +206,49 @@ int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int
|
||||
return r;
|
||||
}
|
||||
|
||||
r = bind(s, &src.sa, sizeof(src.in));
|
||||
if (r < 0)
|
||||
if (bind(s, &src.sa, sizeof(src.in)) < 0)
|
||||
return -errno;
|
||||
|
||||
return TAKE_FD(s);
|
||||
}
|
||||
|
||||
int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
|
||||
const void *packet, size_t len) {
|
||||
int r;
|
||||
int dhcp_network_send_raw_socket(
|
||||
int s,
|
||||
const union sockaddr_union *link,
|
||||
const void *packet,
|
||||
size_t len) {
|
||||
|
||||
/* Do not add assert(s >= 0) here, as this is called in fuzz-dhcp-server, and in that case this
|
||||
* function should fail with negative errno. */
|
||||
|
||||
assert(link);
|
||||
assert(packet);
|
||||
assert(len);
|
||||
assert(len > 0);
|
||||
|
||||
r = sendto(s, packet, len, 0, &link->sa, SOCKADDR_LL_LEN(link->ll));
|
||||
if (r < 0)
|
||||
if (sendto(s, packet, len, 0, &link->sa, SOCKADDR_LL_LEN(link->ll)) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port,
|
||||
const void *packet, size_t len) {
|
||||
int dhcp_network_send_udp_socket(
|
||||
int s,
|
||||
be32_t address,
|
||||
uint16_t port,
|
||||
const void *packet,
|
||||
size_t len) {
|
||||
|
||||
union sockaddr_union dest = {
|
||||
.in.sin_family = AF_INET,
|
||||
.in.sin_port = htobe16(port),
|
||||
.in.sin_addr.s_addr = address,
|
||||
};
|
||||
int r;
|
||||
|
||||
assert(s >= 0);
|
||||
assert(packet);
|
||||
assert(len);
|
||||
assert(len > 0);
|
||||
|
||||
r = sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in));
|
||||
if (r < 0)
|
||||
if (sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in)) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
|
@ -34,16 +34,17 @@ static int icmp6_bind_router_message(const struct icmp6_filter *filter,
|
||||
_cleanup_close_ int s = -1;
|
||||
int r;
|
||||
|
||||
assert(filter);
|
||||
assert(mreq);
|
||||
|
||||
s = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_ICMPV6);
|
||||
if (s < 0)
|
||||
return -errno;
|
||||
|
||||
r = setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, filter, sizeof(*filter));
|
||||
if (r < 0)
|
||||
if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, filter, sizeof(*filter)) < 0)
|
||||
return -errno;
|
||||
|
||||
r = setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq, sizeof(*mreq));
|
||||
if (r < 0)
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq, sizeof(*mreq)) < 0)
|
||||
return -errno;
|
||||
|
||||
/* RFC 3315, section 6.7, bullet point 2 may indicate that an
|
||||
@ -131,15 +132,13 @@ int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
|
||||
.msg_iov = &iov,
|
||||
.msg_iovlen = 1,
|
||||
};
|
||||
int r;
|
||||
|
||||
assert(s >= 0);
|
||||
assert(ether_addr);
|
||||
|
||||
rs.rs_opt_mac = *ether_addr;
|
||||
|
||||
r = sendmsg(s, &msg, 0);
|
||||
if (r < 0)
|
||||
if (sendmsg(s, &msg, 0) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "socket-util.h"
|
||||
|
||||
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 */
|
||||
@ -24,26 +23,21 @@ int lldp_network_bind_raw_socket(int ifindex) {
|
||||
BPF_STMT(BPF_RET + BPF_K, 0), /* drop packet */
|
||||
BPF_STMT(BPF_RET + BPF_K, UINT32_MAX), /* 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);
|
||||
|
||||
@ -52,29 +46,24 @@ int lldp_network_bind_raw_socket(int ifindex) {
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
r = setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog));
|
||||
if (r < 0)
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)) < 0)
|
||||
return -errno;
|
||||
|
||||
/* customer bridge */
|
||||
r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
|
||||
if (r < 0)
|
||||
if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||
return -errno;
|
||||
|
||||
/* non TPMR bridge */
|
||||
mreq.mr_address[ETH_ALEN - 1] = 0x03;
|
||||
r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
|
||||
if (r < 0)
|
||||
if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||
return -errno;
|
||||
|
||||
/* nearest bridge */
|
||||
mreq.mr_address[ETH_ALEN - 1] = 0x0E;
|
||||
r = setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
|
||||
if (r < 0)
|
||||
if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||
return -errno;
|
||||
|
||||
r = bind(fd, &saddrll.sa, sizeof(saddrll.ll));
|
||||
if (r < 0)
|
||||
if (bind(fd, &saddrll.sa, sizeof(saddrll.ll)) < 0)
|
||||
return -errno;
|
||||
|
||||
return TAKE_FD(fd);
|
||||
|
Loading…
Reference in New Issue
Block a user