aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2006-06-27 16:22:38 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-06-29 19:57:53 -0400
commit576a30eb6453439b3c37ba24455ac7090c247b5a (patch)
treee0c427a61e3de5c93e797c09903d910f6f060e64 /net/ipv4
parent68c1692e3ea5d79f24cb5cc566c4a73939d13d25 (diff)
[NET]: Added GSO header verification
When GSO packets come from an untrusted source (e.g., a Xen guest domain), we need to verify the header integrity before passing it to the hardware. Since the first step in GSO is to verify the header, we can reuse that code by adding a new bit to gso_type: SKB_GSO_DODGY. Packets with this bit set can only be fed directly to devices with the corresponding bit NETIF_F_GSO_ROBUST. If the device doesn't have that bit, then the skb is fed to the GSO engine which will allow the packet to be sent to the hardware if it passes the header check. This patch changes the sg flag to a full features flag. The same method can be used to implement TSO ECN support. We simply have to mark packets with CWR set with SKB_GSO_ECN so that only hardware with a corresponding NETIF_F_TSO_ECN can accept them. The GSO engine can either fully segment the packet, or segment the first MTU and pass the rest to the hardware for further segmentation. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/af_inet.c6
-rw-r--r--net/ipv4/tcp.c8
2 files changed, 9 insertions, 5 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 461216b47948..8d157157bf8e 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1097,7 +1097,7 @@ int inet_sk_rebuild_header(struct sock *sk)
1097 1097
1098EXPORT_SYMBOL(inet_sk_rebuild_header); 1098EXPORT_SYMBOL(inet_sk_rebuild_header);
1099 1099
1100static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg) 1100static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
1101{ 1101{
1102 struct sk_buff *segs = ERR_PTR(-EINVAL); 1102 struct sk_buff *segs = ERR_PTR(-EINVAL);
1103 struct iphdr *iph; 1103 struct iphdr *iph;
@@ -1126,10 +1126,10 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg)
1126 rcu_read_lock(); 1126 rcu_read_lock();
1127 ops = rcu_dereference(inet_protos[proto]); 1127 ops = rcu_dereference(inet_protos[proto]);
1128 if (ops && ops->gso_segment) 1128 if (ops && ops->gso_segment)
1129 segs = ops->gso_segment(skb, sg); 1129 segs = ops->gso_segment(skb, features);
1130 rcu_read_unlock(); 1130 rcu_read_unlock();
1131 1131
1132 if (IS_ERR(segs)) 1132 if (!segs || unlikely(IS_ERR(segs)))
1133 goto out; 1133 goto out;
1134 1134
1135 skb = segs; 1135 skb = segs;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index c04176be7ed1..0336422c88a0 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2145,7 +2145,7 @@ int compat_tcp_getsockopt(struct sock *sk, int level, int optname,
2145EXPORT_SYMBOL(compat_tcp_getsockopt); 2145EXPORT_SYMBOL(compat_tcp_getsockopt);
2146#endif 2146#endif
2147 2147
2148struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg) 2148struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
2149{ 2149{
2150 struct sk_buff *segs = ERR_PTR(-EINVAL); 2150 struct sk_buff *segs = ERR_PTR(-EINVAL);
2151 struct tcphdr *th; 2151 struct tcphdr *th;
@@ -2166,10 +2166,14 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int sg)
2166 if (!pskb_may_pull(skb, thlen)) 2166 if (!pskb_may_pull(skb, thlen))
2167 goto out; 2167 goto out;
2168 2168
2169 segs = NULL;
2170 if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
2171 goto out;
2172
2169 oldlen = (u16)~skb->len; 2173 oldlen = (u16)~skb->len;
2170 __skb_pull(skb, thlen); 2174 __skb_pull(skb, thlen);
2171 2175
2172 segs = skb_segment(skb, sg); 2176 segs = skb_segment(skb, features);
2173 if (IS_ERR(segs)) 2177 if (IS_ERR(segs))
2174 goto out; 2178 goto out;
2175 2179