/*!Copyright(c) 2012-2019 Shenzhen TP-LINK Technologies Co.Ltd.
*
*\file url_class.c
*\brief process for URL query
*
*\author Wanghao
*\version 1.0.0
*\date 27Aug19
*
*\history
*
*/
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <string.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/socket.h>
#include <getopt.h>
#include <errno.h>
#include <avira/auc/aucApi.h>
#include <pthread.h>
#include <signal.h>
#include <sys/time.h>
#include <curl/curl.h>
#include "cJSON.h"
#include <uci.h>
#include <mali_url_check.h>
#include <fcntl.h>
#include <unistd.h>
#define printErr(fmt, args...) printf("\033[1m[ %s ] %03d: "fmt"\033[0m", __FUNCTION__, __LINE__, ##args)
#define printWar(fmt, args...) printf("\033[1m[ %s ] %03d: "fmt"\033[0m", __FUNCTION__, __LINE__, ##args)
#define CURL_DEBUG 0
#define URL_CLASS_LOG_LEVEL LOG_LEVEL_MAX
#define URL_CLASS_LOG(level, fmt, args...) \
do \
{ \
if (level >= URL_CLASS_LOG_LEVEL) \
{ \
static char cmd[1024] = {0}, final[1024+128] = {0}; \
struct timeval tv; \
struct tm* local; \
gettimeofday(&tv, NULL); \
local = localtime(&tv.tv_sec); \
memset(cmd,0,sizeof(cmd));memset(final,0,sizeof(final));\
snprintf(cmd, sizeof(cmd), fmt, ##args); \
snprintf(final, sizeof(final), "echo \"%04d-%02d-%02d %02d:%02d:%02d.%03d|level:%d|%s:%d|%s| - ",\
local->tm_year + 1900, local->tm_mon + 1, local->tm_mday, \
local->tm_hour, local->tm_min, local->tm_sec, (int)(tv.tv_usec / 1000), \
level, __FILE__, __LINE__, __func__); \
int _i = 0, _j = strlen(final); \
for(_i = 0; _i < 1024 && _j < 1024+128-15; _i++,_j++) \
{ \
if(cmd[_i] == '\"' || cmd[_i] == '\\' || cmd[_i] == '`' || cmd[_i] == '$') \
{ \
final[_j++] = '\\'; \
} \
final[_j] = cmd[_i]; \
} \
strncpy(final + (final[strlen(final) - 1] == '\n'? strlen(final)-1: strlen(final)), "\"> /dev/console", 16); \
system(final); \
} \
} while (0)
#define MIN(a,b) ((a)<(b) ? (a):(b))
#define MALI_MAX_WAIT_TIME 1024
typedef enum
{
LOG_LEVEL_DEBUG = 0, // log level debug
LOG_LEVEL_INFO, // log level information
LOG_LEVEL_WARN, // log level warning
LOG_LEVEL_ERROR, // log level error
LOG_LEVEL_EMRG, // log level emergency
LOG_LEVEL_MAX
}E_LOG_LEVE;
struct Options
{
bool use_tp_service;
};
struct Options opts;
#define MAX_PAYLOAD 1024 // maximum payload size
#ifndef NETLINK_URL_CLASS
#define NETLINK_URL_CLASS 27
#endif
//#define MAX_URL_ENTRY_LEN 512//256
#define MAX_URL_LEN 256
#define MAX_URL_CAT_DEFAULT 9999
#define PCTL_WEB_URL_ID_ALL 0xfffe
#if SUPPORT_CLOUD_UPDATE_AUC_INFO
#define POST_TRANSFER_TIMEOUT 20
#define POST_CONNECT_TIMEOUT 20
#define AUC_UPDATE_TIME_INTERVAL_DEFAULT 3600 //1h
#define AUC_UPDATE_TIME_INTERVAL_FAST 10 //10s
#define REQUEST_TIMEOUT_MS 8000
#define MAX_TOKEN_LEN 128
#define FILE_CLOUD_TOKEN_HOMECARE "/tmp/cloud/cloud_token_homecare"
#define GET_AUC_URL_POSTFIX "/v1/configuration/auc-service-info"
#define CA_CRT_PATH "/etc/certificate/2048_newroot.cer"
struct auc_update_status_info {
int update_time_interval;
time_t updata_time_stamp_last;
};
static struct auc_update_status_info auc_update_status =
{
.update_time_interval = AUC_UPDATE_TIME_INTERVAL_DEFAULT,
.updata_time_stamp_last = 0,
};
typedef struct _st_http_resinfo
{
long status_code;
}st_http_resinfo;
#endif
enum url_req {
URL_REQ_VOID = 0,
URL_REQ_HELLO,
URL_REQ_CAT,
URL_REQ_LOG,
URL_REQ_LOG_HISTORY,
URL_REQ_BYE,
URL_REQ_END
};
struct url_carrier {
int id;
int info_id;
unsigned char url_len;
unsigned int cat_id;
unsigned int cat_map;
char url[MAX_URL_LEN];
};
enum url_process_status {
URL_PROCESS_READY = 0, //waiting for auc process
URL_PROCESSING //auc is processing, changing url is useless
};
struct url_entry {
int id;
int info_id;
unsigned int cat_map;
unsigned char query;
unsigned char url_len;
enum url_process_status process_flag;
struct url_entry *prev;
struct url_entry *next;
char url[MAX_URL_LEN];
};
pthread_mutex_t url_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mali_url_check_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
//struct url_entry url_array[MAX_URL_ENTRY_LEN];
struct url_entry *url_array;
static struct url_entry url_list = {
.id = 0,
.info_id = 0,
.cat_map = 0,
.query = 0,
.url_len = 0,
.prev = NULL,
.next = NULL,
};
int sock_fd = -1;
//cat mapping table
int mapping_table[][32] = {
{1, 274, 276, 374, 132, -1}, //1100, 1-Games
{2, 193, 447, 449, -1}, //1000, 2-Download
{3, 222, 223, 224, 357, -1}, //900, 3-Media
{4, 107, 388, -1}, //800, 4-Pay-to-surf & Shopping
{5, 414, 445, -1}, //700, 5-Social Networking
{6, 359, 360, 355, 293, 397, 450, 451, -1}, //600, 6-Oline Communications and Search
{7, 443, -1}, //500, 7-Gambling
{10, 241, 179, 76, 170, 167, -1}, //200, 10-Sex Education
{11, 234, 400, 269, 444, 446, 395, 429, 391, 390, 103, 64, 65, 66, 149, 452, 453, 442, -1}, //100, 11-Adult Content
{13, 2, -1}, //000, unsafe, 13-Malware
{14, 3, -1}, //000, unsafe, 14-Phishing
{15, 197, -1}, // 15-web_search
{12, MAX_URL_CAT_DEFAULT, -1}, //2000, 12-Other(Default)
{-1} //END
};
static inline void strncpy_safe(char *__dest, const char *__src, size_t __n)
{
strncpy(__dest, __src, __n);
__dest[__n] = '\0';
}
static void on_exit_handler()
{
struct sockaddr_nl dest_addr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
struct msghdr msg;
int state_smg = 0;
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
if (!nlh) {
printErr("malloc nlmsghdr error!\n");
close(sock_fd);
return;
}
//say bye to kernel
memset(nlh,0,NLMSG_SPACE(MAX_PAYLOAD));
memset(&dest_addr,0,sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0;
dest_addr.nl_groups = 0;
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = 0;
nlh->nlmsg_flags = 0;
nlh->nlmsg_type = URL_REQ_BYE;
iov.iov_base = (void *)nlh;
iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
memset(&msg, 0, sizeof(msg));
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
state_smg = sendmsg(sock_fd, &msg, 0);
if (state_smg < 0) {
printErr("get error sendmsg = %s\n",strerror(errno));
}
if (nlh) {
free(nlh);
}
close(sock_fd);
return;
}
static void signal_exit_handler(int sig)
{
exit(0);
}
static int url_send(int id, unsigned int cat_id, char *url, unsigned char url_len, unsigned short type)
{
struct nlmsghdr *nlh = NULL;
struct iovec iov;
struct msghdr msg;
struct sockaddr_nl dest_addr;
struct url_carrier data;
int state_smg = 0;
int ret = 0;
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
if (!nlh) {
printErr("malloc nlmsghdr error!\n");
return -1;
}
memset(&dest_addr,0,sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0;
dest_addr.nl_groups = 0;
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
nlh->nlmsg_type = type;
memset(&data, 0, sizeof(struct url_carrier));
data.id = id;
data.cat_id = cat_id;
data.url_len = url_len;
strncpy_safe(data.url, url, url_len);
printWar("url_send to kernel, id=%d, cat_id=%x, url=%s, url_len=%d \n", data.id, data.cat_id, data.url, data.url_len);
memcpy(NLMSG_DATA(nlh), &data, sizeof(struct url_carrier));
iov.iov_base = (void *)nlh;
iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
memset(&msg, 0, sizeof(msg));
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
state_smg = sendmsg(sock_fd, &msg, 0);
if (state_smg < 0) {
printErr("get error sendmsg = %s\n",strerror(errno));
ret = -1;
goto out;
}
out:
if (nlh) {
free(nlh);
}
return ret;
}
static void __attribute__((unused)) dump_list(struct url_entry *list)
{
printErr("dump:\n");
while (list) {
printWar("id=%d url=%s\n", list->id, list->url);
list = list->next;
}
}
static void cond_timedwait(long timeout)
{
struct timespec abstime;
struct timeval now;
long nsec = 0;
pthread_mutex_lock(&url_lock);
gettimeofday(&now, NULL);
nsec = now.tv_usec * 1000 + (timeout % 1000) * 1000000;
abstime.tv_sec=now.tv_sec + nsec / 1000000000 + timeout / 1000;
abstime.tv_nsec=nsec % 1000000000;
pthread_cond_timedwait(&cond, &url_lock, &abstime);
pthread_mutex_unlock(&url_lock);
}
#if SUPPORT_CLOUD_UPDATE_AUC_INFO
static int OnDebug(CURL * curl, curl_infotype itype, char * pData, size_t size, void *lpVoid)
{
if (itype == CURLINFO_TEXT)
{
//URL_CLASS_LOG(LOG_LEVEL_DEBUG,"[TEXT]%s", pData);
}
else if (itype == CURLINFO_HEADER_IN)
{
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "[HEADER_IN]%s", pData);
}
else if (itype == CURLINFO_HEADER_OUT)
{
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "[HEADER_OUT]%s", pData);
}
else if (itype == CURLINFO_DATA_IN)
{
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "[DATA_IN]%s", pData);
}
else if (itype == CURLINFO_DATA_OUT)
{
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "[DATA_OUT]%s", pData);
}
return 0;
}
static size_t OnWriteData_Post(void* buffer, size_t size, size_t nmemb, void* lpVoid)
{
if (NULL == buffer)
{
return -1;
}
unsigned int len = (unsigned int)size * (unsigned int)nmemb;
char *str = (char*)malloc(len + 1);
if (NULL == str)
{
return -1;
}
char* pData = (char*)buffer;
memset(str, 0, len + 1);
memcpy(str, pData, len);
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "response: %s\n", str);
char **response = (char**)lpVoid;
*response = str;
return len;
}
static size_t cloud_https_post(const char *pUrl,
const char *requestHeader,
const char *request,
char **response,
st_http_resinfo *pHttpResInfo)
{
CURLcode res;
CURL* curl = NULL;
struct curl_slist *headers = NULL;
#ifdef CURL_DEBUG
char errbuf[CURL_ERROR_SIZE];
memset(errbuf, '\0', CURL_ERROR_SIZE);
#endif
if (NULL == pUrl || NULL == request || NULL == response || NULL == pHttpResInfo)
{
return CURLE_FAILED_INIT;
}
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "pUrl:%s\n requestHeader:%s\n request:%s\n", pUrl, requestHeader, request);
res = curl_global_init(CURL_GLOBAL_ALL);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl global init fail and ret %d", res);
return res;
}
curl = curl_easy_init();
if (NULL == curl)
{
res = CURLE_FAILED_INIT;
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl init fail");
goto exit;
}
//headers = curl_slist_append(headers, "Content-Type: application/json;charset=UTF-8");
headers = curl_slist_append(headers, "Content-Type: application/json");
if (NULL == headers)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl get header list fail");
goto exit;
}
if ((NULL != requestHeader) && (0 < strlen(requestHeader)))
{
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "requestHeader is %s", requestHeader);
headers = curl_slist_append(headers, requestHeader);
if (NULL == headers)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl append requestHeader fail");
goto exit;
}
}
#ifdef CURL_DEBUG
//provide a buffer to store errors in
res = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errbuf);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl set option CURLOPT_ERRORBUFFER ret %d", res);
goto exit;
}
#endif
if (CURL_DEBUG)
{
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "post sesstion debug on");
res = curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl set option CURLOPT_VERBOSE ret %d", res);
goto exit;
}
res = curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, OnDebug);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl set option CURLOPT_DEBUGFUNCTION ret %d", res);
goto exit;
}
}
//set url
res = curl_easy_setopt(curl, CURLOPT_URL, pUrl);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl set option CURLOPT_URL ret %d", res);
goto exit;
}
//set header
res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl set option CURLOPT_HTTPHEADER ret %d", res);
goto exit;
}
//set post method
res = curl_easy_setopt(curl, CURLOPT_POST, 1);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl set option CURLOPT_POST ret %d", res);
goto exit;
}
res = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, request);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl set option CURLOPT_POSTFIELDS ret %d", res);
goto exit;
}
//set read/write params
res = curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl set option CURLOPT_READFUNCTION ret %d", res);
goto exit;
}
res = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, OnWriteData_Post);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl set option CURLOPT_WRITEFUNCTION ret %d", res);
goto exit;
}
res = curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)response);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl set option CURLOPT_WRITEDATA ret %d", res);
goto exit;
}
res = curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl set option CURLOPT_NOSIGNAL ret %d", res);
goto exit;
}
//set certificate info
res = curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl set option CURLOPT_SSL_VERIFYPEER ret %d", res);
goto exit;
}
res = curl_easy_setopt(curl, CURLOPT_CAINFO, CA_CRT_PATH);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl set option CURLOPT_CAINFO ret %d", res);
goto exit;
}
//set CURLOPT_CONNECTTIMEOUT
res = curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, POST_TRANSFER_TIMEOUT);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl set option CURLOPT_CONNECTTIMEOUT ret %d", res);
goto exit;
}
//set CURLOPT_TIMEOUT
res = curl_easy_setopt(curl, CURLOPT_TIMEOUT, POST_CONNECT_TIMEOUT);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl set option CURLOPT_TIMEOUT ret %d", res);
goto exit;
}
//CURLOPT needs to be set_ FOLLOWLOCATION is 1, otherwise, the data after redirecting will not be returned
res = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION,1);
if (CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "curl set option CURLOPT_FOLLOWLOCATION ret %d", res);
goto exit;
}
res = curl_easy_perform(curl);
#ifdef CURL_DEBUG
if(CURLE_OK != res)
{
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "curl post return error: %s", errbuf);
}
#endif
curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &(pHttpResInfo->status_code));
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "cloud_https_post done. ret %d, http status code %d",
res, pHttpResInfo->status_code);
exit:
if (headers)
{
curl_slist_free_all(headers);
}
if (curl)
{
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return res;
}
static int get_token_url(char *token, char *url)
{
int ret = -1;
int retry_count = 3;
FILE *fp = NULL;
while (retry_count > 0)
{
if(fp = fopen(FILE_CLOUD_TOKEN_HOMECARE, "r"))
{
fscanf(fp, "%s", token);
fscanf(fp, "%s", url);
fclose(fp);
ret = 0;
break;
}
else
{
system("cloud_getDevToken homecare");
}
retry_count--;
}
if ((*(token + MAX_TOKEN_LEN - 1) != 0) || (*(url + MAX_URL_LEN - 1) != 0))
{
URL_CLASS_LOG(LOG_LEVEL_WARN, "token or url pointer out of range");
ret = -1;
}
return ret;
}
static char* get_auc_info_from_cloud_request_data()
{
int ret = -1;
cJSON* request_data_json = NULL;
char* request_data = NULL;
unsigned char country_code[3] = {0};
FILE *fp = NULL;
if ((request_data_json = cJSON_CreateObject()) == NULL)
{
goto out;
}
if (fp = popen("getfirm COUNTRY | tr 'A-Z' 'a-z'", "r"))
{
if (fread(country_code, sizeof(char), 2, fp) > 0)
{
cJSON_AddStringToObject(request_data_json, (const char*)"region", (const char*)country_code);
request_data = cJSON_PrintUnformatted(request_data_json);
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "request_data:%s", request_data);
}
pclose(fp);
}
cJSON_Delete(request_data_json);
return request_data;
out:
return NULL;
}
static int get_auc_info_from_cloud(struct auc_info *auc_info, char *device_token, char *url_prefix)
{
int ret = -1;
int ret_post = 0;
char request_url[MAX_URL_LEN] = {0};
char request_header[MAX_TOKEN_LEN + 32] = {0};
char *request_data = NULL;
char *response = NULL;
st_http_resinfo httpResInfo;
cJSON* response_json = NULL;
cJSON* auc_server_json= NULL;
cJSON* api_key_json = NULL;
cJSON* user_guid_json = NULL;
if (auc_info == NULL || device_token == NULL || url_prefix == NULL)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "params error\n");
return ret;
}
memset(&httpResInfo, 0, sizeof(st_http_resinfo));
snprintf(request_url, MAX_URL_LEN, "%s%s", url_prefix, GET_AUC_URL_POSTFIX);
snprintf(request_header, MAX_TOKEN_LEN + 32, "Authorization: %s", device_token);
request_data = get_auc_info_from_cloud_request_data();
//get post result
ret_post = cloud_https_post(request_url, request_header, request_data, &response, &httpResInfo);
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "curl post return %d http retcode: %ld", ret_post, httpResInfo.status_code);
if(request_data)
{
cJSON_free(request_data);
}
if (response && httpResInfo.status_code == 200)
{
response_json = cJSON_Parse(response);
auc_server_json= cJSON_GetObjectItem(response_json, "aucServerUrl");
api_key_json = cJSON_GetObjectItem(response_json, "apiKey");
user_guid_json = cJSON_GetObjectItem(response_json, "userGuid");
if (auc_server_json->valuestring && api_key_json->valuestring && user_guid_json->valuestring)
{
snprintf(auc_info->auc_server, MAX_AUC_SERVER_LEN, "%s", auc_server_json->valuestring);
snprintf(auc_info->api_key, MAX_API_KEY_LEN, "%s", api_key_json->valuestring);
snprintf(auc_info->user_guid, MAX_USER_GUID, "%s", user_guid_json->valuestring);
ret = 0;
}
}
out:
cJSON_Delete(response_json);
return ret;
}
static void set_retry_time_interval(void)
{
if (auc_update_status.update_time_interval == AUC_UPDATE_TIME_INTERVAL_DEFAULT)
{
auc_update_status.update_time_interval = AUC_UPDATE_TIME_INTERVAL_FAST;
}
else if (auc_update_status.update_time_interval < AUC_UPDATE_TIME_INTERVAL_DEFAULT
&& (auc_update_status.update_time_interval * 2) < AUC_UPDATE_TIME_INTERVAL_DEFAULT)
{
auc_update_status.update_time_interval = auc_update_status.update_time_interval * 2;
}
else
{
auc_update_status.update_time_interval = AUC_UPDATE_TIME_INTERVAL_DEFAULT;
}
}
static void update_libauc_url(struct auc_info *auc_info, bool use_tp_service)
{
char device_token[MAX_TOKEN_LEN] = {0};
char cloud_homecare_url[MAX_URL_LEN] = {0};
time_t time_stamp;
memset(device_token, 0, MAX_TOKEN_LEN);
memset(cloud_homecare_url, 0, MAX_URL_LEN);
memset(auc_info->auc_server, 0, MAX_AUC_SERVER_LEN);
memset(auc_info->api_key, 0, MAX_API_KEY_LEN);
memset(auc_info->user_guid, 0, MAX_USER_GUID);
//get time stamp
time(&time_stamp);
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "start time_stamp:%d, updata_time_stamp_last:%d, update_time_interval:%d\n",
time_stamp, auc_update_status.updata_time_stamp_last, auc_update_status.update_time_interval);
if ((time_stamp - auc_update_status.updata_time_stamp_last) >= auc_update_status.update_time_interval)
{
if(use_tp_service)
{
if (0 == (get_token_url(device_token, cloud_homecare_url)))
{
memset(auc_info->tp_auc_server, 0, MAX_AUC_SERVER_LEN);
snprintf(auc_info->tp_auc_server, MAX_AUC_SERVER_LEN, "%s", cloud_homecare_url);
auc_update_status.updata_time_stamp_last = time_stamp;
auc_update_status.update_time_interval = AUC_UPDATE_TIME_INTERVAL_DEFAULT;
}
else
{
auc_update_status.updata_time_stamp_last = time_stamp;
set_retry_time_interval();
}
}
else
{
if (0 == (get_token_url(device_token, cloud_homecare_url)))
{
if (0 == get_auc_info_from_cloud(auc_info, device_token, cloud_homecare_url))
{
auc_update_status.updata_time_stamp_last = time_stamp;
auc_update_status.update_time_interval = AUC_UPDATE_TIME_INTERVAL_DEFAULT;
}
else
{
auc_update_status.updata_time_stamp_last = time_stamp;
set_retry_time_interval();
}
}
else
{
auc_update_status.updata_time_stamp_last = time_stamp;
set_retry_time_interval();
}
}
}
else
{
}
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "end time_stamp:%d, updata_time_stamp_last:%d, update_time_interval:%d\n",
time_stamp, auc_update_status.updata_time_stamp_last, auc_update_status.update_time_interval);
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "auc_server:%s, tp_auc_server:%s, api_key:%s, user_guid:%s\n",
auc_info->auc_server, auc_info->tp_auc_server, auc_info->api_key, auc_info->user_guid);
return;
}
#endif
static void *mali_checkQuery(void *unused)
{
int ret = 0;
int ret_mali = 0;
int failed_num = 0;
unsigned int wait_time = 0;
parse_para para = {0, 0, 0};
srand((uint32_t)getpid());
while (1)
{
ret = parse_config(¶);
if(0 == ret)
{
if ((web_protection)&&(para.web_protection))
{
ret_mali = mali_url_hash_list_update(true);
if (ret_mali < 0)
{
if (!failed_num)
wait_time = 2 + (rand() % 254);
else if (wait_time < MALI_MAX_WAIT_TIME)
wait_time <<= 1;
failed_num++;
sleep(MIN(wait_time, MALI_MAX_WAIT_TIME));
}
else
{
if (!access(CLOUD_HASH_FILE_UPDATE_FLAG, R_OK))
{
pthread_mutex_lock(&mali_url_check_lock);
mali_url_hash_list_update(false);
pthread_mutex_unlock(&mali_url_check_lock);
}
failed_num = 0;
}
}
else if ((web_protection)&&(!para.web_protection))
{
pthread_mutex_lock(&mali_url_check_lock);
mali_url_check_free();
web_protection = false;
pthread_mutex_unlock(&mali_url_check_lock);
failed_num = 0;
}
else if ((!web_protection)&&(para.web_protection))
{
pthread_mutex_lock(&mali_url_check_lock);
ret_mali = mali_url_check_init(false);
if (0 == ret_mali)
{
web_protection = true;
pthread_mutex_unlock(&mali_url_check_lock);
failed_num = 0;
}
else
{
pthread_mutex_unlock(&mali_url_check_lock);
if (!failed_num)
wait_time = 2 + (rand() % 254);
else if (wait_time < MALI_MAX_WAIT_TIME)
wait_time <<= 1;
failed_num++;
sleep(MIN(wait_time, MALI_MAX_WAIT_TIME));
}
}
}
sleep(5);
}
}
void write_to_csv(const char *url, int original_cat_id, int mapped_cat_id, const char *category_name) {
int fd = open("/var/auc_classification_results.csv", O_CREAT | O_WRONLY | O_APPEND, 0644);
if (fd != -1) {
char buffer[512];
const char *name = (category_name != NULL) ? category_name : ""; // 处理NULL情况
snprintf(buffer, sizeof(buffer), "%s,%d,%d,%s\n", url, original_cat_id, mapped_cat_id, name); // 添加名称列
write(fd, buffer, strlen(buffer));
close(fd);
}
}
static void *aucQuery(void *unused)
{
int ret = 0;
struct url_info url_info;
bool is_mali = false;
#if SUPPORT_CLOUD_UPDATE_AUC_INFO
struct auc_info auc_info;
#endif
unsigned int cat_id = 0;
int tmp_id = 0;
int index = 0;
int index_cat = 0;
int index_subcat = 0;
unsigned char matched = 0;
struct url_entry *tmp_list = NULL;
struct url_entry *clean = NULL;
unsigned char tmp_url_len;
char tmp_url[MAX_URL_LEN] = {0};
printWar("create AUC query thread\n");
while (1) {
pthread_mutex_lock(&url_lock);
tmp_list = url_list.next;
pthread_mutex_unlock(&url_lock);
while (tmp_list) {
pthread_mutex_lock(&url_lock);
tmp_list->process_flag = URL_PROCESSING;
pthread_mutex_unlock(&url_lock);
url_info.url = tmp_list->url;
url_info.info_len = 0;
ret = pthread_mutex_trylock(&mali_url_check_lock);
if (!ret)
{
is_mali = web_protection? is_url_malicious(url_info.url) : false;
if (is_mali)
{
cat_id = URL_CAT_SECURITY;
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "Malicious URL detected. URL: %s, Original Cat ID: %d, Mapped Cat ID: %d", url_info.url, cat_id, cat_id);
#if DEBUG
printWar("cat ret=%d url=%s id=%d info_id=%d\n", cat_id, url_info.url, tmp_list->id, tmp_list->info_id);
#endif /* DEBUG */
pthread_mutex_lock(&url_lock);
tmp_list->prev->next = tmp_list->next;
if (tmp_list->next) {
tmp_list->next->prev = tmp_list->prev;
}
tmp_list->query = 1;
tmp_id = tmp_list->id;
tmp_list->id = 0;
tmp_list->info_id = 0;
tmp_list->cat_map = 0;
tmp_url_len = tmp_list->url_len;
memset(tmp_url, 0, MAX_URL_LEN);
strncpy_safe(tmp_url, tmp_list->url, tmp_list->url_len);
clean = tmp_list;
tmp_list = tmp_list->next;
clean->next = NULL;
clean->prev = NULL;
pthread_mutex_unlock(&url_lock);
pthread_mutex_unlock(&mali_url_check_lock);
write_to_csv(url_info.url, cat_id, cat_id, "Security");
goto block_mali;
}
else
{
pthread_mutex_unlock(&mali_url_check_lock);
}
}
if((!opts.use_tp_service && tmp_list->cat_map) ||
(opts.use_tp_service && (tmp_list->info_id != PCTL_WEB_URL_ID_ALL) && (tmp_list->cat_map & (~URL_CAT_SECURITY))))
{
printWar("before send to auc\n");
#if SUPPORT_CLOUD_UPDATE_AUC_INFO
update_libauc_url(&auc_info, opts.use_tp_service);
ret = auc_query(&url_info, &auc_info, opts.use_tp_service);
#else
ret = auc_query(&url_info, opts.use_tp_service);
#endif
printWar("after send to auc\n");
for (index = 0; index < url_info.info_len; index++) {
printWar("cat ret=%d url=%s id=%d name=%s\n", ret, url_info.url, url_info.info[index].id, url_info.info[index].name);
}
}
//remove from url_list
pthread_mutex_lock(&url_lock);
tmp_list->prev->next = tmp_list->next;
if (tmp_list->next) {
tmp_list->next->prev = tmp_list->prev;
}
tmp_list->query = 1;
tmp_id = tmp_list->id;
tmp_list->id = 0;
tmp_list->info_id = 0;
tmp_list->cat_map = 0;
tmp_url_len = tmp_list->url_len;
memset(tmp_url, 0, MAX_URL_LEN);
strncpy_safe(tmp_url, tmp_list->url, tmp_list->url_len);
clean = tmp_list;
tmp_list = tmp_list->next;
clean->next = NULL;
clean->prev = NULL;
pthread_mutex_unlock(&url_lock);
//send to kernel
cat_id = 0;
int original_cat_id = 0;
const char *category_name = "";
for (index = 0; index < url_info.info_len; index++) {
original_cat_id = url_info.info[index].id;
category_name = url_info.info[index].name;
int cat_id = 0; // 每次循环初始化 cat_id
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "Non-malicious URL. URL: %s, Original Cat ID: %d, Mapped Cat ID: %d", url_info.url, original_cat_id, cat_id);
for (index_cat = 0; mapping_table[index_cat][0] > 0; index_cat++) {
matched = 0;
for (index_subcat = 1; mapping_table[index_cat][index_subcat] >= 0; index_subcat++) {
if (url_info.info[index].id == mapping_table[index_cat][index_subcat] ||
mapping_table[index_cat][index_subcat] == MAX_URL_CAT_DEFAULT) {
cat_id |= 0x1 << (mapping_table[index_cat][0] - 1);
matched = 1;
break;
}
}
if (matched) {
break;
}
}
// 将结果写入CSV文件
write_to_csv(url_info.url, original_cat_id, cat_id, category_name);
}
block_mali:
printWar("send to kernel, url=%s cat_id=%x\n", url_info.url, cat_id);
url_send(tmp_id, cat_id, tmp_url, tmp_url_len, URL_REQ_CAT);
printWar("after send to kernel\n");
}
cond_timedwait(500);//500ms
}
return 0;
}
static const char* short_opt = "s:h";
static struct option long_opt[] =
{
{"server" , required_argument , NULL, 'a'},
{"help" , no_argument , NULL, 'h'},
{0 , 0 , NULL, 0 }
};
static void printHelp(char *progName);
static int parseOpts(int argc, char* argv[], struct Options* opt);
static void printHelpInstruction(char *progName);
static unsigned int get_max_url_entry_len(void)
{
unsigned int *url_entry_len = NULL;
int state;
struct msghdr msg;
struct iovec iov;
struct nlmsghdr *nlh = NULL;
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
if (!nlh) {
printErr("malloc nlmsghdr error!\n");
return 0;
}
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
nlh->nlmsg_type = URL_REQ_HELLO;
iov.iov_base = (void *)nlh;
iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
memset(&msg, 0, sizeof(msg));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
if (sock_fd < 0) {
printErr("error getting socket in recving: %s\n", strerror(errno));
return 0;
}
state = recvmsg(sock_fd, &msg, 0);
if(state < 0) {
printWar("state<1\n");
return 0;
}
//store to array
url_entry_len = (unsigned int *)NLMSG_DATA(nlh);
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "msg from kernel, max_url_entry_len=%u\n", *url_entry_len);
return *url_entry_len;
}
int main(int argc, char* argv[])
{
int state;
struct sockaddr_nl src_addr, dest_addr;
struct nlmsghdr *nlh = NULL;
struct iovec iov;
struct msghdr msg;
int retval;
int state_smg = 0;
pthread_t pid, pid_mali;
int pret = 0;
struct url_carrier *tmp = NULL;
int index;
pid_t fpid = 0;
int ret = 0;
int rc = parseOpts(argc, argv, &opts);
unsigned int url_entry_len = 0;
unsigned int malloc_url_entry_len = 0;
if (!rc) {
return 1;
}
fpid = fork();
if (fpid < 0) {
printErr("error fork.../n");
exit(1);
}
else if (fpid > 0) {
exit(0);
}
//setup exit handler
atexit(on_exit_handler);
signal(SIGTERM, signal_exit_handler);
signal(SIGINT, signal_exit_handler);
// Create a socket
sock_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_URL_CLASS);
if (sock_fd < 0) {
printErr("error getting socket: %s\n", strerror(errno));
return -1;
}
int send_buf = 4096;
int recv_buf = 4096;
if(setsockopt(sock_fd, SOL_SOCKET, SO_SNDBUF, &send_buf, sizeof(send_buf)) < 0)
{
printErr("setsockopt: %s", strerror(errno));
}
if(setsockopt(sock_fd, SOL_SOCKET, SO_RCVBUF, &recv_buf, sizeof(recv_buf)) < 0)
{
printErr("setsockopt: %s", strerror(errno));
}
// To prepare binding
memset(&src_addr, 0, sizeof(src_addr));
src_addr.nl_family = AF_NETLINK;
src_addr.nl_pid = getpid();
src_addr.nl_groups = 0;
retval = bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
if (retval < 0) {
printErr("bind failed: %s\n", strerror(errno));
ret = -1;
goto exit;
}
nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
if (!nlh) {
printErr("malloc nlmsghdr error!\n");
ret = -1;
goto exit;
}
memset(&dest_addr,0,sizeof(dest_addr));
dest_addr.nl_family = AF_NETLINK;
dest_addr.nl_pid = 0;
dest_addr.nl_groups = 0;
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_pid = getpid();
nlh->nlmsg_flags = 0;
nlh->nlmsg_type = URL_REQ_HELLO;
iov.iov_base = (void *)nlh;
iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
memset(&msg, 0, sizeof(msg));
msg.msg_name = (void *)&dest_addr;
msg.msg_namelen = sizeof(dest_addr);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
state_smg = sendmsg(sock_fd, &msg, 0);//Hello to kernel
if (state_smg < 0) {
printErr("get error sendmsg = %s\n",strerror(errno));
ret = -1;
goto exit;
}
url_entry_len = get_max_url_entry_len();
if(url_entry_len == 0) {
printErr("error getting url_entry_len\n");
ret = -1;
goto exit;
}
malloc_url_entry_len = url_entry_len * 2.5;//double for backup, ex. id=1 recv and querying, but id=1 deleted by xt_pctl, then another id=1 recv, place it at url_entry_len+1
//if third/fourth... id=1 recv, they are insert in 2*url_entry_len~2.5*url_entry_len in order
url_array = (struct url_entry *)malloc(malloc_url_entry_len * sizeof(struct url_entry));
if (!nlh) {
printErr("malloc url_array error!\n");
ret = -1;
goto exit;
}
//mali_checkQuery thread and AUC query thread
if (pthread_mutex_init(&mali_url_check_lock, NULL) != 0 ) {
printErr("mali_checkQuery pthread_mutex_init failed...%d\n", pret);
ret = -1;
goto exit;
}
if (pthread_mutex_init(&url_lock, NULL) != 0 || pthread_cond_init(&cond, NULL) != 0) {
printErr("auc pthread_mutex_init failed...%d\n", pret);
ret = -1;
goto exit;
}
if ((pret = pthread_create(&pid_mali, NULL, mali_checkQuery, NULL)) != 0){
printErr("mali_checkQuery pthread_create failed...%d\n", pret);
ret = -1;
goto exit;
}
if ((pret = pthread_create(&pid, NULL, aucQuery, NULL)) != 0){
printErr("auc pthread_create failed...%d\n", pret);
ret = -1;
goto exit;
}
memset(url_array, 0, malloc_url_entry_len * sizeof(struct url_entry));
memset(nlh,0,NLMSG_SPACE(MAX_PAYLOAD));//ready to recv kernel info
while (1) {
state = recvmsg(sock_fd, &msg, 0);
if(state < 0) {
printWar("state<1\n");
}
//store to array
tmp = (struct url_carrier *)NLMSG_DATA(nlh);
index = tmp->id;
//URL_CLASS_LOG(LOG_LEVEL_DEBUG, "msg from kernel, url=%s len=%d id=%d", tmp->url, tmp->url_len, tmp->id);
pthread_mutex_lock(&url_lock);
if(index >= url_entry_len)
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "Error: xt_pctl url entry size is larger than url_class(%u)!", url_entry_len);
pthread_mutex_unlock(&url_lock);
continue;
}
if (url_array[index].prev) {//this node is already in list
if(url_array[index].url_len != tmp->url_len || strncmp(url_array[index].url, tmp->url, tmp->url_len) || url_array[index].info_id != tmp->info_id || url_array[index].cat_map != tmp->cat_map)
{
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "Different node already in list, old_url=%s old_len=%d id=%d, old_process_flag=%d", url_array[index].url, url_array[index].url_len, url_array[index].id, url_array[index].process_flag);
if(url_array[index].process_flag == URL_PROCESS_READY)
{//Still can modify
url_array[index].url_len = tmp->url_len;
url_array[index].info_id = tmp->info_id;
url_array[index].cat_map = tmp->cat_map;
strncpy_safe(url_array[index].url, tmp->url, tmp->url_len);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&url_lock);
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "Replace url=%s at url_array[%d]\n", tmp->url, index);
continue;
}
else
{
index = url_entry_len + tmp->id;
if (url_array[index].prev)
{
if(url_array[index].url_len == tmp->url_len && !strncmp(url_array[index].url, tmp->url, tmp->url_len) && url_array[index].info_id == tmp->info_id && url_array[index].cat_map == tmp->cat_map)
{//Exactly same node is already in list
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "url=%s at url_array[%d] already exist!\n", tmp->url, index);
pthread_mutex_unlock(&url_lock);
continue;
}
if(url_array[index].process_flag == URL_PROCESS_READY)
{//Still can modify
url_array[index].url_len = tmp->url_len;
url_array[index].info_id = tmp->info_id;
url_array[index].cat_map = tmp->cat_map;
strncpy_safe(url_array[index].url, tmp->url, tmp->url_len);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&url_lock);
URL_CLASS_LOG(LOG_LEVEL_WARN, "Replace url=%s at url_array[%d]\n", tmp->url, index);
continue;
}
index = 2 * url_entry_len;
while(index < malloc_url_entry_len && url_array[index].prev)
{
index++;
}
if(index >= malloc_url_entry_len)
{
//An auc query is ignored here!
URL_CLASS_LOG(LOG_LEVEL_ERROR, "url_array is full! url=%s query is ignored!\n", tmp->url_len);
pthread_mutex_unlock(&url_lock);
continue;
}
}
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "Place url=%s at url_array[%d]\n", tmp->url, index);
}
}
else
{//Exactly same node is already in list
pthread_mutex_unlock(&url_lock);
continue;
}
}
url_array[index].id = tmp->id;
url_array[index].query = 0;
url_array[index].process_flag = URL_PROCESS_READY;
url_array[index].url_len = tmp->url_len;
url_array[index].info_id = tmp->info_id;
url_array[index].cat_map = tmp->cat_map;
strncpy_safe(url_array[index].url, tmp->url, tmp->url_len);
printWar("msg from kernel, url=%s len=%d id=%d\n", url_array[index].url, url_array[index].url_len, url_array[index].id);
//add to list
url_array[index].next = url_list.next;
if (url_list.next) {
url_list.next->prev = &url_array[index];
}
url_array[index].prev = &url_list;
url_list.next = &url_array[index];
pthread_cond_signal(&cond);
pthread_mutex_unlock(&url_lock);
}
exit:
if (nlh) {
free(nlh);
}
if (url_array) {
free(url_array);
}
on_exit_handler();
return ret;
}
static size_t _strlcpy(char *dst, const char *src, size_t dstsize)
{
size_t srclen = (size_t)strlen(src);
if (dstsize > 0) {
size_t len = (srclen >= dstsize) ? dstsize - 1 : srclen;
memset(dst, 0, (len + 1));
memcpy(dst, src, len);
}
return srclen;
}
static struct uci_context *_uci_context_init(const char *config_path)
{
struct uci_context *uci_ctx = NULL;
uci_ctx = uci_alloc_context();
if (uci_ctx) {
uci_set_confdir(uci_ctx, config_path);
}
return uci_ctx;
}
static void _uci_context_free(struct uci_context *uci_ctx)
{
if (uci_ctx) {
uci_free_context(uci_ctx);
}
}
static int _uci_get_value(char * p_uci_str, char* p_value)
{
struct uci_context *uci_ctx = NULL;
struct uci_element *e = NULL;
struct uci_ptr p_uci;
if (NULL == p_uci_str || NULL == p_value) {
URL_CLASS_LOG(LOG_LEVEL_ERROR, "p_uci_str or p_value is null");
goto error;
}
uci_ctx = _uci_context_init("/etc/config");
if (!uci_ctx) {
URL_CLASS_LOG(LOG_LEVEL_ERROR, "fail to init uci context:%s", p_uci_str);
goto error;
}
if (UCI_OK != uci_lookup_ptr(uci_ctx, &p_uci, p_uci_str, true)) {
URL_CLASS_LOG(LOG_LEVEL_ERROR, "fail to get ptr %s ", p_uci_str);
goto error;
}
e = p_uci.last;
if (UCI_TYPE_OPTION != e->type) {
URL_CLASS_LOG(LOG_LEVEL_ERROR, "element type is not option:%d", e->type);
goto error;
}
if (UCI_TYPE_STRING != p_uci.o->type) {
URL_CLASS_LOG(LOG_LEVEL_ERROR, "option type is not string:%d", p_uci.o->type);
goto error;
}
_strlcpy(p_value, p_uci.o->v.string, 64);
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "Success to get option value %s = %s ", p_uci_str,p_uci.o->v.string);
_uci_context_free(uci_ctx);
return 0;
error:
_uci_context_free(uci_ctx);
return -1;
}
int parseOpts(int argc, char* argv[], struct Options* opt)
{
int c;
int rc = 999;
int use_tp_service = -1;
while((c = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1)
{
switch(c)
{
case -1: /* no more arguments */
case 0: /* long options toggles */
break;
case 's':
if (optarg)
{
if(strcmp(optarg, "avira") == 0)
{
use_tp_service = 0;
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "parse Opts receive use avira service!");
}
else if(strcmp(optarg, "tplink") == 0)
{
use_tp_service = 1;
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "parse Opts receive use tplink service!");
}
else
{
URL_CLASS_LOG(LOG_LEVEL_ERROR, "parse Opts receive %s, not avaliable! Try %s -s tplink or %s -s avira", optarg, argv[0], argv[0]);
}
}
rc = 's';
break;
case 't':
rc = 't';
break;
case 'h':
printHelp(argv[0]);
rc = 0;
break;
case ':':
case '?':
printHelpInstruction(argv[0]);
rc = 0;
break;
default:
printf("%s : invalid option --\n", c);
printHelpInstruction(argv[0]);
rc = 0;
break;
}
}
if(use_tp_service == -1)
{
char _key[64] = "avira.info.status";
char _value[64] = {0};
if (_uci_get_value(_key, _value)) {
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "-s Parameter not found! Config avira.info.status not found! use default avira service!");
opt->use_tp_service = false;
}
else
{
if(strncmp(_value, "available", sizeof("available") - 1) == 0 || strncmp(_value, "libauc_available", sizeof("libauc_available") - 1) == 0)//avira服务可用
{
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "-s Parameter not found! Config avira.info.status=%s! use avira service!", _value);
opt->use_tp_service = false;
}
else
{
URL_CLASS_LOG(LOG_LEVEL_DEBUG, "-s Parameter not found! Config avira.info.status=%s! use tplink service!", _value);
opt->use_tp_service = true;
}
}
}
else
{
opt->use_tp_service = use_tp_service ? true : false;
}
return rc;
}
void printHelpInstruction(char *progName)
{
printf("Try: %s --help for more information\n", progName);
}
void printHelp(char *progName)
{
printf("Usage: %s\n\t -s <tplink/avira> Use the specified service provider", progName);
}
我修改了这个代码的部分内容,如何单独编译这个代码,之后拷贝到我的设备中替换原有进程
最新发布