Commit 39ab923b authored by Jan Včelák's avatar Jan Včelák 🚀

Merge branch 'packet-api-rewrite' into 'master'

parents b6558976 08a6f84e
......@@ -162,16 +162,27 @@ src/libknot/dnssec/zone-sign.h
src/libknot/edns.c
src/libknot/edns.h
src/libknot/libknot.h
src/libknot/nameserver/axfr.c
src/libknot/nameserver/axfr.h
src/libknot/nameserver/chaos.c
src/libknot/nameserver/chaos.h
src/libknot/nameserver/internet.c
src/libknot/nameserver/internet.h
src/libknot/nameserver/ixfr.c
src/libknot/nameserver/ixfr.h
src/libknot/nameserver/name-server.c
src/libknot/nameserver/name-server.h
src/libknot/packet/packet.c
src/libknot/packet/packet.h
src/libknot/packet/query.c
src/libknot/packet/query.h
src/libknot/packet/response.c
src/libknot/packet/response.h
src/libknot/nameserver/ns_proc_query.c
src/libknot/nameserver/ns_proc_query.h
src/libknot/nameserver/nsec_proofs.c
src/libknot/nameserver/nsec_proofs.h
src/libknot/nameserver/update.c
src/libknot/nameserver/update.h
src/libknot/packet/compr.c
src/libknot/packet/compr.h
src/libknot/packet/pkt.c
src/libknot/packet/pkt.h
src/libknot/packet/wire.h
src/libknot/rdata.h
src/libknot/rrset-dump.c
src/libknot/rrset-dump.h
......@@ -194,7 +205,6 @@ src/libknot/util/tolower.c
src/libknot/util/tolower.h
src/libknot/util/utils.c
src/libknot/util/utils.h
src/libknot/util/wire.h
src/libknot/zone/node.c
src/libknot/zone/node.h
src/libknot/zone/zone-contents.c
......@@ -271,6 +281,8 @@ tests/fdset.c
tests/hattrie.c
tests/hhash.c
tests/journal.c
tests/ns.c
tests/pkt.c
tests/rrl.c
tests/rrset.c
tests/runtests.c
......
......@@ -108,14 +108,12 @@ libknot_la_SOURCES = \
libknot/util/utils.h \
libknot/util/tolower.h \
libknot/util/tolower.c \
libknot/util/wire.h \
libknot/util/endian.h \
libknot/packet/query.c \
libknot/packet/response.c \
libknot/packet/packet.c \
libknot/packet/packet.h \
libknot/packet/query.h \
libknot/packet/response.h \
libknot/packet/pkt.c \
libknot/packet/pkt.h \
libknot/packet/compr.c \
libknot/packet/compr.h \
libknot/packet/wire.h \
libknot/zone/zone.c \
libknot/zone/zone-contents.c \
libknot/zone/zone-tree.c \
......@@ -128,10 +126,22 @@ libknot_la_SOURCES = \
libknot/zone/node.c \
libknot/zone/zone-diff.h \
libknot/zone/zone-diff.c \
libknot/nameserver/nsec_proofs.h \
libknot/nameserver/nsec_proofs.c \
libknot/nameserver/name-server.h \
libknot/nameserver/name-server.c \
libknot/nameserver/chaos.h \
libknot/nameserver/chaos.c \
libknot/nameserver/internet.h \
libknot/nameserver/internet.c \
libknot/nameserver/axfr.h \
libknot/nameserver/axfr.c \
libknot/nameserver/ixfr.h \
libknot/nameserver/ixfr.c \
libknot/nameserver/update.h \
libknot/nameserver/update.c \
libknot/nameserver/ns_proc_query.h \
libknot/nameserver/ns_proc_query.c \
libknot/updates/changesets.h \
libknot/updates/changesets.c \
libknot/updates/xfr-in.h \
......
......@@ -26,6 +26,7 @@
#include "common/errcode.h"
#include "common/acl.h"
#include "libknot/util/endian.h"
#include "libknot/tsig.h"
static inline uint32_t ipv4_chunk(const sockaddr_t *a)
{
......@@ -81,7 +82,7 @@ static uint32_t acl_fill_mask32(short nbits)
return htonl(r);
}
static int acl_compare(const sockaddr_t *a1, const sockaddr_t *a2)
static int addr_match(const sockaddr_t *a1, const sockaddr_t *a2)
{
int ret = 0;
uint32_t mask = 0xffffffff;
......@@ -141,55 +142,27 @@ void acl_delete(acl_t **acl)
*acl = 0;
}
int acl_insert(acl_t *acl, const sockaddr_t *addr, void *val)
int acl_insert(acl_t *acl, const sockaddr_t *addr, knot_tsig_key_t *key)
{
if (acl == NULL || addr == NULL) {
return KNOT_EINVAL;
}
/* Create new match. */
acl_match_t *key = malloc(sizeof(acl_match_t));
if (key == NULL) {
acl_match_t *match = malloc(sizeof(acl_match_t));
if (match == NULL) {
return KNOT_ENOMEM;
}
memcpy(&key->addr, addr, sizeof(sockaddr_t));
key->val = val;
/* Sort by prefix length.
* This way the longest prefix match always goes first.
*/
if (EMPTY_LIST(*acl)) {
add_head(acl, &key->n);
} else {
bool inserted = false;
acl_match_t *cur = NULL, *prev = NULL;
WALK_LIST(cur, *acl) {
/* Next node prefix is equal/shorter than current key.
* This means we need to insert before the next node.
*/
if (cur->addr.prefix < addr->prefix) {
if (prev == NULL) { /* First node. */
add_head(acl, &key->n);
} else {
insert_node(&key->n, &prev->n);
}
inserted = true;
break;
}
prev = cur;
}
sockaddr_copy(&match->addr, addr);
match->key = key;
/* Didn't find any better fit, insert at the end. */
if (!inserted) {
add_tail(acl, &key->n);
}
}
add_tail(acl, &match->n);
return KNOT_EOK;
}
acl_match_t* acl_find(acl_t *acl, const sockaddr_t *addr)
acl_match_t* acl_find(acl_t *acl, const sockaddr_t *addr, const knot_dname_t *key_name)
{
if (acl == NULL || addr == NULL) {
return NULL;
......@@ -197,11 +170,25 @@ acl_match_t* acl_find(acl_t *acl, const sockaddr_t *addr)
acl_match_t *cur = NULL;
WALK_LIST(cur, *acl) {
/* Since the list is sorted by prefix length, the first match
* is guaranteed to be longest prefix match (most precise).
*/
if (acl_compare(&cur->addr, addr) == 0) {
return cur;
if (addr_match(&cur->addr, addr) == 0) {
/* NOKEY entry. */
if (cur->key == NULL) {
if (key_name == NULL) {
return cur;
}
/* NOKEY entry, but key provided. */
continue;
}
/* NOKEY provided, but key required. */
if (key_name == NULL) {
continue;
}
/* Key name match. */
if (knot_dname_is_equal(cur->key->name, key_name)) {
return cur;
}
}
}
......
......@@ -32,6 +32,10 @@
#include "common/lists.h"
#include "common/sockaddr.h"
#include "common/mempattern.h"
#include "libknot/tsig.h"
struct knot_tsig_key;
/*! \brief ACL structure. */
typedef list_t acl_t;
......@@ -40,7 +44,7 @@ typedef list_t acl_t;
typedef struct acl_match {
node_t n;
sockaddr_t addr; /*!< \brief Address for comparison. */
void *val; /*!< \brief Associated value (or NULL). */
struct knot_tsig_key *key; /*!< \brief TSIG key. */
} acl_match_t;
/*!
......@@ -69,7 +73,7 @@ void acl_delete(acl_t **acl);
* \retval KNOT_EINVAL
* \retval KNOT_ENOMEM
*/
int acl_insert(acl_t *acl, const sockaddr_t *addr, void *val);
int acl_insert(acl_t *acl, const sockaddr_t *addr, knot_tsig_key_t *key);
/*!
* \brief Match address against ACL.
......@@ -80,7 +84,7 @@ int acl_insert(acl_t *acl, const sockaddr_t *addr, void *val);
* \retval Matching rule instance if found.
* \retval NULL if it didn't find a match.
*/
acl_match_t* acl_find(acl_t *acl, const sockaddr_t *addr);
acl_match_t* acl_find(acl_t *acl, const sockaddr_t *addr, const knot_dname_t *key_name);
/*!
* \brief Truncate ACL.
......
......@@ -384,7 +384,7 @@ void hhash_build_index(hhash_t* tbl)
/* Free old index. */
if (tbl->index) {
if (tbl->mm.free) {
free(tbl->index);
tbl->mm.free(tbl->index);
}
tbl->index = NULL;
}
......
......@@ -177,3 +177,51 @@ size_t list_size(const list_t *l)
return count;
}
/**
* ptrlist_add - add pointer to pointer list
* @to: destination list
* @val: added pointer
* @mm: memory context
*/
ptrnode_t *ptrlist_add(list_t *to, const void *val, mm_ctx_t *mm)
{
ptrnode_t *node = mm->alloc(mm->ctx, sizeof(ptrnode_t));
if (node == NULL) {
return NULL;
} else {
node->d = val;
}
add_tail(to, &node->n);
return node;
}
/**
* ptrlist_free - free all nodes in pointer list
* @list: list nodes
* @mm: memory context
*/
void ptrlist_free(list_t *list, mm_ctx_t *mm)
{
node_t *n = NULL, *nxt = NULL;
WALK_LIST_DELSAFE(n, nxt, *list) {
mm->free(n);
}
init_list(list);
}
/**
* ptrlist_contains - check if list contains pointer
* @list: target list
* @val: searched pointer
*/
bool ptrlist_contains(list_t *list, const void *val)
{
ptrnode_t *n = NULL;
WALK_LIST(n, *list) {
if (n->d == val) {
return true;
}
}
return false;
}
......@@ -83,13 +83,19 @@ void insert_node(node_t *, node_t *);
void list_dup(list_t *dst, list_t *src, size_t itemsz);
size_t list_size(const list_t *);
#include <stdbool.h>
#include "common/mempattern.h"
/*!
* \brief List item for string lists.
* \brief Generic pointer list implementation.
*/
typedef struct strnode_t {
typedef struct ptrnode {
node_t n;
char *str;
} strnode_t;
const void *d;
} ptrnode_t;
ptrnode_t *ptrlist_add(list_t *, const void *, mm_ctx_t *);
void ptrlist_free(list_t *, mm_ctx_t *);
bool ptrlist_contains(list_t *, const void *);
/*! \todo This is broken atm.
#ifndef _BIRD_LISTS_C_
......
......@@ -27,6 +27,7 @@
#include "common/mempattern.h"
#include "common/log.h"
#include "common/slab/alloc-common.h"
#include "common/mempool.h"
static void *mm_malloc(void *ctx, size_t n)
{
......@@ -41,6 +42,13 @@ void mm_ctx_init(mm_ctx_t *mm)
mm->free = free;
}
void mm_ctx_mempool(mm_ctx_t *mm, size_t chunk_size)
{
mm->ctx = mp_new(chunk_size);
mm->alloc = (mm_alloc_t)mp_alloc;
mm->free = mm_nofree;
}
void* xmalloc(size_t l)
{
void *p = malloc(l);
......
......@@ -47,6 +47,9 @@ typedef struct mm_ctx {
/*! \brief Initialize default memory allocation context. */
void mm_ctx_init(mm_ctx_t *mm);
/*! \brief Memory pool context. */
void mm_ctx_mempool(mm_ctx_t *mm, size_t chunk_size);
/*! \brief Allocate memory or die. */
void* xmalloc(size_t l);
......
......@@ -33,6 +33,7 @@
#include "libknot/dname.h"
#include "libknot/binary.h"
#include "libknot/edns.h"
#include "knot/server/rrl.h"
#include "knot/conf/conf.h"
#include "knot/conf/libknotd_la-cf-parse.h" /* Automake generated header. */
......@@ -652,7 +653,7 @@ system:
SET_SIZE(new_config->rrl_size, $3.i, "rate-limit-size");
}
| system RATE_LIMIT_SLIP NUM ';' {
SET_INT(new_config->rrl_slip, $3.i, "rate-limit-slip");
SET_NUM(new_config->rrl_slip, $3.i, 1, RRL_SLIP_MAX, "rate-limit-slip");
}
| system TRANSFERS NUM ';' {
SET_INT(new_config->xfers, $3.i, "transfers");
......
......@@ -443,7 +443,7 @@ static int conf_process(conf_t *conf)
sockaddr_init(&addr, -1);
sockaddr_set(&addr, i->family, i->address, 0);
sockaddr_setprefix(&addr, i->prefix);
acl_insert(conf->ctl.acl, &addr, i);
acl_insert(conf->ctl.acl, &addr, i->key);
}
return ret;
......
......@@ -34,9 +34,7 @@
#include "knot/zone/zone-load.h"
#include "knot/server/socket.h"
#include "knot/server/tcp-handler.h"
#include "libknot/util/wire.h"
#include "libknot/packet/query.h"
#include "libknot/packet/response.h"
#include "libknot/packet/wire.h"
#include "knot/zone/zone-load.h"
#include "knot/zone/estimator.h"
......@@ -137,46 +135,46 @@ static int cmd_remote_print_reply(const knot_rrset_t *rr)
static int cmd_remote_reply(int c)
{
uint8_t *rwire = malloc(SOCKET_MTU_SZ);
knot_packet_t *reply = knot_packet_new();
if (!rwire || !reply) {
free(rwire);
knot_packet_free(&reply);
knot_pkt_t *pkt = knot_pkt_new(NULL, KNOT_WIRE_MAX_PKTSIZE, NULL);
if (!pkt) {
return KNOT_ENOMEM;
}
/* Read response packet. */
int n = tcp_recv(c, rwire, SOCKET_MTU_SZ, NULL);
int n = tcp_recv(c, pkt->wire, pkt->max_size, NULL);
if (n <= 0) {
dbg_server("remote: couldn't receive response = %d\n", n);
knot_packet_free(&reply);
free(rwire);
dbg_server("remote: couldn't receive response = %s\n", knot_strerror(n));
knot_pkt_free(&pkt);
return KNOT_ECONN;
} else {
pkt->size = n;
}
/* Parse packet and check response. */
int ret = remote_parse(reply, rwire, n);
if (ret == KNOT_EOK) {
/* Check RCODE */
ret = knot_packet_rcode(reply);
switch(ret) {
case KNOT_RCODE_NOERROR:
if (knot_packet_authority_rrset_count(reply) > 0) {
ret = cmd_remote_print_reply(reply->authority[0]);
}
break;
case KNOT_RCODE_REFUSED:
ret = KNOT_EDENIED;
break;
default:
ret = KNOT_ERROR;
break;
int ret = remote_parse(pkt);
if (ret != KNOT_EOK) {
knot_pkt_free(&pkt);
return ret;
}
/* Check RCODE */
const knot_pktsection_t *authority = knot_pkt_section(pkt, KNOT_AUTHORITY);
ret = knot_wire_get_rcode(pkt->wire);
switch(ret) {
case KNOT_RCODE_NOERROR:
if (authority->count > 0) {
ret = cmd_remote_print_reply(authority->rr[0]);
}
break;
case KNOT_RCODE_REFUSED:
ret = KNOT_EDENIED;
break;
default:
ret = KNOT_ERROR;
break;
}
/* Response cleanup. */
knot_packet_free(&reply);
free(rwire);
knot_pkt_free(&pkt);
return ret;
}
......@@ -193,16 +191,15 @@ static int cmd_remote(const char *cmd, uint16_t rrt, int argc, char *argv[])
}
/* Make query. */
uint8_t *buf = NULL;
size_t buflen = 0;
knot_packet_t *qr = remote_query(cmd, r->key);
if (!qr) {
knot_pkt_t *pkt = remote_query(cmd, r->key);
if (!pkt) {
log_server_warning("Could not prepare query for '%s'.\n",
cmd);
return 1;
}
/* Build query data. */
knot_pkt_begin(pkt, KNOT_AUTHORITY);
knot_rrset_t *rr = NULL;
if (argc > 0) {
rr = remote_build_rr("data.", rrt);
......@@ -217,23 +214,30 @@ static int cmd_remote(const char *cmd, uint16_t rrt, int argc, char *argv[])
break;
}
}
remote_query_append(qr, rr);
}
if (knot_packet_to_wire(qr, &buf, &buflen) != KNOT_EOK) {
knot_rrset_deep_free(&rr, 1);
knot_packet_free(&qr);
return 1;
int res = knot_pkt_put(pkt, 0, rr, KNOT_PF_FREE);
if (res != KNOT_EOK) {
log_server_error("Couldn't create the query.\n");
knot_rrset_deep_free(&rr, 1);
knot_pkt_free(&pkt);
return 1;
}
}
if (r->key) {
remote_query_sign(buf, &buflen, qr->max_size, r->key);
int res = remote_query_sign(pkt->wire, &pkt->size, pkt->max_size, r->key);
if (res != KNOT_EOK) {
log_server_error("Couldn't sign the packet.\n");
knot_pkt_free(&pkt);
return 1;
}
}
dbg_server("%s: sending query size %zu\n", __func__, pkt->size);
/* Send query. */
int s = socket_create(r->family, SOCK_STREAM, 0);
int conn_state = socket_connect(s, r->family, r->address, r->port);
if (conn_state != KNOT_EOK || tcp_send(s, buf, buflen) <= 0) {
if (conn_state != KNOT_EOK || tcp_send(s, pkt->wire, pkt->size) <= 0) {
char portstr[32] = { '\0' };
if (r->family != AF_UNIX)
snprintf(portstr, sizeof(portstr), "@%d", r->port);
......@@ -256,12 +260,13 @@ static int cmd_remote(const char *cmd, uint16_t rrt, int argc, char *argv[])
}
/* Cleanup. */
if (rc == 0) printf("\n");
knot_rrset_deep_free(&rr, 1);
if (rc == 0) {
printf("\n");
}
/* Close connection. */
socket_close(s);
knot_packet_free(&qr);
knot_pkt_free(&pkt);
return rc;
}
......
This diff is collapsed.
......@@ -28,7 +28,7 @@
#define _KNOTD_REMOTE_H_
#include "knot/conf/conf.h"
#include "libknot/packet/packet.h"
#include "libknot/packet/pkt.h"
#include "libknot/rrset.h"
#include "libknot/dnssec/key.h"
#include "knot/server/server.h"
......@@ -81,14 +81,12 @@ int remote_recv(int r, sockaddr_t *a, uint8_t* buf, size_t *buflen);
/*!
* \brief Parse a RC command.
*
* \param pkt Dst structure for parsed command.
* \param buf Remote command in wire format.
* \param buflen Wire format length.
* \param pkt Query packet.
*
* \retval KNOT_EOK on success.
* \retval knot_error else.
*/
int remote_parse(knot_packet_t* pkt, const uint8_t* buf, size_t buflen);
int remote_parse(knot_pkt_t* pkt);
/*!
* \brief Execute command and prepare answer for client.
......@@ -102,7 +100,7 @@ int remote_parse(knot_packet_t* pkt, const uint8_t* buf, size_t buflen);
* \retval KNOT_EOK on success.
* \retval knot_error else.
*/
int remote_answer(int fd, server_t *s, knot_packet_t *pkt, uint8_t* rwire, size_t rlen);
int remote_answer(int fd, server_t *s, knot_pkt_t *pkt);
/*!
* \brief Accept new client, receive command, process it and send response.
......@@ -111,14 +109,14 @@ int remote_answer(int fd, server_t *s, knot_packet_t *pkt, uint8_t* rwire, size_
*
* \param s Server instance.
* \param ctl_if Control interface.
* \param r RC interface socket.
* \param sock RC interface socket.
* \param buf Buffer for commands/responses.
* \param buflen Maximum buffer size.
*
* \retval KNOT_EOK on success.
* \retval knot_error else.
*/
int remote_process(server_t *s, conf_iface_t *ctl_if, int r,
int remote_process(server_t *s, conf_iface_t *ctl_if, int sock,
uint8_t* buf, size_t buflen);
/* Functions for creating RC packets. */
......@@ -134,18 +132,7 @@ int remote_process(server_t *s, conf_iface_t *ctl_if, int r,
* \retval KNOT_EOK on success.
* \retval knot_error else.
*/
knot_packet_t* remote_query(const char *query, const knot_tsig_key_t *key);
/*!
* \brief Append extra data to RC command packet.
*
* \param qry RC packet.
* \param data Extra data in form of a RR set.
*
* \retval KNOT_EOK on success.
* \retval knot_error else.
*/
int remote_query_append(knot_packet_t *qry, knot_rrset_t *data);
knot_pkt_t* remote_query(const char *query, const knot_tsig_key_t *key);
/*!
* \brief Sign a RC command packet using TSIG key.
......
......@@ -35,7 +35,6 @@
#include "common/errcode.h"
#include "knot/other/debug.h"
#define CPU_ESTIMATE_MAGIC 0 /*!< \brief Extra threads to the number of cores.*/
#define DEFAULT_THR_COUNT 2 /*!< \brief Default thread count. */
#define TCP_BACKLOG_SIZE 10 /*!< \brief TCP listen backlog size. */
#define XFR_THREADS_COUNT 3 /*!< \brief Number of threads for XFR handler. */
......
......@@ -347,8 +347,7 @@ int main(int argc, char **argv)
int res = 0;
log_server_info("Starting server...\n");
if ((server_start(server)) == KNOT_EOK) {
size_t zcount = server->nameserver->zone_db->count;
if (!zcount) {
if (!knot_zonedb_size(server->nameserver->zone_db)) {
log_server_warning("Server started, but no zones served.\n");
}
......
......@@ -286,7 +286,7 @@ static void dt_delete_thread(dthread_t **thread)
* Public APIs.
*/
dt_unit_t *dt_create(int count)
static dt_unit_t *dt_create_unit(int count)
{
// Check count
if (count <= 0) {
......@@ -379,8 +379,7 @@ dt_unit_t *dt_create(int count)
return unit;
}
dt_unit_t *dt_create_coherent(int count, runnable_t runnable,
runnable_t destructor, void *data)
dt_unit_t *dt_create(int count, runnable_t runnable, runnable_t destructor, void *data)
{
// Check count
if (count <= 0) {
......@@ -388,7 +387,7 @@ dt_unit_t *dt_create_coherent(int count, runnable_t runnable,
}
// Create unit
dt_unit_t *unit = dt_create(count);
dt_unit_t *unit = dt_create_unit(count);
if (unit == 0) {
return 0;
}
......@@ -452,39 +451,7 @@ void dt_delete(dt_unit_t **unit)
*unit = 0;
}
int dt_start(dt_unit_t *unit)
{
// Check input
if (unit == 0) {
return KNOT_EINVAL;
}
// Lock unit
pthread_mutex_lock(&unit->_notify_mx);
dt_unit_lock(unit);
for (int i = 0; i < unit->size; ++i) {
dthread_t *thread = unit->threads[i];
int res = dt_start_id(thread);
if (res != 0) {
dbg_dt("dthreads: failed to create thread '%d'.", i);
dt_unit_unlock(unit);
pthread_mutex_unlock(&unit->_notify_mx);
return res;
}
dbg_dt("dthreads: [%p] %s: thread started\n",
thread, __func__);
}
// Unlock unit
dt_unit_unlock(unit);
pthread_cond_broadcast(&unit->_notify);
pthread_mutex_unlock(&unit->_notify_mx);
return KNOT_EOK;
}
int dt_start_id(dthread_t *thread)
static int dt_start_id(dthread_t *thread)
{
// Check input
if (thread == 0) {
......@@ -520,6 +487,38 @@ int