|  | @@ -1,33 +1,134 @@
 | 
		
	
		
			
			| 1 |  | -#include "resolv.h"
 | 
		
	
		
			
			|  | 1 | +/*
 | 
		
	
		
			
			|  | 2 | + * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
 | 
		
	
		
			
			|  | 3 | + *
 | 
		
	
		
			
			|  | 4 | + * This program is free software; you can redistribute it and/or
 | 
		
	
		
			
			|  | 5 | + * modify it under the terms of the GNU General Public License as
 | 
		
	
		
			
			|  | 6 | + * published by the Free Software Foundation; either version 2 of the
 | 
		
	
		
			
			|  | 7 | + * License, or any later version.
 | 
		
	
		
			
			|  | 8 | + *
 | 
		
	
		
			
			|  | 9 | + * This program is distributed in the hope that it will be useful, but
 | 
		
	
		
			
			|  | 10 | + * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
		
	
		
			
			|  | 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
		
	
		
			
			|  | 12 | + * General Public License for more details.
 | 
		
	
		
			
			|  | 13 | + *
 | 
		
	
		
			
			|  | 14 | + * You should have received a copy of the GNU General Public License
 | 
		
	
		
			
			|  | 15 | + * along with this program; if not, write to the Free Software
 | 
		
	
		
			
			|  | 16 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
		
	
		
			
			|  | 17 | + */
 | 
		
	
		
			
			|  | 18 | +
 | 
		
	
		
			
			|  | 19 | +#include <stdint.h>
 | 
		
	
		
			
			|  | 20 | +#include <stdlib.h>
 | 
		
	
		
			
			|  | 21 | +#include <string.h>
 | 
		
	
		
			
			|  | 22 | +#include <errno.h>
 | 
		
	
		
			
			|  | 23 | +#include <gpxe/in.h>
 | 
		
	
		
			
			|  | 24 | +#include <gpxe/resolv.h>
 | 
		
	
		
			
			| 2 | 25 |  
 | 
		
	
		
			
			|  | 26 | +/** @file
 | 
		
	
		
			
			|  | 27 | + *
 | 
		
	
		
			
			|  | 28 | + * Name resolution
 | 
		
	
		
			
			|  | 29 | + *
 | 
		
	
		
			
			|  | 30 | + */
 | 
		
	
		
			
			|  | 31 | +
 | 
		
	
		
			
			|  | 32 | +static struct async_operations resolv_async_operations;
 | 
		
	
		
			
			|  | 33 | +
 | 
		
	
		
			
			|  | 34 | +/** Registered name resolvers */
 | 
		
	
		
			
			| 3 | 35 |  static struct resolver resolvers[0]
 | 
		
	
		
			
			| 4 |  | -	__table_start ( struct resolver, resolver );
 | 
		
	
		
			
			|  | 36 | +	__table_start ( struct resolver, resolvers );
 | 
		
	
		
			
			| 5 | 37 |  static struct resolver resolvers_end[0]
 | 
		
	
		
			
			| 6 |  | -	__table_end ( struct resolver, resolver );
 | 
		
	
		
			
			|  | 38 | +	__table_end ( struct resolver, resolvers );
 | 
		
	
		
			
			| 7 | 39 |  
 | 
		
	
		
			
			| 8 |  | -/*
 | 
		
	
		
			
			| 9 |  | - * Resolve a name (which may be just a dotted quad IP address) to an
 | 
		
	
		
			
			| 10 |  | - * IP address.
 | 
		
	
		
			
			|  | 40 | +/**
 | 
		
	
		
			
			|  | 41 | + * Start name resolution
 | 
		
	
		
			
			| 11 | 42 |   *
 | 
		
	
		
			
			|  | 43 | + * @v name		Host name to resolve
 | 
		
	
		
			
			|  | 44 | + * @v sa		Socket address to fill in
 | 
		
	
		
			
			|  | 45 | + * @v parent		Parent asynchronous operation
 | 
		
	
		
			
			|  | 46 | + * @ret rc		Return status code
 | 
		
	
		
			
			| 12 | 47 |   */
 | 
		
	
		
			
			| 13 |  | -int resolv ( struct in_addr *address, const char *name ) {
 | 
		
	
		
			
			|  | 48 | +int resolv ( const char *name, struct sockaddr *sa, struct async *parent ) {
 | 
		
	
		
			
			|  | 49 | +	struct resolution *resolution;
 | 
		
	
		
			
			| 14 | 50 |  	struct resolver *resolver;
 | 
		
	
		
			
			|  | 51 | +	struct sockaddr_in *sin = ( struct sockaddr_in * ) sa;
 | 
		
	
		
			
			|  | 52 | +	struct in_addr in;
 | 
		
	
		
			
			|  | 53 | +	int rc = -ENXIO;
 | 
		
	
		
			
			|  | 54 | +
 | 
		
	
		
			
			|  | 55 | +	/* Allocate and populate resolution structure */
 | 
		
	
		
			
			|  | 56 | +	resolution = malloc ( sizeof ( *resolution ) );
 | 
		
	
		
			
			|  | 57 | +	if ( ! resolution )
 | 
		
	
		
			
			|  | 58 | +		return -ENOMEM;
 | 
		
	
		
			
			|  | 59 | +	async_init ( &resolution->async, &resolv_async_operations, parent );
 | 
		
	
		
			
			| 15 | 60 |  
 | 
		
	
		
			
			| 16 | 61 |  	/* Check for a dotted quad IP address first */
 | 
		
	
		
			
			| 17 |  | -	if ( inet_aton ( name, address ) ) {
 | 
		
	
		
			
			| 18 |  | -		DBG ( "RESOLV saw valid IP address %s\n", name );
 | 
		
	
		
			
			| 19 |  | -		return 1;
 | 
		
	
		
			
			|  | 62 | +	if ( inet_aton ( name, &in ) != 0 ) {
 | 
		
	
		
			
			|  | 63 | +		DBGC ( resolution, "RESOLV %p saw valid IP address %s\n",
 | 
		
	
		
			
			|  | 64 | +		       resolution, name );
 | 
		
	
		
			
			|  | 65 | +		sin->sin_family = AF_INET;
 | 
		
	
		
			
			|  | 66 | +		sin->sin_addr = in;
 | 
		
	
		
			
			|  | 67 | +		async_done ( &resolution->async, 0 );
 | 
		
	
		
			
			|  | 68 | +		return 0;
 | 
		
	
		
			
			| 20 | 69 |  	}
 | 
		
	
		
			
			| 21 | 70 |  
 | 
		
	
		
			
			| 22 |  | -	/* Try any compiled-in name resolution modules */
 | 
		
	
		
			
			|  | 71 | +	/* Start up all resolvers */
 | 
		
	
		
			
			| 23 | 72 |  	for ( resolver = resolvers ; resolver < resolvers_end ; resolver++ ) {
 | 
		
	
		
			
			| 24 |  | -		if ( resolver->resolv ( address, name ) ) {
 | 
		
	
		
			
			| 25 |  | -			DBG ( "RESOLV resolved \"%s\" to %@ using %s\n",
 | 
		
	
		
			
			| 26 |  | -			      name, address->s_addr, resolver->name );
 | 
		
	
		
			
			| 27 |  | -			return 1;
 | 
		
	
		
			
			|  | 73 | +		if ( ( rc = resolver->resolv ( name, sa,
 | 
		
	
		
			
			|  | 74 | +					       &resolution->async ) ) != 0 ) {
 | 
		
	
		
			
			|  | 75 | +			DBGC ( resolution, "RESOLV %p could not start %s: "
 | 
		
	
		
			
			|  | 76 | +			       "%s\n", resolution, resolver->name,
 | 
		
	
		
			
			|  | 77 | +			       strerror ( rc ) );
 | 
		
	
		
			
			|  | 78 | +			/* Continue to try other resolvers */
 | 
		
	
		
			
			|  | 79 | +			continue;
 | 
		
	
		
			
			| 28 | 80 |  		}
 | 
		
	
		
			
			|  | 81 | +		(resolution->pending)++;
 | 
		
	
		
			
			| 29 | 82 |  	}
 | 
		
	
		
			
			|  | 83 | +	if ( ! resolution->pending )
 | 
		
	
		
			
			|  | 84 | +		goto err;
 | 
		
	
		
			
			| 30 | 85 |  
 | 
		
	
		
			
			| 31 |  | -	DBG ( "RESOLV failed to resolve %s\n", name );
 | 
		
	
		
			
			| 32 | 86 |  	return 0;
 | 
		
	
		
			
			|  | 87 | +
 | 
		
	
		
			
			|  | 88 | + err:
 | 
		
	
		
			
			|  | 89 | +	async_uninit ( &resolution->async );
 | 
		
	
		
			
			|  | 90 | +	free ( resolution );
 | 
		
	
		
			
			|  | 91 | +	return rc;
 | 
		
	
		
			
			| 33 | 92 |  }
 | 
		
	
		
			
			|  | 93 | +
 | 
		
	
		
			
			|  | 94 | +/**
 | 
		
	
		
			
			|  | 95 | + * Handle child name resolution completion
 | 
		
	
		
			
			|  | 96 | + *
 | 
		
	
		
			
			|  | 97 | + * @v async		Name resolution asynchronous operation
 | 
		
	
		
			
			|  | 98 | + * @v signal		SIGCHLD
 | 
		
	
		
			
			|  | 99 | + */
 | 
		
	
		
			
			|  | 100 | +static void resolv_sigchld ( struct async *async,
 | 
		
	
		
			
			|  | 101 | +			     enum signal signal __unused ) {
 | 
		
	
		
			
			|  | 102 | +	struct resolution *resolution =
 | 
		
	
		
			
			|  | 103 | +		container_of ( async, struct resolution, async );
 | 
		
	
		
			
			|  | 104 | +	int rc;
 | 
		
	
		
			
			|  | 105 | +
 | 
		
	
		
			
			|  | 106 | +	/* If this child succeeded, kill all the others and return */
 | 
		
	
		
			
			|  | 107 | +	async_wait ( async, &rc, 1 );
 | 
		
	
		
			
			|  | 108 | +	if ( rc == 0 ) {
 | 
		
	
		
			
			|  | 109 | +		async_signal_children ( async, SIGKILL );
 | 
		
	
		
			
			|  | 110 | +		async_done ( async, 0 );
 | 
		
	
		
			
			|  | 111 | +		return;
 | 
		
	
		
			
			|  | 112 | +	}
 | 
		
	
		
			
			|  | 113 | +
 | 
		
	
		
			
			|  | 114 | +	/* If we have no children left, return failure */
 | 
		
	
		
			
			|  | 115 | +	if ( --(resolution->pending) == 0 )
 | 
		
	
		
			
			|  | 116 | +		async_done ( async, -ENXIO );
 | 
		
	
		
			
			|  | 117 | +}
 | 
		
	
		
			
			|  | 118 | +
 | 
		
	
		
			
			|  | 119 | +/**
 | 
		
	
		
			
			|  | 120 | + * Free name resolution structure
 | 
		
	
		
			
			|  | 121 | + *
 | 
		
	
		
			
			|  | 122 | + * @v async		Asynchronous operation
 | 
		
	
		
			
			|  | 123 | + */
 | 
		
	
		
			
			|  | 124 | +static void resolv_reap ( struct async *async ) {
 | 
		
	
		
			
			|  | 125 | +	free ( container_of ( async, struct resolution, async ) );
 | 
		
	
		
			
			|  | 126 | +}
 | 
		
	
		
			
			|  | 127 | +
 | 
		
	
		
			
			|  | 128 | +/** Name resolution asynchronous operations */
 | 
		
	
		
			
			|  | 129 | +static struct async_operations resolv_async_operations = {
 | 
		
	
		
			
			|  | 130 | +	.reap = resolv_reap,
 | 
		
	
		
			
			|  | 131 | +	.signal = {
 | 
		
	
		
			
			|  | 132 | +		[SIGCHLD] = resolv_sigchld,
 | 
		
	
		
			
			|  | 133 | +	},
 | 
		
	
		
			
			|  | 134 | +};
 |