aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/options.c15
-rw-r--r--src/options.h1
-rw-r--r--src/pkt.c5
-rw-r--r--src/ptunnel.c10
4 files changed, 28 insertions, 3 deletions
diff --git a/src/options.c b/src/options.c
index 85b8a9c..66c44a6 100644
--- a/src/options.c
+++ b/src/options.c
@@ -144,7 +144,7 @@ static const struct option_usage usage[] = {
/** --ack-interval */
{"milliseconds", 0, OPT_DEC32, {.unum = 1000},
"Tune the explicit acknowledgement interval (in milliseconds)\n"
- "Decreasing the acknowlegement interval can improve NAT stability.\n"
+ "Decreasing the acknowledgement interval can improve NAT stability.\n"
},
/** --resend-interval */
{"milliseconds", 0, OPT_DEC32, {.unum = 1500},
@@ -157,6 +157,11 @@ static const struct option_usage usage[] = {
"Decreasing the payload size can avoid corruption of large packets.\n"
"Increasing the payload size can compensate for out-of-order delivery.\n"
},
+ /** --empty-pings */
+ {"count", 0, OPT_DEC32, {.unum = 0},
+ "Tune the number of empty pings to send with each explicit acknowledgement.\n"
+ "Empty pings can compensate for ICMP sequence number inspection.\n"
+ },
/** --daemon */
{"pidfile", 0, OPT_STR, {.str = "/run/ptunnel.pid"},
#ifdef WIN32
@@ -223,6 +228,7 @@ static struct option long_options[] = {
{"ack-interval", required_argument, 0, 'a'},
{"resend-interval", required_argument, 0, 't'},
{"payload-size", required_argument, 0, 'y'},
+ {"empty-pings", required_argument, 0, 'E'},
{"daemon", optional_argument, 0, 'd'},
{"syslog", no_argument, 0, 'S'},
{"user", optional_argument, 0, 'u'},
@@ -409,7 +415,7 @@ int parse_options(int argc, char **argv) {
* since you have to pass long options as '--option=value'. Commonly used
* '--option value' is *NOT* allowed for some libc implementations.
*/
- c = getopt_long(argc, argv, "m:p:l:r::R::c:v:L::o::sP:d::Su::g::C::e::w:a:t:y:h", &long_options[0], &oidx);
+ c = getopt_long(argc, argv, "m:p:l:r::R::c:v:L::o::sP:d::Su::g::C::e::w:a:t:y:E:h", &long_options[0], &oidx);
if (c == -1) break;
switch (c) {
@@ -578,6 +584,11 @@ int parse_options(int argc, char **argv) {
break;
opts.payload_size = atoi(optarg);
break;
+ case 'E':
+ if (!optarg)
+ break;
+ opts.empty_pings = atoi(optarg);
+ break;
case 'h':
print_usage(argv[0]);
exit(EXIT_SUCCESS);
diff --git a/src/options.h b/src/options.h
index b180ef5..7afcfec 100644
--- a/src/options.h
+++ b/src/options.h
@@ -92,6 +92,7 @@ struct options {
uint16_t ack_interval;
uint16_t resend_interval;
uint16_t payload_size;
+ uint16_t empty_pings;
#ifndef WIN32
/** run as daemon if non zero value */
diff --git a/src/pkt.c b/src/pkt.c
index 1d3d1b6..e2fd2a8 100644
--- a/src/pkt.c
+++ b/src/pkt.c
@@ -96,6 +96,7 @@ void handle_packet(char *buf, unsigned bytes, int is_pcap, struct sockaddr_in *a
if (ntohl(pt_pkt->magic) == opts.magic) {
pt_pkt->state = ntohl(pt_pkt->state);
pkt->identifier = ntohs(pkt->identifier);
+ pkt->seq = ntohs(pkt->seq);
pt_pkt->id_no = ntohs(pt_pkt->id_no);
pt_pkt->seq_no = ntohs(pt_pkt->seq_no);
/* Find the relevant connection, if it exists */
@@ -114,8 +115,10 @@ void handle_packet(char *buf, unsigned bytes, int is_pcap, struct sockaddr_in *a
*/
if (cur) {
type_flag = cur->type_flag;
- if (type_flag == (uint32_t)kProxy_flag)
+ if (type_flag == (uint32_t)kProxy_flag) {
cur->icmp_id = pkt->identifier;
+ cur->ping_seq = pkt->seq;
+ }
if (!is_pcap)
cur->xfer.icmp_in++;
}
diff --git a/src/ptunnel.c b/src/ptunnel.c
index 3f12556..640df74 100644
--- a/src/ptunnel.c
+++ b/src/ptunnel.c
@@ -661,12 +661,22 @@ void* pt_proxy(void *args) {
if (cur->last_ack+cur->ack_interval < now && cur->send_wait_ack < cur->window_size &&
cur->remote_ack_val+1 != cur->next_remote_seq)
{
+ idx = cur->send_idx;
cur->last_ack = now;
queue_packet(fwd_sock, cur->pkt_type, 0, 0, cur->id_no, cur->icmp_id,
&cur->my_seq, cur->send_ring, &cur->send_idx, &cur->send_wait_ack,
cur->dst_ip, cur->dst_port, kProto_ack | cur->type_flag,
&cur->dest_addr, cur->next_remote_seq, &cur->send_first_ack, &cur->ping_seq, cur->window_size);
cur->xfer.icmp_ack_out++;
+ if (cur->send_ring[idx].pkt_len > sizeof(icmp_echo_packet_t) && cur->send_ring[idx].pkt->type == 8) {
+ for (uint16_t e = 0; e < opts.empty_pings; e++) {
+ cur->send_ring[idx].pkt->seq = htons(cur->ping_seq);
+ cur->ping_seq++;
+ cur->send_ring[idx].pkt->checksum = htons(calc_icmp_checksum((uint16_t*)cur->send_ring[idx].pkt, sizeof(icmp_echo_packet_t)));
+ sendto(fwd_sock, (const void*)cur->send_ring[idx].pkt, sizeof(icmp_echo_packet_t),
+ 0, (struct sockaddr*)&cur->dest_addr, sizeof(struct sockaddr));
+ }
+ }
}
}
pthread_mutex_unlock(&chain_lock);