| // Copyright 2020 The Go 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 mod` ignores file names for the purpose of resolving |
| // dependencies, and fdio doesn't build on not-Fuchsia. |
| //go:build fuchsia |
| |
| package net |
| |
| import ( |
| "context" |
| "fmt" |
| "sync" |
| "syscall/zx" |
| "syscall/zx/fdio" |
| "syscall/zx/hardware/network" |
| "syscall/zx/net/interfaces" |
| ) |
| |
| var state struct { |
| mu struct { |
| sync.Mutex |
| proxy *interfaces.StateWithCtxInterface |
| } |
| } |
| |
| func stateClient() (*interfaces.StateWithCtxInterface, error) { |
| state.mu.Lock() |
| defer state.mu.Unlock() |
| |
| if state.mu.proxy == nil { |
| request, proxy, err := interfaces.NewStateWithCtxInterfaceRequest() |
| if err != nil { |
| return nil, err |
| } |
| if err := fdio.ServiceConnect("/svc/"+interfaces.StateName, zx.Handle(request.ToChannel())); err != nil { |
| return nil, err |
| } |
| state.mu.proxy = proxy |
| } |
| return state.mu.proxy, nil |
| } |
| |
| // If the ifindex is zero, interfaceTable returns mappings of all |
| // network interfaces. Otherwise it returns a mapping of a specific interface. |
| func interfaceTable(ifindex int) ([]Interface, error) { |
| c, err := stateClient() |
| if err != nil { |
| return nil, err |
| } |
| request, watcher, err := interfaces.NewWatcherWithCtxInterfaceRequest() |
| if err != nil { |
| return nil, err |
| } |
| if err := c.GetWatcher(context.Background(), interfaces.WatcherOptions{}, request); err != nil { |
| return nil, err |
| } |
| var ifs []Interface |
| for { |
| event, err := watcher.Watch(context.Background()) |
| if err != nil { |
| return nil, err |
| } |
| switch w := event.Which(); w { |
| case interfaces.EventIdle: |
| return ifs, nil |
| case interfaces.EventExisting: |
| i := Interface{ |
| Index: int(event.Existing.GetId()), |
| MTU: 0, |
| Name: event.Existing.GetName(), |
| HardwareAddr: nil, |
| } |
| if event.Existing.GetOnline() { |
| // TODO(https://fxbug.dev/44532): uncomment this; some tests are gated |
| // on this and will need to be updated. |
| // i.Flags |= FlagUp |
| } |
| switch class := event.Existing.GetDeviceClass(); class.Which() { |
| case interfaces.DeviceClassLoopback: |
| i.Flags |= FlagLoopback |
| case interfaces.DeviceClassDevice: |
| // TODO(https://fxbug.dev/44532): Set Flag{Broadcast,Multicast}. |
| switch class.Device { |
| case network.DeviceClassPpp: |
| i.Flags |= FlagPointToPoint |
| } |
| } |
| ifs = append(ifs, i) |
| default: |
| return nil, fmt.Errorf("unexpected event %d: %#v", w, event) |
| } |
| } |
| } |
| |
| // If the ifi is nil, interfaceAddrTable returns addresses for all |
| // network interfaces. Otherwise it returns addresses for a specific interface. |
| func interfaceAddrTable(ifi *Interface) ([]Addr, error) { |
| // TODO(44532): implement |
| return nil, nil |
| } |
| |
| // interfaceMulticastAddrTable returns addresses for a specific interface. |
| func interfaceMulticastAddrTable(ifi *Interface) ([]Addr, error) { |
| // TODO(44532): implement |
| return nil, nil |
| } |