aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2005-10-03 16:57:23 -0400
committerDavid S. Miller <davem@davemloft.net>2005-10-03 16:57:23 -0400
commit325ed8239309cb29f10ea58c5a668058ead11479 (patch)
tree77386825b72ac44f4f42a942ef78bd1ff924b351
parentddea7be0ec8d1374f0b483a81566ed56ec9f3905 (diff)
[NET]: Fix packet timestamping.
I've found the problem in general. It affects any 64-bit architecture. The problem occurs when you change the system time. Suppose that when you boot your system clock is forward by a day. This gets recorded down in skb_tv_base. You then wind the clock back by a day. From that point onwards the offset will be negative which essentially overflows the 32-bit variables they're stored in. In fact, why don't we just store the real time stamp in those 32-bit variables? After all, we're not going to overflow for quite a while yet. When we do overflow, we'll need a better solution of course. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/skbuff.h12
-rw-r--r--net/core/skbuff.c5
-rw-r--r--net/ipv4/netfilter/ip_queue.c4
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c4
-rw-r--r--net/ipv6/netfilter/ip6_queue.c4
-rw-r--r--net/netfilter/nfnetlink_log.c4
-rw-r--r--net/netfilter/nfnetlink_queue.c4
-rw-r--r--net/packet/af_packet.c4
8 files changed, 15 insertions, 26 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 2741c0c55e83..466c879f82b8 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -155,8 +155,6 @@ struct skb_shared_info {
155#define SKB_DATAREF_SHIFT 16 155#define SKB_DATAREF_SHIFT 16
156#define SKB_DATAREF_MASK ((1 << SKB_DATAREF_SHIFT) - 1) 156#define SKB_DATAREF_MASK ((1 << SKB_DATAREF_SHIFT) - 1)
157 157
158extern struct timeval skb_tv_base;
159
160struct skb_timeval { 158struct skb_timeval {
161 u32 off_sec; 159 u32 off_sec;
162 u32 off_usec; 160 u32 off_usec;
@@ -175,7 +173,7 @@ enum {
175 * @prev: Previous buffer in list 173 * @prev: Previous buffer in list
176 * @list: List we are on 174 * @list: List we are on
177 * @sk: Socket we are owned by 175 * @sk: Socket we are owned by
178 * @tstamp: Time we arrived stored as offset to skb_tv_base 176 * @tstamp: Time we arrived
179 * @dev: Device we arrived on/are leaving by 177 * @dev: Device we arrived on/are leaving by
180 * @input_dev: Device we arrived on 178 * @input_dev: Device we arrived on
181 * @h: Transport layer header 179 * @h: Transport layer header
@@ -1255,10 +1253,6 @@ static inline void skb_get_timestamp(const struct sk_buff *skb, struct timeval *
1255{ 1253{
1256 stamp->tv_sec = skb->tstamp.off_sec; 1254 stamp->tv_sec = skb->tstamp.off_sec;
1257 stamp->tv_usec = skb->tstamp.off_usec; 1255 stamp->tv_usec = skb->tstamp.off_usec;
1258 if (skb->tstamp.off_sec) {
1259 stamp->tv_sec += skb_tv_base.tv_sec;
1260 stamp->tv_usec += skb_tv_base.tv_usec;
1261 }
1262} 1256}
1263 1257
1264/** 1258/**
@@ -1272,8 +1266,8 @@ static inline void skb_get_timestamp(const struct sk_buff *skb, struct timeval *
1272 */ 1266 */
1273static inline void skb_set_timestamp(struct sk_buff *skb, const struct timeval *stamp) 1267static inline void skb_set_timestamp(struct sk_buff *skb, const struct timeval *stamp)
1274{ 1268{
1275 skb->tstamp.off_sec = stamp->tv_sec - skb_tv_base.tv_sec; 1269 skb->tstamp.off_sec = stamp->tv_sec;
1276 skb->tstamp.off_usec = stamp->tv_usec - skb_tv_base.tv_usec; 1270 skb->tstamp.off_usec = stamp->tv_usec;
1277} 1271}
1278 1272
1279extern void __net_timestamp(struct sk_buff *skb); 1273extern void __net_timestamp(struct sk_buff *skb);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index f80a28785610..0e9431b59fb2 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -71,8 +71,6 @@
71static kmem_cache_t *skbuff_head_cache __read_mostly; 71static kmem_cache_t *skbuff_head_cache __read_mostly;
72static kmem_cache_t *skbuff_fclone_cache __read_mostly; 72static kmem_cache_t *skbuff_fclone_cache __read_mostly;
73 73
74struct timeval __read_mostly skb_tv_base;
75
76/* 74/*
77 * Keep out-of-line to prevent kernel bloat. 75 * Keep out-of-line to prevent kernel bloat.
78 * __builtin_return_address is not used because it is not always 76 * __builtin_return_address is not used because it is not always
@@ -1708,8 +1706,6 @@ void __init skb_init(void)
1708 NULL, NULL); 1706 NULL, NULL);
1709 if (!skbuff_fclone_cache) 1707 if (!skbuff_fclone_cache)
1710 panic("cannot create skbuff cache"); 1708 panic("cannot create skbuff cache");
1711
1712 do_gettimeofday(&skb_tv_base);
1713} 1709}
1714 1710
1715EXPORT_SYMBOL(___pskb_trim); 1711EXPORT_SYMBOL(___pskb_trim);
@@ -1743,4 +1739,3 @@ EXPORT_SYMBOL(skb_prepare_seq_read);
1743EXPORT_SYMBOL(skb_seq_read); 1739EXPORT_SYMBOL(skb_seq_read);
1744EXPORT_SYMBOL(skb_abort_seq_read); 1740EXPORT_SYMBOL(skb_abort_seq_read);
1745EXPORT_SYMBOL(skb_find_text); 1741EXPORT_SYMBOL(skb_find_text);
1746EXPORT_SYMBOL(skb_tv_base);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index d54f14d926f6..36339eb39e17 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -240,8 +240,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
240 240
241 pmsg->packet_id = (unsigned long )entry; 241 pmsg->packet_id = (unsigned long )entry;
242 pmsg->data_len = data_len; 242 pmsg->data_len = data_len;
243 pmsg->timestamp_sec = skb_tv_base.tv_sec + entry->skb->tstamp.off_sec; 243 pmsg->timestamp_sec = entry->skb->tstamp.off_sec;
244 pmsg->timestamp_usec = skb_tv_base.tv_usec + entry->skb->tstamp.off_usec; 244 pmsg->timestamp_usec = entry->skb->tstamp.off_usec;
245 pmsg->mark = entry->skb->nfmark; 245 pmsg->mark = entry->skb->nfmark;
246 pmsg->hook = entry->info->hook; 246 pmsg->hook = entry->info->hook;
247 pmsg->hw_protocol = entry->skb->protocol; 247 pmsg->hw_protocol = entry->skb->protocol;
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index e2c14f3cb2fc..2883ccd8a91d 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -225,8 +225,8 @@ static void ipt_ulog_packet(unsigned int hooknum,
225 225
226 /* copy hook, prefix, timestamp, payload, etc. */ 226 /* copy hook, prefix, timestamp, payload, etc. */
227 pm->data_len = copy_len; 227 pm->data_len = copy_len;
228 pm->timestamp_sec = skb_tv_base.tv_sec + skb->tstamp.off_sec; 228 pm->timestamp_sec = skb->tstamp.off_sec;
229 pm->timestamp_usec = skb_tv_base.tv_usec + skb->tstamp.off_usec; 229 pm->timestamp_usec = skb->tstamp.off_usec;
230 pm->mark = skb->nfmark; 230 pm->mark = skb->nfmark;
231 pm->hook = hooknum; 231 pm->hook = hooknum;
232 if (prefix != NULL) 232 if (prefix != NULL)
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index aa11cf366efa..5027bbe6415e 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -238,8 +238,8 @@ ipq_build_packet_message(struct ipq_queue_entry *entry, int *errp)
238 238
239 pmsg->packet_id = (unsigned long )entry; 239 pmsg->packet_id = (unsigned long )entry;
240 pmsg->data_len = data_len; 240 pmsg->data_len = data_len;
241 pmsg->timestamp_sec = skb_tv_base.tv_sec + entry->skb->tstamp.off_sec; 241 pmsg->timestamp_sec = entry->skb->tstamp.off_sec;
242 pmsg->timestamp_usec = skb_tv_base.tv_usec + entry->skb->tstamp.off_usec; 242 pmsg->timestamp_usec = entry->skb->tstamp.off_usec;
243 pmsg->mark = entry->skb->nfmark; 243 pmsg->mark = entry->skb->nfmark;
244 pmsg->hook = entry->info->hook; 244 pmsg->hook = entry->info->hook;
245 pmsg->hw_protocol = entry->skb->protocol; 245 pmsg->hw_protocol = entry->skb->protocol;
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index ff5601ceedcb..efcd10f996ba 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -494,8 +494,8 @@ __build_packet_message(struct nfulnl_instance *inst,
494 if (skb->tstamp.off_sec) { 494 if (skb->tstamp.off_sec) {
495 struct nfulnl_msg_packet_timestamp ts; 495 struct nfulnl_msg_packet_timestamp ts;
496 496
497 ts.sec = cpu_to_be64(skb_tv_base.tv_sec + skb->tstamp.off_sec); 497 ts.sec = cpu_to_be64(skb->tstamp.off_sec);
498 ts.usec = cpu_to_be64(skb_tv_base.tv_usec + skb->tstamp.off_usec); 498 ts.usec = cpu_to_be64(skb->tstamp.off_usec);
499 499
500 NFA_PUT(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts); 500 NFA_PUT(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts);
501 } 501 }
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index f81fe8c52e99..eaa44c49567b 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -492,8 +492,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
492 if (entry->skb->tstamp.off_sec) { 492 if (entry->skb->tstamp.off_sec) {
493 struct nfqnl_msg_packet_timestamp ts; 493 struct nfqnl_msg_packet_timestamp ts;
494 494
495 ts.sec = cpu_to_be64(skb_tv_base.tv_sec + entry->skb->tstamp.off_sec); 495 ts.sec = cpu_to_be64(entry->skb->tstamp.off_sec);
496 ts.usec = cpu_to_be64(skb_tv_base.tv_usec + entry->skb->tstamp.off_usec); 496 ts.usec = cpu_to_be64(entry->skb->tstamp.off_usec);
497 497
498 NFA_PUT(skb, NFQA_TIMESTAMP, sizeof(ts), &ts); 498 NFA_PUT(skb, NFQA_TIMESTAMP, sizeof(ts), &ts);
499 } 499 }
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 6a67a87384cc..499ae3df4a44 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -654,8 +654,8 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, struct packe
654 __net_timestamp(skb); 654 __net_timestamp(skb);
655 sock_enable_timestamp(sk); 655 sock_enable_timestamp(sk);
656 } 656 }
657 h->tp_sec = skb_tv_base.tv_sec + skb->tstamp.off_sec; 657 h->tp_sec = skb->tstamp.off_sec;
658 h->tp_usec = skb_tv_base.tv_usec + skb->tstamp.off_usec; 658 h->tp_usec = skb->tstamp.off_usec;
659 659
660 sll = (struct sockaddr_ll*)((u8*)h + TPACKET_ALIGN(sizeof(*h))); 660 sll = (struct sockaddr_ll*)((u8*)h + TPACKET_ALIGN(sizeof(*h)));
661 sll->sll_halen = 0; 661 sll->sll_halen = 0;