diff --git a/plugins/inputs/iptables/iptables.go b/plugins/inputs/iptables/iptables.go index af3941718..b552b4657 100644 --- a/plugins/inputs/iptables/iptables.go +++ b/plugins/inputs/iptables/iptables.go @@ -95,7 +95,7 @@ const measurement = "iptables" var errParse = errors.New("Cannot parse iptables list information") var chainNameRe = regexp.MustCompile(`^Chain\s+(\S+)`) var fieldsHeaderRe = regexp.MustCompile(`^\s*pkts\s+bytes\s+`) -var valuesRe = regexp.MustCompile(`^\s*([0-9]+)\s+([0-9]+)\s+.*?(/\*\s(.*)\s\*/)?$`) +var commentRe = regexp.MustCompile(`\s*/\*\s*(.+?)\s*\*/\s*`) func (ipt *Iptables) parseAndGather(data string, acc telegraf.Accumulator) error { lines := strings.Split(data, "\n") @@ -110,17 +110,34 @@ func (ipt *Iptables) parseAndGather(data string, acc telegraf.Accumulator) error return errParse } for _, line := range lines[2:] { - mv := valuesRe.FindAllStringSubmatch(line, -1) - // best effort : if line does not match or rule is not commented forget about it - if len(mv) == 0 || len(mv[0]) != 5 || mv[0][4] == "" { + tokens := strings.Fields(line) + if len(tokens) < 10 { continue } - tags := map[string]string{"table": ipt.Table, "chain": mchain[1], "ruleid": mv[0][4]} + + pkts := tokens[0] + bytes := tokens[1] + end := strings.Join(tokens[9:], " ") + + matches := commentRe.FindStringSubmatch(end) + if matches == nil { + continue + } + + comment := matches[1] + + tags := map[string]string{"table": ipt.Table, "chain": mchain[1], "ruleid": comment} fields := make(map[string]interface{}) - // since parse error is already catched by the regexp, - // we never enter ther error case here => no error check (but still need a test to cover the case) - fields["pkts"], _ = strconv.ParseUint(mv[0][1], 10, 64) - fields["bytes"], _ = strconv.ParseUint(mv[0][2], 10, 64) + + var err error + fields["pkts"], err = strconv.ParseUint(pkts, 10, 64) + if err != nil { + continue + } + fields["bytes"], err = strconv.ParseUint(bytes, 10, 64) + if err != nil { + continue + } acc.AddFields(measurement, fields, tags) } return nil diff --git a/plugins/inputs/iptables/iptables_test.go b/plugins/inputs/iptables/iptables_test.go index 96190713f..cc53ecc99 100644 --- a/plugins/inputs/iptables/iptables_test.go +++ b/plugins/inputs/iptables/iptables_test.go @@ -124,6 +124,36 @@ func TestIptables_Gather(t *testing.T) { {map[string]interface{}{"pkts": uint64(57), "bytes": uint64(4520)}}, }, }, + { // 10 - allow trailing text + table: "mangle", + chains: []string{"SHAPER"}, + values: []string{ + `Chain SHAPER (policy ACCEPT 58 packets, 5096 bytes) + pkts bytes target prot opt in out source destination + 0 0 ACCEPT all -- * * 1.3.5.7 0.0.0.0/0 /* test */ + 0 0 CLASSIFY all -- * * 1.3.5.7 0.0.0.0/0 /* test2 */ CLASSIFY set 1:4 + `}, + tags: []map[string]string{ + map[string]string{"table": "mangle", "chain": "SHAPER", "ruleid": "test"}, + map[string]string{"table": "mangle", "chain": "SHAPER", "ruleid": "test2"}, + }, + fields: [][]map[string]interface{}{ + {map[string]interface{}{"pkts": uint64(0), "bytes": uint64(0)}}, + {map[string]interface{}{"pkts": uint64(0), "bytes": uint64(0)}}, + }, + }, + { // 11 - invalid pkts/bytes + table: "mangle", + chains: []string{"SHAPER"}, + values: []string{ + `Chain SHAPER (policy ACCEPT 58 packets, 5096 bytes) + pkts bytes target prot opt in out source destination + a a ACCEPT all -- * * 1.3.5.7 0.0.0.0/0 /* test */ + a a CLASSIFY all -- * * 1.3.5.7 0.0.0.0/0 /* test2 */ CLASSIFY set 1:4 + `}, + tags: []map[string]string{}, + fields: [][]map[string]interface{}{}, + }, } for i, tt := range tests {