Преглед на файлове

commit before check

master
boB Rudis преди 5 години
родител
ревизия
b99cffd36c
No known key found for this signature in database GPG ключ ID: 1D7529BE14E2BBA9
  1. 1
      DESCRIPTION
  2. 4
      NAMESPACE
  3. 32
      R/RcppExports.R
  4. 88
      R/aaa.R
  5. 2
      R/clandnstine-package.R
  6. 9
      R/print-context.R
  7. 128
      R/resolver.R
  8. 35
      README.Rmd
  9. 72
      README.md
  10. 1
      man/check_is_xptr.Rd
  11. 1
      man/clandnstine.Rd
  12. 11
      man/gdns_lib_version.Rd
  13. 115
      man/gdns_query.Rd
  14. 7
      man/gdns_resolver.Rd
  15. 21
      man/get_address.Rd
  16. 12
      man/int_gdns_resolver.Rd
  17. 1
      man/is_null_xptr_.Rd
  18. 38
      src/RcppExports.cpp
  19. 93
      src/clandnstine-main.cpp
  20. 62
      src/resolver.cpp
  21. 22
      tests/testthat/test-clandnstine.R

1
DESCRIPTION

@ -21,7 +21,6 @@ Suggests:
Depends:
R (>= 3.2.0)
Imports:
httr,
jsonlite,
Rcpp,
magrittr

4
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,"%>%")

32
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 <chr>)
#' @param resolver resolver address. defaults to Quad9; (length 1 <chr>)
#' @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 <chr> 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)
}

88
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
)

2
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

9
R/print-context.R

@ -6,8 +6,13 @@
#' @export
print.gctx <- function(x, ...) {
if (is_null_xptr_(x)) {
cat("<gdns resolver context (INVALID)>\n")
cat("<gdns v", gdns_lib_version(), " resolver context (INVALID)>\n")
} else {
cat("<gdns resolver context; resolvers: ", int_get_resolvers(x) ,">\n", sep="")
cat(
"<gdns v", gdns_lib_version(),
" resolver context; resolvers: [",
paste0(int_get_resolvers(x), collapse=", "),
"]>\n", sep = ""
)
}
}

128
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 <https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml>
#' @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
}
}

35
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}

72
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())
## <gdns v1.5.1 resolver context; resolvers: [9.9.9.9]>
(x <- gdns_resolver("1.1.1.1"))
## <gdns v1.5.1 resolver context; resolvers: [1.1.1.1]>
(x <- gdns_resolver(c("8.8.8.8", "1.1.1.1", "9.9.9.9")))
## <gdns v1.5.1 resolver context; resolvers: [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

1
man/check_is_xptr.Rd

@ -12,3 +12,4 @@ check_is_xptr(s)
\description{
Test whether an object is an external pointer
}
\keyword{internal}

1
man/clandnstine.Rd

@ -18,3 +18,4 @@ Something something 'getdns API/library'.
\author{
Bob Rudis (bob@rud.is)
}
\keyword{internal}

11
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
}

115
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}
}

7
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 <chr> 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")
}

21
man/get_address.Rd

@ -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 <chr>)}
\item{resolver}{resolver address. defaults to Quad9; (length 1 <chr>)}
}
\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")
}

12
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}

1
man/is_null_xptr_.Rd

@ -12,3 +12,4 @@ is_null_xptr_(s)
\description{
Test whether an external pointer is null
}
\keyword{internal}

38
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}
};

93
src/clandnstine-main.cpp

@ -4,76 +4,33 @@
#include <arpa/inet.h>
using namespace Rcpp;
//' Lookup IP Address(es) for a Given Host
//' Return gdns library version
//'
//' @param host host (length 1 <chr>)
//' @param resolver resolver address. defaults to Quad9; (length 1 <chr>)
//' @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));
//
// }
//

62
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 <chr> 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<resolvers.size(); i++) {
r = getdns_str2dict(resolvers[i].c_str(), &resolver_dict);
r = getdns_list_set_dict(resolver_list, i, resolver_dict);
}
getdns_transport_list_t tls_transport[] = { GETDNS_TRANSPORT_TLS };
@ -116,6 +115,7 @@ CharacterVector gdns_get_address(SEXP gctx, std::string host) {
getdns_dict *cur_addr;
getdns_bindata *address;
// TODO Validate we don't need to free these
r = getdns_list_get_dict(addrs, i, &cur_addr);
r = getdns_dict_get_bindata(cur_addr, "address_data", &address);
@ -166,6 +166,7 @@ CharacterVector int_get_resolvers(SEXP gctx) {
getdns_dict *cur_addr;
getdns_bindata *address;
// TODO Validate we don't need to free these
r = getdns_list_get_dict(addrs, i, &cur_addr);
r = getdns_dict_get_bindata(cur_addr, "address_data", &address);
@ -188,5 +189,42 @@ CharacterVector int_get_resolvers(SEXP gctx) {
}
// [[Rcpp::export]]
CharacterVector int_gdns_query(SEXP gctx, std::string name, uint16_t rr) {
uint32_t err;
size_t sz;
getdns_return_t r;
getdns_dict *resp = NULL;
getdns_list *results;
std::string out;
bool ok = false;
getdns_context *ctxt = (getdns_context *)R_ExternalPtrAddr(gctx);
if (gctx == NULL) return(CharacterVector());
if ((r = getdns_general_sync(ctxt, name.c_str(), rr, NULL, &resp))) {
} else if ((r = getdns_dict_get_int(resp, "status", &err))) {
} else if (err != GETDNS_RESPSTATUS_GOOD) {
} else {
ok = true;
}
if (ok) {
char *charout = getdns_print_json_dict(resp, 0);
if (charout) {
out = std::string(charout);
free(charout);
} else {
ok = false;
}
}
if (resp) getdns_dict_destroy(resp);
if (ok) return(wrap(out)); else return(CharacterVector());
}

22
tests/testthat/test-clandnstine.R

@ -1,7 +1,25 @@
context("basic wrapper works")
test_that("we can do something", {
test_that("basic wrapper works", {
x <- get_address("example.com")
expect_is(gdns_lib_version(), "character")
r <- gdns_resolver()
x <- gdns_get_address(r, "example.com")
expect_true(all(c("2606:2800:220:1:248:1893:25c8:1946", "93.184.216.34") %in% x))
r <- gdns_resolver(c("8.8.8.8", "1.1.1.1", "9.9.9.9"))
x <- gdns_get_address(r, "example.com")
expect_true(all(c("2606:2800:220:1:248:1893:25c8:1946", "93.184.216.34") %in% x))
x <- gdns_get_address(r, "example.commm")
expect_length(x, 0)
x <- gdns_query(r, "example.com", "txt")
expect_equal(x$answer_type, 800)
expect_equal(x$canonical_name, "example.com.")
expect_true(grepl("spf", unlist(x$replies_tree$answer[[1]]$rdata$txt_strings)))
})

Зареждане…
Отказ
Запис