Handle hostnames with upper-case letters
[webmin.git] / ipfilter / save_nat.cgi
1 #!/usr/local/bin/perl
2 # Update one NAT rule
3
4 require './ipfilter-lib.pl';
5 &ReadParse();
6 $rules = &get_ipnat_config();
7 if (!$in{'new'}) {
8         # Get the rule
9         $rule = $rules->[$in{'idx'}];
10         }
11 else {
12         $rule = { 'file' => $config{'ipnat_conf'},
13                   'type' => 'ipnat' };
14         }
15
16 if ($in{'delete'}) {
17         # Just deleting
18         &lock_file($rule->{'file'});
19         &delete_rule($rule);
20         &flush_file_lines();
21         &unlock_file($rule->{'file'});
22         &webmin_log("delete", "nat", undef, $rule);
23         &redirect("");
24         exit;
25         }
26
27 # Validate and store inputs, starting with action
28 &error_setup($text{'nat_err'});
29 $rule->{'cmt'} = $in{'cmt'};
30 $rule->{'active'} = $in{'active'};
31 $rule->{'action'} = $in{'action'};
32
33 if ($rule->{'action'} ne 'rdr') {
34         # Parse source options
35         $rule->{'iface'} = &parse_interface_choice("iface", $text{'nat_eiface'});
36         if ($in{'frommode'} == 0) {
37                 delete($rule->{'from'});
38                 &parse_ipmask_input("from");
39                 }
40         else {
41                 $in{'action'} eq 'map-block' && &error($text{'nat_emapblock1'});
42                 $rule->{'from'} = 1;
43                 &parse_object_input($rule, "from");
44                 &parse_object_input($rule, "fromto");
45                 }
46
47         # Parse destination
48         delete($rule->{'tostart'});
49         if ($in{'tomode'} == 0) {
50                 &parse_ipmask_input("to");
51                 }
52         elsif ($in{'tomode'} == 2) {
53                 $rule->{'toip'} = '0.0.0.0';
54                 $rule->{'tomask'} = 32;
55                 }
56         else {
57                 $in{'action'} eq 'map-block' && &error($text{'nat_emapblock2'});
58                 &check_ipaddress($in{'tostart'}) ||
59                         &error($text{'nat_etostart'});
60                 &check_ipaddress($in{'toend'}) ||
61                         &error($text{'nat_etoend'});
62                 $rule->{'tostart'} = $in{'tostart'};
63                 $rule->{'toend'} = $in{'toend'};
64                 }
65
66         # Parse port mapping
67         if ($in{'portmapmode'} == 0) {
68                 delete($rule->{'portmap'});
69                 }
70         else {
71                 $rule->{'portmap'} = $in{'portmap'};
72                 if ($in{'portmapnoauto'}) {
73                         $rule->{'portauto'} = 0;
74                         &valid_port($in{'portmapfrom'}) ||
75                                 &error($text{'nat_eportmapfrom'});
76                         &valid_port($in{'portmapto'}) ||
77                                 &error($text{'nat_eportmapto'});
78                         $rule->{'portmapfrom'} = $in{'portmapfrom'};
79                         $rule->{'portmapto'} = $in{'portmapto'};
80                         }
81                 else {
82                         $rule->{'portauto'} = 1;
83                         }
84                 }
85
86         # Parse application proxy
87         if ($in{'proxymode'} == 0) {
88                 delete($rule->{'proxyport'});
89                 }
90         else {
91                 &parse_proxy_input("proxy");
92                 }
93
94         # Parse other options
95         if ($in{'proto'}) {
96                 $rule->{'proto'} = $in{'protoproto'};
97                 }
98         else {
99                 delete($rule->{'proto'});
100                 }
101         $rule->{'frag'} = $in{'frag'};
102         if ($in{'mssclamp'}) {
103                 $in{'mss'} =~ /^\d+$/ || &error($text{'nat_emss'});
104                 $rule->{'mssclamp'} = $in{'mss'};
105                 }
106         else {
107                 delete($rule->{'mssclamp'});
108                 }
109         if ($in{'oproxy'}) {
110                 &parse_proxy_input("oproxy");
111                 }
112         else {
113                 delete($rule->{'oproxyport'});
114                 }
115         }
116 else {
117         # Validate and store redirect inputs
118         $rule->{'iface'} = &parse_interface_choice("iface", $text{'nat_eiface'});
119
120         # Save redirect address
121         &parse_ipmask_input("from");
122
123         # Save destination ports
124         if ($in{'dportsmode'} == 0) {
125                 &valid_port($in{'dport'}) || &error($text{'nat_edport'});
126                 $rule->{'dport1'} = $in{'dport'};
127                 delete($rule->{'dport2'});
128                 }
129         else {
130                 &valid_port($in{'dport1'}) || &error($text{'nat_edport1'});
131                 &valid_port($in{'dport2'}) || &error($text{'nat_edport2'});
132                 $rule->{'dport1'} = $in{'dport1'};
133                 $rule->{'dport2'} = $in{'dport2'};
134                 }
135
136         # Save protocol
137         $rule->{'rdrproto'} = $in{'rdrproto'};
138
139         # Save redirect IPs
140         @ips = split(/\s+/, $in{'rdrip'});
141         foreach $ip (@ips) {
142                 &check_ipaddress($ip) || &error(&text('net_erdrip', $ip));
143                 }
144         @ips || &error($text{'nat_erdrips'});
145         $rule->{'rdrip'} = \@ips;
146
147         # Save redirect port
148         &valid_port($in{'rdrport'}) || &error($text{'nat_erdrport'});
149         $rule->{'rdrport'} = $in{'rdrport'};
150
151         # Save options
152         $rule->{'round-robin'} = $in{'round-robin'};
153         $rule->{'frag'} = $in{'frag'};
154         if ($in{'mssclamp'}) {
155                 $in{'mss'} =~ /^\d+$/ || &error($text{'nat_emss'});
156                 $rule->{'mssclamp'} = $in{'mss'};
157                 }
158         else {
159                 delete($rule->{'mssclamp'});
160                 }
161         }
162
163 &lock_file($rule->{'file'});
164 if ($in{'new'}) {
165         if ($in{'before'} ne '') {
166                 # Insert before some rule
167                 $before = $rules->[$in{'before'}];
168                 &insert_rule($rule, $before);
169                 }
170         elsif ($in{'after'} ne '') {
171                 if ($in{'after'} == @$rules - 1) {
172                         &create_rule($rule);    # at end anyway
173                         }
174                 else {
175                         # Insert after some rule
176                         $before = $rules->[$in{'after'}+1];
177                         &insert_rule($rule, $before);
178                         }
179                 }
180         else {
181                 # Append to end
182                 &create_rule($rule);
183                 }
184         }
185 else {
186         &modify_rule($rule);
187         }
188 &flush_file_lines();
189 &unlock_file($rule->{'file'});
190 &copy_to_cluster();
191 &webmin_log($in{'new'} ? "create" : "modify", "nat", undef, $rule);
192
193 &redirect("");
194
195 # parse_ipmask_input(prefix)
196 sub parse_ipmask_input
197 {
198 local ($pfx) = @_;
199 &check_ipaddress($in{$pfx."ip"}) || &error($text{'nat_e'.$pfx.'ip'});
200 &check_ipaddress($in{$pfx."mask"}) ||
201     $in{$pfx."mask"} =~ /^\d+$/ &&
202     $in{$pfx."mask"} >= 0 && $in{$pfx."mask"} <= 32 ||
203         &error($text{'nat_e'.$pfx.'ip'});
204 $rule->{$pfx."ip"} = $in{$pfx."ip"};
205 $rule->{$pfx."mask"} = $in{$pfx."mask"};
206 }
207
208 sub parse_proxy_input
209 {
210 local ($pfx) = @_;
211 &valid_port($in{$pfx."port"}) || &error($text{'nat_e'.$pfx.'port'});
212 &valid_port($in{$pfx."name"}) || &error($text{'nat_e'.$pfx.'name'});
213 $rule->{$pfx."port"} = $in{$pfx."port"};
214 $rule->{$pfx."name"} = $in{$pfx."name"};
215 $rule->{$pfx."proto"} = $in{$pfx."proto"};
216 }