blob: 8bed62ed14c309358c2ef265c3a00ef305242931 [file] [log] [blame] [edit]
// 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
}