]> granicus.if.org Git - libnl/commitdiff
xfrm: allow quering optional arguments from xfrmnl_sp_get_sec_ctx()
authorThomas Haller <thaller@redhat.com>
Mon, 27 Feb 2017 16:32:15 +0000 (17:32 +0100)
committerThomas Haller <thaller@redhat.com>
Mon, 27 Feb 2017 16:32:15 +0000 (17:32 +0100)
The previous API of xfrmnl_sp_get_sec_ctx() is totally broken,
as it requires all out-arguments to be set. The user can thus
not know how large the ctx_str buffer must be.

Fix the API by allowing all arguments to be optional. Thus,
a user can first query the size only, and then in a second
step query the ctx_str. Previous version are broken.

include/netlink/utils.h
lib/utils.c
lib/xfrm/sp.c

index 02038c48a1dd943862a8a5813858aa9d2c5f79b5..c94b670d4926f4ea6acf4cc2cf2629e349271e6d 100644 (file)
@@ -267,6 +267,13 @@ enum {
        NL_CAPABILITY_VERSION_3_2_29 = 25,
 #define NL_CAPABILITY_VERSION_3_2_29 NL_CAPABILITY_VERSION_3_2_29
 
+       /**
+        * Support omitting @ctx_str argument to xfrmnl_sp_get_sec_ctx() to check
+        * for required buffer size for context string.
+        */
+       NL_CAPABILITY_XFRM_SP_SEC_CTX_LEN = 26,
+#define NL_CAPABILITY_XFRM_SP_SEC_CTX_LEN NL_CAPABILITY_XFRM_SP_SEC_CTX_LEN
+
        __NL_CAPABILITY_MAX,
        NL_CAPABILITY_MAX = (__NL_CAPABILITY_MAX - 1),
 #define NL_CAPABILITY_MAX NL_CAPABILITY_MAX
index 64e87b6c2a0264315d615c2610338bac3e2e70d0..fb350d13fd2f1d7fb5ffc6c98ed8856e7e8240d5 100644 (file)
@@ -1212,7 +1212,7 @@ int nl_has_capability (int capability)
                        NL_CAPABILITY_NL_RECVMSGS_PEEK_BY_DEFAULT),
                _NL_SET (3,
                        NL_CAPABILITY_VERSION_3_2_29,
-                       0,
+                       NL_CAPABILITY_XFRM_SP_SEC_CTX_LEN,
                        0,
                        0,
                        0,
index cb518613bd0e8b872d747d3adcb14bc72cce523c..0f2ebc14f18e815db3f816511d51a5cd149b24e9 100644 (file)
@@ -1199,16 +1199,43 @@ int xfrmnl_sp_set_share (struct xfrmnl_sp* sp, unsigned int share)
        return 0;
 }
 
+/**
+ * Get the security context.
+ *
+ * @arg sp              The xfrmnl_sp object.
+ * @arg len             An optional output value for the ctx_str length including the xfrmnl_sp header.
+ * @arg exttype         An optional output value.
+ * @arg alg             An optional output value for the security context algorithm.
+ * @arg doi             An optional output value for the security context domain of interpretation.
+ * @arg ctx_len         An optional output value for the security context length, including the
+ *                      terminating null byte ('\0').
+ * @arg ctx_str         An optional buffer large enough for the security context string. It must
+ *                      contain at least @ctx_len bytes. You are advised to create the ctx_str
+ *                      buffer one element larger and ensure NUL termination yourself.
+ *
+ * Warning: you must ensure that @ctx_str is large enough. If you don't know the length before-hand,
+ * call xfrmnl_sp_get_sec_ctx() without @ctx_str argument to query only the required buffer size.
+ * This modified API is available in all versions of libnl3 that support the capability
+ * @def NL_CAPABILITY_XFRM_SP_SEC_CTX_LEN (@see nl_has_capability for further information).
+ *
+ * @return 0 on success or a negative error code.
+ */
 int xfrmnl_sp_get_sec_ctx (struct xfrmnl_sp* sp, unsigned int* len, unsigned int* exttype, unsigned int* alg, unsigned int* doi, unsigned int* ctx_len, char* ctx_str)
 {
        if (sp->ce_mask & XFRM_SP_ATTR_SECCTX)
        {
-               *len    =   sp->sec_ctx->len;
-               *exttype=   sp->sec_ctx->exttype;
-               *alg    =   sp->sec_ctx->ctx_alg;
-               *doi    =   sp->sec_ctx->ctx_doi;
-               *ctx_len=   sp->sec_ctx->ctx_len;
-               memcpy ((void *)ctx_str, (void *)sp->sec_ctx->ctx, sizeof (uint8_t) * sp->sec_ctx->ctx_len);
+               if (len)
+                       *len = sizeof (struct xfrmnl_user_sec_ctx) + sp->sec_ctx->ctx_len;
+               if (exttype)
+                       *exttype = sp->sec_ctx->exttype;
+               if (alg)
+                       *alg = sp->sec_ctx->ctx_alg;
+               if (doi)
+                       *doi = sp->sec_ctx->ctx_doi;
+               if (ctx_len)
+                       *ctx_len = sp->sec_ctx->ctx_len;
+               if (ctx_str)
+                       memcpy ((void *)ctx_str, (void *)sp->sec_ctx->ctx, sp->sec_ctx->ctx_len);
        }
        else
                return -1;