diff options
-rw-r--r-- | pkg/tcpip/link/gre/gre.go | 115 | ||||
-rw-r--r-- | pkg/tcpip/sample/tun_tcp_connect/main.go | 114 |
2 files changed, 119 insertions, 110 deletions
diff --git a/pkg/tcpip/link/gre/gre.go b/pkg/tcpip/link/gre/gre.go index 254a1b4d6..38d281e86 100644 --- a/pkg/tcpip/link/gre/gre.go +++ b/pkg/tcpip/link/gre/gre.go @@ -1,11 +1,18 @@ package gre import ( + "context" "log" "gvisor.dev/gvisor/pkg/tcpip" + "gvisor.dev/gvisor/pkg/tcpip/buffer" + "gvisor.dev/gvisor/pkg/tcpip/header" "gvisor.dev/gvisor/pkg/tcpip/link/channel" + "gvisor.dev/gvisor/pkg/tcpip/network/ipv4" "gvisor.dev/gvisor/pkg/tcpip/stack" + "gvisor.dev/gvisor/pkg/tcpip/transport/gre" + "gvisor.dev/gvisor/pkg/tcpip/transport/raw" + "gvisor.dev/gvisor/pkg/waiter" ) var SIZE = 16 @@ -36,3 +43,111 @@ func (e *Endpoint) Attach(dispatcher stack.NetworkDispatcher) { e.Endpoint.Attach(dispatcher) } + +type GrePacketInfo struct { + pi *channel.PacketInfo +} + +func (g GrePacketInfo) FullPayload() ([]byte, *tcpip.Error){ + log.Println("FullPayload") + pkt := g.pi.Pkt + size := pkt.Size() + vv := buffer.NewVectorisedView(size, pkt.Views()) + var buf = make([]byte, size, size) + pos := 0 + for { + copied, err := vv.Read(buf[pos:]) + log.Printf("VectorisedView Read: %d %d %d %v", size, pos, copied, err) + if err != nil { + return nil, tcpip.ErrBadBuffer + } + pos = pos + copied + if pos == size { + break + } + } + + log.Printf("FullPayload return: %d %v", len(buf), buf) + return buf, nil +} + +func (g GrePacketInfo) Payload(size int) ([]byte, *tcpip.Error){ + log.Println("Payload") + return nil, tcpip.ErrNotSupported +} + +type GreHandlerInfo struct { + ChEp *channel.Endpoint + Raw tcpip.Endpoint + Raddr tcpip.FullAddress +} + +func (info *GreHandlerInfo) greHandler(req *gre.ForwarderRequest) { + pkt := req.Pkt + log.Println("greHandler: ", req.Pkt.Size(), req.Pkt.Views()) + greHdr := header.GRE(pkt.TransportHeader().View()) + proto := greHdr.ProtocolType() + views := pkt.Data.Views() + size := pkt.Data.Size() + data := buffer.NewVectorisedView(size, views) + newPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ + Data: data, + }) + log.Printf("greHandler proto: %d cloned: %v", proto, newPkt.Views()) + + info.ChEp.InjectInbound(proto, newPkt) +} + +func (info *GreHandlerInfo) greRead(ep *channel.Endpoint) { + for { + pi, err := ep.ReadContext(context.Background()); + linkHdr := pi.Pkt.LinkHeader() + greHdr := header.GRE(linkHdr.Push(header.GREHeaderSize)) + greHdr.SetProtocolType(pi.Proto) + log.Printf("greRead %d %v %v %v", pi.Proto, pi, err, greHdr) + opts := tcpip.WriteOptions{ + //To: &info.Raddr + } + info.Raw.Write(GrePacketInfo{&pi}, opts) + } +} + +func (e *Endpoint) Start(s *stack.Stack, laddr, raddr *tcpip.Address) { + // Create TCP endpoint. + var rawWq waiter.Queue + rawEp, tcperr := raw.NewEndpoint(s, ipv4.ProtocolNumber, header.GREProtocolNumber, &rawWq) + if tcperr != nil { + log.Fatal(tcperr) + } + log.Println("EP: %s", rawEp) + + fraddr := tcpip.FullAddress{NIC: 1, Addr: *raddr} + flAddr := tcpip.FullAddress{NIC: 1, Addr: *laddr} + tcperr = rawEp.Bind(flAddr) + if tcperr != nil { + log.Fatal(tcperr) + } + log.Printf("Remote: %v %v", raddr, fraddr) + + // Create GRE + // greEP := grelink.New(mtu - 24) + chEP := e.GetChannel() + // TODO detect IPv4/IPv6 + e.NMaxHeaderLength = header.IPv6FixedHeaderSize + header.GREHeaderSize + + greInfo := GreHandlerInfo{ +// Ep: loEP, + ChEp: chEP, + Raw: rawEp, + Raddr: fraddr, + } + greFwd := gre.NewForwarder(s, greInfo.greHandler) + s.SetTransportProtocolHandler(header.GREProtocolNumber, greFwd.HandlePacket) + + go greInfo.greRead(chEP) + + tcperr = rawEp.Connect(fraddr) + if tcperr != nil { + log.Fatal(tcperr) + } +} diff --git a/pkg/tcpip/sample/tun_tcp_connect/main.go b/pkg/tcpip/sample/tun_tcp_connect/main.go index 4707585d1..0ce9f49af 100644 --- a/pkg/tcpip/sample/tun_tcp_connect/main.go +++ b/pkg/tcpip/sample/tun_tcp_connect/main.go @@ -41,7 +41,6 @@ package main import ( - "context" "bufio" "fmt" "log" @@ -55,16 +54,14 @@ import ( "gvisor.dev/gvisor/pkg/tcpip" "gvisor.dev/gvisor/pkg/tcpip/buffer" "gvisor.dev/gvisor/pkg/tcpip/header" - "gvisor.dev/gvisor/pkg/tcpip/link/channel" "gvisor.dev/gvisor/pkg/tcpip/link/fdbased" - grelink "gvisor.dev/gvisor/pkg/tcpip/link/gre" + gretun "gvisor.dev/gvisor/pkg/tcpip/link/gre" "gvisor.dev/gvisor/pkg/tcpip/link/rawfile" "gvisor.dev/gvisor/pkg/tcpip/link/sniffer" "gvisor.dev/gvisor/pkg/tcpip/link/tun" "gvisor.dev/gvisor/pkg/tcpip/network/ipv4" "gvisor.dev/gvisor/pkg/tcpip/stack" "gvisor.dev/gvisor/pkg/tcpip/transport/gre" - "gvisor.dev/gvisor/pkg/tcpip/transport/raw" "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" "gvisor.dev/gvisor/pkg/waiter" ) @@ -98,74 +95,6 @@ func writer(ch chan struct{}, ep tcpip.Endpoint) { } } -type GrePacketInfo struct { - pi *channel.PacketInfo -} - -func (g GrePacketInfo) FullPayload() ([]byte, *tcpip.Error){ - log.Println("FullPayload") - pkt := g.pi.Pkt - size := pkt.Size() - vv := buffer.NewVectorisedView(size, pkt.Views()) - var buf = make([]byte, size, size) - pos := 0 - for { - copied, err := vv.Read(buf[pos:]) - log.Printf("VectorisedView Read: %d %d %d %v", size, pos, copied, err) - if err != nil { - return nil, tcpip.ErrBadBuffer - } - pos = pos + copied - if pos == size { - break - } - } - - log.Printf("FullPayload return: %d %v", len(buf), buf) - return buf, nil -} - -func (g GrePacketInfo) Payload(size int) ([]byte, *tcpip.Error){ - log.Println("Payload") - return nil, tcpip.ErrNotSupported -} - -type GreHandlerInfo struct { - ChEp *channel.Endpoint - Raw tcpip.Endpoint - Raddr tcpip.FullAddress -} - -func (info *GreHandlerInfo) greHandler(req *gre.ForwarderRequest) { - pkt := req.Pkt - log.Println("greHandler: ", req.Pkt.Size(), req.Pkt.Views()) - greHdr := header.GRE(pkt.TransportHeader().View()) - proto := greHdr.ProtocolType() - views := pkt.Data.Views() - size := pkt.Data.Size() - data := buffer.NewVectorisedView(size, views) - newPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ - Data: data, - }) - log.Printf("greHandler proto: %d cloned: %v", proto, newPkt.Views()) - - info.ChEp.InjectInbound(proto, newPkt) -} - -func (info *GreHandlerInfo) greRead(ep *channel.Endpoint) { - for { - pi, err := ep.ReadContext(context.Background()); - linkHdr := pi.Pkt.LinkHeader() - greHdr := header.GRE(linkHdr.Push(header.GREHeaderSize)) - greHdr.SetProtocolType(pi.Proto) - log.Printf("greRead %d %v %v %v", pi.Proto, pi, err, greHdr) - opts := tcpip.WriteOptions{ - //To: &info.Raddr - } - info.Raw.Write(GrePacketInfo{&pi}, opts) - } -} - func main() { if len(os.Args) != 8 { log.Fatal("Usage: ", os.Args[0], " <tun-device> <local-ipv4-address> <local-port> <remote-ipv4-address> <remote-port> <local-gre-address> <remote-gre-address>") @@ -233,41 +162,9 @@ func main() { log.Fatal(err) } - // Create TCP endpoint. - var rawWq waiter.Queue - rawEp, tcperr := raw.NewEndpoint(s, ipv4.ProtocolNumber, header.GREProtocolNumber, &rawWq) - if tcperr != nil { - log.Fatal(tcperr) - } - log.Println("EP: %s", rawEp) - - raddr := greRemoteAddr - fraddr := tcpip.FullAddress{NIC: 1, Addr: raddr} - fgreAddr := tcpip.FullAddress{NIC: 1, Addr: greAddr} - tcperr = rawEp.Bind(fgreAddr) - if tcperr != nil { - log.Fatal(tcperr) - } - log.Printf("Remote: %v %v", raddr, fraddr) - - // Create GRE - greEP := grelink.New(mtu - 24) - chEP := greEP.GetChannel() - // TODO detect IPv4/IPv6 - greEP.NMaxHeaderLength = header.IPv6FixedHeaderSize + header.GREHeaderSize - - greInfo := GreHandlerInfo{ -// Ep: loEP, - ChEp: chEP, - Raw: rawEp, - Raddr: fraddr, - } - greFwd := gre.NewForwarder(s, greInfo.greHandler) - s.SetTransportProtocolHandler(header.GREProtocolNumber, greFwd.HandlePacket) - - go greInfo.greRead(chEP) + greEP := gretun.New(mtu - 24) if err := s.CreateNIC(2, sniffer.New(greEP)); err != nil { - log.Fatal(err) + log.Fatal(err) } if err := s.AddAddress(2, ipv4.ProtocolNumber, addr); err != nil { log.Fatal(err) @@ -292,10 +189,7 @@ func main() { }) log.Printf("Nics enabled 1:%v 2:%v 3:%v", s.CheckNIC(1), s.CheckNIC(2), s.CheckNIC(3)) - tcperr = rawEp.Connect(fraddr) - if tcperr != nil { - log.Fatal(tcperr) - } + greEP.Start(s, &greAddr, &greRemoteAddr) // Create TCP endpoint. var wq waiter.Queue |