vcpe/srcs/libs/misc/misc.c

459 lines
11 KiB
C

//
// Created by xajhu on 2021/7/2 0002.
//
#include <string.h>
#include <uv.h>
#include <sys/vfs.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/sendfile.h>
#include <linux/if.h>
#include <sys/ioctl.h>
#include <linux/if_ether.h>
#include <sys/time.h>
#include <netinet/udp.h>
#include <netinet/ip.h>
#include "user_errno.h"
#include "misc.h"
#include "zlog_module.h"
#include "common.h"
#include "sds/sds.h"
PSYS_NIC_INFO g_sysNicInfo = NULL;
const char *basename_v2(const char *path) {
const char *tail = strrchr(path, '/');
return tail ? tail + 1 : path;
}
int dirname_v2(const char *path, char *dir) {
const char *tail = strrchr(path, '/');
if (tail) {
memcpy(dir, path, tail - path);
dir[tail - path] = 0;
} else {
strcpy(dir, "./");
}
return 0;
}
unsigned long long get_partition_free_size(const char *pPartPath) {
struct statfs myStatfs;
unsigned long long freeSize;
if (statfs(pPartPath, &myStatfs) == -1) {
return 0;
}
freeSize = myStatfs.f_bsize * myStatfs.f_bfree;
return freeSize;
}
int copy_file(const char *pSrc, const char *pDest) {
int fdSrc, fdDest;
struct stat st;
ssize_t sz;
if (stat(pSrc, &st) != 0) {
LOG_MOD(error, ZLOG_MOD_MISC, "Get File %s Size Error\n", pSrc);
return (-ERR_GET_FILE_SIZE);
}
fdSrc = open(pSrc, O_RDONLY);
if (fdSrc < 0) {
LOG_MOD(error, ZLOG_MOD_MISC, "Open File %s Error\n", pSrc);
return (-ERR_OPEN_FILE);
}
fdDest = open(pDest, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (fdDest < 0) {
close(fdSrc);
LOG_MOD(error, ZLOG_MOD_MISC, "Open File %s Error\n", pDest);
return (-ERR_OPEN_FILE);
}
sz = sendfile(fdDest, fdSrc, NULL, st.st_size);
if (sz != st.st_size) {
LOG_MOD(error, ZLOG_MOD_MISC, "Copy File Size Error: %zd, %ld\n", sz, st.st_size);
close(fdSrc);
close(fdDest);
return (-ERR_COPY_FILE);
}
fsync(fdDest);
close(fdSrc);
close(fdDest);
return (0);
}
char *bin2hex(char *p, const unsigned char *cp, unsigned int count) {
static const char hex_asc[] = "0123456789abcdef";
while (count) {
unsigned char c = *cp++;
/* put lowercase hex digits */
*p++ = (char)(0x20 | hex_asc[c >> 4]);
*p++ = (char)(0x20 | hex_asc[c & 0xf]);
count--;
}
return p;
}
int shell_with_output(const char *pCmd, char **pResult) {
FILE *pFile = NULL;
unsigned int uRdSize;
char *pCmdOut;
*pResult = NULL;
if (pCmd == NULL || strlen(pCmd) == 0) {
return (-ERR_INPUT_PARAMS);
}
pFile = popen(pCmd, "r");
if (pFile == NULL) {
return (-ERR_OPEN_FILE);
}
*pResult = (char *)malloc(4096);
pCmdOut = *pResult;
uRdSize = fread(pCmdOut, sizeof(char), 4096, pFile);
pCmdOut[uRdSize] = 0;
if (pCmdOut[strlen(pCmdOut) - 1] == '\n') {
pCmdOut[strlen(pCmdOut) - 1] = 0;
}
pclose(pFile);
return ERR_SUCCESS;
}
int file_exists(const char *pPath) {
if ((access(pPath, F_OK)) == -1) {
return FALSE;
}
return TRUE;
}
const char *get_cur_process_dir() {
static char g_exePath[4096] = {0};
size_t bufSize = 4096L;
if (strlen((const char *)g_exePath) == 0) {
memset(g_exePath, 0, 4096);
uv_cwd(g_exePath, &bufSize);
}
return (const char *)g_exePath;
}
unsigned long long get_current_time_ms() {
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}
int str_to_mac(const char *str, unsigned char mac[6]) {
int i;
char *s, *e;
if ((mac == NULL) || (str == NULL)) {
return -ERR_INPUT_PARAMS;
}
s = (char *)str;
for (i = 0; i < 6; ++i) {
mac[i] = s ? strtoul(s, &e, 16) : 0;
if (s) {
s = (*e) ? e + 1 : e;
}
}
return ERR_SUCCESS;
}
int str_to_ipaddr(const char *pIp, unsigned int *ipAddr) {
struct in_addr addr;
int ret = inet_aton(pIp, &addr);
if (ret != 0) {
*ipAddr = addr.s_addr;
}
return ret;
}
int get_nic_info(const char *pName,
unsigned int *pIp,
unsigned int *pNetmask,
unsigned int *pBoardcast,
unsigned char *pMac) {
int sock;
struct ifreq ifr;
int err = ERR_SUCCESS;
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sock < 0) {
LOG_MOD(error, ZLOG_MOD_MISC, "Get local NIC information failed\n");
return -ERR_SYS_INIT;
}
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, pName);
if (pIp) {
if (ioctl(sock, SIOCGIFADDR, &ifr) != 0) {
err = ERR_MISC_GET_IPADDR;
} else {
*pIp = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
}
}
if (pNetmask) {
if (ioctl(sock, SIOCGIFNETMASK, &ifr) == 0) {
*pNetmask = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
} else {
err = ERR_MISC_GET_NETMASK;
}
}
if (pBoardcast) {
if (ioctl(sock, SIOCGIFBRDADDR, &ifr) == 0) {
*pBoardcast = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
} else {
err = ERR_MISC_GET_GATEWAY;
}
}
if (pMac) {
if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0) {
memcpy(pMac, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
} else {
err = ERR_MISC_GET_MACADDR;
}
}
close(sock);
return err;
}
const char *u32_to_str_ip(unsigned int ip) {
struct in_addr s = {.s_addr = ip};
if (ip == 0) {
return "";
}
return inet_ntoa(s);
}
const char *u32_to_str_ip_safe(unsigned int ip) {
struct in_addr s = {.s_addr = ip};
if (ip == 0) {
return strdup("");
}
return strdup(inet_ntoa(s));
}
int get_all_network_info(PSYS_NIC_INFO pInfo) {
int i;
unsigned long nicCnt;
struct ifreq buf[4096];
struct ifconf ifc;
PSYS_NIC_INFO pNicInfo;
PNIC_CTX pNic;
if (pInfo == NULL) {
LOG_MOD(error, ZLOG_MOD_MISC, "Malloc memory failed, size: %lu\n", sizeof(SYS_NIC_INFO));
return -ERR_INPUT_PARAMS;
}
if (g_sysNicInfo != NULL) {
pInfo->nicCnt = g_sysNicInfo->nicCnt;
pInfo->pNicCtx = g_sysNicInfo->pNicCtx;
return ERR_SUCCESS;
}
pNicInfo = (PSYS_NIC_INFO)malloc(sizeof(SYS_NIC_INFO));
if (pNicInfo == NULL) {
LOG_MOD(error, ZLOG_MOD_MISC, "Malloc memory failed, size: %lu\n", sizeof(SYS_NIC_INFO));
return -ERR_MALLOC_MEMORY;
}
memset(pNicInfo, 0, sizeof(SYS_NIC_INFO));
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock == -1) {
LOG_MOD(error, ZLOG_MOD_MISC, "Create socket failed\n");
free(pNicInfo);
return -ERR_SOCK_CREATE;
}
memset(&ifc, 0, sizeof(struct ifconf));
ifc.ifc_len = sizeof(struct ifreq) * 4096;
ifc.ifc_buf = (char *)buf;
if (ioctl(sock, SIOCGIFCONF, &ifc) == -1) {
close(sock);
free(pNicInfo);
LOG_MOD(error, ZLOG_MOD_MISC, "IOCTL SIOCGIFCONF socket failed\n");
return -ERR_SYS_CALL;
}
nicCnt = ifc.ifc_len / sizeof(struct ifreq);
pNicInfo->pNicCtx = (PNIC_CTX)malloc(sizeof(NIC_CTX) * nicCnt);
if (pNicInfo->pNicCtx == NULL) {
LOG_MOD(error, ZLOG_MOD_MISC, "Malloc memory failed, size: %lu * %lu\n", sizeof(NIC_CTX), nicCnt);
free(pNicInfo);
close(sock);
return -ERR_MALLOC_MEMORY;
}
LOG_MOD(trace, ZLOG_MOD_MISC, "Malloc memory size: %lu * %lu\n", sizeof(NIC_CTX), nicCnt);
memset(pNicInfo->pNicCtx, 0, sizeof(NIC_CTX) * nicCnt);
pNic = &pNicInfo->pNicCtx[0];
for (i = 0; i < nicCnt; i++) {
U32 ipAddr;
U32 netmaskAddr;
U32 bcAddr;
U8 mac[ETH_ALEN];
int ret = get_nic_info(buf[i].ifr_name, &ipAddr, &netmaskAddr, &bcAddr, mac);
if (ret == ERR_SUCCESS) {
strcpy(pNic->ethName, buf[i].ifr_name);
pNic->ipv4Addr = ipAddr;
pNic->ipv4Mask = netmaskAddr;
pNic->ipv4Boardcast = bcAddr;
memcpy(pNic->mac, mac, ETH_ALEN);
LOG_MOD(trace, ZLOG_MOD_MISC, "Network intreface(%d): %s\n", pNicInfo->nicCnt, pNic->ethName);
LOG_MOD(trace, ZLOG_MOD_MISC, "\t\tIP Address\t:%s\n", u32_to_str_ip(ipAddr));
LOG_MOD(trace, ZLOG_MOD_MISC, "\t\tNetmask Address\t:%s\n", u32_to_str_ip(netmaskAddr));
LOG_MOD(trace, ZLOG_MOD_MISC, "\t\tBoardcast Address\t:%s\n", u32_to_str_ip(bcAddr));
pNicInfo->nicCnt++;
pNic++;
} else {
LOG_MOD(warn,
ZLOG_MOD_MISC,
"Get system nic(%s) information error:%s(%d)\n",
buf[i].ifr_name,
getErrorEnumNameString(ret),
ret);
}
}
close(sock);
g_sysNicInfo = pNicInfo;
pInfo->nicCnt = g_sysNicInfo->nicCnt;
pInfo->pNicCtx = g_sysNicInfo->pNicCtx;
return ERR_SUCCESS;
}
const char *get_cur_process_name() {
static char g_exeName[1024] = {0};
if (strlen(g_exeName) > 0) {
return basename_v2(g_exeName);
}
memset(g_exeName, 0, 1024);
if (readlink("/proc/self/exe", g_exeName, 1023) <= 0) {
return NULL;
}
return basename_v2(g_exeName);
}
unsigned short calc_checksum(unsigned short *buffer, int size, U32 sum) {
unsigned long cksum = ((sum & 0xFFFF0000) >> 16) + (sum & 0xFFFF);
while (size > 1) {
cksum += *buffer++;
size -= sizeof(unsigned short);
}
if (size) {
cksum += *(unsigned short *)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >> 16);
return cksum;
//return (unsigned short)(~cksum);
}
unsigned short ip_checksum(unsigned char *pIp) {
unsigned int csum;
struct iphdr *pIph = (struct iphdr *)pIp;
pIph->check = 0;
csum = calc_checksum((unsigned short *)pIp, 20, 0);
csum = ((csum & 0xFFFF0000) >> 16) + (csum & 0xFFFF);
return (unsigned short)(~csum);
}
unsigned short udp_checksum(unsigned int saddr, unsigned int daddr, unsigned char *pUdp) {
unsigned char padBuf[12];
unsigned int csum;
struct udphdr *pUhd = (struct udphdr *)pUdp;
memcpy(&padBuf[0], &saddr, 4);
memcpy(&padBuf[4], &daddr, 4);
padBuf[8] = 0;
padBuf[9] = 17;
padBuf[10] = pUdp[4];
padBuf[11] = pUdp[5];
pUhd->check = 0;
csum = calc_checksum((unsigned short *)pUdp, ntohs(pUhd->len), 0);
csum = calc_checksum((unsigned short *)padBuf, 12, csum);
csum = ((csum & 0xFFFF0000) >> 16) + (csum & 0xFFFF);
return (unsigned short)(~csum);
}
int string_mac_to_bytes(const char *pStrMac, unsigned char macByte[6]) {
sds *tokens;
int i, nCnt;
if (pStrMac == NULL || strlen(pStrMac) != strlen("00:00:00:00:00:00")) {
LOG_MOD(error, ZLOG_MOD_MISC, "Input params error\n");
return -ERR_INPUT_PARAMS;
}
tokens = sdssplitlen(pStrMac, (int)strlen(pStrMac), ":", 1, &nCnt);
if (nCnt != 6) {
LOG_MOD(error, ZLOG_MOD_MISC, "Input MAC[%s] error: %d\n", pStrMac, nCnt);
return -ERR_INPUT_PARAMS;
}
for (i = 0; i < nCnt; i++) {
macByte[i] = strtoul(tokens[i], NULL, 16);
}
if (tokens) {
sdsfreesplitres(tokens, nCnt);
}
return ERR_SUCCESS;
}