Skip to content

Commit

Permalink
Back out ipv6 changes to diagnose shield tent failures (#59)
Browse files Browse the repository at this point in the history
* telemetry: revert fix portability issues in ipv6 change (#57)

This reverts commit b8ed8c9.
MIN-2834

* telemetry: revert - add router ipv6 address reporting (enabled by feature flag) (#55)

This reverts commit 07aac64.
MIN-2834

Co-authored-by: Tom Keddie (Minim) <Tom Keddie (Minim)>
  • Loading branch information
Tom-Keddie authored Jan 25, 2022
1 parent b8ed8c9 commit cc2e5ab
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 215 deletions.
1 change: 0 additions & 1 deletion files/features-router.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,3 @@ telnet-passwords
port_scanning
rescan_devices
hardware_content_filtering
ipv6_telemetry
109 changes: 12 additions & 97 deletions src/unum/telemetry/telemetry.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,104 +124,19 @@ static char *router_telemetry_json()
cpu_pfint_ptr = NULL;
}

static JSON_VAL_TPL_t wan_ipv6_address_tpl[MAX_IPV6_ADDRESSES_PER_MAC + 1];
static char wan_primary_ipv6_address_str[INET6_ADDRSTRLEN + 4]; // 4 for prefix eg. /128
static char wan_other_ipv6_addresses_str[MAX_IPV6_ADDRESSES_PER_MAC * sizeof(wan_primary_ipv6_address_str)];
memset(wan_other_ipv6_addresses_str, '\0', sizeof(wan_other_ipv6_addresses_str));
DEV_IPV6_CFG_t wan_ipv6_addresses[MAX_IPV6_ADDRESSES_PER_MAC];
memset(wan_ipv6_addresses, '\0', sizeof(wan_ipv6_addresses));
unsigned int wan_primary_ipv6_address_valid = 0;
unsigned int wan_other_ipv6_addresses_valid = 0;
int ix = 0;
int iy = 0;
if (util_get_ipv6cfg(GET_MAIN_WAN_NET_DEV(), wan_ipv6_addresses) == 0) {
for (ix = 0, iy = 0; ix < MAX_IPV6_ADDRESSES_PER_MAC; ix++) {
if (wan_ipv6_addresses[ix].addr.b[0] != '\0') {
char buf[INET6_ADDRSTRLEN] = {'\0'};
inet_ntop(AF_INET6, wan_ipv6_addresses[ix].addr.b, buf, sizeof(buf));
if (wan_ipv6_addresses[ix].flags == DEV_IPV6_CFG_FLAG_PRIMARY) {
snprintf(wan_primary_ipv6_address_str,
sizeof(wan_primary_ipv6_address_str),
"%s/%d",
buf,
(wan_ipv6_addresses[ix].prefix_len) & 127);
wan_primary_ipv6_address_valid = 1;
} else {
snprintf(&wan_other_ipv6_addresses_str[iy * (INET6_ADDRSTRLEN + 4)],
(INET6_ADDRSTRLEN + 4),
"%s/%d",
buf,
(wan_ipv6_addresses[ix].prefix_len) & 127);
wan_ipv6_address_tpl[iy].s = &wan_other_ipv6_addresses_str[iy * (INET6_ADDRSTRLEN + 4)];
wan_ipv6_address_tpl[iy].type = JSON_VAL_STR;
wan_other_ipv6_addresses_valid = 1;
iy++;
}
} else {
wan_ipv6_address_tpl[iy].type = JSON_VAL_END;
break;
}
}
}
static JSON_VAL_TPL_t lan_ipv6_address_tpl[MAX_IPV6_ADDRESSES_PER_MAC + 1];
static char lan_primary_ipv6_address_str[INET6_ADDRSTRLEN + 4]; // 4 for prefix eg. /128
static char lan_other_ipv6_addresses_str[MAX_IPV6_ADDRESSES_PER_MAC * sizeof(lan_primary_ipv6_address_str)];
memset(lan_other_ipv6_addresses_str, '\0', sizeof(lan_other_ipv6_addresses_str));
DEV_IPV6_CFG_t lan_ipv6_addresses[MAX_IPV6_ADDRESSES_PER_MAC];
memset(lan_ipv6_addresses, '\0', sizeof(lan_ipv6_addresses));
unsigned int lan_primary_ipv6_address_valid = 0;
unsigned int lan_other_ipv6_addresses_valid = 0;
if (util_get_ipv6cfg(GET_MAIN_LAN_NET_DEV(), lan_ipv6_addresses) == 0) {
for (ix = 0, iy = 0; ix < MAX_IPV6_ADDRESSES_PER_MAC; ix++) {
if (lan_ipv6_addresses[ix].addr.b[0] != '\0') {
char buf[INET6_ADDRSTRLEN] = {'\0'};
inet_ntop(AF_INET6, lan_ipv6_addresses[ix].addr.b, buf, sizeof(buf));
if (lan_ipv6_addresses[ix].flags == DEV_IPV6_CFG_FLAG_PRIMARY) {
snprintf(lan_primary_ipv6_address_str,
sizeof(lan_primary_ipv6_address_str),
"%s/%d",
buf,
(lan_ipv6_addresses[ix].prefix_len) & 127);
lan_primary_ipv6_address_valid = 1;
} else {
snprintf(&lan_other_ipv6_addresses_str[iy * (INET6_ADDRSTRLEN + 4)],
(INET6_ADDRSTRLEN + 4),
"%s/%d",
buf,
(lan_ipv6_addresses[ix].prefix_len) & 127);
lan_ipv6_address_tpl[iy].s = &lan_other_ipv6_addresses_str[iy * (INET6_ADDRSTRLEN + 4)];
lan_ipv6_address_tpl[iy].type = JSON_VAL_STR;
lan_other_ipv6_addresses_valid = 1;
iy++;
}
} else {
lan_ipv6_address_tpl[iy].type = JSON_VAL_END;
break;
}
}
}

JSON_OBJ_TPL_t tpl = {
{"lan_ip_address", {.type = JSON_VAL_STR, {.s = lan_ip }}},
{"lan_primary_ipv6_address", {.type = JSON_VAL_STR,
{.s = lan_primary_ipv6_address_valid ? lan_primary_ipv6_address_str : NULL}}},
{"lan_other_ipv6_addresses", {.type = JSON_VAL_ARRAY,
{.a = lan_other_ipv6_addresses_valid ? lan_ipv6_address_tpl : NULL}}},
{"wan_ip_address", {.type = JSON_VAL_STR, {.s = wan_ip }}},
{"wan_primary_ipv6_address", {.type = JSON_VAL_STR,
{.s = wan_primary_ipv6_address_valid ? wan_primary_ipv6_address_str : NULL}}},
{"wan_other_ipv6_addresses", {.type = JSON_VAL_ARRAY,
{.a = wan_other_ipv6_addresses_valid ? wan_ipv6_address_tpl : NULL}}},
{"wan_mac_address", {.type = JSON_VAL_STR, {.s = wan_mac}}},
{"no_dns", {.type = JSON_VAL_STR, {.s = no_dns }}},
{"no_time", {.type = JSON_VAL_STR, {.s = no_time}}},
{"mem_free", {.type = JSON_VAL_PFINT,{.fpi = mem_pfint_ptr}}},
{"mem_available", {.type = JSON_VAL_PFINT,{.fpi = mem_pfint_ptr}}},
{"cpu_usage", {.type = JSON_VAL_PFINT,{.fpi = cpu_pfint_ptr}}},
{"cpu_softirq", {.type = JSON_VAL_PFINT,{.fpi = cpu_pfint_ptr}}},
{"cpu_max_usage", {.type = JSON_VAL_PFINT,{.fpi = cpu_pfint_ptr}}},
{"cpu_max_softirq", {.type = JSON_VAL_PFINT,{.fpi = cpu_pfint_ptr}}},
{"seq_num", {.type = JSON_VAL_UL, {.ul = telemetry_seq_num}}},
{"lan_ip_address", {.type = JSON_VAL_STR, {.s = lan_ip }}},
{"wan_ip_address", {.type = JSON_VAL_STR, {.s = wan_ip }}},
{"wan_mac_address", {.type = JSON_VAL_STR, {.s = wan_mac}}},
{"no_dns", {.type = JSON_VAL_STR, {.s = no_dns }}},
{"no_time", {.type = JSON_VAL_STR, {.s = no_time}}},
{"mem_free", {.type = JSON_VAL_PFINT,{.fpi = mem_pfint_ptr}}},
{"mem_available", {.type = JSON_VAL_PFINT,{.fpi = mem_pfint_ptr}}},
{"cpu_usage", {.type = JSON_VAL_PFINT,{.fpi = cpu_pfint_ptr}}},
{"cpu_softirq", {.type = JSON_VAL_PFINT,{.fpi = cpu_pfint_ptr}}},
{"cpu_max_usage", {.type = JSON_VAL_PFINT,{.fpi = cpu_pfint_ptr}}},
{"cpu_max_softirq", {.type = JSON_VAL_PFINT,{.fpi = cpu_pfint_ptr}}},
{"seq_num", {.type = JSON_VAL_UL, {.ul = telemetry_seq_num}}},
{NULL}
};

Expand Down
97 changes: 1 addition & 96 deletions src/unum/util/util_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@

#include "unum.h"

static int nl_sock(NL_SOCK_t *s, int type);
static int nl_recv(NL_SOCK_t *s, char *buf, unsigned int len, int seq_num, int tout);

// Get interface flags
// ifname - the interface name
Expand Down Expand Up @@ -134,7 +132,7 @@ char *util_device_mac()
// The buf length should be at least INET_ADDRSTRLEN bytes.
// If buf is NULL it is not used.
// Returns 0 if successful, error code if fails.
int util_get_ipv4(const char *dev, char *buf)
int util_get_ipv4(char *dev, char *buf)
{
struct ifreq ifr;
int fd = -1;
Expand Down Expand Up @@ -399,99 +397,6 @@ int util_get_ipcfg(char *dev, DEV_IP_CFG_t *ipcfg)
return ret;
}

// Get the IPv6 configuration of a network device.
// Requires a pointer to an array with room for
// MAX_IPV6_ADDRESSES_PER_MAC addresses
// Returns 0 if successful, error code if fails.
int util_get_ipv6cfg(char *dev, DEV_IPV6_CFG_t *ipcfg) {
int ret = -1;
#ifdef FEATURE_IPV6_TELEMETRY
// Create socket
NL_SOCK_t nl_socket = { .s = -1 };
void *req = NULL;
int buf_index = 0;
int if_index = if_nametoindex(dev);
if (if_index == 0) {
log("%s: invalid interface %s\n", __func__, dev);
return -1;
}

for(;;) {
char resp[1024] = {'\0'};
int resp_len = 0;
const int msg_seq = 1;
const struct nlmsghdr *retmsg = NULL;
struct {
struct nlmsghdr nlh;
struct ifaddrmsg ifm;
char buf[128];
} req;

// reference implementation at
// https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/lib/libnetlink.c#n311
if(nl_sock(&nl_socket, NETLINK_ROUTE) < 0) {
log("%s: socket() error: %s\n", __func__, strerror(errno));
ret = -1;
break;
}
req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
req.nlh.nlmsg_type = RTM_GETADDR;
req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_REQUEST;
req.nlh.nlmsg_seq = msg_seq;
req.ifm.ifa_family = AF_INET6;

// send the request
if(send(nl_socket.s, &req, sizeof(req), 0) < 0) {
log("%s: socket() error: %s\n", __func__, strerror(errno));
ret = -4;
break;
}

// Read the response, allow 10sec till timeout
resp_len = nl_recv(&nl_socket, resp, sizeof(resp), msg_seq, 10);
if(resp_len < 0) {
// nl_recv() logs the error message
ret = -5;
break;
}

// parse the response
retmsg = (struct nlmsghdr *)resp;
while (NLMSG_OK(retmsg, resp_len) && buf_index < MAX_IPV6_ADDRESSES_PER_MAC) {
struct ifaddrmsg *retaddr = (struct ifaddrmsg *) NLMSG_DATA(retmsg);
struct rtattr *retrta = (struct rtattr *) IFA_RTA(retaddr);

// extract address strings from attribute list
int att_len = IFA_PAYLOAD(retmsg);
while RTA_OK(retrta, att_len) {
if (retrta->rta_type == IFA_ADDRESS && retaddr->ifa_index == if_index) {
memcpy(&ipcfg[buf_index].addr, RTA_DATA(retrta), sizeof(ipcfg[buf_index].addr));
ipcfg[buf_index].prefix_len = retaddr->ifa_prefixlen;
// TODO, determine the primary TK Jan 2022
ipcfg[buf_index].flags = (buf_index == 0) ? DEV_IPV6_CFG_FLAG_PRIMARY : 0;
buf_index++;
}
retrta = RTA_NEXT(retrta, att_len);
}
retmsg = NLMSG_NEXT(retmsg, resp_len);
}
ret = 0;
break;
} // for(;;)

if(req) {
UTIL_FREE(req);
req = NULL;
}
if(nl_socket.s >= 0) {
close(nl_socket.s);
}
#endif /* FEATURE_IPV6_TELEMETRY */

return ret;
}


// Get network device statistics/counters.
// Returns 0 if successful, error code if fails.
int util_get_dev_stats(char *dev, NET_DEV_STATS_t *st)
Expand Down
22 changes: 1 addition & 21 deletions src/unum/util/util_net.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,6 @@
// Length of the MAC address string (do we have a standard define for that?)
#define MAC_ADDRSTRLEN 18

// Maximum number of ipv6 addresses we support per mac
#ifndef MAX_IPV6_ADDRESSES_PER_MAC
#define MAX_IPV6_ADDRESSES_PER_MAC 4
#endif // MAX_IPV6_ADDRESSES_PER_MAC

// Format string and argument macros for printing MAC addresses
// from printf style functions
#define MAC_PRINTF_FMT_TPL "%02x:%02x:%02x:%02x:%02x:%02x"
Expand Down Expand Up @@ -144,15 +139,6 @@ typedef struct _DEV_IP_CFG {
IPV4_ADDR_t ipv4mask; // byte order is the same as in struct sockaddr
} DEV_IP_CFG_t;

#define DEV_IPV6_CFG_FLAG_PRIMARY 1

// IP configuration structure describing device IPv6 settings
typedef struct _DEV_IPV6_CFG {
IPV6_ADDR_t addr; // byte order is the same as in struct sockaddr_in6
uint8_t prefix_len;
uint8_t flags;
} DEV_IPV6_CFG_t;

// Netlink socket structure
typedef struct _NL_SOCK {
int s; // socket descriptor
Expand Down Expand Up @@ -250,20 +236,14 @@ int util_get_mac(char *dev, unsigned char *mac);
// Returns 0 if successful, error code if fails.
int util_get_ipcfg(char *dev, DEV_IP_CFG_t *ipcfg);

// Get the IPv6 configuration of a network device.
// Requires a pointer to an array with room for
// MAX_IPV6_ADDRESSES_PER_MAC addresses
// Returns 0 if successful, error code if fails.
int util_get_ipv6cfg(char *dev, DEV_IPV6_CFG_t *ipcfg);

// Get device base MAC (format xx:xx:xx:xx:xx:xx, stored at a static location)
char *util_device_mac();

// Get the IPv4 address (as a string) of a network device.
// The buf length should be at least INET_ADDRSTRLEN bytes
// If buf is NULL it is not used.
// Returns 0 if successful, error code if fails.
int util_get_ipv4(const char *dev, char *buf);
int util_get_ipv4(char *dev, char *buf);

// Using getaddrinfo we do a name lookup and then
// *res will be set to the first ip4 sockaddr (or ignored if NULL)
Expand Down

0 comments on commit cc2e5ab

Please sign in to comment.