3 # Update, create or delete a host
5 require './dhcpd-lib.pl';
6 require './params-lib.pl';
8 &lock_file($config{'dhcpd_conf'});
9 ($par, $host, $indent, $npar, $nindent) = get_branch('hst', $in{'new'});
12 %access = &get_module_acl();
13 &error_setup($text{'eacl_aviol'});
15 &error("$text{'eacl_np'} $text{'eacl_pdh'}")
16 if !&can('rw', \%access, $host, 1);
18 elsif ($in{'options'}) {
19 &error("$text{'eacl_np'} $text{'eacl_psh'}")
20 if !&can('r', \%access, $host);
23 &error("$text{'eacl_np'} $text{'eacl_pih'}")
24 unless &can('c', \%access, $host) &&
25 &can('rw', \%access, $par) &&
26 (!$npar || &can('rw', \%access, $npar));
29 &error("$text{'eacl_np'} $text{'eacl_puh'}")
30 unless &can('rw', \%access, $host) &&
31 (!$npar || &can('rw', \%access, $npar));
32 $oldname = $host->{'values'}->[0];
38 &error_setup($text{'shost_faildel'});
39 &save_directive($par, [ $host ], [ ], 0);
40 &drop_dhcpd_acl('hst', \%access, $host->{'values'}->[0]);
42 elsif ($in{'options'}) {
43 # Redirect to client options
44 &redirect("edit_options.cgi?sidx=$in{'sidx'}&uidx=$in{'uidx'}&gidx=$in{'gidx'}&idx=$in{'idx'}");
48 &error_setup($text{'shost_failsave'});
50 # Validate and save inputs
51 $in{'name'} =~ /^[a-z0-9\.\-]+$/i ||
52 &error("'$in{'name'}' $text{'shost_invalidhn'}");
53 $host->{'comment'} = $in{'desc'};
55 # Check for a hostname clash
56 if (($in{'new'} || $in{'name'} ne $host->{'values'}->[0]) &&
57 $access{'uniq_hst'}) {
58 foreach $h (&get_my_shared_network_hosts($npar)) {
59 &error("$text{'eacl_np'} $text{'eacl_uniq'}")
60 if (lc($h->{'values'}->[0]) eq lc($in{'name'}));
63 $host->{'values'} = [ $in{'name'} ];
65 if ($in{'hardware'}) {
66 # Check for hardware clash
67 $oldhard = $in{'new'} ? undef
68 : &find("hardware", $host->{'members'});
69 if ((!$oldhard || $in{'hardware'} ne $oldhard->{'values'}->[1])
70 && $access{'uniq_hst'}) {
71 foreach $h (&get_my_shared_network_hosts($npar)) {
72 $chard = &find("hardware", $h->{'members'});
73 &error("$text{'eacl_np'} $text{'eacl_uniqh'}")
74 if ($chard && lc($chard->{'values'}->[1]) eq lc($in{'hardware'}));
78 # Convert from Windows / Cisco formats
79 $in{'hardware'} =~ s/-/:/g;
80 if ($in{'hardware'} =~ /^([0-9a-f]{2})([0-9a-f]{2}).([0-9a-f]{2})([0-9a-f]{2}).([0-9a-f]{2})([0-9a-f]{2}).([0-9a-f]{2})([0-9a-f]{2})$/) {
81 $in{'hardware'} = "$1:$2:$3:$4:$5:$6";
83 $in{'hardware'} =~ /^([0-9a-f]{1,2}:)*[0-9a-f]{1,2}$/i ||
84 &error(&text('shost_invalidhwa', $in{'hardware'},
85 $in{'hardware_type'}) );
86 @hard = ( { 'name' => 'hardware',
87 'values' => [ $in{'hardware_type'},
88 $in{'hardware'} ] } );
90 &save_directive($host, 'hardware', \@hard);
92 if ($in{'fixed-address'}) {
94 $oldfixed = $in{'new'} ? undef
95 : &find("fixed-address", $host->{'members'});
97 $in{'fixed-address'} ne $oldfixed->{'values'}->[0])
98 && $access{'uniq_hst'}) {
99 foreach $h (&get_my_shared_network_hosts($npar)) {
100 $cfixed = &find("fixed-address",
102 &error("$text{'eacl_np'} $text{'eacl_uniqi'}")
103 if ($cfixed && lc($cfixed->{'values'}->[0]) eq lc($in{'fixed-address'}));
108 if ($in{'fixed-address'} !~ /^[\w\s\.\-,]+$/ ||
109 $in{'fixed-address'} =~ /(^|[\s,])[-_]/ ||
110 $in{'fixed-address'} =~ /\.([\s,\.]|$)/ ||
111 $in{'fixed-address'} =~ /(^|[\s,])\d+\.[\d\.]*[a-z_]/i) {
112 &error(&text('shost_invalidaddr', $in{'fixed-address'}));
114 @fixedip = split(/[,\s]+/, $in{'fixed-address'});
115 @fixed = ( { 'name' => 'fixed-address',
116 'values' => [ join(" , ", @fixedip) ] } );
118 &save_directive($host, 'fixed-address', \@fixed);
120 &parse_params($host);
122 @partypes = ( "", "shared-network", "subnet", "group" );
123 if (!$npar || $in{'assign'} > 0 && $npar->{'name'} ne $partypes[$in{'assign'}]) {
124 if ($in{'jsquirk'}) {
125 &error($text{'shost_invassign'});
128 &redirect("edit_host.cgi?assign=".$in{'assign'}.
129 "&idx=".$in{'idx'}."&gidx=".$in{'gidx'}.
130 "&uidx=".$in{'uidx'}."&sidx=".$in{'sidx'});
135 # save acl for new host
136 &save_dhcpd_acl('rw', 'hst', \%access, $in{'name'});
137 # Add to the end of the parent structure
138 &save_directive($npar, [ ], [ $host ], $nindent);
140 elsif ($par eq $npar) {
142 &save_directive($par, [ $host ], [ $host ], $indent);
143 if ($oldname ne $in{'name'}) {
144 &drop_dhcpd_acl('hst', \%access, $oldname);
145 &save_dhcpd_acl('rw', 'hst', \%access, $in{'name'});
150 &save_directive($par, [ $host ], [ ], 0);
151 &save_directive($npar, [ ], [ $host ], $nindent);
155 &unlock_file($config{'dhcpd_conf'});
156 &webmin_log($in{'delete'} ? 'delete' : $in{'new'} ? 'create' : 'modify',
157 'host', $host->{'values'}->[0], \%in);
158 if ($in{'ret'} eq "group") {
159 $retparms = "sidx=$in{'sidx'}&uidx=$in{'uidx'}&idx=$in{'gidx'}";
161 elsif ($in{'ret'} eq "subnet") {
162 $retparms = "sidx=$in{'sidx'}&idx=$in{'uidx'}";
164 elsif ($in{'ret'} eq "shared") {
165 $retparms = "idx=$in{'sidx'}";
168 &redirect($in{'ret'} ? "edit_$in{'ret'}.cgi?$retparms" : "");