Adding a flag to activate/deactivate process sandboxing
[iot2.git] / iotjava / iotruntime / master / IoTMaster.java
index 154f36a5ad9811993c9512bcad92dfe35e8fe3a0..f3bae940be1f79c0e3f50174d26ddae787d6383d 100644 (file)
@@ -40,7 +40,7 @@ import static java.lang.Math.toIntExact;
  * @version     1.0
  * @since       2016-06-16
  */
-public class IoTMaster {
+public final class IoTMaster {
 
        /**
         * IoTMaster class properties
@@ -51,6 +51,7 @@ public class IoTMaster {
        private CommunicationHandler commHan;
        private LoadBalancer lbIoT;
        private RouterConfig routerConfig;
+       private ProcessJailConfig processJailConfig;
        private ObjectInitHandler objInitHand;
        private ObjectAddressInitHandler objAddInitHand;
        private String[] strObjectNames;
@@ -96,12 +97,12 @@ public class IoTMaster {
        private static String STR_ZB_GATEWAY_ADDRESS;
        private static String STR_ZB_GATEWAY_PORT;
        private static String STR_ZB_IOTMASTER_PORT;
-       private static String STR_NUM_CALLBACK_PORTS;
        private static String STR_JVM_INIT_HEAP_SIZE;
        private static String STR_JVM_MAX_HEAP_SIZE;
-       private static String STR_LANGUAGE;
+       private static String STR_LANGUAGE_CONTROLLER;
        private static String STR_SKEL_CLASS_SUFFIX;
        private static String STR_STUB_CLASS_SUFFIX;
+       private static String STR_ACTIVATE_SANDBOXING;
        private static boolean BOOL_VERBOSE;
 
        /**
@@ -113,6 +114,8 @@ public class IoTMaster {
        private static final String STR_CFG_FILE_EXT = ".config";
        private static final String STR_CLS_FILE_EXT = ".class";
        private static final String STR_JAR_FILE_EXT = ".jar";
+       private static final String STR_MAC_POLICY_EXT = ".tomoyo.pol"; 
+       private static final String STR_SHELL_FILE_EXT = ".sh";
        private static final String STR_SO_FILE_EXT = ".so";
        private static final String STR_ZIP_FILE_EXT = ".zip";
        private static final String STR_TCP_PROTOCOL = "tcp";
@@ -123,6 +126,7 @@ public class IoTMaster {
        private static final String STR_INTERFACE_CLS_CFG = "INTERFACE_CLASS";
        private static final String STR_INT_STUB_CLS_CFG = "INTERFACE_STUB_CLASS";
        private static final String STR_FILE_TRF_CFG = "ADDITIONAL_ZIP_FILE";
+       private static final String STR_LANGUAGE = "LANGUAGE";
        private static final String STR_YES = "Yes";
        private static final String STR_NO = "No";
        private static final String STR_JAVA = "Java";
@@ -130,8 +134,12 @@ public class IoTMaster {
        private static final String STR_SSH = "ssh";
        private static final String STR_SCP = "scp";
        private static final String STR_IOTSLAVE_CPP = "./IoTSlave.o";
+       private static final String STR_SHELL_HEADER = "#!/bin/sh";
+       private static final String STR_JAVA_PATH = "/usr/bin/java";
+       private static final String STR_MAC_POL_PATH = "tomoyo/";
 
        private static int INT_SIZE = 4;        // send length in the size of integer (4 bytes)
+       private static final int INT_DNS_PORT = 53;
 
        /**
         * Runtime class name constants - not to be configured by users
@@ -152,6 +160,7 @@ public class IoTMaster {
                commHan = null;
                lbIoT = null;
                routerConfig = null;
+               processJailConfig = null;
                objInitHand = null;
                objAddInitHand = null;
                strObjectNames = argObjNms;
@@ -187,10 +196,10 @@ public class IoTMaster {
                STR_ZB_GATEWAY_ADDRESS = null;
                STR_ZB_GATEWAY_PORT = null;
                STR_ZB_IOTMASTER_PORT = null;
-               STR_NUM_CALLBACK_PORTS = null;
                STR_JVM_INIT_HEAP_SIZE = null;
                STR_JVM_MAX_HEAP_SIZE = null;
-               STR_LANGUAGE = null;
+               STR_LANGUAGE_CONTROLLER = null;
+               STR_ACTIVATE_SANDBOXING = null;
                BOOL_VERBOSE = false;
        }
 
@@ -206,11 +215,31 @@ public class IoTMaster {
                lbIoT.setupLoadBalancer();
                routerConfig = new RouterConfig();
                routerConfig.getAddressList(STR_ROUTER_ADD);
+               processJailConfig = new ProcessJailConfig();
+               //processJailConfig.setAddressListObject(routerConfig.getAddressListObject());
                objInitHand = new ObjectInitHandler(BOOL_VERBOSE);
                objAddInitHand = new ObjectAddressInitHandler(BOOL_VERBOSE);
                mapClassNameToCrim = new HashMap<String,Object>();
        }
 
+       /**
+        * getPrintWriter() gets a new PrintWriter for a new object
+        *
+        * @param   strObjectName       String object name
+        * @return  PrintWriter
+        */
+       private PrintWriter getPrintWriter(String strObjectName) {
+
+               FileWriter fw = null;
+               try {
+                       fw = new FileWriter(strObjectName);
+               } catch (IOException ex) {
+                       ex.printStackTrace();
+               }
+               PrintWriter printWriter = new PrintWriter(new BufferedWriter(fw));
+               return printWriter;
+       }
+
        /**
         * A method to initialize constants from config file
         *
@@ -246,12 +275,11 @@ public class IoTMaster {
                STR_ZB_GATEWAY_ADDRESS = prop.getProperty("ZIGBEE_GATEWAY_ADDRESS");
                STR_ZB_GATEWAY_PORT = prop.getProperty("ZIGBEE_GATEWAY_PORT");
                STR_ZB_IOTMASTER_PORT = prop.getProperty("ZIGBEE_IOTMASTER_PORT");
-               STR_NUM_CALLBACK_PORTS = prop.getProperty("NUMBER_CALLBACK_PORTS");
                STR_JVM_INIT_HEAP_SIZE = prop.getProperty("JVM_INIT_HEAP_SIZE");
                STR_JVM_MAX_HEAP_SIZE = prop.getProperty("JVM_MAX_HEAP_SIZE");
-               STR_LANGUAGE = prop.getProperty("LANGUAGE");
                STR_SKEL_CLASS_SUFFIX = prop.getProperty("SKEL_CLASS_SUFFIX");
                STR_STUB_CLASS_SUFFIX = prop.getProperty("STUB_CLASS_SUFFIX");
+               STR_ACTIVATE_SANDBOXING = prop.getProperty("ACTIVATE_SANDBOXING");
                if(prop.getProperty("VERBOSE").equals(STR_YES)) {
                        BOOL_VERBOSE = true;
                }
@@ -272,12 +300,11 @@ public class IoTMaster {
                RuntimeOutput.print("STR_ZB_GATEWAY_ADDRESS=" + STR_ZB_GATEWAY_ADDRESS, BOOL_VERBOSE);
                RuntimeOutput.print("STR_ZB_GATEWAY_PORT=" + STR_ZB_GATEWAY_PORT, BOOL_VERBOSE);
                RuntimeOutput.print("STR_ZB_IOTMASTER_PORT=" + STR_ZB_IOTMASTER_PORT, BOOL_VERBOSE);
-               RuntimeOutput.print("STR_NUM_CALLBACK_PORTS=" + STR_NUM_CALLBACK_PORTS, BOOL_VERBOSE);
                RuntimeOutput.print("STR_JVM_INIT_HEAP_SIZE=" + STR_JVM_INIT_HEAP_SIZE, BOOL_VERBOSE);
                RuntimeOutput.print("STR_JVM_MAX_HEAP_SIZE=" + STR_JVM_MAX_HEAP_SIZE, BOOL_VERBOSE);
-               RuntimeOutput.print("STR_LANGUAGE=" + STR_LANGUAGE, BOOL_VERBOSE);
                RuntimeOutput.print("STR_SKEL_CLASS_SUFFIX=" + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE);
                RuntimeOutput.print("STR_STUB_CLASS_SUFFIX=" + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE);
+               RuntimeOutput.print("STR_ACTIVATE_SANDBOXING=" + STR_ACTIVATE_SANDBOXING, BOOL_VERBOSE);
                RuntimeOutput.print("BOOL_VERBOSE=" + BOOL_VERBOSE, BOOL_VERBOSE);
                RuntimeOutput.print("IoTMaster: Information extracted successfully!", BOOL_VERBOSE);
        }
@@ -380,16 +407,17 @@ public class IoTMaster {
         * @params  strIoTSlaveObjectHostAdd  String slave host address
         * @params  inStream                  ObjectInputStream communication
         * @params  inStream                  ObjectOutputStream communication
+        * @params  strLanguage                           String language
         * @return  void
         */
        private void instrumentIoTSetDevice(String strFieldIdentifier, String strObjName, String strFieldName, String strIoTSlaveObjectHostAdd,
-               InputStream inStream, OutputStream outStream)  
+               InputStream inStream, OutputStream outStream, String strLanguage)  
                        throws IOException, ClassNotFoundException, InterruptedException {
 
                // Get information from the set
                List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
                // Create a new IoTSet
-               if(STR_LANGUAGE.equals(STR_JAVA)) {
+               if(strLanguage.equals(STR_JAVA)) {
                        Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
                        commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTDeviceAddress!", inStream, outStream);
                } else
@@ -429,7 +457,7 @@ public class IoTMaster {
                        System.out.println("DEBUG: InstrumentSetDevice: Device address: " + strDeviceAddressKey + "\n\n");
 
                        // Send address one by one
-                       if(STR_LANGUAGE.equals(STR_JAVA)) {
+                       if(strLanguage.equals(STR_JAVA)) {
                                Message msgGetIoTSetObj = null;
                                if (bDstPortWildCard) {
                                        String strUniqueDev = strDeviceAddressKey + ":" + iRow;
@@ -444,7 +472,7 @@ public class IoTMaster {
                                        bSrcPortWildCard, bDstPortWildCard);
                }
                // Reinitialize IoTSet on device object
-               if(STR_LANGUAGE.equals(STR_JAVA))
+               if(strLanguage.equals(STR_JAVA))
                        commMasterToSlave(new MessageSimple(IoTCommCode.REINITIALIZE_IOTSET_FIELD), "Reinitialize IoTSet fields!", inStream, outStream);
                else
                        reinitializeIoTSetFieldCpp(outStream, inStream);
@@ -459,16 +487,17 @@ public class IoTMaster {
         * @params  strIoTSlaveObjectHostAdd  String slave host address
         * @params  inStream                  ObjectInputStream communication
         * @params  inStream                  ObjectOutputStream communication
+        * @params  strLanguage                           String language
         * @return  void
         */
        private void instrumentIoTSetZBDevice(Map.Entry<String,Object> map, String strObjName, String strFieldName, String strIoTSlaveObjectHostAdd,
-               InputStream inStream, OutputStream outStream)  
+               InputStream inStream, OutputStream outStream, String strLanguage)  
                        throws IOException, ClassNotFoundException, InterruptedException {
 
                // Get information from the set
                SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
                // Create a new IoTSet
-               if(STR_LANGUAGE.equals(STR_JAVA)) {
+               if(strLanguage.equals(STR_JAVA)) {
                        Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
                        commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTZigbeeAddress!", inStream, outStream);
                } else  // TODO: will need to implement IoTSet Zigbee for C++ later
@@ -489,7 +518,7 @@ public class IoTMaster {
                RuntimeOutput.print("IoTMaster: Number of rows for IoTZigbeeAddress: " + iRows, BOOL_VERBOSE);
 
                // TODO: DEBUG!!!
-               System.out.println("\n\n DEBUG: InstrumentZigbeeDevice: Object Name: " + strObjName);
+               System.out.println("\n\nDEBUG: InstrumentZigbeeDevice: Object Name: " + strObjName);
                System.out.println("DEBUG: InstrumentZigbeeDevice: Port number: " + commHan.getComPort(strZigbeeGWAddressKey));
                System.out.println("DEBUG: InstrumentZigbeeDevice: Device address: " + strZigbeeGWAddress + "\n\n");
 
@@ -501,7 +530,7 @@ public class IoTMaster {
                        // Send policy to Zigbee gateway - TODO: Need to clear policy first?
                        zbConfig.setPolicy(strIoTSlaveObjectHostAdd, commHan.getComPort(strZigbeeGWAddressKey), strZBDevAddress);
                        // Send address one by one
-                       if(STR_LANGUAGE.equals(STR_JAVA)) {
+                       if(strLanguage.equals(STR_JAVA)) {
                                Message msgGetIoTSetZBObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ZB_DEV_IOTSET_OBJECT, strZBDevAddress);
                                commMasterToSlave(msgGetIoTSetZBObj, "Get IoTSet objects!", inStream, outStream);
                        } else  // TODO: Implement IoTSet Zigbee for C++
@@ -520,16 +549,17 @@ public class IoTMaster {
         * @params  strFieldName              String field name
         * @params  inStream                  ObjectInputStream communication
         * @params  inStream                  ObjectOutputStream communication
+        * @params  strLanguage                           String language
         * @return  void
         */
        private void instrumentIoTSetAddress(String strFieldIdentifier, String strFieldName,
-               InputStream inStream, OutputStream outStream)  
+               InputStream inStream, OutputStream outStream, String strLanguage)  
                        throws IOException, ClassNotFoundException, InterruptedException {
 
                // Get information from the set
                List<Object[]> listObject = objAddInitHand.getFields(strFieldIdentifier);
                // Create a new IoTSet
-               if(STR_LANGUAGE.equals(STR_JAVA)) {
+               if(strLanguage.equals(STR_JAVA)) {
                        Message msgCrtIoTSet = new MessageCreateSetRelation(IoTCommCode.CREATE_NEW_IOTSET, strFieldName);
                        commMasterToSlave(msgCrtIoTSet, "Create new IoTSet for IoTAddress!", inStream, outStream);
                } else
@@ -542,7 +572,7 @@ public class IoTMaster {
                        // Get device address
                        String strAddress = (String) arrFieldValues[0];
                        // Send address one by one
-                       if(STR_LANGUAGE.equals(STR_JAVA)) {
+                       if(strLanguage.equals(STR_JAVA)) {
                                Message msgGetIoTSetAddObj = new MessageGetSimpleDeviceObject(IoTCommCode.GET_ADD_IOTSET_OBJECT, strAddress);
                                commMasterToSlave(msgGetIoTSetAddObj, "Get IoTSet objects!", inStream, outStream);
                        } else  // TODO: Implement IoTSet Address for C++
@@ -557,10 +587,12 @@ public class IoTMaster {
        /**
         * A private method to instrument an object on a specific machine and setting up policies
         *
-        * @params  strFieldObjectID  String field object ID
+        * @params  strFieldObjectID              String field object ID
+        * @params  strObjControllerName          String object controller name
+        * @params  strLanguage                           String language
         * @return  void
         */
-       private void instrumentObject(String strFieldObjectID) throws IOException {
+       private void instrumentObject(String strFieldObjectID, String strObjControllerName, String strLanguage) throws IOException {
 
                // Extract the interface name for RMI
                // e.g. ProximitySensorInterface, TempSensorInterface, etc.
@@ -605,8 +637,18 @@ public class IoTMaster {
                                strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
                        routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd,
                                strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
+                       // Configure MAC policies for objects
+                       //String strFileName = STR_MAC_POL_PATH + strObjClassName + STR_MAC_POLICY_EXT;
+                       String strFileName = STR_MAC_POL_PATH + STR_JAVA + STR_MAC_POLICY_EXT;
+                       if (STR_ACTIVATE_SANDBOXING.equals("Yes")) {
+                               processJailConfig.configureProcessJailDeviceDriverPolicies(strIoTSlaveObjectHostAdd, strObjName, strObjClassName,
+                                       strFileName, strIoTMasterHostAdd, commHan.getComPort(strObjName), commHan.getRMIRegPort(strObjName), 
+                                       commHan.getRMIStubPort(strObjName));
+                               processJailConfig.configureProcessJailContRMIPolicies(strObjControllerName, strIoTSlaveObjectHostAdd, 
+                                       commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName));
+                       }
                        // Instrument the IoTSet declarations inside the class file
-                       instrumentObjectIoTSet(strFieldObjectID);
+                       instrumentObjectIoTSet(strFieldObjectID, strLanguage);
                }
                // Send routing policy to router for controller object
                // ROUTING POLICY: RMI communication - RMI registry and stub ports
@@ -623,35 +665,8 @@ public class IoTMaster {
                        STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
                routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
                        STR_TCP_PROTOCOL, commHan.getRMIStubPort(strObjName));
-               // Send the same set of routing policies for callback ports
-               setCallbackPortsPolicy(strObjName, STR_ROUTER_ADD, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
        }
 
-       /**
-        * A private method to set router policies for callback ports
-        *
-        * @params  strRouterAdd                                String router address
-        * @params  strIoTSlaveControllerHostAdd        String slave controller host address
-        * @params  strIoTSlaveObjectHostAdd            String slave object host address
-        * @params      strProtocol                                             String protocol
-        * @return  iPort                                                       Integer port number
-        */
-       private void setCallbackPortsPolicy(String strObjName, String strRouterAdd, String strIoTSlaveControllerHostAdd, 
-               String strIoTSlaveObjectHostAdd, String strProtocol) {
-
-               int iNumCallbackPorts = Integer.parseInt(STR_NUM_CALLBACK_PORTS);
-               Integer[] rmiCallbackPorts = commHan.getCallbackPorts(strObjName, iNumCallbackPorts);
-
-               // Iterate over port numbers and set up policies
-               for (int i=0; i<iNumCallbackPorts; i++) {
-                       routerConfig.configureRouterMainPolicies(strRouterAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
-                               strProtocol, rmiCallbackPorts[i]);
-                       routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
-                               strProtocol, rmiCallbackPorts[i]);
-                       routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveControllerHostAdd, strIoTSlaveObjectHostAdd,
-                               strProtocol, rmiCallbackPorts[i]);
-               }
-       }
 
        /**
         * A private method to set router policies for IoTDeviceAddress objects
@@ -722,6 +737,9 @@ public class IoTMaster {
                                routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, STR_TCP_PROTOCOL, iDestDeviceDriverPort);
                                routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strIoTSlaveObjectHostAdd, strDeviceAddress);
                                routerConfig.configureHostHTTPPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress);
+                               // Configure MAC policies
+                               if (STR_ACTIVATE_SANDBOXING.equals("Yes"))
+                                       processJailConfig.configureProcessJailGWDevicePolicies(strIoTSlaveObjectHostAdd, STR_ROUTER_ADD, INT_DNS_PORT);
                        } else {
                                // Other port numbers...
                                commHan.addDevicePort(iDestDeviceDriverPort);
@@ -729,6 +747,10 @@ public class IoTMaster {
                                        commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort);
                                routerConfig.configureHostMainPolicies(strIoTSlaveObjectHostAdd, strIoTSlaveObjectHostAdd, strDeviceAddress, strProtocol, 
                                        commHan.getComPort(strDeviceAddressKey), iDestDeviceDriverPort);
+                               // Configure MAC policies
+                               if (STR_ACTIVATE_SANDBOXING.equals("Yes"))
+                                       processJailConfig.configureProcessJailDevicePolicies(strIoTSlaveObjectHostAdd, strProtocol,
+                                               commHan.getComPort(strDeviceAddressKey), strDeviceAddress, iDestDeviceDriverPort);
                        }
                }
        }
@@ -742,7 +764,7 @@ public class IoTMaster {
         * @return  void
         */
        private void setRouterPolicyIoTSetAddress(String strFieldIdentifier, Map.Entry<String,Object> map, 
-               String strHostAddress) {
+               String strHostAddress, String strControllerName) {
 
                // Get information from the set
                SetInstrumenter setInstrumenter = (SetInstrumenter) map.getValue();
@@ -755,6 +777,13 @@ public class IoTMaster {
                        // Get device address
                        String strAddress = (String) arrFieldValues[0];
                        // Setting up router policies for HTTP/HTTPs
+                       if (STR_ACTIVATE_SANDBOXING.equals("Yes")) {
+                               if (strControllerName != null) {
+                                       processJailConfig.configureProcessJailInetAddressPolicies(strControllerName, strAddress);
+                               } else {
+                                       processJailConfig.configureProcessJailInetAddressPolicies(strHostAddress, strAddress);
+                               }
+                       }
                        routerConfig.configureRouterHTTPPolicies(STR_ROUTER_ADD, strHostAddress, strAddress);
                        routerConfig.configureHostHTTPPolicies(strHostAddress, strHostAddress, strAddress);
                }
@@ -765,16 +794,17 @@ public class IoTMaster {
         * <p>
         * Mostly the IoTSet fields would contain IoTDeviceAddress objects
         *
-        * @params  strFieldObjectID  String field object ID
+        * @params  strFieldObjectID    String field object ID
+        * @params  strLanguage                 String language
         * @return  void
         */
-       private void instrumentObjectIoTSet(String strFieldObjectID) throws IOException {
+       private void instrumentObjectIoTSet(String strFieldObjectID, String strLanguage) throws IOException {
 
                // If this is a new object ... then create one
                // Instrument the class source code and look for IoTSet for device addresses
                // e.g. @config private IoTSet<IoTDeviceAddress> lb_addresses;
                HashMap<String,Object> hmObjectFieldObjects = null;
-               if(STR_LANGUAGE.equals(STR_JAVA)) {
+               if(strLanguage.equals(STR_JAVA)) {
                        String strObjectClassNamePath = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CLS_FILE_EXT;
                        FileInputStream fis = new FileInputStream(strObjectClassNamePath);
                        ClassReader cr = new ClassReader(fis);
@@ -808,7 +838,7 @@ public class IoTMaster {
                                        setRouterPolicyIoTSetDevice(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
                                } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) { 
                                // Instrument the IoTAddress
-                                       setRouterPolicyIoTSetAddress(strFieldIdentifier, map, strIoTSlaveObjectHostAdd);
+                                       setRouterPolicyIoTSetAddress(strFieldIdentifier, map, strIoTSlaveObjectHostAdd, null);
                                } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) { 
                                // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
                                        RuntimeOutput.print("IoTMaster: IoTZigbeeAddress found! No router policy is set here..", 
@@ -885,7 +915,7 @@ public class IoTMaster {
                RuntimeOutput.print("IoTMaster: Executing: " + strCmdSend, BOOL_VERBOSE);
                // Unzip file
                String strCmdUnzip = STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " +
-                                       STR_SLAVE_DIR + " sudo unzip " + sFileName + ";";
+                                       STR_SLAVE_DIR + " sudo unzip -o " + sFileName + ";";
                runCommand(strCmdUnzip);
                RuntimeOutput.print("IoTMaster: Executing: " + strCmdUnzip, BOOL_VERBOSE);
 
@@ -899,11 +929,18 @@ public class IoTMaster {
         */
        private String getCmdJavaDriverIoTSlave(String strIoTMasterHostAdd, String strIoTSlaveObjectHostAdd, String strObjName) {
 
-               return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " + STR_RUNTIME_DIR + " sudo java " +
-                       STR_CLS_PATH + " " + STR_RMI_PATH + " " + STR_RMI_HOSTNAME +
-                       strIoTSlaveObjectHostAdd + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
+               // Create an Shell executable
+               String strJavaCommand = STR_SHELL_HEADER + "\nexec " + STR_JAVA_PATH + " " + STR_CLS_PATH + " " + STR_RMI_PATH + " " + 
+                       STR_RMI_HOSTNAME + strIoTSlaveObjectHostAdd + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
                        commHan.getComPort(strObjName) + " " + commHan.getRMIRegPort(strObjName) + " " +
-                       commHan.getRMIStubPort(strObjName) + " >& " + STR_LOG_FILE_PATH + strObjName + ".log &";
+                       commHan.getRMIStubPort(strObjName) + " > " + STR_LOG_FILE_PATH + strObjName + ".log &";
+               String shellFile = "./" + strObjName + STR_SHELL_FILE_EXT;
+               createWrapperShellScript(strJavaCommand, shellFile);
+               // Send the file to the compute node
+               String strCmdSend = "scp " + shellFile + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + ":" + STR_RUNTIME_DIR;
+               runCommand(strCmdSend);
+               System.out.println("IoTMaster: Sending shell file: " + strCmdSend);
+               return STR_SSH + " " + STR_USERNAME + strIoTSlaveObjectHostAdd + " cd " + STR_RUNTIME_DIR + " " + shellFile;
        }
 
 
@@ -920,6 +957,22 @@ public class IoTMaster {
        }
 
 
+       /**
+        * createWrapperShellScript() gets a wrapper shell script
+        *
+        * @param   strCommand          String command
+        * @param   strObjectName       String object name
+        * @return  PrintWriter
+        */
+       private void createWrapperShellScript(String strCommand, String strFileName) {
+
+               PrintWriter printWriter = getPrintWriter(strFileName);
+               printWriter.println(strCommand);
+               printWriter.close();
+               runCommand("chmod 755 " + strFileName);
+       }
+
+
        /**
         * A private method to create an object on a specific machine
         *
@@ -936,10 +989,16 @@ public class IoTMaster {
                String strIoTSlaveObjectHostAdd, String strFieldObjectID, Object[] arrFieldValues, Class[] arrFieldClasses) 
                throws IOException, FileNotFoundException, ClassNotFoundException, InterruptedException {
 
+               // Read config file
+               String sCfgFile = STR_IOT_CODE_PATH + strObjClassName + "/" + strObjClassName + STR_CFG_FILE_EXT;
+               String strLanguageDriver = parseConfigFile(sCfgFile, STR_LANGUAGE + "_" + strObjName);
+               if(strLanguageDriver == null)   // Read just the field LANGUAGE if the first read is null
+                       strLanguageDriver = parseConfigFile(sCfgFile, STR_LANGUAGE);
+               if(strLanguageDriver == null) // Check nullness for the second time - report if it is still null
+                       throw new Error("IoTMaster: Language specification missing in config file: " + sCfgFile);
                // PROFILING
                long start = 0;
                long result = 0;
-
                // PROFILING
                start = System.currentTimeMillis();
 
@@ -950,10 +1009,13 @@ public class IoTMaster {
                //           iotruntime.IoTSlave dw-1.eecs.uci.edu 46151 23829 42874 &
                // The In-Port for IoTMaster is the Out-Port for IoTSlave and vice versa
                String strSSHCommand = null;
-               if(STR_LANGUAGE.equals(STR_JAVA))
+               if(strLanguageDriver.equals(STR_JAVA))
                        strSSHCommand = getCmdJavaDriverIoTSlave(strIoTMasterHostAdd, strIoTSlaveObjectHostAdd, strObjName);
-               else
+               else if(strLanguageDriver.equals(STR_CPP))
                        strSSHCommand = getCmdCppDriverIoTSlave(strIoTMasterHostAdd, strIoTSlaveObjectHostAdd, strObjName);
+               else
+                       throw new Error("IoTMaster: Language specification not recognized: " + strLanguageDriver);
+               RuntimeOutput.print("IoTMaster: Language for " + strObjName + " is " + strLanguageDriver, BOOL_VERBOSE);
 
                RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
                // Start a new thread to start a new JVM
@@ -964,7 +1026,7 @@ public class IoTMaster {
                //OutputStream outStream = new ObjectOutputStream(socket.getOutputStream());
                InputStream inStream = null;
                OutputStream outStream = null;
-               if(STR_LANGUAGE.equals(STR_JAVA)) {
+               if(strLanguageDriver.equals(STR_JAVA)) {
                        inStream = new ObjectInputStream(socket.getInputStream());
                        outStream = new ObjectOutputStream(socket.getOutputStream());
                } else {        // At this point the language is certainly C++, otherwise would've complained above
@@ -980,7 +1042,7 @@ public class IoTMaster {
                // PROFILING
                start = System.currentTimeMillis();
 
-               if(STR_LANGUAGE.equals(STR_JAVA)) {
+               if(strLanguageDriver.equals(STR_JAVA)) {
                        sendFileToJavaSlaveDriver(serverSocket, inStream, outStream, strObjName, 
                                strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName,
                                strIoTSlaveObjectHostAdd, strFieldObjectID, arrFieldValues, arrFieldClasses);
@@ -1023,17 +1085,17 @@ public class IoTMaster {
                                if(setInstrumenter.getObjTableName().equals(STR_IOT_DEV_ADD_CLS)) { 
                                // Instrument the normal IoTDeviceAddress
                                        synchronized(this) {
-                                               instrumentIoTSetDevice(strFieldIdentifier, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream);
+                                               instrumentIoTSetDevice(strFieldIdentifier, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream, strLanguageDriver);
                                        }
                                } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ZB_ADD_CLS)) { 
                                // Instrument the IoTZigbeeAddress - special feature for Zigbee device support
                                        synchronized(this) {
-                                               instrumentIoTSetZBDevice(map, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream);
+                                               instrumentIoTSetZBDevice(map, strObjName, strFieldName, strIoTSlaveObjectHostAdd, inStream, outStream, strLanguageDriver);
                                        }
                                } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) { 
                                // Instrument the IoTAddress
                                        synchronized(this) {
-                                               instrumentIoTSetAddress(strFieldIdentifier, strFieldName, inStream, outStream);
+                                               instrumentIoTSetAddress(strFieldIdentifier, strFieldName, inStream, outStream, strLanguageDriver);
                                        }
                                } else {
                                        String strErrMsg = "IoTMaster: Device driver object can only have IoTSet<IoTAddress>, IoTSet<IoTDeviceAddress>," +
@@ -1047,13 +1109,13 @@ public class IoTMaster {
                }
                // End the session
                // TODO: Change this later
-
-               if(STR_LANGUAGE.equals(STR_JAVA)) {
+               if(strLanguageDriver.equals(STR_JAVA)) {
                        ObjectOutputStream oStream = (ObjectOutputStream) outStream;
                        oStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
-               } else  // C++ side for now will be running continuously because it's an infinite loop (not in a separate thread)
+               } else {        // C++ side for now will be running continuously because it's an infinite loop (not in a separate thread)
+                       createDriverObjectCpp(outStream, inStream);
                        //endSessionCpp(outStream);
-                       ;
+               }
 
                // PROFILING
                result = System.currentTimeMillis()-start;
@@ -1072,7 +1134,7 @@ public class IoTMaster {
         *
         * @return  void
         */
-       private void createControllerObjects() throws InterruptedException {
+       private void createDriverObjects() throws InterruptedException {
 
                // Create a list of threads
                List<Thread> threads = new ArrayList<Thread>();
@@ -1116,9 +1178,10 @@ public class IoTMaster {
         *
         * @params  Map.Entry<String,Object>  Entry of map IoTSet instrumentation
         * @params  strFieldName              String field name
+        * @params  strLanguage                           String language
         * @return  void
         */
-       private void instrumentIoTSet(Map.Entry<String,Object> map, String strFieldName) 
+       private void instrumentIoTSet(Map.Entry<String,Object> map, String strFieldName, String strObjControllerName, String strLanguage
                throws IOException, ClassNotFoundException, InterruptedException {
                                
                // Get information from the set
@@ -1134,11 +1197,10 @@ public class IoTMaster {
                        String strObjID = setInstrumenter.fieldObjectID(iRow);
                        strObjClassName = setInstrumenter.fieldEntryType(strObjID);
                        // Call the method to create an object
-                       instrumentObject(strObjID);
-                       int iNumOfPorts = Integer.parseInt(STR_NUM_CALLBACK_PORTS);
+                       instrumentObject(strObjID, strObjControllerName, strLanguage);
                        objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
                                strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName, commHan.getRMIRegPort(strObjName), 
-                               commHan.getRMIStubPort(strObjName), commHan.getCallbackPorts(strObjName, iNumOfPorts));
+                               commHan.getRMIStubPort(strObjName));
                }
        }
 
@@ -1148,9 +1210,10 @@ public class IoTMaster {
         *
         * @params  Map.Entry<String,Object>  Entry of map IoTRelation instrumentation
         * @params  strFieldName              String field name
+        * @params  strLanguage                           String language
         * @return  void
         */
-       private void instrumentIoTRelation(Map.Entry<String,Object> map, String strFieldName) 
+       private void instrumentIoTRelation(Map.Entry<String,Object> map, String strFieldName, String strObjControllerName, String strLanguage
                throws IOException, ClassNotFoundException, InterruptedException {
 
                        // Get information from the set
@@ -1165,27 +1228,24 @@ public class IoTMaster {
                        String strObjID = relationInstrumenter.firstFieldObjectID(iRow);
                        strObjClassName = relationInstrumenter.firstEntryFieldType(strObjID);
                        // Call the method to create an object
-                       instrumentObject(strObjID);
+                       instrumentObject(strObjID, strObjControllerName, strLanguage);
                        // Get the first object controller host address
                        String strFirstIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
-                       int iNumOfPorts = Integer.parseInt(STR_NUM_CALLBACK_PORTS);
                        objInitHand.addObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
                                strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName, 
-                               commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName), 
-                               commHan.getCallbackPorts(strObjName, iNumOfPorts));
+                               commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName));
                        // Operate on the second set
                        arrFieldClasses = relationInstrumenter.secondFieldClasses(iRow);
                        arrFieldValues = relationInstrumenter.secondFieldValues(iRow);
                        strObjID = relationInstrumenter.secondFieldObjectID(iRow);
                        strObjClassName = relationInstrumenter.secondEntryFieldType(strObjID);
                        // Call the method to create an object
-                       instrumentObject(strObjID);
+                       instrumentObject(strObjID, strObjControllerName, strLanguage);
                        // Get the second object controller host address
                        String strSecondIoTSlaveObjectHostAdd = strIoTSlaveObjectHostAdd;
                        objInitHand.addSecondObjectIntoField(strFieldName, strIoTSlaveObjectHostAdd, strObjName,
                                strObjClassName, strObjClassInterfaceName, strObjStubClsIntfaceName, 
-                               commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName),
-                               commHan.getCallbackPorts(strObjName, iNumOfPorts));
+                               commHan.getRMIRegPort(strObjName), commHan.getRMIStubPort(strObjName));
                        // ROUTING POLICY: first and second controller objects in IoTRelation
                        routerConfig.configureRouterMainPolicies(STR_ROUTER_ADD, strFirstIoTSlaveObjectHostAdd,
                                strSecondIoTSlaveObjectHostAdd, STR_TCP_PROTOCOL);
@@ -1220,8 +1280,8 @@ public class IoTMaster {
                                        // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
                                        commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(),
                                                objInitInfo.getObjectName(), objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), 
-                                               objInitInfo.getObjectStubClassInterfaceName(), objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(),
-                                               objInitInfo.getRMICallbackPorts()), "Get IoTSet object!", inStream, outStream);
+                                               objInitInfo.getObjectStubClassInterfaceName(), objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()), 
+                                               "Get IoTSet object!", inStream, outStream);
 
                                }
                                // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
@@ -1239,14 +1299,14 @@ public class IoTMaster {
                                        commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT, 
                                                objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), objInitInfo.getObjectClassName(),
                                                objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
-                                               objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), objInitInfo.getRMICallbackPorts()), 
+                                               objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort()), 
                                                "Get IoTRelation first object!", inStream, outStream);
                                        ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
                                        // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
                                        commMasterToSlave(new MessageGetObject(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT,
                                                objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(), objSecObj.getObjectClassName(),
                                                objSecObj.getObjectClassInterfaceName(), objSecObj.getObjectStubClassInterfaceName(),
-                                               objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort(), objSecObj.getRMICallbackPorts()), 
+                                               objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort()), 
                                                "Get IoTRelation second object!", inStream, outStream);
                                }
                                // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
@@ -1276,10 +1336,9 @@ public class IoTMaster {
                                List<ObjectInitInfo> listObject = objInitHand.getListObjectInitInfo(str);
                                for (ObjectInitInfo objInitInfo : listObject) {
                                        // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTSET
-                                       getIoTSetRelationObjectCpp(objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), 
-                                               objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), 
-                                               objInitInfo.getObjectStubClassInterfaceName(), objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(),
-                                               objInitInfo.getRMICallbackPorts(), outStream, inStream);
+                                       getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTSET_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), 
+                                               objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
+                                               objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), outStream, inStream);
                                }
                                // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTSET FIELD
                                reinitializeIoTSetFieldCpp(outStream, inStream);
@@ -1292,16 +1351,14 @@ public class IoTMaster {
                                Iterator it = listSecondObject.iterator();
                                for (ObjectInitInfo objInitInfo : listObject) {
                                        // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (FIRST OBJECT)
-                                       getIoTSetRelationObjectCpp(objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), 
-                                               objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), 
-                                               objInitInfo.getObjectStubClassInterfaceName(), objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(),
-                                               objInitInfo.getRMICallbackPorts(), outStream, inStream);
+                                       getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTRELATION_FIRST_OBJECT, objInitInfo.getIoTSlaveObjectHostAdd(), objInitInfo.getObjectName(), 
+                                               objInitInfo.getObjectClassName(), objInitInfo.getObjectClassInterfaceName(), objInitInfo.getObjectStubClassInterfaceName(),
+                                               objInitInfo.getRMIRegistryPort(), objInitInfo.getRMIStubPort(), outStream, inStream);
                                        ObjectInitInfo objSecObj = (ObjectInitInfo) it.next();
                                        // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO FILL IN IOTRELATION (SECOND OBJECT)
-                                       getIoTSetRelationObjectCpp(objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(), 
-                                               objSecObj.getObjectClassName(), objSecObj.getObjectClassInterfaceName(), 
-                                               objSecObj.getObjectStubClassInterfaceName(), objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort(),
-                                               objSecObj.getRMICallbackPorts(), outStream, inStream);
+                                       getIoTSetRelationObjectCpp(IoTCommCode.GET_IOTRELATION_SECOND_OBJECT, objSecObj.getIoTSlaveObjectHostAdd(), objSecObj.getObjectName(), 
+                                               objSecObj.getObjectClassName(), objSecObj.getObjectClassInterfaceName(), objSecObj.getObjectStubClassInterfaceName(),
+                                               objSecObj.getRMIRegistryPort(), objSecObj.getRMIStubPort(), outStream, inStream);
                                }
                                // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO REINITIALIZE IOTRELATION FIELD
                                reinitializeIoTRelationFieldCpp(outStream, inStream);
@@ -1396,6 +1453,39 @@ public class IoTMaster {
                }
        }
 
+       /**
+        * A method to create a thread for policy deployment
+        *
+        * @param  setHostAddresses             Set of strings for host addresses to configure
+        * @return                              void
+        */
+       private void createMACPolicyThreads(Set<String> setHostAddresses) throws IOException {
+
+               // Create a list of threads
+               List<Thread> threads = new ArrayList<Thread>();
+               // Start threads for hosts
+               for(String strAddress : setHostAddresses) {
+                       Thread policyThread = new Thread(new Runnable() {
+                               public void run() {
+                                       synchronized(this) {
+                                               processJailConfig.sendMACPolicies(strAddress);
+                                       }
+                               }
+                       });
+                       threads.add(policyThread);
+                       policyThread.start();
+                       RuntimeOutput.print("Deploying MAC policies for: " + strAddress, BOOL_VERBOSE);
+               }
+               // Join all threads
+               for (Thread thread : threads) {
+                       try {
+                               thread.join();
+                       } catch (InterruptedException ex) {
+                               ex.printStackTrace();
+                       }
+               }
+       }
+
 
        /**
         * A method to send files to Java IoTSlave
@@ -1456,21 +1546,21 @@ public class IoTMaster {
                sendString(sFileName, outStream); recvAck(inStream);
                File file = new File(sFilePath + sFileName);
                int iFileLen = toIntExact(file.length());
-               RuntimeOutput.print("IoTSlave: Sending file " + sFileName + " with length " + iFileLen + " bytes...", BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Sending file " + sFileName + " with length " + iFileLen + " bytes...", BOOL_VERBOSE);
                // Send file length
                sendInteger(iFileLen, outStream); recvAck(inStream);
-               RuntimeOutput.print("IoTSlave: Sent file size!", BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Sent file size!", BOOL_VERBOSE);
                byte[] bytFile = new byte[iFileLen];
                InputStream inFileStream = new FileInputStream(file);
-               RuntimeOutput.print("IoTSlave: Opened file!", BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Opened file!", BOOL_VERBOSE);
 
                OutputStream outFileStream = fileSocket.getOutputStream();
-               RuntimeOutput.print("IoTSlave: Got output stream!", BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Got output stream!", BOOL_VERBOSE);
                int iCount;
                while ((iCount = inFileStream.read(bytFile)) > 0) {
                        outFileStream.write(bytFile, 0, iCount);
                }
-               RuntimeOutput.print("IoTSlave: File sent!", BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: File sent!", BOOL_VERBOSE);
                recvAck(inStream);
        }
 
@@ -1490,7 +1580,7 @@ public class IoTMaster {
                RuntimeOutput.print("IoTMaster: Executing: " + strCmdSend, BOOL_VERBOSE);
                // Unzip file
                String strCmdUnzip = STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
-                                       STR_SLAVE_DIR + " sudo unzip " + sFileName + ";";
+                                       STR_SLAVE_DIR + " sudo unzip -o " + sFileName + ";";
                runCommand(strCmdUnzip);
                RuntimeOutput.print("IoTMaster: Executing: " + strCmdUnzip, BOOL_VERBOSE);
        }
@@ -1525,14 +1615,19 @@ public class IoTMaster {
         */
        private String getCmdJavaIoTSlave(String strObjControllerName) {
 
-               return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " +
-                                       STR_RUNTIME_DIR + " sudo java " + STR_JVM_INIT_HEAP_SIZE + " " + 
-                                       STR_JVM_MAX_HEAP_SIZE + " " + STR_CLS_PATH + " " +
-                                       STR_RMI_PATH + " " + STR_IOT_SLAVE_CLS + " " + strIoTMasterHostAdd + " " +
-                                       commHan.getComPort(strObjControllerName) + " " +
-                                       commHan.getRMIRegPort(strObjControllerName) + " " +
-                                       commHan.getRMIStubPort(strObjControllerName) + " >& " +
-                                       STR_LOG_FILE_PATH + strObjControllerName + ".log &";
+               // Create an Shell executable
+               String strJavaCommand = STR_SHELL_HEADER + "\nexec " + STR_JAVA_PATH + " " + STR_JVM_INIT_HEAP_SIZE + " " + 
+                                       STR_JVM_MAX_HEAP_SIZE + " " + STR_CLS_PATH + " " + STR_RMI_PATH + " " + STR_IOT_SLAVE_CLS + " " + 
+                                       strIoTMasterHostAdd + " " + commHan.getComPort(strObjControllerName) + " " +
+                                       commHan.getRMIRegPort(strObjControllerName) + " " + commHan.getRMIStubPort(strObjControllerName) + 
+                                       " > " + STR_LOG_FILE_PATH + strObjControllerName + ".log &";
+               String shellFile = "./" + strObjControllerName + STR_SHELL_FILE_EXT;
+               createWrapperShellScript(strJavaCommand, shellFile);
+               // Send the file to the compute node
+               String strCmdSend = "scp " + shellFile + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + ":" + STR_RUNTIME_DIR;
+               runCommand(strCmdSend);
+               System.out.println("IoTMaster: Sending main controller shell file: " + strCmdSend);
+               return STR_SSH + " " + STR_USERNAME + strIoTSlaveControllerHostAdd + " cd " + STR_RUNTIME_DIR + " " + shellFile;
        }
 
 
@@ -1631,7 +1726,7 @@ public class IoTMaster {
        /**
         * Receive ACK
         */
-       public boolean recvAck(InputStream inStream) throws IOException {
+       public synchronized boolean recvAck(InputStream inStream) throws IOException {
 
                int intAck = recvInteger(inStream);
                IoTCommCode codeAck = getCode(intAck);
@@ -1674,7 +1769,7 @@ public class IoTMaster {
                sendCommCode(IoTCommCode.CREATE_MAIN_OBJECT, outStream, inStream);
                String strMainObjName = strObjControllerName;
                sendString(strMainObjName, outStream); recvAck(inStream);
-               RuntimeOutput.print("IoTSlave: Create a main object: " + strMainObjName, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Create a main object: " + strMainObjName, BOOL_VERBOSE);
        }
 
 
@@ -1723,27 +1818,27 @@ public class IoTMaster {
                OutputStream outStream, InputStream inStream) throws IOException {
 
                sendCommCode(IoTCommCode.CREATE_OBJECT, outStream, inStream);
-               RuntimeOutput.print("IoTSlave: Send request to create a driver object... ", BOOL_VERBOSE);
-               RuntimeOutput.print("IoTSlave: Driver object name: " + strObjName, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Send request to create a driver object... ", BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Driver object name: " + strObjName, BOOL_VERBOSE);
                sendString(strObjName, outStream); recvAck(inStream);
-               RuntimeOutput.print("IoTSlave: Driver object class name: " + strObjClassName, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Driver object class name: " + strObjClassName, BOOL_VERBOSE);
                sendString(strObjClassName, outStream); recvAck(inStream);
-               RuntimeOutput.print("IoTSlave: Driver object interface name: " + strObjClassInterfaceName, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Driver object interface name: " + strObjClassInterfaceName, BOOL_VERBOSE);
                sendString(strObjStubClsIntfaceName, outStream); recvAck(inStream);
-               RuntimeOutput.print("IoTSlave: Driver object skeleton class name: " + strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Driver object skeleton class name: " + strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, BOOL_VERBOSE);
                sendString(strObjClassInterfaceName + STR_SKEL_CLASS_SUFFIX, outStream); recvAck(inStream);
-               RuntimeOutput.print("IoTSlave: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE);
                sendInteger(iRMIRegistryPort, outStream); recvAck(inStream);
-               RuntimeOutput.print("IoTSlave: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE);
                sendInteger(iRMIStubPort, outStream); recvAck(inStream);
                int numOfArgs = arrFieldValues.length;
-               RuntimeOutput.print("IoTSlave: Send constructor arguments! Number of arguments: " + numOfArgs, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Send constructor arguments! Number of arguments: " + numOfArgs, BOOL_VERBOSE);
                sendInteger(numOfArgs, outStream); recvAck(inStream);
                for(Object obj : arrFieldValues) {
                        String str = getObjectConverted(obj);
                        sendString(str, outStream); recvAck(inStream);
                }
-               RuntimeOutput.print("IoTSlave: Send constructor argument classes!", BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Send constructor argument classes!", BOOL_VERBOSE);
                for(Class cls : arrFieldClasses) {
                        String str = getClassConverted(cls);
                        sendString(str, outStream); recvAck(inStream);
@@ -1757,8 +1852,8 @@ public class IoTMaster {
        public void createNewIoTSetCpp(String strObjFieldName, OutputStream outStream, InputStream inStream) throws IOException {
 
                sendCommCode(IoTCommCode.CREATE_NEW_IOTSET, outStream, inStream);
-               RuntimeOutput.print("IoTSlave: Creating new IoTSet...", BOOL_VERBOSE);
-               RuntimeOutput.print("IoTSlave: Send object field name: " + strObjFieldName, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Creating new IoTSet...", BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Send object field name: " + strObjFieldName, BOOL_VERBOSE);
                sendString(strObjFieldName, outStream); recvAck(inStream);
        }
 
@@ -1769,8 +1864,8 @@ public class IoTMaster {
        public void createNewIoTRelationCpp(String strObjFieldName, OutputStream outStream, InputStream inStream) throws IOException {
 
                sendCommCode(IoTCommCode.CREATE_NEW_IOTRELATION, outStream, inStream);
-               RuntimeOutput.print("IoTSlave: Creating new IoTRelation...", BOOL_VERBOSE);
-               RuntimeOutput.print("IoTSlave: Send object field name: " + strObjFieldName, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Creating new IoTRelation...", BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Send object field name: " + strObjFieldName, BOOL_VERBOSE);
                sendString(strObjFieldName, outStream); recvAck(inStream);
        }
 
@@ -1782,7 +1877,7 @@ public class IoTMaster {
                        String strDeviceAddress, int iSourcePort, int iDestPort, boolean bSourceWildCard, boolean bDestWildCard) throws IOException {
 
                sendCommCode(IoTCommCode.GET_DEVICE_IOTSET_OBJECT, outStream, inStream);
-               RuntimeOutput.print("IoTSlave: Getting IoTDeviceAddress...", BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Getting IoTDeviceAddress...", BOOL_VERBOSE);
                sendString(strDeviceAddress, outStream); recvAck(inStream);
                sendInteger(iSourcePort, outStream); recvAck(inStream);
                sendInteger(iDestPort, outStream); recvAck(inStream);
@@ -1790,38 +1885,34 @@ public class IoTMaster {
                sendInteger(iSourceWildCard, outStream); recvAck(inStream);
                int iDestWildCard = (bDestWildCard ? 1 : 0);
                sendInteger(iDestWildCard, outStream); recvAck(inStream);
-               RuntimeOutput.print("IoTSlave: Send device address: " + strDeviceAddress, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Send device address: " + strDeviceAddress, BOOL_VERBOSE);
        }
 
 
        /**
         * Get a IoTSet content object for C++
         */
-       public void getIoTSetRelationObjectCpp(String strIoTSlaveHostAddress, String strObjectName, String strObjectClassName, 
+       public void getIoTSetRelationObjectCpp(IoTCommCode iotCommCode, String strIoTSlaveHostAddress, String strObjectName, String strObjectClassName, 
                        String strObjectClassInterfaceName, String strObjectStubClassInterfaceName, int iRMIRegistryPort, int iRMIStubPort, 
-                       Integer[] iCallbackPorts, OutputStream outStream, InputStream inStream) throws IOException {
+                       OutputStream outStream, InputStream inStream) throws IOException {
 
-               sendCommCode(IoTCommCode.GET_IOTSET_OBJECT, outStream, inStream);
-               RuntimeOutput.print("IoTSlave: Getting IoTSet object content...", BOOL_VERBOSE);
+               sendCommCode(iotCommCode, outStream, inStream);
+               RuntimeOutput.print("IoTMaster: Getting IoTSet object content...", BOOL_VERBOSE);
                // Send info
-               RuntimeOutput.print("IoTSlave: Send host address: " + strIoTSlaveHostAddress, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Send host address: " + strIoTSlaveHostAddress, BOOL_VERBOSE);
                sendString(strIoTSlaveHostAddress, outStream); recvAck(inStream);
-               RuntimeOutput.print("IoTSlave: Driver object name: " + strObjectName, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Driver object name: " + strObjectName, BOOL_VERBOSE);
                sendString(strObjectName, outStream); recvAck(inStream);
-               RuntimeOutput.print("IoTSlave: Driver object class name: " + strObjectClassName, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Driver object class name: " + strObjectClassName, BOOL_VERBOSE);
                sendString(strObjectClassName, outStream); recvAck(inStream);
-               RuntimeOutput.print("IoTSlave: Driver object interface name: " + strObjectClassInterfaceName, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Driver object interface name: " + strObjectClassInterfaceName, BOOL_VERBOSE);
                sendString(strObjectClassInterfaceName, outStream); recvAck(inStream);
-               RuntimeOutput.print("IoTSlave: Driver object stub class name: " + strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Driver object stub class name: " + strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, BOOL_VERBOSE);
                sendString(strObjectStubClassInterfaceName + STR_STUB_CLASS_SUFFIX, outStream); recvAck(inStream);
-               RuntimeOutput.print("IoTSlave: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Driver object registry port: " + iRMIRegistryPort, BOOL_VERBOSE);
                sendInteger(iRMIRegistryPort, outStream); recvAck(inStream);
-               RuntimeOutput.print("IoTSlave: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Driver object stub port: " + iRMIStubPort, BOOL_VERBOSE);
                sendInteger(iRMIStubPort, outStream); recvAck(inStream);
-               sendInteger(iCallbackPorts.length, outStream); recvAck(inStream);
-               for(Integer i : iCallbackPorts) {
-                       sendInteger(i, outStream); recvAck(inStream);
-               }
        }
 
 
@@ -1830,9 +1921,9 @@ public class IoTMaster {
         */
        private void reinitializeIoTRelationFieldCpp(OutputStream outStream, InputStream inStream) throws IOException {
 
-               RuntimeOutput.print("IoTSlave: About to Reinitialize IoTRelation field!", BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: About to Reinitialize IoTRelation field!", BOOL_VERBOSE);
                sendCommCode(IoTCommCode.REINITIALIZE_IOTRELATION_FIELD, outStream, inStream);
-               RuntimeOutput.print("IoTSlave: Reinitialize IoTRelation field!", BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Reinitialize IoTRelation field!", BOOL_VERBOSE);
        }
 
 
@@ -1841,9 +1932,19 @@ public class IoTMaster {
         */
        private void reinitializeIoTSetFieldCpp(OutputStream outStream, InputStream inStream) throws IOException {
 
-               RuntimeOutput.print("IoTSlave: About to Reinitialize IoTSet field!", BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: About to Reinitialize IoTSet field!", BOOL_VERBOSE);
                sendCommCode(IoTCommCode.REINITIALIZE_IOTSET_FIELD, outStream, inStream);
-               RuntimeOutput.print("IoTSlave: Reinitialize IoTSet field!", BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Reinitialize IoTSet field!", BOOL_VERBOSE);
+       }
+
+
+       /**
+        * Create driver object for C++
+        */
+       private void createDriverObjectCpp(OutputStream outStream, InputStream inStream) throws IOException {
+
+               sendCommCode(IoTCommCode.CREATE_DRIVER_OBJECT, outStream, inStream);
+               RuntimeOutput.print("IoTMaster: Send command to create driver object!", BOOL_VERBOSE);
        }
 
 
@@ -1853,7 +1954,7 @@ public class IoTMaster {
        private void invokeInitMethodCpp(OutputStream outStream, InputStream inStream) throws IOException {
 
                sendCommCode(IoTCommCode.INVOKE_INIT_METHOD, outStream, inStream);
-               RuntimeOutput.print("IoTSlave: Invoke init method!", BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Invoke init method!", BOOL_VERBOSE);
        }
 
 
@@ -1866,8 +1967,8 @@ public class IoTMaster {
                IoTCommCode endSessionCode = IoTCommCode.END_SESSION;
                int intCode = endSessionCode.ordinal();
                sendInteger(intCode, outStream);
-               //RuntimeOutput.print("IoTSlave: Send request to create a main object: " + strObjName, BOOL_VERBOSE);
-               RuntimeOutput.print("IoTSlave: Send request to end session!", BOOL_VERBOSE);
+               //RuntimeOutput.print("IoTMaster: Send request to create a main object: " + strObjName, BOOL_VERBOSE);
+               RuntimeOutput.print("IoTMaster: Send request to end session!", BOOL_VERBOSE);
        }
 
 
@@ -1913,15 +2014,19 @@ public class IoTMaster {
                                        strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
                                routerConfig.configureHostMainPolicies(strIoTSlaveControllerHostAdd, strIoTMasterHostAdd,
                                        strIoTSlaveControllerHostAdd, STR_TCP_PROTOCOL, commHan.getComPort(strObjControllerName));
-
+                               // Read config file
+                               String strControllerCfg = STR_CONT_PATH + strObjControllerName + "/" + strObjControllerName + STR_CFG_FILE_EXT;
+                               STR_LANGUAGE_CONTROLLER = parseConfigFile(strControllerCfg, STR_LANGUAGE);
+                               if(STR_LANGUAGE_CONTROLLER == null)
+                                       throw new Error("IoTMaster: Language specification missing in config file: " + strControllerCfg);
                                // Construct ssh command line and create a controller thread for e.g. AcmeProximity
                                String strSSHCommand = null;
-                               if(STR_LANGUAGE.equals(STR_JAVA))
+                               if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
                                        strSSHCommand = getCmdJavaIoTSlave(strObjControllerName);
-                               else if(STR_LANGUAGE.equals(STR_CPP))
+                               else if(STR_LANGUAGE_CONTROLLER.equals(STR_CPP))
                                        strSSHCommand = getCmdCppIoTSlave(strObjControllerName);
                                else
-                                       throw new Error("IoTMaster: Language specification not recognized: " + STR_LANGUAGE);
+                                       throw new Error("IoTMaster: Language specification not recognized: " + STR_LANGUAGE_CONTROLLER);
                                RuntimeOutput.print(strSSHCommand, BOOL_VERBOSE);
                                createThread(strSSHCommand);
                                // Wait for connection
@@ -1930,7 +2035,7 @@ public class IoTMaster {
                                Socket socket = serverSocket.accept();
                                InputStream inStream = null;
                                OutputStream outStream = null;
-                               if(STR_LANGUAGE.equals(STR_JAVA)) {
+                               if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
                                        inStream = new ObjectInputStream(socket.getInputStream());
                                        outStream = new ObjectOutputStream(socket.getOutputStream());
                                } else {        // At this point the language is certainly C++, otherwise would've complained above
@@ -1952,7 +2057,7 @@ public class IoTMaster {
                                String strControllerClassNamePath = STR_CONT_PATH + strObjControllerName + "/" +
                                        strControllerClassName;
 
-                               if(STR_LANGUAGE.equals(STR_JAVA)) {
+                               if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
                                        sendFileToJavaSlave(strObjControllerName, serverSocket, inStream, outStream);
                                        // Create main controller/device object
                                        commMasterToSlave(new MessageCreateMainObject(IoTCommCode.CREATE_MAIN_OBJECT, strObjControllerName),
@@ -1963,7 +2068,13 @@ public class IoTMaster {
                                        sendFileToCppSlave(strControllerFilePath, strControllerZipFile);
                                        createMainObjectCpp(strObjControllerName, outStream, inStream);
                                }
-
+                               // Write basic MAC policies for controller
+                               //String strFileName = STR_MAC_POL_PATH + strObjControllerName + STR_MAC_POLICY_EXT;
+                               if (STR_ACTIVATE_SANDBOXING.equals("Yes")) {
+                                       String strFileName = STR_MAC_POL_PATH + STR_JAVA + STR_MAC_POLICY_EXT;
+                                       processJailConfig.configureProcessJailControllerPolicies(strObjControllerName, strFileName, 
+                                               strIoTMasterHostAdd, commHan.getComPort(strObjControllerName));
+                               }
                                // PROFILING
                                result = System.currentTimeMillis()-start;
                                System.out.println("\n\n ==> From IoTSlave start until main controller object is created: " + result);
@@ -1976,7 +2087,7 @@ public class IoTMaster {
                                RuntimeOutput.print("IoTMaster: Opening class file: " + strControllerClassName, BOOL_VERBOSE);
                                RuntimeOutput.print("IoTMaster: Class file path: " + strControllerClassNamePath, BOOL_VERBOSE);
                                HashMap<String,Object> hmControllerFieldObjects = null;
-                               if(STR_LANGUAGE.equals(STR_JAVA)) {
+                               if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
                                        FileInputStream fis = new FileInputStream(strControllerClassNamePath);
                                        ClassReader cr = new ClassReader(fis);
                                        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
@@ -2010,16 +2121,21 @@ public class IoTMaster {
                                                        throw new Error(strErrMsg);
                                                } else if(setInstrumenter.getObjTableName().equals(STR_IOT_ADD_CLS)) { 
                                                // Instrument the IoTAddress
-                                                       setRouterPolicyIoTSetAddress(strFieldName, map, strIoTSlaveControllerHostAdd);
-                                                       instrumentIoTSetAddress(strFieldName, strFieldName, inStream, outStream);
+                                                       setRouterPolicyIoTSetAddress(strFieldName, map, strIoTSlaveControllerHostAdd, strObjControllerName);
+                                                       instrumentIoTSetAddress(strFieldName, strFieldName, inStream, outStream, STR_LANGUAGE_CONTROLLER);
                                                } else {
                                                // Any other cases
-                                                       instrumentIoTSet(map, strFieldName);
+                                                       instrumentIoTSet(map, strFieldName, strObjControllerName, STR_LANGUAGE_CONTROLLER);
                                                }
                                        } else if (strClassName.equals(STR_REL_INSTRUMENTER_CLS)) {
-                                               instrumentIoTRelation(map, strFieldName);
+                                               instrumentIoTRelation(map, strFieldName, strObjControllerName, STR_LANGUAGE_CONTROLLER);
                                        }
                                }
+                               // Combine controller MAC policies with the main policy file for the host
+                               String strTempFileName = "./" + strObjControllerName + STR_MAC_POLICY_EXT;
+                               processJailConfig.combineControllerMACPolicies(strIoTSlaveControllerHostAdd, strObjControllerName, strTempFileName);
+                               processJailConfig.close();
+
                                // PROFILING
                                result = System.currentTimeMillis()-start;
                                System.out.println("\n\n ==> Time needed to instrument device driver objects: " + result + "\n\n");
@@ -2053,7 +2169,7 @@ public class IoTMaster {
                                start = System.currentTimeMillis();
 
                                // Separating object creations and Set/Relation initializations
-                               createControllerObjects();
+                               createDriverObjects();
 
                                // PROFILING
                                result = System.currentTimeMillis()-start;
@@ -2062,7 +2178,7 @@ public class IoTMaster {
                                start = System.currentTimeMillis();
 
                                // Sets and relations initializations
-                               if(STR_LANGUAGE.equals(STR_JAVA))
+                               if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
                                        initializeSetsAndRelationsJava(inStream, outStream);
                                else
                                        initializeSetsAndRelationsCpp(inStream, outStream);;
@@ -2071,13 +2187,13 @@ public class IoTMaster {
                                result = System.currentTimeMillis()-start;
                                System.out.println("\n\n ==> Time needed to initialize sets and relations: " + result + "\n\n");
 
-                               if(STR_LANGUAGE.equals(STR_JAVA))
+                               if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA))
                                        // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO EXECUTE INIT METHOD
                                        commMasterToSlave(new MessageSimple(IoTCommCode.INVOKE_INIT_METHOD), "Invoke init() method!", inStream, outStream);
                                else
                                        invokeInitMethodCpp(outStream, inStream);
                                // == COMMUNICATION WITH IOTSLAVE CONTROLLER TO END PROCESS
-                               if(STR_LANGUAGE.equals(STR_JAVA)) {
+                               if(STR_LANGUAGE_CONTROLLER.equals(STR_JAVA)) {
                                        ObjectOutputStream oStream = (ObjectOutputStream) outStream;
                                        oStream.writeObject(new MessageSimple(IoTCommCode.END_SESSION));
                                } else  // C++ side will wait until the program finishes, it's not generating a separate thread for now
@@ -2088,6 +2204,8 @@ public class IoTMaster {
                                serverSocket.close();
                                commHan.printLists();
                                lbIoT.printHostInfo();
+                               if (STR_ACTIVATE_SANDBOXING.equals("Yes"))
+                                       createMACPolicyThreads(setAddresses);
                        }
 
                } catch (IOException          |