432 lines
12 KiB
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;
|
|
}
|