| // Copyright 2018 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 fidlconv |
| |
| import ( |
| "fmt" |
| "net" |
| |
| netfidl "fidl/fuchsia/net" |
| "fidl/fuchsia/net/stack" |
| |
| "gvisor.dev/gvisor/pkg/tcpip" |
| ) |
| |
| func toNet(addr netfidl.IpAddress) net.IP { |
| switch tag := addr.Which(); tag { |
| case netfidl.IpAddressIpv4: |
| return addr.Ipv4.Addr[:] |
| case netfidl.IpAddressIpv6: |
| return addr.Ipv6.Addr[:] |
| default: |
| panic(fmt.Sprintf("invalid IP address tag = %d", tag)) |
| } |
| } |
| |
| func ToTCPIPAddress(addr netfidl.IpAddress) tcpip.Address { |
| return tcpip.Address(toNet(addr)) |
| } |
| |
| func ToNetIpAddress(addr tcpip.Address) netfidl.IpAddress { |
| switch l := len(addr); l { |
| case net.IPv4len: |
| var ipv4 netfidl.Ipv4Address |
| copy(ipv4.Addr[:], addr) |
| return netfidl.IpAddressWithIpv4(ipv4) |
| case net.IPv6len: |
| var ipv6 netfidl.Ipv6Address |
| copy(ipv6.Addr[:], addr) |
| return netfidl.IpAddressWithIpv6(ipv6) |
| default: |
| panic(fmt.Sprintf("invalid IP address length = %d: %x", l, addr)) |
| } |
| } |
| |
| func ToNetSocketAddress(addr tcpip.FullAddress) netfidl.SocketAddress { |
| var out netfidl.SocketAddress |
| switch l := len(addr.Addr); l { |
| case net.IPv4len: |
| var ipv4 netfidl.Ipv4Address |
| copy(ipv4.Addr[:], addr.Addr) |
| out.SetIpv4(netfidl.Ipv4SocketAddress{ |
| Address: ipv4, |
| Port: addr.Port, |
| }) |
| case net.IPv6len: |
| var ipv6 netfidl.Ipv6Address |
| copy(ipv6.Addr[:], addr.Addr) |
| out.SetIpv6(netfidl.Ipv6SocketAddress{ |
| Address: ipv6, |
| Port: addr.Port, |
| ZoneIndex: uint64(addr.NIC), |
| }) |
| default: |
| panic(fmt.Sprintf("invalid IP address length = %d: %x", l, addr.Addr)) |
| } |
| return out |
| } |
| |
| func ToTCPIPSubnet(sn netfidl.Subnet) tcpip.Subnet { |
| a := toNet(sn.Addr) |
| m := net.CIDRMask(int(sn.PrefixLen), len(a)*8) |
| subnet, err := tcpip.NewSubnet(tcpip.Address(a.Mask(m)), tcpip.AddressMask(m)) |
| if err != nil { |
| panic(err) |
| } |
| return subnet |
| } |
| |
| func TcpipRouteToForwardingEntry(route tcpip.Route) stack.ForwardingEntry { |
| forwardingEntry := stack.ForwardingEntry{ |
| Subnet: netfidl.Subnet{ |
| Addr: ToNetIpAddress(route.Destination.ID()), |
| PrefixLen: uint8(route.Destination.Prefix()), |
| }, |
| } |
| // There are two types of destinations: link-local and next-hop. |
| // If a route has a gateway, use that as the next-hop, and ignore the NIC. |
| // Otherwise, it is considered link-local, and use the NIC. |
| if len(route.Gateway) == 0 { |
| forwardingEntry.Destination.SetDeviceId(uint64(route.NIC)) |
| } else { |
| forwardingEntry.Destination.SetNextHop(ToNetIpAddress(route.Gateway)) |
| } |
| return forwardingEntry |
| } |
| |
| func ForwardingEntryToTcpipRoute(forwardingEntry stack.ForwardingEntry) tcpip.Route { |
| route := tcpip.Route{ |
| Destination: ToTCPIPSubnet(forwardingEntry.Subnet), |
| } |
| switch forwardingEntry.Destination.Which() { |
| case stack.ForwardingDestinationDeviceId: |
| route.NIC = tcpip.NICID(forwardingEntry.Destination.DeviceId) |
| case stack.ForwardingDestinationNextHop: |
| route.Gateway = ToTCPIPAddress(forwardingEntry.Destination.NextHop) |
| } |
| return route |
| } |