Adding debian version 3.70~pre8+dfsg-1.
[syslinux-debian/hramrach.git] / gpxe / src / core / resolv.c
blobf4a587f1f5ab4252dd9e54957a81964aa006a0ac
1 /*
2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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.
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <gpxe/in.h>
24 #include <gpxe/xfer.h>
25 #include <gpxe/open.h>
26 #include <gpxe/process.h>
27 #include <gpxe/resolv.h>
29 /** @file
31 * Name resolution
35 /***************************************************************************
37 * Name resolution interfaces
39 ***************************************************************************
42 /**
43 * Name resolution completed
45 * @v resolv Name resolution interface
46 * @v sa Completed socket address (if successful)
47 * @v rc Final status code
49 void resolv_done ( struct resolv_interface *resolv, struct sockaddr *sa,
50 int rc ) {
51 struct resolv_interface *dest = resolv_get_dest ( resolv );
53 resolv_unplug ( resolv );
54 dest->op->done ( dest, sa, rc );
55 resolv_put ( dest );
58 /**
59 * Ignore name resolution done() event
61 * @v resolv Name resolution interface
62 * @v sa Completed socket address (if successful)
63 * @v rc Final status code
65 void ignore_resolv_done ( struct resolv_interface *resolv __unused,
66 struct sockaddr *sa __unused, int rc __unused ) {
67 /* Do nothing */
70 /** Null name resolution interface operations */
71 struct resolv_interface_operations null_resolv_ops = {
72 .done = ignore_resolv_done,
75 /** Null name resolution interface */
76 struct resolv_interface null_resolv = {
77 .intf = {
78 .dest = &null_resolv.intf,
79 .refcnt = NULL,
81 .op = &null_resolv_ops,
84 /***************************************************************************
86 * Numeric name resolver
88 ***************************************************************************
91 /** A numeric name resolver */
92 struct numeric_resolv {
93 /** Reference counter */
94 struct refcnt refcnt;
95 /** Name resolution interface */
96 struct resolv_interface resolv;
97 /** Process */
98 struct process process;
99 /** Completed socket address */
100 struct sockaddr sa;
101 /** Overall status code */
102 int rc;
105 static void numeric_step ( struct process *process ) {
106 struct numeric_resolv *numeric =
107 container_of ( process, struct numeric_resolv, process );
109 resolv_done ( &numeric->resolv, &numeric->sa, numeric->rc );
110 process_del ( process );
113 static int numeric_resolv ( struct resolv_interface *resolv,
114 const char *name, struct sockaddr *sa ) {
115 struct numeric_resolv *numeric;
116 struct sockaddr_in *sin;
118 /* Allocate and initialise structure */
119 numeric = zalloc ( sizeof ( *numeric ) );
120 if ( ! numeric )
121 return -ENOMEM;
122 resolv_init ( &numeric->resolv, &null_resolv_ops, &numeric->refcnt );
123 process_init ( &numeric->process, numeric_step, &numeric->refcnt );
124 memcpy ( &numeric->sa, sa, sizeof ( numeric->sa ) );
126 DBGC ( numeric, "NUMERIC %p attempting to resolve \"%s\"\n",
127 numeric, name );
129 /* Attempt to resolve name */
130 sin = ( ( struct sockaddr_in * ) &numeric->sa );
131 sin->sin_family = AF_INET;
132 if ( inet_aton ( name, &sin->sin_addr ) == 0 )
133 numeric->rc = -EINVAL;
135 /* Attach to parent interface, mortalise self, and return */
136 resolv_plug_plug ( &numeric->resolv, resolv );
137 ref_put ( &numeric->refcnt );
138 return 0;
141 struct resolver numeric_resolver __resolver ( RESOLV_NUMERIC ) = {
142 .name = "NUMERIC",
143 .resolv = numeric_resolv,
146 /***************************************************************************
148 * Name resolution multiplexer
150 ***************************************************************************
153 /** Registered name resolvers */
154 static struct resolver resolvers[0]
155 __table_start ( struct resolver, resolvers );
156 static struct resolver resolvers_end[0]
157 __table_end ( struct resolver, resolvers );
159 /** A name resolution multiplexer */
160 struct resolv_mux {
161 /** Reference counter */
162 struct refcnt refcnt;
163 /** Parent name resolution interface */
164 struct resolv_interface parent;
166 /** Child name resolution interface */
167 struct resolv_interface child;
168 /** Current child resolver */
169 struct resolver *resolver;
171 /** Socket address to complete */
172 struct sockaddr sa;
173 /** Name to be resolved
175 * Must be at end of structure
177 char name[0];
181 * Try current child name resolver
183 * @v mux Name resolution multiplexer
184 * @ret rc Return status code
186 static int resolv_mux_try ( struct resolv_mux *mux ) {
187 struct resolver *resolver = mux->resolver;
188 int rc;
190 DBGC ( mux, "RESOLV %p trying method %s\n", mux, resolver->name );
192 if ( ( rc = resolver->resolv ( &mux->child, mux->name,
193 &mux->sa ) ) != 0 ) {
194 DBGC ( mux, "RESOLV %p could not use method %s: %s\n",
195 mux, resolver->name, strerror ( rc ) );
196 return rc;
199 return 0;
203 * Handle done() event from child name resolver
205 * @v resolv Child name resolution interface
206 * @v sa Completed socket address (if successful)
207 * @v rc Final status code
209 static void resolv_mux_done ( struct resolv_interface *resolv,
210 struct sockaddr *sa, int rc ) {
211 struct resolv_mux *mux =
212 container_of ( resolv, struct resolv_mux, child );
214 /* Unplug child */
215 resolv_unplug ( &mux->child );
217 /* If this resolution succeeded, stop now */
218 if ( rc == 0 ) {
219 DBGC ( mux, "RESOLV %p succeeded using method %s\n",
220 mux, mux->resolver->name );
221 goto finished;
224 /* Attempt next child resolver, if possible */
225 mux->resolver++;
226 if ( mux->resolver >= resolvers_end ) {
227 DBGC ( mux, "RESOLV %p failed to resolve name\n", mux );
228 goto finished;
230 if ( ( rc = resolv_mux_try ( mux ) ) != 0 )
231 goto finished;
233 /* Next resolver is now running */
234 return;
236 finished:
237 resolv_done ( &mux->parent, sa, rc );
240 /** Name resolution multiplexer operations */
241 static struct resolv_interface_operations resolv_mux_child_ops = {
242 .done = resolv_mux_done,
246 * Start name resolution
248 * @v resolv Name resolution interface
249 * @v name Name to resolve
250 * @v sa Socket address to complete
251 * @ret rc Return status code
253 int resolv ( struct resolv_interface *resolv, const char *name,
254 struct sockaddr *sa ) {
255 struct resolv_mux *mux;
256 size_t name_len = ( strlen ( name ) + 1 );
257 int rc;
259 /* Allocate and initialise structure */
260 mux = zalloc ( sizeof ( *mux ) + name_len );
261 if ( ! mux )
262 return -ENOMEM;
263 resolv_init ( &mux->parent, &null_resolv_ops, &mux->refcnt );
264 resolv_init ( &mux->child, &resolv_mux_child_ops, &mux->refcnt );
265 mux->resolver = resolvers;
266 memcpy ( &mux->sa, sa, sizeof ( mux->sa ) );
267 memcpy ( mux->name, name, name_len );
269 DBGC ( mux, "RESOLV %p attempting to resolve \"%s\"\n", mux, name );
271 /* Start first resolver in chain. There will always be at
272 * least one resolver (the numeric resolver), so no need to
273 * check for the zero-resolvers-available case.
275 if ( ( rc = resolv_mux_try ( mux ) ) != 0 )
276 goto err;
278 /* Attach parent interface, mortalise self, and return */
279 resolv_plug_plug ( &mux->parent, resolv );
280 ref_put ( &mux->refcnt );
281 return 0;
283 err:
284 ref_put ( &mux->refcnt );
285 return rc;
288 /***************************************************************************
290 * Named socket opening
292 ***************************************************************************
295 /** A named socket */
296 struct named_socket {
297 /** Reference counter */
298 struct refcnt refcnt;
299 /** Data transfer interface */
300 struct xfer_interface xfer;
301 /** Name resolution interface */
302 struct resolv_interface resolv;
303 /** Communication semantics (e.g. SOCK_STREAM) */
304 int semantics;
305 /** Stored local socket address, if applicable */
306 struct sockaddr local;
307 /** Stored local socket address exists */
308 int have_local;
311 /** Named socket opener data transfer interface operations */
312 static struct xfer_interface_operations named_xfer_ops = {
313 .close = ignore_xfer_close,
314 .vredirect = ignore_xfer_vredirect,
315 .window = no_xfer_window,
316 .alloc_iob = default_xfer_alloc_iob,
317 .deliver_iob = xfer_deliver_as_raw,
318 .deliver_raw = ignore_xfer_deliver_raw,
322 * Handle done() event
324 * @v resolv Name resolution interface
325 * @v sa Completed socket address (if successful)
326 * @v rc Final status code
328 static void named_resolv_done ( struct resolv_interface *resolv,
329 struct sockaddr *sa, int rc ) {
330 struct named_socket *named =
331 container_of ( resolv, struct named_socket, resolv );
333 /* Unplug resolver and nullify data transfer interface */
334 resolv_unplug ( &named->resolv );
335 xfer_nullify ( &named->xfer );
337 /* Redirect if name resolution was successful */
338 if ( rc == 0 ) {
339 rc = xfer_redirect ( &named->xfer, LOCATION_SOCKET,
340 named->semantics, sa,
341 ( named->have_local ?
342 &named->local : NULL ) );
345 /* Close data transfer interface if redirection failed */
346 if ( rc != 0 )
347 xfer_close ( &named->xfer, rc );
349 /* Unplug data transfer interface */
350 xfer_unplug ( &named->xfer );
353 /** Named socket opener name resolution interface operations */
354 static struct resolv_interface_operations named_resolv_ops = {
355 .done = named_resolv_done,
359 * Open named socket
361 * @v semantics Communication semantics (e.g. SOCK_STREAM)
362 * @v peer Peer socket address to complete
363 * @v name Name to resolve
364 * @v local Local socket address, or NULL
365 * @ret rc Return status code
367 int xfer_open_named_socket ( struct xfer_interface *xfer, int semantics,
368 struct sockaddr *peer, const char *name,
369 struct sockaddr *local ) {
370 struct named_socket *named;
371 int rc;
373 /* Allocate and initialise structure */
374 named = zalloc ( sizeof ( *named ) );
375 if ( ! named )
376 return -ENOMEM;
377 xfer_init ( &named->xfer, &named_xfer_ops, &named->refcnt );
378 resolv_init ( &named->resolv, &named_resolv_ops, &named->refcnt );
379 named->semantics = semantics;
380 if ( local ) {
381 memcpy ( &named->local, local, sizeof ( named->local ) );
382 named->have_local = 1;
385 DBGC ( named, "RESOLV %p opening named socket \"%s\"\n",
386 named, name );
388 /* Start name resolution */
389 if ( ( rc = resolv ( &named->resolv, name, peer ) ) != 0 )
390 goto err;
392 /* Attach parent interface, mortalise self, and return */
393 xfer_plug_plug ( &named->xfer, xfer );
394 ref_put ( &named->refcnt );
395 return 0;
397 err:
398 ref_put ( &named->refcnt );
399 return rc;