1
0

tun_dev.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * tun.cpp
  3. *
  4. * Created on: Oct 26, 2017
  5. * Author: root
  6. */
  7. #include "tun_dev.h"
  8. my_time_t last_keep_alive_time = 0;
  9. int get_tun_fd(char *dev_name) {
  10. int tun_fd = open("/dev/net/tun", O_RDWR);
  11. if (tun_fd < 0) {
  12. mylog(log_fatal, "open /dev/net/tun failed");
  13. myexit(-1);
  14. }
  15. struct ifreq ifr;
  16. memset(&ifr, 0, sizeof(ifr));
  17. ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
  18. strncpy(ifr.ifr_name, dev_name, IFNAMSIZ);
  19. if (ioctl(tun_fd, TUNSETIFF, (void *)&ifr) != 0) {
  20. mylog(log_fatal, "open /dev/net/tun failed");
  21. myexit(-1);
  22. }
  23. if (persist_tun == 1) {
  24. if (ioctl(tun_fd, TUNSETPERSIST, 1) != 0) {
  25. mylog(log_warn, "failed to set tun persistent");
  26. }
  27. }
  28. return tun_fd;
  29. }
  30. int set_tun(char *if_name, u32_t local_ip, u32_t remote_ip, int mtu) {
  31. if (manual_set_tun) return 0;
  32. // printf("i m here1\n");
  33. struct ifreq ifr;
  34. struct sockaddr_in sai;
  35. memset(&ifr, 0, sizeof(ifr));
  36. memset(&sai, 0, sizeof(struct sockaddr));
  37. int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  38. strncpy(ifr.ifr_name, if_name, IFNAMSIZ);
  39. sai.sin_family = AF_INET;
  40. sai.sin_port = 0;
  41. sai.sin_addr.s_addr = local_ip;
  42. memcpy(&ifr.ifr_addr, &sai, sizeof(struct sockaddr));
  43. assert(ioctl(sockfd, SIOCSIFADDR, &ifr) == 0); // set source ip
  44. sai.sin_addr.s_addr = remote_ip;
  45. memcpy(&ifr.ifr_addr, &sai, sizeof(struct sockaddr));
  46. assert(ioctl(sockfd, SIOCSIFDSTADDR, &ifr) == 0); // set dest ip
  47. ifr.ifr_mtu = mtu;
  48. assert(ioctl(sockfd, SIOCSIFMTU, &ifr) == 0); // set mtu
  49. assert(ioctl(sockfd, SIOCGIFFLAGS, &ifr) == 0);
  50. // ifr.ifr_flags |= ( IFF_UP|IFF_POINTOPOINT|IFF_RUNNING|IFF_NOARP|IFF_MULTICAST );
  51. ifr.ifr_flags = (IFF_UP | IFF_POINTOPOINT | IFF_RUNNING | IFF_NOARP | IFF_MULTICAST); // set interface flags
  52. assert(ioctl(sockfd, SIOCSIFFLAGS, &ifr) == 0);
  53. // printf("i m here2\n");
  54. return 0;
  55. }
  56. int put_header(char header, char *data, int &len) {
  57. assert(len >= 0);
  58. data[len] = header;
  59. len += 1;
  60. return 0;
  61. }
  62. int get_header(char &header, char *data, int &len) {
  63. assert(len >= 0);
  64. if (len < 1) return -1;
  65. len -= 1;
  66. header = data[len];
  67. return 0;
  68. }
  69. int from_normal_to_fec2(conn_info_t &conn_info, dest_t &dest, char *data, int len, char header) {
  70. int out_n;
  71. char **out_arr;
  72. int *out_len;
  73. my_time_t *out_delay;
  74. from_normal_to_fec(conn_info, data, len, out_n, out_arr, out_len, out_delay);
  75. for (int i = 0; i < out_n; i++) {
  76. char tmp_buf[buf_len];
  77. int tmp_len = out_len[i];
  78. memcpy(tmp_buf, out_arr[i], out_len[i]);
  79. put_header(header, tmp_buf, tmp_len);
  80. delay_send(out_delay[i], dest, tmp_buf, tmp_len); // this is slow but safer.just use this one
  81. // put_header(header,out_arr[i],out_len[i]);//modify in place
  82. // delay_send(out_delay[i],dest,out_arr[i],out_len[i]);//warning this is currently okay,but if you modified fec encoder,you may have to use the above code
  83. }
  84. return 0;
  85. }
  86. int from_fec_to_normal2(conn_info_t &conn_info, dest_t &dest, char *data, int len) {
  87. int out_n;
  88. char **out_arr;
  89. int *out_len;
  90. my_time_t *out_delay;
  91. from_fec_to_normal(conn_info, data, len, out_n, out_arr, out_len, out_delay);
  92. for (int i = 0; i < out_n; i++) {
  93. #if 0
  94. if (program_mode == server_mode) {
  95. char *tmp_data = out_arr[i];
  96. int tmp_len = out_len[i];
  97. iphdr *iph;
  98. iph = (struct iphdr *)tmp_data;
  99. if (tmp_len >= int(sizeof(iphdr)) && iph->version == 4) {
  100. u32_t dest_ip = iph->daddr;
  101. // printf("%s\n",my_ntoa(dest_ip));
  102. if ((ntohl(sub_net_uint32) & 0xFFFFFF00) != (ntohl(dest_ip) & 0xFFFFFF00)) {
  103. string sub = my_ntoa(dest_ip);
  104. string dst = my_ntoa(htonl(ntohl(sub_net_uint32) & 0xFFFFFF00));
  105. mylog(log_warn, "[restriction]packet's dest ip [%s] not in subnet [%s],dropped, maybe you need to compile an un-restricted server\n", sub.c_str(), dst.c_str());
  106. continue;
  107. }
  108. }
  109. }
  110. #endif
  111. delay_send(out_delay[i], dest, out_arr[i], out_len[i]);
  112. }
  113. return 0;
  114. }
  115. int do_mssfix(char *s, int len) // currently only for ipv4
  116. {
  117. if (mssfix == 0) {
  118. return 0;
  119. }
  120. if (len < int(sizeof(iphdr))) {
  121. mylog(log_debug, "packet from tun len=%d <20\n", len);
  122. return -1;
  123. }
  124. iphdr *iph;
  125. iph = (struct iphdr *)s;
  126. if (iph->version != 4) {
  127. // mylog(log_trace,"not ipv4");
  128. return 0;
  129. }
  130. if (iph->protocol != IPPROTO_TCP) {
  131. // mylog(log_trace,"not tcp");
  132. return 0;
  133. }
  134. int ip_len = ntohs(iph->tot_len);
  135. int ip_hdr_len = iph->ihl * 4;
  136. if (len < ip_hdr_len) {
  137. mylog(log_debug, "len<ip_hdr_len,%d %d\n", len, ip_hdr_len);
  138. return -1;
  139. }
  140. if (len < ip_len) {
  141. mylog(log_debug, "len<ip_len,%d %d\n", len, ip_len);
  142. return -1;
  143. }
  144. if (ip_hdr_len > ip_len) {
  145. mylog(log_debug, "ip_hdr_len<ip_len,%d %d\n", ip_hdr_len, ip_len);
  146. return -1;
  147. }
  148. if ((ntohs(iph->frag_off) & (short)(0x1FFF)) != 0) {
  149. // not first segment
  150. // printf("line=%d %x %x \n",__LINE__,(u32_t)ntohs(iph->frag_off),u32_t( ntohs(iph->frag_off) &0xFFF8));
  151. return 0;
  152. }
  153. if ((ntohs(iph->frag_off) & (short)(0x80FF)) != 0) {
  154. // not whole segment
  155. // printf("line=%d \n",__LINE__);
  156. return 0;
  157. }
  158. char *tcp_begin = s + ip_hdr_len;
  159. int tcp_len = ip_len - ip_hdr_len;
  160. if (tcp_len < 20) {
  161. mylog(log_debug, "tcp_len<20,%d\n", tcp_len);
  162. return -1;
  163. }
  164. tcphdr *tcph = (struct tcphdr *)tcp_begin;
  165. if (int(tcph->syn) == 0) // fast fail
  166. {
  167. mylog(log_trace, "tcph->syn==0\n");
  168. return 0;
  169. }
  170. int tcp_hdr_len = tcph->doff * 4;
  171. if (tcp_len < tcp_hdr_len) {
  172. mylog(log_debug, "tcp_len <tcp_hdr_len, %d %d\n", tcp_len, tcp_hdr_len);
  173. return -1;
  174. }
  175. /*
  176. if(tcp_hdr_len==20)
  177. {
  178. //printf("line=%d\n",__LINE__);
  179. mylog(log_trace,"no tcp option\n");
  180. return 0;
  181. }*/
  182. char *ptr = tcp_begin + 20;
  183. char *option_end = tcp_begin + tcp_hdr_len;
  184. while (ptr < option_end) {
  185. if (*ptr == 0) {
  186. return 0;
  187. } else if (*ptr == 1) {
  188. ptr++;
  189. } else if (*ptr == 2) {
  190. if (ptr + 1 >= option_end) {
  191. mylog(log_debug, "invaild option ptr+1==option_end,for mss\n");
  192. return -1;
  193. }
  194. if (*(ptr + 1) != 4) {
  195. mylog(log_debug, "invaild mss len\n");
  196. return -1;
  197. }
  198. if (ptr + 3 >= option_end) {
  199. mylog(log_debug, "ptr+4>option_end for mss\n");
  200. return -1;
  201. }
  202. int mss = read_u16(ptr + 2); // uint8_t(ptr[2])*256+uint8_t(ptr[3]);
  203. int new_mss = mss;
  204. if (new_mss > ::mssfix - 40 - 10) // minus extra 10 for safe
  205. {
  206. new_mss = ::mssfix - 40 - 10;
  207. }
  208. write_u16(ptr + 2, (unsigned short)new_mss);
  209. pseudo_header psh;
  210. psh.source_address = iph->saddr;
  211. psh.dest_address = iph->daddr;
  212. psh.placeholder = 0;
  213. psh.protocol = iph->protocol;
  214. psh.tcp_length = htons(tcp_len);
  215. tcph->check = 0;
  216. tcph->check = tcp_csum(psh, (unsigned short *)tcph, tcp_len);
  217. mylog(log_trace, "mss=%d syn=%d ack=%d, changed mss to %d \n", mss, (int)tcph->syn, (int)tcph->ack, new_mss);
  218. // printf("test=%x\n",u32_t(1));
  219. // printf("frag=%x\n",u32_t( ntohs(iph->frag_off) ));
  220. return 0;
  221. } else {
  222. if (ptr + 1 >= option_end) {
  223. mylog(log_debug, "invaild option ptr+1==option_end\n");
  224. return -1;
  225. } else {
  226. int len = (unsigned char)*(ptr + 1);
  227. if (len <= 1) {
  228. mylog(log_debug, "invaild option len %d\n", len);
  229. return -1;
  230. }
  231. ptr += len;
  232. }
  233. }
  234. }
  235. return 0;
  236. }
  237. int do_keep_alive(dest_t &dest) {
  238. if (get_current_time() - last_keep_alive_time > u64_t(keep_alive_interval)) {
  239. last_keep_alive_time = get_current_time();
  240. char data[buf_len];
  241. int len;
  242. data[0] = header_keep_alive;
  243. len = 1;
  244. assert(dest.cook == 1);
  245. // do_cook(data,len);
  246. delay_send(0, dest, data, len);
  247. }
  248. return 0;
  249. }