// Baseline const product = 'NetRadius'; const version = '0.2.0'; // Load dependencies const dgram = require ('dgram'); const fs = require ('fs'); const http = require ('http'); // Load modules log = require ('./lib/logger.js'); const handlers = require ('./lib/handlers.js'); // Load configuration log.write (product + ' v' + version); config = {}; try { config = JSON.parse (fs.readFileSync ('./config.json').toString ()); } catch (error) { log.write ('Cannot open or read configuration file.'); log.write ('Using defaults'); config = { ports: { radius_authentication: 1812, radius_accounting: 1813, api: 8080 }, storage: "json:./data.json", client_secret: "password", default_vlan_enabled: false } } if (process.env['NETRADIUS_PORT_RADIUS_AUTH']) config.ports.radius_authentication = process.env['NETRADIUS_PORT_RADIUS_AUTH']; if (process.env['NETRADIUS_PORT_RADIUS_ACCT']) config.ports.radius_accounting = process.env['NETRADIUS_PORT_RADIUS_ACCT']; if (process.env['NETRADIUS_PORT_API']) config.ports.api = process.env['NETRADIUS_PORT_API']; if (process.env['NETRADIUS_STORAGE']) config.storage = process.env['NETRADIUS_STORAGE']; if (process.env['NETRADIUS_DEFAULT_VLAN']) config.default_vlan_enabled = process.env['NETRADIUS_DEFAULT_VLAN']; if (process.env['NETRADIUS_DEFAULT_VLAN_ID']) config.default_vlan_id = process.env['NETRADIUS_DEFAULT_VLAN_ID']; if (process.env['NETRADIUS_CLIENT_SECRET']) config.client_secret = process.env['NETRADIUS_CLIENT_SECRET']; // Set defaults config.ports.radius_authentication = 1812; config.ports.radius_accounting = 1813; config.ports.api = 8080; // Display active configuration log.write ('Using configuration: ' + JSON.stringify (config)); // Listeners var listeners = { authentication: { socket: dgram.createSocket ({ type: 'udp4', reuseAddr: true }), handler: handlers.radius.authentication }, accounting: { socket: dgram.createSocket ({ type: 'udp4', reuseAddr: true }), handler: handlers.radius.accounting } }; // RADIUS authentication listeners.authentication.socket.on ('message', (msg, rinfo) => { handlers.radius.authentication (msg, rinfo, (response, err) => { if (!err) { listeners.authentication.socket.send (response, 0, response.length, rinfo.port, rinfo.address, function (err, bytes) { if (err) { console.log ('Error sending response to ', rinfo); } }); } }); }); listeners.authentication.socket.on ('listening', () => { var address = listeners.authentication.socket.address (); log.write ("Authentication listening on " + address.address + ":" + address.port); }); listeners.authentication.socket.bind (config.ports.radius_authentication); // RADIUS accounting listeners.accounting.socket.on ('message', (msg, rinfo) => { handlers.radius.accounting (msg, rinfo, (response, err) => { if (!err) { listeners.accounting.socket.send (response, 0, response.length, rinfo.port, rinfo.address, function (err, bytes) { if (err) { console.log ('Error sending response to ', rinfo); } }); } }); }); listeners.accounting.socket.on ('listening', () => { var address = listeners.accounting.socket.address (); log.write ("Accounting listening on " + address.address + ":" + address.port); }); listeners.accounting.socket.bind (config.ports.radius_accounting); // HTTP listener const respond = (res, content, status) => { if (typeof (content) == "string") { res.write (content); } else { res.write (JSON.stringify (content)); } res.statusCode = status; res.end (); }; http.createServer (function (req, res) { var url = req.url.substring (0, req.url.lastIndexOf ("/")) || req.url; var endpoint = req.method + " " + url; switch (endpoint) { case "GET /health": respond (res, "OK\n\n", 200); break; case "GET /users": handlers.user.getall ((users, err) => { if (err) { respond (res, err, 404); } else { respond (res, users, 200); } }); break; case "GET /user": handlers.user.getone (req.url.substring (req.url.lastIndexOf ("/") + 1), (user, err) => { if (err) { respond (res, err, 404); } else { respond (res, user, 200); } }); break; case "POST /user": var payload = ''; req.on ('data', chunk => { payload += chunk.toString (); }); req.on ('end', () => { handlers.user.create (payload, (status, err) => { if (err) { respond (res, "Error\n\n", 500); } else { respond (res, status, 200); } }); }); break; case "UPDATE /user": var payload = ''; req.on ('data', chunk => { payload += chunk.toString (); }); req.on ('end', () => { handlers.user.update (payload, (status, err) => { if (err) { respond (res, "Error\n\n", 500); } else { respond (res, status, 200); } }); }); break; case "DELETE /user": handlers.user.delete (req.url.substring (req.url.lastIndexOf ("/") + 1), (status, err) => { if (err) { respond (res, "Error\n\n", 500); } else { respond (res, status, 200); } }); break; default: respond (res, "Not found\n\n", 404); } }).listen (8080); log.write ("API listening on port " + config.ports.api); // Exit handles const exitHandler = () => { log.write ('Shutting down'); listeners.authentication.socket.close (); listeners.accounting.socket.close (); log.write ('Exiting'); process.exit (); } process.on ('SIGTERM', exitHandler); process.on ('SIGINT', exitHandler); process.on ('SIGUSR1', exitHandler); process.on ('SIGUSR2', exitHandler);