Skip to content

Commit

Permalink
Merge branch 'dev/all-merged/master' of git://github.com/episource/un…
Browse files Browse the repository at this point in the history
…bound into episource-dev/all-merged/master
  • Loading branch information
wcawijngaards committed Jun 18, 2019
2 parents 0f3eac4 + efb3697 commit 63b2628
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 42 deletions.
6 changes: 4 additions & 2 deletions doc/unbound.conf.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -1768,7 +1768,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
Expand All @@ -1777,7 +1778,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
Expand Down
4 changes: 3 additions & 1 deletion pythonmod/interface.i
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,7 @@ struct config_file {
char* control_key_file;
char* control_cert_file;
int do_daemonize;
char* python_script;
struct config_strlist* python_script;
};

/* ************************************************************************************ *
Expand Down Expand Up @@ -1106,6 +1106,7 @@ struct delegpt {
%rename ("MODULE_STATE_INITIAL") "module_state_initial";
%rename ("MODULE_WAIT_REPLY") "module_wait_reply";
%rename ("MODULE_WAIT_MODULE") "module_wait_module";
%rename ("MODULE_RESTART_NEXT") "module_restart_next";
%rename ("MODULE_WAIT_SUBQUERY") "module_wait_subquery";
%rename ("MODULE_ERROR") "module_error";
%rename ("MODULE_FINISHED") "module_finished";
Expand All @@ -1114,6 +1115,7 @@ enum module_ext_state {
module_state_initial = 0,
module_wait_reply,
module_wait_module,
module_restart_next,
module_wait_subquery,
module_error,
module_finished
Expand Down
84 changes: 52 additions & 32 deletions pythonmod/pythonmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -72,8 +81,6 @@ struct pythonmod_env {
/** Python script filename. */
const char* fname;

/** Python main thread */
PyThreadState* mainthr;
/** Python module. */
PyObject* module;

Expand Down Expand Up @@ -242,14 +249,17 @@ log_py_err(void)

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;
#if PY_MAJOR_VERSION < 3
PyObject* PyFileObject = NULL;
#endif
struct config_strlist* cfg_item = env->cfg->python_script;

struct pythonmod_env* pe = (struct pythonmod_env*)calloc(1, sizeof(struct pythonmod_env));
if (!pe)
Expand All @@ -261,14 +271,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];
Expand All @@ -284,29 +301,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 */
Expand All @@ -328,8 +347,7 @@ int pythonmod_init(struct module_env* env, int id)
/* Load file */
pe->module = PyImport_AddModule("__main__");
pe->dict = PyModule_GetDict(pe->module);
pe->data = Py_None;
Py_INCREF(pe->data);
pe->data = PyDict_New();
PyModule_AddObject(pe->module, "mod_env", pe->data);

/* TODO: deallocation of pe->... if an error occurs */
Expand All @@ -352,6 +370,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;
}
#if PY_MAJOR_VERSION < 3
Expand Down Expand Up @@ -440,9 +459,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);
Expand Down Expand Up @@ -500,8 +521,7 @@ void pythonmod_operate(struct module_qstate* qstate, enum module_ev event,
pq = qstate->minfo[id] = malloc(sizeof(struct pythonmod_qstate));

/* Initialize per query data */
pq->data = Py_None;
Py_INCREF(pq->data);
pq->data = PyDict_New();
}

/* Call operate */
Expand Down
30 changes: 28 additions & 2 deletions util/config_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,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
Expand Down Expand Up @@ -1061,7 +1061,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)
Expand Down Expand Up @@ -1437,6 +1437,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);
Expand Down Expand Up @@ -1651,6 +1652,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)
{
Expand Down
10 changes: 9 additions & 1 deletion util/config_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,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;
Expand Down Expand Up @@ -834,6 +834,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.
Expand Down
4 changes: 2 additions & 2 deletions util/configparser.c
Original file line number Diff line number Diff line change
Expand Up @@ -5752,8 +5752,8 @@ yyparse (void)
#line 2739 "./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 5759 "util/configparser.c" /* yacc.c:1648 */
break;
Expand Down
4 changes: 2 additions & 2 deletions util/configparser.y
Original file line number Diff line number Diff line change
Expand Up @@ -2738,8 +2738,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
{
Expand Down

0 comments on commit 63b2628

Please sign in to comment.