diff --git a/DESCRIPTION b/DESCRIPTION index 17a0010..5fa2211 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -21,7 +21,6 @@ Suggests: Depends: R (>= 3.2.0) Imports: - httr, jsonlite, Rcpp, magrittr diff --git a/NAMESPACE b/NAMESPACE index 8b8363f..c70a794 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -3,9 +3,9 @@ S3method(print,gctx) export("%>%") export(gdns_get_address) +export(gdns_lib_version) +export(gdns_query) export(gdns_resolver) -export(get_address) -import(httr) importFrom(Rcpp,sourceCpp) importFrom(jsonlite,fromJSON) importFrom(magrittr,"%>%") diff --git a/R/RcppExports.R b/R/RcppExports.R index a19dcde..04a0605 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -1,22 +1,17 @@ # Generated by using Rcpp::compileAttributes() -> do not edit by hand # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 -#' Lookup IP Address(es) for a Given Host +#' Return gdns library version #' -#' @param host host (length 1 ) -#' @param resolver resolver address. defaults to Quad9; (length 1 ) #' @export -#' @examples -#' get_address("r-project.org") -#' get_address("yahoo.com", "1.1.1.1") -#' get_address("microsoft.com", "8.8.8.8") -get_address <- function(host, resolver = "9.9.9.9") { - .Call(`_clandnstine_get_address`, host, resolver) +gdns_lib_version <- function() { + .Call(`_clandnstine_gdns_lib_version`) } #' Test whether an object is an external pointer #' #' @param x object to test +#' @keywords internal check_is_xptr <- function(s) { invisible(.Call(`_clandnstine_check_is_xptr`, s)) } @@ -24,20 +19,15 @@ check_is_xptr <- function(s) { #' Test whether an external pointer is null #' #' @param x object to test +#' @keywords internal is_null_xptr_ <- function(s) { .Call(`_clandnstine_is_null_xptr_`, s) } -#' Create a gdns DNS over TLS context and populate it with a resolver -#' for use in resolution functions -#' -#' @param resolver length 1 of a valid DNS over TLS resolver; -#' Defaults to Quad9 (`9.9.9.9`). -#' @export -#' @examples -#' x <- gdns_resolver() -gdns_resolver <- function(resolver = "9.9.9.9") { - .Call(`_clandnstine_gdns_resolver`, resolver) +#' Internal version of gdns_resolver +#' @keywords internal +int_gdns_resolver <- function(resolvers) { + .Call(`_clandnstine_int_gdns_resolver`, resolvers) } #' Resolve a host to an addrss @@ -57,3 +47,7 @@ int_get_resolvers <- function(gctx) { .Call(`_clandnstine_int_get_resolvers`, gctx) } +int_gdns_query <- function(gctx, name, rr) { + .Call(`_clandnstine_int_gdns_query`, gctx, name, rr) +} + diff --git a/R/aaa.R b/R/aaa.R new file mode 100644 index 0000000..0bcc93a --- /dev/null +++ b/R/aaa.R @@ -0,0 +1,88 @@ +rr_types <- c( +a = 1, +ns = 2, +md = 3, +mf = 4, +cname = 5, +soa = 6, +mb = 7, +mg = 8, +mr = 9, +null = 10, +wks = 11, +ptr = 12, +hinfo = 13, +minfo = 14, +mx = 15, +txt = 16, +rp = 17, +afsdb = 18, +x25 = 19, +isdn = 20, +rt = 21, +nsap = 22, +nsap_ptr = 23, +sig = 24, +key = 25, +px = 26, +gpos = 27, +aaaa = 28, +loc = 29, +nxt = 30, +eid = 31, +nimloc = 32, +srv = 33, +atma = 34, +naptr = 35, +kx = 36, +cert = 37, +a6 = 38, +dname = 39, +sink = 40, +opt = 41, +apl = 42, +ds = 43, +sshfp = 44, +ipseckey = 45, +rrsig = 46, +nsec = 47, +dnskey = 48, +dhcid = 49, +nsec3 = 50, +nsec3param = 51, +tlsa = 52, +smimea = 53, +hip = 55, +ninfo = 56, +rkey = 57, +talink = 58, +cds = 59, +cdnskey = 60, +openpgpkey = 61, +csync = 62, +zonemd = 63, +spf = 99, +uinfo = 100, +uid = 101, +gid = 102, +unspec = 103, +nid = 104, +l32 = 105, +l64 = 106, +lp = 107, +eui48 = 108, +eui64 = 109, +tkey = 249, +tsig = 250, +ixfr = 251, +axfr = 252, +mailb = 253, +maila = 254, +any = 255, +uri = 256, +caa = 257, +avc = 258, +doa = 259, +ta = 32768, +dlv = 32769 +) \ No newline at end of file diff --git a/R/clandnstine-package.R b/R/clandnstine-package.R index 03cf0c3..c8e9a5c 100644 --- a/R/clandnstine-package.R +++ b/R/clandnstine-package.R @@ -10,7 +10,7 @@ #' @name clandnstine #' @docType package #' @author Bob Rudis (bob@@rud.is) -#' @import httr +#' @keywords internal #' @importFrom jsonlite fromJSON #' @useDynLib clandnstine, .registration = TRUE #' @importFrom Rcpp sourceCpp diff --git a/R/print-context.R b/R/print-context.R index 90f0d07..a72e532 100644 --- a/R/print-context.R +++ b/R/print-context.R @@ -6,8 +6,13 @@ #' @export print.gctx <- function(x, ...) { if (is_null_xptr_(x)) { - cat("\n") + cat("\n") } else { - cat("\n", sep="") + cat( + "\n", sep = "" + ) } } \ No newline at end of file diff --git a/R/resolver.R b/R/resolver.R new file mode 100644 index 0000000..314b5c2 --- /dev/null +++ b/R/resolver.R @@ -0,0 +1,128 @@ +#' Create a gdns DNS over TLS context and populate it with a resolver +#' for use in resolution functions +#' +#' @param resolver character vector of valid DNS over TLS resolvers; +#' Defaults to Quad9 (`9.9.9.9`). +#' @export +#' @examples +#' x <- gdns_resolver() +#' x <- gdns_resolver("1.1.1.1") +gdns_resolver <- function(resolvers = "9.9.9.9") { + int_gdns_resolver(resolvers) +} + +#' Arbitrary DNS queries +#' +#' Perform any valid resource record inquiry for a given name. See `Details`. +#' +#' This returns a fairly complex result object but that is the nature +#' of DNS queries. You're likely going to want what is in `$replies_tree$answer` +#' but the rest of the structure contains lovely metadata about the query and +#' remote query environment. There will eventually be "as data frame"-ish helpers +#' for this object. +#' +#' Valid values for `rr_type`: +#' - `a` +#' - `a6` +#' - `aaaa` +#' - `afsdb` +#' - `any` +#' - `apl` +#' - `atma` +#' - `avc` +#' - `axfr` +#' - `caa` +#' - `cdnskey` +#' - `cds` +#' - `cert` +#' - `cname` +#' - `csync` +#' - `dhcid` +#' - `dlv` +#' - `dname` +#' - `dnskey` +#' - `doa` +#' - `ds` +#' - `eid` +#' - `eui48` +#' - `eui64` +#' - `gid` +#' - `gpos` +#' - `hinfo` +#' - `hip` +#' - `ipseckey` +#' - `isdn` +#' - `ixfr` +#' - `key` +#' - `kx` +#' - `l32` +#' - `l64` +#' - `loc` +#' - `lp` +#' - `maila` +#' - `mailb` +#' - `mb` +#' - `md` +#' - `mf` +#' - `mg` +#' - `minfo` +#' - `mr` +#' - `mx` +#' - `naptr` +#' - `nid` +#' - `nimloc` +#' - `ninfo` +#' - `ns` +#' - `nsap` +#' - `nsap_ptr` +#' - `nsec` +#' - `nsec3` +#' - `nsec3param` +#' - `null` +#' - `nxt` +#' - `openpgpkey` +#' - `opt` +#' - `ptr` +#' - `px` +#' - `rkey` +#' - `rp` +#' - `rrsig` +#' - `rt` +#' - `sig` +#' - `sink` +#' - `smimea` +#' - `soa` +#' - `spf` +#' - `srv` +#' - `sshfp` +#' - `ta` +#' - `talink` +#' - `tkey` +#' - `tlsa` +#' - `tsig` +#' - `txt` +#' - `uid` +#' - `uinfo` +#' - `unspec` +#' - `uri` +#' - `wks` +#' - `x25` +#' - `zonemd` +#' +#' @references +#' @export +#' @examples +#' x <- gdns_resolver() +#' gdns_query(x, "example.com") +gdns_query <- function(gcx, name, rr_type = "txt") { + + rr_type <- match.arg(trimws(tolower(rr_type[1])), names(rr_types)) + res <- int_gdns_query(gcx, name, unname(as.integer(rr_types[rr_type]))) + if (length(res)) { + out <- jsonlite::fromJSON(res) + out + } else { + NULL + } + +} \ No newline at end of file diff --git a/README.Rmd b/README.Rmd index 59ba952..0ea63b6 100644 --- a/README.Rmd +++ b/README.Rmd @@ -1,7 +1,7 @@ --- output: rmarkdown::github_document editor_options: - chunk_output_type: inline + chunk_output_type: console --- ```{r pkg-knitr-opts, include=FALSE} knitr::opts_chunk$set(collapse=TRUE, fig.retina=2, message=FALSE, warning=FALSE) @@ -32,8 +32,6 @@ Requires [`getdns`](https://getdnsapi.net/) to be installed and available for co I finally grok the getdns api so the package api is going to change wildly and fast. It's only going to support DNS over TLS but will support all types of DNS queries. -The current "got it working" single function is stupid slow since it creates and destroys a context or each lookup. DNS over TLS was designed to support maintaining a session to avoid this overhead so the package is going to migrate to a "create a resolver" then "use this resolver to resolve X" then "destroy (or have R autodestroy)" the C-size resolver context when the R object goes away model pretty quickly. - ## Why? Well, for starters, to help research DNS over TLS servers. Plus, for fun! @@ -82,7 +80,10 @@ It's stupid slow, consumes more CPU and bandwidth but forces adversaries to work The following functions are implemented: -- `get_address`: Lookup IP Address(es) for a Given Host +- `gdns_get_address`: Resolve a host to an addrss +- `gdns_lib_version`: Return gdns library version +- `gdns_query`: Arbitrary DNS queries +- `gdns_resolver`: Create a gdns DNS over TLS context and populate it with a resolver for use in resolution functions ## Installation @@ -102,14 +103,34 @@ packageVersion("clandnstine") ``` +### Get an address(es) from a name: + ```{r addr} -get_address("r-project.org") # use built-in default of Quad9 (9.9.9.9) +gdns_lib_version() + +(x <- gdns_resolver()) + +(x <- gdns_resolver("1.1.1.1")) + +(x <- gdns_resolver(c("8.8.8.8", "1.1.1.1", "9.9.9.9"))) + +(gdns_get_address(x, "rud.is")) -get_address("yahoo.com", "8.8.8.8") # use google and get a bigger return back, too +(gdns_get_address(x, "yahoo.com")) -get_address("doesnotexist.commmm", "1.1.1.1") # nothing to find +(gdns_get_address(x, "yahoo.commmm")) ``` +### Any record type query: + +```{r generic} +str(leno <- gdns_query(x, "lenovo.com", "txt"), 1) + +sort(unlist(leno$replies_tree$answer[[1]]$rdata$txt_strings)) +``` + +Yep. Advertising even in DNS `TXT` records (see item number 8). + ## clandnstine Metrics ```{r cloc, echo=FALSE} diff --git a/README.md b/README.md index 81088cf..6c323e8 100644 --- a/README.md +++ b/README.md @@ -29,13 +29,6 @@ I finally grok the getdns api so the package api is going to change wildly and fast. It’s only going to support DNS over TLS but will support all types of DNS queries. -The current “got it working” single function is stupid slow since it -creates and destroys a context or each lookup. DNS over TLS was designed -to support maintaining a session to avoid this overhead so the package -is going to migrate to a “create a resolver” then “use this resolver to -resolve X” then “destroy (or have R autodestroy)” the C-size resolver -context when the R object goes away model pretty quickly. - ## Why? Well, for starters, to help research DNS over TLS servers. Plus, for @@ -108,7 +101,11 @@ to work pretty hard to try to figure out what you’re looking for. The following functions are implemented: - - `get_address`: Lookup IP Address(es) for a Given Host + - `gdns_get_address`: Resolve a host to an addrss + - `gdns_lib_version`: Return gdns library version + - `gdns_query`: Arbitrary DNS queries + - `gdns_resolver`: Create a gdns DNS over TLS context and populate it + with a resolver for use in resolution functions ## Installation @@ -128,26 +125,65 @@ packageVersion("clandnstine") ## [1] '0.1.0' ``` +### Get an address(es) from a name: + ``` r -get_address("r-project.org") # use built-in default of Quad9 (9.9.9.9) -## [1] "137.208.57.37" +gdns_lib_version() +## [1] "1.5.1" + +(x <- gdns_resolver()) +## + +(x <- gdns_resolver("1.1.1.1")) +## + +(x <- gdns_resolver(c("8.8.8.8", "1.1.1.1", "9.9.9.9"))) +## + +(gdns_get_address(x, "rud.is")) +## [1] "2604:a880:800:10::6bc:2001" "104.236.112.222" -get_address("yahoo.com", "8.8.8.8") # use google and get a bigger return back, too -## [1] "2001:4998:c:1023::4" "2001:4998:c:1023::5" "2001:4998:58:1836::11" "2001:4998:44:41d::4" -## [5] "2001:4998:58:1836::10" "2001:4998:44:41d::3" "72.30.35.10" "98.137.246.7" -## [9] "98.137.246.8" "98.138.219.231" "72.30.35.9" "98.138.219.232" +(gdns_get_address(x, "yahoo.com")) +## [1] "2001:4998:58:1836::11" "2001:4998:58:1836::10" "2001:4998:c:1023::5" "2001:4998:c:1023::4" +## [5] "2001:4998:44:41d::3" "2001:4998:44:41d::4" "98.138.219.232" "98.138.219.231" +## [9] "98.137.246.8" "98.137.246.7" "72.30.35.10" "72.30.35.9" -get_address("doesnotexist.commmm", "1.1.1.1") # nothing to find +(gdns_get_address(x, "yahoo.commmm")) ## character(0) ``` +### Any record type query: + +``` r +str(leno <- gdns_query(x, "lenovo.com", "txt"), 1) +## List of 5 +## $ answer_type : int 800 +## $ canonical_name: chr "lenovo.com." +## $ replies_full : int [1, 1:600] 55 84 129 128 0 1 0 8 0 0 ... +## $ replies_tree :'data.frame': 1 obs. of 7 variables: +## $ status : int 900 + +sort(unlist(leno$replies_tree$answer[[1]]$rdata$txt_strings)) +## [1] "a82c74b37aa84e7c8580f0e32f4d795d" +## [2] "ece42d7743c84d6889abda7011fe6f53" +## [3] "facebook-domain-verification=1r2am7c2bhzrxpqyt0mda0djoquqsi" +## [4] "google-site-verification=VxW_e6r_Ka7A518qfX2MmIMHGnkpGbnACsjSxKFCBw0" +## [5] "iHzQJvsKnyGP2Nm2qBgL3fyBJ0CC9z4GkY/flfk4EzLP8lPxWHDDPKqZWm1TkeF5kEIL+NotYOF1wo7JtUDXXw==" +## [6] "qh7hdmqm4lzs85p704d6wsybgrpsly0j" +## [7] "v=spf1 include:spf.messagelabs.com include:_netblocks.eloqua.com ~all" +## [8] "Visit www.lenovo.com/think for information about Lenovo products and services" +``` + +Yep. Advertising even in DNS `TXT` records (see item number +8). + ## clandnstine Metrics | Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) | | :--- | -------: | ---: | --: | ---: | ----------: | ---: | -------: | ---: | -| C++ | 2 | 0.29 | 72 | 0.79 | 23 | 0.35 | 13 | 0.11 | -| Rmd | 1 | 0.14 | 10 | 0.11 | 38 | 0.58 | 74 | 0.64 | -| R | 4 | 0.57 | 9 | 0.10 | 4 | 0.06 | 28 | 0.24 | +| C++ | 3 | 0.25 | 240 | 0.59 | 66 | 0.50 | 61 | 0.20 | +| R | 8 | 0.67 | 154 | 0.38 | 20 | 0.15 | 168 | 0.54 | +| Rmd | 1 | 0.08 | 16 | 0.04 | 46 | 0.35 | 81 | 0.26 | ## Code of Conduct diff --git a/man/check_is_xptr.Rd b/man/check_is_xptr.Rd index 32c8562..b6277b5 100644 --- a/man/check_is_xptr.Rd +++ b/man/check_is_xptr.Rd @@ -12,3 +12,4 @@ check_is_xptr(s) \description{ Test whether an object is an external pointer } +\keyword{internal} diff --git a/man/clandnstine.Rd b/man/clandnstine.Rd index c7570aa..8e2bcf9 100644 --- a/man/clandnstine.Rd +++ b/man/clandnstine.Rd @@ -18,3 +18,4 @@ Something something 'getdns API/library'. \author{ Bob Rudis (bob@rud.is) } +\keyword{internal} diff --git a/man/gdns_lib_version.Rd b/man/gdns_lib_version.Rd new file mode 100644 index 0000000..aabfa87 --- /dev/null +++ b/man/gdns_lib_version.Rd @@ -0,0 +1,11 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/RcppExports.R +\name{gdns_lib_version} +\alias{gdns_lib_version} +\title{Return gdns library version} +\usage{ +gdns_lib_version() +} +\description{ +Return gdns library version +} diff --git a/man/gdns_query.Rd b/man/gdns_query.Rd new file mode 100644 index 0000000..c471567 --- /dev/null +++ b/man/gdns_query.Rd @@ -0,0 +1,115 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/resolver.R +\name{gdns_query} +\alias{gdns_query} +\title{Arbitrary DNS queries} +\usage{ +gdns_query(gcx, name, rr_type = "txt") +} +\description{ +Perform any valid resource record inquiry for a given name. See \code{Details}. +} +\details{ +This returns a fairly complex result object but that is the nature +of DNS queries. You're likely going to want what is in \code{$replies_tree$answer} +but the rest of the structure contains lovely metadata about the query and +remote query environment. There will eventually be "as data frame"-ish helpers +for this object. + +Valid values for \code{rr_type}: +\itemize{ +\item \code{a} +\item \code{a6} +\item \code{aaaa} +\item \code{afsdb} +\item \code{any} +\item \code{apl} +\item \code{atma} +\item \code{avc} +\item \code{axfr} +\item \code{caa} +\item \code{cdnskey} +\item \code{cds} +\item \code{cert} +\item \code{cname} +\item \code{csync} +\item \code{dhcid} +\item \code{dlv} +\item \code{dname} +\item \code{dnskey} +\item \code{doa} +\item \code{ds} +\item \code{eid} +\item \code{eui48} +\item \code{eui64} +\item \code{gid} +\item \code{gpos} +\item \code{hinfo} +\item \code{hip} +\item \code{ipseckey} +\item \code{isdn} +\item \code{ixfr} +\item \code{key} +\item \code{kx} +\item \code{l32} +\item \code{l64} +\item \code{loc} +\item \code{lp} +\item \code{maila} +\item \code{mailb} +\item \code{mb} +\item \code{md} +\item \code{mf} +\item \code{mg} +\item \code{minfo} +\item \code{mr} +\item \code{mx} +\item \code{naptr} +\item \code{nid} +\item \code{nimloc} +\item \code{ninfo} +\item \code{ns} +\item \code{nsap} +\item \code{nsap_ptr} +\item \code{nsec} +\item \code{nsec3} +\item \code{nsec3param} +\item \code{null} +\item \code{nxt} +\item \code{openpgpkey} +\item \code{opt} +\item \code{ptr} +\item \code{px} +\item \code{rkey} +\item \code{rp} +\item \code{rrsig} +\item \code{rt} +\item \code{sig} +\item \code{sink} +\item \code{smimea} +\item \code{soa} +\item \code{spf} +\item \code{srv} +\item \code{sshfp} +\item \code{ta} +\item \code{talink} +\item \code{tkey} +\item \code{tlsa} +\item \code{tsig} +\item \code{txt} +\item \code{uid} +\item \code{uinfo} +\item \code{unspec} +\item \code{uri} +\item \code{wks} +\item \code{x25} +\item \code{zonemd} +} +} +\examples{ +x <- gdns_resolver() +gdns_query(x, "example.com") +} +\references{ +\url{https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml} +} diff --git a/man/gdns_resolver.Rd b/man/gdns_resolver.Rd index a039e11..f8f5bdd 100644 --- a/man/gdns_resolver.Rd +++ b/man/gdns_resolver.Rd @@ -1,14 +1,14 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/RcppExports.R +% Please edit documentation in R/resolver.R \name{gdns_resolver} \alias{gdns_resolver} \title{Create a gdns DNS over TLS context and populate it with a resolver for use in resolution functions} \usage{ -gdns_resolver(resolver = "9.9.9.9") +gdns_resolver(resolvers = "9.9.9.9") } \arguments{ -\item{resolver}{length 1 of a valid DNS over TLS resolver; +\item{resolver}{character vector of valid DNS over TLS resolvers; Defaults to Quad9 (\code{9.9.9.9}).} } \description{ @@ -17,4 +17,5 @@ for use in resolution functions } \examples{ x <- gdns_resolver() +x <- gdns_resolver("1.1.1.1") } diff --git a/man/get_address.Rd b/man/get_address.Rd deleted file mode 100644 index 0c0e4b2..0000000 --- a/man/get_address.Rd +++ /dev/null @@ -1,21 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/RcppExports.R -\name{get_address} -\alias{get_address} -\title{Lookup IP Address(es) for a Given Host} -\usage{ -get_address(host, resolver = "9.9.9.9") -} -\arguments{ -\item{host}{host (length 1 )} - -\item{resolver}{resolver address. defaults to Quad9; (length 1 )} -} -\description{ -Lookup IP Address(es) for a Given Host -} -\examples{ -get_address("r-project.org") -get_address("yahoo.com", "1.1.1.1") -get_address("microsoft.com", "8.8.8.8") -} diff --git a/man/int_gdns_resolver.Rd b/man/int_gdns_resolver.Rd new file mode 100644 index 0000000..8e6d908 --- /dev/null +++ b/man/int_gdns_resolver.Rd @@ -0,0 +1,12 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/RcppExports.R +\name{int_gdns_resolver} +\alias{int_gdns_resolver} +\title{Internal version of gdns_resolver} +\usage{ +int_gdns_resolver(resolvers) +} +\description{ +Internal version of gdns_resolver +} +\keyword{internal} diff --git a/man/is_null_xptr_.Rd b/man/is_null_xptr_.Rd index e4db932..b9de42c 100644 --- a/man/is_null_xptr_.Rd +++ b/man/is_null_xptr_.Rd @@ -12,3 +12,4 @@ is_null_xptr_(s) \description{ Test whether an external pointer is null } +\keyword{internal} diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 1050363..910ef48 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -5,15 +5,13 @@ using namespace Rcpp; -// get_address -CharacterVector get_address(std::string host, std::string resolver); -RcppExport SEXP _clandnstine_get_address(SEXP hostSEXP, SEXP resolverSEXP) { +// gdns_lib_version +std::string gdns_lib_version(); +RcppExport SEXP _clandnstine_gdns_lib_version() { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< std::string >::type host(hostSEXP); - Rcpp::traits::input_parameter< std::string >::type resolver(resolverSEXP); - rcpp_result_gen = Rcpp::wrap(get_address(host, resolver)); + rcpp_result_gen = Rcpp::wrap(gdns_lib_version()); return rcpp_result_gen; END_RCPP } @@ -38,14 +36,14 @@ BEGIN_RCPP return rcpp_result_gen; END_RCPP } -// gdns_resolver -SEXP gdns_resolver(std::string resolver); -RcppExport SEXP _clandnstine_gdns_resolver(SEXP resolverSEXP) { +// int_gdns_resolver +SEXP int_gdns_resolver(std::vector< std::string > resolvers); +RcppExport SEXP _clandnstine_int_gdns_resolver(SEXP resolversSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; - Rcpp::traits::input_parameter< std::string >::type resolver(resolverSEXP); - rcpp_result_gen = Rcpp::wrap(gdns_resolver(resolver)); + Rcpp::traits::input_parameter< std::vector< std::string > >::type resolvers(resolversSEXP); + rcpp_result_gen = Rcpp::wrap(int_gdns_resolver(resolvers)); return rcpp_result_gen; END_RCPP } @@ -72,14 +70,28 @@ BEGIN_RCPP return rcpp_result_gen; END_RCPP } +// int_gdns_query +CharacterVector int_gdns_query(SEXP gctx, std::string name, uint16_t rr); +RcppExport SEXP _clandnstine_int_gdns_query(SEXP gctxSEXP, SEXP nameSEXP, SEXP rrSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< SEXP >::type gctx(gctxSEXP); + Rcpp::traits::input_parameter< std::string >::type name(nameSEXP); + Rcpp::traits::input_parameter< uint16_t >::type rr(rrSEXP); + rcpp_result_gen = Rcpp::wrap(int_gdns_query(gctx, name, rr)); + return rcpp_result_gen; +END_RCPP +} static const R_CallMethodDef CallEntries[] = { - {"_clandnstine_get_address", (DL_FUNC) &_clandnstine_get_address, 2}, + {"_clandnstine_gdns_lib_version", (DL_FUNC) &_clandnstine_gdns_lib_version, 0}, {"_clandnstine_check_is_xptr", (DL_FUNC) &_clandnstine_check_is_xptr, 1}, {"_clandnstine_is_null_xptr_", (DL_FUNC) &_clandnstine_is_null_xptr_, 1}, - {"_clandnstine_gdns_resolver", (DL_FUNC) &_clandnstine_gdns_resolver, 1}, + {"_clandnstine_int_gdns_resolver", (DL_FUNC) &_clandnstine_int_gdns_resolver, 1}, {"_clandnstine_gdns_get_address", (DL_FUNC) &_clandnstine_gdns_get_address, 2}, {"_clandnstine_int_get_resolvers", (DL_FUNC) &_clandnstine_int_get_resolvers, 1}, + {"_clandnstine_int_gdns_query", (DL_FUNC) &_clandnstine_int_gdns_query, 3}, {NULL, NULL, 0} }; diff --git a/src/clandnstine-main.cpp b/src/clandnstine-main.cpp index 06ac3c9..7104549 100644 --- a/src/clandnstine-main.cpp +++ b/src/clandnstine-main.cpp @@ -4,76 +4,33 @@ #include using namespace Rcpp; -//' Lookup IP Address(es) for a Given Host + +//' Return gdns library version //' -//' @param host host (length 1 ) -//' @param resolver resolver address. defaults to Quad9; (length 1 ) //' @export -//' @examples -//' get_address("r-project.org") -//' get_address("yahoo.com", "1.1.1.1") -//' get_address("microsoft.com", "8.8.8.8") // [[Rcpp::export]] -CharacterVector get_address(std::string host, std::string resolver = "9.9.9.9") { - - uint32_t err; - size_t sz; - getdns_return_t r; - getdns_context *ctxt = NULL; - getdns_dict *resp = NULL; - getdns_list *addrs; - std::vector< std::string > out; - bool ok = false; - - getdns_dict *resolver_dict = getdns_dict_create(); - r = getdns_str2dict(resolver.c_str(), &resolver_dict); - - getdns_list *resolver_list = getdns_list_create(); - r = getdns_list_set_dict(resolver_list, 0, resolver_dict); - - getdns_transport_list_t tls_transport[] = { GETDNS_TRANSPORT_TLS }; - - if ((r = getdns_context_create(&ctxt, 1))) { - } else if ((r = getdns_context_set_dns_transport_list(ctxt, 1, tls_transport))) { - } else if ((r = getdns_context_set_upstream_recursive_servers(ctxt, resolver_list))) { - } else if ((r = getdns_context_set_resolution_type(ctxt, GETDNS_RESOLUTION_STUB))) { - } else if ((r = getdns_address_sync(ctxt, host.c_str(), NULL, &resp))) { - } else if ((r = getdns_dict_get_int(resp, "status", &err))) { - } else if (err != GETDNS_RESPSTATUS_GOOD) { - } else if ((r = getdns_dict_get_list(resp, "just_address_answers", &addrs))) { - } else if (r != GETDNS_RETURN_GOOD) { - } else if ((r = getdns_list_get_length(addrs, &sz))) { - } else { - ok = true; - } - - if (ok) { - - out.reserve(sz); - - for (size_t i = 0; i < sz; ++i) { - - getdns_dict *cur_addr; - getdns_bindata *address; - - r = getdns_list_get_dict(addrs, i, &cur_addr); - r = getdns_dict_get_bindata(cur_addr, "address_data", &address); - - if (address->size == 4 || address->size == 16) { // this is unlikely to be bad - char *addr_str = getdns_display_ip_address(address); - out.push_back(addr_str); - if (addr_str) free(addr_str); - } - - } - - out.shrink_to_fit(); - - } - - if (resp) getdns_dict_destroy(resp); - if (ctxt) getdns_context_destroy(ctxt); +std::string gdns_lib_version() { + return(std::string(getdns_get_version())); +} - if (ok) return(wrap(out)); else return(CharacterVector()); -} +// CharacterVector int_gdns_list_to_r() { +// +// getdns_list *gl; +// +// std::string out; +// +// // if (!lst) return(CharacterVector()); +// // +// // char *res = getdns_print_json_list(lst, 0); +// // if (res) { +// // out = std::string(res); +// // free(res); +// // } else { +// // return(CharacterVector()); +// // } +// +// return(wrap(out)); +// +// } +// diff --git a/src/resolver.cpp b/src/resolver.cpp index 5de12fe..755a573 100644 --- a/src/resolver.cpp +++ b/src/resolver.cpp @@ -7,6 +7,7 @@ using namespace Rcpp; //' Test whether an object is an external pointer //' //' @param x object to test +//' @keywords internal // [[Rcpp::export]] void check_is_xptr(SEXP s) { if (TYPEOF(s) != EXTPTRSXP) { @@ -17,6 +18,7 @@ void check_is_xptr(SEXP s) { //' Test whether an external pointer is null //' //' @param x object to test +//' @keywords internal // [[Rcpp::export]] SEXP is_null_xptr_(SEXP s) { check_is_xptr(s); @@ -30,27 +32,24 @@ static void gctx_finalizer(SEXP ptr) { R_ClearExternalPtr(ptr); /* not really needed */ } -//' Create a gdns DNS over TLS context and populate it with a resolver -//' for use in resolution functions -//' -//' @param resolver length 1 of a valid DNS over TLS resolver; -//' Defaults to Quad9 (`9.9.9.9`). -//' @export -//' @examples -//' x <- gdns_resolver() +//' Internal version of gdns_resolver +//' @keywords internal // [[Rcpp::export]] -SEXP gdns_resolver(std::string resolver = "9.9.9.9") { +SEXP int_gdns_resolver(std::vector< std::string > resolvers) { bool ok = false; SEXP ptr; getdns_return_t r; getdns_context *ctxt = NULL; + // TODO Validate we don't need to free these getdns_dict *resolver_dict = getdns_dict_create(); - r = getdns_str2dict(resolver.c_str(), &resolver_dict); - getdns_list *resolver_list = getdns_list_create(); - r = getdns_list_set_dict(resolver_list, 0, resolver_dict); + + for (int i = 0; i