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_ACTIVATED
error.
I've looked through the libpcap
source 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_rfmon
with 0 clears a flag (e.g. pcap->opt.rfmon
). But, with a new instance (i.e. before calling pcap_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_activate
call. Generally, it doesn't "reset" if we call pcap_close
(Note: For some interfaces, the interface will be marked to reset upon pcap_close
but 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_promisc
instead.
That worked. Thank you.
pcap_set_promisc
works without a secondpcap_set_rfmon
. – Benjamin Mickler