3 # Update, create or delete a subnet
5 require './dhcpd-lib.pl';
6 require './params-lib.pl';
8 &lock_file($config{'dhcpd_conf'});
9 ($par, $sub, $indent, $npar, $nindent) = get_branch('sub', $in{'new'});
10 $parconf = $par->{'members'};
13 %access = &get_module_acl();
14 &error_setup($text{'eacl_aviol'});
16 &error("$text{'eacl_np'} $text{'eacl_pds'}")
17 if !&can('rw', \%access, $sub, 1);
19 elsif ($in{'options'}) {
20 &error("$text{'eacl_np'} $text{'eacl_pss'}")
21 if !&can('r', \%access, $sub);
24 &error("$text{'eacl_np'} $text{'eacl_pis'}")
25 unless &can('c', \%access, $sub) &&
26 &can('rw', \%access, $par) &&
27 (!$npar || &can('rw', \%access, $npar));
29 if ($access{'uniq_sub'}) {
30 foreach $s (&get_subnets()) {
31 &error("$text{'eacl_np'} $text{'eacl_uniq'}")
32 if lc $s->{'values'}->[0] eq lc $in{'network'};
36 elsif (!$in{'leases'}) {
37 &error("$text{'eacl_np'} $text{'eacl_pus'}")
38 unless &can('rw', \%access, $sub) &&
39 (!$npar || &can('rw', \%access, $npar));
44 # Redirect to client options
45 &redirect("edit_options.cgi?sidx=$in{'sidx'}&idx=$in{'idx'}");
48 elsif ($in{'leases'}) {
49 # Redirect to lease list for subnet
50 &redirect("list_leases.cgi?network=$sub->{'values'}->[0]&netmask=$sub->{'values'}->[2]");
55 &error_setup($text{'ssub_faildel'});
56 if ($par->{'name'} eq "shared-network") {
57 @subnets = &find("subnet", $par->{'members'});
59 &error(&text('ssub_nosubnet', $par->{'values'}->[0]));
64 &error_setup($text{'ssub_failsave'});
65 # Validate and save inputs
66 &to_ipaddress($in{'network'}) ||
67 &error("'$in{'network'}' $text{'ssub_invalidsubaddr'}");
68 &check_ipaddress($in{'netmask'}) ||
69 &error("'$in{'netmask'}' $text{'ssub_invalidnmask'}");
70 $oldnetwork = $sub->{'values'}->[0];
71 $sub->{'values'} = [ $in{'network'}, "netmask", $in{'netmask'} ];
74 @wasin = &find("host", $sub->{'members'});
75 foreach $hn (split(/\0/, $in{'hosts'})) {
76 if ($hn =~ /(\d+),(\d+)/) {
77 push(@nowin, $parconf->[$2]->{'members'}->[$1]);
78 $nowpr{$parconf->[$2]->{'members'}->[$1]} =
81 elsif ($hn =~ /(\d+),/) {
82 push(@nowin, $parconf->[$1]);
83 $nowpr{$parconf->[$1]} = $par;
85 if ($nowin[$#nowin]->{'name'} ne "host") {
86 &error($text{'sgroup_echanged'});
89 @wasgin = &find("group", $sub->{'members'});
90 foreach $gn (split(/\0/, $in{'groups'})) {
91 if ($gn =~ /(\d+),(\d+)/) {
92 push(@nowgin, $parconf->[$2]->{'members'}->[$1]);
93 $nowgpr{$parconf->[$2]->{'members'}->[$1]} =
96 elsif ($gn =~ /(\d+),/) {
97 push(@nowgin, $parconf->[$1]);
98 $nowgpr{$parconf->[$1]} = $par;
100 if ($nowgin[$#nowgin]->{'name'} ne "group") {
101 &error($text{'sgroup_echanged'});
105 &error_setup($text{'eacl_aviol'});
106 foreach $h (&unique(@wasin, @nowin)) {
107 $was = &indexof($h, @wasin) != -1;
108 $now = &indexof($h, @nowin) != -1;
110 # per-host ACLs for new or updated hosts
111 if ($was != $now && !&can('rw', \%access, $h)) {
112 &error("$text{'eacl_np'} $text{'eacl_pus'}");
115 # Move out of the subnet
116 &save_directive($sub, [ $h ], [ ], $indent);
117 &save_directive($par, [ ], [ $h ], $indent);
119 elsif ($now && !$was) {
120 # Move into the subnet (maybe from another subnet)
121 &save_directive($nowpr{$h}, [ $h ], [ ], $indent);
122 &save_directive($sub, [ ], [ $h ], $indent + 1);
125 foreach $g (&unique(@wasgin, @nowgin)) {
126 $was = &indexof($g, @wasgin) != -1;
127 $now = &indexof($g, @nowgin) != -1;
129 # per-group ACLs for new or updated groups
130 if ($was != $now && !&can('rw', \%access, $g)) {
131 &error("$text{'eacl_np'} $text{'eacl_pus'}");
134 # Move out of the subnet
135 &save_directive($sub, [ $g ], [ ], $indent);
136 &save_directive($par, [ ], [ $g ], $indent);
138 elsif ($now && !$was) {
139 # Move into the subnet (maybe from another subnet)
140 &save_directive($nowgpr{$g}, [ $g ], [ ], $indent);
141 &save_directive($sub, [ ], [ $g ], $indent + 1);
145 if (!$in{'delete'}) {
146 &error_setup($text{'ssub_failsave'});
147 for($i=0; defined($low = $in{"range_low_$i"}); $i++) {
149 $hi = $in{"range_hi_$i"}; $dyn = $in{"range_dyn_$i"};
150 &check_ipaddress($low) ||
151 &error("'$low' $text{'ssub_invalidipr'}");
152 !$hi || &check_ipaddress($hi) ||
153 &error("'$hi' $text{'ssub_invalidipr'}");
154 $rng = { 'name' => 'range',
155 'values' => [ ($dyn ? "dynamic-bootp" : ()),
156 $low, ($hi ? $hi : ()) ] };
159 &save_directive($sub, "range", \@rng, 1);
160 $sub->{'comment'} = $in{'desc'};
161 &parse_params($sub, 0);
163 if (!npar || $in{'assign'} > 0 && $npar->{'name'} ne "shared-network") {
164 &error($text{'sgroup_echanged'});
167 # save acl for new network
168 &save_dhcpd_acl('rw','sub',\%access,$in{'network'});
169 # Add to the end of the parent structure
170 &save_directive($npar, [ ], [ $sub ], $nindent);
172 elsif ($par eq $npar) {
173 # Update the subnet in the current parent
174 &save_directive($par, [ $sub ], [ $sub ], $nindent);
175 if ($in{'network'} ne $oldnetwork) {
177 &drop_dhcpd_acl('sub', \%access, $oldnetwork);
178 &save_dhcpd_acl('rw','sub',\%access,
184 if ($par->{'name'} eq "shared-network") {
185 @subnets = &find("subnet", $par->{'members'});
187 &error(&text('ssub_nosubnet', $par->{'values'}->[0]));
190 &save_directive($par, [ $sub ], [ ], 0);
191 &save_directive($npar, [ ], [ $sub ], $nindent);
198 if ($in{'hosts'} eq "" && $in{'groups'} eq "") {
199 &drop_dhcpd_acl('sub', \%access, $sub->{'values'}->[0]);
200 &save_directive($par, [ $sub ], [ ], 0);
204 &unlock_file($config{'dhcpd_conf'});
205 &redirect("confirm_delete.cgi?sidx=$in{'sidx'}&idx=$in{'idx'}"
210 &unlock_file($config{'dhcpd_conf'});
211 &webmin_log($in{'delete'} ? 'delete' : $in{'new'} ? 'create' : 'modify',
212 'subnet', "$sub->{'values'}->[0]/$sub->{'values'}->[2]", \%in);
214 &redirect($in{'ret'} eq "shared" ? "edit_shared.cgi?idx=$in{'sidx'}" : "");