|
| 1 | +import { stringToBinary, binaryToString } from "../encoding"; |
| 2 | +import { ParseError } from "../error"; |
| 3 | +import { Slice } from "../packet"; |
| 4 | +import { RR } from "../rr"; |
| 5 | +import { Writer } from "../buffer"; |
| 6 | +import { CharacterString } from "../char"; |
| 7 | +import { Uint16, Uint8 } from "../types"; |
| 8 | + |
| 9 | +/** |
| 10 | + * The DHCID (DHCP Identifier) record is used to associate a DHCP client identity with a domain name. |
| 11 | + * |
| 12 | + * The record contains a digest generated from the client's identifier and FQDN, |
| 13 | + * ensuring only the rightful DHCP client can update the DNS entry. |
| 14 | + * |
| 15 | + * RDATA format (RFC 4701): |
| 16 | + * ``` |
| 17 | + * 0 1 2 3 |
| 18 | + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
| 19 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 20 | + * | identifier type (16 bits) | digest type | | |
| 21 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + |
| 22 | + * | digest (binary) | |
| 23 | + * | | |
| 24 | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| 25 | + * ``` |
| 26 | + * |
| 27 | + * Specified by {@link https://datatracker.ietf.org/doc/html/rfc4701 | RFC 4701} |
| 28 | + */ |
| 29 | +export class DHCID extends RR { |
| 30 | + identifierType!: Uint16; // 2 bytes |
| 31 | + digestType!: Uint8; // 1 byte |
| 32 | + digest!: Uint8Array; // variable length |
| 33 | + |
| 34 | + unpackRdata(rdata: Slice): void { |
| 35 | + this.identifierType = rdata.readUint16(); |
| 36 | + this.digestType = rdata.readUint8(); |
| 37 | + this.digest = rdata.readUint8Array(); |
| 38 | + } |
| 39 | + |
| 40 | + packRdata(buf: Writer): number { |
| 41 | + let n = buf.writeUint16(this.identifierType); |
| 42 | + n += buf.writeUint8(this.digestType); |
| 43 | + n += buf.write(this.digest); |
| 44 | + return n; |
| 45 | + } |
| 46 | + |
| 47 | + parseRdata(rdata: CharacterString[]): void { |
| 48 | + if (rdata.length === 0) { |
| 49 | + throw new ParseError("Missing fields in DHCID RDATA"); |
| 50 | + } |
| 51 | + |
| 52 | + const str = rdata.reduce((v, cur) => v += cur.raw(), ""); |
| 53 | + const data = stringToBinary(str, "base64"); |
| 54 | + |
| 55 | + // At lease has 3 bytes, the first two bytes is the identifier type and |
| 56 | + // the third one is digest type. |
| 57 | + if (data.byteLength < 3) { |
| 58 | + throw new ParseError("Invalid DHCID RDATA"); |
| 59 | + } |
| 60 | + |
| 61 | + this.identifierType = (data[0] << 8) | data[1]; |
| 62 | + this.digestType = data[2]; |
| 63 | + |
| 64 | + this.digest = data.slice(3); |
| 65 | + } |
| 66 | + |
| 67 | + presentRdata(): string { |
| 68 | + const data = new Uint8Array(3 + this.digest.byteLength); |
| 69 | + data[0] = this.identifierType >>> 8; |
| 70 | + data[1] = this.identifierType & 0xff; |
| 71 | + data[2] = this.digestType; |
| 72 | + data.set(this.digest, 3); |
| 73 | + return binaryToString(data, "base64"); |
| 74 | + } |
| 75 | +} |
0 commit comments