package network import ( "bufio" "fmt" "net" "regexp" "strconv" "strings" "github.com/bettercap/bettercap/v2/core" ) // see Windows version to understand why .... func getInterfaceName(iface net.Interface) string { return iface.Name } // See https://github.com/bettercap/bettercap/issues/819 func ForceMonitorMode(iface string) error { _, _ = core.Exec("ip", []string{"link", "set", iface, "down"}) out, err := core.Exec("iw", []string{"dev", iface, "set", "type", "monitor"}) if err != nil { return fmt.Errorf("iw: out=%s err=%s", out, err) } else if out != "" { return fmt.Errorf("Unexpected output while setting interface %s into monitor mode: %s", iface, out) } _, _ = core.Exec("ip", []string{"link", "set", iface, "up"}) return nil } func SetInterfaceChannel(iface string, channel int) error { curr := GetInterfaceChannel(iface) // the interface is already on this channel if curr == channel { return nil } if core.HasBinary("iw") { // Debug("SetInterfaceChannel(%s, %d) iw based", iface, channel) // out, err := core.Exec("iw", []string{"dev", iface, "set", "channel", fmt.Sprintf("%d", channel)}) out, err := core.Exec("iw", []string{"dev", iface, "set", "freq", fmt.Sprintf("%d", Dot11Chan2Freq(channel))}) if err != nil { return fmt.Errorf("iw: out=%s err=%s", out, err) } else if out != "" { return fmt.Errorf("Unexpected output while setting interface %s to channel %d: %s", iface, channel, out) } } else if core.HasBinary("iwconfig") { // Debug("SetInterfaceChannel(%s, %d) iwconfig based") out, err := core.Exec("iwconfig", []string{iface, "channel", fmt.Sprintf("%d", channel)}) if err != nil { return fmt.Errorf("iwconfig: out=%s err=%s", out, err) } else if out != "" { return fmt.Errorf("Unexpected output while setting interface %s to channel %d: %s", iface, channel, out) } } else { return fmt.Errorf("no iw or iwconfig binaries found in $PATH") } SetInterfaceCurrentChannel(iface, channel) return nil } var iwlistFreqParser = regexp.MustCompile(`^\s+Channel.([0-9]+)\s+:\s+([0-9\.]+)\s+GHz.*$`) func iwlistSupportedFrequencies(iface string) ([]int, error) { out, err := core.Exec("iwlist", []string{iface, "freq"}) if err != nil { return nil, err } freqs := make([]int, 0) if out != "" { scanner := bufio.NewScanner(strings.NewReader(out)) for scanner.Scan() { line := scanner.Text() matches := iwlistFreqParser.FindStringSubmatch(line) if len(matches) == 3 { if freq, err := strconv.ParseFloat(matches[2], 64); err == nil { freqs = append(freqs, int(freq*1000)) } } } } return freqs, nil } var iwPhyParser = regexp.MustCompile(`^\s*wiphy\s+(\d+)$`) // var iwFreqParser = regexp.MustCompile(`^\s+\*\s+(\d+)\s+MHz.+dBm.+$`) var iwFreqParser = regexp.MustCompile(`^\s+\*\s+(\d+)\.\d+\s+MHz.+dBm.+$`) func iwSupportedFrequencies(iface string) ([]int, error) { // first determine phy index out, err := core.Exec("iw", []string{iface, "info"}) if err != nil { return nil, fmt.Errorf("error getting %s phy index: %v", iface, err) } phy := int64(-1) scanner := bufio.NewScanner(strings.NewReader(out)) for scanner.Scan() { line := scanner.Text() matches := iwPhyParser.FindStringSubmatch(line) if len(matches) == 2 { if phy, err = strconv.ParseInt(matches[1], 10, 32); err != nil { return nil, fmt.Errorf("error parsing %s phy index: %v (line: %s)", iface, err, line) } } } if phy == -1 { return nil, fmt.Errorf("could not find %s phy index", iface) } // then get phyN info phyName := fmt.Sprintf("phy%d", phy) out, err = core.Exec("iw", []string{phyName, "info"}) if err != nil { return nil, fmt.Errorf("error getting %s (%s) info: %v", phyName, iface, err) } freqs := []int{} scanner = bufio.NewScanner(strings.NewReader(out)) for scanner.Scan() { line := scanner.Text() matches := iwFreqParser.FindStringSubmatch(line) if len(matches) == 2 { if freq, err := strconv.ParseInt(matches[1], 10, 64); err != nil { return nil, fmt.Errorf("error parsing %s freq: %v (line: %s)", iface, err, line) } else { freqs = append(freqs, int(freq)) } } } return freqs, nil } func GetSupportedFrequencies(iface string) ([]int, error) { // give priority to iwlist because of https://github.com/bettercap/bettercap/issues/881 // UPDATE: Changed the priority due iwlist doesn't support 6GHz if core.HasBinary("iw") { return iwSupportedFrequencies(iface) } else if core.HasBinary("iwlist") { return iwlistSupportedFrequencies(iface) } return nil, fmt.Errorf("no iw or iwlist binaries found in $PATH") }