1// Azure's application extension to TLVs for Private Link Services
2// https://docs.microsoft.com/en-us/azure/private-link/private-link-service-overview#getting-connection-information-using-tcp-proxy-v2
3
4package tlvparse
5
6import (
7	"encoding/binary"
8
9	"github.com/pires/go-proxyproto"
10)
11
12const (
13	// Azure's extension
14	PP2_TYPE_AZURE                           = 0xEE
15	PP2_SUBTYPE_AZURE_PRIVATEENDPOINT_LINKID = 0x01
16)
17
18// IsAzurePrivateEndpointLinkID returns true if given TLV matches Azure Private Endpoint LinkID format
19func isAzurePrivateEndpointLinkID(tlv proxyproto.TLV) bool {
20	return tlv.Type == PP2_TYPE_AZURE && len(tlv.Value) == 5 && tlv.Value[0] == PP2_SUBTYPE_AZURE_PRIVATEENDPOINT_LINKID
21}
22
23// AzurePrivateEndpointLinkID returns linkID if given TLV matches Azure Private Endpoint LinkID format
24//
25// Format description:
26//	Field	Length (Octets)	Description
27//	Type	1	PP2_TYPE_AZURE (0xEE)
28//	Length	2	Length of value
29//	Value	1	PP2_SUBTYPE_AZURE_PRIVATEENDPOINT_LINKID (0x01)
30//			4	UINT32 (4 bytes) representing the LINKID of the private endpoint. Encoded in little endian format.
31func azurePrivateEndpointLinkID(tlv proxyproto.TLV) (uint32, error) {
32	if !isAzurePrivateEndpointLinkID(tlv) {
33		return 0, proxyproto.ErrIncompatibleTLV
34	}
35	linkID := binary.LittleEndian.Uint32(tlv.Value[1:])
36	return linkID, nil
37}
38
39// FindAzurePrivateEndpointLinkID returns the first Azure Private Endpoint LinkID if it exists in the TLV collection
40// and a boolean indicating if it was found.
41func FindAzurePrivateEndpointLinkID(tlvs []proxyproto.TLV) (uint32, bool) {
42	for _, tlv := range tlvs {
43		if linkID, err := azurePrivateEndpointLinkID(tlv); err == nil {
44			return linkID, true
45		}
46	}
47	return 0, false
48}
49