QUERY_SERVICE_LOCK_STATUS

博客介绍了QUERY_SERVICE_LOCK_STATUS结构,该结构由QueryServiceLockStatus函数使用,用于返回服务控制管理器数据库的锁定状态信息,还提及了成员和要求等内容。

QUERY_SERVICE_LOCK_STATUS

The QUERY_SERVICE_LOCK_STATUS structure is used by the QueryServiceLockStatus function to return information about the lock status of a service control manager database.

typedef struct _QUERY_SERVICE_LOCK_STATUS {
DWORD fIsLocked;
LPTSTR lpLockOwner;
DWORD dwLockDuration; } QUERY_SERVICE_LOCK_STATUS,
*LPQUERY_SERVICE_LOCK_STATUS;
Members
fIsLocked
Lock status of the database. If this member is nonzero, the database is locked. If it is zero, the database is unlocked.
lpLockOwner
Pointer to a null-terminated string containing the name of the user who acquired the lock.
dwLockDuration
Time since the lock was first acquired, in seconds.
Requirements
ClientRequires Windows XP, Windows 2000 Professional, or Windows NT Workstation.
ServerRequires Windows Server 2003, Windows 2000 Server, or Windows NT Server.
Header

Declared in Winsvc.h; include Windows.h.

Unicode

Implemented as QUERY_SERVICE_LOCK_STATUSW (Unicode) and QUERY_SERVICE_LOCK_STATUSA (ANSI).

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; } 这段代码实现了将分类结果存储到csv文件中的功能,下面第二个代码没有保存的功能,请你根据第一个代码,在不改变第二个代码原本的功能前提下,添加保存到csv文件的功能 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; struct auc_info web_protection_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; #ifdef SUPPORT_BLOCKING_WHITE_LIST bool in_whitelist = false; #endif 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; #ifdef SUPPORT_BLOCKING_WHITE_LIST if(tmp_list->in_whitelist) goto skip; #endif printWar("url_info: url=%s, info_id=0x%x, cat_map=0x%x\n", url_info.url, tmp_list->info_id, tmp_list->cat_map); ret = pthread_mutex_trylock(&mali_url_check_lock); if (!ret) { if(tmp_list->info_id == PCTL_WEB_URL_ID_ALL && web_protection) { #ifdef SUPPORT_WEB_PROTECTION_WHITELIST if(check_web_protection_whitelist(url_info.url)) { printWar("url=%s in web_protection whitelist, skip query!\n", url_info.url); is_mali = false; } else { #endif if(opts.no_avira_web_protection == USE_AVIRA_SPECIAL_WEB_PROTECION_SERVICE) { printWar("before send to avira web_protection\n"); #if SUPPORT_CLOUD_UPDATE_AUC_INFO update_avira_web_protection_url(&web_protection_info); ret = malicious_url_query(&url_info, &web_protection_info); #else ret = malicious_url_query(&url_info); #endif if(url_info.info_len >= 1) { is_mali = (url_info.info[0].id != 1); } else { is_mali = false; } printWar("after send to avira web_protection\n"); } #ifdef SUPPORT_TPLINK_WEB_PROTECTION else if(opts.no_avira_web_protection == USE_TPLINK_WEB_PROTECION_SERVICE) { printWar("before send to tplink web_protection\n"); #if SUPPORT_CLOUD_UPDATE_AUC_INFO update_libauc_url(&auc_info, opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_SERVICE); auc_initialize(&auc_info, opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_SERVICE); malicious_url_query_using_tplink(&url_info, &auc_info); #else auc_initialize(opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_SERVICE); malicious_url_query_using_tplink(&url_info); #endif if(url_info.info_len >= 1) { is_mali = (url_info.info[0].id != 1); } else { is_mali = false; } printWar("after send to tplink web_protection\n"); } #endif else if(opts.no_avira_web_protection == USE_AUC_INSTEAD) { is_mali = false; //Force treat it as a original url, go to auc tmp_list->info_id = PCTL_WEB_URL_ID_ALL + 1; tmp_list->cat_map |= (0x1 << 11); //Fake it as blocking unknown, rather than pure security request(0x0030) printWar("Force run a AUC query\n"); } #ifdef SUPPORT_LOCAL_MALICIOUS_URL_PROTECTION else if(opts.no_avira_web_protection == USE_LOCAL_DATABASE) { printWar("before send to local web_protection datbase\n"); is_mali = web_protection ? is_url_malicious(url_info.url) : false; printWar("after send to avira web_protection datbase\n"); } #endif #ifdef SUPPORT_WEB_PROTECTION_WHITELIST } #endif } else { is_mali = false; } if (is_mali) { cat_id = URL_CAT_SECURITY; #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; #ifdef SUPPORT_BLOCKING_WHITE_LIST tmp_list->in_whitelist = false; #endif 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); goto block_mali; } else { pthread_mutex_unlock(&mali_url_check_lock); } } #ifdef SUPPORT_BLOCKING_WHITE_LIST skip: #endif if(tmp_list->info_id != PCTL_WEB_URL_ID_ALL) { printWar("before send to auc\n"); #if SUPPORT_CLOUD_UPDATE_AUC_INFO update_libauc_url(&auc_info, opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_SERVICE); ret = auc_query(&url_info, &auc_info, opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_SERVICE); #else ret = auc_query(&url_info, opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_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; #ifdef SUPPORT_BLOCKING_WHITE_LIST in_whitelist = tmp_list->in_whitelist; tmp_list->in_whitelist = false; #endif 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; for (index = 0; index < url_info.info_len; index++) { 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; } } } #ifdef SUPPORT_BLOCKING_WHITE_LIST if (in_whitelist && (cat_id & URL_CAT_SECURITY)) { /* if device in whitelist, remove security property from result */ cat_id = cat_id & (~URL_CAT_SECURITY); printWar("url=%s is malicious(in auc), but allow it as its device(mac) is in device whitelist!\n", url_info.url); } #endif #ifdef SUPPORT_WEB_PROTECTION_WHITELIST if ((cat_id & URL_CAT_SECURITY) && check_web_protection_whitelist(url_info.url)) { /* if url is in web_protection whitelist, remove security property from result */ cat_id = cat_id & (~URL_CAT_SECURITY); printWar("url=%s is malicious(in auc), but allow it as it's in web_protection whitelist!\n", url_info.url); } #endif 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; }
09-26
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; } 这段代码实现了将分类结果存储到csv文件中的功能,下面第二个代码没有保存的功能,请你根据第一个代码,在不改变第二个代码原本的功能前提下,添加保存到csv文件的功能 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; struct auc_info web_protection_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; #ifdef SUPPORT_BLOCKING_WHITE_LIST bool in_whitelist = false; #endif 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; #ifdef SUPPORT_BLOCKING_WHITE_LIST if(tmp_list->in_whitelist) goto skip; #endif printWar(“url_info: url=%s, info_id=0x%x, cat_map=0x%x\n”, url_info.url, tmp_list->info_id, tmp_list->cat_map); ret = pthread_mutex_trylock(&mali_url_check_lock); if (!ret) { if(tmp_list->info_id == PCTL_WEB_URL_ID_ALL && web_protection) { #ifdef SUPPORT_WEB_PROTECTION_WHITELIST if(check_web_protection_whitelist(url_info.url)) { printWar("url=%s in web_protection whitelist, skip query!\n", url_info.url); is_mali = false; } else { #endif if(opts.no_avira_web_protection == USE_AVIRA_SPECIAL_WEB_PROTECION_SERVICE) { printWar(“before send to avira web_protection\n”); #if SUPPORT_CLOUD_UPDATE_AUC_INFO update_avira_web_protection_url(&web_protection_info); ret = malicious_url_query(&url_info, &web_protection_info); #else ret = malicious_url_query(&url_info); #endif if(url_info.info_len >= 1) { is_mali = (url_info.info[0].id != 1); } else { is_mali = false; } printWar(“after send to avira web_protection\n”); } #ifdef SUPPORT_TPLINK_WEB_PROTECTION else if(opts.no_avira_web_protection == USE_TPLINK_WEB_PROTECION_SERVICE) { printWar(“before send to tplink web_protection\n”); #if SUPPORT_CLOUD_UPDATE_AUC_INFO update_libauc_url(&auc_info, opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_SERVICE); auc_initialize(&auc_info, opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_SERVICE); malicious_url_query_using_tplink(&url_info, &auc_info); #else auc_initialize(opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_SERVICE); malicious_url_query_using_tplink(&url_info); #endif if(url_info.info_len >= 1) { is_mali = (url_info.info[0].id != 1); } else { is_mali = false; } printWar(“after send to tplink web_protection\n”); } #endif else if(opts.no_avira_web_protection == USE_AUC_INSTEAD) { is_mali = false; //Force treat it as a original url, go to auc tmp_list->info_id = PCTL_WEB_URL_ID_ALL + 1; tmp_list->cat_map |= (0x1 << 11); //Fake it as blocking unknown, rather than pure security request(0x0030) printWar(“Force run a AUC query\n”); } #ifdef SUPPORT_LOCAL_MALICIOUS_URL_PROTECTION else if(opts.no_avira_web_protection == USE_LOCAL_DATABASE) { printWar(“before send to local web_protection datbase\n”); is_mali = web_protection ? is_url_malicious(url_info.url) : false; printWar(“after send to avira web_protection datbase\n”); } #endif #ifdef SUPPORT_WEB_PROTECTION_WHITELIST } #endif } else { is_mali = false; } if (is_mali) { cat_id = URL_CAT_SECURITY; #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; #ifdef SUPPORT_BLOCKING_WHITE_LIST tmp_list->in_whitelist = false; #endif 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); goto block_mali; } else { pthread_mutex_unlock(&mali_url_check_lock); } } #ifdef SUPPORT_BLOCKING_WHITE_LIST skip: #endif if(tmp_list->info_id != PCTL_WEB_URL_ID_ALL) { printWar(“before send to auc\n”); #if SUPPORT_CLOUD_UPDATE_AUC_INFO update_libauc_url(&auc_info, opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_SERVICE); ret = auc_query(&url_info, &auc_info, opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_SERVICE); #else ret = auc_query(&url_info, opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_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; #ifdef SUPPORT_BLOCKING_WHITE_LIST in_whitelist = tmp_list->in_whitelist; tmp_list->in_whitelist = false; #endif 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; for (index = 0; index < url_info.info_len; index++) { 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; } } } #ifdef SUPPORT_BLOCKING_WHITE_LIST if (in_whitelist && (cat_id & URL_CAT_SECURITY)) { /* if device in whitelist, remove security property from result / cat_id = cat_id & (~URL_CAT_SECURITY); printWar(“url=%s is malicious(in auc), but allow it as its device(mac) is in device whitelist!\n”, url_info.url); } #endif #ifdef SUPPORT_WEB_PROTECTION_WHITELIST if ((cat_id & URL_CAT_SECURITY) && check_web_protection_whitelist(url_info.url)) { / if url is in web_protection whitelist, remove security property from result */ cat_id = cat_id & (~URL_CAT_SECURITY); printWar(“url=%s is malicious(in auc), but allow it as it’s in web_protection whitelist!\n”, url_info.url); } #endif 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; }
最新发布
09-26
/*!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(&para); 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) { int fd = open("/var/auc_classification_results.csv", O_CREAT | O_WRONLY | O_APPEND, 0644); if (fd!= -1) { char buffer[512]; snprintf(buffer, sizeof(buffer), "%s,%d,%d\n", url, original_cat_id, mapped_cat_id); 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; #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); 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; for (index = 0; index < url_info.info_len; index++) { original_cat_id = url_info.info[index].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; } } } write_to_csv(url_info.url, original_cat_id, cat_id); 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) { 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); } 还原出代码格式
09-23
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; struct auc_info web_protection_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; #ifdef SUPPORT_BLOCKING_WHITE_LIST bool in_whitelist = false; #endif 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; #ifdef SUPPORT_BLOCKING_WHITE_LIST if(tmp_list->in_whitelist) goto skip; #endif printWar("url_info: url=%s, info_id=0x%x, cat_map=0x%x\n", url_info.url, tmp_list->info_id, tmp_list->cat_map); ret = pthread_mutex_trylock(&mali_url_check_lock); if (!ret) { if(tmp_list->info_id == PCTL_WEB_URL_ID_ALL && web_protection) { #ifdef SUPPORT_WEB_PROTECTION_WHITELIST if(check_web_protection_whitelist(url_info.url)) { printWar("url=%s in web_protection whitelist, skip query!\n", url_info.url); is_mali = false; } else { #endif if(opts.no_avira_web_protection == USE_AVIRA_SPECIAL_WEB_PROTECION_SERVICE) { printWar("before send to avira web_protection\n"); #if SUPPORT_CLOUD_UPDATE_AUC_INFO update_avira_web_protection_url(&web_protection_info); ret = malicious_url_query(&url_info, &web_protection_info); #else ret = malicious_url_query(&url_info); #endif if(url_info.info_len >= 1) { is_mali = (url_info.info[0].id != 1); } else { is_mali = false; } printWar("after send to avira web_protection\n"); } #ifdef SUPPORT_TPLINK_WEB_PROTECTION else if(opts.no_avira_web_protection == USE_TPLINK_WEB_PROTECION_SERVICE) { printWar("before send to tplink web_protection\n"); #if SUPPORT_CLOUD_UPDATE_AUC_INFO update_libauc_url(&auc_info, opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_SERVICE); auc_initialize(&auc_info, opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_SERVICE); malicious_url_query_using_tplink(&url_info, &auc_info); #else auc_initialize(opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_SERVICE); malicious_url_query_using_tplink(&url_info); #endif if(url_info.info_len >= 1) { is_mali = (url_info.info[0].id != 1); } else { is_mali = false; } printWar("after send to tplink web_protection\n"); } #endif else if(opts.no_avira_web_protection == USE_AUC_INSTEAD) { is_mali = false; //Force treat it as a original url, go to auc tmp_list->info_id = PCTL_WEB_URL_ID_ALL + 1; tmp_list->cat_map |= (0x1 << 11); //Fake it as blocking unknown, rather than pure security request(0x0030) printWar("Force run a AUC query\n"); } #ifdef SUPPORT_LOCAL_MALICIOUS_URL_PROTECTION else if(opts.no_avira_web_protection == USE_LOCAL_DATABASE) { printWar("before send to local web_protection datbase\n"); is_mali = web_protection ? is_url_malicious(url_info.url) : false; printWar("after send to avira web_protection datbase\n"); } #endif #ifdef SUPPORT_WEB_PROTECTION_WHITELIST } #endif } else { is_mali = false; } if (is_mali) { cat_id = URL_CAT_SECURITY; #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; #ifdef SUPPORT_BLOCKING_WHITE_LIST tmp_list->in_whitelist = false; #endif 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); goto block_mali; } else { pthread_mutex_unlock(&mali_url_check_lock); } } #ifdef SUPPORT_BLOCKING_WHITE_LIST skip: #endif if(tmp_list->info_id != PCTL_WEB_URL_ID_ALL) { printWar("before send to auc\n"); #if SUPPORT_CLOUD_UPDATE_AUC_INFO update_libauc_url(&auc_info, opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_SERVICE); ret = auc_query(&url_info, &auc_info, opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_SERVICE); #else ret = auc_query(&url_info, opts.content_filter_status == USE_TPLINK_CONTENT_FILTER_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; #ifdef SUPPORT_BLOCKING_WHITE_LIST in_whitelist = tmp_list->in_whitelist; tmp_list->in_whitelist = false; #endif 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; for (index = 0; index < url_info.info_len; index++) { 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; } } } #ifdef SUPPORT_BLOCKING_WHITE_LIST if (in_whitelist && (cat_id & URL_CAT_SECURITY)) { /* if device in whitelist, remove security property from result */ cat_id = cat_id & (~URL_CAT_SECURITY); printWar("url=%s is malicious(in auc), but allow it as its device(mac) is in device whitelist!\n", url_info.url); } #endif #ifdef SUPPORT_WEB_PROTECTION_WHITELIST if ((cat_id & URL_CAT_SECURITY) && check_web_protection_whitelist(url_info.url)) { /* if url is in web_protection whitelist, remove security property from result */ cat_id = cat_id & (~URL_CAT_SECURITY); printWar("url=%s is malicious(in auc), but allow it as it's in web_protection whitelist!\n", url_info.url); } #endif 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; } 这个代码是另一个设备的,我想将保存csv的功能也添加到其中,应该在哪里添加对应的保存代码
09-26
/*!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> #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(&para); 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); } } 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; #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); 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; for (index = 0; index < url_info.info_len; index++) { 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; } } } 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); } 上面的代码在线程中运行时如何查看状态
09-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值