diff options
Diffstat (limited to 'gpxe/src/usr')
-rw-r--r-- | gpxe/src/usr/autoboot.c | 64 | ||||
-rw-r--r-- | gpxe/src/usr/dhcpmgmt.c | 23 | ||||
-rw-r--r-- | gpxe/src/usr/ifmgmt.c | 42 | ||||
-rw-r--r-- | gpxe/src/usr/imgmgmt.c | 4 | ||||
-rw-r--r-- | gpxe/src/usr/iwmgmt.c | 244 | ||||
-rw-r--r-- | gpxe/src/usr/pxemenu.c | 4 | ||||
-rw-r--r-- | gpxe/src/usr/route.c | 4 |
7 files changed, 335 insertions, 50 deletions
diff --git a/gpxe/src/usr/autoboot.c b/gpxe/src/usr/autoboot.c index 98e79a7f..2fa10e6b 100644 --- a/gpxe/src/usr/autoboot.c +++ b/gpxe/src/usr/autoboot.c @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <string.h> #include <stdio.h> #include <errno.h> @@ -37,18 +39,9 @@ * */ -/** Time to wait for link-up */ -#define LINK_WAIT_MS 15000 - /** Shutdown flags for exit */ int shutdown_exit_flags = 0; -/* SAN boot protocols */ -static struct sanboot_protocol sanboot_protocols[0] \ - __table_start ( struct sanboot_protocol, sanboot_protocols ); -static struct sanboot_protocol sanboot_protocols_end[0] \ - __table_end ( struct sanboot_protocol, sanboot_protocols ); - /** * Identify the boot network device * @@ -68,16 +61,16 @@ int boot_next_server_and_filename ( struct in_addr next_server, const char *filename ) { struct uri *uri; struct image *image; - char buf[ 23 /* tftp://xxx.xxx.xxx.xxx/ */ + strlen(filename) + 1 ]; + char buf[ 23 /* tftp://xxx.xxx.xxx.xxx/ */ + + ( 3 * strlen(filename) ) /* completely URI-encoded */ + + 1 /* NUL */ ]; int filename_is_absolute; int rc; /* Construct URI */ uri = parse_uri ( filename ); - if ( ! uri ) { - printf ( "Out of memory\n" ); + if ( ! uri ) return -ENOMEM; - } filename_is_absolute = uri_is_absolute ( uri ); uri_put ( uri ); if ( ! filename_is_absolute ) { @@ -87,27 +80,22 @@ int boot_next_server_and_filename ( struct in_addr next_server, * between filenames with and without initial slashes, * which is significant for TFTP. */ - snprintf ( buf, sizeof ( buf ), "tftp://%s/%s", - inet_ntoa ( next_server ), filename ); + snprintf ( buf, sizeof ( buf ), "tftp://%s/", + inet_ntoa ( next_server ) ); + uri_encode ( filename, buf + strlen ( buf ), + sizeof ( buf ) - strlen ( buf ), URI_PATH ); filename = buf; } image = alloc_image(); - if ( ! image ) { - printf ( "Out of memory\n" ); + if ( ! image ) return -ENOMEM; - } if ( ( rc = imgfetch ( image, filename, register_and_autoload_image ) ) != 0 ) { - printf ( "Could not load %s: %s\n", - filename, strerror ( rc ) ); goto done; } - if ( ( rc = imgexec ( image ) ) != 0 ) { - printf ( "Could not boot %s: %s\n", - filename, strerror ( rc ) ); + if ( ( rc = imgexec ( image ) ) != 0 ) goto done; - } done: image_put ( image ); @@ -124,8 +112,7 @@ int boot_root_path ( const char *root_path ) { struct sanboot_protocol *sanboot; /* Quick hack */ - for ( sanboot = sanboot_protocols ; - sanboot < sanboot_protocols_end ; sanboot++ ) { + for_each_table_entry ( sanboot, SANBOOT_PROTOCOLS ) { if ( strncmp ( root_path, sanboot->prefix, strlen ( sanboot->prefix ) ) == 0 ) { return sanboot->boot ( root_path ); @@ -158,14 +145,6 @@ static int netboot ( struct net_device *netdev ) { return rc; ifstat ( netdev ); - /* Wait for link-up */ - printf ( "Waiting for link-up on %s...", netdev->name ); - if ( ( rc = iflinkwait ( netdev, LINK_WAIT_MS ) ) != 0 ) { - printf ( " no link detected\n" ); - return rc; - } - printf ( " ok\n" ); - /* Configure device via DHCP */ if ( ( rc = dhcp ( netdev ) ) != 0 ) return rc; @@ -176,7 +155,7 @@ static int netboot ( struct net_device *netdev ) { buf, sizeof ( buf ) ); pxe_discovery_control = fetch_uintz_setting ( NULL, &pxe_discovery_control_setting ); - if ( ( strcmp ( buf, "PXEClient" ) == 0 ) && + if ( ( strcmp ( buf, "PXEClient" ) == 0 ) && pxe_menu_boot != NULL && setting_exists ( NULL, &pxe_boot_menu_setting ) && ( ! ( ( pxe_discovery_control & PXEBS_SKIP ) && setting_exists ( NULL, &filename_setting ) ) ) ) { @@ -189,14 +168,25 @@ static int netboot ( struct net_device *netdev ) { fetch_string_setting ( NULL, &filename_setting, buf, sizeof ( buf ) ); if ( buf[0] ) { printf ( "Booting from filename \"%s\"\n", buf ); - return boot_next_server_and_filename ( next_server, buf ); + if ( ( rc = boot_next_server_and_filename ( next_server, + buf ) ) != 0 ) { + printf ( "Could not boot from filename \"%s\": %s\n", + buf, strerror ( rc ) ); + return rc; + } + return 0; } /* No filename; try the root path */ fetch_string_setting ( NULL, &root_path_setting, buf, sizeof ( buf ) ); if ( buf[0] ) { printf ( "Booting from root path \"%s\"\n", buf ); - return boot_root_path ( buf ); + if ( ( rc = boot_root_path ( buf ) ) != 0 ) { + printf ( "Could not boot from root path \"%s\": %s\n", + buf, strerror ( rc ) ); + return rc; + } + return 0; } printf ( "No filename or root path specified\n" ); diff --git a/gpxe/src/usr/dhcpmgmt.c b/gpxe/src/usr/dhcpmgmt.c index 6acf7f6d..f82a3bb8 100644 --- a/gpxe/src/usr/dhcpmgmt.c +++ b/gpxe/src/usr/dhcpmgmt.c @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <string.h> #include <stdio.h> #include <errno.h> @@ -26,6 +28,8 @@ #include <usr/ifmgmt.h> #include <usr/dhcpmgmt.h> +#define LINK_WAIT_MS 15000 + /** @file * * DHCP management @@ -33,16 +37,31 @@ */ int dhcp ( struct net_device *netdev ) { + uint8_t *chaddr; + uint8_t hlen; + uint16_t flags; int rc; /* Check we can open the interface first */ if ( ( rc = ifopen ( netdev ) ) != 0 ) return rc; + /* Wait for link-up */ + if ( ( rc = iflinkwait ( netdev, LINK_WAIT_MS ) ) != 0 ) + return rc; + /* Perform DHCP */ - printf ( "DHCP (%s %s)", netdev->name, netdev_hwaddr ( netdev ) ); - if ( ( rc = start_dhcp ( &monojob, netdev ) ) == 0 ) + chaddr = dhcp_chaddr ( netdev, &hlen, &flags ); + printf ( "DHCP (%s ", netdev->name ); + while ( hlen-- ) + printf ( "%02x%c", *(chaddr++), ( hlen ? ':' : ')' ) ); + + if ( ( rc = start_dhcp ( &monojob, netdev ) ) == 0 ) { rc = monojob_wait ( "" ); + } else if ( rc > 0 ) { + printf ( " using cached\n" ); + rc = 0; + } return rc; } diff --git a/gpxe/src/usr/ifmgmt.c b/gpxe/src/usr/ifmgmt.c index 0ebf5615..d4cc5a5b 100644 --- a/gpxe/src/usr/ifmgmt.c +++ b/gpxe/src/usr/ifmgmt.c @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <string.h> #include <stdio.h> #include <unistd.h> @@ -87,35 +89,59 @@ static void ifstat_errors ( struct net_device_stats *stats, void ifstat ( struct net_device *netdev ) { printf ( "%s: %s on %s (%s)\n" " [Link:%s, TX:%d TXE:%d RX:%d RXE:%d]\n", - netdev->name, netdev_hwaddr ( netdev ), netdev->dev->name, + netdev->name, netdev_addr ( netdev ), netdev->dev->name, ( ( netdev->state & NETDEV_OPEN ) ? "open" : "closed" ), ( netdev_link_ok ( netdev ) ? "up" : "down" ), netdev->tx_stats.good, netdev->tx_stats.bad, netdev->rx_stats.good, netdev->rx_stats.bad ); + if ( ! netdev_link_ok ( netdev ) ) { + printf ( " [Link status: %s]\n", + strerror ( netdev->link_rc ) ); + } ifstat_errors ( &netdev->tx_stats, "TXE" ); ifstat_errors ( &netdev->rx_stats, "RXE" ); } /** - * Wait for link-up + * Wait for link-up, with status indication * * @v netdev Network device * @v max_wait_ms Maximum time to wait, in ms */ int iflinkwait ( struct net_device *netdev, unsigned int max_wait_ms ) { int key; + int rc; + + if ( netdev_link_ok ( netdev ) ) + return 0; + + printf ( "Waiting for link-up on %s...", netdev->name ); while ( 1 ) { - if ( netdev_link_ok ( netdev ) ) - return 0; - if ( max_wait_ms-- == 0 ) - return -ETIMEDOUT; + if ( netdev_link_ok ( netdev ) ) { + rc = 0; + break; + } + if ( max_wait_ms-- == 0 ) { + rc = netdev->link_rc; + break; + } step(); if ( iskey() ) { key = getchar(); - if ( key == CTRL_C ) - return -ECANCELED; + if ( key == CTRL_C ) { + rc = -ECANCELED; + break; + } } mdelay ( 1 ); } + + if ( rc == 0 ) { + printf ( " ok\n" ); + } else { + printf ( " failed: %s\n", strerror ( rc ) ); + } + + return rc; } diff --git a/gpxe/src/usr/imgmgmt.c b/gpxe/src/usr/imgmgmt.c index bd53d824..023e3f0f 100644 --- a/gpxe/src/usr/imgmgmt.c +++ b/gpxe/src/usr/imgmgmt.c @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <stdlib.h> #include <stdio.h> @@ -59,7 +61,7 @@ int imgfetch ( struct image *image, const char *uri_string, if ( password ) uri->password = "***"; unparse_uri ( uri_string_redacted, sizeof ( uri_string_redacted ), - uri ); + uri, URI_ALL ); uri->password = password; if ( ( rc = create_downloader ( &monojob, image, image_register, diff --git a/gpxe/src/usr/iwmgmt.c b/gpxe/src/usr/iwmgmt.c new file mode 100644 index 00000000..59ba103a --- /dev/null +++ b/gpxe/src/usr/iwmgmt.c @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2009 Joshua Oreman <oremanj@rwcr.net>. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include <stdio.h> +#include <console.h> +#include <string.h> +#include <errno.h> +#include <gpxe/net80211.h> +#include <gpxe/ethernet.h> +#include <usr/ifmgmt.h> +#include <usr/iwmgmt.h> +#include <gpxe/errortab.h> + +/** @file + * + * Wireless network interface management + * + */ + +/** + * Print status of 802.11 device + * + * @v dev 802.11 device + */ +void iwstat ( struct net80211_device *dev ) { + + ifstat ( dev->netdev ); + + printf ( " [802.11 "); + if ( dev->state & NET80211_ASSOCIATED ) { + printf ( "SSID '%s', ", dev->essid ); + } else { + printf ( "not associated, " ); + } + if ( dev->channel < dev->nr_channels && dev->rate < dev->nr_rates ) { + printf ( "Ch:%d Sig:%d", dev->channels[dev->channel].channel_nr, + dev->last_signal ); + switch ( dev->hw->signal_type ) { + case NET80211_SIGNAL_NONE: + printf ( "?" ); + break; + case NET80211_SIGNAL_ARBITRARY: + printf ( "/%d", dev->hw->signal_max ); + break; + case NET80211_SIGNAL_DB: + printf ( "/%d dB", dev->hw->signal_max ); + break; + case NET80211_SIGNAL_DBM: + printf ( " dBm" ); + break; + } + printf ( ", Qual:%d%% Rate:%d Mbps]\n", + ( dev->rx_beacon_interval == 0 ? 0 : + 100 * dev->tx_beacon_interval / + dev->rx_beacon_interval ), + dev->rates[dev->rate] / 10 ); + } else { + printf ( "antenna off]\n" ); + } + + if ( dev->state & NET80211_WORKING ) { + printf ( " [associating" ); + if ( dev->associating ) + printf ( " to '%s'", dev->associating->essid ); + printf ( "...]\n" ); + } +} + +/** Identifiers for 802.11 cryptography types, indexed by type number */ +static const char *crypto_types[] = { + [NET80211_CRYPT_NONE] = "Open", + [NET80211_CRYPT_WEP] = "WEP ", + [NET80211_CRYPT_TKIP] = "WPA ", + [NET80211_CRYPT_CCMP] = "WPA2", + [NET80211_CRYPT_UNKNOWN] = "UNK ", +}; + +/** Number of 802.11 cryptography types defined */ +#define NR_CRYPTO_TYPES ( sizeof ( crypto_types ) / sizeof ( crypto_types[0] ) ) + +/** Identifiers for 802.11 authentication types, indexed by type number */ +static const char *auth_types[] = { + [NET80211_SECPROT_NONE] = "", + [NET80211_SECPROT_PSK] = "PSK", + [NET80211_SECPROT_EAP] = "802.1X", + [NET80211_SECPROT_UNKNOWN] = "UNK", +}; + +/** Number of 802.11 authentication types defined */ +#define NR_AUTH_TYPES ( sizeof ( auth_types ) / sizeof ( auth_types[0] ) ) + +/** + * Scan for wireless networks using 802.11 device + * + * @v dev 802.11 device + * @v active Whether to use active scanning + * + * The list of networks found will be printed in tabular format. + * + * This function is safe to call at all times, whether the 802.11 + * device is open or not, but if called while the auto-association + * task is running it will return an error indication. + */ +int iwlist ( struct net80211_device *dev ) { + struct net80211_probe_ctx *ctx; + struct list_head *networks; + struct net80211_wlan *wlan; + char ssid_buf[22]; + int rc; + unsigned i; + int was_opened = dev->netdev->state & NETDEV_OPEN; + int was_channel = dev->channels[dev->channel].channel_nr; + + if ( ! was_opened ) { + dev->state |= NET80211_NO_ASSOC; + rc = netdev_open ( dev->netdev ); + if ( rc < 0 ) + goto err; + } + + if ( dev->state & NET80211_WORKING ) { + rc = -EINVAL; + goto err_close_netdev; + } + + if ( ! was_opened ) { + rc = net80211_prepare_probe ( dev, dev->hw->bands, 0 ); + if ( rc < 0 ) + goto err_close_netdev; + } + + ctx = net80211_probe_start ( dev, "", 0 ); + if ( ! ctx ) { + rc = -ENOMEM; + goto err_close_netdev; + } + + while ( ! ( rc = net80211_probe_step ( ctx ) ) ) { + step(); + } + + networks = net80211_probe_finish_all ( ctx ); + + if ( list_empty ( networks ) ) { + goto err_free_networks; + } + + rc = 0; + + printf ( "Networks on %s:\n\n", dev->netdev->name ); + + /* Output format: + * 0 1 2 3 4 5 6 + * 0123456789012345678901234567890123456789012345678901234567890 + * [Sig] SSID BSSID Ch Crypt/Auth + * ------------------------------------------------------------- + * [ 15] abcdefghijklmnopqrst> 00:00:00:00:00:00 11 Open + * ... or WPA PSK etc. + */ + + /* Quoting the dashes and spaces verbatim uses less code space + than generating them programmatically. */ + printf ( "[Sig] SSID BSSID Ch Crypt/Auth\n" + "-------------------------------------------------------------\n" ); + + list_for_each_entry ( wlan, networks, list ) { + + /* Format SSID into 22-character string, space-padded, + with '>' indicating truncation */ + + snprintf ( ssid_buf, sizeof ( ssid_buf ), "%s", wlan->essid ); + for ( i = strlen ( ssid_buf ); i < sizeof ( ssid_buf ) - 1; + i++ ) + ssid_buf[i] = ' '; + if ( ssid_buf[sizeof ( ssid_buf ) - 2] != ' ' ) + ssid_buf[sizeof ( ssid_buf ) - 2] = '>'; + ssid_buf[sizeof ( ssid_buf ) - 1] = 0; + + /* Sanity check */ + if ( wlan->crypto >= NR_CRYPTO_TYPES || + wlan->handshaking >= NR_AUTH_TYPES ) + continue; + + printf ( "[%3d] %s %s %2d %s %s\n", + wlan->signal < 0 ? 100 + wlan->signal : wlan->signal, + ssid_buf, eth_ntoa ( wlan->bssid ), wlan->channel, + crypto_types[wlan->crypto], + auth_types[wlan->handshaking] ); + } + printf ( "\n" ); + + err_free_networks: + net80211_free_wlanlist ( networks ); + + err_close_netdev: + if ( ! was_opened ) { + dev->state &= ~NET80211_NO_ASSOC; + netdev_close ( dev->netdev ); + } else { + net80211_change_channel ( dev, was_channel ); + } + + if ( ! rc ) + return 0; + + err: + printf ( "Scanning for networks on %s: %s\n", + dev->netdev->name, strerror ( rc ) ); + return rc; +} + + +/* Record error codes as though they come from the 802.11 stack */ +#undef ERRFILE +#define ERRFILE ERRFILE_net80211 + +/** Common 802.11 errors */ +struct errortab common_wireless_errors[] __errortab = { + { EINVAL | EUNIQ_06, "Packet decryption error" }, + { ECONNRESET | EUNIQ_01, "Unspecified reason" }, + { ECONNRESET | EUNIQ_04, "Disassociated due to inactivity" }, + { ECONNRESET | EUNIQ_0F, "4-Way Handshake timeout" }, + { ECONNRESET | EUNIQ_17, "IEEE 802.1X authentication failed" }, + { ECONNREFUSED | EUNIQ_01, "Unspecified failure" }, + { ECONNREFUSED | EUNIQ_0C, "Association denied" }, + { ECONNREFUSED | EUNIQ_0D, "Authentication method not supported" }, +}; diff --git a/gpxe/src/usr/pxemenu.c b/gpxe/src/usr/pxemenu.c index 793cb624..519c200e 100644 --- a/gpxe/src/usr/pxemenu.c +++ b/gpxe/src/usr/pxemenu.c @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdint.h> #include <stdlib.h> #include <stdio.h> @@ -151,7 +153,7 @@ static int pxe_menu_parse ( struct pxe_menu **menu ) { ( num_menu_items * sizeof ( (*menu)->items[0] ) ) ); memcpy ( raw_menu_item, raw_menu, raw_menu_len ); for ( i = 0 ; i < num_menu_items ; i++ ) { - (*menu)->items[i].type = ntohs ( raw_menu_item->type ); + (*menu)->items[i].type = le16_to_cpu ( raw_menu_item->type ); (*menu)->items[i].desc = raw_menu_item->desc; /* Set type to 0; this ensures that the description * for the previous menu item is NUL-terminated. diff --git a/gpxe/src/usr/route.c b/gpxe/src/usr/route.c index f3a49f46..18757419 100644 --- a/gpxe/src/usr/route.c +++ b/gpxe/src/usr/route.c @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stdio.h> #include <gpxe/netdevice.h> #include <gpxe/ip.h> @@ -34,7 +36,7 @@ void route ( void ) { printf ( "%s: %s/", miniroute->netdev->name, inet_ntoa ( miniroute->address ) ); printf ( "%s", inet_ntoa ( miniroute->netmask ) ); - if ( miniroute->gateway.s_addr != INADDR_NONE ) + if ( miniroute->gateway.s_addr ) printf ( " gw %s", inet_ntoa ( miniroute->gateway ) ); if ( ! ( miniroute->netdev->state & NETDEV_OPEN ) ) printf ( " (inaccessible)" ); |