I have a function that enables monitor mode for a WiFi device on macOS using libpcap. This works, but currently the only way to set the WiFi device back to managed mode is to exit the process. I would like to set the WiFi device to managed mode while allowing the process to continue. As far as I can tell, this can't be done with libpcap. How would I set the WiFi device back to managed mode (potentially using the CoreWLAN API in Objective-C?)?
pcap_t *enable_monitor(char *dev) {
wifi_disassociate();
char error_buffer[PCAP_ERRBUF_SIZE];
pcap_t *handle;
int result;
handle = pcap_create(dev, error_buffer);
if (handle == NULL) {
printf("failed to create a handle: %s\n",
error_buffer);
return NULL;
}
result = pcap_set_rfmon(handle, 1);
if (result != 0) {
printf("failed to set pcap rfmon: %s (%s)\n",
pcap_statustostr(result),
pcap_geterr(handle));
return NULL;
}
result = pcap_activate(handle);
if (result != 0) {
printf("failed to activate handle: %s (%s)\n",
pcap_statustostr(result),
pcap_geterr(handle));
return NULL;
}
//pcap_close(handle);
return handle;
}
Edit:
Setting the second argument to cap_set_rfmon to 0 does not seem to set the device to managed mode, it just doesn't set it to monitor mode.
int disable_monitor(pcap_t *handle) {
int result;
result = pcap_set_rfmon(handle, 0);
if (result != 0) {
printf("failed to set pcap rfmon: %s (%s)\n",
pcap_statustostr(result),
pcap_geterr(handle));
return 1;
}
pcap_close(handle);
return 0;
}
int main() {
char *dev = find_wifi_device();
pcap_t *handle = enable_monitor(dev);
sleep(5);
int status = disable_monitor(handle);
printf("Status: %d\n", status);
for (;;)
sleep(100);
}
This results in:
failed to set pcap rfmon: The setting can't be changed after the pcap_t is activated (can't perform operation on activated capture)
Status: 1
Prefaced by my top comments ...
From
man pcap_set_rfmon, it sets the mode. But, it only takes effect "when activated" (i.e.pcap_activate).Further, if called on an already activated handle, the call returns the
PCAP_ERROR_ACTIVATEDerror.I've looked through the
libpcapsource code and ...Once a connection has been activated, I can find no
pcap_*call that will "deactivate" it. So, we may have to close the handle and open a fresh instance.Also, AFAICT, do
pcap_set_rfmonwith 0 clears a flag (e.g.pcap->opt.rfmon). But, with a new instance (i.e. before callingpcap_activate), this should already be clear, so this is an effective no-op.The interface is already in a given mode from the first
pcap_activatecall. Generally, it doesn't "reset" if we callpcap_close(Note: For some interfaces, the interface will be marked to reset uponpcap_closebut we probably can't rely on that in general).What is the default mode? I'm guessing promiscuous mode, so to reset monitor mode, we may have to use
pcap_set_promiscinstead.