rxrpc: Provide kernel interface to set max lifespan on a call
[sfrench/cifs-2.6.git] / net / xfrm / xfrm_output.c
index 9bdf16f1360671fe1cfc58fccfc56af45041c600..a55510f9ff35a711af26e416c6168370fac04ac6 100644 (file)
@@ -61,7 +61,6 @@ static struct dst_entry *skb_dst_pop(struct sk_buff *skb)
  */
 static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
 {
-#if IS_ENABLED(CONFIG_INET_XFRM_MODE_TRANSPORT)
        struct iphdr *iph = ip_hdr(skb);
        int ihl = iph->ihl * 4;
 
@@ -74,10 +73,6 @@ static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
        __skb_pull(skb, ihl);
        memmove(skb_network_header(skb), iph, ihl);
        return 0;
-#else
-       WARN_ON_ONCE(1);
-       return -EOPNOTSUPP;
-#endif
 }
 
 /* Add encapsulation header.
@@ -87,7 +82,7 @@ static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
  */
 static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
 {
-#if IS_ENABLED(CONFIG_INET6_XFRM_MODE_TRANSPORT)
+#if IS_ENABLED(CONFIG_IPV6)
        struct ipv6hdr *iph;
        u8 *prevhdr;
        int hdr_len;
@@ -107,7 +102,7 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
        return 0;
 #else
        WARN_ON_ONCE(1);
-       return -EOPNOTSUPP;
+       return -EAFNOSUPPORT;
 #endif
 }
 
@@ -118,7 +113,7 @@ static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
  */
 static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
 {
-#if IS_ENABLED(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION)
+#if IS_ENABLED(CONFIG_IPV6)
        struct ipv6hdr *iph;
        u8 *prevhdr;
        int hdr_len;
@@ -140,7 +135,7 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
        return 0;
 #else
        WARN_ON_ONCE(1);
-       return -EOPNOTSUPP;
+       return -EAFNOSUPPORT;
 #endif
 }
 
@@ -339,7 +334,7 @@ static int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
        IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
        skb->protocol = htons(ETH_P_IP);
 
-       switch (x->outer_mode->encap) {
+       switch (x->outer_mode.encap) {
        case XFRM_MODE_BEET:
                return xfrm4_beet_encap_add(x, skb);
        case XFRM_MODE_TUNNEL:
@@ -362,7 +357,7 @@ static int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
        skb->ignore_df = 1;
        skb->protocol = htons(ETH_P_IPV6);
 
-       switch (x->outer_mode->encap) {
+       switch (x->outer_mode.encap) {
        case XFRM_MODE_BEET:
                return xfrm6_beet_encap_add(x, skb);
        case XFRM_MODE_TUNNEL:
@@ -378,22 +373,22 @@ static int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
 
 static int xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb)
 {
-       switch (x->outer_mode->encap) {
+       switch (x->outer_mode.encap) {
        case XFRM_MODE_BEET:
        case XFRM_MODE_TUNNEL:
-               if (x->outer_mode->family == AF_INET)
+               if (x->outer_mode.family == AF_INET)
                        return xfrm4_prepare_output(x, skb);
-               if (x->outer_mode->family == AF_INET6)
+               if (x->outer_mode.family == AF_INET6)
                        return xfrm6_prepare_output(x, skb);
                break;
        case XFRM_MODE_TRANSPORT:
-               if (x->outer_mode->family == AF_INET)
+               if (x->outer_mode.family == AF_INET)
                        return xfrm4_transport_output(x, skb);
-               if (x->outer_mode->family == AF_INET6)
+               if (x->outer_mode.family == AF_INET6)
                        return xfrm6_transport_output(x, skb);
                break;
        case XFRM_MODE_ROUTEOPTIMIZATION:
-               if (x->outer_mode->family == AF_INET6)
+               if (x->outer_mode.family == AF_INET6)
                        return xfrm6_ro_output(x, skb);
                WARN_ON_ONCE(1);
                break;
@@ -494,7 +489,7 @@ resume:
                }
                skb_dst_set(skb, dst);
                x = dst->xfrm;
-       } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL));
+       } while (x && !(x->outer_mode.flags & XFRM_MODE_FLAG_TUNNEL));
 
        return 0;
 
@@ -623,16 +618,26 @@ EXPORT_SYMBOL_GPL(xfrm_output);
 
 static int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb)
 {
-       struct xfrm_mode *inner_mode;
+       const struct xfrm_state_afinfo *afinfo;
+       const struct xfrm_mode *inner_mode;
+       int err = -EAFNOSUPPORT;
+
        if (x->sel.family == AF_UNSPEC)
                inner_mode = xfrm_ip2inner_mode(x,
                                xfrm_af2proto(skb_dst(skb)->ops->family));
        else
-               inner_mode = x->inner_mode;
+               inner_mode = &x->inner_mode;
 
        if (inner_mode == NULL)
                return -EAFNOSUPPORT;
-       return inner_mode->afinfo->extract_output(x, skb);
+
+       rcu_read_lock();
+       afinfo = xfrm_state_afinfo_get_rcu(inner_mode->family);
+       if (likely(afinfo))
+               err = afinfo->extract_output(x, skb);
+       rcu_read_unlock();
+
+       return err;
 }
 
 void xfrm_local_error(struct sk_buff *skb, int mtu)