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
5//go:build darwin || dragonfly || freebsd || netbsd || openbsd
6// +build darwin dragonfly freebsd netbsd openbsd
7
8package route
9
10// A Message represents a routing message.
11type Message interface {
12	// Sys returns operating system-specific information.
13	Sys() []Sys
14}
15
16// A Sys reprensents operating system-specific information.
17type Sys interface {
18	// SysType returns a type of operating system-specific
19	// information.
20	SysType() SysType
21}
22
23// A SysType represents a type of operating system-specific
24// information.
25type SysType int
26
27const (
28	SysMetrics SysType = iota
29	SysStats
30)
31
32// ParseRIB parses b as a routing information base and returns a list
33// of routing messages.
34func ParseRIB(typ RIBType, b []byte) ([]Message, error) {
35	if !typ.parseable() {
36		return nil, errUnsupportedMessage
37	}
38	var msgs []Message
39	nmsgs, nskips := 0, 0
40	for len(b) > 4 {
41		nmsgs++
42		l := int(nativeEndian.Uint16(b[:2]))
43		if l == 0 {
44			return nil, errInvalidMessage
45		}
46		if len(b) < l {
47			return nil, errMessageTooShort
48		}
49		if b[2] != rtmVersion {
50			b = b[l:]
51			continue
52		}
53		if w, ok := wireFormats[int(b[3])]; !ok {
54			nskips++
55		} else {
56			m, err := w.parse(typ, b[:l])
57			if err != nil {
58				return nil, err
59			}
60			if m == nil {
61				nskips++
62			} else {
63				msgs = append(msgs, m)
64			}
65		}
66		b = b[l:]
67	}
68	// We failed to parse any of the messages - version mismatch?
69	if nmsgs != len(msgs)+nskips {
70		return nil, errMessageMismatch
71	}
72	return msgs, nil
73}
74