2 * Copyright (C) 2013 IBM Corporation
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <pb-config/pb-config.h>
25 #include <talloc/talloc.h>
26 #include <types/types.h>
31 #include "nc-config.h"
32 #include "nc-widgets.h"
37 NET_CONF_TYPE_DHCP_ALL,
38 NET_CONF_TYPE_DHCP_ONE,
42 struct config_screen {
45 struct nc_widgetset *widgetset;
47 void (*on_exit)(struct cui *);
54 struct nc_widget_checkbox *autoboot_f;
55 struct nc_widget_label *autoboot_l;
56 struct nc_widget_textbox *timeout_f;
57 struct nc_widget_label *timeout_l;
59 struct nc_widget_label *network_l;
60 struct nc_widget_select *network_f;
62 struct nc_widget_label *iface_l;
63 struct nc_widget_select *iface_f;
64 struct nc_widget_label *ip_addr_l;
65 struct nc_widget_textbox *ip_addr_f;
66 struct nc_widget_label *ip_mask_l;
67 struct nc_widget_textbox *ip_mask_f;
68 struct nc_widget_label *gateway_l;
69 struct nc_widget_textbox *gateway_f;
70 struct nc_widget_label *dns_l;
71 struct nc_widget_textbox *dns_f;
73 struct nc_widget_button *ok_b;
74 struct nc_widget_button *cancel_b;
78 static struct config_screen *config_screen_from_scr(struct nc_scr *scr)
80 struct config_screen *config_screen;
82 assert(scr->sig == pb_config_screen_sig);
83 config_screen = (struct config_screen *)
84 ((char *)scr - (size_t)&((struct config_screen *)0)->scr);
85 assert(config_screen->scr.sig == pb_config_screen_sig);
89 static void config_screen_process_key(struct nc_scr *scr, int key)
91 struct config_screen *screen = config_screen_from_scr(scr);
94 handled = widgetset_process_key(screen->widgetset, key);
96 screen->on_exit(screen->cui);
98 wrefresh(screen->scr.main_ncw);
101 static void config_screen_resize(struct nc_scr *scr)
103 struct config_screen *screen = config_screen_from_scr(scr);
107 static int config_screen_post(struct nc_scr *scr)
109 struct config_screen *screen = config_screen_from_scr(scr);
110 widgetset_post(screen->widgetset);
111 nc_scr_frame_draw(scr);
112 wrefresh(scr->main_ncw);
116 static int config_screen_unpost(struct nc_scr *scr)
118 struct config_screen *screen = config_screen_from_scr(scr);
119 widgetset_unpost(screen->widgetset);
123 struct nc_scr *config_screen_scr(struct config_screen *screen)
128 static int screen_process_form(struct config_screen *screen)
130 const struct system_info *sysinfo = screen->cui->sysinfo;
131 struct config *config = talloc_zero(screen, struct config);
132 enum net_conf_type net_conf_type;
133 struct interface_config *iface;
137 config_set_defaults(config);
139 config->autoboot_enabled =
140 widget_checkbox_get_value(screen->widgets.autoboot_f);
143 str = widget_textbox_get_value(screen->widgets.timeout_f);
147 x = strtoul(str, &end, 10);
148 if (!errno && end != str)
149 config->autoboot_timeout_sec = x;
152 net_conf_type = widget_select_get_value(screen->widgets.network_f);
154 /* if we don't have any network interfaces, prevent per-interface
156 if (sysinfo->n_interfaces == 0)
157 net_conf_type = NET_CONF_TYPE_DHCP_ALL;
159 if (net_conf_type == NET_CONF_TYPE_DHCP_ALL) {
160 config->network.n_interfaces = 0;
165 iface = talloc_zero(config, struct interface_config);
166 config->network.n_interfaces = 1;
167 config->network.interfaces = talloc_array(config,
168 struct interface_config *, 1);
169 config->network.interfaces[0] = iface;
171 /* copy hwaddr (from the sysinfo interface data) to
172 * the configuration */
173 idx = widget_select_get_value(screen->widgets.iface_f);
174 memcpy(iface->hwaddr, sysinfo->interfaces[idx]->hwaddr,
175 sizeof(iface->hwaddr));
178 if (net_conf_type == NET_CONF_TYPE_DHCP_ONE) {
179 iface->method = CONFIG_METHOD_DHCP;
182 if (net_conf_type == NET_CONF_TYPE_STATIC) {
183 iface->method = CONFIG_METHOD_STATIC;
184 iface->static_config.address = talloc_asprintf(iface, "%s/%s",
185 widget_textbox_get_value(
186 screen->widgets.ip_addr_f),
187 widget_textbox_get_value(
188 screen->widgets.ip_mask_f));
189 iface->static_config.gateway = talloc_strdup(iface,
190 widget_textbox_get_value(
191 screen->widgets.gateway_f));
194 str = widget_textbox_get_value(screen->widgets.dns_f);
195 if (str && strlen(str)) {
200 dns = strtok_r(str, " \t", &tmp);
205 i = config->network.n_dns_servers++;
206 config->network.dns_servers = talloc_realloc(config,
207 config->network.dns_servers,
209 config->network.n_dns_servers);
210 config->network.dns_servers[i] =
211 talloc_strdup(config, dns);
217 rc = cui_send_config(screen->cui, config);
221 pb_log("cui_send_config failed!\n");
223 pb_debug("config sent!\n");
228 static void ok_click(void *arg)
230 struct config_screen *screen = arg;
231 screen_process_form(screen);
235 static void cancel_click(void *arg)
237 struct config_screen *screen = arg;
241 static int layout_pair(struct config_screen *screen, int y,
242 struct nc_widget_label *label,
243 struct nc_widget *field)
245 struct nc_widget *label_w = widget_label_base(label);
246 widget_move(label_w, y, screen->label_x);
247 widget_move(field, y, screen->field_x);
248 return max(widget_height(label_w), widget_height(field));
251 static void config_screen_layout_widgets(struct config_screen *screen,
252 enum net_conf_type net_conf)
254 struct nc_widget *wl, *wf;
260 y += layout_pair(screen, y, screen->widgets.autoboot_l,
261 widget_checkbox_base(screen->widgets.autoboot_f));
263 y += layout_pair(screen, y, screen->widgets.timeout_l,
264 widget_textbox_base(screen->widgets.timeout_f));
268 y += layout_pair(screen, y, screen->widgets.network_l,
269 widget_select_base(screen->widgets.network_f));
273 /* conditionally show iface select */
274 wl = widget_label_base(screen->widgets.iface_l);
275 wf = widget_select_base(screen->widgets.iface_f);
277 show = net_conf == NET_CONF_TYPE_DHCP_ONE ||
278 net_conf == NET_CONF_TYPE_STATIC;
280 widget_set_visible(wl, show);
281 widget_set_visible(wf, show);
284 y += layout_pair(screen, y, screen->widgets.iface_l, wf) + 1;
286 /* conditionally show static IP params */
287 show = net_conf == NET_CONF_TYPE_STATIC;
289 wl = widget_label_base(screen->widgets.ip_addr_l);
290 wf = widget_textbox_base(screen->widgets.ip_addr_f);
291 widget_set_visible(wl, show);
292 widget_set_visible(wf, show);
293 x = screen->field_x + widget_width(wf) + 1;
296 layout_pair(screen, y, screen->widgets.ip_addr_l, wf);
298 wl = widget_label_base(screen->widgets.ip_mask_l);
299 wf = widget_textbox_base(screen->widgets.ip_mask_f);
300 widget_set_visible(wl, show);
301 widget_set_visible(wf, show);
304 widget_move(wl, y, x);
305 widget_move(wf, y, x + 2);
309 wl = widget_label_base(screen->widgets.gateway_l);
310 wf = widget_textbox_base(screen->widgets.gateway_f);
311 widget_set_visible(wl, show);
312 widget_set_visible(wf, show);
315 y += layout_pair(screen, y, screen->widgets.gateway_l, wf);
317 y += 1 + layout_pair(screen, y, screen->widgets.dns_l,
318 widget_textbox_base(screen->widgets.dns_f));
320 widget_move(widget_button_base(screen->widgets.ok_b),
322 widget_move(widget_button_base(screen->widgets.cancel_b),
323 y, screen->field_x + 10);
326 static void config_screen_network_change(void *arg, int value)
328 struct config_screen *screen = arg;
329 widgetset_unpost(screen->widgetset);
330 config_screen_layout_widgets(screen, value);
331 widgetset_post(screen->widgetset);
334 static void config_screen_setup_widgets(struct config_screen *screen,
335 const struct config *config,
336 const struct system_info *sysinfo)
338 struct nc_widgetset *set = screen->widgetset;
342 build_assert(sizeof(screen->widgets) / sizeof(struct widget *)
345 screen->widgets.autoboot_l = widget_new_label(set, 0, 0, "Autoboot:");
346 screen->widgets.autoboot_f = widget_new_checkbox(set, 0, 0,
347 config->autoboot_enabled);
349 str = talloc_asprintf(screen, "%d", config->autoboot_timeout_sec);
350 screen->widgets.timeout_l = widget_new_label(set, 0, 0, "Timeout:");
351 screen->widgets.timeout_f = widget_new_textbox(set, 0, 0, 5, str);
353 screen->widgets.network_l = widget_new_label(set, 0, 0, "Network");
354 screen->widgets.network_f = widget_new_select(set, 0, 0, 50);
356 widget_select_add_option(screen->widgets.network_f,
357 NET_CONF_TYPE_DHCP_ALL,
358 "DHCP on all active interfaces",
360 widget_select_add_option(screen->widgets.network_f,
361 NET_CONF_TYPE_DHCP_ONE,
362 "DHCP on a specific interface",
364 widget_select_add_option(screen->widgets.network_f,
365 NET_CONF_TYPE_STATIC,
366 "Static IP configuration",
369 widget_select_on_change(screen->widgets.network_f,
370 config_screen_network_change, screen);
372 screen->widgets.iface_l = widget_new_label(set, 0, 0, "Device:");
373 screen->widgets.iface_f = widget_new_select(set, 0, 0, 20);
375 for (i = 0; i < sysinfo->n_interfaces; i++) {
376 struct interface_info *info = sysinfo->interfaces[i];
377 widget_select_add_option(screen->widgets.iface_f,
378 i, info->name, false);
381 screen->widgets.ip_addr_l = widget_new_label(set, 0, 0, "IP/mask:");
382 screen->widgets.ip_addr_f = widget_new_textbox(set, 0, 0, 16, "");
383 screen->widgets.ip_mask_l = widget_new_label(set, 0, 0, "/");
384 screen->widgets.ip_mask_f = widget_new_textbox(set, 0, 0, 3, "");
386 screen->widgets.gateway_l = widget_new_label(set, 0, 0, "Gateway:");
387 screen->widgets.gateway_f = widget_new_textbox(set, 0, 0, 16, "");
389 screen->widgets.dns_l = widget_new_label(set, 0, 0, "DNS Server:");
390 screen->widgets.dns_f = widget_new_textbox(set, 0, 0, 16, "");
392 screen->widgets.ok_b = widget_new_button(set, 0, 0, 6, "OK",
394 screen->widgets.cancel_b = widget_new_button(set, 0, 0, 6, "Cancel",
395 cancel_click, screen);
398 struct config_screen *config_screen_init(struct cui *cui,
399 const struct config *config,
400 const struct system_info *sysinfo,
401 void (*on_exit)(struct cui *))
403 struct config_screen *screen;
405 screen = talloc_zero(cui, struct config_screen);
406 nc_scr_init(&screen->scr, pb_config_screen_sig, 0,
407 cui, config_screen_process_key,
408 config_screen_post, config_screen_unpost,
409 config_screen_resize);
412 screen->on_exit = on_exit;
414 screen->field_x = 16;
416 screen->scr.frame.ltitle = talloc_strdup(screen,
417 "Petitboot System Configuration");
418 screen->scr.frame.rtitle = NULL;
419 screen->scr.frame.help = talloc_strdup(screen,
420 "tab=next, shift+tab=previous");
421 nc_scr_frame_draw(&screen->scr);
423 screen->widgetset = widgetset_create(screen, screen->scr.main_ncw,
424 screen->scr.sub_ncw);
425 config_screen_setup_widgets(screen, config, sysinfo);
426 config_screen_layout_widgets(screen, NET_CONF_TYPE_DHCP_ALL);
428 wrefresh(screen->scr.main_ncw);
429 scrollok(screen->scr.sub_ncw, true);