UNPKG

4.5 kBJavaScriptView Raw
1/*
2Copyright 2011 Timothy J Fontaine <tjfontaine@gmail.com>
3
4Permission is hereby granted, free of charge, to any person obtaining a copy
5of this software and associated documentation files (the "Software"), to deal
6in the Software without restriction, including without limitation the rights
7to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8copies of the Software, and to permit persons to whom the Software is
9furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
21*/
22
23"use strict";
24
25var util = require('util'),
26 Message = require('./message'),
27 fields = require('./fields'),
28 ResourceRecord = require('./resourcerecord'),
29 types = require('./types'),
30 consts = require('./consts'),
31 Packet = require('./packet');
32
33var OptField = function () {
34 this._fields = [
35 fields.Struct('code', 'H'),
36 fields.BufferField('data', 'H'),
37 ];
38 Message.call(this);
39};
40util.inherits(OptField, Message);
41
42var ednsFields = [
43 fields.Label('name'),
44 fields.Struct('type', 'H'),
45 fields.Struct('udpSize', 'H'),
46 fields.Struct('rcode', 'B'),
47 fields.Struct('version', 'B'),
48 fields.Struct('bitfields', 'H'),
49 fields.BufferField('rdata', 'H'),
50];
51
52var bitFields = [
53 fields.SubField('do', 'bitfields', 15, 0x8000),
54];
55
56var OPT = exports.OPT = function (vals) {
57 this._fields = ednsFields;
58 this._sub_fields = bitFields;
59 Message.call(this);
60
61 this.type = consts.NAME_TO_QTYPE.OPT;
62 this.options = [];
63
64 this.initialize(vals);
65};
66util.inherits(OPT, Message);
67
68types.map[consts.NAME_TO_QTYPE.OPT] = OPT;
69types.exported.OPT = OPT;
70
71OPT.prototype.initialize = ResourceRecord.prototype.initialize;
72
73OPT.prototype.pack = function (buff, pos) {
74 var spos = pos;
75
76 this.options.forEach(function(field) {
77 pos += field.pack(buff, pos);
78 });
79
80 this.rdata = buff.slice(spos, pos);
81
82 return Message.prototype.pack.call(this, buff, pos);
83};
84
85OPT.prototype.unpackRData = function () {
86 var field, offset, rdata_pos;
87
88 offset = 0;
89 rdata_pos = this._fields[4].position;
90
91 while (offset !== this.rdata.length) {
92 field = new OptField();
93 offset += field.unpack(this.raw_, rdata_pos + offset);
94 this.options.push(field);
95 }
96};
97
98var EDNSPacket = exports.EDNSPacket = function (socket, rinfo) {
99 Packet.call(this, socket, rinfo);
100
101 Object.defineProperty(this, 'opt', {
102 get: function () {
103 var promoted;
104
105 if (this.additional.length === 0) {
106 this.additional.push(new OPT());
107 }
108
109 promoted = this.additional[0] instanceof OPT;
110
111 if (!promoted) {
112 this.additional[0] = this.additional[0].promote();
113 }
114
115 return this.additional[0];
116 },
117 });
118
119 Object.defineProperty(this, 'rcode', {
120 get: function () {
121 return this.header.rcode + (this.opt.rcode << 4);
122 },
123 set: function (value) {
124 this.opt.rcode = value >> 4;
125 this.header.rcode = value - (this.opt.rcode << 4);
126 },
127 configurable: true,
128 });
129
130 Object.defineProperty(this, 'version', {
131 get: function () {
132 return this.opt.version;
133 },
134 set: function (value) {
135 this.opt.version = value;
136 },
137 });
138
139 Object.defineProperty(this, 'udpSize', {
140 get: function () {
141 return this.opt.udpSize;
142 },
143 set: function (value) {
144 this.opt.udpSize = value;
145 },
146 });
147
148 Object.defineProperty(this, 'do', {
149 get: function () {
150 return this.opt.do;
151 },
152 set: function (value) {
153 this.opt.do = value;
154 },
155 });
156
157 this.version = 0;
158 this.udpSize = 4096;
159 this.do = 1;
160};
161util.inherits(EDNSPacket, Packet);
162
163Packet.prototype.isEDNS = function () {
164 return this.additional.length > 0 && this.additional[0].type === consts.NAME_TO_QTYPE.OPT;
165};
166
167Packet.prototype.promote = function () {
168 var newInstance;
169
170 if (!this.isEDNS()) {
171 return this;
172 }
173
174 newInstance = new EDNSPacket(this._socket, this._rinfo);
175 newInstance.unpack(this.raw_);
176
177 return newInstance;
178};