mirror of
https://github.com/bettercap/bettercap
synced 2025-08-19 13:09:49 -07:00
new: net.show.filter, net.show.limit, net.show.sort and net.show.sort_by parameters to control net.show
This commit is contained in:
parent
431e84ea79
commit
28f8586abb
4 changed files with 178 additions and 29 deletions
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
type Discovery struct {
|
type Discovery struct {
|
||||||
session.SessionModule
|
session.SessionModule
|
||||||
|
selector *ViewSelector
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDiscovery(s *session.Session) *Discovery {
|
func NewDiscovery(s *session.Session) *Discovery {
|
||||||
|
@ -36,33 +37,17 @@ func NewDiscovery(s *session.Session) *Discovery {
|
||||||
d.AddHandler(session.NewModuleHandler("net.show", "",
|
d.AddHandler(session.NewModuleHandler("net.show", "",
|
||||||
"Show cache hosts list (default sorting by ip).",
|
"Show cache hosts list (default sorting by ip).",
|
||||||
func(args []string) error {
|
func(args []string) error {
|
||||||
return d.Show("address", "")
|
return d.Show("")
|
||||||
}))
|
|
||||||
|
|
||||||
d.AddHandler(session.NewModuleHandler("net.show by seen", "",
|
|
||||||
"Show cache hosts list (sort by last seen).",
|
|
||||||
func(args []string) error {
|
|
||||||
return d.Show("seen", "")
|
|
||||||
}))
|
|
||||||
|
|
||||||
d.AddHandler(session.NewModuleHandler("net.show by sent", "",
|
|
||||||
"Show cache hosts list (sort by sent packets).",
|
|
||||||
func(args []string) error {
|
|
||||||
return d.Show("sent", "")
|
|
||||||
}))
|
|
||||||
|
|
||||||
d.AddHandler(session.NewModuleHandler("net.show by rcvd", "",
|
|
||||||
"Show cache hosts list (sort by received packets).",
|
|
||||||
func(args []string) error {
|
|
||||||
return d.Show("rcvd", "")
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
d.AddHandler(session.NewModuleHandler("net.show ADDRESS1, ADDRESS2", `net.show (.+)`,
|
d.AddHandler(session.NewModuleHandler("net.show ADDRESS1, ADDRESS2", `net.show (.+)`,
|
||||||
"Show information about a specific list of addresses (by IP or MAC).",
|
"Show information about a specific list of addresses (by IP or MAC).",
|
||||||
func(args []string) error {
|
func(args []string) error {
|
||||||
return d.Show("address", args[0])
|
return d.Show(args[0])
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
d.selector = ViewSelectorFor(&d.SessionModule, "net.show", []string{"ip", "mac", "seen", "sent", "rcvd"}, "")
|
||||||
|
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,16 +110,44 @@ func (d *Discovery) getRow(e *network.Endpoint, withMeta bool) [][]string {
|
||||||
return rows
|
return rows
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Discovery) Show(by string, expr string) (err error) {
|
func (d *Discovery) doFilter(target *network.Endpoint) bool {
|
||||||
var targets []*network.Endpoint
|
if d.selector.Expression == nil {
|
||||||
if expr != "" {
|
return true
|
||||||
if targets, err = network.ParseEndpoints(expr, d.Session.Lan); err != nil {
|
}
|
||||||
return err
|
return d.selector.Expression.MatchString(target.IpAddress) ||
|
||||||
|
d.selector.Expression.MatchString(target.Ip6Address) ||
|
||||||
|
d.selector.Expression.MatchString(target.HwAddress) ||
|
||||||
|
d.selector.Expression.MatchString(target.Hostname) ||
|
||||||
|
d.selector.Expression.MatchString(target.Alias) ||
|
||||||
|
d.selector.Expression.MatchString(target.Vendor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Discovery) doSelection(arg string) (err error, targets []*network.Endpoint) {
|
||||||
|
if err = d.selector.Update(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if arg != "" {
|
||||||
|
if targets, err = network.ParseEndpoints(arg, d.Session.Lan); err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
targets = d.Session.Lan.List()
|
targets = d.Session.Lan.List()
|
||||||
}
|
}
|
||||||
switch by {
|
|
||||||
|
filtered := []*network.Endpoint{}
|
||||||
|
for _, target := range targets {
|
||||||
|
if d.doFilter(target) {
|
||||||
|
filtered = append(filtered, target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
targets = filtered
|
||||||
|
|
||||||
|
switch d.selector.SortBy {
|
||||||
|
case "ip":
|
||||||
|
sort.Sort(ByIpSorter(targets))
|
||||||
|
case "mac":
|
||||||
|
sort.Sort(ByMacSorter(targets))
|
||||||
case "seen":
|
case "seen":
|
||||||
sort.Sort(BySeenSorter(targets))
|
sort.Sort(BySeenSorter(targets))
|
||||||
case "sent":
|
case "sent":
|
||||||
|
@ -130,6 +158,33 @@ func (d *Discovery) Show(by string, expr string) (err error) {
|
||||||
sort.Sort(ByAddressSorter(targets))
|
sort.Sort(ByAddressSorter(targets))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// default is asc
|
||||||
|
if d.selector.Sort == "desc" {
|
||||||
|
// from https://github.com/golang/go/wiki/SliceTricks
|
||||||
|
for i := len(targets)/2 - 1; i >= 0; i-- {
|
||||||
|
opp := len(targets) - 1 - i
|
||||||
|
targets[i], targets[opp] = targets[opp], targets[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.selector.Limit > 0 {
|
||||||
|
limit := d.selector.Limit
|
||||||
|
max := len(targets)
|
||||||
|
if limit > max {
|
||||||
|
limit = max
|
||||||
|
}
|
||||||
|
targets = targets[0:limit]
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Discovery) Show(arg string) (err error) {
|
||||||
|
var targets []*network.Endpoint
|
||||||
|
if err, targets = d.doSelection(arg); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
pad := 1
|
pad := 1
|
||||||
if d.Session.Interface.HwAddress == d.Session.Gateway.HwAddress {
|
if d.Session.Interface.HwAddress == d.Session.Gateway.HwAddress {
|
||||||
pad = 0
|
pad = 0
|
||||||
|
|
|
@ -17,11 +17,27 @@ func (a ByAddressSorter) Less(i, j int) bool {
|
||||||
return a[i].IpAddressUint32 < a[j].IpAddressUint32
|
return a[i].IpAddressUint32 < a[j].IpAddressUint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ByIpSorter []*network.Endpoint
|
||||||
|
|
||||||
|
func (a ByIpSorter) Len() int { return len(a) }
|
||||||
|
func (a ByIpSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
|
func (a ByIpSorter) Less(i, j int) bool {
|
||||||
|
return a[i].IpAddressUint32 < a[j].IpAddressUint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type ByMacSorter []*network.Endpoint
|
||||||
|
|
||||||
|
func (a ByMacSorter) Len() int { return len(a) }
|
||||||
|
func (a ByMacSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
|
func (a ByMacSorter) Less(i, j int) bool {
|
||||||
|
return a[i].HwAddress < a[j].HwAddress
|
||||||
|
}
|
||||||
|
|
||||||
type BySeenSorter []*network.Endpoint
|
type BySeenSorter []*network.Endpoint
|
||||||
|
|
||||||
func (a BySeenSorter) Len() int { return len(a) }
|
func (a BySeenSorter) Len() int { return len(a) }
|
||||||
func (a BySeenSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
func (a BySeenSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
func (a BySeenSorter) Less(i, j int) bool { return a[i].LastSeen.After(a[j].LastSeen) }
|
func (a BySeenSorter) Less(i, j int) bool { return a[i].LastSeen.Before(a[j].LastSeen) }
|
||||||
|
|
||||||
type BySentSorter []*network.Endpoint
|
type BySentSorter []*network.Endpoint
|
||||||
|
|
||||||
|
@ -43,7 +59,7 @@ func (a BySentSorter) Less(i, j int) bool {
|
||||||
bTraffic = &packets.Traffic{}
|
bTraffic = &packets.Traffic{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bTraffic.Sent < aTraffic.Sent
|
return bTraffic.Sent > aTraffic.Sent
|
||||||
}
|
}
|
||||||
|
|
||||||
type ByRcvdSorter []*network.Endpoint
|
type ByRcvdSorter []*network.Endpoint
|
||||||
|
@ -66,5 +82,5 @@ func (a ByRcvdSorter) Less(i, j int) bool {
|
||||||
bTraffic = &packets.Traffic{}
|
bTraffic = &packets.Traffic{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bTraffic.Received < aTraffic.Received
|
return bTraffic.Received > aTraffic.Received
|
||||||
}
|
}
|
||||||
|
|
93
modules/view_selector.go
Normal file
93
modules/view_selector.go
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
package modules
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/bettercap/bettercap/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ViewSelector struct {
|
||||||
|
owner *session.SessionModule
|
||||||
|
|
||||||
|
Filter string
|
||||||
|
filterName string
|
||||||
|
filterPrev string
|
||||||
|
Expression *regexp.Regexp
|
||||||
|
|
||||||
|
SortBy string
|
||||||
|
sortBys map[string]bool
|
||||||
|
sortByName string
|
||||||
|
|
||||||
|
Sort string
|
||||||
|
sortName string
|
||||||
|
|
||||||
|
Limit int
|
||||||
|
limitName string
|
||||||
|
}
|
||||||
|
|
||||||
|
func ViewSelectorFor(m *session.SessionModule, prefix string, sortBys []string, defSortBy string) *ViewSelector {
|
||||||
|
s := &ViewSelector{
|
||||||
|
owner: m,
|
||||||
|
filterName: prefix + ".filter",
|
||||||
|
filterPrev: "",
|
||||||
|
sortByName: prefix + ".sort_by",
|
||||||
|
sortBys: make(map[string]bool),
|
||||||
|
sortName: prefix + ".sort",
|
||||||
|
limitName: prefix + ".limit",
|
||||||
|
|
||||||
|
SortBy: defSortBy,
|
||||||
|
Sort: "asc",
|
||||||
|
Limit: 0,
|
||||||
|
Filter: "",
|
||||||
|
Expression: nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, sb := range sortBys {
|
||||||
|
s.sortBys[sb] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
m.AddParam(session.NewStringParameter(s.filterName, "", "", "Defines a regular expression filter for "+prefix))
|
||||||
|
m.AddParam(session.NewStringParameter(s.sortByName, defSortBy, "", "Defines sorting field for "+prefix+", available: "+strings.Join(sortBys, ", ")))
|
||||||
|
m.AddParam(session.NewStringParameter(s.sortName, "asc", "", "Defines sorting direction for "+prefix))
|
||||||
|
m.AddParam(session.NewIntParameter(s.limitName, "0", "Defines limit for "+prefix))
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ViewSelector) Update() (err error) {
|
||||||
|
if err, s.Filter = s.owner.StringParam(s.filterName); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Filter != "" {
|
||||||
|
if s.Filter != s.filterPrev {
|
||||||
|
if s.Expression, err = regexp.Compile(s.Filter); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s.Expression = nil
|
||||||
|
}
|
||||||
|
s.filterPrev = s.Filter
|
||||||
|
|
||||||
|
if err, s.SortBy = s.owner.StringParam(s.sortByName); err != nil {
|
||||||
|
return
|
||||||
|
} else if s.SortBy != "" {
|
||||||
|
if _, found := s.sortBys[s.SortBy]; !found {
|
||||||
|
return fmt.Errorf("'%s' is not valid for %s", s.SortBy, s.sortByName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err, s.Sort = s.owner.StringParam(s.sortName); err != nil {
|
||||||
|
return
|
||||||
|
} else if s.Sort != "asc" && s.Sort != "desc" {
|
||||||
|
return fmt.Errorf("'%s' is not valid for %s", s.Sort, s.sortName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err, s.Limit = s.owner.IntParam(s.limitName); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue