diff --git a/cmd/netstack/main.go b/cmd/netstack/main.go new file mode 100644 index 0000000..c74df5d --- /dev/null +++ b/cmd/netstack/main.go @@ -0,0 +1,215 @@ +package main + +import ( + "encoding/binary" + "flag" + "io" + "log" + "net" + "netstack/tcpip" + "netstack/tcpip/header" + "netstack/tcpip/link/fdbased" + "netstack/tcpip/link/tuntap" + "netstack/tcpip/network/arp" + "netstack/tcpip/network/ipv4" + "netstack/tcpip/network/ipv6" + "netstack/tcpip/stack" + "netstack/tcpip/transport/udp" + "netstack/waiter" + "os" + "strings" +) + +var mac = flag.String("mac", "01:01:01:01:01:01", "mac address to use in tap device") + +func main() { + flag.Parse() + if len(flag.Args()) != 2 { + log.Fatal("Usage: ", os.Args[0], " ") + } + + log.SetFlags(log.Lshortfile | log.LstdFlags) + tapName := flag.Arg(0) + listeAddr := flag.Arg(1) + + log.Printf("tap: %v, listeAddr: %v", tapName, listeAddr) + + // Parse the mac address. + maddr, err := net.ParseMAC(*mac) + if err != nil { + log.Fatalf("Bad MAC address: %v", *mac) + } + + parsedAddr := net.ParseIP(listeAddr) + + // 解析地址ip地址,ipv4或者ipv6地址都支持 + var addr tcpip.Address + var proto tcpip.NetworkProtocolNumber + if parsedAddr.To4() != nil { + addr = tcpip.Address(parsedAddr.To4()) + proto = ipv4.ProtocolNumber + } else if parsedAddr.To16() != nil { + addr = tcpip.Address(parsedAddr.To16()) + proto = ipv6.ProtocolNumber + } else { + log.Fatalf("Unknown IP type: %v", parsedAddr) + } + + // 虚拟网卡配置 + conf := &tuntap.Config{ + Name: tapName, + Mode: tuntap.TAP, + } + + var fd int + // 新建虚拟网卡 + fd, err = tuntap.NewNetDev(conf) + if err != nil { + log.Fatal(err) + } + + // 启动tap网卡 + _ = tuntap.SetLinkUp(tapName) + // 设置tap网卡IP地址 + _ = tuntap.AddIP(tapName, listeAddr) + + // 抽象网卡的文件接口 + linkID := fdbased.New(&fdbased.Options{ + FD: fd, + MTU: 1500, + Address: tcpip.LinkAddress(maddr), + }) + + // 新建相关协议的协议栈 + s := stack.New([]string{ipv4.ProtocolName, arp.ProtocolName}, + []string{ /*tcp.ProtocolName, */ udp.ProtocolName}, stack.Options{}) + + // 新建抽象的网卡 + if err := s.CreateNamedNIC(1, "vnic1", linkID); err != nil { + log.Fatal(err) + } + + // 在该协议栈上添加和注册相应的网络层 + if err := s.AddAddress(1, proto, addr); err != nil { + log.Fatal(err) + } + + // 在该协议栈上添加和注册ARP协议 + if err := s.AddAddress(1, arp.ProtocolNumber, arp.ProtocolAddress); err != nil { + log.Fatal(err) + } + + // 添加默认路由 + s.SetRouteTable([]tcpip.Route{ + { + Destination: tcpip.Address(strings.Repeat("\x00", len(addr))), + Mask: tcpip.AddressMask(strings.Repeat("\x00", len(addr))), + Gateway: "", + NIC: 1, + }, + }) + + conn, _ := net.Listen("tcp", "0.0.0.0:9999") + TCPServer(conn, &RCV{s, nil, nil}) + // 同时监听tcp和udp localPort端口 + //tcpEp := tcpListen(s, proto, localPort) + //udpEp := udpListen(s, proto, localPort) + // 关闭监听服务,此时会释放端口 + //tcpEp.Close() + //udpEp.Close() +} + +//func tcpListen(s *stack.Stack, proto tcpip.NetworkProtocolNumber, localPort int) tcpip.Endpoint { +// var wq waiter.Queue +// // 新建一个tcp端 +// ep, err := s.NewEndpoint(tcp.ProtocolNumber, proto, &wq) +// if err != nil { +// log.Fatal(err) +// } +// +// // 绑定IP和端口,这里的IP地址为空,表示绑定任何IP +// // 此时就会调用端口管理器 +// if err := ep.Bind(tcpip.FullAddress{0, "", uint16(localPort)}, nil); err != nil { +// log.Fatal("Bind failed: ", err) +// } +// +// // 开始监听 +// if err := ep.Listen(10); err != nil { +// log.Fatal("Listen failed: ", err) +// } +// +// return ep +//} + +func udpListen(s *stack.Stack, proto tcpip.NetworkProtocolNumber, localPort int) tcpip.Endpoint { + var wq waiter.Queue + // 新建一个udp端 + ep, err := s.NewEndpoint(udp.ProtocolNumber, proto, &wq) + if err != nil { + log.Fatal(err) + } + + // 绑定IP和端口,这里的IP地址为空,表示绑定任何IP + // 0.0.0.0:9999 这台机器上的所有ip的9999段端口数据都会使用该传输层实现 + // 此时就会调用端口管理器 + if err := ep.Bind(tcpip.FullAddress{NIC: 0, Addr: "", Port: uint16(localPort)}, nil); err != nil { + log.Fatal("Bind failed: ", err) + } + + if err := ep.Connect(tcpip.FullAddress{NIC: 0, Addr: "", Port: uint16(localPort)}); err != nil { + log.Fatal("Conn failed: ", err) + } + + // 注意UDP是无连接的,它不需要Listen + return ep +} + +type RCV struct { + *stack.Stack + ep tcpip.Endpoint + rcvBuf []byte +} + +var transportPool = make(map[uint64]tcpip.Endpoint) + +func (r *RCV) Handle(conn net.Conn) { + var err error + r.rcvBuf, err = io.ReadAll(conn) + if err != nil && len(r.rcvBuf) < 9 { // proto + ip + port + panic(err) + } + + switch string(r.rcvBuf[:3]) { + case "udp": + var wq waiter.Queue + // 新建一个udp端 + ep, err := r.NewEndpoint(udp.ProtocolNumber, header.IPv4ProtocolNumber, &wq) + if err != nil { + log.Fatal(err) + } + r.ep = ep + r.Bind() + r.Close() + case "tcp": + default: + return + } +} + +func (r *RCV) Bind() { + if len(r.rcvBuf) < 9 { // udp ip port + log.Println("Error: too few arg") + return + } + port := binary.BigEndian.Uint16(r.rcvBuf[7:9]) + addr := tcpip.FullAddress{ + NIC: 0, + Addr: tcpip.Address(r.rcvBuf[3:7]), + Port: port, + } + r.ep.Bind(addr, nil) +} + +func (r *RCV) Close() { + r.ep.Close() +} diff --git a/cmd/netstack/tcp_server.go b/cmd/netstack/tcp_server.go new file mode 100644 index 0000000..b0975f1 --- /dev/null +++ b/cmd/netstack/tcp_server.go @@ -0,0 +1,38 @@ +package main + +import ( + "fmt" + "log" + "net" + "runtime" + "strings" +) + +type TCPHandler interface { + Handle(net.Conn) +} + +func TCPServer(listener net.Listener, handler TCPHandler) error { + log.Printf("netstack 网络解析地址: %s", listener.Addr()) + + for { + clientConn, err := listener.Accept() + if err != nil { + if nerr, ok := err.(net.Error); ok && nerr.Temporary() { + log.Printf("temporary Accept() failure - %s", err) + runtime.Gosched() + continue + } + // theres no direct way to detect this error because it is not exposed + if !strings.Contains(err.Error(), "use of closed network connection") { + return fmt.Errorf("listener.Accept() error - %s", err) + } + break + } + go handler.Handle(clientConn) + } + + log.Printf("TCP: closing %s", listener.Addr()) + + return nil +} diff --git a/cmd/udp/main.go b/cmd/udp/main.go index a6f7c14..a4ef9e2 100644 --- a/cmd/udp/main.go +++ b/cmd/udp/main.go @@ -5,120 +5,32 @@ import ( "log" "net" "netstack/tcpip" - "netstack/tcpip/link/fdbased" - "netstack/tcpip/link/tuntap" - "netstack/tcpip/network/arp" - "netstack/tcpip/network/ipv4" - "netstack/tcpip/network/ipv6" "netstack/tcpip/stack" "netstack/tcpip/transport/udp" "netstack/waiter" "os" - "strconv" - "strings" ) -var mac = flag.String("mac", "01:01:01:01:01:01", "mac address to use in tap device") - func main() { flag.Parse() - if len(flag.Args()) != 3 { - log.Fatal("Usage: ", os.Args[0], " port") + if len(flag.Args()) != 2 { + log.Fatal("Usage: ", os.Args[0], " port") } log.SetFlags(log.Lshortfile | log.LstdFlags) - tapName := flag.Arg(0) - listeAddr := flag.Arg(1) - portName := flag.Arg(2) + listeAddr := flag.Arg(0) + portName := flag.Arg(1) - log.Printf("tap: %v, listeAddr: %v, portName: %v", tapName, listeAddr, portName) + Socket(listeAddr + ":" + portName) +} - // Parse the mac address. - maddr, err := net.ParseMAC(*mac) +func Socket(addr string) { + conn, err := net.Dial("tcp", addr) if err != nil { - log.Fatalf("Bad MAC address: %v", *mac) + panic(err) } - - parsedAddr := net.ParseIP(listeAddr) - - // 解析地址ip地址,ipv4或者ipv6地址都支持 - var addr tcpip.Address - var proto tcpip.NetworkProtocolNumber - if parsedAddr.To4() != nil { - addr = tcpip.Address(parsedAddr.To4()) - proto = ipv4.ProtocolNumber - } else if parsedAddr.To16() != nil { - addr = tcpip.Address(parsedAddr.To16()) - proto = ipv6.ProtocolNumber - } else { - log.Fatalf("Unknown IP type: %v", parsedAddr) - } - - localPort, err := strconv.Atoi(portName) - if err != nil { - log.Fatalf("Unable to convert port %v: %v", portName, err) - } - - // 虚拟网卡配置 - conf := &tuntap.Config{ - Name: tapName, - Mode: tuntap.TAP, - } - - var fd int - // 新建虚拟网卡 - fd, err = tuntap.NewNetDev(conf) - if err != nil { - log.Fatal(err) - } - - // 启动tap网卡 - _ = tuntap.SetLinkUp(tapName) - // 设置tap网卡IP地址 - _ = tuntap.AddIP(tapName, listeAddr) - - // 抽象网卡的文件接口 - linkID := fdbased.New(&fdbased.Options{ - FD: fd, - MTU: 1500, - Address: tcpip.LinkAddress(maddr), - }) - - // 新建相关协议的协议栈 - s := stack.New([]string{ipv4.ProtocolName, arp.ProtocolName}, - []string{ /*tcp.ProtocolName, */ udp.ProtocolName}, stack.Options{}) - - // 新建抽象的网卡 - if err := s.CreateNamedNIC(1, "vnic1", linkID); err != nil { - log.Fatal(err) - } - - // 在该协议栈上添加和注册相应的网络层 - if err := s.AddAddress(1, proto, addr); err != nil { - log.Fatal(err) - } - - // 在该协议栈上添加和注册ARP协议 - if err := s.AddAddress(1, arp.ProtocolNumber, arp.ProtocolAddress); err != nil { - log.Fatal(err) - } - - // 添加默认路由 - s.SetRouteTable([]tcpip.Route{ - { - Destination: tcpip.Address(strings.Repeat("\x00", len(addr))), - Mask: tcpip.AddressMask(strings.Repeat("\x00", len(addr))), - Gateway: "", - NIC: 1, - }, - }) - - // 同时监听tcp和udp localPort端口 - //tcpEp := tcpListen(s, proto, localPort) - udpEp := udpListen(s, proto, localPort) - // 关闭监听服务,此时会释放端口 - //tcpEp.Close() - udpEp.Close() + conn.Write([]byte("udp\xc0\xa8\x01\x01\x27\x0f")) // bind udp 192.168.1.1 9999 + conn.Close() } //func tcpListen(s *stack.Stack, proto tcpip.NetworkProtocolNumber, localPort int) tcpip.Endpoint { diff --git a/tcpip/stack/stack.go b/tcpip/stack/stack.go index b2e4b17..babbc80 100644 --- a/tcpip/stack/stack.go +++ b/tcpip/stack/stack.go @@ -76,6 +76,7 @@ type Options struct { Stats tcpip.Stats } +// New 新建一个网络协议栈 func New(network []string, transport []string, opts Options) *Stack { clock := opts.Clock if clock == nil { @@ -115,7 +116,9 @@ func New(network []string, transport []string, opts Options) *Stack { proto: transProto, } } - // TODO 添加传输层分流器 + // 添加传输层分流器 + s.demux = newTransportDemuxer(s) + return s } diff --git a/tcpip/stack/transport_demuxer.go b/tcpip/stack/transport_demuxer.go index 8dde1e0..cc63328 100644 --- a/tcpip/stack/transport_demuxer.go +++ b/tcpip/stack/transport_demuxer.go @@ -21,3 +21,8 @@ type transportEndpoints struct { type transportDemuxer struct { protocol map[protocolIDs]*transportEndpoints } + +// 新建一个分流器 +func newTransportDemuxer(stacl *Stack) *transportDemuxer { + return nil +}