cns/routes/routes_windows.go (155 lines of code) (raw):

// Copyright 2017 Microsoft. All rights reserved. // MIT License // +build windows package routes import ( "fmt" "net" "os/exec" "strings" "github.com/Azure/azure-container-networking/cns/logger" ) const ( ipv4RoutingTableStart = "IPv4 Route Table" activeRoutesStart = "Active Routes:" ) func getInterfaceByAddress(address string) (int, error) { logger.Printf("[Azure CNS] getInterfaceByAddress") var ifaces []net.Interface logger.Printf("[Azure CNS] Going to obtain interface for address %s", address) ifaces, err := net.Interfaces() if err != nil { return -1, err } for i := 0; i < len(ifaces); i++ { logger.Debugf("[Azure CNS] Going to check interface %v", ifaces[i].Name) addrs, _ := ifaces[i].Addrs() for _, addr := range addrs { logger.Debugf("[Azure CNS] ipAddress being compared input=%v %v\n", address, addr.String()) ip := strings.Split(addr.String(), "/") if len(ip) != 2 { return -1, fmt.Errorf("Malformed ip: %v", addr.String()) } if ip[0] == address { return ifaces[i].Index, nil } } } return -1, fmt.Errorf( "[Azure CNS] Unable to determine interface index for address %s", address) } func getRoutes() ([]Route, error) { logger.Printf("[Azure CNS] getRoutes") c := exec.Command("cmd", "/C", "route", "print") var routePrintOutput string var routeCount int bytes, err := c.Output() if err == nil { routePrintOutput = string(bytes) logger.Debugf("[Azure CNS] Printing Routing table \n %v\n", routePrintOutput) } else { logger.Printf("Received error in printing routing table %v", err.Error()) return nil, err } routePrint := strings.Split(routePrintOutput, ipv4RoutingTableStart) routeTable := strings.Split(routePrint[1], activeRoutesStart) tokens := strings.Split( strings.Split(routeTable[1], "Metric")[1], "=") table := tokens[0] routes := strings.Split(table, "\r") routeCount = len(routes) logger.Debugf("[Azure CNS] Recevied route count: %d", routeCount) if routeCount == 0 { return nil, nil } localRoutes := make([]Route, routeCount) cntr := 0 truncated := 0 for _, route := range routes { if route != "" { tokens := strings.Fields(route) if len(tokens) != 5 { logger.Printf("[Azure CNS] Ignoring route %s", route) truncated++ } else { logger.Debugf("[Azure CNS] Parsing route: %s %s %s %s %s\n", tokens[0], tokens[1], tokens[2], tokens[3], tokens[4]) rt := Route{ destination: tokens[0], mask: tokens[1], gateway: tokens[2], metric: tokens[4], } if rt.gateway == "On-link" { rt.gateway = "0.0.0.0" } index, err := getInterfaceByAddress(tokens[3]) if err == nil { rt.ifaceIndex = index localRoutes[cntr] = rt cntr++ } else { logger.Printf("[Azure CNS] Error encountered while obtaining index. %v\n", err.Error()) truncated++ } } } } if truncated == routeCount { localRoutes = nil } else { localRoutes = localRoutes[0 : routeCount-truncated-1] } return localRoutes, nil } func containsRoute(routes []Route, route Route) (bool, error) { logger.Printf("[Azure CNS] containsRoute") if routes == nil { return false, nil } for _, existingRoute := range routes { if existingRoute.destination == route.destination && existingRoute.gateway == route.gateway && existingRoute.ifaceIndex == route.ifaceIndex && existingRoute.mask == route.mask { return true, nil } } return false, nil } func putRoutes(routes []Route) error { logger.Printf("[Azure CNS] putRoutes") var err error logger.Printf("[Azure CNS] Going to get current routes") currentRoutes, err := getRoutes() if err != nil { return err } for _, route := range routes { exists, err := containsRoute(currentRoutes, route) if err == nil && !exists { args := []string{ "/C", "route", "ADD", route.destination, "MASK", route.mask, route.gateway, "METRIC", route.metric, "IF", fmt.Sprintf("%d", route.ifaceIndex), } logger.Printf("[Azure CNS] Adding missing route: %v", args) c := exec.Command("cmd", args...) bytes, err := c.Output() if err == nil { logger.Printf("[Azure CNS] Successfully executed add route: %v\n%v", args, string(bytes)) } else { logger.Errorf("[Azure CNS] Failed to execute add route: %v\n%v", args, string(bytes)) } } else { logger.Printf("[Azure CNS] Route already exists. skipping %+v", route) } } return err }