]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-dhcp-client: add sd_dhcp_client_id_to_string()
authorMarc-André Lureau <marcandre.lureau@redhat.com>
Fri, 22 May 2020 09:30:49 +0000 (11:30 +0200)
committerMarc-André Lureau <marcandre.lureau@redhat.com>
Thu, 4 Jun 2020 09:16:15 +0000 (11:16 +0200)
Add a human-friendly pretty-printer for client ID.

src/libsystemd-network/sd-dhcp-client.c
src/systemd/sd-dhcp-client.h

index eaf5c78df048e6ee160f8bd2e36aab032a8be482..d5f25d5a194e5cf51e3cdd34fe2e2f8c88d0dcde 100644 (file)
@@ -27,6 +27,7 @@
 #include "random-util.h"
 #include "string-util.h"
 #include "strv.h"
+#include "utf8.h"
 #include "web-util.h"
 
 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN)  /* Arbitrary limit */
@@ -153,6 +154,60 @@ static int client_receive_message_udp(
                 void *userdata);
 static void client_stop(sd_dhcp_client *client, int error);
 
+int sd_dhcp_client_id_to_string(const void *data, size_t len, char **ret) {
+        const sd_dhcp_client_id *client_id = data;
+        _cleanup_free_ char *t = NULL;
+        int r = 0;
+
+        assert_return(data, -EINVAL);
+        assert_return(len >= 1, -EINVAL);
+        assert_return(ret, -EINVAL);
+
+        len -= 1;
+        if (len > MAX_CLIENT_ID_LEN)
+                return -EINVAL;
+
+        switch (client_id->type) {
+        case 0:
+                if (utf8_is_printable((char *) client_id->gen.data, len))
+                        r = asprintf(&t, "%.*s", (int) len, client_id->gen.data);
+                else
+                        r = asprintf(&t, "DATA");
+                break;
+        case 1:
+                if (len != sizeof_field(sd_dhcp_client_id, eth))
+                        return -EINVAL;
+
+                r = asprintf(&t, "%x:%x:%x:%x:%x:%x",
+                             client_id->eth.haddr[0],
+                             client_id->eth.haddr[1],
+                             client_id->eth.haddr[2],
+                             client_id->eth.haddr[3],
+                             client_id->eth.haddr[4],
+                             client_id->eth.haddr[5]);
+                break;
+        case 2 ... 254:
+                r = asprintf(&t, "ARP/LL");
+                break;
+        case 255:
+                if (len < 6)
+                        return -EINVAL;
+
+                uint32_t iaid = be32toh(client_id->ns.iaid);
+                uint16_t duid_type = be16toh(client_id->ns.duid.type);
+                if (dhcp_validate_duid_len(duid_type, len - 6, true) < 0)
+                        return -EINVAL;
+
+                r = asprintf(&t, "IAID:0x%x/DUID", iaid);
+                break;
+        }
+
+        if (r < 0)
+                return -ENOMEM;
+        *ret = TAKE_PTR(t);
+        return 0;
+}
+
 int sd_dhcp_client_set_callback(
                 sd_dhcp_client *client,
                 sd_dhcp_client_callback_t cb,
index 85b49bae74b872a867579b64cf251fbf311387ea..ac3b5b369c11319b3224c1a98cc9a872c58dec84 100644 (file)
@@ -205,6 +205,8 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client);
  * options when using RFC7844 Anonymity Profiles */
 int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize);
 
+int sd_dhcp_client_id_to_string(const void *data, size_t len, char **ret);
+
 int sd_dhcp_client_attach_event(
                 sd_dhcp_client *client,
                 sd_event *event,