diff options
author | Patrick Plenefisch <phplenefisch@wpi.edu> | 2012-08-30 00:21:33 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2012-09-10 15:31:14 +0100 |
commit | 8e4faa094824cae9633ad512ea40c12805435f82 (patch) | |
tree | 9e92aa5f3c7f29ca47b378704233ec5863b8db80 /src/usr | |
parent | c4500fb7cab08beabeee5c2d1e35f964764a7045 (diff) | |
download | ipxe-8e4faa094824cae9633ad512ea40c12805435f82.tar.gz |
[cmdline] Add standalone "nslookup" command
Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/usr')
-rw-r--r-- | src/usr/nslookup.c | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/src/usr/nslookup.c b/src/usr/nslookup.c new file mode 100644 index 00000000..c931ec5a --- /dev/null +++ b/src/usr/nslookup.c @@ -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; +} |