Skip to content

Make opening a non-existent interface on Linux return 'no such interface' - #1560

Open
afipay wants to merge 1 commit into
the-tcpdump-group:masterfrom
afipay:non-existent-interface
Open

Make opening a non-existent interface on Linux return 'no such interface'#1560
afipay wants to merge 1 commit into
the-tcpdump-group:masterfrom
afipay:non-existent-interface

Conversation

@afipay

@afipay afipay commented Sep 23, 2025

Copy link
Copy Markdown

Fix interface existence check on Linux before privileged operations

When attempting to open a non-existent network interface on Linux,
libpcap would return PCAP_ERROR_PERM_DENIED instead of the correct
PCAP_ERROR_NO_SUCH_DEVICE. This occurred because the privileged
socket(PF_PACKET, SOCK_RAW, 0) call in setup_socket() would fail
with permission errors before interface validation could occur.

This fix adds an interface existence check using an unprivileged
AF_INET socket and SIOCGIFINDEX ioctl before attempting to create
the privileged packet socket. Non-existent interfaces now correctly
return PCAP_ERROR_NO_SUCH_DEVICE.

This resolves the issue where applications like tcpdump would report
"Permission denied" instead of "No such device exists" for non-existent
interfaces, breaking their fallback logic from interface names to indices.

Note: BSD/macOS platforms have the same underlying issue where BPF device
access fails with permission errors before interface validation. This
should be addressed in a separate commit.

Fixes: libpcap issue #1538
Related: tcpdump issue #1334

./tcpdump -i nonexistent
----------------------------------------
tcpdump: nonexistent: No such device exists
(No such device exists)

./tcpdump -i eth999
----------------------------------------
tcpdump: eth999: No such device exists
(No such device exists)

./tcpdump -i 000000000000008
----------------------------------------
tcpdump: Invalid adapter index 8: only 7 interfaces found

./tcpdump -i 00000000000000073
----------------------------------------
tcpdump: Invalid adapter index 73: only 7 interfaces found

@afipay
afipay force-pushed the non-existent-interface branch from 2848591 to b6e51a7 Compare September 23, 2025 04:14
@infrastation

Copy link
Copy Markdown
Member

Thank you for preparing this change. The comments that clarify the problem and the solution should be in the commit message.

Comment thread pcap-bpf.c Outdated
Comment thread pcap-linux.c
Comment thread pcap-bpf.c Outdated
Comment thread pcap-bpf.c Outdated
@infrastation

Copy link
Copy Markdown
Member

On Linux the only proposed change is to iface_get_ts_types(), thus the "check for existence before trying a privileged operation" logic does not apply to Linux:

$ ./testprogs/activatetest 
Trying to use capture device "nosuchdevice"...
FAIL: Permission denied from pcap_activate(), retry with higher privileges.

It looks like the two proposed changes are not related and should be two different commits, each stating and solving a separate problem. Also, since pcap-linux.c already implements helper functions such as iface_get_id(), it would be easy to implement the same logic for Linux. That said, the logic increases the race condition window, which would require some attention.

This requires a bit more work before it is ready.

@afipay
afipay force-pushed the non-existent-interface branch 2 times, most recently from d5797aa to 8b097c7 Compare September 24, 2025 02:01
@afipay
afipay marked this pull request as draft September 24, 2025 03:25
@afipay
afipay force-pushed the non-existent-interface branch from 02956d2 to ffb13dc Compare September 24, 2025 03:45
@afipay
afipay marked this pull request as ready for review September 24, 2025 04:59
@afipay
afipay requested a review from infrastation September 24, 2025 05:52
Comment thread pcap-linux.c Outdated
Comment thread pcap-linux.c Outdated

@infrastation infrastation left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As noted.

@afipay
afipay force-pushed the non-existent-interface branch from 0fa0fea to 7129d48 Compare January 1, 2026 13:01
@afipay afipay closed this Feb 24, 2026
@fxlb fxlb reopened this Mar 3, 2026
@fxlb
fxlb requested a review from guyharris March 3, 2026 07:48
@fxlb
fxlb force-pushed the non-existent-interface branch from 7129d48 to ea3d11d Compare March 3, 2026 14:32
@fxlb

fxlb commented Mar 3, 2026

Copy link
Copy Markdown
Member

Rebased.

@fxlb
fxlb requested a review from mcr March 6, 2026 17:34
@guyharris guyharris changed the title open a non-existent interface should always return 'no such interface' Make opening a non-existent interface on Linux return 'no such interface' Jul 23, 2026
Comment thread pcap-linux.c Outdated
@afipay
afipay force-pushed the non-existent-interface branch from ea3d11d to 4f0bbfa Compare July 24, 2026 16:19
In pcap_activate_linux(), check whether the device exists, using
an unprivileged ioctl socket from get_if_ioctl_socket(), before
attempting any operation that requires privileges, so that
attempting to open a non-existent device consistently reports
PCAP_ERROR_NO_SUCH_DEVICE rather than PCAP_ERROR_PERM_DENIED
from the attempt to create a PF_PACKET socket without
CAP_NET_RAW.

Fixes the-tcpdump-group#1538.
Also addresses the-tcpdump-group/tcpdump#1334, where a
zero-padded numeric interface argument behaved differently
depending on whether its length reached IFNAMSIZ.
@afipay
afipay force-pushed the non-existent-interface branch from 4f0bbfa to a703d58 Compare July 24, 2026 16:20
@guyharris

Copy link
Copy Markdown
Member

Should the check whether a device exists be done before trying to bind it, or after the attempt to bind the device fails with a permission error?

There's a time-of-check/time-of-use issue for both of those, but, if interfaces are appearing or disappearing, there's a risk of an error being reported for a condition that's not true by the time the user sees the error no matter what the code does, so I'm not bothered by that.

The one advantage of doing it afterwards is that fewer system calls are made in the case where everything succeeds, i.e. if the program does have permission to capture. I'm not sure that's a big enough difference to worry about.

@infrastation

Copy link
Copy Markdown
Member

Make it work, make it right, make it fast?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

4 participants