blob: 96701e99b5ab0baa3933457f2ed246a6705ccef4 [file] [log] [blame]
liubin281ac462023-07-19 14:22:54 +08001/*************************************************************
2Description:
3 C file for network control.
4Author:
5 LiuBin
6Date:
7 2019/7/24 17:13:06
8*************************************************************/
9#include <stdio.h>
10#include <stdlib.h>
11#include <unistd.h>
12#include <sys/un.h>
13#include <sys/socket.h>
14#include <netinet/in.h>
15#include <arpa/inet.h>
16#include <errno.h>
17#include <linux/netlink.h>
18#include <linux/rtnetlink.h>
19#include <linux/route.h>
20#include <cutils/properties.h>
21#include <telephony/ril.h>
22
23#include "mbtk_type.h"
24#include "mbtk_net_control.h"
25#include "mbtk_task.h"
26#include "mbtk_utils.h"
27#include "mbtk_str.h"
28
29#ifdef LOG_TAG
30#undef LOG_TAG
31#endif
32#define LOG_TAG "mbtk_net_control"
33#include "mbtk_log.h"
34
35/*************************************************************
36 Constants and Macros
37*************************************************************/
38#define NET_CONTROL_BUF_SIZE 1024
39#ifndef INFTIM
40#define INFTIM (-1) /* infinite poll timeout */
41#endif
42#define MBTK_NET_PING_HOST "223.5.5.5"
43#define MBTK_NET_PING_IP "180.97.33.107" // IP for www.baidu.com
44
45// #define MBTK_NET_MONITOR_SUPPORT
46
47/*************************************************************
48 Variables:local
49*************************************************************/
50static char net_interface[20];
51static char net_ip[20];
b.liueb040652023-09-25 18:50:56 +080052static bool net_if_inited = FALSE;
liubin281ac462023-07-19 14:22:54 +080053static mbtk_net_state_t net_state = MBTK_NET_STATE_OFF;
54static bool net_control_thread_running = FALSE;
55
56#ifdef MBTK_NET_MONITOR_SUPPORT
b.liudeb8e422024-12-14 17:36:56 +080057static pthread_t net_control_thread_id;
liubin281ac462023-07-19 14:22:54 +080058static int net_control_fd = -1;
b.liueb040652023-09-25 18:50:56 +080059static char net_if_name[100] = {0};
liubin281ac462023-07-19 14:22:54 +080060#endif
61
62/*************************************************************
63 Variables:public
64*************************************************************/
65
66
67/*************************************************************
68 Local Function Declaration
69*************************************************************/
b.liueb040652023-09-25 18:50:56 +080070static mbtk_net_state_callback_func net_state_cb = NULL;
liubin281ac462023-07-19 14:22:54 +080071
72/*************************************************************
73 Local Function Definitions
74*************************************************************/
75// Test network connected?
76// ping www.baidu.com
77static bool net_connected(const char *inf)
78{
79 char cmd[100];
80 char cmd_rsp[100];
81
82 // IP get now, ping www.baidu.com
83 memset(cmd,0,100);
84 snprintf(cmd,100,
85 "ping -I %s -c1 -s0 -w1000 %s | grep \"8 bytes from \"",
86 inf,
87 MBTK_NET_PING_HOST);
88 if(!mbtk_cmd_line(cmd,cmd_rsp,100))
89 {
90 LOGE("ping www.baidu.com cmd error.");
91 return FALSE;
92 }
93
94 LOGI("cmd_rsp:%s",cmd_rsp);
95 // ping www.baidu.com success.
96 if(str_startwith(cmd_rsp, "8 bytes from "))
97 {
98 return TRUE;
99 }
100#if 0
101 else if(str_contains(cmd_rsp, "unknown host"))
102 {
103 // DNS error,ping IP angin.
104 memset(cmd,0,100);
105 snprintf(cmd,100,
106 "ping -I %s -c1 -s0 -w1000 %s | grep \"8 bytes from \"",
107 inf,
108 MBTK_NET_PING_IP);
109 if(!mbtk_cmd_line(cmd,cmd_rsp,100))
110 {
111 LOGW("ping www.baidu.com IP cmd error.");
112 return FALSE;
113 }
114
115 if(str_startwith(cmd_rsp, "8 bytes from "))
116 {
117 return TRUE;
118 }
119 else
120 {
121 LOGW("Network unconnected.(ping baidu IP fail)");
122 return FALSE;
123 }
124 }
125#endif
126 else
127 {
128 LOGW("Network unconnected.(ping baidu host fail)");
129 return FALSE;
130 }
131
132 LOGW("ifconfig cmd fail.");
133 return FALSE;
134}
135
136#ifdef MBTK_NET_MONITOR_SUPPORT
137static int net_control_netlink_init()
138{
139 struct sockaddr_nl sa;
140 int len = 2048;
141
142 net_control_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
143 if(net_control_fd < 0)
144 {
145 LOGE("socket() fail.[%d]",errno);
146 return -1;
147 }
148
149 if(setsockopt(net_control_fd,
150 SOL_SOCKET, SO_RCVBUF, &len, sizeof(len)) < 0)
151 {
152 LOGE("setsockopt() fail.[%d]",errno);
153 return -1;
154 }
155
156 bzero(&sa, sizeof(sa));
157 sa.nl_family = AF_NETLINK;
158 sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE /*| RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE*/;
159 if(bind(net_control_fd,
160 (struct sockaddr *) &sa, sizeof(sa)) < 0)
161 {
162 LOGE("bind() fail.[%d]",errno);
163 return -1;
164 }
165
166 return 0;
167}
168
b.liueb040652023-09-25 18:50:56 +0800169static void parse_rtattr(struct rtattr **tb, int max, struct rtattr *attr, int len)
170{
171 for ( ; RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) {
172 if (attr->rta_type <= max) {
173 tb[attr->rta_type] = attr;
174 }
175 }
176}
177
liubin281ac462023-07-19 14:22:54 +0800178static void net_control_if_change(struct nlmsghdr *nh)
179{
b.liueb040652023-09-25 18:50:56 +0800180 int msg_len;
liubin281ac462023-07-19 14:22:54 +0800181 struct rtattr *tb[IFLA_MAX + 1];
182 struct ifinfomsg *ifinfo;
183 bzero(tb, sizeof(tb));
184 if(nh == NULL)
185 {
186 LOGE("mbtk_net_if_change() nh == NULL");
187 return;
188 }
189
190 ifinfo = NLMSG_DATA(nh);
191 if(ifinfo == NULL)
192 {
193 LOGE("mbtk_net_if_change() ifinfo == NULL");
194 return;
195 }
196
b.liueb040652023-09-25 18:50:56 +0800197 msg_len = nh->nlmsg_len - NLMSG_SPACE(sizeof(*ifinfo));
198 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifinfo), msg_len); /* 8 */
liubin281ac462023-07-19 14:22:54 +0800199
b.liueb040652023-09-25 18:50:56 +0800200 LOGD("Interface changed:if_index=%d,if_name=%s,type=%s,state=%s",
201 ifinfo->ifi_index, (tb[IFLA_IFNAME] ? RTA_DATA(tb[IFLA_IFNAME]) : " "),
202 (nh->nlmsg_type == RTM_NEWLINK) ? "NEWLINK" : "DELLINK",
203 (ifinfo->ifi_flags & IFF_UP) ? "up" : "down");
liubin281ac462023-07-19 14:22:54 +0800204
b.liueb040652023-09-25 18:50:56 +0800205 if(net_state_cb) {
206 mbtk_net_if_change_info_t if_info;
207 memset(&if_info, 0x0, sizeof(mbtk_net_if_change_info_t));
208 if_info.if_index = ifinfo->ifi_index;
209 if(tb[IFLA_IFNAME]) {
210 memcpy(if_info.if_name, RTA_DATA(tb[IFLA_IFNAME]), strlen(RTA_DATA(tb[IFLA_IFNAME])));
211 }
212 if_info.type = (nh->nlmsg_type == RTM_NEWLINK) ? MBTK_NET_IF_CHANGE_TYPE_ADD : MBTK_NET_IF_CHANGE_TYPE_DEL;
213 if_info.state = (ifinfo->ifi_flags & IFF_UP) ? MBTK_NET_IF_CHANGE_STATE_UP : MBTK_NET_IF_CHANGE_STATE_DOWN;
214 if(str_empty(net_if_name)) { // No set if name, process all interface change.
215 net_state_cb(MBTK_NET_CHANGE_IF, &if_info);
216 } else {
217 // Only monitor specific interface.
218 if(strcmp(net_if_name, if_info.if_name) == 0) {
219 net_state_cb(MBTK_NET_CHANGE_IF, &if_info);
220 }
221 }
liubin281ac462023-07-19 14:22:54 +0800222 }
223}
224
b.liueb040652023-09-25 18:50:56 +0800225static void net_control_addr_change(struct nlmsghdr *nlh)
liubin281ac462023-07-19 14:22:54 +0800226{
b.liueb040652023-09-25 18:50:56 +0800227 int len;
228 struct rtattr *tb[IFA_MAX + 1];
229 struct ifaddrmsg *ifaddr;
liubin281ac462023-07-19 14:22:54 +0800230
b.liueb040652023-09-25 18:50:56 +0800231 bzero(tb, sizeof(tb));
232 ifaddr = NLMSG_DATA(nlh);
233 len =nlh->nlmsg_len - NLMSG_SPACE(sizeof(*ifaddr));
234 parse_rtattr(tb, IFA_MAX, IFA_RTA (ifaddr), len);
235
236 if (tb[IFA_ADDRESS] != NULL) {
237 char tmp[256] = {0};
238 inet_ntop(ifaddr->ifa_family, RTA_DATA(tb[IFA_ADDRESS]), tmp, sizeof(tmp));
239 LOGD("Address changed:index=%d,type=%s,if_name=%s,addr=%s", ifaddr->ifa_index,
240 (nlh->nlmsg_type == RTM_NEWADDR) ? "NEWADDR":"DELADDR",
241 tb[IFA_LABEL] ? RTA_DATA(tb[IFA_LABEL]) : "Unknown", tmp);
242
243 if(net_state_cb) {
244 mbtk_net_addr_change_info_t addr_info;
245 memset(&addr_info, 0x0, sizeof(mbtk_net_addr_change_info_t));
246 addr_info.if_index = ifaddr->ifa_index;
247 addr_info.type = (nlh->nlmsg_type == RTM_NEWADDR) ? MBTK_NET_ADDR_CHANGE_TYPE_ADD : MBTK_NET_ADDR_CHANGE_TYPE_DEL;
248 if(tb[IFA_LABEL] != NULL) {
249 memcpy(addr_info.if_name, RTA_DATA(tb[IFA_LABEL]), strlen(RTA_DATA(tb[IFA_LABEL])));
250 }
251 if (strlen(tmp) > 0) {
252 memcpy(addr_info.addr, tmp, strlen(tmp));
253 }
254 if(str_empty(net_if_name)) { // No set if name, process all address change.
255 net_state_cb(MBTK_NET_CHANGE_ADDR, &addr_info);
256 } else {
257 // Only monitor specific address.
258 if(strcmp(net_if_name, addr_info.if_name) == 0) {
259 net_state_cb(MBTK_NET_CHANGE_ADDR, &addr_info);
260 }
261 }
262 }
263 } else {
264 LOGD("Address changed:type=%s,if_name=%s,addr=%s",
265 (nlh->nlmsg_type == RTM_NEWADDR) ? "NEWADDR":"DELADDR",
266 tb[IFA_LABEL] ? RTA_DATA(tb[IFA_LABEL]) : "Unknown", "Unknown");
267
268 if(net_state_cb) {
269 mbtk_net_addr_change_info_t addr_info;
270 memset(&addr_info, 0x0, sizeof(mbtk_net_addr_change_info_t));
271 addr_info.if_index = ifaddr->ifa_index;
272 addr_info.type = (nlh->nlmsg_type == RTM_NEWADDR) ? MBTK_NET_ADDR_CHANGE_TYPE_ADD : MBTK_NET_ADDR_CHANGE_TYPE_DEL;
273 if(tb[IFA_LABEL] != NULL) {
274 memcpy(addr_info.if_name, RTA_DATA(tb[IFA_LABEL]), strlen(RTA_DATA(tb[IFA_LABEL])));
275 }
276 if(str_empty(net_if_name)) { // No set if name, process all address change.
277 net_state_cb(MBTK_NET_CHANGE_ADDR, &addr_info);
278 } else {
279 // Only monitor specific address.
280 if(strcmp(net_if_name, addr_info.if_name) == 0) {
281 net_state_cb(MBTK_NET_CHANGE_ADDR, &addr_info);
282 }
283 }
284 }
liubin281ac462023-07-19 14:22:54 +0800285 }
286}
287
288static void* net_control_monitor_run(void *arg)
289{
290 LOGI("net_control_monitor_run start.");
291 if(net_control_netlink_init() < 0)
292 {
293 LOGE("mbtk_net_monitor_run() fail.");
294 return ((void*)0);
295 }
296
297 fd_set rd_set;
298 struct timeval timeout;
299 int select_r;
300 int read_r;
b.liu9e8584b2024-11-06 19:21:28 +0800301// struct sockaddr_nl sa;
liubin281ac462023-07-19 14:22:54 +0800302 struct nlmsghdr *nh;
303 char buff[NET_CONTROL_BUF_SIZE];
304
305 while (net_control_thread_running)
306 {
307 FD_ZERO(&rd_set);
308 FD_SET(net_control_fd, &rd_set);
309 timeout.tv_sec = 5;
310 timeout.tv_usec = 0;
311 select_r = select(net_control_fd + 1, &rd_set, NULL, NULL, &timeout);
312 if (select_r < 0)
313 {
314 perror("select");
315 }
316 else if (select_r > 0)
317 {
318 if (FD_ISSET(net_control_fd, &rd_set))
319 {
320 read_r = read(net_control_fd, buff, NET_CONTROL_BUF_SIZE);
321 LOGI("Net change:read len:%d",read_r);
b.liueb040652023-09-25 18:50:56 +0800322#if 0
liubin281ac462023-07-19 14:22:54 +0800323 int i;
324 for(i = 0; i < 32 && i < read_r; i++)
325 LOGI("data:%x",buff[i]);
b.liueb040652023-09-25 18:50:56 +0800326#endif
liubin281ac462023-07-19 14:22:54 +0800327 for (nh = (struct nlmsghdr *) buff; NLMSG_OK(nh, read_r); nh = NLMSG_NEXT(nh, read_r))
328 {
329 LOGI("msg_type:%d",nh->nlmsg_type);
330 switch (nh->nlmsg_type)
331 {
332 default:
333 LOGI("nh->nlmsg_type = %d\n", nh->nlmsg_type);
334 break;
335 case NLMSG_DONE:
336 case NLMSG_ERROR:
337 break;
338 case RTM_NEWLINK:
339 case RTM_DELLINK:
340 net_control_if_change(nh);
341 break;
342 case RTM_NEWADDR:
343 case RTM_DELADDR:
344 net_control_addr_change(nh);
345 break;
346 case RTM_NEWROUTE:
347 case RTM_DELROUTE:
348 //print_rtmsg(nh);
349 break;
350 }
351
352 }
353 }
354 }
355 }
356
357 LOGD("mbtk_net_monitor_run exist ...");
358
359 return ((void*)0);
360}
361
362static mbtk_task_info net_control_thread =
363{
364 .task_id = &net_control_thread_id,
365 .thread_run = net_control_monitor_run,
366 .args = NULL
367};
368#endif
369
370static int net_control_interface_init()
371{
372 // seth_ltex
373 int i = 0;
374 int size = 0;
375 char result[NET_CONTROL_BUF_SIZE];
376 char cmd[100];
377 int index = 0;
378 while(i <= 7)
379 {
380 size = snprintf(cmd, 100,"ifconfig ccinet%d", i);
381 cmd[size] = '\0';
382 memset(result,0x0,NET_CONTROL_BUF_SIZE);
383 if(mbtk_cmd_line(cmd, result, NET_CONTROL_BUF_SIZE))
384 {
385 index = str_indexof(result,"inet addr:");
386 if(index > 0)
387 {
388 size = snprintf(net_interface, 20,"ccinet%d", i);
389 net_interface[size] = '\0';
390
391 memcpy(net_ip,result + index + 10,20);
392
393 char *ptr = net_ip;
394 while(*ptr && *ptr != ' ')
395 {
396 ptr++;
397 }
398 *ptr = '\0';
399 break;
400 }
401 }
402 i++;
403 }
404
405 LOGI("Interface : %s, IP : %s",net_interface,net_ip);
406 if(index )
407 {
408 return 0;
409 }
410 else{
411 return -1;
412 }
413}
414
415static int net_control_init()
416{
b.liueb040652023-09-25 18:50:56 +0800417 if(net_if_inited)
418 {
419 LOGD("Network control has inited.");
420 return 0;
421 }
liubin281ac462023-07-19 14:22:54 +0800422
423 memset(net_ip,0x0,20);
424 memset(net_interface,0x0,20);
b.liueb040652023-09-25 18:50:56 +0800425 if(net_control_interface_init())
liubin281ac462023-07-19 14:22:54 +0800426 return -1;
liubin281ac462023-07-19 14:22:54 +0800427
b.liueb040652023-09-25 18:50:56 +0800428 net_if_inited = TRUE;
liubin281ac462023-07-19 14:22:54 +0800429 LOGI("net_control_init() success.");
430 return 0;
431}
432
433static int net_control_state_change(bool enable)
434{
435 int size;
436 char result[NET_CONTROL_BUF_SIZE];
437 char cmd[100];
438 if(enable)
439 {
440 // ifconfig seth_lte1 up
441 // ip route add default via 10.94.251.205 dev seth_lte1
442 size = snprintf(cmd,100,"ifconfig %s up",net_interface);
443 cmd[size] = '\0';
444
445 if(mbtk_cmd_line(cmd, result, NET_CONTROL_BUF_SIZE))
446 {
447 size = snprintf(cmd,100,"ip route add default via %s dev %s",net_ip,net_interface);
448 cmd[size] = '\0';
449
450 if(mbtk_cmd_line(cmd, result, NET_CONTROL_BUF_SIZE))
451 {
452 net_state = MBTK_NET_STATE_CONN;
453 return 0;
454 }
455 }
456 }
457 else
458 {
459 // ifconfig seth_lte1 down
460 size = snprintf(cmd,100,"ifconfig %s down",net_interface);
461 cmd[size] = '\0';
462
463 if(mbtk_cmd_line(cmd, result, NET_CONTROL_BUF_SIZE))
464 {
465 net_state = MBTK_NET_STATE_OFF;
466 return 0;
467 }
468 }
469
470 return -1;
471}
472
473/*************************************************************
474 Public Function Definitions
475*************************************************************/
476/*=============================================
477FUNCTION
478 mbtk_net_state_get()
479
480DESCRIPTION
481 Get network state.
482
483DEPENDENCIES
484 None
485
486PARAMETERS
487 None
488
489RETURN VALUE
490 Current network state.
491
492SIDE EFFECTS
493 None
494=============================================*/
495mbtk_net_state_t mbtk_net_state_get()
496{
497 net_control_init();
498
499 net_state = MBTK_NET_STATE_OFF;
500 if(strlen(net_ip) > 0)
501 {
502 if(net_connected(net_interface))
503 net_state = MBTK_NET_STATE_CONN;
504 }
505
506 LOGI("[GET]Net state:%d",net_state);
507
508 if(net_state == MBTK_NET_STATE_CONN)
509 {
510 char value[PROPERTY_VALUE_MAX] = {0};
511 if (property_get("persist.mbtk.netstate", value, "0,0") > 0 && strcmp(value,"0,0")) {
512 int regStatus = 0, gprsState = 0;
513 char *ptr = value;
514 regStatus = atoi(ptr);
515 if((ptr = strstr(ptr, ",")))
516 {
517 gprsState = atoi(ptr + 1);
518 }
519
520 LOGI("regStatus : %d, gprsState : %d", regStatus, gprsState);
521 if(regStatus != 1 && regStatus != 5) // Not Home/Roaming Network.
522 {
523 net_state = MBTK_NET_STATE_CONN_UNKNOWN;
524 }
525 else
526 {
527 if (gprsState == RADIO_TECH_LTE || gprsState == RADIO_TECH_LTEP)
528 {
529 net_state = MBTK_NET_STATE_CONN_4G;
530 }
531 else if ((gprsState == RADIO_TECH_GPRS) || (gprsState == RADIO_TECH_EDGE) || (gprsState == RADIO_TECH_GSM))
532 {
533 net_state = MBTK_NET_STATE_CONN_2G;
534 } else if((gprsState == RADIO_TECH_UMTS) || (gprsState == RADIO_TECH_HSDPA)
535 || (gprsState == RADIO_TECH_HSUPA) || (gprsState == RADIO_TECH_HSPA)) {
536 net_state = MBTK_NET_STATE_CONN_3G;
537 } else {
538 net_state = MBTK_NET_STATE_CONN_UNKNOWN;
539 }
540 }
541 }
542 else
543 {
544 LOGE("property_get persist.mbtk.netstate fail.");
545 net_state = MBTK_NET_STATE_CONN_UNKNOWN;
546 goto end;
547 }
548 }
549
550end:
551 return net_state;
552}
553
554/*=============================================
555FUNCTION
556 mbtk_net_enable()
557
558DESCRIPTION
559 Set network state.
560
561DEPENDENCIES
562 None
563
564PARAMETERS
565 enable
566 TRUE : Enable network.
567 FALSE: Diable network.
568
569RETURN VALUE
570 0 : Success
571 -1: Fail
572
573SIDE EFFECTS
574 None
575=============================================*/
576int mbtk_net_enable(bool enable)
577{
578 if( net_control_init())
579 return -1;
580
581 int result = net_control_state_change(enable);
582
583 LOGI("[SET]Net state:%d",net_state);
584
585 return result;
586}
587
b.liueb040652023-09-25 18:50:56 +0800588int mbtk_net_monitor_reg(const char* if_name, mbtk_net_state_callback_func state_cb)
589{
590 if( net_control_init())
591 return -1;
592
593#ifdef MBTK_NET_MONITOR_SUPPORT
594 net_control_thread_running = TRUE;
595 if(mbtk_task_start(&net_control_thread))
596 {
597 LOGE("Create thread fail.");
b.liueb040652023-09-25 18:50:56 +0800598 net_control_thread_running = FALSE;
599 return -1;
600 }
601#endif
602
603 net_state_cb = state_cb;
604 if(str_empty(if_name)) {
605 memset(net_if_name, 0x0, sizeof(net_if_name));
606 } else {
607 memset(net_if_name, 0x0, sizeof(net_if_name));
608 memcpy(net_if_name, if_name, strlen(if_name));
609 }
610
611 return 0;
612}
613
614