summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichael Brown2007-06-12 00:30:44 +0200
committerMichael Brown2007-06-12 00:30:44 +0200
commitf87bc837f4d00bf716ee521db69aa75ccf96fcf8 (patch)
tree5abb6c3b337068fa36dfe3aadd59f39ac6aac5e9 /src
parentMerge branch 'master' into mcb-tcp-xfer (diff)
downloadipxe-f87bc837f4d00bf716ee521db69aa75ccf96fcf8.tar.gz
ipxe-f87bc837f4d00bf716ee521db69aa75ccf96fcf8.tar.xz
ipxe-f87bc837f4d00bf716ee521db69aa75ccf96fcf8.zip
Updated DNS to use not-yet-implemented UDP data-xfer API.
Diffstat (limited to 'src')
-rw-r--r--src/include/gpxe/dns.h27
-rw-r--r--src/include/gpxe/resolv.h7
-rw-r--r--src/net/udp/dns.c215
3 files changed, 122 insertions, 127 deletions
diff --git a/src/include/gpxe/dns.h b/src/include/gpxe/dns.h
index fca3a7a3..f2249da2 100644
--- a/src/include/gpxe/dns.h
+++ b/src/include/gpxe/dns.h
@@ -9,8 +9,6 @@
#include <stdint.h>
#include <gpxe/in.h>
-#include <gpxe/async.h>
-#include <gpxe/retry.h>
/*
* Constants
@@ -89,29 +87,6 @@ union dns_rr_info {
struct dns_rr_info_cname cname;
};
-/** A DNS request */
-struct dns_request {
- /** Socket address to fill in with resolved address */
- struct sockaddr *sa;
-
- /** Current query packet */
- struct dns_query query;
- /** Length of current query packet */
- struct dns_query_info *qinfo;
- /** Recursion counter */
- unsigned int recursion;
-
- /** Asynchronous operation */
- struct async async;
- /** UDP connection */
- struct udp_connection udp;
- /** Retry timer */
- struct retry_timer timer;
-};
-
-extern struct in_addr nameserver;
-
-extern int dns_resolv ( const char *name, struct sockaddr *sa,
- struct async *parent );
+extern struct sockaddr_tcpip nameserver;
#endif /* _GPXE_DNS_H */
diff --git a/src/include/gpxe/resolv.h b/src/include/gpxe/resolv.h
index 4a4de4c7..772460d9 100644
--- a/src/include/gpxe/resolv.h
+++ b/src/include/gpxe/resolv.h
@@ -153,6 +153,13 @@ struct resolver {
#define __resolver( resolv_order ) \
__table ( struct resolver, resolvers, resolv_order )
+extern void resolv_done ( struct resolv_interface *resolv,
+ struct sockaddr *sa, int rc );
+extern void ignore_resolv_done ( struct resolv_interface *resolv,
+ struct sockaddr *sa, int rc );
+extern struct resolv_interface_operations null_resolv_ops;
+struct resolv_interface null_resolv;
+
extern int resolv ( struct resolv_interface *resolv, const char *name,
struct sockaddr *sa );
diff --git a/src/net/udp/dns.c b/src/net/udp/dns.c
index 22680526..ff28c7e0 100644
--- a/src/net/udp/dns.c
+++ b/src/net/udp/dns.c
@@ -24,9 +24,12 @@
#include <string.h>
#include <errno.h>
#include <byteswap.h>
-#include <gpxe/async.h>
-#include <gpxe/udp.h>
+#include <gpxe/refcnt.h>
+#include <gpxe/xfer.h>
+#include <gpxe/open.h>
#include <gpxe/resolv.h>
+#include <gpxe/retry.h>
+#include <gpxe/tcpip.h>
#include <gpxe/dns.h>
/** @file
@@ -35,8 +38,54 @@
*
*/
-/* The DNS server */
-struct in_addr nameserver = { INADDR_NONE };
+/** The DNS server */
+struct sockaddr_tcpip nameserver = {
+ .st_port = htons ( DNS_PORT ),
+};
+
+/** A DNS request */
+struct dns_request {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** Name resolution interface */
+ struct resolv_interface resolv;
+ /** Data transfer interface */
+ struct xfer_interface socket;
+ /** Retry timer */
+ struct retry_timer timer;
+
+ /** Socket address to fill in with resolved address */
+ struct sockaddr sa;
+ /** Current query packet */
+ struct dns_query query;
+ /** Location of query info structure within current packet
+ *
+ * The query info structure is located immediately after the
+ * compressed name.
+ */
+ struct dns_query_info *qinfo;
+ /** Recursion counter */
+ unsigned int recursion;
+};
+
+/**
+ * Mark DNS request as complete
+ *
+ * @v dns DNS request
+ * @v rc Return status code
+ */
+static void dns_done ( struct dns_request *dns, int rc ) {
+
+ /* Stop the retry timer */
+ stop_timer ( &dns->timer );
+
+ /* Close data transfer interface */
+ xfer_nullify ( &dns->socket );
+ xfer_close ( &dns->socket, rc );
+
+ /* Mark name resolution as complete */
+ resolv_done ( &dns->resolv, &dns->sa, rc );
+}
/**
* Compare DNS reply name against the query name from the original request
@@ -47,7 +96,8 @@ struct in_addr nameserver = { INADDR_NONE };
* @ret zero Names match
* @ret non-zero Names do not match
*/
-static int dns_name_cmp ( struct dns_request *dns, struct dns_header *reply,
+static int dns_name_cmp ( struct dns_request *dns,
+ const struct dns_header *reply,
const char *rname ) {
const char *qname = dns->query.payload;
int i;
@@ -101,7 +151,7 @@ static const char * dns_skip_name ( const char *name ) {
* @ret rr DNS RR, or NULL if not found
*/
static union dns_rr_info * dns_find_rr ( struct dns_request *dns,
- struct dns_header *reply ) {
+ const struct dns_header *reply ) {
int i, cmp;
const char *p = ( ( char * ) reply ) + sizeof ( struct dns_header );
union dns_rr_info *rr_info;
@@ -179,7 +229,7 @@ static inline char * dns_unmake_name ( char *name ) {
* @v buf Buffer into which to decompress DNS name
* @ret next Byte following decompressed DNS name
*/
-static char * dns_decompress_name ( struct dns_header *reply,
+static char * dns_decompress_name ( const struct dns_header *reply,
const char *name, char *buf ) {
int i, len;
@@ -199,30 +249,13 @@ static char * dns_decompress_name ( struct dns_header *reply,
}
/**
- * Mark DNS request as complete
- *
- * @v dns DNS request
- * @v rc Return status code
- */
-static void dns_done ( struct dns_request *dns, int rc ) {
-
- /* Stop the retry timer */
- stop_timer ( &dns->timer );
-
- /* Close UDP connection */
- udp_close ( &dns->udp );
-
- /* Mark async operation as complete */
- async_done ( &dns->async, rc );
-}
-
-/**
* Send next packet in DNS request
*
* @v dns DNS request
*/
-static void dns_send_packet ( struct dns_request *dns ) {
+static int dns_send_packet ( struct dns_request *dns ) {
static unsigned int qid = 0;
+ size_t qlen;
/* Increment query ID */
dns->query.dns.id = htons ( ++qid );
@@ -233,9 +266,9 @@ static void dns_send_packet ( struct dns_request *dns ) {
start_timer ( &dns->timer );
/* Send the data */
- udp_send ( &dns->udp, &dns->query,
- ( ( ( void * ) dns->qinfo ) - ( ( void * ) &dns->query )
- + sizeof ( dns->qinfo ) ) );
+ qlen = ( ( ( void * ) dns->qinfo ) - ( ( void * ) &dns->query )
+ + sizeof ( dns->qinfo ) );
+ return xfer_deliver_raw ( &dns->socket, &dns->query, qlen );
}
/**
@@ -258,18 +291,16 @@ static void dns_timer_expired ( struct retry_timer *timer, int fail ) {
/**
* Receive new data
*
- * @v udp UDP connection
- * @v data Received data
- * @v len Length of received data
- * @v st_src Partially-filled source address
- * @v st_dest Partially-filled destination address
+ * @v socket UDP socket
+ * @v data DNS reply
+ * @v len Length of DNS reply
+ * @ret rc Return status code
*/
-static int dns_newdata ( struct udp_connection *conn, void *data, size_t len,
- struct sockaddr_tcpip *st_src __unused,
- struct sockaddr_tcpip *st_dest __unused ) {
+static int dns_xfer_deliver_raw ( struct xfer_interface *socket,
+ const void *data, size_t len ) {
struct dns_request *dns =
- container_of ( conn, struct dns_request, udp );
- struct dns_header *reply = data;
+ container_of ( socket, struct dns_request, socket );
+ const struct dns_header *reply = data;
union dns_rr_info *rr_info;
struct sockaddr_in *sin;
unsigned int qtype = dns->qinfo->qtype;
@@ -311,7 +342,7 @@ static int dns_newdata ( struct udp_connection *conn, void *data, size_t len,
/* Found the target A record */
DBGC ( dns, "DNS %p found address %s\n",
dns, inet_ntoa ( rr_info->a.in_addr ) );
- sin = ( struct sockaddr_in * ) dns->sa;
+ sin = ( struct sockaddr_in * ) &dns->sa;
sin->sin_family = AF_INET;
sin->sin_addr = rr_info->a.in_addr;
@@ -380,71 +411,62 @@ static int dns_newdata ( struct udp_connection *conn, void *data, size_t len,
}
}
-/** DNS UDP operations */
-struct udp_operations dns_udp_operations = {
- .newdata = dns_newdata,
-};
-
/**
- * Reap asynchronous operation
+ * Receive new data
*
- * @v async Asynchronous operation
+ * @v socket UDP socket
+ * @v rc Reason for close
*/
-static void dns_reap ( struct async *async ) {
+static void dns_xfer_close ( struct xfer_interface *socket, int rc ) {
struct dns_request *dns =
- container_of ( async, struct dns_request, async );
+ container_of ( socket, struct dns_request, socket );
- free ( dns );
-}
+ if ( ! rc )
+ rc = -ECONNABORTED;
-/**
- * Handle SIGKILL
- *
- * @v async Asynchronous operation
- */
-static void dns_sigkill ( struct async *async, enum signal signal __unused ) {
- struct dns_request *dns =
- container_of ( async, struct dns_request, async );
-
- dns_done ( dns, -ECANCELED );
+ dns_done ( dns, rc );
}
-/** DNS asynchronous operations */
-static struct async_operations dns_async_operations = {
- .reap = dns_reap,
- .signal = {
- [SIGKILL] = dns_sigkill,
- },
+/** DNS socket operations */
+static struct xfer_interface_operations dns_socket_operations = {
+ .close = dns_xfer_close,
+ .vredirect = xfer_vopen,
+ .request = ignore_xfer_request,
+ .seek = ignore_xfer_seek,
+ .alloc_iob = default_xfer_alloc_iob,
+ .deliver_iob = xfer_deliver_as_raw,
+ .deliver_raw = dns_xfer_deliver_raw,
};
/**
* Resolve name using DNS
*
- * @v name Host name to resolve
+ * @v resolv Name resolution interface
+ * @v name Name to resolve
* @v sa Socket address to fill in
- * @v parent Parent asynchronous operation
* @ret rc Return status code
*/
-int dns_resolv ( const char *name, struct sockaddr *sa,
- struct async *parent ) {
+static int dns_resolv ( struct resolv_interface *resolv,
+ const char *name, struct sockaddr *sa ) {
struct dns_request *dns;
- union {
- struct sockaddr_tcpip st;
- struct sockaddr_in sin;
- } server;
int rc;
+ /* Fail immediately if no DNS servers */
+ if ( ! nameserver.st_family ) {
+ DBG ( "DNS not attempting to resolve \"%s\": "
+ "no DNS servers\n", name );
+ return -ENXIO;
+ }
+
/* Allocate DNS structure */
dns = malloc ( sizeof ( *dns ) );
- if ( ! dns ) {
- rc = -ENOMEM;
- goto err;
- }
+ if ( ! dns )
+ return -ENOMEM;
memset ( dns, 0, sizeof ( *dns ) );
- dns->sa = sa;
+ resolv_init ( &dns->resolv, &null_resolv_ops, &dns->refcnt );
+ xfer_init ( &dns->socket, &dns_socket_operations, &dns->refcnt );
dns->timer.expired = dns_timer_expired;
- dns->udp.udp_op = &dns_udp_operations;
- async_init ( &dns->async, &dns_async_operations, parent );
+ memcpy ( &dns->sa, sa, sizeof ( dns->sa ) );
/* Create query */
dns->query.dns.flags = htons ( DNS_FLAG_QUERY | DNS_FLAG_OPCODE_QUERY |
@@ -454,34 +476,25 @@ int dns_resolv ( const char *name, struct sockaddr *sa,
dns->qinfo->qtype = htons ( DNS_TYPE_A );
dns->qinfo->qclass = htons ( DNS_CLASS_IN );
- /* Identify nameserver */
- memset ( &server, 0, sizeof ( server ) );
- server.sin.sin_family = AF_INET;
- server.sin.sin_port = htons ( DNS_PORT );
- server.sin.sin_addr = nameserver;
- if ( server.sin.sin_addr.s_addr == INADDR_NONE ) {
- DBGC ( dns, "DNS %p no name servers\n", dns );
- rc = -ENXIO;
- goto err;
- }
-
/* Open UDP connection */
- DBGC ( dns, "DNS %p using nameserver %s\n", dns,
- inet_ntoa ( server.sin.sin_addr ) );
- udp_connect ( &dns->udp, &server.st );
- if ( ( rc = udp_open ( &dns->udp, 0 ) ) != 0 )
+ if ( ( rc = xfer_open_socket ( &dns->socket, SOCK_DGRAM,
+ ( struct sockaddr * ) &nameserver,
+ NULL ) ) != 0 ) {
+ DBGC ( dns, "DNS %p could not open socket: %s\n",
+ dns, strerror ( rc ) );
goto err;
+ }
/* Send first DNS packet */
dns_send_packet ( dns );
+ /* Attach parent interface, mortalise self, and return */
+ resolv_plug_plug ( &dns->resolv, resolv );
+ ref_put ( &dns->refcnt );
return 0;
err:
- DBGC ( dns, "DNS %p could not create request: %s\n",
- dns, strerror ( rc ) );
- async_uninit ( &dns->async );
- free ( dns );
+ ref_put ( &dns->refcnt );
return rc;
}