diff --git a/conn_linux_error_test.go b/conn_linux_error_test.go index 2eeb677..252bb79 100644 --- a/conn_linux_error_test.go +++ b/conn_linux_error_test.go @@ -37,15 +37,16 @@ func TestConnReceiveErrorLinux(t *testing.T) { Header: netlink.Header{ Length: 20, Type: netlink.Error, - Sequence: 1, + Sequence: 1234, PID: 1, }, // -2, little endian (ENOENT) Data: []byte{0xfe, 0xff, 0xff, 0xff}, }}, want: &netlink.OpError{ - Op: "receive", - Err: unix.ENOENT, + Op: "receive", + Err: unix.ENOENT, + Sequence: 1234, }, }, { diff --git a/errors.go b/errors.go index 8c0fce7..a7e3f50 100644 --- a/errors.go +++ b/errors.go @@ -63,6 +63,11 @@ type OpError struct { // library. Err error + // Sequence contains the sequence number of the netlink message which caused + // this error. This will only be valid if Op is "receive", otherwise this + // field will be set to zero. + Sequence uint32 + // Message and Offset contain additional error information provided by the // kernel when the ExtendedAcknowledge option is set on a Conn and the // kernel indicates the AcknowledgeTLVs flag in a response. If this option diff --git a/message.go b/message.go index 5727716..384580e 100644 --- a/message.go +++ b/message.go @@ -276,24 +276,27 @@ func checkMessage(m Message) error { return nil } + oerr := &OpError{ + Op: "receive", + Sequence: m.Header.Sequence, + } + // Errno occupies 4 bytes. const endErrno = 4 if len(m.Data) < endErrno { - return newOpError("receive", errShortErrorMessage) + oerr.Err = errShortErrorMessage + return oerr } c := nlenc.Int32(m.Data[:endErrno]) if c == 0 { // 0 indicates no error. return nil - } - - oerr := &OpError{ - Op: "receive", + } else { // Error code is a negative integer, convert it into an OS-specific raw // system call error, but do not wrap with os.NewSyscallError to signify // that this error was produced by a netlink message; not a system call. - Err: newError(-1 * int(c)), + oerr.Err = newError(-1 * int(c)) } // TODO(mdlayher): investigate the Capped flag. @@ -309,7 +312,8 @@ func checkMessage(m Message) error { if hasHeader { // There is an nlmsghdr preceding the TLVs. if len(m.Data) < endErrno+nlmsgHeaderLen { - return newOpError("receive", errShortErrorMessage) + oerr.Err = errShortErrorMessage + return oerr } // The TLVs should be at the offset indicated by the nlmsghdr.length, @@ -319,7 +323,8 @@ func checkMessage(m Message) error { off = endErrno + int(h.Length) if len(m.Data) < off { - return newOpError("receive", errShortErrorMessage) + oerr.Err = errShortErrorMessage + return oerr } } else { // There is no nlmsghdr preceding the TLVs, parse them directly.