diff options
Diffstat (limited to 'kernel/xpp/utils/zapconf')
-rwxr-xr-x | kernel/xpp/utils/zapconf | 667 |
1 files changed, 130 insertions, 537 deletions
diff --git a/kernel/xpp/utils/zapconf b/kernel/xpp/utils/zapconf index 78a20b9..ac1af0b 100755 --- a/kernel/xpp/utils/zapconf +++ b/kernel/xpp/utils/zapconf @@ -11,555 +11,101 @@ use strict; use File::Basename; BEGIN { my $dir = dirname($0); unshift(@INC, "$dir", "$dir/zconf"); } +use Getopt::Std; use Zaptel; use Zaptel::Xpp; -use Zaptel::Config::Defaults; - -my %default_context = ( - FXO => 'from-pstn', - FXS => 'from-internal', - IN => 'astbank-input', - OUT => 'astbank-output', - BRI_TE => 'from-pstn', - BRI_NT => 'from-internal', - E1_TE => 'from-pstn', - T1_TE => 'from-pstn', - J1_TE => 'from-pstn', - E1_NT => 'from-internal', - T1_NT => 'from-internal', - J1_NT => 'from-internal', - ); - -my %default_group = ( - FXO => 0, - FXS => "5", - IN => '', - OUT => '', - BRI_TE => 0, - BRI_NT => 6, - E1_TE => 0, - T1_TE => 0, - J1_TE => 0, - E1_NT => 6, - T1_NT => 6, - J1_NT => 6, - ); - -my $fxs_default_start = 'ls'; - -my %default_zaptel_signalling = ( - FXO => 'fxsks', - FXS => "fxo{fxs_default_start}", - IN => "fxo{fxs_default_start}", - OUT => "fxo{fxs_default_start}", - ); - -my %default_zapata_signalling = ( - FXO => 'fxs_ks', - FXS => "fxo_{fxs_default_start}", - IN => "fxo_{fxs_default_start}", - OUT => "fxo_{fxs_default_start}", - ); - -my $base_exten = 4000; -my $fxs_immediate = 'no'; -my $lc_country = 'us'; -my $loadzone = $lc_country; -my $defaultzone = $lc_country; -my $bri_sig_style = 'bri_ptmp'; -my $brint_overlap = 'no'; - -my %zaptel_default_vars = ( - base_exten => \$base_exten, - fxs_immediate => \$fxs_immediate, - fxs_default_start => \$fxs_default_start, - lc_country => [ - \$loadzone, - \$defaultzone, - ], - context_lines => \$default_context{FXO}, - context_phones => \$default_context{FXS}, - context_input => \$default_context{IN}, - context_output => \$default_context{OUT}, - group_phones => [ - \$default_group{FXS}, - \$default_group{IN}, - \$default_group{OUT}, - ], - group_lines => \$default_group{FXO}, - ZAPBRI_SIGNALLING => \$bri_sig_style, - brint_overlap => \$brint_overlap, - ); - -sub map_zaptel_defaults { - my %defaults = @_; - foreach my $name (keys %defaults) { - my $val = $defaults{$name}; - my $ref = $zaptel_default_vars{$name}; - my $type = ref $ref; - my @vars = (); - # Some broken shells (msh) export even variables - # That where not defined. Work around that. - next unless defined $val && $val ne ''; - if($type eq 'SCALAR') { - @vars = ($ref); - } elsif($type eq 'ARRAY') { - @vars = @$ref; - } else { - die "$0: Don't know how to map '$name' (type=$type)\n"; - } - foreach my $v (@vars) { - $$v = $val; - } - } -} - - -my $zapconf_file; -my $zapatachannels_file; -my $users_file; -my $zapataconf_file; - -my %files = ( - zaptel => { file => \$zapconf_file, func => \&gen_zaptelconf }, - zapata => { file => \$zapatachannels_file, func => \&gen_zapatachannelsconf }, - users => { file => \$users_file, func => \&gen_usersconf }, - zapataconf => { file => \$zapataconf_file, func => \&gen_zapataconf }, -); - -my @default_files = ("zaptel", "zapata"); - -my @spans = Zaptel::spans(); +use Zaptel::Config::Gen; +use Zaptel::Config::Params; -sub bchan_range($) { - my $span = shift || die; - my $first_chan = ($span->chans())[0]; - my $first_num = $first_chan->num(); - my $range_start = $first_num; - my @range; - my $prev = undef; - - die unless $span->is_digital(); - foreach my $c (@{$span->bchan_list()}) { - my $curr = $c + $first_num; - if(!defined($prev)) { - $prev = $curr; - } elsif($curr != $prev + 1) { - push(@range, sprintf("%d-%d", $range_start, $prev)); - $range_start = $curr; - } - $prev = $curr; - } - if($prev >= $first_num) { - push(@range, sprintf("%d-%d", $range_start, $prev)); - } - return join(',', @range); -} +my $version = '1'; # Functionality version (integer) +my $revision = '$Revision$'; -sub gen_zaptel_signalling($) { - my $chan = shift || die; - my $type = $chan->type; - my $num = $chan->num; - - die "channel $num type $type is not an analog channel\n" if $chan->span->is_digital(); - if($type eq 'EMPTY') { - printf "# channel %d, %s, no module.\n", $num, $chan->fqn; - return; - } - my $sig = $default_zaptel_signalling{$type} || die "unknown default zaptel signalling for chan $num type $type"; - if ($type eq 'IN') { - printf "# astbanktype: input\n"; - } elsif ($type eq 'OUT') { - printf "# astbanktype: output\n"; - } - printf "$sig=$num\n"; -} +my %opts; -my $bri_te_last_timing = 1; - -sub gen_zaptel_digital($) { - my $span = shift || die; - my $num = $span->num() || die; - die "Span #$num is analog" unless $span->is_digital(); - my $termtype = $span->termtype() || die "$0: Span #$num -- unkown termtype [NT/TE]\n"; - my $timing; - my $lbo = 0; - my $framing = $span->framing() || die "$0: No framing information for span #$num\n"; - my $coding = $span->coding() || die "$0: No coding information for span #$num\n"; - my $span_crc4 = $span->crc4(); - $span_crc4 = (defined $span_crc4) ? ",$span_crc4" : ''; - my $span_yellow = $span->yellow(); - $span_yellow = (defined $span_yellow) ? ",$span_yellow" : ''; - - $timing = ($termtype eq 'NT') ? 0 : $bri_te_last_timing++; - printf "span=%d,%d,%d,%s,%s%s%s\n", - $num, - $timing, - $lbo, - $framing, - $coding, - $span_crc4, - $span_yellow; - printf "# termtype: %s\n", lc($termtype); - printf "bchan=%s\n", bchan_range($span); - my $dchan = $span->dchan(); - printf "dchan=%d\n", $dchan->num(); +sub set_defaults { + my $default_file = $ENV{GENCONF_PARAMETERS} || "/etc/genconf_parameters"; + my $params = Zaptel::Config::Params->new($default_file); + #$params->dump; + if($opts{v}) { + print "Default parameters from ", $params->{GENCONF_FILE}, "\n"; + } + my $gconfig = Zaptel::Config::Gen->new($params); + #$gconfig->dump; + return $gconfig; } -sub gen_zaptelconf($) { - my $file = shift || die; - rename "$file", "$file.bak" - or $! == 2 # ENOENT (No dependency on Errno.pm) - or die "Failed to backup old config: $!\n"; - open(F, ">$file") || die "$0: Failed to open $file: $!\n"; - my $old = select F; - printf "# Autogenerated by %s on %s -- do not hand edit\n", $0, scalar(localtime); - print <<"HEAD"; -# Zaptel Configuration File -# -# This file is parsed by the Zaptel Configurator, ztcfg -# -HEAD +sub spans_prep($@) { + my $gconfig = shift || die; + my @spans = @_; foreach my $span (@spans) { - printf "# Span %d: %s %s\n", $span->num, $span->name, $span->description; - if($span->is_digital()) { - gen_zaptel_digital($span); - } else { - foreach my $chan ($span->chans()) { - if(1 || !defined $chan->type) { - my $type = $chan->probe_type; - my $num = $chan->num; - die "Failed probing type for channel $num" - unless defined $type; - $chan->type($type); - } - gen_zaptel_signalling($chan); - } + if($span->is_pri) { + $span->pri_set_fromconfig($gconfig); } - print "\n"; } - print <<"TAIL"; -# Global data - -loadzone = $loadzone -defaultzone = $defaultzone -TAIL - close F; - select $old; } -my %DefaultConfigs = ( - context => 'default', - group => '63', # FIXME: should not be needed. - overlapdial => 'no', - busydetect => 'no', - rxgain => 0, - txgain => 0, -); - -sub reset_zapata_values { - foreach my $arg (@_) { - if (exists $DefaultConfigs{$arg}) { - print "$arg = $DefaultConfigs{$arg}\n"; - } else { - print "$arg =\n"; - } - } -} +sub generator_list($) { + my $gconfig = shift || die; + my @genlist; -sub gen_zapata_digital($) { - my $span = shift || die; - my $num = $span->num() || die; - die "Span #$num is analog" unless $span->is_digital(); - my $type = $span->type() || die "$0: Span #$num -- unkown type\n"; - my $termtype = $span->termtype() || die "$0: Span #$num -- unkown termtype [NT/TE]\n"; - my $group = $default_group{"$type"}; - my $context = $default_context{"$type"}; - my @to_reset = qw/context group/; - - die "$0: missing default group (termtype=$termtype)\n" unless defined($group); - die "$0: missing default context\n" unless $context; - - my $sig = $span->signalling || die "missing signalling info for span #$num type $type"; - grep($bri_sig_style eq $_, 'bri', 'bri_ptmp', 'pri') or die "unknown signalling style for BRI"; - if($span->is_bri() and $bri_sig_style eq 'bri_ptmp') { - $sig .= '_ptmp'; - } - if ($span->is_bri() && $termtype eq 'NT' && $brint_overlap eq 'yes') { - print "overlapdial = yes\n"; - push(@to_reset, qw/overlapdial/); - } - - $group .= "," . (10 + $num); # Invent unique group per span - printf "group=$group\n"; - printf "context=$context\n"; - printf "switchtype = %s\n", $span->switchtype; - printf "signalling = %s\n", $sig; - printf "channel => %s\n", bchan_range($span); - reset_zapata_values(@to_reset); -} - -sub gen_zapata_channel($) { - my $chan = shift || die; - my $type = $chan->type; - my $num = $chan->num; - die "channel $num type $type is not an analog channel\n" if $chan->span->is_digital(); - my $exten = $base_exten + $num; - my $sig = $default_zapata_signalling{$type}; - my $context = $default_context{$type}; - my $group = $default_group{$type}; - my $callerid; - my $immediate; - - return if $type eq 'EMPTY'; - die "missing default_zapata_signalling for chan #$num type $type" unless $sig; - $callerid = ($type eq 'FXO') - ? 'asreceived' - : sprintf "\"Channel %d\" <%04d>", $num, $exten; - if($type eq 'IN') { - $immediate = 'yes'; - } - # FIXME: $immediage should not be set for 'OUT' channels, but meanwhile - # it's better to be compatible with genzaptelconf - $immediate = 'yes' if $fxs_immediate eq 'yes' and $sig =~ /^fxo_/; - my $signalling = $chan->signalling; - $signalling = " " . $signalling if $signalling; - my $info = $chan->info; - $info = " " . $info if $info; - printf ";;; line=\"%d %s%s%s\"\n", $num, $chan->fqn, $signalling, $info; - printf "signalling=$sig\n"; - printf "callerid=$callerid\n"; - printf "mailbox=%04d\n", $exten unless $type eq 'FXO'; - if(defined $group) { - printf "group=$group\n"; - } - printf "context=$context\n"; - printf "immediate=$immediate\n" if defined $immediate; - printf "channel => %d\n", $num; - # Reset following values to default - printf "callerid=\n"; - printf "mailbox=\n" unless $type eq 'FXO'; - if(defined $group) { - printf "group=\n"; - } - printf "context=default\n"; - printf "immediate=no\n" if defined $immediate; - print "\n"; -} - -sub gen_zapatachannelsconf($) { - my $file = shift || die; - rename "$file", "$file.bak" - or $! == 2 # ENOENT (No dependency on Errno.pm) - or die "Failed to backup old config: $!\n"; - open(F, ">$file") || die "$0: Failed to open $file: $!\n"; - my $old = select F; - printf "; Autogenerated by %s on %s -- do not hand edit\n", $0, scalar(localtime); - print <<"HEAD"; -; Zaptel Channels Configurations (zapata.conf) -; -; This is not intended to be a complete zapata.conf. Rather, it is intended -; to be #include-d by /etc/zapata.conf that will include the global settings -; - -HEAD - foreach my $span (@spans) { - printf "; Span %d: %s %s\n", $span->num, $span->name, $span->description; - if($span->is_digital()) { - gen_zapata_digital($span); - } else { - foreach my $chan ($span->chans()) { - gen_zapata_channel($chan); - } + if (@ARGV) { + for my $gen (@ARGV) { + push @genlist, $gen; + } + } else { + # No files given. Use the defaults. + @genlist = ('zaptel', 'zapata'); + if($gconfig->{'pri_connection_type'} eq 'R2') { + push @genlist, 'unicall'; } - print "\n"; } - close F; - select $old; + return @genlist; } -sub gen_users_channel($) { - my $chan = shift || die; - my $type = $chan->type; - my $num = $chan->num; - die "channel $num type $type is not an analog channel\n" if $chan->span->is_digital(); - my $exten = $base_exten + $num; - my $sig = $default_zapata_signalling{$type}; - my $full_name = "$type $num"; - - die "missing default_zapata_signalling for chan #$num type $type" unless $sig; - print << "EOF"; -[$exten] -callwaiting = yes -context = numberplan-custom-1 -fullname = $full_name -cid_number = $exten -hasagent = no -hasdirectory = no -hasiax = no -hasmanager = no -hassip = no -hasvoicemail = yes -host = dynamic -mailbox = $exten -threewaycalling = yes -vmsecret = 1234 -secret = 1234 -signalling = $sig -zapchan = $num -registeriax = no -registersip = no -canreinvite = no -nat = no -dtmfmode = rfc2833 -disallow = all -allow = all - -EOF -} +sub parse_genopts($) { + my $optstr = shift; + my %genopts; -# generate users.conf . The specific users.conf is strictly oriented -# towards using with the asterisk-gui . -# -# This code could have generated a much simpler and smaller -# configuration file, had there been minimal level of support for -# configuration templates in the asterisk configuration rewriting. Right -# now Asterisk's configuration rewriting simply freaks out in the face -# of templates: http://bugs.digium.com/11442 . -sub gen_usersconf($) { - my $file = shift || die; - rename "$file", "$file.bak" - or $! == 2 # ENOENT (No dependency on Errno.pm) - or die "Failed to backup old config: $!\n"; - open(F, ">$file") || die "$0: Failed to open $file: $!\n"; - my $old = select F; - print <<"HEAD"; -;! -;! Automatically generated configuration file -;! Filename: @{[basename($file)]} ($file) -;! Generator: $0 -;! Creation Date: @{[scalar(localtime)]} -;! -[general] -; -; Full name of a user -; -fullname = New User -; -; Starting point of allocation of extensions -; -userbase = @{[$base_exten+1]} -; -; Create voicemail mailbox and use use macro-stdexten -; -hasvoicemail = yes -; -; Set voicemail mailbox @{[$base_exten+1]} password to 1234 -; -vmsecret = 1234 -; -; Create SIP Peer -; -hassip = no -; -; Create IAX friend -; -hasiax = no -; -; Create Agent friend -; -hasagent = no -; -; Create H.323 friend -; -;hash323 = yes -; -; Create manager entry -; -hasmanager = no -; -; Remaining options are not specific to users.conf entries but are general. -; -callwaiting = yes -threewaycalling = yes -callwaitingcallerid = yes -transfer = yes -canpark = yes -cancallforward = yes -callreturn = yes -callgroup = 1 -pickupgroup = 1 -localextenlength = @{[length($base_exten)]} - - -HEAD - foreach my $span (@spans) { - next unless grep { $_ eq $span->type} ( 'FXS', 'IN', 'OUT' ); - printf "; Span %d: %s %s\n", $span->num, $span->name, $span->description; - foreach my $chan ($span->chans()) { - gen_users_channel($chan); - } - print "\n"; + $optstr = '' unless defined $optstr; + foreach my $o (split(/,/, $optstr)) { + my ($k, $v) = split(/=/, $o, 2); + $v = 1 unless defined $v and $v; + $genopts{$k} = $v; } - close F; - select $old; + return %genopts; } -sub gen_zapataconf($) { - my $file = shift || die; - open(F, ">>$file") || die "$0: Failed to open $file: $!\n"; - my $old = select F; - foreach my $span (@spans) { - next unless $span->type eq 'FXO'; - my $current_sig = ""; - for my $chan ($span->chans()) { - my $chan_num = $chan->num; - if ($default_zapata_signalling{$chan->type} ne $current_sig) { - $current_sig = $default_zapata_signalling{$chan->type}; - print "\nsignalling = $current_sig"; - print "\nchannel => $chan_num"; - } else { - print ",$chan_num"; - } +sub generate_files($@) { + my $gconfig = shift || die; + my @spans = @_; + my @generators = generator_list($gconfig); + + for my $gen (@generators) { + my ($name, $optstr) = split(/=/, $gen, 2); + die "Illegal name '$name'\n" unless $name =~ /^\w+$/; + $name =~ s/(.)(.*)/\u$1\L$2/; + my %genopts = parse_genopts($optstr); + $genopts{'freepbx'} = 'yes' if $opts{'F'}; + if(defined $opts{'v'}) { + $genopts{'verbose'} = $opts{v}; } - print "\n"; - } - close F; - select $old; -} - -sub set_defaults { - # Source default files - my ($default_file, %source_defaults) = - Zaptel::Config::Defaults::source_vars(keys(%zaptel_default_vars)); - map_zaptel_defaults(%source_defaults); - # Fixups - foreach my $val (values %default_zaptel_signalling, values %default_zapata_signalling) { - $val =~ s/{fxs_default_start}/$fxs_default_start/g; + $gconfig->run_generator($name, \%genopts, @spans); } - $zapconf_file = $ENV{ZAPCONF_FILE} || "/etc/zaptel.conf"; - $zapatachannels_file = $ENV{ZAPATA_FILE} || "/etc/asterisk/zapata-channels.conf"; - $users_file = $ENV{USERS_FILE} || "/etc/asterisk/users.conf"; - $zapataconf_file = $ENV{ZAPATACONF_FILE} || "/etc/asterisk/zapata.conf"; } -sub parse_args { - return if @ARGV == 0; - @default_files = (); - for my $file (@ARGV) { - die "$0: Unknown file '$file'" unless defined $files{$file}; - push @default_files, $file; - } +getopts('vVF', \%opts) || die "$0: Bad option\n"; +if($opts{'V'}) { + my $revstr = $revision; + $revstr =~ s/[^$]*\$[^:]+:\s*//; + $revstr =~ s/\s*\$.*//; + print "$0: version=$version revision=$revstr\n"; + exit 0; } -sub generate_files { - for my $file (@default_files) { - &{$files{$file}->{func}}(${$files{$file}->{file}}); - } -} -set_defaults; -parse_args; -generate_files; +my $gconfig = set_defaults; +my @spans = Zaptel::spans(); +spans_prep($gconfig, @spans); +generate_files($gconfig, @spans); __END__ @@ -569,35 +115,82 @@ zapconf - Generate configuration for zaptel channels. =head1 SYNOPSIS -zapconf [FILES...] +zapconf [options] [generator...] =head1 DESCRIPTION This script generate configuration files for Zaptel hardware. -Currently it can generate three files: zaptel, zapata, users and zapataconf (see below). -Without arguments, it generates only zaptel and zapata. +It uses two information sources: =over 4 -=item zaptel - /etc/zaptel.conf +=item Hardware + + The actual zaptel hardware is automatically detected on the host. + +=item /etc/genconf_params + +A configuration file that supplements the hardware information. +Its location may be overriden via the C<GENCONF_PARAMETERS> environment +variable. + +=back -Configuration for ztcfg(1). It's location may be overriden by the -environment variable ZAPCONF_FILE. +The zapconf script can generate various kinds of configuration files +as specificed by the generator arguments. Each generator is a perl classes +in Zaptel::Config::Gen namespace. The generator names on the command line +are the class names in lowercase. -=item zapata - /etc/asterisk/zapata-channels.conf +The following generators are currently implemented: zaptel, zapata, unicall, users. +For further documentation on each, please user perldoc on the relevant +class. E.g: C<perldoc Zaptel::Config::Gen::Zapata> + +Each generator on the command line may be passed custom options by assigning +a comma separated list of options to the generator name. E.g: + + zapconf zaptel zapata=verbose unicall + +=head2 Global options: + +=over 4 + +=item -V + +Version -- print version string and exit. + +=item -v + +Verbose -- sets the C<'verbose'> option for all generators. + +=item -F + +Freepbx -- sets the C<'freepbx'> option for all generators. +Currently, zapata is affected. + + +=back + +=head2 Implementation notes: + +=over 4 -Configuration for asterisk(1). It should be included in the main /etc/asterisk/zapata.conf. -It's location may be overriden by the environment variable ZAPATA_FILE. +=item * -=item users - /etc/asterisk/users.conf +F<genconf_parameters> parsing is done via C<Zaptel::Config::Params>. +An object representing the parsed data is instanciated by: +C<Zaptel::Config::Params-E<gt>new()>. +The C<item()> method of this object contains all the hard coded +defaults of the configuration directives. -Configuration for asterisk(1) and AsteriskGUI. -It's location may be overriden by the environment variable USERS_FILE. +=item * -=item zapataconf - /etc/asterisk/zapata.conf +A configuration object is instanciated by C<Zaptel::Config::Gen-E<gt>new($params)>. +The mapping of configuration directives into semantic configuration is +done in the constructor. -Configuration for asterisk(1) and AsteriskGUI. -It's location may be overriden by the environment variable ZAPATACONF_FILE. +=item * +A single generator is run via the the C<run_generator()> method of the +configuration object. =back |