Skip to content

Commit b6e51a7

Browse files
committed
open a non-existent interface should always return 'no such interface'
Signed-off-by: Afshin Paydar <afshin.paydar@deriv.com>
1 parent 5fc0c26 commit b6e51a7

File tree

2 files changed

+87
-6
lines changed

2 files changed

+87
-6
lines changed

pcap-bpf.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@
4141
#ifdef HAVE_SYS_IOCCOM_H
4242
#include <sys/ioccom.h>
4343
#endif
44+
45+
/*
46+
* On most supported platforms <sys/ioctl.h> also defines the SIOCGIF* macros.
47+
* However, on Haiku, illumos and Solaris the macros need <sys/sockio.h>,
48+
* which does not exist in AIX 7, HP-UX 11, GNU/Hurd and Linux (both GNU and
49+
* musl libc).
50+
*/
51+
#if defined(HAVE_SOLARIS) || defined(__HAIKU__) || defined(__sun) || defined(__SVR4)
52+
#include <sys/sockio.h>
53+
#endif
54+
4455
#include <sys/utsname.h>
4556

4657
#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
@@ -626,6 +637,66 @@ bpf_open(char *errbuf)
626637
#define BPF_BIND_SUCCEEDED 0
627638
#define BPF_BIND_BUFFER_TOO_BIG 1
628639

640+
/*
641+
* Check if an interface exists without requiring special privileges.
642+
* Returns 0 if the interface exists, PCAP_ERROR_NO_SUCH_DEVICE if it doesn't,
643+
* or another negative error code on other failures.
644+
*/
645+
static int
646+
check_interface_exists(const char *name, char *errbuf)
647+
{
648+
#ifndef _WIN32
649+
int fd;
650+
struct ifreq ifr;
651+
652+
if (strlen(name) >= sizeof(ifr.ifr_name)) {
653+
/* The name is too long, so it can't possibly exist. */
654+
errbuf[0] = '\0';
655+
return PCAP_ERROR_NO_SUCH_DEVICE;
656+
}
657+
658+
fd = socket(AF_INET, SOCK_DGRAM, 0);
659+
if (fd < 0) {
660+
pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
661+
errno, "socket");
662+
return PCAP_ERROR;
663+
}
664+
665+
memset(&ifr, 0, sizeof(ifr));
666+
pcapint_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
667+
668+
#ifdef SIOCGIFFLAGS
669+
if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
670+
int save_errno = errno;
671+
close(fd);
672+
673+
if (save_errno == ENXIO || save_errno == ENODEV) {
674+
/* Interface doesn't exist */
675+
errbuf[0] = '\0';
676+
return PCAP_ERROR_NO_SUCH_DEVICE;
677+
} else {
678+
/* Some other error occurred */
679+
pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
680+
save_errno, "SIOCGIFFLAGS on %s", name);
681+
return PCAP_ERROR;
682+
}
683+
}
684+
#else
685+
/*
686+
* SIOCGIFFLAGS not available on this platform.
687+
* We can't reliably check interface existence without privileges,
688+
* so we skip the check and let the BPF bind operation handle it.
689+
*/
690+
#endif
691+
692+
close(fd);
693+
return 0;
694+
#else
695+
/* On Windows, skip the check for now */
696+
return 0;
697+
#endif
698+
}
699+
629700
static int
630701
bpf_bind(int fd, const char *name, char *errbuf)
631702
{
@@ -1923,6 +1994,16 @@ pcap_activate_bpf(pcap_t *p)
19231994
int flags = MAP_ANON;
19241995
#endif
19251996

1997+
/*
1998+
* Check if the interface exists before trying to open BPF device.
1999+
* This avoids reporting permission errors when the real issue is
2000+
* that the interface doesn't exist.
2001+
*/
2002+
status = check_interface_exists(p->opt.device, p->errbuf);
2003+
if (status != 0) {
2004+
goto bad;
2005+
}
2006+
19262007
fd = bpf_open(p->errbuf);
19272008
if (fd < 0) {
19282009
status = fd;

pcap-linux.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5164,13 +5164,13 @@ iface_get_ts_types(const char *device, pcap_t *handle, char *ebuf)
51645164

51655165
case ENODEV:
51665166
/*
5167-
* OK, no such device.
5168-
* The user will find that out when they try to
5169-
* activate the device; just return an empty
5170-
* list of time stamp types.
5167+
* No such device.
5168+
*
5169+
* There's nothing more to say, so clear the
5170+
* error message.
51715171
*/
5172-
handle->tstamp_type_list = NULL;
5173-
return 0;
5172+
ebuf[0] = '\0';
5173+
return PCAP_ERROR_NO_SUCH_DEVICE;
51745174

51755175
default:
51765176
/*

0 commit comments

Comments
 (0)