summaryrefslogtreecommitdiff
path: root/src/pkg/net/dnsmsg.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/net/dnsmsg.go')
-rw-r--r--src/pkg/net/dnsmsg.go145
1 files changed, 86 insertions, 59 deletions
diff --git a/src/pkg/net/dnsmsg.go b/src/pkg/net/dnsmsg.go
index dc195caf8..e8eb8d958 100644
--- a/src/pkg/net/dnsmsg.go
+++ b/src/pkg/net/dnsmsg.go
@@ -50,6 +50,7 @@ const (
dnsTypeMINFO = 14
dnsTypeMX = 15
dnsTypeTXT = 16
+ dnsTypeAAAA = 28
dnsTypeSRV = 33
// valid dnsQuestion.qtype only
@@ -244,8 +245,18 @@ type dnsRR_A struct {
A uint32 "ipv4"
}
-func (rr *dnsRR_A) Header() *dnsRR_Header { return &rr.Hdr }
+func (rr *dnsRR_A) Header() *dnsRR_Header {
+ return &rr.Hdr
+}
+
+type dnsRR_AAAA struct {
+ Hdr dnsRR_Header
+ AAAA [16]byte "ipv6"
+}
+func (rr *dnsRR_AAAA) Header() *dnsRR_Header {
+ return &rr.Hdr
+}
// Packing and unpacking.
//
@@ -270,6 +281,7 @@ var rr_mk = map[int]func() dnsRR{
dnsTypeTXT: func() dnsRR { return new(dnsRR_TXT) },
dnsTypeSRV: func() dnsRR { return new(dnsRR_SRV) },
dnsTypeA: func() dnsRR { return new(dnsRR_A) },
+ dnsTypeAAAA: func() dnsRR { return new(dnsRR_AAAA) },
}
// Pack a domain name s into msg[off:].
@@ -377,43 +389,49 @@ Loop:
// TODO(rsc): Move into generic library?
// Pack a reflect.StructValue into msg. Struct members can only be uint16, uint32, string,
-// and other (often anonymous) structs.
-func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, ok bool) {
+// [n]byte, and other (often anonymous) structs.
+func packStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok bool) {
for i := 0; i < val.NumField(); i++ {
- f := val.Type().(*reflect.StructType).Field(i)
- switch fv := val.Field(i).(type) {
+ f := val.Type().Field(i)
+ switch fv := val.Field(i); fv.Kind() {
default:
BadType:
fmt.Fprintf(os.Stderr, "net: dns: unknown packing type %v", f.Type)
return len(msg), false
- case *reflect.StructValue:
+ case reflect.Struct:
off, ok = packStructValue(fv, msg, off)
- case *reflect.UintValue:
- i := fv.Get()
- switch fv.Type().Kind() {
- default:
+ case reflect.Uint16:
+ if off+2 > len(msg) {
+ return len(msg), false
+ }
+ i := fv.Uint()
+ msg[off] = byte(i >> 8)
+ msg[off+1] = byte(i)
+ off += 2
+ case reflect.Uint32:
+ if off+4 > len(msg) {
+ return len(msg), false
+ }
+ i := fv.Uint()
+ msg[off] = byte(i >> 24)
+ msg[off+1] = byte(i >> 16)
+ msg[off+2] = byte(i >> 8)
+ msg[off+3] = byte(i)
+ off += 4
+ case reflect.Array:
+ if fv.Type().Elem().Kind() != reflect.Uint8 {
goto BadType
- case reflect.Uint16:
- if off+2 > len(msg) {
- return len(msg), false
- }
- msg[off] = byte(i >> 8)
- msg[off+1] = byte(i)
- off += 2
- case reflect.Uint32:
- if off+4 > len(msg) {
- return len(msg), false
- }
- msg[off] = byte(i >> 24)
- msg[off+1] = byte(i >> 16)
- msg[off+2] = byte(i >> 8)
- msg[off+3] = byte(i)
- off += 4
}
- case *reflect.StringValue:
+ n := fv.Len()
+ if off+n > len(msg) {
+ return len(msg), false
+ }
+ reflect.Copy(reflect.NewValue(msg[off:off+n]), fv)
+ off += n
+ case reflect.String:
// There are multiple string encodings.
// The tag distinguishes ordinary strings from domain names.
- s := fv.Get()
+ s := fv.String()
switch f.Tag {
default:
fmt.Fprintf(os.Stderr, "net: dns: unknown string tag %v", f.Tag)
@@ -437,8 +455,8 @@ func packStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, o
return off, true
}
-func structValue(any interface{}) *reflect.StructValue {
- return reflect.NewValue(any).(*reflect.PtrValue).Elem().(*reflect.StructValue)
+func structValue(any interface{}) reflect.Value {
+ return reflect.NewValue(any).Elem()
}
func packStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) {
@@ -449,36 +467,41 @@ func packStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) {
// TODO(rsc): Move into generic library?
// Unpack a reflect.StructValue from msg.
// Same restrictions as packStructValue.
-func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int, ok bool) {
+func unpackStructValue(val reflect.Value, msg []byte, off int) (off1 int, ok bool) {
for i := 0; i < val.NumField(); i++ {
- f := val.Type().(*reflect.StructType).Field(i)
- switch fv := val.Field(i).(type) {
+ f := val.Type().Field(i)
+ switch fv := val.Field(i); fv.Kind() {
default:
BadType:
fmt.Fprintf(os.Stderr, "net: dns: unknown packing type %v", f.Type)
return len(msg), false
- case *reflect.StructValue:
+ case reflect.Struct:
off, ok = unpackStructValue(fv, msg, off)
- case *reflect.UintValue:
- switch fv.Type().Kind() {
- default:
+ case reflect.Uint16:
+ if off+2 > len(msg) {
+ return len(msg), false
+ }
+ i := uint16(msg[off])<<8 | uint16(msg[off+1])
+ fv.SetUint(uint64(i))
+ off += 2
+ case reflect.Uint32:
+ if off+4 > len(msg) {
+ return len(msg), false
+ }
+ i := uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3])
+ fv.SetUint(uint64(i))
+ off += 4
+ case reflect.Array:
+ if fv.Type().Elem().Kind() != reflect.Uint8 {
goto BadType
- case reflect.Uint16:
- if off+2 > len(msg) {
- return len(msg), false
- }
- i := uint16(msg[off])<<8 | uint16(msg[off+1])
- fv.Set(uint64(i))
- off += 2
- case reflect.Uint32:
- if off+4 > len(msg) {
- return len(msg), false
- }
- i := uint32(msg[off])<<24 | uint32(msg[off+1])<<16 | uint32(msg[off+2])<<8 | uint32(msg[off+3])
- fv.Set(uint64(i))
- off += 4
}
- case *reflect.StringValue:
+ n := fv.Len()
+ if off+n > len(msg) {
+ return len(msg), false
+ }
+ reflect.Copy(fv, reflect.NewValue(msg[off:off+n]))
+ off += n
+ case reflect.String:
var s string
switch f.Tag {
default:
@@ -502,7 +525,7 @@ func unpackStructValue(val *reflect.StructValue, msg []byte, off int) (off1 int,
off += n
s = string(b)
}
- fv.Set(s)
+ fv.SetString(s)
}
}
return off, true
@@ -515,24 +538,28 @@ func unpackStruct(any interface{}, msg []byte, off int) (off1 int, ok bool) {
// Generic struct printer.
// Doesn't care about the string tag "domain-name",
-// but does look for an "ipv4" tag on uint32 variables,
+// but does look for an "ipv4" tag on uint32 variables
+// and the "ipv6" tag on array variables,
// printing them as IP addresses.
-func printStructValue(val *reflect.StructValue) string {
+func printStructValue(val reflect.Value) string {
s := "{"
for i := 0; i < val.NumField(); i++ {
if i > 0 {
s += ", "
}
- f := val.Type().(*reflect.StructType).Field(i)
+ f := val.Type().Field(i)
if !f.Anonymous {
s += f.Name + "="
}
fval := val.Field(i)
- if fv, ok := fval.(*reflect.StructValue); ok {
+ if fv := fval; fv.Kind() == reflect.Struct {
s += printStructValue(fv)
- } else if fv, ok := fval.(*reflect.UintValue); ok && f.Tag == "ipv4" {
- i := fv.Get()
+ } else if fv := fval; (fv.Kind() == reflect.Uint || fv.Kind() == reflect.Uint8 || fv.Kind() == reflect.Uint16 || fv.Kind() == reflect.Uint32 || fv.Kind() == reflect.Uint64 || fv.Kind() == reflect.Uintptr) && f.Tag == "ipv4" {
+ i := fv.Uint()
s += IPv4(byte(i>>24), byte(i>>16), byte(i>>8), byte(i)).String()
+ } else if fv := fval; fv.Kind() == reflect.Array && f.Tag == "ipv6" {
+ i := fv.Interface().([]byte)
+ s += IP(i).String()
} else {
s += fmt.Sprint(fval.Interface())
}