--- /dev/null
+Javier S. Pedro <javispedro@javispedro.com>
+
+osso-wlan:
+Janne Ylälehto <janne.ylalehto@nokia.com>
+Johan Hedberg <johan.hedberg@nokia.com>
+
+wpa_supplicant:
+Jouni Malinen <j@w1.fi> and contributors
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null
+LIBTOOL=libtool
+
+CFLAGS += -Wall -O2 -DDEBUG -DOSSOLOG_STDERR -shared
+LDFLAGS += -shared -module
+
+# Library flags
+PKG_CFLAGS := $(shell pkg-config --cflags glib-2.0 gconf-2.0 dbus-1 dbus-glib-1 osso-ic)
+PKG_LDFLAGS := $(shell pkg-config --libs glib-2.0 gconf-2.0 dbus-1 dbus-glib-1)
+CFLAGS += $(PKG_CFLAGS)
+LDFLAGS += $(PKG_LDFLAGS)
+
+LTFLAGS = -shared
+
+BINARY = libicd_network_wpa.so
+OBJS = icd.o wlan.o networks.o gconf.o \
+ dbus.o dbus-helper.o dbus-handler.o supp.o
+
+all: $(BINARY)
+
+$(BINARY): $(OBJS)
+ $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ $^
+
+%.o: %.c
+ $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c $< -o $@
+
+clean:
+ $(LIBTOOL) --mode=clean $(RM) libicd_network_wpa.so *.o
+
+install: $(BINARY)
+ $(LIBTOOL) --mode=install install -c --strip --mode=644 \
+ $(BINARY) $(DESTDIR)/usr/lib/icd2/
+ $(LIBTOOL) --mode=finish $(DESTDIR)/usr/lib/icd2/
+
+
+.PHONY: all clean install
+
--- /dev/null
+This won't work at all without patching some system components first:
+
+- The cx3110 kernel module & wpa_supplicant
+ I am including a modified version of Lauro Ramos' cx3110x.patch
+ (makes cx3110x implement WE18) which enables a modified version of
+ wpa_supplicant to work with the driver without disabling
+ libicd-network-wlan in the process.
+ See patches/cx3110-module-src and patches/wpasupplicant.
+
+- "wlancond"
+ Implements a "I'm already reading wireless events by
+ myself, no need to bother me with d-bus events and no need to take
+ down the wireless interface for me, just set powersave" mode.
+ See patches/osso-wlan.
+
+See also
+http://maemo.org/community/maemo-developers/libicd-network-wpa/
+
--- /dev/null
+- Discover why can't I just pass the bssid to icd's search results
+ Right now it just terminates if I do.
+
+- Intra-ESS roaming seems to be slow when using WPA2. Needs testing.
+
--- /dev/null
+/**
+ @file common.h
+
+ Copyright (C) 2009 Javier S. Pedro
+
+ @author Javier S. Pedro <javispedro@javispedro.com>
+
+ This file is part of libicd-network-wpa.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#define WPA_IFACE "wlan0"
+
+#define WPA_NETWORK_TYPE "WLAN_WPA"
+
+#define WPA_GCONF_NETWORK_TYPE "/type"
+#define WPA_GCONF_NETWORK_TYPE_VALUE WPA_NETWORK_TYPE
+
+#define WPA_GCONF_SSID "/wpa_ssid"
+
+#define WPA_GCONF_SETTING_PREFIX "wpa_"
+#define WPA_GCONF_SETTING_PREFIX_LEN 4
+
+#define SEARCH_CONTINUE 0
+#define SEARCH_FINISHED 1
+#define SEARCH_STOPPED 2
+
+#endif
--- /dev/null
+/**
+ @file dbus-helper.c
+
+ Copyright (C) 2004 Nokia Corporation. All rights reserved.
+
+ Copyright (C) 2009 Javier S. Pedro
+
+ @author Janne Ylalehto <janne.ylalehto@nokia.com>
+ @author Johan Hedberg <johan.hedberg@nokia.com>
+
+ @author Javier S. Pedro <javispedro@javispedro.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include <glib.h>
+
+#include <wlancond-dbus.h>
+
+#include "dbus-helper.h"
+#include "dbus-handler.h"
+#include "wlan.h"
+#include "supp.h"
+#include "log.h"
+
+static DBusHandlerResult wlancond_scan_results_handler(DBusMessage *message) {
+ DBusMessageIter iter;
+ gint32 number_of_results, i;
+
+ if (!wlan_is_scanning()) {
+ DLOG_DEBUG("Received scan results we didn't ask for");
+ // TODO: Somehow use them
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ dbus_message_iter_init(message, &iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
+ goto param_err;
+
+ dbus_message_iter_get_basic(&iter, &number_of_results);
+
+ dbus_message_iter_next(&iter);
+
+ for (i = 0; i < number_of_results; i++) {
+ DBusMessageIter array_iter;
+ gint32 ssid_len, bssid_len;
+ gchar * ssid, * bssid;
+ gint32 rssi;
+ guint32 channel, cap_bits;
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE) {
+
+ goto param_err;
+ }
+
+ dbus_message_iter_recurse(&iter, &array_iter);
+ dbus_message_iter_get_fixed_array(&array_iter, &ssid, &ssid_len);
+ dbus_message_iter_next(&iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE) {
+
+ goto param_err;
+ }
+
+ dbus_message_iter_recurse(&iter, &array_iter);
+ dbus_message_iter_get_fixed_array(&array_iter, &bssid, &bssid_len);
+ dbus_message_iter_next(&iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32)
+ goto param_err;
+ dbus_message_iter_get_basic(&iter, &rssi);
+ dbus_message_iter_next(&iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
+ goto param_err;
+ dbus_message_iter_get_basic(&iter, &channel);
+ dbus_message_iter_next(&iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
+ goto param_err;
+ dbus_message_iter_get_basic(&iter, &cap_bits);
+ dbus_message_iter_next(&iter);
+
+ DLOG_INFO("Scan result with %s.", ssid);
+ wlan_notify_ap(ssid, bssid,
+ rssi, channel, cap_bits);
+ }
+
+ DLOG_DEBUG("Handled scan result, results=%ld.",
+ (long) number_of_results);
+
+ wlan_notify_end_of_search();
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+param_err:
+ DLOG_WARN("Parameter error in scan request");
+
+ wlan_notify_end_of_search();
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult supp_state_change_handler(DBusMessage *message) {
+ gchar *old_state, *new_state;
+
+ if (!dbus_message_get_args(
+ message, NULL,
+ DBUS_TYPE_STRING, &new_state,
+ DBUS_TYPE_STRING, &old_state,
+ DBUS_TYPE_INVALID))
+ {
+ DLOG_WARN("Supplicant StateChange signal format error");
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ supp_handle_signal(old_state, new_state);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult wlancond_sig_handler(DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data) {
+ if (dbus_message_is_signal(message,
+ WLANCOND_SIG_INTERFACE,
+ WLANCOND_SCAN_RESULTS_SIG))
+ return wlancond_scan_results_handler(message);
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusHandlerResult supp_sig_handler(DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data) {
+ if (dbus_message_is_signal(message,
+ WPAS_DBUS_IFACE_INTERFACE,
+ WPAS_STATE_CHANGE_SIG))
+ return supp_state_change_handler(message);
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+/**
+ Create bindings for D-BUS handlers.
+ @param connection DBUS connection.
+*/
+void init_dbus_handlers(DBusConnection *connection) {
+ gboolean ret;
+ /*dbus_bool_t ret;
+ ret = dbus_connection_register_object_path(connection,
+ WLANCOND_REQ_PATH,
+ &wlancond_req_vtable,
+ NULL);
+ if (ret == FALSE) {
+ DLOG_ERR("dbus_connection_register_object_path failed");
+ }*/
+
+ dbus_bus_add_match(connection,
+ "interface=" WLANCOND_SIG_INTERFACE
+ ",member=" WLANCOND_SCAN_RESULTS_SIG, NULL);
+
+ ret = dbus_connection_add_filter(connection,
+ (DBusHandleMessageFunction)wlancond_sig_handler, NULL, NULL);
+
+ if (!ret) {
+ DLOG_ERR("dbus_connection_add_filter failed");
+ }
+
+ dbus_bus_add_match(connection,
+ "interface=" WPAS_DBUS_IFACE_INTERFACE
+ ",member=" WPAS_STATE_CHANGE_SIG, NULL);
+
+ ret = dbus_connection_add_filter(connection,
+ (DBusHandleMessageFunction)supp_sig_handler, NULL, NULL);
+
+ if (!ret) {
+ DLOG_ERR("dbus_connection_add_filter failed");
+ }
+}
+
+/**
+ Destroy D-BUS handlers.
+ @param connection DBUS connection.
+*/
+void destroy_dbus_handlers(DBusConnection *connection) {
+ //dbus_connection_unregister_object_path(connection, WLANCOND_REQ_PATH);
+}
--- /dev/null
+/**
+ @file dbus-helper.c
+
+ Copyright (C) 2004 Nokia Corporation. All rights reserved.
+
+ @author Janne Ylalehto <janne.ylalehto@nokia.com>
+ @author Johan Hedberg <johan.hedberg@nokia.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef _DBUS_HANDLER_H_
+#define _DBUS_HANDLER_H_
+
+#ifndef DBUS_API_SUBJECT_TO_CHANGE
+# define DBUS_API_SUBJECT_TO_CHANGE
+# include <dbus/dbus.h>
+#endif
+
+/** Bind functions to corresponding D-Bus messages
+ * @param connection D-Bus connection
+ */
+void init_dbus_handlers(DBusConnection *connection);
+
+/** Free memory allocated to handlers
+ * @param connection D-Bus connection
+ */
+void destroy_dbus_handlers(DBusConnection *connection);
+
+#endif /* _DBUS_HANDLER_H_ */
--- /dev/null
+/**
+ @file dbus-helper.c
+
+ Copyright (C) 2004 Nokia Corporation. All rights reserved.
+ Copyright (C) 2003-2009, Jouni Malinen <j@w1.fi> and contributors.
+ Copyright (C) 2009 Javier S. Pedro
+
+ @author Janne Ylalehto <janne.ylalehto@nokia.com>
+ @author Johan Hedberg <johan.hedberg@nokia.com>
+ @author Jouni Malinen <j@w1.fi> and contributors
+ @author Javier S. Pedro <javispedro@javispedro.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus.h>
+#include "log.h"
+#include "dbus-helper.h"
+
+DBusMessage *new_dbus_signal(const char *path,
+ const char *interface,
+ const char *name,
+ const char *destination) {
+ DBusMessage *signal;
+
+ signal = dbus_message_new_signal(path, interface, name);
+ if (signal == NULL) {
+ die("Out of memory during dbus_message_new_error()");
+ }
+
+ if (destination) {
+ if (!dbus_message_set_destination(signal, destination)) {
+ die("Out of memory during dbus_message_set_destination()");
+ }
+ }
+
+ dbus_message_set_no_reply(signal, TRUE);
+
+ return signal;
+}
+
+DBusMessage *new_dbus_method_call(const char *service,
+ const char *path,
+ const char *interface,
+ const char *method) {
+ DBusMessage *message;
+
+ message = dbus_message_new_method_call(service, path, interface, method);
+ if (message == NULL) {
+ die("Out of memory during dbus_message_new_method_call()");
+ }
+
+ return message;
+}
+
+DBusMessage *new_dbus_method_return(DBusMessage *message) {
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return(message);
+ if (reply == NULL) {
+ die("Out of memory during dbus_message_new_method_return()");
+ }
+
+ return reply;
+}
+
+DBusMessage *new_dbus_error(DBusMessage *message, const char *name) {
+ DBusMessage *error;
+
+ error = dbus_message_new_error(message, name, NULL);
+ if (error == NULL) {
+ die("Out of memory during dbus_message_new_error()");
+ }
+
+ return error;
+}
+
+int send_and_unref(DBusConnection *connection, DBusMessage *message) {
+ if (!dbus_connection_send(connection, message, NULL)) {
+ dbus_message_unref(message);
+ return -1;
+ }
+
+ dbus_connection_flush(connection);
+ dbus_message_unref(message);
+
+ return 0;
+}
+
+int send_invalid_args(DBusConnection *connection, DBusMessage *message) {
+ DBusMessage *reply;
+
+ reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
+
+ return send_and_unref(connection, reply);
+}
+
+void append_dbus_args(DBusMessage *message, int first_arg_type, ...) {
+ dbus_bool_t ret;
+ va_list ap;
+
+ va_start(ap, first_arg_type);
+ ret = dbus_message_append_args_valist(message, first_arg_type, ap);
+ va_end(ap);
+
+ if (ret == FALSE) {
+ die("dbus_message_append_args failed");
+ }
+}
+
+/**
+ * Start a dict in a dbus message. Should be paired with a call to
+ * {@link wpa_dbus_dict_close_write}.
+ *
+ * @param iter A valid dbus message iterator
+ * @param iter_dict (out) A dict iterator to pass to further dict functions
+ * @return 0 on success, -1 on failure
+ *
+ */
+int dbus_dict_open_write(DBusMessageIter *iter,
+ DBusMessageIter *iter_dict)
+{
+ dbus_bool_t result;
+
+ if (!iter || !iter_dict)
+ return FALSE;
+
+ result = dbus_message_iter_open_container(
+ iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ iter_dict);
+
+ return (result ? 0 : -1);
+}
+
+/**
+ * End a dict element in a dbus message. Should be paired with
+ * a call to {@link wpa_dbus_dict_open_write}.
+ *
+ * @param iter valid dbus message iterator, same as passed to
+ * wpa_dbus_dict_open_write()
+ * @param iter_dict a dbus dict iterator returned from
+ * {@link wpa_dbus_dict_open_write}
+ * @return 0 on success, -1 on failure
+ *
+ */
+int dbus_dict_close_write(DBusMessageIter *iter,
+ DBusMessageIter *iter_dict)
+{
+ if (!iter || !iter_dict)
+ return FALSE;
+
+ return dbus_message_iter_close_container(iter, iter_dict) ? 0 : -1;
+}
+
+static const char * _get_type_as_string_from_type(const int type)
+{
+ switch(type) {
+ case DBUS_TYPE_BYTE:
+ return DBUS_TYPE_BYTE_AS_STRING;
+ case DBUS_TYPE_BOOLEAN:
+ return DBUS_TYPE_BOOLEAN_AS_STRING;
+ case DBUS_TYPE_INT16:
+ return DBUS_TYPE_INT16_AS_STRING;
+ case DBUS_TYPE_UINT16:
+ return DBUS_TYPE_UINT16_AS_STRING;
+ case DBUS_TYPE_INT32:
+ return DBUS_TYPE_INT32_AS_STRING;
+ case DBUS_TYPE_UINT32:
+ return DBUS_TYPE_UINT32_AS_STRING;
+ case DBUS_TYPE_INT64:
+ return DBUS_TYPE_INT64_AS_STRING;
+ case DBUS_TYPE_UINT64:
+ return DBUS_TYPE_UINT64_AS_STRING;
+ case DBUS_TYPE_DOUBLE:
+ return DBUS_TYPE_DOUBLE_AS_STRING;
+ case DBUS_TYPE_STRING:
+ return DBUS_TYPE_STRING_AS_STRING;
+ case DBUS_TYPE_OBJECT_PATH:
+ return DBUS_TYPE_OBJECT_PATH_AS_STRING;
+ case DBUS_TYPE_ARRAY:
+ return DBUS_TYPE_ARRAY_AS_STRING;
+ default:
+ return NULL;
+ }
+}
+
+static int _dbus_add_dict_entry_start(
+ DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry,
+ const char *key, const int value_type)
+{
+ if (!dbus_message_iter_open_container(iter_dict,
+ DBUS_TYPE_DICT_ENTRY, NULL,
+ iter_dict_entry))
+ return FALSE;
+
+ if (!dbus_message_iter_append_basic(iter_dict_entry, DBUS_TYPE_STRING,
+ &key))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+static dbus_bool_t _dbus_add_dict_entry_end(
+ DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry,
+ DBusMessageIter *iter_dict_val)
+{
+ if (!dbus_message_iter_close_container(iter_dict_entry, iter_dict_val))
+ return FALSE;
+ if (!dbus_message_iter_close_container(iter_dict, iter_dict_entry))
+ return FALSE;
+
+ return TRUE;
+}
+
+static dbus_bool_t _dbus_add_dict_entry_basic(DBusMessageIter *iter_dict,
+ const char *key,
+ const int value_type,
+ const void *value)
+{
+ DBusMessageIter iter_dict_entry, iter_dict_val;
+ const char *type_as_string = NULL;
+
+ type_as_string = _get_type_as_string_from_type(value_type);
+ if (!type_as_string)
+ return FALSE;
+
+ if (!_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry,
+ key, value_type))
+ return FALSE;
+
+ if (!dbus_message_iter_open_container(&iter_dict_entry,
+ DBUS_TYPE_VARIANT,
+ type_as_string, &iter_dict_val))
+ return FALSE;
+
+ if (!dbus_message_iter_append_basic(&iter_dict_val, value_type, value))
+ return FALSE;
+
+ if (!_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry,
+ &iter_dict_val))
+ return FALSE;
+
+ return TRUE;
+}
+
+/**
+ * Add a string entry to the dict.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ * {@link wpa_dbus_dict_open_write}
+ * @param key The key of the dict item
+ * @param value The string value
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+int dbus_dict_append_string(DBusMessageIter *iter_dict,
+ const char *key, const char *value)
+{
+ if (!key || !value)
+ return FALSE;
+ return _dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_STRING,
+ &value) ? 0 : -1;
+}
+
+/**
+ * Add a 32-bit signed integer to the dict.
+ *
+ * @param iter_dict A valid DBusMessageIter returned from
+ * {@link wpa_dbus_dict_open_write}
+ * @param key The key of the dict item
+ * @param value The 32-bit signed integer value
+ * @return TRUE on success, FALSE on failure
+ *
+ */
+int dbus_dict_append_int32(DBusMessageIter *iter_dict,
+ const char *key,
+ const dbus_int32_t value)
+{
+ if (!key)
+ return FALSE;
+ return _dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT32,
+ &value) ? 0 : -1;
+}
+
--- /dev/null
+/**
+ @file dbus-helper.h
+
+ Copyright (C) 2004 Nokia Corporation. All rights reserved.
+
+ @author Janne Ylälehto <janne.ylalehto@nokia.com>
+ @author Jouni Malinen <j@w1.fi> and contributors
+ @author Javier S. Pedro <javispedro@javispedro.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _DBUS_HELPER_H_
+#define _DBUS_HELPER_H_
+
+#ifndef DBUS_API_SUBJECT_TO_CHANGE
+# define DBUS_API_SUBJECT_TO_CHANGE
+# include <dbus/dbus.h>
+#endif
+
+void append_dbus_args(DBusMessage *message, int first_arg_type, ...);
+
+int send_and_unref(DBusConnection *connection, DBusMessage *message);
+
+int send_invalid_args(DBusConnection *connection, DBusMessage *message);
+
+DBusMessage *new_dbus_signal(const char *path,
+ const char *interface,
+ const char *name,
+ const char *destination);
+
+DBusMessage *new_dbus_method_call(const char *service,
+ const char *path,
+ const char *interface,
+ const char *method);
+
+DBusMessage *new_dbus_method_return(DBusMessage *message);
+
+DBusMessage *new_dbus_error(DBusMessage *message, const char *name);
+
+int dbus_dict_open_write(DBusMessageIter *iter,
+ DBusMessageIter *iter_dict);
+int dbus_dict_close_write(DBusMessageIter *iter,
+ DBusMessageIter *iter_dict);
+
+int dbus_dict_append_string(DBusMessageIter *iter_dict,
+ const char *key, const char *value);
+
+int dbus_dict_append_int32(DBusMessageIter *iter_dict,
+ const char *key,
+ const dbus_int32_t value);
+
+#endif /* _DBUD_HELPER_H_ */
--- /dev/null
+/**
+ @file dbus.c
+
+ Copyright (C) 2004 Nokia Corporation. All rights reserved.
+
+ @author Johan Hedberg <johan.hedberg@nokia.com>
+ @author Janne Ylälehto <janne.ylalehto@nokia.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "log.h"
+#include "dbus.h"
+
+static DBusConnection *_dbus_connection = NULL;
+
+DBusConnection *get_dbus_connection(void) {
+ return _dbus_connection;
+}
+
+int setup_dbus_connection(const char *service,
+ void (*handler_init)(DBusConnection *connection)) {
+ DBusError derror;
+
+ g_assert(_dbus_connection == NULL);
+
+ dbus_error_init(&derror);
+ _dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &derror);
+ if (_dbus_connection == NULL) {
+ DLOG_ERR("System DBus connection failed: %s", derror.message);
+ dbus_error_free(&derror);
+ return -1;
+ }
+ dbus_connection_setup_with_g_main(_dbus_connection, NULL);
+
+ if (service) {
+ int ret = dbus_bus_request_name(_dbus_connection, service, 0,
+ &derror);
+ if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ DLOG_ERR("Could not aquire D-BUS name '%s' (ret: %d)",
+ service, ret);
+ if (dbus_error_is_set(&derror)) {
+ DLOG_DEBUG("%s", derror.message);
+ dbus_error_free(&derror);
+ }
+ return -1;
+ }
+ }
+
+ if (handler_init)
+ handler_init(_dbus_connection);
+
+ return 0;
+}
+
+void close_dbus_connection(void) {
+ g_assert(_dbus_connection != NULL);
+ dbus_connection_unref(_dbus_connection);
+ _dbus_connection = NULL;
+}
--- /dev/null
+/**
+ @file dbus.h
+
+ Copyright (C) 2004 Nokia Corporation. All rights reserved.
+
+ @author Johan Hedberg <johan.hedberg@nokia.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _DBUS_H_
+#define _DBUS_H_
+
+#ifndef DBUS_API_SUBJECT_TO_CHANGE
+# define DBUS_API_SUBJECT_TO_CHANGE
+# include <dbus/dbus.h>
+#endif
+
+/** Connect to the system D-Bus
+ * @returns 0 on success, -1 on failure
+ */
+int setup_dbus_connection(const char *service,
+ void (*handler_init)(DBusConnection *connection));
+
+/** Disconnect from the system D-Bus */
+void close_dbus_connection(void);
+
+DBusConnection *get_dbus_connection(void);
+
+#endif /* _DBUS_H_ */
--- /dev/null
+/**
+ @file gconf.c
+
+ Copyright (C) 2009 Javier S. Pedro
+
+ @author Javier S. Pedro <javispedro@javispedro.com>
+
+ This file is part of libicd-network-wpa.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include <string.h>
+
+#include <glib.h>
+#include <gconf/gconf-client.h>
+
+#include "log.h"
+
+gchar * gconf_get_string(GConfClient *client, gchar * path)
+{
+ GError *error = NULL;
+ gchar *value = gconf_client_get_string(client, path, &error);
+
+ if (error) {
+ DLOG_ERR("Could not get setting:%s, error:%s", path,
+ error->message);
+
+ g_clear_error(&error);
+ value = NULL;
+ } else if (!value) {
+ DLOG_ERR("Could not get setting:%s", path);
+ }
+
+ g_free(path);
+
+ return value;
+}
--- /dev/null
+/**
+ @file gconf.h
+
+ Copyright (C) 2009 Javier S. Pedro
+
+ @author Javier S. Pedro <javispedro@javispedro.com>
+
+ This file is part of libicd-network-wpa.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef _GCONF_H_
+#define _GCONF_H_
+
+gchar * gconf_get_string(GConfClient *client, gchar * path);
+
+#endif
--- /dev/null
+<gconfentryfile>
+ <entrylist base="/system/osso/connectivity/network_type/WLAN_WPA">
+ <entry>
+ <key>gettext_catalog</key>
+ <schema_key>/schemas/system/osso/connectivity/network_type/WLAN_WPA/gettext_catalog</schema_key>
+ <value>
+ <string>osso-connectivity-ui</string>
+ </value>
+ </entry>
+ <entry>
+ <key>icon_name</key>
+ <schema_key>/schemas/system/osso/connectivity/network_type/WLAN_WPA/icon_name</schema_key>
+ <value>
+ <string>qgn_list_connectivity_iaptype_adhocwlan</string>
+ </value>
+ </entry>
+ <entry>
+ <key>idle_timeout</key>
+ <value>
+ <int>0</int>
+ </value>
+ </entry>
+ <entry>
+ <key>name</key>
+ <schema_key>/schemas/system/osso/connectivity/network_type/WLAN_WPA/name</schema_key>
+ <value>
+ <string>conn_mngr_fi_type_wlan_adhoc</string>
+ </value>
+ </entry>
+ <entry>
+ <key>network_modules</key>
+ <schema_key>/schemas/system/osso/connectivity/network_type/WLAN_WPA/network_modules</schema_key>
+ <value>
+ <list type="string">
+ <value>
+ <string>libicd_network_wpa.so</string>
+ </value>
+ <value>
+ <string>libicd_network_ipv4.so</string>
+ </value>
+ <value>
+ <string>libicd_network_ipv6.so</string>
+ </value>
+ </list>
+ </value>
+ </entry>
+ <entry>
+ <key>statusbar_icon_name</key>
+ <schema_key>/schemas/system/osso/connectivity/network_type/WLAN_WPA/statusbar_icon_name</schema_key>
+ <value>
+ <string>qgn_stat_internetconn_adhocwlan</string>
+ </value>
+ </entry>
+ </entrylist>
+</gconfentryfile>
--- /dev/null
+/**
+ @file icd.c
+
+ Copyright (C) 2009 Javier S. Pedro
+
+ @author Javier S. Pedro <javispedro@javispedro.com>
+
+ This file is part of libicd-network-wpa.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include <glib.h>
+
+#include <network_api.h>
+#include <osso-ic-dbus.h>
+
+#include "common.h"
+#include "dbus.h"
+#include "dbus-handler.h"
+#include "log.h"
+#include "supp.h"
+#include "networks.h"
+#include "icd.h"
+
+/** time in seconds a found network is kept cached by icd2 */
+#define ICD_SEARCH_LIFETIME (5 * 60)
+/** time in seconds after which a new network scan is to be triggered */
+#define ICD_SEARCH_INTERVAL (2 * 60)
+
+/** time (in milliseconds) to wait after a wpa_supplicant disconnected event
+ * before calling it a day and shutting down the interface */
+#define ICD_DISCONNECTED_TIMEOUT (60 * 1000)
+
+/** icd flags to use */
+#define ICD_WPA_FLAGS (ICD_NW_ATTR_AUTOCONNECT | ICD_NW_ATTR_IAPNAME)
+
+
+/** equivalent to signal level 0 */
+#define RSSI_MIN (-85)
+/** equivalent to signal level max */
+#define RSSI_MAX (-30)
+/* guaranteed to be random, chosen by fair dice roll :) */
+
+
+static icd_nw_watch_pid_fn icd_watch_fn;
+static gpointer icd_watch_token;
+static icd_nw_close_fn icd_close_fn;
+static icd_nw_status_change_fn icd_status_change_fn;
+static icd_nw_renew_fn icd_renew_fn;
+
+static gchar * cur_network_id = NULL;
+
+/** @see ICD_DISCONNECTED_TIMEOUT */
+static guint connect_timeout = 0;
+
+static inline gint rssi_to_signal(gint rssi)
+{
+ gint signal = rssi - RSSI_MIN + ICD_NW_LEVEL_NONE;
+ signal *= ICD_NW_LEVEL_10;
+ signal /= (RSSI_MAX - RSSI_MIN);
+
+ if (signal < ICD_NW_LEVEL_NONE) return ICD_NW_LEVEL_NONE;
+ else if (signal > ICD_NW_LEVEL_10) return ICD_NW_LEVEL_10;
+ else return signal;
+}
+
+static gboolean disconnected_timeout_cb(gpointer data)
+{
+ // If connect_timeout is 0, we have been disabled.
+ if (!connect_timeout) return FALSE;
+
+ // Disconnected for too long
+ DLOG_DEBUG("Disconnected for way too long");
+ icd_close(ICD_NW_ERROR, ICD_DBUS_ERROR_NETWORK_ERROR);
+ connect_timeout = 0;
+ return FALSE;
+}
+
+/** Supplicant callback while fully connected */
+static void icd_supp_cb(enum supp_status status, const char * error_str,
+ gpointer user_data)
+{
+ DLOG_DEBUG("%s: %d", __func__, status);
+
+ switch (status) {
+ case SUPP_STATUS_ERROR:
+ DLOG_WARN_L("Unexpected supplicant error");
+
+ // Fall through
+ case SUPP_STATUS_KILLED:
+ // Close connection
+ icd_close(ICD_NW_ERROR, ICD_DBUS_ERROR_SYSTEM_ERROR);
+
+ break;
+ case SUPP_STATUS_DISCONNECTED:
+ if (!connect_timeout) {
+ DLOG_DEBUG("Disconnected, starting timeout");
+ connect_timeout = g_timeout_add(
+ ICD_DISCONNECTED_TIMEOUT,
+ disconnected_timeout_cb,
+ NULL
+ );
+ }
+ break;
+ case SUPP_STATUS_CONNECTED:
+ if (connect_timeout) {
+ DLOG_DEBUG("Connected, removing timeout");
+ g_source_remove(connect_timeout);
+ connect_timeout = 0;
+ }
+ break;
+ }
+
+ // TODO Disable PSM while roaming (dis/asociating)?
+}
+
+struct pre_down_data {
+ icd_nw_link_pre_down_cb_fn link_pre_down_cb;
+ gpointer link_pre_down_cb_token;
+};
+
+/** Supplicant callback in link_pre_down mode */
+static void icd_down_supp_cb(enum supp_status status, const char * error_str,
+ gpointer user_data)
+{
+ struct pre_down_data *data = (struct pre_down_data *) user_data;
+ DLOG_DEBUG("%s: %d", __func__, status);
+
+ if (status == SUPP_STATUS_KILLED) {
+ // Everything was fine
+ supp_set_callback(NULL, NULL);
+ data->link_pre_down_cb(ICD_NW_SUCCESS,
+ data->link_pre_down_cb_token);
+ }
+}
+
+static void
+icd_pre_down (const gchar *network_type,
+ const guint network_attrs,
+ const gchar *network_id,
+ const gchar *interface_name,
+ icd_nw_link_pre_down_cb_fn link_pre_down_cb,
+ const gpointer link_pre_down_cb_token,
+ gpointer *private)
+{
+ DLOG_DEBUG(__func__);
+
+
+ struct pre_down_data *data = g_new(struct pre_down_data, 1);
+ data->link_pre_down_cb = link_pre_down_cb;
+ data->link_pre_down_cb_token = link_pre_down_cb_token;
+
+ if (supp_is_active()) {
+ supp_set_callback(icd_down_supp_cb, data);
+
+ // Kill the supplicant,
+ supp_disable();
+ // but wait for the "child exit" event.
+ } else {
+ // Supplicant is already dead, no need to wait.
+ supp_set_callback(NULL, NULL);
+ supp_disable(); // Clears status info
+
+ link_pre_down_cb(ICD_NW_SUCCESS, link_pre_down_cb_token);
+ }
+}
+
+struct post_up_data {
+ icd_nw_link_post_up_cb_fn link_post_up_cb;
+ gpointer link_post_up_cb_token;
+};
+
+/** Supplicant callback in link_post_up status */
+static void icd_up_supp_cb(enum supp_status status, const char * error_str,
+ gpointer user_data)
+{
+ struct post_up_data *data = (struct post_up_data *) user_data;
+ DLOG_DEBUG("%s: %d", __func__, status);
+
+ switch (status) {
+ case SUPP_STATUS_CONNECTED:
+ data->link_post_up_cb(ICD_NW_SUCCESS_NEXT_LAYER,
+ NULL,
+ data->link_post_up_cb_token, NULL);
+
+ supp_set_callback(icd_supp_cb, NULL);
+ g_free(data);
+ break;
+ case SUPP_STATUS_DISCONNECTED:
+ error_str = ICD_DBUS_ERROR_WLAN_AUTH_FAILED;
+
+ // Fall through
+ case SUPP_STATUS_ERROR:
+
+ // An error happened
+ // kill the supplicant before everything crashes.
+ supp_set_callback(NULL, NULL);
+ supp_disable();
+
+ // Fall through
+ case SUPP_STATUS_KILLED:
+ data->link_post_up_cb(ICD_NW_ERROR,
+ error_str,
+ data->link_post_up_cb_token, NULL);
+
+ g_free(data);
+ break;
+
+ }
+}
+
+static void icd_post_up(const gchar *network_type,
+ const guint network_attrs,
+ const gchar *network_id,
+ const gchar *interface_name,
+ icd_nw_link_post_up_cb_fn link_post_up_cb,
+ const gpointer link_post_up_cb_token,
+ gpointer *private)
+{
+ DLOG_DEBUG(__func__);
+
+ struct post_up_data *data = g_new(struct post_up_data, 1);
+ data->link_post_up_cb = link_post_up_cb;
+ data->link_post_up_cb_token = link_post_up_cb_token;
+
+ supp_set_callback(icd_up_supp_cb, data);
+
+ if (supp_enable() != 0)
+ {
+ icd_up_supp_cb(-1, ICD_DBUS_ERROR_SYSTEM_ERROR, data);
+ }
+
+ supp_set_interface(interface_name);
+ supp_set_network_id(network_id);
+}
+
+static void icd_link_down(const gchar *network_type,
+ const guint network_attrs,
+ const gchar *network_id,
+ const gchar *interface_name,
+ icd_nw_link_down_cb_fn link_down_cb,
+ const gpointer link_down_cb_token,
+ gpointer *private)
+{
+ DLOG_DEBUG(__func__);
+
+ networks_disconnect(network_id);
+
+ g_free(cur_network_id);
+ cur_network_id = NULL;
+
+ // TODO: Maybe wait for wlancond->disconnect callback?
+
+ link_down_cb(ICD_NW_SUCCESS, link_down_cb_token);
+}
+
+struct link_up_data {
+ icd_nw_link_up_cb_fn link_up_cb;
+ gpointer link_up_cb_token;
+};
+
+static void icd_link_up_done(int status, const char *error, gpointer user_data)
+{
+ DLOG_DEBUG("%s: %d", __func__, status);
+
+ struct link_up_data *data = (struct link_up_data *) user_data;
+
+ if (status) {
+ g_free(cur_network_id);
+ cur_network_id = NULL;
+ data->link_up_cb(ICD_NW_ERROR,
+ error,
+ WPA_IFACE, data->link_up_cb_token,
+ NULL);
+
+ } else {
+ data->link_up_cb(ICD_NW_SUCCESS_NEXT_LAYER,
+ NULL,
+ WPA_IFACE, data->link_up_cb_token,
+ NULL);
+ }
+
+ g_free(data);
+}
+
+static void icd_link_up(const gchar *network_type,
+ const guint network_attrs,
+ const gchar *network_id,
+ icd_nw_link_up_cb_fn link_up_cb,
+ const gpointer link_up_cb_token,
+ gpointer *private)
+{
+ DLOG_DEBUG("%s: %s", __func__, network_id);
+
+ struct link_up_data *data = g_new(struct link_up_data, 1);
+ data->link_up_cb = link_up_cb;
+ data->link_up_cb_token = link_up_cb_token;
+
+ if (cur_network_id) {
+ DLOG_WARN_L("Double link up");
+
+ data->link_up_cb(ICD_NW_TOO_MANY_CONNECTIONS,
+ NULL,
+ WPA_IFACE, data->link_up_cb_token,
+ NULL);
+
+ return;
+ }
+ cur_network_id = g_strdup(network_id);
+
+ networks_connect(network_id, icd_link_up_done, data);
+}
+
+struct stats_data {
+ icd_nw_link_stats_cb_fn cb;
+ gpointer token;
+};
+
+static void icd_link_stats_done
+ (int status, const char * strdata, int rssi, gpointer user_data)
+{
+ DLOG_DEBUG("%s: %d", __func__, status);
+
+ struct stats_data * data = (struct stats_data *) user_data;
+
+ gint signal = rssi_to_signal(rssi);
+
+ DLOG_DEBUG("status: rssi=%d, signal=%d", rssi, signal);
+
+ data->cb(data->token,
+ WPA_NETWORK_TYPE,
+ ICD_WPA_FLAGS,
+ cur_network_id,
+ /*time_active*/ 0,
+ /*signal*/ signal,
+ /*station_id*/ NULL,
+ /*dB*/ rssi,
+ /*tx*/0,
+ /*rx*/0);
+
+ // IPv[46] module will fill time_active, rx & tx values.
+ // TODO station_id
+
+ g_free(data);
+}
+
+static void icd_link_stats(const gchar *network_type,
+ const guint network_attrs,
+ const gchar *network_id,
+ gpointer *private,
+ icd_nw_link_stats_cb_fn cb,
+ const gpointer link_stats_cb_token)
+{
+ DLOG_DEBUG("%s", __func__);
+
+ struct stats_data *data = g_new(struct stats_data, 1);
+ data->cb = cb;
+ data->token = link_stats_cb_token;
+
+ networks_status(icd_link_stats_done, data);
+}
+
+struct search_data {
+ icd_nw_search_cb_fn search_cb;
+ gpointer search_cb_token;
+};
+
+static void icd_send_search_result(int status, const char * id,
+ const char * ssid, const char * ap, int rssi, gpointer user_data)
+{
+ DLOG_DEBUG("%s: %d", __func__, status);
+
+ struct search_data * data = (struct search_data *) user_data;
+ gint signal;
+
+ switch (status) {
+ case SEARCH_CONTINUE:
+ signal = rssi_to_signal(rssi);
+
+ data->search_cb(ICD_NW_SEARCH_CONTINUE,
+ (gchar *) ssid,
+ WPA_NETWORK_TYPE,
+ ICD_WPA_FLAGS,
+ (gchar *) id,
+ signal,
+ /*ap*/"ap",
+ signal,
+ data->search_cb_token);
+ break;
+ case SEARCH_FINISHED:
+ data->search_cb(ICD_NW_SEARCH_COMPLETE,
+ NULL,
+ WPA_NETWORK_TYPE,
+ 0,
+ NULL,
+ ICD_NW_LEVEL_NONE,
+ NULL,
+ 0,
+ data->search_cb_token);
+ // Fall through
+ case SEARCH_STOPPED:
+ g_free(user_data);
+ break;
+ }
+}
+
+static void icd_start_search(const gchar *network_type,
+ guint search_scope,
+ icd_nw_search_cb_fn search_cb,
+ const gpointer search_cb_token,
+ gpointer *private)
+{
+ DLOG_DEBUG(__func__);
+
+ struct search_data *data = g_new(struct search_data, 1);
+ data->search_cb = search_cb;
+ data->search_cb_token = search_cb_token;
+
+ networks_search_start(icd_send_search_result, data);
+}
+
+static void icd_stop_search(gpointer *private)
+{
+ DLOG_DEBUG(__func__);
+
+ // Never seen this called.
+
+ networks_search_stop();
+}
+
+static void icd_child_exit(const pid_t pid,
+ const gint exit_value,
+ gpointer *private)
+{
+ DLOG_DEBUG(__func__);
+
+ /*// Supplicant crashed/exited!
+ if (killed_supp_cb) {
+ // We have killed it, notify auth layer is now down.
+
+ g_free(killed_supp_cb);
+ killed_supp_cb = 0;
+ } else {
+ DLOG_WARN("Supplicant exited, but we didn't expect it");
+ icd_close(ICD_NW_ERROR, ICD_DBUS_ERROR_SYSTEM_ERROR);
+ }*/
+ supp_handle_killed();
+}
+
+static void icd_network_destruct(gpointer *private)
+{
+ DLOG_DEBUG(__func__);
+
+ // Fortunately, icd kills the supplicant for us.
+
+ close_dbus_connection();
+ networks_free();
+}
+
+gboolean icd_nw_init (
+ struct icd_nw_api *network_api,
+ icd_nw_watch_pid_fn watch_fn,
+ gpointer watch_fn_token,
+ icd_nw_close_fn close_fn,
+ icd_nw_status_change_fn status_change_fn,
+ icd_nw_renew_fn renew_fn )
+{
+ network_api->version = ICD_NW_MODULE_VERSION;
+ network_api->private = NULL;
+
+ network_api->link_pre_down = icd_pre_down;
+ network_api->link_post_up = icd_post_up;
+
+ network_api->link_down = icd_link_down;
+ network_api->link_up = icd_link_up;
+ network_api->link_stats = icd_link_stats;
+
+ network_api->search_lifetime = ICD_SEARCH_LIFETIME;
+ network_api->search_interval = ICD_SEARCH_INTERVAL;
+
+ network_api->start_search = icd_start_search;
+ network_api->stop_search = icd_stop_search;
+
+ network_api->child_exit = icd_child_exit;
+
+ network_api->network_destruct = icd_network_destruct;
+
+ icd_watch_fn = watch_fn;
+ icd_watch_token = watch_fn_token;
+ icd_close_fn = close_fn;
+ icd_status_change_fn = status_change_fn;
+ icd_renew_fn = renew_fn;
+
+ if (networks_initialize() != 0) {
+ DLOG_ERR_L("Network list failed!");
+ return FALSE;
+ }
+
+ if (setup_dbus_connection(NULL, init_dbus_handlers) != 0) {
+ DLOG_ERR_L("D-BUS connection setup failed!");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void icd_watch_pid(const pid_t pid)
+{
+ icd_watch_fn(pid, icd_watch_token);
+}
+
+void icd_close(enum icd_nw_status status,
+ const gchar *err_str)
+{
+ icd_close_fn(status, err_str, WPA_NETWORK_TYPE, ICD_WPA_FLAGS, cur_network_id);
+}
+
--- /dev/null
+/**
+ @file icd.h
+
+ Copyright (C) 2009 Javier S. Pedro
+
+ @author Javier S. Pedro <javispedro@javispedro.com>
+
+ This file is part of libicd-network-wpa.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef _ICD_H_
+#define _ICD_H_
+
+#include <network_api.h>
+
+void icd_watch_pid(const pid_t pid);
+
+void icd_close(enum icd_nw_status status,
+ const gchar *err_str);
+
+#endif
--- /dev/null
+/*
+ libicd-network-wpa-dev
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License version 2.1 as
+ published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this library; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/**
+ @file wlancond.h
+
+ @author Javier S. Pedro
+*/
+
+#ifndef _WLANCOND_SUPP_H_
+#define _WLANCOND_SUPP_H_
+
+#define WLANCOND_USE_SUPPLICANT (1 << 20)
+
+#endif
--- /dev/null
+/**
+ @file log.h
+
+ Copyright (C) 2004 Nokia Corporation. All rights reserved.
+
+ @author Johan Hedberg <johan.hedberg@nokia.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+#ifndef _LOG_H_
+#define _LOG_H_
+
+#include <stdlib.h>
+#include <osso-log.h>
+
+/** Print error message and exit */
+#define die(...) do { \
+ DLOG_ERR(__VA_ARGS__); \
+ exit(EXIT_FAILURE); \
+} while (0)
+
+#endif /* _LOG_H_ */
--- /dev/null
+/**
+ @file networks.c
+
+ Copyright (C) 2009 Javier S. Pedro
+
+ @author Javier S. Pedro <javispedro@javispedro.com>
+
+ This file is part of libicd-network-wpa.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include <libgen.h>
+#include <string.h>
+
+#include <glib.h>
+#include <gconf/gconf-client.h>
+
+#include <icd/osso-ic-gconf.h>
+#include <icd/osso-ic-dbus.h>
+
+#include "common.h"
+#include "log.h"
+#include "wlan.h"
+#include "networks.h"
+#include "gconf.h"
+
+#define FAILED_SCAN_RETRY_WAIT 3 * 1000
+#define FAILED_SCAN_RETRY_TRIES 3
+
+#define GCONF_NETWORK_TYPE "/type"
+
+static GSList *net_list = NULL;
+
+int networks_initialize()
+{
+ DLOG_DEBUG(__func__);
+ GConfClient *client = gconf_client_get_default();
+ GError *error = NULL;
+
+ net_list = NULL;
+
+ if (!client) {
+ DLOG_ERR("Cannot get gconf client");
+ return -1;
+ }
+
+ net_list = gconf_client_all_dirs(client, ICD_GCONF_PATH, &error);
+ if (error) {
+ DLOG_ERR("Could not get setting:%s, error:%s", ICD_GCONF_PATH,
+ error->message);
+ g_clear_error(&error);
+ g_object_unref(client);
+ return -1;
+ }
+
+ // Now, filter networks
+ GSList *prev = NULL;
+ GSList *cur = net_list;
+ while (cur) {
+ gchar* path = g_strconcat(cur->data, WPA_GCONF_NETWORK_TYPE, NULL);
+ gchar* type = gconf_client_get_string(client, path, &error);
+
+ g_free(path);
+
+ if (error) {
+ DLOG_ERR("Could not get setting:%s, error:%s", path,
+ error->message);
+ g_clear_error(&error);
+
+ goto initialize_error;
+ } else if (!type) {
+ DLOG_ERR("Could not get setting:%s", path);
+
+ goto initialize_error;
+ }
+
+ if (strcmp(type, WPA_GCONF_NETWORK_TYPE_VALUE) != 0) {
+ // Remove this network from the list
+ DLOG_DEBUG("Ignoring %s from IAP (type is %s)",
+ (gchar*)cur->data, type);
+ g_free(cur->data);
+ if (prev) {
+ GSList *del = cur;
+ cur = g_slist_next(cur);
+ g_slist_free1(del);
+ prev->next = cur;
+ } else {
+ net_list = g_slist_next(cur);
+ g_slist_free1(cur);
+ cur = net_list;
+ }
+ } else {
+ DLOG_DEBUG("Added network %s from IAP", (gchar*)cur->data);
+
+ prev = cur;
+ cur = g_slist_next(cur);
+ }
+
+ g_free(type);
+ }
+
+ return 0;
+
+initialize_error:
+ g_object_unref(client);
+ networks_free();
+
+ return -1;
+}
+
+static void free_list_item(gpointer data, gpointer user_data)
+{
+ g_free(data);
+}
+
+void networks_free()
+{
+ DLOG_DEBUG(__func__);
+ if (!net_list) return;
+
+ g_slist_foreach(net_list, free_list_item, NULL);
+
+ g_slist_free(net_list);
+ net_list = NULL;
+}
+
+
+/* Scanning networks */
+
+static GSList *scan_cur_net = NULL;
+static gchar *scan_cur_ssid = NULL;
+static int scan_tries = 0;
+static guint scan_retry_timer = 0;
+static networks_search_found scan_found_cb = NULL;
+static gpointer scan_found_cb_data = NULL;
+
+static void networks_search_iteration();
+
+static void networks_search_finished()
+{
+ DLOG_DEBUG(__func__);
+
+ scan_found_cb(SEARCH_FINISHED, NULL,
+ NULL, NULL, 0, scan_found_cb_data);
+ scan_cur_net = NULL;
+
+ scan_found_cb = NULL;
+ scan_found_cb_data = NULL;
+ // Usually a new network_search will not happen on the FINISED cb,
+ // but if you do, you'll have to take care of the pseudorace here.
+
+ networks_search_stop();
+}
+
+static void networks_search_scan_ap_found(int status,
+ const char * ssid, const char * ap, int dB)
+{
+ DLOG_DEBUG(__func__);
+
+ if (!scan_cur_net) return;
+ if (scan_retry_timer) return; // Interface was already scanning
+
+ if (status == SEARCH_FINISHED) {
+ DLOG_DEBUG("Searching for %s done, iterating", scan_cur_ssid);
+ // Go to next network
+ scan_cur_net = g_slist_next(scan_cur_net);
+ if (scan_cur_net) {
+ g_free(scan_cur_ssid);
+ scan_cur_ssid = NULL;
+ scan_tries = 0;
+ networks_search_iteration();
+ } else {
+ // No more networks to search
+ networks_search_finished();
+ }
+ } else if (status == SEARCH_CONTINUE) {
+ DLOG_DEBUG("Found ssid %s", ssid);
+ if (strcmp(ssid, scan_cur_ssid) == 0)
+ {
+ // This is our man
+ gchar *full_name = g_strdup(scan_cur_net->data);
+
+ gchar *base_name = g_strdup(basename(full_name));
+
+ DLOG_INFO("%s (%s) was found",
+ base_name, ssid);
+
+ scan_found_cb(SEARCH_CONTINUE, base_name,
+ ssid, ap, dB, scan_found_cb_data);
+
+ g_free(base_name);
+ g_free(full_name);
+ }
+ }
+}
+
+static gboolean networks_search_retry(gpointer data)
+{
+ DLOG_DEBUG(__func__);
+
+ scan_retry_timer = 0;
+ if (scan_cur_net) networks_search_iteration();
+ // Always disable this timeout,
+ // _search_iteration() will put a newer one if needed
+ return FALSE;
+}
+
+static void networks_search_iteration()
+{
+ DLOG_DEBUG(__func__);
+
+ GConfClient *client = gconf_client_get_default();
+ GError *error = NULL;
+
+ if (!client) {
+ DLOG_ERR("Cannot get gconf client");
+ goto get_gconf_error;
+ }
+
+ DLOG_DEBUG("Test if %s is active", (gchar*)scan_cur_net->data);
+
+ gchar *path = g_strconcat(scan_cur_net->data, WPA_GCONF_SSID, NULL);
+ scan_cur_ssid = gconf_client_get_string(client, path, &error);
+
+ g_object_unref(client);
+
+ if (error) {
+ DLOG_ERR("Could not get setting:%s, error:%s", path,
+ error->message);
+ g_clear_error(&error);
+
+ goto get_ssid_error;
+ }
+ else if (!scan_cur_ssid) {
+ DLOG_ERR("Could not get setting:%s", path);
+
+ goto get_ssid_error;
+ }
+
+ scan_retry_timer = 0;
+
+ int result = wlan_scan(scan_cur_ssid, networks_search_scan_ap_found);
+
+ if (result != 0) {
+ // Something went wront scanning this network, set timeout and
+ // try again
+ scan_tries++;
+ if (scan_tries >= FAILED_SCAN_RETRY_TRIES) {
+ // Give up
+ goto scan_error;
+ } else {
+ scan_retry_timer = g_timeout_add(FAILED_SCAN_RETRY_WAIT,
+ networks_search_retry,
+ NULL);
+ }
+ }
+
+ return;
+get_ssid_error:
+ g_free(path);
+
+get_gconf_error:
+scan_error:
+ networks_search_finished();
+}
+
+void networks_search_start(networks_search_found found_cb, gpointer user_data)
+{
+ DLOG_DEBUG(__func__);
+
+ if (scan_cur_net)
+ return; // Already active
+
+ scan_cur_net = net_list;
+ scan_tries = 0;
+ scan_found_cb = found_cb;
+ scan_found_cb_data = user_data;
+
+ if (scan_cur_net)
+ networks_search_iteration();
+ else // No networks to scan?
+ networks_search_finished();
+}
+
+void networks_search_stop()
+{
+ DLOG_DEBUG(__func__);
+
+ if (scan_found_cb)
+ scan_found_cb(SEARCH_STOPPED,
+ NULL, NULL, NULL, 0, scan_found_cb_data);
+ scan_cur_net = NULL;
+
+ scan_found_cb = NULL;
+ scan_found_cb_data = NULL;
+
+ g_free(scan_cur_ssid);
+ scan_cur_ssid = NULL;
+
+ DLOG_DEBUG("Search stopped");
+}
+
+/* Connecting to networks */
+
+static networks_connect_result connect_result_cb = NULL;
+static gpointer connect_result_cb_data = NULL;
+
+static void networks_connected(int status, const char *error)
+{
+ DLOG_DEBUG("%s: %d", __func__, status);
+
+ if (!connect_result_cb) return;
+
+ if (status) {
+ connect_result_cb(status, ICD_DBUS_ERROR_NETWORK_ERROR,
+ connect_result_cb_data);
+ } else {
+ connect_result_cb(0, NULL,
+ connect_result_cb_data);
+ }
+
+ connect_result_cb = NULL;
+}
+
+void networks_connect(const char * id,
+ networks_connect_result result_cb, gpointer user_data)
+{
+ DLOG_DEBUG("%s: %s", __func__, id);
+ GConfClient *client = gconf_client_get_default();
+
+ connect_result_cb = result_cb;
+ connect_result_cb_data = user_data;
+
+ gchar *net = g_strconcat(ICD_GCONF_PATH, "/", id, NULL);
+ gchar *path, *value;
+
+ // Get ICD network type
+ path = g_strconcat(net, WPA_GCONF_NETWORK_TYPE, NULL);
+ value = gconf_get_string(client, path);
+
+ if (!value || strcmp(value, WPA_GCONF_NETWORK_TYPE_VALUE) != 0) {
+ result_cb(-1, ICD_DBUS_ERROR_INVALID_IAP, user_data);
+ goto connect_error;
+ }
+
+ g_free(value);
+
+ path = g_strconcat(net, WPA_GCONF_SSID, NULL);
+ value = gconf_get_string(client, path);
+
+ if (!value) {
+ result_cb(-1, ICD_DBUS_ERROR_INVALID_IAP, user_data);
+ goto connect_error;
+ }
+
+ wlan_connect(value, networks_connected);
+
+connect_error:
+ if (value) g_free(value);
+}
+
+void networks_disconnect(const char * id)
+{
+ wlan_disconnect();
+}
+
+/* -- STATUS -- */
+
+static networks_status_result status_result_cb = NULL;
+static gpointer status_result_cb_data = NULL;
+
+static void networks_status_reply(int status,
+ const char * essid, int essid_len,
+ const char * bssid, int bssid_len,
+ int qual, int channel, unsigned long security, unsigned long capability,
+ const char * data)
+{
+ if (!status_result_cb) return;
+
+ if (status == 0) {
+ status_result_cb(status, essid, qual, status_result_cb_data);
+ } else {
+ status_result_cb(status, data, 0, status_result_cb_data);
+ }
+}
+
+void networks_status(networks_status_result result_cb, gpointer user_data)
+{
+ status_result_cb = result_cb;
+ status_result_cb_data = user_data;
+
+ wlan_get_status(networks_status_reply);
+}
+
--- /dev/null
+/**
+ @file networks.h
+
+ Copyright (C) 2009 Javier S. Pedro
+
+ @author Javier S. Pedro <javispedro@javispedro.com>
+
+ This file is part of libicd-network-wpa.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef _NETWORKS_H_
+#define _NETWORKS_H_
+
+int networks_initialize();
+void networks_free();
+
+// NULL, NULL, 0 if search ended
+typedef void (*networks_search_found)
+ (int status, const char * id,
+ const char * ssid, const char * ap, int dB, gpointer user_data);
+
+void networks_search_start(networks_search_found found_cb, gpointer user_data);
+void networks_search_stop();
+
+typedef void (*networks_connect_result)
+ (int status, const char * error, gpointer user_data);
+void networks_connect(const char * id,
+ networks_connect_result result_cb, gpointer user_data);
+void networks_disconnect(const char * id);
+
+typedef void (*networks_status_result)
+ (int status, const char * data, int rssi, gpointer user_data);
+void networks_status(networks_status_result result_cb, gpointer user_data);
+
+#endif
--- /dev/null
+diff -rup src.orig/sm_drv_ioctl_umac.c src/sm_drv_ioctl_umac.c
+--- src.orig/sm_drv_ioctl_umac.c 2009-02-16 23:51:34.000000000 +0100
++++ src/sm_drv_ioctl_umac.c 2009-02-23 00:19:10.000000000 +0100
+@@ -1928,6 +1928,435 @@ static int sm_drv_set_pmk(struct net_dev
+ (void *)&key, sizeof(struct obj_stakey));
+ }
+
++static int sm_drv_set_auth(struct net_device *dev,
++ struct iw_request_info *info,
++ union iwreq_data *wrqu, char *extra)
++{
++ struct net_local *priv = netdev_priv(dev);
++ struct iw_param *param = &wrqu->param;
++ u32 authen = 0, dot1x = 0;
++ u32 exunencrypt = 0, privinvoked = 0, wpa = 0;
++ u32 old_wpa;
++ int ret = 0;
++
++ DEBUG(DBG_IOCTL, "SET AUTH\n");
++
++ /* first get the flags */
++ down(&priv->wpa_sem);
++ wpa = old_wpa = priv->wpa;
++ up(&priv->wpa_sem);
++ ret = sm_drv_oid_get(dev, DOT11_OID_AUTHENABLE,
++ (void *)&authen, sizeof(uint32_t));
++ ret |= sm_drv_oid_get(dev, DOT11_OID_PRIVACYINVOKED,
++ (void *)&privinvoked, sizeof(uint32_t));
++ ret |= sm_drv_oid_get(dev, DOT11_OID_EXUNENCRYPTED,
++ (void *)&exunencrypt, sizeof(uint32_t));
++ ret |= sm_drv_oid_get(dev, DOT11_OID_DOT1XENABLE,
++ (void *)&dot1x, sizeof(uint32_t));
++
++ if (ret < 0)
++ goto out;
++
++ switch (param->flags & IW_AUTH_INDEX) {
++ case IW_AUTH_CIPHER_PAIRWISE:
++ case IW_AUTH_CIPHER_GROUP:
++ case IW_AUTH_KEY_MGMT:
++ break;
++
++ case IW_AUTH_WPA_ENABLED:
++ /* Do the same thing as IW_AUTH_WPA_VERSION */
++ if (param->value) {
++ wpa = DOT11_PRIV_INV_TKIP;
++ privinvoked = 1; /* For privacy invoked */
++ exunencrypt = 1; /* Filter out all unencrypted frames */
++ dot1x = 0x01; /* To enable eap filter */
++ authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */
++ } else {
++ wpa = DOT11_PRIV_INV_NONE;
++ privinvoked = 0;
++ exunencrypt = 0; /* Do not filter un-encrypted data */
++ dot1x = 0;
++ }
++ break;
++
++ case IW_AUTH_WPA_VERSION:
++ if (param->value & IW_AUTH_WPA_VERSION_DISABLED) {
++ wpa = DOT11_PRIV_INV_NONE;
++ privinvoked = 0;
++ exunencrypt = 0; /* Do not filter un-encrypted data */
++ dot1x = 0;
++ } else {
++ if (param->value & IW_AUTH_WPA_VERSION_WPA)
++ wpa = DOT11_PRIV_INV_TKIP;
++ else if (param->value & IW_AUTH_WPA_VERSION_WPA2)
++ wpa = DOT11_PRIV_INV_AES_CCMP;
++ privinvoked = 1; /* For privacy invoked */
++ exunencrypt = 1; /* Filter out all unencrypted frames */
++ dot1x = 0x01; /* To enable eap filter */
++ authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */
++ }
++ break;
++
++ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
++ /* dot1x should be the opposite of RX_UNENCRYPTED_EAPOL;
++ * turn off dot1x when allowing receipt of unencrypted EAPOL
++ * frames, turn on dot1x when receipt should be disallowed
++ */
++ dot1x = param->value ? 0 : 0x01;
++ break;
++
++ case IW_AUTH_PRIVACY_INVOKED:
++ privinvoked = param->value ? 1 : 0;
++ break;
++
++ case IW_AUTH_DROP_UNENCRYPTED:
++ exunencrypt = param->value ? 1 : 0;
++ break;
++
++ case IW_AUTH_80211_AUTH_ALG:
++ if (param->value & IW_AUTH_ALG_SHARED_KEY) {
++ /* Only WEP uses _SK and _BOTH */
++ if (wpa > 0) {
++ ret = -EINVAL;
++ goto out;
++ }
++ authen = DOT11_AUTH_SK;
++ } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
++ authen = DOT11_AUTH_OS;
++ } else {
++ ret = -EINVAL;
++ goto out;
++ }
++ break;
++
++ default:
++ return -EOPNOTSUPP;
++ }
++
++ /* Set all the values */
++ down(&priv->wpa_sem);
++ priv->wpa = wpa;
++ up(&priv->wpa_sem);
++
++ sm_drv_oid_set(dev, DOT11_OID_AUTHENABLE,
++ (void *)&authen, sizeof(uint32_t));
++ sm_drv_oid_set(dev, DOT11_OID_PRIVACYINVOKED,
++ (void *)&privinvoked, sizeof(uint32_t));
++ sm_drv_oid_set(dev, DOT11_OID_EXUNENCRYPTED,
++ (void *)&exunencrypt, sizeof(uint32_t));
++ sm_drv_oid_set(dev, DOT11_OID_DOT1XENABLE,
++ (void *)&dot1x, sizeof(uint32_t));
++
++ out:
++ return ret;
++}
++
++static int sm_drv_get_auth(struct net_device *dev,
++ struct iw_request_info *info,
++ union iwreq_data *wrqu, char *extra)
++{
++ struct net_local *priv = netdev_priv(dev);
++ struct iw_param *param = &wrqu->param;
++ u32 authen = 0, dot1x = 0;
++ u32 exunencrypt = 0, privinvoked = 0, wpa = 0;
++ int ret = 0;
++
++ DEBUG(DBG_IOCTL, "GET AUTH\n");
++
++ /* first get the flags */
++ down(&priv->wpa_sem);
++ wpa = priv->wpa;
++ up(&priv->wpa_sem);
++
++ switch (param->flags & IW_AUTH_INDEX) {
++ case IW_AUTH_CIPHER_PAIRWISE:
++ case IW_AUTH_CIPHER_GROUP:
++ case IW_AUTH_KEY_MGMT:
++ /*
++ * wpa_supplicant will control these internally
++ */
++ ret = -EOPNOTSUPP;
++ break;
++
++ case IW_AUTH_WPA_VERSION:
++ switch (wpa) {
++ case DOT11_PRIV_INV_TKIP:
++ param->value = IW_AUTH_WPA_VERSION_WPA;
++ break;
++ case DOT11_PRIV_INV_AES_CCMP:
++ param->value = IW_AUTH_WPA_VERSION_WPA2;
++ break;
++ default:
++ param->value = IW_AUTH_WPA_VERSION_DISABLED;
++ break;
++ }
++ break;
++
++ case IW_AUTH_DROP_UNENCRYPTED:
++ ret = sm_drv_oid_get(dev, DOT11_OID_EXUNENCRYPTED,
++ (void *)&exunencrypt, sizeof(uint32_t));
++ if (ret >= 0)
++ param->value = exunencrypt > 0 ? 1 : 0;
++ break;
++
++ case IW_AUTH_80211_AUTH_ALG:
++ ret = sm_drv_oid_get(dev, DOT11_OID_AUTHENABLE,
++ (void *)&authen, sizeof(uint32_t));
++ if (ret >= 0) {
++ switch (authen) {
++ case DOT11_AUTH_OS:
++ param->value = IW_AUTH_ALG_OPEN_SYSTEM;
++ break;
++ case DOT11_AUTH_BOTH:
++ case DOT11_AUTH_SK:
++ param->value = IW_AUTH_ALG_SHARED_KEY;
++ case DOT11_AUTH_NONE:
++ default:
++ param->value = 0;
++ break;
++ }
++ }
++ break;
++
++ case IW_AUTH_WPA_ENABLED:
++ param->value = wpa > 0 ? 1 : 0;
++ break;
++
++ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
++ ret = sm_drv_oid_get(dev, DOT11_OID_DOT1XENABLE,
++ (void *)&dot1x, sizeof(uint32_t));
++ if (ret >= 0)
++ param->value = dot1x > 0 ? 1 : 0;
++ break;
++
++ case IW_AUTH_PRIVACY_INVOKED:
++ ret = sm_drv_oid_get(dev, DOT11_OID_PRIVACYINVOKED,
++ (void *)&privinvoked, sizeof(uint32_t));
++ if (ret >= 0)
++ param->value = privinvoked > 0 ? 1 : 0;
++ break;
++
++ default:
++ return -EOPNOTSUPP;
++ }
++ return ret;
++}
++
++#define KEY_SIZE_WEP104 13 /* 104/128-bit WEP keys */
++#define KEY_SIZE_WEP40 5 /* 40/64-bit WEP keys */
++#define KEY_SIZE_TKIP 32 /* TKIP keys */
++
++static int sm_drv_set_encodeext(struct net_device *dev,
++ struct iw_request_info *info,
++ union iwreq_data *wrqu,
++ char *extra)
++{
++ struct iw_point *encoding = &wrqu->encoding;
++ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
++ int idx, alg = ext->alg, set_key = 1;
++ int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0;
++ int ret = 0;
++
++ DEBUG(DBG_IOCTL, "SET ENCODEEXT\n");
++
++ /* Determine and validate the key index */
++ idx = (encoding->flags & IW_ENCODE_INDEX) - 1;
++ if (idx) {
++ if (idx < 0 || idx > 3)
++ return -EINVAL;
++ } else {
++ ret = sm_drv_oid_get(dev, DOT11_OID_DEFKEYID,
++ (void *)&idx, sizeof(uint32_t));
++ if (ret < 0)
++ goto out;
++ }
++
++ if (encoding->flags & IW_ENCODE_DISABLED)
++ alg = IW_ENCODE_ALG_NONE;
++
++ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
++ /* Only set transmit key index here, actual
++ * key is set below if needed.
++ */
++ ret = sm_drv_oid_set(dev, DOT11_OID_DEFKEYID,
++ (void *)&idx, sizeof(uint32_t));
++ set_key = ext->key_len > 0 ? 1 : 0;
++ }
++
++ if (set_key) {
++ switch (alg) {
++ case IW_ENCODE_ALG_NONE:
++ break;
++ case IW_ENCODE_ALG_WEP: {
++ struct obj_key key = { DOT11_PRIV_WEP, 0, "" };
++ memset(key.key, 0, sizeof(key.key));
++ if (ext->key_len > KEY_SIZE_WEP104) {
++ ret = -EINVAL;
++ goto out;
++ }
++ if (ext->key_len > KEY_SIZE_WEP40)
++ key.length = KEY_SIZE_WEP104;
++ else
++ key.length = KEY_SIZE_WEP40;
++ memcpy(key.key, ext->key, ext->key_len);
++ ret = sm_drv_oid_set(dev, DOT11_OID_DEFKEYID + idx + 1,
++ (void *)&key,
++ sizeof(struct obj_key));
++ break;
++ }
++ case IW_ENCODE_ALG_TKIP:
++ case IW_ENCODE_ALG_CCMP: {
++ struct obj_stakey key;
++ memset(key.key, 0, sizeof(key.key));
++ if (alg == IW_ENCODE_ALG_TKIP)
++ key.type = DOT11_PRIV_TKIP;
++ else
++ key.type = DOT11_PRIV_AES_CCMP;
++ memcpy(key.address, ext->addr.sa_data, ETH_ALEN);
++ key.length = ext->key_len;
++ key.keyid = idx;
++ key.ext = 0;
++ memcpy(key.key, ext->key, ext->key_len);
++ ret = sm_drv_oid_set(dev, DOT11_OID_STAKEY,
++ (void *)&key,
++ sizeof(struct obj_stakey));
++ break;
++ }
++ default:
++ return -EINVAL;
++ }
++
++ if (ret < 0)
++ goto out;
++
++ }
++
++ /* Read the flags */
++ if (encoding->flags & IW_ENCODE_DISABLED) {
++ /* Encoding disabled,
++ * authen = DOT11_AUTH_OS;
++ * invoke = 0;
++ * exunencrypt = 0; */
++ }
++ if (encoding->flags & IW_ENCODE_OPEN) {
++ /* Encode but accept non-encoded packets. No auth */
++ invoke = 1;
++ }
++ if (encoding->flags & IW_ENCODE_RESTRICTED) {
++ /* Refuse non-encoded packets. Auth */
++ authen = DOT11_AUTH_BOTH;
++ invoke = 1;
++ exunencrypt = 1;
++ }
++
++ /* do the change if requested */
++ if (encoding->flags & IW_ENCODE_MODE) {
++ sm_drv_oid_set(dev, DOT11_OID_AUTHENABLE,
++ (void *)&authen, sizeof(uint32_t));
++ sm_drv_oid_set(dev, DOT11_OID_PRIVACYINVOKED,
++ (void *)&invoke, sizeof(uint32_t));
++ sm_drv_oid_set(dev, DOT11_OID_EXUNENCRYPTED,
++ (void *)&exunencrypt, sizeof(uint32_t));
++ }
++
++ out:
++ return ret;
++}
++
++
++static int sm_drv_get_encodeext(struct net_device *dev,
++ struct iw_request_info *info,
++ union iwreq_data *wrqu,
++ char *extra)
++{
++ struct net_local *priv = netdev_priv(dev);
++ struct iw_point *encoding = &wrqu->encoding;
++ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
++ int idx, max_key_len;
++ int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0, wpa = 0;
++ int ret = 0;
++
++ DEBUG(DBG_IOCTL, "GET ENCODEEXT\n");
++
++ /* first get the flags */
++ ret = sm_drv_oid_get(dev, DOT11_OID_AUTHENABLE,
++ (void *)&authen, sizeof(uint32_t));
++ ret |= sm_drv_oid_get(dev, DOT11_OID_PRIVACYINVOKED,
++ (void *)&invoke, sizeof(uint32_t));
++ ret |= sm_drv_oid_get(dev, DOT11_OID_EXUNENCRYPTED,
++ (void *)&exunencrypt, sizeof(uint32_t));
++ if (ret < 0)
++ goto out;
++
++ max_key_len = encoding->length - sizeof(*ext);
++ if (max_key_len < 0)
++ return -EINVAL;
++
++ idx = (encoding->flags & IW_ENCODE_INDEX) - 1;
++ if (idx) {
++ if (idx < 0 || idx > 3)
++ return -EINVAL;
++ } else {
++ ret = sm_drv_oid_get(dev, DOT11_OID_DEFKEYID,
++ (void *)&idx, sizeof(uint32_t));
++ if (ret < 0)
++ goto out;
++ }
++
++ encoding->flags = idx + 1;
++ memset(ext, 0, sizeof(*ext));
++
++ switch (authen) {
++ case DOT11_AUTH_BOTH:
++ case DOT11_AUTH_SK:
++ wrqu->encoding.flags |= IW_ENCODE_RESTRICTED;
++ case DOT11_AUTH_OS:
++ default:
++ wrqu->encoding.flags |= IW_ENCODE_OPEN;
++ break;
++ }
++
++ down(&priv->wpa_sem);
++ wpa = priv->wpa;
++ up(&priv->wpa_sem);
++
++ if (authen == DOT11_AUTH_OS && !exunencrypt && !invoke && !wpa) {
++ /* No encryption */
++ ext->alg = IW_ENCODE_ALG_NONE;
++ ext->key_len = 0;
++ wrqu->encoding.flags |= IW_ENCODE_DISABLED;
++ } else {
++ struct obj_key *key;
++
++ ret = sm_drv_oid_get(dev, DOT11_OID_DEFKEYID + idx + 1,
++ (void *)&key, sizeof(struct obj_key));
++ if (ret < 0)
++ goto out;
++ if (max_key_len < key->length) {
++ ret = -E2BIG;
++ goto out;
++ }
++ memcpy(ext->key, key->key, key->length);
++ ext->key_len = key->length;
++
++ switch (key->type) {
++ case DOT11_PRIV_TKIP:
++ ext->alg = IW_ENCODE_ALG_TKIP;
++ break;
++ case DOT11_PRIV_AES_CCMP:
++ ext->alg = IW_ENCODE_ALG_CCMP;
++ break;
++ default:
++ case DOT11_PRIV_WEP:
++ ext->alg = IW_ENCODE_ALG_WEP;
++ break;
++ }
++ wrqu->encoding.flags |= IW_ENCODE_ENABLED;
++ }
++
++ out:
++ return ret;
++}
+
+ /* Private handlers */
+
+@@ -2473,10 +2902,10 @@ const iw_handler sm_drv_we_handler[] = {
+ (iw_handler) NULL, /* -- hole -- */
+ (iw_handler) sm_drv_set_genie, /* SIOCSIWGENIE*/
+ (iw_handler) NULL, /* SIOCGIWGENIE */
+- (iw_handler) NULL, /* SIOCSIWAUTH */
+- (iw_handler) NULL, /* SIOCGIWAUTH */
+- (iw_handler) NULL, /* SIOCSIWENCODEEXT */
+- (iw_handler) NULL, /* SIOCGIWENCODEEXT */
++ (iw_handler) sm_drv_set_auth, /* SIOCSIWAUTH */
++ (iw_handler) sm_drv_get_auth, /* SIOCGIWAUTH */
++ (iw_handler) sm_drv_set_encodeext, /* SIOCSIWENCODEEXT */
++ (iw_handler) sm_drv_get_encodeext, /* SIOCGIWENCODEEXT */
+ (iw_handler) sm_drv_set_pmk, /* SIOCSIWPMKSA */
+ };
+
--- /dev/null
+diff -rup osso-wlan-1.3.10/common.h osso-wlan-1.3.10+wpa/common.h
+--- osso-wlan-1.3.10/common.h 2007-12-20 07:20:35.000000000 +0100
++++ osso-wlan-1.3.10+wpa/common.h 2009-02-23 14:03:24.000000000 +0100
+@@ -202,6 +202,7 @@ gboolean set_power_state(guint state, in
+ int get_encryption_info(void);
+ void remove_connect_timer(void);
+ int disassociate_eap(void);
++int using_supplicant(void);
+ int get_mode(void);
+ DBusHandlerResult wlancond_req_handler(DBusConnection *connection,
+ DBusMessage *message, void *user_data);
+diff -rup osso-wlan-1.3.10/dbus-handler.c osso-wlan-1.3.10+wpa/dbus-handler.c
+--- osso-wlan-1.3.10/dbus-handler.c 2007-12-04 12:20:31.000000000 +0100
++++ osso-wlan-1.3.10+wpa/dbus-handler.c 2009-02-23 14:03:32.000000000 +0100
+@@ -37,6 +37,7 @@
+ #include <dbus/dbus.h>
+ #include <eap-dbus.h>
+ #include <wlancond-dbus.h>
++#include <wlancond-supp.h>
+ #ifdef USE_MCE_MODE
+ #include <mce/dbus-names.h>
+ #endif
+@@ -73,6 +74,9 @@ static gboolean power_down_after_scan =
+ static gboolean scan_threshold_supported = FALSE;
+ static dbus_bool_t saved_inactivity = FALSE;
+
++/* Indicates if we are using wpa_supplicant for the job */
++static gboolean use_supplicant = FALSE;
++
+ /* Timer IDs */
+ static guint wlan_if_down_timer_id = 0;
+ static guint wlan_connect_timer_id = 0;
+@@ -605,14 +609,18 @@ static gboolean wlan_connect_timer_cb(vo
+ {
+ wlan_connect_timer_id = 0;
+
+- if (get_wlan_state() == WLAN_INITIALIZED && !get_mic_status()) {
+- DLOG_DEBUG("Association timeout");
+- set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL,
+- FORCE_YES);
+- return FALSE;
++ if (get_wlan_state() == WLAN_INITIALIZED) {
++ if (use_supplicant) {
++ DLOG_DEBUG("wpa_supplicant should do its job now");
++ } else if (!get_mic_status()) {
++ DLOG_DEBUG("Association timeout");
++
++ set_wlan_state(WLAN_NOT_INITIALIZED, DISCONNECTED_SIGNAL,
++ FORCE_YES);
++ } else {
++ DLOG_DEBUG("Association OK");
++ }
+ }
+-
+- //DLOG_DEBUG("Association OK");
+
+ return FALSE;
+ }
+@@ -1176,6 +1184,14 @@ static DBusHandlerResult settings_and_co
+ powersave = WLANCOND_SHORT_CAM;
+ }
+
++ if (flags & WLANCOND_USE_SUPPLICANT) {
++ DLOG_DEBUG("Using wpa_supplicant");
++ use_supplicant = TRUE;
++ encryption = WLANCOND_OPEN; // Don't handle it
++ } else {
++ use_supplicant = FALSE;
++ }
++
+ if (power_level != WLANCOND_TX_POWER10 &&
+ power_level != WLANCOND_TX_POWER100) {
+ DLOG_ERR("Invalid power level");
+@@ -2153,6 +2169,9 @@ int wpa_ie_push(unsigned char* ap_mac_ad
+ DBusMessage *msg;
+ DBusPendingCall *pending;
+
++ if (use_supplicant)
++ return 0;
++
+ if (wlan_status.wpa_ie.ie_valid == IE_NOT_VALID ||
+ selected_ssid == NULL) {
+ DLOG_ERR("WPA IE / SSID (%s) not valid", selected_ssid);
+@@ -2205,6 +2224,9 @@ int wpa_mic_failure_event(dbus_bool_t ke
+ DBusMessage *reply;
+ DBusError derr;
+
++ if (use_supplicant)
++ return 0;
++
+ msg = dbus_message_new_method_call(
+ EAP_SERVICE,
+ EAP_REQ_PATH,
+@@ -2249,6 +2271,9 @@ int disassociate_eap(void) {
+ DBusMessage *reply;
+ DBusError derr;
+
++ if (use_supplicant)
++ return 0;
++
+ msg = dbus_message_new_method_call(
+ EAP_SERVICE,
+ EAP_REQ_PATH,
+@@ -2280,6 +2305,11 @@ int disassociate_eap(void) {
+ return 0;
+ }
+
++int using_supplicant(void)
++{
++ return use_supplicant;
++}
++
+ #ifdef USE_MCE_COVER
+ static DBusHandlerResult ignore_cover_request(DBusMessage *message,
+ DBusConnection *connection)
+diff -rup osso-wlan-1.3.10/dbus-signal.c osso-wlan-1.3.10+wpa/dbus-signal.c
+--- osso-wlan-1.3.10/dbus-signal.c 2008-04-09 12:53:28.000000000 +0200
++++ osso-wlan-1.3.10+wpa/dbus-signal.c 2009-02-27 19:39:32.000000000 +0100
+@@ -274,7 +274,7 @@ static void handle_wap_event(struct scan
+ if (state != WLAN_CONNECTED) {
+ set_wlan_state(WLAN_NO_ADDRESS, NO_SIGNAL, FORCE_NO);
+ }
+- } else {
++ } else if (!using_supplicant()) {
+
+ /* Set_wlan_state puts IF down */
+ set_wlan_state(WLAN_NOT_INITIALIZED,
+@@ -488,7 +488,7 @@ static int handle_wpa_ie_assoc_event_bin
+ int ie_len;
+ int sock;
+
+- if (get_wpa_mode() == FALSE)
++ if (!get_wpa_mode() || using_supplicant())
+ return 0;
+
+ // event is MAC:IE, do minimal sanity checking
+diff -rup osso-wlan-1.3.10/debian/changelog osso-wlan-1.3.10+wpa/debian/changelog
+--- osso-wlan-1.3.10/debian/changelog 2008-04-09 12:54:37.000000000 +0200
++++ osso-wlan-1.3.10+wpa/debian/changelog 2009-02-22 13:58:58.000000000 +0100
+@@ -1,3 +1,9 @@
++osso-wlan (1.3.10+wpa) unstable; urgency=low
++
++ * Added flag USE_SUPPLICANT (meaning "leave me alone")
++
++ -- Javier <javier@javispedro.com> Sun, 22 Feb 2009 13:58:22 +0100
++
+ osso-wlan (1.3.10) unstable; urgency=low
+
+ * Fix build issues for SDK. Fixes: NB#83881
+diff -rup osso-wlan-1.3.10/Makefile osso-wlan-1.3.10+wpa/Makefile
+--- osso-wlan-1.3.10/Makefile 2008-04-09 12:54:37.000000000 +0200
++++ osso-wlan-1.3.10+wpa/Makefile 2009-02-27 19:40:17.000000000 +0100
+@@ -25,7 +25,7 @@ CFLAGS += -DVERSION=\"$(VERSION)\" -D_GN
+
+ # Debug flags
+ #CFLAGS += -g -ggdb -DDEBUG -O0 -rdynamic
+-CFLAGS += -DDEBUG
++#CFLAGS += -DDEBUG -DOSSOLOG_STDERR
+ CFLAGS += -DUSE_MCE_MODE -DACTIVITY_CHECK
+
+ # Library flags
+diff -rup osso-wlan-1.3.10/wpa.c osso-wlan-1.3.10+wpa/wpa.c
+--- osso-wlan-1.3.10/wpa.c 2007-06-08 09:14:17.000000000 +0200
++++ osso-wlan-1.3.10+wpa/wpa.c 2009-02-23 13:55:36.000000000 +0100
+@@ -188,6 +188,7 @@ static gboolean mic_failure_running_cb(v
+
+ gboolean get_mic_status(void)
+ {
++ DLOG_DEBUG("get_mic_status timer=%d", mic_failure_running_timer_id);
+ return (mic_failure_running_timer_id != 0 ? TRUE:FALSE);
+ }
+
+@@ -198,6 +199,12 @@ gboolean get_mic_status(void)
+ */
+ int handle_mic_failure(gboolean key_type)
+ {
++ DLOG_WARN("MIC failure");
++
++ if (using_supplicant()) {
++ DLOG_DEBUG("Using supplicant: ignoring MIC failure");
++ return 0;
++ }
+
+ if (mic_failure_timer_id != 0) {
+
--- /dev/null
+diff -rup wpasupplicant-0.6.4.orig/debian/changelog wpasupplicant-0.6.4/debian/changelog
+--- wpasupplicant-0.6.4.orig/debian/changelog 2009-03-02 14:03:10.000000000 +0100
++++ wpasupplicant-0.6.4/debian/changelog 2009-02-20 12:31:12.000000000 +0100
+@@ -1,3 +1,9 @@
++wpasupplicant (0.6.4-3+n810) unstable; urgency=low
++
++ * Some hacks for cx3110x support.
++
++ -- Reinhard Tartler <siretart@tauware.de> Fri, 20 Feb 2009 12:30:44 +0100
++
+ wpasupplicant (0.6.4-3) unstable; urgency=low
+
+ * Bugfix: "Missing -d in testing for a directory in init script".
+diff -rup wpasupplicant-0.6.4.orig/debian/compat wpasupplicant-0.6.4/debian/compat
+--- wpasupplicant-0.6.4.orig/debian/compat 2009-03-02 14:03:10.000000000 +0100
++++ wpasupplicant-0.6.4/debian/compat 2009-02-16 20:50:34.000000000 +0100
+@@ -1 +1 @@
+-6
++5
+diff -rup wpasupplicant-0.6.4.orig/debian/config/linux wpasupplicant-0.6.4/debian/config/linux
+--- wpasupplicant-0.6.4.orig/debian/config/linux 2009-03-02 14:03:10.000000000 +0100
++++ wpasupplicant-0.6.4/debian/config/linux 2009-02-22 14:11:17.000000000 +0100
+@@ -27,7 +27,7 @@
+ #CONFIG_DRIVER_NDISWRAPPER=y
+
+ # Driver interface for Atmel driver
+-CONFIG_DRIVER_ATMEL=y
++#CONFIG_DRIVER_ATMEL=y
+
+ # Driver interface for Broadcom driver
+ # XXX: Non-GPL header required
+@@ -108,7 +108,7 @@ CONFIG_EAP_GTC=y
+ CONFIG_EAP_OTP=y
+
+ # EAP-SIM (enable CONFIG_PCSC, if EAP-SIM is used)
+-CONFIG_EAP_SIM=y
++#CONFIG_EAP_SIM=y
+
+ # EAP-PSK (experimental; this is _not_ needed for WPA-PSK)
+ CONFIG_EAP_PSK=y
+@@ -120,7 +120,7 @@ CONFIG_EAP_PAX=y
+ CONFIG_EAP_LEAP=y
+
+ # EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
+-CONFIG_EAP_AKA=y
++#CONFIG_EAP_AKA=y
+
+ # EAP-SAKE
+ #CONFIG_EAP_SAKE=y
+@@ -145,11 +145,11 @@ CONFIG_PKCS12=y
+
+ # Smartcard support (i.e., private key on a smartcard), e.g., with openssl
+ # engine.
+-CONFIG_SMARTCARD=y
++#CONFIG_SMARTCARD=y
+
+ # PC/SC interface for smartcards (USIM, GSM SIM)
+ # Enable this if EAP-SIM or EAP-AKA is included
+-CONFIG_PCSC=y
++#CONFIG_PCSC=y
+
+ # Development testing
+ #CONFIG_EAPOL_TEST=y
+@@ -251,7 +251,7 @@ CONFIG_PEERKEY=y
+ # This version is an experimental implementation based on IEEE 802.11w/D1.0
+ # draft and is subject to change since the standard has not yet been finalized.
+ # Driver support is also needed for IEEE 802.11w.
+-CONFIG_IEEE80211W=y
++#CONFIG_IEEE80211W=y
+
+ # Select TLS implementation
+ # openssl = OpenSSL (default)
+diff -rup wpasupplicant-0.6.4.orig/debian/control wpasupplicant-0.6.4/debian/control
+--- wpasupplicant-0.6.4.orig/debian/control 2009-03-02 14:03:10.000000000 +0100
++++ wpasupplicant-0.6.4/debian/control 2009-02-16 20:58:44.000000000 +0100
+@@ -1,21 +1,14 @@
+ Source: wpasupplicant
+ Section: net
+ Priority: optional
+-Maintainer: Debian/Ubuntu wpasupplicant Maintainers <pkg-wpa-devel@lists.alioth.debian.org>
+-Uploaders: Kyle McMartin <kyle@debian.org>, Reinhard Tartler <siretart@tauware.de>, Kel Modderman <kel@otaku42.de>
+-Build-Depends: debhelper (>= 6),
++Maintainer: javispedro
++Build-Depends: debhelper,
+ quilt,
+ libdbus-glib-1-dev,
+ libssl-dev,
+- libpcsclite-dev,
+- libreadline5-dev,
+- libqt4-dev,
++ libreadline4-dev,
+ libdbus-1-dev,
+- docbook,
+- docbook-utils,
+ pkg-config,
+- libpcap-dev [kfreebsd-i386 kfreebsd-amd64],
+- libbsd [kfreebsd-i386 kfreebsd-amd64]
+ Standards-Version: 3.8.0
+ Vcs-Svn: svn://svn.debian.org/pkg-wpa/wpasupplicant/trunk
+ Vcs-Browser: http://svn.debian.org/wsvn/pkg-wpa/wpasupplicant/trunk/
+@@ -23,19 +16,11 @@ Homepage: http://w1.fi/wpa_supplicant/
+
+ Package: wpasupplicant
+ Architecture: any
+-Depends: ${shlibs:Depends}, lsb-base (>= 3.0-6), adduser
++Depends: ${shlibs:Depends}, lsb-base (>= 3.0-6)
+ Suggests: wpagui, libengine-pkcs11-openssl
+ Description: Client support for WPA and WPA2 (IEEE 802.11i)
+ WPA and WPA2 are methods for securing wireless networks, the former
+ using IEEE 802.1X, and the latter using IEEE 802.11i. This software
+ provides key negotiation with the WPA Authenticator, and controls
+ association with IEEE 802.11i networks.
+-
+-Package: wpagui
+-Architecture: any
+-Depends: ${shlibs:Depends}, wpasupplicant (= ${binary:Version})
+-Description: GUI for wpa_supplicant
+- wpagui provides a Qt interface for choosing which configured network
+- to connect to. It also provides a method for browsing 802.11 SSID scan
+- results, an event history log of messages generated by wpa_supplicant,
+- and a method to add or edit wpa_supplicant networks.
++
+diff -rup wpasupplicant-0.6.4.orig/debian/patches/series wpasupplicant-0.6.4/debian/patches/series
+--- wpasupplicant-0.6.4.orig/debian/patches/series 2009-03-02 14:03:10.000000000 +0100
++++ wpasupplicant-0.6.4/debian/patches/series 2009-02-16 20:59:36.000000000 +0100
+@@ -1,6 +1,3 @@
+-01_use_pkg-config_for_pcsc-lite_module.patch
+ 02_dbus_group_policy.patch
+-03_dbus_service_activation_logfile.patch
+ 04_append_mmd_to_default_cflags.patch
+-05_qmake_version_makefile.patch
+ 06_fix_segfault_32bit_compat_ioctls.patch
+diff -rup wpasupplicant-0.6.4.orig/debian/rules wpasupplicant-0.6.4/debian/rules
+--- wpasupplicant-0.6.4.orig/debian/rules 2009-03-02 14:03:10.000000000 +0100
++++ wpasupplicant-0.6.4/debian/rules 2009-02-17 01:59:20.000000000 +0100
+@@ -1,12 +1,10 @@
+ #!/usr/bin/make -f
+
+ # Uncomment this to turn on verbose mode.
+-#export DH_VERBOSE=1
++export DH_VERBOSE=1
+
+ include /usr/share/quilt/quilt.make
+
+-WPAGUI = wpa_gui-qt4
+-
+ CFLAGS = -Wall -g
+ LDFLAGS = -Wl,--as-needed
+
+@@ -18,12 +16,7 @@ endif
+
+ DEB_HOST_ARCH_OS := $(shell dpkg-architecture -qDEB_HOST_ARCH_OS)
+
+-ifeq ($(DEB_HOST_ARCH_OS),kfreebsd)
+- CONFIG := debian/config/kfreebsd
+-else
+- CONFIG := debian/config/linux
+-endif
+-
++CONFIG := debian/config/linux
+
+ build: build-stamp
+ build-stamp: $(QUILT_STAMPFN)
+@@ -33,12 +26,6 @@ build-stamp: $(QUILT_STAMPFN)
+ cp -v $(CONFIG) wpa_supplicant/.config
+ CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" $(MAKE) -C wpa_supplicant all
+
+- # wpa_gui
+- $(MAKE) -C wpa_supplicant $(WPAGUI)
+-
+- # manpages
+- $(MAKE) -C wpa_supplicant/doc/docbook man
+-
+ touch $@
+
+ clean: unpatch
+@@ -46,12 +33,6 @@ clean: unpatch
+
+ $(MAKE) -C wpa_supplicant clean
+
+- if [ -f wpa_supplicant/$(WPAGUI)/Makefile ]; then \
+- $(MAKE) -C wpa_supplicant/$(WPAGUI) distclean ; \
+- fi
+-
+- $(MAKE) -C wpa_supplicant/doc/docbook clean
+-
+ dh_clean wpa_supplicant/.config build-stamp install-stamp
+
+ install: build
+@@ -61,15 +42,6 @@ install: build
+ dh_installdirs
+ dh_install
+
+- # wpa_gui
+- dh_install --package=wpagui wpa_supplicant/$(WPAGUI)/wpa_gui usr/sbin/
+-
+- # ifupdown
+- install --mode=755 -D debian/ifupdown/ifupdown.sh \
+- debian/wpasupplicant/etc/wpa_supplicant/ifupdown.sh
+- install --mode=755 -D debian/ifupdown/functions.sh \
+- debian/wpasupplicant/etc/wpa_supplicant/functions.sh
+-
+ # wpa_action
+ install --mode=755 -D debian/ifupdown/wpa_action.sh \
+ debian/wpasupplicant/sbin/wpa_action
+@@ -84,6 +56,12 @@ install: build
+ mkdir -p debian/wpasupplicant/usr/share/doc/wpasupplicant
+ sed 's/^\([^#]\+=.*\|}\)/#\1/' < wpa_supplicant/wpa_supplicant.conf \
+ > debian/wpasupplicant/usr/share/doc/wpasupplicant/README.wpa_supplicant.conf
++
++ # Clean output a little
++ rm -rf debian/wpasupplicant/etc/network/if*
++ rm -rf debian/wpasupplicant/usr/share/doc
++ rm -rf debian/wpasupplicant/etc/init.d
++
+
+ # Build architecture-independent files here.
+ binary-indep: install
+@@ -92,13 +70,6 @@ binary-indep: install
+ binary-arch: install
+ dh_testdir
+ dh_testroot
+- dh_installchangelogs wpa_supplicant/ChangeLog
+- dh_installdocs
+- dh_installexamples
+- dh_installlogrotate --package=wpasupplicant --name=wpa_action
+- dh_installlogrotate --package=wpasupplicant --name=wpa_supplicant
+- dh_installinit --package=wpasupplicant --name=wpa-ifupdown --no-start -- start 15 0 6 .
+- dh_installman
+ dh_link
+ dh_strip
+ dh_compress
+diff -rup wpasupplicant-0.6.4.orig/debian/wpasupplicant.links wpasupplicant-0.6.4/debian/wpasupplicant.links
+--- wpasupplicant-0.6.4.orig/debian/wpasupplicant.links 2009-03-02 14:03:10.000000000 +0100
++++ wpasupplicant-0.6.4/debian/wpasupplicant.links 2009-02-17 01:54:34.000000000 +0100
+@@ -1,5 +1 @@
+-etc/wpa_supplicant/ifupdown.sh etc/network/if-pre-up.d/wpasupplicant
+-etc/wpa_supplicant/ifupdown.sh etc/network/if-up.d/wpasupplicant
+-etc/wpa_supplicant/ifupdown.sh etc/network/if-down.d/wpasupplicant
+-etc/wpa_supplicant/ifupdown.sh etc/network/if-post-down.d/wpasupplicant
+-usr/share/doc/wpasupplicant/README.Debian usr/share/doc/wpasupplicant/README.modes
++
+diff -rup wpasupplicant-0.6.4.orig/debian/wpasupplicant.postinst wpasupplicant-0.6.4/debian/wpasupplicant.postinst
+--- wpasupplicant-0.6.4.orig/debian/wpasupplicant.postinst 2009-03-02 14:03:10.000000000 +0100
++++ wpasupplicant-0.6.4/debian/wpasupplicant.postinst 2009-02-16 21:09:26.000000000 +0100
+@@ -17,10 +17,7 @@
+
+ case "$1" in
+ configure)
+- # Add the netdev group unless it's already there
+- if ! getent group netdev >/dev/null; then
+- addgroup --quiet --system netdev || true
+- fi
++
+ ;;
+ abort-upgrade|abort-deconfigure|abort-remove)
+ ;;
+diff -rup wpasupplicant-0.6.4.orig/src/drivers/driver_wext.c wpasupplicant-0.6.4/src/drivers/driver_wext.c
+--- wpasupplicant-0.6.4.orig/src/drivers/driver_wext.c 2008-08-10 19:33:12.000000000 +0200
++++ wpasupplicant-0.6.4/src/drivers/driver_wext.c 2009-03-02 14:04:11.000000000 +0100
+@@ -628,6 +628,22 @@ static void wpa_driver_wext_event_wirele
+ os_memcpy(&iwe_buf, pos, sizeof(struct iw_event));
+ custom += IW_EV_POINT_OFF;
+ }
++
++ if (iwe->cmd == IWEVASSOCREQIE ||
++ iwe->cmd == IWEVASSOCRESPIE) {
++ // Find and ignore bssid: put by the driver
++ while (iwe->u.data.length > 0 && *custom != ':')
++ {
++ custom++;
++ iwe->u.data.length--;
++ }
++
++ if (iwe->u.data.length > 0)
++ {
++ custom++;
++ iwe->u.data.length--;
++ }
++ }
+
+ switch (iwe->cmd) {
+ case SIOCGIWAP:
+@@ -1221,7 +1237,6 @@ int wpa_driver_wext_scan(void *priv, con
+ struct wpa_driver_wext_data *drv = priv;
+ struct iwreq iwr;
+ int ret = 0, timeout;
+- struct iw_scan_req req;
+
+ if (ssid_len > IW_ESSID_MAX_SIZE) {
+ wpa_printf(MSG_DEBUG, "%s: too long SSID (%lu)",
+@@ -1233,14 +1248,13 @@ int wpa_driver_wext_scan(void *priv, con
+ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+
+ if (ssid && ssid_len) {
+- os_memset(&req, 0, sizeof(req));
+- req.essid_len = ssid_len;
+- req.bssid.sa_family = ARPHRD_ETHER;
+- os_memset(req.bssid.sa_data, 0xff, ETH_ALEN);
+- os_memcpy(req.essid, ssid, ssid_len);
+- iwr.u.data.pointer = (caddr_t) &req;
+- iwr.u.data.length = sizeof(req);
+- iwr.u.data.flags = IW_SCAN_THIS_ESSID;
++ wpa_printf(MSG_DEBUG, "Scan requested (ret=%d) - scan timeout %d "
++ "seconds", ret, timeout);
++ iwr.u.essid.pointer = (caddr_t) ssid;
++ iwr.u.essid.length = ssid_len;
++ iwr.u.essid.flags = IW_SCAN_THIS_ESSID;
++ } else {
++ iwr.u.essid.flags = IW_SCAN_ALL_ESSID;
+ }
+
+ if (ioctl(drv->ioctl_sock, SIOCSIWSCAN, &iwr) < 0) {
+diff -rup wpasupplicant-0.6.4.orig/wpa_supplicant/scan.c wpasupplicant-0.6.4/wpa_supplicant/scan.c
+--- wpasupplicant-0.6.4.orig/wpa_supplicant/scan.c 2008-08-10 19:33:12.000000000 +0200
++++ wpasupplicant-0.6.4/wpa_supplicant/scan.c 2009-02-20 13:25:51.000000000 +0100
+@@ -140,6 +140,7 @@ static void wpa_supplicant_scan(void *el
+ wpa_printf(MSG_DEBUG, "Trying to get current scan results "
+ "first without requesting a new scan to speed up "
+ "initial association");
++ wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
+ wpa_supplicant_event(wpa_s, EVENT_SCAN_RESULTS, NULL);
+ return;
+ }
--- /dev/null
+/**
+ @file supp.c
+
+ Copyright (C) 2009 Javier S. Pedro
+
+ @author Javier S. Pedro <javispedro@javispedro.com>
+
+ This file is part of libicd-network-wpa.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include <signal.h>
+#include <string.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+#include <gconf/gconf-client.h>
+
+#include <osso-ic-dbus.h>
+#include <osso-ic-gconf.h>
+
+#include "log.h"
+#include "common.h"
+#include "icd.h"
+#include "dbus.h"
+#include "dbus-helper.h"
+#include "supp.h"
+
+/* Errors */
+#define WPAS_ERROR_INVALID_NETWORK \
+ WPAS_DBUS_IFACE_INTERFACE ".InvalidNetwork"
+#define WPAS_ERROR_INVALID_BSSID \
+ WPAS_DBUS_IFACE_INTERFACE ".InvalidBSSID"
+
+#define WPAS_ERROR_INVALID_OPTS \
+ WPAS_DBUS_INTERFACE ".InvalidOptions"
+#define WPAS_ERROR_INVALID_IFACE \
+ WPAS_DBUS_INTERFACE ".InvalidInterface"
+
+#define WPAS_ERROR_ADD_ERROR \
+ WPAS_DBUS_INTERFACE ".AddError"
+#define WPAS_ERROR_EXISTS_ERROR \
+ WPAS_DBUS_INTERFACE ".ExistsError"
+#define WPAS_ERROR_REMOVE_ERROR \
+ WPAS_DBUS_INTERFACE ".RemoveError"
+
+#define WPAS_ERROR_SCAN_ERROR \
+ WPAS_DBUS_IFACE_INTERFACE ".ScanError"
+#define WPAS_ERROR_ADD_NETWORK_ERROR \
+ WPAS_DBUS_IFACE_INTERFACE ".AddNetworkError"
+#define WPAS_ERROR_INTERNAL_ERROR \
+ WPAS_DBUS_IFACE_INTERFACE ".InternalError"
+#define WPAS_ERROR_REMOVE_NETWORK_ERROR \
+ WPAS_DBUS_IFACE_INTERFACE ".RemoveNetworkError"
+
+#define WPAS_DBUS_BSSID_FORMAT "%02x%02x%02x%02x%02x%02x"
+
+static pid_t supp_pid = 0;
+static int supp_activation_tries = 0;
+
+static gchar* supp_iface = NULL;
+static gchar* supp_iface_path = NULL;
+
+static gchar* supp_network_id = NULL;
+static gchar* supp_config_path = NULL;
+
+static gboolean supp_configured = FALSE; // Unused right now
+
+/* Callback for supplicant events */
+static supp_cb_fn supp_cb = NULL;
+static gpointer supp_cb_data = NULL;
+
+static void supp_configure();
+
+void supp_set_callback(supp_cb_fn cb, gpointer user_data)
+{
+ supp_cb = cb;
+ supp_cb_data = user_data;
+}
+
+static inline void supp_callback(int result, const char * message)
+{
+ if (supp_cb) supp_cb(result, message, supp_cb_data);
+}
+
+static gboolean supp_set_interface_retry(gpointer data)
+{
+ DLOG_DEBUG(__func__);
+
+ if (supp_pid && supp_iface) supp_set_interface(supp_iface);
+ return FALSE;
+}
+
+static void add_iface_reply_cb(DBusPendingCall *pending, void *user_data)
+{
+ DBusMessage *reply;
+ DBusError error;
+
+ DLOG_DEBUG("%s", __func__);
+
+ dbus_error_init(&error);
+
+ reply = dbus_pending_call_steal_reply(pending);
+
+ if (dbus_set_error_from_message(&error, reply)) {
+ DLOG_WARN_L("Error in %s:%s", __func__, error.name);
+
+ if (strcmp(DBUS_ERROR_SERVICE_UNKNOWN, error.name) == 0)
+ {
+ // Supplicant not (yet) active? Try later
+ DLOG_DEBUG("Still waiting for supplicant");
+ supp_activation_tries++;
+ if (supp_activation_tries >= 3) {
+ supp_callback(-1, error.name);
+ } else {
+ g_timeout_add(1000,
+ supp_set_interface_retry,
+ NULL);
+ }
+ } else {
+ supp_callback(-1, error.name);
+ }
+
+ dbus_error_free(&error);
+ } else if (reply) {
+ // Move on to next step
+ gchar* path;
+ if (!dbus_message_get_args(
+ reply, NULL,
+ DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID))
+ {
+ supp_callback(-1, error.name);
+ goto iface_reply_error;
+ }
+
+ supp_iface_path = g_strdup(path);
+ DLOG_DEBUG("Got interface path: %s", supp_iface_path);
+ if (supp_network_id && !supp_config_path) {
+ supp_set_network_id(supp_network_id);
+ } else if (supp_config_path && !supp_configured) {
+ supp_configure();
+ }
+ }
+
+iface_reply_error:
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
+}
+
+void supp_unset_interface()
+{
+ // TODO
+ // mostly uneeded, since we're killing the supplicant instead
+ g_free(supp_iface_path);
+ supp_iface_path = NULL;
+ g_free(supp_iface);
+ supp_iface = NULL;
+}
+
+void supp_set_interface(const char * iface)
+{
+ DBusMessage *msg;
+ DBusPendingCall *pending;
+
+ DLOG_DEBUG("%s: %s", __func__, iface);
+
+ if (supp_iface_path) {
+ supp_unset_interface();
+ }
+
+ if (iface != supp_iface) {
+ if (supp_iface) {
+ g_free(supp_iface);
+ }
+
+ supp_iface = g_strdup(iface);
+ }
+
+ msg = new_dbus_method_call(
+ WPAS_DBUS_SERVICE,
+ WPAS_DBUS_PATH,
+ WPAS_DBUS_INTERFACE,
+ "addInterface");
+
+ append_dbus_args(
+ msg,
+ DBUS_TYPE_STRING, &iface,
+ DBUS_TYPE_INVALID);
+
+ if (!dbus_connection_send_with_reply(get_dbus_connection(),
+ msg, &pending, -1))
+ die("Out of memory");
+
+ if (!dbus_pending_call_set_notify(pending,
+ add_iface_reply_cb, NULL, NULL))
+ die("Out of memory");
+
+ dbus_message_unref(msg);
+}
+
+static void add_network_reply_cb(DBusPendingCall *pending, void *user_data)
+{
+ DBusMessage *reply;
+ DBusError error;
+
+ DLOG_DEBUG("%s", __func__);
+
+ dbus_error_init(&error);
+
+ reply = dbus_pending_call_steal_reply(pending);
+
+ if (dbus_set_error_from_message(&error, reply)) {
+ DLOG_WARN_L("Error in %s:%s", __func__, error.name);
+
+ supp_callback(-1, error.name);
+ dbus_error_free(&error);
+ } else if (reply) {
+ // Move on to next step
+ gchar* path;
+ if (!dbus_message_get_args(
+ reply, NULL,
+ DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID))
+ {
+ supp_callback(-1, error.name);
+ goto net_reply_error;
+ }
+
+ supp_config_path = g_strdup(path);
+ DLOG_DEBUG("Got network path: %s", supp_iface_path);
+ if (supp_iface_path && !supp_configured) {
+ supp_configure();
+ }
+ }
+
+net_reply_error:
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
+}
+
+void supp_unset_network_id()
+{
+ g_free(supp_config_path);
+ supp_config_path = NULL;
+ g_free(supp_network_id);
+ supp_network_id = NULL;
+ // TODO
+}
+
+void supp_set_network_id(const char * network_id)
+{
+ DBusMessage *msg;
+ DBusPendingCall *pending;
+
+ DLOG_DEBUG("%s: %s", __func__, network_id);
+
+ if (supp_config_path) {
+ supp_unset_network_id();
+ }
+
+ if (network_id != supp_network_id) {
+ if (supp_network_id) {
+ g_free(supp_network_id);
+ }
+
+ supp_network_id = g_strdup(network_id);
+ }
+
+ if (!supp_iface_path) {
+ DLOG_DEBUG("Deferring network creation");
+ return;
+ }
+
+ msg = new_dbus_method_call(
+ WPAS_DBUS_SERVICE,
+ supp_iface_path,
+ WPAS_DBUS_IFACE_INTERFACE,
+ "addNetwork");
+
+ if (!dbus_connection_send_with_reply(get_dbus_connection(),
+ msg, &pending, -1))
+ die("Out of memory");
+
+ if (!dbus_pending_call_set_notify(pending,
+ add_network_reply_cb, NULL, NULL))
+ die("Out of memory");
+
+ dbus_message_unref(msg);
+}
+
+static gchar * wpas_params[3] = { "/sbin/wpa_supplicant", "-u", NULL };
+
+int supp_enable()
+{
+ DLOG_DEBUG("%s", __func__);
+
+ supp_activation_tries = 0;
+
+ GError* error;
+ GPid pid;
+ if (!g_spawn_async(NULL, wpas_params, NULL,
+ G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL, NULL, &pid, &error)) {
+ DLOG_ERR("Couldn't spawn supplicant: %s", error->message);
+ return -1;
+ }
+
+ supp_pid = pid;
+
+ DLOG_INFO("Spawned %s , pid %d", wpas_params[0], pid);
+
+ icd_watch_pid(supp_pid);
+
+ return 0;
+}
+
+void supp_disable(void)
+{
+ if (supp_pid) {
+ DLOG_INFO("Killing supplicant (pid %d)", supp_pid);
+ kill(supp_pid, SIGTERM);
+ }
+
+ // Consider everything as deconfigured
+ g_free(supp_iface);
+ supp_iface = NULL;
+ g_free(supp_iface_path);
+ supp_iface_path = NULL;
+ g_free(supp_network_id);
+ supp_network_id = NULL;
+ g_free(supp_config_path);
+ supp_config_path = NULL;
+
+ supp_configured = FALSE;
+}
+
+int supp_is_active(void)
+{
+ return supp_pid ? TRUE : FALSE;
+}
+
+void supp_handle_signal(gchar* old_state, gchar* new_state)
+{
+ DLOG_DEBUG("Supplicant StateChange %s -> %s", old_state, new_state);
+
+ if (strcmp(new_state, "COMPLETED") == 0)
+ {
+ supp_callback(SUPP_STATUS_CONNECTED, new_state);
+ } else if (strcmp(new_state, "DISCONNECTED") == 0) {
+ supp_callback(SUPP_STATUS_DISCONNECTED, new_state);
+ }
+}
+
+void supp_handle_killed(void)
+{
+ DLOG_DEBUG("%s", __func__);
+
+ g_spawn_close_pid(supp_pid);
+ supp_pid = 0;
+
+ supp_disable();
+
+ supp_callback(SUPP_STATUS_KILLED, NULL);
+}
+
+static void free_settings_item(gpointer data, gpointer user_data)
+{
+ gconf_entry_free(data);
+}
+
+static void enable_reply_cb(DBusPendingCall *pending, void *user_data)
+{
+ DBusMessage *reply;
+ DBusError error;
+
+ DLOG_DEBUG("%s", __func__);
+
+ dbus_error_init(&error);
+
+ reply = dbus_pending_call_steal_reply(pending);
+
+ if (dbus_set_error_from_message(&error, reply)) {
+ DLOG_WARN_L("Error in %s:%s", __func__, error.name);
+
+ supp_callback(SUPP_STATUS_ERROR, error.name);
+ dbus_error_free(&error);
+ }
+
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
+}
+
+static void supp_enable_network()
+{
+ DBusMessage* message; //The full mesage we are going to send.
+ DBusPendingCall *pending;
+
+ message = dbus_message_new_method_call(
+ WPAS_DBUS_SERVICE,
+ supp_config_path,
+ WPAS_DBUS_IFACE_NETWORK,
+ WPAS_ENABLE_NETWORK_METHOD
+ );
+ if (!message) {
+ DLOG_CRIT_L("Out of memory");
+ supp_callback(-1, ICD_DBUS_ERROR_SYSTEM_ERROR);
+ return;
+ }
+
+ // Send message
+ if (!dbus_connection_send_with_reply(get_dbus_connection(),
+ message, &pending, -1)) {
+ DLOG_CRIT_L("Out of memory");
+ supp_callback(-1, ICD_DBUS_ERROR_SYSTEM_ERROR);
+ goto send_error;
+ }
+
+ if (!dbus_pending_call_set_notify(pending,
+ enable_reply_cb, NULL, NULL)) {
+ DLOG_CRIT_L("Out of memory");
+ supp_callback(-1, ICD_DBUS_ERROR_SYSTEM_ERROR);
+ }
+
+ // Fall through
+send_error:
+ dbus_message_unref(message);
+}
+
+static void configure_reply_cb(DBusPendingCall *pending, void *user_data)
+{
+ DBusMessage *reply;
+ DBusError error;
+
+ DLOG_DEBUG("%s", __func__);
+
+ dbus_error_init(&error);
+
+ reply = dbus_pending_call_steal_reply(pending);
+
+ if (dbus_set_error_from_message(&error, reply)) {
+ DLOG_WARN_L("Error in %s:%s", __func__, error.name);
+
+ supp_callback(-1, error.name);
+ dbus_error_free(&error);
+ } else if (reply) {
+ supp_enable_network();
+ }
+
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
+}
+
+static void supp_configure()
+{
+ // This is going to be long
+ DLOG_DEBUG("%s: %s", __func__, supp_network_id);
+ GConfClient *client = gconf_client_get_default();
+ GError *error = NULL;
+
+ DBusMessage* message; //The full mesage we are going to send.
+ DBusMessageIter iter, iter_dict;
+ DBusPendingCall *pending;
+
+ if (!client) {
+ DLOG_ERR("Cannot get gconf client");
+ supp_callback(-1, ICD_DBUS_ERROR_SYSTEM_ERROR);
+ return;
+ }
+
+ gchar * settings_path = g_strconcat(ICD_GCONF_PATH,
+ "/", supp_network_id, NULL);
+
+ GSList * settings = gconf_client_all_entries(client,
+ settings_path, &error);
+ if (error) {
+ DLOG_ERR("Could not get setting:%s, error:%s", settings_path,
+ error->message);
+ g_free(settings_path);
+ g_clear_error(&error);
+ g_object_unref(client);
+ supp_callback(-1, error->message);
+ return;
+ }
+
+ message = dbus_message_new_method_call(
+ WPAS_DBUS_SERVICE,
+ supp_config_path,
+ WPAS_DBUS_IFACE_NETWORK,
+ WPAS_SET_NETWORK_METHOD
+ );
+ if (!message) {
+ DLOG_CRIT_L("Out of memory");
+ supp_callback(-1, ICD_DBUS_ERROR_SYSTEM_ERROR);
+ goto msg_init_error;
+ }
+
+ dbus_message_iter_init_append(message, &iter);
+ if (dbus_dict_open_write(&iter, &iter_dict) != 0) {
+ DLOG_CRIT_L("Out of memory");
+ supp_callback(-1, ICD_DBUS_ERROR_SYSTEM_ERROR);
+ goto dict_init_error;
+ }
+
+ DLOG_DEBUG("Preparing to send %d settings", g_slist_length(settings));
+
+ GSList* i;
+ for (i = settings; i; i = g_slist_next(i)) {
+ GConfEntry* entry = i->data;
+ gchar * key = g_path_get_basename(gconf_entry_get_key(entry));
+ GConfValue* value = gconf_entry_get_value(entry);
+
+ if (g_ascii_strncasecmp(key,
+ WPA_GCONF_SETTING_PREFIX,
+ WPA_GCONF_SETTING_PREFIX_LEN)) {
+ g_free(key);
+ continue;
+ }
+
+ // Skip prefix
+ key += WPA_GCONF_SETTING_PREFIX_LEN;
+
+ switch (value->type) {
+ case GCONF_VALUE_STRING:
+ DLOG_DEBUG("Setting string %s = %s",
+ key, gconf_value_get_string(value));
+ dbus_dict_append_string(&iter_dict,
+ key, gconf_value_get_string(value));
+ break;
+
+ case GCONF_VALUE_INT:
+ DLOG_DEBUG("Setting int32 %s = %d",
+ key, gconf_value_get_int(value));
+ dbus_dict_append_int32(&iter_dict,
+ key, gconf_value_get_int(value));
+ break;
+ default:
+ DLOG_DEBUG("Unknown setting type for %s",
+ key);
+ break;
+ }
+
+ key -= WPA_GCONF_SETTING_PREFIX_LEN;
+ g_free(key);
+ }
+
+ if (dbus_dict_close_write(&iter, &iter_dict) != 0) {
+ supp_callback(-1, ICD_DBUS_ERROR_SYSTEM_ERROR);
+ goto dict_close_error;
+ }
+
+ // Send message
+ if (!dbus_connection_send_with_reply(get_dbus_connection(),
+ message, &pending, -1)) {
+ DLOG_CRIT_L("Out of memory");
+ supp_callback(-1, ICD_DBUS_ERROR_SYSTEM_ERROR);
+ goto send_error;
+ }
+
+ if (!dbus_pending_call_set_notify(pending,
+ configure_reply_cb, NULL, NULL)) {
+ DLOG_CRIT_L("Out of memory");
+ supp_callback(-1, ICD_DBUS_ERROR_SYSTEM_ERROR);
+ goto send_error;
+ }
+
+ // Fall through
+send_error:
+dict_close_error:
+dict_init_error:
+ dbus_message_unref(message);
+msg_init_error:
+ g_free(settings_path);
+
+ g_slist_foreach(settings, free_settings_item, NULL);
+ g_slist_free(settings);
+
+ g_object_unref(client);
+}
+
--- /dev/null
+#ifndef _SUPP_H_
+#define _SUPP_H_
+
+int supp_enable();
+void supp_disable();
+
+#define WPAS_DBUS_OBJECT_PATH_MAX 150
+
+#define WPAS_DBUS_SERVICE "fi.epitest.hostap.WPASupplicant"
+#define WPAS_DBUS_PATH "/fi/epitest/hostap/WPASupplicant"
+#define WPAS_DBUS_INTERFACE "fi.epitest.hostap.WPASupplicant"
+
+#define WPAS_STATE_CHANGE_SIG "StateChange"
+
+#define WPAS_DBUS_PATH_INTERFACES WPAS_DBUS_PATH "/Interfaces"
+#define WPAS_DBUS_IFACE_INTERFACE WPAS_DBUS_INTERFACE ".Interface"
+
+#define WPAS_DBUS_NETWORKS_PART "Networks"
+#define WPAS_DBUS_IFACE_NETWORK WPAS_DBUS_INTERFACE ".Network"
+
+#define WPAS_DBUS_BSSIDS_PART "BSSIDs"
+#define WPAS_DBUS_IFACE_BSSID WPAS_DBUS_INTERFACE ".BSSID"
+
+#define WPAS_SET_NETWORK_METHOD "set"
+#define WPAS_ENABLE_NETWORK_METHOD "enable"
+
+enum supp_status {
+ SUPP_STATUS_KILLED = -2,
+ SUPP_STATUS_ERROR = -1,
+ SUPP_STATUS_DISCONNECTED = 0,
+ SUPP_STATUS_CONNECTED
+};
+
+typedef void (*supp_cb_fn)(enum supp_status status, const char * data,
+ gpointer user_data);
+
+void supp_set_callback(supp_cb_fn cb, gpointer user_data);
+void supp_set_interface(const char * iface);
+void supp_set_network_id(const char * network_id);
+
+void supp_unset_interface(void);
+void supp_unset_network_id(void);
+
+int supp_is_active(void);
+
+void supp_handle_signal(gchar* old_state, gchar* new_state);
+void supp_handle_killed(void);
+
+#endif
--- /dev/null
+/**
+ @file wlan.c
+
+ Copyright (C) 2004 Nokia Corporation. All rights reserved.
+
+ Copyright (C) 2009 Javier S. Pedro
+
+ @author Janne Ylalehto <janne.ylalehto@nokia.com>
+ @author Johan Hedberg <johan.hedberg@nokia.com>
+
+ @author Javier S. Pedro <javispedro@javispedro.com>
+
+ This file is part of libicd-network-wpa.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include <string.h>
+
+#include <glib.h>
+#include <dbus/dbus.h>
+
+#include <wlancond.h>
+#include <wlancond-dbus.h>
+#include <wlancond-supp.h>
+
+#include "common.h"
+#include "dbus.h"
+#include "dbus-helper.h"
+#include "wlan.h"
+#include "log.h"
+
+/* -- SCANNING -- */
+
+static wlan_found_ap found_ap_cb = NULL;
+
+int wlan_scan(const char * ssid, wlan_found_ap new_found_ap_cb)
+{
+ DBusMessage *msg, *reply;
+ DBusError error;
+
+ DLOG_DEBUG("%s: %s (active)", __func__, ssid);
+
+ dbus_error_init(&error);
+
+ found_ap_cb = new_found_ap_cb;
+
+ msg = new_dbus_method_call(
+ WLANCOND_SERVICE,
+ WLANCOND_REQ_PATH,
+ WLANCOND_REQ_INTERFACE,
+ WLANCOND_SCAN_REQ);
+
+ gint32 power_level = WLANCOND_TX_POWER100;
+ guint32 flags = 0;
+
+ append_dbus_args(
+ msg,
+ DBUS_TYPE_INT32, &power_level,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ssid, strlen(ssid) + 1,
+ DBUS_TYPE_UINT32, &flags,
+
+ DBUS_TYPE_INVALID);
+
+ reply = dbus_connection_send_with_reply_and_block(get_dbus_connection(),
+ msg, -1, &error);
+
+ dbus_message_unref(msg);
+
+ if (reply) {
+ DLOG_DEBUG("Scan reply OK");
+ dbus_message_unref(reply);
+
+ return 0;
+ } else if (dbus_error_is_set(&error)) {
+ DLOG_INFO("Scan pending call result:%s", error.name);
+ dbus_error_free(&error);
+ found_ap_cb = NULL;
+ return -1;
+ } else {
+ DLOG_WARN("Scan without reply");
+ found_ap_cb = NULL;
+ return -1;
+ }
+}
+
+gboolean wlan_is_scanning()
+{
+ return found_ap_cb ? TRUE : FALSE;
+}
+
+void wlan_notify_ap(const char *ssid, const char *bssid,
+ int rssi, unsigned int channel, unsigned int cap_bits)
+{
+ if (found_ap_cb)
+ found_ap_cb(SEARCH_CONTINUE, ssid, bssid, rssi / 2 - 110);
+}
+
+void wlan_notify_end_of_search()
+{
+ wlan_found_ap prev_found_ap_cb = found_ap_cb;
+ found_ap_cb = NULL;
+
+ // A new search may be started right after calling this callback
+
+ if (prev_found_ap_cb)
+ prev_found_ap_cb(SEARCH_FINISHED, NULL, NULL, 0);
+}
+
+/* - CONNECTING - */
+
+static wlan_connected connected_cb;
+
+static void connect_reply_cb(DBusPendingCall *pending, void *user_data)
+{
+ DBusMessage *reply;
+ DBusError error;
+
+ DLOG_DEBUG("Connect reply callback");
+
+ dbus_error_init(&error);
+
+ reply = dbus_pending_call_steal_reply(pending);
+
+ if (dbus_set_error_from_message(&error, reply)) {
+
+ DLOG_DEBUG("Connect pending call result:%s", error.name);
+
+ connected_cb(-1, error.name);
+ dbus_error_free(&error);
+ } else if (reply) {
+ connected_cb(0, NULL);
+ }
+
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
+}
+
+void wlan_connect(const char * ssid, wlan_connected _connected_cb)
+{
+ DBusMessage *msg;
+ DBusPendingCall *pending;
+
+ DLOG_DEBUG("%s: %s", __func__, ssid);
+
+ connected_cb = _connected_cb;
+
+ msg = new_dbus_method_call(
+ WLANCOND_SERVICE,
+ WLANCOND_REQ_PATH,
+ WLANCOND_REQ_INTERFACE,
+ WLANCOND_SETTINGS_AND_CONNECT_REQ);
+
+ guint32 dummy = 0;
+ guint32 *dummyP = &dummy;
+
+ gint32 power_level, mode, encryption, default_key;
+ guint32 adhoc_channel, flags;
+
+ power_level = WLANCOND_TX_POWER100;
+ mode = WLANCOND_INFRA;
+ encryption = 0;
+ default_key = 0;
+ adhoc_channel = 0;
+ flags = WLANCOND_USE_SUPPLICANT;
+
+ append_dbus_args(
+ msg,
+ DBUS_TYPE_INT32, &power_level,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &ssid, strlen(ssid),
+ DBUS_TYPE_INT32, &mode,
+ DBUS_TYPE_INT32, &encryption,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &dummyP, 0,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &dummyP, 0,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &dummyP, 0,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &dummyP, 0,
+ DBUS_TYPE_INT32, &default_key,
+ DBUS_TYPE_UINT32, &adhoc_channel,
+ DBUS_TYPE_UINT32, &flags,
+ DBUS_TYPE_INVALID);
+
+ if (!dbus_connection_send_with_reply(get_dbus_connection(),
+ msg, &pending, -1))
+ die("Out of memory");
+
+ if (!dbus_pending_call_set_notify(pending, connect_reply_cb, NULL, NULL))
+ die("Out of memory");
+
+ dbus_message_unref(msg);
+}
+
+static void disconnect_reply_cb(DBusPendingCall *pending, void *user_data)
+{
+ DBusMessage *reply;
+ DBusError error;
+
+ DLOG_DEBUG("Disconnect reply callback");
+
+ dbus_error_init(&error);
+
+ reply = dbus_pending_call_steal_reply(pending);
+
+ if (dbus_set_error_from_message(&error, reply)) {
+
+ DLOG_DEBUG("Disconnect pending call result:%s", error.name);
+
+ dbus_error_free(&error);
+ }
+
+ // No need to notify, wpa_supplicant will signal that for us
+
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
+}
+
+void wlan_disconnect()
+{
+ DBusMessage *msg;
+ DBusPendingCall *pending;
+
+ DLOG_DEBUG("%s", __func__);
+
+ msg = new_dbus_method_call(
+ WLANCOND_SERVICE,
+ WLANCOND_REQ_PATH,
+ WLANCOND_REQ_INTERFACE,
+ WLANCOND_DISCONNECT_REQ);
+
+ if (!dbus_connection_send_with_reply(get_dbus_connection(),
+ msg, &pending, -1))
+ die("Out of memory");
+
+ if (!dbus_pending_call_set_notify(pending, disconnect_reply_cb, NULL, NULL))
+ die("Out of memory");
+
+ dbus_message_unref(msg);
+}
+
+/* -- STATUS -- */
+
+static wlan_status_reply status_cb;
+
+static void status_reply_cb(DBusPendingCall *pending, void *user_data)
+{
+ DBusMessage *reply;
+ DBusError error;
+
+ DLOG_DEBUG("%s", __func__);
+
+ dbus_error_init(&error);
+
+ reply = dbus_pending_call_steal_reply(pending);
+
+ if (dbus_set_error_from_message(&error, reply)) {
+
+ DLOG_DEBUG("%s error: %s", __func__, error.name);
+ goto dbus_error;
+ } else if (reply) {
+ char *essid, *bssid, *ifname;
+ int essid_len, bssid_len;
+ unsigned long sens, channel, capability, security;
+
+ if (!dbus_message_get_args(
+ reply, &error,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &essid, &essid_len,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &bssid, &bssid_len,
+ DBUS_TYPE_UINT32, &sens,
+ DBUS_TYPE_UINT32, &channel,
+ DBUS_TYPE_UINT32, &capability,
+ DBUS_TYPE_UINT32, &security,
+ DBUS_TYPE_STRING, &ifname,
+ DBUS_TYPE_INVALID))
+ {
+ DLOG_DEBUG("%s parse reply error: %s", __func__,
+ error.name);
+ goto dbus_error;
+ }
+
+ status_cb(0, essid, essid_len, bssid, bssid_len,
+ sens, channel, capability, security,
+ ifname);
+ }
+
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
+
+ return;
+dbus_error:
+ status_cb(-1, NULL, 0, NULL, 0,
+ 0, 0, 0, 0,
+ error.name);
+ dbus_error_free(&error);
+
+ if (reply)
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(pending);
+}
+
+void wlan_get_status(wlan_status_reply reply_cb)
+{
+ DBusMessage *msg;
+ DBusPendingCall *pending;
+
+ DLOG_DEBUG("%s", __func__);
+
+ status_cb = reply_cb;
+
+ msg = new_dbus_method_call(
+ WLANCOND_SERVICE,
+ WLANCOND_REQ_PATH,
+ WLANCOND_REQ_INTERFACE,
+ WLANCOND_STATUS_REQ);
+
+ if (!dbus_connection_send_with_reply(get_dbus_connection(),
+ msg, &pending, -1))
+ die("Out of memory");
+
+ if (!dbus_pending_call_set_notify(pending, status_reply_cb, NULL, NULL))
+ die("Out of memory");
+
+ dbus_message_unref(msg);
+}
+
--- /dev/null
+/**
+ @file wlan.h
+
+ Copyright (C) 2009 Javier S. Pedro
+
+ @author Javier S. Pedro <javispedro@javispedro.com>
+
+ This file is part of libicd-network-wpa.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#ifndef _WLAN_H_
+#define _WLAN_H_
+
+typedef void (*wlan_found_ap)(int status,
+ const char * ssid, const char * ap, int dB);
+int wlan_scan(const char * ssid, wlan_found_ap found_ap_cb);
+
+gboolean wlan_is_scanning();
+void wlan_notify_ap(const char *ssid, const char *bssid,
+ int rssi, unsigned int channel, unsigned int cap_bits);
+void wlan_notify_end_of_search();
+
+
+typedef void (*wlan_connected)(int status, const char *error);
+void wlan_connect(const char *ssid, wlan_connected connected_cb);
+
+void wlan_disconnect();
+
+typedef void (*wlan_status_reply)(int status,
+ const char * essid, int essid_len,
+ const char * bssid, int bssid_len,
+ int qual, int channel, unsigned long security, unsigned long capability,
+ const char * data);
+void wlan_get_status(wlan_status_reply reply_cb);
+
+
+#endif