[nsd-users] ldns bind to source patch
Bryan Duff
bduff at ecessa.com
Mon Oct 15 17:07:54 UTC 2012
This allows binding the connection (UDP only in the patch) to a source
IP (with the purpose of altering routing).
Since this will cause API breakage, I suppose we'll want to alter this
as a separate function call(s) in net and resolver.
This patch includes updating drill to use this.
Thanks.
-Bryan
-------------- next part --------------
Index: resolver.c
===================================================================
--- resolver.c (revision 3757)
+++ resolver.c (working copy)
@@ -26,6 +26,12 @@
return r->_port;
}
+ldns_rdf *
+ldns_resolver_source(const ldns_resolver *r)
+{
+ return r->_source;
+}
+
uint16_t
ldns_resolver_edns_udp_size(const ldns_resolver *r)
{
@@ -234,6 +240,12 @@
r->_port = p;
}
+void
+ldns_resolver_set_source(ldns_resolver *r, ldns_rdf *s)
+{
+ r->_source = s;
+}
+
ldns_rdf *
ldns_resolver_pop_nameserver(ldns_resolver *r)
{
Index: drill/drill.c
===================================================================
--- drill/drill.c (revision 3757)
+++ drill/drill.c (working copy)
@@ -29,6 +29,7 @@
fprintf(stream, "\n\targuments may be placed in random order\n");
fprintf(stream, "\n Options:\n");
fprintf(stream, "\t-D\t\tenable DNSSEC (DO bit)\n");
+ fprintf(stream, "\t-I\t\tsource address to query from\n");
#ifdef HAVE_SSL
fprintf(stream, "\t-T\t\ttrace from the root down to <name>\n");
fprintf(stream, "\t-S\t\tchase signature(s) from <name> to a know key [*]\n");
@@ -103,6 +104,7 @@
ldns_pkt *pkt;
ldns_pkt *qpkt;
char *serv;
+ char *src;
const char *name;
char *name2;
char *progname;
@@ -110,6 +112,7 @@
char *answer_file = NULL;
ldns_buffer *query_buffer = NULL;
ldns_rdf *serv_rdf;
+ ldns_rdf *src_rdf = NULL;
ldns_rr_type type;
ldns_rr_class clas;
#if 0
@@ -157,7 +160,7 @@
int_type = -1; serv = NULL; type = 0;
int_clas = -1; name = NULL; clas = 0;
- qname = NULL;
+ qname = NULL; src = NULL;
progname = strdup(argv[0]);
#ifdef USE_WINSOCK
@@ -195,7 +198,7 @@
/* global first, query opt next, option with parm's last
* and sorted */ /* "46DITSVQf:i:w:q:achuvxzy:so:p:b:k:" */
- while ((c = getopt(argc, argv, "46ab:c:d:Df:hi:Ik:o:p:q:Qr:sStTuvV:w:xy:z")) != -1) {
+ while ((c = getopt(argc, argv, "46ab:c:d:Df:hi:I:k:o:p:q:Qr:sStTuvV:w:xy:z")) != -1) {
switch(c) {
/* global options */
case '4':
@@ -208,7 +211,7 @@
qdnssec = true;
break;
case 'I':
- /* reserved for backward compatibility */
+ src = optarg;
break;
case 'T':
if (PURPOSE == DRILL_CHASE) {
@@ -480,6 +483,14 @@
}
}
+ if (src) {
+ src_rdf = ldns_rdf_new_addr_frm_str(src);
+ if(!src_rdf) {
+ fprintf(stderr, "-I must be (or resolve) to a valid IP[v6] address.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
/* set the nameserver to use */
if (!serv) {
/* no server given make a resolver from /etc/resolv.conf */
@@ -541,6 +552,9 @@
}
/* set the resolver options */
ldns_resolver_set_port(res, qport);
+ if(src_rdf) {
+ ldns_resolver_set_source(res, src_rdf);
+ }
if (verbosity >= 5) {
ldns_resolver_set_debug(res, true);
} else {
@@ -924,6 +938,7 @@
exit:
ldns_rdf_deep_free(qname);
+ ldns_rdf_deep_free(src_rdf);
ldns_resolver_deep_free(res);
ldns_resolver_deep_free(cmdline_res);
ldns_rr_list_deep_free(key_list);
Index: ldns/net.h.in
===================================================================
--- ldns/net.h.in (revision 3757)
+++ ldns/net.h.in (working copy)
@@ -39,7 +39,7 @@
* \param[out] result packet with the answer
* \return status
*/
-ldns_status ldns_udp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout, size_t *answersize);
+ldns_status ldns_udp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, const struct sockaddr_storage *from, socklen_t fromlen, struct timeval timeout, size_t *answersize);
/**
* Send an udp query and don't wait for an answer but return
@@ -51,7 +51,7 @@
* \return the socket used
*/
-int ldns_udp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout);
+int ldns_udp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *from, socklen_t fromlen, const struct sockaddr_storage *to, socklen_t tolen, struct timeval timeout);
/**
* Send an tcp query and don't wait for an answer but return
Index: ldns/resolver.h
===================================================================
--- ldns/resolver.h (revision 3757)
+++ ldns/resolver.h (working copy)
@@ -61,6 +61,9 @@
/** Port to send queries to */
uint16_t _port;
+ /** Source address to query from */
+ ldns_rdf *_source;
+
/** Array of nameservers to query (IP addresses or dnames) */
ldns_rdf **_nameservers;
/** Number of nameservers in \c _nameservers */
@@ -152,6 +155,13 @@
uint16_t ldns_resolver_port(const ldns_resolver *r);
/**
+ * Get the source address the resolver should use
+ * \param[in] r the resolver
+ * \return the source rdf
+ */
+ldns_rdf *ldns_resolver_source(const ldns_resolver *r);
+
+/**
* Is the resolver set to recurse
* \param[in] r the resolver
* \return true if so, otherwise false
@@ -338,6 +348,13 @@
void ldns_resolver_set_port(ldns_resolver *r, uint16_t p);
/**
+ * Set the source rdf (address) the resolver should use
+ * \param[in] r the resolver
+ * \param[in] s the source address
+ */
+void ldns_resolver_set_source(ldns_resolver *r, ldns_rdf *s);
+
+/**
* Set the resolver recursion
* \param[in] r the resolver
* \param[in] b true: set to recurse, false: unset
Index: net.c
===================================================================
--- net.c (revision 3757)
+++ net.c (working copy)
@@ -60,7 +60,9 @@
ldns_send_buffer(ldns_pkt **result, ldns_resolver *r, ldns_buffer *qb, ldns_rdf *tsig_mac)
{
uint8_t i;
-
+
+ struct sockaddr_storage *src = NULL;
+ size_t src_len;
struct sockaddr_storage *ns;
size_t ns_len;
struct timeval tv_s;
@@ -90,6 +92,10 @@
ldns_resolver_nameservers_randomize(r);
}
+ if(ldns_resolver_source(r)) {
+ src = ldns_rdf2native_sockaddr_storage(ldns_resolver_source(r), 0, &src_len);
+ }
+
/* loop through all defined nameservers */
for (i = 0; i < ldns_resolver_nameserver_count(r); i++) {
if (rtt[i] == LDNS_RESOLV_RTT_INF) {
@@ -144,9 +150,8 @@
/* ldns_rdf_print(stdout, ns_array[i]); */
send_status =
ldns_udp_send(&reply_bytes, qb, ns,
- (socklen_t)ns_len, ldns_resolver_timeout(r),
- &reply_size);
-
+ (socklen_t)ns_len, src, (socklen_t)src_len,
+ ldns_resolver_timeout(r), &reply_size);
if (send_status == LDNS_STATUS_OK) {
break;
}
@@ -201,6 +206,9 @@
sleep((unsigned int) ldns_resolver_retrans(r));
}
+ if(src) {
+ LDNS_FREE(src);
+ }
if (all_servers_rtt_inf) {
LDNS_FREE(reply_bytes);
return LDNS_STATUS_RES_NO_NS;
@@ -292,12 +300,13 @@
ldns_status
ldns_udp_send(uint8_t **result, ldns_buffer *qbin, const struct sockaddr_storage *to,
- socklen_t tolen, struct timeval timeout, size_t *answer_size)
+ socklen_t tolen, const struct sockaddr_storage *from, socklen_t fromlen,
+ struct timeval timeout, size_t *answer_size)
{
int sockfd;
uint8_t *answer;
- sockfd = ldns_udp_bgsend(qbin, to, tolen, timeout);
+ sockfd = ldns_udp_bgsend(qbin, from, fromlen, to, tolen, timeout);
if (sockfd == 0) {
return LDNS_STATUS_SOCKET_ERROR;
@@ -335,7 +344,8 @@
}
int
-ldns_udp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *to, socklen_t tolen,
+ldns_udp_bgsend(ldns_buffer *qbin, const struct sockaddr_storage *from, socklen_t fromlen,
+ const struct sockaddr_storage *to, socklen_t tolen,
struct timeval timeout)
{
int sockfd;
@@ -346,6 +356,12 @@
return 0;
}
+ if(from) {
+ if(bind(sockfd, (const struct sockaddr*)from, fromlen)) {
+ return 0;
+ }
+ }
+
if (ldns_udp_send_query(qbin, sockfd, to, tolen) == 0) {
#ifndef USE_WINSOCK
close(sockfd);
More information about the nsd-users
mailing list