Add system info messages
authorJeremy Kerr <jk@ozlabs.org>
Wed, 9 Oct 2013 04:02:08 +0000 (12:02 +0800)
committerJeremy Kerr <jk@ozlabs.org>
Wed, 9 Oct 2013 09:40:04 +0000 (17:40 +0800)
Add a little infrastructure for communicating information about the
system to the petitboot UIs. We just send some identifying info (type
and identifier), as well as the interfaces.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
13 files changed:
discover/Makefile.am
discover/discover-server.c
discover/discover-server.h
discover/network.c
discover/pb-discover.c
discover/sysinfo.c [new file with mode: 0644]
discover/sysinfo.h [new file with mode: 0644]
lib/pb-protocol/pb-protocol.c
lib/pb-protocol/pb-protocol.h
lib/types/types.h
ui/common/discover-client.c
ui/common/discover-client.h
ui/test/discover-test.c

index 848816febbd12bba89e38c8a41a31262c8d4d889..1fd8d96c6001954c1620f6b5865e463146065b35 100644 (file)
@@ -53,6 +53,8 @@ pb_discover_SOURCES = \
        pb-discover.h \
        resource.c \
        resource.h \
+       sysinfo.c \
+       sysinfo.h \
        network.c \
        network.h \
        udev.c \
index 29816ee6a3614d4ad4500b2b7d31307e43fb19dd..25dbd1476cdd9d6cf2ba817d74716d7944e40542 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "device-handler.h"
 #include "discover-server.h"
+#include "sysinfo.h"
 
 struct discover_server {
        int socket;
@@ -167,6 +168,24 @@ static int write_boot_status_message(struct discover_server *server,
        return client_write_message(server, client, message);
 }
 
+static int write_system_info_message(struct discover_server *server,
+               struct client *client, const struct system_info *sysinfo)
+{
+       struct pb_protocol_message *message;
+       int len;
+
+       len = pb_protocol_system_info_len(sysinfo);
+
+       message = pb_protocol_create_message(client,
+                       PB_PROTOCOL_ACTION_SYSTEM_INFO, len);
+       if (!message)
+               return -1;
+
+       pb_protocol_serialise_system_info(sysinfo, message->payload, len);
+
+       return client_write_message(server, client, message);
+}
+
 static int discover_server_process_message(void *arg)
 {
        struct pb_protocol_message *message;
@@ -232,6 +251,11 @@ static int discover_server_process_connection(void *arg)
        client->fd = fd;
        client->server = server;
 
+       /* send sysinfo to client */
+       rc = write_system_info_message(server, client, system_info_get());
+       if (rc)
+               return 0;
+
        /* send existing devices to client */
        n_devices = device_handler_get_device_count(server->device_handler);
        for (i = 0; i < n_devices; i++) {
@@ -296,6 +320,15 @@ void discover_server_notify_boot_status(struct discover_server *server,
                write_boot_status_message(server, client, status);
 }
 
+void discover_server_notify_system_info(struct discover_server *server,
+               const struct system_info *sysinfo)
+{
+       struct client *client;
+
+       list_for_each_entry(&server->clients, client, list)
+               write_system_info_message(server, client, sysinfo);
+}
+
 void discover_server_set_device_source(struct discover_server *server,
                struct device_handler *handler)
 {
index 541afaf776b4bbf718953ec9787b3b17ebcea845..d22fb3845717be5aca95fde226f008ebf93eeb8c 100644 (file)
@@ -7,6 +7,7 @@ struct discover_server;
 struct device_handler;
 struct boot_option;
 struct boot_status;
+struct system_info;
 struct device;
 
 struct discover_server *discover_server_init(struct waitset *waitset);
@@ -24,4 +25,6 @@ void discover_server_notify_device_remove(struct discover_server *server,
                struct device *device);
 void discover_server_notify_boot_status(struct discover_server *server,
                struct boot_status *status);
+void discover_server_notify_system_info(struct discover_server *server,
+               const struct system_info *sysinfo);
 #endif /* _DISCOVER_SERVER_H */
index c853a97b0cf21d8350f702d3c83dac780a79c3b5..9aa975204e0f71de40070340e506d1f3ed6dd3e4 100644 (file)
@@ -20,6 +20,7 @@
 
 #include "file.h"
 #include "network.h"
+#include "sysinfo.h"
 #include "device-handler.h"
 
 #define HWADDR_SIZE    6
@@ -406,6 +407,12 @@ static int network_handle_nlmsg(struct network *network, struct nlmsghdr *nlmsg)
                memcpy(interface->hwaddr, ifaddr, sizeof(interface->hwaddr));
                strncpy(interface->name, ifname, sizeof(interface->name) - 1);
                add_interface(network, interface);
+
+               /* tell the sysinfo code about this interface */
+               if (strcmp(interface->name, "lo"))
+                       system_info_register_interface(
+                                       sizeof(interface->hwaddr),
+                                       interface->hwaddr, interface->name);
        }
 
        configure_interface(network, interface,
index ccd1c7daba597441c9df3dac3e67f89ed2aeab50..9b1f20041da7a7a764233abc4f1d3499775be2a1 100644 (file)
@@ -19,6 +19,7 @@
 #include "discover-server.h"
 #include "device-handler.h"
 #include "network.h"
+#include "sysinfo.h"
 
 static void print_version(void)
 {
@@ -172,6 +173,8 @@ int main(int argc, char *argv[])
        if (opts.no_autoboot == opt_yes)
                config_set_autoboot(false);
 
+       system_info_init(server);
+
        handler = device_handler_init(server, waitset, opts.dry_run == opt_yes);
        if (!handler)
                return EXIT_FAILURE;
diff --git a/discover/sysinfo.c b/discover/sysinfo.c
new file mode 100644 (file)
index 0000000..19dac57
--- /dev/null
@@ -0,0 +1,64 @@
+
+#include <string.h>
+
+#include <talloc/talloc.h>
+
+#include "discover-server.h"
+#include "sysinfo.h"
+
+static struct system_info *sysinfo;
+static struct discover_server *server;
+
+const struct system_info *system_info_get(void)
+{
+       return sysinfo;
+}
+
+void system_info_register_interface(unsigned int hwaddr_size, uint8_t *hwaddr,
+               const char *name)
+{
+       struct interface_info *if_info;
+       unsigned int i;
+
+       for (i = 0; i < sysinfo->n_interfaces; i++) {
+               if_info = sysinfo->interfaces[i];
+
+               if (if_info->hwaddr_size != hwaddr_size)
+                       continue;
+
+               if (memcmp(if_info->hwaddr, hwaddr, hwaddr_size))
+                       continue;
+
+               /* update the name and we're done */
+               talloc_free(if_info->name);
+               if_info->name = talloc_strdup(if_info, name);
+               discover_server_notify_system_info(server, sysinfo);
+               return;
+       }
+
+       if_info = talloc_zero(sysinfo, struct interface_info);
+       if_info->hwaddr_size = hwaddr_size;
+       if_info->hwaddr = talloc_memdup(if_info, hwaddr, hwaddr_size);
+       if_info->name = talloc_strdup(if_info, name);
+
+       sysinfo->n_interfaces++;
+       sysinfo->interfaces = talloc_realloc(sysinfo, sysinfo->interfaces,
+                                               struct interface_info *,
+                                               sysinfo->n_interfaces);
+       sysinfo->interfaces[sysinfo->n_interfaces - 1] = if_info;
+
+       discover_server_notify_system_info(server, sysinfo);
+}
+
+static void system_info_set_identifier(struct system_info *info
+               __attribute__((unused)))
+{
+       /* todo: call helpers to set type & id */
+}
+
+void system_info_init(struct discover_server *s)
+{
+       sysinfo = talloc_zero(server, struct system_info);
+       server = s;
+       system_info_set_identifier(sysinfo);
+}
diff --git a/discover/sysinfo.h b/discover/sysinfo.h
new file mode 100644 (file)
index 0000000..2764784
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef SYSINFO_H
+#define SYSINFO_H
+
+#include <types/types.h>
+
+struct discover_server;
+
+const struct system_info *system_info_get(void);
+
+void system_info_register_interface(unsigned hwaddr_size, uint8_t *hwaddr,
+               const char *name);
+
+void system_info_init(struct discover_server *server);
+
+#endif /* SYSINFO_H */
+
index 681b250e20135ee334c0822a500eae0ea50f2973..46f1addb678421de99900e66629c1c37f9ae331b 100644 (file)
@@ -141,6 +141,18 @@ static int read_string(void *ctx, const char **pos, unsigned int *len,
        return 0;
 }
 
+static int read_u32(const char **pos, unsigned int *len, unsigned int *p)
+{
+       if (*len < sizeof(uint32_t))
+               return -1;
+
+       *p = (unsigned int)__be32_to_cpu(*(uint32_t *)(*pos));
+       *pos += sizeof(uint32_t);
+       *len -= sizeof(uint32_t);
+
+       return 0;
+}
+
 char *pb_protocol_deserialise_string(void *ctx,
                const struct pb_protocol_message *message)
 {
@@ -205,6 +217,23 @@ int pb_protocol_boot_status_len(const struct boot_status *status)
                4;
 }
 
+int pb_protocol_system_info_len(const struct system_info *sysinfo)
+{
+       unsigned int len, i;
+
+       len =   4 + optional_strlen(sysinfo->type) +
+               4 + optional_strlen(sysinfo->identifier) +
+               4;
+
+       for (i = 0; i < sysinfo->n_interfaces; i++) {
+               struct interface_info *if_info = sysinfo->interfaces[i];
+               len +=  4 + if_info->hwaddr_size +
+                       4 + optional_strlen(if_info->name);
+       }
+
+       return len;
+}
+
 int pb_protocol_serialise_device(const struct device *dev,
                char *buf, int buf_len)
 {
@@ -284,6 +313,36 @@ int pb_protocol_serialise_boot_status(const struct boot_status *status,
        return 0;
 }
 
+int pb_protocol_serialise_system_info(const struct system_info *sysinfo,
+               char *buf, int buf_len)
+{
+       char *pos = buf;
+       unsigned int i;
+
+       pos += pb_protocol_serialise_string(pos, sysinfo->type);
+       pos += pb_protocol_serialise_string(pos, sysinfo->identifier);
+
+       *(uint32_t *)pos = __cpu_to_be32(sysinfo->n_interfaces);
+       pos += sizeof(uint32_t);
+
+       for (i = 0; i < sysinfo->n_interfaces; i++) {
+               struct interface_info *if_info = sysinfo->interfaces[i];
+
+               *(uint32_t *)pos = __cpu_to_be32(if_info->hwaddr_size);
+               pos += sizeof(uint32_t);
+
+               memcpy(pos, if_info->hwaddr, if_info->hwaddr_size);
+               pos += if_info->hwaddr_size;
+
+               pos += pb_protocol_serialise_string(pos, if_info->name);
+       }
+
+       assert(pos <= buf + buf_len);
+       (void)buf_len;
+
+       return 0;
+}
+
 int pb_protocol_write_message(int fd, struct pb_protocol_message *message)
 {
        int total_len, rc;
@@ -536,3 +595,54 @@ int pb_protocol_deserialise_boot_status(struct boot_status *status,
 out:
        return rc;
 }
+
+int pb_protocol_deserialise_system_info(struct system_info *sysinfo,
+               const struct pb_protocol_message *message)
+{
+       unsigned int len, i;
+       const char *pos;
+       int rc = -1;
+
+       len = message->payload_len;
+       pos = message->payload;
+
+       /* type and identifier strings */
+       if (read_string(sysinfo, &pos, &len, &sysinfo->type))
+               goto out;
+
+       if (read_string(sysinfo, &pos, &len, &sysinfo->identifier))
+               goto out;
+
+       /* number of interfaces */
+       if (read_u32(&pos, &len, &sysinfo->n_interfaces))
+               goto out;
+
+       sysinfo->interfaces = talloc_array(sysinfo, struct interface_info *,
+                       sysinfo->n_interfaces);
+
+       for (i = 0; i < sysinfo->n_interfaces; i++) {
+               struct interface_info *if_info = talloc(sysinfo,
+                                                       struct interface_info);
+
+               if (read_u32(&pos, &len, &if_info->hwaddr_size))
+                       goto out;
+
+               if (len < if_info->hwaddr_size)
+                       goto out;
+
+               if_info->hwaddr = talloc_memdup(if_info, pos,
+                                               if_info->hwaddr_size);
+               pos += if_info->hwaddr_size;
+               len -= if_info->hwaddr_size;
+
+               if (read_string(if_info, &pos, &len, &if_info->name))
+                       goto out;
+
+               sysinfo->interfaces[i] = if_info;
+       }
+
+       rc = 0;
+
+out:
+       return rc;
+}
index aa79e668635e4613e8049aca171627dabe719b7c..5df7c7fe8bde57c83b4d144e291a2a71d9732e13 100644 (file)
@@ -19,6 +19,7 @@ enum pb_protocol_action {
        PB_PROTOCOL_ACTION_BOOT                 = 0x5,
        PB_PROTOCOL_ACTION_STATUS               = 0x6,
        PB_PROTOCOL_ACTION_CANCEL_DEFAULT       = 0x7,
+       PB_PROTOCOL_ACTION_SYSTEM_INFO          = 0x8,
 };
 
 struct pb_protocol_message {
@@ -33,6 +34,7 @@ int pb_protocol_device_len(const struct device *dev);
 int pb_protocol_boot_option_len(const struct boot_option *opt);
 int pb_protocol_boot_len(const struct boot_command *boot);
 int pb_protocol_boot_status_len(const struct boot_status *status);
+int pb_protocol_system_info_len(const struct system_info *sysinfo);
 int pb_protocol_device_cmp(const struct device *a, const struct device *b);
 
 int pb_protocol_boot_option_cmp(const struct boot_option *a,
@@ -50,6 +52,8 @@ int pb_protocol_serialise_boot_command(const struct boot_command *boot,
                char *buf, int buf_len);
 int pb_protocol_serialise_boot_status(const struct boot_status *status,
                char *buf, int buf_len);
+int pb_protocol_serialise_system_info(const struct system_info *sysinfo,
+               char *buf, int buf_len);
 
 int pb_protocol_write_message(int fd, struct pb_protocol_message *message);
 
@@ -70,4 +74,7 @@ int pb_protocol_deserialise_boot_command(struct boot_command *cmd,
 int pb_protocol_deserialise_boot_status(struct boot_status *status,
                const struct pb_protocol_message *message);
 
+int pb_protocol_deserialise_system_info(struct system_info *sysinfo,
+               const struct pb_protocol_message *message);
+
 #endif /* _PB_PROTOCOL_H */
index bb4b23ca5f601d61e083041580de45a53880eb63..9bb800ca4d125daa5d57169c8256e3d898eb05ea 100644 (file)
@@ -2,6 +2,7 @@
 #define _TYPES_H
 
 #include <stdbool.h>
+#include <stdint.h>
 #include <list/list.h>
 
 enum device_type {
@@ -59,4 +60,18 @@ struct boot_status {
        int     progress;
 };
 
+struct interface_info {
+       unsigned int    hwaddr_size;
+       uint8_t         *hwaddr;
+       char            *name;
+};
+
+struct system_info {
+       char                    *type;
+       char                    *identifier;
+       struct interface_info   **interfaces;
+       unsigned int            n_interfaces;
+};
+
+
 #endif /* _TYPES_H */
index c3f3f383f59fa0bf51f4d72ecf45482259a148db..90cd3b419101c051e35f5da1539eb975673c22ee 100644 (file)
@@ -118,10 +118,19 @@ static void update_status(struct discover_client *client,
        talloc_free(status);
 }
 
+static void update_sysinfo(struct discover_client *client,
+               struct system_info *sysinfo)
+{
+       if (client->ops.update_sysinfo)
+               client->ops.update_sysinfo(sysinfo, client->ops.cb_arg);
+       talloc_free(sysinfo);
+}
+
 static int discover_client_process(void *arg)
 {
        struct discover_client *client = arg;
        struct pb_protocol_message *message;
+       struct system_info *sysinfo;
        struct boot_status *status;
        struct boot_option *opt;
        struct device *dev;
@@ -175,6 +184,16 @@ static int discover_client_process(void *arg)
                }
                update_status(client, status);
                break;
+       case PB_PROTOCOL_ACTION_SYSTEM_INFO:
+               sysinfo = talloc_zero(client, struct system_info);
+
+               rc = pb_protocol_deserialise_system_info(sysinfo, message);
+               if (rc) {
+                       pb_log("%s: invalid sysinfo message?\n", __func__);
+                       return 0;
+               }
+               update_sysinfo(client, sysinfo);
+               break;
        default:
                pb_log("%s: unknown action %d\n", __func__, message->action);
        }
index ed1f504c4e59904ecbcd9d8ac5685b7b7b757e44..feca63b9eac324c2fd77a6005eda2979c25cf3fc 100644 (file)
@@ -26,6 +26,7 @@ struct discover_client_ops {
                        void *arg);
        void (*device_remove)(struct device *device, void *arg);
        void (*update_status)(struct boot_status *status, void *arg);
+       void (*update_sysinfo)(struct system_info *sysinfo, void *arg);
        void *cb_arg;
 };
 
index faf1d893677936fc9307b9329df8244ee33260d2..576f293f6b92881f2944baca4681cbcfc288a307 100644 (file)
@@ -82,11 +82,41 @@ static void print_status(struct boot_status *status,
 
 }
 
+static void print_sysinfo(struct system_info *sysinfo,
+       void __attribute__((unused)) *arg)
+{
+       unsigned int i;
+
+       printf("sysinfo:\n");
+       printf("\ttype:     %s\n", sysinfo->type);
+       printf("\tid:       %s\n", sysinfo->identifier);
+
+       if (sysinfo->n_interfaces == 0)
+               printf("\tno interfaces.\n");
+       else
+               printf("\tinterfaces:\n");
+
+       for (i = 0; i < sysinfo->n_interfaces; i++) {
+               struct interface_info *if_info = sysinfo->interfaces[i];
+               uint8_t *m = if_info->hwaddr;
+
+               printf("\t\tname:   %s\n", if_info->name);
+
+               if (if_info->hwaddr_size == 6)
+                       printf("\t\tmac:    %02x:%02x:%02x:%02x:%02x:%02x\n",
+                                       m[0], m[1], m[2], m[3], m[4], m[5]);
+               else
+                       printf("\t\tmac:    unknown hwaddr size %d\n",
+                                       if_info->hwaddr_size);
+       }
+}
+
 static struct discover_client_ops client_ops = {
        .device_add = print_device_add,
        .boot_option_add = print_boot_option_add,
        .device_remove = print_device_remove,
        .update_status = print_status,
+       .update_sysinfo = print_sysinfo,
 };
 
 int main(void)