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

//go:build !build_with_native_toolchain

package netstack

import (
	"context"
	"crypto/rand"
	"encoding/base64"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"reflect"
	"runtime"
	"strconv"
	"syscall/zx"
	"syscall/zx/fidl"
	"syscall/zx/zxwait"
	"time"

	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/dns"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/filter"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/pprof"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/routes"
	zxtime "go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/time"
	tracingprovider "go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/tracing/provider"

	"go.fuchsia.dev/fuchsia/src/lib/component"
	syslog "go.fuchsia.dev/fuchsia/src/lib/syslog/go"

	"fidl/fuchsia/logger"
	"fidl/fuchsia/net/debug"
	"fidl/fuchsia/net/interfaces"
	"fidl/fuchsia/net/interfaces/admin"
	"fidl/fuchsia/net/name"
	"fidl/fuchsia/net/neighbor"
	"fidl/fuchsia/net/root"
	fnetRoutes "fidl/fuchsia/net/routes"
	routesAdmin "fidl/fuchsia/net/routes/admin"
	"fidl/fuchsia/net/stack"
	"fidl/fuchsia/posix/socket"
	packetsocket "fidl/fuchsia/posix/socket/packet"
	rawsocket "fidl/fuchsia/posix/socket/raw"
	scheduler "fidl/fuchsia/scheduler/deprecated"
	"fidl/fuchsia/stash"
	"fidl/fuchsia/update/verify"

	"gvisor.dev/gvisor/pkg/atomicbitops"
	glog "gvisor.dev/gvisor/pkg/log"
	"gvisor.dev/gvisor/pkg/tcpip"
	"gvisor.dev/gvisor/pkg/tcpip/header"
	"gvisor.dev/gvisor/pkg/tcpip/link/sniffer"
	"gvisor.dev/gvisor/pkg/tcpip/network/arp"
	"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
	"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
	tcpipstack "gvisor.dev/gvisor/pkg/tcpip/stack"
	"gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
	"gvisor.dev/gvisor/pkg/tcpip/transport/raw"
	"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
	"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
)

const (
	// stashStoreIdentificationName is the name used to identify this (netstack)
	// component to the fuchsia.stash.SecureStore service.
	stashStoreIdentificationName = "netstack-stash"

	// opaqueIIDSecretKeyName is the name of the key used to access the secret key
	// for opaque IIDs from the secure stash store.
	opaqueIIDSecretKeyName = "opaque-iid-secret-key"

	// dadTransmits is the number of consecutive NDP Neighbor Solicitation
	// messages sent while performing Duplicate Address Detection on a IPv6
	// tentative address.
	//
	// As per RFC 4862 section 5.1, 1 is the default number of messages to send.
	dadTransmits = 1

	// dadRetransmitTimer is the time between retransmissions of NDP Neighbor
	// Solicitation messages to a neighbor.
	//
	// As per RFC 4861 section 10, 1s is the default time between retransmissions.
	dadRetransmitTimer = time.Second

	// maxRtrSolicitations is the maximum number of Router Solicitation messages
	// to send when a NIC becomes enabled.
	//
	// As per RFC 4861 section 10, 3 is the default number of messages.
	maxRtrSolicitations = 3

	// rtrSolicitationInterval is the amount of time between sending Router
	// Solicitation messages.
	//
	// As per RFC 4861 section 10, 4s is the default time between transmissions.
	rtrSolicitationInterval = 4 * time.Second

	// maxRtrSolicitationDelay is the maximum amount of time to wait before
	// sending the first Router Solicitation message.
	//
	// As per RFC 4861 section 10, 1s is the default maximum time to wait.
	maxRtrSolicitationDelay = time.Second

	// autoGenAddressConflictRetries is the maximum number of times to attempt
	// SLAAC address regeneration in response to DAD conflicts.
	//
	// As per RFC 7217 section, 3 is the default maximum number of retries.
	autoGenAddressConflictRetries = 3

	// maxTempAddrValidLifetime is the maximum amount of time a temporary SLAAC
	// address may be valid for from creation.
	//
	// As per RFC 4941 section 5, 7 days is the default max valid lifetime.
	maxTempAddrValidLifetime = 7 * 24 * time.Hour

	// maxTempAddrPreferredLifetime is the maximum amount of time a temporary
	// SLAAC address may be preferred for from creation.
	//
	// As per RFC 4941 section 5, 1 day is the default max preferred lifetime.
	maxTempAddrPreferredLifetime = 24 * time.Hour

	// regenAdvanceDuration is duration before the deprecation of a temporary
	// address when a new address will be generated.
	//
	// As per RFC 4941 section 5, 5s is the default duration. We make the duration
	// the default duration plus the maximum amount of time for an address to
	// resolve DAD if all but the last regeneration attempts fail. This is to
	// guarantee that if a new address is generated, it will be assigned for at
	// least 5s before the original address is deprecated.
	regenAdvanceDuration = 5*time.Second + dadTransmits*dadRetransmitTimer*(1+autoGenAddressConflictRetries)

	// handleRAs is the configuration for when Router Advertisements should be
	// handled.
	//
	// We want to handle router advertisements even when operating as a router
	// so that we can perform router/prefix discovery and SLAAC.
	handleRAs = ipv6.HandlingRAsAlwaysEnabled
)

type atomicBool struct {
	v *atomicbitops.Uint32
}

// IsBoolFlag implements flag.boolFlag.IsBoolFlag.
//
// See the flag.Value documentation for more information.
func (*atomicBool) IsBoolFlag() bool {
	return true
}

// Set implements flag.Value.Set.
func (a *atomicBool) Set(s string) error {
	v, err := strconv.ParseBool(s)
	if err != nil {
		return err
	}
	var val uint32
	if v {
		val = 1
	}
	a.v.Store(val)
	return nil
}

// String implements flag.Value.String.
func (a *atomicBool) String() string {
	return strconv.FormatBool(a.v.Load() != 0)
}

func init() {
	// As of this writing the default is 1.
	sniffer.LogPackets.Store(0)
}

type glogEmitter struct{}

func (*glogEmitter) Emit(depth int, level glog.Level, timestamp time.Time, format string, v ...interface{}) {
	switch level {
	case glog.Warning:
		syslog.Warnf(format, v...)
	case glog.Info:
		syslog.Infof(format, v...)
	case glog.Debug:
		syslog.Debugf(format, v...)
	}
}

func InstallThreadProfiles(ctx context.Context, componentCtx *component.Context) {
	req, provider, err := scheduler.NewProfileProviderWithCtxInterfaceRequest()
	if err != nil {
		panic(fmt.Sprintf("failed to create %s request: %s", req.Name(), err))
	}
	componentCtx.ConnectToEnvService(req)

	go func() {
		const handlesPerRead = 1
		const bytesPerRead = 1

		channel := zx.GetThreadsChannel()
		for {
			defer func() {
				_ = provider.Close()
			}()
			var handles [handlesPerRead]zx.HandleInfo
			var bytes [bytesPerRead]byte
			var nb, nh uint32
			if err := zxwait.WithRetryContext(ctx, func() error {
				var err error
				nb, nh, err = channel.ReadEtc(bytes[:], handles[:], 0)
				return err
			}, *channel.Handle(), zx.SignalChannelReadable, zx.SignalChannelPeerClosed); err != nil {
				_ = syslog.Errorf("stopped observing for thread profiles: %s", err)
				return
			}
			if nb != bytesPerRead {
				panic(fmt.Sprintf("unexpected %d bytes in channel message", nb))
			}
			if nh != handlesPerRead {
				panic(fmt.Sprintf("unexpected %d handles in channel message", nh))
			}

			handleInfo := handles[0]
			threadType := runtime.ThreadType(bytes[0])

			threadProfile := func() string {
				switch threadType {
				case runtime.WorkerThread:
					return "fuchsia.netstack.go-worker"
				case runtime.SysmonThread:
					return "fuchsia.netstack.go-sysmon"
				default:
					return ""
				}
			}()
			// Skip if no profile is chosen.
			if len(threadProfile) == 0 {
				_ = syslog.Infof("no thread profile for thread type %d", threadType)
				_ = handleInfo.Handle.Close()
				continue
			}
			// Retrieve the koid before transferring the handle.
			koid := func() string {
				info, err := handleInfo.Handle.GetInfoHandleBasic()
				if err != nil {
					return fmt.Sprintf("<%s>", err)
				}
				return fmt.Sprintf("%d", info.Koid)
			}()

			// Attempt to install our thread profile.
			status, err := provider.SetProfileByRole(ctx, handleInfo.Handle, threadProfile)
			if err, ok := err.(*zx.Error); ok {
				switch err.Status {
				case zx.ErrNotFound, zx.ErrPeerClosed, zx.ErrUnavailable:
					_ = syslog.Warnf("connection to %s closed; will not set thread profile %s; FIDL error: %s", req.Name(), threadProfile, err)
					return
				}
			}
			if err != nil {
				_ = syslog.Errorf("failed to set thread profile %s for koid=%s; FIDL error: %s", threadProfile, koid, err)
				continue
			}

			if status := zx.Status(status); status != zx.ErrOk {
				switch status {
				case zx.ErrNotFound:
					_ = syslog.Warnf("did not find thread profile %s for koid=%s", threadProfile, koid)
				default:
					_ = syslog.Errorf("failed to set thread profile %s for koid=%s; rejected with %s", threadProfile, koid, status)
				}
				continue
			}

			_ = syslog.Debugf("successfully set thread profile for koid=%s to %s", koid, threadProfile)
		}
	}()
}

type config struct {
	GOMAXPROCS *int
}

func Main() {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	flags := flag.NewFlagSet(os.Args[0], flag.ContinueOnError)

	logPackets := atomicBool{v: &sniffer.LogPackets}
	flags.Var(&logPackets, "log-packets", "enable packet logging")

	logLevel := syslog.InfoLevel
	flags.Var(&logLevel, "verbosity", "set the logging verbosity")

	var socketStatsTimerPeriod time.Duration
	flags.DurationVar(&socketStatsTimerPeriod, "socket-stats-sampling-interval", time.Minute, "set the interval at which socket stats will be sampled")

	noOpaqueIID := false
	flags.BoolVar(&noOpaqueIID, "no-opaque-iids", false, "disable opaque IIDs")

	fastUDP := true
	flags.BoolVar(&fastUDP, "fast-udp", true, "enable Fast UDP")

	configFile := flags.String("config-data", "/config/data/default.json", "config file to use")

	if err := flags.Parse(os.Args[1:]); err != nil {
		panic(err)
	}

	var config *config
	setMaxProcs := func() bool {
		b, err := os.ReadFile(*configFile)
		if err != nil {
			_ = syslog.Warnf("failed to read config data at %s, continuing with defaults", *configFile)
			return false
		}
		if err := json.Unmarshal(b, &config); err != nil {
			panic(fmt.Sprintf("failed to unmarshal JSON from config file: %s", err))
		}
		if config.GOMAXPROCS != nil {
			prev := runtime.GOMAXPROCS(*config.GOMAXPROCS)
			_ = syslog.Infof("set GOMAXPROCS to %d, was %d (NumCPU = %d)", *config.GOMAXPROCS, prev, runtime.NumCPU())
			return true
		}
		return false
	}()
	if !setMaxProcs {
		_ = syslog.Infof("override for GOMAXPROCS not provided, leaving as default (NumCPU = %d)", runtime.NumCPU())
	}

	componentCtx := component.NewContextFromStartupInfo()

	{
		req, logSink, err := logger.NewLogSinkWithCtxInterfaceRequest()
		if err != nil {
			panic(fmt.Sprintf("failed to create syslog request: %s", err))
		}
		componentCtx.ConnectToEnvService(req)

		options := syslog.LogInitOptions{
			LogLevel: logLevel,
		}
		options.LogSink = logSink
		options.MinSeverityForFileAndLineInfo = logLevel
		options.Tags = []string{"netstack"}

		l, err := syslog.NewLogger(options)
		if err != nil {
			panic(err)
		}
		syslog.SetDefaultLogger(l)
		log.SetOutput(&syslog.Writer{Logger: l})
	}

	log.SetFlags(log.Lshortfile)
	glog.SetTarget(&glogEmitter{})

	// This routine may log; start it after initializing syslog.
	InstallThreadProfiles(ctx, componentCtx)

	_ = syslog.Infof("starting...")

	var opaqueIIDOpts ipv6.OpaqueInterfaceIdentifierOptions
	if !noOpaqueIID {
		secretKeyForOpaqueIID, err := getSecretKeyForOpaqueIID(componentCtx)
		if err != nil {
			panic(fmt.Sprintf("failed to get secret key for opaque IIDs: %s", err))
		}
		opaqueIIDOpts = ipv6.OpaqueInterfaceIdentifierOptions{
			NICNameFromID: func(nicID tcpip.NICID, nicName string) string {
				// As of writing, Netstack creates NICs with names so we return the name
				// the NIC was created with. Just in case, we have a default NIC name
				// format for NICs that were not created with a name.
				if nicName != "" {
					return nicName
				}
				return fmt.Sprintf("opaqueIIDNIC%d", nicID)
			},
			SecretKey: secretKeyForOpaqueIID,
		}
	}

	tempIIDSeed, err := newSecretKey(header.IIDSize)
	if err != nil {
		panic(fmt.Sprintf("failed to get temp IID seed: %s", err))
	}

	ndpDisp := newNDPDispatcher()
	nudDisp := newNudDispatcher()

	dadConfigs := tcpipstack.DADConfigurations{
		DupAddrDetectTransmits: dadTransmits,
		RetransmitTimer:        dadRetransmitTimer,
	}

	stk := tcpipstack.New(tcpipstack.Options{
		NetworkProtocols: []tcpipstack.NetworkProtocolFactory{
			arp.NewProtocolWithOptions(arp.Options{
				DADConfigs: dadConfigs,
			}),
			ipv4.NewProtocolWithOptions(ipv4.Options{
				IGMP: ipv4.IGMPOptions{
					Enabled: true,
				},
			}),
			ipv6.NewProtocolWithOptions(ipv6.Options{
				DADConfigs: dadConfigs,
				NDPConfigs: ipv6.NDPConfigurations{
					MaxRtrSolicitations:           maxRtrSolicitations,
					RtrSolicitationInterval:       rtrSolicitationInterval,
					MaxRtrSolicitationDelay:       maxRtrSolicitationDelay,
					HandleRAs:                     handleRAs,
					DiscoverDefaultRouters:        true,
					DiscoverMoreSpecificRoutes:    true,
					DiscoverOnLinkPrefixes:        true,
					AutoGenGlobalAddresses:        true,
					AutoGenAddressConflictRetries: autoGenAddressConflictRetries,
					AutoGenTempGlobalAddresses:    true,
					MaxTempAddrValidLifetime:      maxTempAddrValidLifetime,
					MaxTempAddrPreferredLifetime:  maxTempAddrPreferredLifetime,
					RegenAdvanceDuration:          regenAdvanceDuration,
				},
				AutoGenLinkLocal: true,
				NDPDisp:          ndpDisp,
				OpaqueIIDOpts:    opaqueIIDOpts,
				TempIIDSeed:      tempIIDSeed,
				MLD: ipv6.MLDOptions{
					Enabled: true,
				},
			}),
		},
		TransportProtocols: []tcpipstack.TransportProtocolFactory{
			icmp.NewProtocol4,
			icmp.NewProtocol6,
			tcp.NewProtocol,
			udp.NewProtocol,
		},
		HandleLocal: true,
		NUDDisp:     nudDisp,

		RawFactory:               &raw.EndpointFactory{},
		AllowPacketEndpointWrite: true,
		Clock:                    &zxtime.Clock{},
	})

	delayEnabled := tcpip.TCPDelayEnabled(true)
	sackEnabled := tcpip.TCPSACKEnabled(true)
	moderateReceiveBufferOption := tcpip.TCPModerateReceiveBufferOption(true)
	for _, opt := range []tcpip.SettableTransportProtocolOption{
		&delayEnabled,
		&sackEnabled,
		&moderateReceiveBufferOption,
	} {
		if err := stk.SetTransportProtocolOption(tcp.ProtocolNumber, opt); err != nil {
			syslog.Fatalf("SetTransportProtocolOption(%d, %#v) failed: %s", tcp.ProtocolNumber, opt, err)
		}
	}

	f := filter.New(stk, &filterNicInfoProvider{stack: stk})

	interfaceEventChan := make(chan interfaceEvent)
	interfacesWatcherChan := make(chan interfaceWatcherRequest)
	fidlInterfaceWatcherStats := &fidlInterfaceWatcherStats{}
	go interfaceWatcherEventLoop(ctx, interfaceEventChan, interfacesWatcherChan, fidlInterfaceWatcherStats)

	interruptChan := make(chan routeInterrupt, maxPendingInterrupts)
	fidlRoutesWatcherMetrics := &fidlRoutesWatcherMetrics{}
	go routesWatcherEventLoop(ctx, interruptChan, fidlRoutesWatcherMetrics)

	ns := &Netstack{
		interfaceEventChan: interfaceEventChan,
		routeTable: routes.NewRouteTableWithOnChangeCallback(
			func(c routes.RoutingTableChange) {
				interruptChan <- &routingTableChange{c}
			},
		),
		dnsConfig:          dns.MakeServersConfig(stk.Clock()),
		stack:              stk,
		stats:              stats{Stats: stk.Stats()},
		nicRemovedHandlers: []NICRemovedHandler{&ndpDisp.dynamicAddressSourceTracker, f},
		featureFlags:       featureFlags{enableFastUDP: fastUDP},
	}

	fastUDPStatus := "disabled"
	if fastUDP {
		fastUDPStatus = "enabled"
	}
	_ = syslog.Infof("fast UDP is %s", fastUDPStatus)
	ns.resetDestinationCache()

	nudDisp.ns = ns
	ndpDisp.ns = ns
	ndpDisp.dynamicAddressSourceTracker.init(ns)

	filter.AddOutgoingService(componentCtx, f)

	{
		if err := ns.addLoopback(); err != nil {
			syslog.Fatalf("loopback: %s", err)
		}
		// Handle all of the already-enqueued NDP events so that DAD
		// completion for ::1 is observed. This ensures that clients
		// to the interface watcher are guaranteed to observe ::1 in
		// the Existing event rather than as a separate Changed event.
		for {
			event := func() ndpEvent {
				ndpDisp.mu.Lock()
				defer ndpDisp.mu.Unlock()

				if len(ndpDisp.mu.events) == 0 {
					return nil
				}
				return ndpDisp.mu.events[0]
			}()
			if event == nil {
				break
			}
			ndpDisp.handleEvent(event)
		}
	}

	ndpDisp.start(ctx)

	dnsWatchers := newDnsServerWatcherCollection(ns.dnsConfig.GetServersCacheAndChannel)

	if err := tracingprovider.Create(componentCtx); err != nil {
		syslog.Warnf("could not create a trace provider: %s", err)
		// Trace manager can not be running, or not available in the namespace. We can continue.
	}

	// The node at /root/fuchsia.inspect.Health is important for testing purposes
	// as it's the only node that is common to both NS2 and NS3.
	componentCtx.OutgoingService.AddDiagnostics("root", &component.DirectoryWrapper{
		Directory: &inspectDirectory{
			asService: (&inspectImpl{
				inner: &rootInspectImpl{
					name: "root",
					health: healthInspectImpl{
						name: "fuchsia.inspect.Health",
					},
				},
			}).asService,
		},
	})
	componentCtx.OutgoingService.AddDiagnostics("configuration", &component.DirectoryWrapper{
		Directory: &inspectDirectory{
			asService: (&inspectImpl{
				inner: &configInspectImpl{
					name:                   "Runtime Configuration Flags",
					logPackets:             &logPackets,
					logLevel:               logLevel,
					socketStatsTimerPeriod: socketStatsTimerPeriod,
					noOpaqueIID:            noOpaqueIID,
					fastUDP:                fastUDP,
					config: configDataInspectImpl{
						name:   "config-data",
						file:   *configFile,
						data:   config,
						numCPU: runtime.NumCPU(),
					},
				},
			}).asService,
		},
	})
	componentCtx.OutgoingService.AddDiagnostics("counters", &component.DirectoryWrapper{
		Directory: &inspectDirectory{
			asService: (&inspectImpl{
				inner: &networkingStatCountersInspectImpl{
					statCounterInspectImpl: statCounterInspectImpl{
						name:  "Networking Stat Counters",
						value: reflect.ValueOf(&ns.stats).Elem(),
					},
					ns: ns,
				},
			}).asService,
		},
	})
	componentCtx.OutgoingService.AddDiagnostics("interfaces", &component.DirectoryWrapper{
		Directory: &inspectDirectory{
			// asService is late-bound so that each call retrieves fresh NIC info.
			asService: func() *component.Service {
				return (&inspectImpl{
					inner: &nicInfoMapInspectImpl{value: ns.getIfStateInfo(stk.NICInfo())},
				}).asService()
			},
		},
	})
	componentCtx.OutgoingService.AddDiagnostics("fidlStats", &component.DirectoryWrapper{
		Directory: &inspectDirectory{
			asService: (&inspectImpl{
				inner: &fidlStatsInspectImpl{
					name:                      "Networking FIDL Protocol Stats",
					fidlInterfaceWatcherStats: fidlInterfaceWatcherStats,
					fidlRoutesWatcherMetrics:  fidlRoutesWatcherMetrics,
				},
			}).asService,
		},
	})
	componentCtx.OutgoingService.AddDiagnostics("sockets", &component.DirectoryWrapper{
		Directory: &inspectDirectory{
			asService: (&inspectImpl{
				inner: &socketInfoMapInspectImpl{
					value: &ns.endpoints,
				},
			}).asService,
		},
	})
	componentCtx.OutgoingService.AddDiagnostics("routes", &component.DirectoryWrapper{
		Directory: &inspectDirectory{
			// asService is late-bound so that each call retrieves fresh routing table info.
			asService: func() *component.Service {
				return (&inspectImpl{
					inner: &routingTableInspectImpl{value: ns.GetExtendedRouteTable()},
				}).asService()
			},
		},
	})
	componentCtx.OutgoingService.AddDiagnostics("memstats", &component.DirectoryWrapper{
		Directory: &inspectDirectory{
			// asService is late-bound so that each call retrieves fresh stats.
			asService: func() *component.Service {
				return (&inspectImpl{
					inner: &memstatsInspectImpl{},
				}).asService()
			},
		},
	})

	// Minimal support for the inspect VMO format allows our profile protos to be
	// picked up by bug reports.
	//
	// To extract these serialized protos from inspect.json, jq can be used:
	//
	// cat iquery.json | \
	// jq '.[] | select(.path | contains("/pprof/")) | .contents.root.pprof.goroutine[4:]' | \
	// xargs echo | base64 --decode > goroutine
	componentCtx.OutgoingService.AddDiagnostics("pprof", pprof.NewNode())

	// Periodically request that the persistence service save counters. This,
	// along with persisted logs, makes it easier to debug connectivity issues
	// before a reboot.
	startPersistClient(ctx, componentCtx, stk.Clock())

	{
		stub := verify.NetstackVerifierWithCtxStub{Impl: &verifier{}}
		componentCtx.OutgoingService.AddService(
			verify.NetstackVerifierName,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stub, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(verify.NetstackVerifierName, "%s", err)
					},
				})

				return nil
			},
		)
	}
	{
		tokenV4, err := zx.NewEvent(0 /* options */)
		if err != nil {
			panic("cannot initialize a zircon event")
		}
		stubV4 := routesAdmin.RouteTableV4WithCtxStub{
			Impl: &routesAdminRouteTableV4Impl{
				routesAdminMainRouteTable: routesAdminMainRouteTable{
					tableId: v4MainTableId,
					token:   tokenV4,
				},
				ns: ns,
			},
		}
		tokenV6, err := zx.NewEvent(0 /* options */)
		if err != nil {
			panic("cannot initialize a zircon event")
		}
		stubV6 := routesAdmin.RouteTableV6WithCtxStub{
			Impl: &routesAdminRouteTableV6Impl{
				routesAdminMainRouteTable: routesAdminMainRouteTable{
					tableId: v6MainTableId,
					token:   tokenV6,
				},
				ns: ns,
			},
		}
		componentCtx.OutgoingService.AddService(
			routesAdmin.RouteTableV4Name,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stubV4, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.ErrorTf(routesAdmin.RouteTableV4Name, "%s", err)
					},
				})
				return nil
			},
		)
		componentCtx.OutgoingService.AddService(
			routesAdmin.RouteTableV6Name,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stubV6, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.ErrorTf(routesAdmin.RouteTableV6Name, "%s", err)
					},
				})
				return nil
			},
		)
		stub := stack.StackWithCtxStub{Impl: &stackImpl{
			ns: ns,
		}}
		componentCtx.OutgoingService.AddService(
			stack.StackName,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stub, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(stack.StackName, "%s", err)
					},
				})
				return nil
			},
		)
	}

	componentCtx.OutgoingService.AddService(
		name.DnsServerWatcherName,
		dnsWatchers.bind,
	)

	{
		stub := stack.LogWithCtxStub{Impl: &logImpl{
			logPackets: &sniffer.LogPackets,
		}}
		componentCtx.OutgoingService.AddService(
			stack.LogName,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stub, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(stack.LogName, "%s", err)
					},
				})
				return nil
			})
	}

	{
		stub := socket.ProviderWithCtxStub{Impl: &providerImpl{ns: ns}}
		componentCtx.OutgoingService.AddService(
			socket.ProviderName,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stub, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(socket.ProviderName, "%s", err)
					},
				})
				return nil
			},
		)
	}

	{
		stub := rawsocket.ProviderWithCtxStub{Impl: &rawProviderImpl{ns: ns}}
		componentCtx.OutgoingService.AddService(
			rawsocket.ProviderName,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stub, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(rawsocket.ProviderName, "%s", err)
					},
				})
				return nil
			},
		)
	}

	{
		stub := packetsocket.ProviderWithCtxStub{Impl: &packetProviderImpl{ns: ns}}
		componentCtx.OutgoingService.AddService(
			packetsocket.ProviderName,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stub, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(packetsocket.ProviderName, "%s", err)
					},
				})
				return nil
			},
		)
	}

	{
		resolveImpl := resolveImpl{
			stack: ns.stack,
		}

		stub := fnetRoutes.StateWithCtxStub{Impl: &resolveImpl}
		componentCtx.OutgoingService.AddService(
			fnetRoutes.StateName,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stub, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(fnetRoutes.StateName, "%s", err)
					},
				})
				return nil
			},
		)
		getWatcherImpl := getWatcherImpl{
			interruptChan: interruptChan,
		}

		stub_v4 := fnetRoutes.StateV4WithCtxStub{Impl: &getWatcherImpl}
		componentCtx.OutgoingService.AddService(
			fnetRoutes.StateV4Name,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stub_v4, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(fnetRoutes.StateV4Name, "%s", err)
					},
				})
				return nil
			},
		)

		stub_v6 := fnetRoutes.StateV6WithCtxStub{Impl: &getWatcherImpl}
		componentCtx.OutgoingService.AddService(
			fnetRoutes.StateV6Name,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stub_v6, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(fnetRoutes.StateV6Name, "%s", err)
					},
				})
				return nil
			},
		)

	}

	{
		stub := interfaces.StateWithCtxStub{Impl: &interfaceStateImpl{watcherChan: interfacesWatcherChan}}
		componentCtx.OutgoingService.AddService(
			interfaces.StateName,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stub, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(interfaces.StateName, "%s", err)
					},
				})
				return nil
			},
		)
	}

	{
		stub := admin.InstallerWithCtxStub{Impl: &interfacesAdminInstallerImpl{ns: ns}}
		componentCtx.OutgoingService.AddService(
			admin.InstallerName,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stub, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(admin.InstallerName, "%s", err)
					},
				})
				return nil
			},
		)
	}

	{
		stub := debug.InterfacesWithCtxStub{Impl: &debugInterfacesImpl{ns: ns}}
		componentCtx.OutgoingService.AddService(
			debug.InterfacesName,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stub, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(debug.InterfacesName, "%s", err)
					},
				})
				return nil
			},
		)
	}

	{
		stub := root.InterfacesWithCtxStub{Impl: &rootInterfacesImpl{ns: ns}}
		componentCtx.OutgoingService.AddService(
			root.InterfacesName,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stub, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(debug.InterfacesName, "%s", err)
					},
				})
				return nil
			},
		)
	}

	{
		stub := root.RoutesV4WithCtxStub{Impl: &rootRoutesV4Impl{ns: ns}}
		componentCtx.OutgoingService.AddService(
			root.RoutesV4Name,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stub, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(root.RoutesV4Name, "%s", err)
					},
				})
				return nil
			},
		)
	}

	{
		stub := root.RoutesV6WithCtxStub{Impl: &rootRoutesV6Impl{ns: ns}}
		componentCtx.OutgoingService.AddService(
			root.RoutesV6Name,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stub, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(root.RoutesV6Name, "%s", err)
					},
				})
				return nil
			},
		)
	}

	{
		stub := debug.DiagnosticsWithCtxStub{Impl: &debugDiagnosticsImpl{}}
		componentCtx.OutgoingService.AddService(
			debug.DiagnosticsName,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &stub, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(debug.DiagnosticsName, "%s", err)
					},
				})
				return nil
			},
		)
	}

	{
		impl := newNeighborImpl(stk)

		viewStub := neighbor.ViewWithCtxStub{Impl: impl}
		componentCtx.OutgoingService.AddService(
			neighbor.ViewName,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &viewStub, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(neighbor.ViewName, "%s", err)
					},
				})
				return nil
			},
		)

		controllerStub := neighbor.ControllerWithCtxStub{Impl: impl}
		componentCtx.OutgoingService.AddService(
			neighbor.ControllerName,
			func(ctx context.Context, c zx.Channel) error {
				go component.Serve(ctx, &controllerStub, c, component.ServeOptions{
					OnError: func(err error) {
						_ = syslog.WarnTf(neighbor.ControllerName, "%s", err)
					},
				})
				return nil
			},
		)

		go impl.observeEvents(nudDisp.events)
	}

	addMulticastIpv4RoutingTableControllerService(componentCtx, ns.stack)
	addMulticastIpv6RoutingTableControllerService(componentCtx, ns.stack)

	componentCtx.BindStartupHandle(context.Background())
}

// newSecretKey returns a new secret key.
func newSecretKey(keyLen int) ([]byte, error) {
	secretKey := make([]byte, keyLen)
	if _, err := io.ReadFull(rand.Reader, secretKey); err != nil {
		return nil, fmt.Errorf("failed to populate a new secret key of %d bytes: %s", keyLen, err)
	}
	return secretKey, nil
}

// newSecretKeyForOpaqueIID returns a new secret key for opaque IID generation.
func newSecretKeyForOpaqueIID() ([]byte, error) {
	return newSecretKey(header.OpaqueIIDSecretKeyMinBytes)
}

// getSecretKeyForOpaqueIID gets a secret key for opaque IID generation from the
// secure stash store service, or attempts to create one. If the stash service
// is unavailable, a temporary secret key will be returned.
func getSecretKeyForOpaqueIID(componentCtx *component.Context) ([]byte, error) {
	syslog.VLogf(syslog.DebugVerbosity, "getting or creating secret key for opaque IID from secure stash store")

	// Connect to the secure stash store service.
	storeReq, store, err := stash.NewSecureStoreWithCtxInterfaceRequest()
	if err != nil {
		syslog.Errorf("could not create the request to connect to the %s service: %s", stash.SecureStoreName, err)
		return newSecretKeyForOpaqueIID()
	}
	defer func() {
		_ = store.Close()
	}()
	componentCtx.ConnectToEnvService(storeReq)

	// Use our secure stash.
	if err := store.Identify(context.Background(), stashStoreIdentificationName); err != nil {
		syslog.Warnf("failed to identify as %s to the secure stash store: %s", stashStoreIdentificationName, err)
		return newSecretKeyForOpaqueIID()
	}
	storeAccessorReq, storeAccessor, err := stash.NewStoreAccessorWithCtxInterfaceRequest()
	if err != nil {
		syslog.Errorf("could not create the secure stash store accessor request: %s", err)
		return newSecretKeyForOpaqueIID()
	}
	defer func() {
		_ = storeAccessor.Close()
	}()
	if err := store.CreateAccessor(context.Background(), false /* readOnly */, storeAccessorReq); err != nil {
		syslog.Warnf("failed to create accessor to the secure stash store: %s", err)
		return newSecretKeyForOpaqueIID()
	}

	// Attempt to get the existing secret key.
	opaqueIIDSecretKeyValue, err := storeAccessor.GetValue(context.Background(), opaqueIIDSecretKeyName)
	if err != nil {
		syslog.Warnf("failed to get opaque IID secret key from secure stash store: %s", err)
		return newSecretKeyForOpaqueIID()
	}

	// If a key exists, make sure it is valid before returning it.
	//
	// The value should be stored as a base64 encoded string.
	//
	// We use a string because stash.Value.Bytesval uses a fuchsia.mem.Buffer
	// which uses a VMO (which uses memory in page size increments). This is
	// wasteful as the key only uses 16 bytes. We base64 encode the string
	// because stash.Value.Stringval expects an ascii string; the store returns an
	// error when flushing the store with a stash.Value.Stringval of raw bytes.
	if opaqueIIDSecretKeyValue != nil && opaqueIIDSecretKeyValue.Which() == stash.ValueStringval {
		syslog.VLogf(syslog.DebugVerbosity, "found a secret key for opaque IIDs in the secure stash store")

		if secretKey, err := base64.StdEncoding.DecodeString(opaqueIIDSecretKeyValue.Stringval); err != nil {
			syslog.Errorf("failed to decode the secret key string: %s", err)
		} else if l := len(secretKey); l != header.OpaqueIIDSecretKeyMinBytes {
			syslog.Errorf("invalid secret key for opaque IIDs; got length = %d, want = %d", l, header.OpaqueIIDSecretKeyMinBytes)
		} else {
			syslog.VLogf(syslog.DebugVerbosity, "using existing secret key for opaque IIDs")
			return secretKey, nil
		}
	}

	// Generate a new secret key as we either do not have one or the one we have
	// is invalid.
	syslog.VLogf(syslog.DebugVerbosity, "generating a new secret key for opaque IIDs")
	secretKey, err := newSecretKeyForOpaqueIID()
	if err != nil {
		return nil, err
	}

	// Store the newly generated key to the secure stash store as a base64
	// encoded string.
	if err := storeAccessor.SetValue(context.Background(), opaqueIIDSecretKeyName, stash.ValueWithStringval(base64.StdEncoding.EncodeToString(secretKey))); err != nil {
		syslog.Errorf("failed to set newly created secret key for opaque IID to secure stash store: %s", err)
		return secretKey, nil
	}
	flushResp, err := storeAccessor.Flush(context.Background())
	if err != nil {
		syslog.Errorf("failed to flush secure stash store with updated secret key for opaque IID: %s", err)
		return secretKey, nil
	}
	switch w := flushResp.Which(); w {
	case stash.StoreAccessorFlushResultErr:
		syslog.Errorf("got error response when flushing secure stash store with updated secret key for opaque IID: %s", flushResp.Err)
		return secretKey, nil

	case stash.StoreAccessorFlushResultResponse:
		syslog.VLogf(syslog.DebugVerbosity, "saved newly generated secret key for opaque IIDs to secure stash store")
		return secretKey, nil

	default:
		panic(fmt.Sprintf("unexpected store accessor flush result type: %d", w))
	}
}

var _ verify.NetstackVerifierWithCtx = (*verifier)(nil)

type verifier struct{}

func (*verifier) Verify(fidl.Context, verify.VerifyOptions) (verify.VerifierVerifyResult, error) {
	// Wait an arbitrary amount of time; if we didn't crash, we're probably healthy.
	<-time.After(15 * time.Second)
	return verify.VerifierVerifyResultWithResponse(verify.VerifierVerifyResponse{}), nil
}
