2017-03-05 00:10:25 +00:00
|
|
|
(function (exports) {
|
|
|
|
'use strict';
|
|
|
|
|
2017-09-28 19:13:18 +00:00
|
|
|
// http://www.zytrax.com/books/dns/ch8/soa.html
|
2017-10-05 21:02:25 +00:00
|
|
|
// https://github.com/tjfontaine/node-dns#resourcerecord
|
2017-09-28 19:13:18 +00:00
|
|
|
|
2017-03-17 00:48:08 +00:00
|
|
|
// Value Meaning/Use
|
|
|
|
// Primary NS Variable length. The name of the Primary Master for the domain. May be a label, pointer, or any combination
|
|
|
|
// Admin MB Variable length. The administrator's mailbox. May be a label, pointer, or any combination
|
|
|
|
// Serial Number Unsigned 32-bit integer
|
|
|
|
// Refresh Interval Unsigned 32-bit integer
|
|
|
|
// Retry Interval Unsigned 32-bit integer
|
|
|
|
// Expiration Limit Unsigned 32-bit integer
|
|
|
|
// Minimum TTL Unsigned 32-bit integer
|
2017-03-05 00:10:25 +00:00
|
|
|
|
|
|
|
exports.DNS_PACKER_TYPE_SOA = function (ab, dv, total, record) {
|
2017-10-07 01:12:19 +00:00
|
|
|
function notNumber(n) {
|
2017-10-07 01:13:21 +00:00
|
|
|
return 'number' !== typeof n || isNaN(n);
|
2017-10-07 01:12:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!record.primary && !record.name_server) {
|
2017-03-17 00:48:08 +00:00
|
|
|
throw new Error("no name server for SOA record");
|
|
|
|
}
|
2017-10-07 01:12:19 +00:00
|
|
|
if (!record.admin && !record.email_addr) {
|
2017-03-17 00:48:08 +00:00
|
|
|
throw new Error("ne email address for SOA record");
|
|
|
|
}
|
2017-10-07 01:12:19 +00:00
|
|
|
if (notNumber(record.serial) && notNumber(record.sn)) {
|
2017-03-10 02:34:27 +00:00
|
|
|
throw new Error("no serial number for SOA record");
|
|
|
|
}
|
2017-10-07 01:12:19 +00:00
|
|
|
if (notNumber(record.refresh) && notNumber(record.ref)) {
|
2017-09-28 19:13:18 +00:00
|
|
|
throw new Error("no refresh for SOA record");
|
2017-03-10 02:34:27 +00:00
|
|
|
}
|
2017-10-07 01:12:19 +00:00
|
|
|
if (notNumber(record.retry) && notNumber(record.ret)) {
|
2017-09-28 19:13:18 +00:00
|
|
|
throw new Error("no update retry for SOA record");
|
2017-03-18 17:38:43 +00:00
|
|
|
}
|
2017-10-07 01:12:19 +00:00
|
|
|
if (notNumber(record.expiration) && notNumber(record.ex)) {
|
2017-09-28 19:13:18 +00:00
|
|
|
throw new Error("no expiry for SOA record");
|
2017-03-10 02:34:27 +00:00
|
|
|
}
|
2017-10-07 01:12:19 +00:00
|
|
|
if (notNumber(record.minimum) && notNumber(record.nx)) {
|
2017-09-28 19:13:18 +00:00
|
|
|
throw new Error("no nxdomain for SOA record");
|
2017-03-10 02:34:27 +00:00
|
|
|
}
|
|
|
|
|
2017-03-18 17:38:43 +00:00
|
|
|
var soaLen = 20; // take into account sn, ref, ret, ex, and nx
|
2017-03-17 00:48:08 +00:00
|
|
|
// (32-bits each. 4Bytes * 5 = 20)
|
|
|
|
var rdLenIndex = total;
|
|
|
|
total += 2; // Save space for RDLENGTH
|
|
|
|
|
2017-10-05 21:02:25 +00:00
|
|
|
//console.log('record.name_server', 1 + record.name_server.length, record.name_server);
|
2017-03-17 00:48:08 +00:00
|
|
|
// pack name_server which is a sequence of labels
|
2017-10-05 21:02:25 +00:00
|
|
|
(record.primary || record.name_server).split('.').forEach(function (label) {
|
2017-09-28 19:13:18 +00:00
|
|
|
soaLen += (1 + label.length);
|
2017-03-17 00:48:08 +00:00
|
|
|
|
|
|
|
dv.setUint8(total, label.length, false);
|
|
|
|
total += 1;
|
|
|
|
|
|
|
|
label.split('').forEach(function(ch) {
|
|
|
|
dv.setUint8(total, ch.charCodeAt(0), false);
|
|
|
|
total += 1;
|
|
|
|
});
|
|
|
|
});
|
2017-09-28 19:13:18 +00:00
|
|
|
// must be terminated by null when not using write null
|
|
|
|
dv.setUint8(total, 0, false);
|
|
|
|
total += 1;
|
|
|
|
soaLen += 1;
|
2017-03-17 00:48:08 +00:00
|
|
|
|
2017-10-05 21:02:25 +00:00
|
|
|
//console.log('record.email_addr', 1 + record.email_addr.length, record.email_addr);
|
2017-03-17 00:48:08 +00:00
|
|
|
// pack email address which is a sequence of labels
|
2017-10-05 21:02:25 +00:00
|
|
|
(record.admin || record.email_addr).split('.').forEach(function (label) {
|
2017-03-17 00:48:08 +00:00
|
|
|
soaLen += 1 + label.length;
|
|
|
|
|
|
|
|
dv.setUint8(total, label.length, false);
|
|
|
|
total += 1;
|
|
|
|
|
|
|
|
label.split('').forEach(function (ch){
|
|
|
|
dv.setUint8(total, ch.charCodeAt(0), false);
|
|
|
|
total += 1;
|
|
|
|
});
|
|
|
|
});
|
2017-09-28 19:13:18 +00:00
|
|
|
// must be terminated by null when not using write null
|
|
|
|
dv.setUint8(total, 0, false);
|
|
|
|
total += 1;
|
|
|
|
soaLen += 1;
|
2017-03-17 00:48:08 +00:00
|
|
|
|
|
|
|
// pack all 32-bit values
|
2017-10-05 21:02:25 +00:00
|
|
|
dv.setUint32(total, parseInt(record.serial || record.sn, 10), false);
|
2017-03-17 00:48:08 +00:00
|
|
|
total+=4;
|
2017-10-05 21:02:25 +00:00
|
|
|
dv.setUint32(total, parseInt(record.refresh || record.ref, 10), false);
|
2017-03-17 00:48:08 +00:00
|
|
|
total+=4;
|
2017-10-05 21:02:25 +00:00
|
|
|
dv.setUint32(total, parseInt(record.retry || record.ret, 10), false);
|
2017-03-18 17:38:43 +00:00
|
|
|
total+=4;
|
2017-10-05 21:02:25 +00:00
|
|
|
dv.setUint32(total, parseInt(record.expiration || record.ex, 10), false);
|
2017-03-17 00:48:08 +00:00
|
|
|
total+=4;
|
2017-10-05 21:02:25 +00:00
|
|
|
dv.setUint32(total, parseInt(record.minimum || record.nx, 10), false);
|
2017-03-17 00:48:08 +00:00
|
|
|
total+=4;
|
|
|
|
|
|
|
|
// RDLENGTH
|
2017-10-05 21:02:25 +00:00
|
|
|
//console.log('rdAt', rdLenIndex);
|
|
|
|
//console.log('soaLen (lables + 2 + 20)', soaLen);
|
2017-03-17 00:48:08 +00:00
|
|
|
dv.setUint16(rdLenIndex, soaLen, false);
|
2017-03-05 00:10:25 +00:00
|
|
|
|
|
|
|
return total;
|
|
|
|
};
|
|
|
|
|
|
|
|
}('undefined' !== typeof window ? window : exports));
|