func (self *LinkHandler) SetLinkState(flag link.Flags) (err error) { var qry *netlink.Message if hdr, ok := self.cache.Header.(*link.Header); ok { // While rtnetlink(7) says changes should always be IFF_QUERY, it has some // behaviours that are undocumented - like limiting actions on SETLINK's to // specific FLAGs. hdr = link.NewHeader(hdr.InterfaceFamily(), hdr.InterfaceType(), hdr.InterfaceIndex(), flag&link.IFF_UP, link.IFF_UP) msg := rtnetlink.Message{Header: hdr} qry, err = netlink.NewMessage(rtnetlink.RTM_SETLINK, netlink.NLM_F_ACK|netlink.NLM_F_REQUEST, msg) } else { err = errors.New("Cant set link flags (invalid cache)") } if err != nil { return } mch, err := self.h.Query(*qry, 1) if err == nil { for m := range mch { switch m.Header.MessageType() { case netlink.NLMSG_ERROR: emsg := &netlink.Error{} err = emsg.UnmarshalNetlink(m.Body) if err == nil && emsg.Code() != 0 { err = emsg } default: err = errors.New("Unexpected netlink message") log.Printf("NetlinkError: %v", err) } } close(mch) } return }
func (self *linkFinder) GetLinkByID(i uint32) (lh *LinkHandler, err error) { qry, err := netlink.NewMessage(rtnetlink.RTM_GETLINK, netlink.NLM_F_REQUEST, link.NewHeader(rtnetlink.AF_UNSPEC, 0, i, 0, 0)) if err == nil { var mch chan netlink.Message mch, err = self.h.Query(*qry, 1) if err == nil { for ii := range mch { switch ii.Header.MessageType() { default: err = errors.New("Unknown message type in response to RTM_GETLINK") case netlink.NLMSG_ERROR: emsg := &netlink.Error{} err = emsg.UnmarshalNetlink(ii.Body) if err == nil && emsg.Code() != 0 { err = emsg } case rtnetlink.RTM_NEWLINK: lhdr := &link.Header{} msg := &rtnetlink.Message{Header: lhdr} err = msg.UnmarshalNetlink(ii.Body) if err == nil { lh = &LinkHandler{h: self.h, cache: msg} } } } close(mch) } } return }
func main() { // This imitates the functionality of rtnl_wilddump_req_filter from bridge/vlan.c in the // iproute2 code. Note that the filter requires kernel 3.9 or newer data := make([]byte, 4) binary.LittleEndian.PutUint32(data, link.RTEXT_FILTER_BRVLAN) lnmsg := link.NewHeader(rtnetlink.AF_BRIDGE, 0, 0, 0, 0) msg := rtnetlink.NewMessage(lnmsg, []netlink.Attribute{{link.IFLA_EXT_MASK, data}}) nlmsg, err := netlink.NewMessage(rtnetlink.RTM_GETLINK, netlink.NLM_F_DUMP|netlink.NLM_F_REQUEST, msg) if err != nil { log.Panicf("Couldn't construct message: %v", err) } nlsock, err := netlink.Dial(netlink.NETLINK_ROUTE) if err != nil { log.Panicf("Couldn't dial netlink: %v", err) } h := netlink.NewHandler(nlsock) ec := make(chan error) go h.Start(ec) c, err := h.Query(*nlmsg, 1) if err != nil { log.Panicf("Couldn't write netlink: %v", err) } for i := range c { if i.Header.MessageType() == netlink.NLMSG_DONE { break } switch i.Header.MessageType() { case rtnetlink.RTM_NEWLINK: hdr := &link.Header{} msg := rtnetlink.NewMessage(hdr, nil) err = msg.UnmarshalNetlink(i.Body) if err == nil { log.Printf("Link[%d] (Family: %v; Type: %v; Flags: %v; Changes: %v)", hdr.InterfaceIndex(), hdr.InterfaceFamily(), hdr.InterfaceType(), hdr.Flags(), hdr.InterfaceChanges()) for i := range msg.Attributes { log.Printf("Attribute[%d]: %v", i, msg.Attributes[i]) } } else { log.Printf("Unmarshal error: %v", err) } default: log.Printf("Unknown type: %v", i) } } }
func (self *linkFinder) GetLinks() (lhs []*LinkHandler, err error) { qry, err := netlink.NewMessage(rtnetlink.RTM_GETLINK, netlink.NLM_F_REQUEST|netlink.NLM_F_ROOT, link.NewHeader(rtnetlink.AF_UNSPEC, 0, 0, 0, 0)) if err != nil { return } var mch chan netlink.Message mch, err = self.h.Query(*qry, 1) if err == nil { for ii := range mch { if ii.Header.MessageType() == netlink.NLMSG_DONE { break } switch ii.Header.MessageType() { default: err = errors.New("Unknown message type in response to RTM_GETLINK") case netlink.NLMSG_ERROR: emsg := &netlink.Error{} err = emsg.UnmarshalNetlink(ii.Body) if err == nil && emsg.Code() != 0 { err = emsg } case rtnetlink.RTM_NEWLINK: lhdr := &link.Header{} msg := &rtnetlink.Message{Header: lhdr} err = msg.UnmarshalNetlink(ii.Body) if err == nil { lhs = append(lhs, &LinkHandler{h: self.h, cache: msg}) } } if err != nil { log.Printf("Internal netlink failure: %v", err) } } } close(mch) return }