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