/*
* Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
* USE OR PERFORMANCE OF THIS SOFTWARE.
*
* The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
* conceived and contributed by Rob Butler.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
* USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* Copyright (C) 1999-2001, 2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*
* Copyright (C) 2009-2012 John Eaglesham
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND JOHN EAGLESHAM
* DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
* JOHN EAGLESHAM BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <EXTERN.h>
#include <perl.h>
#include <dlz_minimal.h>
#include "dlz_perl_driver.h"
/* Enable debug logging? */
#if 0
#else
#define carp(...)
#endif
#ifndef MULTIPLICITY
* before removing the first. In the case of a single global interpreter,
* serious problems arise. We can hack around this, but it's much better to do
* it properly and link against a perl compiled with multiplicity. */
static int global_perl_dont_free = 0;
#endif
typedef struct config_data {
char *perl_source;
/* Functions given to us by bind9 */
/* Note, this code generates warnings due to lost type qualifiers. This code
* is (almost) verbatim from perlembed, and is known to work correctly despite
* the warnings.
*/
EXTERN_C void
{
/* DynaLoader is a special case */
}
/*
* methods
*/
/*
* remember a helper function, from the bind9 dlz_dlopen driver
*/
const char *helper_name, void *ptr)
{
}
return DLZ_DLOPEN_VERSION;
}
{
int rrcount, r;
#ifdef MULTIPLICITY
#endif
dSP;
POPs;
goto CLEAN_UP_AND_RETURN;
}
if (!rrcount) {
goto CLEAN_UP_AND_RETURN;
}
r = 0;
while (r++ < rrcount) {
record_ref = POPs;
if (
(!SvROK(record_ref)) ||
) {
"DLZ Perl: allnodes for zone %s "
"returned an invalid value "
"(expected array of arrayrefs)",
zone);
break;
}
{
"DLZ Perl: allnodes for zone %s "
"returned an array that was missing data",
zone);
break;
}
carp("DLZ Perl: Got record %s/%s = %s",
SvPV_nolen(*rr_data));
if (retval != ISC_R_SUCCESS) {
"DLZ Perl: putnamedrr in allnodes "
"for zone %s failed with code %i "
"(did lookup return invalid record data?)",
break;
}
}
carp("DLZ Perl: Returning from allnodes, r = %i, retval = %i",
r, retval);
return (retval);
}
int r;
#ifdef MULTIPLICITY
#endif
dSP;
/*
* On error there's an undef at the top of the stack. Pop
* it away so we don't leave junk on the stack for the next
* caller.
*/
POPs;
"DLZ Perl: allowzonexfr died in eval: %s",
SvPV_nolen(ERRSV));
} else if (r == 0) {
/* Client returned nothing -- zone not found. */
} else if (r > 1) {
/* Once again, clean out the stack when possible. */
while (r--) POPi;
"DLZ Perl: allowzonexfr returned too many parameters!");
} else {
/*
* the zone.
*/
r = POPi;
if (r)
else
}
return (retval);
}
#if DLZ_DLOPEN_VERSION < 3
#else
#endif
{
int r;
#ifdef MULTIPLICITY
#endif
#if DLZ_DLOPEN_VERSION >= 3
#endif
dSP;
/*
* On error there's an undef at the top of the stack. Pop
* it away so we don't leave junk on the stack for the next
* caller.
*/
POPs;
"DLZ Perl: findzone died in eval: %s",
SvPV_nolen(ERRSV));
} else if (r == 0) {
} else if (r > 1) {
/* Once again, clean out the stack when possible. */
while (r--) POPi;
"DLZ Perl: findzone returned too many parameters!");
} else {
r = POPi;
if (r)
else
}
return (retval);
}
#if DLZ_DLOPEN_VERSION == 1
#else
#endif
{
int rrcount, r;
#ifdef MULTIPLICITY
#endif
#if DLZ_DLOPEN_VERSION >= 2
#endif
dSP;
POPs;
SvPV_nolen(ERRSV));
goto CLEAN_UP_AND_RETURN;
}
if (!rrcount) {
goto CLEAN_UP_AND_RETURN;
}
r = 0;
while (r++ < rrcount) {
record_ref = POPs;
if ((!SvROK(record_ref)) ||
{
"DLZ Perl: lookup returned an "
"invalid value (expected array of arrayrefs)!");
break;
}
"DLZ Perl: lookup for record %s in "
"zone %s returned an array that was "
break;
}
carp("DLZ Perl: Got record %s = %s",
if (retval != ISC_R_SUCCESS) {
"DLZ Perl: putrr for lookup of %s in "
"zone %s failed with code %i "
"(did lookup return invalid record data?)",
break;
}
}
return (retval);
}
const char *
#ifdef MULTIPLICITY
#else
missing_perl_method(const char *perl_class_name)
#endif
{
int i = 0;
perl_class_name, methods[i]);
return methods[i];
}
i++;
}
return (NULL);
}
void **dbdata, ...)
{
char *perl_class_name;
int r;
const char *helper_name;
const char *missing_method_name;
#ifdef MULTIPLICITY
#endif
return (ISC_R_NOMEMORY);
/* fill in the helper functions */
}
if (argc < 2) {
"DLZ Perl '%s': Missing script argument.",
dlzname);
return (ISC_R_FAILURE);
}
if (argc < 3) {
"DLZ Perl '%s': Missing class name argument.",
dlzname);
return (ISC_R_FAILURE);
}
#ifndef MULTIPLICITY
if (global_perl) {
/*
* PERL_SET_CONTEXT not needed here as we're guaranteed to
* have an implicit context thanks to an undefined
* MULTIPLICITY.
*/
global_perl = NULL;
}
#endif
return (ISC_R_FAILURE);
}
#ifdef MULTIPLICITY
#endif
/*
* We will re-create the interpreter during an rndc reconfig, so we
* must set this variable per perlembed in order to insure we can
* clean up Perl at a later time.
*/
/* Prevent crashes from clients writing to $0 */
PL_origalen = 1;
return (ISC_R_NOMEMORY);
}
"DLZ Perl '%s': Failed to parse Perl script, aborting",
dlzname);
goto CLEAN_UP_PERL_AND_FAIL;
}
/* Let Perl know about our callbacks. */
call_argv("DLZ_Perl::clientinfo::bootstrap",
call_argv("DLZ_Perl::bootstrap",
/*
* Run the script. We don't really need to do this since we have
* the init callback, but there's not really a downside either.
*/
"DLZ Perl '%s': Script exited with an error, aborting",
dlzname);
goto CLEAN_UP_PERL_AND_FAIL;
}
#ifdef MULTIPLICITY
#else
#endif
{
"DLZ Perl '%s': Missing required function '%s', "
goto CLEAN_UP_PERL_AND_FAIL;
}
dSP;
/* Build flattened hash of config info. */
/* Argument to pass to new? */
if (argc == 4) {
}
POPs;
"DLZ Perl '%s': new died in eval: %s",
goto CLEAN_UP_PERL_AND_FAIL;
}
"DLZ Perl '%s': new failed to return a blessed object",
dlzname);
goto CLEAN_UP_PERL_AND_FAIL;
}
#ifndef MULTIPLICITY
#endif
return (ISC_R_SUCCESS);
return (ISC_R_FAILURE);
}
#ifdef MULTIPLICITY
#endif
#ifndef MULTIPLICITY
if (!global_perl_dont_free) {
#endif
#ifndef MULTIPLICITY
global_perl = NULL;
}
#endif
}