[dhcp] Allow multiple interfaces in dhcp command
[people/peper/gpxe.git] / src / hci / commands / dhcp_cmd.c
index 96aac8d..6f0a99f 100644 (file)
@@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <gpxe/in.h>
 #include <gpxe/command.h>
 #include <usr/dhcpmgmt.h>
+#include <usr/ifmgmt.h>
 
 /** @file
  *
@@ -45,10 +46,79 @@ FILE_LICENCE ( GPL2_OR_LATER );
  */
 static void dhcp_syntax ( char **argv ) {
        printf ( "Usage:\n"
-                "  %s <interface>\n"
+                "  %s <interface> [<interface> ...]\n"
+                "  %s any\n"
                 "\n"
                 "Configure a network interface using DHCP\n",
-                argv[0] );
+                argv[0], argv[0] );
+}
+
+/**
+ * Attempt to configure a device with dhcp
+ *
+ * @v netdev           Device to configure
+ * @ret rc             Exit code
+ */
+static int dhcp_one_device ( struct net_device *netdev ) {
+       int rc;
+
+       /* Perform DHCP */
+       if ( ( rc = dhcp ( 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 dhcp_one_device() for each name in argv
+ *
+ * @v argc             Number of devices
+ * @v argv             List of device names
+ * @ret rc             Exit code
+ */
+static int dhcp_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 ( dhcp_one_device ( netdev ) == 0 )
+                       return 0;
+       }
+
+       printf ( "Could not configure any interface.\n" );
+       return 1;
+}
+
+/**
+ * Call dhcp_one_device() for each device in net_devices
+ *
+ * @ret rc             Exit code
+ */
+static int dhcp_each_device ( void ) {
+       struct net_device *netdev;
+
+       for_each_netdev ( netdev ) {
+               if ( dhcp_one_device ( netdev ) == 0 )
+                       return 0;
+       }
+
+       printf ( "Could not configure any interface.\n" );
+       return 1;
 }
 
 /**
@@ -63,10 +133,7 @@ static int dhcp_exec ( int argc, char **argv ) {
                { "help", 0, NULL, 'h' },
                { NULL, 0, NULL, 0 },
        };
-       const char *netdev_txt;
-       struct net_device *netdev;
        int c;
-       int rc;
 
        /* Parse options */
        while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
@@ -80,28 +147,16 @@ static int dhcp_exec ( int argc, char **argv ) {
                }
        }
 
-       /* Need exactly one interface name remaining after the options */
-       if ( optind != ( argc - 1 ) ) {
+       /* Need one or more interface names remaining after the options */
+       if ( ( argc - optind ) < 1 ) {
                dhcp_syntax ( argv );
                return 1;
        }
-       netdev_txt = argv[optind];
 
-       /* Parse arguments */
-       netdev = find_netdev ( netdev_txt );
-       if ( ! netdev ) {
-               printf ( "No such interface: %s\n", netdev_txt );
-               return 1;
-       }
-
-       /* Perform DHCP */
-       if ( ( rc = dhcp ( netdev ) ) != 0 ) {
-               printf ( "Could not configure %s: %s\n", netdev->name,
-                        strerror ( rc ) );
-               return 1;
-       }
+       if ( strcmp ( argv[optind], "any" ) == 0 )
+               return dhcp_each_device();
 
-       return 0;
+       return dhcp_each_device_name ( argc - optind, argv + optind );
 }
 
 /**