Skip to content

Commit

Permalink
Merge pull request #8 from linka-cloud/multiport
Browse files Browse the repository at this point in the history
modules: add basic multiport support
  • Loading branch information
leonnicolas authored May 20, 2022
2 parents f11aa2d + e08704c commit 275b7c9
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 0 deletions.
90 changes: 90 additions & 0 deletions match_modules.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ func (p *Parser) parseMatch(ms *[]Match) (state, error) {
s, err = p.parseUdp(&m.Flags)
case "statistic":
s, err = p.parseStatistic(&m.Flags)
case "multiport":
s, err = p.parseMultiport(&m.Flags)
default:
if _, ok := matchModules[lit]; ok {
return sError, fmt.Errorf("match modules %q is not implemented", lit)
Expand Down Expand Up @@ -385,6 +387,78 @@ func (p *Parser) parseTcp(f *map[string]Flag) (state, error) {
return sStart, nil
}

func (p *Parser) parseMultiport(f *map[string]Flag) (state, error) {
s := sStart
for tok, lit := p.scanIgnoreWhitespace(); tok != EOF; tok, lit = p.scanIgnoreWhitespace() {
for nextValue := false; !nextValue; {
nextValue = true
switch s {
case sStart:
switch tok {
case NOT:
s = sINotF
case FLAG:
s = sIF
nextValue = false
default:
return sError, fmt.Errorf("unexpected token %q, expected flag, or \"!\"", lit)
}
case sINotF:
switch {
case lit == "--dports" || lit == "--destination-ports":
(*f)["destination-ports"] = Flag{
Not: true,
Values: p.parsePorts(),
}
s = sStart
case lit == "--sports" || lit == "--source-ports":
(*f)["source-ports"] = Flag{
Not: true,
Values: p.parsePorts(),
}
s = sStart
case lit == "--ports":
(*f)["ports"] = Flag{
Not: true,
Values: p.parsePorts(),
}
s = sStart
default:
p.unscan(1)
return sNot, nil
}
case sIF:
switch {
case lit == "--dports" || lit == "--destination-ports":
(*f)["destination-ports"] = Flag{
Values: p.parsePorts(),
}
s = sStart
case lit == "--sports" || lit == "--source-ports":
(*f)["source-ports"] = Flag{
Values: p.parsePorts(),
}
s = sStart
case lit == "--ports":
(*f)["ports"] = Flag{
Not: true,
Values: p.parsePorts(),
}
s = sStart
default:
// The end of the match statement is reached.
p.unscan(1)
return sStart, nil
}

default:
return sStart, errors.New("unexpected error parsing match extension")
}
}
}
return sStart, nil
}

func (p *Parser) parsePort() string {
_, l := p.scanIgnoreWhitespace()
if t, _ := p.scanIgnoreWhitespace(); t == COLON {
Expand All @@ -396,6 +470,22 @@ func (p *Parser) parsePort() string {
return l
}

func (p *Parser) parsePorts() []string {
var ports []string
_, l := p.scanIgnoreWhitespace()
ports = append(ports, l)
for {
if t, _ := p.scanIgnoreWhitespace(); t == COMMA {
_, c := p.scan()
ports = append(ports, c)
} else {
p.unscan(1)
break
}
}
return ports
}

func (p *Parser) parseList() (strs []string) {
const (
sC state = iota*2 + 1
Expand Down
31 changes: 31 additions & 0 deletions parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,37 @@ func TestParser_Parse(t *testing.T) {
},
err: nil,
},
{
name: "parse rule with multiport jump target DNAT",
s: "-A foo -p tcp -m multiport --dports=25,143,465,587,993,4190 -4 -j DNAT --to-destination 192.168.1.1",
r: Rule{
Chain: "foo",
IPv4: true,
Protocol: &StringPair{
Not: false,
Value: "tcp",
},
Matches: []Match{
{
Type: "multiport",
Flags: map[string]Flag{
"destination-ports": {
Values: []string{"25", "143", "465", "587", "993", "4190"},
},
},
},
},
Jump: &Target{
Name: "DNAT",
Flags: map[string]Flag{
"to-destination": {
Values: []string{"192.168.1.1"},
},
},
},
},
err: nil,
},
{
name: "parse rule with jump target SNAT",
s: "-A foo -o eth0 -4 -j SNAT --to-source 192.168.1.1",
Expand Down

0 comments on commit 275b7c9

Please sign in to comment.