ODPM 266: Go-libmemif + 2 examples.
[govpp.git] / vendor / github.com / google / gopacket / layers / ospf.go
1 // Copyright 2017 Google, Inc. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the LICENSE file in the root of the source
5 // tree.
6
7 package layers
8
9 import (
10         "encoding/binary"
11         "fmt"
12
13         "github.com/google/gopacket"
14 )
15
16 // OSPFType denotes what kind of OSPF type it is
17 type OSPFType uint8
18
19 // Potential values for OSPF.Type.
20 const (
21         OSPFHello                   OSPFType = 1
22         OSPFDatabaseDescription     OSPFType = 2
23         OSPFLinkStateRequest        OSPFType = 3
24         OSPFLinkStateUpdate         OSPFType = 4
25         OSPFLinkStateAcknowledgment OSPFType = 5
26 )
27
28 // LSA Function Codes for LSAheader.LSType
29 const (
30         RouterLSAtype          = 0x2001
31         NetworkLSAtype         = 0x2002
32         InterAreaPrefixLSAtype = 0x2003
33         InterAreaRouterLSAtype = 0x2004
34         ASExternalLSAtype      = 0x4005
35         NSSALSAtype            = 0x2007
36         LinkLSAtype            = 0x0008
37         IntraAreaPrefixLSAtype = 0x2009
38 )
39
40 // String conversions for OSPFType
41 func (i OSPFType) String() string {
42         switch i {
43         case OSPFHello:
44                 return "Hello"
45         case OSPFDatabaseDescription:
46                 return "Database Description"
47         case OSPFLinkStateRequest:
48                 return "Link State Request"
49         case OSPFLinkStateUpdate:
50                 return "Link State Update"
51         case OSPFLinkStateAcknowledgment:
52                 return "Link State Acknowledgment"
53         default:
54                 return ""
55         }
56 }
57
58 // Prefix extends IntraAreaPrefixLSA
59 type Prefix struct {
60         PrefixLength  uint8
61         PrefixOptions uint8
62         Metric        uint16
63         AddressPrefix []byte
64 }
65
66 // IntraAreaPrefixLSA is the struct from RFC 5340  A.4.10.
67 type IntraAreaPrefixLSA struct {
68         NumOfPrefixes  uint16
69         RefLSType      uint16
70         RefLinkStateID uint32
71         RefAdvRouter   uint32
72         Prefixes       []Prefix
73 }
74
75 // LinkLSA is the struct from RFC 5340  A.4.9.
76 type LinkLSA struct {
77         RtrPriority      uint8
78         Options          uint32
79         LinkLocalAddress []byte
80         NumOfPrefixes    uint32
81         Prefixes         []Prefix
82 }
83
84 // ASExternalLSA is the struct from RFC 5340  A.4.7.
85 type ASExternalLSA struct {
86         Flags             uint8
87         Metric            uint32
88         PrefixLength      uint8
89         PrefixOptions     uint8
90         RefLSType         uint16
91         AddressPrefix     []byte
92         ForwardingAddress []byte
93         ExternalRouteTag  uint32
94         RefLinkStateID    uint32
95 }
96
97 // InterAreaRouterLSA is the struct from RFC 5340  A.4.6.
98 type InterAreaRouterLSA struct {
99         Options             uint32
100         Metric              uint32
101         DestinationRouterID uint32
102 }
103
104 // InterAreaPrefixLSA is the struct from RFC 5340  A.4.5.
105 type InterAreaPrefixLSA struct {
106         Metric        uint32
107         PrefixLength  uint8
108         PrefixOptions uint8
109         AddressPrefix []byte
110 }
111
112 // NetworkLSA is the struct from RFC 5340  A.4.4.
113 type NetworkLSA struct {
114         Options        uint32
115         AttachedRouter []uint32
116 }
117
118 // Router extends RouterLSA
119 type Router struct {
120         Type                uint8
121         Metric              uint16
122         InterfaceID         uint32
123         NeighborInterfaceID uint32
124         NeighborRouterID    uint32
125 }
126
127 // RouterLSA is the struct from RFC 5340  A.4.3.
128 type RouterLSA struct {
129         Flags   uint8
130         Options uint32
131         Routers []Router
132 }
133
134 // LSAheader is the struct from RFC 5340  A.4.2.
135 type LSAheader struct {
136         LSAge       uint16
137         LSType      uint16
138         LinkStateID uint32
139         AdvRouter   uint32
140         LSSeqNumber uint32
141         LSChecksum  uint16
142         Length      uint16
143 }
144
145 // LSA links LSAheader with the structs from RFC 5340  A.4.
146 type LSA struct {
147         LSAheader
148         Content interface{}
149 }
150
151 // LSUpdate is the struct from RFC 5340  A.3.5.
152 type LSUpdate struct {
153         NumOfLSAs uint32
154         LSAs      []LSA
155 }
156
157 // LSReq is the struct from RFC 5340  A.3.4.
158 type LSReq struct {
159         LSType    uint16
160         LSID      uint32
161         AdvRouter uint32
162 }
163
164 // DbDescPkg is the struct from RFC 5340  A.3.3.
165 type DbDescPkg struct {
166         Options      uint32
167         InterfaceMTU uint16
168         Flags        uint16
169         DDSeqNumber  uint32
170         LSAinfo      []LSAheader
171 }
172
173 // HelloPkg  is the struct from RFC 5340  A.3.2.
174 type HelloPkg struct {
175         InterfaceID              uint32
176         RtrPriority              uint8
177         Options                  uint32
178         HelloInterval            uint16
179         RouterDeadInterval       uint16
180         DesignatedRouterID       uint32
181         BackupDesignatedRouterID uint32
182         NeighborID               []uint32
183 }
184
185 // HelloPkgV2 extends the HelloPkg struct with OSPFv2 information
186 type HelloPkgV2 struct {
187         HelloPkg
188         NetworkMask uint32
189 }
190
191 // OSPF is a basic OSPF packet header with common fields of Version 2 and Version 3.
192 type OSPF struct {
193         Version      uint8
194         Type         OSPFType
195         PacketLength uint16
196         RouterID     uint32
197         AreaID       uint32
198         Checksum     uint16
199         Content      interface{}
200 }
201
202 //OSPFv2 extend the OSPF head with version 2 specific fields
203 type OSPFv2 struct {
204         BaseLayer
205         OSPF
206         AuType         uint16
207         Authentication uint64
208 }
209
210 // OSPFv3 extend the OSPF head with version 3 specific fields
211 type OSPFv3 struct {
212         BaseLayer
213         OSPF
214         Instance uint8
215         Reserved uint8
216 }
217
218 // getLSAs parses the LSA information from the packet
219 func getLSAs(num uint32, data []byte) ([]LSA, error) {
220         var lsas []LSA
221         var i uint32 = 0
222         var offset uint32 = 0
223         for ; i < num; i++ {
224                 var content interface{}
225                 lstype := binary.BigEndian.Uint16(data[offset+2 : offset+4])
226                 lsalength := binary.BigEndian.Uint16(data[offset+18 : offset+20])
227
228                 switch lstype {
229                 case RouterLSAtype:
230                         var routers []Router
231                         var j uint32
232                         for j = 24; j < uint32(lsalength); j += 16 {
233                                 router := Router{
234                                         Type:                uint8(data[offset+j]),
235                                         Metric:              binary.BigEndian.Uint16(data[offset+j+2 : offset+j+4]),
236                                         InterfaceID:         binary.BigEndian.Uint32(data[offset+j+4 : offset+j+8]),
237                                         NeighborInterfaceID: binary.BigEndian.Uint32(data[offset+j+8 : offset+j+12]),
238                                         NeighborRouterID:    binary.BigEndian.Uint32(data[offset+j+12 : offset+j+16]),
239                                 }
240                                 routers = append(routers, router)
241                         }
242                         content = RouterLSA{
243                                 Flags:   uint8(data[offset+20]),
244                                 Options: binary.BigEndian.Uint32(data[offset+20:offset+24]) & 0x00FFFFFF,
245                                 Routers: routers,
246                         }
247                 case NetworkLSAtype:
248                         var routers []uint32
249                         var j uint32
250                         for j = 24; j < uint32(lsalength); j += 4 {
251                                 routers = append(routers, binary.BigEndian.Uint32(data[offset+j:offset+j+4]))
252                         }
253                         content = NetworkLSA{
254                                 Options:        binary.BigEndian.Uint32(data[offset+20:offset+24]) & 0x00FFFFFF,
255                                 AttachedRouter: routers,
256                         }
257                 case InterAreaPrefixLSAtype:
258                         content = InterAreaPrefixLSA{
259                                 Metric:        binary.BigEndian.Uint32(data[offset+20:offset+24]) & 0x00FFFFFF,
260                                 PrefixLength:  uint8(data[offset+24]),
261                                 PrefixOptions: uint8(data[offset+25]),
262                                 AddressPrefix: data[offset+28 : offset+uint32(lsalength)],
263                         }
264                 case InterAreaRouterLSAtype:
265                         content = InterAreaRouterLSA{
266                                 Options:             binary.BigEndian.Uint32(data[offset+20:offset+24]) & 0x00FFFFFF,
267                                 Metric:              binary.BigEndian.Uint32(data[offset+24:offset+28]) & 0x00FFFFFF,
268                                 DestinationRouterID: binary.BigEndian.Uint32(data[offset+28 : offset+32]),
269                         }
270                 case ASExternalLSAtype:
271                         fallthrough
272                 case NSSALSAtype:
273
274                         flags := uint8(data[offset+20])
275                         prefixLen := uint8(data[offset+24]) / 8
276                         var forwardingAddress []byte
277                         if (flags & 0x02) == 0x02 {
278                                 forwardingAddress = data[offset+28+uint32(prefixLen) : offset+28+uint32(prefixLen)+16]
279                         }
280                         content = ASExternalLSA{
281                                 Flags:             flags,
282                                 Metric:            binary.BigEndian.Uint32(data[offset+20:offset+24]) & 0x00FFFFFF,
283                                 PrefixLength:      prefixLen,
284                                 PrefixOptions:     uint8(data[offset+25]),
285                                 RefLSType:         binary.BigEndian.Uint16(data[offset+26 : offset+28]),
286                                 AddressPrefix:     data[offset+28 : offset+28+uint32(prefixLen)],
287                                 ForwardingAddress: forwardingAddress,
288                         }
289                 case LinkLSAtype:
290                         var prefixes []Prefix
291                         var prefixOffset uint32 = offset + 44
292                         var j uint32
293                         numOfPrefixes := binary.BigEndian.Uint32(data[offset+40 : offset+44])
294                         for j = 0; j < numOfPrefixes; j++ {
295                                 prefixLen := uint8(data[prefixOffset])
296                                 prefix := Prefix{
297                                         PrefixLength:  prefixLen,
298                                         PrefixOptions: uint8(data[prefixOffset+1]),
299                                         AddressPrefix: data[prefixOffset+4 : prefixOffset+4+uint32(prefixLen)/8],
300                                 }
301                                 prefixes = append(prefixes, prefix)
302                                 prefixOffset = prefixOffset + 4 + uint32(prefixLen)/8
303                         }
304                         content = LinkLSA{
305                                 RtrPriority:      uint8(data[offset+20]),
306                                 Options:          binary.BigEndian.Uint32(data[offset+20:offset+24]) & 0x00FFFFFF,
307                                 LinkLocalAddress: data[offset+24 : offset+40],
308                                 NumOfPrefixes:    numOfPrefixes,
309                                 Prefixes:         prefixes,
310                         }
311                 case IntraAreaPrefixLSAtype:
312                         var prefixes []Prefix
313                         var prefixOffset uint32 = offset + 32
314                         var j uint16
315                         numOfPrefixes := binary.BigEndian.Uint16(data[offset+20 : offset+22])
316                         for j = 0; j < numOfPrefixes; j++ {
317                                 prefixLen := uint8(data[prefixOffset])
318                                 prefix := Prefix{
319                                         PrefixLength:  prefixLen,
320                                         PrefixOptions: uint8(data[prefixOffset+1]),
321                                         Metric:        binary.BigEndian.Uint16(data[prefixOffset+2 : prefixOffset+4]),
322                                         AddressPrefix: data[prefixOffset+4 : prefixOffset+4+uint32(prefixLen)/8],
323                                 }
324                                 prefixes = append(prefixes, prefix)
325                                 prefixOffset = prefixOffset + 4 + uint32(prefixLen)
326                         }
327                         content = IntraAreaPrefixLSA{
328                                 NumOfPrefixes:  numOfPrefixes,
329                                 RefLSType:      binary.BigEndian.Uint16(data[offset+22 : offset+24]),
330                                 RefLinkStateID: binary.BigEndian.Uint32(data[offset+24 : offset+28]),
331                                 RefAdvRouter:   binary.BigEndian.Uint32(data[offset+28 : offset+32]),
332                                 Prefixes:       prefixes,
333                         }
334                 default:
335                         return nil, fmt.Errorf("Unknown Link State type.")
336                 }
337                 lsa := LSA{
338                         LSAheader: LSAheader{
339                                 LSAge:       binary.BigEndian.Uint16(data[offset : offset+2]),
340                                 LSType:      lstype,
341                                 LinkStateID: binary.BigEndian.Uint32(data[offset+4 : offset+8]),
342                                 AdvRouter:   binary.BigEndian.Uint32(data[offset+8 : offset+12]),
343                                 LSSeqNumber: binary.BigEndian.Uint32(data[offset+12 : offset+16]),
344                                 LSChecksum:  binary.BigEndian.Uint16(data[offset+16 : offset+18]),
345                                 Length:      lsalength,
346                         },
347                         Content: content,
348                 }
349                 lsas = append(lsas, lsa)
350                 offset += uint32(lsalength)
351         }
352         return lsas, nil
353 }
354
355 // DecodeFromBytes decodes the given bytes into the OSPF layer.
356 func (ospf *OSPFv2) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
357         if len(data) < 24 {
358                 return fmt.Errorf("Packet too smal for OSPF Version 2")
359         }
360
361         ospf.Version = uint8(data[0])
362         ospf.Type = OSPFType(data[1])
363         ospf.PacketLength = binary.BigEndian.Uint16(data[2:4])
364         ospf.RouterID = binary.BigEndian.Uint32(data[4:8])
365         ospf.AreaID = binary.BigEndian.Uint32(data[8:12])
366         ospf.Checksum = binary.BigEndian.Uint16(data[12:14])
367         ospf.AuType = binary.BigEndian.Uint16(data[14:16])
368         ospf.Authentication = binary.BigEndian.Uint64(data[16:24])
369
370         return nil
371 }
372
373 // DecodeFromBytes decodes the given bytes into the OSPF layer.
374 func (ospf *OSPFv3) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
375
376         if len(data) < 16 {
377                 return fmt.Errorf("Packet too smal for OSPF Version 3")
378         }
379
380         ospf.Version = uint8(data[0])
381         ospf.Type = OSPFType(data[1])
382         ospf.PacketLength = binary.BigEndian.Uint16(data[2:4])
383         ospf.RouterID = binary.BigEndian.Uint32(data[4:8])
384         ospf.AreaID = binary.BigEndian.Uint32(data[8:12])
385         ospf.Checksum = binary.BigEndian.Uint16(data[12:14])
386         ospf.Instance = uint8(data[14])
387         ospf.Reserved = uint8(data[15])
388
389         switch ospf.Type {
390         case OSPFHello:
391                 var neighbors []uint32
392                 for i := 36; uint16(i+4) <= ospf.PacketLength; i += 4 {
393                         neighbors = append(neighbors, binary.BigEndian.Uint32(data[i:i+4]))
394                 }
395                 ospf.Content = HelloPkg{
396                         InterfaceID:              binary.BigEndian.Uint32(data[16:20]),
397                         RtrPriority:              uint8(data[20]),
398                         Options:                  binary.BigEndian.Uint32(data[21:25]) >> 8,
399                         HelloInterval:            binary.BigEndian.Uint16(data[24:26]),
400                         RouterDeadInterval:       binary.BigEndian.Uint16(data[26:28]),
401                         DesignatedRouterID:       binary.BigEndian.Uint32(data[28:32]),
402                         BackupDesignatedRouterID: binary.BigEndian.Uint32(data[32:36]),
403                         NeighborID:               neighbors,
404                 }
405         case OSPFDatabaseDescription:
406                 var lsas []LSAheader
407                 for i := 28; uint16(i+20) <= ospf.PacketLength; i += 20 {
408                         lsa := LSAheader{
409                                 LSAge:       binary.BigEndian.Uint16(data[i : i+2]),
410                                 LSType:      binary.BigEndian.Uint16(data[i+2 : i+4]),
411                                 LinkStateID: binary.BigEndian.Uint32(data[i+4 : i+8]),
412                                 AdvRouter:   binary.BigEndian.Uint32(data[i+8 : i+12]),
413                                 LSSeqNumber: binary.BigEndian.Uint32(data[i+12 : i+16]),
414                                 LSChecksum:  binary.BigEndian.Uint16(data[i+16 : i+18]),
415                                 Length:      binary.BigEndian.Uint16(data[i+18 : i+20]),
416                         }
417                         lsas = append(lsas, lsa)
418                 }
419                 ospf.Content = DbDescPkg{
420                         Options:      binary.BigEndian.Uint32(data[16:20]) & 0x00FFFFFF,
421                         InterfaceMTU: binary.BigEndian.Uint16(data[20:22]),
422                         Flags:        binary.BigEndian.Uint16(data[22:24]),
423                         DDSeqNumber:  binary.BigEndian.Uint32(data[24:28]),
424                         LSAinfo:      lsas,
425                 }
426         case OSPFLinkStateRequest:
427                 var lsrs []LSReq
428                 for i := 16; uint16(i+12) <= ospf.PacketLength; i += 12 {
429                         lsr := LSReq{
430                                 LSType:    binary.BigEndian.Uint16(data[i+2 : i+4]),
431                                 LSID:      binary.BigEndian.Uint32(data[i+4 : i+8]),
432                                 AdvRouter: binary.BigEndian.Uint32(data[i+8 : i+12]),
433                         }
434                         lsrs = append(lsrs, lsr)
435                 }
436                 ospf.Content = lsrs
437         case OSPFLinkStateUpdate:
438                 num := binary.BigEndian.Uint32(data[16:20])
439                 lsas, err := getLSAs(num, data[20:])
440                 if err != nil {
441                         return fmt.Errorf("Cannot parse Link State Update packet: %v", err)
442                 }
443                 ospf.Content = LSUpdate{
444                         NumOfLSAs: num,
445                         LSAs:      lsas,
446                 }
447
448         case OSPFLinkStateAcknowledgment:
449                 var lsas []LSAheader
450                 for i := 16; uint16(i+20) <= ospf.PacketLength; i += 20 {
451                         lsa := LSAheader{
452                                 LSAge:       binary.BigEndian.Uint16(data[i : i+2]),
453                                 LSType:      binary.BigEndian.Uint16(data[i+2 : i+4]),
454                                 LinkStateID: binary.BigEndian.Uint32(data[i+4 : i+8]),
455                                 AdvRouter:   binary.BigEndian.Uint32(data[i+8 : i+12]),
456                                 LSSeqNumber: binary.BigEndian.Uint32(data[i+12 : i+16]),
457                                 LSChecksum:  binary.BigEndian.Uint16(data[i+16 : i+18]),
458                                 Length:      binary.BigEndian.Uint16(data[i+18 : i+20]),
459                         }
460                         lsas = append(lsas, lsa)
461                 }
462                 ospf.Content = lsas
463         default:
464         }
465
466         return nil
467 }
468
469 // LayerType returns LayerTypeOSPF
470 func (ospf *OSPFv2) LayerType() gopacket.LayerType {
471         return LayerTypeOSPF
472 }
473 func (ospf *OSPFv3) LayerType() gopacket.LayerType {
474         return LayerTypeOSPF
475 }
476
477 // NextLayerType returns the layer type contained by this DecodingLayer.
478 func (ospf *OSPFv2) NextLayerType() gopacket.LayerType {
479         return gopacket.LayerTypeZero
480 }
481 func (ospf *OSPFv3) NextLayerType() gopacket.LayerType {
482         return gopacket.LayerTypeZero
483 }
484
485 // CanDecode returns the set of layer types that this DecodingLayer can decode.
486 func (ospf *OSPFv2) CanDecode() gopacket.LayerClass {
487         return LayerTypeOSPF
488 }
489 func (ospf *OSPFv3) CanDecode() gopacket.LayerClass {
490         return LayerTypeOSPF
491 }
492
493 func decodeOSPF(data []byte, p gopacket.PacketBuilder) error {
494         if len(data) < 14 {
495                 return fmt.Errorf("Packet too smal for OSPF")
496         }
497
498         switch uint8(data[0]) {
499         case 2:
500                 ospf := &OSPFv2{}
501                 return decodingLayerDecoder(ospf, data, p)
502         case 3:
503                 ospf := &OSPFv3{}
504                 return decodingLayerDecoder(ospf, data, p)
505         default:
506         }
507
508         return fmt.Errorf("Unable to determine OSPF type.")
509 }