Skip to content

Commit e08704c

Browse files
committed
modules: add basic multiport support
Signed-off-by: Adphi <[email protected]>
1 parent f11aa2d commit e08704c

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

match_modules.go

+90
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ func (p *Parser) parseMatch(ms *[]Match) (state, error) {
2828
s, err = p.parseUdp(&m.Flags)
2929
case "statistic":
3030
s, err = p.parseStatistic(&m.Flags)
31+
case "multiport":
32+
s, err = p.parseMultiport(&m.Flags)
3133
default:
3234
if _, ok := matchModules[lit]; ok {
3335
return sError, fmt.Errorf("match modules %q is not implemented", lit)
@@ -385,6 +387,78 @@ func (p *Parser) parseTcp(f *map[string]Flag) (state, error) {
385387
return sStart, nil
386388
}
387389

390+
func (p *Parser) parseMultiport(f *map[string]Flag) (state, error) {
391+
s := sStart
392+
for tok, lit := p.scanIgnoreWhitespace(); tok != EOF; tok, lit = p.scanIgnoreWhitespace() {
393+
for nextValue := false; !nextValue; {
394+
nextValue = true
395+
switch s {
396+
case sStart:
397+
switch tok {
398+
case NOT:
399+
s = sINotF
400+
case FLAG:
401+
s = sIF
402+
nextValue = false
403+
default:
404+
return sError, fmt.Errorf("unexpected token %q, expected flag, or \"!\"", lit)
405+
}
406+
case sINotF:
407+
switch {
408+
case lit == "--dports" || lit == "--destination-ports":
409+
(*f)["destination-ports"] = Flag{
410+
Not: true,
411+
Values: p.parsePorts(),
412+
}
413+
s = sStart
414+
case lit == "--sports" || lit == "--source-ports":
415+
(*f)["source-ports"] = Flag{
416+
Not: true,
417+
Values: p.parsePorts(),
418+
}
419+
s = sStart
420+
case lit == "--ports":
421+
(*f)["ports"] = Flag{
422+
Not: true,
423+
Values: p.parsePorts(),
424+
}
425+
s = sStart
426+
default:
427+
p.unscan(1)
428+
return sNot, nil
429+
}
430+
case sIF:
431+
switch {
432+
case lit == "--dports" || lit == "--destination-ports":
433+
(*f)["destination-ports"] = Flag{
434+
Values: p.parsePorts(),
435+
}
436+
s = sStart
437+
case lit == "--sports" || lit == "--source-ports":
438+
(*f)["source-ports"] = Flag{
439+
Values: p.parsePorts(),
440+
}
441+
s = sStart
442+
case lit == "--ports":
443+
(*f)["ports"] = Flag{
444+
Not: true,
445+
Values: p.parsePorts(),
446+
}
447+
s = sStart
448+
default:
449+
// The end of the match statement is reached.
450+
p.unscan(1)
451+
return sStart, nil
452+
}
453+
454+
default:
455+
return sStart, errors.New("unexpected error parsing match extension")
456+
}
457+
}
458+
}
459+
return sStart, nil
460+
}
461+
388462
func (p *Parser) parsePort() string {
389463
_, l := p.scanIgnoreWhitespace()
390464
if t, _ := p.scanIgnoreWhitespace(); t == COLON {
@@ -396,6 +470,22 @@ func (p *Parser) parsePort() string {
396470
return l
397471
}
398472

473+
func (p *Parser) parsePorts() []string {
474+
var ports []string
475+
_, l := p.scanIgnoreWhitespace()
476+
ports = append(ports, l)
477+
for {
478+
if t, _ := p.scanIgnoreWhitespace(); t == COMMA {
479+
_, c := p.scan()
480+
ports = append(ports, c)
481+
} else {
482+
p.unscan(1)
483+
break
484+
}
485+
}
486+
return ports
487+
}
488+
399489
func (p *Parser) parseList() (strs []string) {
400490
const (
401491
sC state = iota*2 + 1

parser_test.go

+31
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,37 @@ func TestParser_Parse(t *testing.T) {
707707
},
708708
err: nil,
709709
},
710+
{
711+
name: "parse rule with multiport jump target DNAT",
712+
s: "-A foo -p tcp -m multiport --dports=25,143,465,587,993,4190 -4 -j DNAT --to-destination 192.168.1.1",
713+
r: Rule{
714+
Chain: "foo",
715+
IPv4: true,
716+
Protocol: &StringPair{
717+
Not: false,
718+
Value: "tcp",
719+
},
720+
Matches: []Match{
721+
{
722+
Type: "multiport",
723+
Flags: map[string]Flag{
724+
"destination-ports": {
725+
Values: []string{"25", "143", "465", "587", "993", "4190"},
726+
},
727+
},
728+
},
729+
},
730+
Jump: &Target{
731+
Name: "DNAT",
732+
Flags: map[string]Flag{
733+
"to-destination": {
734+
Values: []string{"192.168.1.1"},
735+
},
736+
},
737+
},
738+
},
739+
err: nil,
740+
},
710741
{
711742
name: "parse rule with jump target SNAT",
712743
s: "-A foo -o eth0 -4 -j SNAT --to-source 192.168.1.1",

0 commit comments

Comments
 (0)