#!/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; use POE; use POSIX qw(setsid); use Time::HiRes qw(time); # Our own stuff use opentrafficshaper::version; use opentrafficshaper::logger; # Main config my $globals; # We just create the logger first, its only using STDERR here my $logger = new opentrafficshaper::logger; # # MAIN # $logger->log(LOG_NOTICE,"[MAIN] OpenTrafficShaper v".VERSION." - Copyright (c) 2007-2013, AllWorldIT"); parseCfgCmdLine(); init(); $logger->log(LOG_NOTICE,"[MAIN] Starting..."); 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; # Core configuration manager $logger->log(LOG_INFO,"[MAIN] Initializing config manager..."); my $res = eval(" use opentrafficshaper::plugins::configmanager; plugin_register(\$globals,\"configmanager\",\$opentrafficshaper::plugins::configmanager::pluginInfo); "); if ($@ || (defined($res) && $res != 0)) { $logger->log(LOG_WARN,"[MAIN] Error loading config manager, things WILL BREAK! ($@)"); } else { $logger->log(LOG_DEBUG,"[MAIN] Config manager initialized."); } # Load plugins $logger->log(LOG_INFO,"[MAIN] Initializing plugins..."); 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' ($@)"); } else { $logger->log(LOG_DEBUG,"[MAIN] Plugin '$plugin' loaded."); } } $logger->log(LOG_INFO,"[MAIN] Plugins initialized."); } # 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(@{$globals->{'plugins'}},$info); # If we should, init the module if (defined($info->{'Init'})) { $info->{'Init'}($globals); } return 0; } # NK: Needs work # Become daemon sub daemonize { chdir '/' or die "Can't chdir to /: $!"; open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; open STDOUT, '> /var/log/ppp-gatekeeper/stdout.log' or die "Can't open stdout log: $!"; defined(my $pid = fork) or die "Can't fork: $!"; exit if $pid; setsid or die "Can't start a new session: $!"; open STDERR, '> /var/log/ppp-gatekeeper/stderr.log' or die "Can't open stderr log: $!"; } # vim: ts=4