@ -70,29 +70,29 @@ type Network struct {
Prefix6 netaddr . IPPrefix
Prefix6 netaddr . IPPrefix
mu sync . Mutex
mu sync . Mutex
machine map [ netaddr . IP ] * Machin e
machine map [ netaddr . IP ] * Interfac e
defaultGW * Machin e // optional
defaultGW * Interfac e // optional
lastV4 netaddr . IP
lastV4 netaddr . IP
lastV6 netaddr . IP
lastV6 netaddr . IP
}
}
func ( n * Network ) SetDefaultGateway ( gw * Machin e) {
func ( n * Network ) SetDefaultGateway ( gw If * Interfac e) {
n . mu . Lock ( )
n . mu . Lock ( )
defer n . mu . Unlock ( )
defer n . mu . Unlock ( )
n . defaultGW = gw
n . defaultGW = gw If
}
}
func ( n * Network ) addMachineLocked ( ip netaddr . IP , m * Machin e) {
func ( n * Network ) addMachineLocked ( ip netaddr . IP , iface * Interfac e) {
if m == nil {
if iface == nil {
return // for tests
return // for tests
}
}
if n . machine == nil {
if n . machine == nil {
n . machine = map [ netaddr . IP ] * Machin e{ }
n . machine = map [ netaddr . IP ] * Interfac e{ }
}
}
n . machine [ ip ] = m
n . machine [ ip ] = iface
}
}
func ( n * Network ) allocIPv4 ( m * Machin e) netaddr . IP {
func ( n * Network ) allocIPv4 ( iface * Interfac e) netaddr . IP {
n . mu . Lock ( )
n . mu . Lock ( )
defer n . mu . Unlock ( )
defer n . mu . Unlock ( )
if n . Prefix4 . IsZero ( ) {
if n . Prefix4 . IsZero ( ) {
@ -107,11 +107,11 @@ func (n *Network) allocIPv4(m *Machine) netaddr.IP {
if ! n . Prefix4 . Contains ( n . lastV4 ) {
if ! n . Prefix4 . Contains ( n . lastV4 ) {
panic ( "pool exhausted" )
panic ( "pool exhausted" )
}
}
n . addMachineLocked ( n . lastV4 , m )
n . addMachineLocked ( n . lastV4 , iface )
return n . lastV4
return n . lastV4
}
}
func ( n * Network ) allocIPv6 ( m * Machin e) netaddr . IP {
func ( n * Network ) allocIPv6 ( iface * Interfac e) netaddr . IP {
n . mu . Lock ( )
n . mu . Lock ( )
defer n . mu . Unlock ( )
defer n . mu . Unlock ( )
if n . Prefix6 . IsZero ( ) {
if n . Prefix6 . IsZero ( ) {
@ -126,7 +126,7 @@ func (n *Network) allocIPv6(m *Machine) netaddr.IP {
if ! n . Prefix6 . Contains ( n . lastV6 ) {
if ! n . Prefix6 . Contains ( n . lastV6 ) {
panic ( "pool exhausted" )
panic ( "pool exhausted" )
}
}
n . addMachineLocked ( n . lastV6 , m )
n . addMachineLocked ( n . lastV6 , iface )
return n . lastV6
return n . lastV6
}
}
@ -142,27 +142,28 @@ func addOne(a *[16]byte, index int) {
func ( n * Network ) write ( p [ ] byte , dst , src netaddr . IPPort ) ( num int , err error ) {
func ( n * Network ) write ( p [ ] byte , dst , src netaddr . IPPort ) ( num int , err error ) {
n . mu . Lock ( )
n . mu . Lock ( )
defer n . mu . Unlock ( )
defer n . mu . Unlock ( )
m , ok := n . machine [ dst . IP ]
iface , ok := n . machine [ dst . IP ]
if ! ok {
if ! ok {
if n . defaultGW == nil {
if n . defaultGW == nil {
trace ( p , "net=%s dropped, no route to %v" , n . Name , dst . IP )
trace ( p , "net=%s dropped, no route to %v" , n . Name , dst . IP )
return len ( p ) , nil
return len ( p ) , nil
}
}
m = n . defaultGW
iface = n . defaultGW
}
}
// Pretend it went across the network. Make a copy so nobody
// Pretend it went across the network. Make a copy so nobody
// can later mess with caller's memory.
// can later mess with caller's memory.
trace ( p , "net=%s src=%v dst=%v -> mach=%s ", n . Name , src , dst , m. N ame)
trace ( p , "net=%s src=%v dst=%v -> mach=%s iface=%s ", n . Name , src , dst , iface. machine . N ame, iface . n ame)
pcopy := append ( [ ] byte ( nil ) , p ... )
pcopy := append ( [ ] byte ( nil ) , p ... )
go m. deliverIncomingPacket ( pcopy , dst , src )
go iface. machine . deliverIncomingPacket ( pcopy , iface , dst , src )
return len ( p ) , nil
return len ( p ) , nil
}
}
type Interface struct {
type Interface struct {
net * Network
machine * Machine
name string // optional
net * Network
ips [ ] netaddr . IP // static; not mutated once created
name string // optional
ips [ ] netaddr . IP // static; not mutated once created
}
}
// V4 returns the machine's first IPv4 address, or the zero value if none.
// V4 returns the machine's first IPv4 address, or the zero value if none.
@ -226,7 +227,7 @@ func (v PacketVerdict) String() string {
}
}
// A PacketHandler is a function that can process packets.
// A PacketHandler is a function that can process packets.
type PacketHandler func ( p [ ] byte , dst, src netaddr . IPPort ) PacketVerdict
type PacketHandler func ( p [ ] byte , inIf * Interface , dst, src netaddr . IPPort ) PacketVerdict
// A Machine is a representation of an operating system's network
// A Machine is a representation of an operating system's network
// stack. It has a network routing table and can have multiple
// stack. It has a network routing table and can have multiple
@ -261,11 +262,11 @@ func (m *Machine) Inject(p []byte, dst, src netaddr.IPPort) error {
return err
return err
}
}
func ( m * Machine ) deliverIncomingPacket ( p [ ] byte , dst, src netaddr . IPPort ) {
func ( m * Machine ) deliverIncomingPacket ( p [ ] byte , iface * Interface , dst, src netaddr . IPPort ) {
// TODO: can't hold lock while handling packet. This is safe as
// TODO: can't hold lock while handling packet. This is safe as
// long as you set HandlePacket before traffic starts flowing.
// long as you set HandlePacket before traffic starts flowing.
if m . HandlePacket != nil {
if m . HandlePacket != nil {
verdict := m . HandlePacket ( p , dst, src )
verdict := m . HandlePacket ( p , iface, dst, src )
trace ( p , "mach=%s src=%v dst=%v packethandler verdict=%s" , m . Name , src , dst , verdict )
trace ( p , "mach=%s src=%v dst=%v packethandler verdict=%s" , m . Name , src , dst , verdict )
if verdict == Drop {
if verdict == Drop {
// Custom packet handler ate the packet, we're done.
// Custom packet handler ate the packet, we're done.
@ -318,13 +319,14 @@ func unspecOf(ip netaddr.IP) netaddr.IP {
// default route.
// default route.
func ( m * Machine ) Attach ( interfaceName string , n * Network ) * Interface {
func ( m * Machine ) Attach ( interfaceName string , n * Network ) * Interface {
f := & Interface {
f := & Interface {
net : n ,
machine : m ,
name : interfaceName ,
net : n ,
name : interfaceName ,
}
}
if ip := n . allocIPv4 ( m ) ; ! ip . IsZero ( ) {
if ip := n . allocIPv4 ( f ) ; ! ip . IsZero ( ) {
f . ips = append ( f . ips , ip )
f . ips = append ( f . ips , ip )
}
}
if ip := n . allocIPv6 ( m ) ; ! ip . IsZero ( ) {
if ip := n . allocIPv6 ( f ) ; ! ip . IsZero ( ) {
f . ips = append ( f . ips , ip )
f . ips = append ( f . ips , ip )
}
}