From: Francis Dupont Date: Mon, 20 Jun 2016 21:02:37 +0000 (+0200) Subject: [fdxhook] Added LUA too X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cd195b45d9072cfe13408a4b8ca09a717887f26a;p=thirdparty%2Fkea.git [fdxhook] Added LUA too --- diff --git a/src/hooks/external/lua/Makefile b/src/hooks/external/lua/Makefile new file mode 100644 index 0000000000..5331483155 --- /dev/null +++ b/src/hooks/external/lua/Makefile @@ -0,0 +1,49 @@ +#KEASRC = /tmp/kea/src/lib + +# Kea includes and boost +CPPFLAGS = -I../../.. -I$(KEASRC) -I/usr/local/include +# lua 5.3 +CPPFLAGS += -I/usr/local/include/lua-5.3 + +CXXFLAGS = -DBOOST_ERROR_CODE_HEADER_ONLY -DBOOST_SYSTEM_NO_DEPRECATED +CXXFLAGS += -g -fPIC -dynamic + +# Kea dhcp library +LIBS = -lkea-dhcp++ -lkea-hooks -lkea-exceptions +# lua 5.3 +LIBS += -llua.5.3 -lm + +# Kea dependencies +LDFLAGS = -L/usr/local/Cellar/botan/1.10.12/lib +LDFLAGS += -L$(KEASRC)/dhcp/.libs +LDFLAGS += -L$(KEASRC)/hooks/.libs +LDFLAGS += -L$(KEASRC)/exceptions/.libs +# lua 5.3 +LDFLAGS += -L/usr/local/lib + +SRCS = dso.cc loption.h loption.cc lpkt4.h lpkt4.cc + +OBJS = dso.o loption.o lpkt4.o + +all: kea.so tests + +kea.so: $(OBJS) + g++ -shared $(OBJS) $(LDFLAGS) $(LIBS) -o kea.so + +TESTLIBS = -lkea-dhcpsrv -lkea-dhcp++ -lkea-asiolink -lkea-cc +TESTLIBS += -lkea-hooks -lkea-log -lkea-exceptions + +TESTLDFLAGS = -L/usr/local/Cellar/botan/1.10.12/lib +TESTLDFLAGS += -L$(KEASRC)/dhcpsrv/.libs +TESTLDFLAGS += -L$(KEASRC)/dhcp/.libs +TESTLDFLAGS += -L$(KEASRC)/asiolink/.libs +TESTLDFLAGS += -L$(KEASRC)/cc/.libs +TESTLDFLAGS += -L$(KEASRC)/hooks/.libs +TESTLDFLAGS += -L$(KEASRC)/log/.libs +TESTLDFLAGS += -L$(KEASRC)/exceptions/.libs + +tests: tests.o + g++ tests.o $(TESTLDFLAGS) $(TESTLIBS) -o tests + +clean: + rm -f *.o *.so tests diff --git a/src/hooks/external/lua/NOTES b/src/hooks/external/lua/NOTES new file mode 100644 index 0000000000..7aa22e31f2 --- /dev/null +++ b/src/hooks/external/lua/NOTES @@ -0,0 +1,39 @@ +Implementation notes for lua + +Manifest: + - loption.h loption.cc: the C++ OptionPtr encapsulated into a lua full + userdata with a few methods ported. + + - ppkt4.h ppkt4.cc: the C++ Pkt4Ptr encapsulated into a lua full userdata + with a few methods ported. + + one can complete these lua types or/and new lua type. + + - dso.cc: the kea framework and hook glue: on the kea / C side it is + a dynamic shared object providing the framework and hook entry points, + on the lua side it embeds an interpreter which imports the lua script + hook.lua. + + loption.o, lpkt4.o and dso.o are compiled into kea.so. + + - hook.lua: the lua script which implements the lua part of hook + hook handlers using lua option and pkt4 modules. + + - tests.cc: source of test program which loads the kea.so hook-library + and exercise the pkt4_receive hook. It gives an independent executable. + + - cshenv: C-shell script setting environment variables for a kea + distrib in /tmp/kea on OS X. Note I brewed a recent (vs standard) + version of lua (last one is 5.3.3). + + - Makefile: make config file for OS X. + + - NOTES: this file. + +I was afraid to have to recompile lua for C++ but it was not (yet?) +necessary. + +The preload stuff from linit.c doesn't work. + +A possible bug issue: the allocator (lua_newuserdata) does NOT +clear the memory?! diff --git a/src/hooks/external/lua/cshenv b/src/hooks/external/lua/cshenv new file mode 100644 index 0000000000..b186eb175b --- /dev/null +++ b/src/hooks/external/lua/cshenv @@ -0,0 +1,5 @@ +setenv KEATOP /tmp/kea + +setenv KEASRC $KEATOP/src/lib + +setenv DYLD_LIBRARY_PATH $KEASRC/dhcpsrv/.libs:$KEASRC/eval/.libs:$KEASRC/dhcp_ddns/.libs:$KEASRC/stats/.libs:$KEASRC/hooks/.libs:$KEASRC/config/.libs:$KEASRC/dhcp/.libs:$KEASRC/asiolink/.libs:$KEASRC/dns/.libs:$KEASRC/cc/.libs:$KEASRC/cryptolink/.libs:$KEASRC/log/.libs:$KEASRC/util/threads/.libs:$KEASRC/util/.libs:$KEASRC/exceptions/.libs diff --git a/src/hooks/external/lua/dso.cc b/src/hooks/external/lua/dso.cc new file mode 100644 index 0000000000..e771e90a12 --- /dev/null +++ b/src/hooks/external/lua/dso.cc @@ -0,0 +1,208 @@ +// Copyright (C) 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/. + +#include + +#include + +#include +#include + +#include + +using namespace std; +using namespace isc::data; +using namespace isc::dhcp; +using namespace isc::hooks; +using namespace isc::kea; + +namespace { + // Lua state + lua_State* L; +}; + +extern "C" { + +// Framework functions + +// version +int version() { + return (KEA_HOOKS_VERSION); +} + +// load +int load(LibraryHandle& handle) { + // Get a new state + L = luaL_newstate(); + if (!L) { + cerr << "can't get new state\n"; + return (1); + } + + // Check against version mismatch + luaL_checkversion(L); + + // Add option and pkt4 as to be preloaded modules + static_cast(luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD")); + lua_pushcfunction(L, luaopen_option); + lua_setfield(L, -2, "option"); + lua_pushcfunction(L, luaopen_pkt4); + lua_setfield(L, -2, "pkt4"); + lua_pop(L, 1); + + // Load librairies + luaL_openlibs(L); + + // Load option + luaL_requiref(L, LUA_OPTIONLIBNAME, luaopen_option, 1); + lua_pop(L, 1); + + // Load pkt4 + luaL_requiref(L, LUA_PKT4LIBNAME, luaopen_pkt4, 1); + lua_pop(L, 1); + + // Get the script module name (default "hook.lua" file) + ConstElementPtr script = handle.getParameter("script"); + string scptname = "hook.lua"; + if (script && script->getType() == Element::string) { + scptname = script->stringValue(); + } else { + cout << "no \"script\" parameter: using \"hook.hua\"\n"; + } + int ret = luaL_loadfile(L, scptname.c_str()); + switch (ret) { + case LUA_OK: + break; + case LUA_ERRSYNTAX: + cerr << "syntax error in \"" << scptname << "\": " + << lua_tostring(L, -1) << "\n"; + return (2); + case LUA_ERRFILE: + cerr << "bad file \"" << scptname << "\": " + << lua_tostring(L, -1) << "\n"; + return (2); + case LUA_ERRMEM: + case LUA_ERRGCMM: + cerr << "memory problem loading \"" << scptname << "\": " + << lua_tostring(L, -1) << "\n"; + return (2); + default: + cerr << "unspecified error (" << ret + << ") loading \"" << scptname << "\": " + << lua_tostring(L, -1) << "\n"; + return (2); + } + + // Run the script + ret = lua_pcall(L, 0, 0, 0); + switch (ret) { + case LUA_OK: + break; + case LUA_ERRRUN: + cerr << "runtime error from \"" << scptname << "\": " + << lua_tostring(L, -1) << "\n"; + return (3); + case LUA_ERRMEM: + case LUA_ERRGCMM: + cerr << "memory problem running \"" << scptname << "\": " + << lua_tostring(L, -1) << "\n"; + return (3); + default: + cerr << "unspecified error (" << ret + << ") running \"" << scptname << "\": " + << lua_tostring(L, -1) << "\n"; + return (3); + } + + // Get pkt4_receive handler + ret = lua_getglobal(L, "pkt4_receive"); + switch (ret) { + case LUA_TNIL: + cerr << "can't find \"pkt4_receive\"\n"; + return (4); + case LUA_TFUNCTION: + break; + default: + cerr << "\"pkt4_receive\" is not a function, it is a " + << lua_typename(L, ret) << "\n"; + return (4); + } + lua_pop(L, 1); + + return (0); +} + +// unload +int unload() { + // Release the state + lua_close(L); + L = NULL; + + return (0); +} + +// pkt4_receive hook +int pkt4_receive(CalloutHandle& handle) { + if (lua_getglobal(L, "pkt4_receive") != LUA_TFUNCTION) { + return (0); + } + cout << "pkt4_receive: enter\n"; + + Pkt4Ptr query4; + handle.getArgument("query4", query4); + if (!query4) { + cerr << "pkt4_receive: null query4\n"; + return (0); + } + + void *query = lua_newuserdata(L, sizeof(l_pkt4)); + if (!query) { + cerr << "lua_newuserdata failed\n"; + return (0); + } + memset(query, 0, sizeof(l_pkt4)); + (static_cast(query))->object = query4; + if (luaL_getmetatable(L, LUA_KEAPKT4) == LUA_TNIL) { + cerr << "no metatable for " << LUA_KEAPKT4 << "\n"; + } + lua_pop(L, 1); + luaL_setmetatable(L, LUA_KEAPKT4); + + int ret = lua_pcall(L, 1, 1, 0); + switch (ret) { + case LUA_OK: + break; + case LUA_ERRRUN: + cerr << "runtime error in pkt4_receive: " + << lua_tostring(L, -1) << "\n"; + lua_pop(L, 1); + return (0); + case LUA_ERRMEM: + case LUA_ERRGCMM: + cerr << "memory problem in pkt4_receive: " + << lua_tostring(L, -1) << "\n"; + lua_pop(L, 1); + return (0); + default: + cerr << "unspecified error (" << ret + << ") in pkt4_receive: " + << lua_tostring(L, -1) << "\n"; + lua_pop(L, 1); + return (0); + } + if (lua_type(L, -1) != LUA_TNUMBER) { + cerr << "pkt4_receive didn't return a number\n"; + lua_pop(L, 1); + return (0); + } + ret = static_cast(lua_tonumber(L, -1)); + lua_pop(L, 1); + + cout << "pkt4_receive: return " << ret << "\n"; + return (ret); +} + +} diff --git a/src/hooks/external/lua/hook.lua b/src/hooks/external/lua/hook.lua new file mode 100644 index 0000000000..384e3e61ba --- /dev/null +++ b/src/hooks/external/lua/hook.lua @@ -0,0 +1,27 @@ +-- Copyright (C) 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/. + +-- Support for Kea hook in lua + +print("hook.lua is loading") + +-- require kea + +NEXT_STEP_CONTINUE = 0 +NEXT_STEP_SKIP = 1 +NEXT_STEP_DROP = 2 + +-- pkt4_receive hook point +-- +-- parameter: inout Pkt4Ptr query4 +-- return: next step + +function pkt4_receive(query4) + print("pkt4_receive: handler is called with", tostring(query4)) + return NEXT_STEP_CONTINUE +end + +print("hook.lua loaded") diff --git a/src/hooks/external/lua/loption.cc b/src/hooks/external/lua/loption.cc new file mode 100644 index 0000000000..d47c976851 --- /dev/null +++ b/src/hooks/external/lua/loption.cc @@ -0,0 +1,150 @@ +// Copyright (C) 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/. + +#include + +#include + +#include + +using namespace std; +using namespace isc::dhcp; +using namespace isc::kea; + +// Constructor +l_option::l_option() {} + +namespace { // anonymous namespace + +// factory(universe, type, data) +int factory(lua_State* L) { + // Require 3 arguments + if (lua_gettop(L) - 1 != 3) { + return (luaL_error(L, "option.factory takes 3 arguments")); + } + if (lua_type(L, -3) != LUA_TNUMBER) { + return (luaL_error(L, "universe must be a number")); + } + if (lua_type(L, -2) != LUA_TNUMBER) { + return (luaL_error(L, "type must be a number")); + } + if (lua_type(L, -1) != LUA_TSTRING) { + return (luaL_error(L, "data must be a string")); + } + unsigned char u = static_cast(lua_tonumber(L, -3)); + unsigned short t = static_cast(lua_tonumber(L, -2)); + Option::Universe universe; + switch (u) { + case 4: + universe = Option::V4; + if (t > 255) { + return (luaL_error(L, "out of range type for DHCPv4: %d", + static_cast(t))); + } + break; + case 6: + universe = Option::V6; + break; + default: + return (luaL_error(L, "universe must be 4 or 6 (not %d)", + static_cast(u))); + } + + size_t len = 0; + const char* d = lua_tolstring(L, -1, &len); + OptionBuffer data; + data.resize(len); + if (len) { + memmove(&data[0], d, len); + } + + l_option* const self = + static_cast(lua_newuserdata(L, sizeof(l_option))); + memset(self, 0, sizeof(l_option)); + self->object.reset(new Option(universe, t, data)); + luaL_setmetatable(L, LUA_KEAOPTION); + return (1); +} + +// __gc +int option__gc(lua_State* L) { + // This is a critical code to avoid memory leaks + cout << "option__gc called\n"; + l_option* const self = + static_cast(luaL_checkudata(L, 1, LUA_KEAOPTION)); + self->object.reset(); + return (0); +} + +// __tostring +int option__tostring(lua_State* L) { + l_option* const self = + static_cast(luaL_checkudata(L, 1, LUA_KEAOPTION)); + lua_pushstring(L, self->object->toText(0).c_str()); + return (1); +} + +// getUniverse() method +int getUniverse(lua_State* L) { + l_option* const self = + static_cast(luaL_checkudata(L, 1, LUA_KEAOPTION)); + switch (self->object->getUniverse()) { + case Option::V4: + lua_pushinteger(L, 4); + return (1); + case Option::V6: + lua_pushinteger(L, 6); + return (1); + default: + return (luaL_error(L, "getUniverse")); + } +} + +// Method table +const luaL_Reg option_method[] = { + { "__gc", option__gc }, + { "__tostring", option__tostring }, + { "getUniverse", getUniverse }, + { NULL, NULL } +}; + +// Function table +const luaL_Reg option_function[] = { + { NULL, NULL } +}; + +// Create the module metadata +void createmeta(lua_State* L) { + // create metatable + luaL_newmetatable(L, LUA_KEAOPTION); + // push metatable + lua_pushvalue(L, -1); + // metatable.__index = metatable + lua_setfield(L, -2, "__index"); + // add methods + luaL_setfuncs(L, option_method, 0); + // pop new metatable + lua_pop(L, 1); +} + +} // end of anonymous namespace + +namespace isc { +namespace kea { + +// Initialize the module +int luaopen_option(lua_State* L) { + // new module + luaL_newlib(L, option_function); + createmeta(L); + + // constants + + return (1); +} + +} // namespace lua +} // namespace isc diff --git a/src/hooks/external/lua/loption.h b/src/hooks/external/lua/loption.h new file mode 100644 index 0000000000..c63fd37210 --- /dev/null +++ b/src/hooks/external/lua/loption.h @@ -0,0 +1,32 @@ +// Copyright (C) 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/. + +#ifndef LOPTION_H +#define LOPTION_H 1 + +#include + +namespace isc { +namespace kea { + +// Lua option class +class l_option { + l_option(); + +public: + isc::dhcp::OptionPtr object; +}; + +#define LUA_KEAOPTION "kea-option" + +#define LUA_OPTIONLIBNAME "option" + +LUAMOD_API int luaopen_option(lua_State* L); + +} // namespace kea +} // namespace isc + +#endif // LOPTION_H diff --git a/src/hooks/external/lua/lpkt4.cc b/src/hooks/external/lua/lpkt4.cc new file mode 100644 index 0000000000..d6ccd05a21 --- /dev/null +++ b/src/hooks/external/lua/lpkt4.cc @@ -0,0 +1,95 @@ +// Copyright (C) 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/. + +#include + +#include +#include + +#include + +using namespace std; +using namespace isc::dhcp; +using namespace isc::kea; + +// Constructor +l_pkt4::l_pkt4() {} + +namespace { // anonymous namespace + +// __gc +int pkt4__gc(lua_State* L) { + // This is a critical code to avoid memory leaks + cout << "pkt4__gc called\n"; + l_pkt4* const self = + static_cast(luaL_checkudata(L, 1, LUA_KEAPKT4)); + self->object.reset(); + return (0); +} + +// __tostring +int pkt4__tostring(lua_State* L) { + l_pkt4* const self = + static_cast(luaL_checkudata(L, 1, LUA_KEAPKT4)); + lua_pushstring(L, self->object->toText().c_str()); + return (1); +} + +// addOption(const OptionPtr opt) method +int addOption(lua_State* L) { + l_pkt4* const self = + static_cast(luaL_checkudata(L, 1, LUA_KEAPKT4)); + l_option* const sub = + static_cast(luaL_checkudata(L, 2, LUA_KEAOPTION)); + self->object->addOption(sub->object); + return (0); +} + +// Method table +const luaL_Reg pkt4_method[] = { + { "__gc", pkt4__gc }, + { "__tostring", pkt4__tostring }, + { "addOption", addOption }, + { NULL, NULL } +}; + +// Function table +const luaL_Reg pkt4_function[] = { + { NULL, NULL } +}; + +// Create the module metadata +void createmeta(lua_State* L) { + // create metatable + luaL_newmetatable(L, LUA_KEAPKT4); + // push metatable + lua_pushvalue(L, -1); + // metatable.__index = metatable + lua_setfield(L, -2, "__index"); + // add methods + luaL_setfuncs(L, pkt4_method, 0); + // pop new metatable + lua_pop(L, 1); +} + +} // end of anonymous namespace + +namespace isc { +namespace kea { + +// Initialize the module +int luaopen_pkt4(lua_State* L) { + // new module + luaL_newlib(L, pkt4_function); + createmeta(L); + + // constants + + return (1); +} + +} // namespace lua +} // namespace isc diff --git a/src/hooks/external/lua/lpkt4.h b/src/hooks/external/lua/lpkt4.h new file mode 100644 index 0000000000..496038e41a --- /dev/null +++ b/src/hooks/external/lua/lpkt4.h @@ -0,0 +1,32 @@ +// Copyright (C) 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/. + +#ifndef LPKT4_H +#define LPKT4_H 1 + +#include + +namespace isc { +namespace kea { + +// Lua DHCPv4 packet class +class l_pkt4 { + l_pkt4(); + +public: + isc::dhcp::Pkt4Ptr object; +}; + +#define LUA_KEAPKT4 "kea-pkt4" + +#define LUA_PKT4LIBNAME "pkt4" + +LUAMOD_API int luaopen_pkt4(lua_State* L); + +} // namespace kea +} // namespace isc + +#endif // LPKT4_H diff --git a/src/hooks/external/lua/tests.cc b/src/hooks/external/lua/tests.cc new file mode 100644 index 0000000000..5d21d3a542 --- /dev/null +++ b/src/hooks/external/lua/tests.cc @@ -0,0 +1,146 @@ +// Copyright (C) 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/. + +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace std; +using namespace isc; +using namespace isc::asiolink; +using namespace isc::data; +using namespace isc::dhcp; +using namespace isc::hooks; +using namespace isc::log; + +// config fragment for hooks-libraries +const string config = + "{ \"hooks-libraries\": [" + " { \"library\": \"kea.so\", " + " \"parameters\": " + " { \"script\": \"hook.lua\" }" + " }] }"; + +// main routine +int main() { + // must be first + int hi_pkt4_receive = HooksManager::registerHook("pkt4_receive"); + cout << "pkt4_receive is hook#" << hi_pkt4_receive << "\n"; + + initLogger(); + + // check if there is a library already loaded + vector hooks_libraries = HooksManager::getLibraryNames(); + if (!hooks_libraries.empty()) { + cerr << "hooks_libraries is not empty\n"; + } + + // parse config into json + ElementPtr json = Element::fromJSON(config); + if (!json) { + cerr << "fatal: fromJSON failed\n"; + exit(-1); + } + cout << "config parsed\n"; + + // call the hooks-libraries parser + boost::shared_ptr parser; + try { + const map& cmap = json->mapValue(); + if (cmap.empty()) { + cerr << "fatal: config map is empty\n"; + exit(-1); + } + if (cmap.size() > 1) { + cerr << "config map has more than one element\n"; + } + if (cmap.count("hooks-libraries") == 0) { + cerr << "fatal: no \"hooks-libraries\" in config\n"; + exit(-1); + } + const ConstElementPtr& hl_value = cmap.find("hooks-libraries")->second; + if (!hl_value) { + cerr << "fatal: empty \"hooks-libraries\" value\n"; + exit(-1); + } + parser.reset(new HooksLibrariesParser("hooks-libraries")); + parser->build(hl_value); + parser->commit(); + cout << "config committed\n"; + } catch (const Exception& ex) { + cerr << "fatal: config parsing failed: " << ex.what() << "\n"; + exit(-1); + } + + // check if the library was loaded + HookLibsCollection libraries; + bool changed = false; + parser->getLibraries(libraries, changed); + if (!changed) { + cerr << "commit didn't change libraries\n"; + } + if (libraries.empty()) { + cerr << "fatal: no libraries\n"; + exit(-1); + } + if (libraries.size() > 1) { + cerr << "more than one library\n"; + } + cout << "library is \"" + libraries[0].first + "\"\n"; + if (libraries[0].first != "kea.so") { + cerr << "fatal: library is not \"kea.so\"\n"; + exit(-1); + } + ConstElementPtr params = libraries[0].second; + if (!params) { + cerr << "no parameters\n"; + } else { + cout << "got " << params->size() << " parameters\n"; + } + + // note we can't know this way if it was successfully loaded + + // get the callout + if (!HooksManager::calloutsPresent(hi_pkt4_receive)) { + cerr << "fatal: no callout present for pkt4_receive\n"; + exit(-1); + } + + // from pkt4_unittests.cc + Pkt4Ptr pkt(new Pkt4(DHCPDISCOVER, 0x12345678)); + const uint8_t macAddr[] = {0, 1, 2, 3, 4, 5}; + vector vectorMacAddr(macAddr, macAddr + sizeof(macAddr)); + pkt->setHWAddr(6, 6, vectorMacAddr); + pkt->setHops(13); + // Transaction-id is already set. + pkt->setSecs(42); + pkt->setFlags(BOOTP_BROADCAST); + pkt->setCiaddr(IOAddress("192.0.2.1")); + pkt->setYiaddr(IOAddress("1.2.3.4")); + pkt->setSiaddr(IOAddress("192.0.2.255")); + pkt->setGiaddr(IOAddress("255.255.255.255")); + // Chaddr already set with setHWAddr(). + + // from dhcp4_srv.cc + CalloutHandlePtr co_handle = getCalloutHandle(pkt); + co_handle->deleteAllArguments(); + co_handle->setArgument("query4", pkt); + cout << "calling pkt4_receive callout\n"; + HooksManager::callCallouts(hi_pkt4_receive, *co_handle); + cout << "pkt4_receive callout status " << co_handle->getStatus() << "\n"; + co_handle->getArgument("query4", pkt); + + // TODO... + + exit(0); +} diff --git a/src/hooks/external/ocaml/NOTES b/src/hooks/external/ocaml/NOTES index cd595caa90..1e05e93546 100644 --- a/src/hooks/external/ocaml/NOTES +++ b/src/hooks/external/ocaml/NOTES @@ -42,3 +42,6 @@ problem but it means memory leaks can become hard to track. ocaml is statically typed so there is no type check in the runtime even in the C++ code. So if you bug an external declaration you likely bug the whole thing! + +To finish ocaml has a standard type named option (None | Some of) +so I used the name opt (vs option) for the kea option type.