mirror of
https://github.com/bettercap/bettercap
synced 2025-08-14 02:36:57 -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 {
|
||||
session.SessionModule
|
||||
selector *ViewSelector
|
||||
}
|
||||
|
||||
func NewDiscovery(s *session.Session) *Discovery {
|
||||
|
@ -36,33 +37,17 @@ func NewDiscovery(s *session.Session) *Discovery {
|
|||
d.AddHandler(session.NewModuleHandler("net.show", "",
|
||||
"Show cache hosts list (default sorting by ip).",
|
||||
func(args []string) error {
|
||||
return d.Show("address", "")
|
||||
}))
|
||||
|
||||
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", "")
|
||||
return d.Show("")
|
||||
}))
|
||||
|
||||
d.AddHandler(session.NewModuleHandler("net.show ADDRESS1, ADDRESS2", `net.show (.+)`,
|
||||
"Show information about a specific list of addresses (by IP or MAC).",
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -110,16 +110,44 @@ func (d *Discovery) getRow(e *network.Endpoint, withMeta bool) [][]string {
|
|||
return rows
|
||||
}
|
||||
|
||||
func (d *Discovery) Show(by string, expr string) (err error) {
|
||||
var targets []*network.Endpoint
|
||||
if expr != "" {
|
||||
if targets, err = network.ParseEndpoints(expr, d.Session.Lan); err != nil {
|
||||
return err
|
||||
func (d *Discovery) doFilter(target *network.Endpoint) bool {
|
||||
if d.selector.Expression == nil {
|
||||
return true
|
||||
}
|
||||
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 {
|
||||
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":
|
||||
sort.Sort(BySeenSorter(targets))
|
||||
case "sent":
|
||||
|
@ -130,6 +158,33 @@ func (d *Discovery) Show(by string, expr string) (err error) {
|
|||
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
|
||||
if d.Session.Interface.HwAddress == d.Session.Gateway.HwAddress {
|
||||
pad = 0
|
||||
|
|
|
@ -17,11 +17,27 @@ func (a ByAddressSorter) Less(i, j int) bool {
|
|||
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
|
||||
|
||||
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) 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
|
||||
|
||||
|
@ -43,7 +59,7 @@ func (a BySentSorter) Less(i, j int) bool {
|
|||
bTraffic = &packets.Traffic{}
|
||||
}
|
||||
|
||||
return bTraffic.Sent < aTraffic.Sent
|
||||
return bTraffic.Sent > aTraffic.Sent
|
||||
}
|
||||
|
||||
type ByRcvdSorter []*network.Endpoint
|
||||
|
@ -66,5 +82,5 @@ func (a ByRcvdSorter) Less(i, j int) bool {
|
|||
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