blob: ff3af085d1fb4518759db0ea8f6aad4c9b497817 [file] [log] [blame]
/*************************************************************
Description:
C file for network control.
Author:
LiuBin
Date:
2019/7/24 17:13:06
*************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/route.h>
#include <cutils/properties.h>
#include <telephony/ril.h>
#include "mbtk_type.h"
#include "mbtk_net_control.h"
#include "mbtk_task.h"
#include "mbtk_utils.h"
#include "mbtk_str.h"
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "mbtk_net_control"
#include "mbtk_log.h"
/*************************************************************
Constants and Macros
*************************************************************/
#define NET_CONTROL_BUF_SIZE 1024
#ifndef INFTIM
#define INFTIM (-1) /* infinite poll timeout */
#endif
#define MBTK_NET_PING_HOST "223.5.5.5"
#define MBTK_NET_PING_IP "180.97.33.107" // IP for www.baidu.com
// #define MBTK_NET_MONITOR_SUPPORT
/*************************************************************
Variables:local
*************************************************************/
static char net_interface[20];
static char net_ip[20];
static mbtk_net_state_t net_state = MBTK_NET_STATE_OFF;
static bool net_control_thread_running = FALSE;
#ifdef MBTK_NET_MONITOR_SUPPORT
static pthread_t net_control_thread_id = -1;
static int net_control_fd = -1;
#endif
/*************************************************************
Variables:public
*************************************************************/
/*************************************************************
Local Function Declaration
*************************************************************/
/*************************************************************
Local Function Definitions
*************************************************************/
// Test network connected?
// ping www.baidu.com
static bool net_connected(const char *inf)
{
char cmd[100];
char cmd_rsp[100];
// IP get now, ping www.baidu.com
memset(cmd,0,100);
snprintf(cmd,100,
"ping -I %s -c1 -s0 -w1000 %s | grep \"8 bytes from \"",
inf,
MBTK_NET_PING_HOST);
if(!mbtk_cmd_line(cmd,cmd_rsp,100))
{
LOGE("ping www.baidu.com cmd error.");
return FALSE;
}
LOGI("cmd_rsp:%s",cmd_rsp);
// ping www.baidu.com success.
if(str_startwith(cmd_rsp, "8 bytes from "))
{
return TRUE;
}
#if 0
else if(str_contains(cmd_rsp, "unknown host"))
{
// DNS error,ping IP angin.
memset(cmd,0,100);
snprintf(cmd,100,
"ping -I %s -c1 -s0 -w1000 %s | grep \"8 bytes from \"",
inf,
MBTK_NET_PING_IP);
if(!mbtk_cmd_line(cmd,cmd_rsp,100))
{
LOGW("ping www.baidu.com IP cmd error.");
return FALSE;
}
if(str_startwith(cmd_rsp, "8 bytes from "))
{
return TRUE;
}
else
{
LOGW("Network unconnected.(ping baidu IP fail)");
return FALSE;
}
}
#endif
else
{
LOGW("Network unconnected.(ping baidu host fail)");
return FALSE;
}
LOGW("ifconfig cmd fail.");
return FALSE;
}
#ifdef MBTK_NET_MONITOR_SUPPORT
static int net_control_netlink_init()
{
struct sockaddr_nl sa;
int len = 2048;
net_control_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if(net_control_fd < 0)
{
LOGE("socket() fail.[%d]",errno);
return -1;
}
if(setsockopt(net_control_fd,
SOL_SOCKET, SO_RCVBUF, &len, sizeof(len)) < 0)
{
LOGE("setsockopt() fail.[%d]",errno);
return -1;
}
bzero(&sa, sizeof(sa));
sa.nl_family = AF_NETLINK;
sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE /*| RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE*/;
if(bind(net_control_fd,
(struct sockaddr *) &sa, sizeof(sa)) < 0)
{
LOGE("bind() fail.[%d]",errno);
return -1;
}
return 0;
}
static void net_control_if_change(struct nlmsghdr *nh)
{
struct rtattr *tb[IFLA_MAX + 1];
struct ifinfomsg *ifinfo;
bzero(tb, sizeof(tb));
if(nh == NULL)
{
LOGE("mbtk_net_if_change() nh == NULL");
return;
}
ifinfo = NLMSG_DATA(nh);
if(ifinfo == NULL)
{
LOGE("mbtk_net_if_change() ifinfo == NULL");
return;
}
LOGD("nlmsghdr:%d,%d,%d,%d,%d\n",nh->nlmsg_len,
nh->nlmsg_type,
nh->nlmsg_flags,
nh->nlmsg_seq,
nh->nlmsg_pid);
LOGD("ifinfomsg:%d,%d,%d,%d,%d,%d\n",ifinfo->ifi_family,
ifinfo->__ifi_pad,
ifinfo->ifi_type,
ifinfo->ifi_index,
ifinfo->ifi_flags,
ifinfo->ifi_change);
if((ifinfo->ifi_flags & IFF_RUNNING)
&& (ifinfo->ifi_flags & IFF_LOWER_UP))
{
LOGD("Wired inserted.");
}
else
{
LOGD("Wired not insert.");
}
}
static void net_control_addr_change(struct nlmsghdr *nh)
{
if(nh == NULL)
{
LOGE("mbtk_net_if_change() nh == NULL");
return;
}
if(nh->nlmsg_type==RTM_NEWADDR)
{
LOGD("New addr...");
}
else
{
LOGD("Del addr...");
}
}
static void* net_control_monitor_run(void *arg)
{
LOGI("net_control_monitor_run start.");
if(net_control_netlink_init() < 0)
{
LOGE("mbtk_net_monitor_run() fail.");
return ((void*)0);
}
fd_set rd_set;
struct timeval timeout;
int select_r;
int read_r;
struct sockaddr_nl sa;
struct nlmsghdr *nh;
char buff[NET_CONTROL_BUF_SIZE];
while (net_control_thread_running)
{
FD_ZERO(&rd_set);
FD_SET(net_control_fd, &rd_set);
timeout.tv_sec = 5;
timeout.tv_usec = 0;
select_r = select(net_control_fd + 1, &rd_set, NULL, NULL, &timeout);
if (select_r < 0)
{
perror("select");
}
else if (select_r > 0)
{
if (FD_ISSET(net_control_fd, &rd_set))
{
read_r = read(net_control_fd, buff, NET_CONTROL_BUF_SIZE);
LOGI("Net change:read len:%d",read_r);
int i;
for(i = 0; i < 32 && i < read_r; i++)
LOGI("data:%x",buff[i]);
for (nh = (struct nlmsghdr *) buff; NLMSG_OK(nh, read_r); nh = NLMSG_NEXT(nh, read_r))
{
LOGI("msg_type:%d",nh->nlmsg_type);
switch (nh->nlmsg_type)
{
default:
LOGI("nh->nlmsg_type = %d\n", nh->nlmsg_type);
break;
case NLMSG_DONE:
case NLMSG_ERROR:
break;
case RTM_NEWLINK:
case RTM_DELLINK:
net_control_if_change(nh);
break;
case RTM_NEWADDR:
case RTM_DELADDR:
net_control_addr_change(nh);
break;
case RTM_NEWROUTE:
case RTM_DELROUTE:
//print_rtmsg(nh);
break;
}
}
}
}
}
LOGD("mbtk_net_monitor_run exist ...");
return ((void*)0);
}
static mbtk_task_info net_control_thread =
{
.task_id = &net_control_thread_id,
.thread_run = net_control_monitor_run,
.args = NULL
};
#endif
static int net_control_interface_init()
{
// seth_ltex
int i = 0;
int size = 0;
char result[NET_CONTROL_BUF_SIZE];
char cmd[100];
int index = 0;
while(i <= 7)
{
size = snprintf(cmd, 100,"ifconfig ccinet%d", i);
cmd[size] = '\0';
memset(result,0x0,NET_CONTROL_BUF_SIZE);
if(mbtk_cmd_line(cmd, result, NET_CONTROL_BUF_SIZE))
{
index = str_indexof(result,"inet addr:");
if(index > 0)
{
size = snprintf(net_interface, 20,"ccinet%d", i);
net_interface[size] = '\0';
memcpy(net_ip,result + index + 10,20);
char *ptr = net_ip;
while(*ptr && *ptr != ' ')
{
ptr++;
}
*ptr = '\0';
break;
}
}
i++;
}
LOGI("Interface : %s, IP : %s",net_interface,net_ip);
if(index )
{
return 0;
}
else{
return -1;
}
}
static int net_control_init()
{
// if(net_control_thread_running)
// {
// LOGD("Network control has inited.");
// return 0;
// }
memset(net_ip,0x0,20);
memset(net_interface,0x0,20);
if( net_control_interface_init())
return -1;
net_control_thread_running = TRUE;
#ifdef MBTK_NET_MONITOR_SUPPORT
if(mbtk_task_start(&net_control_thread))
{
LOGE("Create thread fail.");
net_control_thread_id = -1;
net_control_thread_running = FALSE;
return -1;
}
#endif
LOGI("net_control_init() success.");
return 0;
}
static int net_control_state_change(bool enable)
{
int size;
char result[NET_CONTROL_BUF_SIZE];
char cmd[100];
if(enable)
{
// ifconfig seth_lte1 up
// ip route add default via 10.94.251.205 dev seth_lte1
size = snprintf(cmd,100,"ifconfig %s up",net_interface);
cmd[size] = '\0';
if(mbtk_cmd_line(cmd, result, NET_CONTROL_BUF_SIZE))
{
size = snprintf(cmd,100,"ip route add default via %s dev %s",net_ip,net_interface);
cmd[size] = '\0';
if(mbtk_cmd_line(cmd, result, NET_CONTROL_BUF_SIZE))
{
net_state = MBTK_NET_STATE_CONN;
return 0;
}
}
}
else
{
// ifconfig seth_lte1 down
size = snprintf(cmd,100,"ifconfig %s down",net_interface);
cmd[size] = '\0';
if(mbtk_cmd_line(cmd, result, NET_CONTROL_BUF_SIZE))
{
net_state = MBTK_NET_STATE_OFF;
return 0;
}
}
return -1;
}
/*************************************************************
Public Function Definitions
*************************************************************/
/*=============================================
FUNCTION
mbtk_net_state_get()
DESCRIPTION
Get network state.
DEPENDENCIES
None
PARAMETERS
None
RETURN VALUE
Current network state.
SIDE EFFECTS
None
=============================================*/
mbtk_net_state_t mbtk_net_state_get()
{
net_control_init();
net_state = MBTK_NET_STATE_OFF;
if(strlen(net_ip) > 0)
{
if(net_connected(net_interface))
net_state = MBTK_NET_STATE_CONN;
}
LOGI("[GET]Net state:%d",net_state);
if(net_state == MBTK_NET_STATE_CONN)
{
char value[PROPERTY_VALUE_MAX] = {0};
if (property_get("persist.mbtk.netstate", value, "0,0") > 0 && strcmp(value,"0,0")) {
int regStatus = 0, gprsState = 0;
char *ptr = value;
regStatus = atoi(ptr);
if((ptr = strstr(ptr, ",")))
{
gprsState = atoi(ptr + 1);
}
LOGI("regStatus : %d, gprsState : %d", regStatus, gprsState);
if(regStatus != 1 && regStatus != 5) // Not Home/Roaming Network.
{
net_state = MBTK_NET_STATE_CONN_UNKNOWN;
}
else
{
if (gprsState == RADIO_TECH_LTE || gprsState == RADIO_TECH_LTEP)
{
net_state = MBTK_NET_STATE_CONN_4G;
}
else if ((gprsState == RADIO_TECH_GPRS) || (gprsState == RADIO_TECH_EDGE) || (gprsState == RADIO_TECH_GSM))
{
net_state = MBTK_NET_STATE_CONN_2G;
} else if((gprsState == RADIO_TECH_UMTS) || (gprsState == RADIO_TECH_HSDPA)
|| (gprsState == RADIO_TECH_HSUPA) || (gprsState == RADIO_TECH_HSPA)) {
net_state = MBTK_NET_STATE_CONN_3G;
} else {
net_state = MBTK_NET_STATE_CONN_UNKNOWN;
}
}
}
else
{
LOGE("property_get persist.mbtk.netstate fail.");
net_state = MBTK_NET_STATE_CONN_UNKNOWN;
goto end;
}
}
end:
return net_state;
}
/*=============================================
FUNCTION
mbtk_net_enable()
DESCRIPTION
Set network state.
DEPENDENCIES
None
PARAMETERS
enable
TRUE : Enable network.
FALSE: Diable network.
RETURN VALUE
0 : Success
-1: Fail
SIDE EFFECTS
None
=============================================*/
int mbtk_net_enable(bool enable)
{
if( net_control_init())
return -1;
int result = net_control_state_change(enable);
LOGI("[SET]Net state:%d",net_state);
return result;
}