From dfe5aeaa4af251731a7013cf95fcdbf6a7d4c89b Mon Sep 17 00:00:00 2001 From: kellyyeh <42761586+kellyyeh@users.noreply.github.com> Date: Fri, 6 Jan 2023 14:43:24 -0800 Subject: [PATCH] [dhcpmon] Fix dhcpmon socket filter and tx count issue (#13065) Why I did it Fix issue caused by dualtor support PR [dhcpmon] Open different socket for dual tor to enable interface filtering #11201 Improve code How I did it On single ToR, packets received count was duplicated due to socket filter set to "inbound" Tx count not increasing due to filter set to "inbound". Added an outbound socket to count tx packets Added vlan member interface mapping for Ethernet interface to vlan interface lookup in reference to PR Fix multiple vlan issue sonic-dhcp-relay#27 Exit when socket fails to initialize to allow dhcp_relay docker to restart How to verify it Tested on vstestbed single tor and dual tor, sent packets and verify printed out dhcpmon rx and tx counters is correct Correct number of tx increases Tx does not increase when ToR is on standby --- src/dhcpmon/src/dhcp_device.cpp | 316 ++++++++++++++++++-------------- src/dhcpmon/src/dhcp_device.h | 8 +- 2 files changed, 184 insertions(+), 140 deletions(-) diff --git a/src/dhcpmon/src/dhcp_device.cpp b/src/dhcpmon/src/dhcp_device.cpp index 8ec91b057b64..f4f23526e136 100644 --- a/src/dhcpmon/src/dhcp_device.cpp +++ b/src/dhcpmon/src/dhcp_device.cpp @@ -41,6 +41,7 @@ #define DHCP_OPTIONS_HEADER_SIZE 240 /** Offset of DHCP GIADDR */ #define DHCP_GIADDR_OFFSET 24 +#define CLIENT_IF_PREFIX "Ethernet" #define OP_LDHA (BPF_LD | BPF_H | BPF_ABS) /** bpf ldh Abs */ #define OP_LDHI (BPF_LD | BPF_H | BPF_IND) /** bpf ldh Ind */ @@ -51,19 +52,54 @@ #define OP_JSET (BPF_JMP | BPF_JSET | BPF_K) /** bpf jset */ #define OP_LDXB (BPF_LDX | BPF_B | BPF_MSH) /** bpf ldxb */ +std::shared_ptr mConfigDbPtr = std::make_shared ("CONFIG_DB", 0); std::shared_ptr mStateDbPtr = std::make_shared ("STATE_DB", 0); std::shared_ptr mStateDbMuxTablePtr = std::make_shared ( mStateDbPtr.get(), "HW_MUX_CABLE_TABLE" ); -swss::DBConnector configDb("CONFIG_DB", 0); + +/* interface to vlan mapping */ +std::unordered_map vlan_map; + +/** Berkeley Packet Filter program for "udp and (port 67 or port 68)". + * This program is obtained using the following command tcpdump: + * `tcpdump -dd "outbound and udp and (port 67 or port 68)"` + */ +static struct sock_filter dhcp_outbound_bpf_code[] = { + {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0xfffff004}, // (000) ldh #fffff004 + {.code = OP_JEQ, .jt = 0, .jf = 22, .k = 0x00000004}, // (001) jeq #0x04 jt 0 jf 22 + {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0x0000000c}, // (002) ldh [12] + {.code = OP_JEQ, .jt = 0, .jf = 7, .k = 0x000086dd}, // (003) jeq #0x86dd jt 2 jf 9 + {.code = OP_LDB, .jt = 0, .jf = 0, .k = 0x00000014}, // (004) ldb [20] + {.code = OP_JEQ, .jt = 0, .jf = 18, .k = 0x00000011}, // (005) jeq #0x11 jt 4 jf 22 + {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0x00000036}, // (006) ldh [54] + {.code = OP_JEQ, .jt = 15, .jf = 0, .k = 0x00000043}, // (007) jeq #0x43 jt 21 jf 6 + {.code = OP_JEQ, .jt = 14, .jf = 0, .k = 0x00000044}, // (008) jeq #0x44 jt 21 jf 7 + {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0x00000038}, // (009) ldh [56] + {.code = OP_JEQ, .jt = 12, .jf = 11, .k = 0x00000043}, // (010) jeq #0x43 jt 21 jf 20 + {.code = OP_JEQ, .jt = 0, .jf = 12, .k = 0x00000800}, // (011) jeq #0x800 jt 10 jf 22 + {.code = OP_LDB, .jt = 0, .jf = 0, .k = 0x00000017}, // (012) ldb [23] + {.code = OP_JEQ, .jt = 0, .jf = 10, .k = 0x00000011}, // (013) jeq #0x11 jt 12 jf 22 + {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0x00000014}, // (014) ldh [20] + {.code = OP_JSET, .jt = 8, .jf = 0, .k = 0x00001fff}, // (015) jset #0x1fff jt 22 jf 14 + {.code = OP_LDXB, .jt = 0, .jf = 0, .k = 0x0000000e}, // (016) ldxb 4*([14]&0xf) + {.code = OP_LDHI, .jt = 0, .jf = 0, .k = 0x0000000e}, // (017) ldh [x + 14] + {.code = OP_JEQ, .jt = 4, .jf = 0, .k = 0x00000043}, // (018) jeq #0x43 jt 21 jf 17 + {.code = OP_JEQ, .jt = 3, .jf = 0, .k = 0x00000044}, // (019) jeq #0x44 jt 21 jf 18 + {.code = OP_LDHI, .jt = 0, .jf = 0, .k = 0x00000010}, // (020) ldh [x + 16] + {.code = OP_JEQ, .jt = 1, .jf = 0, .k = 0x00000043}, // (021) jeq #0x43 jt 21 jf 20 + {.code = OP_JEQ, .jt = 0, .jf = 1, .k = 0x00000044}, // (022) jeq #0x44 jt 21 jf 22 + {.code = OP_RET, .jt = 0, .jf = 0, .k = 0x00040000}, // (023) ret #262144 + {.code = OP_RET, .jt = 0, .jf = 0, .k = 0x00000000}, // (024) ret #0 +}; /** Berkeley Packet Filter program for "udp and (port 67 or port 68)". * This program is obtained using the following command tcpdump: * `tcpdump -dd "inbound and udp and (port 67 or port 68)"` */ -static struct sock_filter dhcp_bpf_code[] = { +static struct sock_filter dhcp_inbound_bpf_code[] = { {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0xfffff004}, // (000) ldh #fffff004 - {.code = OP_JEQ, .jt = 22, .jf = 0, .k = 0x00000004}, // (001) jeq #0x04 jt 22 jf 0 + {.code = OP_JEQ, .jt = 22, .jf = 0, .k = 0x00000004}, // (001) jeq #0x04 jt 22 jf 0 {.code = OP_LDHA, .jt = 0, .jf = 0, .k = 0x0000000c}, // (002) ldh [12] {.code = OP_JEQ, .jt = 0, .jf = 7, .k = 0x000086dd}, // (003) jeq #0x86dd jt 2 jf 9 {.code = OP_LDB, .jt = 0, .jf = 0, .k = 0x00000014}, // (004) ldb [20] @@ -90,8 +126,11 @@ static struct sock_filter dhcp_bpf_code[] = { }; /** Filter program socket struct */ -static struct sock_fprog dhcp_sock_bfp = { - .len = sizeof(dhcp_bpf_code) / sizeof(*dhcp_bpf_code), .filter = dhcp_bpf_code +static struct sock_fprog dhcp_outbound_sock_bfp = { + .len = sizeof(dhcp_outbound_bpf_code) / sizeof(*dhcp_outbound_bpf_code), .filter = dhcp_outbound_bpf_code +}; +static struct sock_fprog dhcp_inbound_sock_bfp = { + .len = sizeof(dhcp_inbound_bpf_code) / sizeof(*dhcp_inbound_bpf_code), .filter = dhcp_inbound_bpf_code }; /** Aggregate device of DHCP interfaces. It contains aggregate counters from @@ -107,6 +146,17 @@ static dhcp_message_type_t monitored_msgs[] = { DHCP_MESSAGE_TYPE_ACK }; +void update_vlan_mapping(std::string vlan, std::shared_ptr mConfigDbPtr) { + auto match_pattern = std::string("VLAN_MEMBER|") + vlan + std::string("|*"); + auto keys = mConfigDbPtr->keys(match_pattern); + for (auto &itr : keys) { + auto found = itr.find_last_of('|'); + auto interface = itr.substr(found + 1); + vlan_map[interface] = vlan; + syslog(LOG_INFO, "add <%s, %s> into interface vlan map\n", interface.c_str(), vlan.c_str()); + } +} + /** Number of monitored DHCP message type */ static uint8_t monitored_msg_sz = sizeof(monitored_msgs) / sizeof(*monitored_msgs); @@ -163,9 +213,62 @@ static void handle_dhcp_option_53(dhcp_device_context_t *context, } /** - * @code read_callback(fd, event, arg); + * @code client_packet_handler(dhcp_device_context_t *context, ssize_t buffer_sz); + * + * @brief packet handler to process received rx and tx packets + * + * @param context pointer to device (interface) context + * @param buffer_sz buffer that stores received packet data + * + * @return none + */ +static void client_packet_handler(dhcp_device_context_t *context, ssize_t buffer_sz) +{ + struct ether_header *ethhdr = (struct ether_header*) context->buffer; + struct ip *iphdr = (struct ip*) (context->buffer + IP_START_OFFSET); + struct udphdr *udp = (struct udphdr*) (context->buffer + UDP_START_OFFSET); + uint8_t *dhcphdr = context->buffer + DHCP_START_OFFSET; + int dhcp_option_offset = DHCP_START_OFFSET + DHCP_OPTIONS_HEADER_SIZE; + + if (((unsigned)buffer_sz > UDP_START_OFFSET + sizeof(struct udphdr) + DHCP_OPTIONS_HEADER_SIZE) && + (ntohs(udp->len) > DHCP_OPTIONS_HEADER_SIZE)) + { + int dhcp_sz = ntohs(udp->len) < buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr) ? + ntohs(udp->len) : buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr); + int dhcp_option_sz = dhcp_sz - DHCP_OPTIONS_HEADER_SIZE; + const u_char *dhcp_option = context->buffer + dhcp_option_offset; + dhcp_packet_direction_t dir = (ethhdr->ether_shost[0] == context->mac[0] && + ethhdr->ether_shost[1] == context->mac[1] && + ethhdr->ether_shost[2] == context->mac[2] && + ethhdr->ether_shost[3] == context->mac[3] && + ethhdr->ether_shost[4] == context->mac[4] && + ethhdr->ether_shost[5] == context->mac[5]) ? + DHCP_TX : DHCP_RX; + int offset = 0; + while ((offset < (dhcp_option_sz + 1)) && dhcp_option[offset] != 255) { + if (dhcp_option[offset] == OPTION_DHCP_MESSAGE_TYPE) { + if (offset < (dhcp_option_sz + 2)) { + handle_dhcp_option_53(context, &dhcp_option[offset], dir, iphdr, dhcphdr); + } + break; // break while loop since we are only interested in Option 53 + } + + if (dhcp_option[offset] == 0) { // DHCP Option Padding + offset++; + } else { + offset += dhcp_option[offset + 1] + 2; + } + } + } else { + syslog(LOG_WARNING, "read_callback(%s): read length (%ld) is too small to capture DHCP options", + context->intf, buffer_sz); + } +} + +/** + * @code read_tx_callback(fd, event, arg); * - * @brief callback for libevent which is called every time out in order to read queued packet capture + * @brief callback for libevent which is called every time out in order to read queued outgoing packet capture * * @param fd socket to read from * @param event libevent triggered event @@ -173,68 +276,20 @@ static void handle_dhcp_option_53(dhcp_device_context_t *context, * * @return none */ -static void read_callback(int fd, short event, void *arg) +static void read_tx_callback(int fd, short event, void *arg) { dhcp_device_context_t *context = (dhcp_device_context_t*) arg; ssize_t buffer_sz; - while ((event == EV_READ) && - ((buffer_sz = recv(fd, context->buffer, context->snaplen, MSG_DONTWAIT)) > 0)) { - struct ether_header *ethhdr = (struct ether_header*) context->buffer; - struct ip *iphdr = (struct ip*) (context->buffer + IP_START_OFFSET); - struct udphdr *udp = (struct udphdr*) (context->buffer + UDP_START_OFFSET); - uint8_t *dhcphdr = context->buffer + DHCP_START_OFFSET; - int dhcp_option_offset = DHCP_START_OFFSET + DHCP_OPTIONS_HEADER_SIZE; - - if (((unsigned)buffer_sz > UDP_START_OFFSET + sizeof(struct udphdr) + DHCP_OPTIONS_HEADER_SIZE) && - (ntohs(udp->len) > DHCP_OPTIONS_HEADER_SIZE)) { - int dhcp_sz = ntohs(udp->len) < buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr) ? - ntohs(udp->len) : buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr); - int dhcp_option_sz = dhcp_sz - DHCP_OPTIONS_HEADER_SIZE; - const u_char *dhcp_option = context->buffer + dhcp_option_offset; - dhcp_packet_direction_t dir = (ethhdr->ether_shost[0] == context->mac[0] && - ethhdr->ether_shost[1] == context->mac[1] && - ethhdr->ether_shost[2] == context->mac[2] && - ethhdr->ether_shost[3] == context->mac[3] && - ethhdr->ether_shost[4] == context->mac[4] && - ethhdr->ether_shost[5] == context->mac[5]) ? - DHCP_TX : DHCP_RX; - int offset = 0; - int stop_dhcp_processing = 0; - while ((offset < (dhcp_option_sz + 1)) && dhcp_option[offset] != 255) { - switch (dhcp_option[offset]) - { - case 53: - if (offset < (dhcp_option_sz + 2)) { - handle_dhcp_option_53(context, &dhcp_option[offset], dir, iphdr, dhcphdr); - } - stop_dhcp_processing = 1; // break while loop since we are only interested in Option 53 - break; - default: - break; - } - - if (stop_dhcp_processing == 1) { - break; - } - - if (dhcp_option[offset] == 0) { // DHCP Option Padding - offset++; - } else { - offset += dhcp_option[offset + 1] + 2; - } - } - } else { - syslog(LOG_WARNING, "read_callback(%s): read length (%ld) is too small to capture DHCP options", - context->intf, buffer_sz); - } + while ((buffer_sz = recv(fd, context->buffer, context->snaplen, MSG_DONTWAIT)) > 0) { + client_packet_handler(context, buffer_sz); } } /** - * @code read_callback_dual_tor(fd, event, arg); + * @code read_rx_callback(fd, event, arg); * - * @brief callback for libevent which is called every time out in order to read queued packet capture when dual tor mode is enabled + * @brief callback for libevent which is called every time out in order to read queued incoming packet capture * * @param fd socket to read from * @param event libevent triggered event @@ -242,72 +297,37 @@ static void read_callback(int fd, short event, void *arg) * * @return none */ -static void read_callback_dual_tor(int fd, short event, void *arg) +static void read_rx_callback(int fd, short event, void *arg) { dhcp_device_context_t *context = (dhcp_device_context_t*) arg; ssize_t buffer_sz; struct sockaddr_ll sll; socklen_t slen = sizeof sll; - while ((event == EV_READ) && - ((buffer_sz = recvfrom(fd, context->buffer, context->snaplen, MSG_DONTWAIT, (struct sockaddr *)&sll, &slen)) > 0)) + while ((buffer_sz = recvfrom(fd, context->buffer, context->snaplen, MSG_DONTWAIT, (struct sockaddr *)&sll, &slen)) > 0) { - std::string member_table = std::string("VLAN_MEMBER|") + context->intf + "|"; char interfaceName[IF_NAMESIZE]; - char *interface = if_indextoname(sll.sll_ifindex, interfaceName); - std::string state; - std::string intf(interface); - mStateDbMuxTablePtr->hget(intf, "state", state); - if (state != "standby" && configDb.exists(member_table.append(interface))) { - struct ether_header *ethhdr = (struct ether_header*) context->buffer; - struct ip *iphdr = (struct ip*) (context->buffer + IP_START_OFFSET); - struct udphdr *udp = (struct udphdr*) (context->buffer + UDP_START_OFFSET); - uint8_t *dhcphdr = context->buffer + DHCP_START_OFFSET; - int dhcp_option_offset = DHCP_START_OFFSET + DHCP_OPTIONS_HEADER_SIZE; - - if (((unsigned)buffer_sz > UDP_START_OFFSET + sizeof(struct udphdr) + DHCP_OPTIONS_HEADER_SIZE) && - (ntohs(udp->len) > DHCP_OPTIONS_HEADER_SIZE)) - { - int dhcp_sz = ntohs(udp->len) < buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr) ? - ntohs(udp->len) : buffer_sz - UDP_START_OFFSET - sizeof(struct udphdr); - int dhcp_option_sz = dhcp_sz - DHCP_OPTIONS_HEADER_SIZE; - const u_char *dhcp_option = context->buffer + dhcp_option_offset; - dhcp_packet_direction_t dir = (ethhdr->ether_shost[0] == context->mac[0] && - ethhdr->ether_shost[1] == context->mac[1] && - ethhdr->ether_shost[2] == context->mac[2] && - ethhdr->ether_shost[3] == context->mac[3] && - ethhdr->ether_shost[4] == context->mac[4] && - ethhdr->ether_shost[5] == context->mac[5]) ? - DHCP_TX : DHCP_RX; - int offset = 0; - int stop_dhcp_processing = 0; - while ((offset < (dhcp_option_sz + 1)) && dhcp_option[offset] != 255) { - switch (dhcp_option[offset]) - { - case 53: - if (offset < (dhcp_option_sz + 2)) { - handle_dhcp_option_53(context, &dhcp_option[offset], dir, iphdr, dhcphdr); - } - stop_dhcp_processing = 1; // break while loop since we are only interested in Option 53 - break; - default: - break; - } - - if (stop_dhcp_processing == 1) { - break; - } - - if (dhcp_option[offset] == 0) { // DHCP Option Padding - offset++; - } else { - offset += dhcp_option[offset + 1] + 2; - } - } - } else { - syslog(LOG_WARNING, "read_callback(%s): read length (%ld) is too small to capture DHCP options", - context->intf, buffer_sz); + if (if_indextoname(sll.sll_ifindex, interfaceName) == NULL) { + syslog(LOG_WARNING, "invalid input interface index %d\n", sll.sll_ifindex); + continue; + } + std::string intf(interfaceName); + auto vlan = vlan_map.find(intf); + if (vlan == vlan_map.end()) { + if (intf.find(CLIENT_IF_PREFIX) != std::string::npos) { + syslog(LOG_WARNING, "invalid input interface %s\n", interfaceName); + } + continue; + } + + if (dual_tor_sock) { + std::string state; + mStateDbMuxTablePtr->hget(intf, "state", state); + if (state != "standby") { + client_packet_handler(context, buffer_sz); } + } else { + client_packet_handler(context, buffer_sz); } } } @@ -495,22 +515,33 @@ static int init_socket(dhcp_device_context_t *context, const char *intf) int rv = -1; do { - context->sock = socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, htons(ETH_P_ALL)); - if (context->sock < 0) { + context->rx_sock = socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, htons(ETH_P_ALL)); + context->tx_sock = socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, htons(ETH_P_ALL)); + if (context->rx_sock < 0 || context->tx_sock < 0) { syslog(LOG_ALERT, "socket: failed to open socket with '%s'\n", strerror(errno)); - break; + exit(1); } - struct sockaddr_ll addr; - memset(&addr, 0, sizeof(addr)); - addr.sll_ifindex = 0; // any interface - addr.sll_family = AF_PACKET; - addr.sll_protocol = htons(ETH_P_ALL); - if (bind(context->sock, (struct sockaddr *) &addr, sizeof(addr))) { + struct sockaddr_ll rx_addr; + memset(&rx_addr, 0, sizeof(rx_addr)); + rx_addr.sll_ifindex = 0; // any interface + rx_addr.sll_family = AF_PACKET; + rx_addr.sll_protocol = htons(ETH_P_ALL); + if (bind(context->rx_sock, (struct sockaddr *) &rx_addr, sizeof(rx_addr))) { syslog(LOG_ALERT, "bind: failed to bind to interface '%s' with '%s'\n", intf, strerror(errno)); break; } + struct sockaddr_ll tx_addr; + memset(&tx_addr, 0, sizeof(tx_addr)); + tx_addr.sll_ifindex = if_nametoindex(intf); + tx_addr.sll_family = AF_PACKET; + tx_addr.sll_protocol = htons(ETH_P_ALL); + if (bind(context->tx_sock, (struct sockaddr *) &tx_addr, sizeof(tx_addr))) { + syslog(LOG_ALERT, "bind: failed to bind to interface '%s' with '%s'\n", intf, strerror(errno)); + exit(1); + } + strncpy(context->intf, intf, sizeof(context->intf) - 1); context->intf[sizeof(context->intf) - 1] = '\0'; @@ -644,17 +675,18 @@ int dhcp_device_start_capture(dhcp_device_context_t *context, in_addr_t giaddr_ip) { int rv = -1; - struct event *ev; + struct event *rx_ev; + struct event *tx_ev; do { if (context == NULL) { syslog(LOG_ALERT, "NULL interface context pointer'\n"); - break; + exit(1); } if (snaplen < UDP_START_OFFSET + sizeof(struct udphdr) + DHCP_OPTIONS_HEADER_SIZE) { syslog(LOG_ALERT, "dhcp_device_start_capture(%s): snap length is too low to capture DHCP options", context->intf); - break; + exit(1); } context->giaddr_ip = giaddr_ip; @@ -662,25 +694,31 @@ int dhcp_device_start_capture(dhcp_device_context_t *context, context->buffer = (uint8_t *) malloc(snaplen); if (context->buffer == NULL) { syslog(LOG_ALERT, "malloc: failed to allocate memory for socket buffer '%s'\n", strerror(errno)); - break; + exit(1); } context->snaplen = snaplen; - if (setsockopt(context->sock, SOL_SOCKET, SO_ATTACH_FILTER, &dhcp_sock_bfp, sizeof(dhcp_sock_bfp)) != 0) { + if (setsockopt(context->rx_sock, SOL_SOCKET, SO_ATTACH_FILTER, &dhcp_inbound_sock_bfp, sizeof(dhcp_inbound_sock_bfp)) != 0) { syslog(LOG_ALERT, "setsockopt: failed to attach filter with '%s'\n", strerror(errno)); - break; + exit(1); } - if (dual_tor_sock) - ev = event_new(base, context->sock, EV_READ | EV_PERSIST, read_callback_dual_tor, context); - else - ev = event_new(base, context->sock, EV_READ | EV_PERSIST, read_callback, context); + if (setsockopt(context->tx_sock, SOL_SOCKET, SO_ATTACH_FILTER, &dhcp_outbound_sock_bfp, sizeof(dhcp_outbound_sock_bfp)) != 0) { + syslog(LOG_ALERT, "setsockopt: failed to attach filter with '%s'\n", strerror(errno)); + exit(1); + } + + update_vlan_mapping(context->intf, mConfigDbPtr); - if (ev == NULL) { + rx_ev = event_new(base, context->rx_sock, EV_READ | EV_PERSIST, read_rx_callback, context); + tx_ev = event_new(base, context->tx_sock, EV_READ | EV_PERSIST, read_tx_callback, context); + + if (rx_ev == NULL || tx_ev == NULL) { syslog(LOG_ALERT, "event_new: failed to allocate memory for libevent event '%s'\n", strerror(errno)); - break; + exit(1); } - event_add(ev, NULL); + event_add(rx_ev, NULL); + event_add(tx_ev, NULL); rv = 0; } while (0); diff --git a/src/dhcpmon/src/dhcp_device.h b/src/dhcpmon/src/dhcp_device.h index a2b2a789fca6..2e376ac77e6f 100644 --- a/src/dhcpmon/src/dhcp_device.h +++ b/src/dhcpmon/src/dhcp_device.h @@ -35,6 +35,11 @@ typedef enum DHCP_MESSAGE_TYPE_COUNT } dhcp_message_type_t; +enum +{ + OPTION_DHCP_MESSAGE_TYPE = 53, +}; + /** packet direction */ typedef enum { @@ -71,7 +76,8 @@ typedef enum /** DHCP device (interface) context */ typedef struct { - int sock; /** Raw socket associated with this device/interface */ + int rx_sock; /** Raw socket associated with this device/interface to count rx packets */ + int tx_sock; /** Raw socket associated with this device/interface to count tx packets*/ in_addr_t ip; /** network address of this device (interface) */ uint8_t mac[ETHER_ADDR_LEN]; /** hardware address of this device (interface) */ in_addr_t giaddr_ip; /** Gateway IP address */