Commit d25b881d authored by Marek Vavruša's avatar Marek Vavruša

wip: trustanchor(), compat with libknot2/libzscanner1

parent c34ddbf4
......@@ -15,7 +15,8 @@ BUILD_CFLAGS += --coverage
endif
# Dependencies
$(eval $(call find_lib,libknot))
$(eval $(call find_lib,libknot,2.1))
$(eval $(call find_lib,libzscanner,2.1))
$(eval $(call find_lib,libuv,1.0))
$(eval $(call find_alt,lua,luajit))
$(eval $(call find_lib,cmocka))
......@@ -49,6 +50,9 @@ BUILD_CFLAGS += $(addprefix -I,$(wildcard contrib/ccan/*) contrib/murmurhash3)
info:
$(info Target: Knot DNS Resolver $(MAJOR).$(MINOR).$(PATCH)-$(PLATFORM))
$(info Compiler: $(CC) $(BUILD_CFLAGS))
$(info )
$(info Variables)
$(info ---------)
$(info HARDENING: $(HARDENING))
$(info BUILDMODE: $(BUILDMODE))
$(info PREFIX: $(PREFIX))
......@@ -63,14 +67,14 @@ info:
$(info Dependencies)
$(info ------------)
$(info [$(HAS_libknot)] libknot (lib))
$(info [$(HAS_lua)] LuaJIT (daemon))
$(info [$(HAS_lua)] luajit (daemon))
$(info [$(HAS_libuv)] libuv (daemon))
$(info )
$(info Optional)
$(info --------)
$(info [$(HAS_doxygen)] doxygen (doc))
$(info [$(HAS_go)] Go 1.5+ on amd64 (modules/go))
$(info [$(HAS_geoip)] github.com/abh/geoip (modules/tinyweb))
$(info [$(HAS_go)] go (modules/go, Go 1.5+ on amd64))
$(info [$(HAS_geoip)] geoip (modules/tinyweb, github.com/abh/geoip))
$(info [$(HAS_libmemcached)] libmemcached (modules/memcached))
$(info [$(HAS_hiredis)] hiredis (modules/redis))
$(info [$(HAS_cmocka)] cmocka (tests/unit))
......
......@@ -24,7 +24,7 @@ bindings-install: $(kresd_DIST) $(DESTDIR)$(MODULEDIR)
kresd_CFLAGS := -fPIE
kresd_DEPEND := $(libkres) $(contrib)
kresd_LIBS := $(libkres_TARGET) $(contrib_TARGET) $(libknot_LIBS) $(libdnssec_LIBS) $(libuv_LIBS) $(lua_LIBS)
kresd_LIBS := $(libkres_TARGET) $(contrib_TARGET) $(libknot_LIBS) $(libzscanner_LIBS) $(libdnssec_LIBS) $(libuv_LIBS) $(lua_LIBS)
# Make binary
ifeq ($(HAS_lua)|$(HAS_libuv), yes|yes)
......
......@@ -23,6 +23,7 @@
#include <pwd.h>
/* #include <libknot/internal/namedb/knot_db_trie.h> @todo Not supported (doesn't keep value copy) */
#include <libknot/db/db_lmdb.h>
#include <zscanner/scanner.h>
#include "daemon/engine.h"
#include "daemon/bindings.h"
......@@ -199,6 +200,52 @@ static int l_option(lua_State *L)
return 1;
}
/** Enable/disable trust anchor. */
static int l_trustanchor(lua_State *L)
{
struct engine *engine = engine_luaget(L);
const char *anchor = lua_tostring(L, 1);
bool enable = lua_isboolean(L, 2) ? lua_toboolean(L, 2) : true;
if (!anchor) {
return 0;
}
/* If disabling, parse the owner string only. */
if (!enable) {
knot_dname_t *owner = knot_dname_from_str(NULL, anchor, KNOT_DNAME_MAXLEN);
if (!owner) {
lua_pushstring(L, "invalid trust anchor owner");
lua_error(L);
}
lua_pushboolean(L, kr_ta_del(&engine->resolver.trust_anchors, owner) == 0);
free(owner);
return 1;
}
/* Parse the record */
zs_scanner_t *zs = malloc(sizeof(*zs));
if (!zs || zs_init(zs, ".", 1, 0) != 0) {
free(zs);
lua_pushstring(L, "not enough memory");
lua_error(L);
}
int ok = zs_set_input_string(zs, anchor, strlen(anchor)) == 0 &&
zs_parse_all(zs) == 0;
/* Add it to TA set and cleanup */
if (ok) {
ok = kr_ta_add(&engine->resolver.trust_anchors,
zs->r_owner, zs->r_type, zs->r_ttl, zs->r_data, zs->r_data_length) == 0;
}
zs_deinit(zs);
free(zs);
/* Report errors */
if (!ok) {
lua_pushstring(L, "failed to process trust anchor RR");
lua_error(L);
}
lua_pushboolean(L, true);
return 1;
}
/** Unpack JSON object to table */
static void l_unpack_json(lua_State *L, JsonNode *table)
{
......@@ -394,6 +441,8 @@ static int init_state(struct engine *engine)
lua_setglobal(engine->L, "option");
lua_pushcfunction(engine->L, l_setuser);
lua_setglobal(engine->L, "user");
lua_pushcfunction(engine->L, l_trustanchor);
lua_setglobal(engine->L, "trustanchor");
lua_pushcfunction(engine->L, l_libpath);
lua_setglobal(engine->L, "libpath");
lua_pushliteral(engine->L, MODULEDIR);
......
......@@ -11,7 +11,7 @@ local bit = require('bit')
local bor = bit.bor
local band = bit.band
local C = ffi.C
local knot = ffi.load(libpath('libknot', '1'))
local knot = ffi.load(libpath('libknot', '2'))
ffi.cdef[[
/*
......
-- Fetch over HTTPS with peert cert checked
local function https_fetch(url, ca)
local ssl_ok, https = pcall(require, 'ssl.https')
local ltn_ok, ltn12 = pcall(require, 'ltn12')
if not ssl_ok or not ltn_ok then
return nil, 'luasec and luasocket needed for root TA bootstrap'
end
local resp = {}
local r, c, h, s = https.request{
url = url,
cafile = ca,
verify = {'peer', 'fail_if_no_peer_cert' },
protocol = 'tlsv1_2',
sink = ltn12.sink.table(resp),
}
if r == nil then return r, c end
return resp[1]
end
-- Fetch root anchors in XML over HTTPS
local function bootstrap(url, ca)
-- @todo ICANN certificate is verified against current CA
-- this is not ideal, as it should rather verify .xml signature which
-- is signed by ICANN long-lived cert, but luasec has no PKCS7
ca = ca or etcdir..'/icann-ca.pem'
url = url or 'https://data.iana.org/root-anchors/root-anchors.xml'
local xml, err = https_fetch(url, ca)
if not xml then
return false, string.format('[ ta ] fetch of "%s" failed: %s', url, err)
end
-- Parse root trust anchor
local fields = {}
string.gsub(xml, "<([%w]+).->([^<]+)</[%w]+>", function (k, v) fields[k] = v end)
local rrdata = string.format('%s %s %s %s', fields.KeyDigest, fields.Algorithm, fields.DigestType, fields.Digest)
local rr = string.format('%s 0 IN DS %s', fields.TrustAnchor, rrdata)
-- Add to key set, create an empty keyset file to be filled
print('[ ta ] warning: root anchor bootstrapped, you SHOULD check the key manually, see: '..
'https://data.iana.org/root-anchors/draft-icann-dnssec-trust-anchor.html#sigs')
return rr
end
-- Load the module (check for FFI)
local ffi_ok, ffi = pcall(require, 'ffi')
if not ffi_ok then
return { error = 'FFI not available, trust_anchors disabled.' }
-- Simplified TA management, no RFC5011 automatics
return {
-- Reuse Lua/C global function
add = trustanchor,
-- Simplified trust anchor management
config = function (path)
if not path then return end
if not io.open(path, 'r') then
local rr, err = bootstrap()
if not rr then print(err) return false end
io.open(path, 'w'):write(rr..'\n')
end
for line in io.lines(path) do
trustanchor(line)
end
end,
-- Disabled
set_insecure = function () error('[ ta ] FFI not available, this function is disabled') end,
}
end
local kres = require('kres')
local C = ffi.C
......@@ -147,25 +207,6 @@ local function keyset_write(keyset, path)
os.rename(path..'.lock', path)
end
-- Fetch over HTTPS with peert cert checked
local function https_fetch(url, ca)
local ssl_ok, https = pcall(require, 'ssl.https')
local ltn_ok, ltn12 = pcall(require, 'ltn12')
if not ssl_ok or not ltn_ok then
return nil, 'luasec and luasocket needed for root TA bootstrap'
end
local resp = {}
local r, c, h, s = https.request{
url = url,
cafile = ca,
verify = {'peer', 'fail_if_no_peer_cert' },
protocol = 'tlsv1_2',
sink = ltn12.sink.table(resp),
}
if r == nil then return r, c end
return resp[1]
end
-- TA store management
local trust_anchors = {
keyset = {},
......@@ -210,19 +251,21 @@ local trust_anchors = {
return true
end,
-- Load keys from a file (managed)
config = function (path, unmanaged, bootstrap)
bootstrap = true
config = function (path, unmanaged)
-- Bootstrap if requested and keyfile doesn't exist
if bootstrap and not io.open(path, 'r') then
if not trust_anchors.bootstrap() then
if not io.open(path, 'r') then
local rr, msg = bootstrap()
print(msg)
if not rr then
error('you MUST obtain the root TA manually, see: '..
'http://knot-resolver.readthedocs.org/en/latest/daemon.html#enabling-dnssec')
end
trustanchor(rr)
elseif path == trust_anchors.file_current then
return
end
-- Parse new keys
local new_keys = require('zonefile').parse_file(path)
local new_keys = require('zonefile').file(path)
trust_anchors.file_current = path
if unmanaged then trust_anchors.file_current = nil end
trust_anchors.keyset = {}
......@@ -233,11 +276,7 @@ local trust_anchors = {
end,
-- Add DS/DNSKEY record(s) (unmanaged)
add = function (keystr)
local store = kres.context().trust_anchors
return require('zonefile').parser(function (p)
local rr = p:current_rr()
C.kr_ta_add(store, rr.owner, rr.type, rr.ttl, rr.rdata, #rr.rdata)
end):read(keystr..'\n')
return trustanchor(keystr)
end,
-- Negative TA management
set_insecure = function (list)
......@@ -249,33 +288,6 @@ local trust_anchors = {
end
trust_anchors.insecure = list
end,
bootstrap = function (url, ca)
-- Fetch root anchors in XML over HTTPS
-- @todo ICANN certificate is verified against current CA
-- this is not ideal, as it should rather verify .xml signature which
-- is signed by ICANN long-lived cert, but luasec has no PKCS7
ca = ca or etcdir..'/icann-ca.pem'
url = url or 'https://data.iana.org/root-anchors/root-anchors.xml'
local xml, err = https_fetch(url, ca)
if not xml then
print(string.format('[ ta ] fetch of "%s" failed: %s', url, err))
return false
end
-- Parse root trust anchor
local fields = {}
string.gsub(xml, "<([%w]+).->([^<]+)</[%w]+>", function (k, v) fields[k] = v end)
local rrdata = string.format('%s %s %s %s', fields.KeyDigest, fields.Algorithm, fields.DigestType, fields.Digest)
local rr = string.format('%s 0 IN DS %s', fields.TrustAnchor, rrdata)
-- Add to key set, create an empty keyset file to be filled
if trust_anchors.add(rr) ~= 0 then
print(string.format('[ ta ] invalid format of the RR "%s"', rr))
return false
end
print(string.format('[ ta ] bootstrapped root anchor "%s"', rrdata))
print('[ ta ] warning: you SHOULD check the key manually, see: '..
'https://data.iana.org/root-anchors/draft-icann-dnssec-trust-anchor.html#sigs')
return true
end,
}
return trust_anchors
\ No newline at end of file
......@@ -30,7 +30,7 @@ The following is a list of software required to build Knot DNS Resolver from sou
"`GNU Make`_ 3.80+", "*all*", "*(build only)*"
"`pkg-config`_", "*all*", "*(build only)* [#]_"
"C compiler", "*all*", "*(build only)* [#]_"
"libknot_ 2.0+", "*all*", "Knot DNS library (requires autotools, GnuTLS and Jansson)."
"libknot_ 2.1+", "*all*", "Knot DNS library (requires autotools, GnuTLS and Jansson)."
"LuaJIT_ 2.0+", "``daemon``", "Embedded scripting language."
"libuv_ 1.7+", "``daemon``", "Multiplatform I/O and services (libuv_ 1.0 with limitations [#]_)."
......@@ -45,7 +45,6 @@ There are also *optional* packages that enable specific functionality in Knot DN
"hiredis_", "``modules/redis``", "To build redis backend module."
"Go_ 1.5+", "``modules``", "Build modules written in Go."
"cmocka_", "``unit tests``", "Unit testing framework."
"Python_", "``integration tests``", "For test scripts."
"Doxygen_", "``documentation``", "Generating API documentation."
"Sphinx_", "``documentation``", "Building this HTML/PDF documentation."
"breathe_", "``documentation``", "Exposing Doxygen API doc to Sphinx."
......@@ -169,31 +168,37 @@ By default the resolver library is built as a dynamic library with versioned ABI
When the library is linked statically, it usually produces a smaller binary. However linking it to various C modules might violate ODR and increase the size.
Building dependencies
~~~~~~~~~~~~~~~~~~~~~
Resolving dependencies
~~~~~~~~~~~~~~~~~~~~~~
Several dependencies may not be in the packages yet, the script pulls and installs all dependencies in a chroot.
You can avoid rebuilding dependencies by specifying `BUILD_IGNORE` variable, see the Dockerfile_ for example.
Usually you only really need to rebuild libknot_.
The build system relies on `pkg-config`_ to find dependencies.
You can override it to force custom versions of the software by environment variables.
.. code-block:: bash
$ export FAKEROOT="${HOME}/.local"
$ export PKG_CONFIG_PATH="${FAKEROOT}/lib/pkgconfig"
$ export BUILD_IGNORE="..." # Ignore installed dependencies
$ ./scripts/bootstrap-depends.sh ${FAKEROOT}
$ make libknot_CFLAGS="-I/opt/include" libknot_LIBS="-L/opt/lib -lknot -ldnssec"
.. note:: The build system relies on `pkg-config`_ to find dependencies.
You can override it to force custom versions of the software by environment variables.
Optional dependencies may be disabled as well using ``HAS_x=yes|no`` variable.
.. code-block:: bash
.. code-block:: bash
$ make libknot_CFLAGS="-I/opt/include" libknot_LIBS="-L/opt/lib -lknot -lknot-int -ldnssec"
$ make HAS_go=no HAS_cmocka=no
.. warning:: If the dependencies lie outside of library search path, you need to add them somehow.
Try ``LD_LIBRARY_PATH`` on Linux/BSD, and ``DYLD_FALLBACK_LIBRARY_PATH`` on OS X.
Otherwise you need to add the locations to linker search path.
Several dependencies may not be in the packages yet, the script pulls and installs all dependencies in a chroot.
You can avoid rebuilding dependencies by specifying `BUILD_IGNORE` variable, see the Dockerfile_ for example.
Usually you only really need to rebuild libknot_.
.. code-block:: bash
$ export FAKEROOT="${HOME}/.local"
$ export PKG_CONFIG_PATH="${FAKEROOT}/lib/pkgconfig"
$ export BUILD_IGNORE="..." # Ignore installed dependencies
$ ./scripts/bootstrap-depends.sh ${FAKEROOT}
Building extras
~~~~~~~~~~~~~~~
......
......@@ -69,7 +69,7 @@ int kr_authenticate_referral(const knot_rrset_t *ref, const dnssec_key_t *key)
.size = knot_rdata_rdlen(rd),
.data = knot_rdata_data(rd)
};
ret = authenticate_ds(key, &ds_rdata, knot_ds_dtype(&ref->rrs, i));
ret = authenticate_ds(key, &ds_rdata, knot_ds_digest_type(&ref->rrs, i));
if (ret == 0) { /* Found a good DS */
break;
}
......
......@@ -81,15 +81,13 @@ local function rpz_parse(action, path)
['\012rpz-tcp-only\0'] = policy.TC,
-- Policy triggers @NYI@
}
local parser = require('zonefile').parser(function (p)
local name = ffi.string(p.r_owner, p.r_owner_length)
local action = ffi.string(p.r_data, p.r_data_length)
local parser = require('zonefile').new()
if not parser:open(path) then error(string.format('failed to parse "%s"', path)) end
while parser:parse() do
local name = ffi.string(parser.r_owner, parser.r_owner_length)
local action = ffi.string(parser.r_data, parser.r_data_length)
rules[name] = action_map[action]
end, function (p)
print(string.format('[policy.rpz] %s: line %d: %s', path,
tonumber(p.line_counter), p:last_error()))
end)
parser:parse_file(path)
end
return rules
end
......
......@@ -3,8 +3,11 @@
--
local ffi = require('ffi')
local libzscanner = ffi.load(libpath('libzscanner', '0'))
local utils = require('kdns.utils')
local libzscanner = ffi.load(libpath('libzscanner', '1'))
ffi.cdef[[
void free(void *ptr);
void *realloc(void *ptr, size_t size);
/*
* Data structures
......@@ -38,9 +41,16 @@ typedef struct {
uint64_t siz, hp, vp;
int8_t lat_sign, long_sign, alt_sign;
} loc_t;
typedef struct zs_state {
static const int NONE = 0;
static const int DATA = 1;
static const int ERROR = 2;
static const int INCLUDE = 3;
static const int EOF = 4;
static const int STOP = 5;
} zs_state_t;
typedef struct scanner zs_scanner_t;
struct scanner {
typedef struct scanner {
int cs;
int top;
int stack[RAGEL_STACK_SIZE];
......@@ -54,7 +64,8 @@ struct scanner {
uint8_t *item_length_location;
uint32_t buffer_length;
uint8_t buffer[MAX_RDATA_LENGTH];
char include_filename[MAX_RDATA_LENGTH + 1];
char include_filename[MAX_RDATA_LENGTH];
char *path;
window_t windows[BITMAP_WINDOWS];
int16_t last_window;
apl_t apl;
......@@ -68,18 +79,29 @@ struct scanner {
uint8_t zone_origin[MAX_DNAME_LENGTH + MAX_LABEL_LENGTH];
uint16_t default_class;
uint32_t default_ttl;
void (*process_record)(zs_scanner_t *);
void (*process_error)(zs_scanner_t *);
void *data;
char *path;
uint64_t line_counter;
int error_code;
uint64_t error_counter;
bool stop;
int state;
struct {
bool automatic;
void (*record)(struct zs_scanner *);
void (*error)(struct zs_scanner *);
void *data;
} process;
struct {
const char *start;
const char *current;
const char *end;
bool eof;
} input;
struct {
char *name;
int descriptor;
} file;
struct {
int code;
uint64_t counter;
bool fatal;
} error;
uint64_t line_counter;
uint32_t r_owner_length;
uint8_t r_owner[MAX_DNAME_LENGTH + MAX_LABEL_LENGTH];
uint16_t r_class;
......@@ -87,72 +109,115 @@ struct scanner {
uint16_t r_type;
uint32_t r_data_length;
uint8_t r_data[MAX_RDATA_LENGTH];
};
} zs_scanner_t;
/*
* Function signatures
*/
zs_scanner_t* zs_scanner_create(const char *origin,
const uint16_t rclass,
const uint32_t ttl,
void (*process_record)(zs_scanner_t *),
void (*process_error)(zs_scanner_t *),
void *data);
void zs_scanner_free(zs_scanner_t *scanner);
int zs_scanner_parse(zs_scanner_t *scanner,
const char *start,
const char *end,
const bool final_block);
int zs_scanner_parse_file(zs_scanner_t *scanner,
const char *file_name);
int zs_init(zs_scanner_t *scanner, const char *origin, const uint16_t rclass, const uint32_t ttl);
void zs_deinit(zs_scanner_t *scanner);
int zs_set_input_string(zs_scanner_t *scanner, const char *input, size_t size);
int zs_set_input_file(zs_scanner_t *scanner, const char *file_name);
int zs_parse_record(zs_scanner_t *scanner);
const char* zs_strerror(const int code);
]]
-- Constant table
local zs_state = ffi.new('struct zs_state')
-- Sorted set of records
local bsearch = utils.bsearch
sortedset_t = ffi.typeof('struct { knot_rrset_t *at; int32_t len; int32_t cap; }')
ffi.metatype(sortedset_t, {
__gc = function (set)
for i = 0, tonumber(set.len) - 1 do set.at[i]:init(nil, 0) end
ffi.C.free(set.at)
end,
__len = function (set) return tonumber(set.len) end,
__index = {
newrr = function (set, noinit)
-- Reserve enough memory in buffer
if set.cap == set.len then assert(utils.buffer_grow(set)) end
local nid = set.len
set.len = nid + 1
-- Don't initialize if caller is going to do it immediately
if not noinit then
ffi.fill(set.at + nid, ffi.sizeof(set.at[0]))
end
return set.at[nid]
end,
sort = function (set)
-- Prefetch RR set comparison function
return utils.sort(set.at, tonumber(set.len))
end,
search = function (set, owner)
return bsearch(set.at, tonumber(set.len), owner)
end,
searcher = function (set)
return utils.bsearcher(set.at, tonumber(set.len))
end,
}
})
-- Wrap scanner context
local zs_scanner_t = ffi.typeof('zs_scanner_t')
local const_char_t = ffi.typeof('const char *')
local zs_scanner_t = ffi.typeof('struct scanner')
ffi.metatype( zs_scanner_t, {
__new = function(zs, on_record, on_error)
return ffi.gc(libzscanner.zs_scanner_create('.', 1, 3600, on_record, on_error, nil),
libzscanner.zs_scanner_free)
__gc = function(zs) return libzscanner.zs_deinit(zs) end,
__new = function(ct, origin, class, ttl)
if not class then class = 1 end
if not ttl then ttl = 3600 end
local parser = ffi.new(ct)
libzscanner.zs_init(parser, origin, class, ttl)
return parser
end,
__index = {
parse_file = function(zs, file)
return libzscanner.zs_scanner_parse_file(zs, file)
open = function (zs, file)
assert(ffi.istype(zs, zs_scanner_t))
local ret = libzscanner.zs_set_input_file(zs, file)
if ret ~= 0 then return false, zs:strerr() end
return true
end,
read = function(zs, str)
local buf = ffi.cast(ffi.typeof('const char *'), str)
return libzscanner.zs_scanner_parse(zs, buf, buf + #str, false)
parse = function(zs, input)
assert(ffi.istype(zs, zs_scanner_t))
if input ~= nil then libzscanner.zs_set_input_string(zs, input, #input) end
local ret = libzscanner.zs_parse_record(zs)
-- Return current state only when parsed correctly, otherwise return error
if ret == 0 and zs.state ~= zs_state.ERROR then
return zs.state == zs_state.DATA
else
return false, zs:strerr()
end
end,
current_rr = function(zs)
assert(ffi.istype(zs, zs_scanner_t))
return {owner = ffi.string(zs.r_owner, zs.r_owner_length),
ttl = tonumber(zs.r_ttl),
class = tonumber(zs.r_class),
type = tonumber(zs.r_type),
rdata = ffi.string(zs.r_data, zs.r_data_length)}
end,
last_error = function(zs)
return ffi.string(libzscanner.zs_strerror(zs.error_code))
strerr = function(zs)
assert(ffi.istype(zs, zs_scanner_t))
return ffi.string(libzscanner.zs_strerror(zs.error.code))
end,
},
})
-- Module API
local zonefile = {}
function zonefile.parser(on_record, on_error)
return zs_scanner_t(on_record, on_error)
end
function zonefile.parse_file(file)
local records = {}
local context = zonefile.parser(function (parser)
table.insert(records, parser:current_rr())
end)
if context:parse_file(file) ~= 0 then
return nil
end
return records
end
return zonefile
local rrparser = {
new = zs_scanner_t,
file = function (path)
local zs = zs_scanner_t()
local ok, err = zs:open(path)
if not ok then error(err) end
local results = {}
while zs:parse() do
table.insert(results, zs:current_rr())
end
return results
end,
state = zs_state,
set = sortedset_t,
}
return rrparser
#!/bin/bash
set -e
#set -e
CMOCKA_TAG="cmocka-0.4.1"
CMOCKA_URL="git://git.cryptomilk.org/projects/cmocka.git"
LIBUV_TAG="v1.x"
LIBUV_URL="https://github.com/libuv/libuv.git"
KNOT_TAG="27ccff2"
KNOT_TAG="v2.1.0-rc1"
KNOT_URL="https://github.com/CZ-NIC/knot.git"
GMP_TAG="6.0.0"
GMP_URL="https://gmplib.org/download/gmp/gmp-${GMP_TAG}.tar.xz"
......@@ -15,8 +15,8 @@ NETTLE_TAG="2.7.1"
NETTLE_URL="https://ftp.gnu.org/gnu/nettle/nettle-${NETTLE_TAG}.tar.gz"
GNUTLS_TAG="3.3.12"
GNUTLS_URL="ftp://ftp.gnutls.org/gcrypt/gnutls/v3.3/gnutls-${GNUTLS_TAG}.tar.xz"
LUA_TAG="v2.1"
LUA_URL="http://luajit.org/git/luajit-2.0.git"
LUA_TAG="2.1.0-beta1"
LUA_URL="http://luajit.org/download/LuaJIT-${LUA_TAG}.tar.gz"
HIREDIS_TAG="v0.13.3"
HIREDIS_URL="https://github.com/redis/hiredis.git"
LIBMEMCACHED_TAG="1.0.18"
......@@ -109,7 +109,8 @@ pkg libknot ${KNOT_URL} ${KNOT_TAG} include/libknot \
--disable-static --with-lmdb=no --disable-fastparser --disable-daemon --disable-utilities --disable-documentation
pkg cmocka ${CMOCKA_URL} ${CMOCKA_TAG} include/cmocka.h
pkg libuv ${LIBUV_URL} ${LIBUV_TAG} include/uv.h --disable-static
pkg lua ${LUA_URL} ${LUA_TAG} lib/pkgconfig/luajit.pc amalg install BUILDMODE=dynamic LDFLAGS=-lm PREFIX=${PREFIX}
pkg lua ${LUA_URL} ${LUA_TAG} lib/pkgconfig/luajit.pc install BUILDMODE=dynamic LDFLAGS=-lm PREFIX=${PREFIX}
cat build.log
# remove on successful build
rm -rf ${BUILD_DIR}
Subproject commit fff4394152da11c9f373654576907f63e1321411
Subproject commit e6191b2183f8d79972f6df7c7e0edaf4a5eb2855
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment