lib/efi: Cleanup read/write routines
[petitboot] / discover / sysinfo.c
1
2 #include <string.h>
3
4 #include <talloc/talloc.h>
5 #include <process/process.h>
6 #include <log/log.h>
7 #include <url/url.h>
8
9 #include "discover-server.h"
10 #include "platform.h"
11 #include "sysinfo.h"
12
13 static struct system_info *sysinfo;
14 static struct discover_server *server;
15
16 const struct system_info *system_info_get(void)
17 {
18         return sysinfo;
19 }
20
21 void system_info_set_interface_address(unsigned int hwaddr_size,
22                 uint8_t *hwaddr, const char *address)
23 {
24         struct interface_info *if_info;
25         unsigned int i;
26         char mac[20], **if_addr, *new_addr, *subnet;
27
28         for (i = 0; i < sysinfo->n_interfaces; i++) {
29                 if_info = sysinfo->interfaces[i];
30
31                 if (if_info->hwaddr_size != hwaddr_size)
32                         continue;
33
34                 if (memcmp(if_info->hwaddr, hwaddr, hwaddr_size))
35                         continue;
36
37                 /*
38                  * Don't include the subnet from a static config, and check if
39                  * we're updating the IPv4 or IPv6 address.
40                  * */
41                 if ((subnet = strchr(address, '/')))
42                         new_addr = talloc_strndup(if_info, address, subnet - address);
43                 else
44                         new_addr = talloc_strdup(if_info, address);
45                 if (addr_scheme(new_addr) == AF_INET)
46                         if_addr = &if_info->address;
47                 else
48                         if_addr = &if_info->address_v6;
49
50                 /* Found an existing interface. Notify clients if a new address
51                  * is set */
52                 if (!*if_addr || strcmp(*if_addr, address)) {
53                         talloc_free(*if_addr);
54                         *if_addr = new_addr;
55                         discover_server_notify_system_info(server, sysinfo);
56                         return;
57                 }
58         }
59
60         mac_str(hwaddr, hwaddr_size, mac, sizeof(mac));
61         pb_log("Couldn't find interface matching %s\n", mac);
62 }
63
64 void system_info_register_interface(unsigned int hwaddr_size, uint8_t *hwaddr,
65                 const char *name, bool link)
66 {
67         struct interface_info *if_info;
68         unsigned int i;
69
70         for (i = 0; i < sysinfo->n_interfaces; i++) {
71                 bool changed = false;
72
73                 if_info = sysinfo->interfaces[i];
74
75                 if (if_info->hwaddr_size != hwaddr_size)
76                         continue;
77
78                 if (memcmp(if_info->hwaddr, hwaddr, hwaddr_size))
79                         continue;
80
81                 /* Found an existing interface. Notify clients on any name or
82                  * link changes */
83                 if (strcmp(if_info->name, name)) {
84                         talloc_free(if_info->name);
85                         if_info->name = talloc_strdup(if_info, name);
86                         changed = true;
87                 }
88
89                 if (if_info->link != link) {
90                         if_info->link = link;
91                         changed = true;
92                 }
93
94                 if (changed)
95                         discover_server_notify_system_info(server, sysinfo);
96
97                 return;
98         }
99
100         if_info = talloc_zero(sysinfo, struct interface_info);
101         if_info->hwaddr_size = hwaddr_size;
102         if_info->hwaddr = talloc_memdup(if_info, hwaddr, hwaddr_size);
103         if_info->name = talloc_strdup(if_info, name);
104         if_info->link = link;
105
106         sysinfo->n_interfaces++;
107         sysinfo->interfaces = talloc_realloc(sysinfo, sysinfo->interfaces,
108                                                 struct interface_info *,
109                                                 sysinfo->n_interfaces);
110         sysinfo->interfaces[sysinfo->n_interfaces - 1] = if_info;
111
112         discover_server_notify_system_info(server, sysinfo);
113 }
114
115 void system_info_register_blockdev(const char *name, const char *uuid,
116                 const char *mountpoint)
117 {
118         struct blockdev_info *bd_info;
119         unsigned int i;
120
121         for (i = 0; i < sysinfo->n_blockdevs; i++) {
122                 bd_info = sysinfo->blockdevs[i];
123
124                 if (strcmp(bd_info->name, name))
125                         continue;
126
127                 /* update the mountpoint and UUID, and we're done */
128                 talloc_free(bd_info->mountpoint);
129                 bd_info->uuid = talloc_strdup(bd_info, uuid);
130                 bd_info->mountpoint = talloc_strdup(bd_info, mountpoint);
131                 discover_server_notify_system_info(server, sysinfo);
132                 return;
133         }
134
135         bd_info = talloc_zero(sysinfo, struct blockdev_info);
136         bd_info->name = talloc_strdup(bd_info, name);
137         bd_info->uuid = talloc_strdup(bd_info, uuid);
138         bd_info->mountpoint = talloc_strdup(bd_info, mountpoint);
139
140         sysinfo->n_blockdevs++;
141         sysinfo->blockdevs = talloc_realloc(sysinfo, sysinfo->blockdevs,
142                                                 struct blockdev_info *,
143                                                 sysinfo->n_blockdevs);
144         sysinfo->blockdevs[sysinfo->n_blockdevs - 1] = bd_info;
145
146         discover_server_notify_system_info(server, sysinfo);
147 }
148
149 void system_info_init(struct discover_server *s)
150 {
151         server = s;
152         sysinfo = talloc_zero(server, struct system_info);
153         platform_get_sysinfo(sysinfo);
154 }
155
156 /* Only reset device information. Platform information is static */
157 void system_info_reinit(void)
158 {
159         unsigned int i;
160
161         for (i = 0; i < sysinfo->n_blockdevs; i++)
162                 talloc_free(sysinfo->blockdevs[i]);
163         talloc_free(sysinfo->blockdevs);
164         sysinfo->blockdevs = NULL;
165         sysinfo->n_blockdevs = 0;
166
167         for (i = 0; i < sysinfo->n_interfaces; i++)
168                 talloc_free(sysinfo->interfaces[i]);
169         talloc_free(sysinfo->interfaces);
170         sysinfo->interfaces = NULL;
171         sysinfo->n_interfaces = 0;
172 }