/** ** ============================== ** O O O OOOO ** O O O O O O ** O O O O O O ** OOOO OOOO O OOO OOOO ** O O O O O O O ** O O O O O O O ** OOOO OOOO O O OOOO ** ============================== ** Dr. Stefan Bosse http://www.bsslab.de ** ** COPYRIGHT: THIS SOFTWARE, EXECUTABLE AND SOURCE CODE IS OWNED ** BY THE AUTHOR. ** THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED, ** MODIFIED, OR OTHERWISE USED IN A CONTEXT ** OUTSIDE OF THE SOFTWARE SYSTEM. ** ** $AUTHORS: Stefan Bosse ** $INITIAL: (C) 2006-2018 bLAB ** $CREATED: 3-5-15 by sbosse. ** $VERSION: 1.2.6 ** ** $INFO: ** ** DOS: Networking, Commands, Status/Error codes, .. ** ** $ENDOFINFO */ "use strict"; var log = 0; var util = Require('util'); var Io = Require('com/io'); var Comp = Require('com/compat'); var String = Comp.string; var Array = Comp.array; var Perv =Comp.pervasives; var Des48 = Require('dos/des48'); var Base64 = Require('os/base64'); var Rand = Comp.random; var Fs = Require('fs'); //var xmldoc = Require('xmldoc'); function pad(str,size) { while (str.length < (size || 2)) {str = "0" + str;} return str; } /** Direction * var Direction = { NORTH:1, WEST:2, EAST:3, SOUTH:4, ORIGIN:5, tostring:function (i) { switch (i) { case 1: return 'NORTH'; case 2: return 'WEST'; case 3: return 'EAST'; case 4: return 'SOUTH'; case 5: return 'ORIGIN'; default: return 'Direction?'; } } }; */ // Standard Object Service var STD_FIRST_COM = 1000; var STD_LAST_COM = 1999; var STD_FIRST_ERR = (-STD_FIRST_COM); var STD_LAST_ERR = (-STD_LAST_COM); // File Server var AFS_FIRST_COM = 2000; var AFS_LAST_COM = 2099; var AFS_FIRST_ERR = (-AFS_FIRST_COM); var AFS_LAST_ERR = (-AFS_LAST_COM); var AFS_REQBUFSZ = 1024*32; // Directory and Name Server var DNS_FIRST_COM = 2100; var DNS_LAST_COM = 2199; var DNS_FIRST_ERR = (-DNS_FIRST_COM); var DNS_LAST_ERR = (-DNS_LAST_COM); var DNS_MAXCOLUMNS = 4; // System Process Server (incl. Agent Platform Manager) var PS_FIRST_COM = 2200; var PS_LAST_COM = 2299; var PS_FIRST_ERR = (-PS_FIRST_COM); var PS_LAST_ERR = (-PS_LAST_COM); // Broker Server var BR_FIRST_COM = 2300; var BR_LAST_COM = 2399; var BR_FIRST_ERR = (-BR_FIRST_COM); var BR_LAST_ERR = (-BR_LAST_COM); /** RPC Status * * @enum {number} */ var Status = { STD_OK:0, STD_CAPBAD : STD_FIRST_ERR, STD_COMBAD : (STD_FIRST_ERR-1), STD_ARGBAD : (STD_FIRST_ERR-2), STD_NOTNOW : (STD_FIRST_ERR-3), STD_NOSPACE : (STD_FIRST_ERR-4), STD_DENIED : (STD_FIRST_ERR-5), STD_NOMEM : (STD_FIRST_ERR-6), STD_EXISTS : (STD_FIRST_ERR-7), STD_NOTFOUND : (STD_FIRST_ERR-8), STD_SYSERR : (STD_FIRST_ERR-9), STD_INTR : (STD_FIRST_ERR-10), STD_OVERFLOW : (STD_FIRST_ERR-11), STD_WRITEPROT : (STD_FIRST_ERR-12), STD_NOMEDIUM : (STD_FIRST_ERR-13), STD_IOERR : (STD_FIRST_ERR-14), STD_WRONGSRV : (STD_FIRST_ERR-15), STD_OBJBAD : (STD_FIRST_ERR-16), STD_UNKNOWN : (STD_FIRST_ERR-17), DNS_UNAVAIL : (DNS_FIRST_ERR -1), DNS_NOTEMPTY : (DNS_FIRST_ERR -2), DNS_UNREACH : (DNS_FIRST_ERR -3), DNS_CLASH : (DNS_FIRST_ERR -4), RPC_FAILURE : -1, BUF_OVERFLOW : -2, print: function(stat) { switch(stat) { case Status.STD_OK : return 'STD_OK'; case Status.STD_CAPBAD : return 'STD_CAPBAD'; case Status.STD_COMBAD : return 'STD_COMBAD'; case Status.STD_ARGBAD : return 'STD_ARGBAD'; case Status.STD_NOTNOW : return 'STD_NOTNOW'; case Status.STD_NOSPACE : return 'STD_NOSPACE'; case Status.STD_DENIED : return 'STD_DENIED'; case Status.STD_NOMEM : return 'STD_NOMEM'; case Status.STD_EXISTS : return 'STD_EXISTS'; case Status.STD_NOTFOUND : return 'STD_NOTFOUND'; case Status.STD_SYSERR : return 'STD_SYSERR'; case Status.STD_INTR : return 'STD_INTR'; case Status.STD_OVERFLOW : return 'STD_OVERFLOW'; case Status.STD_WRITEPROT : return 'STD_WRITEPROT'; case Status.STD_NOMEDIUM : return 'STD_NOMEDIUM'; case Status.STD_IOERR : return 'STD_IOERR'; case Status.STD_WRONGSRV : return 'STD_WRONGSRV'; case Status.STD_OBJBAD : return 'STD_OBJBAD'; case Status.STD_UNKNOWN : return 'STD_UNKNOWN'; case Status.DNS_UNAVAIL : return 'DNS_UNAVAIL'; case Status.DNS_NOTEMPTY : return 'DNS_NOTEMPTY'; case Status.DNS_UNREACH : return 'DNS_UNREACH'; case Status.DNS_CLASH : return 'DNS_CLASH'; case Status.RPC_FAILURE : return 'RPC_FAILURE'; case Status.BUF_OVERFLOW : return 'BUF_OVERFLOW'; default : return '"'+stat+'"'; } } }; /** RPC Command * * @enum {number} */ var Command = { /* ** Standard Commands */ STD_MONITOR : STD_FIRST_COM, STD_AGE : (STD_FIRST_COM+1), STD_COPY : (STD_FIRST_COM + 2), STD_DESTROY : (STD_FIRST_COM + 3), STD_INFO : (STD_FIRST_COM + 4), STD_RESTRICT : (STD_FIRST_COM + 5), STD_STATUS : (STD_FIRST_COM + 6), STD_TOUCH : (STD_FIRST_COM + 7), STD_GETPARAMS : (STD_FIRST_COM + 8), STD_SETPARAMS : (STD_FIRST_COM + 9), STD_NTOUCH : (STD_FIRST_COM + 10), STD_EXIT : (STD_FIRST_COM + 11), STD_RIGHTS : (STD_FIRST_COM + 12), STD_EXEC : (STD_FIRST_COM + 13), STD_LOCATION : (STD_FIRST_COM + 20), STD_LABEL : (STD_FIRST_COM + 21), /* ** AFC Commands */ AFS_CREATE : (AFS_FIRST_COM + 1), AFS_DELETE : (AFS_FIRST_COM + 2), AFS_FSCK : (AFS_FIRST_COM + 3), AFS_INSERT : (AFS_FIRST_COM + 4), AFS_MODIFY : (AFS_FIRST_COM + 5), AFS_READ : (AFS_FIRST_COM + 6), AFS_SIZE : (AFS_FIRST_COM + 7), AFS_DISK_COMPACT : (AFS_FIRST_COM + 8), AFS_SYNC : (AFS_FIRST_COM + 9), AFS_DESTROY : (AFS_FIRST_COM + 10), /* ** DNS Commands */ DNS_CREATE : (DNS_FIRST_COM), DNS_DISCARD : (DNS_FIRST_COM + 1), DNS_LIST : (DNS_FIRST_COM + 2), DNS_APPEND : (DNS_FIRST_COM + 3), DNS_CHMOD : (DNS_FIRST_COM + 4), DNS_DELETE : (DNS_FIRST_COM + 5), DNS_LOOKUP : (DNS_FIRST_COM + 6), DNS_SETLOOKUP : (DNS_FIRST_COM + 7), DNS_INSTALL : (DNS_FIRST_COM + 8), DNS_REPLACE : (DNS_FIRST_COM + 10), DNS_GETMASKS : (DNS_FIRST_COM + 11), DNS_GETSEQNR : (DNS_FIRST_COM + 12), DNS_RENAME : (DNS_FIRST_COM + 13), DNS_GETROOT : (DNS_FIRST_COM + 14), DNS_GETDEFAFS : (DNS_FIRST_COM + 15), PS_STUN : (PS_FIRST_COM), // Kill a process/ create a snapshot PS_MIGRATE : (PS_FIRST_COM+1), // Execute a process from a snapshot after migration (->next+) PS_EXEC : (PS_FIRST_COM+2), // Execute a process from a snapshot (->next) PS_WRITE : (PS_FIRST_COM+4), // Store a process class template PS_READ : (PS_FIRST_COM+5), // Get a process class template PS_CREATE : (PS_FIRST_COM+6), // Create a process from a template and execute PS_FORK : (PS_FIRST_COM+7), // Fork a process from a running process PS_SIGNAL : (PS_FIRST_COM+8), // Send a signal to a process BR_CONNECT : (BR_FIRST_COM), BR_DISCONN : (BR_FIRST_COM+1), print: function(cmd) { switch(cmd) { case Command.STD_MONITOR : return 'STD_MONITOR'; case Command.STD_AGE : return 'STD_AGE'; case Command.STD_COPY : return 'STD_COPY'; case Command.STD_DESTROY : return 'STD_DESTROY'; case Command.STD_INFO : return 'STD_INFO'; case Command.STD_RESTRICT : return 'STD_RESTRICT'; case Command.STD_STATUS : return 'STD_STATUS'; case Command.STD_TOUCH : return 'STD_TOUCH'; case Command.STD_GETPARAMS : return 'STD_GETPARAMS'; case Command.STD_SETPARAMS : return 'STD_SETPARAMS'; case Command.STD_NTOUCH : return 'STD_NTOUCH'; case Command.STD_EXIT : return 'STD_EXIT'; case Command.STD_RIGHTS : return 'STD_RIGHTS'; case Command.STD_EXEC : return 'STD_EXEC'; case Command.STD_LOCATION : return 'STD_LOCATION'; case Command.STD_LABEL : return 'STD_LABEL'; case Command.AFS_CREATE : return 'AFS_CREATE'; case Command.AFS_DELETE : return 'AFS_DELETE'; case Command.AFS_FSCK : return 'AFS_FSCK'; case Command.AFS_INSERT : return 'AFS_INSERT'; case Command.AFS_MODIFY : return 'AFS_MODIFY'; case Command.AFS_READ : return 'AFS_READ'; case Command.AFS_SIZE : return 'AFS_SIZE'; case Command.AFS_DISK_COMPACT : return 'AFS_DISK_COMPACT'; case Command.AFS_SYNC : return 'AFS_SYNC'; case Command.AFS_DESTROY : return 'AFS_DESTROY'; case Command.DNS_CREATE : return 'DNS_CREATE'; case Command.DNS_DISCARD : return 'DNS_DISCARD'; case Command.DNS_LIST : return 'DNS_LIST'; case Command.DNS_APPEND : return 'DNS_APPEND'; case Command.DNS_CHMOD : return 'DNS_CHMOD'; case Command.DNS_DELETE : return 'DNS_DELETE'; case Command.DNS_LOOKUP : return 'DNS_LOOKUP'; case Command.DNS_SETLOOKUP : return 'DNS_SETLOOKUP'; case Command.DNS_INSTALL : return 'DNS_INSTALL'; case Command.DNS_REPLACE : return 'DNS_REPLACE'; case Command.DNS_GETMASKS : return 'DNS_GETMASKS'; case Command.DNS_GETSEQNR : return 'DNS_GETSEQNR'; case Command.DNS_RENAME : return 'DNS_RENAME'; case Command.DNS_GETROOT : return 'DNS_GETRROT'; case Command.DNS_GETDEFAFS : return 'DNS_GETDEFAFS'; case Command.PS_STUN : return 'PS_STUN'; case Command.PS_EXEC : return 'PS_EXEC'; case Command.PS_MIGRATE : return 'PS_MIGRATE'; case Command.PS_READ : return 'PS_READ'; case Command.PS_WRITE : return 'PS_WRITE'; case Command.PS_CREATE : return 'PS_CREATE'; case Command.PS_FORK : return 'PS_FORK'; case Command.PS_SIGNAL : return 'PS_SIGNAL'; case Command.BR_CONNECT : return 'BR_CONNECT'; case Command.BR_DISCONN : return 'BR_DISCONN'; default: return '"'+cmd+'"'; } } }; var PORT_SIZE = 6; var PRIV_SIZE = 4+PORT_SIZE; var CAP_SIZE = 16; /** Object Rights * * @enum {number} */ var Rights = { AFS_RGT_READ : 0x1, AFS_RGT_CREATE : 0x2, AFS_RGT_MODIFY : 0x4, AFS_RGT_DESTROY : 0x8, AFS_RGT_ADMIN : 0x80, DNS_COLMASK : ((1 << DNS_MAXCOLUMNS) - 1), // Rights to access specific columns of a directory row, one bit, one column. DNS_RGT_COLALL : ((1 << DNS_MAXCOLUMNS) - 1), DNS_RGT_COL1 : 0x01, DNS_RGT_OWNER : 0x01, DNS_RGT_COL2 : 0x02, DNS_RGT_GROUP : 0x02, DNS_RGT_COL3 : 0x04, DNS_RGT_OTHERS : 0x04, DNS_RGT_COL4 : 0x08, DNS_RGT_READ : 0x10, DNS_RGT_CREATE : 0x20, DNS_RGT_MODIFY : 0x40, DNS_RGT_DELETE : 0x80, HOST_INFO : 0x01, HOST_READ : 0x02, HOST_WRITE : 0x04, HOST_EXEC : 0x08, PSR_READ : 0x01, PSR_WRITE : 0x02, PSR_CREATE : 0x04, PSR_DELETE : 0x08, PSR_EXEC : 0x10, PSR_KILL : 0x20, PSR_ALL : 0xff, NEG_SCHED : 0x08, NEG_CPU : 0x10, NEG_RES : 0x20, NEG_LEVEL : 0x40, PRV_ALL_RIGHTS : 0xff }; var DEF_RPC_MAX_HOP = 4; var priv2pub_cache = []; /** * * @param {number []} [port_vals] * @returns {string} */ var port = function (port_vals) { if (port_vals==undefined) port_vals=[0,0,0,0,0,0]; var port=''; for(var i = 0; i< PORT_SIZE;i++) { port=port+Perv.char_of_int(port_vals[i]); } return port; }; /** * * @param {number} [obj] * @param {number} [rights] * @param {port} [rand] * @constructor */ var privat = function (obj,rights,rand) { if (obj==undefined) { // Create empty private field this.prv_obj=0; this.prv_rights=0; this.prv_rand=port(); } else { this.prv_obj = obj; // Integer this.prv_rights = rights; // Integer this.prv_rand = rand; // Port=string } }; /** * * @param {port} [cap_port] * @param {privat} [cap_priv] * @constructor */ var capability = function(cap_port, cap_priv) { if (cap_port==undefined) { // Create empty capability this.cap_port = port(); this.cap_priv = new privat(); } else { this.cap_port = cap_port; // Port=string if (cap_priv==undefined) this.cap_priv = new privat(); else this.cap_priv = cap_priv; // Private } }; /* ** RPC communication is XML based using the HTTP interface. ** RPC communication is synchronous, hence a callback ** function is used to handle the reply (acknowledge). */ /** * * @param {port} [h_port] * @param {privat} [h_priv] * @param {Command} [h_command] * @param {(Status.STD_OK|*)} [h_status] * @constructor */ var header = function(h_port,h_priv,h_command,h_status) { if (h_port==undefined) { // Create empty header this.h_port = port(); this.h_priv = new privat(); this.h_command = undefined; this.h_status = undefined; } else { this.h_port = h_port; this.h_priv = h_priv; this.h_command = h_command; this.h_status = h_status; } }; /** * * @param {number} [obj] * @param {number} [rights] * @param {port} [rand] * @returns {privat} */ function Private(obj,rights,rand) { var _obj = new privat(obj,rights,rand); Object.preventExtensions(_obj); return _obj; } /** * * @param {port} [cap_port] * @param {privat} [cap_priv] * @returns {capability} */ function Capability (cap_port, cap_priv) { var obj = new capability(cap_port, cap_priv); Object.preventExtensions(obj); return obj; } /** * * @param {port} [h_port] * @param {privat} [h_priv] * @param {Command} [h_command] * @param {(Status.STD_OK|*)} [h_status] * @returns {header} */ function Header(h_port,h_priv,h_command,h_status) { var obj = new header(h_port,h_priv,h_command,h_status); Object.preventExtensions(obj); return obj; } /* ** Hash table of all locally created unique ports. */ var uniqports=[]; /** * */ var Net = { // Direction:Direction, PORT_SIZE:PORT_SIZE, PRIV_SIZE:PRIV_SIZE, AFS_REQBUFSZ:AFS_REQBUFSZ, CAP_SIZE:CAP_SIZE, DNS_MAXCOLUMNS:DNS_MAXCOLUMNS, TIMEOUT:5000, DEF_RPC_MAX_HOP:DEF_RPC_MAX_HOP, Status:Status, Command:Command, Rights:Rights, Private:Private, Capability: Capability, Header: Header, Port: port, /** * @type {port} */ nilport: port(), nilpriv: Private(0,0,this.nilport), nilcap: Capability(this.nilport,this.nilpriv), /* ** Utils to get and set single bytes of a port */ get_portbyte: function(port,i) { return Perv.int_of_char(String.get(port,i)) }, set_portbyte: function(port,i,byte) { return String.set(port, i, (Perv.char_of_int(byte))); }, /* * Return a unique key of a capability that can be used for hash tables */ key: function (cap) { return cap.cap_port+ cap.cap_priv.prv_obj+ cap.cap_priv.prv_rights+ cap.cap_priv.prv_rand; }, /* ** Encryption function */ one_way: function (port) { var key = Array.create(64,0); var block = Array.create(48,0); var pubport = String.make (PORT_SIZE,'\0'); var i, j, k; /* ** We actually need 64 bit key. ** Throw some zeroes in at bits 6 and 7 mod 8 ** The bits at 7 mod 8 etc are not used by the algorithm */ j=0; for (i = 0; i< 64; i++) { if ((i & 7) > 5) key[i] = 0; else { if ((this.get_portbyte(port, (j >> 3)) & (1 << (j & 7))) != 0) key[i] = 1; else key[i] = 0; j++; } } Des48.des_OWsetkey(key); /* ** Now go encrypt constant 0 */ block=Des48.des_OWcrypt48(block); /* ** and put the bits in the destination port */ var pb = 0; for (i = 0; i < PORT_SIZE;i++) { var pbyte = 0; for (j = 0; j < 8; j++) { pbyte = pbyte | (block[pb] << j); pb++; } pubport=this.set_portbyte(pubport, i, pbyte); } return pubport; }, /* ** Check whether the required rights [R1;R2;..] are ** present in the rights field rg. Return a boolean value. */ rights_req : function(rights,required) { var all=true; Array.iter(required,function(rq) { if (rq & rights == 0) all = false; }); return all; }, port_cmp: function(port1,port2) { var i; var eq=true; for(i=0;i 0) str = str + ':'; str = str + pad(num.toString(16).toUpperCase(), 2); } } else str='undefined'; return str; }, port_of_str: function (str,compact) { var tokens=str.split(':'),i,port=''; for (i=0;i 0) str = str + ':'; str = str + pad(num.toString(16).toUpperCase(), 2); } } else str='undefined'; return str; }, /** * * @param priv * @returns {string} */ private: function(priv) { var str=''; if (priv==undefined) return 'undefined'; str=priv.prv_obj; str=str+'('+String.format_hex(priv.prv_rights,2).toUpperCase()+')['; str=str+this.port(priv.prv_rand)+']'; return str; }, status: Status.print } }; module.exports = Net;