All pastes #1770165 Raw Edit

Someone

public text v1 · immutable
#1770165 ·published 2010-01-29 01:43 UTC
rendered paste body
Made by eax <eax@eax.uni.cc> on 05/05/2008 (DD/MM/YYYY) @ 18:54 PM (HH:MM).

Hi. This file is intended for you to know how to parse a DNS answer given
by functions like res_query(). As res_query(), res_search() and other
functions related to them are treated on the first part of this reference,
they won't be talked in this file. If you really need to do something
related to DNS, this might be a very useful help file, as the internet is
low on resources about this functions.

			Listing:

	int res_init_parse(const u_char *msg, int msglen, ns_msg *handle) :
	This function must be called before doing anything related to
	parsing. The arguments must be: the query answer must be filled
	into the first argument(const u_char *msg), the answer size on the
	second argument(int msglen) and finally, a ns_msg pointer must be
	passed by the last argument(ns_msg *handle), this last pointer is
	actually a structure, which will be passed to all the other ns_*
	functions.

	const u_char *ns_msg_base(ns_msg handle) : This function will
	return a pointer to the start of the response.

	const u_char *ns_msg_end(ns_msg handle) : This function will return
	a pointer to the end of the response.

	int ns_msg_size(ns_msg handle) : This function will return the size
	of the response.

	u_int16_t ns_msg_id(ns_msg handle) : It will return the
	identification from the header section of the response packet.

	u_int16_t ns_msg_get_flag(ns_msg handle, ns_flag flag) : Returns
	the flag fields from the header section in the response packets.
	The first argument must be the structure filled by ns_init_parse()
	and the second argument must be any of the ns_flags.

	u_int16_t ns_msg_count(ns_msg handle, ns_sect section) : Returns a
	counter from the header section of the response packet. The first
	argument must be, of course, the structure filled in by
	ns_init_parse(), while the second argument can be any of the
	ns_sect enum values.

	int ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr
	*rr) : This function extracts information about a record from the
	answer and stores it in rr.rr(ns_rr *rr). The section parameter
	will be the same as the section specified in ns_msg_count().

	char *ns_rr_name/u_int16_t ns_rr_type/u_int16_t
	ns_rr_class/u_int16_t ns_rr_ttl/u_int16_t ns_rr_rdlen/const u_char
	*ns_rr_rdata(ns_rr rr) : All these functions will return individual
	fields from a DNS answer, the only argument(ns_rr rr) must be the
	structure returned by ns_parserr().

	int ns_name_compress(const char *exp_dn, u_char *comp_dn, size_t
	length, const u_char **dnptrs, const u_char **lastdnptr) : This
	functions compresses a domain name, this function shouldn't be
	called by yourself. However, if you need to compress a domain name
	for something, this will do fine. The first argument is the FQDN,
	null-terminated. The second argument is where the function will
	store the final result, while the third argument(size_t length) is
	the size of the second argument, fourth argument(const u_char
	**dnptrs) is an array of pointers to a previously compressed domain
	names list. And the last argument(const u_char **lastdnptr) is a
	pointer to the fourth argument's last member.

	int ns_name_uncompress(const u_char *msg, const u_char *eomorig,
	const u_char *comp_dn, char *exp_dn, size_t length) : This function
	will uncompress a previously compressed domain name(that used the
	function ns_name_compress()). It's first argument(const u_char
	*msg) is a pointer to the beginning of the DNS answer, the
	second(const u_char *eomorig) is a pointer to the first byte after
	the DNS answer, which will asure you that dns_name_uncompress()
	won't crash. While the third argument(const u_char *comp_dn) is the
	previously compressed domain name, the fifth is where the expanded
	name will be stored and the last argument(size_t length) is the
	size of the fourth argument(char *exp_dn).

	int ns_name_skip(const u_char **ptrptr, const u_char *eom) : It
	will skip a domain name that should be uncompressed. Arguments are:
	first(const u_char **ptrptr) is a pointer to the domain that must
	be skipped, while the second argument(const u_char *eom) is a
	pointer to the first byte after the message, so the function won't
	pass the message maximum length.

	u_int ns_get16(const u_char *cp) : This function will return the unsigned
	short integer from the DNS packet.

	void ns_put16(u_int s, u_char *cp) : Assigns a 16-bit value defined by
	the first argument(u_int s), to the location pointed to by the
	second argument(u_char *cp).

	u_long ns_get32(const u_char *cp) : This function will do the same as
	ns_get16(), but by using a 32-bit integer instead of a 16-bit.

	void ns_put32(u_long l, u_char *cp) : Assigns a 32-bit value defined by
	the first argument(u_long l), to the location pointed to by the
	second argument(u_char *cp).

<------------------------------------------------------------------------>

	This reference may change with future kernel releases, I doubt it
tho.

<------------------------------------------------------------------------>

List of headers required for the use of these functions:
	<sys/types.h>
	<netinet/in.h>
	<netdb.h>
	<arpa/nameser.h>
	<resolv.h>

Note that for the code to compile, you must link with the resolver library,
located at /usr/lib/libresolv.a (-lresolv will work if you don't use NS
parser functions).

The ns_msg structure, from <arpa/nameser.h> (/usr/include/arpa/nameser.h):

typedef struct __ns_msg {
	const u_char	*_msg, *_eom;
	u_int16_t	_id, _flags, _counts[ns_s_max];
	const u_char	*_sections[ns_s_max];
	ns_sect		_sect;
	int		_rrnum;
	const u_char	*_ptr;
} ns_msg;

Note: You won't need to do anything yourself with this structure, still,
its good to know what is in it.

The ns_rr structure, from <arpa/nameser.h> (/usr/include/arpa/nameser.h):

typedef	struct __ns_rr {
	char		name[NS_MAXDNAME];
	u_int16_t	type;
	u_int16_t	rr_class;
	u_int32_t	ttl;
	u_int16_t	rdlength;
	const u_char *	rdata;
} ns_rr;

Note: Again, you won't need to do anything yourself with this structure,
still, its good to know whats in it.

Possible values for "ns_sect", from <arpa/nameser.h>
(/usr/include/arpa/nameser.h):

typedef enum __ns_sect {
	ns_s_qd = 0,		/* Query: Question. */
	ns_s_zn = 0,		/* Update: Zone. */
	ns_s_an = 1,		/* Query: Answer. */
	ns_s_pr = 1,		/* Update: Prerequisites. */
	ns_s_ns = 2,		/* Query: Name servers. */
	ns_s_ud = 2,		/* Update: Update. */
	ns_s_ar = 3,		/* Query|Update: Additional records. */
 	ns_s_max = 4
} ns_sect;

Possible values for "ns_flag" from <arpa/nameser.h> (/usr/include/arpa/nameser.h):

typedef enum __ns_flag {
	ns_f_qr,		/* Question/Response. */
	ns_f_opcode,		/* Operation code. */
	ns_f_aa,		/* Authoritative Answer. */
	ns_f_tc,		/* Truncation occurred. */
	ns_f_rd,		/* Recursion Desired. */
	ns_f_ra,		/* Recursion Available. */
	ns_f_z,			/* MBZ. */
	ns_f_ad,		/* Authentic Data (DNSSEC). */
	ns_f_cd,		/* Checking Disabled (DNSSEC). */
	ns_f_rcode,		/* Response code. */
	ns_f_max
} ns_flag;