mirror of https://github.com/getdnsapi/getdns.git
Merge remote-tracking branch 'jim/features/yaml' into release/v1.2.0
This commit is contained in:
commit
d880d4222b
|
@ -8,6 +8,7 @@ addons:
|
|||
packages:
|
||||
- libunbound-dev
|
||||
- libidn11-dev
|
||||
- libyaml-dev
|
||||
- check
|
||||
- libevent-dev
|
||||
- libev-dev
|
||||
|
|
|
@ -245,7 +245,7 @@ $(distdir):
|
|||
cp $(srcdir)/spec/example/*.[ch] $(distdir)/spec/example
|
||||
cp $(srcdir)/src/tools/Makefile.in $(distdir)/src/tools
|
||||
cp $(srcdir)/src/tools/*.[ch] $(distdir)/src/tools
|
||||
cp $(srcdir)/stubby/stubby.conf.example $(distdir)/stubby
|
||||
cp $(srcdir)/stubby/stubby.yml.example $(distdir)/stubby
|
||||
cp $(srcdir)/stubby/stubby-setdns-macos.sh $(distdir)/stubby
|
||||
cp $(srcdir)/stubby/src/stubby.c $(distdir)/stubby/src
|
||||
cp $(srcdir)/stubby/COPYING $(distdir)/stubby
|
||||
|
|
|
@ -72,6 +72,7 @@ External dependencies are linked outside the getdns API build tree (we rely on c
|
|||
* [libunbound from NLnet Labs](https://unbound.net/) version 1.4.16 or later.
|
||||
* [libidn from the FSF](https://www.gnu.org/software/libidn/) version 1. (Note that the libidn version means the conversions between A-labels and U-labels may permit conversion of formally invalid labels under IDNA2008.)
|
||||
* [libssl and libcrypto from the OpenSSL Project](https://www.openssl.org/) version 0.9.7 or later. (Note: version 1.0.1 or later is required for TLS support, version 1.0.2 or later is required for TLS hostname authentication)
|
||||
* [libyaml](http://pyyaml.org/wiki/LibYAML) version 0.1.6 or later.
|
||||
* Doxygen is used to generate documentation; while this is not technically necessary for the build it makes things a lot more pleasant.
|
||||
|
||||
For example, to build on a recent version of Ubuntu, you would need the following packages:
|
||||
|
@ -99,6 +100,7 @@ Note: If you only want to build stubby, then use the `--with-stubby` option when
|
|||
|
||||
* getdns can be configured for stub resolution mode only with the `--enable-stub-only` option to configure. This removes the dependency on `libunbound`.
|
||||
* Currently getdns only offers two helper functions to deal with IDN: `getdns_convert_ulabel_to_alabel` and `getdns_convert_alabel_to_ulabel`. If you do not need these functions, getdns can be configured to compile without them with the `--without-libidn` option to configure.
|
||||
* getdns can be configured to not support YAML configuration with the `--disable-yaml-config` option to configure. This removes the dependency on `libyaml`.
|
||||
* When both `--enable-stub-only` and `--without-libidn` options are used, getdns has only one dependency left, which is OpenSSL.
|
||||
|
||||
## Extensions and Event loop dependencies
|
||||
|
|
45
configure.ac
45
configure.ac
|
@ -578,6 +578,17 @@ case "$enable_stub_only" in
|
|||
;;
|
||||
esac
|
||||
|
||||
my_with_yaml=1
|
||||
AC_ARG_ENABLE(yaml-config, AC_HELP_STRING([--disable-yaml-config], [Remove support for YAML configuration. Removes the libyaml dependency.]))
|
||||
case "$enable_yaml_config" in
|
||||
no)
|
||||
my_with_yaml=0
|
||||
;;
|
||||
yes|*)
|
||||
AC_DEFINE_UNQUOTED([USE_YAML_CONFIG], [1], [Define this to enable YAML config support.])
|
||||
;;
|
||||
esac
|
||||
|
||||
if test "$USE_WINSOCK" = 1; then
|
||||
AC_MSG_NOTICE([ Building on Windows ... YES! ])
|
||||
AC_DEFINE_UNQUOTED([GETDNS_ON_WINDOWS], [1], [Define this to enable Windows build.])
|
||||
|
@ -619,6 +630,30 @@ else
|
|||
fi
|
||||
fi
|
||||
|
||||
if test $my_with_yaml = 1
|
||||
then
|
||||
AC_ARG_WITH(libyaml, AS_HELP_STRING([--with-libyaml=pathname],
|
||||
[path to libyaml (default: search /usr/local ..)]),
|
||||
[], [withval="yes"])
|
||||
if test x_$withval = x_yes; then
|
||||
for dir in /usr/local /opt/local /usr/pkg /usr/sfw; do
|
||||
if test -f "$dir/include/yaml.h"; then
|
||||
CFLAGS="$CFLAGS -I$dir/include"
|
||||
LDFLAGS="$LDFLAGS -L$dir/lib"
|
||||
AC_MSG_NOTICE([Found libyaml in $dir])
|
||||
break
|
||||
fi
|
||||
done
|
||||
else
|
||||
if test x_$withval != x_no; then
|
||||
CFLAGS="$CFLAGS -I$withval/include"
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||
else
|
||||
my_with_yaml=0
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $my_with_libunbound = 1
|
||||
then
|
||||
# find libunbound
|
||||
|
@ -659,6 +694,16 @@ then
|
|||
])
|
||||
fi
|
||||
|
||||
if test $my_with_yaml = 1
|
||||
then
|
||||
AC_MSG_NOTICE([Checking for dependency libyaml])
|
||||
AC_CHECK_LIB([yaml], [yaml_parser_parse], [], [
|
||||
MISSING_DEPS="${MISSING_DEPS}${MISSING_SEP}libyaml"
|
||||
MISSING_SEP=", "
|
||||
found_all_libs=0
|
||||
])
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(unbound-event-api, AC_HELP_STRING([--disable-unbound-event-api], [Disable usage of libunbounds event API]))
|
||||
case "$enable_unbound_event_api" in
|
||||
no)
|
||||
|
|
|
@ -92,6 +92,8 @@ UTIL_OBJ=rbtree.lo val_secalgo.lo lruhash.lo lookup3.lo locks.lo
|
|||
|
||||
JSMN_OBJ=jsmn.lo
|
||||
|
||||
YAML_OBJ=convert_yaml_to_json.lo
|
||||
|
||||
EXTENSION_OBJ=$(DEFAULT_EVENTLOOP_OBJ) libevent.lo libev.lo
|
||||
|
||||
NON_C99_OBJS=context.lo libuv.lo
|
||||
|
@ -123,6 +125,9 @@ $(UTIL_OBJ):
|
|||
$(JSMN_OBJ):
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -DJSMN_GETDNS -c $(srcdir)/jsmn/$(@:.lo=.c) -o $@
|
||||
|
||||
$(YAML_OBJ):
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $(srcdir)/yaml/$(@:.lo=.c) -o $@
|
||||
|
||||
$(EXTENSION_OBJ):
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) $(WPEDANTICFLAG) -c $(srcdir)/extension/$(@:.lo=.c) -o $@
|
||||
|
||||
|
@ -173,8 +178,8 @@ libgetdns_ext_ev.la: libgetdns.la libev.lo
|
|||
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ libev.lo libgetdns.la $(LDFLAGS) $(EXTENSION_LIBEV_LDFLAGS) $(EXTENSION_LIBEV_EXT_LIBS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/extension/libev.symbols
|
||||
|
||||
|
||||
libgetdns.la: $(GETDNS_OBJ) version.lo context.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ)
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols
|
||||
libgetdns.la: $(GETDNS_OBJ) version.lo context.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(YAML_OBJ)
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(GETDNS_OBJ) version.lo context.lo $(DEFAULT_EVENTLOOP_OBJ) $(GLDNS_OBJ) $(COMPAT_OBJ) $(UTIL_OBJ) $(JSMN_OBJ) $(YAML_OBJ) $(LDFLAGS) -rpath $(libdir) -version-info $(libversion) -no-undefined -export-symbols $(srcdir)/libgetdns.symbols
|
||||
|
||||
test: default
|
||||
cd test && $(MAKE) $@
|
||||
|
@ -188,14 +193,14 @@ stubby.lo: $(stubbysrcdir)/src/stubby.c
|
|||
stubby: stubby.lo libgetdns.la
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ stubby.lo $(LDFLAGS) libgetdns.la
|
||||
|
||||
install-stubby: stubby $(stubbysrcdir)/stubby.conf.example $(stubbysrcdir)/stubby-setdns-macos.sh
|
||||
install-stubby: stubby $(stubbysrcdir)/stubby.yml.example $(stubbysrcdir)/stubby-setdns-macos.sh
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(bindir)
|
||||
$(LIBTOOL) --mode=install cp stubby $(DESTDIR)$(bindir)
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(sbindir)
|
||||
$(INSTALL) -m 755 $(stubbysrcdir)/stubby-setdns-macos.sh $(DESTDIR)$(sbindir)
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(stubbyconfdir)
|
||||
test -f $(DESTDIR)$(stubbyconfdir)/stubby.conf || \
|
||||
$(INSTALL_DATA) $(stubbysrcdir)/stubby.conf.example $(DESTDIR)$(stubbyconfdir)/stubby.conf
|
||||
test -f $(DESTDIR)$(stubbyconfdir)/stubby.yml || \
|
||||
$(INSTALL_DATA) $(stubbysrcdir)/stubby.yml.example $(DESTDIR)$(stubbyconfdir)/stubby.yml
|
||||
|
||||
uninstall-stubby:
|
||||
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(bindir)/stubby
|
||||
|
@ -226,13 +231,14 @@ Makefile: $(srcdir)/Makefile.in ../config.status
|
|||
|
||||
depend:
|
||||
(cd $(srcdir) ; awk 'BEGIN{P=1}{if(P)print}/^# Dependencies/{P=0}' Makefile.in > Makefile.in.new )
|
||||
(blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I"$$blddir" -Iutil/auxiliary *.c gldns/*.c compat/*.c util/*.c jsmn/*.c extension/*.c| \
|
||||
(blddir=`pwd`; cd $(srcdir) ; gcc -MM -I. -I"$$blddir" -Iutil/auxiliary *.c gldns/*.c compat/*.c util/*.c jsmn/*.c yaml/*.c extension/*.c| \
|
||||
sed -e "s? $$blddir/? ?g" \
|
||||
-e 's? gldns/? $$(srcdir)/gldns/?g' \
|
||||
-e 's? compat/? $$(srcdir)/compat/?g' \
|
||||
-e 's? util/auxiliary/util/? $$(srcdir)/util/auxiliary/util/?g' \
|
||||
-e 's? util/? $$(srcdir)/util/?g' \
|
||||
-e 's? jsmn/? $$(srcdir)/jsmn/?g' \
|
||||
-e 's? yaml/? $$(srcdir)/yaml/?g' \
|
||||
-e 's? extension/? $$(srcdir)/extension/?g' \
|
||||
-e 's? \([a-z_-]*\)\.\([ch]\)? $$(srcdir)/\1.\2?g' \
|
||||
-e 's? \$$(srcdir)/config\.h? config.h?g' \
|
||||
|
|
|
@ -3718,6 +3718,8 @@ _get_context_settings(getdns_context* context)
|
|||
|| ( context->edns_maximum_udp_payload_size != -1
|
||||
&& getdns_dict_set_int(result, "edns_maximum_udp_payload_size",
|
||||
context->edns_maximum_udp_payload_size))
|
||||
|| getdns_dict_set_int(result, "edns_client_subnet_private",
|
||||
context->edns_client_subnet_private)
|
||||
|| getdns_dict_set_int(result, "edns_extended_rcode",
|
||||
context->edns_extended_rcode)
|
||||
|| getdns_dict_set_int(result, "edns_version",
|
||||
|
@ -3733,7 +3735,9 @@ _get_context_settings(getdns_context* context)
|
|||
|| getdns_dict_set_int(result, "tls_backoff_time",
|
||||
context->tls_backoff_time)
|
||||
|| getdns_dict_set_int(result, "tls_connection_retries",
|
||||
context->tls_connection_retries))
|
||||
context->tls_connection_retries)
|
||||
|| getdns_dict_set_int(result, "tls_query_padding_blocksize",
|
||||
context->tls_query_padding_blocksize))
|
||||
goto error;
|
||||
|
||||
/* list fields */
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include "dict.h"
|
||||
#include "list.h"
|
||||
#include "jsmn/jsmn.h"
|
||||
#include "yaml/convert_yaml_to_json.h"
|
||||
#include "convert.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -1802,3 +1803,99 @@ getdns_str2int(const char *str, uint32_t *value)
|
|||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_yaml2dict(const char *str, getdns_dict **dict)
|
||||
{
|
||||
#ifdef USE_YAML_CONFIG
|
||||
char *jsonstr;
|
||||
|
||||
if (!str || !dict)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
jsonstr = yaml_string_to_json_string(str);
|
||||
if (jsonstr) {
|
||||
getdns_return_t res = getdns_str2dict(jsonstr, dict);
|
||||
free(jsonstr);
|
||||
return res;
|
||||
} else {
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
#else /* USE_YAML_CONFIG */
|
||||
(void) str;
|
||||
(void) dict;
|
||||
return GETDNS_RETURN_NOT_IMPLEMENTED;
|
||||
#endif /* USE_YAML_CONFIG */
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_yaml2list(const char *str, getdns_list **list)
|
||||
{
|
||||
#ifdef USE_YAML_CONFIG
|
||||
char *jsonstr;
|
||||
|
||||
if (!str || !list)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
jsonstr = yaml_string_to_json_string(str);
|
||||
if (jsonstr) {
|
||||
getdns_return_t res = getdns_str2list(jsonstr, list);
|
||||
free(jsonstr);
|
||||
return res;
|
||||
} else {
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
#else /* USE_YAML_CONFIG */
|
||||
(void) str;
|
||||
(void) list;
|
||||
return GETDNS_RETURN_NOT_IMPLEMENTED;
|
||||
#endif /* USE_YAML_CONFIG */
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_yaml2bindata(const char *str, getdns_bindata **bindata)
|
||||
{
|
||||
#ifdef USE_YAML_CONFIG
|
||||
char *jsonstr;
|
||||
|
||||
if (!str || !bindata)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
jsonstr = yaml_string_to_json_string(str);
|
||||
if (jsonstr) {
|
||||
getdns_return_t res = getdns_str2bindata(jsonstr, bindata);
|
||||
free(jsonstr);
|
||||
return res;
|
||||
} else {
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
#else /* USE_YAML_CONFIG */
|
||||
(void) str;
|
||||
(void) bindata;
|
||||
return GETDNS_RETURN_NOT_IMPLEMENTED;
|
||||
#endif /* USE_YAML_CONFIG */
|
||||
}
|
||||
|
||||
getdns_return_t
|
||||
getdns_yaml2int(const char *str, uint32_t *value)
|
||||
{
|
||||
#ifdef USE_YAML_CONFIG
|
||||
char *jsonstr;
|
||||
|
||||
if (!str || !value)
|
||||
return GETDNS_RETURN_INVALID_PARAMETER;
|
||||
|
||||
jsonstr = yaml_string_to_json_string(str);
|
||||
if (jsonstr) {
|
||||
getdns_return_t res = getdns_str2int(jsonstr, value);
|
||||
free(jsonstr);
|
||||
return res;
|
||||
} else {
|
||||
return GETDNS_RETURN_GENERIC_ERROR;
|
||||
}
|
||||
#else /* USE_YAML_CONFIG */
|
||||
(void) str;
|
||||
(void) value;
|
||||
return GETDNS_RETURN_NOT_IMPLEMENTED;
|
||||
#endif /* USE_YAML_CONFIG */
|
||||
}
|
||||
|
||||
|
|
|
@ -1685,6 +1685,98 @@ getdns_str2bindata(const char *str, getdns_bindata **bindata);
|
|||
getdns_return_t
|
||||
getdns_str2int(const char *str, uint32_t *value);
|
||||
|
||||
/** @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup Uyaml2getdns_data Converting YAML input to getdns data structures
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert YAML text to a getdns_dict.
|
||||
*
|
||||
* @param str A textual representation of a getdns_dict.
|
||||
* The format is similar, but not precisely YAML.
|
||||
* - When str contains an IP or IPv6 address, it is converted
|
||||
* to an getdns dict representation of that address. This may contain
|
||||
* a port, tls_port, tsig spec or tls authentication name in the same
|
||||
* way as may be given with the `getdns_query` tool. For example:
|
||||
* `185.49.140.67:80#443` will result in the following getdns_dict:
|
||||
*
|
||||
* { address_type: "IPv4"
|
||||
* , address_data: "185.49.140.67"
|
||||
* , port: 80
|
||||
* , tls_port: 443
|
||||
* }
|
||||
* @param dict The returned getdns_dict.
|
||||
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_yaml2dict(const char *str, getdns_dict **dict);
|
||||
|
||||
/**
|
||||
* Convert YAML text to a getdns_list.
|
||||
*
|
||||
* @param str A textual representation of a getdns_list.
|
||||
* @param list The returned getdns_list.
|
||||
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_yaml2list(const char *str, getdns_list **list);
|
||||
|
||||
/**
|
||||
* Convert string text to a getdns_bindata.
|
||||
*
|
||||
* @param str A textual representation of a getdns_bindata
|
||||
* The format is similar, but not precisely YAML.
|
||||
* - Strings between double-quotes will be converted to bindata
|
||||
* containers, but *without the trailing null byte*.
|
||||
* For example: `{ suffix: [ "nlnetlabs.nl.", "nlnet.nl." ] }`
|
||||
* - bindata representation of IP or IPv6 addresses may be
|
||||
* given in their presentation format. For example:
|
||||
* `{ dns_root_servers: [ 2001:7fd::1, 193.0.14.129 ] }`
|
||||
* - Arbitrary binary data may be given with a `0x` prefix,
|
||||
* or in base64 encoding.
|
||||
* For example:
|
||||
*
|
||||
* { add_opt_parameters:
|
||||
* { options: [ { option_code: 10
|
||||
* , option_data: 0xA9E4EC50C03F5D65
|
||||
* } ]
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* - Wireformat domain name bindatas can be given with a trailing dot.
|
||||
* For example:
|
||||
*
|
||||
* { upstream_recursive_servers:
|
||||
* [ { address_data : 2a04:b900:0:100::37
|
||||
* , tsig_name : hmac-md5.tsigs.getdnsapi.net.
|
||||
* , tsig_algorithm: hmac-md5.sig-alg.reg.int.
|
||||
* , tsig_secret : 16G69OTeXW6xSQ==
|
||||
* } ]
|
||||
* }
|
||||
* @param bindata The returned getdns_bindata.
|
||||
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_yaml2bindata(const char *str, getdns_bindata **bindata);
|
||||
|
||||
/**
|
||||
* Convert string text to a getdns 32 bits unsigned integer.
|
||||
*
|
||||
* @param str A textual representation of the integer.
|
||||
* The format is similar, but not precisely YAML.
|
||||
* - integer values may be given by the constant name.
|
||||
* For example: `{ resolution_type: GETDNS_RESOLUTION_STUB }`
|
||||
* or `{ specify_class: GETDNS_RRCLASS_CH }`
|
||||
* @param value The returned integer.
|
||||
* @return GETDNS_RETURN_GOOD on success or an error code on failure.
|
||||
*/
|
||||
getdns_return_t
|
||||
getdns_yaml2int(const char *str, uint32_t *value);
|
||||
|
||||
/** @}
|
||||
*/
|
||||
|
||||
|
|
|
@ -159,5 +159,9 @@ getdns_wire2msg_dict_scan
|
|||
getdns_wire2rr_dict
|
||||
getdns_wire2rr_dict_buf
|
||||
getdns_wire2rr_dict_scan
|
||||
getdns_yaml2bindata
|
||||
getdns_yaml2dict
|
||||
getdns_yaml2int
|
||||
getdns_yaml2list
|
||||
plain_mem_funcs_user_arg
|
||||
priv_getdns_context_mf
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
builddir = @BUILDDIR@
|
||||
testname = @TPKG_NAME@
|
||||
LIBTOOL = $(builddir)/libtool
|
||||
|
||||
CFLAGS=-I$(builddir)/src
|
||||
LDLIBS=$(builddir)/src/libgetdns.la
|
||||
|
||||
.SUFFIXES: .c .o .a .lo .h
|
||||
|
||||
.c.lo:
|
||||
$(LIBTOOL) --quiet --tag=CC --mode=compile $(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
$(testname): $(testname).lo
|
||||
$(LIBTOOL) --tag=CC --mode=link $(CC) $(LDLIBS) $(LDFLAGS) -o $(testname) $(testname).lo
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <getdns/getdns.h>
|
||||
#include <getdns/getdns_extra.h>
|
||||
|
||||
int main(int ac, char *av[])
|
||||
{
|
||||
FILE *f;
|
||||
char *buf = NULL;
|
||||
size_t len;
|
||||
ssize_t bytes_read;
|
||||
|
||||
f = fopen(av[1], "r");
|
||||
if (!f) {
|
||||
fprintf(stderr, "Could not open %s", av[1]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
bytes_read = getdelim(&buf, &len, '\0', f);
|
||||
fclose(f);
|
||||
|
||||
if (bytes_read == -1) {
|
||||
fprintf(stderr, "Could not read %s", av[1]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
buf = realloc(buf, bytes_read + 1);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Could not grow buffer");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
buf[bytes_read] = '\0';
|
||||
|
||||
getdns_dict *dict = NULL;
|
||||
getdns_list *list = NULL;
|
||||
getdns_bindata *bindata = NULL;
|
||||
getdns_return_t r;
|
||||
|
||||
if (!(dict = getdns_dict_create())) {
|
||||
fprintf(stderr, "Could not create dict");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = getdns_yaml2dict(buf, &dict);
|
||||
if (r) {
|
||||
fprintf(stderr, "Error setting dict data: %s", getdns_get_errorstr_by_id(r));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now add a list, bindata and int to the dict by hand to check
|
||||
* the other yaml2* functions work.
|
||||
*/
|
||||
if (!(list = getdns_list_create())) {
|
||||
fprintf(stderr, "Could not create list");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = getdns_yaml2list("[\"One\", \"two\", \"three\"]", &list);
|
||||
if (r) {
|
||||
fprintf(stderr, "Error setting list data: %s", getdns_get_errorstr_by_id(r));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = getdns_dict_set_list(dict, "List entry", list);
|
||||
if (r) {
|
||||
fprintf(stderr, "Error adding list to dict: %s", getdns_get_errorstr_by_id(r));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = getdns_yaml2bindata("2001:7fd::1", &bindata);
|
||||
if (r) {
|
||||
fprintf(stderr, "Error setting bindata: %s", getdns_get_errorstr_by_id(r));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = getdns_dict_set_bindata(dict, "Bindata entry", bindata);
|
||||
if (r) {
|
||||
fprintf(stderr, "Error adding list to dict: %s", getdns_get_errorstr_by_id(r));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint32_t intval;
|
||||
r = getdns_yaml2int("32767", &intval);
|
||||
if (r) {
|
||||
fprintf(stderr, "Error setting int: %s", getdns_get_errorstr_by_id(r));
|
||||
goto fail;
|
||||
}
|
||||
if (intval != 32767) {
|
||||
fprintf(stderr, "Error reading int: wrong value");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
char *dict_str = getdns_pretty_print_dict(dict);
|
||||
if (!dict_str) {
|
||||
fprintf(stderr, "Could not convert dict to string");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
printf("%s\n", dict_str);
|
||||
free(dict_str);
|
||||
getdns_dict_destroy(dict);
|
||||
exit(EXIT_SUCCESS);
|
||||
|
||||
fail:
|
||||
if (dict)
|
||||
getdns_dict_destroy(dict);
|
||||
if (list)
|
||||
getdns_list_destroy(list);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
BaseName: 255-yaml-config
|
||||
Version: 1.0
|
||||
Description: Test YAML configuration
|
||||
CreationDate: Wed 13 Sep 2017 12:42:32 BST
|
||||
Maintainer: Jim Hague
|
||||
Category:
|
||||
Component:
|
||||
CmdDepends:
|
||||
Depends: 200-stub-only-compile.tpkg
|
||||
Help:
|
||||
Pre: 255-yaml-config.pre
|
||||
Post:
|
||||
Test: 255-yaml-config.test
|
||||
AuxFiles:
|
||||
Passed:
|
||||
Failure:
|
|
@ -0,0 +1,87 @@
|
|||
{
|
||||
"Bindata entry": <bindata of 0x200107fd000000000000000000000001>,
|
||||
"List entry":
|
||||
[
|
||||
<bindata of "One">,
|
||||
<bindata of "two">,
|
||||
<bindata of "three">
|
||||
],
|
||||
"dnssec_return_status": 1000,
|
||||
"upstream_recursive_servers":
|
||||
[
|
||||
{
|
||||
"address_data": <bindata for 145.100.185.15>,
|
||||
"tls_auth_name": <bindata of "dnsovertls.sinodun.com">,
|
||||
"tls_pubkey_pinset":
|
||||
[
|
||||
{
|
||||
"digest": <bindata of "sha256">,
|
||||
"value": <bindata of 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4=>
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"address_data": <bindata for 145.100.185.16>,
|
||||
"tls_auth_name": <bindata of "dnsovertls1.sinodun.com">,
|
||||
"tls_pubkey_pinset":
|
||||
[
|
||||
{
|
||||
"digest": <bindata of "sha256">,
|
||||
"value": <bindata of cE2ecALeE5B+urJhDrJlVFmf38cJLAvqekONvjvpqUA=>
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"address_data": <bindata for 185.49.141.37>,
|
||||
"tls_auth_name": <bindata of "getdnsapi.net">,
|
||||
"tls_pubkey_pinset":
|
||||
[
|
||||
{
|
||||
"digest": <bindata of "sha256">,
|
||||
"value": <bindata of foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q=>
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"address_data": <bindata for 184.105.193.78>,
|
||||
"tls_auth_name": <bindata of "unicast.censurfridns.dk">
|
||||
},
|
||||
{
|
||||
"address_data": <bindata for 2001:610:1:40ba:145:100:185:15>,
|
||||
"tls_auth_name": <bindata of "dnsovertls.sinodun.com">,
|
||||
"tls_pubkey_pinset":
|
||||
[
|
||||
{
|
||||
"digest": <bindata of "sha256">,
|
||||
"value": <bindata of 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4=>
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"address_data": <bindata for 2001:610:1:40ba:145:100:185:16>,
|
||||
"tls_auth_name": <bindata of "dnsovertls1.sinodun.com">,
|
||||
"tls_pubkey_pinset":
|
||||
[
|
||||
{
|
||||
"digest": <bindata of "sha256">,
|
||||
"value": <bindata of cE2ecALeE5B+urJhDrJlVFmf38cJLAvqekONvjvpqUA=>
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"address_data": <bindata for 2a04:b900:0:100::38>,
|
||||
"tls_auth_name": <bindata of "getdnsapi.net">,
|
||||
"tls_pubkey_pinset":
|
||||
[
|
||||
{
|
||||
"digest": <bindata of "sha256">,
|
||||
"value": <bindata of foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q=>
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"address_data": <bindata for 2620:ff:c000:0:1:0:64:25>,
|
||||
"tls_auth_name": <bindata of "unicast.censurfridns.dk">
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
upstream_recursive_servers:
|
||||
# IPv4 addresses
|
||||
# The Surfnet/Sinodun servers
|
||||
- address_data: 145.100.185.15
|
||||
tls_auth_name: "dnsovertls.sinodun.com"
|
||||
tls_pubkey_pinset:
|
||||
- digest: "sha256"
|
||||
value: 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4=
|
||||
- address_data: 145.100.185.16
|
||||
tls_auth_name: "dnsovertls1.sinodun.com"
|
||||
tls_pubkey_pinset:
|
||||
- digest: "sha256"
|
||||
value: cE2ecALeE5B+urJhDrJlVFmf38cJLAvqekONvjvpqUA=
|
||||
# The getdnsapi.net server
|
||||
- address_data: 185.49.141.37
|
||||
tls_auth_name: "getdnsapi.net"
|
||||
tls_pubkey_pinset:
|
||||
- digest: "sha256"
|
||||
value: foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q=
|
||||
# The uncensored DNS servers (no SPKI available)
|
||||
- address_data: 184.105.193.78
|
||||
tls_auth_name: "unicast.censurfridns.dk"
|
||||
# IPv6 addresses
|
||||
# The Surfnet/Sinodun servers
|
||||
- address_data: 2001:610:1:40ba:145:100:185:15
|
||||
tls_auth_name: "dnsovertls.sinodun.com"
|
||||
tls_pubkey_pinset:
|
||||
- digest: "sha256"
|
||||
value: 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4=
|
||||
- address_data: 2001:610:1:40ba:145:100:185:16
|
||||
tls_auth_name: "dnsovertls1.sinodun.com"
|
||||
tls_pubkey_pinset:
|
||||
- digest: "sha256"
|
||||
value: cE2ecALeE5B+urJhDrJlVFmf38cJLAvqekONvjvpqUA=
|
||||
# The getdnsapi.net server
|
||||
- address_data: 2a04:b900:0:100::38
|
||||
tls_auth_name: "getdnsapi.net"
|
||||
tls_pubkey_pinset:
|
||||
- digest: "sha256"
|
||||
value: foxZRnIh9gZpWnl+zEiKa0EJ2rdCGroMWm02gaxSc9Q=
|
||||
# The uncensored DNS server (no SPKI available)
|
||||
- address_data: 2620:ff:c000:0:1::64:25
|
||||
tls_auth_name: "unicast.censurfridns.dk"
|
||||
|
||||
# Require DNSSEC validation. For releases earlier than 1.2 a trust anchor must
|
||||
# be configured configured manually. This can be done with unbound-anchor.
|
||||
dnssec_return_status: GETDNS_EXTENSION_TRUE
|
|
@ -0,0 +1,14 @@
|
|||
# #-- 255-yaml-config.test --#
|
||||
# source the master var file when it's there
|
||||
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||
# use .tpkg.var.test for in test variable passing
|
||||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||
|
||||
(
|
||||
grep '^CC=' "${BUILDDIR}/build-stub-only/src/Makefile"
|
||||
grep '^LDFLAGS=' "${BUILDDIR}/build-stub-only/src/Makefile"
|
||||
|
||||
BUILDDIR4SED=`echo "${BUILDDIR}/build-stub-only" | sed 's/\//\\\\\//g'`
|
||||
sed -e "s/@BUILDDIR@/${BUILDDIR4SED}/g" \
|
||||
-e "s/@TPKG_NAME@/${TPKG_NAME}/g" "${TPKG_NAME}.Makefile"
|
||||
) > Makefile
|
|
@ -0,0 +1,7 @@
|
|||
# #-- 255-yaml-config.test --#
|
||||
# source the master var file when it's there
|
||||
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
|
||||
# use .tpkg.var.test for in test variable passing
|
||||
[ -f .tpkg.var.test ] && source .tpkg.var.test
|
||||
|
||||
make && "./${TPKG_NAME}" 255-yaml-config.input | tee out && diff out "${TPKG_NAME}.good"
|
|
@ -215,7 +215,8 @@ print_usage(FILE *out, const char *progname)
|
|||
fprintf(out, "\t-C\t<filename>\n");
|
||||
fprintf(out, "\t\tRead settings from config file <filename>\n");
|
||||
fprintf(out, "\t\tThe getdns context will be configured with these settings\n");
|
||||
fprintf(out, "\t\tThe file must be in json dict format.\n");
|
||||
fprintf(out, "\t\tThe file must be in YAML format (with extension of '.yml')\n");
|
||||
fprintf(out, "\t\tor JSON dict format (with extension '.conf')\n");
|
||||
if (i_am_stubby) {
|
||||
fprintf(out, "\t\tBy default, configuration is first read from");
|
||||
fprintf(out, "\n\t\t\"/etc/stubby.conf\" and then from \"$HOME/.stubby.conf\"\n");
|
||||
|
@ -472,16 +473,25 @@ done:
|
|||
return r;
|
||||
}
|
||||
|
||||
static void parse_config(const char *config_str)
|
||||
static void parse_config(const char *config_str, int yaml_config)
|
||||
{
|
||||
getdns_dict *config_dict;
|
||||
getdns_list *list;
|
||||
getdns_return_t r;
|
||||
|
||||
if ((r = getdns_str2dict(config_str, &config_dict)))
|
||||
if (yaml_config) {
|
||||
#ifdef USE_YAML_CONFIG
|
||||
r = getdns_yaml2dict(config_str, &config_dict);
|
||||
#else
|
||||
fprintf(stderr, "Support for YAML configuration files not available.\n");
|
||||
return;
|
||||
#endif
|
||||
} else {
|
||||
r = getdns_str2dict(config_str, &config_dict);
|
||||
}
|
||||
if (r)
|
||||
fprintf(stderr, "Could not parse config file: %s\n",
|
||||
getdns_get_errorstr_by_id(r));
|
||||
|
||||
else {
|
||||
if (!(r = getdns_dict_get_list(
|
||||
config_dict, "listen_addresses", &list))) {
|
||||
|
@ -561,7 +571,7 @@ int parse_config_file(const char *fn, int report_open_failure)
|
|||
}
|
||||
config_file[config_file_sz] = 0;
|
||||
fclose(fh);
|
||||
parse_config(config_file);
|
||||
parse_config(config_file, strstr(fn, ".yml") != NULL);
|
||||
free(config_file);
|
||||
return GETDNS_RETURN_GOOD;
|
||||
}
|
||||
|
@ -650,7 +660,7 @@ getdns_return_t parse_args(int argc, char **argv)
|
|||
}
|
||||
continue;
|
||||
} else if (arg[0] == '{') {
|
||||
parse_config(arg);
|
||||
parse_config(arg, 0);
|
||||
continue;
|
||||
|
||||
} else if (arg[0] != '-') {
|
||||
|
@ -1719,7 +1729,7 @@ main(int argc, char **argv)
|
|||
, "%s/.stubby.conf"
|
||||
, getenv("HOME")
|
||||
);
|
||||
(void) parse_config(default_stubby_config);
|
||||
(void) parse_config(default_stubby_config, 0);
|
||||
(void) parse_config_file("/etc/stubby.conf", 0);
|
||||
if (n_chars > 0 && n_chars < (int)sizeof(home_stubby_conf_fn)){
|
||||
(void) parse_config_file(home_stubby_conf_fn, 0);
|
||||
|
|
|
@ -0,0 +1,550 @@
|
|||
/*
|
||||
* Copyright (c) 2017, NLNet Labs, Verisign, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef USE_YAML_CONFIG
|
||||
|
||||
#include <yaml.h>
|
||||
|
||||
#include "../gldns/gbuffer.h"
|
||||
#include "convert_yaml_to_json.h"
|
||||
|
||||
static int process_yaml_stream(yaml_parser_t *, yaml_event_t *, gldns_buffer *);
|
||||
|
||||
static int process_yaml_document(yaml_parser_t *, yaml_event_t *, gldns_buffer *);
|
||||
|
||||
static int process_yaml_mapping(yaml_parser_t *, yaml_event_t *, gldns_buffer *);
|
||||
|
||||
static int process_yaml_sequence(yaml_parser_t *, yaml_event_t *, gldns_buffer *);
|
||||
|
||||
static int process_yaml_value(yaml_parser_t *, yaml_event_t *, gldns_buffer *);
|
||||
|
||||
static int output_scalar(yaml_event_t *, gldns_buffer *);
|
||||
|
||||
static void report_parser_error(yaml_parser_t *);
|
||||
|
||||
static char* event_type_string(yaml_event_type_t);
|
||||
|
||||
/* public functions */
|
||||
|
||||
char *
|
||||
yaml_string_to_json_string(const char *instr)
|
||||
{
|
||||
assert(instr);
|
||||
|
||||
gldns_buffer *buf;
|
||||
char* json = NULL;
|
||||
|
||||
buf = gldns_buffer_new(8192);
|
||||
if (!buf) {
|
||||
fprintf(stderr, "Could not assign buffer for json output");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
yaml_parser_t parser;
|
||||
yaml_event_t event;
|
||||
|
||||
memset(&parser, 0, sizeof(parser));
|
||||
memset(&event, 0, sizeof(event));
|
||||
|
||||
if (!yaml_parser_initialize(&parser)) {
|
||||
fprintf(stderr, "Could not initialize the parser object\n");
|
||||
goto return_error;
|
||||
}
|
||||
|
||||
/* Set the parser parameters. */
|
||||
yaml_parser_set_input_string(&parser, (const unsigned char *) instr, strlen(instr));
|
||||
|
||||
/* Get the first event. */
|
||||
if (!yaml_parser_parse(&parser, &event)) {
|
||||
report_parser_error(&parser);
|
||||
goto return_error;
|
||||
}
|
||||
|
||||
/* First event should be stream start. */
|
||||
if (event.type != YAML_STREAM_START_EVENT) {
|
||||
fprintf(stderr, "Event error: wrong type of event: %d\n", event.type);
|
||||
goto return_error;
|
||||
}
|
||||
|
||||
if (process_yaml_stream(&parser, &event, buf) != 0) {
|
||||
goto return_error;
|
||||
}
|
||||
|
||||
yaml_event_delete(&event);
|
||||
yaml_parser_delete(&parser);
|
||||
|
||||
/*
|
||||
* gldns_buffer_export() returns a pointer to the data and
|
||||
* sets a flag to prevent it from being deleted by
|
||||
* gldns_buffer_free()
|
||||
*/
|
||||
json = (char *) gldns_buffer_export(buf);
|
||||
gldns_buffer_free(buf);
|
||||
|
||||
return json;
|
||||
|
||||
return_error:
|
||||
|
||||
yaml_event_delete(&event);
|
||||
yaml_parser_delete(&parser);
|
||||
gldns_buffer_free(buf);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* local functions */
|
||||
|
||||
int
|
||||
process_yaml_stream(yaml_parser_t *parser, yaml_event_t *event, gldns_buffer *buf)
|
||||
{
|
||||
assert(parser);
|
||||
assert(event);
|
||||
assert(buf);
|
||||
|
||||
int done = 0;
|
||||
|
||||
while (!done)
|
||||
{
|
||||
/* Delete the event that brought us here */
|
||||
yaml_event_delete(event);
|
||||
|
||||
/* Get the next event. */
|
||||
if (!yaml_parser_parse(parser, event)) {
|
||||
report_parser_error(parser);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (event->type) {
|
||||
case YAML_STREAM_END_EVENT:
|
||||
|
||||
done = 1;
|
||||
break;
|
||||
|
||||
case YAML_DOCUMENT_START_EVENT:
|
||||
|
||||
if (process_yaml_document(parser, event, buf) != 0) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case YAML_STREAM_START_EVENT:
|
||||
case YAML_DOCUMENT_END_EVENT:
|
||||
case YAML_ALIAS_EVENT:
|
||||
case YAML_SCALAR_EVENT:
|
||||
case YAML_SEQUENCE_START_EVENT:
|
||||
case YAML_SEQUENCE_END_EVENT:
|
||||
case YAML_MAPPING_START_EVENT:
|
||||
case YAML_MAPPING_END_EVENT:
|
||||
|
||||
fprintf(stderr,
|
||||
"Event error: %s. Expected YAML_DOCUMENT_START_EVENT or YAML_STREAM_END_EVENT.\n",
|
||||
event_type_string(event->type));
|
||||
return -1;
|
||||
|
||||
default:
|
||||
/* NOTREACHED */
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
process_yaml_document(yaml_parser_t *parser, yaml_event_t *event, gldns_buffer *buf)
|
||||
{
|
||||
assert(parser);
|
||||
assert(event);
|
||||
assert(buf);
|
||||
|
||||
int done = 0;
|
||||
|
||||
while (!done)
|
||||
{
|
||||
/* Delete the event that brought us here */
|
||||
yaml_event_delete(event);
|
||||
|
||||
/* Get the next event. */
|
||||
if (!yaml_parser_parse(parser, event)) {
|
||||
report_parser_error(parser);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (event->type) {
|
||||
case YAML_DOCUMENT_END_EVENT:
|
||||
|
||||
done = 1;
|
||||
break;
|
||||
|
||||
case YAML_MAPPING_START_EVENT:
|
||||
|
||||
if (process_yaml_mapping(parser, event, buf) != 0) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case YAML_SEQUENCE_START_EVENT:
|
||||
|
||||
if (process_yaml_sequence(parser, event, buf) != 0) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case YAML_SCALAR_EVENT:
|
||||
|
||||
if (output_scalar(event, buf) != 0) {
|
||||
fprintf(stderr, "Value error: Error outputting scalar\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case YAML_STREAM_START_EVENT:
|
||||
case YAML_STREAM_END_EVENT:
|
||||
case YAML_DOCUMENT_START_EVENT:
|
||||
case YAML_ALIAS_EVENT:
|
||||
case YAML_SEQUENCE_END_EVENT:
|
||||
case YAML_MAPPING_END_EVENT:
|
||||
|
||||
fprintf(stderr,
|
||||
"Event error: %s. Expected YAML_MAPPING_START_EVENT or YAML_DOCUMENT_END_EVENT.\n",
|
||||
event_type_string(event->type));
|
||||
return -1;
|
||||
|
||||
default:
|
||||
/* NOTREACHED */
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
process_yaml_mapping(yaml_parser_t *parser, yaml_event_t *event, gldns_buffer *buf)
|
||||
{
|
||||
assert(parser);
|
||||
assert(event);
|
||||
assert(buf);
|
||||
|
||||
int done = 0;
|
||||
int members = 0;
|
||||
|
||||
if ( gldns_buffer_printf(buf, "{ ") == -1 )
|
||||
return -1;
|
||||
|
||||
while (!done)
|
||||
{
|
||||
/* Delete the event that brought us here */
|
||||
yaml_event_delete(event);
|
||||
|
||||
/* Get the next event. */
|
||||
if (!yaml_parser_parse(parser, event)) {
|
||||
report_parser_error(parser);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (event->type == YAML_SCALAR_EVENT) {
|
||||
if (members)
|
||||
if (gldns_buffer_printf(buf, ", ") == -1)
|
||||
return -1;
|
||||
|
||||
if (output_scalar(event, buf) != 0) {
|
||||
fprintf(stderr, "Mapping error: Error outputting key\n");
|
||||
return -1;
|
||||
}
|
||||
if (gldns_buffer_printf(buf, ": ") == -1)
|
||||
return -1;
|
||||
|
||||
members = 1;
|
||||
} else if (event->type == YAML_MAPPING_END_EVENT) {
|
||||
if (gldns_buffer_printf(buf, " }") == -1)
|
||||
return -1;
|
||||
done = 1;
|
||||
continue;
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"Event error: %s. Expected YAML_SCALAR_EVENT or YAML_MAPPING_END_EVENT.\n",
|
||||
event_type_string(event->type));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Delete the event that brought us here */
|
||||
yaml_event_delete(event);
|
||||
|
||||
/* Get the next event. */
|
||||
if (!yaml_parser_parse(parser, event)) {
|
||||
report_parser_error(parser);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (event->type) {
|
||||
case YAML_SCALAR_EVENT:
|
||||
case YAML_SEQUENCE_START_EVENT:
|
||||
case YAML_MAPPING_START_EVENT:
|
||||
if (process_yaml_value(parser, event, buf) != 0) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case YAML_STREAM_START_EVENT:
|
||||
case YAML_STREAM_END_EVENT:
|
||||
case YAML_DOCUMENT_START_EVENT:
|
||||
case YAML_DOCUMENT_END_EVENT:
|
||||
case YAML_ALIAS_EVENT:
|
||||
case YAML_SEQUENCE_END_EVENT:
|
||||
case YAML_MAPPING_END_EVENT:
|
||||
fprintf(stderr,
|
||||
"Event error: %s. Expected YAML_MAPPING_START_EVENT, YAML_SEQUENCE_START_EVENT or YAML_SCALAR_EVENT.\n",
|
||||
event_type_string(event->type));
|
||||
return -1;
|
||||
|
||||
default:
|
||||
/* NOTREACHED */
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
process_yaml_sequence(yaml_parser_t *parser, yaml_event_t *event, gldns_buffer *buf)
|
||||
{
|
||||
assert(parser);
|
||||
assert(event);
|
||||
assert(buf);
|
||||
|
||||
int done = 0;
|
||||
int elements = 0;
|
||||
|
||||
if ( gldns_buffer_printf(buf, "[ ") == -1 )
|
||||
return -1;
|
||||
|
||||
while (!done)
|
||||
{
|
||||
/* Delete the event that brought us here */
|
||||
yaml_event_delete(event);
|
||||
|
||||
/* Get the next event. */
|
||||
if (!yaml_parser_parse(parser, event)) {
|
||||
report_parser_error(parser);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (event->type) {
|
||||
case YAML_SCALAR_EVENT:
|
||||
case YAML_SEQUENCE_START_EVENT:
|
||||
case YAML_MAPPING_START_EVENT:
|
||||
|
||||
if (elements)
|
||||
if (gldns_buffer_printf(buf, ", ") == -1)
|
||||
return -1;
|
||||
|
||||
if (process_yaml_value(parser, event, buf) != 0)
|
||||
return -1;
|
||||
|
||||
elements = 1;
|
||||
break;
|
||||
|
||||
case YAML_SEQUENCE_END_EVENT:
|
||||
if (gldns_buffer_printf(buf, " ]") == -1)
|
||||
return -1;
|
||||
done = 1;
|
||||
break;
|
||||
|
||||
case YAML_STREAM_START_EVENT:
|
||||
case YAML_STREAM_END_EVENT:
|
||||
case YAML_DOCUMENT_START_EVENT:
|
||||
case YAML_DOCUMENT_END_EVENT:
|
||||
case YAML_ALIAS_EVENT:
|
||||
case YAML_MAPPING_END_EVENT:
|
||||
fprintf(stderr,
|
||||
"Event error: %s. Expected YAML_MAPPING_START_EVENT, YAML_SEQUENCE_START_EVENT, YAML_SCALAR_EVENT or YAML_SEQUENCE_END_EVENT.\n",
|
||||
event_type_string(event->type));
|
||||
return -1;
|
||||
|
||||
default:
|
||||
/* NOTREACHED */
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
process_yaml_value(yaml_parser_t *parser, yaml_event_t *event, gldns_buffer *buf)
|
||||
{
|
||||
assert(parser);
|
||||
assert(event);
|
||||
assert(buf);
|
||||
|
||||
switch (event->type) {
|
||||
case YAML_SCALAR_EVENT:
|
||||
if (output_scalar(event, buf) != 0) {
|
||||
fprintf(stderr, "Value error: Error outputting scalar\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case YAML_SEQUENCE_START_EVENT:
|
||||
if (process_yaml_sequence(parser, event, buf) != 0) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case YAML_MAPPING_START_EVENT:
|
||||
if (process_yaml_mapping(parser, event, buf) != 0) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Bug: calling process_yaml_value() in the wrong context");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
output_scalar(yaml_event_t *event, gldns_buffer *buf)
|
||||
{
|
||||
const char *fmt = "%s";
|
||||
|
||||
assert(event);
|
||||
assert(buf);
|
||||
assert(event->data.scalar.length > 0);
|
||||
|
||||
if (event->data.scalar.style != YAML_PLAIN_SCALAR_STYLE)
|
||||
fmt = "\"%s\"";
|
||||
|
||||
if ( gldns_buffer_printf(buf, fmt, event->data.scalar.value) == -1 )
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void report_parser_error(yaml_parser_t *parser)
|
||||
{
|
||||
assert(parser);
|
||||
|
||||
/* Display a parser error message. */
|
||||
switch (parser->error) {
|
||||
case YAML_MEMORY_ERROR:
|
||||
fprintf(stderr, "Memory error: Not enough memory for parsing\n");
|
||||
break;
|
||||
|
||||
case YAML_READER_ERROR:
|
||||
if (parser->problem_value != -1) {
|
||||
fprintf(stderr, "Reader error: %s: #%X at %zu\n", parser->problem,
|
||||
parser->problem_value, parser->problem_offset);
|
||||
} else {
|
||||
fprintf(stderr, "Reader error: %s at %zu\n", parser->problem,
|
||||
parser->problem_offset);
|
||||
}
|
||||
break;
|
||||
|
||||
case YAML_SCANNER_ERROR:
|
||||
if (parser->context) {
|
||||
fprintf(stderr, "Scanner error: %s at line %lu, column %lu\n"
|
||||
"%s at line %lu, column %lu\n", parser->context,
|
||||
parser->context_mark.line+1, parser->context_mark.column+1,
|
||||
parser->problem, parser->problem_mark.line+1,
|
||||
parser->problem_mark.column+1);
|
||||
} else {
|
||||
fprintf(stderr, "Scanner error: %s at line %lu, column %lu\n",
|
||||
parser->problem, parser->problem_mark.line+1,
|
||||
parser->problem_mark.column+1);
|
||||
}
|
||||
break;
|
||||
|
||||
case YAML_PARSER_ERROR:
|
||||
if (parser->context) {
|
||||
fprintf(stderr, "Parser error: %s at line %lu, column %lu\n"
|
||||
"%s at line %lu, column %lu\n", parser->context,
|
||||
parser->context_mark.line+1, parser->context_mark.column+1,
|
||||
parser->problem, parser->problem_mark.line+1,
|
||||
parser->problem_mark.column+1);
|
||||
} else {
|
||||
fprintf(stderr, "Parser error: %s at line %lu, column %lu\n",
|
||||
parser->problem, parser->problem_mark.line+1,
|
||||
parser->problem_mark.column+1);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Couldn't happen. */
|
||||
fprintf(stderr, "Internal error\n");
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* TODO - improve this */
|
||||
char*
|
||||
event_type_string(yaml_event_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case YAML_STREAM_START_EVENT:
|
||||
return "YAML_STREAM_START_EVENT";
|
||||
|
||||
case YAML_STREAM_END_EVENT:
|
||||
return "YAML_STREAM_END_EVENT";
|
||||
|
||||
case YAML_DOCUMENT_START_EVENT:
|
||||
return "YAML_DOCUMENT_START_EVENT";
|
||||
|
||||
case YAML_DOCUMENT_END_EVENT:
|
||||
return "YAML_DOCUMENT_END_EVENT";
|
||||
|
||||
case YAML_ALIAS_EVENT:
|
||||
return "YAML_ALIAS_EVENT";
|
||||
|
||||
case YAML_SCALAR_EVENT:
|
||||
return "YAML_SCALAR_EVENT";
|
||||
|
||||
case YAML_SEQUENCE_START_EVENT:
|
||||
return "YAML_SEQUENCE_START_EVENT";
|
||||
|
||||
case YAML_SEQUENCE_END_EVENT:
|
||||
return "YAML_SEQUENCE_END_EVENT";
|
||||
|
||||
case YAML_MAPPING_START_EVENT:
|
||||
return "YAML_MAPPING_START_EVENT";
|
||||
|
||||
case YAML_MAPPING_END_EVENT:
|
||||
return "YAML_MAPPING_END_EVENT";
|
||||
|
||||
default:
|
||||
/* NOTREACHED */
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* USE_YAML_CONFIG */
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2017, NLNet Labs, Verisign, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of the copyright holders nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _CONVERT_YAML_TO_JSON_H
|
||||
#define _CONVERT_YAML_TO_JSON_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* read yaml-syntax data from the string and convert to json-syntax
|
||||
* yaml syntax resitrictions imposed for getdns:
|
||||
* the outer-most data structure must be a yaml mapping
|
||||
* mapping keys must be yaml scalars
|
||||
* plain scalars are output to the json string unchanged
|
||||
* non-plain scalars (quoted, double-quoted, wrapped) are output double-quoted
|
||||
* TODO Test on yaml data containing yaml tags (these are ignored at present)
|
||||
* The code has only been tested on yaml data using indentation style, so it
|
||||
* should be tested on other styles as well.
|
||||
* @param instr the string carrying data in yaml syntax
|
||||
* @return a string of data in json syntax on success
|
||||
* @return NULL if there is a yaml syntax violation
|
||||
* the outer-most structure in not a mapping
|
||||
* a mapping key is complex (a mapping or sequence)
|
||||
*/
|
||||
char * yaml_string_to_json_string(const char *instr);
|
||||
|
||||
#endif //_CONVERT_YAML_TO_JSON_H
|
Loading…
Reference in New Issue