ztp/confingure/prase_config.c

432 lines
12 KiB
C

//
// Created by xajhu on 2019/11/18 0018.
//
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/inotify.h>
#include <errno.h>
#include "common.h"
#include "log.h"
#include "err_code.h"
#include "ztp_config.h"
static char *g_ztpFilePath = NULL;
static char *g_devFilePath = NULL;
static pthread_t g_monThreadId;
static ZTP_CONFIG g_ztpInfo;
static DEVICE_CONFIG g_devInfo;
static void __init_dev_config(PDEVICE_CONFIG pCfg)
{
int i;
memset(pCfg, 0, sizeof(DEVICE_CONFIG));
for(i = 0; i < DEV_MAX_PORT; i++) {
pCfg->port_cfg[i].port_type = UNKNOWN_PORT;
pCfg->port_cfg[i].port_protocol = UNKNOWN_PRO_TYPE;
}
pCfg->lan_config.ip_type = UNKNOWN_IP_TYPE;
}
static int __get_dev_port_config(config_t *pCfg, DEV_PORT_CONFIG pPortCfg[], int *pMaxItems)
{
int i, nItems;
config_setting_t *pSetting;
if(pPortCfg == NULL || pMaxItems == NULL || *pMaxItems <= 0) {
return -ERR_INPUTERR;
}
pSetting = config_lookup(pCfg, "network.port");
if(pSetting == NULL) {
return -ERR_NOTFOUND;
}
nItems = config_setting_length(pSetting);
if(nItems <= 0) {
return -ERR_NOTFOUND;
} else if(nItems > *pMaxItems) {
nItems = *pMaxItems;
}
*pMaxItems = nItems;
for(i = 0; i < *pMaxItems; i++) {
char *pString;
int port_type, port_pro, iValue;
config_setting_t *pSubVal;
config_setting_t *pVal = config_setting_get_elem(pSetting, (unsigned int)i);
if(config_setting_lookup_int(pVal, "port_type", &port_type) == CONFIG_TRUE) {
pPortCfg[i].port_type = port_type;
}
// below this process WAN configures
if(port_type == LAN_PORT) {
continue;
}
if(config_setting_lookup_int(pVal, "protocol", &port_pro) == CONFIG_TRUE) {
pPortCfg[i].port_protocol = port_pro;
}
switch(port_pro) {
case STATIC_TYPE:
pSubVal = config_setting_get_member(pVal, "static");
if(pSubVal == NULL) {
break;
}
if(config_setting_lookup_int(pSubVal, "ip_type", &iValue) == CONFIG_TRUE) {
pPortCfg[i].wan_conf.static_config.ip_type = iValue;
}
if(config_setting_lookup_string(pSubVal, "ip_addr", (const char **)&pString) == CONFIG_TRUE) {
strcpy(pPortCfg[i].wan_conf.static_config.ip_addr, pString);
}
if(config_setting_lookup_string(pSubVal, "netmask", (const char **)&pString) == CONFIG_TRUE) {
strcpy(pPortCfg[i].wan_conf.static_config.netmask, pString);
}
if(config_setting_lookup_string(pSubVal, "gateway", (const char **)&pString) == CONFIG_TRUE) {
strcpy(pPortCfg[i].wan_conf.static_config.gateway, pString);
}
if(config_setting_lookup_string(pSubVal, "master_dns", (const char **)&pString) == CONFIG_TRUE) {
strcpy(pPortCfg[i].wan_conf.static_config.master_dns, pString);
}
if(config_setting_lookup_string(pSubVal, "backup_dns", (const char **)&pString) == CONFIG_TRUE) {
strcpy(pPortCfg[i].wan_conf.static_config.backup_dns, pString);
}
break;
case PPPOE_TYPE:
pSubVal = config_setting_get_member(pVal, "pppoe");
if(pSubVal == NULL) {
break;
}
if(config_setting_lookup_string(pSubVal, "username", (const char **)&pString) == CONFIG_TRUE) {
strcpy(pPortCfg[i].wan_conf.pppoe_config.username, pString);
}
if(config_setting_lookup_string(pSubVal, "password", (const char **)&pString) == CONFIG_TRUE) {
strcpy(pPortCfg[i].wan_conf.pppoe_config.password, pString);
}
break;
case DHCP_TYPE:
break;
default:
break;
}
}
return ERR_OK;
}
int load_dev_config(const char *devId)
{
config_t devCfg;
DEVICE_CONFIG devInfo;
char *pSubDir = g_ztpInfo.dev_dir;
char *pDirPath = strdup(g_ztpFilePath);
char *pDir;
char filePath[MAX_PATH];
memset(filePath, 0, MAX_PATH);
pDir = strrchr(pDirPath, '/');
if(pDir == NULL) {
snprintf(filePath, MAX_PATH, "../%s/%s.conf", pSubDir, devId);
} else {
*pDir = 0;
snprintf(filePath, MAX_PATH, "%s/%s/%s.conf", pDirPath, pSubDir, devId);
}
if(g_devFilePath) {
free(g_devFilePath);
g_devFilePath = strdup(filePath);
}
LOG_EX(LOG_Debug, "Dev configure path: %s\n", filePath);
config_init(&devCfg);
config_set_tab_width(&devCfg, 4);
if(config_read_file(&devCfg, filePath) != CONFIG_TRUE) {
LOG_EX(LOG_Error, "Read device configre file %s error %s at %d\n", filePath,
config_error_text(&devCfg), config_error_file(&devCfg));
config_destroy(&devCfg);
return -ERR_READFILE;
}
__init_dev_config(&devInfo);
devInfo.total_ports = DEV_MAX_PORT;
__get_dev_port_config(&devCfg, devInfo.port_cfg, &devInfo.total_ports);
devInfo.lan_config.ip_type = cfg_get_int_value(&devCfg, "network.lan_network.ip_type", IPV4_TYPE);
strncpy(devInfo.lan_config.ip_addr,
cfg_get_string_value(&devCfg, "network.lan_network.ip_addr", ""), MAX_IP_LEN - 1);
strncpy(devInfo.lan_config.netmask,
cfg_get_string_value(&devCfg, "network.lan_network.netmask", ""), MAX_IP_LEN - 1);
memcpy(&g_devInfo, &devInfo, sizeof(DEVICE_CONFIG));
free(pDirPath);
config_destroy(&devCfg);
return ERR_OK;
}
int load_ztp_config(const char *pPath)
{
config_t ztpCfg;
ZTP_CONFIG ztpInfo;
config_init(&ztpCfg);
config_set_tab_width(&ztpCfg, 4);
memset(&ztpInfo, 0, sizeof(ZTP_CONFIG));
if(config_read_file(&ztpCfg, pPath) != CONFIG_TRUE) {
LOG_EX(LOG_Error, "Read ztp configre file %s error %s at %d\n", pPath,
config_error_text(&ztpCfg), config_error_file(&ztpCfg));
config_destroy(&ztpCfg);
return -ERR_READFILE;
}
ztpInfo.svr_cfg.port = cfg_get_int_value(&ztpCfg, "ztp.server.port", 10000);
strncpy(ztpInfo.svr_cfg.server_url,
cfg_get_string_value(&ztpCfg, "ztp.server.domain", ""), MAX_PATH * 2 - 1);
strncpy(ztpInfo.dev_dir,
cfg_get_string_value(&ztpCfg, "ztp.dev_dir", DEVICE_ZTP_PATH), MAX_PATH - 1);
if(g_ztpInfo.svr_cfg.port != ztpInfo.svr_cfg.port) {
LOG_EX(LOG_Info, "Port Changed: [%d] --> [%d]\n", g_ztpInfo.svr_cfg.port, ztpInfo.svr_cfg.port);
g_ztpInfo.svr_cfg.port = ztpInfo.svr_cfg.port;
}
if(strcmp(g_ztpInfo.svr_cfg.server_url, ztpInfo.svr_cfg.server_url) != 0) {
LOG_EX(LOG_Info, "Url Changed: [%s] --> [%s]\n", g_ztpInfo.svr_cfg.server_url,
ztpInfo.svr_cfg.server_url);
memset(g_ztpInfo.svr_cfg.server_url, 0, MAX_PATH * 2);
strncpy(g_ztpInfo.svr_cfg.server_url, ztpInfo.svr_cfg.server_url, MAX_PATH * 2 - 1);
}
if(strcmp(g_ztpInfo.dev_dir, ztpInfo.dev_dir) != 0) {
LOG_EX(LOG_Info, "Device Changed: [%s] --> [%s]\n", g_ztpInfo.dev_dir, ztpInfo.dev_dir);
memset(g_ztpInfo.dev_dir, 0, MAX_PATH);
strncpy(g_ztpInfo.dev_dir, ztpInfo.dev_dir, MAX_PATH - 1);
}
config_destroy(&ztpCfg);
return ERR_OK;
}
#ifdef MONITOR_ZTP_CFG_FILE
static void *__cfg_file_monitor(void *p)
{
int wd;
int fd = inotify_init();
UNUSED(p);
if(fd == -1) {
LOG_EX(LOG_Error, "Create file watch error: %s\n", strerror(errno));
return NULL;
}
wd = inotify_add_watch(fd, g_ztpFilePath,
(IN_CREATE + IN_DELETE + IN_MODIFY + IN_MOVED_FROM + IN_MOVED_TO));
if(wd < 0) {
LOG_EX(LOG_Error, "Watch %s error %s\n", g_ztpFilePath, strerror(errno));
close(fd);
free(g_ztpFilePath);
return NULL;
}
while(g_ztpFilePath && strlen(g_ztpFilePath) > 0) {
unsigned char buf[MAX_PATH];
struct inotify_event *event = NULL;
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
memset(buf, 0, MAX_PATH);
if(select(fd + 1, &fds, NULL, NULL, NULL) > 0) {
ssize_t len;
unsigned int index = 0;
while(((len = read(fd, &buf, MAX_PATH)) < 0) && (errno == EINTR)); //没有读取到事件。
while(index < len) {
event = (struct inotify_event *)(buf + index);
//LOG_EX(LOG_Info, "event->mask: 0x%08x\n", event->mask);
switch(event->mask) {
case IN_MODIFY:
case IN_MOVED_FROM:
load_ztp_config(g_ztpFilePath);
break;
case IN_MOVED_TO:
case IN_DELETE:
case IN_CREATE:
//config_destroy(&ztpCfg);
break;
default:
break;
}
//获取事件。
index += sizeof(struct inotify_event) + event->len; //移动index指向下一个事件。
}
}
}
inotify_rm_watch(fd, wd);
free(g_ztpFilePath);
pthread_detach(pthread_self());
return NULL;
}
#endif
int init_configure(const char *pPath)
{
memset(&g_ztpInfo, 0, sizeof(ZTP_CONFIG));
__init_dev_config(&g_devInfo);
if(!pPath || strlen(pPath) == 0) {
LOG_EX(LOG_Warn, "Load default ztp configure file: %s\n", DEVICE_ZTP_PATH);
pPath = DEVICE_ZTP_PATH;
} else {
LOG_EX(LOG_Debug, "Load ztp configure file: %s\n", pPath);
}
if(access(pPath, F_OK) != 0) {
LOG_EX(LOG_Error, "Configure file %s not exists\n", pPath);
return -ERR_NOTFOUND;
}
g_ztpFilePath = strdup(pPath);
load_ztp_config(g_ztpFilePath);
#ifdef MONITOR_ZTP_CFG_FILE
pthread_create(&g_monThreadId, NULL, __cfg_file_monitor, NULL);
#endif
return ERR_OK;
}
int cfg_get_array_int_value(config_t *pCfg, const char *pTags, int *pArray, int *pMaxItem)
{
int i, nItems;
config_setting_t *pSetting;
if(pTags == NULL || strlen(pTags) == 0
|| pMaxItem == NULL || *pMaxItem <= 0 || pArray == NULL) {
return -ERR_INPUTERR;
}
pSetting = config_lookup(pCfg, pTags);
if(pSetting == NULL) {
return -ERR_NOTFOUND;
}
nItems = config_setting_length(pSetting);
if(nItems > *pMaxItem) {
nItems = *pMaxItem;
}
*pMaxItem = nItems;
for(i = 0; i < *pMaxItem; i++) {
pArray[i] = config_setting_get_int_elem(pSetting, i);
}
return ERR_OK;
}
char *cfg_get_string_value(config_t *pCfg, const char *pTags, char *pDefValue)
{
char *pValue = pDefValue;
if(pTags == NULL || strlen(pTags) == 0) {
return pDefValue;
}
if(config_lookup_string(pCfg, pTags, (const char **)&pValue) != CONFIG_TRUE) {
return pDefValue;
}
return pValue;
}
int cfg_get_int_value(config_t *pCfg, const char *pTags, int defValue)
{
int iValue = defValue;
if(pTags == NULL || strlen(pTags) == 0) {
return defValue;
}
if(config_lookup_int(pCfg, pTags, &iValue) != CONFIG_TRUE) {
return defValue;
}
return iValue;
}
double cfg_get_float_value(config_t *pCfg, const char *pTags, double defValue)
{
double dValue = defValue;
if(pTags == NULL || strlen(pTags) == 0) {
return defValue;
}
if(config_lookup_float(pCfg, pTags, &dValue) != CONFIG_TRUE) {
return defValue;
}
return dValue;
}
int cfg_get_bool_value(config_t *pCfg, const char *pTags, int defValue)
{
int iValue = defValue;
if(pTags == NULL || strlen(pTags) == 0) {
return defValue;
}
if(config_lookup_bool(pCfg, pTags, &iValue) != CONFIG_TRUE) {
return defValue;
}
return iValue;
}