From 6ce239ece7724c86770ea98e8b4d7ecb8f943d3e Mon Sep 17 00:00:00 2001 From: Inaky Perez-Gonzalez Date: Wed, 10 Dec 2008 03:02:03 -0800 Subject: libwimax: move to address interfaces by attribute (vs by family) Commnunity review asked to move the whole genl schema to addess interfaces by ifindex contained in an attribute on each message. Doing so made it almost impossible to keep the models we had with a single family per interface, so huge rework ensued: - remove pipes and all their APIs: no longer makes sense to have one mcast group per pipe, so this is no longer needed. - create the pipe concept by adding a "pipe name" to the message. Default pipe has no name; as a side benefit, all the pipes are now bidirectional. - side benefit: greatly simplify the msg vs pipe vs mc_rx interface: there is only one interface now, wimax_msg_*() and it contains just a few functions. - Delete all the usage of multicast groups and multicast groups handles - Declare two handles, one for reading notifications, one for writing (eases the work) All in all, this cuts a lot of code; on the bad side, we loose the perfect isolation we had before, where only whoever was listening for something was ever woken up. Signed-off-by: Inaky Perez-Gonzalez --- aclocal.m4 | 8 +- bin/Makefile.in | 6 +- doc/doxygen.conf.in | 2 +- include/wimaxll.h | 123 ++++++------ lib/Makefile.am | 9 +- lib/Makefile.in | 37 +--- lib/genl.c | 2 +- lib/internal.h | 108 +++-------- lib/mc_rx.c | 527 -------------------------------------------------- lib/op-msg.c | 284 +++++++++++++-------------- lib/op-open.c | 242 ++++++++++++++++++++--- lib/op-reset.c | 1 + lib/op-rfkill.c | 1 + lib/pipe.c | 190 ------------------ lib/re-state-change.c | 38 ++-- lib/wimax.c | 52 ++--- ltmain.sh | 14 +- src/Makefile.in | 4 +- src/test-dump-pipe.c | 14 +- 19 files changed, 497 insertions(+), 1165 deletions(-) delete mode 100644 lib/mc_rx.c delete mode 100644 lib/pipe.c 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 . # # 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): *
    - *
  • wimaxll_msg_write() - *
  • wimaxll_rfkill() - *
  • wimaxll_pipe_open(), wimaxll_pipe_msg_read(), - * wimaxll_pipe_msg_free(), wimaxll_pipe_close() - *
  • wimaxll_mc_rx_open(), wimaxll_mc_rx_close(), wimaxll_mc_rx_read() - *
  • wimaxll_reset() + *
  • wimaxll_msg_write(), wimaxll_rfkill(), wimax_reset() + *
  • wimaxll_recv(), wimaxll_msg_read(), + * wimaxll_wait_for_state_change() + *
  • wimax_get_cb_*() and wimax_set_cb_*(). + *
  • wimaxll_recv_fd(), as long as the handle is valid. *
* - * - 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: + *
    + *
  • wimaxll_open() and wimaxll_close() + *
  • wimax_get_cb_*() and wimax_set_cb_*(). + *
* - * - 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 - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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); @@ -350,70 +411,12 @@ 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"); @@ -480,44 +487,22 @@ 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 - * - * 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 \ref state_change_group - * "state change" 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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; -- cgit v1.2.3