return $etc_services;
}
-my $etc_protocols;
-
-sub get_etc_protocols {
- return $etc_protocols if $etc_protocols;
-
- my $filename = "/etc/protocols";
+sub parse_protocol_file {
+ my ($filename) = @_;
my $fh = IO::File->new($filename, O_RDONLY);
if (!$fh) {
close($fh);
+ return $protocols;
+}
+
+my $etc_protocols;
+
+sub get_etc_protocols {
+ return $etc_protocols if $etc_protocols;
+
+ my $protocols = parse_protocol_file('/etc/protocols');
+
# add special case for ICMP v6
$protocols->{byid}->{icmpv6}->{name} = "icmpv6";
$protocols->{byname}->{icmpv6} = $protocols->{byid}->{icmpv6};
my $add_dport = sub {
return if !$rule->{dport};
+
if ($proto eq 'icmp') {
# Note: we use dport to store --icmp-type
die "unknown icmp-type '$rule->{dport}'\n"
my $add_sport = sub {
return if !$rule->{sport};
+
die "protocol $proto does not have ports\n"
if !$PROTOCOLS_WITH_PORTS->{$proto};
if ($multisport) {
}
};
+ # order matters - single port before multiport!
$add_dport->() if $multisport;
$add_sport->();
$add_dport->() if !$multisport;