[PATCH 7/7] ui/ncurses: Allow user to configure IPv6 addresses
Samuel Mendoza-Jonas
sam at mendozajonas.com
Wed May 9 15:37:05 AEST 2018
Add an option to switch between IPv4 and IPv6 address schemes. For now
only support IPv4 /or/ IPv6, not a combination.
Signed-off-by: Samuel Mendoza-Jonas <sam at mendozajonas.com>
---
ui/ncurses/nc-config.c | 114 +++++++++++++++++++++++++++++++++++-----
ui/ncurses/nc-widgets.c | 67 ++++++++++++++++++++++-
ui/ncurses/nc-widgets.h | 4 ++
3 files changed, 171 insertions(+), 14 deletions(-)
diff --git a/ui/ncurses/nc-config.c b/ui/ncurses/nc-config.c
index 5c0f23b..e2c9887 100644
--- a/ui/ncurses/nc-config.c
+++ b/ui/ncurses/nc-config.c
@@ -33,7 +33,7 @@
#include "nc-config.h"
#include "nc-widgets.h"
-#define N_FIELDS 48
+#define N_FIELDS 50
extern struct help_text config_help_text;
@@ -89,6 +89,9 @@ struct config_screen {
struct nc_widget_label *network_l;
struct nc_widget_select *network_f;
+ struct nc_widget_label *net_addr_type_l;
+ struct nc_widget_select *net_addr_type_f;
+
struct nc_widget_label *iface_l;
struct nc_widget_select *iface_f;
struct nc_widget_label *ip_addr_l;
@@ -258,6 +261,11 @@ static int screen_process_form(struct config_screen *screen)
net_conf_type = widget_select_get_value(screen->widgets.network_f);
+ if (widget_select_get_value(screen->widgets.net_addr_type_f) == ADDR_IPV6)
+ config->network.addr_type = ADDR_IPV6;
+ else
+ config->network.addr_type = ADDR_IPV4;
+
/* if we don't have any network interfaces, prevent per-interface
* configuration */
if (sysinfo->n_interfaces == 0)
@@ -527,6 +535,11 @@ static void config_screen_layout_widgets(struct config_screen *screen)
y += 1;
+ y += layout_pair(screen, y, screen->widgets.net_addr_type_l,
+ widget_select_base(screen->widgets.net_addr_type_f));
+
+ y += 1;
+
/* conditionally show iface select */
wl = widget_label_base(screen->widgets.iface_l);
wf = widget_select_base(screen->widgets.iface_f);
@@ -674,6 +687,46 @@ static void config_screen_layout_widgets(struct config_screen *screen)
y, screen->field_x + 28);
}
+static void config_screen_net_addr_change(void *arg, int value)
+{
+ struct config_screen *screen = arg;
+
+ widgetset_unpost(screen->widgetset);
+
+ if (value == ADDR_IPV4) {
+ widget_textbox_set_validator_ipv4(screen->widgets.ip_addr_f);
+ widget_textbox_set_validator_integer(screen->widgets.ip_mask_f,
+ 1, 31);
+ widget_update_label(screen->widgets.ip_addr_mask_help_l,
+ _("(eg. 192.168.0.10 / 24)"));
+
+ widget_textbox_set_validator_ipv4(screen->widgets.gateway_f);
+ widget_update_label(screen->widgets.gateway_help_l,
+ _("(eg. 192.168.0.1)"));
+
+ widget_textbox_set_validator_ipv4_multi(screen->widgets.dns_f);
+ widget_update_label(screen->widgets.dns_help_l,
+ _("(eg. 192.168.0.2)"));
+ } else {
+ widget_textbox_set_validator_ipv6(screen->widgets.ip_addr_f);
+ widget_textbox_set_validator_integer(screen->widgets.ip_mask_f,
+ 1, 127);
+ widget_update_label(screen->widgets.ip_addr_mask_help_l,
+ _("(eg. fd69:d75f::27 / 64)"));
+
+ widget_textbox_set_validator_ipv6(screen->widgets.gateway_f);
+ widget_update_label(screen->widgets.gateway_help_l,
+ _("(eg. fd69:d75f::1)"));
+
+ widget_textbox_set_validator_ipv6_multi(screen->widgets.dns_f);
+ widget_update_label(screen->widgets.dns_help_l,
+ _("(eg. fd69:d75f::2)"));
+ }
+
+ config_screen_layout_widgets(screen);
+ widgetset_post(screen->widgetset);
+}
+
static void config_screen_network_change(void *arg, int value)
{
struct config_screen *screen = arg;
@@ -979,6 +1032,21 @@ static void config_screen_setup_widgets(struct config_screen *screen,
widget_select_on_change(screen->widgets.network_f,
config_screen_network_change, screen);
+ screen->widgets.net_addr_type_l = widget_new_label(set, 0, 0,
+ _("IP Scheme:"));
+ screen->widgets.net_addr_type_f = widget_new_select(set, 0, 0,
+ COLS - screen->field_x - 1);
+
+ widget_select_add_option(screen->widgets.net_addr_type_f,
+ ADDR_IPV4, _("IPv4"),
+ config->network.addr_type == ADDR_IPV4);
+ widget_select_add_option(screen->widgets.net_addr_type_f,
+ ADDR_IPV6, _("IPv6"),
+ config->network.addr_type == ADDR_IPV6);
+
+ widget_select_on_change(screen->widgets.net_addr_type_f,
+ config_screen_net_addr_change, screen);
+
screen->widgets.iface_l = widget_new_label(set, 0, 0, _("Device:"));
screen->widgets.iface_f = widget_new_select(set, 0, 0, 50);
@@ -1024,21 +1092,36 @@ static void config_screen_setup_widgets(struct config_screen *screen,
screen->widgets.ip_addr_f = widget_new_textbox(set, 0, 0, 16, ip);
screen->widgets.ip_mask_l = widget_new_label(set, 0, 0, "/");
screen->widgets.ip_mask_f = widget_new_textbox(set, 0, 0, 3, mask);
- screen->widgets.ip_addr_mask_help_l =
- widget_new_label(set, 0, 0, _("(eg. 192.168.0.10 / 24)"));
widget_textbox_set_fixed_size(screen->widgets.ip_addr_f);
widget_textbox_set_fixed_size(screen->widgets.ip_mask_f);
- widget_textbox_set_validator_ipv4(screen->widgets.ip_addr_f);
- widget_textbox_set_validator_integer(screen->widgets.ip_mask_f, 1, 31);
+ if (config->network.addr_type == ADDR_IPV4) {
+ screen->widgets.ip_addr_mask_help_l =
+ widget_new_label(set, 0, 0, _("(eg. 192.168.0.10 / 24)"));
+ widget_textbox_set_validator_ipv4(screen->widgets.ip_addr_f);
+ widget_textbox_set_validator_integer(screen->widgets.ip_mask_f,
+ 1, 31);
+ } else {
+ screen->widgets.ip_addr_mask_help_l =
+ widget_new_label(set, 0, 0, _("(eg. fd69:d75f::27 / 64)"));
+ widget_textbox_set_validator_ipv6(screen->widgets.ip_addr_f);
+ widget_textbox_set_validator_integer(screen->widgets.ip_mask_f,
+ 1, 127);
+ }
screen->widgets.gateway_l = widget_new_label(set, 0, 0, _("Gateway:"));
screen->widgets.gateway_f = widget_new_textbox(set, 0, 0, 16, gw);
- screen->widgets.gateway_help_l =
- widget_new_label(set, 0, 0, _("(eg. 192.168.0.1)"));
-
widget_textbox_set_fixed_size(screen->widgets.gateway_f);
- widget_textbox_set_validator_ipv4(screen->widgets.gateway_f);
+ if (config->network.addr_type == ADDR_IPV4) {
+ widget_textbox_set_validator_ipv4(screen->widgets.gateway_f);
+ screen->widgets.gateway_help_l =
+ widget_new_label(set, 0, 0, _("(eg. 192.168.0.1)"));
+ } else {
+ widget_textbox_set_validator_ipv6(screen->widgets.gateway_f);
+ screen->widgets.gateway_help_l =
+ widget_new_label(set, 0, 0, _("(eg. fd69:d75f::1)"));
+ }
+
screen->widgets.url_l = widget_new_label(set, 0, 0, _("URL:"));
screen->widgets.url_f = widget_new_textbox(set, 0, 0, 32, url);
@@ -1056,10 +1139,15 @@ static void config_screen_setup_widgets(struct config_screen *screen,
screen->widgets.dns_l = widget_new_label(set, 0, 0,
_("DNS Server(s):"));
screen->widgets.dns_f = widget_new_textbox(set, 0, 0, 32, str);
- screen->widgets.dns_help_l =
- widget_new_label(set, 0, 0, _("(eg. 192.168.0.2)"));
-
- widget_textbox_set_validator_ipv4_multi(screen->widgets.dns_f);
+ if (config->network.addr_type == ADDR_IPV4) {
+ screen->widgets.dns_help_l =
+ widget_new_label(set, 0, 0, _("(eg. 192.168.0.2)"));
+ widget_textbox_set_validator_ipv4_multi(screen->widgets.dns_f);
+ } else {
+ screen->widgets.dns_help_l =
+ widget_new_label(set, 0, 0, _("(eg. fd69:d75f::2)"));
+ widget_textbox_set_validator_ipv6_multi(screen->widgets.dns_f);
+ }
screen->widgets.dns_dhcp_help_l = widget_new_label(set, 0, 0,
_("(if not provided by DHCP server)"));
diff --git a/ui/ncurses/nc-widgets.c b/ui/ncurses/nc-widgets.c
index 93c882b..d17d79d 100644
--- a/ui/ncurses/nc-widgets.c
+++ b/ui/ncurses/nc-widgets.c
@@ -44,8 +44,9 @@
# error "Curses form.h not found."
#endif
-#include <string.h>
+#include <arpa/inet.h>
#include <ctype.h>
+#include <string.h>
#include <talloc/talloc.h>
#include <types/types.h>
@@ -84,6 +85,8 @@ struct nc_widgetset {
/* custom validators */
FIELDTYPE *ipv4_multi_type;
+ FIELDTYPE *ipv6_multi_type;
+ FIELDTYPE *ipv6_type;
FIELDTYPE *url_type;
};
@@ -196,6 +199,10 @@ static int label_destructor(void *ptr)
return 0;
}
+void widget_update_label(struct nc_widget_label *label, char *str)
+{
+ set_field_buffer(label->widget.field, 0, str);
+}
struct nc_widget_label *widget_new_label(struct nc_widgetset *set,
int y, int x, char *str)
@@ -415,11 +422,59 @@ void widget_textbox_set_validator_url(struct nc_widget_textbox *textbox)
set_field_type(textbox->widget.field, textbox->set->url_type);
}
+static bool check_ipv6_field(FIELD *field,
+ const void *arg __attribute__((unused)))
+{
+ uint8_t addr[sizeof(struct in6_addr)];
+ int rc;
+
+ rc = inet_pton(AF_INET6, strip_string(field_buffer(field, 0)), addr);
+
+ return rc == 1;
+}
+
+void widget_textbox_set_validator_ipv6(struct nc_widget_textbox *textbox)
+{
+ if (!textbox->set->ipv6_type) {
+ textbox->set->ipv6_type = new_fieldtype(check_ipv6_field, NULL);
+ }
+ set_field_type(textbox->widget.field, textbox->set->ipv6_type);
+}
+
void widget_textbox_set_validator_ipv4(struct nc_widget_textbox *textbox)
{
set_field_type(textbox->widget.field, TYPE_IPV4);
}
+static bool check_ipv6_multi_char(int c,
+ const void *arg __attribute__((unused)))
+{
+ return isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ||
+ c == ':' || c == ' ';
+}
+
+static bool check_ipv6_multi_field(FIELD *field,
+ const void *arg __attribute__((unused)))
+{
+ char *tok, *saveptr, *str;
+ uint8_t addr[INET6_ADDRSTRLEN];
+ int rc;
+
+ str = field_buffer(field, 0);
+ tok = strtok_r(str, " ", &saveptr);
+ if (!tok || *tok == '\0')
+ return false;
+
+ while (tok) {
+ rc = inet_pton(AF_INET6, tok, addr);
+ if (rc != 1)
+ return false;
+ tok = strtok_r(NULL, " ", &saveptr);
+ }
+
+ return true;
+}
+
static bool check_ipv4_multi_char(int c,
const void *arg __attribute__((unused)))
{
@@ -455,6 +510,16 @@ static bool check_ipv4_multi_field(FIELD *field,
return true;
}
+void widget_textbox_set_validator_ipv6_multi(struct nc_widget_textbox *textbox)
+{
+ if (!textbox->set->ipv6_multi_type) {
+ textbox->set->ipv6_multi_type = new_fieldtype(
+ check_ipv6_multi_field,
+ check_ipv6_multi_char);
+ }
+ set_field_type(textbox->widget.field, textbox->set->ipv6_multi_type);
+}
+
void widget_textbox_set_validator_ipv4_multi(struct nc_widget_textbox *textbox)
{
if (!textbox->set->ipv4_multi_type) {
diff --git a/ui/ncurses/nc-widgets.h b/ui/ncurses/nc-widgets.h
index aa9263f..217215a 100644
--- a/ui/ncurses/nc-widgets.h
+++ b/ui/ncurses/nc-widgets.h
@@ -37,11 +37,15 @@ struct nc_widget_button *widget_new_button(struct nc_widgetset *set,
int y, int x, int size, const char *str,
void (*click)(void *), void *arg);
+void widget_update_label(struct nc_widget_label *label, char *str);
+
void widget_textbox_set_fixed_size(struct nc_widget_textbox *textbox);
void widget_textbox_set_validator_integer(struct nc_widget_textbox *textbox,
long min, long max);
void widget_textbox_set_validator_ipv4(struct nc_widget_textbox *textbox);
void widget_textbox_set_validator_ipv4_multi(struct nc_widget_textbox *textbox);
+void widget_textbox_set_validator_ipv6(struct nc_widget_textbox *textbox);
+void widget_textbox_set_validator_ipv6_multi(struct nc_widget_textbox *textbox);
void widget_textbox_set_validator_url(struct nc_widget_textbox *textbox);
void widget_subset_add_option(struct nc_widget_subset *subset, const char *text);
--
2.17.0
More information about the Petitboot
mailing list