/******************************************************************************* * Copyright (c) 2011, 2016 Eurotech and/or its affiliates * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Eurotech *******************************************************************************/ package org.eclipse.kura.linux.net.route; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.StringTokenizer; import org.eclipse.kura.core.util.ProcessUtil; import org.eclipse.kura.core.util.SafeProcess; import org.eclipse.kura.net.IP4Address; import org.eclipse.kura.net.IP6Address; import org.eclipse.kura.net.IPAddress; import org.eclipse.kura.net.route.RouteConfig; import org.eclipse.kura.net.route.RouteConfigIP4; import org.eclipse.kura.net.route.RouteConfigIP6; import org.slf4j.Logger; import org.slf4j.LoggerFactory; //public class RouteServiceImpl implements RouteService, IConfigurableComponentService { public class RouteServiceImpl implements RouteService { private static Logger s_logger = LoggerFactory.getLogger(RouteServiceImpl.class); private static RouteServiceImpl s_routeService = null; // public static final String CONFIGURATION_NAME = "org.eclipse.kura.net.linux.route"; private String m_osRouteConfigDirectory = null; private RouteServiceImpl() { this.m_osRouteConfigDirectory = "/etc/sysconfig/network-scripts/"; } public static synchronized RouteService getInstance() { if (s_routeService == null) { s_routeService = new RouteServiceImpl(); } return s_routeService; } private void addPersistentStaticRoute(IPAddress destination, IPAddress gateway, IPAddress netmask, String iface) throws Exception { addStaticRoute(destination, gateway, netmask, iface, 0); RouteFile routeFile = new RouteFile(iface); if (routeFile.addRoute(destination, gateway, netmask, iface)) { s_logger.info("Route persistence added"); } else { s_logger.error("Error adding route persistence"); } } @Override public void addStaticRoute(IPAddress destination, IPAddress gateway, IPAddress netmask, String iface, int metric) throws Exception { RouteConfig tmpRoute = null; StringBuffer command = new StringBuffer(); command.append("route add -net " + destination.getHostAddress() + " "); if (netmask != null) { command.append("netmask " + netmask.getHostAddress() + " "); } if (gateway != null) { if (gateway.getHostAddress().compareTo("0.0.0.0") != 0 && gateway.getHostAddress().compareTo("127.0.0.1") != 0) { command.append("gw " + gateway.getHostAddress() + " "); } } if (iface != null) { command.append("dev " + iface + " "); } if (metric != 0 && metric != -1) { command.append("metric " + metric); } SafeProcess proc = null; try { s_logger.debug("Executing command: {}", command.toString()); proc = ProcessUtil.exec(command.toString()); proc.waitFor(); if (proc.exitValue() != 0) { s_logger.error("Error adding static Route: " + command.toString()); throw new Exception("Error adding Static Route"); } } catch (IOException e) { s_logger.error("Error executing command: route -n"); throw e; } finally { if (proc != null) { ProcessUtil.destroy(proc); } } if (destination instanceof IP4Address) { tmpRoute = new RouteConfigIP4((IP4Address) destination, (IP4Address) gateway, (IP4Address) netmask, iface, -1); } else if (destination instanceof IP6Address) { tmpRoute = new RouteConfigIP6((IP6Address) destination, (IP6Address) gateway, (IP6Address) netmask, iface, -1); } s_logger.info("Static route added successfully"); s_logger.debug(tmpRoute.getDescription()); } @Override public RouteConfig getDefaultRoute(String iface) { RouteConfig[] routes = getRoutes(); RouteConfig defaultRoute; ArrayList<RouteConfig> defaultRoutes = new ArrayList<RouteConfig>(); // Search through routes and construct a list of all default routes for the specified interface for (RouteConfig route : routes) { if (route.getInterfaceName().compareTo(iface) == 0 && route.getDestination().getHostAddress().compareTo("0.0.0.0") == 0) { defaultRoutes.add(route); } } // If no default routes exist, return null if (defaultRoutes.size() == 0) { s_logger.debug("No default routes exist for inteface: {}", iface); return null; } // Set the default route to the first one in the list defaultRoute = defaultRoutes.get(0); // Search for the default route with the lowest metric value for (int i = 1; i < defaultRoutes.size(); i++) { if (defaultRoute.getMetric() > defaultRoutes.get(i).getMetric()) { defaultRoute = defaultRoutes.get(i); } } s_logger.info("Default route found for interface: " + iface); s_logger.debug("Default route:\n{}", defaultRoute.getDescription()); return defaultRoute; } @Override public RouteConfig[] getRoutes() { String routeEntry = null; ArrayList<RouteConfig> routeList = new ArrayList<RouteConfig>(); RouteConfig[] routes = null; RouteConfig tmpRoute = null; SafeProcess proc = null; BufferedReader br = null; try { proc = ProcessUtil.exec("route -n"); proc.waitFor(); br = new BufferedReader(new InputStreamReader(proc.getInputStream())); br.readLine(); br.readLine(); while ((routeEntry = br.readLine()) != null) { tmpRoute = entryToRoute(routeEntry); if (tmpRoute != null) { routeList.add(tmpRoute); } } } catch (Exception e) { s_logger.error("Error executing command: route -n", e); return null; } finally { if (br != null) { try { br.close(); } catch (IOException ex) { s_logger.error("I/O Exception while closing BufferedReader!"); } } if (proc != null) { ProcessUtil.destroy(proc); } } routes = new RouteConfig[routeList.size()]; for (int i = 0; i < routes.length; i++) { routes[i] = routeList.get(i); } return routes; } private void removePersistentStaticRoute(IPAddress destination, IPAddress gateway, IPAddress netmask, String iface) throws Exception { removeStaticRoute(destination, gateway, netmask, iface); RouteFile routeFile = new RouteFile(iface); if (routeFile.removeRoute(destination, gateway, netmask, iface)) { s_logger.info("Route persistence removed"); } else { s_logger.error("Error removing route persistence"); } } @Override public void removeStaticRoute(IPAddress destination, IPAddress gateway, IPAddress netmask, String iface) throws Exception { RouteConfig tmpRoute = null; StringBuffer command = new StringBuffer(); command.append("route del -net " + destination.getHostAddress() + " "); if (netmask != null) { command.append("netmask " + netmask.getHostAddress() + " "); } if (gateway != null) { if (gateway.getHostAddress().compareTo("127.0.0.1") != 0) { command.append("gw " + gateway.getHostAddress() + " "); } } if (iface != null) { command.append("dev " + iface + " "); } SafeProcess proc = null; try { s_logger.debug("Executing command: {}", command.toString()); proc = ProcessUtil.exec(command.toString()); proc.waitFor(); if (proc.exitValue() != 0) { s_logger.error("Error removing static Route"); throw new Exception("Error removing Static Route"); } } catch (IOException e) { s_logger.error("Error executing command: route -n"); throw e; } finally { if (proc != null) { ProcessUtil.destroy(proc); } } if (destination instanceof IP4Address) { tmpRoute = new RouteConfigIP4((IP4Address) destination, (IP4Address) gateway, (IP4Address) netmask, iface, -1); } else if (destination instanceof IP6Address) { tmpRoute = new RouteConfigIP6((IP6Address) destination, (IP6Address) gateway, (IP6Address) netmask, iface, -1); } s_logger.info("Static route removed successfully"); s_logger.debug(tmpRoute.getDescription()); } private RouteConfig entryToRoute(String entry) { RouteConfig route; IPAddress destination; IPAddress gateway; IPAddress netmask; int metric; String iface; String tmp; try { route = null; StringTokenizer tok = new StringTokenizer(entry, " "); tmp = tok.nextToken(); destination = IPAddress.parseHostAddress(tmp); gateway = IPAddress.parseHostAddress(tok.nextToken()); netmask = IPAddress.parseHostAddress(tok.nextToken()); tok.nextToken(); metric = Integer.parseInt(tok.nextToken()); tok.nextToken(); tok.nextToken(); iface = tok.nextToken(); } catch (Exception e) { s_logger.error("Error parsing route table entry: " + e.getMessage()); e.printStackTrace(); return null; } if (destination instanceof IP4Address) { route = new RouteConfigIP4((IP4Address) destination, (IP4Address) gateway, (IP4Address) netmask, iface, metric); } else if (destination instanceof IP6Address) { route = new RouteConfigIP6((IP6Address) destination, (IP6Address) gateway, (IP6Address) netmask, iface, metric); } s_logger.trace("Route successfully read from route table entry"); return route; } @Override public String getDefaultInterface(IPAddress destination) { ArrayList<RouteConfig> matches = new ArrayList<RouteConfig>(); RouteConfig[] routes = getRoutes(); for (RouteConfig route : routes) { if (matchesRoute(destination, route)) { matches.add(route); } } if (matches.size() > 0) { RouteConfig dRoute = matches.get(0); for (RouteConfig route : routes) { if (dRoute.getMetric() > route.getMetric()) { dRoute = route; } } s_logger.debug("Found defualt interface " + dRoute.getInterfaceName() + " for destination " + destination.getHostAddress()); return dRoute.getInterfaceName(); } s_logger.debug("No default interface exists for destination {}", destination.getHostAddress()); return null; } private boolean matchesRoute(IPAddress destination, RouteConfig route) { byte mask = (byte) 0xFF; byte[] dest = destination.getAddress(); byte[] routeMask = route.getNetmask().getAddress(); byte[] routeDest = route.getDestination().getAddress(); byte[] dest_masked = new byte[4]; for (int i = 0; i < 4; i++) { if (routeMask[i] == mask) { dest_masked[i] = dest[i]; } else { dest_masked[i] = 0; } } for (int i = 0; i < 4; i++) { if (dest_masked[i] != routeDest[i]) { return false; } } return true; } /* * Container class for a new route from a configuration */ private class ConfigRoute { public int index; public IPAddress destination = null; public IPAddress netmask = null; public IPAddress gateway = null; public String iface = null; public ConfigRoute(int index) { this.index = index; } public boolean isComplete() { return this.destination != null && this.netmask != null && this.gateway != null && this.iface != null; } public String getDescription() { return "dest: " + this.destination.getHostAddress() + " nm: " + this.netmask.getHostAddress() + " gw: " + this.gateway.getHostAddress() + " iface: " + this.iface; } } // public Object receiveConfig(Object config) throws KuraConfigurationException { // Properties props = (Properties)config; // Enumeration keys = props.keys(); // ArrayList newRoutes = new ArrayList(); // String key = null; // String param = null; // int index = 0; // ConfigRoute newRoute = null; // s_logger.debug("New Configuration received with " + props.size() + " elements"); // // // Validate the configuration parameters and create ConfigRoute objects to hold the new routes // while(keys.hasMoreElements()) { // key = (String)keys.nextElement(); // try { // index = getKeyIndex(key); // } catch (NumberFormatException e) { // s_logger.error("Error parsing configuration parameter " + key); // throw new KuraConfigurationException("Error parsing configuration parameter: " + key + ", " + e.getMessage()); // } // param = getKeyParam(key); // // for(int i=0; i<newRoutes.size(); i++) { // ConfigRoute tmpRoute = (ConfigRoute)newRoutes.get(i); // if(tmpRoute.index == index) { // s_logger.debug("New parameter found for route " + index); // newRoute = tmpRoute; // } // } // // if(newRoute == null) { // s_logger.debug("New parameter found for NEW route " + index); // newRoute = new ConfigRoute(index); // newRoutes.add(newRoute); // } // // try { // if(param.compareTo("destination")==0) { // s_logger.debug("New Configuration - Route - destination: " + (String)props.get(key)); // newRoute.destination = InetAddress.getByName((String)props.get(key)); // } else if(param.compareTo("netmask")==0) { // s_logger.debug("New Configuration - Route - netmask: " + (String)props.get(key)); // newRoute.netmask = InetAddress.getByName((String)props.get(key)); // } else if(param.compareTo("gateway")==0) { // s_logger.debug("New Configuration - Route - gateway: " + (String)props.get(key)); // newRoute.gateway = InetAddress.getByName((String)props.get(key)); // } else if(param.compareTo("iface")==0) { // s_logger.debug("New Configuration - Route - iface: " + (String)props.get(key)); // newRoute.iface = (String)props.get(key); // } else { // s_logger.error("Error parsing configuration, unknown parameter: " + key); // throw new KuraConfigurationException("Unknown parameter: " + key); // } // } catch (UnknownHostException e) { // e.printStackTrace(); // s_logger.error("Error parsing configuration, unknown host: " + (String)props.get(key)); // throw new KuraConfigurationException("Unknown host: " + (String)props.get(key)); // // } // newRoute = null; // } // // // Make sure all new route configurations are complete // for(int i=0; i<newRoutes.size(); i++) { // ConfigRoute cr = (ConfigRoute)newRoutes.get(i); // if(!cr.isComplete()) { // s_logger.error("Error parsing configuration, missing parameters for new route " + cr.index); // throw new KuraConfigurationException("Missing parameters for new route " + cr.index); // } else { // s_logger.debug("New complete route configuration: " + cr.getDescription()); // } // } // // // Clear current OS persistent route files // clearPersistenceFiles(); // // // Create new routes // RouteFile routeFile; // for(int i=0; i<newRoutes.size(); i++) { // ConfigRoute cr = (ConfigRoute)newRoutes.get(i); // s_logger.debug("editing route file for interface: " + cr.iface); // routeFile = new RouteFile(cr.iface); // s_logger.debug("adding route: " + cr.getDescription()); // routeFile.addRoute(cr.destination, cr.gateway, cr.netmask, cr.iface); // } // // return null; // } private int getKeyIndex(String key) throws NumberFormatException { int index; try { String indexString = key.substring(key.indexOf("_") + 1); index = Integer.parseInt(indexString); } catch (NumberFormatException e) { e.printStackTrace(); throw e; } return index; } private String getKeyParam(String key) { return key.substring(0, key.indexOf("_")); } private void clearPersistenceFiles() { File dir = new File(this.m_osRouteConfigDirectory); String[] files = dir.list(); for (String file : files) { if (file.startsWith("route-")) { File fileToDelete = new File(this.m_osRouteConfigDirectory + file); fileToDelete.delete(); } } } }