route_classic.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. // Copyright 2016 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // +build darwin dragonfly freebsd netbsd
  5. package route
  6. import "syscall"
  7. func (m *RouteMessage) marshal() ([]byte, error) {
  8. w, ok := wireFormats[m.Type]
  9. if !ok {
  10. return nil, errUnsupportedMessage
  11. }
  12. l := w.bodyOff + addrsSpace(m.Addrs)
  13. b := make([]byte, l)
  14. nativeEndian.PutUint16(b[:2], uint16(l))
  15. if m.Version == 0 {
  16. b[2] = sysRTM_VERSION
  17. } else {
  18. b[2] = byte(m.Version)
  19. }
  20. b[3] = byte(m.Type)
  21. nativeEndian.PutUint32(b[8:12], uint32(m.Flags))
  22. nativeEndian.PutUint16(b[4:6], uint16(m.Index))
  23. nativeEndian.PutUint32(b[16:20], uint32(m.ID))
  24. nativeEndian.PutUint32(b[20:24], uint32(m.Seq))
  25. attrs, err := marshalAddrs(b[w.bodyOff:], m.Addrs)
  26. if err != nil {
  27. return nil, err
  28. }
  29. if attrs > 0 {
  30. nativeEndian.PutUint32(b[12:16], uint32(attrs))
  31. }
  32. return b, nil
  33. }
  34. func (w *wireFormat) parseRouteMessage(typ RIBType, b []byte) (Message, error) {
  35. if len(b) < w.bodyOff {
  36. return nil, errMessageTooShort
  37. }
  38. l := int(nativeEndian.Uint16(b[:2]))
  39. if len(b) < l {
  40. return nil, errInvalidMessage
  41. }
  42. m := &RouteMessage{
  43. Version: int(b[2]),
  44. Type: int(b[3]),
  45. Flags: int(nativeEndian.Uint32(b[8:12])),
  46. Index: int(nativeEndian.Uint16(b[4:6])),
  47. ID: uintptr(nativeEndian.Uint32(b[16:20])),
  48. Seq: int(nativeEndian.Uint32(b[20:24])),
  49. extOff: w.extOff,
  50. raw: b[:l],
  51. }
  52. errno := syscall.Errno(nativeEndian.Uint32(b[28:32]))
  53. if errno != 0 {
  54. m.Err = errno
  55. }
  56. var err error
  57. m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[w.bodyOff:])
  58. if err != nil {
  59. return nil, err
  60. }
  61. return m, nil
  62. }