You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

75 lines
1.8 KiB

  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 (
  7. "runtime"
  8. "syscall"
  9. )
  10. func (m *RouteMessage) marshal() ([]byte, error) {
  11. w, ok := wireFormats[m.Type]
  12. if !ok {
  13. return nil, errUnsupportedMessage
  14. }
  15. l := w.bodyOff + addrsSpace(m.Addrs)
  16. if runtime.GOOS == "darwin" {
  17. // Fix stray pointer writes on macOS.
  18. // See golang.org/issue/22456.
  19. l += 1024
  20. }
  21. b := make([]byte, l)
  22. nativeEndian.PutUint16(b[:2], uint16(l))
  23. if m.Version == 0 {
  24. b[2] = sysRTM_VERSION
  25. } else {
  26. b[2] = byte(m.Version)
  27. }
  28. b[3] = byte(m.Type)
  29. nativeEndian.PutUint32(b[8:12], uint32(m.Flags))
  30. nativeEndian.PutUint16(b[4:6], uint16(m.Index))
  31. nativeEndian.PutUint32(b[16:20], uint32(m.ID))
  32. nativeEndian.PutUint32(b[20:24], uint32(m.Seq))
  33. attrs, err := marshalAddrs(b[w.bodyOff:], m.Addrs)
  34. if err != nil {
  35. return nil, err
  36. }
  37. if attrs > 0 {
  38. nativeEndian.PutUint32(b[12:16], uint32(attrs))
  39. }
  40. return b, nil
  41. }
  42. func (w *wireFormat) parseRouteMessage(typ RIBType, b []byte) (Message, error) {
  43. if len(b) < w.bodyOff {
  44. return nil, errMessageTooShort
  45. }
  46. l := int(nativeEndian.Uint16(b[:2]))
  47. if len(b) < l {
  48. return nil, errInvalidMessage
  49. }
  50. m := &RouteMessage{
  51. Version: int(b[2]),
  52. Type: int(b[3]),
  53. Flags: int(nativeEndian.Uint32(b[8:12])),
  54. Index: int(nativeEndian.Uint16(b[4:6])),
  55. ID: uintptr(nativeEndian.Uint32(b[16:20])),
  56. Seq: int(nativeEndian.Uint32(b[20:24])),
  57. extOff: w.extOff,
  58. raw: b[:l],
  59. }
  60. errno := syscall.Errno(nativeEndian.Uint32(b[28:32]))
  61. if errno != 0 {
  62. m.Err = errno
  63. }
  64. var err error
  65. m.Addrs, err = parseAddrs(uint(nativeEndian.Uint32(b[12:16])), parseKernelInetAddr, b[w.bodyOff:])
  66. if err != nil {
  67. return nil, err
  68. }
  69. return m, nil
  70. }