github.com/icexin/eggos@v0.4.2-0.20220216025428-78b167e4f349/inet/stack.go (about) 1 package inet 2 3 import ( 4 "context" 5 "errors" 6 "time" 7 8 "github.com/icexin/eggos/inet/dhcp" 9 "github.com/icexin/eggos/log" 10 11 "gvisor.dev/gvisor/pkg/tcpip" 12 "gvisor.dev/gvisor/pkg/tcpip/header" 13 "gvisor.dev/gvisor/pkg/tcpip/link/loopback" 14 "gvisor.dev/gvisor/pkg/tcpip/network/arp" 15 "gvisor.dev/gvisor/pkg/tcpip/network/ipv4" 16 "gvisor.dev/gvisor/pkg/tcpip/stack" 17 "gvisor.dev/gvisor/pkg/tcpip/transport/tcp" 18 "gvisor.dev/gvisor/pkg/tcpip/transport/udp" 19 ) 20 21 const ( 22 defaultNIC = 1 23 loopbackNIC = 2 24 ) 25 26 var ( 27 nstack *stack.Stack 28 ) 29 30 func e(err tcpip.Error) error { 31 if err == nil { 32 return nil 33 } 34 return errors.New(err.String()) 35 } 36 37 func Init() { 38 nstack = stack.New(stack.Options{ 39 NetworkProtocols: []stack.NetworkProtocolFactory{arp.NewProtocol, ipv4.NewProtocol}, 40 TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol}, 41 HandleLocal: true, 42 }) 43 44 // add net card interface 45 endpoint := New(&Options{}) 46 err := nstack.CreateNIC(defaultNIC, endpoint) 47 if err != nil { 48 panic(err) 49 } 50 err1 := dodhcp(endpoint.LinkAddress()) 51 if err1 != nil { 52 panic(err) 53 } 54 55 // add loopback interface 56 err = nstack.CreateNIC(loopbackNIC, loopback.New()) 57 if err != nil { 58 panic(err) 59 } 60 addInterfaceAddr(nstack, loopbackNIC, tcpip.Address([]byte{127, 0, 0, 1})) 61 return 62 } 63 64 func addInterfaceAddr(s *stack.Stack, nic tcpip.NICID, addr tcpip.Address) { 65 s.AddAddress(nic, ipv4.ProtocolNumber, addr) 66 // Add route for local network if it doesn't exist already. 67 localRoute := tcpip.Route{ 68 Destination: addr.WithPrefix().Subnet(), 69 Gateway: "", // No gateway for local network. 70 NIC: nic, 71 } 72 73 for _, rt := range s.GetRouteTable() { 74 if rt.Equal(localRoute) { 75 return 76 } 77 } 78 79 // Local route does not exist yet. Add it. 80 s.AddRoute(localRoute) 81 } 82 83 func dodhcp(linkaddr tcpip.LinkAddress) error { 84 dhcpclient := dhcp.NewClient(nstack, defaultNIC, linkaddr) 85 ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) 86 log.Infof("[inet] begin dhcp") 87 err1 := dhcpclient.Request(ctx, "") 88 cancel() 89 if err1 != nil { 90 return err1 91 } 92 log.Infof("[inet] dhcp done") 93 cfg := dhcpclient.Config() 94 log.Infof("[inet] addr:%v", dhcpclient.Address()) 95 log.Infof("[inet] gateway:%v", cfg.Gateway) 96 log.Infof("[inet] mask:%v", cfg.SubnetMask) 97 log.Infof("[inet] dns:%v", cfg.DomainNameServer) 98 99 addInterfaceAddr(nstack, defaultNIC, dhcpclient.Address()) 100 nstack.AddRoute(tcpip.Route{ 101 Destination: header.IPv4EmptySubnet, 102 Gateway: cfg.Gateway, 103 NIC: defaultNIC, 104 }) 105 return nil 106 }