resolv.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 FILE_LICENCE ( GPL2_OR_LATER );
00020 
00021 #include <stdint.h>
00022 #include <stdlib.h>
00023 #include <string.h>
00024 #include <errno.h>
00025 #include <gpxe/in.h>
00026 #include <gpxe/xfer.h>
00027 #include <gpxe/open.h>
00028 #include <gpxe/process.h>
00029 #include <gpxe/resolv.h>
00030 
00031 /** @file
00032  *
00033  * Name resolution
00034  *
00035  */
00036 
00037 /***************************************************************************
00038  *
00039  * Name resolution interfaces
00040  *
00041  ***************************************************************************
00042  */
00043 
00044 /**
00045  * Name resolution completed
00046  *
00047  * @v resolv            Name resolution interface
00048  * @v sa                Completed socket address (if successful)
00049  * @v rc                Final status code
00050  */
00051 void resolv_done ( struct resolv_interface *resolv, struct sockaddr *sa,
00052                    int rc ) {
00053         struct resolv_interface *dest = resolv_get_dest ( resolv );
00054 
00055         resolv_unplug ( resolv );
00056         dest->op->done ( dest, sa, rc );
00057         resolv_put ( dest );
00058 }
00059 
00060 /**
00061  * Ignore name resolution done() event
00062  *
00063  * @v resolv            Name resolution interface
00064  * @v sa                Completed socket address (if successful)
00065  * @v rc                Final status code
00066  */
00067 void ignore_resolv_done ( struct resolv_interface *resolv __unused,
00068                           struct sockaddr *sa __unused, int rc __unused ) {
00069         /* Do nothing */
00070 }
00071 
00072 /** Null name resolution interface operations */
00073 struct resolv_interface_operations null_resolv_ops = {
00074         .done           = ignore_resolv_done,
00075 };
00076 
00077 /** Null name resolution interface */
00078 struct resolv_interface null_resolv = {
00079         .intf = {
00080                 .dest = &null_resolv.intf,
00081                 .refcnt = NULL,
00082         },
00083         .op = &null_resolv_ops,
00084 };
00085 
00086 /***************************************************************************
00087  *
00088  * Numeric name resolver
00089  *
00090  ***************************************************************************
00091  */
00092 
00093 /** A numeric name resolver */
00094 struct numeric_resolv {
00095         /** Reference counter */
00096         struct refcnt refcnt;
00097         /** Name resolution interface */
00098         struct resolv_interface resolv;
00099         /** Process */
00100         struct process process;
00101         /** Completed socket address */
00102         struct sockaddr sa;
00103         /** Overall status code */
00104         int rc;
00105 };
00106 
00107 static void numeric_step ( struct process *process ) {
00108         struct numeric_resolv *numeric =
00109                 container_of ( process, struct numeric_resolv, process );
00110         
00111         resolv_done ( &numeric->resolv, &numeric->sa, numeric->rc );
00112         process_del ( process );
00113 }
00114 
00115 static int numeric_resolv ( struct resolv_interface *resolv,
00116                             const char *name, struct sockaddr *sa ) {
00117         struct numeric_resolv *numeric;
00118         struct sockaddr_in *sin;
00119 
00120         /* Allocate and initialise structure */
00121         numeric = zalloc ( sizeof ( *numeric ) );
00122         if ( ! numeric )
00123                 return -ENOMEM;
00124         resolv_init ( &numeric->resolv, &null_resolv_ops, &numeric->refcnt );
00125         process_init ( &numeric->process, numeric_step, &numeric->refcnt );
00126         memcpy ( &numeric->sa, sa, sizeof ( numeric->sa ) );
00127 
00128         DBGC ( numeric, "NUMERIC %p attempting to resolve \"%s\"\n",
00129                numeric, name );
00130 
00131         /* Attempt to resolve name */
00132         sin = ( ( struct sockaddr_in * ) &numeric->sa );
00133         sin->sin_family = AF_INET;
00134         if ( inet_aton ( name, &sin->sin_addr ) == 0 )
00135                 numeric->rc = -EINVAL;
00136 
00137         /* Attach to parent interface, mortalise self, and return */
00138         resolv_plug_plug ( &numeric->resolv, resolv );
00139         ref_put ( &numeric->refcnt );
00140         return 0;
00141 }
00142 
00143 struct resolver numeric_resolver __resolver ( RESOLV_NUMERIC ) = {
00144         .name = "NUMERIC",
00145         .resolv = numeric_resolv,
00146 };
00147 
00148 /***************************************************************************
00149  *
00150  * Name resolution multiplexer
00151  *
00152  ***************************************************************************
00153  */
00154 
00155 /** A name resolution multiplexer */
00156 struct resolv_mux {
00157         /** Reference counter */
00158         struct refcnt refcnt;
00159         /** Parent name resolution interface */
00160         struct resolv_interface parent;
00161 
00162         /** Child name resolution interface */
00163         struct resolv_interface child;
00164         /** Current child resolver */
00165         struct resolver *resolver;
00166 
00167         /** Socket address to complete */
00168         struct sockaddr sa;
00169         /** Name to be resolved
00170          *
00171          * Must be at end of structure
00172          */
00173         char name[0];
00174 };
00175 
00176 /**
00177  * Try current child name resolver
00178  *
00179  * @v mux               Name resolution multiplexer
00180  * @ret rc              Return status code
00181  */
00182 static int resolv_mux_try ( struct resolv_mux *mux ) {
00183         struct resolver *resolver = mux->resolver;
00184         int rc;
00185 
00186         DBGC ( mux, "RESOLV %p trying method %s\n", mux, resolver->name );
00187 
00188         if ( ( rc = resolver->resolv ( &mux->child, mux->name,
00189                                        &mux->sa ) ) != 0 ) {
00190                 DBGC ( mux, "RESOLV %p could not use method %s: %s\n",
00191                        mux, resolver->name, strerror ( rc ) );
00192                 return rc;
00193         }
00194 
00195         return 0;
00196 }
00197 
00198 /**
00199  * Handle done() event from child name resolver
00200  *
00201  * @v resolv            Child name resolution interface
00202  * @v sa                Completed socket address (if successful)
00203  * @v rc                Final status code
00204  */
00205 static void resolv_mux_done ( struct resolv_interface *resolv,
00206                               struct sockaddr *sa, int rc ) {
00207         struct resolv_mux *mux =
00208                 container_of ( resolv, struct resolv_mux, child );
00209 
00210         /* Unplug child */
00211         resolv_unplug ( &mux->child );
00212 
00213         /* If this resolution succeeded, stop now */
00214         if ( rc == 0 ) {
00215                 DBGC ( mux, "RESOLV %p succeeded using method %s\n",
00216                        mux, mux->resolver->name );
00217                 goto finished;
00218         }
00219 
00220         /* Attempt next child resolver, if possible */
00221         mux->resolver++;
00222         if ( mux->resolver >= table_end ( RESOLVERS ) ) {
00223                 DBGC ( mux, "RESOLV %p failed to resolve name\n", mux );
00224                 goto finished;
00225         }
00226         if ( ( rc = resolv_mux_try ( mux ) ) != 0 )
00227                 goto finished;
00228 
00229         /* Next resolver is now running */
00230         return;
00231         
00232  finished:
00233         resolv_done ( &mux->parent, sa, rc );
00234 }
00235 
00236 /** Name resolution multiplexer operations */
00237 static struct resolv_interface_operations resolv_mux_child_ops = {
00238         .done           = resolv_mux_done,
00239 };
00240 
00241 /**
00242  * Start name resolution
00243  *
00244  * @v resolv            Name resolution interface
00245  * @v name              Name to resolve
00246  * @v sa                Socket address to complete
00247  * @ret rc              Return status code
00248  */
00249 int resolv ( struct resolv_interface *resolv, const char *name,
00250              struct sockaddr *sa ) {
00251         struct resolv_mux *mux;
00252         size_t name_len = ( strlen ( name ) + 1 );
00253         int rc;
00254 
00255         /* Allocate and initialise structure */
00256         mux = zalloc ( sizeof ( *mux ) + name_len );
00257         if ( ! mux )
00258                 return -ENOMEM;
00259         resolv_init ( &mux->parent, &null_resolv_ops, &mux->refcnt );
00260         resolv_init ( &mux->child, &resolv_mux_child_ops, &mux->refcnt );
00261         mux->resolver = table_start ( RESOLVERS );
00262         memcpy ( &mux->sa, sa, sizeof ( mux->sa ) );
00263         memcpy ( mux->name, name, name_len );
00264 
00265         DBGC ( mux, "RESOLV %p attempting to resolve \"%s\"\n", mux, name );
00266 
00267         /* Start first resolver in chain.  There will always be at
00268          * least one resolver (the numeric resolver), so no need to
00269          * check for the zero-resolvers-available case.
00270          */
00271         if ( ( rc = resolv_mux_try ( mux ) ) != 0 )
00272                 goto err;
00273 
00274         /* Attach parent interface, mortalise self, and return */
00275         resolv_plug_plug ( &mux->parent, resolv );
00276         ref_put ( &mux->refcnt );
00277         return 0;
00278 
00279  err:
00280         ref_put ( &mux->refcnt );
00281         return rc;      
00282 }
00283 
00284 /***************************************************************************
00285  *
00286  * Named socket opening
00287  *
00288  ***************************************************************************
00289  */
00290 
00291 /** A named socket */
00292 struct named_socket {
00293         /** Reference counter */
00294         struct refcnt refcnt;
00295         /** Data transfer interface */
00296         struct xfer_interface xfer;
00297         /** Name resolution interface */
00298         struct resolv_interface resolv;
00299         /** Communication semantics (e.g. SOCK_STREAM) */
00300         int semantics;
00301         /** Stored local socket address, if applicable */
00302         struct sockaddr local;
00303         /** Stored local socket address exists */
00304         int have_local;
00305 };
00306 
00307 /**
00308  * Finish using named socket
00309  *
00310  * @v named             Named socket
00311  * @v rc                Reason for finish
00312  */
00313 static void named_done ( struct named_socket *named, int rc ) {
00314 
00315         /* Close all interfaces */
00316         resolv_nullify ( &named->resolv );
00317         xfer_nullify ( &named->xfer );
00318         xfer_close ( &named->xfer, rc );
00319 }
00320 
00321 /**
00322  * Handle close() event
00323  *
00324  * @v xfer              Data transfer interface
00325  * @v rc                Reason for close
00326  */
00327 static void named_xfer_close ( struct xfer_interface *xfer, int rc ) {
00328         struct named_socket *named =
00329                 container_of ( xfer, struct named_socket, xfer );
00330 
00331         named_done ( named, rc );
00332 }
00333 
00334 /** Named socket opener data transfer interface operations */
00335 static struct xfer_interface_operations named_xfer_ops = {
00336         .close          = named_xfer_close,
00337         .vredirect      = ignore_xfer_vredirect,
00338         .window         = no_xfer_window,
00339         .alloc_iob      = default_xfer_alloc_iob,
00340         .deliver_iob    = xfer_deliver_as_raw,
00341         .deliver_raw    = ignore_xfer_deliver_raw,
00342 };
00343 
00344 /**
00345  * Handle done() event
00346  *
00347  * @v resolv            Name resolution interface
00348  * @v sa                Completed socket address (if successful)
00349  * @v rc                Final status code
00350  */
00351 static void named_resolv_done ( struct resolv_interface *resolv,
00352                                 struct sockaddr *sa, int rc ) {
00353         struct named_socket *named =
00354                 container_of ( resolv, struct named_socket, resolv );
00355 
00356         /* Redirect if name resolution was successful */
00357         if ( rc == 0 ) {
00358                 rc = xfer_redirect ( &named->xfer, LOCATION_SOCKET,
00359                                      named->semantics, sa,
00360                                      ( named->have_local ?
00361                                        &named->local : NULL ) );
00362         }
00363 
00364         /* Terminate resolution */
00365         named_done ( named, rc );
00366 }
00367 
00368 /** Named socket opener name resolution interface operations */
00369 static struct resolv_interface_operations named_resolv_ops = {
00370         .done           = named_resolv_done,
00371 };
00372 
00373 /**
00374  * Open named socket
00375  *
00376  * @v semantics         Communication semantics (e.g. SOCK_STREAM)
00377  * @v peer              Peer socket address to complete
00378  * @v name              Name to resolve
00379  * @v local             Local socket address, or NULL
00380  * @ret rc              Return status code
00381  */
00382 int xfer_open_named_socket ( struct xfer_interface *xfer, int semantics,
00383                              struct sockaddr *peer, const char *name,
00384                              struct sockaddr *local ) {
00385         struct named_socket *named;
00386         int rc;
00387 
00388         /* Allocate and initialise structure */
00389         named = zalloc ( sizeof ( *named ) );
00390         if ( ! named )
00391                 return -ENOMEM;
00392         xfer_init ( &named->xfer, &named_xfer_ops, &named->refcnt );
00393         resolv_init ( &named->resolv, &named_resolv_ops, &named->refcnt );
00394         named->semantics = semantics;
00395         if ( local ) {
00396                 memcpy ( &named->local, local, sizeof ( named->local ) );
00397                 named->have_local = 1;
00398         }
00399 
00400         DBGC ( named, "RESOLV %p opening named socket \"%s\"\n",
00401                named, name );
00402 
00403         /* Start name resolution */
00404         if ( ( rc = resolv ( &named->resolv, name, peer ) ) != 0 )
00405                 goto err;
00406 
00407         /* Attach parent interface, mortalise self, and return */
00408         xfer_plug_plug ( &named->xfer, xfer );
00409         ref_put ( &named->refcnt );
00410         return 0;
00411 
00412  err:
00413         ref_put ( &named->refcnt );
00414         return rc;
00415 }

Generated on Tue Apr 6 20:00:51 2010 for gPXE by  doxygen 1.5.7.1