From 09bc68580f3459c65cfddedc8ccbec70b8117883 Mon Sep 17 00:00:00 2001 From: Yoel Caspersen Date: Wed, 13 Oct 2021 20:11:06 +0200 Subject: [PATCH] Moving Option 82 to end of options as per RFC3046 section 2.1. Adjusting tail instead of headers because of complications with variable length DHCP options - beware that this doesn't appear to work with veth interfaces. Use a physical NIC for testing for now. --- dhcp-relay/README | 16 +- dhcp-relay/dhcp-relay.h | 13 +- dhcp-relay/dhcp_kern_xdp.c | 338 ++++++++++++++++++++++++++++++------- dhcp-relay/dhcp_user_xdp.c | 193 +++++++++++++-------- 4 files changed, 421 insertions(+), 139 deletions(-) diff --git a/dhcp-relay/README b/dhcp-relay/README index 7642d6d..698b657 100644 --- a/dhcp-relay/README +++ b/dhcp-relay/README @@ -1,7 +1,7 @@ Usage ----- -dhcp_user_xdp takes network interface and dhcp relay server IP -as inputs and stores it in a map. Filters the incoming DHCP requests and inserts +dhcp_user_xdp takes network interface, DHCP server IP and DHCP relay agent IP +as inputs and stores them in a map. Filters the incoming DHCP requests and inserts option 82 in the DHCP request packets and overwrites the destination IP to that of DHCP relay server IP. @@ -10,7 +10,7 @@ cd bpf-examples/dhcp-relay make Loading bpf program: -sudo ./dhcp_user_xdp -i -d +sudo ./dhcp_user_xdp -i -d -s where, netif: Ingress network interface name @@ -20,6 +20,12 @@ sudo ./dhcp_user_xdp -i -u To run in SKB mode: add option "-m skb" for both load and uload commands -Verify using tcpdump: -sudo tcpdump -s 0 -i port 67 and port 68 -vvv +Please beware that testing requires a physical NIC because we tail extend +packets due to complications with variable length DHCP options. +Enable forwarding and allow local address spoofing: +sudo echo 1 > /proc/sys/net/ipv4/ip_forward +sudo echo 1 > /proc/sys/net/ipv4/conf/all/accept_local + +Verify using tcpdump: +sudo tcpdump -s 0 -i port 67 and port 68 -vvv \ No newline at end of file diff --git a/dhcp-relay/dhcp-relay.h b/dhcp-relay/dhcp-relay.h index ee276b9..2a0c6ed 100644 --- a/dhcp-relay/dhcp-relay.h +++ b/dhcp-relay/dhcp-relay.h @@ -12,10 +12,12 @@ #define RAI_REMOTE_ID 2 #define RAI_OPTION_LEN 2 -#define DEST_PORT 67 /* UDP destination port for dhcp */ -#define MAX_BYTES 280 /* Max bytes supported by xdp load/store apis */ +#define DHCP_SERVER_PORT 67 +#define DHCP_CLIENT_PORT 68 +#define DHCP_REQUEST 1 +#define DHCP_REPLY 2 -/* structure for sub-options in option 82*/ +/* Structure for sub-options in option 82 */ struct sub_option { __u8 option_id; __u8 len; @@ -30,6 +32,11 @@ struct dhcp_option_82 { struct sub_option remote_id; }; +/*structure for dhcp option 255 */ +struct dhcp_option_255 { + __u8 t; +}; + struct dhcp_packet { __u8 op; /* 0: Message opcode/type */ __u8 htype; /* 1: Hardware addr type (net/if_types.h) */ diff --git a/dhcp-relay/dhcp_kern_xdp.c b/dhcp-relay/dhcp_kern_xdp.c index ae0dc5a..281088c 100644 --- a/dhcp-relay/dhcp_kern_xdp.c +++ b/dhcp-relay/dhcp_kern_xdp.c @@ -8,49 +8,66 @@ #include "dhcp-relay.h" /* - * This map is for storing the DHCP relay server - * IP address configured by user. It is received - * as an argument by user program. -*/ + * This map is for storing the DHCP relay configuration, including: + * + * Relay server IP address + * Relay agent IP address + * Relay agent MAC address + * + * Configuration parameters are set by CLI arguments in user space program. + */ struct { __uint(type, BPF_MAP_TYPE_ARRAY); __type(key, __u32); - __type(value, __u32); - __uint(max_entries, 1); -} dhcp_server SEC(".maps"); + __type(value, __u64); + __uint(max_entries, 3); +} relay_config SEC(".maps"); /* Inserts DHCP option 82 into the received dhcp packet * at the specified offset. -*/ -static __always_inline int write_dhcp_option(void *ctx, int offset, - struct collect_vlans *vlans) -{ + */ +static __always_inline int write_dhcp_option_82(void *ctx, int offset, + struct collect_vlans *vlans) { struct dhcp_option_82 option; option.t = DHO_DHCP_AGENT_OPTIONS; option.len = 8; option.circuit_id.option_id = RAI_CIRCUIT_ID; option.circuit_id.len = RAI_OPTION_LEN; - option.circuit_id.val = bpf_htons(vlans->id[0]); + option.circuit_id.val = bpf_ntohs(vlans->id[0]); option.remote_id.option_id = RAI_REMOTE_ID; option.remote_id.len = RAI_OPTION_LEN; - option.remote_id.val = bpf_htons(vlans->id[1]); + option.remote_id.val = bpf_ntohs(vlans->id[1]); - return xdp_store_bytes(ctx, offset, &option, sizeof(option), 0); + return xdp_store_bytes(ctx, offset, &option, sizeof (option), 0); +} + +/* Inserts DHCP option 255 into the received dhcp packet + * at the specified offset. + */ +static __always_inline int write_dhcp_option_255(void *ctx, int offset) { + struct dhcp_option_255 option; + + option.t = 255; + + return xdp_store_bytes(ctx, offset, &option, sizeof (option), 0); } /* Calculates the IP checksum */ static __always_inline int calc_ip_csum(struct iphdr *oldip, struct iphdr *ip, - __u32 oldcsum) -{ - __u32 size = sizeof(struct iphdr); - __u32 csum = bpf_csum_diff((__be32 *)oldip, size, (__be32 *)ip, size, - ~oldcsum); + __u32 oldcsum) { + __u32 size = sizeof (struct iphdr); + __u32 csum = bpf_csum_diff((__be32 *) oldip, size, (__be32 *) ip, size, + ~oldcsum); __u32 sum = (csum >> 16) + (csum & 0xffff); sum += (sum >> 16); return sum; } +#define dhcp_offset \ + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) +//offsetof(struct dhcp_packet, options) + /* Offset to DHCP Options part of the packet */ #define static_offset \ sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr) + \ @@ -59,26 +76,56 @@ static __always_inline int calc_ip_csum(struct iphdr *oldip, struct iphdr *ip, /* Delta value to be adjusted at xdp head*/ #define delta sizeof(struct dhcp_option_82) +#ifndef DHCP_MAX_OPTIONS +#define DHCP_MAX_OPTIONS 20 +#endif + /* buf needs to be a static global var because the verifier won't allow * unaligned stack accesses -*/ -static __u8 buf[static_offset + VLAN_MAX_DEPTH * sizeof(struct vlan_hdr)]; + */ +//static __u8 buf[static_offset + VLAN_MAX_DEPTH * sizeof (struct vlan_hdr)]; + +#define bpf_printk(fmt, ...) \ +({ \ + char ____fmt[] = fmt; \ + bpf_trace_printk(____fmt, sizeof(____fmt), \ + ##__VA_ARGS__); \ +}) /* XDP program for parsing the DHCP packet and inserting the option 82*/ SEC(XDP_PROG_SEC) -int xdp_dhcp_relay(struct xdp_md *ctx) -{ - void *data_end = (void *)(long)ctx->data_end; - void *data = (void *)(long)ctx->data; - struct collect_vlans vlans = { 0 }; +int xdp_dhcp_relay(struct xdp_md *ctx) { + + bpf_printk("\n"); + + /* Tail extend packet */ + int res = bpf_xdp_adjust_tail(ctx, delta); + if (res != 0) { + bpf_printk("Cannot tail extend packet, delta %i - error code %i", delta, res); + return XDP_ABORTED; + } + + //bpf_printk("static_offset %i (hex %x)", static_offset, static_offset); + //bpf_printk("dhcp_offset %i (hex %x)", dhcp_offset, dhcp_offset); + + void *data_end = (void *) (long) ctx->data_end; + void *data = (void *) (long) ctx->data; + struct collect_vlans vlans = {0}; struct ethhdr *eth; struct iphdr *ip; struct iphdr oldip; struct udphdr *udp; - __u32 *dhcp_srv; + struct dhcp_packet *dhcp; + __u32 *dhcp_srv_ip; + __u32 *relay_agent_ip; + __u64 *relay_hwaddr; int rc = XDP_PASS; __u16 offset = static_offset; + __u16 option_offset = offset; __u16 ip_offset = 0; + __u16 vlan_length = 0; + __u8 option_code = 0; + __u8 option_length = 0; int i = 0; /* These keep track of the next header type and iterator pointer */ @@ -95,89 +142,254 @@ int xdp_dhcp_relay(struct xdp_md *ctx) ether_type = parse_ethhdr_vlan(&nh, data_end, ð, &vlans); /* check for valid ether type */ if (ether_type < 0) { + bpf_printk("Cannot determine ethertype"); rc = XDP_ABORTED; goto out; } - if (ether_type != bpf_htons(ETH_P_IP)) + if (ether_type != bpf_htons(ETH_P_IP)) { + bpf_printk("Ethertype %#x is not ETH_P_IP", bpf_ntohs(ether_type)); goto out; + } + + bpf_printk("Ethertype %x", bpf_ntohs(ether_type)); /* Check at least two vlan tags are present */ - if (vlans.id[1] == 0) - goto out; - - /* Read dhcp relay server IP from map */ - dhcp_srv = bpf_map_lookup_elem(&dhcp_server, &key); - if (dhcp_srv == NULL) + if (vlans.id[1] == 0) { + bpf_printk("No VLAN tags set"); goto out; + } h_proto = parse_iphdr(&nh, data_end, &ip); - /* only handle fixed-size IP header due to static copy */ + /* Only handle fixed-size IP header due to static copy */ if (h_proto != IPPROTO_UDP || ip->ihl > 5) { goto out; } - /*old ip hdr backup for re-calculating the checksum later*/ + + /* Old ip hdr backup for re-calculating the checksum later */ oldip = *ip; - ip_offset = ((void *)ip - data) & 0x3fff; + ip_offset = ((void *) ip - data) & 0x3fff; len = parse_udphdr(&nh, data_end, &udp); if (len < 0) goto out; - if (udp->dest != bpf_htons(DEST_PORT)) + /* Handle DHCP packets only */ + if (udp->dest != bpf_htons(DHCP_SERVER_PORT) && udp->dest != bpf_htons(DHCP_CLIENT_PORT)) goto out; - if (xdp_load_bytes(ctx, 0, buf, static_offset)) + /* Read DHCP server IP from config map */ + key = 0; + dhcp_srv_ip = bpf_map_lookup_elem(&relay_config, &key); + if (dhcp_srv_ip == NULL) goto out; + /* Read relay agent IP from config map */ + key = 1; + relay_agent_ip = bpf_map_lookup_elem(&relay_config, &key); + if (relay_agent_ip == NULL) + goto out; + + /* Read relay agent MAC address from config map */ + key = 2; + relay_hwaddr = bpf_map_lookup_elem(&relay_config, &key); + if (relay_hwaddr == NULL) + goto out; + + /* Copy headers of packet to buf */ + //if (xdp_load_bytes(ctx, 0, buf, static_offset)) + // goto out; + + /* Increment offset by 4 bytes for each VLAN (to accomodate VLAN headers */ for (i = 0; i < VLAN_MAX_DEPTH; i++) { if (vlans.id[i]) { - if (xdp_load_bytes(ctx, offset, buf + offset, 4)) - goto out; + + bpf_printk("Found VLAN tag %i at depth %i", vlans.id[i], i); + + /* For each VLAN present, copy 4 bytes of DHCP options to buffer */ + //if (xdp_load_bytes(ctx, offset, buf + offset, 4)) + // goto out; offset += 4; + vlan_length += 4; } } - /* adjusting the packet head by delta size to insert option82 */ - if (bpf_xdp_adjust_head(ctx, 0 - (int)delta) < 0) - return XDP_ABORTED; + /* Find packet boundaries */ + data_end = (void *) (long) ctx->data_end; + data = (void *) (long) ctx->data; - data_end = (void *)(long)ctx->data_end; - data = (void *)(long)ctx->data; + /* Parse DHCP packet */ + if (data + vlan_length + dhcp_offset + sizeof (dhcp) > data_end) { + goto out; + } + dhcp = data + vlan_length + dhcp_offset; + bpf_printk("Parsing DHCP packet, opcode %i, hops %i", dhcp->op, dhcp->hops); + + if (dhcp->op == DHCP_REQUEST && (eth->h_dest[0] == 0xff + && eth->h_dest[1] == 0xff + && eth->h_dest[2] == 0xff + && eth->h_dest[3] == 0xff + && eth->h_dest[4] == 0xff + && eth->h_dest[5] == 0xff)) { + + /* Request from client received as broadcast */ + + bpf_printk("Broadcast packet received, opcode %i, hops %i", dhcp->op, dhcp->hops); + + // Set destination MAC + memcpy(eth->h_dest, relay_hwaddr, ETH_ALEN); + + // Set source MAC + //memcpy(eth->h_source, relay_hwaddr, ETH_ALEN); + + // Set GIADDR + if(&dhcp->giaddr.s_addr + sizeof(relay_agent_ip) > data_end) { + rc = XDP_ABORTED; + goto out; + } + dhcp->giaddr.s_addr = *relay_agent_ip; + + + } else if (dhcp->op == DHCP_REPLY && (eth->h_dest[0] != 0xff + || eth->h_dest[1] != 0xff + || eth->h_dest[2] != 0xff + || eth->h_dest[3] != 0xff + || eth->h_dest[4] != 0xff + || eth->h_dest[5] != 0xff)) { + + /* Response from server received as unicast */ + + bpf_printk("Unicast packet received, opcode %i, hops %i", dhcp->op, dhcp->hops); + + /* FIXME: Add code for reply packets + * Basically: + * - Set dest and src MAC + * - Add VLAN tags + * - Remove option 82 + * - Use XDP_TX (or XDP_REDIRECT) to send the response + * to the end user + */ + + } + + /* Check hops */ + if (dhcp->hops > 16) { + bpf_printk("Max hops exceeded, discarding packet"); + rc = XDP_ABORTED; + goto out; + } + + /* Increment hops */ + dhcp->hops++; + + /* Check if we exceed boundaries to make verifier happy */ if (data + offset > data_end) - return XDP_ABORTED; + goto out; - if (xdp_store_bytes(ctx, 0, buf, static_offset, 0)) - return XDP_ABORTED; + option_offset = offset; - if (offset > static_offset) { + __u8 *pos = (__u8 *) (data + option_offset); + + /* Loop through all DHCP options */ +#pragma unroll DHCP_MAX_OPTIONS + for (i = 0; i < DHCP_MAX_OPTIONS; i++) { + + /* Verifier check */ + if (pos + 1 > data_end) + break; + + option_code = *pos; + + bpf_printk("Got option code %i at offset %i, hex %x", option_code, option_offset, option_offset); + + if (option_code == 255) { + + bpf_printk("Going to write DHCP option at offset %i", option_offset); + + /* Insert Option 82 before END option */ + if (write_dhcp_option_82(ctx, option_offset, &vlans)) { + bpf_printk("Could not write DHCP option 82 at offset %i", option_offset); + return XDP_ABORTED; + } + + /* Set END option */ + + /* Verifier check */ + if (pos + delta > data_end) { + return XDP_ABORTED; + } + pos += delta; + option_offset += delta; + + if (write_dhcp_option_255(ctx, option_offset)) { + bpf_printk("Could not write DHCP option 255 at offset %i", option_offset); + return XDP_ABORTED; + } + + break; + } + pos++; + + option_length = *pos; + option_offset += option_length + 2; + + if (pos + 1 > data_end) { + break; + } + pos++; + + if (pos + option_length > data_end) { + break; + } + pos += option_length; + + } + + //return XDP_PASS; + + /* Copy stored headers from buf to context */ + /*if (xdp_store_bytes(ctx, 0, buf, static_offset, 0)) { + + bpf_printk("xdp_store_bytes(ctx, 0, buf, %i) failed", static_offset); + return XDP_ABORTED; + }*/ + + + /* make space for option 82 - copy DHCP options after increasing offset */ + /*if (offset > static_offset) { offset = static_offset; for (i = 0; i < VLAN_MAX_DEPTH; i++) { - if (vlans.id[i]) { - if (xdp_store_bytes(ctx, offset, buf + offset, - 4, 0)) - return XDP_ABORTED; - offset += 4; - } - } - } - - if (write_dhcp_option(ctx, offset, &vlans)) + if (vlans.id[i]) {*/ + /* */ + /*if (xdp_store_bytes(ctx, offset, buf + offset, + 4, 0)) return XDP_ABORTED; + offset += 4; +} + } + }*/ ip = data + ip_offset; if (ip + 1 > data_end) return XDP_ABORTED; - /* overwrite the destination IP in IP header */ - ip->daddr = *dhcp_srv; + /* Overwrite the destination IP in IP header */ + ip->daddr = *dhcp_srv_ip; - //re-calc ip checksum + /* Overwrite source IP */ + ip->saddr = *relay_agent_ip; + + /* Re-calculate ip checksum */ __u32 sum = calc_ip_csum(&oldip, ip, oldip.check); ip->check = ~sum; rc = XDP_PASS; + + bpf_printk("Wrote DHCP option at offset %i, returning XDP_PASS", offset); + goto out; out: return rc; } + +char _license[] SEC("license") = "GPL"; \ No newline at end of file diff --git a/dhcp-relay/dhcp_user_xdp.c b/dhcp-relay/dhcp_user_xdp.c index b3fa6bd..26afd91 100644 --- a/dhcp-relay/dhcp_user_xdp.c +++ b/dhcp-relay/dhcp_user_xdp.c @@ -13,21 +13,24 @@ #include /* depend on kernel-headers installed */ #include -#define SERVER_MAP "dhcp_server" +#include +#include + +#define SERVER_MAP "relay_config" #define XDP_OBJ "dhcp_kern_xdp.o" static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, + { "help", no_argument, NULL, 'h'}, { "interface", required_argument, NULL, - 'i' }, // Name of interface to run on - { "dhcp-server", required_argument, NULL, 'd' }, - { "mode", required_argument, NULL, 'm' }, - { "unload", no_argument, NULL, 'u' }, - { 0, 0, NULL, 0 } + 'i'}, // Name of interface to run on + { "dhcp-server", required_argument, NULL, 'd'}, + { "relay-agent-address", required_argument, NULL, 's'}, + { "mode", required_argument, NULL, 'm'}, + { "unload", no_argument, NULL, 'u'}, + { 0, 0, NULL, 0} }; -static void print_usage(char *argv[]) -{ +static void print_usage(char *argv[]) { int i; printf("Usage:\n"); printf("%s\n", argv[0]); @@ -45,8 +48,7 @@ static void print_usage(char *argv[]) printf("\n"); } -static int xdp_link_detach(int ifindex, __u32 xdp_flags) -{ +static int xdp_link_detach(int ifindex, __u32 xdp_flags) { int err; if ((err = bpf_set_link_xdp_fd(ifindex, -1, xdp_flags)) < 0) { @@ -57,8 +59,7 @@ static int xdp_link_detach(int ifindex, __u32 xdp_flags) return 0; } -int xdp_link_attach(int ifindex, __u32 xdp_flags, int prog_fd) -{ +int xdp_link_attach(int ifindex, __u32 xdp_flags, int prog_fd) { int err; /* libbpf provide the XDP net_device link-level hook attach helper */ @@ -71,15 +72,15 @@ int xdp_link_attach(int ifindex, __u32 xdp_flags, int prog_fd) ifindex, -err, strerror(-err)); switch (-err) { - case EBUSY: - case EEXIST: - fprintf(stderr, "Hint: XDP already loaded on device\n"); - break; - case EOPNOTSUPP: - fprintf(stderr, "Hint: Native-XDP not supported\n"); - break; - default: - break; + case EBUSY: + case EEXIST: + fprintf(stderr, "Hint: XDP already loaded on device\n"); + break; + case EOPNOTSUPP: + fprintf(stderr, "Hint: Native-XDP not supported\n"); + break; + default: + break; } return -1; } @@ -90,9 +91,9 @@ int xdp_link_attach(int ifindex, __u32 xdp_flags, int prog_fd) /* User program takes two or three arguments * interface name, relay server IP and prog * unload flag -*/ -int main(int argc, char **argv) -{ + */ +int main(int argc, char **argv) { + char filename[256] = "dhcp_kern_xdp.o"; int prog_fd, err; int opt; @@ -104,64 +105,100 @@ int main(int argc, char **argv) struct bpf_object *obj = NULL; int map_fd; int key = 0; - struct in_addr addr = {}; - bool addr_set = false; + struct in_addr dhcp_server_addr = {}; + struct in_addr relay_agent_addr = {}; + bool dhcp_server_addr_set = false; + bool relay_agent_addr_set = false; __u16 ifindex = 0; + int fd; + unsigned char *mac; + struct ifreq ifr; - while ((opt = getopt_long(argc, argv, "hui:d:m:", options, NULL)) != - -1) { + while ((opt = getopt_long(argc, argv, "hui:d:m:s:", options, NULL)) != + -1) { switch (opt) { - case 'i': - strncpy(dev, optarg, IF_NAMESIZE); - dev[IF_NAMESIZE - 1] = '\0'; - ifindex = if_nametoindex(dev); - if (ifindex <= 0) { - printf("Couldn't find ifname:%s \n", dev); - return -EINVAL; - } - break; - case 'd': - if (inet_aton(optarg, &addr) == 0) { - fprintf(stderr, - "Couldn't validate IP address:%s\n", - optarg); - return -EINVAL; - } - addr_set = true; - break; - case 'm': - if (strcmp(optarg, "skb") == 0) { - xdp_flags = XDP_FLAGS_SKB_MODE; - } else if (strcmp(optarg, "drv") != 0) { - fprintf(stderr, "Invalid mode: %s\n", optarg); - return -EINVAL; - } + case 'i': + strncpy(dev, optarg, IF_NAMESIZE); + dev[IF_NAMESIZE - 1] = '\0'; + ifindex = if_nametoindex(dev); + if (ifindex <= 0) { + printf("Couldn't find ifname:%s \n", dev); + return -EINVAL; + } + break; + case 'd': // DHCP server address + if (inet_aton(optarg, &dhcp_server_addr) == 0) { + fprintf(stderr, + "Couldn't validate DHCP server IP address:%s\n", + optarg); + return -EINVAL; + } + dhcp_server_addr_set = true; + break; + case 's': // Relay agent address + if (inet_aton(optarg, &relay_agent_addr) == 0) { + fprintf(stderr, + "Couldn't validate relay agent IP address:%s\n", + optarg); + return -EINVAL; + } + relay_agent_addr_set = true; + break; + case 'm': + if (strcmp(optarg, "skb") == 0) { + xdp_flags = XDP_FLAGS_SKB_MODE; + } else if (strcmp(optarg, "drv") != 0) { + fprintf(stderr, "Invalid mode: %s\n", optarg); + return -EINVAL; + } - break; - case 'u': - do_unload = 1; - break; - case 'h': - print_usage(argv); - exit(0); - default: - fprintf(stderr, "Unknown option %s\n", argv[optind]); - return -EINVAL; + break; + case 'u': + do_unload = 1; + break; + case 'h': + print_usage(argv); + exit(0); + default: + fprintf(stderr, "Unknown option %s\n", argv[optind]); + return -EINVAL; } } if (!ifindex) { - fprintf(stderr, "Missing ifname\n"); + fprintf(stderr, "Please specify interface name\n"); return -EINVAL; } - if (!addr_set) { - fprintf(stderr, "Missing server address\n"); + if (!dhcp_server_addr_set) { + fprintf(stderr, "Please specify DHCP server address with -d parameter\n"); + return -EINVAL; + } + if (!relay_agent_addr_set) { + fprintf(stderr, "Please specify DHCP relay agent address with -s parameter\n"); return -EINVAL; } if (do_unload) return xdp_link_detach(ifindex, xdp_flags); + // Find MAC address of interface + fd = socket(AF_INET, SOCK_DGRAM, 0); + + ifr.ifr_addr.sa_family = AF_INET; + strncpy(ifr.ifr_name, dev, IF_NAMESIZE); + + ioctl(fd, SIOCGIFHWADDR, &ifr); + + close(fd); + + mac = (unsigned char *) ifr.ifr_hwaddr.sa_data; + + __u64 hwaddr = 0; + memcpy(&hwaddr, (unsigned char *) ifr.ifr_hwaddr.sa_data, 6); + + //display mac address + printf("Mac : %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + /* Load the BPF-ELF object file and get back first BPF_prog FD */ err = bpf_prog_load(filename, BPF_PROG_TYPE_XDP, &obj, &prog_fd); if (err) { @@ -191,7 +228,27 @@ int main(int argc, char **argv) exit(-1); } - err = bpf_map_update_elem(map_fd, &key, &addr.s_addr, BPF_ANY); + // Set DHCP server address + key = 0; + err = bpf_map_update_elem(map_fd, &key, &dhcp_server_addr.s_addr, BPF_ANY); + if (err) { + fprintf(stderr, "Could not update map %s in %s\n", SERVER_MAP, + XDP_OBJ); + exit(-1); + } + + // Set relay agent IP address + key = 1; + err = bpf_map_update_elem(map_fd, &key, &relay_agent_addr.s_addr, BPF_ANY); + if (err) { + fprintf(stderr, "Could not update map %s in %s\n", SERVER_MAP, + XDP_OBJ); + exit(-1); + } + + // Set relay agent MAC address + key = 2; + err = bpf_map_update_elem(map_fd, &key, &hwaddr, BPF_ANY); if (err) { fprintf(stderr, "Could not update map %s in %s\n", SERVER_MAP, XDP_OBJ);