|
@@ -599,16 +599,27 @@ struct xfrm_mgr {
|
|
|
int xfrm_register_km(struct xfrm_mgr *km);
|
|
|
int xfrm_unregister_km(struct xfrm_mgr *km);
|
|
|
|
|
|
+struct xfrm_tunnel_skb_cb {
|
|
|
+ union {
|
|
|
+ struct inet_skb_parm h4;
|
|
|
+ struct inet6_skb_parm h6;
|
|
|
+ } header;
|
|
|
+
|
|
|
+ union {
|
|
|
+ struct ip_tunnel *ip4;
|
|
|
+ struct ip6_tnl *ip6;
|
|
|
+ } tunnel;
|
|
|
+};
|
|
|
+
|
|
|
+#define XFRM_TUNNEL_SKB_CB(__skb) ((struct xfrm_tunnel_skb_cb *)&((__skb)->cb[0]))
|
|
|
+
|
|
|
/*
|
|
|
* This structure is used for the duration where packets are being
|
|
|
* transformed by IPsec. As soon as the packet leaves IPsec the
|
|
|
* area beyond the generic IP part may be overwritten.
|
|
|
*/
|
|
|
struct xfrm_skb_cb {
|
|
|
- union {
|
|
|
- struct inet_skb_parm h4;
|
|
|
- struct inet6_skb_parm h6;
|
|
|
- } header;
|
|
|
+ struct xfrm_tunnel_skb_cb header;
|
|
|
|
|
|
/* Sequence number for replay protection. */
|
|
|
union {
|
|
@@ -630,10 +641,7 @@ struct xfrm_skb_cb {
|
|
|
* to transmit header information to the mode input/output functions.
|
|
|
*/
|
|
|
struct xfrm_mode_skb_cb {
|
|
|
- union {
|
|
|
- struct inet_skb_parm h4;
|
|
|
- struct inet6_skb_parm h6;
|
|
|
- } header;
|
|
|
+ struct xfrm_tunnel_skb_cb header;
|
|
|
|
|
|
/* Copied from header for IPv4, always set to zero and DF for IPv6. */
|
|
|
__be16 id;
|
|
@@ -665,10 +673,7 @@ struct xfrm_mode_skb_cb {
|
|
|
* related information.
|
|
|
*/
|
|
|
struct xfrm_spi_skb_cb {
|
|
|
- union {
|
|
|
- struct inet_skb_parm h4;
|
|
|
- struct inet6_skb_parm h6;
|
|
|
- } header;
|
|
|
+ struct xfrm_tunnel_skb_cb header;
|
|
|
|
|
|
unsigned int daddroff;
|
|
|
unsigned int family;
|
|
@@ -1510,6 +1515,7 @@ int xfrm4_rcv(struct sk_buff *skb);
|
|
|
|
|
|
static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
|
|
|
{
|
|
|
+ XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
|
|
|
XFRM_SPI_SKB_CB(skb)->family = AF_INET;
|
|
|
XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
|
|
|
return xfrm_input(skb, nexthdr, spi, 0);
|
|
@@ -1781,4 +1787,24 @@ static inline int xfrm_rcv_cb(struct sk_buff *skb, unsigned int family,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static inline int xfrm_tunnel_check(struct sk_buff *skb, struct xfrm_state *x,
|
|
|
+ unsigned int family)
|
|
|
+{
|
|
|
+ bool tunnel = false;
|
|
|
+
|
|
|
+ switch(family) {
|
|
|
+ case AF_INET:
|
|
|
+ if (XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4)
|
|
|
+ tunnel = true;
|
|
|
+ break;
|
|
|
+ case AF_INET6:
|
|
|
+ if (XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6)
|
|
|
+ tunnel = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (tunnel && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
#endif /* _NET_XFRM_H */
|