(function () { 'use strict'; var input = process.argv[2]; var fs = require('fs'); var nb = fs.readFileSync(input, null); var ab = nb.buffer.slice(nb.byteOffset, nb.byteOffset + nb.byteLength); var dv = new DataView(ab); // // read header // console.log(''); console.log('//////////////////'); console.log('// HEADER //'); console.log('//////////////////'); console.log(''); console.log('id (int)', dv.getUint16(0)); var flags = dv.getUint16(2, false); console.log('header 0x', flags.toString(16)); var flagsstr = '' + 'qr ' + ((flags & 0x8000) >> 15) + ', ' + 'opcode ' + ((flags & 0x7800) >> 11) + ', ' + 'aa ' + ((flags & 0x400) >> 10) + ', ' + 'tc ' + ((flags & 0x200) >> 9) + ', ' + 'rd ' + ((flags & 0x100) >> 8) + ', ' + 'ra ' + ((flags & 0x80) >> 7) + ', ' + 'res1 ' + ((flags & 0x40) >> 6) + ', ' + 'res2 ' + ((flags & 0x20) >> 5) + ', ' + 'res3 ' + ((flags & 0x10) >> 4) + ', ' + 'rcode ' + ((flags & 0xF)); console.log('(flags: ' + flagsstr); var qdcount = dv.getUint16(4, false); // query count var ancount = dv.getUint16(6, false); // answer count var nscount = dv.getUint16(8, false); // authority count var arcount = dv.getUint16(10, false); // additional count var count; console.log('qdcount', qdcount); console.log('ancount', ancount); console.log('nscount', nscount); console.log('arcount', arcount); function unpackQuestion(dv, total, len) { var qnames = []; var labelLen; while (true) { if (total >= len) { break; } labelLen = dv.getUint8(total, false); // additional count total += 1; if (!labelLen) { break; } if (192 === labelLen) { console.log('ERROR: Compression pointer found'); console.log(dv.getUint8(total, false)); console.log(dv.getUint8(dv.getUint8(total + 0, false), false)); console.log(dv.getUint8(dv.getUint8(total + 1, false), false)); console.log(dv.getUint8(dv.getUint8(total + 2, false), false)); break; } var i; var label = ''; console.log('label len', labelLen); for (i = 0; i < labelLen; i += 1) { label += String.fromCharCode(dv.getUint8(total + i, false)); } total += label.length; console.log('label:', label); qnames.push(label); } // leading length and (potentially) trailing null console.log('QNAME (len ' + (qnames.join('.').length + 1 + (labelLen ? 0 : 1)) + '):', qnames.join('.')); console.log('QTYPE (len 2):', dv.getUint16(total, false)); total += 2; console.log('QCLASS (len 2):', dv.getUint16(total, false)); total += 2; return { total: total , qname: qnames.join('.') }; } var q = { total: 12 }; function mapChar(ch) { return JSON.stringify(String.fromCharCode(ch)) + '(' + ch + ')'; } console.log(''); console.log('//////////////////'); console.log('// QUESTION //'); console.log('//////////////////'); console.log(''); for (count = 0; count < qdcount; count += 1) { console.log(''); console.log('Question ' + (count + 1) + ' of ' + qdcount + ' (byte index: ' + q.total + ')'); q = unpackQuestion(dv, q.total, ab.byteLength); console.log(''); } console.log(''); console.log('//////////////////'); console.log('// ANSWER //'); console.log('//////////////////'); console.log(''); for (count = 0; count < ancount; count += 1) { console.log(''); console.log('Answer', count + 1, 'of', ancount + ' (byte index: ' + q.total + ')'); q = unpackQuestion(dv, q.total, ab.byteLength); console.log(''); } console.log(''); console.log('//////////////////'); console.log('// AUTHORITY //'); console.log('//////////////////'); console.log(''); for (count = 0; count < nscount; count += 1) { console.log(''); console.log('Authority', count + 1, 'of', nscount + ' (byte index: ' + q.total + ')'); q = unpackQuestion(dv, q.total, ab.byteLength); console.log('ttl (len 4):', dv.getUint32(q.total, false)); q.total += 4; q.rdlength = dv.getUint16(q.total, false); console.log('rdlen (len 2):', q.rdlength); q.total += 2; console.log('rrdata (len ' + q.rdlength + '):'); console.log([].slice.call(new Uint8Array(ab), q.total, q.total + q.rdlength).map(mapChar).join(' ')); q.total += q.rdlength; console.log(''); } console.log(''); console.log('//////////////////'); console.log('// ADDITIONAL //'); console.log('//////////////////'); console.log(''); for (count = 0; count < arcount; count += 1) { console.log(''); console.log('Additional', count + 1, 'of', arcount + ' (byte index: ' + q.total + ')'); q = unpackQuestion(dv, q.total, ab.byteLength); console.log(''); } }());