]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
kernel-netlink: Add SA direction attribute
authorTobias Brunner <tobias@strongswan.org>
Tue, 30 Apr 2024 09:39:00 +0000 (11:39 +0200)
committerTobias Brunner <tobias@strongswan.org>
Wed, 7 Aug 2024 12:41:28 +0000 (14:41 +0200)
src/libcharon/plugins/kernel_netlink/kernel_netlink_ipsec.c

index 493a22910a4fb6a33a72738c115adb31367e1586..88734b0dabff53780932edcbb5860aec7a285648 100644 (file)
@@ -1187,6 +1187,112 @@ METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
                        (this->sa_lastused ? KERNEL_SA_USE_TIME : 0);
 }
 
+/**
+ * Format the mark for debug messages
+ */
+static void format_mark(char *buf, int buflen, mark_t mark)
+{
+       if (mark.value | mark.mask)
+       {
+               snprintf(buf, buflen, " (mark %u/0x%08x)", mark.value, mark.mask);
+       }
+}
+
+/**
+ * Add a XFRM mark to message if required
+ */
+static bool add_mark(struct nlmsghdr *hdr, int buflen, mark_t mark)
+{
+       if (mark.value | mark.mask)
+       {
+               struct xfrm_mark *xmrk;
+
+               xmrk = netlink_reserve(hdr, buflen, XFRMA_MARK, sizeof(*xmrk));
+               if (!xmrk)
+               {
+                       return FALSE;
+               }
+               xmrk->v = mark.value;
+               xmrk->m = mark.mask;
+       }
+       return TRUE;
+}
+
+/**
+ * Format the security label for debug messages
+ */
+static void format_label(char *buf, int buflen, sec_label_t *label)
+{
+       if (label)
+       {
+               snprintf(buf, buflen, " (ctx %s)", label->get_string(label));
+       }
+}
+
+/**
+ * Add a security label to message if required
+ */
+static bool add_label(struct nlmsghdr *hdr, int buflen, sec_label_t *label)
+{
+       if (label)
+       {
+#ifdef USE_SELINUX
+               struct xfrm_user_sec_ctx *ctx;
+               chunk_t enc = label->get_encoding(label);
+               int len = sizeof(*ctx) + enc.len;
+
+               ctx = netlink_reserve(hdr, buflen, XFRMA_SEC_CTX, len);
+               if (!ctx)
+               {
+                       return FALSE;
+               }
+               /* this attribute for some reason duplicates the generic header */
+               ctx->exttype = XFRMA_SEC_CTX;
+               ctx->len = len;
+
+               ctx->ctx_doi = XFRM_SC_DOI_LSM;
+               ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
+               ctx->ctx_len = enc.len;
+               memcpy((void*)(ctx + 1), enc.ptr, enc.len);
+#endif
+       }
+       return TRUE;
+}
+
+/**
+ * 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;
+}
+
+/**
+ * Add a uint8 attribute to message
+ */
+static bool add_uint8(struct nlmsghdr *hdr, int buflen,
+                                         enum xfrm_attr_type_t type, uint8_t value)
+{
+       uint8_t *xvalue;
+
+       xvalue = netlink_reserve(hdr, buflen, type, sizeof(*xvalue));
+       if (!xvalue)
+       {
+               return FALSE;
+       }
+       *xvalue = value;
+       return TRUE;
+}
+
 /**
  * Get an SPI for a specific protocol from the kernel.
  */
@@ -1216,6 +1322,11 @@ static status_t get_spi_internal(private_kernel_netlink_ipsec_t *this,
        userspi->min = min;
        userspi->max = max;
 
+       if (!add_uint8(hdr, sizeof(request), XFRMA_SA_DIR, XFRM_SA_DIR_IN))
+       {
+               return FAILED;
+       }
+
        if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS)
        {
                hdr = out;
@@ -1295,95 +1406,6 @@ METHOD(kernel_ipsec_t, get_cpi, status_t,
        return SUCCESS;
 }
 
-/**
- * Format the mark for debug messages
- */
-static void format_mark(char *buf, int buflen, mark_t mark)
-{
-       if (mark.value | mark.mask)
-       {
-               snprintf(buf, buflen, " (mark %u/0x%08x)", mark.value, mark.mask);
-       }
-}
-
-/**
- * Add a XFRM mark to message if required
- */
-static bool add_mark(struct nlmsghdr *hdr, int buflen, mark_t mark)
-{
-       if (mark.value | mark.mask)
-       {
-               struct xfrm_mark *xmrk;
-
-               xmrk = netlink_reserve(hdr, buflen, XFRMA_MARK, sizeof(*xmrk));
-               if (!xmrk)
-               {
-                       return FALSE;
-               }
-               xmrk->v = mark.value;
-               xmrk->m = mark.mask;
-       }
-       return TRUE;
-}
-
-/**
- * Format the security label for debug messages
- */
-static void format_label(char *buf, int buflen, sec_label_t *label)
-{
-       if (label)
-       {
-               snprintf(buf, buflen, " (ctx %s)", label->get_string(label));
-       }
-}
-
-/**
- * Add a security label to message if required
- */
-static bool add_label(struct nlmsghdr *hdr, int buflen, sec_label_t *label)
-{
-       if (label)
-       {
-#ifdef USE_SELINUX
-               struct xfrm_user_sec_ctx *ctx;
-               chunk_t enc = label->get_encoding(label);
-               int len = sizeof(*ctx) + enc.len;
-
-               ctx = netlink_reserve(hdr, buflen, XFRMA_SEC_CTX, len);
-               if (!ctx)
-               {
-                       return FALSE;
-               }
-               /* this attribute for some reason duplicates the generic header */
-               ctx->exttype = XFRMA_SEC_CTX;
-               ctx->len = len;
-
-               ctx->ctx_doi = XFRM_SC_DOI_LSM;
-               ctx->ctx_alg = XFRM_SC_ALG_SELINUX;
-               ctx->ctx_len = enc.len;
-               memcpy((void*)(ctx + 1), enc.ptr, enc.len);
-#endif
-       }
-       return TRUE;
-}
-
-/**
- * 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;
-}
-
 /* ETHTOOL_GSSET_INFO is available since 2.6.34 and ETH_SS_FEATURES (enum) and
  * ETHTOOL_GFEATURES since 2.6.39, so check for the latter */
 #ifdef ETHTOOL_GFEATURES
@@ -2046,6 +2068,12 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
                }
        }
 
+       if (!add_uint8(hdr, sizeof(request), XFRMA_SA_DIR,
+                                  data->inbound ? XFRM_SA_DIR_IN : XFRM_SA_DIR_OUT))
+       {
+               goto failed;
+       }
+
        if (id->proto != IPPROTO_COMP)
        {
                /* generally, we don't need a replay window for outbound SAs, however,