diff --git a/addr.go b/addr.go index fe3e3d3..f08c956 100644 --- a/addr.go +++ b/addr.go @@ -10,11 +10,13 @@ import ( // include a mask, so it stores the address as a net.IPNet. type Addr struct { *net.IPNet - Label string - Flags int - Scope int - Peer *net.IPNet - Broadcast net.IP + Label string + Flags int + Scope int + Peer *net.IPNet + Broadcast net.IP + PreferedLft int + ValidLft int } // String returns $ip/$netmask $label diff --git a/addr_linux.go b/addr_linux.go index 220f0f2..75b9c56 100644 --- a/addr_linux.go +++ b/addr_linux.go @@ -199,6 +199,10 @@ func parseAddr(m []byte) (addr Addr, family, index int, err error) { addr.Label = string(attr.Value[:len(attr.Value)-1]) case IFA_FLAGS: addr.Flags = int(native.Uint32(attr.Value[0:4])) + case nl.IFA_CACHEINFO: + ci := nl.DeserializeIfaCacheInfo(attr.Value) + addr.PreferedLft = int(ci.IfaPrefered) + addr.ValidLft = int(ci.IfaValid) } } diff --git a/nl/addr_linux.go b/nl/addr_linux.go index 17088fa..fe362e9 100644 --- a/nl/addr_linux.go +++ b/nl/addr_linux.go @@ -45,3 +45,32 @@ func (msg *IfAddrmsg) Serialize() []byte { func (msg *IfAddrmsg) Len() int { return syscall.SizeofIfAddrmsg } + +// struct ifa_cacheinfo { +// __u32 ifa_prefered; +// __u32 ifa_valid; +// __u32 cstamp; /* created timestamp, hundredths of seconds */ +// __u32 tstamp; /* updated timestamp, hundredths of seconds */ +// }; + +const IFA_CACHEINFO = 6 +const SizeofIfaCacheInfo = 0x10 + +type IfaCacheInfo struct { + IfaPrefered uint32 + IfaValid uint32 + Cstamp uint32 + Tstamp uint32 +} + +func (msg *IfaCacheInfo) Len() int { + return SizeofIfaCacheInfo +} + +func DeserializeIfaCacheInfo(b []byte) *IfaCacheInfo { + return (*IfaCacheInfo)(unsafe.Pointer(&b[0:SizeofIfaCacheInfo][0])) +} + +func (msg *IfaCacheInfo) Serialize() []byte { + return (*(*[SizeofIfaCacheInfo]byte)(unsafe.Pointer(msg)))[:] +} diff --git a/nl/addr_linux_test.go b/nl/addr_linux_test.go index 98c3b21..07b0201 100644 --- a/nl/addr_linux_test.go +++ b/nl/addr_linux_test.go @@ -37,3 +37,32 @@ func TestIfAddrmsgDeserializeSerialize(t *testing.T) { msg := DeserializeIfAddrmsg(orig) testDeserializeSerialize(t, orig, safemsg, msg) } + +func (msg *IfaCacheInfo) write(b []byte) { + native := NativeEndian() + native.PutUint32(b[0:4], uint32(msg.IfaPrefered)) + native.PutUint32(b[4:8], uint32(msg.IfaValid)) + native.PutUint32(b[8:12], uint32(msg.Cstamp)) + native.PutUint32(b[12:16], uint32(msg.Tstamp)) +} + +func (msg *IfaCacheInfo) serializeSafe() []byte { + length := SizeofIfaCacheInfo + b := make([]byte, length) + msg.write(b) + return b +} + +func deserializeIfaCacheInfoSafe(b []byte) *IfaCacheInfo { + var msg = IfaCacheInfo{} + binary.Read(bytes.NewReader(b[0:SizeofIfaCacheInfo]), NativeEndian(), &msg) + return &msg +} + +func TestIfaCacheInfoDeserializeSerialize(t *testing.T) { + var orig = make([]byte, SizeofIfaCacheInfo) + rand.Read(orig) + safemsg := deserializeIfaCacheInfoSafe(orig) + msg := DeserializeIfaCacheInfo(orig) + testDeserializeSerialize(t, orig, safemsg, msg) +}