]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[cmdline] Add standalone "nslookup" command
authorPatrick Plenefisch <phplenefisch@wpi.edu>
Wed, 29 Aug 2012 23:21:33 +0000 (00:21 +0100)
committerMichael Brown <mcb30@ipxe.org>
Mon, 10 Sep 2012 14:31:14 +0000 (15:31 +0100)
Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/config/config.c
src/config/general.h
src/hci/commands/nslookup_cmd.c [new file with mode: 0644]
src/include/ipxe/errfile.h
src/include/usr/nslookup.h [new file with mode: 0644]
src/usr/nslookup.c [new file with mode: 0644]

index 78ae93c43157386eba6ce8b3df2653d34d9e773a..81519779cbe8a72528527122f1e1dadadad3c809 100644 (file)
@@ -247,6 +247,9 @@ REQUIRE_OBJECT ( cpuid_cmd );
 #ifdef SYNC_CMD
 REQUIRE_OBJECT ( sync_cmd );
 #endif
+#ifdef NSLOOKUP_CMD
+REQUIRE_OBJECT ( nslookup_cmd );
+#endif
 
 /*
  * Drag in miscellaneous objects
index 638320a46c5f1ef85315ffda495f4e00a632fb92..9f0bb521b580cf34d58eeb00c5a708c82f19d5ba 100644 (file)
@@ -119,6 +119,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #define MENU_CMD               /* Menu commands */
 #define LOGIN_CMD              /* Login command */
 #define SYNC_CMD               /* Sync command */
+//#define NSLOOKUP_CMD         /* DNS resolving command */
 //#define TIME_CMD             /* Time commands */
 //#define DIGEST_CMD           /* Image crypto digest commands */
 //#define LOTEST_CMD           /* Loopback testing commands */
diff --git a/src/hci/commands/nslookup_cmd.c b/src/hci/commands/nslookup_cmd.c
new file mode 100644 (file)
index 0000000..265afdc
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 Patrick Plenefisch <phplenefisch@wpi.edu>.
+ *
+ * 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.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdio.h>
+#include <getopt.h>
+#include <ipxe/command.h>
+#include <ipxe/parseopt.h>
+#include <usr/nslookup.h>
+
+/** @file
+ *
+ * nslookup command
+ *
+ */
+
+/** "nslookup" options */
+struct nslookup_options {};
+
+/** "nslookup" option list */
+static struct option_descriptor nslookup_opts[] = {};
+
+/** "nslookup" command descriptor */
+static struct command_descriptor nslookup_cmd =
+       COMMAND_DESC ( struct nslookup_options, nslookup_opts, 2, 2,
+                      "<setting> <name>" );
+
+/**
+ * The "nslookup" command
+ *
+ * @v argc             Argument count
+ * @v argv             Argument list
+ * @ret rc             Return status code
+ */
+static int nslookup_exec ( int argc, char **argv ) {
+       struct nslookup_options opts;
+       const char *name;
+       const char *setting_name;
+       int rc;
+
+       /* Parse options */
+       if ( ( rc = parse_options ( argc, argv, &nslookup_cmd, &opts ) ) != 0 )
+               return rc;
+
+       /* Parse setting name */
+       setting_name = argv[optind];
+
+       /* Parse name to be resolved */
+       name = argv[ optind + 1 ];
+
+       /* Look up name */
+       if ( ( rc = nslookup ( name, setting_name ) ) != 0 )
+               return rc;
+
+       return 0;
+}
+
+/** The "nslookup" command */
+struct command nslookup_command __command = {
+       .name = "nslookup",
+       .exec = nslookup_exec,
+};
index 5fc0e08218878a7981d85aee1bc09146be063933..8edf5ccb04e7961556f3061d43b6f37c5746c9b7 100644 (file)
@@ -262,6 +262,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #define ERRFILE_menu_cmd             ( ERRFILE_OTHER | 0x002d0000 )
 #define ERRFILE_validator            ( ERRFILE_OTHER | 0x002e0000 )
 #define ERRFILE_ocsp                 ( ERRFILE_OTHER | 0x002f0000 )
+#define ERRFILE_nslookup             ( ERRFILE_OTHER | 0x00300000 )
 
 /** @} */
 
diff --git a/src/include/usr/nslookup.h b/src/include/usr/nslookup.h
new file mode 100644 (file)
index 0000000..d34649e
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _USR_NSLOOKUP_H
+#define _USR_NSLOOKUP_H
+
+/** @file
+ *
+ * Standalone name resolution
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+extern int nslookup ( const char *name, const char *setting_name );
+
+#endif /* _USR_NSLOOKUP_H */
diff --git a/src/usr/nslookup.c b/src/usr/nslookup.c
new file mode 100644 (file)
index 0000000..c931ec5
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2012 Patrick Plenefisch <phplenefisch@wpi.edu>.
+ *
+ * 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.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <ipxe/resolv.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/monojob.h>
+#include <ipxe/settings.h>
+#include <usr/nslookup.h>
+
+/** @file
+ *
+ * Standalone name resolution
+ *
+ */
+
+/** A name resolution request */
+struct nslookup {
+       /** Reference count for this object */
+       struct refcnt refcnt;
+
+       /** Job control interface */
+       struct interface job;
+       /** Data transfer interface */
+       struct interface resolver;
+
+       /** Setting name */
+       const char *setting_name;
+};
+
+/**
+ * Terminate name resolution
+ *
+ * @v nslookup         Name resolution request
+ * @v rc               Reason for termination
+ */
+static void nslookup_close ( struct nslookup *nslookup, int rc ) {
+
+       /* Shut down interfaces */
+       intf_shutdown ( &nslookup->resolver, rc );
+       intf_shutdown ( &nslookup->job, rc );
+}
+
+/**
+ * Handle resolved name
+ *
+ * @v nslookup         Name resolution request
+ * @v sa               Completed socket address
+ */
+static void nslookup_resolv_done ( struct nslookup *nslookup,
+                                  struct sockaddr *sa ) {
+       struct sockaddr_in *sin;
+       struct setting_type *type;
+       void *data;
+       size_t len;
+       int rc;
+
+       /* Extract address */
+       switch ( sa->sa_family ) {
+       case AF_INET:
+               sin = ( ( struct sockaddr_in * ) sa );
+               data = &sin->sin_addr;
+               len = sizeof ( sin->sin_addr );
+               type = &setting_type_ipv4;
+               break;
+       default:
+               rc = -ENOTSUP;
+               goto err;
+       }
+
+       /* Save in specified setting */
+       if ( ( rc = store_named_setting ( nslookup->setting_name, type,
+                                         data, len ) ) != 0 )
+               goto err;
+
+ err:
+       /* Terminate name resolution */
+       nslookup_close ( nslookup, rc );
+}
+
+/** Name resolution resolver interface operations */
+static struct interface_operation nslookup_resolver_operations[] = {
+       INTF_OP ( resolv_done, struct nslookup *, nslookup_resolv_done ),
+       INTF_OP ( intf_close, struct nslookup *, nslookup_close ),
+};
+
+/** Name resolution resolver interface descriptor */
+static struct interface_descriptor nslookup_resolver_desc =
+       INTF_DESC_PASSTHRU ( struct nslookup, resolver,
+                            nslookup_resolver_operations, job );
+
+/** Name resolution job control interface operations */
+static struct interface_operation nslookup_job_operations[] = {
+       INTF_OP ( intf_close, struct nslookup *, nslookup_close ),
+};
+
+/** Name resolution job control interface descriptor */
+static struct interface_descriptor nslookup_job_desc =
+       INTF_DESC_PASSTHRU ( struct nslookup, job,
+                            nslookup_job_operations, resolver );
+
+/**
+ * Initiate standalone name resolution
+ *
+ * @v job              Parent interface
+ * @v name             Name to resolve
+ * @v setting_name     Setting name
+ * @ret rc             Return status code
+ */
+static int resolv_setting ( struct interface *job, const char *name,
+                           const char *setting_name ) {
+       struct nslookup *nslookup;
+       struct sockaddr sa;
+       char *setting_name_copy;
+       int rc;
+
+       /* Allocate and initialise structure */
+       nslookup = zalloc ( sizeof ( *nslookup ) + strlen ( setting_name )
+                           + 1 /* NUL */ );
+       if ( ! nslookup )
+               return -ENOMEM;
+       ref_init ( &nslookup->refcnt, NULL );
+       intf_init ( &nslookup->job, &nslookup_job_desc, &nslookup->refcnt );
+       intf_init ( &nslookup->resolver, &nslookup_resolver_desc,
+                   &nslookup->refcnt );
+       setting_name_copy = ( ( void * ) ( nslookup + 1 ) );
+       strcpy ( setting_name_copy, setting_name );
+       nslookup->setting_name = setting_name_copy;
+
+       /* Start name resolution */
+       memset ( &sa, 0, sizeof ( sa ) );
+       if ( ( rc = resolv ( &nslookup->resolver, name, &sa ) ) != 0 )
+               goto err_resolv;
+
+       /* Attach parent interface, mortalise self, and return */
+       intf_plug_plug ( &nslookup->job, job );
+       ref_put ( &nslookup->refcnt );
+       return 0;
+
+ err_resolv:
+       ref_put ( &nslookup->refcnt );
+       return rc;
+}
+
+/**
+ * Perform (blocking) standalone name resolution
+ *
+ * @v name             Name to resolve
+ * @v setting_name     Setting name
+ * @ret rc             Return status code
+ */
+int nslookup ( const char *name, const char *setting_name ) {
+       int rc;
+
+       /* Perform name resolution */
+       if ( ( rc = resolv_setting ( &monojob, name, setting_name ) ) == 0 )
+               rc = monojob_wait ( NULL );
+       if ( rc != 0 ) {
+               printf ( "Could not resolve %s: %s\n", name, strerror ( rc ) );
+               return rc;
+       }
+
+       return 0;
+}