mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 12:41:29 +00:00
Use pcap_open and pcap_set_immediate_mode in nsock. Closes #1291
This commit is contained in:
@@ -90,3 +90,4 @@
|
|||||||
#undef HAVE_KQUEUE
|
#undef HAVE_KQUEUE
|
||||||
|
|
||||||
#undef PCAP_NETMASK_UNKNOWN
|
#undef PCAP_NETMASK_UNKNOWN
|
||||||
|
#undef HAVE_PCAP_SET_IMMEDIATE_MODE
|
||||||
|
|||||||
16
nsock/src/configure
vendored
16
nsock/src/configure
vendored
@@ -3639,7 +3639,23 @@ if test "$with_libpcap" != "no" -a "$have_libpcap" = "no"; then
|
|||||||
LIBPCAP_LIB=${top_nmap_srcdir}/libpcap
|
LIBPCAP_LIB=${top_nmap_srcdir}/libpcap
|
||||||
LIBPCAP_LIBS=${LIBPCAP_LIB}/libpcap.a
|
LIBPCAP_LIBS=${LIBPCAP_LIB}/libpcap.a
|
||||||
have_libpcap=yes
|
have_libpcap=yes
|
||||||
|
|
||||||
|
$as_echo "#define HAVE_PCAP_SET_IMMEDIATE_MODE 1" >>confdefs.h
|
||||||
|
|
||||||
|
else
|
||||||
|
for ac_func in pcap_set_immediate_mode
|
||||||
|
do :
|
||||||
|
ac_fn_c_check_func "$LINENO" "pcap_set_immediate_mode" "ac_cv_func_pcap_set_immediate_mode"
|
||||||
|
if test "x$ac_cv_func_pcap_set_immediate_mode" = xyes; then :
|
||||||
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
#define HAVE_PCAP_SET_IMMEDIATE_MODE 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
fi
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
if test "$have_libpcap" != "no"; then
|
if test "$have_libpcap" != "no"; then
|
||||||
|
|
||||||
$as_echo "#define HAVE_PCAP 1" >>confdefs.h
|
$as_echo "#define HAVE_PCAP 1" >>confdefs.h
|
||||||
|
|||||||
@@ -161,7 +161,11 @@ if test "$with_libpcap" != "no" -a "$have_libpcap" = "no"; then
|
|||||||
LIBPCAP_LIB=${top_nmap_srcdir}/libpcap
|
LIBPCAP_LIB=${top_nmap_srcdir}/libpcap
|
||||||
LIBPCAP_LIBS=${LIBPCAP_LIB}/libpcap.a
|
LIBPCAP_LIBS=${LIBPCAP_LIB}/libpcap.a
|
||||||
have_libpcap=yes
|
have_libpcap=yes
|
||||||
|
AC_DEFINE(HAVE_PCAP_SET_IMMEDIATE_MODE, 1, [Included libpcap has pcap_set_immediate_mode])
|
||||||
|
else
|
||||||
|
AC_CHECK_FUNCS([pcap_set_immediate_mode])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$have_libpcap" != "no"; then
|
if test "$have_libpcap" != "no"; then
|
||||||
AC_DEFINE(HAVE_PCAP, 1, [libpcap is available])
|
AC_DEFINE(HAVE_PCAP, 1, [libpcap is available])
|
||||||
if test "${LIBPCAP_INC+set}" = "set"; then
|
if test "${LIBPCAP_INC+set}" = "set"; then
|
||||||
|
|||||||
@@ -197,23 +197,6 @@ static int nsock_pcap_get_l3_offset(pcap_t *pt, int *dl) {
|
|||||||
return (offset);
|
return (offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nsock_pcap_try_open(struct npool *nsp, mspcap *mp, const char *dev,
|
|
||||||
int snaplen, int promisc, int timeout_ms,
|
|
||||||
char *errbuf) {
|
|
||||||
/* TODO: Convert from pcap_open_live to pcap_create and set appropriate options.
|
|
||||||
* Maybe expose an API for setting said options. We can't assume that all
|
|
||||||
* Nsock apps will want the same options that Nmap wants, especially the
|
|
||||||
* options Nmap wants for port scanning.
|
|
||||||
*/
|
|
||||||
mp->pt = pcap_open_live(dev, snaplen, promisc, timeout_ms, errbuf);
|
|
||||||
if (!mp->pt) {
|
|
||||||
nsock_log_error("pcap_open_live(%s, %d, %d, %d) failed with error: %s",
|
|
||||||
dev, snaplen, promisc, timeout_ms, errbuf);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert new nsiod to pcap descriptor. Other parameters have
|
/* Convert new nsiod to pcap descriptor. Other parameters have
|
||||||
* the same meaning as for pcap_open_live in pcap(3).
|
* the same meaning as for pcap_open_live in pcap(3).
|
||||||
* device : pcap-style device name
|
* device : pcap-style device name
|
||||||
@@ -270,23 +253,54 @@ int nsock_pcap_open(nsock_pool nsp, nsock_iod nsiod, const char *pcap_device,
|
|||||||
"(promisc=%i snaplen=%i to_ms=%i) (IOD #%li)",
|
"(promisc=%i snaplen=%i to_ms=%i) (IOD #%li)",
|
||||||
pcap_device,bpf, promisc, snaplen, to_ms, nsi->id);
|
pcap_device,bpf, promisc, snaplen, to_ms, nsi->id);
|
||||||
|
|
||||||
failed = 0;
|
#ifdef __amigaos__
|
||||||
do {
|
// Amiga doesn't have pcap_create
|
||||||
rc = nsock_pcap_try_open(ms, mp, pcap_device, snaplen, promisc, to_ms, errbuf);
|
// TODO: Does Nmap still work on Amiga?
|
||||||
if (rc) {
|
mp->pt = pcap_open_live(pcap_device, snaplen, promisc, to_ms, errbuf);
|
||||||
failed++;
|
if (!mp->pt) {
|
||||||
nsock_log_error("Will wait %d seconds then retry.", 4 * failed);
|
nsock_log_error("pcap_open_live(%s, %d, %d, %d) failed with error: %s",
|
||||||
sleep(4 * failed);
|
pcap_device, snaplen, promisc, to_ms, errbuf);
|
||||||
}
|
|
||||||
} while (rc && failed < PCAP_OPEN_MAX_RETRIES);
|
|
||||||
|
|
||||||
if (rc) {
|
|
||||||
nsock_log_error("pcap_open_live(%s, %d, %d, %d) failed %d times.",
|
|
||||||
pcap_device, snaplen, promisc, to_ms, failed);
|
|
||||||
nsock_log_error(PCAP_FAILURE_EXPL_MESSAGE);
|
nsock_log_error(PCAP_FAILURE_EXPL_MESSAGE);
|
||||||
nsock_log_error("Can't open pcap! Are you root?");
|
nsock_log_error("Can't open pcap! Are you root?");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
mp->pt = pcap_create(pcap_device, errbuf);
|
||||||
|
if (!mp->pt) {
|
||||||
|
nsock_log_error("pcap_create(%s) failed with error: %s", pcap_device, errbuf);
|
||||||
|
nsock_log_error(PCAP_FAILURE_EXPL_MESSAGE);
|
||||||
|
nsock_log_error("Can't open pcap! Are you root?");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MY_PCAP_SET(func, p_t, val) do {\
|
||||||
|
failed = func(p_t, val);\
|
||||||
|
if (failed) {\
|
||||||
|
nsock_log_error(#func "(%d) FAILED: %d.", val, failed);\
|
||||||
|
pcap_close(p_t);\
|
||||||
|
return -1;\
|
||||||
|
}\
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
MY_PCAP_SET(pcap_set_snaplen, mp->pt, snaplen);
|
||||||
|
MY_PCAP_SET(pcap_set_promisc, mp->pt, promisc);
|
||||||
|
MY_PCAP_SET(pcap_set_timeout, mp->pt, to_ms);
|
||||||
|
#ifdef HAVE_PCAP_SET_IMMEDIATE_MODE
|
||||||
|
MY_PCAP_SET(pcap_set_immediate_mode, mp->pt, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
failed = pcap_activate(mp->pt);
|
||||||
|
if (failed < 0) {
|
||||||
|
// PCAP error
|
||||||
|
nsock_log_error("pcap_activate(%s) FAILED: %s.", pcap_device, pcap_geterr(mp->pt));
|
||||||
|
pcap_close(mp->pt);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (failed > 0) {
|
||||||
|
// PCAP warning, report but assume it'll still work
|
||||||
|
nsock_log_error("pcap_activate(%s) WARNING: %s.", pcap_device, pcap_geterr(mp->pt));
|
||||||
|
}
|
||||||
|
#endif /* not __amigaos__ */
|
||||||
|
|
||||||
rc = nsock_pcap_set_filter(ms, mp->pt, pcap_device, bpf);
|
rc = nsock_pcap_set_filter(ms, mp->pt, pcap_device, bpf);
|
||||||
if (rc)
|
if (rc)
|
||||||
@@ -308,18 +322,21 @@ int nsock_pcap_open(nsock_pool nsp, nsock_iod nsiod, const char *pcap_device,
|
|||||||
#endif
|
#endif
|
||||||
mp->readsd_count = 0;
|
mp->readsd_count = 0;
|
||||||
|
|
||||||
|
#ifndef HAVE_PCAP_SET_IMMEDIATE_MODE
|
||||||
|
/* This is already handled by pcap_set_immediate_mode if available */
|
||||||
|
#ifdef BIOCIMMEDIATE
|
||||||
/* Without setting this ioctl, some systems (BSDs, though it depends on the
|
/* Without setting this ioctl, some systems (BSDs, though it depends on the
|
||||||
* release) will buffer packets in non-blocking mode and only return them in a
|
* release) will buffer packets in non-blocking mode and only return them in a
|
||||||
* bunch when the buffer is full. Setting the ioctl makes each one be
|
* bunch when the buffer is full. Setting the ioctl makes each one be
|
||||||
* delivered immediately. This is how Linux works by default. See the comments
|
* delivered immediately. This is how Linux works by default. See the comments
|
||||||
* surrounding the setting of BIOCIMMEDIATE in libpcap/pcap-bpf.c. */
|
* surrounding the setting of BIOCIMMEDIATE in libpcap/pcap-bpf.c. */
|
||||||
#ifdef BIOCIMMEDIATE
|
|
||||||
if (mp->pcap_desc != -1) {
|
if (mp->pcap_desc != -1) {
|
||||||
int immediate = 1;
|
int immediate = 1;
|
||||||
|
|
||||||
if (ioctl(mp->pcap_desc, BIOCIMMEDIATE, &immediate) < 0)
|
if (ioctl(mp->pcap_desc, BIOCIMMEDIATE, &immediate) < 0)
|
||||||
fatal("Cannot set BIOCIMMEDIATE on pcap descriptor");
|
fatal("Cannot set BIOCIMMEDIATE on pcap descriptor");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Set device non-blocking */
|
/* Set device non-blocking */
|
||||||
|
|||||||
Reference in New Issue
Block a user