aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/hci/mucurses/widgets/label.c74
-rw-r--r--src/hci/tui/settings_ui.c3
-rw-r--r--src/hci/tui/widget_ui.c143
-rw-r--r--src/include/ipxe/dhcpv6.h2
-rw-r--r--src/include/ipxe/in.h2
-rw-r--r--src/include/ipxe/ip.h22
-rw-r--r--src/include/ipxe/widget.h34
-rw-r--r--src/net/ipv4.c18
-rw-r--r--src/net/ndp.c2
-rw-r--r--src/net/udp/dhcpv6.c111
10 files changed, 133 insertions, 278 deletions
diff --git a/src/hci/mucurses/widgets/label.c b/src/hci/mucurses/widgets/label.c
deleted file mode 100644
index 29057f0..0000000
--- a/src/hci/mucurses/widgets/label.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <string.h>
-#include <assert.h>
-#include <ipxe/label.h>
-
-/** @file
- *
- * Text label widget
- *
- */
-
-/**
- * Draw text label widget
- *
- * @v widget Text widget
- */
-static void draw_label ( struct widget *widget ) {
- struct label *label = container_of ( widget, struct label, widget );
- unsigned int width = widget->width;
- unsigned int col = widget->col;
- const char *text = label->text;
-
- /* Centre label if width is non-zero */
- if ( width )
- col += ( ( width - strlen ( text ) ) / 2 );
-
- /* Print label content */
- attron ( A_BOLD );
- mvprintw ( widget->row, col, "%s", text );
- attroff ( A_BOLD );
-}
-
-/**
- * Edit text label widget
- *
- * @v widget Text widget
- * @v key Key pressed by user
- * @ret key Key returned to application, or zero
- */
-static int edit_label ( struct widget *widget __unused, int key ) {
-
- /* Cannot be edited */
- return key;
-}
-
-/** Text label widget operations */
-struct widget_operations label_operations = {
- .draw = draw_label,
- .edit = edit_label,
-};
diff --git a/src/hci/tui/settings_ui.c b/src/hci/tui/settings_ui.c
index bc08750..57ff9e9 100644
--- a/src/hci/tui/settings_ui.c
+++ b/src/hci/tui/settings_ui.c
@@ -109,8 +109,6 @@ struct settings_ui {
struct jump_scroller scroll;
/** Current row */
struct settings_ui_row row;
- /** Widget set used for editing setting */
- struct widgets widgets;
};
/**
@@ -389,7 +387,6 @@ static int main_loop ( struct settings *settings ) {
/* Print initial screen content */
color_set ( CPAIR_NORMAL, NULL );
memset ( &ui, 0, sizeof ( ui ) );
- init_widgets ( &ui.widgets );
select_settings ( &ui, settings );
while ( 1 ) {
diff --git a/src/hci/tui/widget_ui.c b/src/hci/tui/widget_ui.c
deleted file mode 100644
index 961545c..0000000
--- a/src/hci/tui/widget_ui.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2024 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/** @file
- *
- * Text widget UI
- *
- */
-
-#include <errno.h>
-#include <curses.h>
-#include <ipxe/ansicol.h>
-#include <ipxe/widget.h>
-
-/**
- * Find editable widget in widget set
- *
- * @v widgets Text widget set
- * @v index Editable widget index
- * @ret widget Editable widget, or NULL
- */
-static struct widget * find_widget ( struct widgets *widgets,
- unsigned int index ) {
- struct widget *widget;
-
- list_for_each_entry ( widget, &widgets->list, list ) {
- if ( ! ( widget->flags & WIDGET_EDITABLE ) )
- continue;
- if ( index-- == 0 )
- return widget;
- }
- return NULL;
-}
-
-/**
- * Text widget user interface main loop
- *
- * @v widgets Text widget set
- * @ret rc Return status code
- */
-static int widget_ui_loop ( struct widgets *widgets ) {
- struct widget *widget;
- unsigned int current;
- unsigned int count;
- int key;
-
- /* Draw all widgets */
- list_for_each_entry ( widget, &widgets->list, list )
- draw_widget ( widget );
-
- /* Count editable widgets */
- count = 0;
- while ( find_widget ( widgets, count ) != NULL )
- count++;
-
- /* Main loop */
- current = 0;
- while ( 1 ) {
-
- /* Identify current widget */
- widget = find_widget ( widgets, current );
- if ( ! widget )
- return -ENOENT;
-
- /* Redraw current widget */
- draw_widget ( widget );
-
- /* Process keypress */
- key = edit_widget ( widget, getkey ( 0 ) );
- switch ( key ) {
- case KEY_UP:
- if ( current > 0 )
- current--;
- break;
- case KEY_DOWN:
- if ( ++current == count )
- current--;
- break;
- case TAB:
- if ( ++current == count )
- current = 0;
- break;
- case KEY_ENTER:
- current++;
- if ( current >= count )
- return 0;
- break;
- case CTRL_C:
- case ESC:
- return -ECANCELED;
- default:
- /* Do nothing for unrecognised keys or edit errors */
- break;
- }
- }
-}
-
-/**
- * Present text widget user interface
- *
- * @v widgets Text widget set
- * @ret rc Return status code
- */
-int widget_ui ( struct widgets *widgets ) {
- int rc;
-
- /* Initialise UI */
- initscr();
- start_color();
- color_set ( CPAIR_NORMAL, NULL );
- erase();
-
- /* Run main loop */
- rc = widget_ui_loop ( widgets );
-
- /* Terminate UI */
- color_set ( CPAIR_NORMAL, NULL );
- endwin();
-
- return rc;
-}
diff --git a/src/include/ipxe/dhcpv6.h b/src/include/ipxe/dhcpv6.h
index 6e70f7e..065e9c3 100644
--- a/src/include/ipxe/dhcpv6.h
+++ b/src/include/ipxe/dhcpv6.h
@@ -276,6 +276,6 @@ static inline void ipv6_all_dhcp_relay_and_servers ( struct in6_addr *addr ) {
}
extern int start_dhcpv6 ( struct interface *job, struct net_device *netdev,
- int stateful );
+ struct in6_addr *router, int stateful );
#endif /* _IPXE_DHCPV6_H */
diff --git a/src/include/ipxe/in.h b/src/include/ipxe/in.h
index 3044d63..05a8122 100644
--- a/src/include/ipxe/in.h
+++ b/src/include/ipxe/in.h
@@ -33,6 +33,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#define IN_IS_MULTICAST( addr ) \
( ( (addr) & htonl ( 0xf0000000 ) ) == htonl ( 0xe0000000 ) )
+#define IN_IS_SMALL( mask ) ( (mask) & htonl ( 0x00000003 ) )
+
/**
* IP address structure
*/
diff --git a/src/include/ipxe/ip.h b/src/include/ipxe/ip.h
index 285be6d..b1b5cb2 100644
--- a/src/include/ipxe/ip.h
+++ b/src/include/ipxe/ip.h
@@ -64,9 +64,27 @@ struct ipv4_miniroute {
/** IPv4 address */
struct in_addr address;
- /** Subnet mask */
+ /** Subnet mask
+ *
+ * An address with all of these bits in common with our IPv4
+ * address is in the local subnet.
+ */
struct in_addr netmask;
- /** Gateway address */
+ /** Host mask
+ *
+ * An address in the local subnet with all of these bits set
+ * to zero represents the network address, and an address in
+ * the local subnet with all of these bits set to one
+ * represents the directed broadcast address. All other
+ * addresses in the local subnet are valid host addresses.
+ *
+ * For most subnets, this is the inverse of the subnet mask.
+ * In a small subnet (/31 or /32) there is no network address
+ * or directed broadcast address, and all addresses in the
+ * subnet are valid host addresses.
+ */
+ struct in_addr hostmask;
+ /** Gateway address, or zero for no gateway */
struct in_addr gateway;
};
diff --git a/src/include/ipxe/widget.h b/src/include/ipxe/widget.h
index 0d8af10..945b467 100644
--- a/src/include/ipxe/widget.h
+++ b/src/include/ipxe/widget.h
@@ -10,18 +10,9 @@
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <curses.h>
-#include <ipxe/list.h>
-
-/** A text widget set */
-struct widgets {
- /** List of widgets (in tab order) */
- struct list_head list;
-};
/** A text widget */
struct widget {
- /** List of widgets (in tab order) */
- struct list_head list;
/** Widget operations */
struct widget_operations *op;
@@ -66,17 +57,6 @@ struct widget_operations {
};
/**
- * Initialise text widget set
- *
- * @v widgets Text widget set
- */
-static inline __attribute__ (( always_inline )) void
-init_widgets ( struct widgets *widgets ) {
-
- INIT_LIST_HEAD ( &widgets->list );
-}
-
-/**
* Initialise text widget
*
* @v widget Text widget
@@ -98,18 +78,6 @@ init_widget ( struct widget *widget, struct widget_operations *op,
}
/**
- * Append text widget
- *
- * @v widgets Text widget set
- * @v widget Text widget
- */
-static inline __attribute__ (( always_inline )) void
-add_widget ( struct widgets *widgets, struct widget *widget ) {
-
- list_add_tail ( &widget->list, &widgets->list );
-}
-
-/**
* Draw text widget
*
* @v widget Text widget
@@ -137,6 +105,4 @@ edit_widget ( struct widget *widget, int key ) {
return widget->op->edit ( widget, key );
}
-extern int widget_ui ( struct widgets *widgets );
-
#endif /* _IPXE_WIDGET_H */
diff --git a/src/net/ipv4.c b/src/net/ipv4.c
index b91fa2a..5d0cb0f 100644
--- a/src/net/ipv4.c
+++ b/src/net/ipv4.c
@@ -85,9 +85,18 @@ static int add_ipv4_miniroute ( struct net_device *netdev,
struct in_addr address, struct in_addr netmask,
struct in_addr gateway ) {
struct ipv4_miniroute *miniroute;
+ struct in_addr hostmask;
+ struct in_addr broadcast;
+ /* Calculate host mask */
+ hostmask.s_addr = ( IN_IS_SMALL ( netmask.s_addr ) ?
+ INADDR_NONE : ~netmask.s_addr );
+ broadcast.s_addr = ( address.s_addr | hostmask.s_addr );
+
+ /* Print debugging information */
DBGC ( netdev, "IPv4 add %s", inet_ntoa ( address ) );
DBGC ( netdev, "/%s ", inet_ntoa ( netmask ) );
+ DBGC ( netdev, "bc %s ", inet_ntoa ( broadcast ) );
if ( gateway.s_addr )
DBGC ( netdev, "gw %s ", inet_ntoa ( gateway ) );
DBGC ( netdev, "via %s\n", netdev->name );
@@ -103,8 +112,9 @@ static int add_ipv4_miniroute ( struct net_device *netdev,
miniroute->netdev = netdev_get ( netdev );
miniroute->address = address;
miniroute->netmask = netmask;
+ miniroute->hostmask = hostmask;
miniroute->gateway = gateway;
-
+
/* Add to end of list if we have a gateway, otherwise
* to start of list.
*/
@@ -310,7 +320,7 @@ static int ipv4_tx ( struct io_buffer *iobuf,
struct sockaddr_in *sin_dest = ( ( struct sockaddr_in * ) st_dest );
struct ipv4_miniroute *miniroute;
struct in_addr next_hop;
- struct in_addr netmask = { .s_addr = 0 };
+ struct in_addr hostmask = { .s_addr = INADDR_NONE };
uint8_t ll_dest_buf[MAX_LL_ADDR_LEN];
const void *ll_dest;
int rc;
@@ -338,7 +348,7 @@ static int ipv4_tx ( struct io_buffer *iobuf,
( ( miniroute = ipv4_route ( sin_dest->sin_scope_id,
&next_hop ) ) != NULL ) ) {
iphdr->src = miniroute->address;
- netmask = miniroute->netmask;
+ hostmask = miniroute->hostmask;
netdev = miniroute->netdev;
}
if ( ! netdev ) {
@@ -373,7 +383,7 @@ static int ipv4_tx ( struct io_buffer *iobuf,
ntohs ( iphdr->chksum ) );
/* Calculate link-layer destination address, if possible */
- if ( ( ( next_hop.s_addr ^ INADDR_BROADCAST ) & ~netmask.s_addr ) == 0){
+ if ( ( ( ~next_hop.s_addr ) & hostmask.s_addr ) == 0 ) {
/* Broadcast address */
ipv4_stats.out_bcast_pkts++;
ll_dest = netdev->ll_broadcast;
diff --git a/src/net/ndp.c b/src/net/ndp.c
index 373a936..3c555f4 100644
--- a/src/net/ndp.c
+++ b/src/net/ndp.c
@@ -1221,7 +1221,7 @@ ipv6conf_rx_router_advertisement ( struct net_device *netdev,
/* Start DHCPv6 if required */
if ( radv->flags & ( NDP_ROUTER_MANAGED | NDP_ROUTER_OTHER ) ) {
stateful = ( radv->flags & NDP_ROUTER_MANAGED );
- if ( ( rc = start_dhcpv6 ( &ipv6conf->dhcp, netdev,
+ if ( ( rc = start_dhcpv6 ( &ipv6conf->dhcp, netdev, router,
stateful ) ) != 0 ) {
DBGC ( netdev, "NDP %s could not start state%s DHCPv6: "
"%s\n", netdev->name,
diff --git a/src/net/udp/dhcpv6.c b/src/net/udp/dhcpv6.c
index 9e27dec..a491098 100644
--- a/src/net/udp/dhcpv6.c
+++ b/src/net/udp/dhcpv6.c
@@ -268,6 +268,8 @@ struct dhcpv6_settings {
struct settings settings;
/** Leased address */
struct in6_addr lease;
+ /** Router address */
+ struct in6_addr router;
/** Option list */
struct dhcpv6_option_list options;
};
@@ -283,25 +285,21 @@ static int dhcpv6_applies ( struct settings *settings __unused,
const struct setting *setting ) {
return ( ( setting->scope == &dhcpv6_scope ) ||
- ( setting_cmp ( setting, &ip6_setting ) == 0 ) );
+ ( setting->scope == &ipv6_settings_scope ) );
}
/**
* Fetch value of DHCPv6 leased address
*
- * @v dhcpset DHCPv6 settings
+ * @v dhcpv6set DHCPv6 settings
* @v data Buffer to fill with setting data
* @v len Length of buffer
* @ret len Length of setting data, or negative error
*/
-static int dhcpv6_fetch_lease ( struct dhcpv6_settings *dhcpv6set,
- void *data, size_t len ) {
+static int dhcpv6_fetch_ip6 ( struct dhcpv6_settings *dhcpv6set,
+ void *data, size_t len ) {
struct in6_addr *lease = &dhcpv6set->lease;
- /* Do nothing unless a leased address exists */
- if ( IN6_IS_ADDR_UNSPECIFIED ( lease ) )
- return -ENOENT;
-
/* Copy leased address */
if ( len > sizeof ( *lease ) )
len = sizeof ( *lease );
@@ -311,6 +309,72 @@ static int dhcpv6_fetch_lease ( struct dhcpv6_settings *dhcpv6set,
}
/**
+ * Fetch value of DHCPv6 implicit address prefix length
+ *
+ * @v dhcpv6set DHCPv6 settings
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+static int dhcpv6_fetch_len6 ( struct dhcpv6_settings *dhcpv6set __unused,
+ void *data, size_t len ) {
+ uint8_t *len6 = data;
+
+ /* Default to assuming this is the only address on the link.
+ * If the address falls within a known prefix, then the IPv6
+ * routing table construction logic will match it against that
+ * prefix.
+ */
+ if ( len )
+ *len6 = IPV6_MAX_PREFIX_LEN;
+
+ return sizeof ( *len6 );
+}
+
+/**
+ * Fetch value of DHCPv6 router address
+ *
+ * @v dhcpv6set DHCPv6 settings
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+static int dhcpv6_fetch_gateway6 ( struct dhcpv6_settings *dhcpv6set,
+ void *data, size_t len ) {
+ struct in6_addr *router = &dhcpv6set->router;
+
+ /* Copy router address */
+ if ( len > sizeof ( *router ) )
+ len = sizeof ( *router );
+ memcpy ( data, router, len );
+
+ return sizeof ( *router );
+}
+
+/** A DHCPv6 address setting operation */
+struct dhcpv6_address_operation {
+ /** Generic setting */
+ const struct setting *setting;
+ /**
+ * Fetch value of setting
+ *
+ * @v dhcpv6set DHCPv6 settings
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
+ */
+ int ( * fetch ) ( struct dhcpv6_settings *dhcpv6set,
+ void *data, size_t len );
+};
+
+/** DHCPv6 address settings operations */
+static struct dhcpv6_address_operation dhcpv6_address_operations[] = {
+ { &ip6_setting, dhcpv6_fetch_ip6 },
+ { &len6_setting, dhcpv6_fetch_len6 },
+ { &gateway6_setting, dhcpv6_fetch_gateway6 },
+};
+
+/**
* Fetch value of DHCPv6 setting
*
* @v settings Settings block
@@ -325,11 +389,20 @@ static int dhcpv6_fetch ( struct settings *settings,
struct dhcpv6_settings *dhcpv6set =
container_of ( settings, struct dhcpv6_settings, settings );
const union dhcpv6_any_option *option;
+ struct dhcpv6_address_operation *op;
size_t option_len;
-
- /* Handle leased address */
- if ( setting_cmp ( setting, &ip6_setting ) == 0 )
- return dhcpv6_fetch_lease ( dhcpv6set, data, len );
+ unsigned int i;
+
+ /* Handle address settings */
+ for ( i = 0 ; i < ( sizeof ( dhcpv6_address_operations ) /
+ sizeof ( dhcpv6_address_operations[0] ) ) ; i++ ) {
+ op = &dhcpv6_address_operations[i];
+ if ( setting_cmp ( setting, op->setting ) != 0 )
+ continue;
+ if ( IN6_IS_ADDR_UNSPECIFIED ( &dhcpv6set->lease ) )
+ return -ENOENT;
+ return op->fetch ( dhcpv6set, data, len );
+ }
/* Find option */
option = dhcpv6_option ( &dhcpv6set->options, setting->tag );
@@ -354,11 +427,12 @@ static struct settings_operations dhcpv6_settings_operations = {
* Register DHCPv6 options as network device settings
*
* @v lease DHCPv6 leased address
+ * @v router DHCPv6 router address
* @v options DHCPv6 option list
* @v parent Parent settings block
* @ret rc Return status code
*/
-static int dhcpv6_register ( struct in6_addr *lease,
+static int dhcpv6_register ( struct in6_addr *lease, struct in6_addr *router,
struct dhcpv6_option_list *options,
struct settings *parent ) {
struct dhcpv6_settings *dhcpv6set;
@@ -382,6 +456,7 @@ static int dhcpv6_register ( struct in6_addr *lease,
dhcpv6set->options.data = data;
dhcpv6set->options.len = len;
memcpy ( &dhcpv6set->lease, lease, sizeof ( dhcpv6set->lease ) );
+ memcpy ( &dhcpv6set->router, router, sizeof ( dhcpv6set->router ) );
/* Register settings */
if ( ( rc = register_settings ( &dhcpv6set->settings, parent,
@@ -501,6 +576,8 @@ struct dhcpv6_session {
/** Network device being configured */
struct net_device *netdev;
+ /** Router address */
+ struct in6_addr router;
/** Transaction ID */
uint8_t xid[3];
/** Identity association ID */
@@ -876,8 +953,8 @@ static int dhcpv6_rx ( struct dhcpv6_session *dhcpv6,
}
/* Register settings */
- if ( ( rc = dhcpv6_register ( &dhcpv6->lease, &options,
- parent ) ) != 0 ) {
+ if ( ( rc = dhcpv6_register ( &dhcpv6->lease, &dhcpv6->router,
+ &options, parent ) ) != 0 ) {
DBGC ( dhcpv6, "DHCPv6 %s could not register settings: %s\n",
dhcpv6->netdev->name, strerror ( rc ) );
goto done;
@@ -915,11 +992,12 @@ static struct interface_descriptor dhcpv6_xfer_desc =
*
* @v job Job control interface
* @v netdev Network device
+ * @v router Router address
* @v stateful Perform stateful address autoconfiguration
* @ret rc Return status code
*/
int start_dhcpv6 ( struct interface *job, struct net_device *netdev,
- int stateful ) {
+ struct in6_addr *router, int stateful ) {
struct ll_protocol *ll_protocol = netdev->ll_protocol;
struct dhcpv6_session *dhcpv6;
struct {
@@ -944,6 +1022,7 @@ int start_dhcpv6 ( struct interface *job, struct net_device *netdev,
intf_init ( &dhcpv6->job, &dhcpv6_job_desc, &dhcpv6->refcnt );
intf_init ( &dhcpv6->xfer, &dhcpv6_xfer_desc, &dhcpv6->refcnt );
dhcpv6->netdev = netdev_get ( netdev );
+ memcpy ( &dhcpv6->router, router, sizeof ( dhcpv6->router ) );
xid = random();
memcpy ( dhcpv6->xid, &xid, sizeof ( dhcpv6->xid ) );
dhcpv6->start = currticks();