diff options
-rw-r--r-- | aclocal.m4 | 8 | ||||
-rw-r--r-- | bin/Makefile.in | 6 | ||||
-rw-r--r-- | doc/doxygen.conf.in | 2 | ||||
-rw-r--r-- | include/wimaxll.h | 123 | ||||
-rw-r--r-- | lib/Makefile.am | 9 | ||||
-rw-r--r-- | lib/Makefile.in | 37 | ||||
-rw-r--r-- | lib/genl.c | 2 | ||||
-rw-r--r-- | lib/internal.h | 108 | ||||
-rw-r--r-- | lib/mc_rx.c | 527 | ||||
-rw-r--r-- | lib/op-msg.c | 284 | ||||
-rw-r--r-- | lib/op-open.c | 242 | ||||
-rw-r--r-- | lib/op-reset.c | 1 | ||||
-rw-r--r-- | lib/op-rfkill.c | 1 | ||||
-rw-r--r-- | lib/pipe.c | 190 | ||||
-rw-r--r-- | lib/re-state-change.c | 38 | ||||
-rw-r--r-- | lib/wimax.c | 52 | ||||
-rw-r--r-- | ltmain.sh | 14 | ||||
-rw-r--r-- | src/Makefile.in | 4 | ||||
-rw-r--r-- | src/test-dump-pipe.c | 14 |
19 files changed, 497 insertions, 1165 deletions
@@ -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 @@ -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; } @@ -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; |