mirror of
https://github.com/bettercap/bettercap
synced 2025-07-07 05:22:04 -07:00
135 lines
2.7 KiB
Go
135 lines
2.7 KiB
Go
package network
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/bettercap/bettercap/core"
|
|
)
|
|
|
|
var ErrNoIfaces = errors.New("No active interfaces found.")
|
|
var ErrNoGateway = errors.New("Could not detect gateway.")
|
|
|
|
const (
|
|
MonitorModeAddress = "0.0.0.0"
|
|
BroadcastSuffix = ".255"
|
|
BroadcastMac = "ff:ff:ff:ff:ff:ff"
|
|
IPv4MulticastStart = "01:00:5e:00:00:00"
|
|
IPv4MulticastEnd = "01:00:5e:7f:ff:ff"
|
|
)
|
|
|
|
var (
|
|
BroadcastHw = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
|
|
IPv4Validator = regexp.MustCompile("^[0-9\\.]+/?\\d*$")
|
|
)
|
|
|
|
func NormalizeMac(mac string) string {
|
|
var parts []string
|
|
if strings.ContainsRune(mac, '-') {
|
|
parts = strings.Split(mac, "-")
|
|
} else {
|
|
parts = strings.Split(mac, ":")
|
|
}
|
|
|
|
for i, p := range parts {
|
|
if len(p) < 2 {
|
|
parts[i] = "0" + p
|
|
}
|
|
}
|
|
return strings.Join(parts, ":")
|
|
}
|
|
|
|
func buildEndpointFromInterface(iface net.Interface) (*Endpoint, error) {
|
|
addrs, err := iface.Addrs()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
ifName := getInterfaceName(iface)
|
|
|
|
e := NewEndpointNoResolve(MonitorModeAddress, iface.HardwareAddr.String(), ifName, 0)
|
|
|
|
e.Index = iface.Index
|
|
|
|
for _, a := range addrs {
|
|
address := a.String()
|
|
if IPv4Validator.MatchString(address) {
|
|
if strings.IndexRune(address, '/') == -1 {
|
|
// plain ip
|
|
e.SetIP(address)
|
|
} else {
|
|
// ip/bits
|
|
e.SetNetwork(address)
|
|
}
|
|
} else {
|
|
// ipv6/xxx
|
|
e.SetIPv6(address)
|
|
}
|
|
}
|
|
|
|
return e, nil
|
|
}
|
|
|
|
func matchByAddress(iface net.Interface, name string) bool {
|
|
ifMac := iface.HardwareAddr.String()
|
|
if NormalizeMac(ifMac) == NormalizeMac(name) {
|
|
return true
|
|
}
|
|
|
|
addrs, err := iface.Addrs()
|
|
if err == nil {
|
|
for _, addr := range addrs {
|
|
ip := addr.String()
|
|
if ip == name || strings.HasPrefix(ip, name) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func findInterfaceByName(name string, ifaces []net.Interface) (*Endpoint, error) {
|
|
for _, iface := range ifaces {
|
|
ifName := getInterfaceName(iface)
|
|
if ifName == name || matchByAddress(iface, name) {
|
|
return buildEndpointFromInterface(iface)
|
|
}
|
|
}
|
|
|
|
return nil, fmt.Errorf("No interface matching '%s' found.", name)
|
|
}
|
|
|
|
func FindInterface(name string) (*Endpoint, error) {
|
|
ifaces, err := net.Interfaces()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
name = core.Trim(name)
|
|
if name != "" {
|
|
return findInterfaceByName(name, ifaces)
|
|
}
|
|
|
|
// user did not provide an interface name,
|
|
// return the first one with a valid ipv4
|
|
// address
|
|
for _, iface := range ifaces {
|
|
addrs, err := iface.Addrs()
|
|
if err != nil {
|
|
fmt.Printf("WTF of the day: %s", err)
|
|
continue
|
|
}
|
|
|
|
for _, address := range addrs {
|
|
ip := address.String()
|
|
if strings.Contains(ip, "127.0.0.1") == false && IPv4Validator.MatchString(ip) {
|
|
return buildEndpointFromInterface(iface)
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil, ErrNoIfaces
|
|
}
|