|  | // Copyright 2016 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | // +build darwin dragonfly freebsd netbsd | 
|  |  | 
|  | package route | 
|  |  | 
|  | import ( | 
|  | "runtime" | 
|  | "syscall" | 
|  | ) | 
|  |  | 
|  | func (m *RouteMessage) marshal() ([]byte, error) { | 
|  | w, ok := wireFormats[m.Type] | 
|  | if !ok { | 
|  | return nil, errUnsupportedMessage | 
|  | } | 
|  | l := w.bodyOff + addrsSpace(m.Addrs) | 
|  | if runtime.GOOS == "darwin" { | 
|  | // Fix stray pointer writes on macOS. | 
|  | // See golang.org/issue/22456. | 
|  | l += 1024 | 
|  | } | 
|  | b := make([]byte, l) | 
|  | nativeEndian.PutUint16(b[:2], uint16(l)) | 
|  | if m.Version == 0 { | 
|  | b[2] = sysRTM_VERSION | 
|  | } else { | 
|  | b[2] = byte(m.Version) | 
|  | } | 
|  | b[3] = byte(m.Type) | 
|  | nativeEndian.PutUint32(b[8:12], uint32(m.Flags)) | 
|  | nativeEndian.PutUint16(b[4:6], uint16(m.Index)) | 
|  | nativeEndian.PutUint32(b[16:20], uint32(m.ID)) | 
|  | nativeEndian.PutUint32(b[20:24], uint32(m.Seq)) | 
|  | attrs, err := marshalAddrs(b[w.bodyOff:], m.Addrs) | 
|  | if err != nil { | 
|  | return nil, err | 
|  | } | 
|  | if attrs > 0 { | 
|  | nativeEndian.PutUint32(b[12:16], uint32(attrs)) | 
|  | } | 
|  | return b, nil | 
|  | } | 
|  |  | 
|  | func (w *wireFormat) parseRouteMessage(typ RIBType, b []byte) (Message, error) { | 
|  | if len(b) < w.bodyOff { | 
|  | return nil, errMessageTooShort | 
|  | } | 
|  | l := int(nativeEndian.Uint16(b[:2])) | 
|  | if len(b) < l { | 
|  | return nil, errInvalidMessage | 
|  | } | 
|  | m := &RouteMessage{ | 
|  | Version: int(b[2]), | 
|  | Type:    int(b[3]), | 
|  | Flags:   int(nativeEndian.Uint32(b[8:12])), | 
|  | Index:   int(nativeEndian.Uint16(b[4:6])), | 
|  | ID:      uintptr(nativeEndian.Uint32(b[16:20])), | 
|  | Seq:     int(nativeEndian.Uint32(b[20:24])), | 
|  | extOff:  w.extOff, | 
|  | raw:     b[:l], | 
|  | } | 
|  | errno := syscall.Errno(nativeEndian.Uint32(b[28:32])) | 
|  | if errno != 0 { | 
|  | m.Err = errno | 
|  | } | 
|  | var err error | 
|  | m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[w.bodyOff:]) | 
|  | if err != nil { | 
|  | return nil, err | 
|  | } | 
|  | return m, nil | 
|  | } |