diff options
-rw-r--r-- | src/hci/mucurses/widgets/label.c | 74 | ||||
-rw-r--r-- | src/hci/tui/settings_ui.c | 3 | ||||
-rw-r--r-- | src/hci/tui/widget_ui.c | 143 | ||||
-rw-r--r-- | src/include/ipxe/dhcpv6.h | 2 | ||||
-rw-r--r-- | src/include/ipxe/in.h | 2 | ||||
-rw-r--r-- | src/include/ipxe/ip.h | 22 | ||||
-rw-r--r-- | src/include/ipxe/widget.h | 34 | ||||
-rw-r--r-- | src/net/ipv4.c | 18 | ||||
-rw-r--r-- | src/net/ndp.c | 2 | ||||
-rw-r--r-- | src/net/udp/dhcpv6.c | 111 |
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(); |