Add support for aliases on red-Interface (static Red)
authorPeter Pfeiffer <peterman@ipfire.org>
Thu, 12 Mar 2009 14:22:11 +0000 (15:22 +0100)
committerPeter Pfeiffer <peterman@ipfire.org>
Thu, 12 Mar 2009 14:22:11 +0000 (15:22 +0100)
config/menu/30-network.menu [changed mode: 0644->0755]
html/cgi-bin/aliases.cgi [new file with mode: 0755]
src/misc-progs/Makefile [changed mode: 0644->0755]
src/misc-progs/setaliases.c [new file with mode: 0755]

old mode 100644 (file)
new mode 100755 (executable)
index d3eecf5..6c0d63c
@@ -45,7 +45,7 @@
                                  'caption' => $Lang::tr{'aliases'},
                                  'uri' => '/cgi-bin/aliases.cgi',
                                  'title' => "$Lang::tr{'aliases'}",
-                                 'enabled' => 0,
+                                 'enabled' => 1,
                                  };
     $subnetwork->{'80.wakeonlan'} = {
                                  'caption' => $Lang::tr{'WakeOnLan'},
diff --git a/html/cgi-bin/aliases.cgi b/html/cgi-bin/aliases.cgi
new file mode 100755 (executable)
index 0000000..c8d4362
--- /dev/null
@@ -0,0 +1,500 @@
+#!/usr/bin/perl\r
+#\r
+# IPCop CGI's - aliases.cgi\r
+#\r
+# This code is distributed under the terms of the GPL\r
+#\r
+# (c) Steve Bootes 2002/04/13 - Manage IP Aliases\r
+#\r
+# $Id: aliases.cgi,v 1.5.2.18 2006/12/08 21:59:59 eoberlander Exp $\r
+\r
+\r
+# to fully troubleshot your code, uncomment diagnostics, Carp and cluck lines\r
+#use diagnostics; # need to add the file /usr/lib/perl5/5.8.x/pods/perldiag.pod before to work\r
+# next look at /var/log/httpd/error_log , http://www.perl.com/pub/a/2002/05/07/mod_perl.html may help\r
+#use warnings;\r
+use strict;\r
+#use Carp ();\r
+#local $SIG{__WARN__} = \&Carp::cluck;\r
+\r
+require '/var/ipfire/general-functions.pl';    # replace /var/ipcop with /var/ipcop in case of manual install\r
+require "${General::swroot}/lang.pl";\r
+require "${General::swroot}/header.pl";\r
+\r
+#workaround to suppress a warning when a variable is used only once\r
+my @dummy = ( ${Header::colouryellow} );\r
+   @dummy = ( ${Header::table1colour} );\r
+   @dummy = ( ${Header::table2colour} );\r
+undef (@dummy);\r
+\r
+# Files used\r
+my $setting = "${General::swroot}/ethernet/settings";\r
+our $datafile = "${General::swroot}/ethernet/aliases";\r
+\r
+\r
+our %settings=();\r
+#Settings1\r
+\r
+#Settings2 for editing the multi-line list\r
+#Must not be saved !\r
+$settings{'IP'} = '';\r
+$settings{'ENABLED'} = 'off';          # Every check box must be set to off\r
+$settings{'NAME'} = '';\r
+my @nosaved=('IP','ENABLED','NAME');   # List here ALL setting2 fields. Mandatory\r
+    \r
+$settings{'ACTION'} = '';              # add/edit/remove\r
+$settings{'KEY1'} = '';                        # point record for ACTION\r
+\r
+#Define each field that can be used to sort columns\r
+my $sortstring='^IP|^NAME';\r
+my $errormessage = '';\r
+my $warnmessage = '';\r
+\r
+&Header::showhttpheaders();\r
+\r
+# Read needed Ipcop netsettings\r
+my %netsettings=();\r
+$netsettings{'SORT_ALIASES'} = 'NAME';         # default sort\r
+&General::readhash($setting, \%netsettings);\r
+\r
+#Get GUI values\r
+&Header::getcgihash(\%settings);\r
+\r
+# Load multiline data\r
+our @current = ();\r
+if (open(FILE, "$datafile")) {\r
+    @current = <FILE>;\r
+    close (FILE);\r
+}\r
+\r
+#\r
+# Check Settings1 first because they are needed before working on @current\r
+#\r
+# Remove if no Setting1 needed\r
+#\r
+if ($settings{'ACTION'} eq $Lang::tr{'save'}) {\r
+    \r
+    #\r
+    #Validate static Settings1 here\r
+    #\r
+    \r
+    unless ($errormessage) {                                   # Everything is ok, save settings\r
+       #map (delete ($settings{$_}) ,(@nosaved,'ACTION','KEY1'));# Must never be saved \r
+       #&General::writehash($setting, \%settings);             # Save good settings\r
+       #$settings{'ACTION'} = $Lang::tr{'save'};               # Recreate  'ACTION'\r
+       #map ($settings{$_}= '',(@nosaved,'KEY1'));             # and reinit var to empty\r
+       \r
+       # Rebuild configuration file if needed\r
+       &BuildConfiguration;\r
+    }\r
+\r
+    ERROR:                                             # Leave the faulty field untouched\r
+} else {\r
+    #&General::readhash($setting, \%settings);         # Get saved settings and reset to good if needed\r
+}\r
+\r
+## Now manipulate the multi-line list with Settings2\r
+# Basic actions are:\r
+#      toggle the check box\r
+#      add/update a new line\r
+#      begin editing a line\r
+#      remove a line\r
+\r
+\r
+# Toggle enable/disable field.  Field is in second position\r
+if ($settings{'ACTION'} eq $Lang::tr{'toggle enable disable'}) {\r
+    #move out new line\r
+    chomp(@current[$settings{'KEY1'}]);\r
+    my @temp = split(/\,/,@current[$settings{'KEY1'}]);\r
+    $temp[1] = $temp[1] eq 'on' ? 'off' : 'on';                # Toggle the field\r
+    $temp[2] = '' if ( $temp[2] eq '' );\r
+    @current[$settings{'KEY1'}] = join (',',@temp)."\n";\r
+    $settings{'KEY1'} = '';                            # End edit mode\r
+    \r
+    &General::log($Lang::tr{'ip alias changed'});\r
+    \r
+    #Save current\r
+    open(FILE, ">$datafile") or die 'Unable to open aliases file.';\r
+    print FILE @current;\r
+    close(FILE);\r
+       \r
+    # Rebuild configuration file\r
+    &BuildConfiguration;\r
+}\r
+\r
+if ($settings{'ACTION'} eq $Lang::tr{'add'}) {\r
+    # Validate inputs\r
+    if (! &General::validip($settings{'IP'})) {$errormessage = "invalid ip"};\r
+    $settings{'NAME'} = &Header::cleanhtml($settings{'NAME'});\r
+\r
+    # Make sure we haven't duplicated an alias or RED\r
+    my $spacer='';\r
+    if ($settings{'IP'} eq $netsettings{'RED_ADDRESS'}) {\r
+       $errormessage = $Lang::tr{'duplicate ip'} . ' (RED)';\r
+        $spacer=" & ";\r
+    }\r
+    my $idx=0;\r
+    foreach my $line (@current) {\r
+        chomp ($line);\r
+        my @temp = split (/\,/, $line);\r
+        if ( ($settings{'KEY1'} eq '')||(($settings{'KEY1'} ne '') && ($settings{'KEY1'} != $idx))) { # update\r
+           if ($temp[0] eq $settings{'IP'}) {\r
+               $errormessage .= $spacer.$Lang::tr{'duplicate ip'};\r
+               $spacer=" & ";\r
+           }\r
+           if ($temp[2] eq $settings{'NAME'} && $temp[2] ne '') {\r
+               $errormessage .= $spacer.$Lang::tr{'duplicate name'};\r
+               $spacer=" & ";\r
+               }\r
+       }\r
+       $idx++;\r
+    }\r
+    unless ($errormessage) {\r
+       if ($settings{'KEY1'} eq '') { #add or edit ?\r
+           unshift (@current, "$settings{'IP'},$settings{'ENABLED'},$settings{'NAME'}\n");\r
+           &General::log($Lang::tr{'ip alias added'});\r
+       } else {\r
+           @current[$settings{'KEY1'}] = "$settings{'IP'},$settings{'ENABLED'},$settings{'NAME'}\n";\r
+           $settings{'KEY1'} = '';       # End edit mode\r
+           &General::log($Lang::tr{'ip alias changed'});\r
+       }\r
+\r
+       # Write changes to config file.\r
+       &SortDataFile;                          # sort newly added/modified entry\r
+\r
+       &BuildConfiguration;                    # then re-build conf which use new data\r
+       \r
+##\r
+## if entering data line is repetitive, choose here to not erase fields between each addition\r
+##\r
+       map ($settings{$_}='' ,@nosaved);       # Clear fields\r
+    }\r
+}\r
+\r
+if ($settings{'ACTION'} eq $Lang::tr{'edit'}) {\r
+    #move out new line\r
+    my $line = @current[$settings{'KEY1'}];    # KEY1 is the index in current\r
+    chomp($line);\r
+    my @temp = split(/\,/, $line);\r
+\r
+##\r
+## move data fields to Setting2 for edition\r
+##\r
+    $settings{'IP'}=$temp[0];                  # Prepare the screen for editing\r
+    $settings{'ENABLED'}=$temp[1];\r
+    $settings{'NAME'}=$temp[2];\r
+}\r
+\r
+if ($settings{'ACTION'} eq $Lang::tr{'remove'}) {\r
+    splice (@current,$settings{'KEY1'},1);             # Delete line \r
+    open(FILE, ">$datafile") or die 'Unable to open aliases file.';\r
+    print FILE @current;\r
+    close(FILE);\r
+    $settings{'KEY1'} = '';                            # End remove mode\r
+    &General::log($Lang::tr{'ip alias removed'});\r
+\r
+    &BuildConfiguration;                               # then re-build conf which use new data\r
+}\r
+\r
+\r
+\r
+##  Check if sorting is asked\r
+# If same column clicked, reverse the sort.\r
+if ($ENV{'QUERY_STRING'} =~ /$sortstring/ ) {\r
+    my $newsort=$ENV{'QUERY_STRING'};\r
+    my $actual=$netsettings{'SORT_ALIASES'};\r
+    #Reverse actual sort ?\r
+    if ($actual =~ $newsort) {\r
+       my $Rev='';\r
+       if ($actual !~ 'Rev') {\r
+           $Rev='Rev';\r
+       }\r
+       $newsort.=$Rev;\r
+    }\r
+    $netsettings{'SORT_ALIASES'}=$newsort;\r
+    &General::writehash($setting, \%netsettings);\r
+    &SortDataFile;\r
+    $settings{'ACTION'} = 'SORT';                      # Recreate  'ACTION'\r
+}\r
+\r
+# Default initial value\r
+if ($settings{'ACTION'} eq '' ) { # First launch from GUI\r
+    $settings{'ENABLED'} ='on';\r
+}\r
+    \r
+&Header::openpage($Lang::tr{'external aliases configuration'}, 1, '');\r
+&Header::openbigbox('100%', 'left', '', $errormessage);\r
+my %checked =();     # Checkbox manipulations\r
+\r
+if ($errormessage) {\r
+    &Header::openbox('100%', 'left', $Lang::tr{'error messages'});\r
+    print "<font class='base'>$errormessage&nbsp;</font>";\r
+    &Header::closebox();\r
+}\r
+unless (( $netsettings{'CONFIG_TYPE'} =~ /^(1|2|3|4)$/ ) && ($netsettings{'RED_TYPE'} eq 'STATIC'))\r
+{\r
+    &Header::openbox('100%', 'left', $Lang::tr{'capswarning'});\r
+    print <<END\r
+    <table width='100%'>\r
+    <tr>\r
+    <td width='100%' class='boldbase' align='center'><font color='${Header::colourred}'><b>$Lang::tr{'aliases not active'}</b></font></td>\r
+    </tr>\r
+    </table>\r
+END\r
+;\r
+    &Header::closebox();\r
+}\r
+                                                                       \r
+#\r
+# Second check box is for editing the list\r
+#\r
+$checked{'ENABLED'}{'on'} = ($settings{'ENABLED'} eq 'on') ? "checked='checked'" : '' ;\r
+\r
+my $buttontext = $Lang::tr{'add'};\r
+if ($settings{'KEY1'} ne '') {\r
+    $buttontext = $Lang::tr{'update'};\r
+    &Header::openbox('100%', 'left', $Lang::tr{'edit an existing alias'});\r
+} else {\r
+    &Header::openbox('100%', 'left', $Lang::tr{'add new alias'});\r
+}\r
+\r
+#Edited line number (KEY1) passed until cleared by 'save' or 'remove' or 'new sort order'\r
+print <<END\r
+<form method='post' action='$ENV{'SCRIPT_NAME'}'>\r
+<input type='hidden' name='KEY1' value='$settings{'KEY1'}' />\r
+<table width='100%'>\r
+<tr>\r
+<td class='base'><font color='${Header::colourred}'>$Lang::tr{'name'}:&nbsp;<img src='/blob.gif' alt='*' /></font></td>\r
+<td><input type='text' name='NAME' value='$settings{'NAME'}' size='32' /></td>\r
+<td class='base' align='right'><font color='${Header::colourred}'>$Lang::tr{'alias ip'}:&nbsp;</font></td>\r
+<td><input type='text' name='IP' value='$settings{'IP'}' size='16' /></td>\r
+<td class='base' align='right'>$Lang::tr{'enabled'}&nbsp;</td>\r
+<td><input type='checkbox' name='ENABLED' $checked{'ENABLED'}{'on'} /></td>\r
+</tr>\r
+</table>\r
+<hr />\r
+<table width='100%'>\r
+<tr>\r
+    <td class='base' width='55%'><img src='/blob.gif' align='top' alt='*' />&nbsp;$Lang::tr{'this field may be blank'}</td>\r
+    <td width='40%' align='center'><input type='hidden' name='ACTION' value='$Lang::tr{'add'}' /><input type='submit' name='SUBMIT' value='$buttontext' /></td>\r
+    <td width='5%' align='right'> \r
+        <a href='${General::adminmanualurl}/section-dialup.html#services-extalias' target='_blank'><img src='/images/web-support.png' title='$Lang::tr{'online help en'}' /></a>\r
+    </td>\r
+</tr>\r
+</table>\r
+</form>\r
+END\r
+;\r
+&Header::closebox();\r
+\r
+# Add visual indicators to column headings to show sort order - EO\r
+my $sortarrow1 = '';\r
+my $sortarrow2 = '';\r
+\r
+if ($netsettings{'SORT_ALIASES'} eq 'NAMERev') {\r
+       $sortarrow1 = $Header::sortdn;\r
+} elsif ($netsettings{'SORT_ALIASES'} eq 'NAME') {\r
+       $sortarrow1 = $Header::sortup;\r
+} elsif ($netsettings{'SORT_ALIASES'} eq 'IPRev') {\r
+       $sortarrow2 = $Header::sortdn;\r
+} else {\r
+       $sortarrow2 = $Header::sortup;\r
+}\r
+\r
+#\r
+# Third box shows the list, in columns\r
+#\r
+# Columns headers may content a link. In this case it must be named in $sortstring\r
+#\r
+&Header::openbox('100%', 'left', $Lang::tr{'current aliases'});\r
+print <<END\r
+<table width='100%'>\r
+<tr>\r
+    <td width='50%' align='center'><a href='$ENV{'SCRIPT_NAME'}?NAME'><b>$Lang::tr{'name'}</b></a> $sortarrow1</td>\r
+    <td width='45%' align='center'><a href='$ENV{'SCRIPT_NAME'}?IP'><b>$Lang::tr{'alias ip'}</b></a> $sortarrow2</td>\r
+    <td width='5%' colspan='3' class='boldbase' align='center'><b>$Lang::tr{'action'}</b></td>\r
+</tr>\r
+END\r
+;\r
+\r
+#\r
+# Print each line of @current list\r
+#\r
+# each data line is splitted into @temp.\r
+#\r
+\r
+my $key = 0;\r
+foreach my $line (@current) {\r
+    chomp($line);\r
+    my @temp = split(/\,/,$line);\r
+\r
+    #Choose icon for checkbox\r
+    my $gif = '';\r
+    my $gdesc = '';\r
+    if ($temp[1] eq "on") {\r
+       $gif = 'on.gif';\r
+       $gdesc = $Lang::tr{'click to disable'};\r
+    } else {\r
+       $gif = 'off.gif';\r
+       $gdesc = $Lang::tr{'click to enable'}; \r
+    }\r
+\r
+    #Colorize each line\r
+    if ($settings{'KEY1'} eq $key) {\r
+       print "<tr bgcolor='${Header::colouryellow}'>";\r
+    } elsif ($key % 2) {\r
+       print "<tr bgcolor='${Header::table2colour}'>";\r
+    } else {\r
+       print "<tr bgcolor='${Header::table1colour}'>"; \r
+    }\r
+\r
+    print <<END\r
+<td align='center'>$temp[2]</td>\r
+<td align='center'>$temp[0]</td>\r
+\r
+<td align='center'>\r
+<form method='post' action='$ENV{'SCRIPT_NAME'}'>\r
+<input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />\r
+<input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' />\r
+<input type='hidden' name='KEY1' value='$key' />\r
+</form>\r
+</td>\r
+\r
+<td align='center'>\r
+<form method='post' action='$ENV{'SCRIPT_NAME'}'>\r
+<input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' />\r
+<input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />\r
+<input type='hidden' name='KEY1' value='$key' />\r
+</form>\r
+</td>\r
+\r
+<td align='center'>\r
+<form method='post' action='$ENV{'SCRIPT_NAME'}'>\r
+<input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />\r
+<input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />\r
+<input type='hidden' name='KEY1' value='$key' />\r
+</form>\r
+</td>\r
+</tr>\r
+END\r
+;\r
+    $key++;\r
+}\r
+print "</table>";\r
+\r
+# If table contains entries, print 'Key to action icons'\r
+if ($key) {\r
+print <<END\r
+<table>\r
+<tr>\r
+    <td class='boldbase'>&nbsp;<b>$Lang::tr{'legend'}:&nbsp;</b></td>\r
+    <td><img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>\r
+    <td class='base'>$Lang::tr{'click to disable'}</td>\r
+    <td>&nbsp;&nbsp;</td>\r
+    <td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>\r
+    <td class='base'>$Lang::tr{'click to enable'}</td>\r
+    <td>&nbsp;&nbsp;</td>\r
+    <td><img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td>\r
+    <td class='base'>$Lang::tr{'edit'}</td>\r
+    <td>&nbsp;&nbsp;</td>\r
+    <td><img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>\r
+    <td class='base'>$Lang::tr{'remove'}</td>\r
+</tr>\r
+</table>\r
+END\r
+;\r
+}\r
+\r
+&Header::closebox();\r
+&Header::closebigbox();\r
+&Header::closepage();\r
+\r
+## Ouf it's the end !\r
+\r
+\r
+\r
+# Sort the "current" array according to choices\r
+sub SortDataFile\r
+{\r
+    our %entries = ();\r
+    \r
+    # Sort pair of record received in $a $b special vars.\r
+    # When IP is specified use numeric sort else alpha.\r
+    # If sortname ends with 'Rev', do reverse sort.\r
+    #\r
+    sub fixedleasesort {\r
+       my $qs='';             # The sort field specified minus 'Rev'\r
+       if (rindex ($netsettings{'SORT_ALIASES'},'Rev') != -1) {\r
+           $qs=substr ($netsettings{'SORT_ALIASES'},0,length($netsettings{'SORT_ALIASES'})-3);\r
+           if ($qs eq 'IP') {\r
+               my @a = split(/\./,$entries{$a}->{$qs});\r
+               my @b = split(/\./,$entries{$b}->{$qs});\r
+               ($b[0]<=>$a[0]) ||\r
+               ($b[1]<=>$a[1]) ||\r
+               ($b[2]<=>$a[2]) ||\r
+               ($b[3]<=>$a[3]);\r
+           } else {\r
+               $entries{$b}->{$qs} cmp $entries{$a}->{$qs};\r
+           }\r
+       } else { #not reverse\r
+           $qs=$netsettings{'SORT_ALIASES'};\r
+           if ($qs eq 'IP') {\r
+               my @a = split(/\./,$entries{$a}->{$qs});\r
+               my @b = split(/\./,$entries{$b}->{$qs});\r
+               ($a[0]<=>$b[0]) ||\r
+               ($a[1]<=>$b[1]) ||\r
+               ($a[2]<=>$b[2]) ||\r
+               ($a[3]<=>$b[3]);\r
+           } else {\r
+               $entries{$a}->{$qs} cmp $entries{$b}->{$qs};\r
+           }\r
+       }\r
+    }\r
+\r
+    #Use an associative array (%entries)\r
+    my $key = 0;\r
+    foreach my $line (@current) {\r
+       chomp( $line); #remove newline because can be on field 5 or 6 (addition of REMARK)\r
+       my @temp = split (',',$line);\r
+       \r
+       # Build a pair 'Field Name',value for each of the data dataline.\r
+       # Each SORTABLE field must have is pair.\r
+       # Other data fields (non sortable) can be grouped in one\r
+       \r
+       # Exemple\r
+       # F1,F2,F3,F4,F5       only F1 F2 for sorting\r
+       # my @record = ('KEY',$key++,\r
+       #               'F1',$temp[0],\r
+       #               'F2',$temp[1],\r
+       #               'DATA',join(',',@temp[2..4])    );  #group remainning values, with separator (,)\r
+       \r
+       # The KEY,key record permits doublons. If removed, then F1 becomes the key without doublon permitted.\r
+       \r
+       \r
+       my @record = ('KEY',$key++,'IP',$temp[0],'ENABLED',$temp[1],'NAME',$temp[2]);\r
+       my $record = {};                                # create a reference to empty hash\r
+       %{$record} = @record;                           # populate that hash with @record\r
+       $entries{$record->{KEY}} = $record;             # add this to a hash of hashes\r
+    }\r
+    \r
+    open(FILE, ">$datafile") or die 'Unable to open aliases file.';\r
+\r
+    # Each field value is printed , with the newline ! Don't forget separator and order of them.\r
+    foreach my $entry (sort fixedleasesort keys %entries) {\r
+       print FILE "$entries{$entry}->{IP},$entries{$entry}->{ENABLED},$entries{$entry}->{NAME}\n";\r
+    }\r
+\r
+    close(FILE);\r
+    # Reload sorted  @current\r
+    open (FILE, "$datafile");\r
+    @current = <FILE>;\r
+    close (FILE);\r
+}\r
+\r
+#                                                  \r
+# Build the configuration file for application aliases\r
+#\r
+sub BuildConfiguration {\r
+    # Restart service associated with this\r
+    system '/usr/local/bin/setaliases';\r
+}\r
old mode 100644 (file)
new mode 100755 (executable)
index 1fe5b36..66c8677
@@ -31,7 +31,8 @@ SUID_PROGS = setdmzholes setportfw setxtaccess \
        logwatch openvpnctrl outgoingfwctrl \
        wirelessctrl getipstat getiptstate qosctrl launch-ether-wake \
        redctrl syslogdctrl extrahdctrl sambactrl upnpctrl tripwirectrl \
-       smartctrl clamavctrl addonctrl pakfire mpfirectrl wlanapctrl
+       smartctrl clamavctrl addonctrl pakfire mpfirectrl wlanapctrl \
+       setaliases
 
 install : all
        install -m 755  $(PROGS) /usr/local/bin
@@ -143,3 +144,7 @@ syslogdctrl: syslogdctrl.c setuid.o ../install+setup/libsmooth/varval.o
 
 wlanapctrl: wlanapctrl.c setuid.o ../install+setup/libsmooth/varval.o
        $(COMPILE) -I../install+setup/libsmooth/ wlanapctrl.c setuid.o ../install+setup/libsmooth/varval.o -o $@
+
+setaliases: setaliases.c setuid.o ../install+setup/libsmooth/varval.o
+       $(COMPILE) -I../install+setup/libsmooth/ setaliases.c setuid.o ../install+setup/libsmooth/varval.o -o $@
+
diff --git a/src/misc-progs/setaliases.c b/src/misc-progs/setaliases.c
new file mode 100755 (executable)
index 0000000..a03e148
--- /dev/null
@@ -0,0 +1,196 @@
+/*\r
+ * setaliases - configure red aliased interfaces\r
+ *\r
+ * This program is distributed under the terms of the GNU General Public\r
+ * Licence.  See the file COPYING for details.\r
+ *\r
+ * (c) Steve Bootes, 2002/04/15\r
+ *\r
+ * 21/04/03 Robert Kerr Changed to link directly to libsmooth rather than\r
+ *                      using a copy & paste\r
+ *\r
+ * $Id: setaliases.c,v 1.2.2.5 2006/07/25 23:15:20 franck78 Exp $\r
+ *\r
+ */\r
+\r
+#include "libsmooth.h"\r
+#include "setuid.h"\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+#include <unistd.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <fcntl.h>\r
+\r
+struct keyvalue *kv = NULL;\r
+FILE *file = NULL;\r
+\r
+void exithandler(void)\r
+{\r
+       if (kv) freekeyvalues(kv);\r
+       if (file) fclose(file);\r
+}\r
+\r
+int main(void)\r
+{\r
+       char s[STRING_SIZE];\r
+       char command[STRING_SIZE];\r
+       char red_netmask[STRING_SIZE];\r
+       char red_broadcast[STRING_SIZE];\r
+       char red_dev[STRING_SIZE];\r
+       char default_gateway[STRING_SIZE];\r
+       char *aliasip;\r
+       char *enabled;\r
+       char *sptr;\r
+       char *comment;\r
+       int alias;\r
+       int count;\r
+\r
+       if (!(initsetuid()))\r
+       {\r
+               fprintf(stderr, "Cannot run setuid\n");\r
+               exit(1);\r
+       }\r
+\r
+       atexit(exithandler);\r
+\r
+       /* Init the keyvalue structure */\r
+       kv=initkeyvalues();\r
+\r
+       /* Read in the current values */\r
+       if (!readkeyvalues(kv, CONFIG_ROOT "/ethernet/settings"))\r
+       {\r
+               fprintf(stderr, "Cannot read ethernet settings\n");\r
+               exit(1);\r
+       }\r
+\r
+       /* Find the CONFIG_TYPE value */\r
+       if (!findkey(kv, "CONFIG_TYPE", s))\r
+       {\r
+               fprintf(stderr, "Cannot read CONFIG_TYPE\n");\r
+               exit(1);\r
+       }\r
+\r
+       /* Check for CONFIG_TYPE=2 or 3 i.e. RED ethernet present. If not,\r
+        * exit gracefully.  This is not an error... */\r
+       if (!((strcmp(s, "1")==0) || (strcmp(s, "2")==0) || (strcmp(s, "3")==0) || (strcmp(s, "4")==0)))\r
+               exit(0);\r
+\r
+       /* Now check the RED_TYPE - aliases only work with STATIC.\r
+        * At least, that's what /etc/rc.d/rc.netaddress.up thinks.. */\r
+\r
+       /* Find the RED_TYPE value */\r
+       if (!findkey(kv, "RED_TYPE", s))\r
+       {\r
+               fprintf(stderr, "Cannot read RED_TYPE\n");\r
+               exit(1);\r
+       }\r
+       \r
+       /* Make sure it's the right type */\r
+       if (!(strcmp(s, "STATIC")==0)) \r
+               exit(0);\r
+\r
+       /* Get the RED interface details */\r
+       if((!findkey(kv, "RED_NETMASK", red_netmask)) || (!findkey(kv, "RED_BROADCAST", red_broadcast)) || \r
+               (!findkey(kv, "RED_DEV", red_dev)) || (!findkey(kv, "DEFAULT_GATEWAY", default_gateway)))\r
+       {\r
+               fprintf(stderr, "Cannot read RED settings\n");\r
+               exit(1);\r
+       }\r
+               \r
+       if (!VALID_DEVICE(red_dev))\r
+       {\r
+               fprintf(stderr, "Bad red_dev: %s\n", red_dev);\r
+               exit(1);\r
+       }\r
+\r
+       if (!VALID_IP(red_netmask))\r
+       {\r
+               fprintf(stderr, "Bad red_netmask : %s\n", red_netmask);\r
+               exit(1);\r
+       }\r
+\r
+       if (!VALID_IP(red_broadcast))\r
+       {\r
+               fprintf(stderr, "Bad red_broadcast : %s\n", red_broadcast);\r
+               exit(1);\r
+       }\r
+\r
+       if (!VALID_IP(default_gateway))\r
+       {\r
+               fprintf(stderr, "Bad default_gateway : %s\n", default_gateway);\r
+               exit(1);\r
+       }\r
+\r
+       /* down the aliases in turn until ifconfig complains */\r
+       alias=0;\r
+       do\r
+       {\r
+               memset(command, 0, STRING_SIZE);\r
+               snprintf(command, STRING_SIZE-1, "/sbin/ifconfig %s:%d down 2>/dev/null", red_dev, alias++);\r
+       } while (safe_system(command)==0);\r
+\r
+       /* Now set up the new aliases from the config file */\r
+        if (!(file = fopen(CONFIG_ROOT "/ethernet/aliases", "r")))\r
+        {\r
+                fprintf(stderr, "Unable to open aliases configuration file\n");\r
+                exit(1);\r
+        }\r
+\r
+       alias=0;\r
+       int linecounter = 0;\r
+        while (fgets(s, STRING_SIZE, file) != NULL)\r
+        {\r
+               linecounter++;\r
+                if (s[strlen(s) - 1] == '\n')\r
+                        s[strlen(s) - 1] = '\0';\r
+                count = 0;\r
+                aliasip = NULL;\r
+                enabled = NULL;\r
+                comment = NULL;\r
+                sptr = strtok(s, ",");\r
+                while (sptr)\r
+                {\r
+                        if (count == 0)\r
+                                aliasip = sptr;\r
+                        if (count == 1)\r
+                                enabled = sptr;\r
+                        else\r
+                                comment = sptr;\r
+                        count++;\r
+                       sptr = strtok(NULL, ",");\r
+               }\r
+\r
+               if (!(aliasip && enabled)) {\r
+                       fprintf(stderr, "Incomplete data line: in %s(%d)\n",\r
+                                       CONFIG_ROOT "/ethernet/aliases",\r
+                                       linecounter);\r
+                       exit(1);\r
+               }\r
+               if (!strcmp(enabled, "on") == 0)        /* disabled rule? */\r
+                       continue;\r
+\r
+               if (!VALID_IP(aliasip))\r
+                {\r
+                        fprintf(stderr, "Bad alias : %s in %s(%d)\n",\r
+                                       aliasip,\r
+                                       CONFIG_ROOT "/ethernet/aliases",\r
+                                       linecounter);\r
+                        exit(1);\r
+                }\r
+\r
+               memset(command, 0, STRING_SIZE);\r
+               snprintf(command, STRING_SIZE-1,\r
+                               "/sbin/ifconfig %s:%d %s netmask %s broadcast %s up",\r
+                            red_dev, alias, aliasip, red_netmask, red_broadcast);\r
+               safe_system(command);\r
+               memset(command, 0, STRING_SIZE);\r
+               snprintf(command, STRING_SIZE-1,\r
+                               "/usr/sbin/arping -q -c 1 -w 1 -i %s -S %s %s",\r
+                               red_dev, aliasip, default_gateway);\r
+               safe_system(command);\r
+               alias++;\r
+       }\r
+       return 0;\r
+}\r