// Copyright 2021 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.

//go:build !build_with_native_toolchain
// +build !build_with_native_toolchain

package netstack

import (
	"context"
	"errors"
	"fmt"
	"strings"
	"sync"
	"syscall/zx"
	"syscall/zx/fidl"

	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/link/netdevice"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/routes"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/time"
	"go.fuchsia.dev/fuchsia/src/lib/component"
	syslog "go.fuchsia.dev/fuchsia/src/lib/syslog/go"

	"fidl/fuchsia/hardware/network"
	"fidl/fuchsia/net"
	"fidl/fuchsia/net/interfaces/admin"

	"gvisor.dev/gvisor/pkg/tcpip"
	"gvisor.dev/gvisor/pkg/tcpip/header"
	"gvisor.dev/gvisor/pkg/tcpip/link/ethernet"
	"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
	"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
	"gvisor.dev/gvisor/pkg/tcpip/stack"
)

const (
	addressStateProviderName = "fuchsia.net.interfaces.admin/AddressStateProvider"
	controlName              = "fuchsia.net.interfaces.admin/Control"
	deviceControlName        = "fuchsia.net.interfaces.admin/DeviceControl"
)

type addressStateProviderCollection struct {
	nicid tcpip.NICID
	mu    struct {
		sync.Mutex
		providers map[tcpip.Address]*adminAddressStateProviderImpl
	}
}

// Called when DAD completes.
//
// Note that `online` must not change when calling this function (`ifState.mu`
// must be held).
func (pc *addressStateProviderCollection) onDuplicateAddressDetectionCompleteLocked(nicid tcpip.NICID, addr tcpip.Address, online, success bool) {
	pi, ok := pc.mu.providers[addr]
	if !ok {
		return
	}
	pi.mu.Lock()
	defer pi.mu.Unlock()

	if success {
		// If DAD completed successfully but the interface is currently offline, do
		// not set the assignment state to ASSIGNED.
		if !online {
			_ = syslog.Warnf("interface %d is offline when DAD completed for %s", pc.nicid, addr)
		} else {
			pi.setStateLocked(admin.AddressAssignmentStateAssigned)
		}
	} else {
		delete(pc.mu.providers, addr)
		pi.onRemoveLocked(admin.AddressRemovalReasonDadFailed)
	}
}

func (pc *addressStateProviderCollection) onAddressRemove(addr tcpip.Address) {
	pc.mu.Lock()
	defer pc.mu.Unlock()

	if pi, ok := pc.mu.providers[addr]; ok {
		delete(pc.mu.providers, addr)
		pi.onRemove(admin.AddressRemovalReasonUserRemoved)
	}
}

func (pc *addressStateProviderCollection) onInterfaceRemove() {
	pc.mu.Lock()
	defer pc.mu.Unlock()

	for addr, pi := range pc.mu.providers {
		delete(pc.mu.providers, addr)
		pi.onRemove(admin.AddressRemovalReasonInterfaceRemoved)
	}
}

// TODO(https://fxbug.dev/82045): Avoid racing interface up/down against DAD.
// Note that this function should be called while holding a lock which prevents
// `online` from mutating.
func (pc *addressStateProviderCollection) onInterfaceOnlineChangeLocked(online bool) {
	for _, pi := range pc.mu.providers {
		pi.setInitialState(online)
	}
}

var _ admin.AddressStateProviderWithCtx = (*adminAddressStateProviderImpl)(nil)

type adminAddressStateProviderImpl struct {
	cancelServe  context.CancelFunc
	ready        chan struct{}
	protocolAddr tcpip.ProtocolAddress
	mu           struct {
		sync.Mutex
		eventProxy admin.AddressStateProviderEventProxy
		isHanging  bool
		// NB: lastObserved is the zero value iff the client has yet to observe the
		// state for the first time.
		state, lastObserved admin.AddressAssignmentState
		detached            bool
	}
}

func (pi *adminAddressStateProviderImpl) setInitialState(online bool) {
	pi.mu.Lock()
	defer pi.mu.Unlock()

	// If DAD won the race and set the assignment state to ASSIGNED already,
	// leave the state as ASSIGNED rather than setting it to TENTATIVE.
	if online && pi.mu.state == admin.AddressAssignmentStateAssigned {
		_ = syslog.WarnTf(addressStateProviderName, "%s already in ASSIGNED state when interface became online", pi.protocolAddr.AddressWithPrefix.Address)
	} else {
		// TODO(https://fxbug.dev/82045): Don't assume that DAD is always enabled.
		pi.setStateLocked(initialAddressAssignmentState(pi.protocolAddr, online))
	}
}

func (pi *adminAddressStateProviderImpl) setStateLocked(state admin.AddressAssignmentState) {
	pi.mu.state = state
	if pi.mu.lastObserved != pi.mu.state {
		syslog.DebugTf(addressStateProviderName, "address %+v state changed from %s to %s", pi.protocolAddr, pi.mu.lastObserved, pi.mu.state)
		select {
		case pi.ready <- struct{}{}:
		default:
		}
	}
}

func (pi *adminAddressStateProviderImpl) onRemove(reason admin.AddressRemovalReason) {
	pi.mu.Lock()
	defer pi.mu.Unlock()

	pi.onRemoveLocked(reason)
}

func (pi *adminAddressStateProviderImpl) onRemoveLocked(reason admin.AddressRemovalReason) {
	if err := pi.mu.eventProxy.OnAddressRemoved(reason); err != nil {
		var zxError *zx.Error
		if !errors.As(err, &zxError) || (zxError.Status != zx.ErrPeerClosed && zxError.Status != zx.ErrBadHandle) {
			_ = syslog.WarnTf(addressStateProviderName, "failed to send OnAddressRemoved(%s) for %s: %s", reason, pi.protocolAddr.AddressWithPrefix.Address, err)
		}
	}
	pi.cancelServe()
}

// TODO(https://fxbug.dev/80621): Add support for updating an address's
// properties (valid and expected lifetimes).
func (pi *adminAddressStateProviderImpl) UpdateAddressProperties(_ fidl.Context, addressProperties admin.AddressProperties) error {
	_ = syslog.WarnTf(addressStateProviderName, "UpdateAddressProperties for %s: not supported", pi.protocolAddr.AddressWithPrefix.Address)

	pi.onRemove(admin.AddressRemovalReasonUserRemoved)
	// Always return an error here so we never issue a response to the request.
	return fmt.Errorf("UpdateAddressPoprties is for %s: not supported", pi.protocolAddr.AddressWithPrefix.Address)
}

func (pi *adminAddressStateProviderImpl) Detach(fidl.Context) error {
	pi.mu.Lock()
	defer pi.mu.Unlock()

	pi.mu.detached = true
	return nil
}

func (pi *adminAddressStateProviderImpl) WatchAddressAssignmentState(ctx fidl.Context) (admin.AddressAssignmentState, error) {
	pi.mu.Lock()
	defer pi.mu.Unlock()

	if pi.mu.isHanging {
		pi.cancelServe()
		return 0, errors.New("not allowed to call WatchAddressAssignmentState when a call is already in progress")
	}

	for {
		if pi.mu.lastObserved != pi.mu.state {
			state := pi.mu.state
			pi.mu.lastObserved = state
			syslog.DebugTf(addressStateProviderName, "address %+v observed state: %s", pi.protocolAddr, state)
			return state, nil
		}

		pi.mu.isHanging = true
		pi.mu.Unlock()

		var err error
		select {
		case <-pi.ready:
		case <-ctx.Done():
			err = fmt.Errorf("cancelled: %w", ctx.Err())
		}

		pi.mu.Lock()
		pi.mu.isHanging = false
		if err != nil {
			return 0, err
		}
	}
}

func interfaceAddressToProtocolAddress(addr net.InterfaceAddress) tcpip.ProtocolAddress {
	var protocolAddr tcpip.ProtocolAddress
	switch tag := addr.Which(); tag {
	case net.InterfaceAddressIpv4:
		protocolAddr.Protocol = ipv4.ProtocolNumber
		protocolAddr.AddressWithPrefix.Address = tcpip.Address(addr.Ipv4.Addr.Addr[:])
		protocolAddr.AddressWithPrefix.PrefixLen = int(addr.Ipv4.PrefixLen)
	case net.InterfaceAddressIpv6:
		protocolAddr.Protocol = ipv6.ProtocolNumber
		protocolAddr.AddressWithPrefix.Address = tcpip.Address(addr.Ipv6.Addr[:])
		// TODO(https://fxbug.dev/81929): Don't lie about the prefix length to gVisor.
		protocolAddr.AddressWithPrefix.PrefixLen = 8 * header.IPv6AddressSize
	default:
		panic(fmt.Sprintf("unknown address: %#v", addr))
	}
	return protocolAddr
}

func initialAddressAssignmentState(protocolAddr tcpip.ProtocolAddress, online bool) admin.AddressAssignmentState {
	if !online {
		return admin.AddressAssignmentStateUnavailable
	}
	switch protocolAddr.Protocol {
	case header.IPv4ProtocolNumber:
		return admin.AddressAssignmentStateAssigned
	case header.IPv6ProtocolNumber:
		return admin.AddressAssignmentStateTentative
	default:
		panic(fmt.Sprintf("unknown protocol in address %s: %d", protocolAddr.AddressWithPrefix, protocolAddr.Protocol))
	}
}

var _ admin.ControlWithCtx = (*adminControlImpl)(nil)

type adminControlImpl struct {
	ns          *Netstack
	nicid       tcpip.NICID
	cancelServe context.CancelFunc
	doneChannel chan struct{}
	// TODO(https://fxbug.dev/85061): encode owned, strong, and weak refs once
	// cloning Control is allowed.
	isStrongRef bool
}

func (ci *adminControlImpl) Enable(fidl.Context) (admin.ControlEnableResult, error) {
	nicInfo, ok := ci.ns.stack.NICInfo()[ci.nicid]
	if !ok {
		// All serving control channels must be canceled before removing NICs from
		// the stack, this is a violation of that invariant.
		panic(fmt.Sprintf("NIC %d not found", ci.nicid))
	}

	wasEnabled, err := nicInfo.Context.(*ifState).setState(true /* enabled */)
	if err != nil {
		// The only known error path that causes this failure is failure from the
		// device layers, which all mean we're possible racing with shutdown.
		_ = syslog.Errorf("ifs.Up() failed (NIC %d): %s", ci.nicid, err)
		return admin.ControlEnableResult{}, err
	}

	return admin.ControlEnableResultWithResponse(
		admin.ControlEnableResponse{
			DidEnable: !wasEnabled,
		}), nil
}

func (ci *adminControlImpl) Disable(fidl.Context) (admin.ControlDisableResult, error) {
	nicInfo, ok := ci.ns.stack.NICInfo()[ci.nicid]
	if !ok {
		// All serving control channels must be canceled before removing NICs from
		// the stack, this is a violation of that invariant.
		panic(fmt.Sprintf("NIC %d not found", ci.nicid))
	}

	wasEnabled, err := nicInfo.Context.(*ifState).setState(false /* enabled */)
	if err != nil {
		// The only known error path that causes this failure is failure from the
		// device layers, which all mean we're possible racing with shutdown.
		_ = syslog.Errorf("ifs.Down() failed (NIC %d): %s", ci.nicid, err)
		return admin.ControlDisableResult{}, err
	}

	return admin.ControlDisableResultWithResponse(
		admin.ControlDisableResponse{
			DidDisable: wasEnabled,
		}), nil
}

func (ci *adminControlImpl) Detach(fidl.Context) error {
	// Make it a weak ref but don't decrease the reference count. If this was a
	// strong ref, the interface will leak.
	//
	// TODO(https://fxbug.dev/87963): Detach should only be allowed on OWNED refs
	// once we allow cloning Control.
	ci.isStrongRef = false
	return nil
}

func (ci *adminControlImpl) AddAddress(_ fidl.Context, interfaceAddr net.InterfaceAddress, parameters admin.AddressParameters, request admin.AddressStateProviderWithCtxInterfaceRequest) error {
	protocolAddr := interfaceAddressToProtocolAddress(interfaceAddr)
	addr := protocolAddr.AddressWithPrefix.Address

	nicInfo, ok := ci.ns.stack.NICInfo()[ci.nicid]
	if !ok {
		// All serving control channels must be canceled before removing NICs from
		// the stack, this is a violation of that invariant.
		panic(fmt.Sprintf("NIC %d not found", ci.nicid))
	}
	ifs := nicInfo.Context.(*ifState)

	ctx, cancel := context.WithCancel(context.Background())
	impl := adminAddressStateProviderImpl{
		ready:        make(chan struct{}, 1),
		cancelServe:  cancel,
		protocolAddr: protocolAddr,
	}
	impl.mu.eventProxy.Channel = request.Channel

	if reason := func() admin.AddressRemovalReason {
		// TODO(https://fxbug.dev/80621): Add support for address lifetimes.
		var b strings.Builder
		if parameters.HasTemporary() {
			b.WriteString(fmt.Sprintf(" temporary=%t", parameters.GetTemporary()))
		}
		if parameters.HasInitialProperties() {
			properties := parameters.GetInitialProperties()
			if properties.HasPreferredLifetimeInfo() {
				b.WriteString(fmt.Sprintf(" preferredLifetimeInfo=%#v", properties.GetPreferredLifetimeInfo()))
			}
			if properties.HasValidLifetimeEnd() {
				b.WriteString(fmt.Sprintf(" validLifetimeEnd=%s", time.Monotonic(properties.GetValidLifetimeEnd())))
			}
		}
		if unsupportedProperties := b.String(); unsupportedProperties != "" {
			_ = syslog.WarnTf(controlName, "AddAddress called with unsupported parameters:%s", unsupportedProperties)
			return admin.AddressRemovalReasonInvalid
		}

		if protocolAddr.AddressWithPrefix.PrefixLen > 8*len(protocolAddr.AddressWithPrefix.Address) {
			return admin.AddressRemovalReasonInvalid
		}

		// NB: Must lock `ifState.mu` and then `addressStateProviderCollection.mu`
		// to prevent interface online changes (which acquire the same locks in
		// the same order) from interposing a modification to address assignment
		// state before the `impl` is inserted into the collection.
		//
		// `ifState.mu` is released as soon as possible to avoid deadlock issues.
		online := func() bool {
			ifs.mu.Lock()
			defer ifs.mu.Unlock()

			ifs.addressStateProviders.mu.Lock()
			return ifs.IsUpLocked()
		}()
		defer ifs.addressStateProviders.mu.Unlock()

		if _, ok := ifs.addressStateProviders.mu.providers[addr]; ok {
			return admin.AddressRemovalReasonAlreadyAssigned
		}

		status := ci.ns.addInterfaceAddress(ci.nicid, protocolAddr, false /* addRoute */)
		_ = syslog.DebugTf(addressStateProviderName, "addInterfaceAddress(%d, %+v, false) = %s", ci.nicid, protocolAddr, status)
		switch status {
		case zx.ErrOk:
			impl.mu.state = initialAddressAssignmentState(protocolAddr, online)
			_ = syslog.DebugTf(addressStateProviderName, "initial state for %+v: %s", protocolAddr, impl.mu.state)
			ifs.addressStateProviders.mu.providers[addr] = &impl
			return 0
		case zx.ErrInvalidArgs:
			return admin.AddressRemovalReasonInvalid
		case zx.ErrNotFound:
			return admin.AddressRemovalReasonInterfaceRemoved
		case zx.ErrAlreadyExists:
			return admin.AddressRemovalReasonAlreadyAssigned
		default:
			panic(fmt.Errorf("unexpected internal AddAddress error %s", status))
			return admin.AddressRemovalReasonUserRemoved
		}
	}(); reason != 0 {
		if err := impl.mu.eventProxy.OnAddressRemoved(reason); err != nil {
			var zxError *zx.Error
			if !errors.As(err, &zxError) || (zxError.Status != zx.ErrPeerClosed && zxError.Status != zx.ErrBadHandle) {
				_ = syslog.WarnTf(controlName, "failed to send OnAddressRemoved(%s) for %s: %s", reason, protocolAddr.AddressWithPrefix.Address, err)
			}
		}
		if err := impl.mu.eventProxy.Close(); err != nil {
			_ = syslog.WarnTf(controlName, "failed to close %s channel", addressStateProviderName)
		}
		return nil
	}

	go func() {
		component.Serve(ctx, &admin.AddressStateProviderWithCtxStub{Impl: &impl}, request.Channel, component.ServeOptions{
			Concurrent: true,
			OnError: func(err error) {
				_ = syslog.WarnTf(addressStateProviderName, "address state provider for %s: %s", addr, err)
			},
		})

		if pi, ok := func() (*adminAddressStateProviderImpl, bool) {
			ifs.addressStateProviders.mu.Lock()
			defer ifs.addressStateProviders.mu.Unlock()

			// The impl may have already been removed due to address removal.
			pi, ok := ifs.addressStateProviders.mu.providers[addr]
			if ok {
				// Removing the address will also attempt to delete from
				// the address state providers map, so delete from it and unlock
				// immediately to avoid lock ordering and deadlock issues.
				delete(ifs.addressStateProviders.mu.providers, addr)
			}
			return pi, ok
		}(); ok {
			pi.mu.Lock()
			remove := !pi.mu.detached
			pi.mu.Unlock()

			if remove {
				// NB: Removing the address will also attempt to access the address state
				// provider collection and delete the impl out of it if found. The lock
				// on the collection must not be held at this point to prevent the
				// deadlock.
				if status := ci.ns.removeInterfaceAddress(ci.nicid, pi.protocolAddr, false /* removeRoute */); status != zx.ErrOk && status != zx.ErrNotFound {
					// If address has already been removed, don't consider it an error.
					_ = syslog.ErrorTf(addressStateProviderName, "failed to remove address %s on channel closure: %s", addr, status)
				}
			}
		}
	}()
	return nil
}

func (ci *adminControlImpl) RemoveAddress(_ fidl.Context, address net.InterfaceAddress) (admin.ControlRemoveAddressResult, error) {
	protocolAddr := interfaceAddressToProtocolAddress(address)
	switch zxErr := ci.ns.removeInterfaceAddress(ci.nicid, protocolAddr, false /* removeRoute */); zxErr {
	case zx.ErrOk:
		return admin.ControlRemoveAddressResultWithResponse(admin.ControlRemoveAddressResponse{DidRemove: true}), nil
	case zx.ErrNotFound:
		return admin.ControlRemoveAddressResultWithResponse(admin.ControlRemoveAddressResponse{DidRemove: false}), nil
	default:
		panic(fmt.Sprintf("removeInterfaceAddress(%d, %v, false) = %s", ci.nicid, protocolAddr, zxErr))
	}
}

func (ci *adminControlImpl) GetId(fidl.Context) (uint64, error) {
	return uint64(ci.nicid), nil
}

type adminControlCollection struct {
	mu struct {
		sync.Mutex
		removalReason  admin.InterfaceRemovedReason
		controls       map[*adminControlImpl]struct{}
		strongRefCount uint
	}
}

func (c *adminControlCollection) onInterfaceRemove(reason admin.InterfaceRemovedReason) {
	c.mu.Lock()
	controls := c.mu.controls
	c.mu.controls = nil
	c.mu.removalReason = reason
	c.mu.Unlock()

	for control := range controls {
		control.cancelServe()
	}
	for control := range controls {
		<-control.doneChannel
	}
}

func (ifs *ifState) addAdminConnection(request admin.ControlWithCtxInterfaceRequest, strong bool) {

	impl, ctx := func() (*adminControlImpl, context.Context) {
		ifs.adminControls.mu.Lock()
		defer ifs.adminControls.mu.Unlock()

		// Do not add more connections to an interface that is tearing down.
		if ifs.adminControls.mu.removalReason != 0 {
			if err := request.Channel.Close(); err != nil {
				_ = syslog.ErrorTf(controlName, "request.channel.Close() = %s", err)
			}
			return nil, nil
		}

		ctx, cancel := context.WithCancel(context.Background())
		impl := &adminControlImpl{
			ns:          ifs.ns,
			nicid:       ifs.nicid,
			cancelServe: cancel,
			doneChannel: make(chan struct{}),
			isStrongRef: strong,
		}

		ifs.adminControls.mu.controls[impl] = struct{}{}
		if impl.isStrongRef {
			ifs.adminControls.mu.strongRefCount++
		}

		return impl, ctx
	}()
	if impl == nil {
		return
	}

	go func() {
		defer close(impl.doneChannel)

		requestChannel := request.Channel
		defer func() {
			if !requestChannel.Handle().IsValid() {
				return
			}
			if err := requestChannel.Close(); err != nil {
				_ = syslog.ErrorTf(controlName, "requestChannel.Close() = %s", err)
			}
		}()

		component.Serve(ctx, &admin.ControlWithCtxStub{Impl: impl}, requestChannel, component.ServeOptions{
			Concurrent:       false,
			KeepChannelAlive: true,
			OnError: func(err error) {
				_ = syslog.WarnTf(controlName, "%s", err)
			},
		})

		// NB: anonymous function is used to restrict section where the lock is
		// held.
		ifStateToRemove := func() *ifState {
			ifs.adminControls.mu.Lock()
			defer ifs.adminControls.mu.Unlock()
			wasCanceled := errors.Is(ctx.Err(), context.Canceled)
			if wasCanceled {
				reason := ifs.adminControls.mu.removalReason
				if reason == 0 {
					panic("serve context canceled without storing a reason")
				}
				eventProxy := admin.ControlEventProxy{Channel: requestChannel}
				if err := eventProxy.OnInterfaceRemoved(reason); err != nil {
					_ = syslog.WarnTf(controlName, "failed to send interface close reason %s: %s", reason, err)
				}
				// Take the channel back from the proxy, since the proxy *may* have closed
				// the channel, in which case we want to prevent a double close on
				// the deferred cleanup.
				requestChannel = eventProxy.Channel
			}

			delete(ifs.adminControls.mu.controls, impl)
			// Don't consider destroying if not a strong ref.
			//
			// Note that the implementation can change from a strong to a weak ref if
			// Detach is called, which is how we allow interfaces to leak.
			//
			// This is also how we prevent destruction from interfaces created with
			// the legacy API, since they never have strong refs.
			if !impl.isStrongRef {
				return nil
			}
			ifs.adminControls.mu.strongRefCount--

			// If serving was canceled, that means that removal happened due to
			// outside cancelation already.
			if wasCanceled {
				return nil
			}
			// Don't destroy if there are any strong refs left.
			if ifs.adminControls.mu.strongRefCount != 0 {
				return nil
			}

			// We're good to remove this interface.
			// Prevent new connections while we're holding the collection lock,
			// avoiding races between here and removing the interface below.
			ifs.adminControls.mu.removalReason = admin.InterfaceRemovedReasonUser

			nicInfo, ok := impl.ns.stack.NICInfo()[impl.nicid]
			if !ok {
				panic(fmt.Sprintf("failed to find interface %d", impl.nicid))
			}
			// We can safely remove the interface now because we're certain that
			// this control impl is not in the collection anymore, so it can't
			// deadlock waiting for control interfaces to finish.
			return nicInfo.Context.(*ifState)
		}()

		if ifStateToRemove != nil {
			ifStateToRemove.RemoveByUser()
		}

	}()
}

var _ admin.InstallerWithCtx = (*interfacesAdminInstallerImpl)(nil)

type interfacesAdminInstallerImpl struct {
	ns *Netstack
}

func (i *interfacesAdminInstallerImpl) InstallDevice(_ fidl.Context, device network.DeviceWithCtxInterface, deviceControl admin.DeviceControlWithCtxInterfaceRequest) error {

	client, err := netdevice.NewClient(context.Background(), &device, &netdevice.SimpleSessionConfigFactory{})
	if err != nil {
		_ = syslog.WarnTf(controlName, "InstallDevice: %s", err)
		_ = deviceControl.Close()
		return nil
	}

	ctx, cancel := context.WithCancel(context.Background())
	impl := &interfacesAdminDeviceControlImpl{
		ns:           i.ns,
		deviceClient: client,
		cancelServe:  cancel,
	}

	// Running the device client and serving the FIDL are tied to the same
	// context because their lifecycles are linked.
	go func() {
		impl.deviceClient.Run(ctx)
		impl.cancelServe()
	}()

	go func() {
		component.Serve(ctx, &admin.DeviceControlWithCtxStub{Impl: impl}, deviceControl.Channel, component.ServeOptions{
			OnError: func(err error) {
				_ = syslog.WarnTf(deviceControlName, "%s", err)
			},
		})

		if !impl.detached {
			// Device lifecycle is tied to channel lifetime.
			if err := impl.deviceClient.Close(); err != nil {
				_ = syslog.ErrorTf(deviceControlName, "deviceClient.Close() = %s", err)
			}
		}
	}()

	return nil
}

var _ admin.DeviceControlWithCtx = (*interfacesAdminDeviceControlImpl)(nil)

type interfacesAdminDeviceControlImpl struct {
	ns           *Netstack
	deviceClient *netdevice.Client
	cancelServe  context.CancelFunc
	detached     bool
}

func (d *interfacesAdminDeviceControlImpl) CreateInterface(_ fidl.Context, portId network.PortId, control admin.ControlWithCtxInterfaceRequest, options admin.Options) error {

	ifs, closeReason := func() (*ifState, admin.InterfaceRemovedReason) {
		port, err := d.deviceClient.NewPort(context.Background(), portId)
		if err != nil {
			_ = syslog.WarnTf(deviceControlName, "NewPort(_, %d) failed: %s", portId, err)
			{
				var unsupported *netdevice.InvalidPortOperatingModeError
				if errors.As(err, &unsupported) {
					return nil, admin.InterfaceRemovedReasonBadPort
				}
			}
			{
				var alreadyBound *netdevice.PortAlreadyBoundError
				if errors.As(err, &alreadyBound) {
					return nil, admin.InterfaceRemovedReasonPortAlreadyBound
				}
			}

			// Assume all other errors are due to problems communicating with the
			// port.
			return nil, admin.InterfaceRemovedReasonPortClosed
		}
		defer func() {
			if port != nil {
				_ = port.Close()
			}
		}()

		var namePrefix string
		var linkEndpoint stack.LinkEndpoint
		switch mode := port.Mode(); mode {
		case netdevice.PortModeEthernet:
			namePrefix = "eth"
			linkEndpoint = ethernet.New(port)
		case netdevice.PortModeIp:
			namePrefix = "ip"
			linkEndpoint = port
		default:
			panic(fmt.Sprintf("unknown port mode %d", mode))
		}

		ifs, err := d.ns.addEndpoint(
			makeEndpointName(namePrefix, options.GetNameWithDefault("")),
			linkEndpoint,
			port,
			port,
			routes.Metric(options.GetMetricWithDefault(0)),
		)
		if err != nil {
			_ = syslog.WarnTf(deviceControlName, "addEndpoint failed: %s", err)
			var tcpipError *TcpIpError
			if errors.As(err, &tcpipError) {
				switch tcpipError.Err.(type) {
				case *tcpip.ErrDuplicateNICID:
					return nil, admin.InterfaceRemovedReasonDuplicateName
				}
			}
			panic(fmt.Sprintf("unexpected error ns.AddEndpoint(..) = %s", err))
		}

		// Prevent deferred cleanup from running.
		port = nil

		return ifs, 0
	}()

	if closeReason != 0 {
		proxy := admin.ControlEventProxy{
			Channel: control.Channel,
		}
		if err := proxy.OnInterfaceRemoved(closeReason); err != nil {
			_ = syslog.WarnTf(deviceControlName, "failed to write terminal event %s: %s", closeReason, err)
		}
		_ = control.Close()
		return nil
	}

	ifs.addAdminConnection(control, true /* strong */)

	return nil
}

func (d *interfacesAdminDeviceControlImpl) Detach(fidl.Context) error {
	d.detached = true
	return nil
}
