int mesg_assemble (G_List *an_list, G_List *ns_list, G_List *ar_list,
		   u_char *buf, uint16_t buflen, u_char *mesg, int mesg_len) {
	uint16_t dnames[MESG_ASSEMBLE_OFFSET_LEN];
	u_char *ucp, *ucp_tmp;
	int written_len, ret;
	Mesg_Hdr *hdr;

	/* check if header is already present */
	if (mesg)
		memcpy (buf, mesg, mesg_len);
	else
		memset (buf, 0, buflen);

	hdr = (Mesg_Hdr *) buf;

	written_len = 0;

	/* check and reset header */
	hdr->qr = 1;
	hdr->ancnt = 0;
	hdr->nscnt = 0;
	hdr->arcnt = 0;

	if (hdr->qdcnt) {
		int qdcnt = ntohs(hdr->qdcnt);

		/*
		 * Register question name to compression name list
		 * Note that for simplicity we only register
		 * the first, and ignore multiple question
		 */
		dnames[0] = (uint16_t) (sizeof (Mesg_Hdr));
		dnames[1] = 0;	/* terminator */

		/*
		 * Skip the question section.
		 */
		ucp = buf + sizeof(Mesg_Hdr);
		while (qdcnt--) {
			/* skip QNAME */
			if (!(ucp = mesg_skip_dname(ucp, buf + mesg_len)) ||
			    ucp + 2 * sizeof(uint16_t) > buf + mesg_len) {
				syslog (LOG_NOTICE, "query message overrun");
				return -1;
			}
			/* skip QTYPE and QCLASS */
			ucp += (2 * sizeof(uint16_t));
		}
		written_len = ucp - buf;
	} else {
		/* there mustnot be any question */
		written_len = sizeof (Mesg_Hdr);
		ucp = buf + written_len;
		dnames[0] = 0;
	}

	/* write answers */
	ucp_tmp = ucp;
	ret = mesg_write_rrset_list (an_list, buf, buf + buflen, dnames,
				     MESG_ASSEMBLE_OFFSET_LEN, &ucp,
				     &(hdr->ancnt));
	if (ret < 0) {
		/* truncated message */
		hdr->tc = 1;
		return ucp_tmp - buf;
	}
	written_len += ret;

	/* write ns */
	ucp_tmp = ucp;
	ret = mesg_write_rrset_list (ns_list, buf, buf + buflen, dnames,
				     MESG_ASSEMBLE_OFFSET_LEN, &ucp,
				     &(hdr->nscnt));
	if (ret < 0) {
		/* truncated message */
		hdr->tc = 1;
		return ucp_tmp - buf;
	}
	written_len += ret;

	/* write additonal records */
	ucp_tmp = ucp;
	ret = mesg_write_rrset_list (ar_list, buf, buf + buflen, dnames,
				     MESG_ASSEMBLE_OFFSET_LEN, &ucp,
				     &(hdr->arcnt));
	/*
	 * ignore if error -- we may leave out additional
	 * records if we do not have room for them
	 */
	if (ret < 0)
		return ucp_tmp - buf;
	else
		return written_len + ret;
}
int mesg_assemble (G_List *an_list, G_List *ns_list, G_List *ar_list,
		   u_char *buf, uint16_t buflen, u_char *mesg, int mesg_len) {
	uint16_t dnames[MESG_ASSEMBLE_OFFSET_LEN];
	u_char *ucp, *ucp_tmp;
	int written_len, ret;
	Mesg_Hdr *hdr;

	 
	if (mesg)
		memcpy (buf, mesg, mesg_len);
	else
		memset (buf, 0, buflen);

	hdr = (Mesg_Hdr *) buf;

	written_len = 0;

	 
	hdr->qr = 1;
	hdr->ancnt = 0;
	hdr->nscnt = 0;
	hdr->arcnt = 0;

	if (hdr->qdcnt) {
		int qdcnt = ntohs(hdr->qdcnt);

		 
		dnames[0] = (uint16_t) (sizeof (Mesg_Hdr));
		dnames[1] = 0;	 

		 
		ucp = buf + sizeof(Mesg_Hdr);
		while (qdcnt--) {
			 
			if (!(ucp = mesg_skip_dname(ucp, buf + mesg_len)) ||
			    ucp + 2 * sizeof(uint16_t) > buf + mesg_len) {
				syslog (LOG_NOTICE, "query message overrun");
				return -1;
			}
			 
			ucp += (2 * sizeof(uint16_t));
		}
		written_len = ucp - buf;
	} else {
		 
		written_len = sizeof (Mesg_Hdr);
		ucp = buf + written_len;
		dnames[0] = 0;
	}

	 
	ucp_tmp = ucp;
	ret = mesg_write_rrset_list (an_list, buf, buf + buflen, dnames,
				     MESG_ASSEMBLE_OFFSET_LEN, &ucp,
				     &(hdr->ancnt));
	if (ret < 0) {
		 
		hdr->tc = 1;
		return ucp_tmp - buf;
	}
	written_len += ret;

	 
	ucp_tmp = ucp;
	ret = mesg_write_rrset_list (ns_list, buf, buf + buflen, dnames,
				     MESG_ASSEMBLE_OFFSET_LEN, &ucp,
				     &(hdr->nscnt));
	if (ret < 0) {
		 
		hdr->tc = 1;
		return ucp_tmp - buf;
	}
	written_len += ret;

	 
	ucp_tmp = ucp;
	ret = mesg_write_rrset_list (ar_list, buf, buf + buflen, dnames,
				     MESG_ASSEMBLE_OFFSET_LEN, &ucp,
				     &(hdr->arcnt));
	 
	if (ret < 0)
		return ucp_tmp - buf;
	else
		return written_len + ret;
}