Skip to content

Commit 7eaddee

Browse files
authored
Merge pull request #17 from MEschenbacher/icmp-type
Add match extension for icmp and icmp6
2 parents fd02469 + 4bd1313 commit 7eaddee

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed

match_modules.go

+106
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ func (p *Parser) parseMatch(ms *[]Match) (state, error) {
3030
s, err = p.parseStatistic(&m.Flags)
3131
case "multiport":
3232
s, err = p.parseMultiport(&m.Flags)
33+
case "icmp":
34+
s, err = p.parseIcmp(&m.Flags)
35+
case "icmp6":
36+
s, err = p.parseIcmp6(&m.Flags)
3337
default:
3438
if _, ok := matchModules[lit]; ok {
3539
return sError, fmt.Errorf("match modules %q is not implemented", lit)
@@ -529,3 +533,105 @@ func (p *Parser) parseComment(f *map[string]Flag) (state, error) {
529533
}
530534
return sStart, nil
531535
}
536+
537+
func (p *Parser) parseIcmp(f *map[string]Flag) (state, error) {
538+
s := sStart
539+
for tok, lit := p.scanIgnoreWhitespace(); tok != EOF; tok, lit = p.scanIgnoreWhitespace() {
540+
for nextValue := false; !nextValue; {
541+
nextValue = true
542+
switch s {
543+
case sStart:
544+
switch tok {
545+
case NOT:
546+
s = sINotF
547+
case FLAG:
548+
s = sIF
549+
nextValue = false
550+
default:
551+
return sError, fmt.Errorf("unexpected token %q, expected flag, or \"!\"", lit)
552+
}
553+
case sINotF:
554+
switch {
555+
case lit == "--icmp-type":
556+
_, lit := p.scanIgnoreWhitespace()
557+
(*f)["icmp-type"] = Flag{
558+
Not: true,
559+
Values: []string{lit},
560+
}
561+
s = sStart
562+
default:
563+
p.unscan(1)
564+
return sNot, nil
565+
}
566+
case sIF:
567+
switch {
568+
case lit == "--icmp-type":
569+
_, lit := p.scanIgnoreWhitespace()
570+
(*f)["icmp-type"] = Flag{
571+
Values: []string{lit},
572+
}
573+
s = sStart
574+
default:
575+
// The end of the match statement is reached.
576+
p.unscan(1)
577+
return sStart, nil
578+
}
579+
580+
default:
581+
return sStart, errors.New("unexpected error parsing match extension")
582+
}
583+
}
584+
}
585+
return sStart, nil
586+
}
587+
588+
func (p *Parser) parseIcmp6(f *map[string]Flag) (state, error) {
589+
s := sStart
590+
for tok, lit := p.scanIgnoreWhitespace(); tok != EOF; tok, lit = p.scanIgnoreWhitespace() {
591+
for nextValue := false; !nextValue; {
592+
nextValue = true
593+
switch s {
594+
case sStart:
595+
switch tok {
596+
case NOT:
597+
s = sINotF
598+
case FLAG:
599+
s = sIF
600+
nextValue = false
601+
default:
602+
return sError, fmt.Errorf("unexpected token %q, expected flag, or \"!\"", lit)
603+
}
604+
case sINotF:
605+
switch {
606+
case lit == "--icmpv6-type":
607+
_, lit := p.scanIgnoreWhitespace()
608+
(*f)["icmpv6-type"] = Flag{
609+
Not: true,
610+
Values: []string{lit},
611+
}
612+
s = sStart
613+
default:
614+
p.unscan(1)
615+
return sNot, nil
616+
}
617+
case sIF:
618+
switch {
619+
case lit == "--icmpv6-type":
620+
_, lit := p.scanIgnoreWhitespace()
621+
(*f)["icmpv6-type"] = Flag{
622+
Values: []string{lit},
623+
}
624+
s = sStart
625+
default:
626+
// The end of the match statement is reached.
627+
p.unscan(1)
628+
return sStart, nil
629+
}
630+
631+
default:
632+
return sStart, errors.New("unexpected error parsing match extension")
633+
}
634+
}
635+
}
636+
return sStart, nil
637+
}

parser_test.go

+40
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,46 @@ func TestParser_Parse(t *testing.T) {
605605
},
606606
err: nil,
607607
},
608+
{
609+
name: "parse rule with icmp type",
610+
s: "-A foo -p icmp -m icmp --icmp-type 11",
611+
r: Rule{
612+
Chain: "foo",
613+
Protocol: &StringPair{
614+
Not: false,
615+
Value: "icmp",
616+
},
617+
Matches: []Match{
618+
{
619+
Type: "icmp",
620+
Flags: map[string]Flag{
621+
"icmp-type": {Values: []string{"11"}},
622+
},
623+
},
624+
},
625+
},
626+
err: nil,
627+
},
628+
{
629+
name: "parse rule with icmp type",
630+
s: "-A foo -p ipv6-icmp -m icmp6 --icmpv6-type 11",
631+
r: Rule{
632+
Chain: "foo",
633+
Protocol: &StringPair{
634+
Not: false,
635+
Value: "ipv6-icmp",
636+
},
637+
Matches: []Match{
638+
{
639+
Type: "icmp6",
640+
Flags: map[string]Flag{
641+
"icmpv6-type": {Values: []string{"11"}},
642+
},
643+
},
644+
},
645+
},
646+
err: nil,
647+
},
608648
{
609649
name: "parse rule with match expression tcp and a lot of flags and overwriting",
610650
s: "-A foo -m tcp --tcp-flags SYN,FIN ACK --sport 1010 ! --dport=1000:1010 --syn! --syn ! --tcp-option 1 ! -f ",

0 commit comments

Comments
 (0)