summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/acl.c137
-rw-r--r--src/common/descriptor.c49
-rw-r--r--src/common/descriptor.h33
-rw-r--r--src/common/errcode.c2
-rw-r--r--src/common/errcode.h2
5 files changed, 147 insertions, 76 deletions
diff --git a/src/common/acl.c b/src/common/acl.c
index 26d3847..fa20d62 100644
--- a/src/common/acl.c
+++ b/src/common/acl.c
@@ -19,88 +19,99 @@
#include <assert.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <limits.h>
#include "common/acl.h"
+#include "libknot/util/endian.h"
-static inline uint32_t acl_sa_ipv4(sockaddr_t *a) {
+static inline uint32_t ipv4_chunk(sockaddr_t *a)
+{
+ /* Stored as big end first. */
return a->addr4.sin_addr.s_addr;
}
-static inline uint32_t acl_fill_mask32(short c) {
- /*! \todo Consider optimizing using LUT. */
- assert(c >= 0 && c <= 32);
- unsigned r = 0;
- /*! This actually builds big-endian mask
- * as we will match against addresses in
- * network byte-order (big-endian).
- * Otherwise it should be built from
- * HO bit -> LO bit.
- */
- for (char i = 0; i < c; ++i) {
- r |= (1 << i);
- }
- return r;
+static inline uint32_t ipv6_chunk(sockaddr_t *a, uint8_t idx)
+{
+ /* Is byte array, 4x 32bit value. */
+ return ((uint32_t *)&a->addr6.sin6_addr)[idx];
}
-static int acl_compare(void *k1, void *k2)
+static inline uint32_t ip_chunk(sockaddr_t *a, uint8_t idx)
{
- sockaddr_t* a1 = (sockaddr_t *)k1;
- sockaddr_t* a2 = (sockaddr_t *)k2;
+ if (sockaddr_family(a) == AF_INET)
+ return ipv4_chunk(a);
- /* Check different length, IPv4 goes first. */
- int ldiff = a1->len - a2->len;
- if (ldiff != 0) {
- return ldiff < 0 ? -1 : 1;
- }
+ return ipv6_chunk(a, idx);
+}
- /* Compare integers if IPv4. */
- if (sockaddr_family(a1) == AF_INET) {
+/*! \brief Compare chunks using given mask. */
+static int cmp_chunk(sockaddr_t *a, sockaddr_t *b, uint8_t idx, uint32_t mask)
+{
+ const uint32_t c1 = ip_chunk(a, idx) & mask;
+ const uint32_t c2 = ip_chunk(b, idx) & mask;
- /* Compute mask .*/
- uint32_t mask = acl_fill_mask32(a1->prefix);
+ if (c1 > c2)
+ return 1;
+ if (c1 < c2)
+ return -1;
+ return 0;
+}
- /* Compare address. */
- int cmp1 = (acl_sa_ipv4(a1) & mask);
- int cmp2 = (acl_sa_ipv4(a2) & mask);
- if (cmp1 > cmp2) return 1;
- if (cmp1 < cmp2) return -1;
- return 0;
+/*!
+ * \brief Calculate bitmask for byte array from the MSB.
+ *
+ * \note i.e. 8 means top 8 bits set, 11111111000000000000000000000000
+ *
+ * \param nbits number of bits set to 1
+ * \return mask
+ */
+static uint32_t acl_fill_mask32(short nbits)
+{
+ assert(nbits >= 0 && nbits <= 32);
+ uint32_t r = 0;
+ for (char i = 0; i < nbits; ++i) {
+ r |= 1 << (31 - i);
}
- /* IPv6 matching. */
-#ifndef DISABLE_IPV6
- if (sockaddr_family(a1) == AF_INET6) {
-
- /* Get mask .*/
- short chunk = a1->prefix;
-
- /* Compare address by 32bit chunks. */
- uint32_t* a1p = (uint32_t *)(&a1->addr6.sin6_addr);
- uint32_t* a2p = (uint32_t *)(&a2->addr6.sin6_addr);
-
- /* Mask 0 = 0 bits to compare from LO->HO (in big-endian).
- * Mask 128 = 128 bits to compare.
- */
- while (chunk > 0) {
- uint32_t mask = 0xffffffff;
- if ((size_t)chunk > sizeof(mask) << 3) {
- chunk -= sizeof(mask) << 3;
- } else {
- mask = acl_fill_mask32(chunk);
- chunk = 0;
- }
-
- int cmp1 = (*(a1p++) & mask);
- int cmp2 = (*(a2p++) & mask);
- if (cmp1 > cmp2) return 1;
- if (cmp1 < cmp2) return -1;
+ /* Make sure the mask is in network byte order. */
+ return htonl(r);
+}
+
+static int acl_compare(void *k1, void *k2)
+{
+ int ret = 0;
+ sockaddr_t* a1 = (sockaddr_t *)k1;
+ sockaddr_t* a2 = (sockaddr_t *)k2;
+ uint32_t mask = 0xffffffff;
+ short mask_bits = a1->prefix;
+ const short chunk_bits = sizeof(mask) * CHAR_BIT;
+
+ /* Check different length, IPv4 goes first. */
+ if (a1->len != a2->len) {
+ if (a1->len < a2->len)
+ return -1;
+ else
+ return 1;
+ }
+
+ /* At most 4xchunk_bits for IPv6 */
+ unsigned i = 0;
+ while (ret == 0 && mask_bits > 0) {
+ /* Compute mask for current chunk. */
+ if (mask_bits <= chunk_bits) {
+ mask = acl_fill_mask32(mask_bits);
+ mask_bits = 0; /* Last chunk */
+ } else {
+ mask_bits -= chunk_bits;
}
- return 0;
+ /* Empty mask - shortcut, we're done. */
+ if (mask > 0)
+ ret = cmp_chunk(a1, a2, i, mask);
+ ++i;
}
-#endif
- return 0;
+ return ret;
}
acl_t *acl_new(acl_rule_t default_rule, const char *name)
diff --git a/src/common/descriptor.c b/src/common/descriptor.c
index 233a995..5f2af94 100644
--- a/src/common/descriptor.c
+++ b/src/common/descriptor.c
@@ -76,12 +76,12 @@ static const rdata_descriptor_t rdata_descriptors[] = {
KNOT_RDATA_WF_END }, "KEY" },
[KNOT_RRTYPE_AAAA] = { { 16, KNOT_RDATA_WF_END }, "AAAA" },
[KNOT_RRTYPE_LOC] = { { 16, KNOT_RDATA_WF_END }, "LOC" },
- [KNOT_RRTYPE_SRV] = { { 6, KNOT_RDATA_WF_UNCOMPRESSED_DNAME,
+ [KNOT_RRTYPE_SRV] = { { 6, KNOT_RDATA_WF_COMPRESSED_DNAME,
KNOT_RDATA_WF_END }, "SRV" },
[KNOT_RRTYPE_NAPTR] = { { KNOT_RDATA_WF_NAPTR_HEADER,
- KNOT_RDATA_WF_UNCOMPRESSED_DNAME,
+ KNOT_RDATA_WF_COMPRESSED_DNAME,
KNOT_RDATA_WF_END }, "NAPTR" },
- [KNOT_RRTYPE_KX] = { { 2, KNOT_RDATA_WF_COMPRESSED_DNAME,
+ [KNOT_RRTYPE_KX] = { { 2, KNOT_RDATA_WF_UNCOMPRESSED_DNAME,
KNOT_RDATA_WF_END }, "KX" },
[KNOT_RRTYPE_CERT] = { { KNOT_RDATA_WF_REMAINDER,
KNOT_RDATA_WF_END }, "CERT" },
@@ -97,10 +97,10 @@ static const rdata_descriptor_t rdata_descriptors[] = {
KNOT_RDATA_WF_END }, "SSHFP" },
[KNOT_RRTYPE_IPSECKEY] = { { KNOT_RDATA_WF_REMAINDER,
KNOT_RDATA_WF_END }, "IPSECKEY" },
- [KNOT_RRTYPE_RRSIG] = { { 18, KNOT_RDATA_WF_LITERAL_DNAME,
+ [KNOT_RRTYPE_RRSIG] = { { 18, KNOT_RDATA_WF_UNCOMPRESSED_DNAME,
KNOT_RDATA_WF_REMAINDER,
KNOT_RDATA_WF_END }, "RRSIG" },
- [KNOT_RRTYPE_NSEC] = { { KNOT_RDATA_WF_LITERAL_DNAME,
+ [KNOT_RRTYPE_NSEC] = { { KNOT_RDATA_WF_UNCOMPRESSED_DNAME,
KNOT_RDATA_WF_REMAINDER,
KNOT_RDATA_WF_END }, "NSEC" },
[KNOT_RRTYPE_DNSKEY] = { { KNOT_RDATA_WF_REMAINDER,
@@ -118,7 +118,7 @@ static const rdata_descriptor_t rdata_descriptors[] = {
[KNOT_RRTYPE_NID] = { { 10 }, "NID" },
[KNOT_RRTYPE_L32] = { { 6 }, "L32" },
[KNOT_RRTYPE_L64] = { { 10 }, "L64" },
- [KNOT_RRTYPE_LP] = { { 2, KNOT_RDATA_WF_COMPRESSED_DNAME },
+ [KNOT_RRTYPE_LP] = { { 2, KNOT_RDATA_WF_UNCOMPRESSED_DNAME },
"LP" },
[KNOT_RRTYPE_EUI48] = { { 6, KNOT_RDATA_WF_END }, "EUI48" },
[KNOT_RRTYPE_EUI64] = { { 8, KNOT_RDATA_WF_END }, "EUI64" },
@@ -136,6 +136,30 @@ static const rdata_descriptor_t rdata_descriptors[] = {
KNOT_RDATA_WF_END }, "ANY" },
};
+/*!
+ * \brief Some (OBSOLETE) RR type descriptors.
+ */
+static const rdata_descriptor_t obsolete_rdata_descriptors[] = {
+ [0] = { { KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, NULL },
+ [KNOT_RRTYPE_MD] = { { KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "MD" },
+ [KNOT_RRTYPE_MF] = { { KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "MF" },
+ [KNOT_RRTYPE_MB] = { { KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "MB" },
+ [KNOT_RRTYPE_MG] = { { KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "MG" },
+ [KNOT_RRTYPE_MR] = { { KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "MR" },
+ [KNOT_RRTYPE_PX] = { { 2, KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_END }, "PX" },
+ [KNOT_RRTYPE_NXT] = { { KNOT_RDATA_WF_COMPRESSED_DNAME,
+ KNOT_RDATA_WF_REMAINDER,
+ KNOT_RDATA_WF_END }, "NXT" },
+};
+
const rdata_descriptor_t *get_rdata_descriptor(const uint16_t type)
{
if (type <= KNOT_RRTYPE_ANY && rdata_descriptors[type].type_name != 0) {
@@ -145,6 +169,16 @@ const rdata_descriptor_t *get_rdata_descriptor(const uint16_t type)
}
}
+const rdata_descriptor_t *get_obsolete_rdata_descriptor(const uint16_t type)
+{
+ if (type <= KNOT_RRTYPE_NXT &&
+ obsolete_rdata_descriptors[type].type_name != 0) {
+ return &obsolete_rdata_descriptors[type];
+ } else {
+ return &obsolete_rdata_descriptors[0];
+ }
+}
+
int knot_rrtype_to_string(const uint16_t rrtype,
char *out,
const size_t out_len)
@@ -251,8 +285,7 @@ int knot_rrclass_from_string(const char *name, uint16_t *num)
int descriptor_item_is_dname(const int item)
{
- return item == KNOT_RDATA_WF_LITERAL_DNAME ||
- item == KNOT_RDATA_WF_COMPRESSED_DNAME ||
+ return item == KNOT_RDATA_WF_COMPRESSED_DNAME ||
item == KNOT_RDATA_WF_UNCOMPRESSED_DNAME;
}
diff --git a/src/common/descriptor.h b/src/common/descriptor.h
index d7938cb..f7c2327 100644
--- a/src/common/descriptor.h
+++ b/src/common/descriptor.h
@@ -110,6 +110,25 @@ enum knot_rr_type {
};
/*!
+ * \brief Some (OBSOLETE) resource record type constants.
+ *
+ * http://www.iana.org/assignments/dns-parameters/dns-parameters.xml
+ *
+ * \note These records can contain compressed domain name in rdata so
+ * it is important to know the position of it during transfers.
+ * See RFC 3597#4.
+ */
+enum knot_obsolete_rr_type {
+ KNOT_RRTYPE_MD = 3,
+ KNOT_RRTYPE_MF = 4,
+ KNOT_RRTYPE_MB = 7,
+ KNOT_RRTYPE_MG = 8,
+ KNOT_RRTYPE_MR = 9,
+ KNOT_RRTYPE_PX = 26,
+ KNOT_RRTYPE_NXT = 30
+};
+
+/*!
* \brief Constants characterising the wire format of RDATA items.
*/
enum knot_rdata_wireformat {
@@ -117,8 +136,6 @@ enum knot_rdata_wireformat {
KNOT_RDATA_WF_COMPRESSED_DNAME = -10,
/*!< Uncompressed dname. */
KNOT_RDATA_WF_UNCOMPRESSED_DNAME,
- /*!< Dname with preserved letter cases. */
- KNOT_RDATA_WF_LITERAL_DNAME,
/*!< Initial part of NAPTR record before dname. */
KNOT_RDATA_WF_NAPTR_HEADER,
/*!< Uninteresting final part of a record. */
@@ -140,7 +157,7 @@ typedef struct {
/*!
* \brief Gets rdata descriptor for given RR name.
*
- * \param name Mnemonic of RR type whose descriptor should be retvaled.
+ * \param name Mnemonic of RR type whose descriptor should be returned.
*
* \retval RR descriptor for given name, NULL descriptor if
* unknown type.
@@ -148,6 +165,16 @@ typedef struct {
const rdata_descriptor_t *get_rdata_descriptor(const uint16_t type);
/*!
+ * \brief Gets rdata descriptor for given RR name (obsolete version).
+ *
+ * \param name Mnemonic of RR type whose descriptor should be returned.
+ *
+ * \retval RR descriptor for given name, NULL descriptor if
+ * unknown type.
+ */
+const rdata_descriptor_t *get_obsolete_rdata_descriptor(const uint16_t type);
+
+/*!
* \brief Converts numeric type representation to mnemonic string.
*
* \param rrtype Type RR type code to be converted.
diff --git a/src/common/errcode.c b/src/common/errcode.c
index b555805..50b37dd 100644
--- a/src/common/errcode.c
+++ b/src/common/errcode.c
@@ -52,7 +52,7 @@ const error_table_t knot_error_msgs[] = {
{ KNOT_ECRYPTO, "Error in crypto library." },
{ KNOT_ENSEC3PAR, "Missing or wrong NSEC3PARAM record." },
{ KNOT_ENSEC3CHAIN, "Missing or wrong NSEC3 chain in the zone." },
- { KNOT_EBADZONE, "Name does not belong to the zone." },
+ { KNOT_EOUTOFZONE, "Name does not belong to the zone." },
{ KNOT_EHASH, "Error in hash table." },
{ KNOT_EZONEINVAL, "Invalid zone file." },
{ KNOT_ENOZONE, "No such zone found." },
diff --git a/src/common/errcode.h b/src/common/errcode.h
index 69f6ed5..c29a433 100644
--- a/src/common/errcode.h
+++ b/src/common/errcode.h
@@ -71,7 +71,7 @@ enum knot_error {
KNOT_ECRYPTO, /*!< Error in crypto library. */
KNOT_ENSEC3PAR, /*!< Missing or wrong NSEC3PARAM record. */
KNOT_ENSEC3CHAIN, /*!< Missing or wrong NSEC3 chain in the zone. */
- KNOT_EBADZONE, /*!< Domain name does not belong to the zone. */
+ KNOT_EOUTOFZONE, /*!< Domain name does not belong to the zone. */
KNOT_EHASH, /*!< Error in hash table. */
KNOT_EZONEINVAL, /*!< Invalid zone file. */
KNOT_ENOZONE, /*!< No such zone found. */