ソースを参照

A working name resolution framework

tags/v0.9.3
Michael Brown 18年前
コミット
4e3976711d
7個のファイルの変更188行の追加45行の削除
  1. 2
    2
      src/config.h
  2. 117
    16
      src/core/resolv.c
  3. 47
    0
      src/include/gpxe/resolv.h
  4. 0
    16
      src/include/resolv.h
  5. 5
    9
      src/net/tcp/http.c
  6. 7
    0
      src/net/udp/dns.c
  7. 10
    2
      src/usr/dhcpmgmt.c

+ 2
- 2
src/config.h ファイルの表示

@@ -72,7 +72,7 @@
72 72
 
73 73
 #define	DOWNLOAD_PROTO_TFTP	/* Trivial File Transfer Protocol */
74 74
 #undef	DOWNLOAD_PROTO_NFS	/* Network File System */
75
-#undef	DOWNLOAD_PROTO_HTTP	/* Hypertext Transfer Protocol */
75
+#define	DOWNLOAD_PROTO_HTTP	/* Hypertext Transfer Protocol */
76 76
 #undef	DOWNLOAD_PROTO_TFTM	/* Multicast Trivial File Transfer Protocol */
77 77
 #undef	DOWNLOAD_PROTO_SLAM	/* Scalable Local Area Multicast */
78 78
 #undef	DOWNLOAD_PROTO_FSP	/* FSP? */
@@ -85,7 +85,7 @@
85 85
  *
86 86
  */
87 87
 
88
-#undef	DNS_RESOLVER		/* DNS resolver */
88
+#define	DNS_RESOLVER		/* DNS resolver */
89 89
 #undef	NMB_RESOLVER		/* NMB resolver */
90 90
 
91 91
 /* @END general.h */

+ 117
- 16
src/core/resolv.c ファイルの表示

@@ -1,33 +1,134 @@
1
-#include "resolv.h"
1
+/*
2
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
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.
8
+ *
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.
13
+ *
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.
17
+ */
18
+
19
+#include <stdint.h>
20
+#include <stdlib.h>
21
+#include <string.h>
22
+#include <errno.h>
23
+#include <gpxe/in.h>
24
+#include <gpxe/resolv.h>
2 25
 
26
+/** @file
27
+ *
28
+ * Name resolution
29
+ *
30
+ */
31
+
32
+static struct async_operations resolv_async_operations;
33
+
34
+/** Registered name resolvers */
3 35
 static struct resolver resolvers[0]
4
-	__table_start ( struct resolver, resolver );
36
+	__table_start ( struct resolver, resolvers );
5 37
 static struct resolver resolvers_end[0]
6
-	__table_end ( struct resolver, resolver );
38
+	__table_end ( struct resolver, resolvers );
7 39
 
8
-/*
9
- * Resolve a name (which may be just a dotted quad IP address) to an
10
- * IP address.
40
+/**
41
+ * Start name resolution
11 42
  *
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
12 47
  */
13
-int resolv ( struct in_addr *address, const char *name ) {
48
+int resolv ( const char *name, struct sockaddr *sa, struct async *parent ) {
49
+	struct resolution *resolution;
14 50
 	struct resolver *resolver;
51
+	struct sockaddr_in *sin = ( struct sockaddr_in * ) sa;
52
+	struct in_addr in;
53
+	int rc = -ENXIO;
54
+
55
+	/* Allocate and populate resolution structure */
56
+	resolution = malloc ( sizeof ( *resolution ) );
57
+	if ( ! resolution )
58
+		return -ENOMEM;
59
+	async_init ( &resolution->async, &resolv_async_operations, parent );
15 60
 
16 61
 	/* Check for a dotted quad IP address first */
17
-	if ( inet_aton ( name, address ) ) {
18
-		DBG ( "RESOLV saw valid IP address %s\n", name );
19
-		return 1;
62
+	if ( inet_aton ( name, &in ) != 0 ) {
63
+		DBGC ( resolution, "RESOLV %p saw valid IP address %s\n",
64
+		       resolution, name );
65
+		sin->sin_family = AF_INET;
66
+		sin->sin_addr = in;
67
+		async_done ( &resolution->async, 0 );
68
+		return 0;
20 69
 	}
21 70
 
22
-	/* Try any compiled-in name resolution modules */
71
+	/* Start up all resolvers */
23 72
 	for ( resolver = resolvers ; resolver < resolvers_end ; resolver++ ) {
24
-		if ( resolver->resolv ( address, name ) ) {
25
-			DBG ( "RESOLV resolved \"%s\" to %@ using %s\n",
26
-			      name, address->s_addr, resolver->name );
27
-			return 1;
73
+		if ( ( rc = resolver->resolv ( name, sa,
74
+					       &resolution->async ) ) != 0 ) {
75
+			DBGC ( resolution, "RESOLV %p could not start %s: "
76
+			       "%s\n", resolution, resolver->name,
77
+			       strerror ( rc ) );
78
+			/* Continue to try other resolvers */
79
+			continue;
28 80
 		}
81
+		(resolution->pending)++;
29 82
 	}
83
+	if ( ! resolution->pending )
84
+		goto err;
30 85
 
31
-	DBG ( "RESOLV failed to resolve %s\n", name );
32 86
 	return 0;
87
+
88
+ err:
89
+	async_uninit ( &resolution->async );
90
+	free ( resolution );
91
+	return rc;
33 92
 }
93
+
94
+/**
95
+ * Handle child name resolution completion
96
+ *
97
+ * @v async		Name resolution asynchronous operation
98
+ * @v signal		SIGCHLD
99
+ */
100
+static void resolv_sigchld ( struct async *async,
101
+			     enum signal signal __unused ) {
102
+	struct resolution *resolution =
103
+		container_of ( async, struct resolution, async );
104
+	int rc;
105
+
106
+	/* If this child succeeded, kill all the others and return */
107
+	async_wait ( async, &rc, 1 );
108
+	if ( rc == 0 ) {
109
+		async_signal_children ( async, SIGKILL );
110
+		async_done ( async, 0 );
111
+		return;
112
+	}
113
+
114
+	/* If we have no children left, return failure */
115
+	if ( --(resolution->pending) == 0 )
116
+		async_done ( async, -ENXIO );
117
+}
118
+
119
+/**
120
+ * Free name resolution structure
121
+ *
122
+ * @v async		Asynchronous operation
123
+ */
124
+static void resolv_reap ( struct async *async ) {
125
+	free ( container_of ( async, struct resolution, async ) );
126
+}
127
+
128
+/** Name resolution asynchronous operations */
129
+static struct async_operations resolv_async_operations = {
130
+	.reap = resolv_reap,
131
+	.signal = {
132
+		[SIGCHLD] = resolv_sigchld,
133
+	},
134
+};

+ 47
- 0
src/include/gpxe/resolv.h ファイルの表示

@@ -0,0 +1,47 @@
1
+#ifndef _GPXE_RESOLV_H
2
+#define _GPXE_RESOLV_H
3
+
4
+/** @file
5
+ *
6
+ * Name resolution
7
+ *
8
+ */
9
+
10
+struct sockaddr;
11
+
12
+#include <gpxe/async.h>
13
+#include <gpxe/tables.h>
14
+
15
+/** A name resolver */
16
+struct resolver {
17
+	/** Name of this resolver (e.g. "DNS") */
18
+	const char *name;
19
+	/** Start name resolution
20
+	 *
21
+	 * @v name		Host name to resolve
22
+	 * @v sa		Socket address to fill in
23
+	 * @v parent		Parent asynchronous operation
24
+	 * @ret rc		Return status code
25
+	 *
26
+	 * The asynchronous process must be prepared to accept
27
+	 * SIGKILL.
28
+	 */
29
+	int ( * resolv ) ( const char *name, struct sockaddr *sa,
30
+			   struct async *parent );
31
+};
32
+
33
+/** A name resolution in progress */
34
+struct resolution {
35
+	/** Asynchronous operation */
36
+	struct async async;
37
+	/** Numner of active child resolvers */
38
+	unsigned int pending;
39
+};
40
+
41
+/** Register as a name resolver */
42
+#define __resolver __table ( struct resolver, resolvers, 01 )
43
+
44
+extern int resolv ( const char *name, struct sockaddr *sa,
45
+		    struct async *parent );
46
+
47
+#endif /* _GPXE_RESOLV_H */

+ 0
- 16
src/include/resolv.h ファイルの表示

@@ -1,16 +0,0 @@
1
-#ifndef RESOLV_H
2
-#define RESOLV_H
3
-
4
-#include <gpxe/in.h>
5
-#include <gpxe/tables.h>
6
-
7
-struct resolver {
8
-	const char *name;
9
-	int ( * resolv ) ( struct in_addr *address, const char *name );
10
-};
11
-
12
-#define __resolver __table ( struct resolver, resolver, 01 )
13
-
14
-extern int resolv ( struct in_addr *address, const char *name );
15
-
16
-#endif /* RESOLV_H */

+ 5
- 9
src/net/tcp/http.c ファイルの表示

@@ -35,6 +35,7 @@
35 35
 #include <gpxe/uri.h>
36 36
 #include <gpxe/buffer.h>
37 37
 #include <gpxe/download.h>
38
+#include <gpxe/resolv.h>
38 39
 #include <gpxe/http.h>
39 40
 
40 41
 static struct async_operations http_async_operations;
@@ -391,17 +392,12 @@ int http_get ( struct uri *uri, struct buffer *buffer, struct async *parent ) {
391 392
 	http->buffer = buffer;
392 393
 	async_init ( &http->async, &http_async_operations, parent );
393 394
 
394
-
395
-#warning "Quick name resolution hack"
396
-	extern int dns_resolv ( const char *name,
397
-				struct sockaddr *sa,
398
-				struct async *parent );
399
-		
400
-	if ( ( rc = dns_resolv ( uri->host, &http->server,
401
-				 &http->async ) ) != 0 )
395
+	/* Start name resolution.  The download proper will start when
396
+	 * name resolution completes.
397
+	 */
398
+	if ( ( rc = resolv ( uri->host, &http->server, &http->async ) ) != 0 )
402 399
 		goto err;
403 400
 
404
-
405 401
 	return 0;
406 402
 
407 403
  err:

+ 7
- 0
src/net/udp/dns.c ファイルの表示

@@ -26,6 +26,7 @@
26 26
 #include <byteswap.h>
27 27
 #include <gpxe/async.h>
28 28
 #include <gpxe/udp.h>
29
+#include <gpxe/resolv.h>
29 30
 #include <gpxe/dns.h>
30 31
 
31 32
 /** @file
@@ -468,3 +469,9 @@ int dns_resolv ( const char *name, struct sockaddr *sa,
468 469
 	free ( dns );
469 470
 	return rc;
470 471
 }
472
+
473
+/** DNS name resolver */
474
+struct resolver dns_resolver __resolver = {
475
+	.name = "DNS",
476
+	.resolv = dns_resolv,
477
+};

+ 10
- 2
src/usr/dhcpmgmt.c ファイルの表示

@@ -24,6 +24,7 @@
24 24
 #include <gpxe/dhcp.h>
25 25
 #include <gpxe/async.h>
26 26
 #include <gpxe/netdevice.h>
27
+#include <gpxe/dns.h>
27 28
 #include <usr/ifmgmt.h>
28 29
 #include <usr/dhcpmgmt.h>
29 30
 
@@ -33,6 +34,9 @@
33 34
  *
34 35
  */
35 36
 
37
+/* Avoid dragging in dns.o */
38
+struct in_addr nameserver;
39
+
36 40
 /**
37 41
  * Configure network device via DHCP
38 42
  *
@@ -42,8 +46,8 @@
42 46
 int dhcp ( struct net_device *netdev ) {
43 47
 	static struct dhcp_option_block *dhcp_options = NULL;
44 48
 	struct dhcp_session dhcp;
45
-	struct in_addr address = { htonl ( 0 ) };
46
-	struct in_addr netmask = { htonl ( 0 ) };
49
+	struct in_addr address = { 0 };
50
+	struct in_addr netmask = { 0 };
47 51
 	struct in_addr gateway = { INADDR_NONE };
48 52
 	struct async async;
49 53
 	int rc;
@@ -90,5 +94,9 @@ int dhcp ( struct net_device *netdev ) {
90 94
 		return rc;
91 95
 	}
92 96
 
97
+	/* Retrieve other DHCP options that we care about */
98
+	find_dhcp_ipv4_option ( dhcp_options, DHCP_DNS_SERVERS,
99
+				&nameserver );
100
+
93 101
 	return 0;
94 102
 }

読み込み中…
キャンセル
保存