diff options
author | Chris Gorham <gorhamc90@gmail.com> | 2018-12-12 07:17:09 -0700 |
---|---|---|
committer | Pablo Mazzini <pmazzini@gmail.com> | 2018-12-12 14:17:09 +0000 |
commit | 2b569280e441c779406c8b2aaa1283ca5ce0f15b (patch) | |
tree | 958baf282cbdbce007a2c566dfdec53cb2246c91 /dhcpv6/ztpv6/parse_remote_id.go | |
parent | 94fe644699296ec03ad8eadfed31289b1098c5a0 (diff) |
[dhcpv6/ztpv6] Adding Parsing Vendor Opts and Parsing Remote Id Opts lib for ztpv6 (#208)
Diffstat (limited to 'dhcpv6/ztpv6/parse_remote_id.go')
-rw-r--r-- | dhcpv6/ztpv6/parse_remote_id.go | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/dhcpv6/ztpv6/parse_remote_id.go b/dhcpv6/ztpv6/parse_remote_id.go new file mode 100644 index 0000000..5991e96 --- /dev/null +++ b/dhcpv6/ztpv6/parse_remote_id.go @@ -0,0 +1,84 @@ +package ztpv6 + +import ( + "errors" + "fmt" + "regexp" + + "github.com/insomniacslk/dhcp/dhcpv6" +) + +var ( + // Arista Port, Vlan Pattern + aristaPVPattern = regexp.MustCompile("Ethernet(?P<port>[0-9]+):(?P<vlan>[0-9]+)") + // Arista Slot, Mod, Port Pattern + aristaSMPPattern = regexp.MustCompile("Ethernet(?P<slot>[0-9]+)/(?P<module>[0-9]+)/(?P<port>[0-9]+)") +) + +// CircuitID represents the structure of network vendor interface formats +type CircuitID struct { + Slot string + Module string + Port string + SubPort string + Vlan string +} + +// ParseRemoteId will parse the RemoteId Option data for Vendor Specific data +func ParseRemoteId(packet dhcpv6.DHCPv6) (*CircuitID, error) { + // Need to decapsulate the packet after multiple relays in order to reach RemoteId data + inner, err := dhcpv6.DecapsulateRelayIndex(packet, -1) + if err != nil { + return nil, fmt.Errorf("failed to decapsulate relay index: %v", err) + } + + if rid := inner.GetOneOption(dhcpv6.OptionRemoteID); rid != nil { + remoteID := string(rid.(*dhcpv6.OptRemoteId).RemoteID()) + circ, err := matchCircuitId(remoteID) + if err != nil { + return nil, err + } + return circ, nil + } + return nil, errors.New("failed to parse RemoteID option data") +} + +func matchCircuitId(remoteID string) (*CircuitID, error) { + var names, matches []string + + switch { + case aristaPVPattern.MatchString(remoteID): + matches = aristaPVPattern.FindStringSubmatch(remoteID) + names = aristaPVPattern.SubexpNames() + case aristaSMPPattern.MatchString(remoteID): + matches = aristaSMPPattern.FindStringSubmatch(remoteID) + names = aristaSMPPattern.SubexpNames() + } + + if len(matches) == 0 { + return nil, fmt.Errorf("no circuitId regex matches for %v", remoteID) + } + + var circuit CircuitID + for i, match := range matches { + switch names[i] { + case "port": + circuit.Port = match + case "slot": + circuit.Slot = match + case "module": + circuit.Module = match + case "subport": + circuit.SubPort = match + case "vlan": + circuit.Vlan = match + } + } + + return &circuit, nil +} + +// FormatCircuitID is the CircuitID format we send in our Bootfile URL for ZTP devices +func (c *CircuitID) FormatCircuitID() string { + return fmt.Sprintf("%v,%v,%v,%v,%v", c.Slot, c.Module, c.Port, c.SubPort, c.Vlan) +} |