kernel-netlink: Add support for setting mark/mask an SA should apply to processed...
authorTobias Brunner <tobias@strongswan.org>
Fri, 20 Apr 2018 12:01:12 +0000 (14:01 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 31 Aug 2018 10:24:30 +0000 (12:24 +0200)
src/include/linux/xfrm.h
src/libcharon/kernel/kernel_ipsec.h
src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c

index dbaa4f1..35261c9 100644 (file)
@@ -302,8 +302,11 @@ enum xfrm_attr_type_t {
        XFRMA_ADDRESS_FILTER,   /* struct xfrm_address_filter */
        XFRMA_PAD,
        XFRMA_OFFLOAD_DEV,      /* struct xfrm_state_offload */
+       XFRMA_SET_MARK,         /* __u32 */
+       XFRMA_SET_MARK_MASK,    /* __u32 */
        __XFRMA_MAX
 
+#define XFRMA_OUTPUT_MARK XFRMA_SET_MARK       /* Compatibility */
 #define XFRMA_MAX (__XFRMA_MAX - 1)
 };
 
index 195c80c..4158eb4 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2016 Andreas Steffen
- * Copyright (C) 2006-2016 Tobias Brunner
+ * Copyright (C) 2006-2018 Tobias Brunner
  * Copyright (C) 2006 Daniel Roethlisberger
  * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
@@ -93,6 +93,8 @@ struct kernel_ipsec_add_sa_t {
        bool encap;
        /** no (disabled), yes (enabled), auto (enabled if supported) */
        hw_offload_t hw_offload;
+       /** Mark the SA should apply to packets after processing */
+       mark_t mark;
        /** TRUE to use Extended Sequence Numbers */
        bool esn;
        /** TRUE to copy the DF bit to the outer IPv4 header in tunnel mode */
index 33e982d..1292e08 100644 (file)
@@ -1336,6 +1336,23 @@ static bool add_mark(struct nlmsghdr *hdr, int buflen, mark_t mark)
 }
 
 /**
+ * Add a uint32 attribute to message
+ */
+static bool add_uint32(struct nlmsghdr *hdr, int buflen,
+                                          enum xfrm_attr_type_t type, uint32_t value)
+{
+       uint32_t *xvalue;
+
+       xvalue = netlink_reserve(hdr, buflen, type, sizeof(*xvalue));
+       if (!xvalue)
+       {
+               return FALSE;
+       }
+       *xvalue = value;
+       return TRUE;
+}
+
+/**
  * Check if kernel supports HW offload
  */
 static void netlink_find_offload_feature(const char *ifname, int query_socket)
@@ -1616,16 +1633,12 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                        case DSCP_COPY_IN_ONLY:
                        case DSCP_COPY_NO:
                        {
-                               uint32_t *xflags;
-
-                               xflags = netlink_reserve(hdr, sizeof(request),
-                                                                                XFRMA_SA_EXTRA_FLAGS, sizeof(*xflags));
-                               if (!xflags)
+                               /* currently the only extra flag */
+                               if (!add_uint32(hdr, sizeof(request), XFRMA_SA_EXTRA_FLAGS,
+                                                               XFRM_SA_XFLAG_DONT_ENCAP_DSCP))
                                {
                                        goto failed;
                                }
-                               /* currently the only extra flag */
-                               *xflags |= XFRM_SA_XFLAG_DONT_ENCAP_DSCP;
                                break;
                        }
                        default:
@@ -1876,17 +1889,23 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                goto failed;
        }
 
+       if (ipcomp == IPCOMP_NONE && (data->mark.value | data->mark.mask))
+       {
+               if (!add_uint32(hdr, sizeof(request), XFRMA_SET_MARK,
+                                               data->mark.value) ||
+                       !add_uint32(hdr, sizeof(request), XFRMA_SET_MARK_MASK,
+                                               data->mark.mask))
+               {
+                       goto failed;
+               }
+       }
+
        if (data->tfc && id->proto == IPPROTO_ESP && mode == MODE_TUNNEL)
        {       /* the kernel supports TFC padding only for tunnel mode ESP SAs */
-               uint32_t *tfcpad;
-
-               tfcpad = netlink_reserve(hdr, sizeof(request), XFRMA_TFCPAD,
-                                                                sizeof(*tfcpad));
-               if (!tfcpad)
+               if (!add_uint32(hdr, sizeof(request), XFRMA_TFCPAD, data->tfc))
                {
                        goto failed;
                }
-               *tfcpad = data->tfc;
        }
 
        if (id->proto != IPPROTO_COMP)