// 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 }, 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_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']; 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 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": res.write ('OK\n\n'); res.statusCode = 200; res.end (); break; case "POST /user": var payload = ''; req.on ('data', chunk => { payload += chunk.toString (); }); req.on ('end', () => { handlers.user.create (payload, (status, err) => { if (err) { res.write ('Error\n'); res.statusCode = 500; res.end (); } else { res.write (status); res.statusCode = 200; res.end (); } }); }); break; case "UPDATE /user": var payload = ''; req.on ('data', chunk => { payload += chunk.toString (); }); req.on ('end', () => { handlers.user.update (payload, (status, err) => { if (err) { res.write ('Error\n'); res.statusCode = 500; res.end (); } else { res.write (status); res.statusCode = 200; res.end (); } }); }); break; case "DELETE /user": handlers.user.delete (req.url.substring (req.url.lastIndexOf ("/") + 1), (status, err) => { if (err) { res.write ('Error\n'); res.statusCode = 500; res.end (); } else { res.write (status); res.statusCode = 200; res.end (); } }); break; default: res.write ('Not found\n'); res.statusCode = 404; res.end (); } }).listen (8080); // 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);