Introduce the ability to send arbitrary initial tcp timestamps that are not
tied directly to jiffies.  The basic conecpt is every tcp_request_sock and
tcp_sock now has a ts_off offset that represents the difference between
tcp_time_stamp and the timestamp we send and expect to
receive.

This has the advantage of not divulging system information (uptime)
depending on the policy chosen for the initial timestamps.

A policy where ts_off is always set to zero should produce no change in
behavior.  The policy implemented is not intended for real use, but just as
a simple example.  A realistic example would probably be similar to the tcp
init sequence generator.

Signed-off-by: Glenn Griffin <[EMAIL PROTECTED]>
---
 include/linux/tcp.h      |    6 ++++++
 include/net/tcp.h        |    2 +-
 net/ipv4/tcp_input.c     |   12 ++++++------
 net/ipv4/tcp_ipv4.c      |    2 +-
 net/ipv4/tcp_minisocks.c |    5 +++--
 net/ipv4/tcp_output.c    |    8 +++++---
 net/ipv6/tcp_ipv6.c      |    2 +-
 7 files changed, 23 insertions(+), 14 deletions(-)

diff --git a/include/linux/tcp.h b/include/linux/tcp.h
index 08027f1..68387dc 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -232,6 +232,7 @@ struct tcp_request_sock {
 #endif
        u32                             rcv_isn;
        u32                             snt_isn;
+       u32                             ts_off;
 };
 
 static inline struct tcp_request_sock *tcp_rsk(const struct request_sock *req)
@@ -311,6 +312,11 @@ struct tcp_sock {
        struct tcp_options_received rx_opt;
 
 /*
+ *     offset of transmitted tcp timestamp from jiffies
+ */
+       u32     ts_off;
+
+/*
  *     Slow start and congestion control (see also Nagle, and Karn & Partridge)
  */
        u32     snd_ssthresh;   /* Slow start size threshold            */
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 7de4ea3..c935de7 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -395,7 +395,7 @@ extern int                  tcp_recvmsg(struct kiocb *iocb, 
struct sock *sk,
 
 extern void                    tcp_parse_options(struct sk_buff *skb,
                                                  struct tcp_options_received 
*opt_rx,
-                                                 int estab);
+                                                 int estab, u32 tsecr_off);
 
 /*
  *     TCP v4 functions exported for the inet6 API
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 19c449f..95fa8dc 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3264,7 +3264,7 @@ uninteresting_ack:
  * the fast version below fails.
  */
 void tcp_parse_options(struct sk_buff *skb, struct tcp_options_received 
*opt_rx,
-                      int estab)
+                      int estab, u32 tsecr_off)
 {
        unsigned char *ptr;
        struct tcphdr *th = tcp_hdr(skb);
@@ -3322,7 +3322,7 @@ void tcp_parse_options(struct sk_buff *skb, struct 
tcp_options_received *opt_rx,
                                     (!estab && sysctl_tcp_timestamps))) {
                                        opt_rx->saw_tstamp = 1;
                                        opt_rx->rcv_tsval = 
ntohl(get_unaligned((__be32 *)ptr));
-                                       opt_rx->rcv_tsecr = 
ntohl(get_unaligned((__be32 *)(ptr+4)));
+                                       opt_rx->rcv_tsecr = 
ntohl(get_unaligned((__be32 *)(ptr+4))) - tsecr_off;
                                }
                                break;
                        case TCPOPT_SACK_PERM:
@@ -3374,11 +3374,11 @@ static int tcp_fast_parse_options(struct sk_buff *skb, 
struct tcphdr *th,
                        ++ptr;
                        tp->rx_opt.rcv_tsval = ntohl(*ptr);
                        ++ptr;
-                       tp->rx_opt.rcv_tsecr = ntohl(*ptr);
+                       tp->rx_opt.rcv_tsecr = ntohl(*ptr) - tp->ts_off;
                        return 1;
                }
        }
-       tcp_parse_options(skb, &tp->rx_opt, 1);
+       tcp_parse_options(skb, &tp->rx_opt, 1, tp->ts_off);
        return 1;
 }
 
@@ -4615,7 +4615,7 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff 
*skb,
                        ++ptr;
                        tp->rx_opt.rcv_tsval = ntohl(*ptr);
                        ++ptr;
-                       tp->rx_opt.rcv_tsecr = ntohl(*ptr);
+                       tp->rx_opt.rcv_tsecr = ntohl(*ptr) - tp->ts_off;
 
                        /* If PAWS failed, check it more carefully in slow path 
*/
                        if ((s32)(tp->rx_opt.rcv_tsval - tp->rx_opt.ts_recent) 
< 0)
@@ -4824,7 +4824,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, 
struct sk_buff *skb,
        struct inet_connection_sock *icsk = inet_csk(sk);
        int saved_clamp = tp->rx_opt.mss_clamp;
 
-       tcp_parse_options(skb, &tp->rx_opt, 0);
+       tcp_parse_options(skb, &tp->rx_opt, 0, tp->ts_off);
 
        if (th->ack) {
                /* rfc793:
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 63414ea..267eda9 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1295,7 +1295,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff 
*skb)
        tmp_opt.mss_clamp = 536;
        tmp_opt.user_mss  = tcp_sk(sk)->rx_opt.user_mss;
 
-       tcp_parse_options(skb, &tmp_opt, 0);
+       tcp_parse_options(skb, &tmp_opt, 0, 0);
 
        if (want_cookie) {
                tcp_clear_options(&tmp_opt);
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index b61b768..648f84e 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -102,7 +102,7 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, 
struct sk_buff *skb,
 
        tmp_opt.saw_tstamp = 0;
        if (th->doff > (sizeof(*th) >> 2) && tcptw->tw_ts_recent_stamp) {
-               tcp_parse_options(skb, &tmp_opt, 0);
+               tcp_parse_options(skb, &tmp_opt, 0, 0);
 
                if (tmp_opt.saw_tstamp) {
                        tmp_opt.ts_recent       = tcptw->tw_ts_recent;
@@ -442,6 +442,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, 
struct request_sock *req,
                        inet_csk_reset_keepalive_timer(newsk,
                                                       
keepalive_time_when(newtp));
 
+               newtp->ts_off = treq->ts_off;
                newtp->rx_opt.tstamp_ok = ireq->tstamp_ok;
                if ((newtp->rx_opt.sack_ok = ireq->sack_ok) != 0) {
                        if (sysctl_tcp_fack)
@@ -502,7 +503,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff 
*skb,
 
        tmp_opt.saw_tstamp = 0;
        if (th->doff > (sizeof(struct tcphdr)>>2)) {
-               tcp_parse_options(skb, &tmp_opt, 0);
+               tcp_parse_options(skb, &tmp_opt, 0, tcp_rsk(req)->ts_off);
 
                if (tmp_opt.saw_tstamp) {
                        tmp_opt.ts_recent = req->ts_recent;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index ed750f9..81f1383 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -583,7 +583,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff 
*skb, int clone_it,
                                      (sysctl_flags & SYSCTL_FLAG_SACK),
                                      (sysctl_flags & SYSCTL_FLAG_WSCALE),
                                      tp->rx_opt.rcv_wscale,
-                                     tcb->when,
+                                     tcb->when + tp->ts_off,
                                      tp->rx_opt.ts_recent,
 
 #ifdef CONFIG_TCP_MD5SIG
@@ -592,7 +592,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff 
*skb, int clone_it,
                                      NULL);
        } else {
                tcp_build_and_update_options((__be32 *)(th + 1),
-                                            tp, tcb->when,
+                                            tp, tcb->when + tp->ts_off,
 #ifdef CONFIG_TCP_MD5SIG
                                             md5 ? &md5_hash_location :
 #endif
@@ -2227,9 +2227,10 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct 
dst_entry *dst,
        th->window = htons(min(req->rcv_wnd, 65535U));
 
        TCP_SKB_CB(skb)->when = tcp_time_stamp;
+       tcp_rsk(req)->ts_off = 1000 - TCP_SKB_CB(skb)->when;
        tcp_syn_build_options((__be32 *)(th + 1), dst_metric(dst, RTAX_ADVMSS), 
ireq->tstamp_ok,
                              ireq->sack_ok, ireq->wscale_ok, ireq->rcv_wscale,
-                             TCP_SKB_CB(skb)->when,
+                             TCP_SKB_CB(skb)->when + tcp_rsk(req)->ts_off,
                              req->ts_recent,
                              (
 #ifdef CONFIG_TCP_MD5SIG
@@ -2335,6 +2336,7 @@ int tcp_connect(struct sock *sk)
 
        /* Send it off. */
        TCP_SKB_CB(buff)->when = tcp_time_stamp;
+       tp->ts_off = 2000 - TCP_SKB_CB(buff)->when;
        tp->retrans_stamp = TCP_SKB_CB(buff)->when;
        skb_header_release(buff);
        __tcp_add_write_queue_tail(sk, buff);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 12750f2..896ebd0 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1264,7 +1264,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct 
sk_buff *skb)
        tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - 
sizeof(struct ipv6hdr);
        tmp_opt.user_mss = tp->rx_opt.user_mss;
 
-       tcp_parse_options(skb, &tmp_opt, 0);
+       tcp_parse_options(skb, &tmp_opt, 0, 0);
 
        tmp_opt.tstamp_ok = tmp_opt.saw_tstamp;
        tcp_openreq_init(req, &tmp_opt, skb);
-- 
1.5.4

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to