aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2010-11-13 17:42:47 -0800
committerGuy Harris <guy@alum.mit.edu>2010-11-13 17:42:47 -0800
commitade794238b623a81e2585d1c2073a3bececa10ae (patch)
treec2b6496fb80a1d7e96d27671e449169aade7c7b0
parent38ef87dd396d9f2a13f640828815e3067a360c0d (diff)
Add support for libnl 2.x, adapted from a newer version of the iw command.
-rw-r--r--config.h.in3
-rwxr-xr-xconfigure108
-rw-r--r--configure.in40
-rw-r--r--pcap-linux.c58
4 files changed, 184 insertions, 25 deletions
diff --git a/config.h.in b/config.h.in
index f988e8f..3b9ce3c 100644
--- a/config.h.in
+++ b/config.h.in
@@ -52,6 +52,9 @@
/* if libnl exists */
#undef HAVE_LIBNL
+/* if libnl exists and is version 2.x */
+#undef HAVE_LIBNL_2_x
+
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
diff --git a/configure b/configure
index e85d87e..c204a87 100755
--- a/configure
+++ b/configure
@@ -7341,7 +7341,93 @@ fi
if test x$with_libnl != xno ; then
- { echo "$as_me:$LINENO: checking for nl_handle_alloc in -lnl" >&5
+ #
+ # Try libnl 2.x first.
+ #
+ { echo "$as_me:$LINENO: checking for nl_socket_alloc in -lnl" >&5
+echo $ECHO_N "checking for nl_socket_alloc in -lnl... $ECHO_C" >&6; }
+if test "${ac_cv_lib_nl_nl_socket_alloc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnl $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 GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char nl_socket_alloc ();
+int
+main ()
+{
+return nl_socket_alloc ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&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); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_nl_nl_socket_alloc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_nl_nl_socket_alloc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_nl_nl_socket_alloc" >&5
+echo "${ECHO_T}$ac_cv_lib_nl_nl_socket_alloc" >&6; }
+if test $ac_cv_lib_nl_nl_socket_alloc = yes; then
+
+ #
+ # Yes, we have libnl 2.x.
+ #
+ LIBS="-lnl-genl -lnl $LIBS"
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBNL 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBNL_2_x 1
+_ACEOF
+
+
+else
+
+ #
+ # No, we don't; do we have libnl 1.x?
+ #
+ { echo "$as_me:$LINENO: checking for nl_handle_alloc in -lnl" >&5
echo $ECHO_N "checking for nl_handle_alloc in -lnl... $ECHO_C" >&6; }
if test "${ac_cv_lib_nl_nl_handle_alloc+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
@@ -7403,18 +7489,30 @@ fi
{ echo "$as_me:$LINENO: result: $ac_cv_lib_nl_nl_handle_alloc" >&5
echo "${ECHO_T}$ac_cv_lib_nl_nl_handle_alloc" >&6; }
if test $ac_cv_lib_nl_nl_handle_alloc = yes; then
- LIBS="-lnl $LIBS"
+
+ #
+ # Yes.
+ #
+ LIBS="-lnl $LIBS"
cat >>confdefs.h <<\_ACEOF
#define HAVE_LIBNL 1
_ACEOF
+
else
- if test x$with_libnl = xyes ; then
- { { echo "$as_me:$LINENO: error: libnl support requested but libnl not found" >&5
+
+ #
+ # No, we don't have libnl at all.
+ #
+ if test x$with_libnl = xyes ; then
+ { { echo "$as_me:$LINENO: error: libnl support requested but libnl not found" >&5
echo "$as_me: error: libnl support requested but libnl not found" >&2;}
{ (exit 1); exit 1; }; }
- fi
+ fi
+
+fi
+
fi
diff --git a/configure.in b/configure.in
index d71d3fd..3c1cedf 100644
--- a/configure.in
+++ b/configure.in
@@ -445,13 +445,39 @@ linux)
with_libnl=$withval,,)
if test x$with_libnl != xno ; then
- AC_CHECK_LIB(nl, nl_handle_alloc,
- LIBS="-lnl $LIBS"
- AC_DEFINE(HAVE_LIBNL,1,[if libnl exists]),
- if test x$with_libnl = xyes ; then
- AC_MSG_ERROR([libnl support requested but libnl not found])
- fi
- )
+ #
+ # Try libnl 2.x first.
+ #
+ AC_CHECK_LIB(nl, nl_socket_alloc,
+ [
+ #
+ # Yes, we have libnl 2.x.
+ #
+ LIBS="-lnl-genl -lnl $LIBS"
+ AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
+ AC_DEFINE(HAVE_LIBNL_2_x,1,[if libnl exists and is version 2.x])
+ ],
+ [
+ #
+ # No, we don't; do we have libnl 1.x?
+ #
+ AC_CHECK_LIB(nl, nl_handle_alloc,
+ [
+ #
+ # Yes.
+ #
+ LIBS="-lnl $LIBS"
+ AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
+ ],
+ [
+ #
+ # No, we don't have libnl at all.
+ #
+ if test x$with_libnl = xyes ; then
+ AC_MSG_ERROR([libnl support requested but libnl not found])
+ fi
+ ])
+ ])
fi
AC_LBL_TPACKET_STATS
diff --git a/pcap-linux.c b/pcap-linux.c
index f8b3f10..deabbc4 100644
--- a/pcap-linux.c
+++ b/pcap-linux.c
@@ -527,8 +527,37 @@ get_mac80211_phydev(pcap_t *handle, const char *device, char *phydev_path,
return 1;
}
+#ifndef HAVE_LIBNL_2_x
+/* libnl 2.x compatibility code */
+
+#define nl_sock nl_handle
+
+static inline struct nl_handle *
+nl_socket_alloc(void)
+{
+ return nl_handle_alloc();
+}
+
+static inline void
+nl_socket_free(struct nl_handle *h)
+{
+ nl_handle_destroy(h);
+}
+
+static inline int
+__genl_ctrl_alloc_cache(struct nl_handle *h, struct nl_cache **cache)
+{
+ struct nl_cache *tmp = genl_ctrl_alloc_cache(h);
+ if (!tmp)
+ return -ENOMEM;
+ *cache = tmp;
+ return 0;
+}
+#define genl_ctrl_alloc_cache __genl_ctrl_alloc_cache
+#endif /* !HAVE_LIBNL_2_x */
+
struct nl80211_state {
- struct nl_handle *nl_handle;
+ struct nl_sock *nl_sock;
struct nl_cache *nl_cache;
struct genl_family *nl80211;
};
@@ -536,23 +565,26 @@ struct nl80211_state {
static int
nl80211_init(pcap_t *handle, struct nl80211_state *state, const char *device)
{
- state->nl_handle = nl_handle_alloc();
- if (!state->nl_handle) {
+ int err;
+
+ state->nl_sock = nl_socket_alloc();
+ if (!state->nl_sock) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: failed to allocate netlink handle", device);
return PCAP_ERROR;
}
- if (genl_connect(state->nl_handle)) {
+ if (genl_connect(state->nl_sock)) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"%s: failed to connect to generic netlink", device);
goto out_handle_destroy;
}
- state->nl_cache = genl_ctrl_alloc_cache(state->nl_handle);
- if (!state->nl_cache) {
+ err = genl_ctrl_alloc_cache(state->nl_sock, &state->nl_cache);
+ if (err < 0) {
snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
- "%s: failed to allocate generic netlink cache", device);
+ "%s: failed to allocate generic netlink cache: %s",
+ device, strerror(-err));
goto out_handle_destroy;
}
@@ -568,7 +600,7 @@ nl80211_init(pcap_t *handle, struct nl80211_state *state, const char *device)
out_cache_free:
nl_cache_free(state->nl_cache);
out_handle_destroy:
- nl_handle_destroy(state->nl_handle);
+ nl_socket_free(state->nl_sock);
return PCAP_ERROR;
}
@@ -577,7 +609,7 @@ nl80211_cleanup(struct nl80211_state *state)
{
genl_family_put(state->nl80211);
nl_cache_free(state->nl_cache);
- nl_handle_destroy(state->nl_handle);
+ nl_socket_free(state->nl_sock);
}
static int
@@ -605,7 +637,7 @@ add_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, mondevice);
NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR);
- err = nl_send_auto_complete(state->nl_handle, msg);
+ err = nl_send_auto_complete(state->nl_sock, msg);
if (err < 0) {
if (err == -ENFILE) {
/*
@@ -626,7 +658,7 @@ add_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
return PCAP_ERROR;
}
}
- err = nl_wait_for_ack(state->nl_handle);
+ err = nl_wait_for_ack(state->nl_sock);
if (err < 0) {
if (err == -ENFILE) {
/*
@@ -685,7 +717,7 @@ del_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
0, NL80211_CMD_DEL_INTERFACE, 0);
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
- err = nl_send_auto_complete(state->nl_handle, msg);
+ err = nl_send_auto_complete(state->nl_sock, msg);
if (err < 0) {
if (err == -ENFILE) {
/*
@@ -706,7 +738,7 @@ del_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
return PCAP_ERROR;
}
}
- err = nl_wait_for_ack(state->nl_handle);
+ err = nl_wait_for_ack(state->nl_sock);
if (err < 0) {
if (err == -ENFILE) {
/*