// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package main

import (
	"context"
	"fmt"
	"log"
	"sort"
	"strings"
	"sync"

	"netstack/dns"
	"netstack/fidlconv"
	"netstack/filter"
	"netstack/link/bridge"
	"netstack/link/eth"
	"netstack/link/stats"
	"netstack/netiface"
	"netstack/util"

	"fidl/fuchsia/devicesettings"
	"fidl/fuchsia/hardware/ethernet"
	"fidl/fuchsia/net"
	"fidl/fuchsia/netstack"

	"github.com/google/netstack/dhcp"
	"github.com/google/netstack/tcpip"
	"github.com/google/netstack/tcpip/header"
	"github.com/google/netstack/tcpip/link/loopback"
	"github.com/google/netstack/tcpip/link/sniffer"
	"github.com/google/netstack/tcpip/network/arp"
	"github.com/google/netstack/tcpip/network/ipv4"
	"github.com/google/netstack/tcpip/network/ipv6"
	"github.com/google/netstack/tcpip/stack"
)

const (
	deviceSettingsManagerNodenameKey = "DeviceName"
	defaultNodename                  = "fuchsia-unset-device-name"

	ipv4Loopback tcpip.Address = "\x7f\x00\x00\x01"
	ipv6Loopback tcpip.Address = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
)

// A Netstack tracks all of the running state of the network stack.
type Netstack struct {
	arena *eth.Arena

	deviceSettings *devicesettings.DeviceSettingsManagerInterface
	dnsClient      *dns.Client

	mu struct {
		sync.Mutex
		stack              *stack.Stack
		transactionRequest *netstack.RouteTableTransactionInterfaceRequest
	}
	nodename string
	ifStates map[tcpip.NICID]*ifState

	countNIC tcpip.NICID

	filter *filter.Filter
}

type dhcpState struct {
	client  *dhcp.Client
	ctx     context.Context
	cancel  context.CancelFunc
	enabled bool
}

// Each ifState tracks the state of a network interface.
type ifState struct {
	ns     *Netstack
	ctx    context.Context
	cancel context.CancelFunc
	eth    eth.Controller
	state  eth.State
	dhcpState

	// guarded by ns.mu
	// NIC is defined in //garnet/go/src/netstack/netiface/netiface.go
	// TODO(porce): Consider replacement with //third_party/netstack/tcpip/stack/stack.go
	nic *netiface.NIC

	// The "outermost" LinkEndpoint implementation (the composition of link
	// endpoint functionality happens by wrapping other link endpoints).
	endpoint stack.LinkEndpoint

	// statsEP and bridgeable are wrapper LinkEndpoint implementations that need
	// to be accessed by their concrete type.
	statsEP    *stats.StatsEndpoint
	bridgeable *bridge.BridgeableEndpoint
}

func defaultRouteTable(nicid tcpip.NICID, gateway tcpip.Address) []tcpip.Route {
	return []tcpip.Route{
		{
			Destination: tcpip.Address(strings.Repeat("\x00", 4)),
			Mask:        tcpip.AddressMask(strings.Repeat("\x00", 4)),
			Gateway:     gateway,
			NIC:         nicid,
		},
		{
			Destination: tcpip.Address(strings.Repeat("\x00", 16)),
			Mask:        tcpip.AddressMask(strings.Repeat("\x00", 16)),
			NIC:         nicid,
		},
	}
}

func subnetRoute(addr tcpip.Address, mask tcpip.AddressMask, nicid tcpip.NICID) tcpip.Route {
	return tcpip.Route{
		Destination: util.ApplyMask(addr, mask),
		Mask:        tcpip.AddressMask(mask),
		Gateway:     tcpip.Address(""),
		NIC:         nicid,
	}
}

func (ns *Netstack) removeInterfaceAddress(nic tcpip.NICID, protocol tcpip.NetworkProtocolNumber, addr tcpip.Address, prefixLen uint8) error {
	subnet, err := toSubnet(addr, prefixLen)
	if err != nil {
		return fmt.Errorf("error parsing subnet format for NIC ID %d: %s", nic, err)
	}

	if hasSubnet, err := ns.mu.stack.ContainsSubnet(nic, subnet); err != nil {
		return fmt.Errorf("error finding subnet %+v for NIC ID %d: %s", subnet, nic, err)
	} else if hasSubnet {
		if err := ns.mu.stack.RemoveSubnet(nic, subnet); err != nil {
			return fmt.Errorf("error removing subnet %+v from NIC ID %d: %s", subnet, nic, err)
		}
	} else {
		return fmt.Errorf("no such subnet %+v for NIC ID %d", subnet, nic)
	}

	if err := ns.mu.stack.RemoveAddress(nic, addr); err != nil {
		return fmt.Errorf("error removing address %s from NIC ID %d: %s", addr, nic, err)
	}

	ifs, ok := ns.ifStates[nic]
	if !ok {
		panic(fmt.Sprintf("Interface state table out of sync: NIC [%d] known to third_party/netstack not found in garnet/netstack", nic))
	}

	{
		addr, subnet, err := ns.mu.stack.GetMainNICAddress(nic, protocol)
		if err != nil {
			return fmt.Errorf("error querying NIC ID %d, error: %s", nic, err)
		}
		netmask := subnet.Mask()
		if netmask == "" {
			addressSize := len(addr) * 8
			netmask = util.CIDRMask(addressSize, addressSize)
		}
		ifs.staticAddressChanged(addr, netmask)
	}

	return nil
}

func toSubnet(address tcpip.Address, prefixLen uint8) (tcpip.Subnet, error) {
	m := util.CIDRMask(int(prefixLen), int(len(address)*8))
	return tcpip.NewSubnet(util.ApplyMask(address, m), m)
}

func (ns *Netstack) setInterfaceAddress(nic tcpip.NICID, protocol tcpip.NetworkProtocolNumber, addr tcpip.Address, prefixLen uint8) error {
	subnet, err := toSubnet(addr, prefixLen)
	if err != nil {
		return fmt.Errorf("error parsing subnet format for NIC ID %d: %s", nic, err)
	}

	if err := ns.mu.stack.AddAddress(nic, protocol, addr); err != nil {
		return fmt.Errorf("error adding address %s to NIC ID %d: %s", addr, nic, err)
	}

	if err := ns.mu.stack.AddSubnet(nic, protocol, subnet); err != nil {
		return fmt.Errorf("error adding subnet %+v to NIC ID %d: %s", subnet, nic, err)
	}

	ifs, ok := ns.ifStates[nic]
	if !ok {
		panic(fmt.Sprintf("Interface state table out of sync: NIC [%d] known to third_party/netstack not found in garnet/netstack", nic))
	}

	ifs.staticAddressChanged(addr, subnet.Mask())
	return nil
}

func (ifs *ifState) staticAddressChanged(newAddr tcpip.Address, netmask tcpip.AddressMask) {
	ifs.ns.mu.Lock()
	ifs.nic.Addr = newAddr
	ifs.nic.Netmask = netmask
	ifs.ns.mu.Unlock()

	OnInterfacesChanged()
}

func (ifs *ifState) dhcpAcquired(oldAddr, newAddr tcpip.Address, config dhcp.Config) {
	if oldAddr != "" && oldAddr != newAddr {
		log.Printf("NIC %s: DHCP IP %s expired", ifs.nic.Name, oldAddr)
	}
	if config.Error != nil {
		log.Printf("%v", config.Error)
		return
	}
	if newAddr == "" {
		log.Printf("NIC %s: DHCP could not acquire address", ifs.nic.Name)
		return
	}
	log.Printf("NIC %s: DHCP acquired IP %s for %s", ifs.nic.Name, newAddr, config.LeaseLength)
	log.Printf("NIC %s: Adding DNS servers: %v", ifs.nic.Name, config.DNS)

	// Update default route with new gateway.
	ifs.ns.mu.Lock()
	ifs.nic.Routes = defaultRouteTable(ifs.nic.ID, config.Gateway)
	ifs.nic.Routes = append(ifs.nic.Routes, subnetRoute(newAddr, config.SubnetMask, ifs.nic.ID))
	ifs.nic.Netmask = config.SubnetMask
	ifs.nic.Addr = newAddr
	ifs.nic.DNSServers = config.DNS
	ifs.ns.mu.Unlock()

	ifs.ns.mu.stack.SetRouteTable(ifs.ns.flattenRouteTables())
	ifs.ns.dnsClient.SetRuntimeServers(ifs.ns.getRuntimeDNSServerRefs())

	OnInterfacesChanged()
}

func (ifs *ifState) setDHCPStatus(enabled bool) {
	ifs.ns.mu.Lock()
	defer ifs.ns.mu.Unlock()
	d := &ifs.dhcpState
	if enabled == d.enabled {
		return
	}
	if enabled {
		d.ctx, d.cancel = context.WithCancel(ifs.ctx)
		if c := d.client; c != nil {
			c.Run(d.ctx)
		} else {
			panic(fmt.Sprintf("nil DHCP client on interface %s", ifs.nic.Name))
		}
	} else if d.cancel != nil {
		d.cancel()
	}
	d.enabled = enabled
}

func (ifs *ifState) stateChange(s eth.State) {
	switch s {
	case eth.StateClosed:
		ifs.ns.mu.Lock()
		delete(ifs.ns.ifStates, ifs.nic.ID)
		ifs.ns.mu.Unlock()
		fallthrough
	case eth.StateDown:
		log.Printf("NIC %s: stopped", ifs.nic.Name)
		if ifs.cancel != nil {
			ifs.cancel()
		}
		if ifs.dhcpState.cancel != nil {
			// TODO: consider remembering DHCP status
			ifs.setDHCPStatus(false)
		}

		// TODO(crawshaw): more cleanup to be done here:
		// 	- remove link endpoint
		//	- reclaim NICID?

		ifs.ns.mu.Lock()
		ifs.nic.Routes = nil
		ifs.nic.Netmask = "\xff\xff\xff\xff"
		ifs.nic.Addr = "\x00\x00\x00\x00"
		ifs.nic.DNSServers = nil
		ifs.ns.mu.Unlock()

		ifs.ns.mu.stack.SetRouteTable(ifs.ns.flattenRouteTables())
		ifs.ns.dnsClient.SetRuntimeServers(ifs.ns.getRuntimeDNSServerRefs())
	case eth.StateStarted:
		// Only call `restarted` if we are not in the initial state (which means we're still starting).
		if ifs.state != eth.StateUnknown {
			log.Printf("NIC %s: restarting", ifs.nic.Name)
			ifs.ns.mu.Lock()
			ifs.ctx, ifs.cancel = context.WithCancel(context.Background())
			ifs.nic.Routes = defaultRouteTable(ifs.nic.ID, "")
			ifs.ns.mu.Unlock()

			ifs.ns.mu.stack.SetRouteTable(ifs.ns.flattenRouteTables())
			ifs.setDHCPStatus(true)
		}
	}
	ifs.state = s
	// Note: This will fire again once DHCP succeeds.
	OnInterfacesChanged()
}

func (ns *Netstack) flattenRouteTables() []tcpip.Route {
	ns.mu.Lock()
	defer ns.mu.Unlock()

	routes := make([]tcpip.Route, 0)
	nics := make(map[tcpip.NICID]*netiface.NIC)
	for _, ifs := range ns.ifStates {
		routes = append(routes, ifs.nic.Routes...)
		nics[ifs.nic.ID] = ifs.nic
	}
	sort.Slice(routes, func(i, j int) bool {
		return netiface.Less(&routes[i], &routes[j], nics)
	})
	if debug {
		for i, ifs := range ns.ifStates {
			log.Printf("[%v] nicid: %v, addr: %v, routes: %v",
				i, ifs.nic.ID, ifs.nic.Addr, ifs.nic.Routes)
		}
	}

	return routes
}

// Return a slice of references to each NIC's DNS servers.
// The caller takes ownership of the returned slice.
func (ns *Netstack) getRuntimeDNSServerRefs() []*[]tcpip.Address {
	ns.mu.Lock()
	defer ns.mu.Unlock()

	refs := make([]*[]tcpip.Address, 0, len(ns.ifStates))
	for _, ifs := range ns.ifStates {
		refs = append(refs, &ifs.nic.DNSServers)
	}
	return refs
}

func (ns *Netstack) getDNSServers() []tcpip.Address {
	ns.mu.Lock()
	defer ns.mu.Unlock()

	defaultServers := ns.dnsClient.GetDefaultServers()
	uniqServers := make(map[tcpip.Address]struct{})
	for _, ifs := range ns.ifStates {
		for _, server := range ifs.nic.DNSServers {
			uniqServers[server] = struct{}{}
		}
	}

	out := make([]tcpip.Address, 0, len(defaultServers)+len(uniqServers))
	out = append(out, defaultServers...)
	for server := range uniqServers {
		out = append(out, server)
	}
	return out
}

func (ns *Netstack) getNodeName() string {
	nodename, status, err := ns.deviceSettings.GetString(deviceSettingsManagerNodenameKey)
	if err != nil {
		log.Printf("getNodeName: error accessing device settings: %s", err)
		return defaultNodename
	}
	if status != devicesettings.StatusOk {
		var reportStatus string
		switch status {
		case devicesettings.StatusErrNotSet:
			reportStatus = "key not set"
		case devicesettings.StatusErrInvalidSetting:
			reportStatus = "invalid setting"
		case devicesettings.StatusErrRead:
			reportStatus = "error reading key"
		case devicesettings.StatusErrIncorrectType:
			reportStatus = "value type was incorrect"
		case devicesettings.StatusErrUnknown:
			reportStatus = "unknown"
		default:
			reportStatus = fmt.Sprintf("unknown status code: %d", status)
		}
		if debug {
			log.Printf("getNodeName: device settings error: %s", reportStatus)
		}
		return defaultNodename
	}
	return nodename
}

// TODO(tamird): refactor to use addEndpoint.
func (ns *Netstack) addLoopback() error {
	const nicid = 1
	ctx, cancel := context.WithCancel(context.Background())
	nic := &netiface.NIC{
		ID:       nicid,
		Addr:     ipv4Loopback,
		Netmask:  tcpip.AddressMask(strings.Repeat("\xff", len(ipv4Loopback))),
		Features: ethernet.InfoFeatureLoopback,
		Routes: []tcpip.Route{
			{
				Destination: ipv4Loopback,
				Mask:        tcpip.AddressMask(strings.Repeat("\xff", 4)),
				NIC:         nicid,
			},
			{
				Destination: ipv6Loopback,
				Mask:        tcpip.AddressMask(strings.Repeat("\xff", 16)),
				NIC:         nicid,
			},
		},
	}

	nic.Name = "lo"

	ifs := &ifState{
		ns:     ns,
		ctx:    ctx,
		cancel: cancel,
		nic:    nic,
		state:  eth.StateStarted,
	}

	ns.mu.Lock()
	if len(ns.ifStates) > 0 {
		ns.mu.Unlock()
		return fmt.Errorf("loopback: other interfaces already registered")
	}
	ns.ifStates[nicid] = ifs
	ns.countNIC++
	ns.mu.Unlock()

	linkID := loopback.New()
	if debug {
		linkID = sniffer.New(linkID)
	}
	linkID, ifs.statsEP = stats.NewEndpoint(linkID)
	ifs.statsEP.Nic = ifs.nic

	if err := ns.mu.stack.CreateNIC(nicid, linkID); err != nil {
		return fmt.Errorf("loopback: could not create interface: %v", err)
	}
	if err := ns.mu.stack.AddAddress(nicid, ipv4.ProtocolNumber, ipv4Loopback); err != nil {
		return fmt.Errorf("loopback: adding ipv4 address failed: %v", err)
	}
	if err := ns.mu.stack.AddAddress(nicid, ipv6.ProtocolNumber, ipv6Loopback); err != nil {
		return fmt.Errorf("loopback: adding ipv6 address failed: %v", err)
	}

	ns.mu.stack.SetRouteTable(ns.flattenRouteTables())

	return nil
}

func (ns *Netstack) Bridge(nics []tcpip.NICID) (*ifState, error) {
	links := make([]*bridge.BridgeableEndpoint, 0, len(nics))
	for _, nicid := range nics {
		nic, ok := ns.ifStates[nicid]
		if !ok {
			panic("NIC known by netstack not in interface table")
		}
		if err := nic.eth.SetPromiscuousMode(true); err != nil {
			return nil, err
		}
		links = append(links, nic.bridgeable)
	}

	return ns.addEndpoint(func(ifs *ifState) (stack.LinkEndpoint, error) {
		b := bridge.New(links)
		ifs.eth = b
		return b, nil
	}, func(ifs *ifState) error {
		if len(ifs.nic.Name) == 0 {
			ifs.nic.Name = fmt.Sprintf("br%d", ifs.nic.ID)
		}
		return ifs.eth.Up()
	})
}

func (ns *Netstack) addEth(topological_path string, config netstack.InterfaceConfig, device ethernet.Device) (*ifState, error) {
	var client *eth.Client
	return ns.addEndpoint(func(ifs *ifState) (stack.LinkEndpoint, error) {
		var err error
		client, err = eth.NewClient("netstack", topological_path, device, ns.arena)
		if err != nil {
			return nil, err
		}
		ifs.eth = client
		ifs.nic.Features = client.Info.Features
		ifs.nic.Name = config.Name
		return eth.NewLinkEndpoint(client), nil
	}, func(ifs *ifState) error {
		if len(ifs.nic.Name) == 0 {
			ifs.nic.Name = fmt.Sprintf("eth%d", ifs.nic.ID)
		}

		switch config.IpAddressConfig.Which() {
		case netstack.IpAddressConfigDhcp:
			ifs.setDHCPStatus(true)
		case netstack.IpAddressConfigStaticIp:
			subnet := config.IpAddressConfig.StaticIp
			protocol, tcpipAddr, retval := ns.validateInterfaceAddress(subnet.Addr, subnet.PrefixLen)
			if retval.Status != netstack.StatusOk {
				return fmt.Errorf("NIC %s: received static IpAddressConfig with an invalid IP specified: [%+v]", ifs.nic.Name, subnet)
			}
			ns.setInterfaceAddress(ifs.nic.ID, protocol, tcpipAddr, subnet.PrefixLen)
		}
		return ifs.eth.Up()
	})
}

func (ns *Netstack) addEndpoint(makeEndpoint func(*ifState) (stack.LinkEndpoint, error), finalize func(*ifState) error) (*ifState, error) {
	ctx, cancel := context.WithCancel(context.Background())

	ifs := &ifState{
		ns:     ns,
		ctx:    ctx,
		cancel: cancel,
		nic: &netiface.NIC{
			Addr:    "\x00\x00\x00\x00",
			Netmask: "\xff\xff\xff\xff",
		},
		state: eth.StateUnknown,
	}

	ep, err := makeEndpoint(ifs)
	if err != nil {
		return nil, err
	}
	if ifs.eth == nil {
		return nil, fmt.Errorf("makeEndpoint func did not set ifs.eth")
	}
	ifs.eth.SetOnStateChange(ifs.stateChange)
	linkID := stack.RegisterLinkEndpoint(ep)
	linkAddr := ep.LinkAddress()
	lladdr := header.LinkLocalAddr(linkAddr)

	// LinkEndpoint chains:
	// Put sniffer as close as the NIC.
	if debug {
		// A wrapper LinkEndpoint should encapsulate the underlying
		// one, and manifest itself to 3rd party netstack.
		linkID = sniffer.New(linkID)
	}

	linkID = filter.NewEndpoint(ns.filter, linkID)
	linkID, ifs.statsEP = stats.NewEndpoint(linkID)
	ifs.statsEP.Nic = ifs.nic
	linkID, ifs.bridgeable = bridge.NewEndpoint(linkID)
	ifs.endpoint = ifs.bridgeable

	ns.mu.Lock()
	ifs.nic.Ipv6addrs = []tcpip.Address{lladdr}

	nicid := ns.countNIC + 1
	ifs.nic.ID = nicid
	ifs.nic.Routes = defaultRouteTable(nicid, "")
	ns.ifStates[nicid] = ifs
	ns.countNIC++
	ns.mu.Unlock()

	log.Printf("NIC %s added", ifs.nic.Name)

	if err := ns.mu.stack.CreateNIC(nicid, linkID); err != nil {
		return nil, fmt.Errorf("NIC %s: could not create NIC: %v", ifs.nic.Name, err)
	}
	if err := ns.mu.stack.AddAddress(nicid, arp.ProtocolNumber, arp.ProtocolAddress); err != nil {
		return nil, fmt.Errorf("NIC %s: adding arp address failed: %v", ifs.nic.Name, err)
	}
	if err := ns.mu.stack.AddAddress(nicid, ipv6.ProtocolNumber, lladdr); err != nil {
		return nil, fmt.Errorf("NIC %s: adding link-local IPv6 %v failed: %v", ifs.nic.Name, lladdr, err)
	}
	snaddr := header.SolicitedNodeAddr(lladdr)
	if err := ns.mu.stack.AddAddress(nicid, ipv6.ProtocolNumber, snaddr); err != nil {
		return nil, fmt.Errorf("NIC %s: adding solicited-node IPv6 %v (link-local IPv6 %v) failed: %v", ifs.nic.Name, snaddr, lladdr, err)
	}
	log.Printf("NIC %s: link-local IPv6: %v", ifs.nic.Name, lladdr)

	ifs.dhcpState.client = dhcp.NewClient(ns.mu.stack, nicid, linkAddr, ifs.dhcpAcquired)

	// Add default route. This will get clobbered later when we get a DHCP response.
	ns.mu.stack.SetRouteTable(ns.flattenRouteTables())

	return ifs, finalize(ifs)
}

func (ns *Netstack) validateInterfaceAddress(address net.IpAddress, prefixLen uint8) (tcpip.NetworkProtocolNumber, tcpip.Address, netstack.NetErr) {
	var protocol tcpip.NetworkProtocolNumber
	switch address.Which() {
	case net.IpAddressIpv4:
		protocol = ipv4.ProtocolNumber
	case net.IpAddressIpv6:
		return 0, "", netstack.NetErr{Status: netstack.StatusIpv4Only, Message: "IPv6 not yet supported"}
	}

	addr := fidlconv.ToTCPIPAddress(address)

	if (8 * len(addr)) < int(prefixLen) {
		return 0, "", netstack.NetErr{Status: netstack.StatusParseError, Message: "prefix length exceeds address length"}
	}

	return protocol, addr, netstack.NetErr{Status: netstack.StatusOk}
}
