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.
24 #include <gpxe/resolv.h>
32 static struct async_operations resolv_async_operations
;
34 /** Registered name resolvers */
35 static struct resolver resolvers
[0]
36 __table_start ( struct resolver
, resolvers
);
37 static struct resolver resolvers_end
[0]
38 __table_end ( struct resolver
, resolvers
);
41 * Start name resolution
43 * @v name Host name to resolve
44 * @v sa Socket address to fill in
45 * @v parent Parent asynchronous operation
46 * @ret rc Return status code
48 int resolv ( const char *name
, struct sockaddr
*sa
, struct async
*parent
) {
49 struct resolution
*resolution
;
50 struct resolver
*resolver
;
51 struct sockaddr_in
*sin
= ( struct sockaddr_in
* ) sa
;
55 /* Allocate and populate resolution structure */
56 resolution
= malloc ( sizeof ( *resolution
) );
59 memset ( resolution
, 0, sizeof ( *resolution
) );
60 async_init ( &resolution
->async
, &resolv_async_operations
, parent
);
62 /* Check for a dotted quad IP address first */
63 if ( inet_aton ( name
, &in
) != 0 ) {
64 DBGC ( resolution
, "RESOLV %p saw valid IP address %s\n",
66 sin
->sin_family
= AF_INET
;
68 async_done ( &resolution
->async
, 0 );
72 /* Start up all resolvers */
73 for ( resolver
= resolvers
; resolver
< resolvers_end
; resolver
++ ) {
74 if ( ( rc
= resolver
->resolv ( name
, sa
,
75 &resolution
->async
) ) != 0 ) {
76 DBGC ( resolution
, "RESOLV %p could not start %s: "
77 "%s\n", resolution
, resolver
->name
,
79 /* Continue to try other resolvers */
82 (resolution
->pending
)++;
84 if ( ! resolution
->pending
)
90 async_uninit ( &resolution
->async
);
96 * Handle child name resolution completion
98 * @v async Name resolution asynchronous operation
101 static void resolv_sigchld ( struct async
*async
,
102 enum signal signal __unused
) {
103 struct resolution
*resolution
=
104 container_of ( async
, struct resolution
, async
);
108 async_wait ( async
, &rc
, 1 );
110 /* If this child succeeded, kill all the others. They should
111 * immediately die (invoking resolv_sigchld() again, which
112 * won't do anything because the exit status is non-zero and
113 * the pending count won't reach zero until this instance
117 async_signal_children ( async
, SIGKILL
);
119 /* When we have no children left, exit */
120 if ( --(resolution
->pending
) == 0 )
121 async_done ( async
, rc
);
125 * Free name resolution structure
127 * @v async Asynchronous operation
129 static void resolv_reap ( struct async
*async
) {
130 free ( container_of ( async
, struct resolution
, async
) );
133 /** Name resolution asynchronous operations */
134 static struct async_operations resolv_async_operations
= {
137 [SIGKILL
] = async_signal_children
,
138 [SIGCHLD
] = resolv_sigchld
,