1// Copyright 2012 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
7package layers
8
9import (
10	"encoding/binary"
11	"fmt"
12	"github.com/google/gopacket"
13)
14
15type EAPCode uint8
16type EAPType uint8
17
18const (
19	EAPCodeRequest  EAPCode = 1
20	EAPCodeResponse EAPCode = 2
21	EAPCodeSuccess  EAPCode = 3
22	EAPCodeFailure  EAPCode = 4
23
24	// EAPTypeNone means that this EAP layer has no Type or TypeData.
25	// Success and Failure EAPs will have this set.
26	EAPTypeNone EAPType = 0
27
28	EAPTypeIdentity     EAPType = 1
29	EAPTypeNotification EAPType = 2
30	EAPTypeNACK         EAPType = 3
31	EAPTypeOTP          EAPType = 4
32	EAPTypeTokenCard    EAPType = 5
33)
34
35// EAP defines an Extensible Authentication Protocol (rfc 3748) layer.
36type EAP struct {
37	BaseLayer
38	Code     EAPCode
39	Id       uint8
40	Length   uint16
41	Type     EAPType
42	TypeData []byte
43}
44
45// LayerType returns LayerTypeEAP.
46func (e *EAP) LayerType() gopacket.LayerType { return LayerTypeEAP }
47
48// DecodeFromBytes decodes the given bytes into this layer.
49func (e *EAP) DecodeFromBytes(data []byte, df gopacket.DecodeFeedback) error {
50	e.Code = EAPCode(data[0])
51	e.Id = data[1]
52	e.Length = binary.BigEndian.Uint16(data[2:4])
53	switch {
54	case e.Length > 4:
55		e.Type = EAPType(data[4])
56		e.TypeData = data[5:]
57	case e.Length == 4:
58		e.Type = 0
59		e.TypeData = nil
60	default:
61		return fmt.Errorf("invalid EAP length %d", e.Length)
62	}
63	e.BaseLayer.Contents = data[:e.Length]
64	e.BaseLayer.Payload = data[e.Length:] // Should be 0 bytes
65	return nil
66}
67
68// SerializeTo writes the serialized form of this layer into the
69// SerializationBuffer, implementing gopacket.SerializableLayer.
70// See the docs for gopacket.SerializableLayer for more info.
71func (e *EAP) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
72	if opts.FixLengths {
73		e.Length = uint16(len(e.TypeData) + 1)
74	}
75	size := len(e.TypeData) + 4
76	if size > 4 {
77		size++
78	}
79	bytes, err := b.PrependBytes(size)
80	if err != nil {
81		return err
82	}
83	bytes[0] = byte(e.Code)
84	bytes[1] = e.Id
85	binary.BigEndian.PutUint16(bytes[2:], e.Length)
86	if size > 4 {
87		bytes[4] = byte(e.Type)
88		copy(bytes[5:], e.TypeData)
89	}
90	return nil
91}
92
93// CanDecode returns the set of layer types that this DecodingLayer can decode.
94func (e *EAP) CanDecode() gopacket.LayerClass {
95	return LayerTypeEAP
96}
97
98// NextLayerType returns the layer type contained by this DecodingLayer.
99func (e *EAP) NextLayerType() gopacket.LayerType {
100	return gopacket.LayerTypeZero
101}
102
103func decodeEAP(data []byte, p gopacket.PacketBuilder) error {
104	e := &EAP{}
105	return decodingLayerDecoder(e, data, p)
106}
107