diff --git a/.gitmodules b/.gitmodules index dcc3740421ae..261aeecc577a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -112,3 +112,6 @@ [submodule "src/dhcprelay"] path = src/dhcprelay url = https://github.com/sonic-net/sonic-dhcp-relay.git +[submodule "src/dhcpmon"] + path = src/dhcpmon + url = https://github.com/sonic-net/sonic-dhcpmon.git diff --git a/rules/dhcpmon.dep b/rules/dhcpmon.dep index cd8a410a8e95..0a72c375349a 100644 --- a/rules/dhcpmon.dep +++ b/rules/dhcpmon.dep @@ -2,9 +2,10 @@ SPATH := $($(SONIC_DHCPMON)_SRC_PATH) DEP_FILES := $(SONIC_COMMON_FILES_LIST) rules/dhcpmon.mk rules/dhcpmon.dep DEP_FILES += $(SONIC_COMMON_BASE_FILES_LIST) -DEP_FILES += $(shell git ls-files $(SPATH)) +SMDEP_FILES := $(addprefix $(SPATH)/,$(shell cd $(SPATH) && git ls-files)) $(SONIC_DHCPMON)_CACHE_MODE := GIT_CONTENT_SHA $(SONIC_DHCPMON)_DEP_FLAGS := $(SONIC_COMMON_FLAGS_LIST) $(SONIC_DHCPMON)_DEP_FILES := $(DEP_FILES) - +$(SONIC_DHCPMON)_SMDEP_FILES := $(SMDEP_FILES) +$(SONIC_DHCPMON)_SMDEP_PATHS := $(SPATH) \ No newline at end of file diff --git a/src/dhcpmon b/src/dhcpmon new file mode 160000 index 000000000000..fc20a97ba2eb --- /dev/null +++ b/src/dhcpmon @@ -0,0 +1 @@ +Subproject commit fc20a97ba2eba753974ea95d504d130093030596 diff --git a/src/dhcpmon/.gitignore b/src/dhcpmon/.gitignore deleted file mode 100644 index 9d09ae6b3f1a..000000000000 --- a/src/dhcpmon/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -debian/* -!debian/changelog -!debian/compat -!debian/control -!debian/rules diff --git a/src/dhcpmon/Makefile b/src/dhcpmon/Makefile deleted file mode 100644 index 4d21f57199f2..000000000000 --- a/src/dhcpmon/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -RM := rm -rf -DHCPMON_TARGET := dhcpmon -CP := cp -MKDIR := mkdir -CC := g++ -MV := mv -PWD := $(shell pwd) - -# All of the sources participating in the build are defined here --include src/subdir.mk --include objects.mk - -ifneq ($(MAKECMDGOALS),clean) -ifneq ($(strip $(C_DEPS)),) --include $(C_DEPS) -endif -endif - -# Add inputs and outputs from these tool invocations to the build variables - -# All Target -all: sonic-dhcpmon - -# Tool invocations -sonic-dhcpmon: $(OBJS) $(USER_OBJS) - @echo 'Building target: $@' - @echo 'Invoking: G++ C Linker' - $(CC) -o "$(DHCPMON_TARGET)" $(OBJS) $(USER_OBJS) $(LIBS) - @echo 'Finished building target: $@' - @echo ' ' - -# Other Targets -install: - $(MKDIR) -p $(DESTDIR)/usr/sbin - $(MV) $(DHCPMON_TARGET) $(DESTDIR)/usr/sbin - -deinstall: - $(RM) $(DESTDIR)/usr/sbin/$(DHCPMON_TARGET) - $(RM) -rf $(DESTDIR)/usr/sbin - -clean: - -$(RM) $(EXECUTABLES)$(OBJS)$(C_DEPS) $(DHCPMON_TARGET) - -@echo ' ' - -.PHONY: all clean dependents diff --git a/src/dhcpmon/debian/changelog b/src/dhcpmon/debian/changelog deleted file mode 100644 index 83b79d6d93bd..000000000000 --- a/src/dhcpmon/debian/changelog +++ /dev/null @@ -1,5 +0,0 @@ -sonic-dhcpmon (1.0.0-0) UNRELEASED; urgency=medium - - * Initial release. - - -- Tamer Ahmed Mon, 09 Dec 2019 12:00:00 -0700 diff --git a/src/dhcpmon/debian/compat b/src/dhcpmon/debian/compat deleted file mode 100644 index 48082f72f087..000000000000 --- a/src/dhcpmon/debian/compat +++ /dev/null @@ -1 +0,0 @@ -12 diff --git a/src/dhcpmon/debian/control b/src/dhcpmon/debian/control deleted file mode 100644 index c70c274f19fd..000000000000 --- a/src/dhcpmon/debian/control +++ /dev/null @@ -1,14 +0,0 @@ -Source: sonic-dhcpmon -Section: devel -Priority: optional -Maintainer: Tamer Ahmed -Build-Depends: debhelper (>= 12.0.0), libevent-dev, libexplain-dev -Standards-Version: 3.9.3 -Homepage: https://github.com/Azure/sonic-buildimage -XS-Go-Import-Path: github.com/Azure/sonic-buildimage - -Package: sonic-dhcpmon -Architecture: any -Built-Using: ${misc:Built-Using} -Depends: ${shlibs:Depends} -Description: SONiC DHCP Monitor diff --git a/src/dhcpmon/debian/rules b/src/dhcpmon/debian/rules deleted file mode 100755 index 76fc7ea1f839..000000000000 --- a/src/dhcpmon/debian/rules +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/make -f - -export DEB_BUILD_MAINT_OPTIONS=hardening=+all - -DEB_CFLAGS_APPEND=-std=gnu11 -export DEB_CFLAGS_APPEND - -%: - dh $@ --parallel diff --git a/src/dhcpmon/objects.mk b/src/dhcpmon/objects.mk deleted file mode 100644 index dc0d09e5021f..000000000000 --- a/src/dhcpmon/objects.mk +++ /dev/null @@ -1,4 +0,0 @@ -USER_OBJS := - -LIBS := -levent -lexplain -lswsscommon -pthread -lboost_thread -lboost_system -lhiredis - diff --git a/src/dhcpmon/src/dhcp_device.cpp b/src/dhcpmon/src/dhcp_device.cpp deleted file mode 100644 index ac46ef6d1351..000000000000 --- a/src/dhcpmon/src/dhcp_device.cpp +++ /dev/null @@ -1,868 +0,0 @@ -/** - * @file dhcp_device.c - * - * device (interface) module - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "subscriberstatetable.h" -#include "select.h" - -#include "dhcp_devman.h" -#include "dhcp_device.h" - -/** Counter print width */ -#define DHCP_COUNTER_WIDTH 9 - -/** Start of Ether header of a captured frame */ -#define ETHER_START_OFFSET 0 -/** Start of IP header of a captured frame */ -#define IP_START_OFFSET (ETHER_START_OFFSET + ETHER_HDR_LEN) -/** Start of UDP header of a captured frame */ -#define UDP_START_OFFSET (IP_START_OFFSET + sizeof(struct ip)) -/** Start of DHCP header of a captured frame */ -#define DHCP_START_OFFSET (UDP_START_OFFSET + sizeof(struct udphdr)) -/** Start of DHCP Options segment of a captured frame */ -#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 */ -#define OP_LDB (BPF_LD | BPF_B | BPF_ABS) /** bpf ldb Abs*/ -#define OP_JEQ (BPF_JMP | BPF_JEQ | BPF_K) /** bpf jeq */ -#define OP_JGT (BPF_JMP | BPF_JGT | BPF_K) /** bpf jgt */ -#define OP_RET (BPF_RET | BPF_K) /** bpf ret */ -#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" - ); - -/* interface to vlan mapping */ -std::unordered_map vlan_map; - -/* interface to port-channel mapping */ -std::unordered_map portchan_map; - -/* interface to mgmt port mapping */ -std::unordered_map mgmt_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_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_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 -}; - -/** Filter program socket struct */ -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 -}; - -static uint8_t *rx_recv_buffer = NULL; -static uint8_t *tx_recv_buffer = NULL; -static uint32_t snap_length; - -/** Aggregate device of DHCP interfaces. It contains aggregate counters from - all interfaces - */ -static dhcp_device_context_t aggregate_dev = {0}; - -/** Monitored DHCP message type */ -static dhcp_message_type_t monitored_msgs[] = { - DHCP_MESSAGE_TYPE_DISCOVER, - DHCP_MESSAGE_TYPE_OFFER, - DHCP_MESSAGE_TYPE_REQUEST, - DHCP_MESSAGE_TYPE_ACK -}; - -/** update ethernet interface to vlan map - * VLAN_MEMBER|Vlan1000|Ethernet48 - */ -void update_vlan_mapping(std::shared_ptr db_conn) { - auto match_pattern = std::string("VLAN_MEMBER|*"); - auto keys = db_conn->keys(match_pattern); - for (auto &itr : keys) { - auto first = itr.find_first_of('|'); - auto second = itr.find_last_of('|'); - auto vlan = itr.substr(first + 1, second - first - 1); - auto interface = itr.substr(second + 1); - vlan_map[interface] = vlan; - syslog(LOG_INFO, "add <%s, %s> into interface vlan map\n", interface.c_str(), vlan.c_str()); - } -} - -/** update ethernet interface to port-channel map - * PORTCHANNEL_MEMBER|PortChannel101|Ethernet112 - */ -void update_portchannel_mapping(std::shared_ptr db_conn) { - auto match_pattern = std::string("PORTCHANNEL_MEMBER|*"); - auto keys = db_conn->keys(match_pattern); - for (auto &itr : keys) { - auto first = itr.find_first_of('|'); - auto second = itr.find_last_of('|'); - auto portchannel = itr.substr(first + 1, second - first - 1); - auto interface = itr.substr(second + 1); - portchan_map[interface] = portchannel; - syslog(LOG_INFO, "add <%s, %s> into interface port-channel map\n", interface.c_str(), portchannel.c_str()); - } -} - -/** update interface to mgmt map - */ -void update_mgmt_mapping() { - auto mgmt = dhcp_devman_get_mgmt_dev(); - if (mgmt) { - auto name = std::string(mgmt->intf); - mgmt_map[name] = name; - } -} - -dhcp_device_context_t *find_device_context(std::unordered_map *intfs, std::string if_name) { - auto intf = intfs->find(if_name); - if (intf == intfs->end()) { - return NULL; - } - return intf->second->dev_context; -} - -/** Number of monitored DHCP message type */ -static uint8_t monitored_msg_sz = sizeof(monitored_msgs) / sizeof(*monitored_msgs); - -/** - * @code handle_dhcp_option_53(context, dhcp_option, dir, iphdr, dhcphdr); - * - * @brief handle the logic related to DHCP option 53 - * - * @param context Device (interface) context - * @param dhcp_option pointer to DHCP option buffer space - * @param dir packet direction - * @param iphdr pointer to packet IP header - * @param dhcphdr pointer to DHCP header - * - * @return none - */ -static void handle_dhcp_option_53(dhcp_device_context_t *context, - const u_char *dhcp_option, - dhcp_packet_direction_t dir, - struct ip *iphdr, - uint8_t *dhcphdr) -{ - in_addr_t giaddr; - switch (dhcp_option[2]) - { - // DHCP messages send by client - case DHCP_MESSAGE_TYPE_DISCOVER: - case DHCP_MESSAGE_TYPE_REQUEST: - case DHCP_MESSAGE_TYPE_DECLINE: - case DHCP_MESSAGE_TYPE_RELEASE: - case DHCP_MESSAGE_TYPE_INFORM: - giaddr = ntohl(dhcphdr[DHCP_GIADDR_OFFSET] << 24 | dhcphdr[DHCP_GIADDR_OFFSET + 1] << 16 | - dhcphdr[DHCP_GIADDR_OFFSET + 2] << 8 | dhcphdr[DHCP_GIADDR_OFFSET + 3]); - if ((context->giaddr_ip == giaddr && context->is_uplink && dir == DHCP_TX) || - (!context->is_uplink && dir == DHCP_RX && iphdr->ip_dst.s_addr == INADDR_BROADCAST)) { - context->counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++; - aggregate_dev.counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++; - } - break; - // DHCP messages send by server - case DHCP_MESSAGE_TYPE_OFFER: - case DHCP_MESSAGE_TYPE_ACK: - case DHCP_MESSAGE_TYPE_NAK: - if ((context->giaddr_ip == iphdr->ip_dst.s_addr && context->is_uplink && dir == DHCP_RX) || - (!context->is_uplink && dir == DHCP_TX)) { - context->counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++; - aggregate_dev.counters[DHCP_COUNTERS_CURRENT][dir][dhcp_option[2]]++; - } - break; - default: - syslog(LOG_WARNING, "handle_dhcp_option_53(%s): Unknown DHCP option 53 type %d", context->intf, dhcp_option[2]); - break; - } -} - -/** - * @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, uint8_t *buffer, - ssize_t buffer_sz, dhcp_packet_direction_t dir) -{ - struct ip *iphdr = (struct ip*) (buffer + IP_START_OFFSET); - struct udphdr *udp = (struct udphdr*) (buffer + UDP_START_OFFSET); - uint8_t *dhcphdr = 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 = buffer + dhcp_option_offset; - - 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; - } - } - } -} - -static dhcp_device_context_t *interface_to_dev_context(std::unordered_map *devices, - std::string ifname) -{ - auto vlan = vlan_map.find(ifname); - if (vlan != vlan_map.end()) { - if (dual_tor_sock) { - std::string state; - mStateDbMuxTablePtr->hget(ifname, "state", state); - if (state == "standby") { - return NULL; - } - } - return find_device_context(devices, vlan->second); - } else { - auto port_channel = portchan_map.find(ifname); - if (port_channel != portchan_map.end()) { - return find_device_context(devices, port_channel->second); - } - else { - // mgmt interface check - auto mgmt = mgmt_map.find(ifname); - if (mgmt != mgmt_map.end()) { - return find_device_context(devices, mgmt->second); - } - } - } - return NULL; -} - - -/** - * @code read_tx_callback(fd, event, arg); - * - * @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 - * @param arg user provided argument for callback (interface context) - * - * @return none - */ -static void read_tx_callback(int fd, short event, void *arg) -{ - auto devices = (std::unordered_map *)arg; - ssize_t buffer_sz; - struct sockaddr_ll sll; - socklen_t slen = sizeof sll; - dhcp_device_context_t *context = NULL; - - while ((buffer_sz = recvfrom(fd, tx_recv_buffer, snap_length, MSG_DONTWAIT, (struct sockaddr *)&sll, &slen)) > 0) - { - char interfaceName[IF_NAMESIZE]; - if (if_indextoname(sll.sll_ifindex, interfaceName) == NULL) { - syslog(LOG_WARNING, "invalid output interface index %d\n", sll.sll_ifindex); - continue; - } - std::string intf(interfaceName); - context = find_device_context(devices, intf); - if (context) { - client_packet_handler(context, tx_recv_buffer, buffer_sz, DHCP_TX); - } - } -} - -/** - * @code read_rx_callback(fd, event, arg); - * - * @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 - * @param arg user provided argument for callback (interface context) - * - * @return none - */ -static void read_rx_callback(int fd, short event, void *arg) -{ - auto devices = (std::unordered_map *)arg; - ssize_t buffer_sz; - struct sockaddr_ll sll; - socklen_t slen = sizeof(sll); - dhcp_device_context_t *context = NULL; - - while ((buffer_sz = recvfrom(fd, rx_recv_buffer, snap_length, MSG_DONTWAIT, (struct sockaddr *)&sll, &slen)) > 0) - { - char interfaceName[IF_NAMESIZE]; - 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); - context = interface_to_dev_context(devices, intf); - if (context) { - client_packet_handler(context, rx_recv_buffer, buffer_sz, DHCP_RX); - } - } -} - -/** - * @code dhcp_device_is_dhcp_inactive(counters); - * - * @brief Check if there were no DHCP activity - * - * @param counters current/snapshot counter - * - * @return true if there were no DHCP activity, false otherwise - */ -static bool dhcp_device_is_dhcp_inactive(uint64_t counters[][DHCP_DIR_COUNT][DHCP_MESSAGE_TYPE_COUNT]) -{ - uint64_t *rx_counters = counters[DHCP_COUNTERS_CURRENT][DHCP_RX]; - uint64_t *rx_counter_snapshot = counters[DHCP_COUNTERS_SNAPSHOT][DHCP_RX]; - - bool rv = true; - for (uint8_t i = 0; (i < monitored_msg_sz) && rv; i++) { - rv = rx_counters[monitored_msgs[i]] == rx_counter_snapshot[monitored_msgs[i]]; - } - - return rv; -} - -/** - * @code dhcp_device_is_dhcp_msg_unhealthy(type, counters); - * - * @brief Check if DHCP relay is functioning properly for message of type 'type'. - * For every rx of message 'type', there should be increment of the same message type. - * - * @param type DHCP message type - * @param counters current/snapshot counter - * - * @return true if DHCP message 'type' is transmitted,false otherwise - */ -static bool dhcp_device_is_dhcp_msg_unhealthy(dhcp_message_type_t type, - uint64_t counters[][DHCP_DIR_COUNT][DHCP_MESSAGE_TYPE_COUNT]) -{ - // check if DHCP message 'type' is being relayed - return ((counters[DHCP_COUNTERS_CURRENT][DHCP_RX][type] > counters[DHCP_COUNTERS_SNAPSHOT][DHCP_RX][type]) && - (counters[DHCP_COUNTERS_CURRENT][DHCP_TX][type] <= counters[DHCP_COUNTERS_SNAPSHOT][DHCP_TX][type]) ); -} - -/** - * @code dhcp_device_check_positive_health(counters, counters_snapshot); - * - * @brief Check if DHCP relay is functioning properly for monitored messages (Discover, Offer, Request, ACK.) - * For every rx of monitored messages, there should be increment of the same message type. - * - * @param counters current/snapshot counter - * - * @return DHCP_MON_STATUS_HEALTHY, DHCP_MON_STATUS_UNHEALTHY, or DHCP_MON_STATUS_INDETERMINATE - */ -static dhcp_mon_status_t dhcp_device_check_positive_health(uint64_t counters[][DHCP_DIR_COUNT][DHCP_MESSAGE_TYPE_COUNT]) -{ - dhcp_mon_status_t rv = DHCP_MON_STATUS_HEALTHY; - - bool is_dhcp_unhealthy = false; - for (uint8_t i = 0; (i < monitored_msg_sz) && !is_dhcp_unhealthy; i++) { - is_dhcp_unhealthy = dhcp_device_is_dhcp_msg_unhealthy(monitored_msgs[i], counters); - } - - // if we have rx DORA then we should have corresponding tx DORA (DORA being relayed) - if (is_dhcp_unhealthy) { - rv = DHCP_MON_STATUS_UNHEALTHY; - } - - return rv; -} - -/** - * @code dhcp_device_check_negative_health(counters); - * - * @brief Check that DHCP relayed messages are not being transmitted out of this interface/dev - * using its counters. The interface is negatively healthy if there are not DHCP message - * travelling through it. - * - * @param counters recent interface counter - * @param counters_snapshot snapshot counters - * - * @return DHCP_MON_STATUS_HEALTHY, DHCP_MON_STATUS_UNHEALTHY, or DHCP_MON_STATUS_INDETERMINATE - */ -static dhcp_mon_status_t dhcp_device_check_negative_health(uint64_t counters[][DHCP_DIR_COUNT][DHCP_MESSAGE_TYPE_COUNT]) -{ - dhcp_mon_status_t rv = DHCP_MON_STATUS_HEALTHY; - - uint64_t *tx_counters = counters[DHCP_COUNTERS_CURRENT][DHCP_TX]; - uint64_t *tx_counter_snapshot = counters[DHCP_COUNTERS_SNAPSHOT][DHCP_TX]; - - bool is_dhcp_unhealthy = false; - for (uint8_t i = 0; (i < monitored_msg_sz) && !is_dhcp_unhealthy; i++) { - is_dhcp_unhealthy = tx_counters[monitored_msgs[i]] > tx_counter_snapshot[monitored_msgs[i]]; - } - - // for negative validation, return unhealthy if DHCP packet are being - // transmitted out of the device/interface - if (is_dhcp_unhealthy) { - rv = DHCP_MON_STATUS_UNHEALTHY; - } - - return rv; -} - -/** - * @code dhcp_device_check_health(check_type, counters, counters_snapshot); - * - * @brief Check that DHCP relay is functioning properly given a check type. Positive check - * indicates for every rx of DHCP message of type 'type', there would increment of - * the corresponding TX of the same message type. While negative check indicates the - * device should not be actively transmitting any DHCP messages. If it does, it is - * considered unhealthy. - * - * @param check_type type of health check - * @param counters current/snapshot counter - * - * @return DHCP_MON_STATUS_HEALTHY, DHCP_MON_STATUS_UNHEALTHY, or DHCP_MON_STATUS_INDETERMINATE - */ -static dhcp_mon_status_t dhcp_device_check_health(dhcp_mon_check_t check_type, - uint64_t counters[][DHCP_DIR_COUNT][DHCP_MESSAGE_TYPE_COUNT]) -{ - dhcp_mon_status_t rv = DHCP_MON_STATUS_HEALTHY; - - if (dhcp_device_is_dhcp_inactive(aggregate_dev.counters)) { - rv = DHCP_MON_STATUS_INDETERMINATE; - } else if (check_type == DHCP_MON_CHECK_POSITIVE) { - rv = dhcp_device_check_positive_health(counters); - } else if (check_type == DHCP_MON_CHECK_NEGATIVE) { - rv = dhcp_device_check_negative_health(counters); - } - - return rv; -} - -/** - * @code dhcp_print_counters(vlan_intf, type, counters); - * - * @brief prints DHCP counters to sylsog. - * - * @param vlan_intf vlan interface name - * @param type counter type - * @param counters interface counter - * - * @return none - */ -static void dhcp_print_counters(const char *vlan_intf, - dhcp_counters_type_t type, - uint64_t counters[][DHCP_MESSAGE_TYPE_COUNT]) -{ - static const char *counter_desc[DHCP_COUNTERS_COUNT] = { - [DHCP_COUNTERS_CURRENT] = " Current", - [DHCP_COUNTERS_SNAPSHOT] = "Snapshot" - }; - - syslog( - LOG_NOTICE, - "[%*s-%*s rx/tx] Discover: %*" PRIu64 "/%*" PRIu64 ", Offer: %*" PRIu64 "/%*" PRIu64 - ", Request: %*" PRIu64 "/%*" PRIu64 ", ACK: %*" PRIu64 "/%*" PRIu64 "\n", - IF_NAMESIZE, vlan_intf, - (int) strlen(counter_desc[type]), counter_desc[type], - DHCP_COUNTER_WIDTH, counters[DHCP_RX][DHCP_MESSAGE_TYPE_DISCOVER], - DHCP_COUNTER_WIDTH, counters[DHCP_TX][DHCP_MESSAGE_TYPE_DISCOVER], - DHCP_COUNTER_WIDTH, counters[DHCP_RX][DHCP_MESSAGE_TYPE_OFFER], - DHCP_COUNTER_WIDTH, counters[DHCP_TX][DHCP_MESSAGE_TYPE_OFFER], - DHCP_COUNTER_WIDTH, counters[DHCP_RX][DHCP_MESSAGE_TYPE_REQUEST], - DHCP_COUNTER_WIDTH, counters[DHCP_TX][DHCP_MESSAGE_TYPE_REQUEST], - DHCP_COUNTER_WIDTH, counters[DHCP_RX][DHCP_MESSAGE_TYPE_ACK], - DHCP_COUNTER_WIDTH, counters[DHCP_TX][DHCP_MESSAGE_TYPE_ACK] - ); -} - -/** - * @code init_socket(); - * - * @brief initializes rx/tx sockets, bind it to interface and bpf program - * - * @return 0 on success, otherwise for failure - */ -static int init_socket() -{ - int rv = -1; - - do { - auto rx_sock = socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, htons(ETH_P_ALL)); - auto tx_sock = socket(AF_PACKET, SOCK_RAW | SOCK_NONBLOCK, htons(ETH_P_ALL)); - if (rx_sock < 0 || tx_sock < 0) { - syslog(LOG_ALERT, "socket: failed to open socket with '%s'\n", strerror(errno)); - exit(1); - } - - 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(rx_sock, (struct sockaddr *) &rx_addr, sizeof(rx_addr))) { - syslog(LOG_ALERT, "bind: failed to bind to all interface with '%s'\n", strerror(errno)); - break; - } - - struct sockaddr_ll tx_addr; - memset(&tx_addr, 0, sizeof(tx_addr)); - tx_addr.sll_ifindex = 0; // any interface - tx_addr.sll_family = AF_PACKET; - tx_addr.sll_protocol = htons(ETH_P_ALL); - if (bind(tx_sock, (struct sockaddr *) &tx_addr, sizeof(tx_addr))) { - syslog(LOG_ALERT, "bind: failed to bind to interface with '%s'\n", strerror(errno)); - exit(1); - } - - for (auto &itr : intfs) { - itr.second->dev_context->rx_sock = rx_sock; - itr.second->dev_context->tx_sock = tx_sock; - } - rv = 0; - } while (0); - - return rv; -} - -static void init_recv_buffers(int snaplen) -{ - snap_length = snaplen; - rx_recv_buffer = (uint8_t *) malloc(snaplen); - if (rx_recv_buffer == NULL) { - syslog(LOG_ALERT, "malloc: failed to allocate memory for socket rx buffer '%s'\n", strerror(errno)); - exit(1); - } - - tx_recv_buffer = (uint8_t *) malloc(snaplen); - if (tx_recv_buffer == NULL) { - syslog(LOG_ALERT, "malloc: failed to allocate memory for socket tx buffer '%s'\n", strerror(errno)); - exit(1); - } -} - -/** - * @code initialize_intf_mac_and_ip_addr(context); - * - * @brief initializes device (interface) mac/ip addresses - * - * @param context pointer to device (interface) context - * - * @return 0 on success, otherwise for failure - */ -int initialize_intf_mac_and_ip_addr(dhcp_device_context_t *context) -{ - int rv = -1; - - do { - int fd; - struct ifreq ifr; - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { - syslog(LOG_ALERT, "socket: %s", strerror(errno)); - break; - } - - ifr.ifr_addr.sa_family = AF_INET; - strncpy(ifr.ifr_name, context->intf, sizeof(ifr.ifr_name) - 1); - ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0'; - - // Get network address - if (ioctl(fd, SIOCGIFADDR, &ifr) == -1) { - syslog(LOG_ALERT, "ioctl: %s", explain_ioctl(fd, SIOCGIFADDR, &ifr)); - break; - } - context->ip = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; - - // Get mac address - if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) { - syslog(LOG_ALERT, "ioctl: %s", explain_ioctl(fd, SIOCGIFHWADDR, &ifr)); - break; - } - memcpy(context->mac, ifr.ifr_hwaddr.sa_data, sizeof(context->mac)); - - close(fd); - - rv = 0; - } while (0); - - return rv; -} - -/** - * @code dhcp_device_get_ip(context); - * - * @brief Accessor method - * - * @param context pointer to device (interface) context - * - * @return interface IP - */ -int dhcp_device_get_ip(dhcp_device_context_t *context, in_addr_t *ip) -{ - int rv = -1; - - if (context != NULL && ip != NULL) { - *ip = context->ip; - rv = 0; - } - - return rv; -} - -/** - * @code dhcp_device_get_aggregate_context(); - * - * @brief Accessor method - * - * @return pointer to aggregate device (interface) context - */ -dhcp_device_context_t* dhcp_device_get_aggregate_context() -{ - return &aggregate_dev; -} - -/** - * @code dhcp_device_init(context, intf, is_uplink); - * - * @brief initializes device (interface) that handles packet capture per interface. - */ -int dhcp_device_init(dhcp_device_context_t **context, const char *intf, uint8_t is_uplink) -{ - int rv = -1; - dhcp_device_context_t *dev_context = NULL; - - if ((context != NULL) && (strlen(intf) < sizeof(dev_context->intf))) { - dev_context = (dhcp_device_context_t *) malloc(sizeof(dhcp_device_context_t)); - if (dev_context != NULL) { - // set device name - strncpy(dev_context->intf, intf, sizeof(dev_context->intf) - 1); - dev_context->intf[sizeof(dev_context->intf) - 1] = '\0'; - // set device meta data - if (initialize_intf_mac_and_ip_addr(dev_context) == 0) { - dev_context->is_uplink = is_uplink; - memset(dev_context->counters, 0, sizeof(dev_context->counters)); - *context = dev_context; - rv = 0; - } - } - else { - syslog(LOG_ALERT, "malloc: failed to allocated device context memory for '%s'", dev_context->intf); - } - } - - return rv; -} - -/** - * @code dhcp_device_start_capture(snaplen, base, giaddr_ip); - * - * @brief starts packet capture on this interface - */ -int dhcp_device_start_capture(size_t snaplen, struct event_base *base, in_addr_t giaddr_ip) -{ - int rv = -1; - struct event *rx_ev; - struct event *tx_ev; - int rx_sock = -1, tx_sock = -1; - - do { - if (snaplen < UDP_START_OFFSET + sizeof(struct udphdr) + DHCP_OPTIONS_HEADER_SIZE) { - syslog(LOG_ALERT, "dhcp_device_start_capture: snap length is too low to capture DHCP options"); - exit(1); - } - - init_socket(); - - init_recv_buffers(snaplen); - - update_vlan_mapping(mConfigDbPtr); - update_portchannel_mapping(mConfigDbPtr); - update_mgmt_mapping(); - - for (auto &itr : intfs) { - itr.second->dev_context->snaplen = snaplen; - itr.second->dev_context->giaddr_ip = giaddr_ip; - // all interface dev context has same rx/tx socket - rx_sock = itr.second->dev_context->rx_sock; - tx_sock = itr.second->dev_context->tx_sock; - } - - if (rx_sock == -1 || tx_sock == -1) { - syslog(LOG_ALERT, "dhcp_device_start_capture: invalid rx_sock or tx_sock"); - exit(1); - } - if (setsockopt(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)); - exit(1); - } - - if (setsockopt(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); - } - - rx_ev = event_new(base, rx_sock, EV_READ | EV_PERSIST, read_rx_callback, &intfs); - tx_ev = event_new(base, tx_sock, EV_READ | EV_PERSIST, read_tx_callback, &intfs); - - if (rx_ev == NULL || tx_ev == NULL) { - syslog(LOG_ALERT, "event_new: failed to allocate memory for libevent event '%s'\n", strerror(errno)); - exit(1); - } - event_add(rx_ev, NULL); - event_add(tx_ev, NULL); - - rv = 0; - } while (0); - - return rv; -} - -/** - * @code dhcp_device_shutdown(context); - * - * @brief shuts down device (interface). Also, stops packet capture on interface and cleans up any allocated memory - */ -void dhcp_device_shutdown(dhcp_device_context_t *context) -{ - free(context); -} - -/** - * @code dhcp_device_get_status(check_type, context); - * - * @brief collects DHCP relay status info for a given interface. If context is null, it will report aggregate - * status - */ -dhcp_mon_status_t dhcp_device_get_status(dhcp_mon_check_t check_type, dhcp_device_context_t *context) -{ - dhcp_mon_status_t rv = DHCP_MON_STATUS_HEALTHY; - - if (context != NULL) { - rv = dhcp_device_check_health(check_type, context->counters); - } - - return rv; -} - -/** - * @code dhcp_device_update_snapshot(context); - * - * @brief Update device/interface counters snapshot - */ -void dhcp_device_update_snapshot(dhcp_device_context_t *context) -{ - if (context != NULL) { - memcpy(context->counters[DHCP_COUNTERS_SNAPSHOT], - context->counters[DHCP_COUNTERS_CURRENT], - sizeof(context->counters[DHCP_COUNTERS_SNAPSHOT])); - } -} - -/** - * @code dhcp_device_print_status(context, type); - * - * @brief prints status counters to syslog. - */ -void dhcp_device_print_status(dhcp_device_context_t *context, dhcp_counters_type_t type) -{ - if (context != NULL) { - dhcp_print_counters(context->intf, type, context->counters[type]); - } -} diff --git a/src/dhcpmon/src/dhcp_device.h b/src/dhcpmon/src/dhcp_device.h deleted file mode 100644 index cd8eab1ee7eb..000000000000 --- a/src/dhcpmon/src/dhcp_device.h +++ /dev/null @@ -1,197 +0,0 @@ -/** - * @file dhcp_device.h - * - * device (interface) module - */ - -#ifndef DHCP_DEVICE_H_ -#define DHCP_DEVICE_H_ - -#include -#include -#include -#include - -#include -#include -#include - -extern bool dual_tor_sock; -extern std::unordered_map intfs; - -/** - * DHCP message types - **/ -typedef enum -{ - DHCP_MESSAGE_TYPE_DISCOVER = 1, - DHCP_MESSAGE_TYPE_OFFER = 2, - DHCP_MESSAGE_TYPE_REQUEST = 3, - DHCP_MESSAGE_TYPE_DECLINE = 4, - DHCP_MESSAGE_TYPE_ACK = 5, - DHCP_MESSAGE_TYPE_NAK = 6, - DHCP_MESSAGE_TYPE_RELEASE = 7, - DHCP_MESSAGE_TYPE_INFORM = 8, - - DHCP_MESSAGE_TYPE_COUNT -} dhcp_message_type_t; - -enum -{ - OPTION_DHCP_MESSAGE_TYPE = 53, -}; - -/** packet direction */ -typedef enum -{ - DHCP_RX, /** RX DHCP packet */ - DHCP_TX, /** TX DHCP packet */ - - DHCP_DIR_COUNT -} dhcp_packet_direction_t; - -/** counters type */ -typedef enum -{ - DHCP_COUNTERS_CURRENT, /** DHCP current counters */ - DHCP_COUNTERS_SNAPSHOT, /** DHCP snapshot counters */ - - DHCP_COUNTERS_COUNT -} dhcp_counters_type_t; - -/** dhcp health status */ -typedef enum -{ - DHCP_MON_STATUS_HEALTHY, /** DHCP relay is healthy */ - DHCP_MON_STATUS_UNHEALTHY, /** DHCP relay is unhealthy and is missing out on some packets */ - DHCP_MON_STATUS_INDETERMINATE, /** DHCP relay health could not be determined */ -} dhcp_mon_status_t; - -/** dhcp check type */ -typedef enum -{ - DHCP_MON_CHECK_NEGATIVE, /** Presence of relayed DHCP packets activity is flagged as unhealthy state */ - DHCP_MON_CHECK_POSITIVE, /** Validate that received DORA packets are relayed */ -} dhcp_mon_check_t; - -/** DHCP device (interface) context */ -typedef struct -{ - 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 */ - uint8_t is_uplink; /** north interface? */ - char intf[IF_NAMESIZE]; /** device (interface) name */ - size_t snaplen; /** snap length or buffer size */ - uint64_t counters[DHCP_COUNTERS_COUNT][DHCP_DIR_COUNT][DHCP_MESSAGE_TYPE_COUNT]; - /** current/snapshot counters of DHCP packets */ -} dhcp_device_context_t; - -/** - * @code initialize_intf_mac_and_ip_addr(context); - * - * @brief initializes device (interface) mac/ip addresses - * - * @param context pointer to device (interface) context - * - * @return 0 on success, otherwise for failure - */ -int initialize_intf_mac_and_ip_addr(dhcp_device_context_t *context); - -/** - * @code dhcp_device_get_ip(context, ip); - * - * @brief Accessor method - * - * @param context pointer to device (interface) context - * @param ip(out) pointer to device IP - * - * @return 0 on success, otherwise for failure - */ -int dhcp_device_get_ip(dhcp_device_context_t *context, in_addr_t *ip); - -/** - * @code dhcp_device_get_aggregate_context(); - * - * @brief Accessor method - * - * @return pointer to aggregate device (interface) context - */ -dhcp_device_context_t* dhcp_device_get_aggregate_context(); - -/** - * @code dhcp_device_init(context, intf, is_uplink); - * - * @brief initializes device (interface) that handles packet capture per interface. - * - * @param context(inout) pointer to device (interface) context - * @param intf interface name - * @param is_uplink uplink interface - * - * @return 0 on success, otherwise for failure - */ -int dhcp_device_init(dhcp_device_context_t **context, - const char *intf, - uint8_t is_uplink); - -/** - * @code dhcp_device_start_capture(snaplen, base, giaddr_ip); - * - * @brief starts packet capture on this interface - * - * @param snaplen length of packet capture - * @param base pointer to libevent base - * @param giaddr_ip gateway IP address - * - * @return 0 on success, otherwise for failure - */ -int dhcp_device_start_capture(size_t snaplen, struct event_base *base, in_addr_t giaddr_ip); - -/** - * @code dhcp_device_shutdown(context); - * - * @brief shuts down device (interface). Also, stops packet capture on interface and cleans up any allocated memory - * - * @param context Device (interface) context - * - * @return nonedhcp_device_shutdown - */ -void dhcp_device_shutdown(dhcp_device_context_t *context); - -/** - * @code dhcp_device_get_status(check_type, context); - * - * @brief collects DHCP relay status info for a given interface. If context is null, it will report aggregate - * status - * - * @param check_type Type of validation - * @param context Device (interface) context - * - * @return DHCP_MON_STATUS_HEALTHY, DHCP_MON_STATUS_UNHEALTHY, or DHCP_MON_STATUS_INDETERMINATE - */ -dhcp_mon_status_t dhcp_device_get_status(dhcp_mon_check_t check_type, dhcp_device_context_t *context); - -/** - * @code dhcp_device_update_snapshot(context); - * - * @param context Device (interface) context - * - * @brief Update device/interface counters snapshot - */ -void dhcp_device_update_snapshot(dhcp_device_context_t *context); - -/** - * @code dhcp_device_print_status(context, type); - * - * @brief prints status counters to syslog. If context is null, it will print aggregate status - * - * @param context Device (interface) context - * @param counters_type Counter type to be printed - * - * @return none - */ -void dhcp_device_print_status(dhcp_device_context_t *context, dhcp_counters_type_t type); - -#endif /* DHCP_DEVICE_H_ */ diff --git a/src/dhcpmon/src/dhcp_devman.cpp b/src/dhcpmon/src/dhcp_devman.cpp deleted file mode 100644 index 0fa490d138bd..000000000000 --- a/src/dhcpmon/src/dhcp_devman.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/** - * @file dhcp_devman.c - * - * Device (interface) manager - */ -#include -#include -#include -#include -#include - -#include "dhcp_devman.h" - -/** Prefix appended to Aggregation device */ -#define AGG_DEV_PREFIX "Agg-" - -/** intfs map of interfaces */ -std::unordered_map intfs; -/** dhcp_num_south_intf number of south interfaces */ -static uint32_t dhcp_num_south_intf = 0; -/** dhcp_num_north_intf number of north interfaces */ -static uint32_t dhcp_num_north_intf = 0; -/** dhcp_num_mgmt_intf number of mgmt interfaces */ -static uint32_t dhcp_num_mgmt_intf = 0; - -/** On Device vlan interface IP address corresponding vlan downlink IP - * This IP is used to filter Offer/Ack packet coming from DHCP server */ -static in_addr_t vlan_ip = 0; - -/* Device loopback interface ip, which will be used as the giaddr in dual tor setup. */ -static in_addr_t loopback_ip = 0; - -/* Whether the device is in dual tor mode, 0 as default for single tor mode. */ -static int dual_tor_mode = 0; - -/** mgmt interface */ -static struct intf *mgmt_intf = NULL; - -/** - * @code dhcp_devman_get_vlan_intf(); - * - * Accessor method - */ -dhcp_device_context_t* dhcp_devman_get_agg_dev() -{ - return dhcp_device_get_aggregate_context(); -} - -/** - * @code dhcp_devman_get_mgmt_dev(); - * - * Accessor method - */ -dhcp_device_context_t* dhcp_devman_get_mgmt_dev() -{ - return mgmt_intf ? mgmt_intf->dev_context : NULL; -} - -/** - * @code dhcp_devman_shutdown(); - * - * shuts down device (interface) manager. Also, stops packet capture on interface and cleans up any allocated - * memory - */ -void dhcp_devman_shutdown() -{ - for (auto it = intfs.begin(); it != intfs.end();) { - auto inf = it->second; - dhcp_device_shutdown(inf->dev_context); - it = intfs.erase(it); - free(inf); - } -} - -/** - * @code dhcp_devman_add_intf(name, is_uplink); - * - * @brief adds interface to the device manager. - */ -int dhcp_devman_add_intf(const char *name, char intf_type) -{ - int rv = -1; - struct intf *dev = (struct intf*) malloc(sizeof(struct intf)); - - if (dev != NULL) { - dev->name = name; - dev->is_uplink = intf_type != 'd'; - - switch (intf_type) - { - case 'u': - dhcp_num_north_intf++; - break; - case 'd': - dhcp_num_south_intf++; - assert(dhcp_num_south_intf <= 1); - break; - case 'm': - dhcp_num_mgmt_intf++; - assert(dhcp_num_mgmt_intf <= 1); - mgmt_intf = dev; - break; - default: - break; - } - - rv = dhcp_device_init(&dev->dev_context, dev->name, dev->is_uplink); - if (rv == 0 && intf_type == 'd') { - rv = dhcp_device_get_ip(dev->dev_context, &vlan_ip); - - dhcp_device_context_t *agg_dev = dhcp_device_get_aggregate_context(); - - strncpy(agg_dev->intf, AGG_DEV_PREFIX, strlen(AGG_DEV_PREFIX) + 1); - strncpy(agg_dev->intf + strlen(AGG_DEV_PREFIX), name, sizeof(agg_dev->intf) - strlen(AGG_DEV_PREFIX) - 1); - agg_dev->intf[sizeof(agg_dev->intf) - 1] = '\0'; - syslog(LOG_INFO, "dhcpmon add aggregate interface '%s'\n", agg_dev->intf); - } - std::string if_name; - if_name.assign(dev->name); - intfs[if_name] = dev; - } - else { - syslog(LOG_ALERT, "malloc: failed to allocate memory for intf '%s'\n", name); - } - - return rv; -} - -/** - * @code dhcp_devman_setup_dual_tor_mode(name); - * - * @brief set up dual tor mode: 1) set dual_tor_mode flag and 2) retrieve loopback_ip. - */ -int dhcp_devman_setup_dual_tor_mode(const char *name) -{ - int rv = -1; - - dhcp_device_context_t loopback_intf_context; - - if (strlen(name) < sizeof(loopback_intf_context.intf)) { - strncpy(loopback_intf_context.intf, name, sizeof(loopback_intf_context.intf) - 1); - loopback_intf_context.intf[sizeof(loopback_intf_context.intf) - 1] = '\0'; - } else { - syslog(LOG_ALERT, "loopback interface name (%s) is too long", name); - return rv; - } - - if (initialize_intf_mac_and_ip_addr(&loopback_intf_context) == 0 && - dhcp_device_get_ip(&loopback_intf_context, &loopback_ip) == 0) { - dual_tor_mode = 1; - } else { - syslog(LOG_ALERT, "failed to retrieve ip addr for loopback interface (%s)", name); - return rv; - } - - rv = 0; - return rv; -} - -/** - * @code dhcp_devman_start_capture(snaplen, base); - * - * @brief start packet capture on the devman interface list - */ -int dhcp_devman_start_capture(size_t snaplen, struct event_base *base) -{ - int rv = -1; - - if ((dhcp_num_south_intf == 1) && (dhcp_num_north_intf >= 1)) { - rv = dhcp_device_start_capture(snaplen, base, dual_tor_mode ? loopback_ip : vlan_ip); - if (rv != 0) { - syslog(LOG_ALERT, "Capturing DHCP packets on interface failed"); - exit(1); - } - } - else { - syslog(LOG_ERR, "Invalid number of interfaces, downlink/south %d, uplink/north %d\n", - dhcp_num_south_intf, dhcp_num_north_intf); - } - - return rv; -} - -/** - * @code dhcp_devman_get_status(check_type, context); - * - * @brief collects DHCP relay status info. - */ -dhcp_mon_status_t dhcp_devman_get_status(dhcp_mon_check_t check_type, dhcp_device_context_t *context) -{ - return dhcp_device_get_status(check_type, context); -} - -/** - * @code dhcp_devman_update_snapshot(context); - * - * @brief Update device/interface counters snapshot - */ -void dhcp_devman_update_snapshot(dhcp_device_context_t *context) -{ - if (context == NULL) { - for (auto &itr : intfs) { - dhcp_device_update_snapshot(itr.second->dev_context); - } - dhcp_device_update_snapshot(dhcp_devman_get_agg_dev()); - } else { - dhcp_device_update_snapshot(context); - } -} - -/** - * @code dhcp_devman_print_status(context, type); - * - * @brief prints status counters to syslog, if context is null, it prints status counters for all interfaces - */ -void dhcp_devman_print_status(dhcp_device_context_t *context, dhcp_counters_type_t type) -{ - if (context == NULL) { - for (auto &itr : intfs) { - dhcp_device_print_status(itr.second->dev_context, type); - } - dhcp_device_print_status(dhcp_devman_get_agg_dev(), type); - } else { - dhcp_device_print_status(context, type); - } -} diff --git a/src/dhcpmon/src/dhcp_devman.h b/src/dhcpmon/src/dhcp_devman.h deleted file mode 100644 index d1c80cf30e9f..000000000000 --- a/src/dhcpmon/src/dhcp_devman.h +++ /dev/null @@ -1,132 +0,0 @@ -/** - * @file dhcp_devman.h - * - * Device (interface) manager - */ - -#ifndef DHCP_DEVMAN_H_ -#define DHCP_DEVMAN_H_ - -#include -#include -#include - -#include "dhcp_device.h" - -/** struct for interface information */ -struct intf -{ - const char *name; /** interface name */ - uint8_t is_uplink; /** is uplink (north) interface */ - dhcp_device_context_t *dev_context; /** device (interface_ context */ -}; - -/** - * @code dhcp_devman_init(); - * - * @brief initializes device (interface) manager that keeps track of interfaces and assert that there is one south - * interface and as many north interfaces - * - * @return none - */ -void dhcp_devman_init(); - -/** - * @code dhcp_devman_shutdown(); - * - * @brief shuts down device (interface) manager. Also, stops packet capture on interface and cleans up any allocated - * memory - * - * @return none - */ -void dhcp_devman_shutdown(); - -/** - * @code dhcp_devman_get_vlan_intf(); - * - * @brief Accessor method - * - * @return pointer to aggregate device (interface) context - */ -dhcp_device_context_t* dhcp_devman_get_agg_dev(); - -/** - * @code dhcp_devman_get_mgmt_intf_context(); - * - * @brief Accessor method - * - * @return pointer to mgmt interface context - */ -dhcp_device_context_t* dhcp_devman_get_mgmt_dev(); - -/** - * @code dhcp_devman_add_intf(name, uplink); - * - * @brief adds interface to the device manager. - * - * @param name interface name - * @param intf_type 'u' for uplink (north) interface - * 'd' for downlink (south) interface - * 'm' for mgmt interface - * - * @return 0 on success, nonzero otherwise - */ -int dhcp_devman_add_intf(const char *name, char intf_type); - -/** - * @code dhcp_devman_setup_dual_tor_mode(name); - * - * @brief set up dual tor mode: 1) set dual_tor_mode flag and 2) retrieve loopback_ip. - * - * @param name interface name - * - * @return 0 on success, nonzero otherwise - */ -int dhcp_devman_setup_dual_tor_mode(const char *name); - -/** - * @code dhcp_devman_start_capture(snaplen, base); - * - * @brief start packet capture on the devman interface list - * - * @param snaplen packet packet capture snap length - * @param base libevent base - * - * @return 0 on success, nonzero otherwise - */ -int dhcp_devman_start_capture(size_t snaplen, struct event_base *base); - -/** - * @code dhcp_devman_get_status(check_type, context); - * - * @brief collects DHCP relay status info. - * - * @param check_type Type of validation - * @param context pointer to device (interface) context - * - * @return DHCP_MON_STATUS_HEALTHY, DHCP_MON_STATUS_UNHEALTHY, or DHCP_MON_STATUS_INDETERMINATE - */ -dhcp_mon_status_t dhcp_devman_get_status(dhcp_mon_check_t check_type, dhcp_device_context_t *context); - -/** - * @code dhcp_devman_update_snapshot(context); - * - * @param context Device (interface) context - * - * @brief Update device/interface counters snapshot - */ -void dhcp_devman_update_snapshot(dhcp_device_context_t *context); - -/** - * @code dhcp_devman_print_status(context, type); - * - * @brief prints status counters to syslog - * - * @param context pointer to device (interface) context - * @param type Counter type to be printed - * - * @return none - */ -void dhcp_devman_print_status(dhcp_device_context_t *context, dhcp_counters_type_t type); - -#endif /* DHCP_DEVMAN_H_ */ diff --git a/src/dhcpmon/src/dhcp_mon.cpp b/src/dhcpmon/src/dhcp_mon.cpp deleted file mode 100644 index 21b0a363d874..000000000000 --- a/src/dhcpmon/src/dhcp_mon.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/** - * @file dhcp_mon.c - * - * @brief dhcp relay monitor module - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dhcp_mon.h" -#include "dhcp_devman.h" - -/** DHCP device/interface state */ -typedef struct -{ - dhcp_mon_check_t check_type; /** check type */ - dhcp_device_context_t* (*get_context)(); /** functor to a device context accessor function */ - int count; /** count in the number of unhealthy checks */ - const char *msg; /** message to be printed if unhealthy state is determined */ -} dhcp_mon_state_t; - -/** window_interval_sec monitoring window for dhcp relay health checks */ -static int window_interval_sec = 18; -/** dhcp_unhealthy_max_count max count of consecutive unhealthy statuses before reporting to syslog */ -static int dhcp_unhealthy_max_count = 10; -/** dhcpmon debug mode control flag */ -static bool debug_on = false; -/** libevent base struct */ -static struct event_base *base; -/** libevent timeout event struct */ -static struct event *ev_timeout = NULL; -/** libevent SIGINT signal event struct */ -static struct event *ev_sigint; -/** libevent SIGTERM signal event struct */ -static struct event *ev_sigterm; -/** libevent SIGUSR1 signal event struct */ -static struct event *ev_sigusr1; - -/** DHCP monitor state data for aggregate device for mgmt device */ -static dhcp_mon_state_t state_data[] = { - [0] = { - .check_type = DHCP_MON_CHECK_POSITIVE, - .get_context = dhcp_devman_get_agg_dev, - .count = 0, - .msg = "dhcpmon detected disparity in DHCP Relay behavior. Duration: %d (sec) for vlan: '%s'\n" - }, - [1] = { - .check_type = DHCP_MON_CHECK_NEGATIVE, - .get_context = dhcp_devman_get_mgmt_dev, - .count = 0, - .msg = "dhcpmon detected DHCP packets traveling through mgmt interface (please check BGP routes.)" - " Duration: %d (sec) for intf: '%s'\n" - } -}; - -/** - * @code signal_callback(fd, event, arg); - * - * @brief signal handler for dhcpmon. It will initiate shutdown when signal is caught - * - * @param fd libevent socket - * @param event event triggered - * @param arg pointer to user provided context (libevent base) - * - * @return none - */ -static void signal_callback(evutil_socket_t fd, short event, void *arg) -{ - syslog(LOG_ALERT, "Received signal: '%s'\n", strsignal(fd)); - dhcp_devman_print_status(NULL, DHCP_COUNTERS_CURRENT); - if ((fd == SIGTERM) || (fd == SIGINT)) { - dhcp_mon_stop(); - } -} - -/** - * @code check_dhcp_relay_health(state_data); - * - * @brief check DHCP relay overall health - * - * @param state_data pointer to dhcpmon state data - * - * @return none - */ -static void check_dhcp_relay_health(dhcp_mon_state_t *state_data) -{ - dhcp_device_context_t *context = state_data->get_context(); - dhcp_mon_status_t dhcp_mon_status = dhcp_devman_get_status(state_data->check_type, context); - - switch (dhcp_mon_status) - { - case DHCP_MON_STATUS_UNHEALTHY: - if (++state_data->count > dhcp_unhealthy_max_count) { - syslog(LOG_ALERT, state_data->msg, state_data->count * window_interval_sec, context->intf); - dhcp_devman_print_status(context, DHCP_COUNTERS_SNAPSHOT); - dhcp_devman_print_status(context, DHCP_COUNTERS_CURRENT); - } - break; - case DHCP_MON_STATUS_HEALTHY: - state_data->count = 0; - break; - case DHCP_MON_STATUS_INDETERMINATE: - if (state_data->count) { - state_data->count++; - } - break; - default: - syslog(LOG_ERR, "DHCP Relay returned unknown status %d\n", dhcp_mon_status); - break; - } -} - -/** - * @code timeout_callback(fd, event, arg); - * - * @brief periodic timer call back - * - * @param fd libevent socket - * @param event event triggered - * @param arg pointer user provided context (libevent base) - * - * @return none - */ -static void timeout_callback(evutil_socket_t fd, short event, void *arg) -{ - for (uint8_t i = 0; i < sizeof(state_data) / sizeof(*state_data); i++) { - check_dhcp_relay_health(&state_data[i]); - } - - dhcp_devman_update_snapshot(NULL); - - if (debug_on) { - dhcp_devman_print_status(NULL, DHCP_COUNTERS_SNAPSHOT); - dhcp_devman_print_status(NULL, DHCP_COUNTERS_CURRENT); - } -} - -/** - * @code dhcp_mon_init(window_sec, max_count); - * - * initializes event base and periodic timer event that continuously collects dhcp relay health status every window_sec - * seconds. It also writes to syslog when dhcp relay has been unhealthy for consecutive max_count checks. - * - */ -int dhcp_mon_init(int window_sec, int max_count) -{ - int rv = -1; - - do { - window_interval_sec = window_sec; - dhcp_unhealthy_max_count = max_count; - - base = event_base_new(); - if (base == NULL) { - syslog(LOG_ERR, "Could not initialize libevent!\n"); - break; - } - - ev_sigint = evsignal_new(base, SIGINT, signal_callback, base); - if (ev_sigint == NULL) { - syslog(LOG_ERR, "Could not create SIGINT libevent signal!\n"); - break; - } - - ev_sigterm = evsignal_new(base, SIGTERM, signal_callback, base); - if (ev_sigterm == NULL) { - syslog(LOG_ERR, "Could not create SIGTERM libevent signal!\n"); - break; - } - - ev_sigusr1 = evsignal_new(base, SIGUSR1, signal_callback, base); - if (ev_sigusr1 == NULL) { - syslog(LOG_ERR, "Could not create SIGUSER1 libevent signal!\n"); - break; - } - - ev_timeout = event_new(base, -1, EV_PERSIST, timeout_callback, base); - if (ev_timeout == NULL) { - syslog(LOG_ERR, "Could not create libevent timer!\n"); - break; - } - - rv = 0; - } while (0); - - return rv; -} - -/** - * @code dhcp_mon_shutdown(); - * - * @brief shuts down libevent loop - */ -void dhcp_mon_shutdown() -{ - event_del(ev_timeout); - event_del(ev_sigint); - event_del(ev_sigterm); - event_del(ev_sigusr1); - - event_free(ev_timeout); - event_free(ev_sigint); - event_free(ev_sigterm); - event_free(ev_sigusr1); - - event_base_free(base); -} - -/** - * @code dhcp_mon_start(snaplen, debug_mode); - * - * @brief start monitoring DHCP Relay - */ -int dhcp_mon_start(size_t snaplen, bool debug_mode) -{ - int rv = -1; - debug_on = debug_mode; - - do - { - if (dhcp_devman_start_capture(snaplen, base) != 0) { - break; - } - - if (evsignal_add(ev_sigint, NULL) != 0) { - syslog(LOG_ERR, "Could not add SIGINT libevent signal!\n"); - break; - } - - if (evsignal_add(ev_sigterm, NULL) != 0) { - syslog(LOG_ERR, "Could not add SIGTERM libevent signal!\n"); - break; - } - - if (evsignal_add(ev_sigusr1, NULL) != 0) { - syslog(LOG_ERR, "Could not add SIGUSR1 libevent signal!\n"); - break; - } - - struct timeval event_time = {.tv_sec = window_interval_sec, .tv_usec = 0}; - if (evtimer_add(ev_timeout, &event_time) != 0) { - syslog(LOG_ERR, "Could not add event timer to libevent!\n"); - break; - } - - if (event_base_dispatch(base) != 0) { - syslog(LOG_ERR, "Could not start libevent dispatching loop!\n"); - break; - } - rv = 0; - } while (0); - - return rv; -} - -/** - * @code dhcp_mon_stop(); - * - * @brief stop monitoring DHCP Relay - */ -void dhcp_mon_stop() -{ - event_base_loopexit(base, NULL); -} diff --git a/src/dhcpmon/src/dhcp_mon.h b/src/dhcpmon/src/dhcp_mon.h deleted file mode 100644 index 5bae01f5962b..000000000000 --- a/src/dhcpmon/src/dhcp_mon.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @file dhcp_mon.h - * - * @brief dhcp relay monitor module - * - */ - -#ifndef DHCP_MON_H_ -#define DHCP_MON_H_ - -/** - * @code dhcp_mon_init(window_ssec, max_count); - * - * @brief initializes event base and periodic timer event that continuously collects dhcp relay health status every - * window_sec seconds. It also writes to syslog when dhcp relay has been unhealthy for consecutive max_count - * checks. - * - * @param window_sec time interval between health checks - * @param max_count max count of consecutive unhealthy statuses before reporting to syslog - * - * @return 0 upon success, otherwise upon failure - */ -int dhcp_mon_init(int window_sec, int max_count); - -/** - * @code dhcp_mon_shutdown(); - * - * @brief shuts down libevent loop - * - * @return none - */ -void dhcp_mon_shutdown(); - -/** - * @code dhcp_mon_start(snaplen, debug); - * - * @brief start monitoring DHCP Relay - * - * @param snaplen packet capture length - * @param debug turn on debug or not - * - * @return 0 upon success, otherwise upon failure - */ -int dhcp_mon_start(size_t snaplen, bool debug); - -/** - * @code dhcp_mon_stop(); - * - * @brief stop monitoring DHCP Relay - * - * @return none - */ -void dhcp_mon_stop(); - -#endif /* DHCP_MON_H_ */ diff --git a/src/dhcpmon/src/main.cpp b/src/dhcpmon/src/main.cpp deleted file mode 100644 index e660bbd908a9..000000000000 --- a/src/dhcpmon/src/main.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/** - * @file main.c - * - * @brief: Main entry point for dhcpmon utility. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "subscriberstatetable.h" -#include "select.h" - -#include "dhcp_mon.h" -#include "dhcp_devman.h" -#include "dhcp_device.h" - -/** dhcpmon_default_snaplen: default snap length of packet being captured */ -static const size_t dhcpmon_default_snaplen = 65535; -/** dhcpmon_default_health_check_window: default value for a time window, during which DHCP DORA packet counts are being - * collected */ -static const uint32_t dhcpmon_default_health_check_window = 18; -/** dhcpmon_default_unhealthy_max_count: default max consecutive unhealthy status reported before reporting an issue - * with DHCP relay */ -static const uint32_t dhcpmon_default_unhealthy_max_count = 10; - -bool dual_tor_sock = false; - -/** - * @code usage(prog); - * - * @brief prints help message about how to use dhcpmon utility - * - * @param prog program name - * - * @return none - */ -static void usage(const char *prog) -{ - printf("Usage: %s -id {-iu }+ -im [-u ]" - "[-w ] [-c ] [-s ] [-D] [-d]\n", prog); - printf("where\n"); - printf("\tsouth interface: is a vlan interface,\n"); - printf("\tnorth interface: is a TOR-T1 interface,\n"); - printf("\tloopback interface: is the loopback interface for dual tor setup,\n"); - printf("\tsnapshot window: during which DHCP counters are gathered and DHCP status is validated (default %d),\n", - dhcpmon_default_health_check_window); - printf("\tunhealthy status count: count of consecutive unhealthy status before writing an alert to syslog " - "(default %d),\n", - dhcpmon_default_unhealthy_max_count); - printf("\tsnap length: snap length of packet capture (default %ld),\n", dhcpmon_default_snaplen); - printf("\t-D: debug mode: print counter to syslog\n"); - printf("\t-d: daemonize %s.\n", prog); - - exit(EXIT_SUCCESS); -} - -/** - * @code dhcpmon_daemonize(); - * - * @brief make this utility run as a daemon. - * - * @return none - */ -static void dhcpmon_daemonize() -{ - pid_t pid, sid; - pid = fork(); - if (pid < 0) { - syslog(LOG_ALERT, "fork: %s", strerror(errno)); - exit(EXIT_FAILURE); - } - - if (pid > 0) { - exit(EXIT_SUCCESS); - } - - // this is the daemon running now - umask(0); - // Create a new SID for the child process - sid = setsid(); - if (sid < 0) { - syslog(LOG_ALERT, "setsid: %s", strerror(errno)); - exit(EXIT_FAILURE); - } - - // Change the current working directory - if ((chdir("/")) < 0) { - syslog(LOG_ALERT, "chdir: %s", strerror(errno)); - exit(EXIT_FAILURE); - } - - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); -} - -/** - * @code main(argc, argv); - * - * @brief main entry point of dhcpmon utility - * - * @return int 0 on success, otherwise on failure - */ -int main(int argc, char **argv) -{ - int rv = EXIT_FAILURE; - int i; - int window_interval = dhcpmon_default_health_check_window; - int max_unhealthy_count = dhcpmon_default_unhealthy_max_count; - size_t snaplen = dhcpmon_default_snaplen; - int make_daemon = 0; - bool debug_mode = false; - - setlogmask(LOG_UPTO(LOG_INFO)); - openlog(basename(argv[0]), LOG_CONS | LOG_PID | LOG_NDELAY, LOG_DAEMON); - - for (i = 1; i < argc;) { - if ((argv[i] == NULL) || (argv[i][0] != '-')) { - break; - } - switch (argv[i][1]) - { - case 'h': - usage(basename(argv[0])); - break; - case 'i': - if (dhcp_devman_add_intf(argv[i + 1], argv[i][2]) != 0) { - usage(basename(argv[0])); - } - i += 2; - break; - case 'u': - dual_tor_sock = true; - if (dhcp_devman_setup_dual_tor_mode(argv[i + 1]) != 0) { - usage(basename(argv[0])); - } - i += 2; - break; - case 'd': - make_daemon = 1; - i++; - break; - case 's': - snaplen = atoi(argv[i + 1]); - i += 2; - break; - case 'w': - window_interval = atoi(argv[i + 1]); - i += 2; - break; - case 'c': - max_unhealthy_count = atoi(argv[i + 1]); - i += 2; - break; - case 'D': - debug_mode = true; - i += 1; - break; - default: - fprintf(stderr, "%s: %c: Unknown option\n", basename(argv[0]), argv[i][1]); - usage(basename(argv[0])); - } - } - - if (make_daemon) { - dhcpmon_daemonize(); - } - - if ((dhcp_mon_init(window_interval, max_unhealthy_count) == 0) && - (dhcp_mon_start(snaplen, debug_mode) == 0)) { - - rv = EXIT_SUCCESS; - - dhcp_mon_shutdown(); - } - - dhcp_devman_shutdown(); - - closelog(); - - return rv; -} diff --git a/src/dhcpmon/src/subdir.mk b/src/dhcpmon/src/subdir.mk deleted file mode 100644 index dd808aeb7202..000000000000 --- a/src/dhcpmon/src/subdir.mk +++ /dev/null @@ -1,29 +0,0 @@ -# Add inputs and outputs from these tool invocations to the build variables -CC := g++ - -C_SRCS += \ -../src/dhcp_device.cpp \ -../src/dhcp_devman.cpp \ -../src/dhcp_mon.cpp \ -../src/main.cpp - -OBJS += \ -./src/dhcp_device.o \ -./src/dhcp_devman.o \ -./src/dhcp_mon.o \ -./src/main.o - -C_DEPS += \ -./src/dhcp_device.d \ -./src/dhcp_devman.d \ -./src/dhcp_mon.d \ -./src/main.d - - -# Each subdirectory must supply rules for building sources it contributes -src/%.o: src/%.cpp - @echo 'Building file: $<' - @echo 'Invoking: GCC C Compiler' - $(CC) -O3 -g3 -Wall -I$(PWD)/../sonic-swss-common/common -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<" - @echo 'Finished building: $<' - @echo ' '