package routing import ( "bufio" "bytes" "net" "os/exec" "strconv" "strings" "github.com/asaskevich/govalidator" "github.com/pkg/errors" stringsutil "github.com/projectdiscovery/utils/strings" ) // New creates a routing engine for windows func New() (Router, error) { var routes []*Route for _, iptype := range []RouteType{IPv4, IPv6} { netshCmd := exec.Command("netsh", "interface", iptype.String(), "show", "route") netshOutput, err := netshCmd.Output() if err != nil { return nil, err } scanner := bufio.NewScanner(bytes.NewReader(netshOutput)) for scanner.Scan() { outputLine := strings.TrimSpace(scanner.Text()) if outputLine == "" { continue } parts := stringsutil.SplitAny(outputLine, " \t") if len(parts) >= 6 && govalidator.IsNumeric(parts[4]) { prefix := parts[3] _, _, err := net.ParseCIDR(prefix) if err != nil { return nil, err } gateway := parts[5] interfaceIndex, err := strconv.Atoi(parts[4]) if err != nil { return nil, err } networkInterface, err := net.InterfaceByIndex(interfaceIndex) if err != nil { return nil, err } isDefault := stringsutil.EqualFoldAny(prefix, "0.0.0.0/0", "::/0") route := &Route{ Type: iptype, Default: isDefault, Destination: prefix, Gateway: gateway, NetworkInterface: networkInterface, } routes = append(routes, route) } } } return &RouterWindows{Routes: routes}, nil } type RouterWindows struct { Routes []*Route } func (r *RouterWindows) Route(dst net.IP) (iface *net.Interface, gateway, preferredSrc net.IP, err error) { route, err := FindRouteForIp(dst, r.Routes) if err != nil { return nil, nil, nil, errors.Wrap(err, "could not find route") } if route.NetworkInterface == nil { return nil, nil, nil, errors.Wrap(err, "could not find network interface") } ip, err := FindSourceIpForIp(route, dst) if err != nil { return nil, nil, nil, errors.Wrap(err, "could not find source ip") } return route.NetworkInterface, net.IP(route.Gateway), ip, nil } func (r *RouterWindows) RouteWithSrc(input net.HardwareAddr, src, dst net.IP) (iface *net.Interface, gateway, preferredSrc net.IP, err error) { route, err := FindRouteWithHwAndIp(input, src, r.Routes) if err != nil { return nil, nil, nil, err } return route.NetworkInterface, net.IP(route.Gateway), src, nil }