initial import libicd_network_wpa_0_0_1
authorJavier S. Pedro <javier@javispedro.com>
Fri, 4 Sep 2009 21:54:03 +0000 (23:54 +0200)
committerJavier S. Pedro <javier@javispedro.com>
Fri, 4 Sep 2009 21:54:03 +0000 (23:54 +0200)
29 files changed:
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
Makefile [new file with mode: 0644]
README [new file with mode: 0644]
TODO [new file with mode: 0644]
common.h [new file with mode: 0644]
dbus-handler.c [new file with mode: 0644]
dbus-handler.h [new file with mode: 0644]
dbus-helper.c [new file with mode: 0644]
dbus-helper.h [new file with mode: 0644]
dbus.c [new file with mode: 0644]
dbus.h [new file with mode: 0644]
gconf.c [new file with mode: 0644]
gconf.h [new file with mode: 0644]
gconf/network-type.xml [new file with mode: 0644]
icd.c [new file with mode: 0644]
icd.h [new file with mode: 0644]
include/wlancond-supp.h [new file with mode: 0644]
log.h [new file with mode: 0644]
networks.c [new file with mode: 0644]
networks.h [new file with mode: 0644]
patches/cx3110-module-src-2.0.15.patch [new file with mode: 0644]
patches/osso-wlan-1.3.10.patch [new file with mode: 0644]
patches/wpasupplicant-0.6.4.patch [new file with mode: 0644]
supp.c [new file with mode: 0644]
supp.h [new file with mode: 0644]
welcome [deleted file]
wlan.c [new file with mode: 0644]
wlan.h [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..c3fddc9
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,8 @@
+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
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..d60c31a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+                   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.
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..acd2cab
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,36 @@
+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
+
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..566c4f8
--- /dev/null
+++ b/README
@@ -0,0 +1,18 @@
+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/
+
diff --git a/TODO b/TODO
new file mode 100644 (file)
index 0000000..755823c
--- /dev/null
+++ b/TODO
@@ -0,0 +1,5 @@
+- 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.
+
diff --git a/common.h b/common.h
new file mode 100644 (file)
index 0000000..3f3fca3
--- /dev/null
+++ b/common.h
@@ -0,0 +1,45 @@
+/**
+  @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
diff --git a/dbus-handler.c b/dbus-handler.c
new file mode 100644 (file)
index 0000000..02ce44e
--- /dev/null
@@ -0,0 +1,202 @@
+/**
+  @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);
+}
diff --git a/dbus-handler.h b/dbus-handler.h
new file mode 100644 (file)
index 0000000..a274b6a
--- /dev/null
@@ -0,0 +1,43 @@
+/**
+  @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_ */
diff --git a/dbus-helper.c b/dbus-helper.c
new file mode 100644 (file)
index 0000000..4d3d025
--- /dev/null
@@ -0,0 +1,308 @@
+/**
+  @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;
+}
+
diff --git a/dbus-helper.h b/dbus-helper.h
new file mode 100644 (file)
index 0000000..094ce0c
--- /dev/null
@@ -0,0 +1,65 @@
+/**
+  @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_ */
diff --git a/dbus.c b/dbus.c
new file mode 100644 (file)
index 0000000..cd14973
--- /dev/null
+++ b/dbus.c
@@ -0,0 +1,81 @@
+/**
+  @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;
+}
diff --git a/dbus.h b/dbus.h
new file mode 100644 (file)
index 0000000..ba53f24
--- /dev/null
+++ b/dbus.h
@@ -0,0 +1,42 @@
+/**
+  @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_ */
diff --git a/gconf.c b/gconf.c
new file mode 100644 (file)
index 0000000..f08e567
--- /dev/null
+++ b/gconf.c
@@ -0,0 +1,51 @@
+/**
+  @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;
+}
diff --git a/gconf.h b/gconf.h
new file mode 100644 (file)
index 0000000..4c52dee
--- /dev/null
+++ b/gconf.h
@@ -0,0 +1,31 @@
+/**
+  @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
diff --git a/gconf/network-type.xml b/gconf/network-type.xml
new file mode 100644 (file)
index 0000000..98b9f1c
--- /dev/null
@@ -0,0 +1,55 @@
+<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>
diff --git a/icd.c b/icd.c
new file mode 100644 (file)
index 0000000..4b07322
--- /dev/null
+++ b/icd.c
@@ -0,0 +1,531 @@
+/**
+  @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);
+}
+
diff --git a/icd.h b/icd.h
new file mode 100644 (file)
index 0000000..467fbb7
--- /dev/null
+++ b/icd.h
@@ -0,0 +1,36 @@
+/**
+  @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
diff --git a/include/wlancond-supp.h b/include/wlancond-supp.h
new file mode 100644 (file)
index 0000000..97b95f3
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+  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
diff --git a/log.h b/log.h
new file mode 100644 (file)
index 0000000..9c45895
--- /dev/null
+++ b/log.h
@@ -0,0 +1,35 @@
+/**
+  @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_ */
diff --git a/networks.c b/networks.c
new file mode 100644 (file)
index 0000000..0761948
--- /dev/null
@@ -0,0 +1,408 @@
+/**
+  @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);
+}
+
diff --git a/networks.h b/networks.h
new file mode 100644 (file)
index 0000000..c06c41e
--- /dev/null
@@ -0,0 +1,50 @@
+/**
+  @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
diff --git a/patches/cx3110-module-src-2.0.15.patch b/patches/cx3110-module-src-2.0.15.patch
new file mode 100644 (file)
index 0000000..4745894
--- /dev/null
@@ -0,0 +1,454 @@
+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 */
+ };
diff --git a/patches/osso-wlan-1.3.10.patch b/patches/osso-wlan-1.3.10.patch
new file mode 100644 (file)
index 0000000..3ed92d1
--- /dev/null
@@ -0,0 +1,185 @@
+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) {
diff --git a/patches/wpasupplicant-0.6.4.patch b/patches/wpasupplicant-0.6.4.patch
new file mode 100644 (file)
index 0000000..97f4fdb
--- /dev/null
@@ -0,0 +1,324 @@
+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;
+       }
diff --git a/supp.c b/supp.c
new file mode 100644 (file)
index 0000000..3877e46
--- /dev/null
+++ b/supp.c
@@ -0,0 +1,598 @@
+/**
+  @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);
+}
+
diff --git a/supp.h b/supp.h
new file mode 100644 (file)
index 0000000..0314d57
--- /dev/null
+++ b/supp.h
@@ -0,0 +1,49 @@
+#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
diff --git a/welcome b/welcome
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/wlan.c b/wlan.c
new file mode 100644 (file)
index 0000000..659e922
--- /dev/null
+++ b/wlan.c
@@ -0,0 +1,339 @@
+/**
+  @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);
+}
+
diff --git a/wlan.h b/wlan.h
new file mode 100644 (file)
index 0000000..b3a29f3
--- /dev/null
+++ b/wlan.h
@@ -0,0 +1,52 @@
+/**
+  @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