Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2007 Michael Brown <mbrown (at) 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 FILE_LICENCE ( GPL2_OR_LATER );
     20 
     21 #include <stdint.h>
     22 #include <stdlib.h>
     23 #include <string.h>
     24 #include <errno.h>
     25 #include <gpxe/in.h>
     26 #include <gpxe/xfer.h>
     27 #include <gpxe/open.h>
     28 #include <gpxe/process.h>
     29 #include <gpxe/resolv.h>
     30 
     31 /** @file
     32  *
     33  * Name resolution
     34  *
     35  */
     36 
     37 /***************************************************************************
     38  *
     39  * Name resolution interfaces
     40  *
     41  ***************************************************************************
     42  */
     43 
     44 /**
     45  * Name resolution completed
     46  *
     47  * @v resolv		Name resolution interface
     48  * @v sa		Completed socket address (if successful)
     49  * @v rc		Final status code
     50  */
     51 void resolv_done ( struct resolv_interface *resolv, struct sockaddr *sa,
     52 		   int rc ) {
     53 	struct resolv_interface *dest = resolv_get_dest ( resolv );
     54 
     55 	resolv_unplug ( resolv );
     56 	dest->op->done ( dest, sa, rc );
     57 	resolv_put ( dest );
     58 }
     59 
     60 /**
     61  * Ignore name resolution done() event
     62  *
     63  * @v resolv		Name resolution interface
     64  * @v sa		Completed socket address (if successful)
     65  * @v rc		Final status code
     66  */
     67 void ignore_resolv_done ( struct resolv_interface *resolv __unused,
     68 			  struct sockaddr *sa __unused, int rc __unused ) {
     69 	/* Do nothing */
     70 }
     71 
     72 /** Null name resolution interface operations */
     73 struct resolv_interface_operations null_resolv_ops = {
     74 	.done		= ignore_resolv_done,
     75 };
     76 
     77 /** Null name resolution interface */
     78 struct resolv_interface null_resolv = {
     79 	.intf = {
     80 		.dest = &null_resolv.intf,
     81 		.refcnt = NULL,
     82 	},
     83 	.op = &null_resolv_ops,
     84 };
     85 
     86 /***************************************************************************
     87  *
     88  * Numeric name resolver
     89  *
     90  ***************************************************************************
     91  */
     92 
     93 /** A numeric name resolver */
     94 struct numeric_resolv {
     95 	/** Reference counter */
     96 	struct refcnt refcnt;
     97 	/** Name resolution interface */
     98 	struct resolv_interface resolv;
     99 	/** Process */
    100 	struct process process;
    101 	/** Completed socket address */
    102 	struct sockaddr sa;
    103 	/** Overall status code */
    104 	int rc;
    105 };
    106 
    107 static void numeric_step ( struct process *process ) {
    108 	struct numeric_resolv *numeric =
    109 		container_of ( process, struct numeric_resolv, process );
    110 
    111 	resolv_done ( &numeric->resolv, &numeric->sa, numeric->rc );
    112 	process_del ( process );
    113 }
    114 
    115 static int numeric_resolv ( struct resolv_interface *resolv,
    116 			    const char *name, struct sockaddr *sa ) {
    117 	struct numeric_resolv *numeric;
    118 	struct sockaddr_in *sin;
    119 
    120 	/* Allocate and initialise structure */
    121 	numeric = zalloc ( sizeof ( *numeric ) );
    122 	if ( ! numeric )
    123 		return -ENOMEM;
    124 	resolv_init ( &numeric->resolv, &null_resolv_ops, &numeric->refcnt );
    125 	process_init ( &numeric->process, numeric_step, &numeric->refcnt );
    126 	memcpy ( &numeric->sa, sa, sizeof ( numeric->sa ) );
    127 
    128 	DBGC ( numeric, "NUMERIC %p attempting to resolve \"%s\"\n",
    129 	       numeric, name );
    130 
    131 	/* Attempt to resolve name */
    132 	sin = ( ( struct sockaddr_in * ) &numeric->sa );
    133 	sin->sin_family = AF_INET;
    134 	if ( inet_aton ( name, &sin->sin_addr ) == 0 )
    135 		numeric->rc = -EINVAL;
    136 
    137 	/* Attach to parent interface, mortalise self, and return */
    138 	resolv_plug_plug ( &numeric->resolv, resolv );
    139 	ref_put ( &numeric->refcnt );
    140 	return 0;
    141 }
    142 
    143 struct resolver numeric_resolver __resolver ( RESOLV_NUMERIC ) = {
    144 	.name = "NUMERIC",
    145 	.resolv = numeric_resolv,
    146 };
    147 
    148 /***************************************************************************
    149  *
    150  * Name resolution multiplexer
    151  *
    152  ***************************************************************************
    153  */
    154 
    155 /** A name resolution multiplexer */
    156 struct resolv_mux {
    157 	/** Reference counter */
    158 	struct refcnt refcnt;
    159 	/** Parent name resolution interface */
    160 	struct resolv_interface parent;
    161 
    162 	/** Child name resolution interface */
    163 	struct resolv_interface child;
    164 	/** Current child resolver */
    165 	struct resolver *resolver;
    166 
    167 	/** Socket address to complete */
    168 	struct sockaddr sa;
    169 	/** Name to be resolved
    170 	 *
    171 	 * Must be at end of structure
    172 	 */
    173 	char name[0];
    174 };
    175 
    176 /**
    177  * Try current child name resolver
    178  *
    179  * @v mux		Name resolution multiplexer
    180  * @ret rc		Return status code
    181  */
    182 static int resolv_mux_try ( struct resolv_mux *mux ) {
    183 	struct resolver *resolver = mux->resolver;
    184 	int rc;
    185 
    186 	DBGC ( mux, "RESOLV %p trying method %s\n", mux, resolver->name );
    187 
    188 	if ( ( rc = resolver->resolv ( &mux->child, mux->name,
    189 				       &mux->sa ) ) != 0 ) {
    190 		DBGC ( mux, "RESOLV %p could not use method %s: %s\n",
    191 		       mux, resolver->name, strerror ( rc ) );
    192 		return rc;
    193 	}
    194 
    195 	return 0;
    196 }
    197 
    198 /**
    199  * Handle done() event from child name resolver
    200  *
    201  * @v resolv		Child name resolution interface
    202  * @v sa		Completed socket address (if successful)
    203  * @v rc		Final status code
    204  */
    205 static void resolv_mux_done ( struct resolv_interface *resolv,
    206 			      struct sockaddr *sa, int rc ) {
    207 	struct resolv_mux *mux =
    208 		container_of ( resolv, struct resolv_mux, child );
    209 
    210 	/* Unplug child */
    211 	resolv_unplug ( &mux->child );
    212 
    213 	/* If this resolution succeeded, stop now */
    214 	if ( rc == 0 ) {
    215 		DBGC ( mux, "RESOLV %p succeeded using method %s\n",
    216 		       mux, mux->resolver->name );
    217 		goto finished;
    218 	}
    219 
    220 	/* Attempt next child resolver, if possible */
    221 	mux->resolver++;
    222 	if ( mux->resolver >= table_end ( RESOLVERS ) ) {
    223 		DBGC ( mux, "RESOLV %p failed to resolve name\n", mux );
    224 		goto finished;
    225 	}
    226 	if ( ( rc = resolv_mux_try ( mux ) ) != 0 )
    227 		goto finished;
    228 
    229 	/* Next resolver is now running */
    230 	return;
    231 
    232  finished:
    233 	resolv_done ( &mux->parent, sa, rc );
    234 }
    235 
    236 /** Name resolution multiplexer operations */
    237 static struct resolv_interface_operations resolv_mux_child_ops = {
    238 	.done		= resolv_mux_done,
    239 };
    240 
    241 /**
    242  * Start name resolution
    243  *
    244  * @v resolv		Name resolution interface
    245  * @v name		Name to resolve
    246  * @v sa		Socket address to complete
    247  * @ret rc		Return status code
    248  */
    249 int resolv ( struct resolv_interface *resolv, const char *name,
    250 	     struct sockaddr *sa ) {
    251 	struct resolv_mux *mux;
    252 	size_t name_len = ( strlen ( name ) + 1 );
    253 	int rc;
    254 
    255 	/* Allocate and initialise structure */
    256 	mux = zalloc ( sizeof ( *mux ) + name_len );
    257 	if ( ! mux )
    258 		return -ENOMEM;
    259 	resolv_init ( &mux->parent, &null_resolv_ops, &mux->refcnt );
    260 	resolv_init ( &mux->child, &resolv_mux_child_ops, &mux->refcnt );
    261 	mux->resolver = table_start ( RESOLVERS );
    262 	memcpy ( &mux->sa, sa, sizeof ( mux->sa ) );
    263 	memcpy ( mux->name, name, name_len );
    264 
    265 	DBGC ( mux, "RESOLV %p attempting to resolve \"%s\"\n", mux, name );
    266 
    267 	/* Start first resolver in chain.  There will always be at
    268 	 * least one resolver (the numeric resolver), so no need to
    269 	 * check for the zero-resolvers-available case.
    270 	 */
    271 	if ( ( rc = resolv_mux_try ( mux ) ) != 0 )
    272 		goto err;
    273 
    274 	/* Attach parent interface, mortalise self, and return */
    275 	resolv_plug_plug ( &mux->parent, resolv );
    276 	ref_put ( &mux->refcnt );
    277 	return 0;
    278 
    279  err:
    280 	ref_put ( &mux->refcnt );
    281 	return rc;
    282 }
    283 
    284 /***************************************************************************
    285  *
    286  * Named socket opening
    287  *
    288  ***************************************************************************
    289  */
    290 
    291 /** A named socket */
    292 struct named_socket {
    293 	/** Reference counter */
    294 	struct refcnt refcnt;
    295 	/** Data transfer interface */
    296 	struct xfer_interface xfer;
    297 	/** Name resolution interface */
    298 	struct resolv_interface resolv;
    299 	/** Communication semantics (e.g. SOCK_STREAM) */
    300 	int semantics;
    301 	/** Stored local socket address, if applicable */
    302 	struct sockaddr local;
    303 	/** Stored local socket address exists */
    304 	int have_local;
    305 };
    306 
    307 /**
    308  * Finish using named socket
    309  *
    310  * @v named		Named socket
    311  * @v rc		Reason for finish
    312  */
    313 static void named_done ( struct named_socket *named, int rc ) {
    314 
    315 	/* Close all interfaces */
    316 	resolv_nullify ( &named->resolv );
    317 	xfer_nullify ( &named->xfer );
    318 	xfer_close ( &named->xfer, rc );
    319 }
    320 
    321 /**
    322  * Handle close() event
    323  *
    324  * @v xfer		Data transfer interface
    325  * @v rc		Reason for close
    326  */
    327 static void named_xfer_close ( struct xfer_interface *xfer, int rc ) {
    328 	struct named_socket *named =
    329 		container_of ( xfer, struct named_socket, xfer );
    330 
    331 	named_done ( named, rc );
    332 }
    333 
    334 /** Named socket opener data transfer interface operations */
    335 static struct xfer_interface_operations named_xfer_ops = {
    336 	.close		= named_xfer_close,
    337 	.vredirect	= ignore_xfer_vredirect,
    338 	.window		= no_xfer_window,
    339 	.alloc_iob	= default_xfer_alloc_iob,
    340 	.deliver_iob	= xfer_deliver_as_raw,
    341 	.deliver_raw	= ignore_xfer_deliver_raw,
    342 };
    343 
    344 /**
    345  * Handle done() event
    346  *
    347  * @v resolv		Name resolution interface
    348  * @v sa		Completed socket address (if successful)
    349  * @v rc		Final status code
    350  */
    351 static void named_resolv_done ( struct resolv_interface *resolv,
    352 				struct sockaddr *sa, int rc ) {
    353 	struct named_socket *named =
    354 		container_of ( resolv, struct named_socket, resolv );
    355 
    356 	/* Redirect if name resolution was successful */
    357 	if ( rc == 0 ) {
    358 		rc = xfer_redirect ( &named->xfer, LOCATION_SOCKET,
    359 				     named->semantics, sa,
    360 				     ( named->have_local ?
    361 				       &named->local : NULL ) );
    362 	}
    363 
    364 	/* Terminate resolution */
    365 	named_done ( named, rc );
    366 }
    367 
    368 /** Named socket opener name resolution interface operations */
    369 static struct resolv_interface_operations named_resolv_ops = {
    370 	.done		= named_resolv_done,
    371 };
    372 
    373 /**
    374  * Open named socket
    375  *
    376  * @v semantics		Communication semantics (e.g. SOCK_STREAM)
    377  * @v peer		Peer socket address to complete
    378  * @v name		Name to resolve
    379  * @v local		Local socket address, or NULL
    380  * @ret rc		Return status code
    381  */
    382 int xfer_open_named_socket ( struct xfer_interface *xfer, int semantics,
    383 			     struct sockaddr *peer, const char *name,
    384 			     struct sockaddr *local ) {
    385 	struct named_socket *named;
    386 	int rc;
    387 
    388 	/* Allocate and initialise structure */
    389 	named = zalloc ( sizeof ( *named ) );
    390 	if ( ! named )
    391 		return -ENOMEM;
    392 	xfer_init ( &named->xfer, &named_xfer_ops, &named->refcnt );
    393 	resolv_init ( &named->resolv, &named_resolv_ops, &named->refcnt );
    394 	named->semantics = semantics;
    395 	if ( local ) {
    396 		memcpy ( &named->local, local, sizeof ( named->local ) );
    397 		named->have_local = 1;
    398 	}
    399 
    400 	DBGC ( named, "RESOLV %p opening named socket \"%s\"\n",
    401 	       named, name );
    402 
    403 	/* Start name resolution */
    404 	if ( ( rc = resolv ( &named->resolv, name, peer ) ) != 0 )
    405 		goto err;
    406 
    407 	/* Attach parent interface, mortalise self, and return */
    408 	xfer_plug_plug ( &named->xfer, xfer );
    409 	ref_put ( &named->refcnt );
    410 	return 0;
    411 
    412  err:
    413 	ref_put ( &named->refcnt );
    414 	return rc;
    415 }
    416