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., 51 Franklin Street, Fifth Floor, Boston, MA
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL
);
30 #include <ipxe/xfer.h>
31 #include <ipxe/open.h>
32 #include <ipxe/process.h>
33 #include <ipxe/socket.h>
34 #include <ipxe/resolv.h>
42 /***************************************************************************
44 * Name resolution interfaces
46 ***************************************************************************
52 * @v intf Object interface
53 * @v sa Completed socket address (if successful)
55 void resolv_done ( struct interface
*intf
, struct sockaddr
*sa
) {
56 struct interface
*dest
;
57 resolv_done_TYPE ( void * ) *op
=
58 intf_get_dest_op ( intf
, resolv_done
, &dest
);
59 void *object
= intf_object ( dest
);
61 DBGC ( INTF_COL ( intf
), "INTF " INTF_INTF_FMT
" resolv_done\n",
62 INTF_INTF_DBG ( intf
, dest
) );
67 /* Default is to ignore resolutions */
73 /***************************************************************************
75 * Numeric name resolver
77 ***************************************************************************
80 /** A numeric name resolver */
81 struct numeric_resolv
{
82 /** Reference counter */
84 /** Name resolution interface */
85 struct interface resolv
;
87 struct process process
;
88 /** Completed socket address */
90 /** Overall status code */
94 static void numeric_step ( struct numeric_resolv
*numeric
) {
96 if ( numeric
->rc
== 0 )
97 resolv_done ( &numeric
->resolv
, &numeric
->sa
);
98 intf_shutdown ( &numeric
->resolv
, numeric
->rc
);
101 static struct process_descriptor numeric_process_desc
=
102 PROC_DESC_ONCE ( struct numeric_resolv
, process
, numeric_step
);
104 static int numeric_resolv ( struct interface
*resolv
,
105 const char *name
, struct sockaddr
*sa
) {
106 struct numeric_resolv
*numeric
;
108 /* Allocate and initialise structure */
109 numeric
= zalloc ( sizeof ( *numeric
) );
112 ref_init ( &numeric
->refcnt
, NULL
);
113 intf_init ( &numeric
->resolv
, &null_intf_desc
, &numeric
->refcnt
);
114 process_init ( &numeric
->process
, &numeric_process_desc
,
116 memcpy ( &numeric
->sa
, sa
, sizeof ( numeric
->sa
) );
118 /* Attempt to resolve name */
119 numeric
->rc
= sock_aton ( name
, &numeric
->sa
);
121 /* Attach to parent interface, mortalise self, and return */
122 intf_plug_plug ( &numeric
->resolv
, resolv
);
123 ref_put ( &numeric
->refcnt
);
127 struct resolver numeric_resolver
__resolver ( RESOLV_NUMERIC
) = {
129 .resolv
= numeric_resolv
,
132 /***************************************************************************
134 * Name resolution multiplexer
136 ***************************************************************************
139 /** A name resolution multiplexer */
141 /** Reference counter */
142 struct refcnt refcnt
;
143 /** Parent name resolution interface */
144 struct interface parent
;
146 /** Child name resolution interface */
147 struct interface child
;
148 /** Current child resolver */
149 struct resolver
*resolver
;
151 /** Socket address to complete */
153 /** Name to be resolved
155 * Must be at end of structure
161 * Try current child name resolver
163 * @v mux Name resolution multiplexer
164 * @ret rc Return status code
166 static int resmux_try ( struct resolv_mux
*mux
) {
167 struct resolver
*resolver
= mux
->resolver
;
170 DBGC ( mux
, "RESOLV %p trying method %s\n", mux
, resolver
->name
);
172 if ( ( rc
= resolver
->resolv ( &mux
->child
, mux
->name
,
173 &mux
->sa
) ) != 0 ) {
174 DBGC ( mux
, "RESOLV %p could not use method %s: %s\n",
175 mux
, resolver
->name
, strerror ( rc
) );
183 * Child resolved name
185 * @v mux Name resolution multiplexer
186 * @v sa Completed socket address
188 static void resmux_child_resolv_done ( struct resolv_mux
*mux
,
189 struct sockaddr
*sa
) {
191 DBGC ( mux
, "RESOLV %p resolved \"%s\" to %s using method %s\n",
192 mux
, mux
->name
, sock_ntoa ( sa
), mux
->resolver
->name
);
194 /* Pass resolution to parent */
195 resolv_done ( &mux
->parent
, sa
);
199 * Child finished resolution
201 * @v mux Name resolution multiplexer
202 * @v rc Return status code
204 static void resmux_child_close ( struct resolv_mux
*mux
, int rc
) {
206 /* Restart child interface */
207 intf_restart ( &mux
->child
, rc
);
209 /* If this resolution succeeded, stop now */
211 DBGC ( mux
, "RESOLV %p succeeded using method %s\n",
212 mux
, mux
->resolver
->name
);
216 /* Attempt next child resolver, if possible */
218 if ( mux
->resolver
>= table_end ( RESOLVERS
) ) {
219 DBGC ( mux
, "RESOLV %p failed to resolve name\n", mux
);
222 if ( ( rc
= resmux_try ( mux
) ) != 0 )
225 /* Next resolver is now running */
229 intf_shutdown ( &mux
->parent
, rc
);
232 /** Name resolution multiplexer child interface operations */
233 static struct interface_operation resmux_child_op
[] = {
234 INTF_OP ( resolv_done
, struct resolv_mux
*, resmux_child_resolv_done
),
235 INTF_OP ( intf_close
, struct resolv_mux
*, resmux_child_close
),
238 /** Name resolution multiplexer child interface descriptor */
239 static struct interface_descriptor resmux_child_desc
=
240 INTF_DESC ( struct resolv_mux
, child
, resmux_child_op
);
243 * Start name resolution
245 * @v resolv Name resolution interface
246 * @v name Name to resolve
247 * @v sa Socket address to complete
248 * @ret rc Return status code
250 int resolv ( struct interface
*resolv
, const char *name
,
251 struct sockaddr
*sa
) {
252 struct resolv_mux
*mux
;
253 size_t name_len
= ( strlen ( name
) + 1 );
256 /* Allocate and initialise structure */
257 mux
= zalloc ( sizeof ( *mux
) + name_len
);
260 ref_init ( &mux
->refcnt
, NULL
);
261 intf_init ( &mux
->parent
, &null_intf_desc
, &mux
->refcnt
);
262 intf_init ( &mux
->child
, &resmux_child_desc
, &mux
->refcnt
);
263 mux
->resolver
= table_start ( RESOLVERS
);
265 memcpy ( &mux
->sa
, sa
, sizeof ( mux
->sa
) );
266 memcpy ( mux
->name
, name
, name_len
);
268 DBGC ( mux
, "RESOLV %p attempting to resolve \"%s\"\n", mux
, name
);
270 /* Start first resolver in chain. There will always be at
271 * least one resolver (the numeric resolver), so no need to
272 * check for the zero-resolvers-available case.
274 if ( ( rc
= resmux_try ( mux
) ) != 0 )
277 /* Attach parent interface, mortalise self, and return */
278 intf_plug_plug ( &mux
->parent
, resolv
);
279 ref_put ( &mux
->refcnt
);
283 ref_put ( &mux
->refcnt
);
287 /***************************************************************************
289 * Named socket opening
291 ***************************************************************************
294 /** A named socket */
295 struct named_socket
{
296 /** Reference counter */
297 struct refcnt refcnt
;
298 /** Data transfer interface */
299 struct interface xfer
;
300 /** Name resolution interface */
301 struct interface resolv
;
302 /** Communication semantics (e.g. SOCK_STREAM) */
304 /** Stored local socket address, if applicable */
305 struct sockaddr local
;
306 /** Stored local socket address exists */
311 * Terminate named socket opener
313 * @v named Named socket
314 * @v rc Reason for termination
316 static void named_close ( struct named_socket
*named
, int rc
) {
317 /* Shut down interfaces */
318 intf_shutdown ( &named
->resolv
, rc
);
319 intf_shutdown ( &named
->xfer
, rc
);
323 * Check flow control window
325 * @v named Named socket
326 * @ret len Length of window
328 static size_t named_window ( struct named_socket
*named __unused
) {
329 /* Not ready for data until we have redirected away */
333 /** Named socket opener data transfer interface operations */
334 static struct interface_operation named_xfer_ops
[] = {
335 INTF_OP ( xfer_window
, struct named_socket
*, named_window
),
336 INTF_OP ( intf_close
, struct named_socket
*, named_close
),
339 /** Named socket opener data transfer interface descriptor */
340 static struct interface_descriptor named_xfer_desc
=
341 INTF_DESC ( struct named_socket
, xfer
, named_xfer_ops
);
346 * @v named Named socket
347 * @v sa Completed socket address
349 static void named_resolv_done ( struct named_socket
*named
,
350 struct sockaddr
*sa
) {
353 /* Nullify data transfer interface */
354 intf_nullify ( &named
->xfer
);
356 /* Redirect data-xfer interface */
357 if ( ( rc
= xfer_redirect ( &named
->xfer
, LOCATION_SOCKET
,
358 named
->semantics
, sa
,
359 ( named
->have_local ?
360 &named
->local
: NULL
) ) ) != 0 ) {
361 /* Redirection failed - do not unplug data-xfer interface */
362 DBGC ( named
, "NAMED %p could not redirect: %s\n",
363 named
, strerror ( rc
) );
365 /* Redirection succeeded - unplug data-xfer interface */
366 DBGC ( named
, "NAMED %p redirected successfully\n", named
);
367 intf_unplug ( &named
->xfer
);
370 /* Terminate named socket opener */
371 named_close ( named
, rc
);
374 /** Named socket opener resolver interface operations */
375 static struct interface_operation named_resolv_op
[] = {
376 INTF_OP ( intf_close
, struct named_socket
*, named_close
),
377 INTF_OP ( resolv_done
, struct named_socket
*, named_resolv_done
),
380 /** Named socket opener resolver interface descriptor */
381 static struct interface_descriptor named_resolv_desc
=
382 INTF_DESC ( struct named_socket
, resolv
, named_resolv_op
);
387 * @v semantics Communication semantics (e.g. SOCK_STREAM)
388 * @v peer Peer socket address to complete
389 * @v name Name to resolve
390 * @v local Local socket address, or NULL
391 * @ret rc Return status code
393 int xfer_open_named_socket ( struct interface
*xfer
, int semantics
,
394 struct sockaddr
*peer
, const char *name
,
395 struct sockaddr
*local
) {
396 struct named_socket
*named
;
399 /* Allocate and initialise structure */
400 named
= zalloc ( sizeof ( *named
) );
403 ref_init ( &named
->refcnt
, NULL
);
404 intf_init ( &named
->xfer
, &named_xfer_desc
, &named
->refcnt
);
405 intf_init ( &named
->resolv
, &named_resolv_desc
, &named
->refcnt
);
406 named
->semantics
= semantics
;
408 memcpy ( &named
->local
, local
, sizeof ( named
->local
) );
409 named
->have_local
= 1;
412 DBGC ( named
, "NAMED %p opening \"%s\"\n",
415 /* Start name resolution */
416 if ( ( rc
= resolv ( &named
->resolv
, name
, peer
) ) != 0 )
419 /* Attach parent interface, mortalise self, and return */
420 intf_plug_plug ( &named
->xfer
, xfer
);
421 ref_put ( &named
->refcnt
);
425 ref_put ( &named
->refcnt
);