1
2
3
4
5
6
7 package routebsd
8
9 import (
10 "fmt"
11 "runtime"
12 "syscall"
13 )
14
15 func (m *InterfaceMessage) String() string {
16 var attrs addrAttrs
17 if runtime.GOOS == "openbsd" {
18 attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
19 } else {
20 attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
21 }
22 return fmt.Sprintf("%s", attrs)
23 }
24
25 func (m *InterfaceAddrMessage) String() string {
26 var attrs addrAttrs
27 if runtime.GOOS == "openbsd" {
28 attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
29 } else {
30 attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
31 }
32 return fmt.Sprintf("%s", attrs)
33 }
34
35 func (m *InterfaceMulticastAddrMessage) String() string {
36 return fmt.Sprintf("%s", addrAttrs(nativeEndian.Uint32(m.raw[4:8])))
37 }
38
39 type addrAttrs uint
40
41 var addrAttrNames = [...]string{
42 "dst",
43 "gateway",
44 "netmask",
45 "genmask",
46 "ifp",
47 "ifa",
48 "author",
49 "brd",
50 "df:mpls1-n:tag-o:src",
51 "df:mpls2-o:srcmask",
52 "df:mpls3-o:label",
53 "o:bfd",
54 "o:dns",
55 "o:static",
56 "o:search",
57 }
58
59 func (attrs addrAttrs) String() string {
60 var s string
61 for i, name := range addrAttrNames {
62 if attrs&(1<<uint(i)) != 0 {
63 if s != "" {
64 s += "|"
65 }
66 s += name
67 }
68 }
69 if s == "" {
70 return "<nil>"
71 }
72 return s
73 }
74
75 type msgs []Message
76
77 func (ms msgs) validate() ([]string, error) {
78 var ss []string
79 for _, m := range ms {
80 switch m := m.(type) {
81 case *InterfaceMessage:
82 var attrs addrAttrs
83 if runtime.GOOS == "openbsd" {
84 attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
85 } else {
86 attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
87 }
88 if err := addrs(m.Addrs).match(attrs); err != nil {
89 return nil, err
90 }
91 ss = append(ss, m.String()+" "+addrs(m.Addrs).String())
92 case *InterfaceAddrMessage:
93 var attrs addrAttrs
94 if runtime.GOOS == "openbsd" {
95 attrs = addrAttrs(nativeEndian.Uint32(m.raw[12:16]))
96 } else {
97 attrs = addrAttrs(nativeEndian.Uint32(m.raw[4:8]))
98 }
99 if err := addrs(m.Addrs).match(attrs); err != nil {
100 return nil, err
101 }
102 ss = append(ss, m.String()+" "+addrs(m.Addrs).String())
103 case *InterfaceMulticastAddrMessage:
104 if err := addrs(m.Addrs).match(addrAttrs(nativeEndian.Uint32(m.raw[4:8]))); err != nil {
105 return nil, err
106 }
107 ss = append(ss, m.String()+" "+addrs(m.Addrs).String())
108 default:
109 ss = append(ss, fmt.Sprintf("%+v", m))
110 }
111 }
112 return ss, nil
113 }
114
115 type addrFamily int
116
117 func (af addrFamily) String() string {
118 switch af {
119 case syscall.AF_UNSPEC:
120 return "unspec"
121 case syscall.AF_LINK:
122 return "link"
123 case syscall.AF_INET:
124 return "inet4"
125 case syscall.AF_INET6:
126 return "inet6"
127 default:
128 return fmt.Sprintf("%d", af)
129 }
130 }
131
132 const hexDigit = "0123456789abcdef"
133
134 type llAddr []byte
135
136 func (a llAddr) String() string {
137 if len(a) == 0 {
138 return ""
139 }
140 buf := make([]byte, 0, len(a)*3-1)
141 for i, b := range a {
142 if i > 0 {
143 buf = append(buf, ':')
144 }
145 buf = append(buf, hexDigit[b>>4])
146 buf = append(buf, hexDigit[b&0xF])
147 }
148 return string(buf)
149 }
150
151 type ipAddr []byte
152
153 func (a ipAddr) String() string {
154 if len(a) == 0 {
155 return "<nil>"
156 }
157 if len(a) == 4 {
158 return fmt.Sprintf("%d.%d.%d.%d", a[0], a[1], a[2], a[3])
159 }
160 if len(a) == 16 {
161 return fmt.Sprintf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15])
162 }
163 s := make([]byte, len(a)*2)
164 for i, tn := range a {
165 s[i*2], s[i*2+1] = hexDigit[tn>>4], hexDigit[tn&0xf]
166 }
167 return string(s)
168 }
169
170 func (a *LinkAddr) String() string {
171 name := a.Name
172 if name == "" {
173 name = "<nil>"
174 }
175 lla := llAddr(a.Addr).String()
176 if lla == "" {
177 lla = "<nil>"
178 }
179 return fmt.Sprintf("(%v %d %s %s)", addrFamily(a.Family()), a.Index, name, lla)
180 }
181
182 func (a *InetAddr) String() string {
183 return fmt.Sprintf("(%v %v)", addrFamily(a.Family()), a.IP)
184 }
185
186 type addrs []Addr
187
188 func (as addrs) String() string {
189 var s string
190 for _, a := range as {
191 if a == nil {
192 continue
193 }
194 if len(s) > 0 {
195 s += " "
196 }
197 switch a := a.(type) {
198 case *LinkAddr:
199 s += a.String()
200 case *InetAddr:
201 s += a.String()
202 }
203 }
204 if s == "" {
205 return "<nil>"
206 }
207 return s
208 }
209
210 func (as addrs) match(attrs addrAttrs) error {
211 var ts addrAttrs
212 af := syscall.AF_UNSPEC
213 for i := range as {
214 if as[i] != nil {
215 ts |= 1 << uint(i)
216 }
217 switch addr := as[i].(type) {
218 case *InetAddr:
219 got := 0
220 if addr.IP.Is4() {
221 got = syscall.AF_INET
222 } else if addr.IP.Is6() {
223 got = syscall.AF_INET6
224 }
225 if af == syscall.AF_UNSPEC {
226 if got != 0 {
227 af = got
228 }
229 }
230 if got != 0 && af != got {
231 return fmt.Errorf("got %v; want %v", addrs(as), addrFamily(af))
232 }
233 }
234 }
235 if ts != attrs && ts > attrs {
236 return fmt.Errorf("%v not included in %v", ts, attrs)
237 }
238 return nil
239 }
240
View as plain text