#include <uapi/linux/ip.h>
#include <uapi/linux/ipv6.h>
-#define DNS_PORT 53
+#define DNS_PORT 53
// do not use libc includes because this causes clang
// to include 32bit headers on 64bit ( only ) systems.
-typedef __u8 uint8_t;
+typedef __u8 uint8_t;
typedef __u16 uint16_t;
typedef __u32 uint32_t;
typedef __u64 uint64_t;
* Copyright 2020, NLnet Labs, All rights reserved.
*/
struct cursor {
- void *pos;
- void *end;
+ void* pos;
+ void* end;
};
/*
struct dnshdr {
uint16_t id;
union {
- struct {
+ struct {
#if BYTE_ORDER == LITTLE_ENDIAN
- uint8_t rd : 1;
- uint8_t tc : 1;
- uint8_t aa : 1;
- uint8_t opcode : 4;
- uint8_t qr : 1;
-
- uint8_t rcode : 4;
- uint8_t cd : 1;
- uint8_t ad : 1;
- uint8_t z : 1;
- uint8_t ra : 1;
+ uint8_t rd : 1;
+ uint8_t tc : 1;
+ uint8_t aa : 1;
+ uint8_t opcode : 4;
+ uint8_t qr : 1;
+
+ uint8_t rcode : 4;
+ uint8_t cd : 1;
+ uint8_t ad : 1;
+ uint8_t z : 1;
+ uint8_t ra : 1;
#elif BYTE_ORDER == BIG_ENDIAN || BYTE_ORDER == PDP_ENDIAN
- uint8_t qr : 1;
- uint8_t opcode : 4;
- uint8_t aa : 1;
- uint8_t tc : 1;
- uint8_t rd : 1;
-
- uint8_t ra : 1;
- uint8_t z : 1;
- uint8_t ad : 1;
- uint8_t cd : 1;
- uint8_t rcode : 4;
+ uint8_t qr : 1;
+ uint8_t opcode : 4;
+ uint8_t aa : 1;
+ uint8_t tc : 1;
+ uint8_t rd : 1;
+
+ uint8_t ra : 1;
+ uint8_t z : 1;
+ uint8_t ad : 1;
+ uint8_t cd : 1;
+ uint8_t rcode : 4;
#endif
- } as_bits_and_pieces;
- uint16_t as_value;
+ } as_bits_and_pieces;
+ uint16_t as_value;
} flags;
uint16_t qdcount;
uint16_t ancount;
/*
* Store the qname and qtype
*/
-struct dns_qname
-{
+struct dns_qname {
uint8_t qname[255];
uint16_t qtype;
};
* Initializer of a cursor pointer
* Copyright 2020, NLnet Labs, All rights reserved.
*/
-static inline void cursor_init(struct cursor *c, struct xdp_md *ctx)
-{
- c->end = (void *)(long)ctx->data_end;
- c->pos = (void *)(long)ctx->data;
+static inline void cursor_init(struct cursor* c, struct xdp_md* ctx) {
+ c->end = (void*)(long)ctx->data_end;
+ c->pos = (void*)(long)ctx->data;
}
/*
* Copyright 2020, NLnet Labs, All rights reserved.
*/
#define PARSE_FUNC_DECLARATION(STRUCT) \
-static inline struct STRUCT *parse_ ## STRUCT (struct cursor *c) \
-{ \
- struct STRUCT *ret = c->pos; \
- if (c->pos + sizeof(struct STRUCT) > c->end) \
- return 0; \
- c->pos += sizeof(struct STRUCT); \
- return ret; \
-}
+ static inline struct STRUCT* parse_##STRUCT(struct cursor* c) { \
+ struct STRUCT* ret = c->pos; \
+ if (c->pos + sizeof(struct STRUCT) > c->end) \
+ return 0; \
+ c->pos += sizeof(struct STRUCT); \
+ return ret; \
+ }
PARSE_FUNC_DECLARATION(ethhdr)
PARSE_FUNC_DECLARATION(vlanhdr)
* Parse ethernet frame and fill the struct
* Copyright 2020, NLnet Labs, All rights reserved.
*/
-static inline struct ethhdr *parse_eth(struct cursor *c, uint16_t *eth_proto)
-{
- struct ethhdr *eth;
+static inline struct ethhdr* parse_eth(struct cursor* c, uint16_t* eth_proto) {
+ struct ethhdr* eth;
if (!(eth = parse_ethhdr(c)))
- return 0;
+ return 0;
*eth_proto = eth->h_proto;
if (*eth_proto == bpf_htons(ETH_P_8021Q)
- || *eth_proto == bpf_htons(ETH_P_8021AD)) {
- struct vlanhdr *vlan;
+ || *eth_proto == bpf_htons(ETH_P_8021AD)) {
+ struct vlanhdr* vlan;
- if (!(vlan = parse_vlanhdr(c)))
- return 0;
+ if (!(vlan = parse_vlanhdr(c)))
+ return 0;
- *eth_proto = vlan->encap_proto;
- if (*eth_proto == bpf_htons(ETH_P_8021Q)
- || *eth_proto == bpf_htons(ETH_P_8021AD)) {
- if (!(vlan = parse_vlanhdr(c)))
- return 0;
+ *eth_proto = vlan->encap_proto;
+ if (*eth_proto == bpf_htons(ETH_P_8021Q)
+ || *eth_proto == bpf_htons(ETH_P_8021AD)) {
+ if (!(vlan = parse_vlanhdr(c)))
+ return 0;
- *eth_proto = vlan->encap_proto;
- }
+ *eth_proto = vlan->encap_proto;
+ }
}
return eth;
}
/*
* Parse DNS QName and fill the struct
*/
-static inline void parse_qname(struct cursor *c, struct dns_qname *query)
-{
+static inline void parse_qname(struct cursor* c, struct dns_qname* query) {
uint8_t qname_byte;
uint16_t qtype;
int length = 0;
- for(int i = 0; i<255; i++) {
- bpf_probe_read_kernel(&qname_byte, sizeof(qname_byte), c->pos);
+ for (int i = 0; i < 255; i++) {
+ bpf_probe_read_kernel(&qname_byte, sizeof(qname_byte), c->pos);
- c->pos += 1;
- if (length == 0) {
- if (qname_byte == 0 || qname_byte > 63 ) {
- break;
- }
- length += qname_byte;
- } else {
- length--;
- }
- if (qname_byte >= 'A' && qname_byte <= 'Z') {
- query->qname[i] = qname_byte + ('a' - 'A');
- } else {
- query->qname[i] = qname_byte;
+ c->pos += 1;
+ if (length == 0) {
+ if (qname_byte == 0 || qname_byte > 63) {
+ break;
}
+ length += qname_byte;
+ } else {
+ length--;
+ }
+ if (qname_byte >= 'A' && qname_byte <= 'Z') {
+ query->qname[i] = qname_byte + ('a' - 'A');
+ } else {
+ query->qname[i] = qname_byte;
+ }
}
bpf_probe_read_kernel(&(query->qtype), sizeof(query->qtype), c->pos);
/*
* Push data regarding the dropped/redirected packet to a perf buffer
*/
-static inline void log_packet(struct xdp_md *ctx, enum dns_action action) {
+static inline void log_packet(struct xdp_md* ctx, enum dns_action action) {
// store variables
- struct cursor c;
- struct ethhdr *eth;
- uint16_t eth_proto;
- struct iphdr *ipv4;
- struct ipv6hdr *ipv6;
- struct udphdr *udp;
- struct dnshdr *dns;
- int r = 0;
+ struct cursor c;
+ struct ethhdr* eth;
+ uint16_t eth_proto;
+ struct iphdr* ipv4;
+ struct ipv6hdr* ipv6;
+ struct udphdr* udp;
+ struct dnshdr* dns;
+ int r = 0;
struct pktdata {
- uint32_t ipv4_src;
- uint8_t ipv6_src[16];
+ uint32_t ipv4_src;
+ uint8_t ipv6_src[16];
struct dns_qname query;
} packet_info = {0};
cursor_init(&c, ctx);
if ((eth = parse_eth(&c, ð_proto))) {
- if (eth_proto == bpf_htons(ETH_P_IP))
- {
- if ((ipv4 = parse_iphdr(&c)))
- {
- if (action == DROP)
- {
- memcpy(&(packet_info.ipv4_src), &(ipv4->saddr), sizeof(packet_info.ipv4_src));
- }
- else if (action == TC)
- {
- memcpy(&(packet_info.ipv4_src), &(ipv4->daddr), sizeof(packet_info.ipv4_src));
- }
- if ((udp = parse_udphdr(&c)))
- {
- if ((dns = parse_dnshdr(&c)))
- {
- parse_qname(&c, &(packet_info.query));
- }
- }
- }
+ if (eth_proto == bpf_htons(ETH_P_IP)) {
+ if ((ipv4 = parse_iphdr(&c))) {
+ if (action == DROP) {
+ memcpy(&(packet_info.ipv4_src), &(ipv4->saddr), sizeof(packet_info.ipv4_src));
+ } else if (action == TC) {
+ memcpy(&(packet_info.ipv4_src), &(ipv4->daddr), sizeof(packet_info.ipv4_src));
+ }
+ if ((udp = parse_udphdr(&c))) {
+ if ((dns = parse_dnshdr(&c))) {
+ parse_qname(&c, &(packet_info.query));
+ }
+ }
+ }
+ } else if (eth_proto == bpf_htons(ETH_P_IPV6)) {
+ if ((ipv6 = parse_ipv6hdr(&c))) {
+ if (action == DROP) {
+ memcpy(&(packet_info.ipv6_src), &(ipv6->saddr.in6_u.u6_addr8), 16);
+ } else if (action == TC) {
+ memcpy(&(packet_info.ipv6_src), &(ipv6->daddr.in6_u.u6_addr8), 16);
}
- else if (eth_proto == bpf_htons(ETH_P_IPV6))
- {
- if ((ipv6 = parse_ipv6hdr(&c)))
- {
- if (action == DROP)
- {
- memcpy(&(packet_info.ipv6_src), &(ipv6->saddr.in6_u.u6_addr8), 16);
- }
- else if (action == TC)
- {
- memcpy(&(packet_info.ipv6_src), &(ipv6->daddr.in6_u.u6_addr8), 16);
- }
- if ((udp = parse_udphdr(&c)))
- {
- if ((dns = parse_dnshdr(&c)))
- {
- parse_qname(&c, &(packet_info.query));
- }
- }
- }
+ if ((udp = parse_udphdr(&c))) {
+ if ((dns = parse_dnshdr(&c))) {
+ parse_qname(&c, &(packet_info.query));
+ }
}
+ }
+ }
}
events.perf_submit(ctx, &packet_info, sizeof(packet_info));
}
-int log_drop(struct xdp_md *ctx)
-{
+int log_drop(struct xdp_md* ctx) {
log_packet(ctx, DROP);
return XDP_DROP;
}
-int log_tc(struct xdp_md *ctx)
-{
+int log_tc(struct xdp_md* ctx) {
log_packet(ctx, TC);
return XDP_TX;
}