blob: c1d73ce178788e0876dd32a1028b46c1a9bbae2d [file] [log] [blame]
/**
* @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 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;
}
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;
}
/******************************************************************************/