diff --git a/CuteDNS.files b/CuteDNS.files
index a09c50bc5a56b7bf38ae3f6baca7189d68c31d4c..c1a6b4428ada4bd5fd0c28d0e8b113fbf030feff 100644
--- a/CuteDNS.files
+++ b/CuteDNS.files
@@ -66,3 +66,5 @@ src/dnslib/consts.h
 src/tests/dnslib/dnslib_dname_tests.c
 src/tests/dnslib/dnslib_rdata_tests.c
 src/tests/dnslib/dnslib_rrset_tests.c
+src/dnslib/descriptor.h
+src/dnslib/descriptor.c
diff --git a/src/dnslib/descriptor.c b/src/dnslib/descriptor.c
index 070bc284117d7017f8caaaf524b91c7ebd7dfc11..91e2cd16aa6323cbfa60d5dc91f7e75a9ca7ccea 100644
--- a/src/dnslib/descriptor.c
+++ b/src/dnslib/descriptor.c
@@ -61,7 +61,7 @@ static dnslib_rrtype_descriptor_t dnslib_rrtype_descriptors[DNSLIB_RRTYPE_DESCRI
   	  { DNSLIB_RDATA_WF_BINARY }, true },
   	/* 11 */
   	{ DNSLIB_RRTYPE_WKS, "WKS", 2,
-  	  { DNSLIB_RDATA_WF_A, DNSLIB_RDATA_WF_BINARY }, true },
+	  { DNSLIB_RDATA_WF_A, DNSLIB_RDATA_WF_BINARY }, true },
   	/* 12 */
   	{ DNSLIB_RRTYPE_PTR, "PTR", 1,
   	  { DNSLIB_RDATA_WF_COMPRESSED_DNAME }, true },
@@ -75,7 +75,7 @@ static dnslib_rrtype_descriptor_t dnslib_rrtype_descriptors[DNSLIB_RRTYPE_DESCRI
   	{ DNSLIB_RRTYPE_MX, "MX", 2,
   	  { DNSLIB_RDATA_WF_SHORT, DNSLIB_RDATA_WF_COMPRESSED_DNAME }, true },
   	/* 16 */ /* This is obscure, but I guess there's no other way */
-  	{ DNSLIB_RRTYPE_TXT, "TXT", MAXRDATALEN,
+	{ DNSLIB_RRTYPE_TXT, "TXT", MAX_RDATA_ITEMS,
   	  { DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT,
   	    DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT,
   	    DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT,
@@ -166,7 +166,7 @@ static dnslib_rrtype_descriptor_t dnslib_rrtype_descriptors[DNSLIB_RRTYPE_DESCRI
   	{ DNSLIB_RRTYPE_OPT, "OPT", 1,
   	  { DNSLIB_RDATA_WF_BINARY }, true },
   	/* 42 */
-  	{ DNSLIB_RRTYPE_APL, "APL", MAXRDATALEN,
+	{ DNSLIB_RRTYPE_APL, "APL", MAX_RDATA_ITEMS,
   	  { DNSLIB_RDATA_WF_APL, DNSLIB_RDATA_WF_APL, DNSLIB_RDATA_WF_APL, DNSLIB_RDATA_WF_APL,
   	    DNSLIB_RDATA_WF_APL, DNSLIB_RDATA_WF_APL, DNSLIB_RDATA_WF_APL, DNSLIB_RDATA_WF_APL,
   	    DNSLIB_RDATA_WF_APL, DNSLIB_RDATA_WF_APL, DNSLIB_RDATA_WF_APL, DNSLIB_RDATA_WF_APL,
@@ -229,7 +229,7 @@ static dnslib_rrtype_descriptor_t dnslib_rrtype_descriptors[DNSLIB_RRTYPE_DESCRI
     /* There's a GNU extension that works like this: [first ... last] = value */
   
   	/* 99 */
-  	[99] = { DNSLIB_RRTYPE_SPF, "SPF", MAXRDATALEN,
+	[99] = { DNSLIB_RRTYPE_SPF, "SPF", MAX_RDATA_ITEMS,
   	  { DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT,
   	    DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT,
   	    DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT, DNSLIB_RDATA_WF_TEXT,
diff --git a/src/dnslib/descriptor.h b/src/dnslib/descriptor.h
index 95b00350f4dfcda17e9ed3779b13ad683f6e7511..465a9a3592e65b1f6b4825e7fb849495ecff123b 100644
--- a/src/dnslib/descriptor.h
+++ b/src/dnslib/descriptor.h
@@ -15,7 +15,12 @@
 
 #include "common.h"
 
-enum mxrdtln { MAXRDATALEN = 64 };
+enum mxrdtln
+{
+	MAX_RDATA_ITEMS = 64,
+	MAX_RDATA_ITEM_SIZE = 255,
+	MAX_RDATA_WIRE_SIZE = MAX_RDATA_ITEMS * MAX_RDATA_ITEM_SIZE
+};
 //#define MAXRDATALEN 64
 
 /* 64 is in NSD. Seems a little too much, but I'd say it's not a real issue. */
@@ -154,7 +159,7 @@ struct dnslib_rrtype_descriptor
   	uint16_t type;	/* RR type */
   	const char *name;	/* Textual name.  */
   	uint8_t length;	/* Maximum number of RDATA items.  */
-  	uint8_t wireformat[MAXRDATALEN]; /* rdata_wireformat_type */
+	uint8_t wireformat[MAX_RDATA_ITEMS]; /* rdata_wireformat_type */
     bool fixed_items; /* Has fixed number of RDATA items? */
 };
 
diff --git a/src/dnslib/rdata.c b/src/dnslib/rdata.c
index bea66afc860a75b5523d0ebd93ae8727b7106b38..51ac0b1cdc96aa0352368b6e8868321d8265510d 100644
--- a/src/dnslib/rdata.c
+++ b/src/dnslib/rdata.c
@@ -4,12 +4,55 @@
 #include <string.h>
 #include "common.h"
 #include "rdata.h"
+#include "descriptor.h"
+#include "dname.h"
+
+/*----------------------------------------------------------------------------*/
+/* Non-API functions                                                          */
+/*----------------------------------------------------------------------------*/
+
+static int dnslib_rdata_compare_binary( const uint8_t *d1, const uint8_t *d2,
+										int count1, int count2 )
+{
+	int i1 = 0, i2 = 0;
+
+	// length stored in the first octet
+	if (count1 < 0) {
+		// take count from the first byte
+		count1 = (int)d1[0];
+		// and start from the second byte
+		i1 = 1;
+	}
+	if (count2 < 0) {	// dtto
+		count2 = (int)d2[0];
+		i2 = 1;
+	}
+
+
+	while (i1 < count1 && i2 < count2 && d1[i1] == d2[i2]) {
+		++i1;
+		++i2;
+	}
+
+	if (i1 == count1 && i2 == count2) {
+		return 0;
+	}
+
+	if (i1 == count1 && i2 < count2) {
+		return -1;
+	} else if (i2 == count2 && i1 < count1) {
+		return 1;
+	} else {
+		assert(i1 < count1 && i2 < count2);
+		return (d1[i1] < d2[i2]) ? -1 : 1;
+	}
+}
 
 /*----------------------------------------------------------------------------*/
 /* API functions                                                              */
 /*----------------------------------------------------------------------------*/
 
-dnslib_rdata_t *dnslib_rdata_new( uint count )
+dnslib_rdata_t *dnslib_rdata_new()
 {
 	dnslib_rdata_t *rdata = (dnslib_rdata_t *)malloc(sizeof(dnslib_rdata_t));
 	if (rdata == NULL) {
@@ -18,15 +61,7 @@ dnslib_rdata_t *dnslib_rdata_new( uint count )
 	}
 
 	rdata->items = NULL;
-
-	if (count > 0 && (rdata->items = (dnslib_rdata_item_t *)calloc(
-			count, sizeof(dnslib_rdata_item_t))) == NULL) {
-		ERR_ALLOC_FAILED;
-		free(rdata);
-		return NULL;
-	}
-
-	rdata->count = count;
+	rdata->count = 0;
 
 	return rdata;
 }
@@ -52,14 +87,14 @@ int dnslib_rdata_set_items( dnslib_rdata_t *rdata,
 		return 1;
 	}
 
-	if (rdata->count == 0) {	// empty so far, allocate new space
-		assert(rdata->items == NULL);
-		if ((rdata->items = (dnslib_rdata_item_t *)malloc(
-				count * sizeof(dnslib_rdata_item_t))) == NULL) {
-			ERR_ALLOC_FAILED;
-			return -1;
-		}
-	} else if (rdata->count != count) {
+	if (rdata->items != NULL) {	// not empty
+		return -1;
+	}
+
+	assert(rdata->count == 0);
+	if ((rdata->items = (dnslib_rdata_item_t *)malloc(
+			count * sizeof(dnslib_rdata_item_t))) == NULL) {
+		ERR_ALLOC_FAILED;
 		return -2;
 	}
 
@@ -92,3 +127,209 @@ void dnslib_rdata_free( dnslib_rdata_t **rdata )
 	free(*rdata);
 	*rdata = NULL;
 }
+
+/*----------------------------------------------------------------------------*/
+
+uint dnslib_rdata_wire_size( const dnslib_rdata_t *rdata,
+							 const uint8_t *format )
+{
+	uint size = 0;
+
+	for (int i = 0; i < rdata->count; ++i) {
+		switch (format[i]) {
+		case DNSLIB_RDATA_WF_COMPRESSED_DNAME:
+		case DNSLIB_RDATA_WF_UNCOMPRESSED_DNAME:
+		case DNSLIB_RDATA_WF_LITERAL_DNAME:
+			size += dnslib_dname_size(rdata->items[i].dname);
+			break;
+		case DNSLIB_RDATA_WF_BYTE:
+			size += 1;
+			break;
+		case DNSLIB_RDATA_WF_SHORT:
+			size += 2;
+			break;
+		case DNSLIB_RDATA_WF_LONG:
+			size += 4;
+			break;
+		case DNSLIB_RDATA_WF_A:
+			size += 4;
+			break;
+		case DNSLIB_RDATA_WF_AAAA:
+			size += 16;
+			break;
+		case DNSLIB_RDATA_WF_TEXT:
+		case DNSLIB_RDATA_WF_BINARYWITHLENGTH:
+			// size stored in the first byte, but the first byte also counts
+			size += rdata->items[i].raw_data[0] + 1;
+			break;
+		case DNSLIB_RDATA_WF_BINARY:
+		case DNSLIB_RDATA_WF_APL:			// saved as binary
+		case DNSLIB_RDATA_WF_IPSECGATEWAY:	// saved as binary
+			// size stored in the first byte, first byte doesn't count
+			size += rdata->items[i].raw_data[0];
+			break;
+		default:
+			assert(0);
+		}
+	}
+	return size;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int dnslib_rdata_to_wire( const dnslib_rdata_t *rdata, const uint8_t *format,
+						  uint8_t *buffer, uint buf_size )
+{
+	uint copied = 0;
+	uint8_t tmp[MAX_RDATA_WIRE_SIZE];
+	uint8_t *to = tmp;
+
+	for (int i = 0; i < rdata->count; ++i) {
+		assert(copied < MAX_RDATA_WIRE_SIZE);
+
+		switch (format[i]) {
+		case DNSLIB_RDATA_WF_COMPRESSED_DNAME:
+		case DNSLIB_RDATA_WF_UNCOMPRESSED_DNAME:
+		case DNSLIB_RDATA_WF_LITERAL_DNAME: {
+			uint size = dnslib_dname_size(rdata->items[i].dname);
+			memcpy(to, dnslib_dname_name(rdata->items[i].dname), size);
+			to += size;
+			copied += size;
+		} break;
+		case DNSLIB_RDATA_WF_BYTE:
+			*(to++) = rdata->items[i].int8;
+			++copied;
+			break;
+		case DNSLIB_RDATA_WF_SHORT: {
+			const uint8_t *from = (uint8_t *)(&rdata->items[i].int16);
+			// copy from last byte to first (little to big endian)
+			// TODO: check endianness of the machine
+			from += 1;
+			for (int i = 0; i < 2; ++i) {
+				*(to++) = *(from--);
+				++copied;
+			}
+		} break;
+		case DNSLIB_RDATA_WF_LONG: {
+			const uint8_t *from = (uint8_t *)(&rdata->items[i].int32);
+			// copy from last byte to first (little to big endian)
+			// TODO: check endianness of the machine
+			from += 3;
+			for (int i = 0; i < 4; ++i) {
+				*(to++) = *(from--);
+				++copied;
+			}
+		} break;
+		case DNSLIB_RDATA_WF_A: {
+			const uint8_t *from = rdata->items[i].a;
+			for (int i = 0; i < 4; ++i) {
+				*(to++) = *(from++);
+				++copied;
+			}
+		} break;
+		case DNSLIB_RDATA_WF_AAAA: {
+			const uint8_t *from = rdata->items[i].raw_data;
+			for (int i = 0; i < 16; ++i) {
+				*(to++) = *(from++);
+				++copied;
+			}
+		} break;
+		case DNSLIB_RDATA_WF_TEXT:
+		case DNSLIB_RDATA_WF_BINARYWITHLENGTH:
+			// size stored in the first byte, but the first byte also needs to
+			// be copied
+			memcpy(to, rdata->items[i].raw_data,
+				   rdata->items[i].raw_data[0] + 1);
+			copied += rdata->items[i].raw_data[0] + 1;
+			to += rdata->items[i].raw_data[0] + 1;
+			break;
+		case DNSLIB_RDATA_WF_BINARY:
+		case DNSLIB_RDATA_WF_APL:			// saved as binary
+		case DNSLIB_RDATA_WF_IPSECGATEWAY:	// saved as binary
+			// size stored in the first byte, first byte must not be copied
+			memcpy(to, &(rdata->items[i].raw_data[1]),
+				   rdata->items[i].raw_data[0]);
+			copied += rdata->items[i].raw_data[0];
+			to += rdata->items[i].raw_data[0];
+			break;
+		default:
+			assert(0);
+		}
+	}
+
+	if (copied > buf_size) {
+		log_warning("Not enough place allocated for function "
+					"dnslib_rdata_to_wire(). Allocated %u, need %u\n",
+					buf_size, copied);
+		return -1;
+	}
+
+	memcpy(buffer, tmp, copied);
+	return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+
+int dnslib_rdata_compare( const dnslib_rdata_t *r1, const dnslib_rdata_t *r2,
+						  const uint8_t *format )
+{
+	uint count = (r1->count < r2->count) ? r1->count : r2->count;
+
+	int cmp = 0;
+
+	for (int i = 0; i < count; ++i) {
+		dnslib_rdata_item_t *item1 = &r2->items[i];
+		dnslib_rdata_item_t *item2 = &r2->items[i];
+
+		switch (format[i]) {
+		case DNSLIB_RDATA_WF_COMPRESSED_DNAME:
+		case DNSLIB_RDATA_WF_UNCOMPRESSED_DNAME:
+		case DNSLIB_RDATA_WF_LITERAL_DNAME:
+			cmp = dnslib_rdata_compare_binary(
+					dnslib_dname_name(item1->dname),
+					dnslib_dname_name(item2->dname),
+					dnslib_dname_size(item1->dname),
+					dnslib_dname_size(item2->dname));
+			break;
+		case DNSLIB_RDATA_WF_BYTE:
+			cmp = (item1->int8 == item2->int8) ? 0 : (
+					(r1->items[i].int8 < item2->int8) ? -1 : 1);
+			break;
+		case DNSLIB_RDATA_WF_SHORT:
+			cmp = (item1->int16 == item2->int16) ? 0 : (
+					(item1->int16 < item2->int16) ? -1 : 1);
+			break;
+		case DNSLIB_RDATA_WF_LONG:
+			cmp = (item1->int32 == item2->int32) ? 0 : (
+					(item1->int32 < item2->int32) ? -1 : 1);
+			break;
+		case DNSLIB_RDATA_WF_A:
+			cmp = dnslib_rdata_compare_binary(item1->a, item2->a, 4, 4);
+			break;
+		case DNSLIB_RDATA_WF_AAAA:
+			cmp = dnslib_rdata_compare_binary(item1->raw_data, item2->raw_data,
+											  16, 16);
+			break;
+		case DNSLIB_RDATA_WF_TEXT:
+		case DNSLIB_RDATA_WF_BINARYWITHLENGTH:
+			cmp = dnslib_rdata_compare_binary(&item1->raw_data[1],
+					&item2->raw_data[1], (int)item1->raw_data[0],
+					(int)item2->raw_data[0]);
+			break;
+		case DNSLIB_RDATA_WF_BINARY:
+		case DNSLIB_RDATA_WF_APL:			// saved as binary
+		case DNSLIB_RDATA_WF_IPSECGATEWAY:	// saved as binary
+			cmp = dnslib_rdata_compare_binary(item1->a, item2->a, -1, -1);
+			break;
+		default:
+			assert(0);
+		}
+
+		if (cmp != 0) {
+			return cmp;
+		}
+	}
+
+	assert(cmp == 0);
+	return 0;
+}
diff --git a/src/dnslib/rdata.h b/src/dnslib/rdata.h
index 21cc0e553e3c2e5335f532d72bdaaf61831ee55f..4d7ad9744e99a349fd514bd16a7f4a4b21c53622 100644
--- a/src/dnslib/rdata.h
+++ b/src/dnslib/rdata.h
@@ -26,12 +26,19 @@
  * require special treatment within some RDATA (e.g. compressing in packets).
  */
 union dnslib_rdata_item {
+	dnslib_dname_t *dname; /*!< RDATA item represented as a domain name. */
+	uint8_t int8;	/*!< 8bit unsigned integer */
+	uint16_t int16;		/*!< 16bit unsigned integer */
+	uint32_t int32;		/*!< 32bit unsigned integer */
+	uint8_t a[4];		/*!< A address - four 8bit integers */
 	/*!
 	 * \brief RDATA item represented as raw array of octets.
-	 * \note Will this be convenient enough? What about parsing? (in runtime?)
+	 *
+	 * In most cases the first octet will be the length of the array. The only
+	 * now known exception will be when storing AAAA address which has known
+	 * length (sixteen 8bit integers), so there is no need to store the lenght.
 	 */
 	uint8_t *raw_data;
-	dnslib_dname_t *dname; /*!< RDATA item represented as a domain name. */
 };
 
 typedef union dnslib_rdata_item dnslib_rdata_item_t;
@@ -43,11 +50,19 @@ typedef union dnslib_rdata_item dnslib_rdata_item_t;
  * Each RDATA may be logically divided into items, each of possible different
  * type (see dnslib_rdata_item). This structure stores an array of such items.
  * It is not dynamic, so any RDATA structure may hold either 0 or one specified
- * number of items which cannot be changed later.
+ * number of items which cannot be changed later. However, the number of items
+ * may be different for each RDATA structure. The number of items should be
+ * given by descriptors for each RR type. Some types may have variable number
+ * of items. In such cases, the last item in the array will be set tu NULL
+ * to distinguish the actual count of items.
+ *
+ * \todo Find out whether NULL is appropriate value. If it is a possible
+ *       value for some of the items, we must find some other way to deal with
+ *       this.
  *
  * This structure does not hold information about the RDATA items, such as
  * what type is which item or how long are they. This information should be
- * stored elsewhere (probably globally) as it is RR-specific and given for each
+ * stored elsewhere (in descriptors) as it is RR-specific and given for each
  * RR type.
  */
 struct dnslib_rdata {
@@ -60,15 +75,11 @@ typedef struct dnslib_rdata dnslib_rdata_t;
 
 /*----------------------------------------------------------------------------*/
 /*!
- * \brief Creates an empty RDATA structure and possibly reserves space for data.
- *
- * \param count Number of RDATA items to be later stored in this structure.
- *
- * If \a count > 0, all RDATA items are initialized to 0.
+ * \brief Creates an empty RDATA structure.
  *
  * \return Pointer to the new RDATA structure or NULL if an error occured.
  */
-dnslib_rdata_t *dnslib_rdata_new( uint count );
+dnslib_rdata_t *dnslib_rdata_new();
 
 /*!
  * \brief Sets the RDATA item on position \a pos.
@@ -122,6 +133,36 @@ int dnslib_rdata_set_items( dnslib_rdata_t *rdata,
 const dnslib_rdata_item_t *dnslib_rdata_get_item( const dnslib_rdata_t *rdata,
 												  uint pos );
 
+/*!
+ * \brief Returns the size of the RDATA in wire format.
+ *
+ * \param rdata RDATA structure to get the wire format size of.
+ * \param format RDATA format descriptor.
+ *
+ * \return Size of the RDATA in wire format.
+ *
+ * \todo Consider adding the size to the structure for faster retrieval.
+ */
+uint dnslib_rdata_wire_size( const dnslib_rdata_t *rdata,
+							 const uint8_t *format );
+
+/*!
+ * \brief Converts the RDATA to wire format.
+ *
+ * \param rdata RDATA structure to convert to wire format.
+ * \param format RDATA format descriptor.
+ * \param buffer Place to put the wire format into.
+ * \param buf_size Size of the buffer.
+ *
+ * \return 0 on success.
+ * \return <> 0 otherwise.
+ *
+ * \todo Do we really need all those different kinds of RDATA items? It makes
+ *       converting more complicated.
+ */
+int dnslib_rdata_to_wire( const dnslib_rdata_t *rdata, const uint8_t *format,
+						  uint8_t *buffer, uint buf_size );
+
 /*!
  * \brief Destroys the RDATA structure.
  *
@@ -136,6 +177,12 @@ const dnslib_rdata_item_t *dnslib_rdata_get_item( const dnslib_rdata_t *rdata,
  */
 void dnslib_rdata_free( dnslib_rdata_t **rdata );
 
+/*!
+ *
+ */
+int dnslib_rdata_compare( const dnslib_rdata_t *r1, const dnslib_rdata_t *r2,
+						  const uint8_t *format );
+
 #endif /* _CUTEDNS_RDATA_H */
 
 /*! @} */