diff options
-rw-r--r-- | dhcpv4/ztpv4/ztp.go | 26 | ||||
-rw-r--r-- | dhcpv4/ztpv4/ztp_test.go | 8 | ||||
-rw-r--r-- | iana/entid.go | 6 |
3 files changed, 35 insertions, 5 deletions
diff --git a/dhcpv4/ztpv4/ztp.go b/dhcpv4/ztpv4/ztp.go index ef8e13d..c57d958 100644 --- a/dhcpv4/ztpv4/ztp.go +++ b/dhcpv4/ztpv4/ztp.go @@ -3,6 +3,8 @@ package ztpv4 import ( "bytes" "errors" + "fmt" + "strconv" "strings" "github.com/insomniacslk/dhcp/dhcpv4" @@ -16,6 +18,7 @@ type VendorData struct { } var errVendorOptionMalformed = errors.New("malformed vendor option") +var errClientIDOptionMissing = errors.New("client identifier option is missing") func parseClassIdentifier(packet *dhcpv4.DHCPv4) (*VendorData, error) { vd := &VendorData{} @@ -66,6 +69,25 @@ func parseClassIdentifier(packet *dhcpv4.DHCPv4) (*VendorData, error) { vd.VendorName = p[0] return vd, nil + // For Ciena the class identifier (opt 60) is written in the following format: + // {vendor iana code}-{product}-{type} + // For Ciena the iana code is 1271 + // The product type is a number that maps to a Ciena product + // The type is used to identified different subtype of the product. + // An example can be ‘1271-23422Z11-123’. + case strings.HasPrefix(vc, strconv.Itoa(int(iana.EntIDCienaCorporation))): + v := strings.Split(vc, "-") + if len(v) != 3 { + return nil, fmt.Errorf("%w got '%s'", errVendorOptionMalformed, vc) + } + vd.VendorName = iana.EntIDCienaCorporation.String() + vd.Model = v[1] + "-" + v[2] + vd.Serial = dhcpv4.GetString(dhcpv4.OptionClientIdentifier, packet.Options) + if len(vd.Serial) == 0 { + return nil, errClientIDOptionMissing + } + return vd, nil + // Cisco Firepower FPR4100/9300 models use Opt 60 for model info // and Opt 61 contains the serial number case vc == "FPR4100" || vc == "FPR9300": @@ -73,12 +95,10 @@ func parseClassIdentifier(packet *dhcpv4.DHCPv4) (*VendorData, error) { vd.Model = vc vd.Serial = dhcpv4.GetString(dhcpv4.OptionClientIdentifier, packet.Options) if len(vd.Serial) == 0 { - return nil, errors.New("client identifier option is missing") + return nil, errClientIDOptionMissing } return vd, nil - } - return nil, nil } diff --git a/dhcpv4/ztpv4/ztp_test.go b/dhcpv4/ztpv4/ztp_test.go index 189ed3b..bee2230 100644 --- a/dhcpv4/ztpv4/ztp_test.go +++ b/dhcpv4/ztpv4/ztp_test.go @@ -53,6 +53,14 @@ func TestParseClassIdentifier(t *testing.T) { want: &VendorData{VendorName: "Cisco Systems", Model: "FPR4100", Serial: "JMX2525X0BW"}, }, {name: "ciscoNoSerial", vc: "FPR4100", fail: true}, + { + name: "ciena", + vc: "1271-00011E00-032", + ci: []byte("JUSTASN"), + want: &VendorData{VendorName: "Ciena Corporation", Model: "00011E00-032", Serial: "JUSTASN"}, + }, + {name: "cienaInvalidVendorClass", vc: "127100011E00032", fail: true}, + {name: "cienaNoSerial", vc: "1271-00011E00-032", fail: true}, } for _, tc := range tt { diff --git a/iana/entid.go b/iana/entid.go index df2ca13..dbcb51e 100644 --- a/iana/entid.go +++ b/iana/entid.go @@ -5,11 +5,13 @@ type EntID int // See https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers for values const ( - EntIDCiscoSystems EntID = 9 + EntIDCiscoSystems EntID = 9 + EntIDCienaCorporation EntID = 1271 ) var entIDToStringMap = map[EntID]string{ - EntIDCiscoSystems: "Cisco Systems", + EntIDCiscoSystems: "Cisco Systems", + EntIDCienaCorporation: "Ciena Corporation", } // String returns the vendor name for a given Enterprise ID |