mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-09-29 07:56:37 +08:00
126 lines
2.8 KiB
Go
126 lines
2.8 KiB
Go
package nftables
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type CounterSample struct {
|
|
ForwardID int64
|
|
Direction string
|
|
Protocol string
|
|
Bytes uint64
|
|
Packets uint64
|
|
}
|
|
|
|
func ParseCounterComment(comment string) (CounterSample, bool) {
|
|
parts := strings.Split(comment, " ")
|
|
if len(parts) != 4 || parts[0] != "flvx" {
|
|
return CounterSample{}, false
|
|
}
|
|
if !strings.HasPrefix(parts[1], "forward:") {
|
|
return CounterSample{}, false
|
|
}
|
|
forwardText := strings.TrimPrefix(parts[1], "forward:")
|
|
forwardID, err := strconv.ParseInt(forwardText, 10, 64)
|
|
if err != nil || forwardID <= 0 {
|
|
return CounterSample{}, false
|
|
}
|
|
direction := parts[2]
|
|
if direction != CounterDirectionToTarget && direction != CounterDirectionFromTarget {
|
|
return CounterSample{}, false
|
|
}
|
|
protocol := parts[3]
|
|
if protocol != "tcp" && protocol != "udp" {
|
|
return CounterSample{}, false
|
|
}
|
|
return CounterSample{
|
|
ForwardID: forwardID,
|
|
Direction: direction,
|
|
Protocol: protocol,
|
|
}, true
|
|
}
|
|
|
|
func ParseCounterSamples(raw []byte) ([]CounterSample, error) {
|
|
var doc nftListTable
|
|
if err := json.Unmarshal(raw, &doc); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
samples := make([]CounterSample, 0)
|
|
for _, item := range doc.Nftables {
|
|
ruleRaw, ok := item["rule"]
|
|
if !ok {
|
|
continue
|
|
}
|
|
var rule nftCounterRule
|
|
if err := json.Unmarshal(ruleRaw, &rule); err != nil {
|
|
return nil, err
|
|
}
|
|
if rule.Table != "flvx" || rule.Chain != "forward" {
|
|
continue
|
|
}
|
|
|
|
sample, ok, err := parseCounterRule(rule)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !ok {
|
|
continue
|
|
}
|
|
samples = append(samples, sample)
|
|
}
|
|
return samples, nil
|
|
}
|
|
|
|
type nftListTable struct {
|
|
Nftables []map[string]json.RawMessage `json:"nftables"`
|
|
}
|
|
|
|
type nftCounterRule struct {
|
|
Table string `json:"table"`
|
|
Chain string `json:"chain"`
|
|
Comment string `json:"comment"`
|
|
Expr []map[string]json.RawMessage `json:"expr"`
|
|
}
|
|
|
|
type nftCounter struct {
|
|
Bytes uint64 `json:"bytes"`
|
|
Packets uint64 `json:"packets"`
|
|
}
|
|
|
|
func parseCounterRule(rule nftCounterRule) (CounterSample, bool, error) {
|
|
var (
|
|
counter nftCounter
|
|
hasCounter bool
|
|
comment = rule.Comment
|
|
)
|
|
|
|
for _, expr := range rule.Expr {
|
|
if rawCounter, ok := expr["counter"]; ok {
|
|
if err := json.Unmarshal(rawCounter, &counter); err != nil {
|
|
return CounterSample{}, false, err
|
|
}
|
|
hasCounter = true
|
|
continue
|
|
}
|
|
if rawComment, ok := expr["comment"]; ok && strings.TrimSpace(comment) == "" {
|
|
if err := json.Unmarshal(rawComment, &comment); err != nil {
|
|
return CounterSample{}, false, err
|
|
}
|
|
}
|
|
}
|
|
if !hasCounter {
|
|
return CounterSample{}, false, nil
|
|
}
|
|
|
|
sample, ok := ParseCounterComment(comment)
|
|
if !ok {
|
|
return CounterSample{}, false, nil
|
|
}
|
|
sample.Bytes = counter.Bytes
|
|
sample.Packets = counter.Packets
|
|
return sample, true, nil
|
|
}
|