diff options
Diffstat (limited to 'internal/dns/rr_opt.go')
| -rw-r--r-- | internal/dns/rr_opt.go | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/internal/dns/rr_opt.go b/internal/dns/rr_opt.go new file mode 100644 index 0000000..77bc1ee --- /dev/null +++ b/internal/dns/rr_opt.go @@ -0,0 +1,57 @@ +package dns + +import "fmt" + +// https://datatracker.ietf.org/doc/html/rfc6891#section-4.1 +type Option struct { + Code uint16 + Data []byte +} + +type OPT struct { + // https://datatracker.ietf.org/doc/html/rfc6891#section-4.3 + UDPSize uint16 + ExtRCode uint8 + Version uint8 + DO bool + Z uint16 + Options []Option +} + +func (o *OPT) Type() uint16 { return TypeOPT } + +func (o *OPT) Pack(p *packer) error { + for _, opt := range o.Options { + p.writeUint16(opt.Code) + p.writeUint16(uint16(len(opt.Data))) + p.buf = append(p.buf, opt.Data...) + } + return nil +} + +func (o *OPT) Unpack(u *unpacker, length uint16) error { + end := u.off + int(length) + for u.off < end { + code, err := u.readUint16() + if err != nil { + return err + } + optLen, err := u.readUint16() + if err != nil { + return err + } + if u.off+int(optLen) > end { + return fmt.Errorf("dns: opt data overflow") + } + o.Options = append(o.Options, Option{ + Code: code, + Data: append([]byte(nil), u.buf[u.off:u.off+int(optLen)]...), + }) + u.off += int(optLen) + } + return nil +} + +func (o *OPT) String() string { + return fmt.Sprintf("OPT udpsize=%d extrcode=%d version=%d do=%t", o.UDPSize, o.ExtRCode, o.Version, o.DO) +} |
