dect
/
libpcap
Archived
13
0
Fork 0

Support for libdlpi, and for enabling "passive mode" on Solaris systems

that support it, from Sagun Shakya.
This commit is contained in:
guy 2008-03-13 18:16:37 +00:00
parent e9c012f5fd
commit e598e9e145
11 changed files with 1165 additions and 418 deletions

3
FILES
View File

@ -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

View File

@ -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

29
aclocal.m4 vendored
View File

@ -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])

View File

@ -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

448
configure vendored
View File

@ -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)

View File

@ -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)

349
dlpisubs.c Normal file
View File

@ -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));
}

28
dlpisubs.h Normal file
View File

@ -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

View File

@ -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)

View File

@ -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 */

356
pcap-libdlpi.c Normal file
View 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));
}