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