]> git.proxmox.com Git - pve-firewall.git/blame - src/PVE/API2/Firewall/IPSet.pm
ipsets: catch zero-prefix entries
[pve-firewall.git] / src / PVE / API2 / Firewall / IPSet.pm
CommitLineData
009ee3ac
DM
1package PVE::API2::Firewall::IPSetBase;
2
3use strict;
4use warnings;
4a11bba5 5use PVE::Exception qw(raise raise_param_exc);
009ee3ac
DM
6use PVE::JSONSchema qw(get_standard_option);
7
8use PVE::Firewall;
9
10use base qw(PVE::RESTHandler);
11
12my $api_properties = {
13 cidr => {
14 description => "Network/IP specification in CIDR format.",
ae029a88 15 type => 'string', format => 'IPorCIDRorAlias',
009ee3ac 16 },
e74a87f5 17 name => get_standard_option('ipset-name'),
009ee3ac
DM
18 comment => {
19 type => 'string',
20 optional => 1,
21 },
22 nomatch => {
23 type => 'boolean',
24 optional => 1,
25 },
26};
27
28sub load_config {
29 my ($class, $param) = @_;
30
31 die "implement this in subclass";
1210ae94
DM
32
33 #return ($cluster_conf, $fw_conf, $ipset);
009ee3ac
DM
34}
35
1210ae94
DM
36sub save_config {
37 my ($class, $param, $fw_conf) = @_;
009ee3ac
DM
38
39 die "implement this in subclass";
40}
41
9f6845cf
DM
42sub rule_env {
43 my ($class, $param) = @_;
44
45 die "implement this in subclass";
46}
47
1210ae94
DM
48sub save_ipset {
49 my ($class, $param, $fw_conf, $ipset) = @_;
50
51 if (!defined($ipset)) {
52 delete $fw_conf->{ipset}->{$param->{name}};
53 } else {
54 $fw_conf->{ipset}->{$param->{name}} = $ipset;
55 }
56
57 $class->save_config($param, $fw_conf);
58}
59
009ee3ac
DM
60my $additional_param_hash = {};
61
62sub additional_parameters {
63 my ($class, $new_value) = @_;
64
65 if (defined($new_value)) {
66 $additional_param_hash->{$class} = $new_value;
67 }
68
69 # return a copy
70 my $copy = {};
71 my $org = $additional_param_hash->{$class} || {};
72 foreach my $p (keys %$org) { $copy->{$p} = $org->{$p}; }
73 return $copy;
74}
75
76sub register_get_ipset {
77 my ($class) = @_;
78
79 my $properties = $class->additional_parameters();
80
81 $properties->{name} = $api_properties->{name};
82
83 $class->register_method({
84 name => 'get_ipset',
85 path => '',
86 method => 'GET',
87 description => "List IPSet content",
9f6845cf 88 permissions => PVE::Firewall::rules_audit_permissions($class->rule_env()),
009ee3ac
DM
89 parameters => {
90 additionalProperties => 0,
91 properties => $properties,
92 },
93 returns => {
94 type => 'array',
95 items => {
96 type => "object",
97 properties => {
98 cidr => {
99 type => 'string',
100 },
101 comment => {
102 type => 'string',
103 optional => 1,
104 },
105 nomatch => {
106 type => 'boolean',
107 optional => 1,
d72c631c
DM
108 },
109 digest => get_standard_option('pve-config-digest', { optional => 0} ),
009ee3ac
DM
110 },
111 },
112 links => [ { rel => 'child', href => "{cidr}" } ],
113 },
114 code => sub {
115 my ($param) = @_;
116
1210ae94 117 my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
009ee3ac 118
5d38d64f 119 return PVE::Firewall::copy_list_with_digest($ipset);
009ee3ac
DM
120 }});
121}
122
1210ae94
DM
123sub register_delete_ipset {
124 my ($class) = @_;
125
126 my $properties = $class->additional_parameters();
127
128 $properties->{name} = get_standard_option('ipset-name');
129
130 $class->register_method({
131 name => 'delete_ipset',
132 path => '',
133 method => 'DELETE',
134 description => "Delete IPSet",
135 protected => 1,
9f6845cf 136 permissions => PVE::Firewall::rules_modify_permissions($class->rule_env()),
1210ae94
DM
137 parameters => {
138 additionalProperties => 0,
139 properties => $properties,
140 },
141 returns => { type => 'null' },
142 code => sub {
143 my ($param) = @_;
144
145 my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
146
147 die "IPSet '$param->{name}' is not empty\n"
148 if scalar(@$ipset);
149
150 $class->save_ipset($param, $fw_conf, undef);
151
152 return undef;
153 }});
154}
155
a33c74f6 156sub register_create_ip {
009ee3ac
DM
157 my ($class) = @_;
158
159 my $properties = $class->additional_parameters();
160
161 $properties->{name} = $api_properties->{name};
162 $properties->{cidr} = $api_properties->{cidr};
163 $properties->{nomatch} = $api_properties->{nomatch};
164 $properties->{comment} = $api_properties->{comment};
d72c631c 165
009ee3ac 166 $class->register_method({
a33c74f6 167 name => 'create_ip',
009ee3ac
DM
168 path => '',
169 method => 'POST',
170 description => "Add IP or Network to IPSet.",
171 protected => 1,
9f6845cf 172 permissions => PVE::Firewall::rules_modify_permissions($class->rule_env()),
009ee3ac
DM
173 parameters => {
174 additionalProperties => 0,
175 properties => $properties,
176 },
177 returns => { type => "null" },
178 code => sub {
179 my ($param) = @_;
180
1210ae94 181 my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
009ee3ac 182
4a11bba5
DM
183 my $cidr = $param->{cidr};
184
185 foreach my $entry (@$ipset) {
186 raise_param_exc({ cidr => "address '$cidr' already exists" })
187 if $entry->{cidr} eq $cidr;
188 }
189
6c221576 190 # make sure alias exists (if $cidr is an alias)
f9792937
DM
191 PVE::Firewall::resolve_alias($cluster_conf, $fw_conf, $cidr)
192 if $cidr =~ m/^${PVE::Firewall::ip_alias_pattern}$/;
7c619bbb 193
4a11bba5 194 my $data = { cidr => $cidr };
7c619bbb 195
009ee3ac
DM
196 $data->{nomatch} = 1 if $param->{nomatch};
197 $data->{comment} = $param->{comment} if $param->{comment};
198
009ee3ac
DM
199 unshift @$ipset, $data;
200
201 $class->save_ipset($param, $fw_conf, $ipset);
202
203 return undef;
204 }});
205}
206
a33c74f6
DM
207sub register_read_ip {
208 my ($class) = @_;
209
210 my $properties = $class->additional_parameters();
211
212 $properties->{name} = $api_properties->{name};
213 $properties->{cidr} = $api_properties->{cidr};
214
215 $class->register_method({
216 name => 'read_ip',
217 path => '{cidr}',
218 method => 'GET',
219 description => "Read IP or Network settings from IPSet.",
9f6845cf 220 permissions => PVE::Firewall::rules_audit_permissions($class->rule_env()),
a33c74f6
DM
221 protected => 1,
222 parameters => {
223 additionalProperties => 0,
224 properties => $properties,
225 },
226 returns => { type => "object" },
227 code => sub {
228 my ($param) = @_;
229
1210ae94 230 my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
a33c74f6 231
5d38d64f
DM
232 my $list = PVE::Firewall::copy_list_with_digest($ipset);
233
234 foreach my $entry (@$list) {
d72c631c 235 if ($entry->{cidr} eq $param->{cidr}) {
d72c631c
DM
236 return $entry;
237 }
a33c74f6
DM
238 }
239
240 raise_param_exc({ cidr => "no such IP/Network" });
241 }});
242}
243
244sub register_update_ip {
245 my ($class) = @_;
246
247 my $properties = $class->additional_parameters();
248
249 $properties->{name} = $api_properties->{name};
250 $properties->{cidr} = $api_properties->{cidr};
251 $properties->{nomatch} = $api_properties->{nomatch};
252 $properties->{comment} = $api_properties->{comment};
d72c631c
DM
253 $properties->{digest} = get_standard_option('pve-config-digest');
254
a33c74f6
DM
255 $class->register_method({
256 name => 'update_ip',
257 path => '{cidr}',
258 method => 'PUT',
259 description => "Update IP or Network settings",
260 protected => 1,
9f6845cf 261 permissions => PVE::Firewall::rules_modify_permissions($class->rule_env()),
a33c74f6
DM
262 parameters => {
263 additionalProperties => 0,
264 properties => $properties,
265 },
266 returns => { type => "null" },
267 code => sub {
268 my ($param) = @_;
269
1210ae94 270 my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
a33c74f6 271
5d38d64f
DM
272 my (undef, $digest) = PVE::Firewall::copy_list_with_digest($ipset);
273 PVE::Tools::assert_if_modified($digest, $param->{digest});
d72c631c 274
a33c74f6
DM
275 foreach my $entry (@$ipset) {
276 if($entry->{cidr} eq $param->{cidr}) {
277 $entry->{nomatch} = $param->{nomatch};
278 $entry->{comment} = $param->{comment};
279 $class->save_ipset($param, $fw_conf, $ipset);
280 return;
281 }
282 }
283
284 raise_param_exc({ cidr => "no such IP/Network" });
285 }});
286}
287
288sub register_delete_ip {
009ee3ac
DM
289 my ($class) = @_;
290
291 my $properties = $class->additional_parameters();
292
293 $properties->{name} = $api_properties->{name};
294 $properties->{cidr} = $api_properties->{cidr};
d72c631c
DM
295 $properties->{digest} = get_standard_option('pve-config-digest');
296
009ee3ac
DM
297 $class->register_method({
298 name => 'remove_ip',
299 path => '{cidr}',
300 method => 'DELETE',
301 description => "Remove IP or Network from IPSet.",
302 protected => 1,
9f6845cf 303 permissions => PVE::Firewall::rules_modify_permissions($class->rule_env()),
009ee3ac
DM
304 parameters => {
305 additionalProperties => 0,
306 properties => $properties,
307 },
308 returns => { type => "null" },
309 code => sub {
310 my ($param) = @_;
311
1210ae94 312 my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
009ee3ac 313
5d38d64f
DM
314 my (undef, $digest) = PVE::Firewall::copy_list_with_digest($ipset);
315 PVE::Tools::assert_if_modified($digest, $param->{digest});
d72c631c 316
4a11bba5
DM
317 my $new = [];
318
319 foreach my $entry (@$ipset) {
320 push @$new, $entry if $entry->{cidr} ne $param->{cidr};
321 }
009ee3ac 322
4a11bba5
DM
323 $class->save_ipset($param, $fw_conf, $new);
324
009ee3ac
DM
325 return undef;
326 }});
327}
328
329sub register_handlers {
330 my ($class) = @_;
331
1210ae94 332 $class->register_delete_ipset();
009ee3ac 333 $class->register_get_ipset();
a33c74f6
DM
334 $class->register_create_ip();
335 $class->register_read_ip();
336 $class->register_update_ip();
337 $class->register_delete_ip();
009ee3ac
DM
338}
339
340package PVE::API2::Firewall::ClusterIPset;
341
342use strict;
343use warnings;
344
345use base qw(PVE::API2::Firewall::IPSetBase);
346
9f6845cf
DM
347sub rule_env {
348 my ($class, $param) = @_;
349
350 return 'cluster';
351}
352
009ee3ac
DM
353sub load_config {
354 my ($class, $param) = @_;
355
356 my $fw_conf = PVE::Firewall::load_clusterfw_conf();
357 my $ipset = $fw_conf->{ipset}->{$param->{name}};
358 die "no such IPSet '$param->{name}'\n" if !defined($ipset);
359
1210ae94 360 return (undef, $fw_conf, $ipset);
009ee3ac
DM
361}
362
1210ae94
DM
363sub save_config {
364 my ($class, $param, $fw_conf) = @_;
009ee3ac 365
009ee3ac
DM
366 PVE::Firewall::save_clusterfw_conf($fw_conf);
367}
368
369__PACKAGE__->register_handlers();
370
1210ae94
DM
371package PVE::API2::Firewall::VMIPset;
372
373use strict;
374use warnings;
375use PVE::JSONSchema qw(get_standard_option);
376
377use base qw(PVE::API2::Firewall::IPSetBase);
378
9f6845cf
DM
379sub rule_env {
380 my ($class, $param) = @_;
381
382 return 'vm';
383}
384
1210ae94
DM
385__PACKAGE__->additional_parameters({
386 node => get_standard_option('pve-node'),
387 vmid => get_standard_option('pve-vmid'),
388});
389
390sub load_config {
391 my ($class, $param) = @_;
392
393 my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
394 my $fw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, 'vm', $param->{vmid});
395 my $ipset = $fw_conf->{ipset}->{$param->{name}};
396 die "no such IPSet '$param->{name}'\n" if !defined($ipset);
397
398 return ($cluster_conf, $fw_conf, $ipset);
399}
400
401sub save_config {
402 my ($class, $param, $fw_conf) = @_;
403
404 PVE::Firewall::save_vmfw_conf($param->{vmid}, $fw_conf);
405}
406
407__PACKAGE__->register_handlers();
408
409package PVE::API2::Firewall::CTIPset;
410
411use strict;
412use warnings;
413use PVE::JSONSchema qw(get_standard_option);
414
415use base qw(PVE::API2::Firewall::IPSetBase);
416
9f6845cf
DM
417sub rule_env {
418 my ($class, $param) = @_;
419
420 return 'ct';
421}
422
1210ae94
DM
423__PACKAGE__->additional_parameters({
424 node => get_standard_option('pve-node'),
425 vmid => get_standard_option('pve-vmid'),
426});
427
428sub load_config {
429 my ($class, $param) = @_;
430
431 my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
432 my $fw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, 'ct', $param->{vmid});
433 my $ipset = $fw_conf->{ipset}->{$param->{name}};
434 die "no such IPSet '$param->{name}'\n" if !defined($ipset);
435
436 return ($cluster_conf, $fw_conf, $ipset);
437}
438
439sub save_config {
440 my ($class, $param, $fw_conf) = @_;
441
442 PVE::Firewall::save_vmfw_conf($param->{vmid}, $fw_conf);
443}
444
445__PACKAGE__->register_handlers();
446
c85c87f9
DM
447package PVE::API2::Firewall::BaseIPSetList;
448
449use strict;
450use warnings;
e74a87f5 451use PVE::JSONSchema qw(get_standard_option);
c85c87f9 452use PVE::Exception qw(raise_param_exc);
e74a87f5 453use PVE::Firewall;
c85c87f9
DM
454
455use base qw(PVE::RESTHandler);
456
1210ae94
DM
457sub load_config {
458 my ($class, $param) = @_;
459
460 die "implement this in subclass";
461
462 #return ($cluster_conf, $fw_conf);
463}
464
465sub save_config {
466 my ($class, $param, $fw_conf) = @_;
467
468 die "implement this in subclass";
469}
470
9f6845cf
DM
471sub rule_env {
472 my ($class, $param) = @_;
473
474 die "implement this in subclass";
475}
476
1210ae94
DM
477my $additional_param_hash_list = {};
478
479sub additional_parameters {
480 my ($class, $new_value) = @_;
481
482 if (defined($new_value)) {
483 $additional_param_hash_list->{$class} = $new_value;
484 }
485
486 # return a copy
487 my $copy = {};
488 my $org = $additional_param_hash_list->{$class} || {};
489 foreach my $p (keys %$org) { $copy->{$p} = $org->{$p}; }
490 return $copy;
491}
492
5d38d64f
DM
493my $get_ipset_list = sub {
494 my ($fw_conf) = @_;
495
496 my $res = [];
497 foreach my $name (keys %{$fw_conf->{ipset}}) {
498 my $data = {
499 name => $name,
500 };
501 if (my $comment = $fw_conf->{ipset_comments}->{$name}) {
502 $data->{comment} = $comment;
503 }
504 push @$res, $data;
505 }
506
507 my ($list, $digest) = PVE::Firewall::copy_list_with_digest($res);
508
509 return wantarray ? ($list, $digest) : $list;
510};
511
c85c87f9
DM
512sub register_index {
513 my ($class) = @_;
514
1210ae94
DM
515 my $properties = $class->additional_parameters();
516
c85c87f9
DM
517 $class->register_method({
518 name => 'ipset_index',
519 path => '',
520 method => 'GET',
521 description => "List IPSets",
9f6845cf 522 permissions => PVE::Firewall::rules_audit_permissions($class->rule_env()),
c85c87f9
DM
523 parameters => {
524 additionalProperties => 0,
1210ae94 525 properties => $properties,
c85c87f9
DM
526 },
527 returns => {
528 type => 'array',
529 items => {
530 type => "object",
531 properties => {
e74a87f5 532 name => get_standard_option('ipset-name'),
d72c631c
DM
533 digest => get_standard_option('pve-config-digest', { optional => 0} ),
534 comment => {
535 type => 'string',
536 optional => 1,
537 }
c85c87f9
DM
538 },
539 },
540 links => [ { rel => 'child', href => "{name}" } ],
541 },
542 code => sub {
543 my ($param) = @_;
544
1210ae94 545 my ($cluster_conf, $fw_conf) = $class->load_config($param);
c85c87f9 546
5d38d64f 547 return &$get_ipset_list($fw_conf);
c85c87f9
DM
548 }});
549}
550
551sub register_create {
552 my ($class) = @_;
553
1210ae94
DM
554 my $properties = $class->additional_parameters();
555
556 $properties->{name} = get_standard_option('ipset-name');
557
558 $properties->{comment} = { type => 'string', optional => 1 };
559
560 $properties->{digest} = get_standard_option('pve-config-digest');
561
562 $properties->{rename} = get_standard_option('ipset-name', {
563 description => "Rename an existing IPSet. You can set 'rename' to the same value as 'name' to update the 'comment' of an existing IPSet.",
564 optional => 1 });
565
c85c87f9
DM
566 $class->register_method({
567 name => 'create_ipset',
568 path => '',
569 method => 'POST',
570 description => "Create new IPSet",
571 protected => 1,
9f6845cf 572 permissions => PVE::Firewall::rules_modify_permissions($class->rule_env()),
c85c87f9
DM
573 parameters => {
574 additionalProperties => 0,
1210ae94 575 properties => $properties,
c85c87f9
DM
576 },
577 returns => { type => 'null' },
578 code => sub {
579 my ($param) = @_;
580
1210ae94 581 my ($cluster_conf, $fw_conf) = $class->load_config($param);
c85c87f9 582
bc374ca7 583 if ($param->{rename}) {
5d38d64f
DM
584 my (undef, $digest) = &$get_ipset_list($fw_conf);
585 PVE::Tools::assert_if_modified($digest, $param->{digest});
586
bc374ca7
DM
587 raise_param_exc({ name => "IPSet '$param->{rename}' does not exists" })
588 if !$fw_conf->{ipset}->{$param->{rename}};
5d38d64f 589
5da1a229
DC
590 # prevent overwriting existing ipset
591 raise_param_exc({ name => "IPSet '$param->{name}' does already exist"})
592 if $fw_conf->{ipset}->{$param->{name}} &&
593 $param->{name} ne $param->{rename};
594
bc374ca7
DM
595 my $data = delete $fw_conf->{ipset}->{$param->{rename}};
596 $fw_conf->{ipset}->{$param->{name}} = $data;
d72c631c
DM
597 if (my $comment = delete $fw_conf->{ipset_comments}->{$param->{rename}}) {
598 $fw_conf->{ipset_comments}->{$param->{name}} = $comment;
599 }
600 $fw_conf->{ipset_comments}->{$param->{name}} = $param->{comment} if defined($param->{comment});
5d38d64f
DM
601 } else {
602 foreach my $name (keys %{$fw_conf->{ipset}}) {
603 raise_param_exc({ name => "IPSet '$name' already exists" })
604 if $name eq $param->{name};
605 }
606
bc374ca7 607 $fw_conf->{ipset}->{$param->{name}} = [];
d72c631c 608 $fw_conf->{ipset_comments}->{$param->{name}} = $param->{comment} if defined($param->{comment});
bc374ca7
DM
609 }
610
1210ae94 611 $class->save_config($param, $fw_conf);
c85c87f9
DM
612
613 return undef;
614 }});
615}
616
1210ae94 617sub register_handlers {
c85c87f9
DM
618 my ($class) = @_;
619
1210ae94
DM
620 $class->register_index();
621 $class->register_create();
622}
c85c87f9 623
1210ae94 624package PVE::API2::Firewall::ClusterIPSetList;
c85c87f9 625
1210ae94
DM
626use strict;
627use warnings;
628use PVE::Firewall;
5d38d64f 629
1210ae94
DM
630use base qw(PVE::API2::Firewall::BaseIPSetList);
631
9f6845cf
DM
632sub rule_env {
633 my ($class, $param) = @_;
634
635 return 'cluster';
636}
637
1210ae94
DM
638sub load_config {
639 my ($class, $param) = @_;
640
641 my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
642 return (undef, $cluster_conf);
643}
c85c87f9 644
1210ae94
DM
645sub save_config {
646 my ($class, $param, $fw_conf) = @_;
c85c87f9 647
1210ae94
DM
648 PVE::Firewall::save_clusterfw_conf($fw_conf);
649}
c85c87f9 650
1210ae94
DM
651__PACKAGE__->register_handlers();
652
653__PACKAGE__->register_method ({
654 subclass => "PVE::API2::Firewall::ClusterIPset",
655 path => '{name}',
656 # set fragment delimiter (no subdirs) - we need that, because CIDR address contain a slash '/'
657 fragmentDelimiter => '',
658});
659
660package PVE::API2::Firewall::VMIPSetList;
661
662use strict;
663use warnings;
664use PVE::JSONSchema qw(get_standard_option);
665use PVE::Firewall;
666
667use base qw(PVE::API2::Firewall::BaseIPSetList);
668
669__PACKAGE__->additional_parameters({
670 node => get_standard_option('pve-node'),
671 vmid => get_standard_option('pve-vmid'),
672});
673
9f6845cf
DM
674sub rule_env {
675 my ($class, $param) = @_;
676
677 return 'vm';
678}
679
1210ae94
DM
680sub load_config {
681 my ($class, $param) = @_;
682
683 my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
684 my $fw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, 'vm', $param->{vmid});
685 return ($cluster_conf, $fw_conf);
c85c87f9
DM
686}
687
1210ae94
DM
688sub save_config {
689 my ($class, $param, $fw_conf) = @_;
c85c87f9 690
1210ae94 691 PVE::Firewall::save_vmfw_conf($param->{vmid}, $fw_conf);
c85c87f9
DM
692}
693
1210ae94
DM
694__PACKAGE__->register_handlers();
695
696__PACKAGE__->register_method ({
697 subclass => "PVE::API2::Firewall::VMIPset",
698 path => '{name}',
699 # set fragment delimiter (no subdirs) - we need that, because CIDR address contain a slash '/'
700 fragmentDelimiter => '',
701});
702
703package PVE::API2::Firewall::CTIPSetList;
c85c87f9
DM
704
705use strict;
706use warnings;
1210ae94 707use PVE::JSONSchema qw(get_standard_option);
c85c87f9
DM
708use PVE::Firewall;
709
710use base qw(PVE::API2::Firewall::BaseIPSetList);
711
1210ae94
DM
712__PACKAGE__->additional_parameters({
713 node => get_standard_option('pve-node'),
714 vmid => get_standard_option('pve-vmid'),
715});
716
9f6845cf
DM
717sub rule_env {
718 my ($class, $param) = @_;
719
720 return 'ct';
721}
722
c85c87f9 723sub load_config {
1210ae94 724 my ($class, $param) = @_;
c85c87f9 725
1210ae94
DM
726 my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
727 my $fw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, 'ct', $param->{vmid});
728 return ($cluster_conf, $fw_conf);
c85c87f9
DM
729}
730
731sub save_config {
1210ae94 732 my ($class, $param, $fw_conf) = @_;
c85c87f9 733
1210ae94 734 PVE::Firewall::save_vmfw_conf($param->{vmid}, $fw_conf);
c85c87f9
DM
735}
736
737__PACKAGE__->register_handlers();
738
739__PACKAGE__->register_method ({
1210ae94 740 subclass => "PVE::API2::Firewall::CTIPset",
c85c87f9
DM
741 path => '{name}',
742 # set fragment delimiter (no subdirs) - we need that, because CIDR address contain a slash '/'
743 fragmentDelimiter => '',
744});
745
009ee3ac 7461;