mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-01-05 14:29:37 -05:00
Merge branch 'dev/pythonmod-multi-instance/v1.9.0' into dev/all-merged/master
This commit is contained in:
commit
efb3697332
7 changed files with 97 additions and 38 deletions
|
|
@ -1752,7 +1752,8 @@ clause gives the settings for the \fIpython\fR(1) script module. This module
|
|||
acts like the iterator and validator modules do, on queries and answers.
|
||||
To enable the script module it has to be compiled into the daemon,
|
||||
and the word "python" has to be put in the \fBmodule\-config:\fR option
|
||||
(usually first, or between the validator and iterator).
|
||||
(usually first, or between the validator and iterator). Multiple instances of
|
||||
the python module are supported by adding the word "python" more than once.
|
||||
.LP
|
||||
If the \fBchroot:\fR option is enabled, you should make sure Python's
|
||||
library directory structure is bind mounted in the new root environment, see
|
||||
|
|
@ -1761,7 +1762,8 @@ absolute path relative to the new root, or as a relative path to the working
|
|||
directory.
|
||||
.TP
|
||||
.B python\-script: \fI<python file>\fR
|
||||
The script file to load.
|
||||
The script file to load. Repeat this option for every python module instance
|
||||
added to the \fBmodule\-config:\fR option.
|
||||
.SS "DNS64 Module Options"
|
||||
.LP
|
||||
The dns64 module must be configured in the \fBmodule\-config:\fR "dns64
|
||||
|
|
|
|||
|
|
@ -1026,7 +1026,7 @@ struct config_file {
|
|||
char* control_key_file;
|
||||
char* control_cert_file;
|
||||
int do_daemonize;
|
||||
char* python_script;
|
||||
struct config_strlist* python_script;
|
||||
};
|
||||
|
||||
/* ************************************************************************************ *
|
||||
|
|
|
|||
|
|
@ -64,6 +64,15 @@ typedef struct PyThreadState PyThreadState;
|
|||
typedef void* PyGILState_STATE;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* counter for python module instances
|
||||
* incremented by pythonmod_init(...)
|
||||
*/
|
||||
int py_mod_count = 0;
|
||||
|
||||
/** Python main thread */
|
||||
PyThreadState* mainthr;
|
||||
|
||||
/**
|
||||
* Global state for the module.
|
||||
*/
|
||||
|
|
@ -72,8 +81,6 @@ struct pythonmod_env {
|
|||
/** Python script filename. */
|
||||
const char* fname;
|
||||
|
||||
/** Python main thread */
|
||||
PyThreadState* mainthr;
|
||||
/** Python module. */
|
||||
PyObject* module;
|
||||
|
||||
|
|
@ -242,11 +249,15 @@ cleanup:
|
|||
|
||||
int pythonmod_init(struct module_env* env, int id)
|
||||
{
|
||||
int py_mod_idx = py_mod_count++;
|
||||
|
||||
/* Initialize module */
|
||||
FILE* script_py = NULL;
|
||||
PyObject* py_init_arg, *res;
|
||||
PyGILState_STATE gil;
|
||||
int init_standard = 1;
|
||||
int init_standard = 1, i = 0;
|
||||
|
||||
struct config_strlist* cfg_item = env->cfg->python_script;
|
||||
|
||||
struct pythonmod_env* pe = (struct pythonmod_env*)calloc(1, sizeof(struct pythonmod_env));
|
||||
if (!pe)
|
||||
|
|
@ -258,14 +269,21 @@ int pythonmod_init(struct module_env* env, int id)
|
|||
env->modinfo[id] = (void*) pe;
|
||||
|
||||
/* Initialize module */
|
||||
pe->fname = env->cfg->python_script;
|
||||
pe->fname=NULL; i = 0;
|
||||
while (cfg_item!=NULL) {
|
||||
if (py_mod_idx==i++) {
|
||||
pe->fname=cfg_item->str;
|
||||
break;
|
||||
}
|
||||
cfg_item = cfg_item->next;
|
||||
}
|
||||
if(pe->fname==NULL || pe->fname[0]==0) {
|
||||
log_err("pythonmod: no script given.");
|
||||
log_err("pythonmod[%d]: no script given.", py_mod_idx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initialize Python libraries */
|
||||
if (!Py_IsInitialized())
|
||||
if (py_mod_count==1 && !Py_IsInitialized())
|
||||
{
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
wchar_t progname[8];
|
||||
|
|
@ -281,29 +299,31 @@ int pythonmod_init(struct module_env* env, int id)
|
|||
Py_Initialize();
|
||||
PyEval_InitThreads();
|
||||
SWIG_init();
|
||||
pe->mainthr = PyEval_SaveThread();
|
||||
mainthr = PyEval_SaveThread();
|
||||
}
|
||||
|
||||
gil = PyGILState_Ensure();
|
||||
|
||||
/* Initialize Python */
|
||||
PyRun_SimpleString("import sys \n");
|
||||
PyRun_SimpleString("sys.path.append('.') \n");
|
||||
if(env->cfg->directory && env->cfg->directory[0]) {
|
||||
char wdir[1524];
|
||||
snprintf(wdir, sizeof(wdir), "sys.path.append('%s') \n",
|
||||
env->cfg->directory);
|
||||
PyRun_SimpleString(wdir);
|
||||
}
|
||||
PyRun_SimpleString("sys.path.append('"RUN_DIR"') \n");
|
||||
PyRun_SimpleString("sys.path.append('"SHARE_DIR"') \n");
|
||||
PyRun_SimpleString("import distutils.sysconfig \n");
|
||||
PyRun_SimpleString("sys.path.append(distutils.sysconfig.get_python_lib(1,0)) \n");
|
||||
if (PyRun_SimpleString("from unboundmodule import *\n") < 0)
|
||||
{
|
||||
log_err("pythonmod: cannot initialize core module: unboundmodule.py");
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
if (py_mod_count==1) {
|
||||
/* Initialize Python */
|
||||
PyRun_SimpleString("import sys \n");
|
||||
PyRun_SimpleString("sys.path.append('.') \n");
|
||||
if(env->cfg->directory && env->cfg->directory[0]) {
|
||||
char wdir[1524];
|
||||
snprintf(wdir, sizeof(wdir), "sys.path.append('%s') \n",
|
||||
env->cfg->directory);
|
||||
PyRun_SimpleString(wdir);
|
||||
}
|
||||
PyRun_SimpleString("sys.path.append('"RUN_DIR"') \n");
|
||||
PyRun_SimpleString("sys.path.append('"SHARE_DIR"') \n");
|
||||
PyRun_SimpleString("import distutils.sysconfig \n");
|
||||
PyRun_SimpleString("sys.path.append(distutils.sysconfig.get_python_lib(1,0)) \n");
|
||||
if (PyRun_SimpleString("from unboundmodule import *\n") < 0)
|
||||
{
|
||||
log_err("pythonmod: cannot initialize core module: unboundmodule.py");
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check Python file load */
|
||||
|
|
@ -340,6 +360,7 @@ int pythonmod_init(struct module_env* env, int id)
|
|||
(void)PyParser_SimpleParseFile(script_py, pe->fname, Py_file_input);
|
||||
log_py_err();
|
||||
PyGILState_Release(gil);
|
||||
fclose(script_py);
|
||||
return 0;
|
||||
}
|
||||
fclose(script_py);
|
||||
|
|
@ -424,9 +445,11 @@ void pythonmod_deinit(struct module_env* env, int id)
|
|||
Py_XDECREF(pe->data);
|
||||
PyGILState_Release(gil);
|
||||
|
||||
PyEval_RestoreThread(pe->mainthr);
|
||||
Py_Finalize();
|
||||
pe->mainthr = NULL;
|
||||
if(--py_mod_count==0) {
|
||||
PyEval_RestoreThread(mainthr);
|
||||
Py_Finalize();
|
||||
mainthr = NULL;
|
||||
}
|
||||
}
|
||||
pe->fname = NULL;
|
||||
free(pe);
|
||||
|
|
|
|||
|
|
@ -602,7 +602,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
|||
else S_STR("control-key-file:", control_key_file)
|
||||
else S_STR("control-cert-file:", control_cert_file)
|
||||
else S_STR("module-config:", module_conf)
|
||||
else S_STR("python-script:", python_script)
|
||||
else S_STRLIST("python-script:", python_script)
|
||||
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
|
||||
|
|
@ -1054,7 +1054,7 @@ config_get_option(struct config_file* cfg, const char* opt,
|
|||
else O_YNO(opt, "unblock-lan-zones", unblock_lan_zones)
|
||||
else O_YNO(opt, "insecure-lan-zones", insecure_lan_zones)
|
||||
else O_DEC(opt, "max-udp-size", max_udp_size)
|
||||
else O_STR(opt, "python-script", python_script)
|
||||
else O_LST(opt, "python-script", python_script)
|
||||
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)
|
||||
|
|
@ -1420,6 +1420,7 @@ config_delete(struct config_file* cfg)
|
|||
free(cfg->dnstap_version);
|
||||
config_deldblstrlist(cfg->ratelimit_for_domain);
|
||||
config_deldblstrlist(cfg->ratelimit_below_domain);
|
||||
config_delstrlist(cfg->python_script);
|
||||
#ifdef USE_IPSECMOD
|
||||
free(cfg->ipsecmod_hook);
|
||||
config_delstrlist(cfg->ipsecmod_whitelist);
|
||||
|
|
@ -1630,6 +1631,31 @@ cfg_strlist_insert(struct config_strlist** head, char* item)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
cfg_strlist_append_ex(struct config_strlist** head, char* item)
|
||||
{
|
||||
struct config_strlist *s;
|
||||
if(!item || !head)
|
||||
return 0;
|
||||
s = (struct config_strlist*)calloc(1, sizeof(struct config_strlist));
|
||||
if(!s)
|
||||
return 0;
|
||||
s->str = item;
|
||||
s->next = NULL;
|
||||
|
||||
if (*head==NULL) {
|
||||
*head = s;
|
||||
} else {
|
||||
struct config_strlist *last = *head;
|
||||
while (last->next!=NULL) {
|
||||
last = last->next;
|
||||
}
|
||||
last->next = s;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
cfg_str2list_insert(struct config_str2list** head, char* item, char* i2)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -433,7 +433,7 @@ struct config_file {
|
|||
char* control_cert_file;
|
||||
|
||||
/** Python script file */
|
||||
char* python_script;
|
||||
struct config_strlist* python_script;
|
||||
|
||||
/** Use systemd socket activation. */
|
||||
int use_systemd;
|
||||
|
|
@ -820,6 +820,14 @@ char* config_collate_cat(struct config_strlist* list);
|
|||
*/
|
||||
int cfg_strlist_append(struct config_strlist_head* list, char* item);
|
||||
|
||||
/**
|
||||
* Searches the end of a string list and appends the given text.
|
||||
* @param head: pointer to strlist head variable.
|
||||
* @param item: new item. malloced by caller. if NULL the insertion fails.
|
||||
* @return true on success.
|
||||
*/
|
||||
int cfg_strlist_append_ex(struct config_strlist** head, char* item);
|
||||
|
||||
/**
|
||||
* Find string in strlist.
|
||||
* @param head: pointer to strlist head variable.
|
||||
|
|
|
|||
|
|
@ -5716,8 +5716,8 @@ yyreduce:
|
|||
#line 2721 "./util/configparser.y" /* yacc.c:1648 */
|
||||
{
|
||||
OUTYY(("P(python-script:%s)\n", (yyvsp[0].str)));
|
||||
free(cfg_parser->cfg->python_script);
|
||||
cfg_parser->cfg->python_script = (yyvsp[0].str);
|
||||
if(!cfg_strlist_append_ex(&cfg_parser->cfg->python_script, (yyvsp[0].str)))
|
||||
yyerror("out of memory");
|
||||
}
|
||||
#line 5723 "util/configparser.c" /* yacc.c:1648 */
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -2720,8 +2720,8 @@ content_py: py_script
|
|||
py_script: VAR_PYTHON_SCRIPT STRING_ARG
|
||||
{
|
||||
OUTYY(("P(python-script:%s)\n", $2));
|
||||
free(cfg_parser->cfg->python_script);
|
||||
cfg_parser->cfg->python_script = $2;
|
||||
if(!cfg_strlist_append_ex(&cfg_parser->cfg->python_script, $2))
|
||||
yyerror("out of memory");
|
||||
}
|
||||
server_disable_dnssec_lame_check: VAR_DISABLE_DNSSEC_LAME_CHECK STRING_ARG
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue