[Feature][T106]ZXW P56U09 code
Only Configure: Yes
Affected branch: master
Affected module: unknow
Is it affected on both ZXIC and MTK: only ZXIC
Self-test: No
Doc Update: No
Change-Id: I3cbd8b420271eb20c2b40ebe5c78f83059cd42f3
diff --git a/ap/lib/libsoftap/netotherapi.c b/ap/lib/libsoftap/netotherapi.c
new file mode 100755
index 0000000..4fb37f5
--- /dev/null
+++ b/ap/lib/libsoftap/netotherapi.c
@@ -0,0 +1,1788 @@
+/**
+* @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_AAAA 28 //Ipv6 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]; //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 to %s...", dns_server);
+ 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) == T_A) //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");
+ free(answers[i].name);
+ free(answers[i].rdata);
+ }
+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};
+
+ snprintf(nv_dns, sizeof(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));
+ snprintf(nv_dns, sizeof(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;
+}
+
+int my_gethostbyname6(unsigned char *host, char *dev_name, char* dns_server, int query_type, struct in6_addr* ip6)
+{
+ unsigned char buf[1025], *qname, *reader;
+ int i, j, stop, s, ans_max, ret = 0;
+ struct timeval tv;
+ struct ifreq ifr = {0};
+ struct RES_RECORD answers[20]; //the replies from the DNS server
+ struct sockaddr_in6 dest = {0};
+ struct in6_addr a = {0};
+ struct DNS_HEADER *dns = NULL;
+ struct QUESTION *qinfo = NULL;
+ char nv_cmd[64] = {0};
+ char ip_src[64] = {0};
+ struct sockaddr_in6 src = {0};
+
+ printf("Resolving %s", host);
+
+ s = socket(AF_INET6, 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;
+ }
+ snprintf(nv_cmd, sizeof(nv_cmd), "%s_ipv6_ip", dev_name);
+ sc_cfg_get(nv_cmd, ip_src, sizeof(ip_src));
+ src.sin6_family = AF_INET6;
+ if(inet_pton(AF_INET6, ip_src, &src.sin6_addr) <= 0){
+ printf("inet_pton fail1 \n");
+ goto out;
+ }
+ if (bind(s, (struct sockaddr*)&src, sizeof(src)) < 0) {
+ printf("bind fail \n");
+ goto out;
+ }
+ dest.sin6_family = AF_INET6;
+ dest.sin6_port = htons(53);
+ if(inet_pton(AF_INET6, dns_server, &dest.sin6_addr) <= 0){
+ printf("inet_pton fail2 \n");
+ goto out;
+ }
+ //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 to %s...", dns_server);
+ 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;
+ 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) == T_AAAA) //if its an ipv6 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_AAAA) //IPv6 address
+ {
+ char ip6_addr[IPV6ADDLEN_MAX] = {0};
+ memcpy(&a, answers[i].rdata, sizeof(struct in6_addr));
+ if(inet_ntop(AF_INET6, &a, ip6_addr, sizeof(ip6_addr))){
+ if(ip6)
+ memcpy(ip6, &a, sizeof(struct in6_addr));
+ printf("%p has IPv6 address : %s", ip6, ip6_addr);
+ ret = 1;
+ }else
+ printf("nohas IPv6 address len:%d", answers[i].resource->data_len);
+ }
+
+ if (ntohs(answers[i].resource->type) == 5) {
+ //Canonical name for an alias
+ printf("has alias name : %s", answers[i].rdata);
+ }
+ printf("\n");
+ free(answers[i].name);
+ free(answers[i].rdata);
+ }
+out:
+ close(s);
+ return ret;
+}
+
+int gethostbyname6_l(char *hostname,char* dev_name, struct in6_addr* ip6)
+{
+ int i = 0;
+ unsigned long ret = 0;
+ char dns_servers[DNS_SERVER_NUM][64] = {0};
+
+ //Get the DNS servers from the resolv.conf file
+ char nv_dns[64] = {0};
+ char ip_dns[64] = {0};
+
+ sprintf(nv_dns, "%s_ipv6_pridns_auto", 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_ipv6_secdns_auto", 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++)
+ {
+ if(my_gethostbyname6(hostname, dev_name , dns_servers[i], T_AAAA, ip6))
+ return 0;
+ }
+ return -1;
+}
+
+
+/******************************************************************************/
+
+