00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
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
00062
00063
00064
00065
00066
00067 void ignore_resolv_done ( struct resolv_interface *resolv __unused,
00068 struct sockaddr *sa __unused, int rc __unused ) {
00069
00070 }
00071
00072
00073 struct resolv_interface_operations null_resolv_ops = {
00074 .done = ignore_resolv_done,
00075 };
00076
00077
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
00089
00090
00091
00092
00093
00094 struct numeric_resolv {
00095
00096 struct refcnt refcnt;
00097
00098 struct resolv_interface resolv;
00099
00100 struct process process;
00101
00102 struct sockaddr sa;
00103
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
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
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
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
00151
00152
00153
00154
00155
00156 struct resolv_mux {
00157
00158 struct refcnt refcnt;
00159
00160 struct resolv_interface parent;
00161
00162
00163 struct resolv_interface child;
00164
00165 struct resolver *resolver;
00166
00167
00168 struct sockaddr sa;
00169
00170
00171
00172
00173 char name[0];
00174 };
00175
00176
00177
00178
00179
00180
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
00200
00201
00202
00203
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
00211 resolv_unplug ( &mux->child );
00212
00213
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
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
00230 return;
00231
00232 finished:
00233 resolv_done ( &mux->parent, sa, rc );
00234 }
00235
00236
00237 static struct resolv_interface_operations resolv_mux_child_ops = {
00238 .done = resolv_mux_done,
00239 };
00240
00241
00242
00243
00244
00245
00246
00247
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
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
00268
00269
00270
00271 if ( ( rc = resolv_mux_try ( mux ) ) != 0 )
00272 goto err;
00273
00274
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
00287
00288
00289
00290
00291
00292 struct named_socket {
00293
00294 struct refcnt refcnt;
00295
00296 struct xfer_interface xfer;
00297
00298 struct resolv_interface resolv;
00299
00300 int semantics;
00301
00302 struct sockaddr local;
00303
00304 int have_local;
00305 };
00306
00307
00308
00309
00310
00311
00312
00313 static void named_done ( struct named_socket *named, int rc ) {
00314
00315
00316 resolv_nullify ( &named->resolv );
00317 xfer_nullify ( &named->xfer );
00318 xfer_close ( &named->xfer, rc );
00319 }
00320
00321
00322
00323
00324
00325
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
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
00346
00347
00348
00349
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
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
00365 named_done ( named, rc );
00366 }
00367
00368
00369 static struct resolv_interface_operations named_resolv_ops = {
00370 .done = named_resolv_done,
00371 };
00372
00373
00374
00375
00376
00377
00378
00379
00380
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
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
00404 if ( ( rc = resolv ( &named->resolv, name, peer ) ) != 0 )
00405 goto err;
00406
00407
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 }