pdesc.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /*
  2. * pdesc.c
  3. * ptunnel is licensed under the BSD license:
  4. *
  5. * Copyright (c) 2004-2011, Daniel Stoedle <daniels@cs.uit.no>,
  6. * Yellow Lemon Software. All rights reserved.
  7. *
  8. * Copyright (c) 2017-2019, Toni Uhlig <matzeton@googlemail.com>
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. *
  13. * - Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. *
  16. * - Redistributions in binary form must reproduce the above copyright notice,
  17. * this list of conditions and the following disclaimer in the documentation
  18. * and/or other materials provided with the distribution.
  19. *
  20. * - Neither the name of the Yellow Lemon Software nor the names of its
  21. * contributors may be used to endorse or promote products derived from this
  22. * software without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  25. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  28. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  29. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  30. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  31. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  32. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  33. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  34. * POSSIBILITY OF SUCH DAMAGE.
  35. *
  36. * Contacting the author:
  37. * You can get in touch with me, Daniel Stødle (that's the Norwegian letter oe,
  38. * in case your text editor didn't realize), here: <daniels@cs.uit.no>
  39. *
  40. * The official ptunnel website is here:
  41. * <http://www.cs.uit.no/~daniels/PingTunnel/>
  42. *
  43. * Note that the source code is best viewed with tabs set to 4 spaces.
  44. */
  45. #include <stdlib.h>
  46. #include <sys/time.h>
  47. #include <assert.h>
  48. #include "pdesc.h"
  49. #include "options.h"
  50. #include "utils.h"
  51. #include "ptunnel.h"
  52. /* create_and_insert_proxy_desc: Creates a new proxy descriptor, linking it into
  53. * the descriptor chain. If the sock argument is 0, the function will establish
  54. * a TCP connection to the ip and port given by dst_ip, dst_port.
  55. */
  56. proxy_desc_t *create_and_insert_proxy_desc(uint16_t id_no, uint16_t icmp_id,
  57. int sock, struct sockaddr_in *addr,
  58. uint32_t dst_ip, uint32_t dst_port,
  59. uint32_t init_state, enum pkt_flag type) {
  60. proxy_desc_t *cur;
  61. pthread_mutex_lock(&chain_lock);
  62. if (num_tunnels >= opts.max_tunnels) {
  63. pt_log(kLog_info, "Discarding incoming connection - too many tunnels! Maximum count is %u (adjust with the -m switch).\n", opts.max_tunnels);
  64. if (sock)
  65. close(sock);
  66. pthread_mutex_unlock(&chain_lock);
  67. return 0;
  68. }
  69. num_tunnels++;
  70. pthread_mutex_unlock(&chain_lock);
  71. pt_log(kLog_debug, "Adding proxy desc to run loop. Type is %s. Will create socket: %s\n", (type == kUser_flag ? "user" : "proxy"), (sock ? "No" : "Yes"));
  72. cur = (proxy_desc_t *) calloc(1, sizeof(proxy_desc_t));
  73. cur->id_no = id_no;
  74. cur->dest_addr = *addr;
  75. cur->dst_ip = dst_ip;
  76. cur->dst_port = dst_port;
  77. cur->icmp_id = icmp_id;
  78. if (!sock) {
  79. cur->sock = socket(AF_INET, SOCK_STREAM, 0);
  80. memset(addr, 0, sizeof(struct sockaddr_in));
  81. addr->sin_port = htons((uint16_t)dst_port);
  82. addr->sin_addr.s_addr = dst_ip;
  83. addr->sin_family = AF_INET;
  84. /* Let's just assume success, shall we? */
  85. if (cur->sock >= 0 &&
  86. connect(cur->sock, (struct sockaddr*)addr, sizeof(struct sockaddr_in)) < 0)
  87. {
  88. pt_log(kLog_error, "Connect to %s:%d failed: %s\n", inet_ntoa(*(struct in_addr*)&addr->sin_addr.s_addr) , ntohs(addr->sin_port), strerror(errno));
  89. }
  90. } else {
  91. cur->sock = sock;
  92. }
  93. cur->state = init_state;
  94. cur->type_flag = type;
  95. if (cur->type_flag == kUser_flag) {
  96. cur->pkt_type = kICMP_echo_request;
  97. } else {
  98. cur->pkt_type = (opts.unprivileged ? kICMP_echo_request : kICMP_echo_reply);
  99. }
  100. cur->buf = (char *) malloc(icmp_receive_buf_len);
  101. cur->last_activity = time_as_double();
  102. cur->authenticated = 0;
  103. pthread_mutex_lock(&chain_lock);
  104. cur->next = chain;
  105. chain = cur;
  106. pthread_mutex_unlock(&chain_lock);
  107. cur->xfer.bytes_in = 0.0;
  108. cur->xfer.bytes_out = 0.0;
  109. cur->window_size = kPing_window_size;
  110. cur->ack_interval = 1.0;
  111. cur->resend_interval = 1.5;
  112. cur->send_ring = (icmp_desc_t *) calloc(cur->window_size, sizeof(icmp_desc_t));
  113. cur->recv_ring = (forward_desc_t **) calloc(cur->window_size, sizeof(forward_desc_t *));
  114. return cur;
  115. }
  116. /* remove_proxy_desc: Removes the given proxy desc, freeing its resources.
  117. * Assumes that we hold the chain_lock.
  118. */
  119. void remove_proxy_desc(proxy_desc_t *cur, proxy_desc_t *prev) {
  120. struct timeval tt;
  121. pt_log(kLog_debug, "Removing proxy descriptor.\n");
  122. /* Get a timestamp, for making an entry in the seq_expiry_tbl */
  123. gettimeofday(&tt, 0);
  124. seq_expiry_tbl[cur->id_no] = tt.tv_sec+(2*kAutomatic_close_timeout);
  125. /* Free resources associated with connection */
  126. if (cur->buf)
  127. free(cur->buf);
  128. cur->buf = 0;
  129. remove_proxy_desc_rings(cur);
  130. close(cur->sock);
  131. cur->sock = 0;
  132. /* Keep list up-to-date */
  133. if (prev)
  134. prev->next = cur->next;
  135. else
  136. chain = cur->next;
  137. if (cur->challenge)
  138. free(cur->challenge);
  139. free(cur);
  140. num_tunnels--;
  141. }
  142. void remove_proxy_desc_rings(proxy_desc_t *cur) {
  143. int i;
  144. for (i=0;i<cur->window_size;i++) {
  145. if (cur->send_ring[i].pkt)
  146. free(cur->send_ring[i].pkt);
  147. cur->send_ring[i].pkt = 0;
  148. if (cur->recv_ring[i])
  149. free(cur->recv_ring[i]);
  150. cur->recv_ring[i] = 0;
  151. }
  152. free(cur->send_ring);
  153. free(cur->recv_ring);
  154. cur->recv_idx = 0;
  155. cur->recv_xfer_idx = 0;
  156. cur->send_idx = 0;
  157. cur->send_first_ack = 0;
  158. cur->recv_wait_send = 0;
  159. cur->send_wait_ack = 0;
  160. cur->next_resend_start = 0;
  161. }
  162. forward_desc_t* create_fwd_desc(uint16_t seq_no, uint32_t data_len, char *data) {
  163. forward_desc_t *fwd_desc;
  164. fwd_desc = (forward_desc_t *) malloc(sizeof(forward_desc_t)+data_len);
  165. fwd_desc->seq_no = seq_no;
  166. fwd_desc->length = data_len;
  167. fwd_desc->remaining = data_len;
  168. if (data_len > 0)
  169. memcpy(fwd_desc->data, data, data_len);
  170. return fwd_desc;
  171. }
  172. /* queue_packet:
  173. * Creates an ICMP packet descriptor, and sends it. The packet descriptor is added
  174. * to the given send ring, for potential resends later on.
  175. */
  176. int queue_packet(int sock_fd, proxy_desc_t *cur, char *buf, size_t bufsiz,
  177. uint32_t dest_ip, uint32_t dest_port, uint32_t state)
  178. {
  179. int pkt_len = sizeof(icmp_echo_packet_t) +
  180. sizeof(ping_tunnel_pkt_t) + bufsiz;
  181. int err = 0;
  182. icmp_echo_packet_t *pkt = 0;
  183. ping_tunnel_pkt_t *pt_pkt = 0;
  184. uint16_t ack_val;
  185. uint8_t * icmp_chksm_ptr;
  186. assert(sock_fd >= 0);
  187. assert(cur);
  188. if (sock_fd < 0 || !cur)
  189. return -1;
  190. ack_val = cur->next_remote_seq - 1;
  191. if (pkt_len % 2)
  192. pkt_len++;
  193. pkt = (icmp_echo_packet_t *) calloc(1, pkt_len);
  194. /* ICMP Echo request or reply */
  195. pkt->type = cur->pkt_type;
  196. /* Must be zero (non-zero requires root) */
  197. pkt->code = 0;
  198. pkt->identifier = htons(cur->icmp_id);
  199. pkt->seq = htons(cur->ping_seq);
  200. pkt->checksum = 0;
  201. cur->ping_seq++;
  202. /* Add our information */
  203. pt_pkt = (ping_tunnel_pkt_t*)pkt->data;
  204. pt_pkt->magic = htonl(opts.magic);
  205. pt_pkt->dst_ip = dest_ip;
  206. pt_pkt->dst_port = htonl(dest_port);
  207. pt_pkt->ack = htonl(ack_val);
  208. pt_pkt->data_len = htonl(bufsiz);
  209. pt_pkt->state = htonl(state);
  210. pt_pkt->seq_no = htons(cur->my_seq);
  211. pt_pkt->id_no = htons(cur->id_no);
  212. /* Copy user data */
  213. if (buf && bufsiz > 0)
  214. memcpy(pt_pkt->data, buf, bufsiz);
  215. icmp_chksm_ptr = (uint8_t*)pkt;
  216. pkt->checksum = htons(calc_icmp_checksum((uint16_t*)icmp_chksm_ptr, pkt_len));
  217. /* Send it! */
  218. pt_log(kLog_sendrecv, "Send: %4d [%4d] bytes "
  219. "[id = 0x%04X] [seq = %d] "
  220. "[seq_no = %d] [type = %s] "
  221. "[ack = %d] [icmp = %d] "
  222. "[user = %s]\n",
  223. pkt_len, bufsiz,
  224. cur->icmp_id, cur->ping_seq,
  225. cur->my_seq, state_name[state & (~kFlag_mask)],
  226. ack_val, cur->pkt_type,
  227. ((state & kUser_flag) == kUser_flag ? "yes" : "no"));
  228. log_sendrecv_hexstr("SEND ICMP", pkt, sizeof(*pkt));
  229. log_sendrecv_hexstr("SEND PTNG", pt_pkt, sizeof(*pt_pkt));
  230. if (pkt_len - (pt_pkt->data - (char *)pkt) > 0) {
  231. log_sendrecv_hexstr("SEND PAYL", pt_pkt->data, pkt_len - (pt_pkt->data - (char *)pkt));
  232. }
  233. err = sendto(sock_fd, (const void*)pkt, pkt_len, 0,
  234. (struct sockaddr*)&cur->dest_addr, sizeof(struct sockaddr));
  235. if (err < 0) {
  236. pt_log(kLog_error, "Failed to send ICMP packet: %s\n", strerror(errno));
  237. free(pkt);
  238. return -1;
  239. }
  240. else if (err != pkt_len)
  241. pt_log(kLog_error, "WARNING WARNING, didn't send entire packet\n");
  242. /* Update sequence no's and so on */
  243. cur->send_ring[cur->send_idx].pkt = pkt;
  244. cur->send_ring[cur->send_idx].pkt_len = pkt_len;
  245. cur->send_ring[cur->send_idx].last_resend = time_as_double();
  246. cur->send_ring[cur->send_idx].seq_no = cur->my_seq;
  247. cur->send_ring[cur->send_idx].icmp_id = cur->icmp_id;
  248. cur->my_seq++;
  249. if (!cur->send_ring[cur->send_first_ack].pkt)
  250. cur->send_first_ack = cur->send_idx;
  251. cur->send_wait_ack++;
  252. cur->send_idx++;
  253. if (cur->send_idx >= cur->window_size)
  254. cur->send_idx = 0;
  255. return 0;
  256. }
  257. /* send_packets:
  258. * Examines the passed-in ring, and forwards data in it over TCP.
  259. */
  260. uint32_t send_packets(forward_desc_t *ring[], int *xfer_idx, int *await_send, int *sock, uint16_t window_size) {
  261. forward_desc_t *fwd_desc;
  262. int bytes, total = 0;
  263. while (*await_send > 0) {
  264. fwd_desc = ring[*xfer_idx];
  265. if (!fwd_desc)/* We haven't got this packet yet.. */
  266. break;
  267. if (fwd_desc->length > 0) {
  268. bytes = send(*sock, &fwd_desc->data[fwd_desc->length - fwd_desc->remaining],
  269. fwd_desc->remaining, 0);
  270. if (bytes < 0) {
  271. printf("Weirdness.\n");
  272. /* TODO: send close stuff */
  273. close(*sock);
  274. *sock = 0;
  275. break;
  276. }
  277. fwd_desc->remaining -= bytes;
  278. total += bytes;
  279. }
  280. if (!fwd_desc->remaining) {
  281. ring[*xfer_idx] = 0;
  282. free(fwd_desc);
  283. (*xfer_idx)++;
  284. (*await_send)--;
  285. if (*xfer_idx >= window_size)
  286. *xfer_idx = 0;
  287. }
  288. else
  289. break;
  290. }
  291. return total;
  292. }