//go:build linux
// +build linux

// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"). You may
// not use this file except in compliance with the License. A copy of the
// License is located at
//
//	http://aws.amazon.com/apache2.0/
//
// or in the "license" file accompanying this file. This file is distributed
// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
// express or implied. See the License for the specific language governing
// permissions and limitations under the License.

package ecscni

import cniTypes "github.com/containernetworking/cni/pkg/types"

const (
	// defaultVethName is the name of veth pair name in the container namespace
	defaultVethName = "ecs-eth0"
	// defaultENIName is the name of eni interface name in the container namespace
	defaultENIName = "eth0"
	// defaultBridgeName is the default name of bridge created for container to
	// communicate with ecs-agent
	defaultBridgeName = "ecs-bridge"
	// defaultAppMeshIfName is the default name of app mesh to setup iptable rules
	// for app mesh container. IfName is mandatory field to invoke CNI plugin.
	defaultAppMeshIfName = "aws-appmesh"
	// defaultServiceConnectIfName is the default ifname used for invoking ServiceConnect CNI plugin.
	// Even though the actual SC netns configuration does not require IfName, we still need to pass in a placeholder
	// value because IfName is a mandatory field to invoke any CNI plugin.
	// Additionally, the API spec requires that ifName length to be <= 15 chars.
	defaultServiceConnectIfName = "ecs-sc"
	// ECSIPAMPluginName is the binary of the ipam plugin
	ECSIPAMPluginName = "ecs-ipam"
	// ECSBridgePluginName is the binary of the bridge plugin
	ECSBridgePluginName = "ecs-bridge"
	// ECSAppMeshPluginName is the binary of aws-appmesh plugin
	ECSAppMeshPluginName = "aws-appmesh"
	// ECSBranchENIPluginName is the binary of the branch-eni plugin
	ECSBranchENIPluginName = "vpc-branch-eni"
	// ECSServiceConnectPluginName is the binary of the service connect plugin
	ECSServiceConnectPluginName = "ecs-serviceconnect"
	// NetnsFormat is used to construct the path to cotainer network namespace
	NetnsFormat = "/host/proc/%s/ns/net"
	// Starting with CNI plugin v0.8.0 (this PR https://github.com/containernetworking/cni/pull/698)
	// NetworkName has to be non-empty field for network config.
	// We do not actually make use of the field, hence passing in a placeholder string to fulfill the API spec
	defaultNetworkName = "network-name"
)

// IPAMNetworkConfig is the config format accepted by the plugin
type IPAMNetworkConfig struct {
	Name       string     `json:"name,omitempty"`
	Type       string     `json:"type,omitempty"`
	CNIVersion string     `json:"cniVersion,omitempty"`
	IPAM       IPAMConfig `json:"ipam"`
}

// IPAMConfig contains all the information needed to invoke the ipam plugin
type IPAMConfig struct {
	// Type is the cni plugin name
	Type string `json:"type,omitempty"`
	// ID is the information stored in the ipam along with ip as key-value pair
	ID string `json:"id,omitempty"`
	// CNIVersion is the cni spec version to use
	CNIVersion string `json:"cniVersion,omitempty"`
	// IPV4Subnet is the ip address range managed by ipam
	IPV4Subnet string `json:"ipv4-subnet,omitempty"`
	// IPV4Address is the ip address to deal with(assign or release) in ipam
	IPV4Address *cniTypes.IPNet `json:"ipv4-address,omitempty"`
	// IPV4Gateway is the gateway returned by ipam, defalut the '.1' in the subnet
	IPV4Gateway string `json:"ipv4-gateway,omitempty"`
	// IPV4Routes is the route to added in the containerr namespace
	IPV4Routes []*cniTypes.Route `json:"ipv4-routes,omitempty"`
}

// BridgeConfig contains all the information needed to invoke the bridge plugin
type BridgeConfig struct {
	// Type is the cni plugin name
	Type string `json:"type,omitempty"`
	// CNIVersion is the cni spec version to use
	CNIVersion string `json:"cniVersion,omitempty"`
	// BridgeName is the name of bridge
	BridgeName string `json:"bridge"`
	// IsGw indicates whether the bridge act as a gateway, it determines whether
	// an ip address needs to assign to the bridge
	IsGW bool `json:"isGateway"`
	// IsDefaultGW indicates whether the bridge is the gateway of the container
	IsDefaultGW bool `json:"isDefaultGateway"`
	// ForceAddress indicates whether a new ip should be assigned if the bridge
	// has already a different ip
	ForceAddress bool `json:"forceAddress"`
	// IPMasq indicates whether to setup the IP Masquerade for traffic originating
	// from this network
	IPMasq bool `json:"ipMasq"`
	// MTU sets MTU of the bridge interface
	MTU int `json:"mtu"`
	// HairpinMode sets the hairpin mode of interface on the bridge
	HairpinMode bool `json:"hairpinMode"`
	// IPAM is the configuration to acquire ip/route from ipam plugin
	IPAM IPAMConfig `json:"ipam,omitempty"`
}

// AppMeshConfig contains all the information needed to invoke the app mesh plugin
type AppMeshConfig struct {
	// Type is the cni plugin name
	Type string `json:"type,omitempty"`
	// CNIVersion is the cni spec version to use
	CNIVersion string `json:"cniVersion,omitempty"`
	// IgnoredUID specifies egress traffic from the processes owned by the UID will be ignored
	IgnoredUID string `json:"ignoredUID,omitempty"`
	// IgnoredGID specifies egress traffic from the processes owned by the GID will be ignored
	IgnoredGID string `json:"ignoredGID,omitempty"`
	// ProxyIngressPort is the ingress port number that proxy is listening on
	ProxyIngressPort string `json:"proxyIngressPort"`
	// ProxyEgressPort is the egress port number that proxy is listening on
	ProxyEgressPort string `json:"proxyEgressPort"`
	// AppPorts specifies port numbers that application is listening on
	AppPorts []string `json:"appPorts"`
	// EgressIgnoredPorts is the list of ports for which egress traffic will be ignored
	EgressIgnoredPorts []string `json:"egressIgnoredPorts,omitempty"`
	// EgressIgnoredIPs is the list of IPs for which egress traffic will be ignored
	EgressIgnoredIPs []string `json:"egressIgnoredIPs,omitempty"`
}

// BranchENIConfig contains all the information needed to invoke the vpc-branch-eni plugin
type BranchENIConfig struct {
	// CNIVersion is the CNI spec version to use
	CNIVersion string `json:"cniVersion,omitempty"`
	// Name is the CNI network name
	Name string `json:"name,omitempty"`
	// Type is the CNI plugin name
	Type string `json:"type,omitempty"`

	// TrunkMACAddress is the MAC address of the trunk ENI
	TrunkMACAddress string `json:"trunkMACAddress,omitempty"`
	// BranchVlanID is the VLAN ID of the branch ENI
	BranchVlanID string `json:"branchVlanID,omitempty"`
	// BranchMacAddress is the MAC address of the branch ENI
	BranchMACAddress string `json:"branchMACAddress"`
	// IPAddresses contains the IP addresses of the branch ENI.
	IPAddresses []string `json:"ipAddresses"`
	// GatewayIPAddresses contains the IP addresses of the default gateway in the subnet.
	GatewayIPAddresses []string `json:"gatewayIPAddresses"`
	// BlockInstanceMetdata specifies if InstanceMetadata endpoint should be blocked.
	BlockInstanceMetadata bool `json:"blockInstanceMetadata"`
	// InterfaceType is the type of the interface to connect the branch ENI to
	InterfaceType string `json:"interfaceType,omitempty"`
}

type ServiceConnectConfig struct {
	// CNIVersion is the CNI spec version to use
	CNIVersion string `json:"cniVersion,omitempty"`
	// Name is the CNI network name
	Name string `json:"name,omitempty"`
	// Type is the CNI plugin name
	Type string `json:"type,omitempty"`

	// IngressConfig (optional) specifies the netfilter rules to be set for incoming requests.
	IngressConfig []IngressConfigJSONEntry `json:"ingressConfig,omitempty"`
	// EgressConfig (optional) specifies the netfilter rules to be set for outgoing requests.
	EgressConfig *EgressConfigJSON `json:"egressConfig,omitempty"`
	// EnableIPv4 (optional) specifies whether to set the rules in IPV4 table. Default value is false.
	EnableIPv4 bool `json:"enableIPv4,omitempty"`
	// EnableIPv6 (optional) specifies whether to set the rules in IPV6 table. Default value is false.
	EnableIPv6 bool `json:"enableIPv6,omitempty"`
}

// IngressConfig defines the ingress network config in JSON format for the ecs-serviceconnect CNI plugin.
type IngressConfigJSONEntry struct {
	ListenerPort  uint16 `json:"listenerPort"`
	InterceptPort uint16 `json:"interceptPort,omitempty"`
}

// RedirectMode defines the type of redirection of traffic to be used.
type RedirectMode string

const (
	NAT    RedirectMode = "nat"
	TPROXY RedirectMode = "tproxy"
)

// EgressConfig defines the egress network config in JSON format for the ecs-serviceconnect CNI plugin.
type EgressConfigJSON struct {
	ListenerPort uint16          `json:"listenerPort"`
	RedirectIP   *RedirectIPJson `json:"redirectIP"`
	RedirectMode string          `json:"redirectMode"`
	VIP          VIPConfigJSON   `json:"vip"`
}

// RedirectIPJson defines the IP to be redirected in JSON format for the ecs-serviceconnect CNI plugin.
type RedirectIPJson struct {
	IPv4 string `json:"ipv4,omitempty"`
	IPv6 string `json:"ipv6,omitempty"`
}

// VIPConfigJSON defines the EgressVIP network config in JSON format for the ecs-serviceconnect CNI plugin.
type VIPConfigJSON struct {
	IPv4CIDR string `json:"ipv4Cidr,omitempty"`
	IPv6CIDR string `json:"ipv6Cidr,omitempty"`
}
