From: Matthew Iselin <[email protected]> Signed-off-by: Matthew Iselin <[email protected]> --- src/config/config.c | 3 + src/config/general.h | 1 + src/hci/commands/ipv6_cmd.c | 180 +++++++++++++++++++++++++++++++++++++++++++ src/include/usr/ip6mgmt.h | 17 ++++ src/usr/ip6mgmt.c | 76 ++++++++++++++++++ 5 files changed, 277 insertions(+), 0 deletions(-) create mode 100644 src/hci/commands/ipv6_cmd.c create mode 100644 src/include/usr/ip6mgmt.h create mode 100644 src/usr/ip6mgmt.c
diff --git a/src/config/config.c b/src/config/config.c index f468064..cf6d6ba 100644 --- a/src/config/config.c +++ b/src/config/config.c @@ -238,6 +238,9 @@ REQUIRE_OBJECT ( digest_cmd ); #ifdef PXE_CMD REQUIRE_OBJECT ( pxe_cmd ); #endif +#ifdef IPV6_CMD +REQUIRE_OBJECT ( ipv6_cmd ); +#endif /* * Drag in miscellaneous objects diff --git a/src/config/general.h b/src/config/general.h index b58dff9..0bb364e 100644 --- a/src/config/general.h +++ b/src/config/general.h @@ -121,6 +121,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #undef TIME_CMD /* Time commands */ #undef DIGEST_CMD /* Image crypto digest commands */ //#undef PXE_CMD /* PXE commands */ +#define IPV6_CMD /* IPv6 commands */ /* * Error message tables to include diff --git a/src/hci/commands/ipv6_cmd.c b/src/hci/commands/ipv6_cmd.c new file mode 100644 index 0000000..e794e6c --- /dev/null +++ b/src/hci/commands/ipv6_cmd.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2011 Matthew Iselin <[email protected]>. + * + * 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 <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <stddef.h> +#include <string.h> +#include <assert.h> +#include <getopt.h> +#include <gpxe/netdevice.h> +#include <gpxe/in.h> +#include <gpxe/command.h> +#include <usr/ip6mgmt.h> +#include <usr/ifmgmt.h> + +/** @file + * + * IPv6 management commands + * + */ + +/** + * "ipv6" command syntax message + * + * @v argv Argument list + */ +static void ipv6_syntax ( char **argv ) { + printf ( "Usage:\n" + " %s <interface> [<interface> ...]\n" + " %s any\n" + "\n" + "Prepare a network interface for use with IPv6\n", + argv[0], argv[0] ); +} + + +/** + * Attempt to configure a device with an IPv6 link-local address + * + * @v netdev Device to configure + * @ret rc Exit code + */ +static int ipv6_one_device ( struct net_device *netdev ) { + int rc; + + /* Perform autoconfiguration */ + if ( ( rc = ip6_autoconf ( netdev ) ) != 0 ) { + /* Close the device on error to avoid out-of-memory */ + netdev_close ( netdev ); + + printf ( "Could not configure %s: %s\n", netdev->name, + strerror ( rc ) ); + return 1; + } + + return 0; +} + +/** + * Call ipv6_one_device() for each name in argv + * + * @v argc Number of devices + * @v argv List of device names + * @ret rc Exit code + */ +static int ipv6_each_device_name ( int argc, char **argv ) { + int i; + char *netdev_name; + struct net_device *netdev; + + for ( i = 0; i < argc; i++ ) { + netdev_name = argv[i]; + netdev = find_netdev ( netdev_name ); + + if ( ! netdev ) { + printf ( "No such interface: %s\n", netdev_name ); + continue; + } + + if ( ipv6_one_device ( netdev ) == 0 ) + return 0; + } + + printf ( "Could not configure any interface.\n" ); + return 1; +} + +/** + * Call ipv6_one_device() for each device in net_devices + * + * @ret rc Exit code + */ +static int ipv6_each_device ( void ) { + struct net_device *netdev; + + for_each_netdev ( netdev ) { + if ( ipv6_one_device ( netdev ) == 0 ) + return 0; + } + + printf ( "Could not configure any interface.\n" ); + return 1; +} + +/** + * The "ipv6" command + * + * @v argc Argument count + * @v argv Argument list + * @ret rc Exit code + */ +static int ipv6_exec ( int argc __unused, char **argv __unused ) { + static struct option longopts[] = { + { "help", 0, NULL, 'h' }, + { NULL, 0, NULL, 0 }, + }; + int c; + + /* Parse options */ + while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){ + switch ( c ) { + case 'h': + /* Display help text */ + default: + /* Unrecognised/invalid option */ + ipv6_syntax ( argv ); + return 1; + } + } + + /* Need one or more interface names remaining after the options */ + if ( ( argc - optind ) < 1 ) { + ipv6_syntax ( argv ); + return 1; + } + + if ( strcmp ( argv[optind], "any" ) == 0 ) + return ipv6_each_device(); + + return ipv6_each_device_name ( argc - optind, argv + optind ); +} + +static int dhcp6_exec ( int argc __unused, char **argv __unused ) { + printf ( "DHCPv6 is not yet implemented.\n" ); + return 0; +} + +/** IPv6 management commands */ +struct command ipv6_commands[] __command = { + { + .name = "ipv6", + .exec = ipv6_exec, + }, + { + .name = "dhcp6", + .exec = dhcp6_exec, + } +}; + + diff --git a/src/include/usr/ip6mgmt.h b/src/include/usr/ip6mgmt.h new file mode 100644 index 0000000..9c17285 --- /dev/null +++ b/src/include/usr/ip6mgmt.h @@ -0,0 +1,17 @@ +#ifndef _USR_IPV6MGMT_H +#define _USR_IPV6MGMT_H + +/** @file + * + * IPv6 management + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +struct net_device; + +extern int ip6_autoconf ( struct net_device *netdev ); + +#endif /* _USR_IPV6MGMT_H */ + diff --git a/src/usr/ip6mgmt.c b/src/usr/ip6mgmt.c new file mode 100644 index 0000000..0809c7b --- /dev/null +++ b/src/usr/ip6mgmt.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2011 Matthew Iselin <[email protected]>. + * + * 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 <string.h> +#include <stdio.h> +#include <errno.h> +#include <gpxe/netdevice.h> +#include <gpxe/in.h> +#include <gpxe/ip6.h> +#include <gpxe/monojob.h> +#include <gpxe/process.h> +#include <usr/ifmgmt.h> +#include <usr/ip6mgmt.h> + +#define LINK_WAIT_MS 15000 + +/* Maximum length of the link-layer address we'll insert as an EUI-64. */ +#define AUTOCONF_LL_MAX 6 + +int ip6_autoconf ( struct net_device *netdev __unused ) { + struct in6_addr ip6addr; + size_t ll_size; + 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; + + /* Create the host ID part of the IPv6 address from the Link-Layer + * address on the netdevice. */ + memset ( &ip6addr, 0, sizeof (struct in6_addr) ); + + ll_size = netdev->ll_protocol->ll_addr_len; + if ( ll_size < 6 ) { + memcpy ( ip6addr.s6_addr + (8 - ll_size), netdev->ll_addr, ll_size ); + } else { + /* Create an EUI-64 identifier. */ + memcpy( ip6addr.s6_addr + 8, netdev->ll_addr, 3 ); + memcpy( ip6addr.s6_addr + 8 + 5, netdev->ll_addr + 3, 3 ); + ip6addr.s6_addr[11] = 0xFF; + ip6addr.s6_addr[12] = 0xFE; + + /* Designate that this is in fact an EUI-64. */ + ip6addr.s6_addr[8] |= 0x2; + } + + /* Fill in the link-local prefix. */ + ip6addr.s6_addr[0] = 0xFE; + ip6addr.s6_addr[1] = 0x80; + + DBG( "ip6 autoconfig address is %s\n", inet6_ntoa(ip6addr) ); + + return 0; +} + -- 1.7.2.5 _______________________________________________ gPXE-devel mailing list [email protected] http://etherboot.org/mailman/listinfo/gpxe-devel
