]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/confile_utils.c
network: add test-suite for configuration items
[mirror_lxc.git] / src / lxc / confile_utils.c
CommitLineData
0b843d35
CB
1/* liblxcapi
2 *
3 * Copyright © 2017 Christian Brauner <christian.brauner@ubuntu.com>.
4 * Copyright © 2017 Canonical Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2, as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
ce2f5ae8
CB
20#include "config.h"
21
0b843d35 22#include <stdio.h>
ce2f5ae8 23#include <stdlib.h>
0b843d35
CB
24#include <string.h>
25
663e9916 26#include "conf.h"
ce2f5ae8
CB
27#include "confile.h"
28#include "confile_utils.h"
29#include "error.h"
663e9916 30#include "log.h"
ce2f5ae8 31#include "list.h"
0b843d35
CB
32#include "utils.h"
33
ce2f5ae8
CB
34lxc_log_define(lxc_confile_utils, lxc);
35
0b843d35
CB
36int parse_idmaps(const char *idmap, char *type, unsigned long *nsid,
37 unsigned long *hostid, unsigned long *range)
38{
39 int ret = -1;
40 unsigned long tmp_hostid, tmp_nsid, tmp_range;
41 char tmp_type;
42 char *window, *slide;
43 char *dup = NULL;
44
45 /* Duplicate string. */
46 dup = strdup(idmap);
47 if (!dup)
48 goto on_error;
49
50 /* A prototypical idmap entry would be: "u 1000 1000000 65536" */
51
52 /* align */
53 slide = window = dup;
54 /* skip whitespace */
55 slide += strspn(slide, " \t\r");
56 if (slide != window && *slide == '\0')
57 goto on_error;
58
59 /* Validate type. */
60 if (*slide != 'u' && *slide != 'g')
61 goto on_error;
62 /* Assign type. */
63 tmp_type = *slide;
64
65 /* move beyond type */
66 slide++;
67 /* align */
68 window = slide;
69 /* Validate that only whitespace follows. */
70 slide += strspn(slide, " \t\r");
71 /* There must be whitespace. */
72 if (slide == window)
73 goto on_error;
74
75 /* Mark beginning of nsuid. */
76 window = slide;
77 /* Validate that non-whitespace follows. */
78 slide += strcspn(slide, " \t\r");
79 /* There must be non-whitespace. */
80 if (slide == window || *slide == '\0')
81 goto on_error;
82 /* Mark end of nsuid. */
83 *slide = '\0';
84
85 /* Parse nsuid. */
86 if (lxc_safe_ulong(window, &tmp_nsid) < 0)
87 goto on_error;
88
89 /* Move beyond \0. */
90 slide++;
91 /* align */
92 window = slide;
93 /* Validate that only whitespace follows. */
94 slide += strspn(slide, " \t\r");
95 /* If there was only one whitespace then we whiped it with our \0 above.
96 * So only ensure that we're not at the end of the string.
97 */
98 if (*slide == '\0')
99 goto on_error;
100
101 /* Mark beginning of hostid. */
102 window = slide;
103 /* Validate that non-whitespace follows. */
104 slide += strcspn(slide, " \t\r");
105 /* There must be non-whitespace. */
106 if (slide == window || *slide == '\0')
107 goto on_error;
108 /* Mark end of nsuid. */
109 *slide = '\0';
110
111 /* Parse hostid. */
112 if (lxc_safe_ulong(window, &tmp_hostid) < 0)
113 goto on_error;
114
115 /* Move beyond \0. */
116 slide++;
117 /* align */
118 window = slide;
119 /* Validate that only whitespace follows. */
120 slide += strspn(slide, " \t\r");
121 /* If there was only one whitespace then we whiped it with our \0 above.
122 * So only ensure that we're not at the end of the string.
123 */
124 if (*slide == '\0')
125 goto on_error;
126
127 /* Mark beginning of range. */
128 window = slide;
129 /* Validate that non-whitespace follows. */
130 slide += strcspn(slide, " \t\r");
131 /* There must be non-whitespace. */
132 if (slide == window)
133 goto on_error;
134
135 /* The range is the last valid entry we expect. So make sure that there
136 * is not trailing garbage and if there is, error out.
137 */
138 if (*(slide + strspn(slide, " \t\r\n")) != '\0')
139 goto on_error;
140 /* Mark end of range. */
141 *slide = '\0';
142
143 /* Parse range. */
144 if (lxc_safe_ulong(window, &tmp_range) < 0)
145 goto on_error;
146
147 *type = tmp_type;
148 *nsid = tmp_nsid;
149 *hostid = tmp_hostid;
150 *range = tmp_range;
151
152 /* Yay, we survived. */
153 ret = 0;
154
155on_error:
156 free(dup);
157
158 return ret;
159}
663e9916
CB
160
161bool lxc_config_value_empty(const char *value)
162{
163 if (value && strlen(value) > 0)
164 return false;
165
166 return true;
167}
ce2f5ae8 168
ce2f5ae8
CB
169/* Takes care of finding the correct netdev struct in the networks list or
170 * allocates a new one if it couldn't be found.
171 */
172struct lxc_netdev *lxc_get_netdev_by_idx(struct lxc_conf *conf,
0070b1c4 173 unsigned int idx, bool allocate)
ce2f5ae8
CB
174{
175 struct lxc_list *newlist;
176 struct lxc_netdev *netdev = NULL;
177 struct lxc_list *networks = &conf->network;
178 struct lxc_list *insert = networks;
179
180 /* lookup network */
0070b1c4
CB
181 if (!lxc_list_empty(networks)) {
182 lxc_list_for_each(insert, networks) {
183 netdev = insert->elem;
184 if (netdev->idx >= idx)
185 break;
186 }
187
188 /* network already exists */
189 if (netdev->idx == idx)
190 return netdev;
191 }
192
193 if (!allocate)
194 return NULL;
ce2f5ae8
CB
195
196 /* network does not exist */
197 netdev = malloc(sizeof(*netdev));
198 if (!netdev)
199 return NULL;
200
201 memset(netdev, 0, sizeof(*netdev));
202 lxc_list_init(&netdev->ipv4);
203 lxc_list_init(&netdev->ipv6);
204
205 /* give network a unique index */
206 netdev->idx = idx;
207
208 /* prepare new list */
209 newlist = malloc(sizeof(*newlist));
210 if (!newlist) {
211 free(netdev);
212 return NULL;
213 }
214
215 lxc_list_init(newlist);
216 newlist->elem = netdev;
217
218 /* Insert will now point to the correct position to insert the new
219 * netdev.
220 */
221 lxc_list_add_tail(insert, newlist);
222
223 return netdev;
224}
1ed6ba91
CB
225
226void lxc_log_configured_netdevs(const struct lxc_conf *conf)
227{
228 struct lxc_netdev *netdev;
229 struct lxc_list *it = (struct lxc_list *)&conf->network;;
230
231 if ((conf->loglevel != LXC_LOG_LEVEL_TRACE) &&
232 (lxc_log_get_level() != LXC_LOG_LEVEL_TRACE))
233 return;
234
235 if (lxc_list_empty(it)) {
236 TRACE("container has no networks configured");
237 return;
238 }
239
240 lxc_list_for_each(it, &conf->network) {
241 netdev = it->elem;
242
243 TRACE("index: %d", netdev->idx);
244 switch (netdev->type) {
245 case LXC_NET_VETH:
246 TRACE("type: veth");
247 break;
248 case LXC_NET_MACVLAN:
249 TRACE("type: macvlan");
250 break;
251 case LXC_NET_VLAN:
252 TRACE("type: vlan");
253 break;
254 case LXC_NET_PHYS:
255 TRACE("type: phys");
256 break;
257 case LXC_NET_EMPTY:
258 TRACE("type: empty");
259 break;
260 case LXC_NET_NONE:
261 TRACE("type: none");
262 break;
263 default:
264 ERROR("invalid network type %d", netdev->type);
265 return;
266 }
267
268 TRACE("flags: %s", netdev->flags == IFF_UP ? "up" : "none");
269 if (netdev->link)
270 TRACE("link: %s", netdev->link);
271 if (netdev->name)
272 TRACE("name: %s", netdev->name);
273 if (netdev->hwaddr)
274 TRACE("hwaddr: %s", netdev->hwaddr);
275 if (netdev->mtu)
276 TRACE("mtu: %s", netdev->mtu);
277 if (netdev->upscript)
278 TRACE("upscript: %s", netdev->upscript);
279 if (netdev->downscript)
280 TRACE("downscript: %s", netdev->downscript);
281 }
282}
519df1c1 283
e5d2fd7c
CB
284static void lxc_free_netdev(struct lxc_netdev *netdev)
285{
286 struct lxc_list *cur, *next;
287
288 free(netdev->link);
289 free(netdev->name);
290 if (netdev->type == LXC_NET_VETH)
291 free(netdev->priv.veth_attr.pair);
292 free(netdev->upscript);
293 free(netdev->downscript);
294 free(netdev->hwaddr);
295 free(netdev->mtu);
296
297 free(netdev->ipv4_gateway);
298 lxc_list_for_each_safe(cur, &netdev->ipv4, next) {
299 lxc_list_del(cur);
300 free(cur->elem);
301 free(cur);
302 }
303
304 free(netdev->ipv6_gateway);
305 lxc_list_for_each_safe(cur, &netdev->ipv6, next) {
306 lxc_list_del(cur);
307 free(cur->elem);
308 free(cur);
309 }
310
311 free(netdev);
312}
313
519df1c1
CB
314bool lxc_remove_nic_by_idx(struct lxc_conf *conf, unsigned int idx)
315{
e5d2fd7c 316 struct lxc_list *cur, *next;
519df1c1
CB
317 struct lxc_netdev *netdev;
318 bool found = false;
319
320 lxc_list_for_each_safe(cur, &conf->network, next) {
321 netdev = cur->elem;
322 if (netdev->idx != idx)
323 continue;
324
325 lxc_list_del(cur);
326 found = true;
327 break;
328 }
329
330 if (!found)
331 return false;
332
e5d2fd7c 333 lxc_free_netdev(netdev);
519df1c1
CB
334 free(cur);
335
336 return true;
337}
e5d2fd7c
CB
338
339void lxc_free_networks(struct lxc_conf *conf)
340{
341 struct lxc_list *cur, *next;
342 struct lxc_netdev *netdev;
343
344 lxc_list_for_each_safe(cur, &conf->network, next) {
345 netdev = cur->elem;
346 lxc_free_netdev(netdev);
347 free(cur);
348 }
349
350 /* prevent segfaults */
351 lxc_list_init(&conf->network);
352}