wm: dnsparser

ref: 1766db24dfb733bd1f574bf0882527356f177397
dir: /common.h/

View raw version
#define debug 0

enum
{
	/* sizes and stuff */
	ETHER_LEN = 14,
	ETHER_ADDR_LEN = 6,
	
	UDP_SIZE = 8,

	/* sizes of each field in header */
	ETHER_DST = ETHER_ADDR_LEN,
	ETHER_SRC = ETHER_ADDR_LEN,
	ETHER_TYPE = 2,

	PKT_VHL = 1,
	PKT_DSFIELD = 1,
	PKT_LEN = 2,
	PKT_ID = 2,
	// PKT_FLAGS = 1, /* 3 bits */
	PKT_FRAGOFFSET = 2, /* 12 bits */
	PKT_TTL = 1,
	PKT_PROTO = 1,
	PKT_SUM = 2,
	PKT_SRC = 4,
	PKT_DST = 4,

	/* udp stuff */
	UDP_SRCPORT = 2,
	UDP_DSTPORT = 2,
	UDP_LEN = 2,
	UDP_SUM = 2,
	
	/* tcp stuff */
	TCP_SRCPORT = 2,
	TCP_DSTPORT = 2,
	TCP_SEQNUM = 4,
	TCP_ACKNUM = 4,
	TCP_OFFSET = 1, /* half a byte is used */
	TCP_FLAGS = 1,
	TCP_WINSIZE = 2,
	TCP_SUM = 2,
	TCP_URGPTR = 2,
	TCP_OPTS = 2,

	/* tcp flags @ 13 */
	TCP_FLAG_ACK = 0x010,
	TCP_FLAG_PSH = 0x008,
	TCP_FLAG_SYN = 0x002,
	TCP_FLAG_FIN = 0x001,
	
	/* dns */
	DNS_ID = 2,
	DNS_FLAGS = 2,
	DNS_COUNT_QUERIES = 2,
	DNS_COUNT_ANSWERS = 2,
	DNS_COUNT_AUTH_RR = 2,
	DNS_COUNT_ADD_RR = 2,
	DNS_TYPE = 2,
	DNS_CLASS = 2,
	DNS_BACKREF = 2, /* that c0 ff thingi which back references */
	DNS_TTL = 4,
	DNS_LEN = 2,
	
	/* dns flags bits @ 2 */
	DNS_ISRESP = 0x8000,
	DNS_OPCODE = 0x7800,
	
	DNS_FLAGS_OPCODE_QUERY = 0x4000,
	DNS_FLAGS_OPCODE_IQUERY = 0x2000,
	DNS_FLAGS_OPCODE_STATUS = 0x1000,	/* 2 bits */
	DNS_FLAGS_OPCODE_NOTIFY = 0x0800,
	
	DNS_AUTH = 0x0400,
	DNS_TRUNCATED = 0x0200,
	DNS_RD = 0x0100,
	DNS_RA = 0x0080,
	DNS_Z = 0x0040,
	DNS_AD = 0x0020,
	DNS_CD = 0x0010,
	DNS_RCODE = 0x000F,
	
	/* tls record */
	TLS_RECORD = 4,
	TLS_RECORD_CONTENTTYPE = 1,
	TLS_RECORD_VERSION = 1,
	TLS_RECORD_LEN = 2,
	
	/* tls record versions */
	TLS_RECORD_10 = 0x301,
	TLS_RECORD_11 = 0x302,
	TLS_RECORD_12 = 0x303,
	TLS_RECORD_13 = 0x304,
	
	/* tls 1.2 handshake */
	TLS_HANDSHAKE_TYPE = 1,
	TLS_HANDSHAKE_LEN = 3,
	TLS_HANDSHAKE_VERSION = 2,
	TLS_HANDSHAKE_RANDOM = 32,
	TLS_HANDSHAKE_SESSIONID_LEN = 1,
	TLS_HANDSHAKE_SESSIONID = 32,
	TLS_HANDSHAKE_CIPHERS_LEN = 2,
	TLS_HANDSHAKE_CIPHERS = 54,
	TLS_HANDSHAKE_COMP_LEN = 1,
	TLS_HANDSHAKE_COMPS = 1,
	TLS_HANDSHAKE_EXTS_LEN = 2, /* number of all extensions */
	TLS_HANDSHAKE_EXT_TYPE = 2,
	TLS_HANDSHAKE_EXT_LEN = 2, /* (data) length of a specfic extension */
		
	/* ether types */
	ETHER_IP4 = 0x800,
	ETHER_IP6 = 0x86dd,

	/* packet types */
	PKT_TCP = 6,
	PKT_UDP = 17,

	/* dns types */
	DNS_TYPE_A = 1,
	DNS_TYPE_CNAME = 5,
	DNS_TYPE_MX = 15,
	DNS_TYPE_TXT = 16,
	DNS_TYPE_AAAA = 28,
	
	/* dns classes */
	DNS_CLASS_IN = 1, /* lonely :( */
	
	/* tls handshake types */
	TLS_HELLO_REQ = 0,
	TLS_CLIENT_HELLO = 1,
	TLS_SERVER_HELLO = 2,
	TLS_NEW_TICKET = 4,
	TLS_END_OF_EARLY_DATA = 5,
	TLS_CERT = 11,
	TLS_CERT_REQ = 13,
	TLS_FINISHED = 20,
	
	/* tls content types */
	TLS_ALERT = 21,
	TLS_HANDSHAKE = 22,
	TLS_APPLICATION_DATA = 23,
	TLS_HEARTBEAT = 24,
	TLS_CID = 25, /* ? */
	TLS_ACK = 26,
	TLS_RTC = 27, /* ? */
};

/*
 * each parser have at least these two
 * they may have more functions internally and externally
 */
typedef struct
{
	char *name;
	int (*parse)();
	void (*print)();
}Parser;

extern pcap_t *handle;
extern struct bpf_program dnsfilter;

/* common.c */
uint16_t get2(const u_char *octet);
uint32_t get4(const u_char *octet);
void err(int fatal, char *fmt, ...);

/* ether.c */
typedef struct
{
	uint8_t dst[ETHER_ADDR_LEN];
	uint8_t src[ETHER_ADDR_LEN];
	int type;
}Ether;

char* etherTypeToStr(uint16_t frame);
int parseEther(const u_char *pkt, Ether *e);
void printEther(Ether e);

extern Parser etherParser;

/* (ipv4) pkt.c */
typedef struct
{
	uint8_t version;
	uint8_t headerlen;
	uint8_t dsfield;
	uint8_t len;
	uint16_t id;
	uint8_t flags;
	uint16_t fragoffset;
	uint8_t ttl;
	uint8_t proto; /* UDP, TCP */
	uint16_t sum; /* checksum of packet */

	uint32_t srcip;
	uint32_t dstip;
}Pkt;

#define IP4_HL(octet)	(octet & 0x0f)
#define IP4_V(octet)	(octet >> 4) 

int parsePkt(const u_char *pkt, Pkt *p);
char* pktTypeToStr(const u_char pkt);
void printPkt(Pkt p);

extern Parser pktParser;

/* udp.c */
typedef struct
{
	uint16_t srcport;
	uint16_t dstport;

	uint16_t len;
	uint16_t sum;
}Udp;

int parseUdp(const u_char *pkt, Udp *udp);
void printUdp(Udp udp);

extern Parser udpParser;

/* tcp.c */
typedef struct
{
	uint16_t srcport;
	uint16_t dstport;

	uint32_t seqnum;
	uint32_t acknum;
	
	uint16_t offset;
	uint16_t flags;
	
	uint16_t winsize;
	uint8_t sum;
	
	uint16_t urgentptr;
	/* we don't care about options */
}Tcp;

int parseTcp(const u_char *pkt, Tcp *tcp);
void printTcp(Tcp tcp);

extern Parser tcpParser;

/*
 * dns.c
 * a maximum size of 255 for strings is assumed
 */
typedef struct
{
	/* is it response or request */
	uint16_t id;
	uint16_t flags;
	
	/* count(s) */
	uint16_t nQueries;
	uint16_t nAnswers;
	uint16_t nAuthRR;
	uint16_t nAddRR;
	
	char domain[255];
	
	uint8_t type;
	uint8_t class;
	uint32_t ttl;
	uint32_t len;
	union
	{
		/* A */
		uint8_t ip[4];

		/* AAAA */
		uint16_t ip6[8];

		/* CNAME */
		u_char cname[255];
	};
}Dns;

int parseDnsCname(const u_char *pkt, u_char cname[255], uint pos, uint len);
int parseDns(const u_char *pkt, Dns *dns);
char* dnsClassToStr(uint16_t class);
char* dnsTypeToStr(uint16_t type);
void printDns(Dns dns);
extern Parser dnsParser;

/* tls.c */
typedef struct
{
	uint8_t len;
	uint8_t data[];
}TlsTuple;

typedef struct
{
	uint8_t type;
	uint32_t len;
	uint16_t version;
	
	uint8_t random[32];
	
	TlsTuple sessionId;
	TlsTuple cipherSuits;
	TlsTuple compressionMethods;
	TlsTuple extensions;
}TlsHandshake;

typedef struct
{
	uint8_t contenttype;
	uint16_t rversion; /* record version */
	uint16_t len;
	
	TlsHandshake handshake;
}Tls;

extern Parser tlsParser;