| /** |
| * @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; |
| } |
| |
| |
| |
| |
| /******************************************************************************/ |
| |
| |