| /** | 
 | * @file netotherapi.c | 
 | * @brief Public APIs of Sanechips | 
 | * | 
 | * Copyright (C) 2017 Sanechips Technology Co., Ltd. | 
 | * @author  Linxu Gebin | 
 | * @defgroup si_id Sanechips | 
 | * | 
 | * This program is free software; you can redistribute it and/or modify | 
 | * it under the terms of the GNU General Public License version 2 as | 
 | * published by the Free Software Foundation. | 
 | ************************************************************************* | 
 | */ | 
 |  | 
 | /******************************************************************************* | 
 |  *							 Include header files							   * | 
 |  ******************************************************************************/ | 
 |  | 
 | #include <stdio.h> | 
 | #include <unistd.h> | 
 | #include <sys/types.h> | 
 | #include <fcntl.h> | 
 | #include <string.h> | 
 | #include <stdlib.h> | 
 | #include <assert.h> | 
 | #include <syslog.h> | 
 | #include <sys/klog.h> | 
 | #include <sys/msg.h> | 
 | #include "message.h" | 
 | #include <sys/time.h> | 
 | #include <asm/types.h> | 
 | #include <netinet/ether.h> | 
 | #include <netinet/in.h> | 
 | #include <net/if.h> | 
 | #include <netdb.h> | 
 | #include <sys/socket.h> | 
 | #include <signal.h> | 
 | #include <sys/ioctl.h> | 
 | #include <linux/netlink.h> | 
 | #include <linux/rtnetlink.h> | 
 | #include <sys/types.h> | 
 | #include <pthread.h> | 
 | #include "softap_api.h" | 
 | #include <netotherapi.h> | 
 | #include <dirent.h> | 
 | #include <limits.h> | 
 |  | 
 | /******************************************************************************* | 
 |  *                             Type definitions                                * | 
 |  ******************************************************************************/ | 
 | /** | 
 | * @brief route information | 
 | * @param dstAddr destination address | 
 | * @param srcAddr source address | 
 | * @param gateWay gateWay | 
 | * @param ifName NIC name | 
 | */ | 
 | struct route_info { | 
 | 	u_int dstAddr; | 
 | 	u_int srcAddr; | 
 | 	u_int gateWay; | 
 | 	char ifName[IF_NAMESIZE]; | 
 | }; | 
 |  | 
 | #define BUFSIZE 8192 | 
 |  | 
 | #define SPINLOCK_IOC_MAGIC	'S' | 
 |  | 
 | #define SPINLOCK_GET_STATUS  _IOWR(SPINLOCK_IOC_MAGIC,1,char *) | 
 |  | 
 | #define READ_BUF_SIZE 56 | 
 | /******************************************************************************* | 
 |  *                      Inline function implementations                        * | 
 |  ******************************************************************************/ | 
 | inline char *strip_space(char *str) | 
 | { | 
 | 	while (*str == ' ') | 
 | 		str++; | 
 | 	return str; | 
 | } | 
 | /******************************************************************************* | 
 |  *                      Local function implementations                         * | 
 |  ******************************************************************************/ | 
 | /* дÎļþ²Ù×÷º¯Êý */ | 
 | int write_file(const char *filepath, int flags, const char *buf, int size) | 
 | { | 
 | 	int fd = 0; | 
 | 	int ret = 0; | 
 |  | 
 | 	fd = open(filepath, flags, 0644); | 
 | 	if (fd < 0) { | 
 | 		slog(MISC_PRINT, SLOG_ERR, "write_to_file open %s fail, error:%s! \n", filepath, strerror(errno)); | 
 | 		ret = -1; | 
 | 		goto out; | 
 | 	} | 
 |  | 
 |     ret = TEMP_FAILURE_RETRY(write(fd, buf, size)); | 
 | 	if (ret != size) { | 
 | 		slog(MISC_PRINT, SLOG_ERR, "write_to_file write %s fail, error:%s! \n", filepath, strerror(errno)); | 
 | 		ret = -1; | 
 | 		goto out; | 
 | 	} | 
 | 	if(fsync(fd) < 0) | 
 |     { | 
 |         // todo: cov m | 
 |     }   | 
 |      | 
 | 	ret = 0; | 
 |  | 
 | out: | 
 | 	if (fd >= 0) | 
 | 		close(fd); | 
 | 	return ret; | 
 | } | 
 |  | 
 | /* дÎļþ: ¸²¸Çд */ | 
 | int write_to_file(const char *filepath, const char *buf, int size) | 
 | { | 
 | 	return write_file(filepath, O_WRONLY | O_CREAT | O_TRUNC, buf, size); | 
 | } | 
 |  | 
 | /* дÎļþ: β²¿×·¼Óд  */ | 
 | int append_to_file(const char *filepath, const char *buf, int size) | 
 | { | 
 | 	return write_file(filepath, O_WRONLY | O_APPEND | O_CREAT, buf, size); | 
 | } | 
 |  | 
 | //¿â½Ó¿Úctime¡¢asctime»á»»ÐУ¬Ôì³ÉÿÌõlog±»·ÖÐÐÏÔʾ£¬²»·½±ã¿´£¬ËùÒÔ½«ctimeÔ´ÂëÉÔ΢¸ÄÔìÏ | 
 | static char *str_ctime(const struct tm *timeptr) | 
 | { | 
 | 	/*static const char wday_name[][4] = { | 
 | 	  "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" | 
 | 	};*/ | 
 |  | 
 | 	static const char mon_name[][4] = { | 
 | 		"Jan", "Feb", "Mar", "Apr", "May", "Jun", | 
 | 		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" | 
 | 	}; | 
 |  | 
 | 	static char result[26]; | 
 |  | 
 | 	/*sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d", | 
 | 	  wday_name[timeptr->tm_wday], | 
 | 	  mon_name[timeptr->tm_mon], | 
 | 	  timeptr->tm_mday, timeptr->tm_hour, | 
 | 	  timeptr->tm_min, timeptr->tm_sec, | 
 | 	  1900 + timeptr->tm_year);*/ | 
 | 	snprintf(result, sizeof(result), "%.3s%3d %.2d:%.2d:%.2d %d", | 
 | 	        mon_name[timeptr->tm_mon], | 
 | 	        timeptr->tm_mday, timeptr->tm_hour, | 
 | 	        timeptr->tm_min, timeptr->tm_sec, | 
 | 	        1900 + timeptr->tm_year); | 
 | 	return result; | 
 | } | 
 |  | 
 | /******************************************************************************* | 
 |  *                      Global function implementations                        * | 
 |  ******************************************************************************/ | 
 |  | 
 | /****************************************/ | 
 | //input:  nv_str:nvÄÚÈÝÖ¸Õë    * nv_param ½âÎöºó²ÎÊýµÄÖ¸Õë | 
 | //output:   param_num     nv_param | 
 | //ʾÀý: | 
 | //   int num; | 
 | //   char** nv_param; | 
 | //   num = nv_analyze(nv_str,&nv_param) | 
 | //   strcmp(nv_param[0],"aaa") ... | 
 | //   strcmp(nv_param[1],"bbb") ... | 
 | //   ... | 
 | //   free(nv_param); | 
 | // | 
 | /****************************************/ | 
 |  | 
 | int nv_analyze(char* nv_str, char*** nv_param) | 
 | { | 
 | 	int param_num = 1; | 
 | 	int i = 0; | 
 | 	char* str_ptr; | 
 | 	char** mem_ptr; | 
 | 	char* tmp_ptr; | 
 | 	for (str_ptr = nv_str; *str_ptr != '\0'; str_ptr++) { | 
 | 		if (*str_ptr == '+') | 
 | 			param_num++; | 
 | 	} | 
 | 	mem_ptr = (char**)malloc((1 + sizeof(char*)) * param_num + strlen(nv_str)); | 
 | 	if (mem_ptr == NULL) {//klocwork | 
 | 		return -1; | 
 | 	} | 
 | 	memset(mem_ptr, 0, (1 + sizeof(char*)) * param_num + strlen(nv_str)); | 
 | 	* nv_param = mem_ptr; | 
 | 	str_ptr = strtok(nv_str, "+"); | 
 | 	tmp_ptr = (char*)(mem_ptr + param_num); | 
 | 	while (str_ptr != NULL) { | 
 | 		memcpy((mem_ptr + i), &tmp_ptr, sizeof(char*)); | 
 | 		strcpy(tmp_ptr, str_ptr); | 
 | 		tmp_ptr = (char*)((long)tmp_ptr + strlen(str_ptr) + 1); | 
 | 		i ++; | 
 | 		str_ptr = strtok(NULL, "+"); | 
 | 	} | 
 | 	return param_num; | 
 | } | 
 |  | 
 |  | 
 | char* getField(char *a_line, char *delim, int count) | 
 | { | 
 | 	int i = 0; | 
 | 	char *tok = NULL; | 
 | 	char *save = NULL; | 
 | 	tok = strtok_r(a_line, delim, &save); | 
 | 	while (tok) { | 
 | 		if (i == count) | 
 | 			break; | 
 | 		i++; | 
 | 		tok = strtok_r(NULL, delim, &save); | 
 | 	} | 
 | 	if (tok) | 
 | 		return tok; | 
 |  | 
 | 	return NULL; | 
 | } | 
 |  | 
 | void  free_dhcp_list(struct list_head *dhcp_info_list) | 
 | { | 
 | 	DHCPOFFERADDR_LIST_t *dhcp_info_temp  = NULL; | 
 | 	DHCPOFFERADDR_LIST_t *dhcp_info_temp1 = NULL; | 
 |  | 
 | 	list_for_each_entry_safe(dhcp_info_temp, dhcp_info_temp1, dhcp_info_list, list) { | 
 | 		list_del(&dhcp_info_temp->list); | 
 | 		free(dhcp_info_temp); | 
 | 	} | 
 | } | 
 |  | 
 | void  free_laninfo_list(struct list_head *file_info_list) | 
 | { | 
 | 	LAN_INFO_LIST_t *lan_info_list_tmp  = NULL; | 
 | 	LAN_INFO_LIST_t *lan_info_list_tmp1 = NULL; | 
 |  | 
 | 	list_for_each_entry_safe(lan_info_list_tmp, lan_info_list_tmp1, file_info_list, list) { | 
 | 		list_del(&lan_info_list_tmp->list); | 
 | 		free(lan_info_list_tmp); | 
 | 	} | 
 |  | 
 | } | 
 |  | 
 | /************************************************************************** | 
 | * º¯ÊýÃû³Æ£º getIfStatistic | 
 | * ¹¦ÄÜÃèÊö£º »ñÈ¡ÍøÂçÉ豸µ±Ç°Á÷Á¿ | 
 | * ²ÎÊý˵Ã÷£º interface:     Íø¿ÚÉ豸Ãû³Æ | 
 | *            type:          Á÷Á¿ÀàÐÍ£¬ÉÏÐС¢ÏÂÐбÈÌØ»ò°ü¸öÊý | 
 | *            result_data:   ±£´æÁ÷Á¿Öµ | 
 | * ·µ »Ø Öµ£º ʧ°Ü·µ»Ø-1£¬³É¹¦·µ»Ø0 | 
 | **************************************************************************/ | 
 | int getIfStatistic(char *interface, int type, unsigned long long *result_data) | 
 | { | 
 | 	int found_flag = 0; | 
 | 	int skip_line = 2; | 
 | 	char temp_rcv[64] = {0}; | 
 | 	char buf[1024], *field, *semiColon = NULL; | 
 | 	long long result_data_num = 0; | 
 | 	FILE *fp = fopen(PROC_IF_STATISTIC, "r"); | 
 | 	if (!fp) { | 
 | 		slog(MISC_PRINT, SLOG_ERR, "no proc?\n"); | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	while (fgets(buf, 1024, fp)) { | 
 | 		char *ifname; | 
 | 		if (skip_line != 0) { | 
 | 			skip_line--; | 
 | 			continue; | 
 | 		} | 
 | 		if (!(semiColon = strchr(buf, ':'))) | 
 | 			continue; | 
 | 		*semiColon = '\0'; | 
 | 		ifname = buf; | 
 | 		ifname = strip_space(ifname); | 
 |  | 
 | 		if (!strcmp(ifname, interface)) { | 
 | 			found_flag = 1; | 
 | 			break; | 
 | 		} | 
 | 	} | 
 | 	fclose(fp); | 
 |  | 
 | 	if (found_flag == 0) { | 
 | 		slog(MISC_PRINT, SLOG_DEBUG, "[fluxstat]getIfStatistic no found data======\n"); | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	semiColon++; | 
 |  | 
 | 	switch (type) { | 
 | 	case TXBYTE: | 
 | 		if ((field = getField(semiColon, " ", 8))) { | 
 | 			errno = 0; | 
 | 			result_data_num = strtoull(field, NULL, 10); | 
 | 			if (errno == ERANGE)// kw ERRNO.NOT_CHECKED | 
 | 			{ | 
 | 				printf("strtoull errno %d: %s\n", errno, strerror(errno)); | 
 | 			} | 
 | 			if (result_data_num < 0 || result_data_num > LLONG_MAX-1) | 
 | 				result_data_num = 0; | 
 | 			*result_data = result_data_num; | 
 | 			 | 
 | 			slog(MISC_PRINT, SLOG_DEBUG, "[getIfStatistic]TXBYTE field:%s, result_data:%llu\n", field, *result_data); | 
 | 			return 0; //kw 3 | 
 | 		} | 
 | 		break; | 
 | 	case TXPACKET: | 
 | 		if ((field = getField(semiColon, " ", 9))) { | 
 | 			errno = 0; | 
 | 			result_data_num = strtoull(field, NULL, 10); | 
 | 			if (errno == ERANGE)// kw ERRNO.NOT_CHECKED | 
 | 			{ | 
 | 				printf("strtoull errno %d: %s\n", errno, strerror(errno)); | 
 | 			} | 
 | 			if (result_data_num < 0 || result_data_num > LLONG_MAX-1) | 
 | 				result_data_num = 0; | 
 | 			*result_data = result_data_num; | 
 | 			return 0; | 
 | 		} | 
 | 		break; | 
 | 	case TXERR: | 
 | 		if ((field = getField(semiColon, " ", 10))) { | 
 | 			errno = 0; | 
 | 			result_data_num = strtoull(field, NULL, 10); | 
 | 			if (errno == ERANGE)// kw ERRNO.NOT_CHECKED | 
 | 			{ | 
 | 				printf("strtoull errno %d: %s\n", errno, strerror(errno)); | 
 | 			} | 
 | 			if (result_data_num < 0 || result_data_num > LLONG_MAX-1) | 
 | 				result_data_num = 0; | 
 | 			*result_data = result_data_num; | 
 | 			 | 
 | 			return 0; //kw 3 | 
 | 		} | 
 | 		break; | 
 | 	case TXDROP: | 
 | 		if ((field = getField(semiColon, " ", 11))) { | 
 | 			errno = 0; | 
 | 			result_data_num = strtoull(field, NULL, 10); | 
 | 			if (errno == ERANGE)// kw ERRNO.NOT_CHECKED | 
 | 			{ | 
 | 				printf("strtoull errno %d: %s\n", errno, strerror(errno)); | 
 | 			} | 
 | 			if (result_data_num < 0 || result_data_num > LLONG_MAX-1) | 
 | 				result_data_num = 0; | 
 | 			*result_data = result_data_num; | 
 | 			return 0; | 
 | 		} | 
 | 		break; | 
 | 	case RXBYTE: | 
 | 		if ((field = getField(semiColon, " ", 0))) { | 
 | 			errno = 0; | 
 | 			result_data_num = strtoull(field, NULL, 10); | 
 | 			if (errno == ERANGE)// kw ERRNO.NOT_CHECKED | 
 | 			{ | 
 | 				printf("strtoull errno %d: %s\n", errno, strerror(errno)); | 
 | 			} | 
 | 			if (result_data_num < 0 || result_data_num > LLONG_MAX-1) | 
 | 				result_data_num = 0; | 
 | 			*result_data = result_data_num; | 
 | 			slog(MISC_PRINT, SLOG_DEBUG, "[getIfStatistic]RXBYTE field:%s, result_data:%llu\n", field, *result_data); | 
 | 			return 0; | 
 | 		} | 
 | 		break; | 
 | 	case RXPACKET: | 
 | 		if ((field = getField(semiColon, " ", 1))) { | 
 | 			errno = 0; | 
 | 			result_data_num = strtoull(field, NULL, 10); | 
 | 			if (errno == ERANGE)// kw ERRNO.NOT_CHECKED | 
 | 			{ | 
 | 				printf("strtoull errno %d: %s\n", errno, strerror(errno)); | 
 | 			} | 
 | 			if (result_data_num < 0 || result_data_num > LLONG_MAX-1) | 
 | 				result_data_num = 0; | 
 | 			*result_data = result_data_num; | 
 | 			return 0; | 
 | 		} | 
 | 		break; | 
 | 	case RXERR: | 
 | 		if ((field = getField(semiColon, " ", 2))) { | 
 | 			errno = 0; | 
 | 			result_data_num = strtoull(field, NULL, 10); | 
 | 			if (errno == ERANGE)// kw ERRNO.NOT_CHECKED | 
 | 			{ | 
 | 				printf("strtoull errno %d: %s\n", errno, strerror(errno)); | 
 | 			} | 
 | 			if (result_data_num < 0 || result_data_num > LLONG_MAX-1) | 
 | 				result_data_num = 0; | 
 | 			*result_data = result_data_num; | 
 | 			return 0; | 
 | 		} | 
 | 		break; | 
 | 	case RXDROP: | 
 | 		if ((field = getField(semiColon, " ", 3))) { | 
 | 			errno = 0; | 
 | 			result_data_num = strtoull(field, NULL, 10); | 
 | 			if (errno == ERANGE)// kw ERRNO.NOT_CHECKED | 
 | 			{ | 
 | 				printf("strtoull errno %d: %s\n", errno, strerror(errno)); | 
 | 			} | 
 | 			if (result_data_num < 0 || result_data_num > LLONG_MAX-1) | 
 | 				result_data_num = 0; | 
 | 			*result_data = result_data_num; | 
 | 			return 0; | 
 | 		} | 
 | 		break; | 
 | 	} | 
 | 	return -1; | 
 | } | 
 |  | 
 | void *safe_malloc(int size, BOOL is_assert) | 
 | { | 
 | 	void *ret = malloc(size); | 
 |  | 
 | 	if (ret == NULL) { | 
 | 		if (is_assert == TRUE) { | 
 | 			assert(ret); | 
 | 		} else { | 
 | 			printf("[%s][%s] ----can not get memory", __FILE__, __FUNCTION__); | 
 | 		} | 
 | 	} else { | 
 | 		memset(ret, 0, size); | 
 | 	} | 
 |  | 
 | 	return ret; | 
 | } | 
 |  | 
 | //ÊäÈësize±ØÐëÊÇdestµÄ³¤¶È | 
 | void safe_strcpy(char *dest, char *source, int size) | 
 | { | 
 | 	if (dest == NULL || source == NULL || size < 1) { | 
 | 		return; | 
 | 	} | 
 |  | 
 | 	strncpy(dest, source, size - 1); | 
 | 	dest[size - 1] = '\0'; | 
 | } | 
 |  | 
 | int get_dev_list(struct pc_node* mypc_node) | 
 | { | 
 | 	int ret = 0; | 
 |  | 
 | 	ret = netioctl_handle(NIOCGPCINFO, mypc_node); | 
 | 	if (-1 == ret) { | 
 | 		slog(NET_PRINT, SLOG_ERR, "NIOCGPCINFO err"); | 
 | 		return -1; | 
 | 	} | 
 | 	return 0; | 
 | } | 
 |  | 
 | int  zte_get_mac_list_from_lease(struct list_head *dhcp_list_info) | 
 | { | 
 | 	FILE *leaseFile    = NULL; | 
 | 	int64_t leaseFirst = 0; | 
 | 	char buf[32]; | 
 |  | 
 | 	DHCPOFFERADDRNET dhcpInfo = {0}; | 
 |  | 
 | 	char path_conf[50] = {0}; | 
 | 	char path_file[100] = {0}; | 
 |  | 
 | 	if (!list_empty(dhcp_list_info)) | 
 | 		return -1; | 
 |  | 
 | 	sc_cfg_get("path_conf", path_conf, sizeof(path_conf)); | 
 | 	sprintf(path_file, "%s/udhcpd.leases", path_conf); | 
 |  | 
 | 	leaseFile = fopen(path_file, "r"); | 
 | 	if (leaseFile == NULL) { | 
 | 		fprintf(stderr, "can not open file udhcpd.leases."); | 
 | 		return -1 ; | 
 | 	} | 
 |  | 
 | 	if (fread(&leaseFirst, 1, sizeof(leaseFirst), leaseFile) != sizeof(leaseFirst)) { | 
 | 		fprintf(stderr, "read the first part of udhcpd.leases fail!"); | 
 | 		fclose(leaseFile); | 
 | 		return -1 ; | 
 | 	} | 
 |  | 
 | 	memset(buf, 0x00, sizeof(buf)); | 
 | 	sc_cfg_get("dhcpEnabled", buf, sizeof(buf)); | 
 | 	if (strcmp(buf, "0") == 0) { | 
 | 		fclose(leaseFile); | 
 | 		return -1 ; | 
 | 	} | 
 |  | 
 | 	while ((fread(&dhcpInfo, 1, sizeof(dhcpInfo), leaseFile) == sizeof(dhcpInfo))) { | 
 | 		DHCPOFFERADDR_LIST_t *dhcpInfo_ptr = (DHCPOFFERADDR_LIST_t *)safe_malloc(sizeof(DHCPOFFERADDR_LIST_t), TRUE); | 
 | 		if (!dhcpInfo_ptr) { | 
 | 			slog(NET_PRINT, SLOG_ERR, "get_lan_info_list safe_malloc dhcpInfo_ptr fail \n"); | 
 | 			return -1; | 
 | 		} | 
 | 		memcpy(&(dhcpInfo_ptr->dhcp_info), &dhcpInfo, sizeof(DHCPOFFERADDRNET)); | 
 | 		list_add_tail(&dhcpInfo_ptr->list, dhcp_list_info); | 
 | 	} | 
 |  | 
 | 	fclose(leaseFile); | 
 | 	return 0; | 
 | } | 
 |  | 
 | void flash_file(char *file, char *file_num) | 
 | { | 
 | 	char newFile[128] = {0}; | 
 | 	char oldFile[128] = {0}; | 
 | 	int i = 0;//klocwork | 
 | 	int i_file_num = atoi(file_num); | 
 |  | 
 |     if(i_file_num < 0 || i_file_num > INT_MAX-1) | 
 |     { | 
 |         return ; | 
 |     } | 
 |      | 
 | 	for (i = i_file_num - 2; i > 0 && i < 1000; i--) { | 
 | 		sprintf(newFile, "%s_bk%d", file, i); | 
 | 		sprintf(oldFile, "%s_bk%d", file, i + 1); | 
 | 		if ((access(newFile, F_OK)) == 0) { | 
 | 			if(rename(newFile, oldFile) < 0){ | 
 |                 // cov M  | 
 |             } | 
 | 		} | 
 | 	} | 
 | 	sprintf(newFile, "%s_bk1", file); | 
 |  | 
 |     if(rename(file, newFile) < 0) | 
 |     { | 
 |         // cov M | 
 |     } | 
 | } | 
 |  | 
 | void file_write(char *filename, char *info) | 
 | { | 
 | 	FILE *fp; | 
 | 	char logpath[128]  = {0}; | 
 | 	char logname[128] = {0}; | 
 | 	char filesize[32]	= {0}; | 
 | 	char temp[64]	= {0}; | 
 | 	int flag = 0; | 
 | 	time_t now; | 
 | 	struct tm *timenow; | 
 |  | 
 | 	time(&now); | 
 | 	timenow = localtime(&now); | 
 | 	if (!timenow) {//klocwork | 
 | 		printf("localtime get err.\n"); | 
 | 		return; | 
 | 	} | 
 |  | 
 | 	if (!filename || 0 == strcmp(filename, "")) { | 
 | 		printf("filename is err.\n"); | 
 | 		return; | 
 | 	} | 
 |  | 
 | 	//Ö¸¶¨logÎļþ´óС£¬Èç¹ûδָ¶¨¾ÍÓÃĬÈÏcomm_logsize | 
 | 	sprintf(temp, "%s_logsize", filename); | 
 | 	sc_cfg_get(temp, filesize, sizeof(filesize)); | 
 | 	if (0 == strcmp(filesize, "0")) { | 
 | 		return ; | 
 | 	} else if (0 == strcmp(filesize, "")) { | 
 | 		sc_cfg_get("comm_logsize", filesize, sizeof(filesize)); | 
 | 		if (0 == strcmp(filesize, "0") || 0 == strcmp(filesize, "")) { | 
 | 			printf("filesize is not set.\n"); | 
 | 			return; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	sc_cfg_get("path_log", logpath, sizeof(logpath)); | 
 | 	snprintf(logname, sizeof(logname), "%s%s.log", logpath, filename); | 
 |  | 
 | 	fp = fopen(logname, "a"); | 
 | 	if (!fp) { | 
 | 		printf("fopen %s failed \n", logname); | 
 | 		return; | 
 | 	} | 
 | 	//flock»úÖÆ²¢²»ÄÜÕæµÄÆðµ½lock×÷Ó㬷µ»Ø»áÔì³Éunlock²»µô | 
 | 	/* | 
 | 	else if (flock(fileno(fp), LOCK_EX) != 0) | 
 | 	{ | 
 | 	    perror("flock"); | 
 | 		fclose(fp); | 
 | 	    return; | 
 | 	}*/ | 
 |  | 
 | 	fprintf(fp, "%s:%s\n", str_ctime(timenow), info); | 
 | 	//fprintf(fp, "%s %s %s[%d]: %s", ctime(timenow), asctime(timenow), filename, getpid(), info); | 
 | 	fflush(fp); | 
 | 	fseek(fp, 0L, SEEK_END); | 
 |  | 
 | 	if (ftell(fp) > atoi(filesize)) | 
 | 		flag = 1; | 
 |  | 
 | 	//flock(fileno(fp), LOCK_UN); | 
 | 	fclose(fp); | 
 |  | 
 | 	if (flag == 1) { | 
 | 		flash_file(logname, "2"); | 
 | 	} | 
 | } | 
 |  | 
 | int echo_file(char *filename, char*info) | 
 | { | 
 | 	int len; | 
 | 	int ret; | 
 | 	int fd; | 
 | 	if (!filename || 0 == strcmp(filename, "") || !info) { | 
 | 		printf("echo filename is err.\n"); | 
 | 		return -1; | 
 | 	} | 
 | 	fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, 777); | 
 | 	if (fd < 0) { | 
 | 		printf("%s open failed!\n", filename); | 
 | 		return -1; | 
 | 	} | 
 | 	len = strlen(info); | 
 | 	ret = write(fd, info, len); | 
 |  | 
 | 	close(fd); | 
 |  | 
 | 	return ret; | 
 | } | 
 |  | 
 | void save_file(char *filename, char* info) | 
 | { | 
 | 	FILE* fp; | 
 | 	char filepath[128]  = {0}; | 
 | 	char filesize[32]	= {0}; | 
 | 	char filenum[32]	= {0}; | 
 | 	char temp[64]	= {0}; | 
 | 	int flag = 0; | 
 | 	time_t now; | 
 | 	struct tm *timenow; | 
 | 	time(&now); | 
 | 	timenow = localtime(&now); | 
 | 	if (!timenow) {//klocwork | 
 | 		printf("localtime get err.\n"); | 
 | 		return; | 
 | 	} | 
 |  | 
 | 	if (!filename || 0 == strcmp(filename, "")) { | 
 | 		printf("filename is err.\n"); | 
 | 		return; | 
 | 	} | 
 | 	sprintf(temp, "%sfile", filename); | 
 | 	sc_cfg_get(temp, filepath, sizeof(filepath)); | 
 | 	sprintf(temp, "%sfileSize", filename); | 
 | 	sc_cfg_get(temp, filesize, sizeof(filesize)); | 
 | 	if (0 == strcmp(filesize, "0") || 0 == strcmp(filesize, "")) { | 
 | 		printf("filesize is not set.\n"); | 
 | 		return; | 
 | 	} | 
 |  | 
 | 	sprintf(temp, "%sNum", filename); | 
 | 	sc_cfg_get(temp, filenum, sizeof(filenum)); | 
 | 	fp = fopen(filepath, "a"); | 
 | 	if (!fp) { | 
 | 		printf("fopen %s failed \n", filepath); | 
 | 		return; | 
 | 	} else if (flock(fileno(fp), LOCK_EX) != 0) { | 
 | 		perror("flock"); | 
 | 		fclose(fp); | 
 | 		return; | 
 | 	} | 
 |  | 
 | 	fprintf(fp, "%s %s\n", str_ctime(timenow), info); | 
 | 	fflush(fp); | 
 | 	fseek(fp, 0L, SEEK_END); | 
 | 	if (ftell(fp) > atoi(filesize)) | 
 | 		flag = 1; | 
 |  | 
 | 	flock(fileno(fp), LOCK_UN); | 
 | 	fclose(fp); | 
 |  | 
 | 	if (flag == 1) { | 
 | 		flash_file(filepath, "2"); | 
 | 	} | 
 | } | 
 |  | 
 | struct timeval timeget(void) | 
 | { | 
 | 	struct timeval now; | 
 | 	unsigned char  timestr[60] = {0}; | 
 | 	unsigned char  uptimestr[30] = {0}; | 
 | 	unsigned char * dotaddr = NULL; | 
 | 	unsigned long second; | 
 | 	char error = 0; | 
 | 	FILE * timefile = NULL; | 
 |     int read_len = 0; | 
 |  | 
 | 	timefile = fopen("/proc/uptime", "r"); | 
 | 	if (!timefile) { | 
 | 		printf("[%s:line:%d] error opening '/proc/uptime'", __FILE__, __LINE__); | 
 | 		error = 1; | 
 | 		goto out; | 
 | 	} | 
 | 	//klocwork  cov M | 
 | 	read_len = fread(timestr, sizeof(char), sizeof(timestr)-1, timefile); | 
 | 	if (read_len == 0 ) { | 
 | 		printf("[%s:line:%d] read '/proc/uptime' error", __FILE__, __LINE__); | 
 | 		error = 1; | 
 | 		goto out; | 
 | 	} | 
 | 	timestr[sizeof(timestr)-1] = '\0';//cov | 
 | 	dotaddr = strchr(timestr, '.'); | 
 | 	if (dotaddr != NULL && (dotaddr - timestr) < (30 - 2))//cov | 
 | 		memcpy(uptimestr, timestr, dotaddr - timestr + 2); | 
 | 	else { | 
 | 		printf("[%s:line:%d] uptime string is too long", __FILE__, __LINE__); | 
 | 		error = 1; | 
 | 		goto out; | 
 | 	} | 
 | 	uptimestr[dotaddr - timestr + 2] = '\0'; | 
 |  | 
 | out: | 
 | 	if (error) { | 
 | 		now.tv_sec  = 0; | 
 | 		now.tv_usec = 0; | 
 | 	} else { | 
 | 		now.tv_sec  = atol(uptimestr); | 
 | 		now.tv_usec = 0; | 
 | 	} | 
 | 	if (timefile) {//klocwork | 
 | 		fclose(timefile); | 
 | 	} | 
 | 	return now; | 
 | } | 
 |  | 
 | unsigned long time_sec() | 
 | { | 
 | 	struct timeval uptime; | 
 |  | 
 | 	uptime = timeget(); | 
 | 	//printf("uptime = %lu \n",(unsigned long)uptime.tv_sec); | 
 | 	return uptime.tv_sec; | 
 | } | 
 |  | 
 | int get_lan_info_list(struct list_head *file_list_info) | 
 | { | 
 | 	FILE *lanFile    = NULL; | 
 | 	char buf[32]; | 
 |  | 
 | 	LAN_INFO_t lanInfo = {0}; | 
 | 	char path_conf[50] = {0}; | 
 | 	char path_file[100] = {0}; | 
 |  | 
 | 	if (!list_empty(file_list_info)) { | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	sc_cfg_get("path_conf", path_conf, sizeof(path_conf)); | 
 | 	sprintf(path_file, "%s/laninfo.tmp", path_conf); | 
 |  | 
 | 	lanFile = fopen(path_file, "r"); | 
 | 	if (lanFile == NULL) { | 
 | 		slog(NET_PRINT, SLOG_ERR, "fopen laninfo.tmp fail \n"); | 
 | 		return 0; | 
 | 	} | 
 |  | 
 | 	while (fread(&lanInfo, sizeof(LAN_INFO_t), 1, lanFile) == 1) { | 
 | 		LAN_INFO_LIST_t *lanInfo_ptr = (LAN_INFO_LIST_t *)safe_malloc(sizeof(LAN_INFO_LIST_t), TRUE); | 
 | 		if (!lanInfo_ptr) { | 
 | 			slog(NET_PRINT, SLOG_ERR, "get_lan_info_list safe_malloc lanInfo_ptr fail \n"); | 
 | 			return -1; | 
 | 		} | 
 | 		memcpy(&(lanInfo_ptr->lan_info), &lanInfo, sizeof(LAN_INFO_t)); | 
 | 		list_add_tail(&lanInfo_ptr->list, file_list_info); | 
 | 	} | 
 |  | 
 | 	fclose(lanFile); | 
 | 	return 0; | 
 |  | 
 | } | 
 |  | 
 | /* ÉèÖó¬Ê±Ëø£¬ ³¬Ê±0±íʾÓÀ¾ÃËø - Ôݲ»¶ÔÍ⣬ÐèÒªms¼¶±ðʱ¿ª·Å */ | 
 | int set_wake_lock_timeout_ms(const char *lockid, unsigned long interval_ms) | 
 | { | 
 | 	char *p = NULL; | 
 | 	int ret = -1; | 
 |  | 
 | 	if ((lockid == NULL) || (*lockid == '\0'))  | 
 | 		return -1; | 
 |  | 
 | 	if (interval_ms == 0) { | 
 | 		ret = asprintf(&p, "%s", lockid); | 
 | 	} else { | 
 | 		ret = asprintf(&p, "%s %lu000000", lockid, interval_ms); | 
 | 	} | 
 | 	if (ret < 0) { | 
 | 		ret = -1; | 
 | 		goto out; | 
 | 	} | 
 | 	ret = write_to_file(WAKE_LOCK_PATH, p, strlen(p)); | 
 | 	 | 
 | out: | 
 | 	safe_free(p); | 
 | 	return ret; | 
 | } | 
 |  | 
 | /* »ñÈ¡wakelockËø */ | 
 | int set_wake_lock(const char *lockId) | 
 | { | 
 | 	return set_wake_lock_timeout_ms(lockId, 0); | 
 | } | 
 |  | 
 | /* ÉèÖó¬Ê±Ëø */ | 
 | int set_wake_lock_timeout(const char *lockId, unsigned long seconds) | 
 | { | 
 | 	return set_wake_lock_timeout_ms(lockId, seconds * 1000); | 
 | } | 
 |  | 
 | /* ÊÍ·ÅwakelockËø */ | 
 | int set_wake_unlock(const char *lockId) | 
 | { | 
 | 	if ((lockId == NULL) || (*lockId == '\0')) | 
 | 		return -1; | 
 | 	 | 
 | 	return write_to_file(WAKE_UNLOCK_PATH, lockId, strlen(lockId)); | 
 | } | 
 |  | 
 | int readNlSock(int sockFd, char *bufPtr, int seqNum, int pId) | 
 | { | 
 | 	struct nlmsghdr *nlHdr; | 
 | 	int readLen = 0, msgLen = 0; | 
 | 	do { | 
 | 		//ÊÕµ½Äں˵ÄÓ¦´ð | 
 | 		if ((readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0)) < 0) { | 
 | 			perror("SOCK READ: "); | 
 | 			return -1; | 
 | 		} | 
 |  | 
 |  | 
 | 		nlHdr = (struct nlmsghdr *)bufPtr; | 
 | 		//¼ì²éheaderÊÇ·ñÓÐЧ | 
 | 		if ((NLMSG_OK(nlHdr, readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR)) { | 
 | 			perror("Error in recieved packet"); | 
 | 			return -1; | 
 | 		} | 
 |  | 
 |  | 
 |  | 
 |  | 
 | 		if (nlHdr->nlmsg_type == NLMSG_DONE) { | 
 | 			break; | 
 | 		} else { | 
 | 			bufPtr += readLen; | 
 | 			msgLen += readLen; | 
 | 		} | 
 |  | 
 | 		if ((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0) { | 
 | 			break; | 
 | 		} | 
 | 	} while ((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId)); | 
 | 	return msgLen; | 
 | } | 
 |  | 
 | //coverity | 
 | static int net_RTA_OK(struct rtattr *rta, unsigned int len) | 
 | { | 
 | 	return RTA_OK(rta, len); | 
 | } | 
 |  | 
 | //·ÖÎö·µ»ØµÄ·ÓÉÐÅÏ¢ | 
 | void parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo) | 
 | { | 
 | 	struct rtmsg *rtMsg; | 
 | 	struct rtattr *rtAttr; | 
 | 	int rtLen, dstLen; | 
 | 	//char *tempBuf = NULL; | 
 | 	struct in_addr dst; | 
 | 	struct in_addr gate; | 
 | 	char cmd[128]; | 
 | 	char dstaddr[32], srcaddr[32]; | 
 |  | 
 |  | 
 | 	//tempBuf = (char *)malloc(100); | 
 | 	rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr); | 
 | 	// If the route is not for AF_INET or does not belong to main routing table | 
 | 	//then return. | 
 | 	if ((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN)) | 
 | 		return; | 
 | 	//printf("rtmsg srclen:%d,dstlen:%d\n",rtMsg->rtm_src_len,rtMsg->rtm_dst_len); | 
 | 	dstLen = rtMsg->rtm_dst_len; //·ÓɱíÖÐÄ¿µÄµØÖ·µÄÑÚÂ볤¶È | 
 |  | 
 |  | 
 | 	rtAttr = (struct rtattr *)RTM_RTA(rtMsg); | 
 | 	rtLen = RTM_PAYLOAD(nlHdr); | 
 | 	for (; net_RTA_OK(rtAttr, rtLen); rtAttr = RTA_NEXT(rtAttr, rtLen)) { | 
 | 		switch (rtAttr->rta_type) { | 
 | 		case RTA_OIF: | 
 | 			if_indextoname(*(int *)RTA_DATA(rtAttr), rtInfo->ifName);       //Íø¿¨Ãû³Æ | 
 | 			break; | 
 | 		case RTA_GATEWAY: | 
 | 			rtInfo->gateWay = *(u_int *)RTA_DATA(rtAttr);                       //´ËÌõ·ÓÉÏîµÄÍø¹Ø | 
 | 			break; | 
 | 		case RTA_PREFSRC: | 
 | 			rtInfo->srcAddr = *(u_int *)RTA_DATA(rtAttr);                       //·ÓÉÏîµÄÔ´µØÖ· | 
 | 			break; | 
 | 		case RTA_DST: | 
 | 			rtInfo->dstAddr = *(u_int *)RTA_DATA(rtAttr);                       //·ÓÉÏîÖеÄÄ¿µÄµØÖ· | 
 | 			break; | 
 | 		} | 
 | 	} | 
 | 	dst.s_addr = rtInfo->dstAddr; | 
 |  | 
 | 	printf("oif:%s\t", rtInfo->ifName); | 
 | 	gate.s_addr = rtInfo->gateWay; | 
 | 	printf("%s\n", (char *)inet_ntoa(gate)); | 
 |  | 
 | 	printf("src:%s\n", (char *)inet_ntoa(gate)); | 
 | 	snprintf(srcaddr, sizeof(srcaddr), "%s", (char *)inet_ntoa(gate));//klocwork | 
 | 	gate.s_addr = rtInfo->dstAddr; | 
 | 	printf("dst:%s\n", (char *)inet_ntoa(gate)); | 
 |  | 
 | 	//free(tempBuf); | 
 | 	return; | 
 | } | 
 |  | 
 | /****************************************/ | 
 | //½Ó¿Ú¹¦ÄÜ£º ¼ì²âÊÇ·ñÅäÖÃÁËȱʡ·ÓÉ£¬ÐèÒªÁ¬ÍâÍøµÄÓ¦ÓÿÉÒÔµ÷Óñ¾½Ó¿ÚÅжÏÍøÂçÊÇ·ñ¾ÍÐ÷ | 
 | //return: | 
 | //    -1: error; | 
 | //     0: ÍøÂçδ¾ÍÐ÷ | 
 | //     1: ÍøÂçÒѾÍÐ÷ | 
 | /****************************************/ | 
 | int default_route_check() | 
 | { | 
 | 	struct nlmsghdr *nlMsg; | 
 | 	struct rtmsg *rtMsg; | 
 | 	struct route_info *rtInfo; | 
 | 	char *msgBuf = malloc(BUFSIZE); | 
 |  | 
 |  | 
 | 	int sock, len, msgSeq = 0; | 
 |  | 
 |     if(NULL == msgBuf) { | 
 |         softap_assert(""); | 
 | 		return -1;//klocwork | 
 |     } | 
 |  | 
 | 	if ((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) { | 
 | 		perror("Socket Creation: "); | 
 | 		free(msgBuf); | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	memset(msgBuf, 0, BUFSIZE); | 
 |  | 
 | 	nlMsg = (struct nlmsghdr *)msgBuf; | 
 | 	rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg); | 
 | 	nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message. | 
 | 	nlMsg->nlmsg_type = RTM_GETROUTE; // Get the routes from kernel routing table . | 
 | 	nlMsg->nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; // The message is a request for dump. | 
 | 	nlMsg->nlmsg_seq = msgSeq++; // Sequence of the message packet. | 
 | 	nlMsg->nlmsg_pid = getpid(); // PID of process sending the request. | 
 |  | 
 | 	if (send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0) { | 
 | 		printf("Write To Socket Failed¡\n"); | 
 | 		free(msgBuf); | 
 | 		close(sock); | 
 | 		return -1; | 
 | 	} | 
 |  | 
 | 	if ((len = readNlSock(sock, msgBuf, msgSeq, getpid())) < 0) { | 
 | 		printf("Read From Socket Failed¡\n"); | 
 | 		free(msgBuf); | 
 | 		close(sock); | 
 | 		return -1; | 
 | 	} | 
 |  | 
 |  | 
 | 	rtInfo = (struct route_info *)malloc(sizeof(struct route_info)); | 
 | 	if (NULL == rtInfo) { //klocwork | 
 | 		printf("Malloc route_info Failed¡\n"); | 
 | 		free(msgBuf); | 
 | 		close(sock); | 
 | 		return -1; | 
 | 	} | 
 | 	for (; NLMSG_OK(nlMsg, len); nlMsg = NLMSG_NEXT(nlMsg, len)) { | 
 | 		memset(rtInfo, 0, sizeof(struct route_info)); | 
 | 		parseRoutes(nlMsg, rtInfo); | 
 | 		if (rtInfo->dstAddr == 0 && strlen(rtInfo->ifName)) { | 
 | 			printf("default wan :%s \n", rtInfo->ifName); | 
 | 			free(rtInfo); | 
 | 			close(sock); | 
 | 			free(msgBuf); | 
 | 			return 1; | 
 | 		} | 
 | 	} | 
 | 	free(rtInfo); | 
 | 	close(sock); | 
 | 	free(msgBuf); | 
 | 	return 0; | 
 | } | 
 |  | 
 |  | 
 |  | 
 | /**************************************/ | 
 | //½Ó¿Ú¹¦ÄÜ:   ¼ì²âflashÊÇ·ñ±»ÆäËûºËÕ¼Óà | 
 | //return: | 
 | //             0   -----  flashûÓб»Õ¼Óà | 
 | //		   1   -----  flashÕý±»ÆäËûºËÕ¼Óà | 
 | //		  -1  -----  open½Úµãʧ°Ü | 
 | //		  -2  -----  ioctlʧ°Ü | 
 | /**************************************/ | 
 |  | 
 | int flash_mutex_check() | 
 | { | 
 | 	int fd, ret; | 
 | 	char arg = 3; | 
 | 	fd = open("/dev/softspinlock", O_RDWR); | 
 | 	//printf("fd = %d \n",fd); | 
 | 	if (fd < 0) | 
 | 		return -1; | 
 |  | 
 | 	ret = ioctl(fd, SPINLOCK_GET_STATUS, &arg); | 
 | 	//printf("ret = %d  arg = %d \n",ret,arg); | 
 | 	if (ret < 0) { | 
 | 		close(fd); | 
 | 		return -2; | 
 | 	} | 
 | 	close(fd); | 
 | 	return arg; | 
 |  | 
 | } | 
 |  | 
 | //»ñȡָ¶¨Ïß³ÌÃûµÄpidºÅ£¬×¢Ò⣺µ÷Óøú¯Êý»ñÈ¡·µ»ØÖµ£¬Ê¹ÓúóÒ»¶¨ÒªÊͷŸÃÄÚ´æ¿Õ¼ä | 
 | pid_t* find_pid_by_name(char *pidName) | 
 | { | 
 | 	DIR *dir; | 
 | 	struct dirent *next; | 
 | 	pid_t* pidList = NULL; | 
 | 	pid_t* tmpList = NULL; | 
 | 	int i = 0; | 
 | 	 | 
 | 	//procÖаüÀ¨µ±Ç°µÄ½ø³ÌÐÅÏ¢£¬¶ÁÈ¡¸ÃĿ¼ | 
 | 	dir = opendir("/proc"); | 
 | 	if(!dir) | 
 | 	{ | 
 | 		perror("Cannot open /proc"); | 
 | 		return pidList; | 
 | 	} | 
 | 	//±éÀú/procÏÂĿ¼ | 
 | 	while((next = readdir(dir)) != NULL) | 
 | 	{ | 
 | 		FILE *status; | 
 | 		char filename[READ_BUF_SIZE] = {0};//klocwork | 
 | 		char filename1[READ_BUF_SIZE] = {0};//klocwork | 
 | 		char name[READ_BUF_SIZE] = {0}; | 
 | 		//skip ".." since that is outside /proc | 
 | 		if(0 == strcmp(next->d_name,"..")) | 
 | 			continue; | 
 | 		//if it isn't a number,we skip it | 
 | 		if(!isdigit(*next->d_name)) | 
 | 			continue; | 
 | 		 | 
 | 		snprintf(filename,sizeof(filename),"/proc/%s/status",next->d_name); | 
 |  | 
 | 		if(!(status = fopen(filename,"r"))) | 
 | 		{ | 
 | 			continue; | 
 | 		} | 
 | 		if(NULL == fgets(filename1,READ_BUF_SIZE-1,status)) | 
 | 		{ | 
 | 			fclose(status); | 
 | 			continue; | 
 | 		} | 
 | 		fclose(status); | 
 | 		 | 
 | 		//»ñÈ¡½ø³Ìpid£¬Í¬Ê±Ò²»áÓжà¸öÏàͬ½ø³ÌÃûµÄÇé¿ö | 
 | 		sscanf(filename1, "%*s %s", name); | 
 | 		if(0 == strcmp(name,pidName)) | 
 | 		{ | 
 | 			//pidList = realloc(pidList,sizeof(pid_t)*(i+2)); | 
 | 			//klocwork | 
 | 			tmpList = realloc(pidList,sizeof(pid_t)*(i+2)); | 
 | 			if (NULL == tmpList) { | 
 | 				continue; | 
 | 			} | 
 | 			pidList = tmpList; | 
 | 			errno = 0; | 
 | 			pidList[i++] = strtol(next->d_name,NULL,0); | 
 | 			if (errno == ERANGE)// kw ERRNO.NOT_CHECKED | 
 | 			{ | 
 | 				printf("strtol errno %d: %s\n", errno, strerror(errno)); | 
 | 			} | 
 | 		} | 
 | 	} | 
 | 	if(pidList) | 
 | 	{ | 
 | 		pidList[i] = 0; | 
 | 	} | 
 | 	closedir(dir); | 
 | 	return pidList; | 
 | } | 
 |  | 
 | void handle_quit(int signo) | 
 | { | 
 |     pthread_exit(NULL); | 
 | } | 
 |  | 
 | /* gethostbyname¹¦ÄÜÖж¨Ê±Æ÷³¬Ê±´¦Àíº¯Êý */ | 
 | void gethostbyname_timeout(int msg_id) | 
 | { | 
 | 	slog(NET_PRINT, SLOG_DEBUG, "gethostbyname_timeout begin,msg_id=%d\n",msg_id); | 
 | 	if(ipc_send_message(msg_id, msg_id, MSG_GET_HOST_BY_NAME_TIMEOUT,0, 0, 0) < 0) | 
 |     { | 
 |         // todo: for cov M | 
 |     }         | 
 | } | 
 |  | 
 | /** | 
 | * gethostbyname¹¦ÄÜÖд´½¨¶¨Ê±Æ÷ | 
 | * second_time: ³¬Ê±Ê±³¤ | 
 | * msg_id:         Ïß³Ìid | 
 | */ | 
 | void gethostbyname_creattimer(int second_time, int msg_id) | 
 | { | 
 | 	slog(NET_PRINT, SLOG_DEBUG, "gethostbyname_creattimer begin\n"); | 
 | 	sc_timer_delete(TIMER_GETHOSTBYNAME_ID); | 
 | 	sc_timer_create(TIMER_GETHOSTBYNAME_ID, TIMER_FLAG_ONCE, second_time*1000, gethostbyname_timeout, (void *)msg_id); | 
 | } | 
 |  | 
 | /* gethostbyname¹¦ÄÜÖÐɾ³ý¶¨Ê±Æ÷ */ | 
 | void gethostbyname_deletetimer() | 
 | { | 
 | 	slog(NET_PRINT, SLOG_DEBUG, "gethostbyname_deletetimer begin\n"); | 
 | 	sc_timer_delete(TIMER_GETHOSTBYNAME_ID); | 
 | } | 
 |  | 
 | void *gethostbyname_timer(void *arg) | 
 | { | 
 | 	int time = 0; | 
 | 	char *name = NULL; | 
 | 	int msg_id; | 
 | 	struct hostent* hptr = NULL; | 
 | 	 | 
 | 	time =((struct gethostbyname_info *)arg)->time; | 
 | 	name = ((struct gethostbyname_info *)arg)->name; | 
 | 	msg_id = ((struct gethostbyname_info *)arg)->msg_id; | 
 |  | 
 | 	slog(NET_PRINT, SLOG_DEBUG, "gethostbyname_timer time=%d,name=%s,msg_id=%d\n", time, name, msg_id); | 
 | 	 | 
 | 	signal(SIGQUIT, handle_quit); | 
 | 	 | 
 | 	gethostbyname_creattimer(time, msg_id); //Æð¶¨Ê±Æ÷ | 
 | 	 | 
 | 	hptr = gethostbyname(name); | 
 | 	if(NULL != hptr) //»ñÈ¡µ½hostÐÅÏ¢ | 
 | 	{ | 
 | 		slog(NET_PRINT, SLOG_DEBUG, "gethostbyname_timer get info\n"); | 
 | 		gethostbyname_deletetimer(); //ɾ³ý¶¨Ê±Æ÷ | 
 | 		slog(NET_PRINT, SLOG_DEBUG, "gethostbyname_timer result hostname=%s\n",hptr->h_name); | 
 | 		//¸øÖ÷½ø³Ì·¢ÏûÏ¢ | 
 | 		if(ipc_send_message(msg_id, msg_id, MSG_GET_HOST_BY_NAME_SUCCESS, sizeof(void *), (UCHAR *)&hptr, 0) < 0) | 
 |         { | 
 |             // todo: for cov M | 
 |         }       | 
 | 		pthread_exit(NULL); | 
 | 	} | 
 | 	return NULL; | 
 | } | 
 |  | 
 | //·â×°gethostbynameº¯Êý£¬Ôö¼ÓÒ»¸ö³¬Ê±Ê±¼äµÄÈë²Î£¬timeµ¥Î»ÎªÃë | 
 | //Èç¹û³¬¹ý³¬Ê±Ê±¼äÈÔÈ»»ñÈ¡²»µ½hostÐÅÏ¢£¬Ôòº¯Êý·µ»Ø²»¼ÌÐø×èÈû | 
 | //¶¨Ê±Æ÷IDÏß³ÌÄÚ¹²Ïí£¬Ò»¸ö½ø³Ì²»ÒªÍ¬Ê±µ÷ÓÃ¸Ã½Ó¿Ú | 
 | struct hostent *gethostbyname_t(const char *name, int time) | 
 | { | 
 | 	slog(NET_PRINT, SLOG_DEBUG, "gethostbyname_t begin\n"); | 
 | 	pthread_t pthread; | 
 | 	int my_handle = 0; | 
 | 	int module_id = MODULE_ID_AP_GETHOSTBYNAME_BASE; | 
 | 	int ret = 0; | 
 | 	int msg_ret = 0; | 
 | 	struct hostent* hostresultinfo = NULL; | 
 | 	struct gethostbyname_info myhostinfo = {0}; | 
 | 	MSG_BUF rsp_msg = {0}; | 
 | 	LONG msgSize =  sizeof(MSG_BUF) - sizeof(LONG); | 
 | 	if(0 == time) | 
 | 	{ | 
 | 		slog(NET_PRINT, SLOG_DEBUG, "gethostbyname_t time =0\n"); | 
 | 		return gethostbyname(name); | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		slog(NET_PRINT, SLOG_DEBUG, "gethostbyname_t time = %d\n",time); | 
 |  | 
 |         //¶¯Ì¬´´½¨ÁÙʱµÄÏûÏ¢¶ÓÁйܵÀ | 
 |         //msggetʹÓòÎÊýIPC_CREAT | IPC_EXCL| 0600£¬Åжϵ±Ç°module_idµÄÏûÏ¢¶ÓÁÐÊÇ·ñ | 
 |         //´æÔÚ£¬Èç¹û²»´æÔÚ£¬Ö±½Ó´´½¨ÐµÄÏûÏ¢¶ÓÁУ»Èç¹û´æÔÚ£¬·µ»ØÖµÎ´-1£¬È»ºómodule_id | 
 |         //Öµ¼Ó1£¬²»¶ÏÑ»·Ö±µ½ÕÒµ½Ã»ÓÐʹÓõÄmodule_idÖµ | 
 | 		while((my_handle = msgget(module_id,IPC_CREAT | IPC_EXCL| 0600)) == -1)  | 
 | 		{ | 
 |         	module_id++; | 
 | 			//µ±module_id´óÓÚMODULE_ID_ATDYNAMIC_ENDֵʱ£¬Ö÷¶¯¶ÏÑÔ | 
 | 			if (module_id > MODULE_ID_AP_GETHOSTBYNAME_END)  | 
 | 			{ | 
 | 				softap_assert("MODULE_ID_AP_GETHOSTBYNAME_END!!!!!!!!!!!\n"); | 
 | 			} | 
 | 		} | 
 | 		myhostinfo.time = time; | 
 | 		strncpy(myhostinfo.name, name, sizeof(myhostinfo.name)-1); | 
 | 		myhostinfo.msg_id = module_id; | 
 | 		//Æð×ÓỊ̈߳¬ÔÚ×ÓÏß³ÌÀï´´½¨¶¨Ê±Æ÷ | 
 | 		ret = pthread_create(&pthread, NULL, (void *)gethostbyname_timer, (void *)&myhostinfo); | 
 | 		if (ret < 0 || pthread == NULL) { | 
 | 			slog(NET_PRINT, SLOG_DEBUG, "creat thread fail\n"); | 
 | 			return NULL; | 
 | 		} | 
 | 		while(1) | 
 | 		{ | 
 | 			msg_ret = 0; | 
 | 			memset(&rsp_msg, 0x00, sizeof(MSG_BUF)); | 
 | 			msg_ret = msgrcv(my_handle, &rsp_msg, msgSize, 0, 0); | 
 | 			if (msg_ret < 0) | 
 |         	{ | 
 |         		continue; | 
 | 			} | 
 |  | 
 | 			if(rsp_msg.usMsgCmd == MSG_GET_HOST_BY_NAME_SUCCESS) | 
 | 			{ | 
 | 				slog(NET_PRINT, SLOG_DEBUG, "gethostbyname_t success\n"); | 
 | 				hostresultinfo = (struct hostent*)(*(int *)rsp_msg.aucDataBuf); | 
 | 				slog(NET_PRINT, SLOG_DEBUG, "gethostbyname_t result:name=%s\n",hostresultinfo->h_name); | 
 | 				return hostresultinfo; | 
 | 			} | 
 | 			else if(rsp_msg.usMsgCmd == MSG_GET_HOST_BY_NAME_TIMEOUT) | 
 | 			{ | 
 | 				slog(NET_PRINT, SLOG_DEBUG, "gethostbyname_t fail\n"); | 
 | 				pthread_kill(pthread, SIGQUIT); | 
 | 				return NULL; | 
 | 			} | 
 | 			else | 
 | 			{ | 
 | 				slog(NET_PRINT, SLOG_ERR, "gethostbyname_t fail\n"); | 
 | 			} | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | /******************************************************************************/ | 
 |  | 
 | #define DNS_SERVER_NUM 2 | 
 |  | 
 | #define T_A 1 //Ipv4 address | 
 | #define T_NS 2 //Nameserver | 
 | #define T_CNAME 5 // canonical name | 
 | #define T_SOA 6 /* start of authority zone */ | 
 | #define T_PTR 12 /* domain name pointer */ | 
 | #define T_MX 15 //Mail server | 
 |  | 
 |  | 
 |  | 
 | //DNS header structure | 
 | struct DNS_HEADER { | 
 | 	unsigned short id; // identification number | 
 |  | 
 | 	unsigned char rd :1; // recursion desired | 
 | 	unsigned char tc :1; // truncated message | 
 | 	unsigned char aa :1; // authoritive answer | 
 | 	unsigned char opcode :4; // purpose of message | 
 | 	unsigned char qr :1; // query/response flag | 
 |  | 
 | 	unsigned char rcode :4; // response code | 
 | 	unsigned char cd :1; // checking disabled | 
 | 	unsigned char ad :1; // authenticated data | 
 | 	unsigned char z :1; // its z! reserved | 
 | 	unsigned char ra :1; // recursion available | 
 |  | 
 | 	unsigned short q_count; // number of question entries | 
 | 	unsigned short ans_count; // number of answer entries | 
 | 	unsigned short auth_count; // number of authority entries | 
 | 	unsigned short add_count; // number of resource entries | 
 | }; | 
 |  | 
 | //Constant sized fields of query structure | 
 | struct QUESTION { | 
 | 	unsigned short qtype; | 
 | 	unsigned short qclass; | 
 | }; | 
 |  | 
 | //Constant sized fields of the resource record structure | 
 | #pragma pack(push, 1) | 
 | struct R_DATA { | 
 | 	unsigned short type; | 
 | 	unsigned short _class; | 
 | 	unsigned int ttl; | 
 | 	unsigned short data_len; | 
 | }; | 
 | #pragma pack(pop) | 
 |  | 
 | //Pointers to resource record contents | 
 | struct RES_RECORD { | 
 | 	unsigned char *name; | 
 | 	struct R_DATA *resource; | 
 | 	unsigned char *rdata; | 
 | }; | 
 |  | 
 | //Structure of a Query | 
 | typedef struct { | 
 | 	unsigned char *name; | 
 | 	struct QUESTION *ques; | 
 | } QUERY; | 
 |  | 
 |  | 
 | void ChangetoDnsNameFormat(unsigned char* dns, unsigned char* host) { | 
 | 	int lock = 0, i; | 
 | 	strcat((char*) host, "."); | 
 |  | 
 | 	for (i = 0; i < strlen((char*) host); i++) { | 
 | 		if (host[i] == '.') { | 
 | 			*dns++ = i - lock; | 
 | 			for (; lock < i; lock++) { | 
 | 				*dns++ = host[lock]; | 
 | 			} | 
 | 			lock++; //or lock=i+1; | 
 | 		} | 
 | 	} | 
 | 	*dns++ = '\0'; | 
 | } | 
 |  | 
 | u_char* ReadName(unsigned char* reader, unsigned char* buffer, int* count) { | 
 | 	unsigned char *name; | 
 | 	unsigned int p = 0, jumped = 0, offset; | 
 | 	int i, j; | 
 |  | 
 | 	*count = 1; | 
 | 	name = (unsigned char*) malloc(256); | 
 | 	if (!name) | 
 | 		return NULL;//klocwork | 
 |  | 
 | 	name[0] = '\0'; | 
 |  | 
 | 	//read the names in 3www6google3com format | 
 | 	while (*reader != 0) { | 
 | 		if (*reader >= 192) { | 
 | 			offset = (*reader) * 256 + *(reader + 1) - 49152; //49152 = 11000000 00000000 ;) | 
 | 			reader = buffer + offset - 1; | 
 | 			jumped = 1; //we have jumped to another location so counting wont go up! | 
 | 		} else { | 
 | 			name[p++] = *reader; | 
 | 		} | 
 |  | 
 | 		reader = reader + 1; | 
 |  | 
 | 		if (jumped == 0) { | 
 | 			*count = *count + 1; //if we havent jumped to another location then we can count up | 
 | 		} | 
 | 	} | 
 |  | 
 | 	name[p] = '\0'; //string complete | 
 | 	if (jumped == 1) { | 
 | 		*count = *count + 1; //number of steps we actually moved forward in the packet | 
 | 	} | 
 |  | 
 | 	//now convert 3www6google3com0 to www.google.com | 
 | 	for (i = 0; i < (int) strlen((const char*) name); i++) { | 
 | 		p = name[i]; | 
 | 		for (j = 0; j < (int) p; j++) { | 
 | 			name[i] = name[i + 1]; | 
 | 			i = i + 1; | 
 | 		} | 
 | 		name[i] = '.'; | 
 | 	} | 
 | 	name[i - 1] = '\0'; //remove the last dot | 
 | 	return name; | 
 | } | 
 |  | 
 | unsigned long my_gethostbyname(unsigned char *host, char *dev_name,char* dns_server, int query_type) { | 
 | 	unsigned char buf[1025], *qname, *reader; | 
 | 	int i, j, stop, s, ans_max; | 
 | 	struct timeval tv; | 
 | 	unsigned long ret = 0; | 
 | 	struct ifreq ifr; | 
 | 	 | 
 | 	struct sockaddr_in a; | 
 |  | 
 | 	struct RES_RECORD answers[20], auth[20], addit[20]; //the replies from the DNS server | 
 | 	struct sockaddr_in dest; | 
 |  | 
 | 	struct DNS_HEADER *dns = NULL; | 
 | 	struct QUESTION *qinfo = NULL; | 
 |  | 
 | 	printf("Resolving %s", host); | 
 |  | 
 | 	s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //UDP packet for DNS queries | 
 | 	if(s < 0) | 
 |     { | 
 |         printf("socket return fail \n"); | 
 |         return ret; | 
 |     }    | 
 | 	 | 
 | 	memset(&ifr,0,sizeof(ifr));     | 
 | 	strncpy(ifr.ifr_name, dev_name, sizeof(ifr.ifr_name)-1); | 
 | 	if(setsockopt(s,SOL_SOCKET,SO_BINDTODEVICE,(char*)&ifr,sizeof(ifr)) < 0){ | 
 | 		printf("SO_BINDTODEVICE fail \n"); | 
 | 		goto out; | 
 | 	} | 
 | 	tv.tv_sec = 5; | 
 | 	tv.tv_usec = 0; | 
 | 	if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) { | 
 | 		printf("socket option  SO_RCVTIMEO not support\n"); | 
 | 		goto out; | 
 | 	} | 
 | 	dest.sin_family = AF_INET; | 
 | 	dest.sin_port = htons(53); | 
 | 	dest.sin_addr.s_addr = inet_addr(dns_server); //dns servers | 
 |  | 
 | 	//Set the DNS structure to standard queries | 
 | 	dns = (struct DNS_HEADER *) &buf; | 
 |  | 
 | 	dns->id = (unsigned short) htons(getpid()); | 
 | 	dns->qr = 0; //This is a query | 
 | 	dns->opcode = 0; //This is a standard query | 
 | 	dns->aa = 0; //Not Authoritative | 
 | 	dns->tc = 0; //This message is not truncated | 
 | 	dns->rd = 1; //Recursion Desired | 
 | 	dns->ra = 0; //Recursion not available! hey we dont have it (lol) | 
 | 	dns->z = 0; | 
 | 	dns->ad = 0; | 
 | 	dns->cd = 0; | 
 | 	dns->rcode = 0; | 
 | 	dns->q_count = htons(1); //we have only 1 question | 
 | 	dns->ans_count = 0; | 
 | 	dns->auth_count = 0; | 
 | 	dns->add_count = 0; | 
 |  | 
 | 	//point to the query portion | 
 | 	qname = (unsigned char*) &buf[sizeof(struct DNS_HEADER)]; | 
 |  | 
 | 	ChangetoDnsNameFormat(qname, host); | 
 | 	qinfo = (struct QUESTION*) &buf[sizeof(struct DNS_HEADER) | 
 | 			+ (strlen((const char*) qname) + 1)]; //fill it | 
 |  | 
 | 	qinfo->qtype = htons(query_type); //type of the query , A , MX , CNAME , NS etc | 
 | 	qinfo->qclass = htons(1); //its internet (lol) | 
 |  | 
 | 	printf("\nSending Packet..."); | 
 | 	if (sendto(s, (char*) buf, | 
 | 			sizeof(struct DNS_HEADER) + (strlen((const char*) qname) + 1) | 
 | 					+ sizeof(struct QUESTION), 0, (struct sockaddr*) &dest, | 
 | 			sizeof(dest)) < 0) { | 
 | 		perror("sendto failed"); | 
 | 	} | 
 | 	printf("Done"); | 
 |  | 
 | 	//Receive the answer | 
 | 	i = sizeof dest; | 
 | 	printf("\nReceiving answer..."); | 
 | 	if (recvfrom(s, (char*) buf, sizeof(buf)-1, 0, (struct sockaddr*) &dest, | 
 | 			(socklen_t*) &i) < 0) { | 
 | 		perror("recvfrom failed"); | 
 | 	} | 
 | 	*(buf+sizeof(buf)-1) = 0; | 
 | 	printf("Done"); | 
 |  | 
 | 	dns = (struct DNS_HEADER*) buf; | 
 | 	if((sizeof(struct DNS_HEADER) +  | 
 | 		(strlen((const char*) qname) + 1)+  | 
 | 		sizeof(struct QUESTION)) >= sizeof(buf)) | 
 | 	{ | 
 | 		perror("my_gethostbyname error"); | 
 | 		goto out; | 
 | 	} | 
 | 	 | 
 | 	//move ahead of the dns header and the query field | 
 | 	reader = &buf[sizeof(struct DNS_HEADER) + (strlen((const char*) qname) + 1) | 
 | 			+ sizeof(struct QUESTION)]; | 
 |  | 
 | 	//printf("\nThe response contains : "); | 
 | 	//printf("\n %d Questions.", ntohs(dns->q_count)); | 
 | 	//printf("\n %d Answers.", ntohs(dns->ans_count)); | 
 | 	//printf("\n %d Authoritative Servers.", ntohs(dns->auth_count)); | 
 | 	//printf("\n %d Additional records.\n\n", ntohs(dns->add_count)); | 
 |  | 
 | 	//Start reading answers | 
 | 	stop = 0; | 
 | 	//klocwork | 
 | 	//ans_max = ((ntohs(dns->ans_count) <= (sizeof(answers)/sizeof(answers[0]))) ? ntohs(dns->ans_count) : (sizeof(answers)/sizeof(answers[0]))); | 
 | 	ans_max = ntohs(dns->ans_count); | 
 | 	if (ans_max > (sizeof(answers)/sizeof(answers[0]))) | 
 | 		ans_max = (sizeof(answers)/sizeof(answers[0])); | 
 | 	for (i = 0; i < ans_max; i++)  | 
 | 	{ | 
 | 		answers[i].name = ReadName(reader, buf, &stop); | 
 | 		reader = reader + stop; | 
 |  | 
 | 		answers[i].resource = (struct R_DATA*) (reader); | 
 | 		reader = reader + sizeof(struct R_DATA); | 
 |  | 
 | 		if (ntohs(answers[i].resource->type) == 1) //if its an ipv4 address | 
 | 				{ | 
 | 			answers[i].rdata = (unsigned char*) malloc( | 
 | 					ntohs(answers[i].resource->data_len)); | 
 |  | 
 | 			for (j = 0; j < ntohs(answers[i].resource->data_len); j++) { | 
 | 				answers[i].rdata[j] = reader[j]; | 
 | 			} | 
 |  | 
 | 			answers[i].rdata[ntohs(answers[i].resource->data_len)] = '\0'; | 
 |  | 
 | 			reader = reader + ntohs(answers[i].resource->data_len); | 
 | 		} else { | 
 | 			answers[i].rdata = ReadName(reader, buf, &stop); | 
 | 			reader = reader + stop; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	//print answers | 
 | 	printf("\nAnswer Records : %d \n", ntohs(dns->ans_count)); | 
 | 	for (i = 0; i < ans_max; i++) { | 
 | 		printf("Name : %s ", answers[i].name); | 
 |  | 
 | 		if (ntohs(answers[i].resource->type) == T_A) //IPv4 address | 
 | 		{ | 
 | 			long *p; | 
 | 			p = (long*) answers[i].rdata; | 
 | 			a.sin_addr.s_addr = (*p); //working without ntohl | 
 | #if 1       // cov M | 
 | 			char * s_addr = inet_ntoa(a.sin_addr); | 
 | 			printf("has IPv4 address : %s", s_addr); | 
 | #else | 
 |             printf("has IPv4 address : %s", inet_ntoa(a.sin_addr)); | 
 | #endif | 
 | 			ret = (unsigned long)a.sin_addr.s_addr; | 
 | 		} | 
 |  | 
 | 		if (ntohs(answers[i].resource->type) == 5) { | 
 | 			//Canonical name for an alias | 
 | 			printf("has alias name : %s", answers[i].rdata); | 
 | 		} | 
 |  | 
 | 		printf("\n"); | 
 | 	} | 
 | out: | 
 | 	close(s); | 
 | 	return ret; | 
 | } | 
 |  | 
 |  | 
 | unsigned long gethostbyname_l(char *hostname,char* dev_name)  | 
 | { | 
 | 	int i = 0; | 
 | 	unsigned long ret = 0; | 
 | 	char dns_servers[DNS_SERVER_NUM][32] = {0}; | 
 |  | 
 | 	//Get the DNS servers from the resolv.conf file | 
 | 	char nv_dns[32]	= {0}; | 
 | 	char ip_dns[32]	= {0}; | 
 | 	 | 
 |     sprintf(nv_dns, "%s_pridns", dev_name); | 
 | 	sc_cfg_get(nv_dns, ip_dns, sizeof(ip_dns)); | 
 | 	strcpy(dns_servers[0], ip_dns); | 
 |  | 
 | 	memset(nv_dns,0,sizeof(nv_dns)); | 
 | 	memset(ip_dns,0,sizeof(ip_dns)); | 
 | 	sprintf(nv_dns, "%s_secdns", dev_name); | 
 | 	sc_cfg_get(nv_dns, ip_dns, sizeof(ip_dns)); | 
 | 	strcpy(dns_servers[1], ip_dns); | 
 |  | 
 | 	 | 
 | 	//Now get the ip of this hostname , A record | 
 | 	for(i=0;i<DNS_SERVER_NUM;i++) | 
 | 	{ | 
 | 		ret = my_gethostbyname(hostname, dev_name , dns_servers[i], T_A); | 
 | 		if(ret > 0) | 
 | 			break; | 
 | 	} | 
 |   | 
 | 	return ret; | 
 | } | 
 |  | 
 |  | 
 |  | 
 |  | 
 | /******************************************************************************/ | 
 |  | 
 |  |