Skip to content

Commit eb2c1a9

Browse files
committed
Hacks for ipv6
1 parent 2199d4c commit eb2c1a9

File tree

3 files changed

+110
-0
lines changed

3 files changed

+110
-0
lines changed

pkg/tap/link.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import (
99
"gvisor.dev/gvisor/pkg/tcpip"
1010
"gvisor.dev/gvisor/pkg/tcpip/buffer"
1111
"gvisor.dev/gvisor/pkg/tcpip/header"
12+
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
1213
"gvisor.dev/gvisor/pkg/tcpip/stack"
14+
"gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
1315
)
1416

1517
type LinkEndpoint struct {
@@ -111,6 +113,17 @@ func (e *LinkEndpoint) WritePacket(r stack.RouteInfo, protocol tcpip.NetworkProt
111113
}
112114
}
113115

116+
if pkt.NetworkProtocolNumber == ipv6.ProtocolNumber && pkt.TransportProtocolNumber == icmp.ProtocolNumber6 {
117+
transportLayer := header.ICMPv6(pkt.TransportHeader().View())
118+
if transportLayer.Type() == header.ICMPv6NeighborAdvert {
119+
ip := header.NDPNeighborAdvert(transportLayer.MessageBody()).TargetAddress().String()
120+
if ip != "fe80::1" {
121+
log.Debugf("dropping spoofing packets from the gateway about IP %s", ip)
122+
return nil
123+
}
124+
}
125+
}
126+
114127
if e.debug {
115128
vv := buffer.NewVectorisedView(pkt.Size(), pkt.Views())
116129
packet := gopacket.NewPacket(vv.ToView(), layers.LayerTypeEthernet, gopacket.Default)

pkg/tap/router_advertisement.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package tap
2+
3+
import (
4+
"encoding/binary"
5+
6+
"gvisor.dev/gvisor/pkg/tcpip"
7+
"gvisor.dev/gvisor/pkg/tcpip/buffer"
8+
"gvisor.dev/gvisor/pkg/tcpip/header"
9+
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
10+
"gvisor.dev/gvisor/pkg/tcpip/stack"
11+
"gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
12+
)
13+
14+
// raBuf returns a valid NDP Router Advertisement with options, router
15+
// preference and DHCPv6 configurations specified.
16+
func raBuf(src, dst tcpip.LinkAddress, ip tcpip.Address, rl uint16, managedAddress, otherConfigurations bool, prf header.NDPRoutePreference, optSer header.NDPOptionsSerializer) *stack.PacketBuffer {
17+
const flagsByte = 1
18+
const routerLifetimeOffset = 2
19+
20+
icmpSize := header.ICMPv6HeaderSize + header.NDPRAMinimumSize + optSer.Length()
21+
hdr := buffer.NewPrependable(header.EthernetMinimumSize + header.IPv6MinimumSize + icmpSize)
22+
pkt := header.ICMPv6(hdr.Prepend(icmpSize))
23+
pkt.SetType(header.ICMPv6RouterAdvert)
24+
pkt.SetCode(0)
25+
raPayload := pkt.MessageBody()
26+
ra := header.NDPRouterAdvert(raPayload)
27+
// Populate the Router Lifetime.
28+
binary.BigEndian.PutUint16(raPayload[routerLifetimeOffset:], rl)
29+
// Populate the Managed Address flag field.
30+
if managedAddress {
31+
// The Managed Addresses flag field is the 7th bit of the flags byte.
32+
raPayload[flagsByte] |= 1 << 7
33+
}
34+
// Populate the Other Configurations flag field.
35+
if otherConfigurations {
36+
// The Other Configurations flag field is the 6th bit of the flags byte.
37+
raPayload[flagsByte] |= 1 << 6
38+
}
39+
// The Prf field is held in the flags byte.
40+
raPayload[flagsByte] |= byte(prf) << 3
41+
opts := ra.Options()
42+
opts.Serialize(optSer)
43+
pkt.SetChecksum(header.ICMPv6Checksum(header.ICMPv6ChecksumParams{
44+
Header: pkt,
45+
Src: ip,
46+
Dst: header.IPv6AllNodesMulticastAddress,
47+
}))
48+
payloadLength := hdr.UsedLength()
49+
iph := header.IPv6(hdr.Prepend(header.IPv6MinimumSize))
50+
iph.Encode(&header.IPv6Fields{
51+
PayloadLength: uint16(payloadLength),
52+
TransportProtocol: icmp.ProtocolNumber6,
53+
HopLimit: header.NDPHopLimit,
54+
SrcAddr: ip,
55+
DstAddr: header.IPv6AllNodesMulticastAddress,
56+
})
57+
58+
eth := header.Ethernet(hdr.Prepend(header.EthernetMinimumSize))
59+
eth.Encode(&header.EthernetFields{
60+
Type: ipv6.ProtocolNumber,
61+
SrcAddr: src,
62+
DstAddr: dst,
63+
})
64+
return stack.NewPacketBuffer(stack.PacketBufferOptions{
65+
Data: hdr.View().ToVectorisedView(),
66+
})
67+
}
68+
69+
// raBufWithOpts returns a valid NDP Router Advertisement with options.
70+
//
71+
// Note, raBufWithOpts does not populate any of the RA fields other than the
72+
// Router Lifetime.
73+
func raBufWithOpts(src, dst tcpip.LinkAddress, ip tcpip.Address, rl uint16, optSer header.NDPOptionsSerializer) *stack.PacketBuffer {
74+
return raBuf(src, dst, ip, rl, false /* managedAddress */, false /* otherConfigurations */, 0 /* prf */, optSer)
75+
}
76+
77+
// raBuf returns a valid NDP Router Advertisement.
78+
//
79+
// Note, raBuf does not populate any of the RA fields other than the
80+
// Router Lifetime.
81+
func raBufSimple(src, dst tcpip.LinkAddress, ip tcpip.Address, rl uint16) *stack.PacketBuffer {
82+
return raBufWithOpts(src, dst, ip, rl, header.NDPOptionsSerializer{})
83+
}

pkg/tap/switch.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"gvisor.dev/gvisor/pkg/tcpip"
1616
"gvisor.dev/gvisor/pkg/tcpip/buffer"
1717
"gvisor.dev/gvisor/pkg/tcpip/header"
18+
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
1819
"gvisor.dev/gvisor/pkg/tcpip/stack"
1920
)
2021

@@ -217,6 +218,19 @@ loop:
217218
e.cam[eth.SourceAddress()] = id
218219
e.camLock.Unlock()
219220

221+
if eth.Type() == ipv6.ProtocolNumber {
222+
networkLayer := header.IPv6(buf[header.EthernetMinimumSize:])
223+
if networkLayer.TransportProtocol() == header.ICMPv6ProtocolNumber {
224+
transportLayer := header.ICMPv6(networkLayer.Payload())
225+
if transportLayer.Type() == header.ICMPv6RouterSolicit {
226+
routerAdvertisement := raBufSimple(e.gateway.LinkAddress(), eth.SourceAddress(), tcpip.Address(net.ParseIP("fe80::1")), 1000)
227+
if err := e.tx(e.gateway.LinkAddress(), eth.SourceAddress(), routerAdvertisement); err != nil {
228+
log.Error(err)
229+
}
230+
}
231+
}
232+
}
233+
220234
if eth.DestinationAddress() != e.gateway.LinkAddress() {
221235
if err := e.tx(eth.SourceAddress(), eth.DestinationAddress(), stack.NewPacketBuffer(stack.PacketBufferOptions{
222236
Data: vv,

0 commit comments

Comments
 (0)