From 2f9641289a415102983d28a42342337afc90c390 Mon Sep 17 00:00:00 2001 From: am Date: Wed, 3 Oct 2012 15:41:29 +1300 Subject: [PATCH 1/3] reorganising to standard structure --- GITIGNORE => .gitignore | 1 + src/{ => netlink}/address.go | 0 src/{ => netlink}/attr_helpers.go | 0 src/{ => netlink}/attribute.go | 0 src/{ => netlink}/error.go | 0 src/{ => netlink}/family.go | 0 src/{ => netlink}/flags.go | 0 src/{ => netlink}/handler.go | 0 src/{ => netlink}/header.go | 0 src/{ => netlink}/message.go | 0 src/{ => netlink}/pad.go | 0 src/{ => netlink}/rtmanip/Makefile | 0 src/{ => netlink}/rtmanip/links.go | 0 src/{ => netlink}/rtnetlink/Makefile | 0 src/{ => netlink}/rtnetlink/README | 0 src/{ => netlink}/rtnetlink/addr/Makefile | 0 src/{ => netlink}/rtnetlink/addr/attribute_types.go | 0 src/{ => netlink}/rtnetlink/addr/flags.go | 0 src/{ => netlink}/rtnetlink/addr/header.go | 0 src/{ => netlink}/rtnetlink/family.go | 0 src/{ => netlink}/rtnetlink/groups.go | 0 src/{ => netlink}/rtnetlink/header.go | 0 src/{ => netlink}/rtnetlink/link/Makefile | 0 src/{ => netlink}/rtnetlink/link/attribute_types.go | 0 src/{ => netlink}/rtnetlink/link/flags.go | 0 src/{ => netlink}/rtnetlink/link/header.go | 0 src/{ => netlink}/rtnetlink/message.go | 0 src/{ => netlink}/rtnetlink/message_types.go | 0 src/{ => netlink}/rtnetlink/route/Makefile | 0 src/{ => netlink}/rtnetlink/route/attribute_types.go | 0 src/{ => netlink}/rtnetlink/route/flags.go | 0 src/{ => netlink}/rtnetlink/route/header.go | 0 src/{ => netlink}/rtnetlink/route/origin.go | 0 src/{ => netlink}/rtnetlink/route/table.go | 0 src/{ => netlink}/rtnetlink/route/types.go | 0 src/{ => netlink}/rtnetlink/scope.go | 0 src/{ => netlink}/socket.go | 0 src/{ => netlink}/types.go | 0 38 files changed, 1 insertion(+) rename GITIGNORE => .gitignore (95%) rename src/{ => netlink}/address.go (100%) rename src/{ => netlink}/attr_helpers.go (100%) rename src/{ => netlink}/attribute.go (100%) rename src/{ => netlink}/error.go (100%) rename src/{ => netlink}/family.go (100%) rename src/{ => netlink}/flags.go (100%) rename src/{ => netlink}/handler.go (100%) rename src/{ => netlink}/header.go (100%) rename src/{ => netlink}/message.go (100%) rename src/{ => netlink}/pad.go (100%) rename src/{ => netlink}/rtmanip/Makefile (100%) rename src/{ => netlink}/rtmanip/links.go (100%) rename src/{ => netlink}/rtnetlink/Makefile (100%) rename src/{ => netlink}/rtnetlink/README (100%) rename src/{ => netlink}/rtnetlink/addr/Makefile (100%) rename src/{ => netlink}/rtnetlink/addr/attribute_types.go (100%) rename src/{ => netlink}/rtnetlink/addr/flags.go (100%) rename src/{ => netlink}/rtnetlink/addr/header.go (100%) rename src/{ => netlink}/rtnetlink/family.go (100%) rename src/{ => netlink}/rtnetlink/groups.go (100%) rename src/{ => netlink}/rtnetlink/header.go (100%) rename src/{ => netlink}/rtnetlink/link/Makefile (100%) rename src/{ => netlink}/rtnetlink/link/attribute_types.go (100%) rename src/{ => netlink}/rtnetlink/link/flags.go (100%) rename src/{ => netlink}/rtnetlink/link/header.go (100%) rename src/{ => netlink}/rtnetlink/message.go (100%) rename src/{ => netlink}/rtnetlink/message_types.go (100%) rename src/{ => netlink}/rtnetlink/route/Makefile (100%) rename src/{ => netlink}/rtnetlink/route/attribute_types.go (100%) rename src/{ => netlink}/rtnetlink/route/flags.go (100%) rename src/{ => netlink}/rtnetlink/route/header.go (100%) rename src/{ => netlink}/rtnetlink/route/origin.go (100%) rename src/{ => netlink}/rtnetlink/route/table.go (100%) rename src/{ => netlink}/rtnetlink/route/types.go (100%) rename src/{ => netlink}/rtnetlink/scope.go (100%) rename src/{ => netlink}/socket.go (100%) rename src/{ => netlink}/types.go (100%) diff --git a/GITIGNORE b/.gitignore similarity index 95% rename from GITIGNORE rename to .gitignore index 2c10515..4bef869 100644 --- a/GITIGNORE +++ b/.gitignore @@ -6,3 +6,4 @@ tools/get_routes tools/get_addrs tools/get_links tools/ifmanip +pkg diff --git a/src/address.go b/src/netlink/address.go similarity index 100% rename from src/address.go rename to src/netlink/address.go diff --git a/src/attr_helpers.go b/src/netlink/attr_helpers.go similarity index 100% rename from src/attr_helpers.go rename to src/netlink/attr_helpers.go diff --git a/src/attribute.go b/src/netlink/attribute.go similarity index 100% rename from src/attribute.go rename to src/netlink/attribute.go diff --git a/src/error.go b/src/netlink/error.go similarity index 100% rename from src/error.go rename to src/netlink/error.go diff --git a/src/family.go b/src/netlink/family.go similarity index 100% rename from src/family.go rename to src/netlink/family.go diff --git a/src/flags.go b/src/netlink/flags.go similarity index 100% rename from src/flags.go rename to src/netlink/flags.go diff --git a/src/handler.go b/src/netlink/handler.go similarity index 100% rename from src/handler.go rename to src/netlink/handler.go diff --git a/src/header.go b/src/netlink/header.go similarity index 100% rename from src/header.go rename to src/netlink/header.go diff --git a/src/message.go b/src/netlink/message.go similarity index 100% rename from src/message.go rename to src/netlink/message.go diff --git a/src/pad.go b/src/netlink/pad.go similarity index 100% rename from src/pad.go rename to src/netlink/pad.go diff --git a/src/rtmanip/Makefile b/src/netlink/rtmanip/Makefile similarity index 100% rename from src/rtmanip/Makefile rename to src/netlink/rtmanip/Makefile diff --git a/src/rtmanip/links.go b/src/netlink/rtmanip/links.go similarity index 100% rename from src/rtmanip/links.go rename to src/netlink/rtmanip/links.go diff --git a/src/rtnetlink/Makefile b/src/netlink/rtnetlink/Makefile similarity index 100% rename from src/rtnetlink/Makefile rename to src/netlink/rtnetlink/Makefile diff --git a/src/rtnetlink/README b/src/netlink/rtnetlink/README similarity index 100% rename from src/rtnetlink/README rename to src/netlink/rtnetlink/README diff --git a/src/rtnetlink/addr/Makefile b/src/netlink/rtnetlink/addr/Makefile similarity index 100% rename from src/rtnetlink/addr/Makefile rename to src/netlink/rtnetlink/addr/Makefile diff --git a/src/rtnetlink/addr/attribute_types.go b/src/netlink/rtnetlink/addr/attribute_types.go similarity index 100% rename from src/rtnetlink/addr/attribute_types.go rename to src/netlink/rtnetlink/addr/attribute_types.go diff --git a/src/rtnetlink/addr/flags.go b/src/netlink/rtnetlink/addr/flags.go similarity index 100% rename from src/rtnetlink/addr/flags.go rename to src/netlink/rtnetlink/addr/flags.go diff --git a/src/rtnetlink/addr/header.go b/src/netlink/rtnetlink/addr/header.go similarity index 100% rename from src/rtnetlink/addr/header.go rename to src/netlink/rtnetlink/addr/header.go diff --git a/src/rtnetlink/family.go b/src/netlink/rtnetlink/family.go similarity index 100% rename from src/rtnetlink/family.go rename to src/netlink/rtnetlink/family.go diff --git a/src/rtnetlink/groups.go b/src/netlink/rtnetlink/groups.go similarity index 100% rename from src/rtnetlink/groups.go rename to src/netlink/rtnetlink/groups.go diff --git a/src/rtnetlink/header.go b/src/netlink/rtnetlink/header.go similarity index 100% rename from src/rtnetlink/header.go rename to src/netlink/rtnetlink/header.go diff --git a/src/rtnetlink/link/Makefile b/src/netlink/rtnetlink/link/Makefile similarity index 100% rename from src/rtnetlink/link/Makefile rename to src/netlink/rtnetlink/link/Makefile diff --git a/src/rtnetlink/link/attribute_types.go b/src/netlink/rtnetlink/link/attribute_types.go similarity index 100% rename from src/rtnetlink/link/attribute_types.go rename to src/netlink/rtnetlink/link/attribute_types.go diff --git a/src/rtnetlink/link/flags.go b/src/netlink/rtnetlink/link/flags.go similarity index 100% rename from src/rtnetlink/link/flags.go rename to src/netlink/rtnetlink/link/flags.go diff --git a/src/rtnetlink/link/header.go b/src/netlink/rtnetlink/link/header.go similarity index 100% rename from src/rtnetlink/link/header.go rename to src/netlink/rtnetlink/link/header.go diff --git a/src/rtnetlink/message.go b/src/netlink/rtnetlink/message.go similarity index 100% rename from src/rtnetlink/message.go rename to src/netlink/rtnetlink/message.go diff --git a/src/rtnetlink/message_types.go b/src/netlink/rtnetlink/message_types.go similarity index 100% rename from src/rtnetlink/message_types.go rename to src/netlink/rtnetlink/message_types.go diff --git a/src/rtnetlink/route/Makefile b/src/netlink/rtnetlink/route/Makefile similarity index 100% rename from src/rtnetlink/route/Makefile rename to src/netlink/rtnetlink/route/Makefile diff --git a/src/rtnetlink/route/attribute_types.go b/src/netlink/rtnetlink/route/attribute_types.go similarity index 100% rename from src/rtnetlink/route/attribute_types.go rename to src/netlink/rtnetlink/route/attribute_types.go diff --git a/src/rtnetlink/route/flags.go b/src/netlink/rtnetlink/route/flags.go similarity index 100% rename from src/rtnetlink/route/flags.go rename to src/netlink/rtnetlink/route/flags.go diff --git a/src/rtnetlink/route/header.go b/src/netlink/rtnetlink/route/header.go similarity index 100% rename from src/rtnetlink/route/header.go rename to src/netlink/rtnetlink/route/header.go diff --git a/src/rtnetlink/route/origin.go b/src/netlink/rtnetlink/route/origin.go similarity index 100% rename from src/rtnetlink/route/origin.go rename to src/netlink/rtnetlink/route/origin.go diff --git a/src/rtnetlink/route/table.go b/src/netlink/rtnetlink/route/table.go similarity index 100% rename from src/rtnetlink/route/table.go rename to src/netlink/rtnetlink/route/table.go diff --git a/src/rtnetlink/route/types.go b/src/netlink/rtnetlink/route/types.go similarity index 100% rename from src/rtnetlink/route/types.go rename to src/netlink/rtnetlink/route/types.go diff --git a/src/rtnetlink/scope.go b/src/netlink/rtnetlink/scope.go similarity index 100% rename from src/rtnetlink/scope.go rename to src/netlink/rtnetlink/scope.go diff --git a/src/socket.go b/src/netlink/socket.go similarity index 100% rename from src/socket.go rename to src/netlink/socket.go diff --git a/src/types.go b/src/netlink/types.go similarity index 100% rename from src/types.go rename to src/netlink/types.go From 07104a9fb58956f39c0ba5702f3e0e2b85cf50c9 Mon Sep 17 00:00:00 2001 From: am Date: Wed, 3 Oct 2012 15:49:12 +1300 Subject: [PATCH 2/3] updated sources to run on v1.0 --- src/netlink/attr_helpers.go | 85 ++++---- src/netlink/attribute.go | 87 ++++---- src/netlink/error.go | 43 ++-- src/netlink/handler.go | 104 ++++----- src/netlink/header.go | 72 +++--- src/netlink/message.go | 79 +++---- src/netlink/rtmanip/links.go | 303 ++++++++++++++------------ src/netlink/rtnetlink/addr/header.go | 52 ++--- src/netlink/rtnetlink/header.go | 9 +- src/netlink/rtnetlink/link/header.go | 57 ++--- src/netlink/rtnetlink/message.go | 97 +++++---- src/netlink/rtnetlink/route/header.go | 70 +++--- src/netlink/socket.go | 61 +++--- tools/get_addrs.go | 99 ++++----- tools/get_links.go | 79 +++---- tools/get_routes.go | 81 +++---- tools/ifmanip.go | 81 +++---- 17 files changed, 760 insertions(+), 699 deletions(-) diff --git a/src/netlink/attr_helpers.go b/src/netlink/attr_helpers.go index fe99936..c21f6a9 100644 --- a/src/netlink/attr_helpers.go +++ b/src/netlink/attr_helpers.go @@ -9,71 +9,74 @@ package netlink import "log" -import "encoding/binary" -import "os" +import ( + "encoding/binary" + "errors" +) + import "bytes" // The attributeFinder interface should be used by READERS, // Writers will need to use an AttributeWriter type AttributeFinder interface { - GetAttribute(AttributeType)(Attribute, os.Error) + GetAttribute(AttributeType) (Attribute, error) } // AttributeWriters allow attributes to be added/updated. type AttributeWriter interface { - SetAttribute(Attribute) + SetAttribute(Attribute) } // Sets the attribute value to the string specified by 's'. // s will be NULL terminated. -func SetAttributeCString(aw AttributeWriter, at AttributeType, s string){ - buff := bytes.NewBufferString(s+ "\x00") - log.Printf("Buff: %X", buff.Bytes()) - aw.SetAttribute(Attribute{Type: at, Body: buff.Bytes() }) - return +func SetAttributeCString(aw AttributeWriter, at AttributeType, s string) { + buff := bytes.NewBufferString(s + "\x00") + log.Printf("Buff: %X", buff.Bytes()) + aw.SetAttribute(Attribute{Type: at, Body: buff.Bytes()}) + return } // Returns the attribute as an uint32 (or an error if the attr size is not // 32 bits. -func GetAttributeUint32(af AttributeFinder, at AttributeType)(out uint32, err os.Error){ - attr, err := af.GetAttribute(at) - if err == nil { - body := attr.Body - if len(body) != 4 { - err = os.NewError("Attribute wrong size for Uint32") - } else { - out = binary.LittleEndian.Uint32(body) - } - } - return +func GetAttributeUint32(af AttributeFinder, at AttributeType) (out uint32, err error) { + attr, err := af.GetAttribute(at) + if err == nil { + body := attr.Body + if len(body) != 4 { + err = errors.New("Attribute wrong size for Uint32") + } else { + out = binary.LittleEndian.Uint32(body) + } + } + return } // Gets an attribute value as a string. // Note, for much of RTNetlink, you want GetAttributeCString, // which will verify and chop the tailing NULL. -func GetAttributeString(af AttributeFinder, at AttributeType)(out string, err os.Error){ - attr, err := af.GetAttribute(at) - if err == nil { - out = string(attr.Body) - } - return +func GetAttributeString(af AttributeFinder, at AttributeType) (out string, err error) { + attr, err := af.GetAttribute(at) + if err == nil { + out = string(attr.Body) + } + return } // Same as GetAttributeString, but expects the string to be NULL terminated, // the null terminator will be stripped.. -func GetAttributeCString(af AttributeFinder, at AttributeType)(out string, err os.Error){ - attr, err := af.GetAttribute(at) - if err == nil { - outbody := attr.Body - if len(outbody) == 0 { - err = os.NewError("Invalid body") - } else { - if outbody[len(outbody) -1 ] != 0 { - err = os.NewError("Expected NULL-terminated string") - } else { - out = string(outbody[0: len(outbody) - 1]) - } - } - } - return +func GetAttributeCString(af AttributeFinder, at AttributeType) (out string, err error) { + attr, err := af.GetAttribute(at) + if err == nil { + outbody := attr.Body + if len(outbody) == 0 { + err = errors.New("Invalid body") + } else { + if outbody[len(outbody)-1] != 0 { + err = errors.New("Expected NULL-terminated string") + } else { + out = string(outbody[0 : len(outbody)-1]) + } + } + } + return } diff --git a/src/netlink/attribute.go b/src/netlink/attribute.go index e44be9c..a9fa3fc 100644 --- a/src/netlink/attribute.go +++ b/src/netlink/attribute.go @@ -1,4 +1,5 @@ package netlink + /* Copyright (c) 2011, Abneptis LLC. All rights reserved. Original Author: James D. Nurmi @@ -7,9 +8,12 @@ package netlink */ import "fmt" -import "os" + import "bytes" -import "encoding/binary" +import ( + "encoding/binary" + "errors" +) // A basic netlink type used for identifying // nlattrs in a message. @@ -20,54 +24,53 @@ type AttributeType uint16 // Length and Type are 16 bit integers, so values may not // exceed 2^16. type Attribute struct { - Type AttributeType - Body []byte + Type AttributeType + Body []byte } // Marshals a netlink attribute as a full LTV tuple. -func (self Attribute)MarshalNetlink(pad int)(out []byte, err os.Error){ - l := len(self.Body) - out = make([]byte, l + 4) - binary.LittleEndian.PutUint16(out[0:2], uint16(len(self.Body)+4)) - binary.LittleEndian.PutUint16(out[2:4], uint16(self.Type)) - copy(out[4:], self.Body[0:]) - out = PadBytes(out, pad) - return +func (self Attribute) MarshalNetlink(pad int) (out []byte, err error) { + l := len(self.Body) + out = make([]byte, l+4) + binary.LittleEndian.PutUint16(out[0:2], uint16(len(self.Body)+4)) + binary.LittleEndian.PutUint16(out[2:4], uint16(self.Type)) + copy(out[4:], self.Body[0:]) + out = PadBytes(out, pad) + return } // Unmarshals a netlink attribute. -func UnmarshalAttributes(in []byte, padding int)(out []Attribute, err os.Error){ - pos := 0 - for pos < len(in) { - l := binary.LittleEndian.Uint16(in[pos:pos+2]) - if int(l) > len(in) - pos { - err = os.NewError("Can't parse attribute (too long)") - break - } - if l > 4 { - t := binary.LittleEndian.Uint16(in[pos+2:pos+4]) - out = append(out, Attribute{Type: AttributeType(t), Body:in[pos+4:pos + int(l)]}) - pos = Reposition(pos + int(l), padding) - } else { - err = os.NewError(fmt.Sprintf("Invalid Attributeibute (Len: %d):", l)) - break - } - } - return +func UnmarshalAttributes(in []byte, padding int) (out []Attribute, err error) { + pos := 0 + for pos < len(in) { + l := binary.LittleEndian.Uint16(in[pos : pos+2]) + if int(l) > len(in)-pos { + err = errors.New("Can't parse attribute (too long)") + break + } + if l > 4 { + t := binary.LittleEndian.Uint16(in[pos+2 : pos+4]) + out = append(out, Attribute{Type: AttributeType(t), Body: in[pos+4 : pos+int(l)]}) + pos = Reposition(pos+int(l), padding) + } else { + err = errors.New(fmt.Sprintf("Invalid Attributeibute (Len: %d):", l)) + break + } + } + return } // Returns the padded bytes of a marshalled list of attributes. // Any marshalling error will cause the sequence to abort. -func MarshalAttributes(in []Attribute, padding int)(out []byte, err os.Error){ - for i := range(in){ - var b []byte - b, err = in[i].MarshalNetlink(padding) - if err == nil { - out = bytes.Join([][]byte{out, b}, []byte{}) - } else { - break - } - } - return +func MarshalAttributes(in []Attribute, padding int) (out []byte, err error) { + for i := range in { + var b []byte + b, err = in[i].MarshalNetlink(padding) + if err == nil { + out = bytes.Join([][]byte{out, b}, []byte{}) + } else { + break + } + } + return } - diff --git a/src/netlink/error.go b/src/netlink/error.go index 27dff02..dd000ae 100644 --- a/src/netlink/error.go +++ b/src/netlink/error.go @@ -1,4 +1,5 @@ package netlink + /* Copyright (c) 2011, Abneptis LLC. All rights reserved. Original Author: James D. Nurmi @@ -7,37 +8,43 @@ package netlink */ import "fmt" -import "encoding/binary" -import "os" -import "syscall" +import ( + "encoding/binary" + "errors" +) + +//import "syscall" // Unlike other headers, errors MAY be longer than the minimum length. -const ERROR_LENGTH = HEADER_LENGTH+4 +const ERROR_LENGTH = HEADER_LENGTH + 4 + // Represents a netlink Error message. type Error [ERROR_LENGTH]byte // The error code (-errno) of the netlink message. // 0 is used for netlink ACK's. -func (self Error)Code()(int32){ - return int32(binary.LittleEndian.Uint32(self[0:4])) +func (self Error) Code() int32 { + return int32(binary.LittleEndian.Uint32(self[0:4])) } // Marshals an error to the wire. -func (self Error)MarshalNetlink(pad int)(out []byte, err os.Error){ - out = PadBytes(self[0:ERROR_LENGTH], pad) - return +func (self Error) MarshalNetlink(pad int) (out []byte, err error) { + out = PadBytes(self[0:ERROR_LENGTH], pad) + return } // Unmarshals an error from a netlink message. -func (self *Error)UnmarshalNetlink(in []byte, pad int)(err os.Error){ - if len(in) < ERROR_LENGTH { - return os.NewError(fmt.Sprintf("Invalid netlink error length: %d", len(in))) - } - copy(self[0:ERROR_LENGTH], in) - return +func (self *Error) UnmarshalNetlink(in []byte, pad int) (err error) { + if len(in) < ERROR_LENGTH { + return errors.New(fmt.Sprintf("Invalid netlink error length: %d", len(in))) + } + copy(self[0:ERROR_LENGTH], in) + return } -// Implements os.Error by using syscall.Errstr(-Code()) -func (self Error)String()(string){ - return syscall.Errstr(int(-self.Code())) + +// Implements os.Error by using err.Error(-Code()) +func (self Error) Error() string { +// return Errstr(int(-self.Code())) + return "Error string unimplemented" } diff --git a/src/netlink/handler.go b/src/netlink/handler.go index a734fb6..d65523b 100644 --- a/src/netlink/handler.go +++ b/src/netlink/handler.go @@ -8,77 +8,79 @@ package netlink */ //import "log" -import "bufio" -import "os" +import ( + "bufio" + "errors" +) + import "fmt" import "sync" // A handler implements a simple Mux for netlink messages, ensuring // each query gets a unique sequence number and a channel to collect responses. type Handler struct { - sock *Socket - recipients map[uint32]chan Message - next_seq uint32 - lock sync.Mutex + sock *Socket + recipients map[uint32]chan Message + next_seq uint32 + lock sync.Mutex } // Used as an atomic counter for sequence numbering. // No check is made to see that sequences aren't still in use on roll-over. -func (self *Handler)Seq()(out uint32){ - self.lock.Lock() - out = self.next_seq - self.next_seq++ - self.lock.Unlock() - return +func (self *Handler) Seq() (out uint32) { + self.lock.Lock() + out = self.next_seq + self.next_seq++ + self.lock.Unlock() + return } -func NewHandler(sock *Socket)(*Handler){ - return &Handler{sock:sock, recipients: map[uint32]chan Message{}, next_seq: 1} +func NewHandler(sock *Socket) *Handler { + return &Handler{sock: sock, recipients: map[uint32]chan Message{}, next_seq: 1} } // Send a message. If SequenceNumber is unset, Seq() will be used // to generate one. -func (self *Handler)Query(msg Message, l int, pad int)(ch chan Message, err os.Error){ - if msg.Header.MessageSequence() == 0 { - msg.Header.SetMessageSequence(self.Seq()) - } - ob, err := msg.MarshalNetlink(pad) - if err == nil { - ch = make(chan Message, l) - self.recipients[msg.Header.MessageSequence()] = ch - _, err = self.sock.Write(ob) - } - return +func (self *Handler) Query(msg Message, l int, pad int) (ch chan Message, err error) { + if msg.Header.MessageSequence() == 0 { + msg.Header.SetMessageSequence(self.Seq()) + } + ob, err := msg.MarshalNetlink(pad) + if err == nil { + ch = make(chan Message, l) + self.recipients[msg.Header.MessageSequence()] = ch + _, err = self.sock.Write(ob) + } + return } // Usually called in a goroutine, Start spawns a thread // that demux's incoming netlink responses. // Echan is used to report internal netlink errors, and may // be set to nil (but you will likely miss bugs!) -func (self *Handler)Start(echan chan os.Error){ - r := bufio.NewReader(self.sock) - for { - msg, err := ReadMessage(r, 4) - if err == nil { - if self.recipients[msg.Header.MessageSequence()] == nil { - if nil != echan { - echan <- os.NewError(fmt.Sprintf("GoNetlink: No handler found for seq %d", - msg.Header.MessageSequence())) - } - continue - } else { - self.recipients[msg.Header.MessageSequence()] <- *msg - if msg.Header.MessageFlags() & NLM_F_MULTI == 0 { - close(self.recipients[msg.Header.MessageSequence()]) - self.recipients[msg.Header.MessageSequence()] = nil, false - } - } - } else { - if nil != echan { - echan <- err - } - } - } - return +func (self *Handler) Start(echan chan error) { + r := bufio.NewReader(self.sock) + for { + msg, err := ReadMessage(r, 4) + if err == nil { + if self.recipients[msg.Header.MessageSequence()] == nil { + if nil != echan { + echan <- errors.New(fmt.Sprintf("GoNetlink: No handler found for seq %d", + msg.Header.MessageSequence())) + } + continue + } else { + self.recipients[msg.Header.MessageSequence()] <- *msg + if msg.Header.MessageFlags()&NLM_F_MULTI == 0 { + close(self.recipients[msg.Header.MessageSequence()]) + delete(self.recipients, msg.Header.MessageSequence()) + } + } + } else { + if nil != echan { + echan <- err + } + } + } + return } - diff --git a/src/netlink/header.go b/src/netlink/header.go index b22959d..98cacaa 100644 --- a/src/netlink/header.go +++ b/src/netlink/header.go @@ -7,47 +7,53 @@ package netlink See LICENSE for details */ -import "os" -import "encoding/binary" +import ( + "encoding/binary" + "errors" +) const HEADER_LENGTH = 16 // Represents the header of a netlink.Message type Header [HEADER_LENGTH]byte -func (self Header)Len()(int){ return HEADER_LENGTH} - -func (self Header)MessageLength()(uint32) { return binary.LittleEndian.Uint32(self[0:4]) } -func (self *Header)SetMessageLength(in uint32) { binary.LittleEndian.PutUint32(self[0:4], in)} -func (self Header)MessageType()(MessageType) { return MessageType(binary.LittleEndian.Uint16(self[4:6]))} -func (self Header)MessageFlags()(MessageFlags) { return MessageFlags(binary.LittleEndian.Uint16(self[6:8]))} -func (self Header)MessageSequence()(uint32) { return binary.LittleEndian.Uint32(self[8:12])} -func (self *Header)SetMessageSequence(in uint32) { binary.LittleEndian.PutUint32(self[8:12], in)} -func (self Header)MessagePid()(uint32) { return binary.LittleEndian.Uint32(self[12:16])} - -func NewHeader(t MessageType, f MessageFlags, seq uint32)(h *Header){ - h = &Header{} - binary.LittleEndian.PutUint32(h[0:4], HEADER_LENGTH) - binary.LittleEndian.PutUint16(h[4:6], uint16(t)) - binary.LittleEndian.PutUint16(h[6:8], uint16(f)) - binary.LittleEndian.PutUint32(h[8:12], seq) - binary.LittleEndian.PutUint32(h[12:16], 0) - - return +func (self Header) Len() int { return HEADER_LENGTH } + +func (self Header) MessageLength() uint32 { return binary.LittleEndian.Uint32(self[0:4]) } +func (self *Header) SetMessageLength(in uint32) { binary.LittleEndian.PutUint32(self[0:4], in) } +func (self Header) MessageType() MessageType { + return MessageType(binary.LittleEndian.Uint16(self[4:6])) +} +func (self Header) MessageFlags() MessageFlags { + return MessageFlags(binary.LittleEndian.Uint16(self[6:8])) +} +func (self Header) MessageSequence() uint32 { return binary.LittleEndian.Uint32(self[8:12]) } +func (self *Header) SetMessageSequence(in uint32) { binary.LittleEndian.PutUint32(self[8:12], in) } +func (self Header) MessagePid() uint32 { return binary.LittleEndian.Uint32(self[12:16]) } + +func NewHeader(t MessageType, f MessageFlags, seq uint32) (h *Header) { + h = &Header{} + binary.LittleEndian.PutUint32(h[0:4], HEADER_LENGTH) + binary.LittleEndian.PutUint16(h[4:6], uint16(t)) + binary.LittleEndian.PutUint16(h[6:8], uint16(f)) + binary.LittleEndian.PutUint32(h[8:12], seq) + binary.LittleEndian.PutUint32(h[12:16], 0) + + return } -func (self Header)MarshalNetlink(pad int)(out []byte, err os.Error){ - out = make([]byte, HEADER_LENGTH) - copy(out, self[0:HEADER_LENGTH]) - out = PadBytes(out, pad) - return +func (self Header) MarshalNetlink(pad int) (out []byte, err error) { + out = make([]byte, HEADER_LENGTH) + copy(out, self[0:HEADER_LENGTH]) + out = PadBytes(out, pad) + return } -func (self *Header)UnmarshalNetlink(in []byte, pad int)(err os.Error){ - if len(in) != HEADER_LENGTH { - err = os.NewError("Incorrect NetlinkHeader length") - } else { - copy(self[0:HEADER_LENGTH], in[0:HEADER_LENGTH]) - } - return +func (self *Header) UnmarshalNetlink(in []byte, pad int) (err error) { + if len(in) != HEADER_LENGTH { + err = errors.New("Incorrect NetlinkHeader length") + } else { + copy(self[0:HEADER_LENGTH], in[0:HEADER_LENGTH]) + } + return } diff --git a/src/netlink/message.go b/src/netlink/message.go index a1ae095..482b287 100644 --- a/src/netlink/message.go +++ b/src/netlink/message.go @@ -7,63 +7,66 @@ package netlink See LICENSE for details */ -import "fmt" +import ( + "errors" + "fmt" +) import "bytes" -import "os" + import "io" // A netlink message contains a Netlink header, // and a body of bytes. type Message struct { - Header *Header - Body []byte + Header *Header + Body []byte } // NetlinkMarshaler's are used to pad and format netlink data. type NetlinkMarshaler interface { - MarshalNetlink(int)([]byte, os.Error) + MarshalNetlink(int) ([]byte, error) } // Creates a new message from a marshalable object -func NewMessage(t MessageType, f MessageFlags, u NetlinkMarshaler, pad int)(msg *Message, err os.Error){ - msg = &Message{Header: NewHeader(t,f,0) } - msg.Body, err = u.MarshalNetlink(pad) - if err == nil { - msg.Header.SetMessageLength(uint32(msg.Header.Len()) + uint32(len (msg.Body))) - } - return +func NewMessage(t MessageType, f MessageFlags, u NetlinkMarshaler, pad int) (msg *Message, err error) { + msg = &Message{Header: NewHeader(t, f, 0)} + msg.Body, err = u.MarshalNetlink(pad) + if err == nil { + msg.Header.SetMessageLength(uint32(msg.Header.Len()) + uint32(len(msg.Body))) + } + return } // Reads a message from an io.Reader, with a specified padding. // NB: Netlink uses a very strict protocol, and it is encouraged // that r be a bufio.Reader -func ReadMessage(r io.Reader, pad int)(msg *Message, err os.Error){ - var n int - msg = &Message{Header: &Header{}} - ib := make([]byte, msg.Header.Len()) - n, err = r.Read(ib) - if err == nil && n != msg.Header.Len() { - err = os.NewError("Incomplete netlink header") - } - if err == nil { - err = msg.Header.UnmarshalNetlink(ib, pad) - if err == nil { - msg.Body = make([]byte, msg.Header.MessageLength() - uint32(msg.Header.Len())) - n, err = r.Read(msg.Body) - if err == nil && n != int(msg.Header.MessageLength()) - int(msg.Header.Len()) { - err = os.NewError(fmt.Sprintf("Incomplete netlink message body (Got: %d; Expected: %d)", n, int(msg.Header.MessageLength()) - int(msg.Header.Len()))) - } else { - } - } - } - return +func ReadMessage(r io.Reader, pad int) (msg *Message, err error) { + var n int + msg = &Message{Header: &Header{}} + ib := make([]byte, msg.Header.Len()) + n, err = r.Read(ib) + if err == nil && n != msg.Header.Len() { + err = errors.New("Incomplete netlink header") + } + if err == nil { + err = msg.Header.UnmarshalNetlink(ib, pad) + if err == nil { + msg.Body = make([]byte, msg.Header.MessageLength()-uint32(msg.Header.Len())) + n, err = r.Read(msg.Body) + if err == nil && n != int(msg.Header.MessageLength())-int(msg.Header.Len()) { + err = errors.New(fmt.Sprintf("Incomplete netlink message body (Got: %d; Expected: %d)", n, int(msg.Header.MessageLength())-int(msg.Header.Len()))) + } else { + } + } + } + return } // Marshals a message with appropriate padding (generally none). -func (self Message)MarshalNetlink(pad int)(out []byte, err os.Error){ - hdrout, err := self.Header.MarshalNetlink(pad) - if err == nil { - out = bytes.Join([][]byte{hdrout, self.Body}, []byte{}) - } - return +func (self Message) MarshalNetlink(pad int) (out []byte, err error) { + hdrout, err := self.Header.MarshalNetlink(pad) + if err == nil { + out = bytes.Join([][]byte{hdrout, self.Body}, []byte{}) + } + return } diff --git a/src/netlink/rtmanip/links.go b/src/netlink/rtmanip/links.go index 6b94396..913608a 100644 --- a/src/netlink/rtmanip/links.go +++ b/src/netlink/rtmanip/links.go @@ -1,4 +1,5 @@ package rtmanip + /* Copyright (c) 2011, Abneptis LLC. All rights reserved. Original Author: James D. Nurmi @@ -6,179 +7,201 @@ package rtmanip See LICENSE for details */ -import "netlink/rtnetlink/link" +import ( + "errors" + "netlink/rtnetlink/link" +) import "netlink/rtnetlink" import "netlink" -import "os" + import "log" type LinkHandler struct { - h *netlink.Handler - cache *rtnetlink.Message + h *netlink.Handler + cache *rtnetlink.Message } -func (self *LinkHandler)LinkBroadcastAddress()(s []byte){ - attr, err := self.cache.GetAttribute(link.IFLA_BROADCAST) - if err == nil { - s = attr.Body - } - return +func (self *LinkHandler) LinkBroadcastAddress() (s []byte) { + attr, err := self.cache.GetAttribute(link.IFLA_BROADCAST) + if err == nil { + s = attr.Body + } + return } -func (self *LinkHandler)LinkAddress()(s []byte){ - attr, err := self.cache.GetAttribute(link.IFLA_ADDRESS) - if err == nil { - s = attr.Body - } - return +func (self *LinkHandler) LinkAddress() (s []byte) { + attr, err := self.cache.GetAttribute(link.IFLA_ADDRESS) + if err == nil { + s = attr.Body + } + return } -func (self *LinkHandler)Refresh()(err os.Error){ - if hdr, ok := self.cache.Header.(*link.Header); ok { - lf := &linkFinder{h: self.h} - l, err := lf.GetLinkByID(hdr.InterfaceIndex()) - if err == nil { - *self.cache = *l.cache - } - } - return +func (self *LinkHandler) Refresh() (err error) { + if hdr, ok := self.cache.Header.(*link.Header); ok { + lf := &linkFinder{h: self.h} + l, err := lf.GetLinkByID(hdr.InterfaceIndex()) + if err == nil { + *self.cache = *l.cache + } + } + return } -func (self *LinkHandler)LinkMTU()(i uint32){ - i, _ = netlink.GetAttributeUint32(self.cache, link.IFLA_MTU) - return +func (self *LinkHandler) LinkMTU() (i uint32) { + i, _ = netlink.GetAttributeUint32(self.cache, link.IFLA_MTU) + return } -func (self *LinkHandler)SetLinkState(flag link.Flags)(err os.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, 4) - } else { - err = os.NewError("Cant set link flags (invalid cache)") - } - if err != nil { return } - mch, err := self.h.Query(*qry,1, 4) - if err == nil { - for m := range(mch) { - switch m.Header.MessageType() { - case netlink.NLMSG_ERROR: - emsg := &netlink.Error{} - err = emsg.UnmarshalNetlink(m.Body, 4) - if err == nil && emsg.Code() != 0 { err = emsg } - default: - err = os.NewError("Unexpected netlink message") - log.Printf("NetlinkError: %v", err) - } - } - close(mch) - } - return +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, 4) + } else { + err = errors.New("Cant set link flags (invalid cache)") + } + if err != nil { + return + } + mch, err := self.h.Query(*qry, 1, 4) + if err == nil { + for m := range mch { + switch m.Header.MessageType() { + case netlink.NLMSG_ERROR: + emsg := &netlink.Error{} + err = emsg.UnmarshalNetlink(m.Body, 4) + 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 *LinkHandler)LinkFlags()(flags link.Flags){ - if hdr, ok := self.cache.Header.(*link.Header); ok { - flags = hdr.Flags() - } - return +func (self *LinkHandler) LinkFlags() (flags link.Flags) { + if hdr, ok := self.cache.Header.(*link.Header); ok { + flags = hdr.Flags() + } + return } -func (self *LinkHandler)LinkIndex()(i uint32){ - if hdr, ok := self.cache.Header.(*link.Header); ok { - i = hdr.InterfaceIndex() - } - return +func (self *LinkHandler) LinkIndex() (i uint32) { + if hdr, ok := self.cache.Header.(*link.Header); ok { + i = hdr.InterfaceIndex() + } + return } -func (self *LinkHandler)LinkName()(s string){ - s, _ = netlink.GetAttributeCString(self.cache, link.IFLA_IFNAME) - return +func (self *LinkHandler) LinkName() (s string) { + s, _ = netlink.GetAttributeCString(self.cache, link.IFLA_IFNAME) + return } type LinkFinder interface { - GetLinkByID(uint32)(*LinkHandler, os.Error) - GetLinkByName(string)(*LinkHandler, os.Error) - GetLinks()([]*LinkHandler, os.Error) + GetLinkByID(uint32) (*LinkHandler, error) + GetLinkByName(string) (*LinkHandler, error) + GetLinks() ([]*LinkHandler, error) } type linkFinder struct { - h *netlink.Handler + h *netlink.Handler } -func NewLinkFinder(h *netlink.Handler)(LinkFinder){ - return &linkFinder{h:h} +func NewLinkFinder(h *netlink.Handler) LinkFinder { + return &linkFinder{h: h} } -func (self *linkFinder)GetLinkByName(s string)(lh *LinkHandler, err os.Error){ - lhs, err := self.GetLinks() - for i := range(lhs) { - if lhs[i].LinkName() == s { - lh = lhs[i] - break - } - } - if lh == nil { err = os.NewError("Interface not found")} - return +func (self *linkFinder) GetLinkByName(s string) (lh *LinkHandler, err error) { + lhs, err := self.GetLinks() + for i := range lhs { + if lhs[i].LinkName() == s { + lh = lhs[i] + break + } + } + if lh == nil { + err = errors.New("Interface not found") + } + return } -func (self *linkFinder)GetLinkByID(i uint32)(lh *LinkHandler, err os.Error){ - qry, err := netlink.NewMessage(rtnetlink.RTM_GETLINK, netlink.NLM_F_REQUEST, - link.NewHeader(rtnetlink.AF_UNSPEC, 0, i, 0,0), 4) - if err == nil { - var mch chan netlink.Message - mch, err = self.h.Query(*qry,1, 4) - if err == nil { - for ii := range(mch) { - switch ii.Header.MessageType(){ - default: err = os.NewError("Unknown message type in response to RTM_GETLINK") - case netlink.NLMSG_ERROR: - emsg := &netlink.Error{} - err = emsg.UnmarshalNetlink(ii.Body, 4) - 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, 4) - if err == nil { lh = &LinkHandler{h: self.h, cache: msg} } - } - } - 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), 4) + if err == nil { + var mch chan netlink.Message + mch, err = self.h.Query(*qry, 1, 4) + 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, 4) + 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, 4) + if err == nil { + lh = &LinkHandler{h: self.h, cache: msg} + } + } + } + close(mch) + } + } + return } -func (self *linkFinder)GetLinks()(lhs []*LinkHandler, err os.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), 4) - if err != nil { return } - var mch chan netlink.Message - mch, err = self.h.Query(*qry,1, 4) - if err == nil { - for ii := range(mch) { - if ii.Header.MessageType() == netlink.NLMSG_DONE { break } - switch ii.Header.MessageType(){ - default: - err = os.NewError("Unknown message type in response to RTM_GETLINK") - case netlink.NLMSG_ERROR: - emsg := &netlink.Error{} - err = emsg.UnmarshalNetlink(ii.Body, 4) - 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, 4) - 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 +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), 4) + if err != nil { + return + } + var mch chan netlink.Message + mch, err = self.h.Query(*qry, 1, 4) + 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, 4) + 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, 4) + 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 } diff --git a/src/netlink/rtnetlink/addr/header.go b/src/netlink/rtnetlink/addr/header.go index f99de11..74ce755 100644 --- a/src/netlink/rtnetlink/addr/header.go +++ b/src/netlink/rtnetlink/addr/header.go @@ -1,4 +1,5 @@ package addr + /* Copyright (c) 2011, Abneptis LLC. All rights reserved. Original Author: James D. Nurmi @@ -6,39 +7,40 @@ package addr See LICENSE for details */ -import "encoding/binary" +import ( + "encoding/binary" + "errors" +) import "netlink/rtnetlink" import "netlink" -import "os" - const HEADER_LENGTH = 8 + type Header [HEADER_LENGTH]byte -func NewHeader(afam rtnetlink.Family, pl uint8, fl Flags, scope rtnetlink.Scope, ifindex uint32)(*Header){ - hdr := Header{byte(afam), pl, byte(fl), byte(scope)} - binary.LittleEndian.PutUint32(hdr[4:8], ifindex) - return &hdr +func NewHeader(afam rtnetlink.Family, pl uint8, fl Flags, scope rtnetlink.Scope, ifindex uint32) *Header { + hdr := Header{byte(afam), pl, byte(fl), byte(scope)} + binary.LittleEndian.PutUint32(hdr[4:8], ifindex) + return &hdr } - -func (self Header)Len()(int){ return HEADER_LENGTH } -func (self Header)AddressFamily()(rtnetlink.Family){ return rtnetlink.Family(self[0]) } -func (self Header)PrefixLength()(uint8){ return self[1] } -func (self Header)Flags()(Flags){ return Flags(self[2]) } -func (self Header)Scope()(rtnetlink.Scope){ return rtnetlink.Scope(self[3]) } -func (self Header)InterfaceIndex()(uint32){ return binary.LittleEndian.Uint32(self[4:8]) } - -func (self *Header)UnmarshalNetlink(in []byte, pad int)(err os.Error){ - if len(in) != HEADER_LENGTH { - err = os.NewError("Wrong length for Header") - } else { - copy(self[0:HEADER_LENGTH], in[0:HEADER_LENGTH]) - } - return +func (self Header) Len() int { return HEADER_LENGTH } +func (self Header) AddressFamily() rtnetlink.Family { return rtnetlink.Family(self[0]) } +func (self Header) PrefixLength() uint8 { return self[1] } +func (self Header) Flags() Flags { return Flags(self[2]) } +func (self Header) Scope() rtnetlink.Scope { return rtnetlink.Scope(self[3]) } +func (self Header) InterfaceIndex() uint32 { return binary.LittleEndian.Uint32(self[4:8]) } + +func (self *Header) UnmarshalNetlink(in []byte, pad int) (err error) { + if len(in) != HEADER_LENGTH { + err = errors.New("Wrong length for Header") + } else { + copy(self[0:HEADER_LENGTH], in[0:HEADER_LENGTH]) + } + return } -func (self Header)MarshalNetlink(pad int)(out []byte, err os.Error){ - out = netlink.PadBytes(self[0:HEADER_LENGTH], pad) - return +func (self Header) MarshalNetlink(pad int) (out []byte, err error) { + out = netlink.PadBytes(self[0:HEADER_LENGTH], pad) + return } diff --git a/src/netlink/rtnetlink/header.go b/src/netlink/rtnetlink/header.go index 1f92699..a4bdccc 100644 --- a/src/netlink/rtnetlink/header.go +++ b/src/netlink/rtnetlink/header.go @@ -1,4 +1,5 @@ package rtnetlink + /* Copyright (c) 2011, Abneptis LLC. All rights reserved. Original Author: James D. Nurmi @@ -6,12 +7,10 @@ package rtnetlink See LICENSE for details */ -import "os" - // An RTNetlink Header describes the structures // between the netlink header and the nlattributes. type Header interface { - Len()(int) // The (unpadded) length of the Header. - UnmarshalNetlink([]byte, int)(os.Error) - MarshalNetlink(int)([]byte, os.Error) + Len() int // The (unpadded) length of the Header. + UnmarshalNetlink([]byte, int) error + MarshalNetlink(int) ([]byte, error) } diff --git a/src/netlink/rtnetlink/link/header.go b/src/netlink/rtnetlink/link/header.go index 595da82..66eb556 100644 --- a/src/netlink/rtnetlink/link/header.go +++ b/src/netlink/rtnetlink/link/header.go @@ -1,4 +1,5 @@ package link + /* Copyright (c) 2011, Abneptis LLC. All rights reserved. Original Author: James D. Nurmi @@ -8,41 +9,43 @@ package link import "netlink" import "netlink/rtnetlink" -import "os" -import "encoding/binary" +import ( + "encoding/binary" + "errors" +) const HEADER_LENGTH = 16 + type Header [16]byte -func NewHeader(fam rtnetlink.Family, itype uint16, iindex uint32, flags, changes Flags)(hdr *Header){ - hdr = &Header{byte(fam)} - binary.LittleEndian.PutUint16(hdr[2:4], itype) - binary.LittleEndian.PutUint32(hdr[4:8], iindex) - binary.LittleEndian.PutUint32(hdr[8:12], uint32(flags)) - binary.LittleEndian.PutUint32(hdr[12:16], uint32(changes)) - return +func NewHeader(fam rtnetlink.Family, itype uint16, iindex uint32, flags, changes Flags) (hdr *Header) { + hdr = &Header{byte(fam)} + binary.LittleEndian.PutUint16(hdr[2:4], itype) + binary.LittleEndian.PutUint32(hdr[4:8], iindex) + binary.LittleEndian.PutUint32(hdr[8:12], uint32(flags)) + binary.LittleEndian.PutUint32(hdr[12:16], uint32(changes)) + return } -func (self Header)Len()(int) { return HEADER_LENGTH } -func (self *Header)UnmarshalNetlink(in []byte, pad int)(err os.Error){ - if len(in) != HEADER_LENGTH { - err = os.NewError("Wrong length for Header") - } else { - copy(self[0:HEADER_LENGTH], in[0:HEADER_LENGTH]) - } - return +func (self Header) Len() int { return HEADER_LENGTH } +func (self *Header) UnmarshalNetlink(in []byte, pad int) (err error) { + if len(in) != HEADER_LENGTH { + err = errors.New("Wrong length for Header") + } else { + copy(self[0:HEADER_LENGTH], in[0:HEADER_LENGTH]) + } + return } -func (self Header)MarshalNetlink(pad int)(out []byte, err os.Error){ - out = netlink.PadBytes(self[0:HEADER_LENGTH], pad) - return +func (self Header) MarshalNetlink(pad int) (out []byte, err error) { + out = netlink.PadBytes(self[0:HEADER_LENGTH], pad) + return } -func (self Header)Flags()(Flags){ return Flags(binary.LittleEndian.Uint32(self[8:12])) } -func (self *Header)SetFlags(f Flags){ binary.LittleEndian.PutUint32(self[8:12], uint32(f)) } -func (self Header)InterfaceFamily()(rtnetlink.Family){ return rtnetlink.Family(self[0])} -func (self Header)InterfaceType()(uint16){ return binary.LittleEndian.Uint16(self[2:4]) } -func (self Header)InterfaceIndex()(uint32){ return binary.LittleEndian.Uint32(self[4:8]) } -func (self Header)InterfaceChanges()(Flags){ return Flags(binary.LittleEndian.Uint32(self[12:16])) } - +func (self Header) Flags() Flags { return Flags(binary.LittleEndian.Uint32(self[8:12])) } +func (self *Header) SetFlags(f Flags) { binary.LittleEndian.PutUint32(self[8:12], uint32(f)) } +func (self Header) InterfaceFamily() rtnetlink.Family { return rtnetlink.Family(self[0]) } +func (self Header) InterfaceType() uint16 { return binary.LittleEndian.Uint16(self[2:4]) } +func (self Header) InterfaceIndex() uint32 { return binary.LittleEndian.Uint32(self[4:8]) } +func (self Header) InterfaceChanges() Flags { return Flags(binary.LittleEndian.Uint32(self[12:16])) } diff --git a/src/netlink/rtnetlink/message.go b/src/netlink/rtnetlink/message.go index d79d8d9..de3da0e 100644 --- a/src/netlink/rtnetlink/message.go +++ b/src/netlink/rtnetlink/message.go @@ -1,4 +1,5 @@ package rtnetlink + /* Copyright (c) 2011, Abneptis LLC. All rights reserved. Original Author: James D. Nurmi @@ -6,77 +7,79 @@ package rtnetlink See LICENSE for details */ -import "bytes" +import ( + "bytes" + "errors" +) import "netlink" -import "os" // A Message contains a Header object and a series of attributes. // It is extracted from the Body of a netlink.Message type Message struct { - Header Header - Attributes []netlink.Attribute + Header Header + Attributes []netlink.Attribute } // Create a new rtnetlink.Message based off of a header an list of attributes // (which may be nil or empty). -func NewMessage(h Header, attrs []netlink.Attribute)(*Message){ - return &Message{Header:h, Attributes: attrs} +func NewMessage(h Header, attrs []netlink.Attribute) *Message { + return &Message{Header: h, Attributes: attrs} } // Replace or append the attribute with the AttributeType of // attr -func (self *Message)SetAttribute(attr netlink.Attribute){ - t := attr.Type - for i := range(self.Attributes){ - if t == self.Attributes[i].Type { - self.Attributes[i] = attr - return - } - } - self.Attributes = append(self.Attributes, attr) - return +func (self *Message) SetAttribute(attr netlink.Attribute) { + t := attr.Type + for i := range self.Attributes { + if t == self.Attributes[i].Type { + self.Attributes[i] = attr + return + } + } + self.Attributes = append(self.Attributes, attr) + return } // Retrieve (the first) Attribute identified by Type, // returning an error if not found. -func (self Message)GetAttribute(t netlink.AttributeType)(attr netlink.Attribute, err os.Error){ - for i := range(self.Attributes){ - if t == self.Attributes[i].Type { - attr = self.Attributes[i] - return - } - } - err = os.NewError("Attribute not found") - return +func (self Message) GetAttribute(t netlink.AttributeType) (attr netlink.Attribute, err error) { + for i := range self.Attributes { + if t == self.Attributes[i].Type { + attr = self.Attributes[i] + return + } + } + err = errors.New("Attribute not found") + return } // Handles the appropriate calls to marshal the Header and Attribute values, // and return an appropriately padded result. -func (self Message)MarshalNetlink(pad int)(out []byte, err os.Error){ - hb, err := self.Header.MarshalNetlink(pad) - if err == nil { - var bb []byte - bb, err = netlink.MarshalAttributes(self.Attributes, pad) - if err == nil { - out = bytes.Join([][]byte{ hb, bb }, []byte{} ) - } - } - return +func (self Message) MarshalNetlink(pad int) (out []byte, err error) { + hb, err := self.Header.MarshalNetlink(pad) + if err == nil { + var bb []byte + bb, err = netlink.MarshalAttributes(self.Attributes, pad) + if err == nil { + out = bytes.Join([][]byte{hb, bb}, []byte{}) + } + } + return } // Unmarshals a generic message using the header as a guide. // An error will be returned if the header cannot unmarshal properly, // or any attribute in the series failed. -func (self *Message)UnmarshalNetlink(in []byte, pad int)(err os.Error){ - if len(in) < self.Header.Len() { - return os.NewError("Insufficient data for unmarshal of Header") - } - err = self.Header.UnmarshalNetlink(in[0:self.Header.Len()], pad) - if err == nil { - pos := netlink.Reposition(self.Header.Len(), pad) - if len(in) > pos { - self.Attributes, err = netlink.UnmarshalAttributes(in[pos:], pad) - } - } - return +func (self *Message) UnmarshalNetlink(in []byte, pad int) (err error) { + if len(in) < self.Header.Len() { + return errors.New("Insufficient data for unmarshal of Header") + } + err = self.Header.UnmarshalNetlink(in[0:self.Header.Len()], pad) + if err == nil { + pos := netlink.Reposition(self.Header.Len(), pad) + if len(in) > pos { + self.Attributes, err = netlink.UnmarshalAttributes(in[pos:], pad) + } + } + return } diff --git a/src/netlink/rtnetlink/route/header.go b/src/netlink/rtnetlink/route/header.go index 8fe9e22..965b3ae 100644 --- a/src/netlink/rtnetlink/route/header.go +++ b/src/netlink/rtnetlink/route/header.go @@ -1,4 +1,5 @@ package route + /* Copyright (c) 2011, Abneptis LLC. All rights reserved. Original Author: James D. Nurmi @@ -6,48 +7,47 @@ package route See LICENSE for details */ -import "encoding/binary" +import ( + "encoding/binary" + "errors" +) import "netlink/rtnetlink" import "netlink" -import "os" - type Header [12]byte -func NewHeader(afam rtnetlink.Family, dl uint8, sl uint8, tos uint8, t Table, o Origin, s rtnetlink.Scope, T Type, f Flags)(*Header){ - hdr := Header{byte(afam), dl, sl, tos, byte(t), byte(o), byte(s), byte(T)} - binary.LittleEndian.PutUint32(hdr[8:12], uint32(f)) - return &hdr +func NewHeader(afam rtnetlink.Family, dl uint8, sl uint8, tos uint8, t Table, o Origin, s rtnetlink.Scope, T Type, f Flags) *Header { + hdr := Header{byte(afam), dl, sl, tos, byte(t), byte(o), byte(s), byte(T)} + binary.LittleEndian.PutUint32(hdr[8:12], uint32(f)) + return &hdr } - -func (self Header)Len()(int) { return 12 } -func (self Header)AddressFamily()(rtnetlink.Family){ return rtnetlink.Family(self[0]) } -func (self Header)AddressDestLength()(uint8){ return self[1] } -func (self Header)AddressSourceLength()(uint8){ return self[2] } -func (self Header)TOS()(uint8){ return self[3] } -func (self Header)RoutingTable()(Table){ return Table(self[4]) } -func (self Header)RouteOrigin()(Origin){ return Origin(self[5]) } -func (self Header)AddressScope()(rtnetlink.Scope){ return rtnetlink.Scope(self[6]) } -func (self Header)RouteType()(Type){ return Type(self[7]) } -func (self Header)Flags()(Flags) { return Flags(binary.LittleEndian.Uint32(self[8:12])) } - - -func (self *Header)UnmarshalNetlink(in []byte, pad int)(err os.Error){ - if len(in) < 12 { - err = os.NewError("Too short to be a valid Routing Message") - } - if err == nil { - copy(self[0:12], in[0:12]) - } - return +func (self Header) Len() int { return 12 } +func (self Header) AddressFamily() rtnetlink.Family { return rtnetlink.Family(self[0]) } +func (self Header) AddressDestLength() uint8 { return self[1] } +func (self Header) AddressSourceLength() uint8 { return self[2] } +func (self Header) TOS() uint8 { return self[3] } +func (self Header) RoutingTable() Table { return Table(self[4]) } +func (self Header) RouteOrigin() Origin { return Origin(self[5]) } +func (self Header) AddressScope() rtnetlink.Scope { return rtnetlink.Scope(self[6]) } +func (self Header) RouteType() Type { return Type(self[7]) } +func (self Header) Flags() Flags { return Flags(binary.LittleEndian.Uint32(self[8:12])) } + +func (self *Header) UnmarshalNetlink(in []byte, pad int) (err error) { + if len(in) < 12 { + err = errors.New("Too short to be a valid Routing Message") + } + if err == nil { + copy(self[0:12], in[0:12]) + } + return } -func (self Header)MarshalNetlink(pad int)(out []byte, err os.Error){ - if err == nil { - out = make([]byte, 12) - copy(out, self[0:]) - out = netlink.PadBytes(out, pad) - } - return +func (self Header) MarshalNetlink(pad int) (out []byte, err error) { + if err == nil { + out = make([]byte, 12) + copy(out, self[0:]) + out = netlink.PadBytes(out, pad) + } + return } diff --git a/src/netlink/socket.go b/src/netlink/socket.go index 3969fe9..961fa9f 100644 --- a/src/netlink/socket.go +++ b/src/netlink/socket.go @@ -7,59 +7,60 @@ package netlink See LICENSE for details */ -import "os" +import ( + "errors" +) import "syscall" +import "fmt" // A netlink.Socket implements the lowest level of netlink communications. type Socket struct { - fd int + fd int } -func toErr(eno int)(err os.Error){ - if eno != 0 { err = os.NewError(syscall.Errstr(eno))} - return +func toErr(eno int) (err error) { + if eno != 0 { + //err = errors.New(syscall.Errstr(eno)) + err = errors.New(fmt.Sprintf("undefined errorstring for error number %s", eno)) + } + return } // Dials a netlink socket. Usually you do not need permissions for this, // though specific commands may be rejected. -func Dial(nlf NetlinkFamily)(rwc *Socket, err os.Error){ - fdno, errno := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_DGRAM, int(nlf)) - err = toErr(errno) - if err == nil { - rwc = &Socket{fd:fdno} - } - return +func Dial(nlf NetlinkFamily) (rwc *Socket, err error) { + fdno, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_DGRAM, int(nlf)) +// err = toErr(errno) + if err == nil { + rwc = &Socket{fd: fdno} + } + return } // Close the netlink socket -func (self *Socket)Close()(err os.Error){ - errno := syscall.Close(self.fd) - err = toErr(errno) - return +func (self *Socket) Close() (err error) { + syscall.Close(self.fd) + //err = toErr(errno) + return } // Writes to the netlink socket. Data should be (1 or more) complete // netlink frames, as netlink is not friendly w/ fragmentation. -func (self *Socket)Write(in []byte)(n int, err os.Error){ - n, errno := syscall.Write(self.fd, in) - err = toErr(errno) - return +func (self *Socket) Write(in []byte) (n int, err error) { + n, err = syscall.Write(self.fd, in) + return } // Reads from a netlink socket. Generally should be a bufio with // at least an 8k buffer. More for machines with large routing tables. -func (self *Socket)Read(in []byte)(n int, err os.Error){ - n, errno := syscall.Read(self.fd, in) - err = toErr(errno) - return +func (self *Socket) Read(in []byte) (n int, err error) { + n, err = syscall.Read(self.fd, in) + return } // Bind the netlink socket to receive multicast messages -func (self *Socket)Bind(pid, groups uint32) (err os.Error) { +func (self *Socket) Bind(pid, groups uint32) (err error) { addr := &syscall.SockaddrNetlink{Pid: pid, Groups: groups} - e := syscall.Bind(self.fd, addr) - if e != 0 { - err = os.Errno(e) - } + err = syscall.Bind(self.fd, addr) return -} \ No newline at end of file +} diff --git a/tools/get_addrs.go b/tools/get_addrs.go index f37c323..e791b92 100644 --- a/tools/get_addrs.go +++ b/tools/get_addrs.go @@ -10,61 +10,62 @@ package main See LICENSE for details */ -import "os" import "netlink/rtnetlink/addr" import "netlink/rtnetlink" import "log" import "netlink" -func logec(c chan os.Error){ - for i := range(c) { - log.Printf("Error: %v", i) - } +func logec(c chan error) { + for i := range c { + log.Printf("Error: %v", i) + } } -func main(){ - nlmsg, err := netlink.NewMessage(rtnetlink.RTM_GETADDR, netlink.NLM_F_DUMP|netlink.NLM_F_REQUEST, &addr.Header{}, 4) - if err != nil { - log.Exitf("Couldn't construct message: %v", err) - } - log.Printf("Dialing: %v", nlmsg) - nlsock, err := netlink.Dial(netlink.NETLINK_ROUTE) - if err != nil { - log.Exitf("Couldn't dial netlink: %v", err) - } - h := netlink.NewHandler(nlsock) - ec := make(chan os.Error) - go logec(ec) - go h.Start(ec) - log.Printf("Sending query: %v", nlmsg) - c, err := h.Query(*nlmsg, 1, 4) - log.Printf("Sent query: %v", nlmsg.Header) - if err != nil { - log.Exitf("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_NEWADDR: - hdr := &addr.Header{} - msg := rtnetlink.NewMessage(hdr, nil) - err = msg.UnmarshalNetlink(i.Body, 4) - if err == nil { - log.Printf("Family: %v; Length: %d; Flags: %v; Scope: %v; IFIndex: %d", - hdr.AddressFamily(), hdr.PrefixLength(), hdr.Flags(), hdr.Scope(), - hdr.InterfaceIndex()) +func main() { + nlmsg, err := netlink.NewMessage(rtnetlink.RTM_GETADDR, netlink.NLM_F_DUMP|netlink.NLM_F_REQUEST, &addr.Header{}, 4) + if err != nil { + log.Fatalf("Couldn't construct message: %v", err) + } + log.Printf("Dialing: %v", nlmsg) + nlsock, err := netlink.Dial(netlink.NETLINK_ROUTE) + if err != nil { + log.Fatalf("Couldn't dial netlink: %v", err) + } + h := netlink.NewHandler(nlsock) + ec := make(chan error) + go logec(ec) + go h.Start(ec) + log.Printf("Sending query: %v", nlmsg) + c, err := h.Query(*nlmsg, 1, 4) + log.Printf("Sent query: %v", nlmsg.Header) + if err != nil { + log.Fatalf("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_NEWADDR: + hdr := &addr.Header{} + msg := rtnetlink.NewMessage(hdr, nil) + err = msg.UnmarshalNetlink(i.Body, 4) + if err == nil { + log.Printf("Family: %v; Length: %d; Flags: %v; Scope: %v; IFIndex: %d", + hdr.AddressFamily(), hdr.PrefixLength(), hdr.Flags(), hdr.Scope(), + hdr.InterfaceIndex()) - 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) - } - if err != nil { - log.Printf("Handler error: %v", err) - } - } + 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) + } + if err != nil { + log.Printf("Handler error: %v", err) + } + } } diff --git a/tools/get_links.go b/tools/get_links.go index 643536f..a163143 100644 --- a/tools/get_links.go +++ b/tools/get_links.go @@ -10,48 +10,49 @@ package main See LICENSE for details */ -import "os" import "netlink/rtnetlink/link" import "netlink/rtnetlink" import "log" import "netlink" -func main(){ - nlmsg, err := netlink.NewMessage(rtnetlink.RTM_GETLINK, netlink.NLM_F_DUMP|netlink.NLM_F_REQUEST, &link.Header{},4) - if err != nil { - log.Exitf("Couldn't construct message: %v", err) - } - nlsock, err := netlink.Dial(netlink.NETLINK_ROUTE) - if err != nil { - log.Exitf("Couldn't dial netlink: %v", err) - } - h := netlink.NewHandler(nlsock) - ec := make(chan os.Error) - go h.Start(ec) - c, err := h.Query(*nlmsg, 1, 4) - if err != nil { - log.Exitf("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, 4) - 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 main() { + nlmsg, err := netlink.NewMessage(rtnetlink.RTM_GETLINK, netlink.NLM_F_DUMP|netlink.NLM_F_REQUEST, &link.Header{}, 4) + if err != nil { + log.Fatalf("Couldn't construct message: %v", err) + } + nlsock, err := netlink.Dial(netlink.NETLINK_ROUTE) + if err != nil { + log.Fatalf("Couldn't dial netlink: %v", err) + } + h := netlink.NewHandler(nlsock) + ec := make(chan error) + go h.Start(ec) + c, err := h.Query(*nlmsg, 1, 4) + if err != nil { + log.Fatalf("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, 4) + 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) + } + } } diff --git a/tools/get_routes.go b/tools/get_routes.go index fea1341..ca43eae 100644 --- a/tools/get_routes.go +++ b/tools/get_routes.go @@ -10,50 +10,51 @@ package main See LICENSE for details */ -import "os" import "netlink/rtnetlink/route" import "netlink/rtnetlink" import "log" import "netlink" -func main(){ - rtmsg := route.NewHeader(0,0,0,0,0,0,0,0,0) - nlmsg, err := netlink.NewMessage(rtnetlink.RTM_GETROUTE, netlink.NLM_F_DUMP|netlink.NLM_F_REQUEST, rtmsg, 2) - if err != nil { - log.Exitf("Couldn't construct message: %v", err) - } - nlsock, err := netlink.Dial(netlink.NETLINK_ROUTE) - if err != nil { - log.Exitf("Couldn't dial netlink: %v", err) - } - h := netlink.NewHandler(nlsock) - ec := make(chan os.Error) - go h.Start(ec) - c, err := h.Query(*nlmsg, 1, 4) - if err != nil { - log.Exitf("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_NEWROUTE: - hdr := &route.Header{} - msg := rtnetlink.NewMessage(hdr, nil) - err = msg.UnmarshalNetlink(i.Body, 4) +func main() { + rtmsg := route.NewHeader(0, 0, 0, 0, 0, 0, 0, 0, 0) + nlmsg, err := netlink.NewMessage(rtnetlink.RTM_GETROUTE, netlink.NLM_F_DUMP|netlink.NLM_F_REQUEST, rtmsg, 2) + if err != nil { + log.Fatalf("Couldn't construct message: %v", err) + } + nlsock, err := netlink.Dial(netlink.NETLINK_ROUTE) + if err != nil { + log.Fatalf("Couldn't dial netlink: %v", err) + } + h := netlink.NewHandler(nlsock) + ec := make(chan error) + go h.Start(ec) + c, err := h.Query(*nlmsg, 1, 4) + if err != nil { + log.Fatalf("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_NEWROUTE: + hdr := &route.Header{} + msg := rtnetlink.NewMessage(hdr, nil) + err = msg.UnmarshalNetlink(i.Body, 4) - if err == nil { - log.Printf("Route: %v (%d/%d) TOS: %d; (Table: %v; Origin: %v; Scope: %v; Type: %v; Flags: %v", - hdr.AddressFamily(), hdr.AddressDestLength(), hdr.AddressSourceLength(), - hdr.TOS(), hdr.RoutingTable(), hdr.RouteOrigin(), hdr.AddressScope(), - hdr.RouteType(), hdr.Flags()) - 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) - } - } + if err == nil { + log.Printf("Route: %v (%d/%d) TOS: %d; (Table: %v; Origin: %v; Scope: %v; Type: %v; Flags: %v", + hdr.AddressFamily(), hdr.AddressDestLength(), hdr.AddressSourceLength(), + hdr.TOS(), hdr.RoutingTable(), hdr.RouteOrigin(), hdr.AddressScope(), + hdr.RouteType(), hdr.Flags()) + 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) + } + } } diff --git a/tools/ifmanip.go b/tools/ifmanip.go index a16b4f7..9b23922 100644 --- a/tools/ifmanip.go +++ b/tools/ifmanip.go @@ -12,46 +12,49 @@ import "netlink/rtmanip" import "netlink/rtnetlink/link" import "flag" import "log" -import "os" -var doUp = flag.Bool("up",false, "Turn interface up") -var doDown = flag.Bool("down",false, "Turn interface up") +var doUp = flag.Bool("up", false, "Turn interface up") +var doDown = flag.Bool("down", false, "Turn interface up") var ifName = flag.String("ifname", "", "Interface to use") -func main(){ - flag.Parse() - nlsock, err := netlink.Dial(netlink.NETLINK_ROUTE) - if err != nil { - log.Exitf("Couldn't dial netlink: %v", err) - } - h := netlink.NewHandler(nlsock) - ec := make(chan os.Error) - go func(){ - for e := range(ec) { - log.Printf("Netlink error: %v", e) - } - }() - go h.Start(ec) - lf := rtmanip.NewLinkFinder(h) - l, err := lf.GetLinkByName(*ifName) - if err == nil { - if *doDown { - err = l.SetLinkState(^link.IFF_UP, link.IFF_UP) - if err != nil { log.Printf("Couldn't turn down interface: %v", err) } - l.Refresh() - } - if *doUp { - err = l.SetLinkState(link.IFF_UP, link.IFF_UP) - if err != nil { log.Printf("Couldn't turn up interface: %v", err) } - l.Refresh() - } - log.Printf("Link Index: %d", l.LinkIndex()) - log.Printf("Link Name: %s", l.LinkName()) - log.Printf("Link Flags: %s", l.LinkFlags()) - log.Printf("Link MTU: %d", l.LinkMTU()) - log.Printf("Link (l2) Address: %x", l.LinkAddress()) - log.Printf("Link (l2) Broadcast: %x", l.LinkBroadcastAddress()) - } else { - log.Exitf("Couldn't get link: %v", err) - } +func main() { + flag.Parse() + nlsock, err := netlink.Dial(netlink.NETLINK_ROUTE) + if err != nil { + log.Fatalf("Couldn't dial netlink: %v", err) + } + h := netlink.NewHandler(nlsock) + ec := make(chan error) + go func() { + for e := range ec { + log.Printf("Netlink error: %v", e) + } + }() + go h.Start(ec) + lf := rtmanip.NewLinkFinder(h) + l, err := lf.GetLinkByName(*ifName) + if err == nil { + if *doDown { + err = l.SetLinkState(^link.IFF_UP) + if err != nil { + log.Printf("Couldn't turn down interface: %v", err) + } + l.Refresh() + } + if *doUp { + err = l.SetLinkState(link.IFF_UP) + if err != nil { + log.Printf("Couldn't turn up interface: %v", err) + } + l.Refresh() + } + log.Printf("Link Index: %d", l.LinkIndex()) + log.Printf("Link Name: %s", l.LinkName()) + log.Printf("Link Flags: %s", l.LinkFlags()) + log.Printf("Link MTU: %d", l.LinkMTU()) + log.Printf("Link (l2) Address: %x", l.LinkAddress()) + log.Printf("Link (l2) Broadcast: %x", l.LinkBroadcastAddress()) + } else { + log.Fatalf("Couldn't get link: %s, %v", *ifName, err) + } } From 796b4a8aebe4c492500396a8a9b87fbb392dc3a8 Mon Sep 17 00:00:00 2001 From: Amir Laher Date: Wed, 3 Oct 2012 15:58:46 +1300 Subject: [PATCH 3/3] removed unused helpers for old syscall.Error --- src/netlink/error.go | 6 ------ src/netlink/socket.go | 12 ------------ 2 files changed, 18 deletions(-) diff --git a/src/netlink/error.go b/src/netlink/error.go index dd000ae..ed96f4c 100644 --- a/src/netlink/error.go +++ b/src/netlink/error.go @@ -42,9 +42,3 @@ func (self *Error) UnmarshalNetlink(in []byte, pad int) (err error) { return } - -// Implements os.Error by using err.Error(-Code()) -func (self Error) Error() string { -// return Errstr(int(-self.Code())) - return "Error string unimplemented" -} diff --git a/src/netlink/socket.go b/src/netlink/socket.go index 961fa9f..9392ef4 100644 --- a/src/netlink/socket.go +++ b/src/netlink/socket.go @@ -7,25 +7,13 @@ package netlink See LICENSE for details */ -import ( - "errors" -) import "syscall" -import "fmt" // A netlink.Socket implements the lowest level of netlink communications. type Socket struct { fd int } -func toErr(eno int) (err error) { - if eno != 0 { - //err = errors.New(syscall.Errstr(eno)) - err = errors.New(fmt.Sprintf("undefined errorstring for error number %s", eno)) - } - return -} - // Dials a netlink socket. Usually you do not need permissions for this, // though specific commands may be rejected. func Dial(nlf NetlinkFamily) (rwc *Socket, err error) {