You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
5.5 KiB

2 years ago
  1. #include <sys/socket.h>
  2. #include <sys/select.h>
  3. #include <sys/types.h>
  4. #include <net/if.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <arpa/inet.h>
  8. #include <endian.h>
  9. #include "libmnl/ifutils.h"
  10. #include "libmnl/dhcp/dhcp.h"
  11. #include "util.h"
  12. #include "QMIThread.h"
  13. static int ql_raw_ip_mode_check(const char *ifname)
  14. {
  15. int fd;
  16. char raw_ip[128];
  17. char mode[2] = "X";
  18. int mode_change = 0;
  19. snprintf(raw_ip, sizeof(raw_ip), "/sys/class/net/%s/qmi/raw_ip", ifname);
  20. if (access(raw_ip, F_OK))
  21. return 0;
  22. fd = open(raw_ip, O_RDWR | O_NONBLOCK | O_NOCTTY);
  23. if (fd < 0)
  24. {
  25. dbg_time("%s %d fail to open(%s), errno:%d (%s)", __FILE__, __LINE__, raw_ip, errno, strerror(errno));
  26. return 0;
  27. }
  28. read(fd, mode, 2);
  29. if (mode[0] == '0' || mode[0] == 'N')
  30. {
  31. if_link_down(ifname);
  32. dbg_time("echo Y > /sys/class/net/%s/qmi/raw_ip", ifname);
  33. mode[0] = 'Y';
  34. write(fd, mode, 2);
  35. mode_change = 1;
  36. if_link_up(ifname);
  37. }
  38. close(fd);
  39. return mode_change;
  40. }
  41. static void ql_set_driver_link_state(PROFILE_T *profile, int link_state)
  42. {
  43. char link_file[128];
  44. int fd;
  45. int new_state = 0;
  46. snprintf(link_file, sizeof(link_file), "/sys/class/net/%s/link_state", profile->usbnet_adapter);
  47. fd = open(link_file, O_RDWR | O_NONBLOCK | O_NOCTTY);
  48. if (fd == -1)
  49. {
  50. if (errno != ENOENT)
  51. dbg_time("Fail to access %s, errno: %d (%s)", link_file, errno, strerror(errno));
  52. return;
  53. }
  54. if (profile->qmap_mode <= 1)
  55. new_state = !!link_state;
  56. else
  57. {
  58. //0x80 means link off this pdp
  59. new_state = (link_state ? 0x00 : 0x80) + profile->pdp;
  60. }
  61. snprintf(link_file, sizeof(link_file), "%d\n", new_state);
  62. write(fd, link_file, sizeof(link_file));
  63. if (link_state == 0 && profile->qmap_mode > 1)
  64. {
  65. size_t rc;
  66. lseek(fd, 0, SEEK_SET);
  67. rc = read(fd, link_file, sizeof(link_file));
  68. if (rc > 1 && (!strcasecmp(link_file, "0\n") || !strcasecmp(link_file, "0x0\n")))
  69. {
  70. if_link_down(profile->usbnet_adapter);
  71. }
  72. }
  73. close(fd);
  74. }
  75. void udhcpc_start(PROFILE_T *profile)
  76. {
  77. char *ifname = profile->usbnet_adapter;
  78. ql_set_driver_link_state(profile, 1);
  79. ql_raw_ip_mode_check(ifname);
  80. if (profile->qmapnet_adapter)
  81. {
  82. ifname = profile->qmapnet_adapter;
  83. }
  84. if (profile->rawIP && profile->ipv4.Address && profile->ipv4.Mtu)
  85. {
  86. if_set_mtu(ifname, (profile->ipv4.Mtu));
  87. }
  88. if (strcmp(ifname, profile->usbnet_adapter))
  89. {
  90. if_link_up(profile->usbnet_adapter);
  91. }
  92. if_link_up(ifname);
  93. #if 1 //for bridge mode, only one public IP, so do udhcpc manually
  94. if (ql_bridge_mode_detect(profile))
  95. {
  96. return;
  97. }
  98. #endif
  99. // if use DHCP(should make with ${DHCP} src files)
  100. // do_dhcp(ifname);
  101. // return 0;
  102. /* IPv4 Addr Info */
  103. if (profile->ipv4.Address)
  104. {
  105. dbg_time("IPv4 MTU: %d", profile->ipv4.Mtu);
  106. dbg_time("IPv4 Address: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.Address)));
  107. dbg_time("IPv4 Netmask: %d", mask_to_prefix_v4(ntohl(profile->ipv4.SubnetMask)));
  108. dbg_time("IPv4 Gateway: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.Gateway)));
  109. dbg_time("IPv4 DNS1: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.DnsPrimary)));
  110. dbg_time("IPv4 DNS2: %s", ipaddr_to_string_v4(ntohl(profile->ipv4.DnsSecondary)));
  111. if_set_network_v4(ifname, ntohl(profile->ipv4.Address),
  112. mask_to_prefix_v4(profile->ipv4.SubnetMask),
  113. ntohl(profile->ipv4.Gateway),
  114. ntohl(profile->ipv4.DnsPrimary),
  115. ntohl(profile->ipv4.DnsSecondary));
  116. }
  117. if (profile->ipv6.Address[0] && profile->ipv6.PrefixLengthIPAddr)
  118. {
  119. //module do not support DHCPv6, only support 'Router Solicit'
  120. //and it seem if enable /proc/sys/net/ipv6/conf/all/forwarding, Kernel do not send RS
  121. const char *forward_file = "/proc/sys/net/ipv6/conf/all/forwarding";
  122. int forward_fd = open(forward_file, O_RDONLY);
  123. if (forward_fd > 0)
  124. {
  125. char forward_state[2];
  126. read(forward_fd, forward_state, 2);
  127. if (forward_state[0] == '1')
  128. {
  129. dbg_time("%s enabled, kernel maybe donot send 'Router Solicit'", forward_file);
  130. }
  131. close(forward_fd);
  132. }
  133. dbg_time("IPv6 MTU: %d", profile->ipv6.Mtu);
  134. dbg_time("IPv6 Address: %s", ipaddr_to_string_v6(profile->ipv6.Address));
  135. dbg_time("IPv6 Netmask: %d", profile->ipv6.PrefixLengthIPAddr);
  136. dbg_time("IPv6 Gateway: %s", ipaddr_to_string_v6(profile->ipv6.Gateway));
  137. dbg_time("IPv6 DNS1: %s", ipaddr_to_string_v6(profile->ipv6.DnsPrimary));
  138. dbg_time("IPv6 DNS2: %s", ipaddr_to_string_v6(profile->ipv6.DnsSecondary));
  139. if_set_network_v6(ifname, profile->ipv6.Address, profile->ipv6.PrefixLengthIPAddr,
  140. profile->ipv6.Gateway, profile->ipv6.DnsPrimary, profile->ipv6.DnsSecondary);
  141. }
  142. }
  143. void udhcpc_stop(PROFILE_T *profile)
  144. {
  145. char *ifname = profile->usbnet_adapter;
  146. ql_set_driver_link_state(profile, 0);
  147. if (profile->qmapnet_adapter)
  148. {
  149. ifname = profile->qmapnet_adapter;
  150. }
  151. if_link_down(ifname);
  152. if_flush_v4_addr(ifname);
  153. if_flush_v6_addr(ifname);
  154. }