Skip to content
Snippets Groups Projects
opentrafficshaperd 7.01 KiB
Newer Older
Nigel Kukard's avatar
Nigel Kukard committed
#!/usr/bin/perl
# Main OpenTrafficShaper program
# Copyright (C) 2007-2013, AllWorldIT
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

use strict;
use warnings;


# Set the dirs we look for library files in
use lib('/usr/local/lib/opentrafficshaper-1.0','/usr/lib/opentrafficshaper-1.0',
		'/usr/lib64/opentrafficshaper-1.0','opentrafficshaper','awitpt');

# System stuff we need
use Config::IniFiles;
use Getopt::Long;
Nigel Kukard's avatar
Nigel Kukard committed
use Time::HiRes qw(time);

# Our own stuff
use opentrafficshaper::version;
use opentrafficshaper::logger;
use Radius::Dictionary;
use Radius::Packet;


# Main config
my $globals;
# We just create the logger first, its only using STDERR here
my $logger = new opentrafficshaper::logger;



# Process basically starts here
$logger->log(LOG_NOTICE,"[MAIN] OpenTrafficShaper v".VERSION." - Copyright (c) 2007-2013, AllWorldIT");
parseCfgCmdLine();
init();




# This is our configuration processing session
# TODO: Current just a trigger
POE::Session->create(
  inline_states => {
	_start => sub {
	  $_[KERNEL]->delay(tick => 5);
	},

	tick => sub {
	  print STDERR "tick at ", time(), ":  users = ". (keys %{$globals->{'users'}})  ."\n";
	  $_[KERNEL]->delay(tick => 5);
	},
  }
);



#
# MAIN
#
$logger->log(LOG_NOTICE,"[MAIN] Starting...");
Nigel Kukard's avatar
Nigel Kukard committed
POE::Kernel->run();
exit;





# Function to parse our config and commandline
sub parseCfgCmdLine
{

	# Set defaults
	my $cfg;
	$cfg->{'config_file'} = "/etc/opentrafficshaper.conf";

	$cfg->{'timeout'} = 120;
	$cfg->{'background'} = "yes";
	$cfg->{'pid_file'} = "/var/run/opentrafficshaper/opentrafficshaperd.pid";
	$cfg->{'log_level'} = 2;
	$cfg->{'log_file'} = "/var/log/opentrafficshaper/opentrafficshaperd.log";

#	$server->{'host'} = "*";
#	$server->{'port'} = [ 1812, 1813 ];
#	$server->{'proto'} = 'udp';

	# Parse command line params
	my $cmdline;
	%{$cmdline} = ();
	GetOptions(
			\%{$cmdline},
			"help",
			"config:s",
			"debug",
			"fg",
	) or die "Error parsing commandline arguments";

	# Check for some args
	if ($cmdline->{'help'}) {
		displayHelp();
		exit 0;
	}
	if (defined($cmdline->{'config'}) && $cmdline->{'config'} ne "") {
		$cfg->{'config_file'} = $cmdline->{'config'};
	}

	# Check config file exists
	if (! -f $cfg->{'config_file'}) {
		die("No configuration file '".$cfg->{'config_file'}."' found!\n");
	}

	# Use config file, ignore case
	tie my %inifile, 'Config::IniFiles', (
			-file => $cfg->{'config_file'},
			-nocase => 1
	) or die "Failed to open config file '".$cfg->{'config_file'}."': $!";
	# Copy config
	my %config = %inifile;

	# Pull in params for the server
	my @server_params = (
			'log_level','log_file',
			'host',
			'pid_file',
			'user', 'group',
			'timeout',
			'background',
	);
	foreach my $param (@server_params) {
		$cfg->{$param} = $config{'server'}{$param} if (defined($config{'server'}{$param}));
	}

	# Override
	if ($cmdline->{'debug'}) {
		$cfg->{'log_level'} = 4;
		$cfg->{'debug'} = 1;
	}

	# If we set on commandline for foreground, keep in foreground
	if ($cmdline->{'fg'} || (defined($config{'server'}{'background'}) && $config{'server'}{'background'} eq "no" )) {
		$cfg->{'background'} = undef;
		$cfg->{'log_file'} = undef;
	} else {
		$cfg->{'setsid'} = 1;
	}

	# Loop with logging detail
	if (defined($config{'server'}{'log_detail'})) {
		# Lets see what we have to enable
		foreach my $detail (split(/[,\s;]/,$config{'server'}{'log_detail'})) {
			$cfg->{'logging'}{$detail} = 1;
		}
	}

	#
	# System plugins
	#
	if (ref($config{'plugins'}{'load'}) eq "ARRAY") {
		foreach my $plugin (@{$config{'plugins'}{'load'}}) {
			$plugin =~ s/\s+//g;
	 		# Skip comments
	 		next if ($plugin =~ /^#/);
			push(@{$cfg->{'plugin_list'}},$plugin);
		}
	} elsif (defined($config{'plugins'}{'load'})) {
		my @pluginList = split(/\s+/,$config{'plugins'}{'load'});
		foreach my $plugin (@pluginList) {
			# Skip comments
			next if ($plugin =~ /^#/);
			push(@{$cfg->{'plugin_list'}},$plugin);
		}
	}

	#
	# Dictionary configuration
	#
	# Split off dictionaries to load
	if (ref($config{'dictionary'}->{'load'}) eq "ARRAY") {
		foreach my $dict (@{$config{'dictionary'}->{'load'}}) {
			$dict =~ s/\s+//g;
	 		# Skip comments
	 		next if ($dict =~ /^#/);
			push(@{$cfg->{'dictionary_list'}},$dict);
		}
	} elsif (defined($config{'dictionary'}->{'load'})) {
		my @dictList = split(/\s+/,$config{'dictionary'}->{'load'});
		foreach my $dict (@dictList) {
			# Skip comments
			next if ($dict =~ /^#/);
			push(@{$cfg->{'dictionary_list'}},$dict);
		}
	}

	# Check if the user specified a cache_file in the config
	if (defined($config{'server'}{'cache_file'})) {
		$cfg->{'cache_file'} = $config{'server'}{'cache_file'};
	}

	$globals->{'config'} = $cfg;
}


# Display help
sub displayHelp {

	print(STDERR<<EOF);

Usage: $0 [args]
	--config=<file>		Configuration file
	--debug				Put into debug mode
	--fg				   Don't go into background

EOF
}


# Initialize things we need
sub init
{
	# Certain things we need
	$globals->{'users'} = { };
	$globals->{'logger'} = $logger;
	$globals->{'version'} = VERSION;
Nigel Kukard's avatar
Nigel Kukard committed

	# Load dictionaries
	$logger->log(LOG_INFO,"[MAIN] Initializing dictionaries...");
Nigel Kukard's avatar
Nigel Kukard committed
	my $dict = new Radius::Dictionary;
	foreach my $df (@{$globals->{'config'}->{'dictionary_list'}}) {
		# Load dictionary
		if (!$dict->readfile($df)) {
			$logger->log(LOG_WARN,"[MAIN] Failed to load dictionary '$df': $!");
		$logger->log(LOG_DEBUG,"[MAIN] Loaded dictionary '$df'.");
	$logger->log(LOG_INFO,"[MAIN] Dictionaries initialized.");
Nigel Kukard's avatar
Nigel Kukard committed
	# Store the dictionary
	$globals->{'radius'}->{'dictionary'} = $dict;


	# Load plugins
	$logger->log(LOG_INFO,"[MAIN] Initializing plugins...");
Nigel Kukard's avatar
Nigel Kukard committed
	foreach my $plugin (@{$globals->{'config'}->{'plugin_list'}}) {
		# Load plugin
		my $res = eval("
			use opentrafficshaper::plugins::${plugin}::${plugin};
			plugin_register(\$globals,\"${plugin}\",\$opentrafficshaper::plugins::${plugin}::pluginInfo);
		");
		if ($@ || (defined($res) && $res != 0)) {
			$logger->log(LOG_WARN,"[MAIN] Error loading plugin $plugin ($@)");
Nigel Kukard's avatar
Nigel Kukard committed
		} else {
			$logger->log(LOG_DEBUG,"[MAIN] Plugin '$plugin' loaded.");
	$logger->log(LOG_INFO,"[MAIN] Plugins initialized.");
Nigel Kukard's avatar
Nigel Kukard committed
}
# Register plugin info
sub plugin_register {
	my ($globals,$plugin,$info) = @_;


	# If no info, return
	if (!defined($info)) {
		$logger->log(LOG_WARN,"WARNING: Plugin info not found for plugin => $plugin\n");
		return -1;
	}

	# Set real module name & save
	$info->{'Plugin'} = $plugin;
#	push(@{$logger->{'module_list'}},$info);

	# If we should, init the module
	if (defined($info->{'Init'})) {
		$info->{'Init'}($globals);
	}

	return 0;
}

# vim: ts=4