diff --git a/network/net_darwin.go b/network/net_darwin.go index 5d339c36..5e8ce195 100644 --- a/network/net_darwin.go +++ b/network/net_darwin.go @@ -1,60 +1,55 @@ package network +/* +#cgo LDFLAGS: -framework CoreWLAN -framework Foundation +#include +#include + +const char *GetSupportedFrequencies(const char *iface); +bool SetInterfaceChannel(const char *iface, int channel); +*/ +import "C" + import ( - "fmt" + "encoding/json" + "errors" "net" - "regexp" - "strconv" - - "github.com/bettercap/bettercap/core" - - "github.com/evilsocket/islazy/str" + "unsafe" ) -const airPortPath = "/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport" - -var WiFiChannelParser = regexp.MustCompile(`(?m)^.*Supported Channels: (.*)$`) - -// see Windows version to understand why .... func getInterfaceName(iface net.Interface) string { return iface.Name } func SetInterfaceChannel(iface string, channel int) error { - curr := GetInterfaceChannel(iface) - // the interface is already on this channel - if curr == channel { - return nil - } + cIface := C.CString(iface) + defer C.free(unsafe.Pointer(cIface)) - _, err := core.Exec(airPortPath, []string{iface, fmt.Sprintf("-c%d", channel)}) - if err != nil { - return err + success := C.SetInterfaceChannel(cIface, C.int(channel)) + if !success { + return errors.New("failed to set interface channel") } SetInterfaceCurrentChannel(iface, channel) return nil } -func getFrequenciesFromChannels(output string) ([]int, error) { - freqs := make([]int, 0) - if output != "" { - if matches := WiFiChannelParser.FindStringSubmatch(output); len(matches) == 2 { - for _, channel := range str.Comma(matches[1]) { - re := regexp.MustCompile(`\d+`) - if channel, err := strconv.Atoi(re.FindString(channel)); err == nil { - freqs = append(freqs, Dot11Chan2Freq(channel)) - } - } - } - } - return freqs, nil -} - func GetSupportedFrequencies(iface string) ([]int, error) { - out, err := core.Exec("system_profiler", []string{"SPAirPortDataType"}) + cIface := C.CString(iface) + defer C.free(unsafe.Pointer(cIface)) + + cFrequencies := C.GetSupportedFrequencies(cIface) + if cFrequencies == nil { + return nil, errors.New("failed to get supported frequencies") + } + defer C.free(unsafe.Pointer(cFrequencies)) + + frequenciesStr := C.GoString(cFrequencies) + var frequencies []int + err := json.Unmarshal([]byte(frequenciesStr), &frequencies) if err != nil { return nil, err } - return getFrequenciesFromChannels(out) + + return frequencies, nil } diff --git a/network/net_darwin.m b/network/net_darwin.m new file mode 100644 index 00000000..1a2876cf --- /dev/null +++ b/network/net_darwin.m @@ -0,0 +1,72 @@ +#import +#import + +// The go side of things expects frequencies. +int chan2freq(int channel) { + if(channel <= 13){ + return ((channel - 1) * 5) + 2412; + } else if(channel == 14) { + return 2484; + } else if(channel <= 173) { + return ((channel - 7) * 5) + 5035; + } else if(channel == 177) { + return 5885; + } + return 0; +} + +const char *GetSupportedFrequencies(const char *iface) { + @autoreleasepool { + NSString *interfaceName = [NSString stringWithUTF8String:iface]; + CWInterface *interface = [CWInterface interfaceWithName:interfaceName]; + if (!interface) { + return NULL; + } + + NSSet *supportedChannels = [interface supportedWLANChannels]; + NSMutableArray *frequencies = [NSMutableArray arrayWithCapacity:[supportedChannels count]]; + + for (CWChannel *channel in supportedChannels) { + // The go side of things expects frequencies. + [frequencies addObject:@(chan2freq(channel.channelNumber))]; + } + + NSError *error = nil; + NSData *jsonData = [NSJSONSerialization dataWithJSONObject:frequencies options:0 error:&error]; + if (!jsonData) { + NSLog(@"Failed to serialize frequencies: %@", error); + return NULL; + } + + NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + return strdup([jsonString UTF8String]); + } +} + +bool SetInterfaceChannel(const char *iface, int channel) { + @autoreleasepool { + NSString *interfaceName = [NSString stringWithUTF8String:iface]; + CWInterface *interface = [CWInterface interfaceWithName:interfaceName]; + if (!interface) { + return false; + } + + NSError *error = nil; + NSSet *supportedChannels = [interface supportedWLANChannels]; + for (CWChannel * channelObj in supportedChannels) { + // it looks like we can't directly build a CWChannel object anymore + if ([channelObj channelNumber] == channel) { + [interface setWLANChannel:channelObj error:nil]; + if (error) { + NSLog(@"Failed to set channel: %@", error); + return false; + } + return true; + } + } + + NSLog(@"channel %d not supported", channel); + + return false; + } +} \ No newline at end of file