summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--aclocal.m48
-rw-r--r--bin/Makefile.in6
-rw-r--r--doc/doxygen.conf.in2
-rw-r--r--include/wimaxll.h123
-rw-r--r--lib/Makefile.am9
-rw-r--r--lib/Makefile.in37
-rw-r--r--lib/genl.c2
-rw-r--r--lib/internal.h108
-rw-r--r--lib/mc_rx.c527
-rw-r--r--lib/op-msg.c284
-rw-r--r--lib/op-open.c242
-rw-r--r--lib/op-reset.c1
-rw-r--r--lib/op-rfkill.c1
-rw-r--r--lib/pipe.c190
-rw-r--r--lib/re-state-change.c38
-rw-r--r--lib/wimax.c52
-rw-r--r--ltmain.sh14
-rw-r--r--src/Makefile.in4
-rw-r--r--src/test-dump-pipe.c14
19 files changed, 497 insertions, 1165 deletions
diff --git a/aclocal.m4 b/aclocal.m4
index a94c7e1..fb0285a 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1522,7 +1522,7 @@ darwin* | rhapsody*)
shlibpath_var=DYLD_LIBRARY_PATH
shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
m4_if([$1], [],[
- sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
+ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
;;
@@ -6672,7 +6672,7 @@ AC_MSG_RESULT([$SED])
])
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
-#
+#
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
#
# This program is free software; you can redistribute it and/or modify
@@ -6712,7 +6712,7 @@ if test -n "$PKG_CONFIG"; then
AC_MSG_RESULT([no])
PKG_CONFIG=""
fi
-
+
fi[]dnl
])# PKG_PROG_PKG_CONFIG
@@ -6793,7 +6793,7 @@ if test $pkg_failed = yes; then
_PKG_SHORT_ERRORS_SUPPORTED
if test $_pkg_short_errors_supported = yes; then
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
- else
+ else
$1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
fi
# Put the nasty error message in config.log where it belongs
diff --git a/bin/Makefile.in b/bin/Makefile.in
index 28d613e..071e717 100644
--- a/bin/Makefile.in
+++ b/bin/Makefile.in
@@ -271,13 +271,13 @@ clean-binPROGRAMS:
echo " rm -f $$p $$f"; \
rm -f $$p $$f ; \
done
-wimaxll-reset$(EXEEXT): $(wimaxll_reset_OBJECTS) $(wimaxll_reset_DEPENDENCIES)
+wimaxll-reset$(EXEEXT): $(wimaxll_reset_OBJECTS) $(wimaxll_reset_DEPENDENCIES)
@rm -f wimaxll-reset$(EXEEXT)
$(LINK) $(wimaxll_reset_OBJECTS) $(wimaxll_reset_LDADD) $(LIBS)
-wimaxll-rfkill$(EXEEXT): $(wimaxll_rfkill_OBJECTS) $(wimaxll_rfkill_DEPENDENCIES)
+wimaxll-rfkill$(EXEEXT): $(wimaxll_rfkill_OBJECTS) $(wimaxll_rfkill_DEPENDENCIES)
@rm -f wimaxll-rfkill$(EXEEXT)
$(LINK) $(wimaxll_rfkill_OBJECTS) $(wimaxll_rfkill_LDADD) $(LIBS)
-wimaxll-wait-for-state-change$(EXEEXT): $(wimaxll_wait_for_state_change_OBJECTS) $(wimaxll_wait_for_state_change_DEPENDENCIES)
+wimaxll-wait-for-state-change$(EXEEXT): $(wimaxll_wait_for_state_change_OBJECTS) $(wimaxll_wait_for_state_change_DEPENDENCIES)
@rm -f wimaxll-wait-for-state-change$(EXEEXT)
$(LINK) $(wimaxll_wait_for_state_change_OBJECTS) $(wimaxll_wait_for_state_change_LDADD) $(LIBS)
install-binSCRIPTS: $(bin_SCRIPTS)
diff --git a/doc/doxygen.conf.in b/doc/doxygen.conf.in
index 7b64550..fa0b0e4 100644
--- a/doc/doxygen.conf.in
+++ b/doc/doxygen.conf.in
@@ -535,7 +535,7 @@ EXCLUDE_SYMLINKS = NO
# against the file with absolute path, so to exclude all test directories
# for example use the pattern */test/*
-EXCLUDE_PATTERNS = */libnl-20071015.git/* */.hg/*
+EXCLUDE_PATTERNS = */libnl-20071015.git/* */.hg/* */.git/*
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the output.
diff --git a/include/wimaxll.h b/include/wimaxll.h
index 7d06c53..6dc71ff 100644
--- a/include/wimaxll.h
+++ b/include/wimaxll.h
@@ -50,7 +50,7 @@
*
* This library is provided as a convenience and using it is not
* required to talk to the WiMAX kernel stack. It is possible to do so
- * by interacting with it over generic netlink.
+ * by interacting with it over generic netlink directly.
*
* \note this is a very low level library. It does not provide the
* caller with means to scan, connect, disconnect, etc from a WiMAX
@@ -104,21 +104,17 @@
*
* The WiMAX kernel stack will broadcast notifications and
* driver-specific messages to all the user space clients connected to
- * it over the default \e message \e pipe.
- *
- * Different drivers might implement pipes other then default pipe to
- * which applications can listen to. For more information, see \ref
- * the_messaging_interface "the messaging interface".
+ * it over a generic netlink multicast group.
*
* To listen to said notifications, a library client needs to block
- * waiting for them or set \ref callbacks "callbacks" and integrate into
- * some kind of main loop using \e select() to detect notifications
- * ready from the kernel.
+ * waiting for them or set \ref callbacks "callbacks" and integrate
+ * into some kind of main loop using \e select() call to detect
+ * incoming notifications.
*
* Simple example of mainloop integration:
*
* @code
- * int fd = wimaxll_msg_fd(wmx);
+ * int fd = wimaxll_recv_fd(wmx);
* fd_set pipe_fds, read_fds;
* ...
* // Main loop
@@ -128,14 +124,13 @@
* read_fds = pipe_fds;
* select(FD_SETSIZE, &read_fds, NULL, NULL, NULL);
* if (FD_ISSET(fd, &read_fds))
- * wimaxll_pipe_read(wmx, wimax_msg_pipe_id(wmx));
+ * wimaxll_recv(wmx);
* }
* @endcode
*
- * This code will call wimaxll_pipe_read() on the default \e message
- * \e pipe when notifications are available for delivery. Calling said
- * function will execute, for each notification, the callback
- * associated to it.
+ * This code will call wimaxll_recv() when notifications are available
+ * for delivery. Calling said function will execute, for each
+ * notification, the callback associated to it.
*
* To wait for a \e state \e change notification, for example:
*
@@ -148,8 +143,8 @@
* waiting on a main loop. See \ref state_change_group "state changes"
* for more information.
*
- * To wait for a (device-specific) message from the driver on the
- * default \e message pipe, an application would use:
+ * To wait for a (device-specific) message from the driver, an
+ * application would use:
*
* @code
* void *msg;
@@ -171,9 +166,8 @@
* received from a message pipe. See
* wimaxll_pipe_set_cb_msg_to_user().
*
- * A message can be sent to the driver over the default \e message
- * pipe with wimaxll_msg_write(). Note you cannot send messages to the
- * driver over other pipes that are not the default \e message pipe.
+ * A message can be sent to the driver with wimaxll_msg_write().
+ * not the default \e message pipe.
*
* For more details, see \ref the_messaging_interface.
*
@@ -195,28 +189,32 @@
*
* @section multithreading Multithreading
*
- * This library is not threaded or locked. The maximum level of
- * paralellism you can do with one handle is:
+ * This library is not threaded or locked. Internally it uses two
+ * different netlink handles, one for receiving and one for sending;
+ * thus the maximum level of paralellism you can do with one handle
+ * is:
*
* - Functions that can't be executed in parallel when using the same
- * handle (need to be serialized):
+ * wimaxll handle (need to be serialized):
* <ul>
- * <li> wimaxll_msg_write()
- * <li> wimaxll_rfkill()
- * <li> wimaxll_pipe_open(), wimaxll_pipe_msg_read(),
- * wimaxll_pipe_msg_free(), wimaxll_pipe_close()
- * <li> wimaxll_mc_rx_open(), wimaxll_mc_rx_close(), wimaxll_mc_rx_read()
- * <li> wimaxll_reset()
+ * <li> wimaxll_msg_write(), wimaxll_rfkill(), wimax_reset()
+ * <li> wimaxll_recv(), wimaxll_msg_read(),
+ * wimaxll_wait_for_state_change()
+ * <li> wimax_get_cb_*() and wimax_set_cb_*().
+ * <li> wimaxll_recv_fd(), as long as the handle is valid.
* </ul>
*
- * - wimaxll_msg_read(), wimaxll_pipe_msg_read() and wimaxll_mc_rx_read()
- * can be run in parallel with other functions, except with
- * themselves.
+ * - Function calls that have to be always serialized with respect to
+ * any other:
+ * <ul>
+ * <li> wimaxll_open() and wimaxll_close()
+ * <li> wimax_get_cb_*() and wimax_set_cb_*().
+ * </ul>
*
- * - callbacks are all executed serially; don't call any pipe
- * management function from inside a callback.
+ * - callbacks are all executed serially; don't call wimax_recv() from
+ * inside a callback.
*
- * - \a wimaxll_swap_*() and \a wimaxll_*cpu*() can all be parallelized.
+ * Any function not covered by the in this list can be parallelizable.
*/
@@ -246,7 +244,7 @@ struct nlattr;
* When notification callbacks are being executed, the processing of
* notifications from the kernel is effectively blocked by it. Care
* must be taken not to call blocking functions, especially
- * wimaxll_pipe_read().
+ * wimaxll_recv().
*
* Callbacks are always passed a pointer to a private context as set
* by the application. The context is always of type struct
@@ -276,17 +274,20 @@ struct nlattr;
* \param wmx WiMAX device handle
* \param ctx Context passed by the user with
* wimaxll_pipe_set_cb_msg_to_user().
+ * \param pipe_name Name of the pipe the message is sent for
* \param data Pointer to a buffer with the message data.
* \param size Size of the buffer
* \return 0 if it is ok to keep processing messages, -EBUSY if
* message processing should stop and control be returned to the
- * caller.
+ * caller. -EINPROGRESS if the callback wants to ignore the
+ * message.
*
* \ingroup the_messaging_interface
*/
typedef int (*wimaxll_msg_to_user_cb_f)(struct wimaxll_handle *wmx,
struct wimaxll_gnl_cb_context *ctx,
- const char *data, size_t size);
+ const char *pipe_name,
+ const void *data, size_t size);
/**
* Callback for a \e state \e change notification from the WiMAX
@@ -434,9 +435,9 @@ static inline // ugly workaround for doxygen
* \param val value to set for \a result
*
* \ingroup callbacks
- * \fn static void wimaxll_cb_context_set_result(struct wimaxll_gnl_cb_context *ctx, int val)
+ * \fn static void wimaxll_cb_maybe_set_result(struct wimaxll_gnl_cb_context *ctx, int val)
*/
-void wimaxll_cb_context_set_result(struct wimaxll_gnl_cb_context *ctx, int val)
+void wimaxll_cb_maybe_set_result(struct wimaxll_gnl_cb_context *ctx, int val)
{
if (ctx != NULL && ctx->result == -EINPROGRESS)
ctx->result = val;
@@ -448,35 +449,25 @@ struct wimaxll_handle *wimaxll_open(const char *device_name);
void wimaxll_close(struct wimaxll_handle *);
const char *wimaxll_ifname(const struct wimaxll_handle *);
-/* Very low level handling of pipes for reading generic netlink
- * messages from the kernel */
-int wimaxll_mc_rx_open(struct wimaxll_handle *, const char *);
-int wimaxll_mc_rx_fd(struct wimaxll_handle *, unsigned);
-void wimaxll_mc_rx_close(struct wimaxll_handle *, unsigned);
-ssize_t wimaxll_mc_rx_read(struct wimaxll_handle *, unsigned);
-
-/* Handling of pipes for generic netlink messages from the kernel */
-int wimaxll_pipe_open(struct wimaxll_handle *, const char *);
-int wimaxll_pipe_fd(struct wimaxll_handle *, unsigned);
-ssize_t wimaxll_pipe_read(struct wimaxll_handle *, unsigned pipe_id);
-void wimaxll_pipe_close(struct wimaxll_handle *, unsigned);
-
-/* driver-user messaging interface for all the pipes */
-ssize_t wimaxll_pipe_msg_read(struct wimaxll_handle *, unsigned, void **);
-void wimaxll_pipe_msg_free(void *);
-void wimaxll_pipe_get_cb_msg_to_user(struct wimaxll_handle *, unsigned pipe_id,
- wimaxll_msg_to_user_cb_f *,
- struct wimaxll_gnl_cb_context **);
-void wimaxll_pipe_set_cb_msg_to_user(struct wimaxll_handle *, unsigned pipe_id,
- wimaxll_msg_to_user_cb_f,
- struct wimaxll_gnl_cb_context *);
+/* Wait for data from the kernel, execute callbacks */
+int wimaxll_recv_fd(struct wimaxll_handle *);
+int wimaxll_recv(struct wimaxll_handle *);
/* Default (bidirectional) message pipe from the kernel */
-int wimaxll_msg_fd(struct wimaxll_handle *);
-ssize_t wimaxll_msg_read(struct wimaxll_handle *, void **);
-ssize_t wimaxll_msg_write(struct wimaxll_handle *, const void *, size_t);
+ssize_t wimaxll_msg_write(struct wimaxll_handle *, const char *,
+ const void *, size_t);
+
+void wimaxll_get_cb_msg_to_user(struct wimaxll_handle *,
+ wimaxll_msg_to_user_cb_f *,
+ struct wimaxll_gnl_cb_context **);
+void wimaxll_set_cb_msg_to_user(struct wimaxll_handle *,
+ wimaxll_msg_to_user_cb_f,
+ struct wimaxll_gnl_cb_context *);
+
+#define WIMAX_PIPE_ANY (NULL-1)
+ssize_t wimaxll_msg_read(struct wimaxll_handle *, const char *pine_name,
+ void **);
void wimaxll_msg_free(void *);
-unsigned wimaxll_msg_pipe_id(struct wimaxll_handle *);
/* generic API */
int wimaxll_rfkill(struct wimaxll_handle *, enum wimax_rf_state);
diff --git a/lib/Makefile.am b/lib/Makefile.am
index b8cb42e..0a26f11 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -14,8 +14,6 @@ libwimaxll_sources = \
op-msg.c \
op-reset.c \
op-rfkill.c \
- mc_rx.c \
- pipe.c \
re-state-change.c \
wimax.c
@@ -23,8 +21,9 @@ libwimaxll_la_SOURCES = $(libwimaxll_sources)
# Trick automake
libwimaxll_la_CFLAGS = $(AM_CFLAGS)
# -version-info is CURRENT:REVISION:AGE
+# CURRENT: inc for added, removed/changed interfaces
# REVISION: inc for changes that do not affect the external interface
-# CURRENT: inc for added interfaces
-# AGE: inc for removed/changed existing interfaces
-libwimaxll_la_LDFLAGS = -version-info 0:0:0 $(LIBNL1_LIBS)
+# AGE: inc for added interfaces
+# set to zero if removed existing interfaces
+libwimaxll_la_LDFLAGS = -version-info 1:0:0 $(LIBNL1_LIBS)
libwimaxll_a_SOURCES = $(libwimaxll_sources)
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 2bc46dc..55e32ea 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -57,8 +57,8 @@ ARFLAGS = cru
libwimaxll_a_AR = $(AR) $(ARFLAGS)
libwimaxll_a_LIBADD =
am__objects_1 = genl.$(OBJEXT) op-open.$(OBJEXT) op-msg.$(OBJEXT) \
- op-reset.$(OBJEXT) op-rfkill.$(OBJEXT) mc_rx.$(OBJEXT) \
- pipe.$(OBJEXT) re-state-change.$(OBJEXT) wimax.$(OBJEXT)
+ op-reset.$(OBJEXT) op-rfkill.$(OBJEXT) \
+ re-state-change.$(OBJEXT) wimax.$(OBJEXT)
am_libwimaxll_a_OBJECTS = $(am__objects_1)
libwimaxll_a_OBJECTS = $(am_libwimaxll_a_OBJECTS)
libLTLIBRARIES_INSTALL = $(INSTALL)
@@ -66,8 +66,7 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
libwimaxll_la_LIBADD =
am__objects_2 = libwimaxll_la-genl.lo libwimaxll_la-op-open.lo \
libwimaxll_la-op-msg.lo libwimaxll_la-op-reset.lo \
- libwimaxll_la-op-rfkill.lo libwimaxll_la-mc_rx.lo \
- libwimaxll_la-pipe.lo libwimaxll_la-re-state-change.lo \
+ libwimaxll_la-op-rfkill.lo libwimaxll_la-re-state-change.lo \
libwimaxll_la-wimax.lo
am_libwimaxll_la_OBJECTS = $(am__objects_2)
libwimaxll_la_OBJECTS = $(am_libwimaxll_la_OBJECTS)
@@ -220,8 +219,6 @@ libwimaxll_sources = \
op-msg.c \
op-reset.c \
op-rfkill.c \
- mc_rx.c \
- pipe.c \
re-state-change.c \
wimax.c
@@ -229,10 +226,10 @@ libwimaxll_la_SOURCES = $(libwimaxll_sources)
# Trick automake
libwimaxll_la_CFLAGS = $(AM_CFLAGS)
# -version-info is CURRENT:REVISION:AGE
-# REVISION: inc for changes that do not affect the external interface
# CURRENT: inc for added interfaces
+# REVISION: inc for changes that do not affect the external interface
# AGE: inc for removed/changed existing interfaces
-libwimaxll_la_LDFLAGS = -version-info 0:0:0 $(LIBNL1_LIBS)
+libwimaxll_la_LDFLAGS = -version-info 1:0:0 $(LIBNL1_LIBS)
libwimaxll_a_SOURCES = $(libwimaxll_sources)
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-am
@@ -278,7 +275,7 @@ config.h: stamp-h1
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
@rm -f stamp-h1
cd $(top_builddir) && $(SHELL) ./config.status lib/config.h
-$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_srcdir) && $(AUTOHEADER)
rm -f stamp-h1
touch $@
@@ -314,7 +311,7 @@ uninstall-libLIBRARIES:
clean-libLIBRARIES:
-test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES)
-libwimaxll.a: $(libwimaxll_a_OBJECTS) $(libwimaxll_a_DEPENDENCIES)
+libwimaxll.a: $(libwimaxll_a_OBJECTS) $(libwimaxll_a_DEPENDENCIES)
-rm -f libwimaxll.a
$(libwimaxll_a_AR) libwimaxll.a $(libwimaxll_a_OBJECTS) $(libwimaxll_a_LIBADD)
$(RANLIB) libwimaxll.a
@@ -345,7 +342,7 @@ clean-libLTLIBRARIES:
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
-libwimaxll.la: $(libwimaxll_la_OBJECTS) $(libwimaxll_la_DEPENDENCIES)
+libwimaxll.la: $(libwimaxll_la_OBJECTS) $(libwimaxll_la_DEPENDENCIES)
$(libwimaxll_la_LINK) -rpath $(libdir) $(libwimaxll_la_OBJECTS) $(libwimaxll_la_LIBADD) $(LIBS)
mostlyclean-compile:
@@ -356,20 +353,16 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/genl.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwimaxll_la-genl.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwimaxll_la-mc_rx.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwimaxll_la-op-msg.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwimaxll_la-op-open.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwimaxll_la-op-reset.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwimaxll_la-op-rfkill.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwimaxll_la-pipe.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwimaxll_la-re-state-change.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libwimaxll_la-wimax.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mc_rx.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/op-msg.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/op-open.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/op-reset.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/op-rfkill.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pipe.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/re-state-change.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wimax.Po@am__quote@
@@ -429,20 +422,6 @@ libwimaxll_la-op-rfkill.lo: op-rfkill.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwimaxll_la_CFLAGS) $(CFLAGS) -c -o libwimaxll_la-op-rfkill.lo `test -f 'op-rfkill.c' || echo '$(srcdir)/'`op-rfkill.c
-libwimaxll_la-mc_rx.lo: mc_rx.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwimaxll_la_CFLAGS) $(CFLAGS) -MT libwimaxll_la-mc_rx.lo -MD -MP -MF $(DEPDIR)/libwimaxll_la-mc_rx.Tpo -c -o libwimaxll_la-mc_rx.lo `test -f 'mc_rx.c' || echo '$(srcdir)/'`mc_rx.c
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libwimaxll_la-mc_rx.Tpo $(DEPDIR)/libwimaxll_la-mc_rx.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mc_rx.c' object='libwimaxll_la-mc_rx.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwimaxll_la_CFLAGS) $(CFLAGS) -c -o libwimaxll_la-mc_rx.lo `test -f 'mc_rx.c' || echo '$(srcdir)/'`mc_rx.c
-
-libwimaxll_la-pipe.lo: pipe.c
-@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwimaxll_la_CFLAGS) $(CFLAGS) -MT libwimaxll_la-pipe.lo -MD -MP -MF $(DEPDIR)/libwimaxll_la-pipe.Tpo -c -o libwimaxll_la-pipe.lo `test -f 'pipe.c' || echo '$(srcdir)/'`pipe.c
-@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libwimaxll_la-pipe.Tpo $(DEPDIR)/libwimaxll_la-pipe.Plo
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pipe.c' object='libwimaxll_la-pipe.lo' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwimaxll_la_CFLAGS) $(CFLAGS) -c -o libwimaxll_la-pipe.lo `test -f 'pipe.c' || echo '$(srcdir)/'`pipe.c
-
libwimaxll_la-re-state-change.lo: re-state-change.c
@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libwimaxll_la_CFLAGS) $(CFLAGS) -MT libwimaxll_la-re-state-change.lo -MD -MP -MF $(DEPDIR)/libwimaxll_la-re-state-change.Tpo -c -o libwimaxll_la-re-state-change.lo `test -f 're-state-change.c' || echo '$(srcdir)/'`re-state-change.c
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/libwimaxll_la-re-state-change.Tpo $(DEPDIR)/libwimaxll_la-re-state-change.Plo
diff --git a/lib/genl.c b/lib/genl.c
index 60f359c..9dc3f09 100644
--- a/lib/genl.c
+++ b/lib/genl.c
@@ -158,7 +158,7 @@ int nl_get_multicast_groups(struct nl_handle *handle,
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, family_handler, &arg);
while (ret > 0)
- nl_recvmsgs(handle, cb);
+ ret = nl_recvmsgs(handle, cb);
nla_put_failure:
out:
nl_cb_put(cb);
diff --git a/lib/internal.h b/lib/internal.h
index 03bfdce..2d63e6f 100644
--- a/lib/internal.h
+++ b/lib/internal.h
@@ -46,28 +46,6 @@ enum {
* name.
*/
WIMAXLL_IFNAME_LEN = __WIMAXLL_IFNAME_LEN,
- /**
- * WMAX_MC_MAX - Maximum number of multicast groups that a
- * WiMAX interface can offer (this doesn't count the
- * reports group, which is separate).
- */
- WIMAXLL_MC_MAX = 5,
-};
-
-
-struct wimaxll_mc_handle;
-
-
-/**
- * A description of a generic netlink multicast group
- *
- * \param name Name of the group
- * \param id ID of the group
- */
-struct wimaxll_mc_group {
- char name[GENL_NAMSIZ];
- int id;
- struct wimaxll_mc_handle *mch;
};
@@ -79,66 +57,38 @@ struct wimaxll_mc_group {
* \internal
*
* In order to simplify multithread support, we use to different \a
- * libnl handles, one for sending to the kernel, one (for each pipe
- * open to a multicast group) for reading from the kernel. This allows
- * us to parallelize \c wimaxll_msg_write() and \c wimaxll_msg_read() at
- * the same time in a multithreaded environment.
- *
- * FIXME: this needs some rewriting
- *
- * \param ifidx Interface Index
+ * libnl handles, one for sending to the kernel, one for receiving
+ * from the kernel (multicast group). This allows us to parallelize \c
+ * wimaxll_msg_write() and \c wimaxll_msg_read() at the same time in a
+ * multithreaded environment, for example.
+ *
+ * \param ifidx Interface Index (of the network interface)
+ * \param gnl_family_id Generic Netlink Family ID assigned to the
+ * device; we maintain it here (for each interface) because we
+ * want to discover it every time we open. This solves the case of
+ * the WiMAX modules being reloaded (and the ID changing) while
+ * this library is running; this way it takes only a new open when
+ * the new device is discovered.
+ * \param mcg_id Id of the 'msg' multicast group
+ * \param name name of the wimax interface
* \param nlh_tx handle for writing to the kernel.
* Internal note: You \b have \b to set the handlers for
* %NL_CB_VALID and nl_cb_err() callbacks, as each callsite will
* do it to suit their needs. See wimaxll_rfkill() for an
* example. Any other callback you are supposed to restore to what
* it was before.
- * \param gnl_family_id Generic Netlink Family ID assigned to the device
- * \param mc_msg Index in the \a gnl_mc array of the "msg"
- * multicast group.
- * \param name name of the wimax interface
- * \param gnl_mc Array of information about the different multicast
- * groups supported by the device. At least the "msg" group is
- * always supported. The rest are optional and depend on what the
- * driver implements.
+ * \param nlh_rx handle for reading from the kernel.
+ * \param nl_rx_cb Callbacks for the nlh_rx handle
+ *
+ * FIXME: add doc on callbacks
*/
struct wimaxll_handle {
unsigned ifidx;
- struct nl_handle *nlh_tx;
- int gnl_family_id;
- unsigned mc_msg, mc_n;
+ int gnl_family_id, mcg_id;
char name[__WIMAXLL_IFNAME_LEN];
- struct wimaxll_mc_group gnl_mc[WIMAXLL_MC_MAX];
-};
-
-/**
- * Multicast group handle
- *
- * \internal
- *
- * This structure encapsulates all that we need to read from a single
- * multicast group. We could have a single handle for doing all, but
- * by definition of the interface, different multicast groups carry
- * different traffic (with different needs). Rather than multiplex it
- * here, we multiplex at the kernel by sending it via an specific pipe
- * that knows how to handle it already.
- *
- * This way the driver can define it's own private pipes (if needed)
- * for high bandwidth traffic (for example, tracing information)
- * without affecting the rest of the groups (channels).
- *
- * msg_done is used by the ack and error generic netlink callbacks to
- * indicate to the message receving loop that all the parts of the
- * message have been received.
- */
-struct wimaxll_mc_handle {
- int idx;
- struct wimaxll_handle *wmx;
+ struct nl_handle *nlh_tx;
struct nl_handle *nlh_rx;
- struct nl_cb *nl_cb;
- ssize_t result;
- unsigned msg_done:1; /* internal */
wimaxll_msg_to_user_cb_f msg_to_user_cb;
struct wimaxll_gnl_cb_context *msg_to_user_context;
@@ -148,26 +98,12 @@ struct wimaxll_mc_handle {
};
-static inline
-void wimaxll_mch_maybe_set_result(struct wimaxll_mc_handle *mch, int val)
-{
- if (mch->result == -EINPROGRESS)
- mch->result = val;
-}
-
-
/* Utilities */
int wimaxll_wait_for_ack(struct wimaxll_handle *);
-int wimaxll_gnl_handle_msg_to_user(struct wimaxll_handle *,
- struct wimaxll_mc_handle *,
- struct nl_msg *);
-int wimaxll_gnl_handle_state_change(struct wimaxll_handle *,
- struct wimaxll_mc_handle *,
- struct nl_msg *);
+int wimaxll_gnl_handle_msg_to_user(struct wimaxll_handle *, struct nl_msg *);
+int wimaxll_gnl_handle_state_change(struct wimaxll_handle *, struct nl_msg *);
int wimaxll_gnl_error_cb(struct sockaddr_nl *, struct nlmsgerr *, void *);
int wimaxll_gnl_ack_cb(struct nl_msg *msg, void *_mch);
-struct wimaxll_mc_handle *__wimaxll_get_mc_handle(struct wimaxll_handle *,
- int pipe_id);
#define wimaxll_container_of(pointer, type, member) \
diff --git a/lib/mc_rx.c b/lib/mc_rx.c
deleted file mode 100644
index 42f13a6..0000000
--- a/lib/mc_rx.c
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Linux WiMax
- * Framework for reading from multicast groups
- *
- *
- * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
- * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/**
- * @defgroup mc_rx Reading form Generic Netlink multicast groups
- *
- * The WiMAX stack sends asynchronous traffic (notifications and
- * messages) to user space through Generic Netlink multicast groups;
- * thus, when reading that traffic from the kernel, libwimaxll
- * actually reads from a generic netlink multicast group.
- *
- * This allows the kernel to send a single notification that can be
- * received by an undetermined (and unbound) number of listeners. As
- * well, this also allows a very flexible way to multiplex different
- * channels without affecting all the listeners.
- *
- * What is called a \e pipe is mapped over one of these multicast
- * groups.
- *
- * \b Example:
- *
- * If a driver wants to send tracing information to an application in
- * user space for analysis, it can create a new \e pipe (Generic
- * Netlink multicast group) and send it over there.
- *
- * The application can listen to it and its traffic volume won't
- * affect other applications listening to other events coming from the
- * same device. Some of these other applications could not be ready
- * ready to cope with such a high traffic.
- *
- * If the same model were implemented just using different netlink
- * messages, all applications listening to events from the driver
- * would be awakened every time any kind of message were sent, even if
- * they do not need to listen to some of those messages.
- *
- * \warning This is a \b very \b low level interface that is for
- * internal use.
- *
- * \warning If you have to use it in an application, it probably means
- * something is wrong.
- *
- * \warning You might want to use higher level messaging interfaces,
- * such as the \ref the_pipe_interface_group "the pipe interface"
- * or the \ref the_messaging_interface "the messaging interface".
- *
- * \section usage Usage
- *
- * The functions provided by this interface are almost identical than
- * those of the \ref the_pipe_interface_group "pipe interface". The
- * main difference is that wimaxll_mc_rx_read() operates at a lower
- * level.
- *
- * \code
- * int mc_handle;
- * ssize_t bytes;
- * ...
- * mc_handle = wimaxll_mc_rx_open(wimaxll_handle, "name");
- * ...
- * bytes = wimaxll_mc_rx_read(wimaxll_handle, mc_handle);
- * ...
- * wimaxll_mc_rx_close(wimaxll_handle, mc_handle);
- * \endcode
- *
- * \a my_callback is a function that will be called for every valid
- * message received from the kernel on a single call to
- * wimaxll_mc_rx_read().
- *
- * Internally, each \e open pipe/multicast-group contains the list of
- * callbacks for each known message. This is used a look up table for
- * executing them on reception.
- *
- * \section roadmap Roadmap
- *
- * \code
- *
- * wimaxll_mc_rx_open()
- * wimaxll_mc_idx_by_name()
- *
- * wimaxll_mc_rx_read()
- * nl_recvmsgs()
- * wimaxll_seq_check_cb()
- * wimaxll_gnl_error_cb()
- * wimaxll_gnl_cb()
- * wimaxll_gnl_handle_state_change()
- * wimaxll_gnl_handle_msg_to_user()
- * wimaxll_mch_maybe_set_result()
- *
- * wimaxll_mc_rx_fd()
- * __wimaxll_mc_handle()
- * wimaxll_mc_rx_close()
- * \endcode
- */
-#define _GNU_SOURCE
-#include <sys/types.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <assert.h>
-#include <linux/types.h>
-#include <netlink/msg.h>
-#include <netlink/genl/genl.h>
-#include <wimaxll.h>
-#include "internal.h"
-#define D_LOCAL 0
-#include "debug.h"
-
-
-static
-/**
- * Lookup the index for a named multicast group
- *
- * \param wmx WiMAX device handle
- * \param name Name of the multicast group to lookup.
- * \return On success, non-zero positive index for the multicast
- * group; on error, negative errno code.
- *
- * Look up the index of the named multicast group in the cache
- * obtained at wimaxll_open() time.
- *
- * \internal
- * \ingroup mc_rx
- * \fn int wimaxll_mc_idx_by_name(struct wimaxll_handle *wmx, const char *name)
- */
-int wimaxll_mc_idx_by_name(struct wimaxll_handle *wmx, const char *name)
-{
- unsigned cnt;
- for (cnt = 0; cnt < WIMAXLL_MC_MAX; cnt++)
- if (!strcmp(wmx->gnl_mc[cnt].name, name))
- return cnt;
- return -EPROTONOSUPPORT;
-}
-
-
-/*
- * Netlink callback for (disabled) sequence check
- *
- * When reading from multicast groups ignore the sequence check, as
- * they are events (as indicated by the netlink documentation; see the
- * documentation on nl_disable_sequence_check(), for example here:
- * http://people.suug.ch/~tgr/libnl/doc-1.1/
- * group__socket.html#g0ff2f43147e3a4547f7109578b3ca422).
- *
- * We need to do this \e manually, as we are using a new callback set
- * group and thus the libnl defaults set by
- * nl_disable_sequence_check() don't apply.
- */
-static
-int wimaxll_seq_check_cb(struct nl_msg *msg, void *arg)
-{
- return NL_OK;
-}
-
-
-static
-/**
- * Callback to process a (succesful) message coming from generic
- * netlink
- *
- * \internal
- *
- * Called by nl_recvmsgs() when a valid message is received. We
- * multiplex and handle messages that are known to the library. If the
- * message is unknown, do nothing other than setting -ENODATA.
- *
- * When reading from a pipe with wimaxll_pipe_read(), -ENODATA is
- * considered a retryable error -- effectively, the message is
- * skipped.
- *
- * \fn int wimaxll_gnl_cb(struct nl_msg *msg, void *_mch)
- */
-int wimaxll_gnl_cb(struct nl_msg *msg, void *_mch)
-{
- ssize_t result;
- struct wimaxll_mc_handle *mch = _mch;
- struct wimaxll_handle *wmx = mch->wmx;
- struct nlmsghdr *nl_hdr;
- struct genlmsghdr *gnl_hdr;
-
- d_fnstart(7, wmx, "(msg %p mch %p)\n", msg, mch);
- nl_hdr = nlmsg_hdr(msg);
- gnl_hdr = nlmsg_data(nl_hdr);
-
- switch (gnl_hdr->cmd) {
- case WIMAX_GNL_OP_MSG_TO_USER:
- if (mch->msg_to_user_cb)
- result = wimaxll_gnl_handle_msg_to_user(wmx, mch, msg);
- else
- goto out_no_handler;
- break;
- case WIMAX_GNL_RE_STATE_CHANGE:
- if (mch->state_change_cb)
- result = wimaxll_gnl_handle_state_change(wmx, mch, msg);
- else
- goto out_no_handler;
- break;
- default:
- goto error_unknown_msg;
- }
- wimaxll_mch_maybe_set_result(mch, 0);
- d_fnend(7, wmx, "(msg %p mch %p) = %zd\n", msg, mch, result);
- return result;
-
-error_unknown_msg:
- d_printf(1, wmx, "E: %s: received unknown gnl message %d\n",
- __func__, gnl_hdr->cmd);
-out_no_handler:
- wimaxll_mch_maybe_set_result(mch, -ENODATA);
- result = NL_SKIP;
- d_fnend(7, wmx, "(msg %p mch %p) = %zd\n", msg, mch, result);
- return result;
-}
-
-
-/**
- * Open a handle for reception from a multicast group
- *
- * \param wmx WiMAX device handle
- * \param mc_name Name of the multicast group that has to be opened
- *
- * \return If successful, a non-negative handle number (\e { the
- * multicast group descriptor}), to be given to other functions
- * for actual operation. In case of error, a negative errno code.
- *
- * Allocates a handle to use for reception of data on from a single
- * multicast group.
- *
- * Only one handle may be opened at the same time to each multicast
- * group.
- *
- * \ingroup mc_rx
- */
-int wimaxll_mc_rx_open(struct wimaxll_handle *wmx,
- const char *mc_name)
-{
- int result, idx;
- struct wimaxll_mc_handle *mch;
-
- d_fnstart(3, wmx, "(wmx %p mc_name %s)\n", wmx, mc_name);
- idx = wimaxll_mc_idx_by_name(wmx, mc_name);
- if (idx < 0) {
- result = idx;
- wimaxll_msg(wmx, "E: mc group \"%s\" "
- "not supported: %d\n", mc_name, result);
- goto error_mc_idx_by_name;
- }
- d_printf(2, wmx, "D: idx is %d\n", idx);
- result = -EBUSY;
- if (wmx->gnl_mc[idx].mch) {
- wimaxll_msg(wmx, "E: BUG! trying to open handle to multicast "
- "group \"%s\", which is already open\n", mc_name);
- goto error_reopen;
- }
-
- /* Alloc a new multicast group handle */
- result = -ENOMEM;
- mch = malloc(sizeof(*mch));
- if (mch == NULL) {
- wimaxll_msg(wmx, "E: mc group %s: cannot allocate handle\n",
- mc_name);
- goto error_alloc;
- }
- memset(mch, 0, sizeof(*mch));
- mch->wmx = wmx;
- mch->nlh_rx = nl_handle_alloc();
- if (mch->nlh_rx == NULL) {
- result = nl_get_errno();
- wimaxll_msg(wmx, "E: mc group %s: cannot allocate RX netlink "
- "handle: %d\n", mc_name, result);
- goto error_nl_handle_alloc_rx;
- }
- result = nl_connect(mch->nlh_rx, NETLINK_GENERIC);
- if (result < 0) {
- wimaxll_msg(wmx, "E: mc group %s: cannot connect RX netlink: "
- "%d\n", mc_name, result);
- goto error_nl_connect_rx;
- }
-
- result = nl_socket_add_membership(mch->nlh_rx, wmx->gnl_mc[idx].id);
- if (result < 0) {
- wimaxll_msg(wmx, "E: mc group %s: cannot join multicast group "
- "%u: %d\n", mc_name, wmx->gnl_mc[idx].id, result);
- goto error_nl_add_membership;
- }
-
- mch->nl_cb = nl_cb_alloc(NL_CB_VERBOSE);
- if (mch->nl_cb == NULL) {
- result = -ENOMEM;
- wimaxll_msg(wmx, "E: mc group %s: cannot allocate callback\n",
- mc_name);
- goto error_cb_alloc;
- }
-
- nl_cb_set(mch->nl_cb, NL_CB_ACK, NL_CB_CUSTOM, wimaxll_gnl_ack_cb, mch);
- nl_cb_set(mch->nl_cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
- wimaxll_seq_check_cb, NULL);
- nl_cb_set(mch->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, wimaxll_gnl_cb, mch);
- nl_cb_err(mch->nl_cb, NL_CB_CUSTOM, wimaxll_gnl_error_cb, mch);
- wmx->gnl_mc[idx].mch = mch;
- d_fnend(3, wmx, "(wmx %p mc_name %s) = %d\n", wmx, mc_name, idx);
- return idx;
-
-error_cb_alloc:
- /* No need to drop membership, it is removed when we close the
- * handle */
-error_nl_add_membership:
- nl_close(mch->nlh_rx);
-error_nl_connect_rx:
- nl_handle_destroy(mch->nlh_rx);
-error_nl_handle_alloc_rx:
- free(mch);
-error_alloc:
-error_reopen:
-error_mc_idx_by_name:
- d_fnend(3, wmx, "(wmx %p mc_name %s) = %d\n", wmx, mc_name, result);
- return result;
-}
-
-
-/**
- * Close a multicast group handle
- *
- * \param wmx WiMAX handle
- * \param idx Multicast group handle (as returned by wimaxll_mc_rx_open()).
- *
- * Releases resources associated to open multicast group handle.
- *
- * \ingroup mc_rx
- */
-void wimaxll_mc_rx_close(struct wimaxll_handle *wmx, unsigned idx)
-{
- struct wimaxll_mc_handle *mch;
- d_fnstart(3, wmx, "(wmx %p idx %u)\n", wmx, idx);
- if (idx >= WIMAXLL_MC_MAX) {
- wimaxll_msg(wmx, "E: BUG! multicast group index %u "
- "higher than allowed maximum %u\n",
- idx, WIMAXLL_MC_MAX);
- goto out;
- }
- mch = wmx->gnl_mc[idx].mch;
- wmx->gnl_mc[idx].mch = NULL;
- nl_cb_put(mch->nl_cb);
- /* No need to drop handle membership to the msg group, closing
- * it does it */
- nl_close(mch->nlh_rx);
- nl_handle_destroy(mch->nlh_rx);
- free(mch);
-out:
- d_fnend(3, wmx, "(wmx %p idx %u) = void\n", wmx, idx);
-}
-
-
-/**
- * Return the multicast group handle associated to a Pipe ID
- *
- * \internal
- *
- * \param wmx WiMAX device handle
- * \param pipe_id Multicast group ID, as returned by
- * wimaxll_mc_rx_open().
- * \return file descriptor associated to the multicast group, that can
- * be fed to functions like select().
- *
- * \ingroup mc_rx
- */
-struct wimaxll_mc_handle *__wimaxll_get_mc_handle(struct wimaxll_handle *wmx,
- int pipe_id)
-{
- struct wimaxll_mc_handle *mch = NULL;
-
- if (pipe_id >= WIMAXLL_MC_MAX) {
- wimaxll_msg(wmx, "E: BUG! mc group #%u does not exist!\n",
- pipe_id);
- goto error;
- }
- mch = wmx->gnl_mc[pipe_id].mch;
- if (mch == NULL) {
- wimaxll_msg(wmx, "E: BUG! trying to read from non-opened "
- "mc group #%u\n", pipe_id);
- goto error;
- }
-error:
- return mch;
-}
-
-
-/**
- * Return the file descriptor associated to a multicast group
- *
- * \param wmx WiMAX handle
- * \param pipe_id Multicast group handle, as returned by
- * wimaxll_mc_rx_open().
- * \return file descriptor associated to the multicast group, that can
- * be fed to functions like select().
- *
- * This allows to select() on the file descriptor, which will block
- * until a message is available, that then can be read with
- * wimaxll_mc_rx_read().
- *
- * \ingroup mc_rx
- */
-int wimaxll_mc_rx_fd(struct wimaxll_handle *wmx, unsigned pipe_id)
-{
- int result = -EBADFD;
- struct wimaxll_mc_handle *mch;
-
- d_fnstart(3, wmx, "(wmx %p pipe_id %u)\n", wmx, pipe_id);
- mch = __wimaxll_get_mc_handle(wmx, pipe_id);
- if (mch != NULL)
- result = nl_socket_get_fd(mch->nlh_rx);
- d_fnend(3, wmx, "(wmx %p pipe_id %u) = %zd\n", wmx, pipe_id, result);
- return result;
-}
-
-
-/**
- * Read from a multicast group
- *
- * \param wmx WiMAX device handle
- * \param index Multicast group handle, as returned by
- * wimaxll_mc_rx_open().
- * \return Value returned by the callback functions (depending on the
- * implementation of the callback). On error, a negative errno
- * code:
- *
- * -%EINPROGRESS: the message was not received.
- *
- * -%ENODATA: messages were received, but none of the known types.
- *
- * Read one or more messages from a multicast group and for each valid
- * one, execute the callbacks set in the multi cast handle.
- *
- * The callbacks are expected to handle the messages and set
- * information in the context specific to the mc handle
- * (mch->cb_ctx). In case of any type of errors (cb_ctx.result < 0),
- * it is expected that no resources will be tied to the context.
- *
- * \remarks This is a blocking call.
- *
- * \ingroup mc_rx
- *
- * \internal
- *
- * This calls nl_recvmsgs() on the handle specific to a multi-cast
- * group; wimaxll_gnl_cb() will be called for succesfully received
- * generic netlink messages from the kernel and execute the callbacks
- * for each.
- */
-ssize_t wimaxll_mc_rx_read(struct wimaxll_handle *wmx, unsigned index)
-{
- ssize_t result;
- struct wimaxll_mc_handle *mch;
-
- d_fnstart(3, wmx, "(wmx %p index %u)\n", wmx, index);
- if (index >= WIMAXLL_MC_MAX) {
- wimaxll_msg(wmx, "E: BUG! mc group #%u does not exist!\n",
- index);
- result = -EINVAL;
- goto error_bad_index;
- }
- mch = wmx->gnl_mc[index].mch;
- if (mch == NULL) {
- wimaxll_msg(wmx, "E: BUG! trying to read from non-opened "
- "mc group #%u\n", index);
- result = -EBADF;
- goto error_not_open;
- }
-
- /*
- * The reading and processing happens here
- *
- * libnl's nl_recvmsgs() will read and call the different
- * callbacks we specified at wimaxll_mc_rx_open() time. That's
- * where the processing of the message content is done.
- *
- * Now, messages from the kernel don't carry ACKs or NLERRs,
- * so we are just receiving a message packet all the
- * time--except if things go wrong.
- */
- mch->result = -EINPROGRESS;
- mch->msg_done = 0;
- d_printf(2, wmx, "I: Calling nl_recvmsgs()\n");
- result = nl_recvmsgs(mch->nlh_rx, mch->nl_cb);
- if (result < 0)
- wimaxll_msg(wmx, "E: %s: nl_recvmgsgs failed: %d\n",
- __func__, result);
- else
- result = mch->result;
- /* No complains on error; the kernel might just be sending an
- * error out; pass it through. */
-error_not_open:
-error_bad_index:
- d_fnend(3, wmx, "(wmx %p index %u) = %zd\n", wmx, index, result);
- return result;
-}
diff --git a/lib/op-msg.c b/lib/op-msg.c
index 60eb9ea..bebb0bc 100644
--- a/lib/op-msg.c
+++ b/lib/op-msg.c
@@ -116,13 +116,10 @@
* @code
* void *msg;
* ...
- * handle = wimaxll_pipe_open(wmx, "PIPENAME");
- * ...
- * wimaxll_pipe_msg_read(wmx, handle, &msg);
+ * wimaxll_msg_read(wmx, "PIPE NAME", &msg);
* ...
* wimaxll_msg_free(msg);
* ...
- * wimaxll_pipe_close(wmx, handle);
* @endcode
*
* More information about the details of this interface can be found
@@ -177,33 +174,27 @@ struct nla_policy wimaxll_gnl_msg_from_user_policy[WIMAX_GNL_ATTR_MAX + 1] = {
* \param msg Pointer to netlink message
* \return \c enum nl_cb_action
*
- * wimaxll_mc_rx_read() calls libnl's nl_recvmsgs() to receive messages;
+ * wimaxll_recv() calls libnl's nl_recvmsgs() to receive messages;
* when a valid message is received, it goes into a loop that selects
* a callback to run for each type of message and it will call this
* function.
*
- * This just expects a _MSG_TO_USER message, whose payload is what
- * has to be passed to the caller. Because nl_recvmsgs() will free the
- * message data, a new buffer has to be allocated and copied (a patch
- * has been merged already to future versions of libnl that helps in
- * this).
- *
- * It stores the buffer and size (or result in case of error) in the
- * context passed in \e mch->msg_to_user_context.
+ * This "netlink" callback will just de-marshall the arguments and
+ * call the callback set by the user with wimaxll_set_cb_msg_to_user().
*/
int wimaxll_gnl_handle_msg_to_user(struct wimaxll_handle *wmx,
- struct wimaxll_mc_handle *mch,
- struct nl_msg *msg)
+ struct nl_msg *msg)
{
size_t size;
ssize_t result;
struct nlmsghdr *nl_hdr;
struct genlmsghdr *gnl_hdr;
struct nlattr *tb[WIMAX_GNL_ATTR_MAX+1];
- struct wimaxll_gnl_cb_context *ctx = mch->msg_to_user_context;
+ struct wimaxll_gnl_cb_context *ctx = wmx->msg_to_user_context;
+ const char *pipe_name;
void *data;
- d_fnstart(7, wmx, "(wmx %p mch %p msg %p)\n", wmx, mch, msg);
+ d_fnstart(7, wmx, "(wmx %p msg %p)\n", wmx, msg);
nl_hdr = nlmsg_hdr(msg);
gnl_hdr = nlmsg_data(nl_hdr);
@@ -215,37 +206,56 @@ int wimaxll_gnl_handle_msg_to_user(struct wimaxll_handle *wmx,
if (result < 0) {
wimaxll_msg(wmx, "E: %s: genlmsg_parse() failed: %d\n",
__func__, result);
- wimaxll_cb_context_set_result(ctx, result);
+ wimaxll_cb_maybe_set_result(ctx, result);
result = NL_SKIP;
goto error_parse;
}
+ /* Find if the message is for the interface wmx represents */
+ if (tb[WIMAX_GNL_MSG_IFIDX] == NULL) {
+ wimaxll_msg(wmx, "E: %s: cannot find IFIDX attribute\n",
+ __func__);
+ wimaxll_cb_maybe_set_result(ctx, -ENODEV);
+ result = NL_SKIP;
+ goto error_no_attrs;
+
+ }
+ if (wmx->ifidx != nla_get_u32(tb[WIMAX_GNL_MSG_IFIDX])) {
+ result = NL_OK;
+ goto error_not_for_us;
+ }
+ /* Extract marshalled arguments */
if (tb[WIMAX_GNL_MSG_DATA] == NULL) {
wimaxll_msg(wmx, "E: %s: cannot find MSG_DATA attribute\n",
__func__);
- wimaxll_cb_context_set_result(ctx, -ENXIO);
+ wimaxll_cb_maybe_set_result(ctx, -ENXIO);
result = NL_SKIP;
goto error_no_attrs;
}
- wimaxll_cb_context_set_result(ctx, 0);
-
size = nla_len(tb[WIMAX_GNL_MSG_DATA]);
data = nla_data(tb[WIMAX_GNL_MSG_DATA]);
+ if (tb[WIMAX_GNL_MSG_PIPE_NAME])
+ pipe_name = nla_get_string(tb[WIMAX_GNL_MSG_PIPE_NAME]);
+ else
+ pipe_name = NULL;
+
d_printf(1, wmx, "D: CRX genlmsghdr cmd %u version %u\n",
gnl_hdr->cmd, gnl_hdr->version);
- d_printf(1, wmx, "D: CRX msg from kernel %u bytes\n", size);
+ d_printf(1, wmx, "D: CRX msg from kernel %u bytes pipe %s\n",
+ size, pipe_name);
d_dump(2, wmx, data, size);
- /* This was set by whoever called nl_recmvsgs (or
- * wimaxll_mc_rx_read() or wimaxll_pipe_read()) */
- if (mch->msg_to_user_cb(wmx, ctx, data, size) == -EBUSY)
+ /* Now execute the callback for handling msg-to-user */
+ result = wmx->msg_to_user_cb(wmx, ctx, pipe_name, data, size);
+ if (result == -EBUSY)
result = NL_STOP;
else
result = NL_OK;
error_no_attrs:
+error_not_for_us:
error_parse:
- d_fnend(7, wmx, "(wmx %p mch %p msg %p) = %d\n", wmx, mch, msg, result);
+ d_fnend(7, wmx, "(wmx %p msg %p) = %d\n", wmx, msg, result);
return result;
}
@@ -259,28 +269,69 @@ struct wimaxll_cb_msg_to_user_context {
/*
* Default handling of messages
*
- * When someone calls wimaxll_msg_read() or wimaxll_pipe_msg_read(), those
- * functions set this default callback, which will just copy the data
- * to a buffer and pass that pointer to the caller along with the size.
+ * When someone calls wimaxll_msg_read() those functions set this
+ * default callback, which will just copy the data to a buffer and
+ * pass that pointer to the caller along with the size.
*/
static
int wimaxll_cb_msg_to_user(struct wimaxll_handle *wmx,
- struct wimaxll_gnl_cb_context *ctx,
- const char *data, size_t data_size)
+ struct wimaxll_gnl_cb_context *ctx,
+ const char *pipe_name,
+ const void *data, size_t data_size)
{
+ int result;
struct wimaxll_cb_msg_to_user_context *mtu_ctx =
wimaxll_container_of(
ctx, struct wimaxll_cb_msg_to_user_context, ctx);
+ const char *dst_pipe_name = mtu_ctx->data;
+ int pipe_match;
+
+ d_fnstart(3, wmx, "(wmx %p ctx %p pipe_name %s data %p size %zd)\n",
+ wmx, ctx, pipe_name, data, data_size);
+
+ result = -EBUSY;
+ if (mtu_ctx->ctx.result != -EINPROGRESS)
+ goto out;
+ /*
+ * Is there a match in requested pipes? (dst_pipe_name ==
+ * WIMAX_PIPE_ANY), * messages for any pipe work.
+ *
+ * This way of checking makes it kind of easier to read...if
+ * the user requests messages from the default pipe (pipe_name
+ * == NULL), we want only those. Sucks strcmp doesn't take
+ * NULLs :)
+ */
+ d_printf(3, wmx, "dst_pipe_name %s\n", dst_pipe_name);
+
+ if (dst_pipe_name == WIMAX_PIPE_ANY)
+ pipe_match = 1;
+ else if (dst_pipe_name == NULL && pipe_name == NULL)
+ pipe_match = 1;
+ else if ((dst_pipe_name == NULL && pipe_name != NULL)
+ || (dst_pipe_name != NULL && pipe_name == NULL))
+ pipe_match = 0;
+ else if (strcmp(dst_pipe_name, pipe_name) == 0)
+ pipe_match = 1;
+ else
+ pipe_match = 0;
+
+ result = -EINPROGRESS;
+ if (pipe_match == 0) /* Not addressed to us */
+ goto out;
- if (mtu_ctx->data)
- return -EBUSY;
mtu_ctx->data = malloc(data_size);
if (mtu_ctx->data) {
memcpy(mtu_ctx->data, data, data_size);
ctx->result = data_size;
} else
ctx->result = -ENOMEM;
- return 0;
+ /* Now tell wimaxll_recv() [the callback dispatcher] to stop
+ * and return control to the caller */
+ result = -EBUSY;
+out:
+ d_fnend(3, wmx, "(wmx %p ctx %p pipe_name %s data %p size %zd) = %d\n",
+ wmx, ctx, pipe_name, data, data_size, result);
+ return result;
}
@@ -288,9 +339,10 @@ int wimaxll_cb_msg_to_user(struct wimaxll_handle *wmx,
* Read a message from any WiMAX kernel-user pipe
*
* \param wmx WiMAX device handle
- * \param pipe_id Pipe to read from (as returned by
- * wimaxll_pipe_open()). To use the default pipe, indicate
- * use wimax_msg_pipe_id().
+ * \param pipe_name Name of the pipe for which we want to read a
+ * message. If NULL, only messages from the default pipe (without
+ * pipe name) will be received. To receive messages from any pipe,
+ * use pipe ~NULL.
* \param buf Somewhere where to store the pointer to the message data.
* \return If successful, a positive (and \c *buf set) or zero size of
* the message; on error, a negative \a errno code (\c buf
@@ -304,45 +356,54 @@ int wimaxll_cb_msg_to_user(struct wimaxll_handle *wmx,
* \note This is a blocking call.
*
* \ingroup the_messaging_interface
+ *
+ * \internal
+ *
+ * We use the data pointer of the context structure to pass the
+ * pipe_name to the callback. This is ok, as we process only one
+ * message and then return.
*/
-ssize_t wimaxll_pipe_msg_read(struct wimaxll_handle *wmx, unsigned pipe_id,
- void **buf)
+ssize_t wimaxll_msg_read(struct wimaxll_handle *wmx,
+ const char *pipe_name, void **buf)
{
ssize_t result;
struct wimaxll_cb_msg_to_user_context mtu_ctx = {
.ctx = WIMAXLL_GNL_CB_CONTEXT_INIT(wmx),
- .data = NULL,
+ .data = (void *) pipe_name,
};
wimaxll_msg_to_user_cb_f prev_cb = NULL;
struct wimaxll_gnl_cb_context *prev_priv = NULL;
- d_fnstart(3, wmx, "(wmx %p buf %p)\n", wmx, buf);
- wimaxll_pipe_get_cb_msg_to_user(wmx, pipe_id, &prev_cb, &prev_priv);
- wimaxll_pipe_set_cb_msg_to_user(wmx, pipe_id,
- wimaxll_cb_msg_to_user, &mtu_ctx.ctx);
- result = wimaxll_pipe_read(wmx, pipe_id);
+ d_fnstart(3, wmx, "(wmx %p pipe_name %s, buf %p)\n",
+ wmx, pipe_name, buf);
+ wimaxll_get_cb_msg_to_user(wmx, &prev_cb, &prev_priv);
+ wimaxll_set_cb_msg_to_user(wmx, wimaxll_cb_msg_to_user,
+ &mtu_ctx.ctx);
+ do {
+ /* Loop until we get a message in the desired pipe */
+ result = wimaxll_recv(wmx);
+ d_printf(3, wmx, "I: mtu_ctx.result %zd result %zd\n",
+ mtu_ctx.ctx.result, result);
+ } while (result >= 0 && mtu_ctx.ctx.result == -EINPROGRESS);
if (result >= 0) {
*buf = mtu_ctx.data;
result = mtu_ctx.ctx.result;
}
- wimaxll_pipe_set_cb_msg_to_user(wmx, pipe_id, prev_cb, prev_priv);
- d_fnend(3, wmx, "(wmx %p buf %p) = %zd\n", wmx, buf, result);
+ wimaxll_set_cb_msg_to_user(wmx, prev_cb, prev_priv);
+ d_fnend(3, wmx, "(wmx %p pipe_name %s buf %p) = %zd\n",
+ wmx, pipe_name, buf, result);
return result;
}
/**
- * Free a message received with wimaxll_pipe_msg_read() or
- * wimaxll_msg_read()
+ * Free a message received with wimaxll_msg_read()
*
- * \param msg message pointer returned by wimaxll_pipe_msg_read() or
- * wimaxll_msg_read().
- *
- * \note this function is the same as wimaxll_msg_free()
+ * \param msg message pointer returned by wimaxll_msg_read().
*
* \ingroup the_messaging_interface
*/
-void wimaxll_pipe_msg_free(void *msg)
+void wimaxll_msg_free(void *msg)
{
d_fnstart(3, NULL, "(msg %p)\n", msg);
free(msg);
@@ -351,69 +412,11 @@ void wimaxll_pipe_msg_free(void *msg)
/**
- * Return the file descriptor associated to the default \e message pipe
- *
- * \param wmx WiMAX device handle
- * \return file descriptor associated to the messaging group, that can
- * be fed to functions like select().
- *
- * This allows to select() on the file descriptor, which will block
- * until a message is available, that then can be read with
- * wimaxll_pipe_read().
- *
- * \ingroup the_messaging_interface
- */
-int wimaxll_msg_fd(struct wimaxll_handle *wmx)
-{
- return wimaxll_mc_rx_fd(wmx, wmx->mc_msg);
-}
-
-
-/**
- * Read a message from the WiMAX default \e message pipe.
- *
- * \param wmx WiMAX device handle
- * \param buf Somewhere where to store the pointer to the message data.
- * \return If successful, a positive (and \c *buf set) or zero size of
- * the message; on error, a negative \a errno code (\c buf
- * n/a).
- *
- * Returns a message allocated in \c *buf as sent by the kernel via
- * the default \e message pipe. The message is allocated by the
- * library and owned by the caller. When done, it has to be freed with
- * wimaxll_msg_free() to release the space allocated to it.
- *
- * \note This is a blocking call.
- *
- * \ingroup the_messaging_interface
- */
-ssize_t wimaxll_msg_read(struct wimaxll_handle *wmx, void **buf)
-{
- return wimaxll_pipe_msg_read(wmx, wmx->mc_msg, buf);
-}
-
-
-/**
- * Free a message received with wimaxll_pipe_msg_read() or
- * wimaxll_msg_read()
- *
- * \param msg message pointer returned by wimaxll_pipe_msg_read() or
- * wimaxll_msg_read().
- *
- * \note this function is the same as wimaxll_pipe_msg_free()
- *
- * \ingroup the_messaging_interface
- */
-void wimaxll_msg_free(void *msg)
-{
- wimaxll_pipe_msg_free(msg);
-}
-
-
-/**
* Send a driver-specific message to a WiMAX device
*
* \param wmx wimax device descriptor
+ * \param pipe_name Name of the pipe for which to send the message;
+ * NULL to send it to no pipe in particular.
* \param buf Pointer to the wimax message.
* \param size size of the message.
*
@@ -428,6 +431,7 @@ void wimaxll_msg_free(void *msg)
* \ingroup the_messaging_interface
*/
ssize_t wimaxll_msg_write(struct wimaxll_handle *wmx,
+ const char *pipe_name,
const void *buf, size_t size)
{
ssize_t result;
@@ -452,6 +456,9 @@ ssize_t wimaxll_msg_write(struct wimaxll_handle *wmx,
goto error_msg_prep;
}
+ nla_put_u32(nl_msg, WIMAX_GNL_MSG_IFIDX, (__u32) wmx->ifidx);
+ if (pipe_name != NULL)
+ nla_put_string(nl_msg, WIMAX_GNL_MSG_PIPE_NAME, pipe_name);
nla_put(nl_msg, WIMAX_GNL_MSG_DATA, size, buf);
d_printf(5, wmx, "D: CTX nl + genl header:\n");
@@ -481,43 +488,21 @@ error_msg_alloc:
/**
- * Return the pipe ID for the messaging interface
- *
- * @param wmx WiMAX device descriptor
- * @return Pipe id of the messaging interface, that can be used with
- * the wimaxll_pipe_*() functions.
- *
- * \ingroup the_messaging_interface_group
- */
-unsigned wimaxll_msg_pipe_id(struct wimaxll_handle *wmx)
-{
- return wmx->mc_msg;
-}
-
-
-/**
* Get the callback and priv pointer for a MSG_TO_USER message
*
* \param wmx WiMAX handle.
- * \param pipe_id Pipe on which to listen for the message [as returned
- * by wimaxll_pipe_open()].
* \param cb Where to store the current callback function.
* \param context Where to store the private data pointer passed to the
* callback.
*
* \ingroup the_messaging_interface_group
*/
-void wimaxll_pipe_get_cb_msg_to_user(
- struct wimaxll_handle *wmx, unsigned pipe_id,
- wimaxll_msg_to_user_cb_f *cb, struct wimaxll_gnl_cb_context **context)
+void wimaxll_get_cb_msg_to_user(
+ struct wimaxll_handle *wmx, wimaxll_msg_to_user_cb_f *cb,
+ struct wimaxll_gnl_cb_context **context)
{
- struct wimaxll_mc_handle *mch;
-
- mch = __wimaxll_get_mc_handle(wmx, pipe_id);
- if (mch != NULL) {
- *cb = mch->msg_to_user_cb;
- *context = mch->msg_to_user_context;
- }
+ *cb = wmx->msg_to_user_cb;
+ *context = wmx->msg_to_user_context;
}
@@ -525,8 +510,6 @@ void wimaxll_pipe_get_cb_msg_to_user(
* Set the callback and priv pointer for a MSG_TO_USER message
*
* \param wmx WiMAX handle.
- * \param pipe_id Pipe on which to listen for the message [as returned
- * by wimaxll_pipe_open()].
* \param cb Callback function to set
* \param context Private data pointer to pass to the callback
* function (wrap a \a struct wimaxll_gnl_cb_context in your context
@@ -535,15 +518,10 @@ void wimaxll_pipe_get_cb_msg_to_user(
*
* \ingroup the_messaging_interface_group
*/
-void wimaxll_pipe_set_cb_msg_to_user(
- struct wimaxll_handle *wmx, unsigned pipe_id,
- wimaxll_msg_to_user_cb_f cb, struct wimaxll_gnl_cb_context *context)
+void wimaxll_set_cb_msg_to_user(
+ struct wimaxll_handle *wmx, wimaxll_msg_to_user_cb_f cb,
+ struct wimaxll_gnl_cb_context *context)
{
- struct wimaxll_mc_handle *mch;
-
- mch = __wimaxll_get_mc_handle(wmx, pipe_id);
- if (mch != NULL) {
- mch->msg_to_user_cb = cb;
- mch->msg_to_user_context = context;
- }
+ wmx->msg_to_user_cb = cb;
+ wmx->msg_to_user_context = context;
}
diff --git a/lib/op-open.c b/lib/op-open.c
index 360cd16..583d360 100644
--- a/lib/op-open.c
+++ b/lib/op-open.c
@@ -79,17 +79,190 @@
#include "debug.h"
+/*
+ * Netlink callback for (disabled) sequence check
+ *
+ * When reading from multicast groups ignore the sequence check, as
+ * they are events (as indicated by the netlink documentation; see the
+ * documentation on nl_disable_sequence_check(), for example here:
+ * http://people.suug.ch/~tgr/libnl/doc-1.1/
+ * group__socket.html#g0ff2f43147e3a4547f7109578b3ca422).
+ *
+ * We need to do this \e manually, as we are using a new callback set
+ * group and thus the libnl defaults set by
+ * nl_disable_sequence_check() don't apply.
+ */
+static
+int wimaxll_seq_check_cb(struct nl_msg *msg, void *arg)
+{
+ return NL_OK;
+}
+
+
+static
+/**
+ * Callback to process a (succesful) message coming from generic
+ * netlink
+ *
+ * \internal
+ *
+ * Called by nl_recvmsgs() when a valid message is received. We
+ * multiplex and handle messages that are known to the library. If the
+ * message is unknown, do nothing other than setting -ENODATA.
+ *
+ * When reading from a pipe with wimaxll_pipe_read(), -ENODATA is
+ * considered a retryable error -- effectively, the message is
+ * skipped.
+ *
+ * \fn int wimaxll_gnl_cb(struct nl_msg *msg, void *_ctx)
+ */
+int wimaxll_gnl_cb(struct nl_msg *msg, void *_ctx)
+{
+ ssize_t result;
+ struct wimaxll_gnl_cb_context *ctx = _ctx;
+ struct wimaxll_handle *wmx = ctx->wmx;
+ struct nlmsghdr *nl_hdr;
+ struct genlmsghdr *gnl_hdr;
+
+ d_fnstart(3, wmx, "(msg %p wmx %p)\n", msg, wmx);
+ nl_hdr = nlmsg_hdr(msg);
+ gnl_hdr = nlmsg_data(nl_hdr);
+
+ d_printf(3, wmx, "E: %s: received gnl message %d\n",
+ __func__, gnl_hdr->cmd);
+ switch (gnl_hdr->cmd) {
+ case WIMAX_GNL_OP_MSG_TO_USER:
+ if (wmx->msg_to_user_cb)
+ result = wimaxll_gnl_handle_msg_to_user(wmx, msg);
+ else
+ goto out_no_handler;
+ break;
+ case WIMAX_GNL_RE_STATE_CHANGE:
+ if (wmx->state_change_cb)
+ result = wimaxll_gnl_handle_state_change(wmx, msg);
+ else
+ goto out_no_handler;
+ break;
+ default:
+ goto error_unknown_msg;
+ }
+ wimaxll_cb_maybe_set_result(ctx, 0);
+ d_fnend(3, wmx, "(msg %p ctx %p) = %zd\n", msg, ctx, result);
+ return result;
+
+error_unknown_msg:
+ d_printf(3, wmx, "E: %s: received unknown gnl message %d\n",
+ __func__, gnl_hdr->cmd);
+out_no_handler:
+ wimaxll_cb_maybe_set_result(ctx, -ENODATA);
+ result = NL_SKIP;
+ d_fnend(3, wmx, "(msg %p ctx %p) = %zd\n", msg, ctx, result);
+ return result;
+}
+
+
+
+
+/**
+ * Return the file descriptor associated to a WiMAX handle
+ *
+ * \param wmx WiMAX device handle
+ *
+ * \return file descriptor associated to the handle can be fed to
+ * functions like select() to wait for notifications to be ready..
+ *
+ * This allows to select() on the file descriptor, which will block
+ * until a message is available, that then can be read with
+ * wimaxll_recv().
+ *
+ * \ingroup the_messaging_interface
+ */
+int wimaxll_recv_fd(struct wimaxll_handle *wmx)
+{
+ return nl_socket_get_fd(wmx->nlh_rx);
+}
+
+
+/**
+ * Read notifications from the WiMAX multicast group
+ *
+ * \param wmx WiMAX device handle
+ * \return Value returned by the callback functions (depending on the
+ * implementation of the callback). On error, a negative errno
+ * code:
+ *
+ * -%EINPROGRESS: the message was not received.
+ *
+ * -%ENODATA: messages were received, but none of the known types.
+ *
+ * Read one or more messages from a multicast group and for each valid
+ * one, execute the callbacks set in the multi cast handle.
+ *
+ * The callbacks are expected to handle the messages and set
+ * information in the context specific to the mc handle
+ * (mch->cb_ctx). In case of any type of errors (cb_ctx.result < 0),
+ * it is expected that no resources will be tied to the context.
+ *
+ * \remarks This is a blocking call.
+ *
+ * \ingroup mc_rx
+ *
+ * \internal
+ *
+ * This calls nl_recvmsgs() on the handle specific to a multi-cast
+ * group; wimaxll_gnl_cb() will be called for succesfully received
+ * generic netlink messages from the kernel and execute the callbacks
+ * for each.
+ */
+ssize_t wimaxll_recv(struct wimaxll_handle *wmx)
+{
+ ssize_t result;
+ struct wimaxll_gnl_cb_context ctx = WIMAXLL_GNL_CB_CONTEXT_INIT(wmx);
+ struct nl_cb *cb;
+
+ d_fnstart(3, wmx, "(wmx %p)\n", wmx);
+
+ /*
+ * The reading and processing happens here
+ *
+ * libnl's nl_recvmsgs() will read and call the different
+ * callbacks we specified wimaxll_open() time. That's where
+ * the processing of the message content is done.
+ */
+ cb = nl_socket_get_cb(wmx->nlh_rx);
+ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, wimaxll_gnl_ack_cb, &ctx);
+ nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
+ wimaxll_seq_check_cb, NULL);
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, wimaxll_gnl_cb, &ctx);
+ nl_cb_err(cb, NL_CB_CUSTOM, wimaxll_gnl_error_cb, &ctx);
+ d_printf(2, wmx, "I: Calling nl_recvmsgs()\n");
+ do {
+ ctx.result = -EINPROGRESS;
+ result = nl_recvmsgs(wmx->nlh_rx, cb);
+ d_printf(3, wmx, "I: ctx.result %zd result %zd\n",
+ ctx.result, result);
+ } while ((ctx.result == -EINPROGRESS || ctx.result == -ENODATA)
+ && result >= 0);
+ if (result < 0)
+ wimaxll_msg(wmx, "E: %s: nl_recvmgsgs failed: %d\n",
+ __func__, result);
+ else
+ result = ctx.result;
+ /* No complains on error; the kernel might just be sending an
+ * error out; pass it through. */
+ d_fnend(3, wmx, "(wmx %p) = %zd\n", wmx, result);
+ return result;
+}
+
+
static
void wimaxll_mc_group_cb(void *_wmx, const char *name, int id)
{
struct wimaxll_handle *wmx = _wmx;
- if (wmx->mc_n < sizeof(wmx->gnl_mc) / sizeof(wmx->gnl_mc[0])) {
- struct wimaxll_mc_group *gmc = &wmx->gnl_mc[wmx->mc_n];
- strncpy(gmc->name, name, sizeof(gmc->name));
- gmc->id = id;
- wmx->mc_n++;
- }
+ if (strcmp(name, "msg"))
+ return;
+ wmx->mcg_id = id;
}
@@ -97,7 +270,6 @@ static
int wimaxll_gnl_resolve(struct wimaxll_handle *wmx)
{
int result, version;
- char buf[64];
unsigned major, minor;
d_fnstart(5, wmx, "(wmx %p)\n", wmx);
@@ -107,8 +279,7 @@ int wimaxll_gnl_resolve(struct wimaxll_handle *wmx)
wimaxll_msg(wmx, "E: device %s does not exist\n", wmx->name);
goto error_no_dev;
}
- snprintf(buf, sizeof(buf), "WiMAX %u", wmx->ifidx);
- result = genl_ctrl_resolve(wmx->nlh_tx, buf);
+ result = genl_ctrl_resolve(wmx->nlh_tx, "WiMAX");
if (result < 0) {
wimaxll_msg(wmx, "E: device %s presents no WiMAX interface; "
"it might not exist, not be be a WiMAX device or "
@@ -119,9 +290,9 @@ int wimaxll_gnl_resolve(struct wimaxll_handle *wmx)
wmx->gnl_family_id = result;
d_printf(1, wmx, "D: WiMAX device %s, genl family ID %d\n",
wmx->name, wmx->gnl_family_id);
- nl_get_multicast_groups(wmx->nlh_tx, buf, wimaxll_mc_group_cb, wmx);
+ nl_get_multicast_groups(wmx->nlh_tx, "WiMAX", wimaxll_mc_group_cb, wmx);
- version = genl_ctrl_get_version(wmx->nlh_tx, buf);
+ version = genl_ctrl_get_version(wmx->nlh_tx, "WiMAX");
/* Check version compatibility -- check include/linux/wimax.h
* for a complete description. The idea is to allow for good
* expandability of the interface without causing breakage. */
@@ -210,25 +381,39 @@ struct wimaxll_handle *wimaxll_open(const char *device)
goto error_nl_connect_tx;
}
+ /* Set up the RX side */
+ wmx->nlh_rx = nl_handle_alloc();
+ if (wmx->nlh_rx == NULL) {
+ result = nl_get_errno();
+ wimaxll_msg(wmx, "E: RX: cannot allocate netlink handle: %d\n",
+ result);
+ goto error_nl_handle_alloc_rx;
+ }
+ result = nl_connect(wmx->nlh_rx, NETLINK_GENERIC);
+ if (result < 0) {
+ wimaxll_msg(wmx, "E: RX: cannot connect netlink: %d\n", result);
+ goto error_nl_connect_rx;
+ }
+
result = wimaxll_gnl_resolve(wmx); /* Get genl information */
- if (result < 0)
+ if (result < 0) /* fills wmx->mcg_id */
goto error_gnl_resolve;
- result = wimaxll_mc_rx_open(wmx, "msg");
- if (result == -EPROTONOSUPPORT) /* not open? */
- wmx->mc_msg = WIMAXLL_MC_MAX; /* for wimaxll_mc_rx_read() */
- else if (result < 0) {
- wimaxll_msg(wmx, "E: cannot open 'msg' multicast group: "
- "%d\n", result);
- goto error_msg_open;
- } else
- wmx->mc_msg = result;
+ result = nl_socket_add_membership(wmx->nlh_rx, wmx->mcg_id);
+ if (result < 0) {
+ wimaxll_msg(wmx, "E: RX: cannot join multicast group %u: %d\n",
+ wmx->mcg_id, result);
+ goto error_nl_add_membership;
+ }
d_fnend(3, wmx, "(device %s) = %p\n", device, wmx);
return wmx;
- wimaxll_mc_rx_close(wmx, wmx->mc_msg);
-error_msg_open:
+error_nl_add_membership:
error_gnl_resolve:
+ nl_close(wmx->nlh_rx);
+error_nl_connect_rx:
+ nl_handle_destroy(wmx->nlh_rx);
+error_nl_handle_alloc_rx:
nl_close(wmx->nlh_tx);
error_nl_connect_tx:
nl_handle_destroy(wmx->nlh_tx);
@@ -249,18 +434,13 @@ error_gnl_handle_alloc:
* \ingroup device_management
* \internal
*
- * Performs the natural oposite actions done in wimaxll_open(). All
- * generic netlink multicast groups are destroyed, the netlink handle
- * is closed and destroyed and finally, the actual handle is released.
+ * Performs the natural oposite actions done in wimaxll_open().
*/
void wimaxll_close(struct wimaxll_handle *wmx)
{
- unsigned cnt;
-
d_fnstart(3, NULL, "(wmx %p)\n", wmx);
- for (cnt = 0; cnt < WIMAXLL_MC_MAX; cnt++)
- if (wmx->gnl_mc[cnt].mch)
- wimaxll_mc_rx_close(wmx, cnt);
+ nl_close(wmx->nlh_rx);
+ nl_handle_destroy(wmx->nlh_rx);
nl_close(wmx->nlh_tx);
nl_handle_destroy(wmx->nlh_tx);
wimaxll_free(wmx);
diff --git a/lib/op-reset.c b/lib/op-reset.c
index df94186..434d235 100644
--- a/lib/op-reset.c
+++ b/lib/op-reset.c
@@ -104,6 +104,7 @@ int wimaxll_reset(struct wimaxll_handle *wmx)
"%d 0x%08x\n", result, result);
goto error_msg_prep;
}
+ nla_put_u32(msg, WIMAX_GNL_RESET_IFIDX, (__u32) wmx->ifidx);
result = nl_send_auto_complete(wmx->nlh_tx, msg);
if (result < 0) {
wimaxll_msg(wmx, "E: RESET: error sending message: %zd\n",
diff --git a/lib/op-rfkill.c b/lib/op-rfkill.c
index 48d1110..3e9e793 100644
--- a/lib/op-rfkill.c
+++ b/lib/op-rfkill.c
@@ -110,6 +110,7 @@ int wimaxll_rfkill(struct wimaxll_handle *wmx, enum wimax_rf_state state)
"%d 0x%08x\n", result, result);
goto error_msg_prep;
}
+ nla_put_u32(msg, WIMAX_GNL_RFKILL_IFIDX, (__u32) wmx->ifidx);
nla_put_u32(msg, WIMAX_GNL_RFKILL_STATE, (__u32) state);
result = nl_send_auto_complete(wmx->nlh_tx, msg);
if (result < 0) {
diff --git a/lib/pipe.c b/lib/pipe.c
deleted file mode 100644
index 560b3c5..0000000
--- a/lib/pipe.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Linux WiMax
- * Pipe implementation
- *
- *
- * Copyright (C) 2007-2008 Intel Corporation. All rights reserved.
- * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/**
- * \defgroup the_pipe_interface_group The pipe interface
- *
- * This is a collection of tools for managing access to the different
- * pipes that a WiMAX kernel driver can export.
- *
- * There is always a default pipe, the \e message pipe, on which the
- * kernel sends notifications (such as the <em> \ref state_change_group
- * "state change" </em> notification) and \ref the_messaging_interface
- * "driver-specific messages".
- *
- * The driver can create other pipes for sending messages out of band
- * without clogging the default \e message pipe. This can be used, for
- * example, for high bandwidth driver-specific diagnostics.
- *
- * This is a low level interface and other than wimaxll_pipe_read()
- * for reading notifications from the kernel stack in a mainloop, a
- * normal library user should not need to use much of it.
- *
- * It is implemented a very thin layer on top of the \ref mc_rx
- * "multicast RX interface".
- *
- * \section usage Usage
- *
- * If a WiMAX driver exports a set of pipes (each one with a different
- * name), a handle to it can be opened with:
- *
- * \code
- * pipe_id = wimaxll_pipe_open(wmx, "pipename");
- * \endcode
- *
- * likewise, to close said pipe:
- *
- * \code
- * wimaxll_pipe_close(wmx, pipe_id);
- * \endcode
- *
- * To obtain the file descriptor associated to an opened pipe so that
- * it can be fed to select():
- *
- * \code
- * fd = wimaxll_pipe_fd(wmx, pipe_id);
- * \endcode
- *
- * and finally to read from said pipe and execute the callbacks
- * associated to each different notification from the kernel
- *
- * \code
- * wimaxll_pipe_read(wmx, pipe_id);
- * \endcode
- *
- * The default \e message pipe is always open, and it's \e pipe_id can
- * be obtained with wimaxll_msg_pipe_id().
- */
-#define _GNU_SOURCE
-#include <sys/types.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <assert.h>
-#include <linux/types.h>
-#include <netlink/msg.h>
-#include <netlink/genl/genl.h>
-#include <wimaxll.h>
-#include "internal.h"
-#define D_LOCAL 0
-#include "debug.h"
-
-
-/**
- * Open a handle to receive messages from a WiMAX pipe
- *
- * \param wmx WiMAX device handle
- * \param pipe_name Name of the pipe to open
- *
- * \return If successful, a non-negative pipe handle number (\e {the
- * pipe id}). In case of error, a negative errno code.
- *
- * Opens a handle to receive data from the given WiMAX named
- * pipe. wimaxll_pipe_msg_read() can be used to listen for data sent by
- * the kernel on the named pipe.
- *
- * Only one handle may be opened at the same time to each pipe.
- *
- * \ingroup the_pipe_interface_group
- */
-int wimaxll_pipe_open(struct wimaxll_handle *wmx, const char *pipe_name)
-{
- return wimaxll_mc_rx_open(wmx, pipe_name);
-}
-
-
-/**
- * Return the file descriptor associated to a multicast group
- *
- * \param wmx WiMAX device handle
- * \param pipe_id Pipe ID, as returned by wimaxll_pipe_open().
- * \return file descriptor associated to the multicast group, that can
- * be fed to functions like select().
- *
- * This allows to select() on the file descriptor, which will block
- * until a message is available, that then can be read with
- * wimaxll_pipe_read() or wimaxll_pipe_msg_read().
- *
- * \ingroup the_pipe_interface_group
- */
-int wimaxll_pipe_fd(struct wimaxll_handle *wmx, unsigned pipe_id)
-{
- return wimaxll_mc_rx_fd(wmx, pipe_id);
-}
-
-
-/**
- * Read any kind of kernel messages from a pipe and execute callbacks
- *
- * \param wmx WiMAX device handle
- * \param pipe_id Pipe to read from [as returned by wimaxll_pipe_open()].
- * \return If successful, 0 and the callbacks to known notifications will
- * be called. On error, a negative errno code:
- *
- * -%EINPROGRESS: no messages received
- *
- * When reading notifications from the kernel, any unknown type will
- * be ignored.
- *
- * \note This is a blocking call.
- *
- * \ingroup the_pipe_interface_group
- */
-ssize_t wimaxll_pipe_read(struct wimaxll_handle *wmx, unsigned pipe_id)
-{
- ssize_t result = -EINPROGRESS;
- d_fnstart(3, wmx, "(wmx %p pipe_id %u)\n", wmx, pipe_id);
- while (result == -EINPROGRESS || result == -ENODATA)
- result = wimaxll_mc_rx_read(wmx, pipe_id);
- d_fnend(3, wmx, "(wmx %p pipe_id %u) = %zd\n", wmx, pipe_id, result);
- return result;
-}
-
-
-/**
- * Close an a connection to a WiMAX pipe
- *
- * @param wmx WiMAX device handle
- * \param pipe_id Pipe to close [as returned by wimaxll_pipe_open()].
- *
- * Closes the connection to the given WiMAX pipe.
- *
- * \ingroup the_pipe_interface_group
- */
-void wimaxll_pipe_close(struct wimaxll_handle *wmx, unsigned pipe_id)
-{
- wimaxll_mc_rx_close(wmx, pipe_id);
-}
diff --git a/lib/re-state-change.c b/lib/re-state-change.c
index f90891a..faa90c8 100644
--- a/lib/re-state-change.c
+++ b/lib/re-state-change.c
@@ -118,17 +118,16 @@ struct nla_policy wimaxll_gnl_re_state_change_policy[WIMAX_GNL_ATTR_MAX + 1] = {
* wimaxll_pipe_read()).
*/
int wimaxll_gnl_handle_state_change(struct wimaxll_handle *wmx,
- struct wimaxll_mc_handle *mch,
struct nl_msg *msg)
{
ssize_t result;
struct nlmsghdr *nl_hdr;
struct genlmsghdr *gnl_hdr;
struct nlattr *tb[WIMAX_GNL_ATTR_MAX+1];
- struct wimaxll_gnl_cb_context *ctx = mch->state_change_context;
+ struct wimaxll_gnl_cb_context *ctx = wmx->state_change_context;
enum wimax_st old_state, new_state;
- d_fnstart(7, wmx, "(msg %p mch %p)\n", msg, mch);
+ d_fnstart(7, wmx, "(msg %p)\n", msg);
nl_hdr = nlmsg_hdr(msg);
gnl_hdr = nlmsg_data(nl_hdr);
@@ -140,14 +139,14 @@ int wimaxll_gnl_handle_state_change(struct wimaxll_handle *wmx,
if (result < 0) {
wimaxll_msg(wmx, "E: %s: genlmsg_parse() failed: %d\n",
__func__, result);
- wimaxll_cb_context_set_result(ctx, result);
+ wimaxll_cb_maybe_set_result(ctx, result);
result = NL_SKIP;
goto error_parse;
}
if (tb[WIMAX_GNL_STCH_STATE_OLD] == NULL) {
wimaxll_msg(wmx, "E: %s: cannot find STCH_STATE_OLD "
"attribute\n", __func__);
- wimaxll_cb_context_set_result(ctx, -ENXIO);
+ wimaxll_cb_maybe_set_result(ctx, -ENXIO);
result = NL_SKIP;
goto error_no_attrs;
@@ -157,17 +156,21 @@ int wimaxll_gnl_handle_state_change(struct wimaxll_handle *wmx,
if (tb[WIMAX_GNL_STCH_STATE_NEW] == NULL) {
wimaxll_msg(wmx, "E: %s: cannot find STCH_STATE_NEW "
"attribute\n", __func__);
- wimaxll_cb_context_set_result(ctx, -ENXIO);
+ wimaxll_cb_maybe_set_result(ctx, -ENXIO);
result = NL_SKIP;
goto error_no_attrs;
}
new_state = nla_get_u8(tb[WIMAX_GNL_STCH_STATE_NEW]);
- wimaxll_cb_context_set_result(ctx, 0);
d_printf(1, wmx, "D: CRX re_state_change old %u new %u\n",
old_state, new_state);
- if (mch->state_change_cb(wmx, ctx, old_state, new_state) == -EBUSY)
+
+ /* Now execute the callback for handling re-state-change; if
+ * it doesn't update the context's result code, we'll do. */
+ result = wmx->state_change_cb(wmx, ctx, old_state, new_state);
+ wimaxll_cb_maybe_set_result(ctx, result);
+ if (result == -EBUSY)
result = NL_STOP;
else
result = NL_OK;
@@ -203,12 +206,8 @@ void wimaxll_get_cb_state_change(struct wimaxll_handle *wmx,
wimaxll_state_change_cb_f *cb,
struct wimaxll_gnl_cb_context **context)
{
- struct wimaxll_mc_handle *mch;
- mch = __wimaxll_get_mc_handle(wmx, wmx->mc_msg);
- if (mch != NULL) {
- *cb = mch->state_change_cb;
- *context = mch->state_change_context;
- }
+ *cb = wmx->state_change_cb;
+ *context = wmx->state_change_context;
}
@@ -225,13 +224,8 @@ void wimaxll_set_cb_state_change(struct wimaxll_handle *wmx,
wimaxll_state_change_cb_f cb,
struct wimaxll_gnl_cb_context *context)
{
- struct wimaxll_mc_handle *mch;
-
- mch = __wimaxll_get_mc_handle(wmx, wmx->mc_msg);
- if (mch != NULL) {
- mch->state_change_cb = cb;
- mch->state_change_context = context;
- }
+ wmx->state_change_cb = cb;
+ wmx->state_change_context = context;
}
@@ -301,7 +295,7 @@ ssize_t wimaxll_wait_for_state_change(struct wimaxll_handle *wmx,
wmx, old_state, new_state);
wimaxll_get_cb_state_change(wmx, &prev_cb, &prev_ctx);
wimaxll_set_cb_state_change(wmx, wimaxll_cb_state_change, &ctx.ctx);
- result = wimaxll_pipe_read(wmx, wmx->mc_msg);
+ result = wimaxll_recv(wmx);
/* the callback filled out *old_state and *new_state if ok */
wimaxll_set_cb_state_change(wmx, prev_cb, prev_ctx);
d_fnend(3, wmx, "(wmx %p old_state %p [%u] new_state %p [%u])\n",
diff --git a/lib/wimax.c b/lib/wimax.c
index 91967ca..5014c41 100644
--- a/lib/wimax.c
+++ b/lib/wimax.c
@@ -60,7 +60,7 @@
*
* \param nla Source netlink address
* \param nlerr Netlink error descritor
- * \param _mch Pointer to (\a struct wimaxll_mc_handle)
+ * \param _ctx Pointer to (\a struct wimaxll_gnl_cb_context)
*
* \return 'enum nl_cb_action', NL_OK if there is no error, NL_STOP on
* error and _mch->result possibly updated.
@@ -70,17 +70,17 @@
* store the result of an error message from the kernel.
*/
int wimaxll_gnl_error_cb(struct sockaddr_nl *nla, struct nlmsgerr *nlerr,
- void *_mch)
+ void *_ctx)
{
- struct wimaxll_mc_handle *mch = _mch;
- struct wimaxll_handle *wmx = mch->wmx;
+ struct wimaxll_gnl_cb_context *ctx = _ctx;
+ struct wimaxll_handle *wmx = ctx->wmx;
- d_fnstart(7, wmx, "(nla %p nlnerr %p [%d] mch %p)\n",
- nla, nlerr, nlerr->error, _mch);
- wimaxll_mch_maybe_set_result(mch, nlerr->error);
- mch->msg_done = 1;
- d_fnend(7, wmx, "(nla %p nlnerr %p [%d] mch %p) = NL_STOP\n",
- nla, nlerr, nlerr->error, _mch);
+ d_fnstart(3, wmx, "(nla %p nlnerr %p [%d] ctx %p)\n",
+ nla, nlerr, nlerr->error, _ctx);
+ wimaxll_cb_maybe_set_result(ctx, nlerr->error);
+ ctx->msg_done = 1;
+ d_fnend(3, wmx, "(nla %p nlnerr %p [%d] ctx %p) = NL_STOP\n",
+ nla, nlerr, nlerr->error, _ctx);
return NL_STOP;
}
@@ -102,15 +102,15 @@ int wimaxll_gnl_error_cb(struct sockaddr_nl *nla, struct nlmsgerr *nlerr,
*
* Frontend to this is wimaxll_wait_for_ack()
*/
-int wimaxll_gnl_ack_cb(struct nl_msg *msg, void *_mch)
+int wimaxll_gnl_ack_cb(struct nl_msg *msg, void *_ctx)
{
int result;
struct nlmsghdr *nl_hdr;
struct nlmsgerr *nl_err;
size_t size = nlmsg_len(nlmsg_hdr(msg));
- struct wimaxll_mc_handle *mch = _mch;
+ struct wimaxll_gnl_cb_context *ctx = _ctx;
- d_fnstart(7, NULL, "(msg %p mch %p)\n", msg, _mch);
+ d_fnstart(7, NULL, "(msg %p ctx %p)\n", msg, _ctx);
nl_hdr = nlmsg_hdr(msg);
size = nlmsg_len(nl_hdr);
nl_err = nlmsg_data(nl_hdr);
@@ -131,20 +131,20 @@ int wimaxll_gnl_ack_cb(struct nl_msg *msg, void *_mch)
result = -EBADE;
goto error_bad_type;
}
- d_printf(4, NULL, "netlink ack: nlmsgerr error %d for "
+ d_printf(3, NULL, "netlink ack: nlmsgerr error %d for "
"nlmsghdr len %u type %u flags 0x%04x seq 0x%x pid %u\n",
nl_err->error,
nl_err->msg.nlmsg_len, nl_err->msg.nlmsg_type,
nl_err->msg.nlmsg_flags, nl_err->msg.nlmsg_seq,
nl_err->msg.nlmsg_pid);
- wimaxll_mch_maybe_set_result(mch, nl_err->error);
+ wimaxll_cb_maybe_set_result(ctx, nl_err->error);
if (nl_err->error < 0)
d_printf(2, NULL, "D: netlink ack: received netlink error %d\n",
nl_err->error);
- mch->msg_done = 1;
+ ctx->msg_done = 1;
error_ack_short:
error_bad_type:
- d_fnend(7, NULL, "(msg %p mch %p) = NL_STOP\n", msg, _mch);
+ d_fnend(7, NULL, "(msg %p ctx %p) = NL_STOP\n", msg, _ctx);
return NL_STOP;
}
@@ -166,20 +166,20 @@ int wimaxll_wait_for_ack(struct wimaxll_handle *wmx)
{
int result;
struct nl_cb *cb;
- struct wimaxll_mc_handle fake_mch;
+ struct wimaxll_gnl_cb_context ctx;
- fake_mch.wmx = wmx;
- fake_mch.result = -EINPROGRESS;
- fake_mch.msg_done = 0;
+ ctx.wmx = wmx;
+ ctx.result = -EINPROGRESS;
+ ctx.msg_done = 0;
cb = nl_socket_get_cb(wmx->nlh_tx);
- nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, wimaxll_gnl_ack_cb, &fake_mch);
+ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, wimaxll_gnl_ack_cb, &ctx);
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, NL_CB_DEFAULT, NULL);
- nl_cb_err(cb, NL_CB_CUSTOM, wimaxll_gnl_error_cb, &fake_mch);
+ nl_cb_err(cb, NL_CB_CUSTOM, wimaxll_gnl_error_cb, &ctx);
do
result = nl_recvmsgs(wmx->nlh_tx, cb);
- while (fake_mch.msg_done == 0 && result >= 0);
- result = fake_mch.result;
+ while (ctx.msg_done == 0 && result >= 0);
+ result = ctx.result;
nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, NL_CB_DEFAULT, NULL);
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, NL_CB_DEFAULT, NULL);
nl_cb_err(cb, NL_CB_CUSTOM, NL_CB_DEFAULT, NULL);
@@ -187,7 +187,7 @@ int wimaxll_wait_for_ack(struct wimaxll_handle *wmx)
if (result < 0)
return result;
else
- return fake_mch.result;
+ return ctx.result;
}
diff --git a/ltmain.sh b/ltmain.sh
index 49c5745..5def351 100644
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -382,7 +382,7 @@ func_extract_archives ()
darwin_curdir=`pwd`
darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'`
darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
- if test -n "$darwin_arches"; then
+ if test -n "$darwin_arches"; then
darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
darwin_arch=
$show "$darwin_base_archive has multiple architectures $darwin_arches"
@@ -580,7 +580,7 @@ if test -n "$prevopt"; then
fi
case $disable_libs in
-no)
+no)
;;
shared)
build_libtool_libs=no
@@ -751,7 +751,7 @@ if test -z "$show_help"; then
# Many Bourne shells cannot handle close brackets correctly
# in scan sets, and some SunOS ksh mistreat backslash-escaping
# in scan sets (worked around with variable expansion),
- # and furthermore cannot handle '|' '&' '(' ')' in scan sets
+ # and furthermore cannot handle '|' '&' '(' ')' in scan sets
# at all, so we specify them separately.
*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
lastarg="\"$lastarg\""
@@ -1531,7 +1531,7 @@ EOF
-framework|-arch|-isysroot)
case " $CC " in
- *" ${arg} ${1} "* | *" ${arg} ${1} "*)
+ *" ${arg} ${1} "* | *" ${arg} ${1} "*)
prev=darwin_framework_skip ;;
*) compiler_flags="$compiler_flags $arg"
prev=darwin_framework ;;
@@ -4070,7 +4070,7 @@ EOF
libobjs="$libobjs $func_extract_archives_result"
fi
fi
-
+
if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
eval flag=\"$thread_safe_flag_spec\"
linker_flags="$linker_flags $flag"
@@ -5861,7 +5861,7 @@ relink_command=\"$relink_command\""
case $arg in
-d) isdir=yes ;;
- -f)
+ -f)
case " $install_prog " in
*[\\\ /]cp\ *) ;;
*) prev=$arg ;;
@@ -6254,7 +6254,7 @@ relink_command=\"$relink_command\""
fi
# remove .exe since cygwin /usr/bin/install will append another
- # one anyway
+ # one anyway
case $install_prog,$host in
*/usr/bin/install*,*cygwin*)
case $file:$destfile in
diff --git a/src/Makefile.in b/src/Makefile.in
index 15c8365..a5de712 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -229,10 +229,10 @@ clean-noinstPROGRAMS:
echo " rm -f $$p $$f"; \
rm -f $$p $$f ; \
done
-test-dump-pipe$(EXEEXT): $(test_dump_pipe_OBJECTS) $(test_dump_pipe_DEPENDENCIES)
+test-dump-pipe$(EXEEXT): $(test_dump_pipe_OBJECTS) $(test_dump_pipe_DEPENDENCIES)
@rm -f test-dump-pipe$(EXEEXT)
$(LINK) $(test_dump_pipe_OBJECTS) $(test_dump_pipe_LDADD) $(LIBS)
-test-rfkill$(EXEEXT): $(test_rfkill_OBJECTS) $(test_rfkill_DEPENDENCIES)
+test-rfkill$(EXEEXT): $(test_rfkill_OBJECTS) $(test_rfkill_DEPENDENCIES)
@rm -f test-rfkill$(EXEEXT)
$(LINK) $(test_rfkill_OBJECTS) $(test_rfkill_LDADD) $(LIBS)
diff --git a/src/test-dump-pipe.c b/src/test-dump-pipe.c
index e6a2a6b..122ef88 100644
--- a/src/test-dump-pipe.c
+++ b/src/test-dump-pipe.c
@@ -63,7 +63,6 @@ void dump(const void *_ptr, size_t size)
int main(int argc, char **argv)
{
ssize_t result;
- unsigned pipe_id;
struct wimaxll_handle *wmx;
char *dev_name, *pipe_name;
void *buf;
@@ -84,16 +83,9 @@ int main(int argc, char **argv)
}
fprintf(stderr, "I: Reading from pipe %s\n", pipe_name);
- result = wimaxll_pipe_open(wmx, pipe_name);
- if (result < 0) {
- fprintf(stderr, "E: cannot open pipe %s: %d\n",
- pipe_name, result);
- goto error_pipe_open;
- }
- pipe_id = result;
while (1) {
- result = wimaxll_pipe_msg_read(wmx, pipe_id, &buf);
+ result = wimaxll_msg_read(wmx, pipe_name, &buf);
if (result < 0) {
fprintf(stderr, "E: reading from pipe %s failed: %d\n",
pipe_name, result);
@@ -102,11 +94,9 @@ int main(int argc, char **argv)
printf("I: message received from pipe %s, %zu bytes\n",
pipe_name, result);
dump(buf, result);
- wimaxll_pipe_msg_free(buf);
+ wimaxll_msg_free(buf);
}
- wimaxll_pipe_close(wmx, pipe_id);
result = 0;
-error_pipe_open:
wimaxll_close(wmx);
error_wimaxll_open:
return result;