mirror of
https://github.com/NLnetLabs/unbound.git
synced 2024-09-21 06:37:08 +00:00
Add dynamic library support
This commit is contained in:
parent
eb2283332b
commit
1762437121
26
Makefile.in
26
Makefile.in
@ -25,6 +25,7 @@ DNSTAP_SRC=@DNSTAP_SRC@
|
||||
DNSTAP_OBJ=@DNSTAP_OBJ@
|
||||
DNSCRYPT_SRC=@DNSCRYPT_SRC@
|
||||
DNSCRYPT_OBJ=@DNSCRYPT_OBJ@
|
||||
WITH_DYNLIBMODULE=@WITH_DYNLIBMODULE@
|
||||
WITH_PYTHONMODULE=@WITH_PYTHONMODULE@
|
||||
WITH_PYUNBOUND=@WITH_PYUNBOUND@
|
||||
PY_MAJOR_VERSION=@PY_MAJOR_VERSION@
|
||||
@ -87,6 +88,12 @@ LINTFLAGS+="-D__uint16_t=uint16_t" "-DEVP_PKEY_ASN1_METHOD=int" "-D_RuneLocale=i
|
||||
|
||||
INSTALL=$(SHELL) $(srcdir)/install-sh
|
||||
|
||||
DYNLIBMOD_SRC=dynlibmod/dynlibmod.c
|
||||
DYNLIBMOD_OBJ=@DYNLIBMOD_OBJ@
|
||||
DYNLIBMOD_HEADER=@DYNLIBMOD_HEADER@
|
||||
DYNLIBMOD_EXTRALIBS=@DYNLIBMOD_EXTRALIBS@
|
||||
|
||||
|
||||
#pythonmod.c is not here, it is mentioned by itself in its own rules,
|
||||
#makedepend fails on missing interface.h otherwise.
|
||||
PYTHONMOD_SRC=pythonmod/pythonmod_utils.c
|
||||
@ -139,7 +146,7 @@ autotrust.lo val_anchor.lo \
|
||||
validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
|
||||
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo redis.lo authzone.lo \
|
||||
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
|
||||
$(IPSECMOD_OBJ) $(IPSET_OBJ) respip.lo
|
||||
$(IPSECMOD_OBJ) $(IPSET_OBJ) $(DYNLIBMOD_OBJ) respip.lo
|
||||
COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
|
||||
outside_network.lo
|
||||
COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo
|
||||
@ -326,7 +333,7 @@ libunbound.la: $(LIBUNBOUND_OBJ_LINK)
|
||||
$(LINK_LIB) $(UBSYMS) -o $@ $(LIBUNBOUND_OBJ_LINK) -rpath $(libdir) $(SSLLIB) $(LIBS)
|
||||
|
||||
unbound$(EXEEXT): $(DAEMON_OBJ_LINK) libunbound.la
|
||||
$(LINK) -o $@ $(DAEMON_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS)
|
||||
$(LINK) -o $@ $(DAEMON_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS)
|
||||
|
||||
unbound-checkconf$(EXEEXT): $(CHECKCONF_OBJ_LINK) libunbound.la
|
||||
$(LINK) -o $@ $(CHECKCONF_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS)
|
||||
@ -453,6 +460,7 @@ clean:
|
||||
rm -f unbound$(EXEEXT) unbound-checkconf$(EXEEXT) unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup libunbound.la unbound.h
|
||||
rm -f $(ALL_SRC:.c=.lint)
|
||||
rm -f _unbound.la libunbound/python/libunbound_wrap.c libunbound/python/unbound.py pythonmod/interface.h pythonmod/unboundmodule.py
|
||||
rm -f libunbound.a
|
||||
rm -rf autom4te.cache .libs build doc/html doc/xml
|
||||
|
||||
realclean: clean
|
||||
@ -622,6 +630,7 @@ depend:
|
||||
-e 's?$$(srcdir)/pythonmod/pythonmod.h?$$(PYTHONMOD_HEADER)?g' \
|
||||
-e 's?$$(srcdir)/edns-subnet/subnetmod.h $$(srcdir)/edns-subnet/subnet-whitelist.h $$(srcdir)/edns-subnet/edns-subnet.h $$(srcdir)/edns-subnet/addrtree.h?$$(SUBNET_HEADER)?g' \
|
||||
-e 's?$$(srcdir)/ipsecmod/ipsecmod.h $$(srcdir)/ipsecmod/ipsecmod-whitelist.h?$$(IPSECMOD_HEADER)?g' \
|
||||
-e 's?$$(srcdir)/dynlibmod/dynlibmod.h?$$(DYNLIBMOD_HEADER)?g' \
|
||||
-e 's!\(.*\)\.o[ :]*!\1.lo \1.o: !g' \
|
||||
> $(DEPEND_TMP)
|
||||
cp $(DEPEND_TARGET) $(DEPEND_TMP2)
|
||||
@ -783,7 +792,7 @@ modstack.lo modstack.o: $(srcdir)/services/modstack.c config.h $(srcdir)/service
|
||||
$(srcdir)/services/view.h $(PYTHONMOD_HEADER) $(srcdir)/ipsecmod/ipsecmod.h \
|
||||
$(srcdir)/edns-subnet/subnetmod.h $(srcdir)/util/alloc.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/edns-subnet/addrtree.h $(srcdir)/edns-subnet/edns-subnet.h \
|
||||
$(srcdir)/ipset/ipset.h
|
||||
$(srcdir)/ipset/ipset.h $(srcdir)/dynlibmod/dynlibmod.h
|
||||
view.lo view.o: $(srcdir)/services/view.c config.h $(srcdir)/services/view.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \
|
||||
@ -865,7 +874,8 @@ fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/
|
||||
$(srcdir)/libunbound/unbound-event.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/respip/respip.h $(PYTHONMOD_HEADER) \
|
||||
$(srcdir)/ipsecmod/ipsecmod.h $(srcdir)/edns-subnet/subnetmod.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/edns-subnet/addrtree.h $(srcdir)/edns-subnet/edns-subnet.h $(srcdir)/ipset/ipset.h
|
||||
$(srcdir)/edns-subnet/addrtree.h $(srcdir)/edns-subnet/edns-subnet.h $(srcdir)/ipset/ipset.h \
|
||||
$(srcdir)/dynlibmod/dynlibmod.h
|
||||
locks.lo locks.o: $(srcdir)/util/locks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
|
||||
log.lo log.o: $(srcdir)/util/log.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/sldns/sbuffer.h
|
||||
mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h
|
||||
@ -1072,6 +1082,14 @@ dnstap.lo dnstap.o: $(srcdir)/dnstap/dnstap.c config.h $(srcdir)/sldns/sbuffer.
|
||||
dnstap/dnstap.pb-c.h
|
||||
dnstap.pb-c.lo dnstap.pb-c.o: dnstap/dnstap.pb-c.c dnstap/dnstap.pb-c.h \
|
||||
|
||||
dynlibmod.lo dynlibmod.o: $(srcdir)/dynlibmod/dynlibmod.c config.h $(srcdir)/dynlibmod/dynlibmod.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/rbtree.h\
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/services/cache/dns.h $(srcdir)/sldns/wire2str.h
|
||||
ipsecmod.lo ipsecmod.o: $(srcdir)/ipsecmod/ipsecmod.c config.h $(srcdir)/ipsecmod/ipsecmod.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
|
@ -836,6 +836,9 @@
|
||||
/* Define if you want Python module. */
|
||||
#undef WITH_PYTHONMODULE
|
||||
|
||||
/* Define if you want dynamic library module. */
|
||||
#undef WITH_DYNLIBMODULE
|
||||
|
||||
/* Define if you want PyUnbound. */
|
||||
#undef WITH_PYUNBOUND
|
||||
|
||||
|
35
configure
vendored
35
configure
vendored
@ -697,6 +697,10 @@ PYTHON_LDFLAGS
|
||||
PYTHON_CPPFLAGS
|
||||
PYTHON
|
||||
PYTHON_VERSION
|
||||
DYNLIBMOD_EXTRALIBS
|
||||
DYNLIBMOD_HEADER
|
||||
DYNLIBMOD_OBJ
|
||||
WITH_DYNLIBMODULE
|
||||
PTHREAD_CFLAGS_ONLY
|
||||
PTHREAD_CFLAGS
|
||||
PTHREAD_LIBS
|
||||
@ -851,6 +855,7 @@ enable_alloc_nonregional
|
||||
with_pthreads
|
||||
with_solaris_threads
|
||||
with_syslog_facility
|
||||
with_dynlibmodule
|
||||
with_pyunbound
|
||||
with_pythonmodule
|
||||
enable_swig_version_check
|
||||
@ -1607,6 +1612,8 @@ Optional Packages:
|
||||
--with-solaris-threads use solaris native thread library.
|
||||
--with-syslog-facility=LOCAL0 - LOCAL7
|
||||
set SYSLOG_FACILITY, default DAEMON
|
||||
--with-dynlibmodule build dynamic library module, or
|
||||
--without-dynlibmodule to disable it. (default=no)
|
||||
--with-pyunbound build PyUnbound, or --without-pyunbound to skip it.
|
||||
(default=no)
|
||||
--with-pythonmodule build Python module, or --without-pythonmodule to
|
||||
@ -17123,6 +17130,34 @@ cat >>confdefs.h <<_ACEOF
|
||||
_ACEOF
|
||||
|
||||
|
||||
# Check for dynamic library module
|
||||
|
||||
# Check whether --with-dynlibmodule was given.
|
||||
if test "${with_dynlibmodule+set}" = set; then :
|
||||
withval=$with_dynlibmodule;
|
||||
else
|
||||
withval="no"
|
||||
fi
|
||||
|
||||
|
||||
if test x_$withval != x_no; then
|
||||
|
||||
$as_echo "#define WITH_DYNLIBMODULE 1" >>confdefs.h
|
||||
|
||||
WITH_DYNLIBMODULE=yes
|
||||
|
||||
DYNLIBMOD_OBJ="dynlibmod.lo"
|
||||
|
||||
DYNLIBMOD_HEADER='$(srcdir)/dynlibmod/dynlibmod.h'
|
||||
|
||||
if test $on_mingw = "no"; then
|
||||
DYNLIBMOD_EXTRALIBS="-ldl -export-dynamic"
|
||||
else
|
||||
DYNLIBMOD_EXTRALIBS="-Wl,--export-all-symbols,--out-implib,libunbound.a"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# Check for PyUnbound
|
||||
|
||||
# Check whether --with-pyunbound was given.
|
||||
|
22
configure.ac
22
configure.ac
@ -616,6 +616,28 @@ case "${UNBOUND_SYSLOG_FACILITY}" in
|
||||
esac
|
||||
AC_DEFINE_UNQUOTED(UB_SYSLOG_FACILITY,${UNBOUND_SYSLOG_FACILITY},[the SYSLOG_FACILITY to use, default LOG_DAEMON])
|
||||
|
||||
# Check for dynamic library module
|
||||
AC_ARG_WITH(dynlibmodule,
|
||||
AC_HELP_STRING([--with-dynlibmodule],
|
||||
[build dynamic library module, or --without-dynlibmodule to disable it. (default=no)]),
|
||||
[], [ withval="no" ])
|
||||
|
||||
if test x_$withval != x_no; then
|
||||
AC_DEFINE(WITH_DYNLIBMODULE, 1, [Define if you want dynlib module.])
|
||||
WITH_DYNLIBMODULE=yes
|
||||
AC_SUBST(WITH_DYNLIBMODULE)
|
||||
DYNLIBMOD_OBJ="dynlibmod.lo"
|
||||
AC_SUBST(DYNLIBMOD_OBJ)
|
||||
DYNLIBMOD_HEADER='$(srcdir)/dynlibmod/dynlibmod.h'
|
||||
AC_SUBST(DYNLIBMOD_HEADER)
|
||||
if test $on_mingw = "no"; then
|
||||
DYNLIBMOD_EXTRALIBS="-ldl -export-dynamic"
|
||||
else
|
||||
DYNLIBMOD_EXTRALIBS="-Wl,--export-all-symbols,--out-implib,libunbound.a"
|
||||
fi
|
||||
AC_SUBST(DYNLIBMOD_EXTRALIBS)
|
||||
fi
|
||||
|
||||
# Check for PyUnbound
|
||||
AC_ARG_WITH(pyunbound,
|
||||
AC_HELP_STRING([--with-pyunbound],
|
||||
|
236
dynlibmod/dynlibmod.c
Normal file
236
dynlibmod/dynlibmod.c
Normal file
@ -0,0 +1,236 @@
|
||||
#include "config.h"
|
||||
#include "util/module.h"
|
||||
#include "util/config_file.h"
|
||||
#include "dynlibmod/dynlibmod.h"
|
||||
|
||||
#if HAVE_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#define __DYNSYM FARPROC
|
||||
#define __LOADSYM GetProcAddress
|
||||
void log_dlerror() {
|
||||
DWORD dwLastError = GetLastError();
|
||||
LPSTR MessageBuffer;
|
||||
DWORD dwBufferLength;
|
||||
DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM ;
|
||||
if(dwBufferLength = FormatMessageA(
|
||||
dwFormatFlags,
|
||||
NULL, // module to get message from (NULL == system)
|
||||
dwLastError,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
|
||||
(LPSTR) &MessageBuffer,
|
||||
0,
|
||||
NULL
|
||||
))
|
||||
{
|
||||
DWORD dwBytesWritten;
|
||||
|
||||
//
|
||||
// Output message string on stderr.
|
||||
//
|
||||
log_info("dynlibmod: %s (%ld)", MessageBuffer, dwLastError);
|
||||
//WriteFile(
|
||||
// GetStdHandle(STD_ERROR_HANDLE),
|
||||
// MessageBuffer,
|
||||
// dwBufferLength,
|
||||
// &dwBytesWritten,
|
||||
// NULL
|
||||
// );
|
||||
|
||||
//
|
||||
// Free the buffer allocated by the system.
|
||||
//
|
||||
LocalFree(MessageBuffer);
|
||||
}
|
||||
|
||||
}
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#define __DYNSYM void*
|
||||
#define __LOADSYM dlsym
|
||||
void log_dlerror() {
|
||||
log_err("dynlibmod: %s", dlerror());
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Global state for the module.
|
||||
*/
|
||||
|
||||
typedef int (*func_init_t)(int, struct config_file*);
|
||||
typedef int (*func_deinit_t)(int);
|
||||
typedef int (*func_operate_t)(int, enum module_ev event, struct module_qstate* qstate, void*);
|
||||
typedef int (*func_inform_t)(int, struct module_qstate* qstate, struct module_qstate* super, void*);
|
||||
struct dynlibmod_env {
|
||||
|
||||
/** Dynamic library filename. */
|
||||
const char* fname;
|
||||
|
||||
/** Module init function */
|
||||
func_init_t func_init;
|
||||
/** Module deinit function */
|
||||
func_deinit_t func_deinit;
|
||||
/** Module operate function */
|
||||
func_operate_t func_operate;
|
||||
/** Module super_inform function */
|
||||
func_inform_t func_inform;
|
||||
|
||||
/** Module qstate. */
|
||||
struct module_qstate* qstate;
|
||||
};
|
||||
|
||||
struct dynlibmod_qstate {
|
||||
|
||||
/** Module per query data. */
|
||||
void* data;
|
||||
};
|
||||
|
||||
/** dynlib module init */
|
||||
int dynlibmod_init(struct module_env* env, int id) {
|
||||
struct dynlibmod_env* de = (struct dynlibmod_env*)calloc(1, sizeof(struct dynlibmod_env));
|
||||
if (!de)
|
||||
{
|
||||
log_err("dynlibmod: malloc failure");
|
||||
return 0;
|
||||
}
|
||||
|
||||
env->modinfo[id] = (void*) de;
|
||||
|
||||
de->fname = env->cfg->dynlib_file;
|
||||
if (de->fname == NULL || de->fname[0] == 0) {
|
||||
log_err("dynlibmod: no dynamic library given.");
|
||||
return 0;
|
||||
}
|
||||
log_info("Trying to load library %s", de->fname);
|
||||
#ifndef HAVE_WINDOWS_H
|
||||
void* dynamic_library = dlopen(de->fname, RTLD_LAZY | RTLD_GLOBAL);
|
||||
#else
|
||||
HMODULE dynamic_library = LoadLibrary(de->fname);
|
||||
#endif
|
||||
if (dynamic_library == NULL) {
|
||||
log_dlerror();
|
||||
log_err("dynlibmod: unable to load dynamic library.");
|
||||
return 0;
|
||||
} else {
|
||||
__DYNSYM initializer = __LOADSYM(dynamic_library,"init");
|
||||
if (initializer == NULL) {
|
||||
log_err("dynlibmod: unable to load init procedure from dynamic library.");
|
||||
#ifndef HAVE_WINDOWS_H
|
||||
log_err("dynlibmod: %s", dlerror());
|
||||
#endif
|
||||
return 0;
|
||||
} else {
|
||||
de->func_init = (func_init_t) initializer;
|
||||
}
|
||||
__DYNSYM deinitializer = __LOADSYM(dynamic_library,"deinit");
|
||||
if (deinitializer == NULL) {
|
||||
log_err("dynlibmod: unable to load deinit procedure from dynamic library.");
|
||||
#ifndef HAVE_WINDOWS_H
|
||||
log_err("dynlibmod: %s", dlerror());
|
||||
#endif
|
||||
return 0;
|
||||
} else {
|
||||
de->func_deinit = (func_deinit_t) deinitializer;
|
||||
}
|
||||
__DYNSYM operate = __LOADSYM(dynamic_library,"operate");
|
||||
if (operate == NULL) {
|
||||
log_err("dynlibmod: unable to load operate procedure from dynamic library.");
|
||||
#ifndef HAVE_WINDOWS_H
|
||||
log_err("dynlibmod: %s", dlerror());
|
||||
#endif
|
||||
return 0;
|
||||
} else {
|
||||
de->func_operate = (func_operate_t) operate;
|
||||
}
|
||||
__DYNSYM inform = __LOADSYM(dynamic_library,"inform_super");
|
||||
if (inform == NULL) {
|
||||
log_err("dynlibmod: unable to load inform_super procedure from dynamic library.");
|
||||
#ifndef HAVE_WINDOWS_H
|
||||
log_err("dynlibmod: %s", dlerror());
|
||||
#endif
|
||||
return 0;
|
||||
} else {
|
||||
de->func_inform = (func_inform_t) inform;
|
||||
}
|
||||
}
|
||||
de->func_init(id, env->cfg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** dynlib module deinit */
|
||||
void dynlibmod_deinit(struct module_env* env, int id) {
|
||||
struct dynlibmod_env* de = env->modinfo[id];
|
||||
if(de == NULL)
|
||||
return;
|
||||
de->func_deinit(id);
|
||||
de->fname = NULL;
|
||||
free(de);
|
||||
}
|
||||
|
||||
/** dynlib module operate on a query */
|
||||
void dynlibmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
int id, struct outbound_entry* outbound) {
|
||||
struct dynlibmod_env* de = qstate->env->modinfo[id];
|
||||
struct dynlibmod_qstate* dq = (struct dynlibmod_qstate*)qstate->minfo[id];
|
||||
|
||||
void * data = dq == NULL ? NULL : dq->data;
|
||||
int ret = de->func_operate(id, event, qstate, data);
|
||||
if (ret != 1) {
|
||||
log_err("dynlibmod: dynamic library returned bad code from operate %d.", ret);
|
||||
qstate->ext_state[id] = module_error;
|
||||
}
|
||||
}
|
||||
|
||||
/** dynlib module */
|
||||
void dynlibmod_inform_super(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* super) {
|
||||
struct dynlibmod_env* de = qstate->env->modinfo[id];
|
||||
struct dynlibmod_qstate* dq = (struct dynlibmod_qstate*)qstate->minfo[id];
|
||||
|
||||
void * data = dq == NULL ? NULL : dq->data;
|
||||
int ret = de->func_inform(id, qstate, super, data);
|
||||
if (ret != 1) {
|
||||
log_err("dynlibmod: dynamic library returned bad code from inform_super %d.", ret);
|
||||
qstate->ext_state[id] = module_error;
|
||||
}
|
||||
}
|
||||
|
||||
/** dynlib module cleanup query state */
|
||||
void dynlibmod_clear(struct module_qstate* qstate, int id) {
|
||||
struct dynlibmod_qstate* dq;
|
||||
if (qstate == NULL)
|
||||
return;
|
||||
|
||||
dq = (struct dynlibmod_qstate*)qstate->minfo[id];
|
||||
verbose(VERB_ALGO, "dynlibmod: clear, id: %d, dq:%p", id, dq);
|
||||
if(dq != NULL) {
|
||||
/* Free qstate */
|
||||
free(dq);
|
||||
}
|
||||
|
||||
qstate->minfo[id] = NULL;
|
||||
}
|
||||
|
||||
/** dynlib module alloc size routine */
|
||||
size_t dynlibmod_get_mem(struct module_env* env, int id) {
|
||||
struct dynlibmod_env* de = (struct dynlibmod_env*)env->modinfo[id];
|
||||
verbose(VERB_ALGO, "dynlibmod: get_mem, id: %d, de:%p", id, de);
|
||||
if(!de)
|
||||
return 0;
|
||||
return sizeof(*de);
|
||||
}
|
||||
|
||||
/**
|
||||
* The module function block
|
||||
*/
|
||||
static struct module_func_block dynlibmod_block = {
|
||||
"dynlib",
|
||||
&dynlibmod_init, &dynlibmod_deinit, &dynlibmod_operate, &dynlibmod_inform_super,
|
||||
&dynlibmod_clear, &dynlibmod_get_mem
|
||||
};
|
||||
|
||||
struct module_func_block* dynlibmod_get_funcblock(void)
|
||||
{
|
||||
return &dynlibmod_block;
|
||||
}
|
71
dynlibmod/dynlibmod.h
Normal file
71
dynlibmod/dynlibmod.h
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* dynlibmod.h: module header file
|
||||
*
|
||||
* Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
|
||||
* Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* 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 name of the organization 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 THE REGENTS OR CONTRIBUTORS 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.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Dynamic loading module for unbound. Loads dynamic library.
|
||||
*/
|
||||
#ifndef DYNLIBMOD_H
|
||||
#define DYNLIBMOD_H
|
||||
#include "util/module.h"
|
||||
#include "services/outbound_list.h"
|
||||
|
||||
/**
|
||||
* Get the module function block.
|
||||
* @return: function block with function pointers to module methods.
|
||||
*/
|
||||
struct module_func_block* dynlibmod_get_funcblock(void);
|
||||
|
||||
/** dynlib module init */
|
||||
int dynlibmod_init(struct module_env* env, int id);
|
||||
|
||||
/** dynlib module deinit */
|
||||
void dynlibmod_deinit(struct module_env* env, int id);
|
||||
|
||||
/** dynlib module operate on a query */
|
||||
void dynlibmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
int id, struct outbound_entry* outbound);
|
||||
|
||||
/** dynlib module */
|
||||
void dynlibmod_inform_super(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* super);
|
||||
|
||||
/** dynlib module cleanup query state */
|
||||
void dynlibmod_clear(struct module_qstate* qstate, int id);
|
||||
|
||||
/** dynlib module alloc size routine */
|
||||
size_t dynlibmod_get_mem(struct module_env* env, int id);
|
||||
|
||||
#endif /* DYNLIBMOD_H */
|
45
dynlibmod/examples/helloworld.c
Normal file
45
dynlibmod/examples/helloworld.c
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This is an example to show how dynamic libraries can be made to work with
|
||||
* unbound. To build a .so file simply run:
|
||||
* gcc -I../.. -shared -Wall -Werror -fpic -o helloworld.so helloworld.c
|
||||
* And to build for windows, first make unbound with the --with-dynlibmod
|
||||
* switch, then use this command:
|
||||
* x86_64-w64-mingw32-gcc -m64 -I../.. -shared -Wall -Werror -fpic -o helloworld.dll helloworld.c -L../.. -l:libunbound.a
|
||||
* to cross-compile a 64-bit Windows DLL.
|
||||
*/
|
||||
|
||||
#include "../../config.h"
|
||||
#include "../../util/module.h"
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
#define EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define EXPORT
|
||||
#endif
|
||||
|
||||
EXPORT int init(int id, struct config_file* cfg) {
|
||||
log_info("Hello world from init");
|
||||
return 1;
|
||||
}
|
||||
|
||||
EXPORT int deinit(int id) {
|
||||
log_info("Hello world from deinit");
|
||||
return 1;
|
||||
}
|
||||
|
||||
EXPORT int operate(int id, enum module_ev event, struct module_qstate* qstate, void* data) {
|
||||
log_info("Hello world from operate");
|
||||
if (event == module_event_new || event == module_event_pass) {
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
} else if (event == module_event_moddone) {
|
||||
qstate->ext_state[id] = module_finished;
|
||||
} else {
|
||||
qstate->ext_state[id] = module_error;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
EXPORT int inform_super(int id, struct module_qstate* qstate, struct module_qstate* super, void* data) {
|
||||
log_info("Hello world from inform_super");
|
||||
return 1;
|
||||
}
|
@ -51,6 +51,9 @@
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
#include "pythonmod/pythonmod.h"
|
||||
#endif
|
||||
#ifdef WITH_DYNLIBMODULE
|
||||
#include "dynlibmod/dynlibmod.h"
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
#include "cachedb/cachedb.h"
|
||||
#endif
|
||||
@ -140,6 +143,9 @@ module_list_avail(void)
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
"python",
|
||||
#endif
|
||||
#ifdef WITH_DYNLIBMODULE
|
||||
"dynlib",
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
"cachedb",
|
||||
#endif
|
||||
@ -171,6 +177,9 @@ module_funcs_avail(void)
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
&pythonmod_get_funcblock,
|
||||
#endif
|
||||
#ifdef WITH_DYNLIBMODULE
|
||||
&dynlibmod_get_funcblock,
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
&cachedb_get_funcblock,
|
||||
#endif
|
||||
|
@ -264,6 +264,7 @@ config_create(void)
|
||||
cfg->unblock_lan_zones = 0;
|
||||
cfg->insecure_lan_zones = 0;
|
||||
cfg->python_script = NULL;
|
||||
cfg->dynlib_file = NULL;
|
||||
cfg->remote_control_enable = 0;
|
||||
cfg->control_ifs.first = NULL;
|
||||
cfg->control_ifs.last = NULL;
|
||||
@ -610,6 +611,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
||||
else S_STR("control-cert-file:", control_cert_file)
|
||||
else S_STR("module-config:", module_conf)
|
||||
else S_STRLIST("python-script:", python_script)
|
||||
else S_STR("dynlib-file:", dynlib_file)
|
||||
else S_YNO("disable-dnssec-lame-check:", disable_dnssec_lame_check)
|
||||
#ifdef CLIENT_SUBNET
|
||||
/* Can't set max subnet prefix here, since that value is used when
|
||||
@ -1062,6 +1064,7 @@ config_get_option(struct config_file* cfg, const char* opt,
|
||||
else O_YNO(opt, "insecure-lan-zones", insecure_lan_zones)
|
||||
else O_DEC(opt, "max-udp-size", max_udp_size)
|
||||
else O_LST(opt, "python-script", python_script)
|
||||
else O_STR(opt, "dynlib-file", dynlib_file)
|
||||
else O_YNO(opt, "disable-dnssec-lame-check", disable_dnssec_lame_check)
|
||||
else O_DEC(opt, "ip-ratelimit", ip_ratelimit)
|
||||
else O_DEC(opt, "ratelimit", ratelimit)
|
||||
@ -1398,6 +1401,7 @@ config_delete(struct config_file* cfg)
|
||||
free(cfg->version);
|
||||
free(cfg->module_conf);
|
||||
free(cfg->outgoing_avail_ports);
|
||||
free(cfg->dynlib_file);
|
||||
config_delstrlist(cfg->caps_whitelist);
|
||||
config_delstrlist(cfg->private_address);
|
||||
config_delstrlist(cfg->private_domain);
|
||||
|
@ -439,6 +439,9 @@ struct config_file {
|
||||
/** Python script file */
|
||||
struct config_strlist* python_script;
|
||||
|
||||
/** Dynamic library file */
|
||||
char* dynlib_file;
|
||||
|
||||
/** Use systemd socket activation. */
|
||||
int use_systemd;
|
||||
|
||||
|
@ -404,6 +404,8 @@ control-key-file{COLON} { YDVAR(1, VAR_CONTROL_KEY_FILE) }
|
||||
control-cert-file{COLON} { YDVAR(1, VAR_CONTROL_CERT_FILE) }
|
||||
python-script{COLON} { YDVAR(1, VAR_PYTHON_SCRIPT) }
|
||||
python{COLON} { YDVAR(0, VAR_PYTHON) }
|
||||
dynlib-file{COLON} { YDVAR(1, VAR_DYNLIB_FILE) }
|
||||
dynlib{COLON} { YDVAR(0, VAR_DYNLIB) }
|
||||
domain-insecure{COLON} { YDVAR(1, VAR_DOMAIN_INSECURE) }
|
||||
minimal-responses{COLON} { YDVAR(1, VAR_MINIMAL_RESPONSES) }
|
||||
rrset-roundrobin{COLON} { YDVAR(1, VAR_RRSET_ROUNDROBIN) }
|
||||
|
@ -168,6 +168,7 @@ extern struct config_parser_state* cfg_parser;
|
||||
%token VAR_STREAM_WAIT_SIZE VAR_TLS_CIPHERS VAR_TLS_CIPHERSUITES
|
||||
%token VAR_TLS_SESSION_TICKET_KEYS
|
||||
%token VAR_IPSET VAR_IPSET_NAME_V4 VAR_IPSET_NAME_V6
|
||||
%token VAR_DYNLIB VAR_DYNLIB_FILE
|
||||
|
||||
%%
|
||||
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||||
@ -175,7 +176,7 @@ toplevelvar: serverstart contents_server | stubstart contents_stub |
|
||||
forwardstart contents_forward | pythonstart contents_py |
|
||||
rcstart contents_rc | dtstart contents_dt | viewstart contents_view |
|
||||
dnscstart contents_dnsc | cachedbstart contents_cachedb |
|
||||
ipsetstart contents_ipset | authstart contents_auth
|
||||
ipsetstart contents_ipset | authstart contents_auth | dynlibstart contents_dl
|
||||
;
|
||||
|
||||
/* server: declaration */
|
||||
@ -2741,6 +2742,21 @@ py_script: VAR_PYTHON_SCRIPT STRING_ARG
|
||||
if(!cfg_strlist_append_ex(&cfg_parser->cfg->python_script, $2))
|
||||
yyerror("out of memory");
|
||||
}
|
||||
dynlibstart: VAR_DYNLIB
|
||||
{
|
||||
OUTYY(("\nP(dynlib:)\n"));
|
||||
}
|
||||
;
|
||||
contents_dl: contents_dl content_dl
|
||||
| ;
|
||||
content_dl: dl_file
|
||||
;
|
||||
dl_file: VAR_DYNLIB_FILE STRING_ARG
|
||||
{
|
||||
OUTYY(("P(dynlib-file:%s)\n", $2));
|
||||
free(cfg_parser->cfg->dynlib_file);
|
||||
cfg_parser->cfg->dynlib_file = $2;
|
||||
}
|
||||
server_disable_dnssec_lame_check: VAR_DISABLE_DNSSEC_LAME_CHECK STRING_ARG
|
||||
{
|
||||
OUTYY(("P(disable_dnssec_lame_check:%s)\n", $2));
|
||||
|
@ -81,6 +81,9 @@
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
#include "pythonmod/pythonmod.h"
|
||||
#endif
|
||||
#ifdef WITH_DYNLIBMODULE
|
||||
#include "dynlibmod/dynlibmod.h"
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
#include "cachedb/cachedb.h"
|
||||
#endif
|
||||
@ -379,6 +382,9 @@ fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id))
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
else if(fptr == &pythonmod_init) return 1;
|
||||
#endif
|
||||
#ifdef WITH_DYNLIBMODULE
|
||||
else if(fptr == &dynlibmod_init) return 1;
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
else if(fptr == &cachedb_init) return 1;
|
||||
#endif
|
||||
@ -404,6 +410,9 @@ fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id))
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
else if(fptr == &pythonmod_deinit) return 1;
|
||||
#endif
|
||||
#ifdef WITH_DYNLIBMODULE
|
||||
else if(fptr == &dynlibmod_deinit) return 1;
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
else if(fptr == &cachedb_deinit) return 1;
|
||||
#endif
|
||||
@ -430,6 +439,9 @@ fptr_whitelist_mod_operate(void (*fptr)(struct module_qstate* qstate,
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
else if(fptr == &pythonmod_operate) return 1;
|
||||
#endif
|
||||
#ifdef WITH_DYNLIBMODULE
|
||||
else if(fptr == &dynlibmod_operate) return 1;
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
else if(fptr == &cachedb_operate) return 1;
|
||||
#endif
|
||||
@ -456,6 +468,9 @@ fptr_whitelist_mod_inform_super(void (*fptr)(
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
else if(fptr == &pythonmod_inform_super) return 1;
|
||||
#endif
|
||||
#ifdef WITH_DYNLIBMODULE
|
||||
else if(fptr == &dynlibmod_inform_super) return 1;
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
else if(fptr == &cachedb_inform_super) return 1;
|
||||
#endif
|
||||
@ -482,6 +497,9 @@ fptr_whitelist_mod_clear(void (*fptr)(struct module_qstate* qstate,
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
else if(fptr == &pythonmod_clear) return 1;
|
||||
#endif
|
||||
#ifdef WITH_DYNLIBMODULE
|
||||
else if(fptr == &dynlibmod_clear) return 1;
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
else if(fptr == &cachedb_clear) return 1;
|
||||
#endif
|
||||
@ -507,6 +525,9 @@ fptr_whitelist_mod_get_mem(size_t (*fptr)(struct module_env* env, int id))
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
else if(fptr == &pythonmod_get_mem) return 1;
|
||||
#endif
|
||||
#ifdef WITH_DYNLIBMODULE
|
||||
else if(fptr == &dynlibmod_get_mem) return 1;
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
else if(fptr == &cachedb_get_mem) return 1;
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user