| // 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 ( |
| "flag" |
| "log" |
| "syscall/zx" |
| "syscall/zx/fidl" |
| |
| "app/context" |
| "netstack/connectivity" |
| "netstack/dns" |
| "netstack/filter" |
| "netstack/link/eth" |
| |
| "fidl/fuchsia/devicesettings" |
| "fidl/fuchsia/net" |
| "fidl/fuchsia/net/stack" |
| "fidl/fuchsia/netstack" |
| |
| "github.com/google/netstack/tcpip" |
| "github.com/google/netstack/tcpip/network/arp" |
| "github.com/google/netstack/tcpip/network/ipv4" |
| "github.com/google/netstack/tcpip/network/ipv6" |
| tcpipstack "github.com/google/netstack/tcpip/stack" |
| "github.com/google/netstack/tcpip/transport/ping" |
| "github.com/google/netstack/tcpip/transport/tcp" |
| "github.com/google/netstack/tcpip/transport/udp" |
| ) |
| |
| var OnInterfacesChanged func() |
| |
| func main() { |
| flag.Parse() |
| log.SetFlags(0) |
| log.SetPrefix("netstack: ") |
| log.Print("started") |
| |
| ctx := context.CreateFromStartupInfo() |
| |
| stk := tcpipstack.New([]string{ |
| ipv4.ProtocolName, |
| ipv6.ProtocolName, |
| arp.ProtocolName, |
| }, []string{ |
| ping.ProtocolName4, |
| tcp.ProtocolName, |
| udp.ProtocolName, |
| }, tcpipstack.Options{}) |
| if err := stk.SetTransportProtocolOption(tcp.ProtocolNumber, tcp.SACKEnabled(true)); err != nil { |
| log.Fatalf("method SetTransportProtocolOption(%v, tcp.SACKEnabled(true)) failed: %v", tcp.ProtocolNumber, err) |
| } |
| |
| s, err := newSocketServer(stk, ctx) |
| if err != nil { |
| log.Fatal(err) |
| } |
| log.Print("socket server started") |
| |
| arena, err := eth.NewArena() |
| if err != nil { |
| log.Fatalf("ethernet: %s", err) |
| } |
| |
| req, ds, err := devicesettings.NewDeviceSettingsManagerInterfaceRequest() |
| if err != nil { |
| log.Fatalf("could not connect to device settings service: %s", err) |
| } |
| |
| ctx.ConnectToEnvService(req) |
| |
| ns := &Netstack{ |
| arena: arena, |
| socketServer: s, |
| dnsClient: dns.NewClient(stk), |
| deviceSettings: ds, |
| ifStates: make(map[tcpip.NICID]*ifState), |
| } |
| ns.mu.stack = stk |
| |
| if err := ns.addLoopback(); err != nil { |
| log.Fatalf("loopback: %s", err) |
| } |
| |
| s.setNetstack(ns) |
| |
| // TODO(NET-1263): register resolver admin service once clients don't crash netstack |
| // var dnsService netstack.ResolverAdminService |
| var netstackService netstack.NetstackService |
| |
| OnInterfacesChanged = func() { |
| interfaces := getInterfaces(ns) |
| connectivity.InferAndNotify(interfaces) |
| for key := range netstackService.Bindings { |
| if p, ok := netstackService.EventProxyFor(key); ok { |
| if err := p.OnInterfacesChanged(interfaces); err != nil { |
| log.Printf("OnInterfacesChanged failed: %v", err) |
| } |
| } |
| } |
| } |
| |
| ctx.OutgoingService.AddService(netstack.NetstackName, func(c zx.Channel) error { |
| k, err := netstackService.Add(&netstackImpl{ |
| ns: ns, |
| }, c, nil) |
| if err != nil { |
| log.Fatal(err) |
| } |
| // Send a synthetic InterfacesChanged event to each client when they join |
| // Prevents clients from having to race GetInterfaces / InterfacesChanged. |
| if p, ok := netstackService.EventProxyFor(k); ok { |
| if err := p.OnInterfacesChanged(getInterfaces(ns)); err != nil { |
| log.Printf("OnInterfacesChanged failed: %v", err) |
| } |
| } |
| return nil |
| }) |
| |
| // TODO(NET-1263): register resolver admin service once clients don't crash netstack |
| // when registering. |
| // ctx.OutgoingService.AddService(netstack.ResolverAdminName, func(c zx.Channel) error { |
| // _, err := dnsService.Add(&dnsImpl{ns: ns}, c, nil) |
| // return err |
| // }) |
| |
| var stackService stack.StackService |
| ctx.OutgoingService.AddService(stack.StackName, func(c zx.Channel) error { |
| _, err := stackService.Add(&stackImpl{ns: ns}, c, nil) |
| return err |
| }) |
| |
| var socketProvider net.LegacySocketProviderService |
| ctx.OutgoingService.AddService(net.LegacySocketProviderName, func(c zx.Channel) error { |
| _, err := socketProvider.Add(&socketProviderImpl{ns: ns}, c, nil) |
| return err |
| }) |
| if err := connectivity.AddOutgoingService(ctx); err != nil { |
| log.Fatal(err) |
| } |
| |
| f := filter.New(stk.PortManager) |
| if err := filter.AddOutgoingService(ctx, f); err != nil { |
| log.Fatal(err) |
| } |
| ns.filter = f |
| |
| ctx.Serve() |
| |
| // Serve FIDL bindings on two threads. Since the Go FIDL bindings are blocking, |
| // this allows two outstanding requests at a time. |
| // TODO(tkilbourn): revisit this and tune the number of serving threads. |
| for i := 0; i < 2; i++ { |
| go fidl.Serve() |
| } |
| |
| <-(chan struct{})(nil) |
| } |