Hi: This is part of my previous proposal on strengthening policy checks. This patch makes the xfrm_tunnel code use the same receive functions as other IPSEC tunnels. As a result, this inserts the tunnel state into the security path. This should be OK as our current policy check allows unspecified SAs. It also means that the IPCOMP SA selector is checked even when the packet is not compressed. Of course, if the user creates multiple IPCOMP SAs between the same pair of hosts with differing selectors, then they deserve to lose. One side effect is that it makes the NOECN flag useful for IPCOMP SAs assuming that the user makes sure that all IPCOMP SAs sharing the same tunnel state agrees on the flag. Cheers, -- Debian GNU/Linux 3.0 is out! ( http://www.debian.org/ ) Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Index: kernel-source-2.5/net/ipv4/ipcomp.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv4/ipcomp.c,v retrieving revision 1.3 diff -u -r1.3 ipcomp.c --- kernel-source-2.5/net/ipv4/ipcomp.c 29 Jul 2003 11:11:34 -0000 1.3 +++ kernel-source-2.5/net/ipv4/ipcomp.c 29 Jul 2003 11:21:08 -0000 @@ -280,6 +280,7 @@ t->props.family = AF_INET; t->props.mode = 1; t->props.saddr.a4 = x->props.saddr.a4; + t->props.flags = x->props.flags; t->type = xfrm_get_type(IPPROTO_IPIP, t->props.family); if (t->type == NULL) Index: kernel-source-2.5/net/ipv4/xfrm4_tunnel.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv4/xfrm4_tunnel.c,v retrieving revision 1.1.1.3 diff -u -r1.1.1.3 xfrm4_tunnel.c --- kernel-source-2.5/net/ipv4/xfrm4_tunnel.c 17 Jun 2003 04:19:40 -0000 1.1.1.3 +++ kernel-source-2.5/net/ipv4/xfrm4_tunnel.c 29 Jul 2003 11:13:32 -0000 @@ -83,31 +83,8 @@ return err; } -static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff *skb) -{ - struct iphdr *inner_iph = skb->nh.iph; - - if (INET_ECN_is_ce(outer_iph->tos) && - INET_ECN_is_not_ce(inner_iph->tos)) - IP_ECN_set_ce(inner_iph); -} - static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) { - struct iphdr *outer_iph = skb->nh.iph; - - if (!pskb_may_pull(skb, sizeof(struct iphdr))) - return -EINVAL; - skb->mac.raw = skb->nh.raw; - skb->nh.raw = skb->data; - memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); - dst_release(skb->dst); - skb->dst = NULL; - skb->protocol = htons(ETH_P_IP); - skb->pkt_type = PACKET_HOST; - ipip_ecn_decapsulate(outer_iph, skb); - netif_rx(skb); - return 0; } @@ -149,46 +126,12 @@ static int ipip_rcv(struct sk_buff *skb) { struct xfrm_tunnel *handler = ipip_handler; - struct xfrm_state *x = NULL; - int err; /* Tunnel devices take precedence. */ - if (handler) { - err = handler->handler(skb); - if (!err) - goto out; - } + if (handler && handler->handler(skb) == 0) + return 0; - x = xfrm_state_lookup((xfrm_address_t *)&skb->nh.iph->daddr, - skb->nh.iph->saddr, - IPPROTO_IPIP, AF_INET); - - if (!x) - goto drop; - - spin_lock(&x->lock); - - if (unlikely(x->km.state != XFRM_STATE_VALID)) - goto drop_unlock; - - err = ipip_xfrm_rcv(x, NULL, skb); - if (err) - goto drop_unlock; - - x->curlft.bytes += skb->len; - x->curlft.packets++; - spin_unlock(&x->lock); - xfrm_state_put(x); -out: - return err; - -drop_unlock: - spin_unlock(&x->lock); - xfrm_state_put(x); -drop: - err = NET_RX_DROP; - kfree_skb(skb); - goto out; + return xfrm4_rcv(skb); } static void ipip_err(struct sk_buff *skb, u32 info) Index: kernel-source-2.5/net/xfrm/xfrm_input.c =================================================================== RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/xfrm/xfrm_input.c,v retrieving revision 1.2 diff -u -r1.2 xfrm_input.c --- kernel-source-2.5/net/xfrm/xfrm_input.c 28 Jul 2003 11:31:30 -0000 1.2 +++ kernel-source-2.5/net/xfrm/xfrm_input.c 29 Jul 2003 11:13:32 -0000 @@ -62,6 +62,12 @@ *spi = ntohl(ntohs(*(u16*)(skb->h.raw + 2))); *seq = 0; return 0; + case IPPROTO_IPIP: + if (!pskb_may_pull(skb, sizeof(struct iphdr))) + return -EINVAL; + *spi = skb->nh.iph->saddr; + *seq = 0; + return 0; default: return 1; }