Support for libdlpi, and for enabling "passive mode" on Solaris systems
that support it, from Sagun Shakya.
This commit is contained in:
parent
e9c012f5fd
commit
e598e9e145
3
FILES
3
FILES
|
@ -33,6 +33,8 @@ config.h.in
|
|||
config.sub
|
||||
configure
|
||||
configure.in
|
||||
dlpisubs.c
|
||||
dlpisubs.h
|
||||
etherent.c
|
||||
ethertype.h
|
||||
fad-getad.c
|
||||
|
@ -94,6 +96,7 @@ pcap-dos.c
|
|||
pcap-dos.h
|
||||
pcap-enet.c
|
||||
pcap-int.h
|
||||
pcap-libdlpi.c
|
||||
pcap-linux.c
|
||||
pcap-namedb.h
|
||||
pcap-nit.c
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.21.2.3 2008-01-06 21:14:55 guy Exp $ (LBL)
|
||||
@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.21.2.4 2008-03-13 18:16:37 guy Exp $ (LBL)
|
||||
|
||||
To build libpcap, run "./configure" (a shell script). The configure
|
||||
script will determine your system attributes and generate an
|
||||
|
@ -327,6 +327,8 @@ config.h.in - autoconf input
|
|||
config.sub - autoconf support
|
||||
configure - configure script (run this first)
|
||||
configure.in - configure script source
|
||||
dlpisubs.c - DLPI-related functions for pcap-dlpi.c and pcap-libdlpi.c
|
||||
dlpisubs.h - DLPI-related function declarations
|
||||
etherent.c - /etc/ethers support routines
|
||||
ethertype.h - Ethernet protocol types and names definitions
|
||||
fad-getad.c - pcap_findalldevs() for systems with getifaddrs()
|
||||
|
@ -370,6 +372,7 @@ pcap-dos.c - MS-DOS capture support
|
|||
pcap-dos.h - headers for MS-DOS capture support
|
||||
pcap-enet.c - enet support
|
||||
pcap-int.h - internal libpcap definitions
|
||||
pcap-libdlpi.c - Data Link Provider Interface support for systems with libdlpi
|
||||
pcap-linux.c - Linux packet socket support
|
||||
pcap-namedb.h - header for backwards compatibility
|
||||
pcap-nit.c - SunOS Network Interface Tap support
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
dnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.86.2.2 2008-02-06 11:20:05 guy Exp $ (LBL)
|
||||
dnl @(#) $Header: /tcpdump/master/libpcap/aclocal.m4,v 1.86.2.3 2008-03-13 18:16:37 guy Exp $ (LBL)
|
||||
dnl
|
||||
dnl Copyright (c) 1995, 1996, 1997, 1998
|
||||
dnl The Regents of the University of California. All rights reserved.
|
||||
|
@ -903,3 +903,30 @@ AC_DEFUN(AC_LBL_TPACKET_STATS,
|
|||
if test $ac_cv_lbl_tpacket_stats = yes; then
|
||||
AC_DEFINE(HAVE_TPACKET_STATS,1,[if if_packet.h has tpacket_stats defined])
|
||||
fi])
|
||||
|
||||
dnl
|
||||
dnl Checks to see if Solaris has the dl_passive_req_t struct defined
|
||||
dnl in <sys/dlpi.h>.
|
||||
dnl
|
||||
dnl usage:
|
||||
dnl
|
||||
dnl AC_LBL_DL_PASSIVE_REQ_T
|
||||
dnl
|
||||
dnl results:
|
||||
dnl
|
||||
dnl HAVE_DLPI_PASSIVE (defined)
|
||||
dnl
|
||||
AC_DEFUN(AC_LBL_DL_PASSIVE_REQ_T,
|
||||
[AC_MSG_CHECKING(if dl_passive_req_t struct exists)
|
||||
AC_CACHE_VAL(ac_cv_lbl_has_dl_passive_req_t,
|
||||
AC_TRY_COMPILE([
|
||||
# include <sys/types.h>
|
||||
# include <sys/dlpi.h>],
|
||||
[u_int i = sizeof(dl_passive_req_t)],
|
||||
ac_cv_lbl_has_dl_passive_req_t=yes,
|
||||
ac_cv_lbl_has_dl_passive_req_t=no))
|
||||
AC_MSG_RESULT($ac_cv_lbl_has_dl_passive_req_t)
|
||||
if test $ac_cv_lbl_has_dl_passive_req_t = yes ; then
|
||||
AC_DEFINE(HAVE_DLPI_PASSIVE,1,[if passive_req_t primitive
|
||||
exists])
|
||||
fi])
|
||||
|
|
|
@ -32,6 +32,9 @@
|
|||
/* define if you have a /dev/dlpi */
|
||||
#undef HAVE_DEV_DLPI
|
||||
|
||||
/* if passive_req_t primitive exists */
|
||||
#undef HAVE_DLPI_PASSIVE
|
||||
|
||||
/* Define to 1 if you have the `ether_hostton' function. */
|
||||
#undef HAVE_ETHER_HOSTTON
|
||||
|
||||
|
@ -50,6 +53,9 @@
|
|||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* if libdlpi exists */
|
||||
#undef HAVE_LIBDLPI
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#undef HAVE_LIMITS_H
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#! /bin/sh
|
||||
# From configure.in Revision: 1.138.2.7 .
|
||||
# From configure.in Revision: 1.138.2.8 .
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.59.
|
||||
#
|
||||
|
@ -5999,7 +5999,96 @@ elif test -r /usr/include/odmi.h ; then
|
|||
#
|
||||
V_PCAP=bpf
|
||||
elif test -r /usr/include/sys/dlpi.h ; then
|
||||
V_PCAP=dlpi
|
||||
#
|
||||
# Checks to see if Solaris has the public libdlpi(3LIB) library.
|
||||
# Note: The existence of /usr/include/libdlpi.h does not mean it is the
|
||||
# public libdlpi(3LIB) version. Before libdlpi was made public, a
|
||||
# private version also existed, which did not have the same APIs.
|
||||
# Due to a gcc bug, the default search path for 32-bit libraries does
|
||||
# not include /lib, we add it explicitly here.
|
||||
# [http://bugs.opensolaris.org/view_bug.do?bug_id=6619485].
|
||||
# Also, due to the bug above applications that link to libpcap with
|
||||
# libdlpi will have to add "-L/lib" option to "configure".
|
||||
#
|
||||
saved_ldflags=$LDFLAGS
|
||||
LDFLAGS="$LIBS -L/lib"
|
||||
echo "$as_me:$LINENO: checking for dlpi_walk in -ldlpi" >&5
|
||||
echo $ECHO_N "checking for dlpi_walk in -ldlpi... $ECHO_C" >&6
|
||||
if test "${ac_cv_lib_dlpi_dlpi_walk+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-ldlpi $LIBS"
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any gcc2 internal prototype to avoid an error. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
/* We use char because int might match the return type of a gcc2
|
||||
builtin and then its argument prototype would still apply. */
|
||||
char dlpi_walk ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
dlpi_walk ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
|
||||
(eval $ac_link) 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -z "$ac_c_werror_flag"
|
||||
|| test ! -s conftest.err'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; } &&
|
||||
{ ac_try='test -s conftest$ac_exeext'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
ac_cv_lib_dlpi_dlpi_walk=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_cv_lib_dlpi_dlpi_walk=no
|
||||
fi
|
||||
rm -f conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: $ac_cv_lib_dlpi_dlpi_walk" >&5
|
||||
echo "${ECHO_T}$ac_cv_lib_dlpi_dlpi_walk" >&6
|
||||
if test $ac_cv_lib_dlpi_dlpi_walk = yes; then
|
||||
LIBS="-ldlpi $LIBS"
|
||||
V_PCAP=libdlpi
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_LIBDLPI 1
|
||||
_ACEOF
|
||||
|
||||
else
|
||||
V_PCAP=dlpi
|
||||
fi
|
||||
|
||||
LDFLAGS=$saved_ldflags
|
||||
elif test -c /dev/bpf0 ; then # check again in case not readable
|
||||
V_PCAP=bpf
|
||||
elif test -c /dev/enet ; then # check again in case not readable
|
||||
|
@ -6291,148 +6380,7 @@ else
|
|||
#
|
||||
case "$V_PCAP" in
|
||||
|
||||
dlpi)
|
||||
#
|
||||
# This might be Solaris 8 or later, with
|
||||
# SIOCGLIFCONF, or it might be some other OS
|
||||
# or some older version of Solaris, with
|
||||
# just SIOCGIFCONF.
|
||||
#
|
||||
echo "$as_me:$LINENO: checking whether we have SIOCGLIFCONF" >&5
|
||||
echo $ECHO_N "checking whether we have SIOCGLIFCONF... $ECHO_C" >&6
|
||||
if test "${ac_cv_lbl_have_siocglifconf+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <sys/param.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
ioctl(0, SIOCGLIFCONF, (char *)0);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
|
||||
(eval $ac_compile) 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -z "$ac_c_werror_flag"
|
||||
|| test ! -s conftest.err'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; } &&
|
||||
{ ac_try='test -s conftest.$ac_objext'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
ac_cv_lbl_have_siocglifconf=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_cv_lbl_have_siocglifconf=no
|
||||
fi
|
||||
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
|
||||
echo "$as_me:$LINENO: result: $ac_cv_lbl_have_siocglifconf" >&5
|
||||
echo "${ECHO_T}$ac_cv_lbl_have_siocglifconf" >&6
|
||||
if test $ac_cv_lbl_have_siocglifconf = yes ; then
|
||||
V_FINDALLDEVS=glifc
|
||||
else
|
||||
V_FINDALLDEVS=gifc
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
#
|
||||
# Assume we just have SIOCGIFCONF.
|
||||
# (XXX - on at least later Linux kernels, there's
|
||||
# another mechanism, and we should be using that
|
||||
# instead.)
|
||||
#
|
||||
V_FINDALLDEVS=gifc
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
fi;
|
||||
|
||||
echo "$as_me:$LINENO: checking if --enable-ipv6 option is specified" >&5
|
||||
echo $ECHO_N "checking if --enable-ipv6 option is specified... $ECHO_C" >&6
|
||||
# Check whether --enable-ipv6 or --disable-ipv6 was given.
|
||||
if test "${enable_ipv6+set}" = set; then
|
||||
enableval="$enable_ipv6"
|
||||
|
||||
fi;
|
||||
if test "$enable_ipv6" = "yes"; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define INET6 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: ${enable_ipv6-no}" >&5
|
||||
echo "${ECHO_T}${enable_ipv6-no}" >&6
|
||||
|
||||
echo "$as_me:$LINENO: checking whether to build optimizer debugging code" >&5
|
||||
echo $ECHO_N "checking whether to build optimizer debugging code... $ECHO_C" >&6
|
||||
# Check whether --enable-optimizer-dbg or --disable-optimizer-dbg was given.
|
||||
if test "${enable_optimizer_dbg+set}" = set; then
|
||||
enableval="$enable_optimizer_dbg"
|
||||
|
||||
fi;
|
||||
if test "$enable_optimizer_dbg" = "yes"; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define BDEBUG 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: ${enable_optimizer_dbg-no}" >&5
|
||||
echo "${ECHO_T}${enable_optimizer_dbg-no}" >&6
|
||||
|
||||
echo "$as_me:$LINENO: checking whether to build parser debugging code" >&5
|
||||
echo $ECHO_N "checking whether to build parser debugging code... $ECHO_C" >&6
|
||||
# Check whether --enable-yydebug or --disable-yydebug was given.
|
||||
if test "${enable_yydebug+set}" = set; then
|
||||
enableval="$enable_yydebug"
|
||||
|
||||
fi;
|
||||
if test "$enable_yydebug" = "yes"; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define YYDEBUG 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: ${enable_yydebug-no}" >&5
|
||||
echo "${ECHO_T}${enable_yydebug-no}" >&6
|
||||
|
||||
case "$V_PCAP" in
|
||||
|
||||
dlpi)
|
||||
dlpi|libdlpi)
|
||||
|
||||
|
||||
for ac_header in sys/bufmod.h sys/dlpi_ext.h
|
||||
|
@ -6584,6 +6532,151 @@ fi
|
|||
|
||||
done
|
||||
|
||||
#
|
||||
# This might be Solaris 8 or later, with
|
||||
# SIOCGLIFCONF, or it might be some other OS
|
||||
# or some older version of Solaris, with
|
||||
# just SIOCGIFCONF.
|
||||
#
|
||||
echo "$as_me:$LINENO: checking whether we have SIOCGLIFCONF" >&5
|
||||
echo $ECHO_N "checking whether we have SIOCGLIFCONF... $ECHO_C" >&6
|
||||
if test "${ac_cv_lbl_have_siocglifconf+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <sys/param.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
ioctl(0, SIOCGLIFCONF, (char *)0);
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
|
||||
(eval $ac_compile) 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -z "$ac_c_werror_flag"
|
||||
|| test ! -s conftest.err'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; } &&
|
||||
{ ac_try='test -s conftest.$ac_objext'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
ac_cv_lbl_have_siocglifconf=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_cv_lbl_have_siocglifconf=no
|
||||
fi
|
||||
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
|
||||
echo "$as_me:$LINENO: result: $ac_cv_lbl_have_siocglifconf" >&5
|
||||
echo "${ECHO_T}$ac_cv_lbl_have_siocglifconf" >&6
|
||||
if test $ac_cv_lbl_have_siocglifconf = yes ; then
|
||||
V_FINDALLDEVS=glifc
|
||||
else
|
||||
V_FINDALLDEVS=gifc
|
||||
fi
|
||||
#
|
||||
# Needed for common functions used by pcap-[dlpi,libdlpi].c
|
||||
#
|
||||
SSRC="dlpisubs.c"
|
||||
;;
|
||||
|
||||
*)
|
||||
#
|
||||
# Assume we just have SIOCGIFCONF.
|
||||
# (XXX - on at least later Linux kernels, there's
|
||||
# another mechanism, and we should be using that
|
||||
# instead.)
|
||||
#
|
||||
V_FINDALLDEVS=gifc
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
fi;
|
||||
|
||||
echo "$as_me:$LINENO: checking if --enable-ipv6 option is specified" >&5
|
||||
echo $ECHO_N "checking if --enable-ipv6 option is specified... $ECHO_C" >&6
|
||||
# Check whether --enable-ipv6 or --disable-ipv6 was given.
|
||||
if test "${enable_ipv6+set}" = set; then
|
||||
enableval="$enable_ipv6"
|
||||
|
||||
fi;
|
||||
if test "$enable_ipv6" = "yes"; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define INET6 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: ${enable_ipv6-no}" >&5
|
||||
echo "${ECHO_T}${enable_ipv6-no}" >&6
|
||||
|
||||
echo "$as_me:$LINENO: checking whether to build optimizer debugging code" >&5
|
||||
echo $ECHO_N "checking whether to build optimizer debugging code... $ECHO_C" >&6
|
||||
# Check whether --enable-optimizer-dbg or --disable-optimizer-dbg was given.
|
||||
if test "${enable_optimizer_dbg+set}" = set; then
|
||||
enableval="$enable_optimizer_dbg"
|
||||
|
||||
fi;
|
||||
if test "$enable_optimizer_dbg" = "yes"; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define BDEBUG 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: ${enable_optimizer_dbg-no}" >&5
|
||||
echo "${ECHO_T}${enable_optimizer_dbg-no}" >&6
|
||||
|
||||
echo "$as_me:$LINENO: checking whether to build parser debugging code" >&5
|
||||
echo $ECHO_N "checking whether to build parser debugging code... $ECHO_C" >&6
|
||||
# Check whether --enable-yydebug or --disable-yydebug was given.
|
||||
if test "${enable_yydebug+set}" = set; then
|
||||
enableval="$enable_yydebug"
|
||||
|
||||
fi;
|
||||
if test "$enable_yydebug" = "yes"; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define YYDEBUG 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
echo "$as_me:$LINENO: result: ${enable_yydebug-no}" >&5
|
||||
echo "${ECHO_T}${enable_yydebug-no}" >&6
|
||||
|
||||
case "$V_PCAP" in
|
||||
|
||||
dlpi)
|
||||
echo "$as_me:$LINENO: checking for /dev/dlpi device" >&5
|
||||
echo $ECHO_N "checking for /dev/dlpi device... $ECHO_C" >&6
|
||||
if test -c /dev/dlpi ; then
|
||||
|
@ -6613,6 +6706,73 @@ _ACEOF
|
|||
echo "${ECHO_T}no" >&6
|
||||
fi
|
||||
fi
|
||||
#
|
||||
# This check is for Solaris with DLPI support for passive modes.
|
||||
# See dlpi(7P) for more details.
|
||||
#
|
||||
echo "$as_me:$LINENO: checking if dl_passive_req_t struct exists" >&5
|
||||
echo $ECHO_N "checking if dl_passive_req_t struct exists... $ECHO_C" >&6
|
||||
if test "${ac_cv_lbl_has_dl_passive_req_t+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
# include <sys/types.h>
|
||||
# include <sys/dlpi.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
u_int i = sizeof(dl_passive_req_t)
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
|
||||
(eval $ac_compile) 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -z "$ac_c_werror_flag"
|
||||
|| test ! -s conftest.err'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; } &&
|
||||
{ ac_try='test -s conftest.$ac_objext'
|
||||
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
ac_cv_lbl_has_dl_passive_req_t=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_cv_lbl_has_dl_passive_req_t=no
|
||||
fi
|
||||
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
fi
|
||||
|
||||
echo "$as_me:$LINENO: result: $ac_cv_lbl_has_dl_passive_req_t" >&5
|
||||
echo "${ECHO_T}$ac_cv_lbl_has_dl_passive_req_t" >&6
|
||||
if test $ac_cv_lbl_has_dl_passive_req_t = yes ; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_DLPI_PASSIVE 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
;;
|
||||
|
||||
linux)
|
||||
|
|
37
configure.in
37
configure.in
|
@ -1,4 +1,4 @@
|
|||
dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.138.2.7 2008-02-04 21:10:36 guy Exp $ (LBL)
|
||||
dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.138.2.8 2008-03-13 18:16:37 guy Exp $ (LBL)
|
||||
dnl
|
||||
dnl Copyright (c) 1994, 1995, 1996, 1997
|
||||
dnl The Regents of the University of California. All rights reserved.
|
||||
|
@ -6,7 +6,7 @@ dnl
|
|||
dnl Process this file with autoconf to produce a configure script.
|
||||
dnl
|
||||
|
||||
AC_REVISION($Revision: 1.138.2.7 $)
|
||||
AC_REVISION($Revision: 1.138.2.8 $)
|
||||
AC_PREREQ(2.50)
|
||||
AC_INIT(pcap.c)
|
||||
|
||||
|
@ -252,7 +252,25 @@ elif test -r /usr/include/odmi.h ; then
|
|||
#
|
||||
V_PCAP=bpf
|
||||
elif test -r /usr/include/sys/dlpi.h ; then
|
||||
V_PCAP=dlpi
|
||||
#
|
||||
# Checks to see if Solaris has the public libdlpi(3LIB) library.
|
||||
# Note: The existence of /usr/include/libdlpi.h does not mean it is the
|
||||
# public libdlpi(3LIB) version. Before libdlpi was made public, a
|
||||
# private version also existed, which did not have the same APIs.
|
||||
# Due to a gcc bug, the default search path for 32-bit libraries does
|
||||
# not include /lib, we add it explicitly here.
|
||||
# [http://bugs.opensolaris.org/view_bug.do?bug_id=6619485].
|
||||
# Also, due to the bug above applications that link to libpcap with
|
||||
# libdlpi will have to add "-L/lib" option to "configure".
|
||||
#
|
||||
saved_ldflags=$LDFLAGS
|
||||
LDFLAGS="$LIBS -L/lib"
|
||||
AC_CHECK_LIB(dlpi, dlpi_walk,
|
||||
LIBS="-ldlpi $LIBS"
|
||||
V_PCAP=libdlpi
|
||||
AC_DEFINE(HAVE_LIBDLPI,1,[if libdlpi exists]),
|
||||
V_PCAP=dlpi)
|
||||
LDFLAGS=$saved_ldflags
|
||||
elif test -c /dev/bpf0 ; then # check again in case not readable
|
||||
V_PCAP=bpf
|
||||
elif test -c /dev/enet ; then # check again in case not readable
|
||||
|
@ -310,7 +328,8 @@ else
|
|||
#
|
||||
case "$V_PCAP" in
|
||||
|
||||
dlpi)
|
||||
dlpi|libdlpi)
|
||||
AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h)
|
||||
#
|
||||
# This might be Solaris 8 or later, with
|
||||
# SIOCGLIFCONF, or it might be some other OS
|
||||
|
@ -334,6 +353,10 @@ else
|
|||
else
|
||||
V_FINDALLDEVS=gifc
|
||||
fi
|
||||
#
|
||||
# Needed for common functions used by pcap-[dlpi,libdlpi].c
|
||||
#
|
||||
SSRC="dlpisubs.c"
|
||||
;;
|
||||
|
||||
*)
|
||||
|
@ -373,7 +396,6 @@ AC_MSG_RESULT(${enable_yydebug-no})
|
|||
case "$V_PCAP" in
|
||||
|
||||
dlpi)
|
||||
AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h)
|
||||
AC_MSG_CHECKING(for /dev/dlpi device)
|
||||
if test -c /dev/dlpi ; then
|
||||
AC_MSG_RESULT(yes)
|
||||
|
@ -389,6 +411,11 @@ dlpi)
|
|||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
fi
|
||||
#
|
||||
# This check is for Solaris with DLPI support for passive modes.
|
||||
# See dlpi(7P) for more details.
|
||||
#
|
||||
AC_LBL_DL_PASSIVE_REQ_T
|
||||
;;
|
||||
|
||||
linux)
|
||||
|
|
|
@ -0,0 +1,349 @@
|
|||
/*
|
||||
* This code is derived from code formerly in pcap-dlpi.c, originally
|
||||
* contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk), University College
|
||||
* London, and subsequently modified by Guy Harris (guy@alum.mit.edu),
|
||||
* Mark Pizzolato <List-tcpdump-workers@subscriptions.pizzolato.net>,
|
||||
* Mark C. Brown (mbrown@hp.com), and Sagun Shakya <Sagun.Shakya@Sun.COM>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains dlpi/libdlpi related common functions used
|
||||
* by pcap-[dlpi,libdlpi].c.
|
||||
*/
|
||||
#ifndef lint
|
||||
static const char rcsid[] _U_ =
|
||||
"@(#) $Header: /tcpdump/master/libpcap/dlpisubs.c,v 1.1.2.1 2008-03-13 18:17:17 guy Exp $ (LBL)";
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
/*
|
||||
* Size of a bufmod chunk to pass upstream; that appears to be the
|
||||
* biggest value to which you can set it, and setting it to that value
|
||||
* (which is bigger than what appears to be the Solaris default of 8192)
|
||||
* reduces the number of packet drops.
|
||||
*/
|
||||
#define CHUNKSIZE 65536
|
||||
|
||||
/*
|
||||
* Size of the buffer to allocate for packet data we read; it must be
|
||||
* large enough to hold a chunk.
|
||||
*/
|
||||
#define PKTBUFSIZE CHUNKSIZE
|
||||
|
||||
#else /* HAVE_SYS_BUFMOD_H */
|
||||
|
||||
/*
|
||||
* Size of the buffer to allocate for packet data we read; this is
|
||||
* what the value used to be - there's no particular reason why it
|
||||
* should be tied to MAXDLBUF, but we'll leave it as this for now.
|
||||
*/
|
||||
#define PKTBUFSIZE (MAXDLBUF * sizeof(bpf_u_int32))
|
||||
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
#include <sys/bufmod.h>
|
||||
#endif
|
||||
#include <sys/dlpi.h>
|
||||
#include <sys/stream.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <memory.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stropts.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "pcap-int.h"
|
||||
#include "dlpisubs.h"
|
||||
|
||||
static void pcap_stream_err(const char *, int, char *);
|
||||
|
||||
/*
|
||||
* Get the packet statistics.
|
||||
*/
|
||||
int
|
||||
pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps)
|
||||
{
|
||||
|
||||
/*
|
||||
* "ps_recv" counts packets handed to the filter, not packets
|
||||
* that passed the filter. As filtering is done in userland,
|
||||
* this would not include packets dropped because we ran out
|
||||
* of buffer space; in order to make this more like other
|
||||
* platforms (Linux 2.4 and later, BSDs with BPF), where the
|
||||
* "packets received" count includes packets received but dropped
|
||||
* due to running out of buffer space, and to keep from confusing
|
||||
* applications that, for example, compute packet drop percentages,
|
||||
* we also make it count packets dropped by "bufmod" (otherwise we
|
||||
* might run the risk of the packet drop count being bigger than
|
||||
* the received-packet count).
|
||||
*
|
||||
* "ps_drop" counts packets dropped by "bufmod" because of
|
||||
* flow control requirements or resource exhaustion; it doesn't
|
||||
* count packets dropped by the interface driver, or packets
|
||||
* dropped upstream. As filtering is done in userland, it counts
|
||||
* packets regardless of whether they would've passed the filter.
|
||||
*
|
||||
* These statistics don't include packets not yet read from
|
||||
* the kernel by libpcap, but they may include packets not
|
||||
* yet read from libpcap by the application.
|
||||
*/
|
||||
*ps = p->md.stat;
|
||||
|
||||
/*
|
||||
* Add in the drop count, as per the above comment.
|
||||
*/
|
||||
ps->ps_recv += ps->ps_drop;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop through the packets and call the callback for each packet.
|
||||
* Return the number of packets read.
|
||||
*/
|
||||
int
|
||||
pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user,
|
||||
int count, u_char *bufp, int len)
|
||||
{
|
||||
int n, caplen, origlen;
|
||||
u_char *ep, *pk;
|
||||
struct pcap_pkthdr pkthdr;
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
struct sb_hdr *sbp;
|
||||
#ifdef LBL_ALIGN
|
||||
struct sb_hdr sbhdr;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Loop through packets */
|
||||
ep = bufp + len;
|
||||
n = 0;
|
||||
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
while (bufp < ep) {
|
||||
/*
|
||||
* Has "pcap_breakloop()" been called?
|
||||
* If so, return immediately - if we haven't read any
|
||||
* packets, clear the flag and return -2 to indicate
|
||||
* that we were told to break out of the loop, otherwise
|
||||
* leave the flag set, so that the *next* call will break
|
||||
* out of the loop without having read any packets, and
|
||||
* return the number of packets we've processed so far.
|
||||
*/
|
||||
if (p->break_loop) {
|
||||
if (n == 0) {
|
||||
p->break_loop = 0;
|
||||
return (-2);
|
||||
} else {
|
||||
p->bp = bufp;
|
||||
p->cc = ep - bufp;
|
||||
return (n);
|
||||
}
|
||||
}
|
||||
#ifdef LBL_ALIGN
|
||||
if ((long)bufp & 3) {
|
||||
sbp = &sbhdr;
|
||||
memcpy(sbp, bufp, sizeof(*sbp));
|
||||
} else
|
||||
#endif
|
||||
sbp = (struct sb_hdr *)bufp;
|
||||
p->md.stat.ps_drop = sbp->sbh_drops;
|
||||
pk = bufp + sizeof(*sbp);
|
||||
bufp += sbp->sbh_totlen;
|
||||
origlen = sbp->sbh_origlen;
|
||||
caplen = sbp->sbh_msglen;
|
||||
#else
|
||||
origlen = len;
|
||||
caplen = min(p->snapshot, len);
|
||||
pk = bufp;
|
||||
bufp += caplen;
|
||||
#endif
|
||||
++p->md.stat.ps_recv;
|
||||
if (bpf_filter(p->fcode.bf_insns, pk, origlen, caplen)) {
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec;
|
||||
pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec;
|
||||
#else
|
||||
(void) gettimeofday(&pkthdr.ts, NULL);
|
||||
#endif
|
||||
pkthdr.len = origlen;
|
||||
pkthdr.caplen = caplen;
|
||||
/* Insure caplen does not exceed snapshot */
|
||||
if (pkthdr.caplen > p->snapshot)
|
||||
pkthdr.caplen = p->snapshot;
|
||||
(*callback)(user, &pkthdr, pk);
|
||||
if (++n >= count && count >= 0) {
|
||||
p->cc = ep - bufp;
|
||||
p->bp = bufp;
|
||||
return (n);
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
}
|
||||
#endif
|
||||
p->cc = 0;
|
||||
return (n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the mac type. Returns -1 if no matching mac type found, otherwise 0.
|
||||
*/
|
||||
int
|
||||
pcap_process_mactype(pcap_t *p, u_int mactype, char *ebuf)
|
||||
{
|
||||
int retv = 0;
|
||||
|
||||
switch (mactype) {
|
||||
|
||||
case DL_CSMACD:
|
||||
case DL_ETHER:
|
||||
p->linktype = DLT_EN10MB;
|
||||
p->offset = 2;
|
||||
/*
|
||||
* This is (presumably) a real Ethernet capture; give it a
|
||||
* link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
|
||||
* that an application can let you choose it, in case you're
|
||||
* capturing DOCSIS traffic that a Cisco Cable Modem
|
||||
* Termination System is putting out onto an Ethernet (it
|
||||
* doesn't put an Ethernet header onto the wire, it puts raw
|
||||
* DOCSIS frames out on the wire inside the low-level
|
||||
* Ethernet framing).
|
||||
*/
|
||||
p->dlt_list = (u_int *)malloc(sizeof(u_int) * 2);
|
||||
/*
|
||||
* If that fails, just leave the list empty.
|
||||
*/
|
||||
if (p->dlt_list != NULL) {
|
||||
p->dlt_list[0] = DLT_EN10MB;
|
||||
p->dlt_list[1] = DLT_DOCSIS;
|
||||
p->dlt_count = 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case DL_FDDI:
|
||||
p->linktype = DLT_FDDI;
|
||||
p->offset = 3;
|
||||
break;
|
||||
|
||||
case DL_TPR:
|
||||
/* XXX - what about DL_TPB? Is that Token Bus? */
|
||||
p->linktype = DLT_IEEE802;
|
||||
p->offset = 2;
|
||||
break;
|
||||
|
||||
#ifdef HAVE_SOLARIS
|
||||
case DL_IPATM:
|
||||
p->linktype = DLT_SUNATM;
|
||||
p->offset = 0; /* works for LANE and LLC encapsulation */
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown mactype %u",
|
||||
mactype);
|
||||
retv = -1;
|
||||
}
|
||||
|
||||
return (retv);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
/*
|
||||
* Push and configure the buffer module. Returns -1 for error, otherwise 0.
|
||||
*/
|
||||
int
|
||||
pcap_conf_bufmod(pcap_t *p, int snaplen, int timeout, char *ebuf)
|
||||
{
|
||||
int retv = 0;
|
||||
|
||||
bpf_u_int32 ss, chunksize;
|
||||
|
||||
/* Non-standard call to get the data nicely buffered. */
|
||||
if (ioctl(p->fd, I_PUSH, "bufmod") != 0) {
|
||||
pcap_stream_err("I_PUSH bufmod", errno, ebuf);
|
||||
retv = -1;
|
||||
}
|
||||
|
||||
ss = snaplen;
|
||||
if (ss > 0 &&
|
||||
strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) {
|
||||
pcap_stream_err("SBIOCSSNAP", errno, ebuf);
|
||||
retv = -1;
|
||||
}
|
||||
|
||||
/* Set up the bufmod timeout. */
|
||||
if (timeout != 0) {
|
||||
struct timeval to;
|
||||
|
||||
to.tv_sec = timeout / 1000;
|
||||
to.tv_usec = (timeout * 1000) % 1000000;
|
||||
if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {
|
||||
pcap_stream_err("SBIOCSTIME", errno, ebuf);
|
||||
retv = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the chunk length. */
|
||||
chunksize = CHUNKSIZE;
|
||||
if (strioctl(p->fd, SBIOCSCHUNK, sizeof(chunksize), (char *)&chunksize)
|
||||
!= 0) {
|
||||
pcap_stream_err("SBIOCSCHUNKP", errno, ebuf);
|
||||
retv = -1;
|
||||
}
|
||||
|
||||
return (retv);
|
||||
}
|
||||
#endif /* HAVE_SYS_BUFMOD_H */
|
||||
|
||||
/*
|
||||
* Allocate data buffer. Returns -1 if memory allocation fails, else 0.
|
||||
*/
|
||||
int
|
||||
pcap_alloc_databuf(pcap_t *p, char *ebuf)
|
||||
{
|
||||
p->bufsize = PKTBUFSIZE;
|
||||
p->buffer = (u_char *)malloc(p->bufsize + p->offset);
|
||||
if (p->buffer == NULL) {
|
||||
strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue a STREAMS I_STR ioctl. Returns -1 on error, otherwise
|
||||
* length of returned data on success.
|
||||
*/
|
||||
int
|
||||
strioctl(int fd, int cmd, int len, char *dp)
|
||||
{
|
||||
struct strioctl str;
|
||||
int retv;
|
||||
|
||||
str.ic_cmd = cmd;
|
||||
str.ic_timout = -1;
|
||||
str.ic_len = len;
|
||||
str.ic_dp = dp;
|
||||
if ((retv = ioctl(fd, I_STR, &str)) < 0)
|
||||
return (retv);
|
||||
|
||||
return (str.ic_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write stream error message to errbuf.
|
||||
*/
|
||||
static void
|
||||
pcap_stream_err(const char *func, int err, char *errbuf)
|
||||
{
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", func, pcap_strerror(err));
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/dlpisubs.h,v 1.1.2.1 2008-03-13 18:17:17 guy Exp $
|
||||
*/
|
||||
|
||||
#ifndef dlpisubs_h
|
||||
#define dlpisubs_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Functions used by dlpisubs.c.
|
||||
*/
|
||||
int pcap_stats_dlpi(pcap_t *, struct pcap_stat *);
|
||||
int pcap_process_pkts(pcap_t *, pcap_handler, u_char *, int, u_char *, int);
|
||||
int pcap_process_mactype(pcap_t *, u_int, char *);
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
int pcap_conf_bufmod(pcap_t *, int, int, char *);
|
||||
#endif
|
||||
int pcap_alloc_databuf(pcap_t *, char *);
|
||||
int strioctl(int, int, int, char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
310
pcap-dlpi.c
310
pcap-dlpi.c
|
@ -22,7 +22,7 @@
|
|||
* University College London, and subsequently modified by
|
||||
* Guy Harris (guy@alum.mit.edu), Mark Pizzolato
|
||||
* <List-tcpdump-workers@subscriptions.pizzolato.net>,
|
||||
* and Mark C. Brown (mbrown@hp.com).
|
||||
* Mark C. Brown (mbrown@hp.com), and Sagun Shakya <Sagun.Shakya@Sun.COM>.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -70,7 +70,7 @@
|
|||
|
||||
#ifndef lint
|
||||
static const char rcsid[] _U_ =
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.116.2.3 2008-02-02 20:58:31 guy Exp $ (LBL)";
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.116.2.4 2008-03-13 18:16:37 guy Exp $ (LBL)";
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
|
@ -121,6 +121,7 @@ static const char rcsid[] _U_ =
|
|||
#endif
|
||||
|
||||
#include "pcap-int.h"
|
||||
#include "dlpisubs.h"
|
||||
|
||||
#ifdef HAVE_OS_PROTO_H
|
||||
#include "os-proto.h"
|
||||
|
@ -136,33 +137,6 @@ static const char rcsid[] _U_ =
|
|||
|
||||
#define MAXDLBUF 8192
|
||||
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
|
||||
/*
|
||||
* Size of a bufmod chunk to pass upstream; that appears to be the biggest
|
||||
* value to which you can set it, and setting it to that value (which
|
||||
* is bigger than what appears to be the Solaris default of 8192)
|
||||
* reduces the number of packet drops.
|
||||
*/
|
||||
#define CHUNKSIZE 65536
|
||||
|
||||
/*
|
||||
* Size of the buffer to allocate for packet data we read; it must be
|
||||
* large enough to hold a chunk.
|
||||
*/
|
||||
#define PKTBUFSIZE CHUNKSIZE
|
||||
|
||||
#else /* HAVE_SYS_BUFMOD_H */
|
||||
|
||||
/*
|
||||
* Size of the buffer to allocate for packet data we read; this is
|
||||
* what the value used to be - there's no particular reason why it
|
||||
* should be tied to MAXDLBUF, but we'll leave it as this for now.
|
||||
*/
|
||||
#define PKTBUFSIZE (MAXDLBUF * sizeof(bpf_u_int32))
|
||||
|
||||
#endif
|
||||
|
||||
/* Forwards */
|
||||
static char *split_dname(char *, int *, char *);
|
||||
static int dl_doattach(int, int, char *);
|
||||
|
@ -176,6 +150,11 @@ static int dlpromisconreq(int, bpf_u_int32, char *);
|
|||
static int dlokack(int, const char *, char *, char *);
|
||||
static int dlinforeq(int, char *);
|
||||
static int dlinfoack(int, char *, char *);
|
||||
|
||||
#ifdef HAVE_DLPI_PASSIVE
|
||||
static void dlpassive(int, char *);
|
||||
#endif
|
||||
|
||||
#ifdef DL_HP_RAWDLS
|
||||
static int dlrawdatareq(int, const u_char *, int);
|
||||
#endif
|
||||
|
@ -186,9 +165,6 @@ static char *dlprim(bpf_u_int32);
|
|||
static char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *);
|
||||
#endif
|
||||
static int send_request(int, char *, int, char *, char *);
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
static int strioctl(int, int, int, char *);
|
||||
#endif
|
||||
#ifdef HAVE_HPUX9
|
||||
static int dlpi_kread(int, off_t, void *, u_int, char *);
|
||||
#endif
|
||||
|
@ -196,42 +172,6 @@ static int dlpi_kread(int, off_t, void *, u_int, char *);
|
|||
static int get_dlpi_ppa(int, const char *, int, char *);
|
||||
#endif
|
||||
|
||||
static int
|
||||
pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps)
|
||||
{
|
||||
|
||||
/*
|
||||
* "ps_recv" counts packets handed to the filter, not packets
|
||||
* that passed the filter. As filtering is done in userland,
|
||||
* this would not include packets dropped because we ran out
|
||||
* of buffer space; in order to make this more like other
|
||||
* platforms (Linux 2.4 and later, BSDs with BPF), where the
|
||||
* "packets received" count includes packets received but dropped
|
||||
* due to running out of buffer space, and to keep from confusing
|
||||
* applications that, for example, compute packet drop percentages,
|
||||
* we also make it count packets dropped by "bufmod" (otherwise we
|
||||
* might run the risk of the packet drop count being bigger than
|
||||
* the received-packet count).
|
||||
*
|
||||
* "ps_drop" counts packets dropped by "bufmod" because of
|
||||
* flow control requirements or resource exhaustion; it doesn't
|
||||
* count packets dropped by the interface driver, or packets
|
||||
* dropped upstream. As filtering is done in userland, it counts
|
||||
* packets regardless of whether they would've passed the filter.
|
||||
*
|
||||
* These statistics don't include packets not yet read from
|
||||
* the kernel by libpcap, but they may include packets not
|
||||
* yet read from libpcap by the application.
|
||||
*/
|
||||
*ps = p->md.stat;
|
||||
|
||||
/*
|
||||
* Add in the drop count, as per the above comment.
|
||||
*/
|
||||
ps->ps_recv += ps->ps_drop;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* XXX Needed by HP-UX (at least) */
|
||||
static bpf_u_int32 ctlbuf[MAXDLBUF];
|
||||
static struct strbuf ctl = {
|
||||
|
@ -243,17 +183,10 @@ static struct strbuf ctl = {
|
|||
static int
|
||||
pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
{
|
||||
register int cc, n, caplen, origlen;
|
||||
register u_char *bp, *ep, *pk;
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
register struct sb_hdr *sbp;
|
||||
#ifdef LBL_ALIGN
|
||||
struct sb_hdr sbhdr;
|
||||
#endif
|
||||
#endif
|
||||
int cc;
|
||||
u_char *bp;
|
||||
int flags;
|
||||
struct strbuf data;
|
||||
struct pcap_pkthdr pkthdr;
|
||||
|
||||
flags = 0;
|
||||
cc = p->cc;
|
||||
|
@ -301,73 +234,7 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
|||
} else
|
||||
bp = p->bp;
|
||||
|
||||
/* Loop through packets */
|
||||
ep = bp + cc;
|
||||
n = 0;
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
while (bp < ep) {
|
||||
/*
|
||||
* Has "pcap_breakloop()" been called?
|
||||
* If so, return immediately - if we haven't read any
|
||||
* packets, clear the flag and return -2 to indicate
|
||||
* that we were told to break out of the loop, otherwise
|
||||
* leave the flag set, so that the *next* call will break
|
||||
* out of the loop without having read any packets, and
|
||||
* return the number of packets we've processed so far.
|
||||
*/
|
||||
if (p->break_loop) {
|
||||
if (n == 0) {
|
||||
p->break_loop = 0;
|
||||
return (-2);
|
||||
} else {
|
||||
p->bp = bp;
|
||||
p->cc = ep - bp;
|
||||
return (n);
|
||||
}
|
||||
}
|
||||
#ifdef LBL_ALIGN
|
||||
if ((long)bp & 3) {
|
||||
sbp = &sbhdr;
|
||||
memcpy(sbp, bp, sizeof(*sbp));
|
||||
} else
|
||||
#endif
|
||||
sbp = (struct sb_hdr *)bp;
|
||||
p->md.stat.ps_drop = sbp->sbh_drops;
|
||||
pk = bp + sizeof(*sbp);
|
||||
bp += sbp->sbh_totlen;
|
||||
origlen = sbp->sbh_origlen;
|
||||
caplen = sbp->sbh_msglen;
|
||||
#else
|
||||
origlen = cc;
|
||||
caplen = min(p->snapshot, cc);
|
||||
pk = bp;
|
||||
bp += caplen;
|
||||
#endif
|
||||
++p->md.stat.ps_recv;
|
||||
if (bpf_filter(p->fcode.bf_insns, pk, origlen, caplen)) {
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec;
|
||||
pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec;
|
||||
#else
|
||||
(void)gettimeofday(&pkthdr.ts, NULL);
|
||||
#endif
|
||||
pkthdr.len = origlen;
|
||||
pkthdr.caplen = caplen;
|
||||
/* Insure caplen does not exceed snapshot */
|
||||
if (pkthdr.caplen > p->snapshot)
|
||||
pkthdr.caplen = p->snapshot;
|
||||
(*callback)(user, &pkthdr, pk);
|
||||
if (++n >= cnt && cnt > 0) {
|
||||
p->cc = ep - bp;
|
||||
p->bp = bp;
|
||||
return (n);
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
}
|
||||
#endif
|
||||
p->cc = 0;
|
||||
return (n);
|
||||
return (pcap_process_pkts(p, callback, user, cnt, bp, cc));
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -466,7 +333,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
|||
#endif
|
||||
register dl_info_ack_t *infop;
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
bpf_u_int32 ss, chunksize;
|
||||
bpf_u_int32 ss;
|
||||
#ifdef HAVE_SOLARIS
|
||||
register char *release;
|
||||
bpf_u_int32 osmajor, osminor, osmicro;
|
||||
|
@ -637,6 +504,13 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
|||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_DLPI_PASSIVE
|
||||
/*
|
||||
* Enable Passive mode to be able to capture on aggregated link.
|
||||
* Not supported in all Solaris versions.
|
||||
*/
|
||||
dlpassive(p->fd, ebuf);
|
||||
#endif
|
||||
/*
|
||||
** Bind (defer if using HP-UX 9 or HP-UX 10.20 or later, totally
|
||||
** skip if using SINIX)
|
||||
|
@ -783,58 +657,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
|||
goto bad;
|
||||
|
||||
infop = &((union DL_primitives *)buf)->info_ack;
|
||||
switch (infop->dl_mac_type) {
|
||||
|
||||
case DL_CSMACD:
|
||||
case DL_ETHER:
|
||||
p->linktype = DLT_EN10MB;
|
||||
p->offset = 2;
|
||||
/*
|
||||
* This is (presumably) a real Ethernet capture; give it a
|
||||
* link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
|
||||
* that an application can let you choose it, in case you're
|
||||
* capturing DOCSIS traffic that a Cisco Cable Modem
|
||||
* Termination System is putting out onto an Ethernet (it
|
||||
* doesn't put an Ethernet header onto the wire, it puts raw
|
||||
* DOCSIS frames out on the wire inside the low-level
|
||||
* Ethernet framing).
|
||||
*/
|
||||
p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
|
||||
/*
|
||||
* If that fails, just leave the list empty.
|
||||
*/
|
||||
if (p->dlt_list != NULL) {
|
||||
p->dlt_list[0] = DLT_EN10MB;
|
||||
p->dlt_list[1] = DLT_DOCSIS;
|
||||
p->dlt_count = 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case DL_FDDI:
|
||||
p->linktype = DLT_FDDI;
|
||||
p->offset = 3;
|
||||
break;
|
||||
|
||||
case DL_TPR:
|
||||
/*
|
||||
* XXX - what about DL_TPB? Is that Token Bus?
|
||||
*/
|
||||
p->linktype = DLT_IEEE802;
|
||||
p->offset = 2;
|
||||
break;
|
||||
|
||||
#ifdef HAVE_SOLARIS
|
||||
case DL_IPATM:
|
||||
p->linktype = DLT_SUNATM;
|
||||
p->offset = 0; /* works for LANE and LLC encapsulation */
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown mac type %lu",
|
||||
(unsigned long)infop->dl_mac_type);
|
||||
if (pcap_process_mactype(p, infop->dl_mac_type, ebuf) != 0)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
#ifdef DLIOCRAW
|
||||
/*
|
||||
|
@ -848,19 +672,9 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
/*
|
||||
** Another non standard call to get the data nicely buffered
|
||||
*/
|
||||
if (ioctl(p->fd, I_PUSH, "bufmod") != 0) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "I_PUSH bufmod: %s",
|
||||
pcap_strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
ss = snaplen;
|
||||
|
||||
/*
|
||||
** Now that the bufmod is pushed lets configure it.
|
||||
**
|
||||
** There is a bug in bufmod(7). When dealing with messages of
|
||||
** less than snaplen size it strips data from the beginning not
|
||||
** the end.
|
||||
|
@ -868,7 +682,6 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
|||
** This bug is fixed in 5.3.2. Also, there is a patch available.
|
||||
** Ask for bugid 1149065.
|
||||
*/
|
||||
ss = snaplen;
|
||||
#ifdef HAVE_SOLARIS
|
||||
release = get_release(&osmajor, &osminor, &osmicro);
|
||||
if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) &&
|
||||
|
@ -879,38 +692,11 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
|||
ss = 0;
|
||||
}
|
||||
#endif
|
||||
if (ss > 0 &&
|
||||
strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSSNAP: %s",
|
||||
pcap_strerror(errno));
|
||||
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
/* Push and configure bufmod. */
|
||||
if (pcap_conf_bufmod(p, ss, to_ms, ebuf) != 0)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set up the bufmod timeout
|
||||
*/
|
||||
if (to_ms != 0) {
|
||||
struct timeval to;
|
||||
|
||||
to.tv_sec = to_ms / 1000;
|
||||
to.tv_usec = (to_ms * 1000) % 1000000;
|
||||
if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSTIME: %s",
|
||||
pcap_strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the chunk length.
|
||||
*/
|
||||
chunksize = CHUNKSIZE;
|
||||
if (strioctl(p->fd, SBIOCSCHUNK, sizeof(chunksize), (char *)&chunksize)
|
||||
!= 0) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSCHUNKP: %s",
|
||||
pcap_strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -922,13 +708,9 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
|||
goto bad;
|
||||
}
|
||||
|
||||
/* Allocate data buffer */
|
||||
p->bufsize = PKTBUFSIZE;
|
||||
p->buffer = (u_char *)malloc(p->bufsize + p->offset);
|
||||
if (p->buffer == NULL) {
|
||||
strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
|
||||
/* Allocate data buffer. */
|
||||
if (pcap_alloc_databuf(p, ebuf) != 0)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/*
|
||||
* "p->fd" is an FD for a STREAMS device, so "select()" and
|
||||
|
@ -1484,6 +1266,24 @@ dlinfoack(int fd, char *bufp, char *ebuf)
|
|||
return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf, NULL));
|
||||
}
|
||||
|
||||
#ifdef HAVE_DLPI_PASSIVE
|
||||
/*
|
||||
* Enable DLPI passive mode. We do not care if this request fails, as this
|
||||
* indicates the underlying DLPI device does not support link aggregation.
|
||||
*/
|
||||
static void
|
||||
dlpassive(int fd, char *ebuf)
|
||||
{
|
||||
dl_passive_req_t req;
|
||||
bpf_u_int32 buf[MAXDLBUF];
|
||||
|
||||
req.dl_primitive = DL_PASSIVE_REQ;
|
||||
|
||||
if (send_request(fd, (char *)&req, sizeof(req), "dlpassive", ebuf) == 0)
|
||||
(void) dlokack(fd, "dlpassive", (char *)buf, ebuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DL_HP_RAWDLS
|
||||
/*
|
||||
* There's an ack *if* there's an error.
|
||||
|
@ -1520,26 +1320,6 @@ dlrawdatareq(int fd, const u_char *datap, int datalen)
|
|||
}
|
||||
#endif /* DL_HP_RAWDLS */
|
||||
|
||||
#ifdef HAVE_SYS_BUFMOD_H
|
||||
static int
|
||||
strioctl(int fd, int cmd, int len, char *dp)
|
||||
{
|
||||
struct strioctl str;
|
||||
int rc;
|
||||
|
||||
str.ic_cmd = cmd;
|
||||
str.ic_timout = -1;
|
||||
str.ic_len = len;
|
||||
str.ic_dp = dp;
|
||||
rc = ioctl(fd, I_STR, &str);
|
||||
|
||||
if (rc < 0)
|
||||
return (rc);
|
||||
else
|
||||
return (str.ic_len);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
|
||||
static char *
|
||||
get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp)
|
||||
|
|
12
pcap-int.h
12
pcap-int.h
|
@ -30,11 +30,11 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.85.2.2 2008-01-06 20:24:12 guy Exp $ (LBL)
|
||||
* @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.85.2.3 2008-03-13 18:16:37 guy Exp $ (LBL)
|
||||
*/
|
||||
|
||||
#ifndef pcap_int_h
|
||||
#define pcap_int_h
|
||||
#define pcap_int_h
|
||||
|
||||
#include <pcap/pcap.h>
|
||||
|
||||
|
@ -42,6 +42,10 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDLPI
|
||||
#include <libdlpi.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <Packet32.h>
|
||||
#endif /* WIN32 */
|
||||
|
@ -167,6 +171,10 @@ struct pcap {
|
|||
int selectable_fd;
|
||||
int send_fd;
|
||||
#endif /* WIN32 */
|
||||
|
||||
#ifdef HAVE_LIBDLPI
|
||||
dlpi_handle_t dlpi_hd;
|
||||
#endif
|
||||
int snapshot;
|
||||
int linktype; /* Network linktype */
|
||||
int linktype_ext; /* Extended information stored in the linktype field of a file */
|
||||
|
|
|
@ -0,0 +1,356 @@
|
|||
/*
|
||||
* Copyright (c) 1993, 1994, 1995, 1996, 1997
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the University of California,
|
||||
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* This code contributed by Sagun Shakya (sagun.shakya@sun.com)
|
||||
*/
|
||||
/*
|
||||
* Packet capture routines for DLPI using libdlpi under SunOS 5.11.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] _U_ =
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap-libdlpi.c,v 1.1.2.1 2008-03-13 18:17:17 guy Exp $ (LBL)";
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/bufmod.h>
|
||||
#include <sys/stream.h>
|
||||
#include <libdlpi.h>
|
||||
#include <errno.h>
|
||||
#include <memory.h>
|
||||
#include <stropts.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pcap-int.h"
|
||||
#include "dlpisubs.h"
|
||||
|
||||
/* Forwards. */
|
||||
static int pcap_read_libdlpi(pcap_t *, int, pcap_handler, u_char *);
|
||||
static int pcap_inject_libdlpi(pcap_t *, const void *, size_t);
|
||||
static void pcap_close_libdlpi(pcap_t *);
|
||||
static void pcap_libdlpi_err(const char *, const char *, int, char *);
|
||||
|
||||
/*
|
||||
* list_interfaces() will list all the network links that are
|
||||
* available on a system.
|
||||
*/
|
||||
static boolean_t list_interfaces(const char *, void *);
|
||||
|
||||
typedef struct linknamelist {
|
||||
char linkname[DLPI_LINKNAME_MAX];
|
||||
struct linknamelist *lnl_next;
|
||||
} linknamelist_t;
|
||||
|
||||
typedef struct linkwalk {
|
||||
linknamelist_t *lw_list;
|
||||
int lw_err;
|
||||
} linkwalk_t;
|
||||
|
||||
/*
|
||||
* The caller of this function should free the memory allocated
|
||||
* for each linknamelist_t "entry" allocated.
|
||||
*/
|
||||
static boolean_t
|
||||
list_interfaces(const char *linkname, void *arg)
|
||||
{
|
||||
linkwalk_t *lwp = arg;
|
||||
linknamelist_t *entry;
|
||||
|
||||
if ((entry = calloc(1, sizeof(linknamelist_t))) == NULL) {
|
||||
lwp->lw_err = ENOMEM;
|
||||
return (B_TRUE);
|
||||
}
|
||||
(void) strlcpy(entry->linkname, linkname, DLPI_LINKNAME_MAX);
|
||||
|
||||
if (lwp->lw_list == NULL) {
|
||||
lwp->lw_list = entry;
|
||||
} else {
|
||||
entry->lnl_next = lwp->lw_list;
|
||||
lwp->lw_list = entry;
|
||||
}
|
||||
|
||||
return (B_FALSE);
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
||||
char *ebuf)
|
||||
{
|
||||
int retv;
|
||||
pcap_t *p;
|
||||
dlpi_handle_t dh;
|
||||
dlpi_info_t dlinfo;
|
||||
bpf_u_int32 ss, chunksize;
|
||||
|
||||
if ((p = (pcap_t *)malloc(sizeof(*p))) == NULL) {
|
||||
strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
|
||||
return (NULL);
|
||||
}
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->fd = -1; /* indicate that it hasn't been opened yet */
|
||||
p->dlpi_hd;
|
||||
p->send_fd = -1;
|
||||
|
||||
/*
|
||||
* Enable Solaris raw and passive DLPI extensions;
|
||||
* dlpi_open() will not fail if the underlying link does not support
|
||||
* passive mode. See dlpi(7P) for details.
|
||||
*/
|
||||
retv = dlpi_open(device, &dh, DLPI_RAW|DLPI_PASSIVE);
|
||||
if (retv != DLPI_SUCCESS) {
|
||||
pcap_libdlpi_err(device, "dlpi_open", retv, ebuf);
|
||||
goto bad;
|
||||
}
|
||||
p->dlpi_hd = dh;
|
||||
|
||||
p->snapshot = snaplen;
|
||||
|
||||
/* Bind with DLPI_ANY_SAP. */
|
||||
if ((retv = dlpi_bind(p->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) {
|
||||
pcap_libdlpi_err(device, "dlpi_bind", retv, ebuf);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Enable promiscuous mode. */
|
||||
if (promisc) {
|
||||
retv = dlpi_promiscon(p->dlpi_hd, DL_PROMISC_PHYS);
|
||||
if (retv != DLPI_SUCCESS) {
|
||||
pcap_libdlpi_err(device, "dlpi_promisc(PHYSICAL)",
|
||||
retv, ebuf);
|
||||
goto bad;
|
||||
}
|
||||
} else {
|
||||
/* Try to enable multicast. */
|
||||
retv = dlpi_promiscon(p->dlpi_hd, DL_PROMISC_MULTI);
|
||||
if (retv != DLPI_SUCCESS) {
|
||||
pcap_libdlpi_err(device, "dlpi_promisc(MULTI)",
|
||||
retv, ebuf);
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try to enable SAP promiscuity. */
|
||||
if ((retv = dlpi_promiscon(p->dlpi_hd, DL_PROMISC_SAP)) != DLPI_SUCCESS) {
|
||||
if (!promisc) {
|
||||
pcap_libdlpi_err(device, "dlpi_promisc(SAP)",
|
||||
retv, ebuf);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Not fatal, since the DL_PROMISC_PHYS mode worked. */
|
||||
fprintf(stderr, "WARNING: dlpi_promisc(SAP) failed on"
|
||||
" %s:(%s)\n", device, dlpi_strerror(retv));
|
||||
}
|
||||
|
||||
/* Determine link type. */
|
||||
if ((retv = dlpi_info(p->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) {
|
||||
pcap_libdlpi_err(device, "dlpi_info", retv, ebuf);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
if (pcap_process_mactype(p, dlinfo.di_mactype, ebuf) != 0)
|
||||
goto bad;
|
||||
|
||||
p->fd = dlpi_fd(p->dlpi_hd);
|
||||
|
||||
/* Push and configure bufmod. */
|
||||
if (pcap_conf_bufmod(p, ss, to_ms, ebuf) != 0)
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
* Flush the read side.
|
||||
*/
|
||||
if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",
|
||||
pcap_strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Allocate data buffer. */
|
||||
if (pcap_alloc_databuf(p, ebuf) != 0)
|
||||
goto bad;
|
||||
|
||||
/*
|
||||
* "p->fd" is a FD for a STREAMS device, so "select()" and
|
||||
* "poll()" should work on it.
|
||||
*/
|
||||
p->selectable_fd = p->fd;
|
||||
|
||||
p->read_op = pcap_read_libdlpi;
|
||||
p->inject_op = pcap_inject_libdlpi;
|
||||
p->setfilter_op = install_bpf_program; /* No kernel filtering */
|
||||
p->setdirection_op = NULL; /* Not implemented */
|
||||
p->set_datalink_op = NULL; /* Can't change data link type */
|
||||
p->getnonblock_op = pcap_getnonblock_fd;
|
||||
p->setnonblock_op = pcap_setnonblock_fd;
|
||||
p->stats_op = pcap_stats_dlpi;
|
||||
p->close_op = pcap_close_libdlpi;
|
||||
|
||||
return (p);
|
||||
bad:
|
||||
/* Get rid of any link-layer type list we allocated. */
|
||||
if (p->dlt_list != NULL)
|
||||
free(p->dlt_list);
|
||||
pcap_close_libdlpi(p);
|
||||
free(p);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* In Solaris, the "standard" mechanism" i.e SIOCGLIFCONF will only find
|
||||
* network links that are plumbed and are up. dlpi_walk(3DLPI) will find
|
||||
* additional network links present in the system.
|
||||
*/
|
||||
int
|
||||
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
{
|
||||
int retv = 0;
|
||||
|
||||
linknamelist_t *entry, *next;
|
||||
linkwalk_t lw = {NULL, 0};
|
||||
int save_errno;
|
||||
|
||||
/* dlpi_walk() for loopback will be added here. */
|
||||
|
||||
dlpi_walk(list_interfaces, &lw, 0);
|
||||
|
||||
if (lw.lw_err != 0) {
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE,
|
||||
"dlpi_walk: %s", pcap_strerror(lw.lw_err));
|
||||
retv = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Add linkname if it does not exist on the list. */
|
||||
for (entry = lw.lw_list; entry != NULL; entry = entry->lnl_next) {
|
||||
if (pcap_add_if(alldevsp, entry->linkname, 0, NULL, errbuf) < 0)
|
||||
retv = -1;
|
||||
}
|
||||
done:
|
||||
save_errno = errno;
|
||||
for (entry = lw.lw_list; entry != NULL; entry = next) {
|
||||
next = entry->lnl_next;
|
||||
free(entry);
|
||||
}
|
||||
errno = save_errno;
|
||||
|
||||
return (retv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read data received on DLPI handle. Returns -2 if told to terminate, else
|
||||
* returns the number of packets read.
|
||||
*/
|
||||
static int
|
||||
pcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user)
|
||||
{
|
||||
int len;
|
||||
u_char *bufp;
|
||||
size_t msglen;
|
||||
int retv;
|
||||
|
||||
len = p->cc;
|
||||
if (len != 0) {
|
||||
bufp = p->bp;
|
||||
goto process_pkts;
|
||||
}
|
||||
do {
|
||||
/* Has "pcap_breakloop()" been called? */
|
||||
if (p->break_loop) {
|
||||
/*
|
||||
* Yes - clear the flag that indicates that it has,
|
||||
* and return -2 to indicate that we were told to
|
||||
* break out of the loop.
|
||||
*/
|
||||
p->break_loop = 0;
|
||||
return (-2);
|
||||
}
|
||||
|
||||
msglen = p->bufsize;
|
||||
bufp = p->buffer + p->offset;
|
||||
|
||||
retv = dlpi_recv(p->dlpi_hd, NULL, NULL, bufp,
|
||||
&msglen, -1, NULL);
|
||||
if (retv != DLPI_SUCCESS) {
|
||||
/*
|
||||
* This is most likely a call to terminate out of the
|
||||
* loop. So, do not return an error message, instead
|
||||
* check if "pcap_breakloop()" has been called above.
|
||||
*/
|
||||
if (retv == DL_SYSERR && errno == EINTR) {
|
||||
len = 0;
|
||||
continue;
|
||||
}
|
||||
pcap_libdlpi_err(dlpi_linkname(p->dlpi_hd),
|
||||
"dlpi_recv", retv, p->errbuf);
|
||||
return (-1);
|
||||
}
|
||||
len = msglen;
|
||||
} while (len == 0);
|
||||
|
||||
process_pkts:
|
||||
return (pcap_process_pkts(p, callback, user, count, bufp, len));
|
||||
}
|
||||
|
||||
static int
|
||||
pcap_inject_libdlpi(pcap_t *p, const void *buf, size_t size)
|
||||
{
|
||||
int retv;
|
||||
|
||||
retv = dlpi_send(p->dlpi_hd, NULL, 0, buf, size, NULL);
|
||||
if (retv != DLPI_SUCCESS) {
|
||||
pcap_libdlpi_err(dlpi_linkname(p->dlpi_hd), "dlpi_send", retv,
|
||||
p->errbuf);
|
||||
return (-1);
|
||||
}
|
||||
/*
|
||||
* dlpi_send(3DLPI) does not provide a way to return the number of
|
||||
* bytes sent on the wire. Based on the fact that DLPI_SUCCESS was
|
||||
* returned we are assuming 'size' bytes were sent.
|
||||
*/
|
||||
return (size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close dlpi handle and deallocate data buffer.
|
||||
*/
|
||||
static void
|
||||
pcap_close_libdlpi(pcap_t *p)
|
||||
{
|
||||
dlpi_close(p->dlpi_hd);
|
||||
free(p->buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write error message to buffer.
|
||||
*/
|
||||
static void
|
||||
pcap_libdlpi_err(const char *linkname, const char *func, int err, char *errbuf)
|
||||
{
|
||||
snprintf(errbuf, PCAP_ERRBUF_SIZE, "libpcap: %s failed on %s: %s",
|
||||
func, linkname, dlpi_strerror(err));
|
||||
}
|
Reference in New Issue