// AddrList gets a list of IP addresses in the system. // Equivalent to: `ip addr show`. // The list can be filtered by link and ip family. func AddrList(link Link, family int) ([]Addr, error) { req := nl.NewNetlinkRequest(syscall.RTM_GETADDR, syscall.NLM_F_DUMP) msg := nl.NewIfInfomsg(family) req.AddData(msg) msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWADDR) if err != nil { return nil, err } index := 0 if link != nil { base := link.Attrs() ensureIndex(base) index = base.Index } res := make([]Addr, 0) for _, m := range msgs { msg := nl.DeserializeIfAddrmsg(m) if link != nil && msg.Index != uint32(index) { // Ignore messages from other interfaces continue } attrs, err := nl.ParseRouteAttr(m[msg.Len():]) if err != nil { return nil, err } var addr Addr for _, attr := range attrs { switch attr.Attr.Type { case syscall.IFA_ADDRESS: addr.IPNet = &net.IPNet{ IP: attr.Value, Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), } case syscall.IFA_LABEL: addr.Label = string(attr.Value[:len(attr.Value)-1]) } } res = append(res, addr) } return res, nil }
func parseAddr(m []byte) (addr Addr, family, index int, err error) { msg := nl.DeserializeIfAddrmsg(m) family = -1 index = -1 attrs, err1 := nl.ParseRouteAttr(m[msg.Len():]) if err1 != nil { err = err1 return } family = int(msg.Family) index = int(msg.Index) var local, dst *net.IPNet for _, attr := range attrs { switch attr.Attr.Type { case syscall.IFA_ADDRESS: dst = &net.IPNet{ IP: attr.Value, Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), } addr.Peer = dst case syscall.IFA_LOCAL: local = &net.IPNet{ IP: attr.Value, Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), } addr.IPNet = local case syscall.IFA_LABEL: addr.Label = string(attr.Value[:len(attr.Value)-1]) case IFA_FLAGS: addr.Flags = int(native.Uint32(attr.Value[0:4])) } } // IFA_LOCAL should be there but if not, fall back to IFA_ADDRESS if local != nil { addr.IPNet = local } else { addr.IPNet = dst } addr.Scope = int(msg.Scope) return }
// AddrList gets a list of IP addresses in the system. // Equivalent to: `ip addr show`. // The list can be filtered by link and ip family. func AddrList(link Link, family int) ([]Addr, error) { req := nl.NewNetlinkRequest(syscall.RTM_GETADDR, syscall.NLM_F_DUMP) msg := nl.NewIfInfomsg(family) req.AddData(msg) msgs, err := req.Execute(syscall.NETLINK_ROUTE, syscall.RTM_NEWADDR) if err != nil { return nil, err } index := 0 if link != nil { base := link.Attrs() ensureIndex(base) index = base.Index } var res []Addr for _, m := range msgs { msg := nl.DeserializeIfAddrmsg(m) if link != nil && msg.Index != uint32(index) { // Ignore messages from other interfaces continue } attrs, err := nl.ParseRouteAttr(m[msg.Len():]) if err != nil { return nil, err } var local, dst *net.IPNet var addr Addr for _, attr := range attrs { switch attr.Attr.Type { case syscall.IFA_ADDRESS: dst = &net.IPNet{ IP: attr.Value, Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), } case syscall.IFA_LOCAL: local = &net.IPNet{ IP: attr.Value, Mask: net.CIDRMask(int(msg.Prefixlen), 8*len(attr.Value)), } case syscall.IFA_LABEL: addr.Label = string(attr.Value[:len(attr.Value)-1]) case IFA_FLAGS: addr.Flags = int(native.Uint32(attr.Value[0:4])) } } // IFA_LOCAL should be there but if not, fall back to IFA_ADDRESS if local != nil { addr.IPNet = local } else { addr.IPNet = dst } addr.Scope = int(msg.Scope) res = append(res, addr) } return res, nil }