diff -urN netapplet-1.0.0/ChangeLog.gentoo netapplet-1.0.0-gentoo/ChangeLog.gentoo --- netapplet-1.0.0/ChangeLog.gentoo 1969-12-31 19:00:00.000000000 -0500 +++ netapplet-1.0.0-gentoo/ChangeLog.gentoo 2005-01-08 11:12:47.671986585 -0500 @@ -0,0 +1,88 @@ +2005-01-08 Richard Ferguson + + * src/netdaemon.c: reworked get_interfaces to read /proc/net/dev instead + of parsing /etc/conf.d/net. This is needed because the + new net scripts don't need to have an entry in the + conf.d/net file. The default is always dhcp. + + * src/netapplet.c: added some logic to the other_essid function to + properly handle existing keys for given essid's + +2004-12-31 Richard Ferguson + + * src/netdaemon.c: added some new code to clear the essid stored + in the wireless file after an association is made. + we do this because not having an essid defined is + a better default then having an essid defined that + is not available. + + * src/netapplet.c: Same as above, plus some general code cleanups. + +2004-12-30 Richard Ferguson + + * src/netdaemon.c: implemented new get_keys handler for new + encryption key code. Updated essid hanlder + for new key maniplulation option. Also removed + support for direct iwconfig execution. This new + release will depend on wireless-config or the new + baselayout code. + + * src/netapplet.c: implemented new key code to remove requirement + on gnome-keyring. + + * src/netcommon.c: moved a few functions to here that can be used + by both applet and daemon + +2004-12-23 Richard Ferguson + + * src/netdaemon.c: fixed syntax of how the wireless file is saved. + Cleaned up essid/key argument excaping. + + * src/netapplet.c: changed listing of preferred aps to a sub menu + to not clutter the main menu. Also increased the + limit to 10. Cleaned up a few places where strings + were getting transmitted without proper escaping. + +2004-12-22 Richard Ferguson + + * src/netdaemon.c: implemented gentoo preferred aps behavior + + * src/netapplet.c: implemented gentoo preferred aps behavior, a list of + the last five aps you successfully connected to + +2004-12-16 Richard Ferguson + + * src/netdaemon.c: fix a few issues with regards to active interfaces + + general clean up of gentoo additions + + * src/netapplet.c: more work on the new wireless behavior. Should be + working semi reliably. let me know if you run into + problems + + general clean up of gentoo additions + +2004-12-15 Richard Ferguson + + * src/netdaemon.c: removed skip_poll completely + + clean up poll_interfaces function + + added call to netdaemon_do_change_active() for direct + iwconfig mode to get a new ip + + fixed a few memory leaks in netdaemon_do_change_essid() + + * src/netapplet.c: first attempt at showing the available accesspoints + even when the wireless connection is not active. This + has a known limitation of only supporting a single + wireless interface + + +2004-12-15 Richard Ferguson + + * ported existing 0.98.0 patch to new 1.0.0 release. + +YYYY-MM-DD NAME + + * file: change diff -urN netapplet-1.0.0/config.h.in netapplet-1.0.0-gentoo/config.h.in --- netapplet-1.0.0/config.h.in 2004-12-06 23:50:31.000000000 -0500 +++ netapplet-1.0.0-gentoo/config.h.in 2004-12-15 16:27:59.000000000 -0500 @@ -6,6 +6,12 @@ /* Name of default gettext domain */ #undef GETTEXT_PACKAGE +/* gst network-admin executable path */ +#undef GST_NETWORKADMIN_PATH + +/* gst network-admin installed */ +#undef GST_NETWORKADMIN_TOOL + /* Define to 1 if you have the `bind_textdomain_codeset' function. */ #undef HAVE_BIND_TEXTDOMAIN_CODESET @@ -63,6 +69,9 @@ /* Minor Version Number */ #undef MINOR_VERSION +/* network configuration enabled */ +#undef NETWORK_CONF_TOOL + /* Name of package */ #undef PACKAGE diff -urN netapplet-1.0.0/configure netapplet-1.0.0-gentoo/configure --- netapplet-1.0.0/configure 2004-12-06 23:50:34.000000000 -0500 +++ netapplet-1.0.0-gentoo/configure 2004-12-30 09:33:54.000000000 -0500 @@ -309,7 +309,7 @@ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO AMTAR install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot MAJOR_VERSION MINOR_VERSION MICRO_VERSION MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CPP EGREP GETTEXT_PACKAGE INTLTOOL_DESKTOP_RULE INTLTOOL_DIRECTORY_RULE INTLTOOL_KEYS_RULE INTLTOOL_PROP_RULE INTLTOOL_OAF_RULE INTLTOOL_PONG_RULE INTLTOOL_SERVER_RULE INTLTOOL_SHEET_RULE INTLTOOL_SOUNDLIST_RULE INTLTOOL_UI_RULE INTLTOOL_XAM_RULE INTLTOOL_KBD_RULE INTLTOOL_XML_RULE INTLTOOL_CAVES_RULE INTLTOOL_SCHEMAS_RULE INTLTOOL_THEME_RULE INTLTOOL_EXTRACT INTLTOOL_MERGE INTLTOOL_UPDATE INTLTOOL_PERL USE_NLS MSGFMT GMSGFMT XGETTEXT CATALOGS CATOBJEXT DATADIRNAME GMOFILES INSTOBJEXT INTLLIBS PO_IN_DATADIR_TRUE PO_IN_DATADIR_FALSE POFILES POSUB PKG_CONFIG NETAPPLET_CFLAGS NETAPPLET_LIBS NETDAEMON_CFLAGS NETDAEMON_LIBS LIBOBJS LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO AMTAR install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot MAJOR_VERSION MINOR_VERSION MICRO_VERSION MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CPP EGREP GETTEXT_PACKAGE INTLTOOL_DESKTOP_RULE INTLTOOL_DIRECTORY_RULE INTLTOOL_KEYS_RULE INTLTOOL_PROP_RULE INTLTOOL_OAF_RULE INTLTOOL_PONG_RULE INTLTOOL_SERVER_RULE INTLTOOL_SHEET_RULE INTLTOOL_SOUNDLIST_RULE INTLTOOL_UI_RULE INTLTOOL_XAM_RULE INTLTOOL_KBD_RULE INTLTOOL_XML_RULE INTLTOOL_CAVES_RULE INTLTOOL_SCHEMAS_RULE INTLTOOL_THEME_RULE INTLTOOL_EXTRACT INTLTOOL_MERGE INTLTOOL_UPDATE INTLTOOL_PERL USE_NLS MSGFMT GMSGFMT XGETTEXT CATALOGS CATOBJEXT DATADIRNAME GMOFILES INSTOBJEXT INTLLIBS PO_IN_DATADIR_TRUE PO_IN_DATADIR_FALSE POFILES POSUB PKG_CONFIG NETAPPLET_CFLAGS NETAPPLET_LIBS NETDAEMON_CFLAGS NETDAEMON_LIBS NETWORKADMIN_TOOL LIBOBJS LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -6059,23 +6059,23 @@ else PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then - echo "$as_me:$LINENO: checking for libgnomeui-2.0 libglade-2.0 gnome-keyring-1" >&5 -echo $ECHO_N "checking for libgnomeui-2.0 libglade-2.0 gnome-keyring-1... $ECHO_C" >&6 + echo "$as_me:$LINENO: checking for libgnomeui-2.0 libglade-2.0" >&5 +echo $ECHO_N "checking for libgnomeui-2.0 libglade-2.0... $ECHO_C" >&6 - if $PKG_CONFIG --exists "libgnomeui-2.0 libglade-2.0 gnome-keyring-1" ; then + if $PKG_CONFIG --exists "libgnomeui-2.0 libglade-2.0" ; then echo "$as_me:$LINENO: result: yes" >&5 echo "${ECHO_T}yes" >&6 succeeded=yes echo "$as_me:$LINENO: checking NETAPPLET_CFLAGS" >&5 echo $ECHO_N "checking NETAPPLET_CFLAGS... $ECHO_C" >&6 - NETAPPLET_CFLAGS=`$PKG_CONFIG --cflags "libgnomeui-2.0 libglade-2.0 gnome-keyring-1"` + NETAPPLET_CFLAGS=`$PKG_CONFIG --cflags "libgnomeui-2.0 libglade-2.0"` echo "$as_me:$LINENO: result: $NETAPPLET_CFLAGS" >&5 echo "${ECHO_T}$NETAPPLET_CFLAGS" >&6 echo "$as_me:$LINENO: checking NETAPPLET_LIBS" >&5 echo $ECHO_N "checking NETAPPLET_LIBS... $ECHO_C" >&6 - NETAPPLET_LIBS=`$PKG_CONFIG --libs "libgnomeui-2.0 libglade-2.0 gnome-keyring-1"` + NETAPPLET_LIBS=`$PKG_CONFIG --libs "libgnomeui-2.0 libglade-2.0"` echo "$as_me:$LINENO: result: $NETAPPLET_LIBS" >&5 echo "${ECHO_T}$NETAPPLET_LIBS" >&6 else @@ -6083,7 +6083,7 @@ NETAPPLET_LIBS="" ## If we have a custom action on failure, don't print errors, but ## do set a variable so people can do so. - NETAPPLET_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "libgnomeui-2.0 libglade-2.0 gnome-keyring-1"` + NETAPPLET_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "libgnomeui-2.0 libglade-2.0"` echo $NETAPPLET_PKG_ERRORS fi @@ -6098,8 +6098,8 @@ if test $succeeded = yes; then : else - { { echo "$as_me:$LINENO: error: Library requirements (libgnomeui-2.0 libglade-2.0 gnome-keyring-1) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them." >&5 -echo "$as_me: error: Library requirements (libgnomeui-2.0 libglade-2.0 gnome-keyring-1) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them." >&2;} + { { echo "$as_me:$LINENO: error: Library requirements (libgnomeui-2.0 libglade-2.0) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them." >&5 +echo "$as_me: error: Library requirements (libgnomeui-2.0 libglade-2.0) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them." >&2;} { (exit 1); exit 1; }; } fi @@ -6573,6 +6573,70 @@ fi fi + +### check for network-admin from gnome system tools package + +# Extract the first word of "network-admin", so it can be a program name with args. +set dummy network-admin; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_path_NETWORKADMIN_TOOL+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $NETWORKADMIN_TOOL in + [\\/]* | ?:[\\/]*) + ac_cv_path_NETWORKADMIN_TOOL="$NETWORKADMIN_TOOL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_NETWORKADMIN_TOOL="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + ;; +esac +fi +NETWORKADMIN_TOOL=$ac_cv_path_NETWORKADMIN_TOOL + +if test -n "$NETWORKADMIN_TOOL"; then + echo "$as_me:$LINENO: result: $NETWORKADMIN_TOOL" >&5 +echo "${ECHO_T}$NETWORKADMIN_TOOL" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test "x${NETWORKADMIN_TOOL}" = "x"; then + { echo "$as_me:$LINENO: WARNING: network-admin executable not found in your path" >&5 +echo "$as_me: WARNING: network-admin executable not found in your path" >&2;} +else + +cat >>confdefs.h <<\_ACEOF +#define NETWORK_CONF_TOOL 1 +_ACEOF + + +cat >>confdefs.h <<\_ACEOF +#define GST_NETWORKADMIN_TOOL 1 +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define GST_NETWORKADMIN_PATH "${NETWORKADMIN_TOOL}" +_ACEOF + +fi + + ### build makefiles ac_config_files="$ac_config_files Makefile icons/Makefile icons/16x16/Makefile icons/24x24/Makefile src/Makefile po/Makefile.in" @@ -7327,6 +7391,7 @@ s,@NETAPPLET_LIBS@,$NETAPPLET_LIBS,;t t s,@NETDAEMON_CFLAGS@,$NETDAEMON_CFLAGS,;t t s,@NETDAEMON_LIBS@,$NETDAEMON_LIBS,;t t +s,@NETWORKADMIN_TOOL@,$NETWORKADMIN_TOOL,;t t s,@LIBOBJS@,$LIBOBJS,;t t s,@LTLIBOBJS@,$LTLIBOBJS,;t t CEOF diff -urN netapplet-1.0.0/configure.in netapplet-1.0.0-gentoo/configure.in --- netapplet-1.0.0/configure.in 2004-10-18 15:37:56.000000000 -0400 +++ netapplet-1.0.0-gentoo/configure.in 2004-12-30 09:33:32.000000000 -0500 @@ -40,7 +40,7 @@ ### get cflags and libs -PKG_CHECK_MODULES(NETAPPLET, libgnomeui-2.0 libglade-2.0 gnome-keyring-1) +PKG_CHECK_MODULES(NETAPPLET, libgnomeui-2.0 libglade-2.0) PKG_CHECK_MODULES(NETDAEMON, glib-2.0) ### look for iwlib @@ -93,6 +93,19 @@ fi fi + +### check for network-admin from gnome system tools package + +AC_PATH_PROG(NETWORKADMIN_TOOL, network-admin) +if test "x${NETWORKADMIN_TOOL}" = "x"; then + AC_MSG_WARN([network-admin executable not found in your path]) +else + AC_DEFINE(NETWORK_CONF_TOOL, 1, [network configuration enabled]) + AC_DEFINE(GST_NETWORKADMIN_TOOL, 1, [gst network-admin installed]) + AC_DEFINE_UNQUOTED(GST_NETWORKADMIN_PATH, "${NETWORKADMIN_TOOL}", [gst network-admin executable path]) +fi + + ### build makefiles AC_OUTPUT([ diff -urN netapplet-1.0.0/netapplet.desktop netapplet-1.0.0-gentoo/netapplet.desktop --- netapplet-1.0.0/netapplet.desktop 2004-10-18 15:37:11.000000000 -0400 +++ netapplet-1.0.0-gentoo/netapplet.desktop 2004-12-15 16:27:59.000000000 -0500 @@ -25,10 +25,11 @@ Comment[pt_BR]=Mini-Aplicativo do Painel do Seletor de Rede Comment[zh_CN]=网络选择器面板小程序 Comment[zh_TW]=網路選擇器面板程式 +Categories=GNOME;Application;System;Utility; +Encoding=UTF-8 Exec=netapplet Icon=netapplet.png Terminal=false Type=Application TryExec=netapplet -Categories=GNOME;Application;Internet;X-Ximian-Main; StartupNotify=false diff -urN netapplet-1.0.0/src/netapplet.c netapplet-1.0.0-gentoo/src/netapplet.c --- netapplet-1.0.0/src/netapplet.c 2004-10-18 15:37:12.000000000 -0400 +++ netapplet-1.0.0-gentoo/src/netapplet.c 2005-01-08 10:49:05.000000000 -0500 @@ -21,7 +21,6 @@ #include #include #include -#include #include "eggtrayicon.h" #include "netcommon.h" @@ -39,20 +38,20 @@ # define N_(String) (String) #endif -#define ETHERNET_ICON "gnome-dev-ethernet" +#define ETHERNET_ICON "gnome-dev-ethernet" #define DIALUP_ICON "gnome-dev-modem" -#define WIRELESS_ICON_0 "wireless-tower-0" -#define WIRELESS_ICON_1 "wireless-tower-1" -#define WIRELESS_ICON_2 "wireless-tower-2" -#define WIRELESS_ICON_3 "wireless-tower-3" -#define WIRELESS_ICON_4 "wireless-tower-4" -#define DISCONNECT_ICON "stock_calc-cancel" +#define WIRELESS_ICON_0 "wireless-tower-0" +#define WIRELESS_ICON_1 "wireless-tower-1" +#define WIRELESS_ICON_2 "wireless-tower-2" +#define WIRELESS_ICON_3 "wireless-tower-3" +#define WIRELESS_ICON_4 "wireless-tower-4" +#define DISCONNECT_ICON "stock_calc-cancel" #define BROKEN_ICON "stock_calc-cancel" -#define UNKNOWN_ICON "stock_unknown" +#define UNKNOWN_ICON "stock_unknown" -#define GLADE_APPLET GLADEDIR "/netapplet.glade" +#define GLADE_APPLET GLADEDIR "/netapplet.glade" -#define YAST2_ARGV { "/opt/kde3/bin/kdesu", "-n", "/sbin/yast2", "lan", NULL } +#define MAX_PREFERRED_APS 10 typedef struct { char *interface; /* interface name, e.g. eth0 */ @@ -61,14 +60,14 @@ } Connection; typedef struct { - double strength; /* wireless quality, should be [0.0, 1.0) */ - char *essid; /* ESSID name */ + double strength; /* wireless quality, should be [0.0, 1.0) */ + char *essid; /* ESSID name */ gboolean is_encrypted; /* is this network encrypted ? */ } Accesspoint; typedef struct { - GIOChannel *channel; /* our GIO to the daemon */ - GHashTable *handlers; /* hash of msg -> handler */ + GIOChannel *channel; /* our GIO to the daemon */ + GHashTable *handlers; /* hash of msg -> handler */ gboolean authorized; EggTrayIcon *tray_icon; @@ -76,21 +75,29 @@ GtkWidget *icon; GtkTooltips *tooltips; GtkWidget *popup_menu; - const char *default_keyring; const char *icon_name; int last_panel_h; GSList *connections; /* of Connection */ - Connection *active; /* active connection */ + Connection *active; /* active connection */ + int wireless_available; /* do we have a wireless interface? */ + char *wireless_interface; /* which is the wireless interface? */ + GSList *accesspoints; /* of Accesspoints */ - Accesspoint *active_ap; /* Active access point */ + Accesspoint *active_ap; /* Active access point */ double link_quality; /* global link quality [0,1] */ + gboolean clear_essid; /* do we need to clear the essid? */ + + GList *preferred_aps; /* of preferred accesspoints */ + GSList *keys; /* of essids with associated keys */ + gboolean need_keys; /* keep track if we need a keys update */ } NetApplet; static NetApplet *netapplet; static void populate_popup_menu (void); +static void other_essid_cb (GtkMenuItem*, gpointer); static void netapplet_set_icon (const char *icon_name) @@ -160,9 +167,7 @@ tip = g_strdup_printf ("Wireless connection (secure): " "%d%%", (int)(netapplet->active_ap->strength * 100)); } else { - g_warning ("icon_name=%s\n", icon_name); - g_assert_not_reached (); - return; /* bleh */ + tip = _("Unknown connection"); } gtk_tooltips_set_tip (netapplet->tooltips, netapplet->button, @@ -173,30 +178,158 @@ static void netapplet_set_connection (Connection *conn) { - netcommon_send_message (netapplet->channel, "change", conn->interface, + netcommon_send_message (netapplet->channel, "set_active", conn->interface, NULL); } +static guint +essid_has_key(gchar* essid) { + GSList *iter; + gchar *escaped, *key_essid; + + escaped = escape_essid_for_key(essid); + + for (iter = netapplet->keys; iter != NULL; iter=iter->next) { + key_essid = iter->data; + if (strcmp(key_essid, escaped) == 0) { + g_free(escaped); + return 1; + } + } + + g_free(escaped); + return 0; +} + + +static guint +preferred_aps_add(gchar* newessid) { + GList *iter, *paps; + gchar *essid; + guint found= 0; + guint len, i; + + paps = netapplet->preferred_aps; + + for (iter = paps; iter != NULL; iter=iter->next) { + essid = iter->data; + if (strcmp(essid, newessid) == 0) { + if (iter == paps) { + /* already first entry */ + return 0; + } else { + found = 1; + break; + } + } + } + + /* if we found it, move it to the front of + * the list */ + if (found) + paps = g_list_remove(paps, essid); + else + essid = g_strdup(newessid); + + paps = g_list_prepend(paps, essid); + + /* trim list to limit entries */ + len = g_list_length(paps); + + if (len > MAX_PREFERRED_APS) { + for (i=0; idata; + paps = g_list_remove(paps, essid); + g_free(essid); + } + } + + netapplet->preferred_aps = paps; + + return 1; +} + static void -netapplet_set_essid (const char *essid, const char *key) +netapplet_set_preferred_aps (void) { - if (netapplet->active) { - char *escaped_essid; + GList *iter; + GString *msg; + gchar *essid; + + msg = g_string_sized_new (512); /* start big to avoid resizes */ + g_string_printf (msg, "set_preferred_aps"); + + for (iter = netapplet->preferred_aps; iter != NULL; iter=iter->next) { + essid = netcommon_escape_argument(iter->data); + g_string_append_printf(msg, " %s", essid); + g_free(essid); + } + + netcommon_send_message(netapplet->channel, msg->str, NULL); - escaped_essid = netcommon_escape_argument (essid); + g_string_free(msg, TRUE); +} - netcommon_send_message (netapplet->channel, "essid", - netapplet->active->interface, - escaped_essid, key, NULL); +static void +netapplet_set_essid (const char *essid, const char *use_key, const char *key) +{ + char *iface; + char *escaped_essid; + char *escaped_key; + + if (netapplet->active && + (strcmp(netapplet->active->type, "Wireless") == 0)) { + iface = g_strdup(netapplet->active->interface); + } else if (netapplet->wireless_available) { + iface = g_strdup(netapplet->wireless_interface); + } else { + return; + } + + escaped_essid = netcommon_escape_argument (essid); + escaped_key = netcommon_escape_argument (key); + + netcommon_send_message (netapplet->channel, "set_essid", + iface, escaped_essid, use_key, escaped_key, NULL); - g_free (escaped_essid); + /* we just set the essid, once we get a connect signal, + * clear it */ + netapplet->clear_essid = TRUE; + netapplet->need_keys = TRUE; + + g_free (escaped_essid); + g_free (escaped_key); + g_free (iface); +} + +static void +netapplet_clr_essid (const gchar *up_interface) +{ + char *iface; + + if (netapplet->active && + (strcmp(netapplet->active->type, "Wireless") == 0)) { + iface = g_strdup(netapplet->active->interface); + } else if (netapplet->wireless_available) { + iface = g_strdup(netapplet->wireless_interface); + } else { + return; } + + netcommon_send_message (netapplet->channel, "clr_essid", + iface, up_interface, NULL); + + /* the essid has been cleared */ + netapplet->clear_essid = FALSE; + + g_free (iface); } static void netapplet_get_connections (void) { - netcommon_send_message (netapplet->channel, "list_interfaces", NULL); + netcommon_send_message (netapplet->channel, "get_interfaces", NULL); } static void @@ -208,18 +341,30 @@ static void netapplet_get_wireless (const char *interface) { - netcommon_send_message (netapplet->channel, "wireless", interface, + netcommon_send_message (netapplet->channel, "get_wireless", interface, NULL); } static void netapplet_get_accesspoints (const char *interface) { - netcommon_send_message (netapplet->channel, "accesspoints", interface, + netcommon_send_message (netapplet->channel, "get_accesspoints", interface, NULL); } static void +netapplet_get_keys (void) +{ + netcommon_send_message (netapplet->channel, "get_keys", NULL); +} + +static void +netapplet_get_preferred_aps (void) +{ + netcommon_send_message (netapplet->channel, "get_preferred_aps", NULL); +} + +static void conn_free (Connection *conn) { g_free (conn->interface); @@ -251,6 +396,22 @@ netapplet->active_ap = NULL; } +static void +netapplet_free_keys (void) +{ + g_slist_foreach (netapplet->keys, (GFunc) essid_free, NULL); + g_slist_free (netapplet->keys); + netapplet->keys = NULL; +} + +static void +netapplet_free_preferred_aps (void) +{ + g_list_foreach (netapplet->preferred_aps, (GFunc) essid_free, NULL); + g_list_free (netapplet->preferred_aps); + netapplet->preferred_aps = NULL; +} + static Connection * netapplet_get_connection_by_interface (const char *interface) { @@ -354,6 +515,8 @@ netapplet_get_connections (); netapplet_get_active (); + netapplet_get_keys (); + netapplet_get_preferred_aps (); } static void @@ -367,7 +530,16 @@ conn = netapplet_get_connection_by_interface (interface); g_assert (conn != NULL); - netapplet_set_connection (conn); + if (strcmp(conn->type, "Wireless") == 0) { + if (netapplet->preferred_aps) { + /* do we have a preferred_aps list? */ + netapplet_clr_essid("1"); + } else { + /* if we don't, ask for essid/key */ + other_essid_cb(NULL,NULL); + } + } else + netapplet_set_connection (conn); } static void @@ -394,278 +566,29 @@ gtk_widget_destroy (dialog); } -typedef void (*GDICallback) (gpointer user_data); - -typedef struct { - gboolean create_if_needed; - GDICallback callback; - gpointer user_data; -} GetDefaultInfo; - -static void -set_default_keyring_cb (GnomeKeyringResult result, - gpointer data) -{ - GetDefaultInfo *gdi = data; - - if (result != GNOME_KEYRING_RESULT_OK) { - g_warning (_("Error trying to set default keyring: %d"), - result); - g_free (gdi); - return; - } - - netapplet->default_keyring = "default"; - - gdi->callback (gdi->user_data); - g_free (gdi); -} - - -static void -create_keyring_cb (GnomeKeyringResult result, gpointer data) -{ - GetDefaultInfo *gdi = data; - - if (result != GNOME_KEYRING_RESULT_OK) { - g_warning (_("Error trying to create keyring: %d"), - result); - g_free (gdi); - return; - } - - gnome_keyring_set_default_keyring ("default", set_default_keyring_cb, - gdi, NULL); -} - -static void -get_default_keyring_cb (GnomeKeyringResult result, const char *string, - gpointer data) -{ - GetDefaultInfo *gdi = data; - - if (result != GNOME_KEYRING_RESULT_OK) { - g_warning (_("Error trying to get default keyring: %d"), - result); - g_free (gdi); - return; - } - - /* - * Ugh. If there isn't a default keyring we have to create one - * ourselves, which is incredibly inconvenient. - */ - if (string == NULL && gdi->create_if_needed) { - gnome_keyring_create ("default", - NULL, /* ask user */ - create_keyring_cb, - gdi, NULL); - } else { - /* Note! "string" could still be NULL */ - netapplet->default_keyring = g_strdup (string); - gdi->callback (gdi->user_data); - g_free (gdi); - } -} - -static void -get_default_keyring (gboolean create_if_needed, - GDICallback callback, - gpointer user_data) -{ - GetDefaultInfo *gdi = g_new0 (GetDefaultInfo, 1); - - gdi->create_if_needed = create_if_needed; - gdi->callback = callback; - gdi->user_data = user_data; - - /* - * Ugh. We have to try to get the default keyring and stick it - * in some ugly-ass global variable because some keyring functions - * (notably gnome_keyring_unlock() won't take NULL to mean the - * default keyring. - * - * This is fixed in 0.3.x keyring, so hopefully will be - * temporary. - */ - gnome_keyring_get_default_keyring (get_default_keyring_cb, gdi, NULL); -} - -static void -create_item_cb (GnomeKeyringResult result, - guint32 val G_GNUC_UNUSED, - gpointer data G_GNUC_UNUSED) -{ - if (result != GNOME_KEYRING_RESULT_OK) - g_warning (_("Unable to save to keyring! Err: %d"), result); -} - -static void -create_item (const char *essid, const char *key) -{ - GnomeKeyringAttributeList *attributes; - GnomeKeyringAttribute attr; - char *name; - - attributes = gnome_keyring_attribute_list_new (); - - attr.name = g_strdup ("essid"); - attr.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING; - attr.value.string = g_strdup (essid); - g_array_append_val (attributes, attr); - - name = g_strdup_printf (_("Password for network \"%s\""), essid); - - gnome_keyring_item_create (netapplet->default_keyring, - GNOME_KEYRING_ITEM_GENERIC_SECRET, - name, - attributes, - key, - TRUE, - create_item_cb, NULL, NULL); - - g_free (name); -} - -typedef struct { - char *essid; - char *key; -} SaveInfo; - -static void -queue_create (gpointer user_data) -{ - SaveInfo *sinfo = user_data; - - if (netapplet->default_keyring != NULL) - create_item (sinfo->essid, sinfo->key); - - g_free (sinfo->essid); - g_free (sinfo->key); - g_free (sinfo); -} - -static void -keyring_save (const char *essid, const char *key) -{ - SaveInfo *sinfo; - - sinfo = g_new0 (SaveInfo, 1); - sinfo->essid = g_strdup (essid); - sinfo->key = g_strdup (key); - - if (netapplet->default_keyring == NULL) - get_default_keyring (TRUE, queue_create, sinfo); - else - create_item (essid, key); -} - -static void -entry_changed_cb (GtkEntry *entry, gpointer user_data) -{ - GtkWidget *widget = GTK_WIDGET (user_data); - const char *text; - - text = gtk_entry_get_text (entry); - - if (text == NULL || *text == '\0') - gtk_widget_set_sensitive (widget, FALSE); - else - gtk_widget_set_sensitive (widget, TRUE); -} - static void -show_key_dialog (const char *essid) +get_key (const char *essid) { GladeXML *xml; - GtkWidget *dialog, *entry_key, *checkbox_keyring; - char *old_essid; + GtkWidget *dialog, *entry_key; xml = glade_xml_new (GLADE_APPLET, "dialog-key", NULL); dialog = glade_xml_get_widget (xml, "dialog-key"); - checkbox_keyring = glade_xml_get_widget (xml, "checkbutton-keyring"); - gtk_widget_set_sensitive (checkbox_keyring, FALSE); - - entry_key = glade_xml_get_widget (xml, "entry-key"); - g_signal_connect (entry_key, "changed", - G_CALLBACK (entry_changed_cb), - checkbox_keyring); - - old_essid = g_strdup (essid); - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { const char *key; + entry_key = glade_xml_get_widget (xml, "entry-key"); key = gtk_entry_get_text (GTK_ENTRY (entry_key)); - netapplet_set_essid (old_essid, key); - - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox_keyring))) - keyring_save (old_essid, key); + netapplet_set_essid (essid, "1", key); } - g_free (old_essid); gtk_widget_destroy (dialog); g_object_unref (xml); } static void -get_item_cb (GnomeKeyringResult result, GList *list, gpointer data) -{ - char *essid = data; - GnomeKeyringFound *found; - - if (result != GNOME_KEYRING_RESULT_OK) { - show_key_dialog (essid); - return; - } - - /* Not found in keyring */ - if (list == NULL) { - show_key_dialog (essid); - return; - } - - found = (GnomeKeyringFound *) list->data; - - netapplet_set_essid (essid, found->secret); - - g_free (essid); -} - -static void -get_item (const char *essid) -{ - gnome_keyring_find_itemsv (GNOME_KEYRING_ITEM_GENERIC_SECRET, - get_item_cb, - g_strdup (essid), - NULL, - "essid", - GNOME_KEYRING_ATTRIBUTE_TYPE_STRING, - essid, - NULL); -} - -static void -queue_get (gpointer user_data) -{ - const char *essid = user_data; - - if (netapplet->default_keyring != NULL) - get_item (essid); -} - -static void -keyring_load (const char *essid) -{ - if (netapplet->default_keyring == NULL) - get_default_keyring (FALSE, queue_get, (gpointer) essid); - else - get_item (essid); -} - -static void essid_activate_cb (GtkMenuItem *mi G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED) @@ -677,47 +600,129 @@ ap = netapplet_get_accesspoint_by_essid (essid); g_assert (ap); - if (ap->is_encrypted) - keyring_load (ap->essid); + if (ap->is_encrypted) { + if (essid_has_key(ap->essid)) + netapplet_set_essid (ap->essid, "0", ""); + else + get_key (ap->essid); + } else + netapplet_set_essid (ap->essid, "1", ""); + + /* set to clear essid */ + netapplet->clear_essid = TRUE; + netapplet->need_keys = TRUE; +} + +static guint +other_essid_clear_key() { + GtkWidget *dialog; + guint clear; + + dialog = gtk_message_dialog_new_with_markup ( + NULL, 0, GTK_MESSAGE_WARNING, GTK_BUTTONS_NONE, + _("" + "Exisiting key found for ESSID" + "\n\n" + "An exisiting key has been found for the desired ESSID. " + "You either did not specify a key or entered a blank key. " + "Do you want to use the existing key or clear the stored key?")); + gtk_dialog_add_buttons (GTK_DIALOG (dialog), + "_Use Exisiting Key", GTK_RESPONSE_CANCEL, + "_Clear Key", GTK_RESPONSE_OK, + NULL); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) + clear = 1; else - netapplet_set_essid (ap->essid, ""); + clear = 0; + + gtk_widget_destroy (dialog); + return clear; } static void other_essid_cb (GtkMenuItem *mi G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED) { - GtkWidget *dialog, *entry_key, *checkbox_keyring; + GtkWidget *dialog, *entry_key; GladeXML *xml; xml = glade_xml_new (GLADE_APPLET, "dialog-essid", NULL); dialog = glade_xml_get_widget (xml, "dialog-essid"); - - checkbox_keyring = glade_xml_get_widget (xml, "checkbutton-keyring"); - gtk_widget_set_sensitive (checkbox_keyring, FALSE); - - entry_key = glade_xml_get_widget (xml, "entry-key"); - g_signal_connect (entry_key, "changed", - G_CALLBACK (entry_changed_cb), checkbox_keyring); - + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { GtkWidget *entry_essid; - const char *essid, *key; + const gchar *essid, *key; entry_essid = glade_xml_get_widget (xml, "entry-essid"); + entry_key = glade_xml_get_widget (xml, "entry-key"); essid = gtk_entry_get_text (GTK_ENTRY (entry_essid)); key = gtk_entry_get_text (GTK_ENTRY (entry_key)); + + if (essid_has_key((gchar*) essid)) { + if (!strcmp(key, "")) { + /* there is an existing key, but no key was + * entered, do we want to clear the key or + * use what is already there? */ + if (other_essid_clear_key()) + netapplet_set_essid(essid, "1", key); + else + netapplet_set_essid(essid, "0", key); + + } else { + /* there is an exisiting key, but use the + * entered key instead */ + netapplet_set_essid (essid, "1", key); + } + } else + /* no exisiting key, use what was entered */ + netapplet_set_essid (essid, "1", key); - if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox_keyring))) - keyring_save (essid, key); - - netapplet_set_essid (essid, key); + /* set to clear essid */ + netapplet->clear_essid = TRUE; + netapplet->need_keys = TRUE; } gtk_widget_destroy (dialog); g_object_unref (xml); } +static void +refresh_accesspoints_cb (GtkMenuItem *mi G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED) +{ + char *iface; + + if (netapplet->active && + (strcmp(netapplet->active->type, "Wireless") == 0)) { + iface = g_strdup(netapplet->active->interface); + } else if (netapplet->wireless_available) { + iface = g_strdup(netapplet->wireless_interface); + } else { + return; + } + + netapplet_get_accesspoints(iface); + + g_free(iface); +} + +static void +preferred_aps_activate_cb (GtkMenuItem *mi G_GNUC_UNUSED, + gpointer user_data G_GNUC_UNUSED) +{ + gchar *essid; + essid = g_object_get_data (G_OBJECT (mi), "essid"); + + /* update preferred aps and reup the network*/ + if (preferred_aps_add(essid)) { + netapplet_set_preferred_aps(); + populate_popup_menu(); + } + + netapplet_clr_essid ("1"); +} + + static GtkWidget * get_label (GtkWidget *info_dialog, GladeXML *xml, const char *name) { @@ -876,12 +881,16 @@ g_free (mac); } +#ifdef NETWORK_CONF_TOOL static void configure_activate_cb (GtkMenuItem *mi G_GNUC_UNUSED, gpointer user_data G_GNUC_UNUSED) { - char *argv[] = YAST2_ARGV; GError *err = NULL; + + char *argv[2]; + argv[0] = GST_NETWORKADMIN_PATH; + argv[1] = NULL; if (!g_spawn_async (NULL, argv, NULL, 0, NULL, NULL, NULL, &err)) { GtkWidget *dialog; @@ -896,7 +905,9 @@ g_error_free (err); } + return; } +#endif static void quit_cb (GtkMenuItem *mi G_GNUC_UNUSED, @@ -965,8 +976,9 @@ static void populate_popup_menu (void) { - GtkWidget *mi, *image; + GtkWidget *mi, *sm, *image; GSList *iter; + GList *iter2; g_list_foreach (GTK_MENU_SHELL (netapplet->popup_menu)->children, remove_old_items, netapplet->popup_menu); @@ -1034,9 +1046,6 @@ /* Build list of wireless accesspoints ... */ if (netapplet->accesspoints) mi = gtk_menu_item_new_with_label (_("Wireless Networks")); - else if (!(netapplet->active && - strcmp (netapplet->active->type, "Wireless") == 0)) - mi = gtk_menu_item_new_with_label (_("Wireless disabled")); else mi = gtk_menu_item_new_with_label ( _("No wireless networks available")); @@ -1069,10 +1078,47 @@ gtk_widget_show (mi); g_free (display_name); } + + mi = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (netapplet->popup_menu), mi); + gtk_widget_show (mi); + + if (netapplet->preferred_aps) { + sm = gtk_menu_new(); + + for (iter2 = netapplet->preferred_aps; iter2 != NULL; iter2 = iter2->next) { + char *essid = iter2->data; + + mi = gtk_image_menu_item_new_with_mnemonic (essid); + + if (essid_has_key(essid)) { + image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION, + GTK_ICON_SIZE_MENU); + gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), + image); + } + + gtk_menu_shell_append (GTK_MENU_SHELL (sm), mi); + + g_object_set_data_full (G_OBJECT (mi), "essid", + g_strdup (essid), g_free); + g_signal_connect (mi, "activate", + G_CALLBACK (preferred_aps_activate_cb), NULL); + gtk_widget_set_sensitive (mi, netapplet->authorized); + gtk_widget_show (mi); + } + + image = gtk_image_new_from_stock (GTK_STOCK_INDEX, + GTK_ICON_SIZE_MENU); + mi = gtk_image_menu_item_new_with_mnemonic (_("Preferred Networks")); + gtk_image_menu_item_set_image ((GtkImageMenuItem*) mi, image); + gtk_widget_show (mi); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), sm); + gtk_menu_shell_append (GTK_MENU_SHELL (netapplet->popup_menu), mi); + } - if (netapplet->active && - strcmp (netapplet->active->type, "Wireless") == 0) { - mi = gtk_menu_item_new_with_label ("Other ..."); + if (netapplet->wireless_available) { + mi = gtk_menu_item_new_with_label ("Other Network..."); gtk_menu_shell_append (GTK_MENU_SHELL (netapplet->popup_menu), mi); g_signal_connect (mi, "activate", G_CALLBACK (other_essid_cb), @@ -1080,12 +1126,24 @@ gtk_widget_set_sensitive (mi, netapplet->authorized); gtk_widget_show (mi); - } - - mi = gtk_separator_menu_item_new (); - gtk_menu_shell_append (GTK_MENU_SHELL (netapplet->popup_menu), mi); - gtk_widget_show (mi); + + + image = gtk_image_new_from_stock (GTK_STOCK_REFRESH, + GTK_ICON_SIZE_MENU); + mi = gtk_image_menu_item_new_with_mnemonic (_("Refresh Networks")); + gtk_image_menu_item_set_image ((GtkImageMenuItem*) mi, image); + gtk_menu_shell_append (GTK_MENU_SHELL (netapplet->popup_menu), mi); + g_signal_connect (mi, "activate", G_CALLBACK (refresh_accesspoints_cb), + NULL); + gtk_widget_set_sensitive (mi, netapplet->authorized); + gtk_widget_show (mi); + + mi = gtk_separator_menu_item_new (); + gtk_menu_shell_append (GTK_MENU_SHELL (netapplet->popup_menu), mi); + gtk_widget_show (mi); + } + /* 'Connection Information' item */ image = gtk_image_new_from_stock (GTK_STOCK_PROPERTIES, GTK_ICON_SIZE_MENU); @@ -1096,6 +1154,7 @@ gtk_widget_show (mi); g_signal_connect (mi, "activate", G_CALLBACK (show_info_cb), netapplet); +#ifdef NETWORK_CONF_TOOL /* 'Configure Network Settings' item */ image = gtk_image_new_from_stock (GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU); @@ -1106,6 +1165,7 @@ gtk_widget_show (mi); g_signal_connect (mi, "activate", G_CALLBACK (configure_activate_cb), netapplet); +#endif mi = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (netapplet->popup_menu), mi); @@ -1325,15 +1385,50 @@ netapplet->accesspoints = new_aps; netapplet->active_ap = new_active; - netapplet->active->icon = wireless_icon (netapplet->active); - netapplet_set_icon (netapplet->active->icon); - if (changed) populate_popup_menu (); else update_popup_accesspoint_strengths (); } +static void +netapplet_handle_keys (GIOChannel *channel G_GNUC_UNUSED, + char **args) +{ + GSList *keys = NULL; + char **iter; + + for (iter = &args[1]; *iter != NULL; iter++) { + char *essid; + essid = g_strdup(*iter); + keys = g_slist_append(keys, essid); + } + + netapplet_free_keys(); + netapplet->keys = keys; + netapplet->need_keys = FALSE; + populate_popup_menu(); +} + +static void +netapplet_handle_preferred_aps (GIOChannel *channel G_GNUC_UNUSED, + char **args) +{ + GList *p_aps = NULL; + char **iter; + + for (iter = &args[1]; *iter != NULL; iter++) { + char *essid; + essid = g_strdup(*iter); + p_aps = g_list_append(p_aps, essid); + } + + netapplet_free_preferred_aps(); + netapplet->preferred_aps = p_aps; + + populate_popup_menu(); +} + /* * handle the 'wireless' message, which tells us the active ESSID * @@ -1372,6 +1467,15 @@ netapplet->active_ap = ap; } + if (preferred_aps_add(args[1])) + netapplet_set_preferred_aps(); + + if (netapplet->clear_essid) + netapplet_clr_essid("0"); + + if (netapplet->need_keys) + netapplet_get_keys(); + out: populate_popup_menu (); } @@ -1382,10 +1486,7 @@ { netapplet_set_icon (DISCONNECT_ICON); netapplet->active = NULL; - if (netapplet->accesspoints) { - /* remove no-longer-valid wireless information */ - netapplet_free_accesspoints (); - } + netapplet->active_ap = NULL; populate_popup_menu (); } @@ -1431,6 +1532,11 @@ char **iter; Connection *new_active = NULL; + if (netapplet->wireless_available) + g_free(netapplet->wireless_interface); + + netapplet->wireless_available = 0; + /* * This is used to restore netapplet->active to the new Connection * value obtained below. This avoids a race where netapplet->active @@ -1454,6 +1560,13 @@ if (strcmp (type, TYPE_WIRELESS) == 0) { conn->type = "Wireless"; conn->icon = wireless_icon (conn); + + /* track the wireless interface. for more than one wireless + * interface, the first one becomes default */ + if (!netapplet->wireless_available) { + netapplet->wireless_available = 1; + netapplet->wireless_interface = g_strdup(interface); + } } else if (strcmp (type, TYPE_ETHERNET) == 0) { conn->type = "Ethernet"; conn->icon = ETHERNET_ICON; @@ -1522,9 +1635,8 @@ if (g_str_has_prefix (netapplet->active->type, "Wireless")) { netapplet_get_accesspoints (netapplet->active->interface); netapplet_get_wireless (netapplet->active->interface); - } else if (netapplet->accesspoints) { - /* remove no-longer-valid wireless information */ - netapplet_free_accesspoints (); + } else { + netapplet->active_ap = NULL; } if (changed) { @@ -1601,18 +1713,14 @@ /* Protocol handlers */ applet->handlers = g_hash_table_new (g_str_hash, g_str_equal); - g_hash_table_insert (applet->handlers, "interfaces", - netapplet_handle_interfaces); - g_hash_table_insert (applet->handlers, "active", - netapplet_handle_active); - g_hash_table_insert (applet->handlers, "wireless", - netapplet_handle_wireless); - g_hash_table_insert (applet->handlers, "accesspoints", - netapplet_handle_accesspoints); - g_hash_table_insert (applet->handlers, "disconnected", - netapplet_handle_disconnected); - g_hash_table_insert (applet->handlers, "unauthorized", - netapplet_handle_unauthorized); + g_hash_table_insert (applet->handlers, "interfaces", netapplet_handle_interfaces); + g_hash_table_insert (applet->handlers, "active", netapplet_handle_active); + g_hash_table_insert (applet->handlers, "wireless", netapplet_handle_wireless); + g_hash_table_insert (applet->handlers, "accesspoints", netapplet_handle_accesspoints); + g_hash_table_insert (applet->handlers, "preferred_aps", netapplet_handle_preferred_aps); + g_hash_table_insert (applet->handlers, "keys", netapplet_handle_keys); + g_hash_table_insert (applet->handlers, "disconnected", netapplet_handle_disconnected); + g_hash_table_insert (applet->handlers, "unauthorized", netapplet_handle_unauthorized); return applet; } diff -urN netapplet-1.0.0/src/netapplet.glade netapplet-1.0.0-gentoo/src/netapplet.glade --- netapplet-1.0.0/src/netapplet.glade 2004-08-03 14:07:10.000000000 -0400 +++ netapplet-1.0.0-gentoo/src/netapplet.glade 2004-12-30 07:42:29.000000000 -0500 @@ -681,7 +681,7 @@ 0 True - * + * True @@ -778,11 +778,11 @@ True True True - False + True 0 True - * + * True @@ -798,39 +798,6 @@ True - - - - 6 - True - False - 0 - - - - True - True - Add to Keyring - True - GTK_RELIEF_NORMAL - True - False - False - True - - - 0 - False - False - - - - - 0 - True - True - - 0 @@ -972,11 +939,11 @@ True True True - False + True 0 True - * + * True @@ -992,39 +959,6 @@ False - - - - 6 - True - False - 0 - - - - True - True - Add to Keyring - True - GTK_RELIEF_NORMAL - True - False - False - True - - - 0 - False - False - - - - - 0 - False - False - - diff -urN netapplet-1.0.0/src/netcommon.c netapplet-1.0.0-gentoo/src/netcommon.c --- netapplet-1.0.0/src/netcommon.c 2004-09-02 13:39:43.000000000 -0400 +++ netapplet-1.0.0-gentoo/src/netcommon.c 2004-12-30 08:18:18.000000000 -0500 @@ -13,7 +13,7 @@ #include "netcommon.h" -//#define NETCOMMON_DEBUG +#define NETCOMMON_DEBUG #ifdef NETCOMMON_DEBUG # include @@ -224,3 +224,30 @@ return escaped; } + +/* ESSID Related Functions */ + +void +essid_free (char *essid) +{ + g_free (essid); +} + +gchar * +escape_essid_for_key (const gchar *essid) +{ + gchar *escaped; + + escaped = g_strdup(essid); + escaped = g_strcanon(escaped, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", '_'); + return escaped; +} + +gchar * +escape_essid_for_quotes (const gchar *essid) +{ + gchar *escaped; + escaped = g_strescape(essid, NULL); + return escaped; +} + diff -urN netapplet-1.0.0/src/netcommon.h netapplet-1.0.0-gentoo/src/netcommon.h --- netapplet-1.0.0/src/netcommon.h 2004-09-13 14:39:56.000000000 -0400 +++ netapplet-1.0.0-gentoo/src/netcommon.h 2004-12-30 08:18:05.000000000 -0500 @@ -23,4 +23,8 @@ extern gboolean netapplet_get_clipboard (void); +void essid_free (char *essid); +gchar * escape_essid_for_key (const gchar *essid); +gchar * escape_essid_for_quotes (const gchar *essid); + #endif diff -urN netapplet-1.0.0/src/netdaemon.c netapplet-1.0.0-gentoo/src/netdaemon.c --- netapplet-1.0.0/src/netdaemon.c 2004-09-20 16:49:06.000000000 -0400 +++ netapplet-1.0.0-gentoo/src/netdaemon.c 2005-01-08 09:50:13.000000000 -0500 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -25,38 +26,245 @@ #include "netcommon.h" -#define NETWORK_SYSCONF_PATH "/etc/sysconfig/network" -#define IFCFG_PREFIX "ifcfg-" -#define GETCFG_CMD "/sbin/getcfg" -#define GETCFG_INTERFACE_CMD "/sbin/getcfg-interface" -#define IFUP_BIN "/sbin/ifup" -#define IFDOWN_BIN "/sbin/ifdown" -#define ROUTE_CMD "/sbin/route" +#define PROC_NET_DEV "/proc/net/dev" +#define CONFD_WIRELESS "/etc/conf.d/wireless" +#define NET_INIT_PREFIX "/etc/init.d/net." +#define NET_INIT_ARGS "--quiet" + +#define ROUTE_CMD "/sbin/route" #define MAX_QUAL_OVERRIDE 90 /* for driver's with a broken max */ #define ROUTE_ARGV { ROUTE_CMD, "-n", NULL } -#define TIMEOUT_INTERVAL 10000 +#define TIMEOUT_INTERVAL 60000 +#define TIMEOUT_INTERVAL_ONE_SHOT 20000 typedef struct { GIOChannel *channel; /* GIOChannel that requested this scan */ - char *interface; /* network interface we are scanning */ - int fd; /* open fd from iw_sockets_open () */ + char *interface; /* network interface we are scanning */ + int fd; /* open fd from iw_sockets_open () */ } ScanningInfo; typedef struct { char essid[IW_ESSID_MAX_SIZE + 1]; /* ESSID name */ - int quality; /* link quality */ - gboolean is_encrypted; /* is this AP encrypted? */ + int quality; /* link quality */ + gboolean is_encrypted; /* is this AP encrypted? */ } APInfo; -static GHashTable *hash; /* hash table for commands */ +static GHashTable *hash; /* hash table for commands */ static GSList *current_connections; /* list of GIOChannels */ -static gboolean skip_poll = FALSE; /* Skip one round of polling, - for slow network changes */ +static char *active_iface = NULL; /* The last active interface */ + +static gboolean poll_interfaces (gpointer user_data G_GNUC_UNUSED); +static gboolean poll_interfaces_one_shot (gpointer user_data G_GNUC_UNUSED); + +static GSList * +essid_extract(gchar *str) { + guint i, start = 0; + gint in_essid = 0; + gchar c, *essid; + + GSList *list = NULL; + + for (i=0; imessage); + g_error_free(err); + return NULL; + } + + while (g_io_channel_read_line (file, &data, NULL, NULL, &err) == + G_IO_STATUS_NORMAL && essid_list == NULL) { + + + if (g_str_has_prefix(data, "key_")) { + key_data = g_strsplit_set (data, "_=", 0); + if (key_data[1] != NULL) + essid_list = g_slist_prepend(essid_list, g_strdup(key_data[1])); + + g_strfreev(key_data); + } + g_free(data); + } + + /* close the file */ + if ( g_io_channel_shutdown (file, FALSE, &err) != G_IO_STATUS_NORMAL ) { + g_error ("Unable to close "CONFD_WIRELESS" : %s\n", + err->message); + g_error_free (err); + } + g_io_channel_unref( file ); + + if (essid_list != NULL) + return essid_list; + else + return NULL; +} + +static GSList * +gentoo_wireless_get_preferred_aps() { + GError *err = NULL; + GIOChannel *file; + gchar *data; + gchar **pref_data; + GSList *essid_list = NULL; + + file = g_io_channel_new_file( CONFD_WIRELESS, "r", &err ); + if( !file ) { + g_error( "Unable to open "CONFD_WIRELESS": %s", + err->message); + g_error_free(err); + return NULL; + } + + while (g_io_channel_read_line (file, &data, NULL, NULL, &err) == + G_IO_STATUS_NORMAL && essid_list == NULL) { + + + if (g_str_has_prefix(data, "preferred_aps")) { + pref_data = g_strsplit_set (data, "()", 0); + if (pref_data[1] != NULL) + essid_list = essid_extract(pref_data[1]); + + g_strfreev(pref_data); + } + g_free(data); + } + + /* close the file */ + if ( g_io_channel_shutdown (file, FALSE, &err) != G_IO_STATUS_NORMAL ) { + g_error ("Unable to close "CONFD_WIRELESS" : %s\n", + err->message); + g_error_free (err); + } + g_io_channel_unref( file ); + + if (essid_list != NULL) + return essid_list; + else + return NULL; +} + +static void +gentoo_wireless_set_preferred_aps(gchar** list) { + GError *err = NULL; + GString *output; + GIOChannel *file; + gchar *data = NULL; + gchar **essid, *escaped; + + file = g_io_channel_new_file (CONFD_WIRELESS, "r", &err); + if (!file) { + g_warning ("Failed to open %s: %s\n", CONFD_WIRELESS, err->message); + g_error_free (err); + return; + } + + output = g_string_sized_new (512); /* start big to prevent resizing */ + + /* remove the preferred_aps line */ + while (g_io_channel_read_line (file, &data, NULL, NULL, &err) == + G_IO_STATUS_NORMAL) { + if (!g_str_has_prefix (data, "preferred_aps")) + g_string_append (output, data); + + g_free (data); + } + + if (err) { + g_warning ("Failed to read %s: %s\n", CONFD_WIRELESS, err->message); + g_error_free (err); + return; + } + + /* add back the updated lines */ + g_string_append_printf(output, "preferred_aps=( "); + + for (essid=&list[0]; *essid != NULL; essid++) { + escaped = escape_essid_for_quotes(*essid); + g_string_append_printf(output, "\"%s\" ", escaped); + g_free(escaped); + } + + g_string_append_printf(output, ")\n"); + + /* close, truncate, and reopen the file for writing */ + g_io_channel_unref (file); + file = g_io_channel_new_file (CONFD_WIRELESS, "w", &err); + if (!file) { + g_warning ("Failed to open %s: %s\n", CONFD_WIRELESS, err->message); + g_error_free (err); + g_string_free(output, TRUE); + return; + } -static char *active_iface = NULL; /* The last active interface */ + /* write out the new file in one swoop */ + if (g_io_channel_write_chars (file, output->str, -1, NULL, &err) != + G_IO_STATUS_NORMAL) { + g_warning ("Failed to write to %s: %s\n", CONFD_WIRELESS, err->message); + g_error_free (err); + g_string_free(output, TRUE); + g_io_channel_unref (file); + return; + } + g_string_free(output, TRUE); + g_io_channel_flush (file, NULL); + g_io_channel_unref (file); +} + +static guint +gentoo_verify_device(gchar *device) { + gchar *initscript; + guint verify; + + initscript = g_strconcat( NET_INIT_PREFIX, device, NULL ); + + /* make sure we have an initscript for this device */ + if (g_file_test(initscript, G_FILE_TEST_EXISTS)) + verify = 1; + else + verify = 0; + + g_free( initscript ); + + return verify; +} static const char * get_network_type (const char *interface) @@ -87,77 +295,50 @@ get_interfaces (void) { GError *err = NULL; - GDir *dir; - const char *name; GSList *iface_list = NULL; - - dir = g_dir_open (NETWORK_SYSCONF_PATH, 0, &err); - if (!dir) { - g_error ("Unable to open "NETWORK_SYSCONF_PATH": %s", - err->message); + GIOChannel *file; + gchar *data, *data2; + gchar **ifacedata; + guint skip; + + file = g_io_channel_new_file( PROC_NET_DEV, "r", &err ); + if( !file ) { + g_error( "Unable to open "PROC_NET_DEV": %s", + err->message); + g_error_free(err); return NULL; } - - do { - char *interface; - const char *argv[3]; - - name = g_dir_read_name (dir); - if (name == NULL || strncmp (name, IFCFG_PREFIX, - sizeof (IFCFG_PREFIX) - 1) != 0) - continue; - - /* Blacklist the loopback device */ - if (strcmp (name, IFCFG_PREFIX"lo") == 0) - continue; - - /* - * Blacklist "ip6tnl*" and "mip6mnha" interfaces, which - * the SUSE package miplv6 dumps into the sysconf path. - */ - if (g_str_has_prefix (name, IFCFG_PREFIX"ip6tnl") || - g_str_has_prefix (name, IFCFG_PREFIX"mipmnha")) - continue; - - argv[0] = GETCFG_INTERFACE_CMD; - argv[1] = (char *) name + sizeof (IFCFG_PREFIX) - 1; - argv[2] = NULL; - - if (!g_spawn_sync (NULL, (char **) argv, NULL, 0, - NULL, NULL, &interface, NULL, - NULL, &err)) { - g_warning ("Unable to execute " - GETCFG_INTERFACE_CMD": %s", - err->message); - g_error_free (err); + + /* extract devices known to kernel */ + skip = 2; + while (g_io_channel_read_line (file, &data, NULL, NULL, &err) == G_IO_STATUS_NORMAL) { + /* skip first two lines */ + if (skip) { + skip--; + g_free(data); continue; } - - if (interface != NULL && interface[0] != '\0') { - /* strip whitespace */ - interface = g_strstrip (interface); - - /* - * Workaround for some strange behavior in - * getcfg-interface. If you bring up a ppp0 - * interface, and if you run it (as root), it - * might return "no" as the interface name while - * it's in the process of connecting. If that's - * the case, then return the name as the - * interface instead. - */ - if (strcmp (interface, "no") == 0) { - g_free (interface); - interface = g_strdup (argv[1]); + + data2 = g_strchug(data); + ifacedata = g_strsplit_set (data2, ":", 0); + /* if the device is no the loopback */ + if (strcmp(ifacedata[0], "lo")) { + if (gentoo_verify_device(ifacedata[0])) { + iface_list = g_slist_prepend (iface_list, g_strdup(ifacedata[0])); } + } + + g_strfreev(ifacedata); + g_free(data); + } - iface_list = g_slist_prepend (iface_list, interface); - } else - g_free (interface); - - } while (name); - - g_dir_close (dir); + /* close the file */ + if ( g_io_channel_shutdown (file, FALSE, &err) != G_IO_STATUS_NORMAL ) { + g_error ("Unable to close /etc/conf.d/net : %s\n", + err->message); + g_error_free (err); + } + g_io_channel_unref( file ); return iface_list; } @@ -171,19 +352,26 @@ iface_list = get_interfaces (); for (iter = iface_list; iter != NULL; iter = iter->next) { - const char *argv[3], *interface = iter->data; + const char *argv[4], *interface = iter->data; + gchar *initscript = g_strconcat( NET_INIT_PREFIX, interface, NULL ); - argv[0] = IFDOWN_BIN; - argv[1] = interface; - argv[2] = NULL; + /* GENTOO: we use the gentoo stop init scripts + when bringing the interfaces down + ie /etc/init.d/net.IFX stop + */ + argv[0] = initscript; + argv[1] = NET_INIT_ARGS; + argv[2] = "stop"; + argv[3] = NULL; if (!g_spawn_sync (NULL, (char **) argv, NULL, 0, NULL, NULL, NULL, NULL, NULL, &err)) { - g_warning ("Unable to exec " IFDOWN_BIN ": %s", + g_warning ("Unable to exec %s stop: %s", initscript, err->message); g_error_free (err); } + g_free( initscript ); } g_free (active_iface); @@ -203,11 +391,12 @@ } static void -netdaemon_do_change_active (GIOChannel *channel G_GNUC_UNUSED, char **args) +netdaemon_do_set_active (GIOChannel *channel G_GNUC_UNUSED, char **args) { - const char *argv[3]; + const char *argv[4]; GError *err = NULL; int ret; + gchar* initscript; if (!args[1]) return; @@ -219,15 +408,20 @@ */ netdaemon_disconnect_all (); - argv[0] = IFUP_BIN; - argv[1] = args[1]; - argv[2] = NULL; + /* GENTOO: as for disconnect_all() we use the init scripts + found in /etc/init.d/net.IFX here + */ + initscript = g_strconcat( NET_INIT_PREFIX, args[1], NULL ); + argv[0] = initscript; + argv[1] = NET_INIT_ARGS; + argv[2] = "start"; + argv[3] = NULL; if (!g_spawn_sync (NULL, (char **) argv, NULL, 0, NULL, NULL, NULL, NULL, &ret, &err)) { - g_warning ("Unable to exec " IFUP_BIN ": %s", - err->message); + g_warning ("Unable to exec %s start: %s", initscript, + err->message); g_error_free (err); } @@ -237,15 +431,15 @@ active_iface = g_strdup (args[1]); } - /* - * Let's skip the next poll so we can wait for these interfaces to - * come up. - */ - skip_poll = TRUE; + g_free( initscript ); + + /* add a one time call to poll_interfaces after the + * active update applies */ + g_timeout_add (TIMEOUT_INTERVAL_ONE_SHOT, poll_interfaces_one_shot, NULL); } static void -netdaemon_do_list_interfaces (GIOChannel *channel G_GNUC_UNUSED, +netdaemon_do_get_interfaces (GIOChannel *channel G_GNUC_UNUSED, char **args G_GNUC_UNUSED) { GSList *iface_list, *iter; @@ -263,7 +457,7 @@ if (active_iface != NULL && strcmp (active_iface, interface) == 0) found_active = TRUE; - + type = get_network_type (interface); if (ifaces == NULL) @@ -326,20 +520,17 @@ } } - /* - * FIXME: Not totally sure this is right. We may want to check to - * make sure the interface is up before unconditionally sending - * the old active iface, but this is better than nothing. + /* Changed the behavior so that if the no active iface is + * detected in the above route command, assume we have been + * disconnected. */ - if (active_iface != NULL) - netcommon_send_message (channel, "active", active_iface, NULL); - else { - /* - * we did not find an active interface - tell the client - * as much - */ - netcommon_send_message (channel, "disconnected", NULL); + + if (active_iface != NULL) { + g_free(active_iface); + active_iface = NULL; } + + netcommon_send_message (channel, "disconnected", NULL); out: g_strfreev (lines); @@ -411,6 +602,11 @@ for (iter = aps; iter != NULL; iter = iter->next) { APInfo *ap = iter->data, *best; + + /* essid hidden filter, this may need work for other network drivers */ + if (strcmp(ap->essid, "") == 0) + continue; + /* * Scanning returns an entry for each AP on a given ESSID, but * we only want to see one entry per ESSID, with the highest @@ -662,17 +858,128 @@ } } -static char * -escape_essid (const char *essid) +static void +netdaemon_do_list_accesspoints (GIOChannel *channel G_GNUC_UNUSED, + char **args G_GNUC_UNUSED) +{ + GSList *iface_list, *iter; + char *pargs[3]; + + iface_list = get_interfaces (); + if (!iface_list) + return; + + pargs[0] = "accesspoints"; + pargs[1] = NULL; + pargs[2] = NULL; + + for (iter = iface_list; iter != NULL; iter = iter->next) { + const char *interface = iter->data; + const char *type; + + type = get_network_type (interface); + + if (strcmp (type, TYPE_WIRELESS) == 0) { + pargs[1] = g_strdup(interface); + } + } + + g_slist_foreach (iface_list, (GFunc) g_free, NULL); + g_slist_free (iface_list); + + if (pargs[1] != NULL) { + netdaemon_do_get_accesspoints(channel, pargs); + g_free(pargs[1]); + } +} + +static gchar* +essid_compress(gchar* essid) { + + gchar c; + guint i, j = 0; + gchar *cessid; + + cessid = g_new0(gchar, strlen(essid) + 1); + + for (i=0; inext) { + /* essid is already in a form suitable for sending*/ + g_string_append_printf(msg, " %s", (gchar*) iter->data); + } + + g_slist_foreach(essid_list, (GFunc) essid_free, NULL); + g_slist_free(essid_list); + + netcommon_send_message(channel, msg->str, NULL); +} + +static void +netdaemon_do_get_preferred_aps (GIOChannel *channel G_GNUC_UNUSED, char **args G_GNUC_UNUSED) { - char **tokens; - char *escaped; + GSList *essid_list; + GSList *iter; + GString *msg; + gchar *essid, *escaped; + + + msg = g_string_sized_new (256); + g_string_printf(msg, "preferred_aps"); + + essid_list = gentoo_wireless_get_preferred_aps(); + if (essid_list == NULL) + return; - tokens = g_strsplit (essid, "'", 0); - escaped = g_strjoinv ("'\\''", tokens); - g_strfreev (tokens); + for (iter=essid_list; iter!=NULL; iter=iter->next) { + essid = essid_compress(iter->data); + escaped = netcommon_escape_argument (essid); + g_string_append_printf(msg, " %s", escaped); + g_free(escaped); + g_free(essid); + } + + g_slist_foreach(essid_list, (GFunc) essid_free, NULL); + g_slist_free(essid_list); + + netcommon_send_message(channel, msg->str, NULL); +} - return escaped; +static void +netdaemon_do_set_preferred_aps (GIOChannel *channel G_GNUC_UNUSED, char **args G_GNUC_UNUSED) +{ + gentoo_wireless_set_preferred_aps(&args[1]); } /* @@ -681,135 +988,155 @@ * args[0] is 'essid' (ignored) * args[1] is the current interface * args[2] is the new ESSID - * args[3] is the new ESSID's wireless encryption key ("" if no key) + * args[3] tells us whether to manipulate the key entry + * args[4] is the new ESSID's wireless encryption key ("" if no key) */ static void -netdaemon_do_change_essid (GIOChannel *channel, char **args) +netdaemon_do_set_essid (GIOChannel *channel, char **args) { + GError *err = NULL; GString *output; - const char *argv[3]; - char *data = NULL, *getcfg, *p, *cfg; GIOChannel *file; - GError *err = NULL; - char *escaped_essid; + char *data = NULL, *essid_prefix, *key_prefix, *escaped_essid; - argv[0] = GETCFG_CMD; - argv[1] = args[1]; - argv[2] = NULL; + file = g_io_channel_new_file (CONFD_WIRELESS, "r", &err); + if (!file) { + g_warning ("Failed to open %s: %s\n", CONFD_WIRELESS, err->message); + g_error_free (err); + return; + } + + /* setup wireless-config strings */ + essid_prefix = g_strdup_printf("essid_%s=", args[1]); + escaped_essid = escape_essid_for_key(args[2]); + key_prefix = g_strdup_printf("key_%s=", escaped_essid); + g_free(escaped_essid); + + output = g_string_sized_new (512); /* start big to prevent resizing */ - /* get the configuration information for this interface */ - if (!g_spawn_sync (NULL, (char **) argv, NULL, 0, NULL, NULL, - &getcfg, NULL, NULL, &err)) { - g_warning ("Unable to execute "GETCFG_CMD": %s", - err->message); - g_error_free (err); - return; + /* remove the offending lines */ + while (g_io_channel_read_line (file, &data, NULL, NULL, &err) == + G_IO_STATUS_NORMAL) { + + if (!g_str_has_prefix (data, essid_prefix) && + (!g_str_has_prefix (data, key_prefix) || !strcmp(args[3], "0"))) + g_string_append (output, data); + + g_free (data); } - /* get the ifcfg name for this interface */ - cfg = strstr (getcfg, "HWD_CONFIG_0"); - if (!cfg) { - g_warning ("Unable to determine configuration file for " - "interface %s", args[1]); - goto out_free_getcfg; - } - cfg = strstr (cfg, "="); - if (!cfg) { - g_warning ("Unable to determine configuration file for " - "interface %s", args[1]); - goto out_free_getcfg; - } - cfg++; - p = strstr (cfg, ";"); - if (!p) { - g_warning ("Unable to determine configuration file for " - "interface %s", args[1]); - goto out_free_getcfg; + if (err) { + g_warning ("Failed to read %s: %s\n", CONFD_WIRELESS, err->message); + g_error_free (err); + g_free(essid_prefix); + g_free(key_prefix); + return; } - p[0] = '\0'; - cfg = g_strdup_printf (NETWORK_SYSCONF_PATH"/"IFCFG_PREFIX"%s", cfg); - output = g_string_sized_new (512); /* start big to prevent resizing */ + /* add back the updated lines */ + escaped_essid = escape_essid_for_quotes(args[2]); + g_string_append_printf (output, "%s\"%s\"\n", essid_prefix, escaped_essid); + g_free(escaped_essid); + if (!strcmp(args[3], "1") && strcmp(args[4],"")) { + g_string_append_printf (output, "%s\"%s\"\n", key_prefix, args[4]); + } + + g_free(essid_prefix); + g_free(key_prefix); + + /* close, truncate, and reopen the file for writing */ + g_io_channel_unref (file); + file = g_io_channel_new_file (CONFD_WIRELESS, "w", &err); + if (!file) { + g_warning ("Failed to open %s: %s\n", CONFD_WIRELESS, err->message); + g_error_free (err); + g_string_free(output, TRUE); + return; + } - file = g_io_channel_new_file (cfg, "r", &err); + /* write out the new file in one swoop */ + if (g_io_channel_write_chars (file, output->str, -1, NULL, &err) != + G_IO_STATUS_NORMAL) { + g_warning ("Failed to write to %s: %s\n", CONFD_WIRELESS, err->message); + g_error_free (err); + g_string_free(output, TRUE); + g_io_channel_unref (file); + return; + } + g_string_free(output, TRUE); + g_io_channel_flush (file, NULL); + g_io_channel_unref (file); + + netdaemon_do_set_active (channel, args); + + return; +} + +static void +netdaemon_do_clr_essid (GIOChannel *channel, char **args) +{ + GError *err = NULL; + GString *output; + GIOChannel *file; + char *data = NULL, *essid_prefix; + + file = g_io_channel_new_file (CONFD_WIRELESS, "r", &err); if (!file) { - g_warning ("Failed to open %s: %s\n", cfg, err->message); + g_warning ("Failed to open %s: %s\n", CONFD_WIRELESS, err->message); g_error_free (err); - goto out_free_getcfg; + return; } + + /* setup wireless-config strings */ + essid_prefix = g_strdup_printf("essid_%s=", args[1]); + + output = g_string_sized_new (512); /* start big to prevent resizing */ /* remove the offending lines */ while (g_io_channel_read_line (file, &data, NULL, NULL, &err) == G_IO_STATUS_NORMAL) { - if (!g_str_has_prefix (data, "WIRELESS_ESSID=") && - !g_str_has_prefix (data, "WIRELESS_NWID=''") && - !g_str_has_prefix (data, "WIRELESS_KEY=''") && - !g_str_has_prefix (data, "WIRELESS_KEY_0=") && - !g_str_has_prefix (data, "WIRELESS_KEY_LENGTH=") && - !g_str_has_prefix (data, "WIRELESS_AP") && - !g_str_has_prefix (data, "WIRELESS_BITRATE") && - !g_str_has_prefix (data, "WIRELESS_CHANNEL") && - !g_str_has_prefix (data, "WIRELESS_MODE") && - !g_str_has_prefix (data, "WIRELESS_FREQUENCY") && - !g_str_has_prefix (data, "WIRELESS_DEFAULT_KEY=")) + + if (!g_str_has_prefix (data, essid_prefix)) g_string_append (output, data); g_free (data); } + + g_free(essid_prefix); if (err) { - g_warning ("Failed to read %s: %s\n", cfg, err->message); + g_warning ("Failed to read %s: %s\n", CONFD_WIRELESS, err->message); g_error_free (err); - goto out; + return; } - /* add back the updated lines */ - escaped_essid = escape_essid (args[2]); - g_string_append_printf (output, "WIRELESS_ESSID='%s'\n", - escaped_essid); - g_free (escaped_essid); - - g_string_append_printf (output, "WIRELESS_KEY_0='%s'\n", args[3]); - - /* return the other lines to a nice sane default */ - g_string_append_printf (output, "WIRELESS_NWID=''\n"); - g_string_append_printf (output, "WIRELESS_KEY=''\n"); - g_string_append_printf (output, "WIRELESS_DEFAULT_KEY='0'\n"); - g_string_append_printf (output, "WIRELESS_KEY_LENGTH='128'\n"); - g_string_append_printf (output, "WIRELESS_AP=''\n"); - g_string_append_printf (output, "WIRELESS_BITRATE='auto'\n"); - g_string_append_printf (output, "WIRELESS_CHANNEL=''\n"); - g_string_append_printf (output, "WIRELESS_MODE='Managed'\n"); - g_string_append_printf (output, "WIRELESS_FREQUENCY=''"); - /* close, truncate, and reopen the file for writing */ g_io_channel_unref (file); - file = g_io_channel_new_file (cfg, "w", &err); + file = g_io_channel_new_file (CONFD_WIRELESS, "w", &err); if (!file) { - g_warning ("Failed to open %s: %s\n", cfg, err->message); + g_warning ("Failed to open %s: %s\n", CONFD_WIRELESS, err->message); g_error_free (err); - goto out; + g_string_free(output, TRUE); + return; } /* write out the new file in one swoop */ if (g_io_channel_write_chars (file, output->str, -1, NULL, &err) != G_IO_STATUS_NORMAL) { - g_warning ("Failed to write to %s: %s\n", cfg, err->message); + g_warning ("Failed to write to %s: %s\n", CONFD_WIRELESS, err->message); g_error_free (err); - goto out; + g_string_free(output, TRUE); + g_io_channel_unref (file); + return; } - + g_string_free(output, TRUE); g_io_channel_flush (file, NULL); - - netdaemon_do_change_active (channel, args); - -out: - g_string_free (output, TRUE); g_io_channel_unref (file); - g_free (cfg); -out_free_getcfg: - g_free (getcfg); + if (!strcmp(args[2], "1")) + netdaemon_do_set_active (channel, args); + + return; } static void @@ -850,11 +1177,10 @@ iw_pr_ether (ap_addr, wrq.u.ap_addr.sa_data); if (!is_valid_ap_address (ap_addr)) { - /* This is kind of ugly... */ - char *argv[] = { "essid", (char *) interface, - "any", "", NULL }; + char *argv[] = { "clr_essid", (char *) interface, + "0", NULL }; - netdaemon_do_change_essid (channel, argv); + netdaemon_do_clr_essid (channel, argv); goto out; } } @@ -922,6 +1248,10 @@ current_connections = g_slist_prepend (current_connections, gio); g_io_add_watch (gio, G_IO_HUP, connection_hup, NULL); + + /* after new connection is made, poll interfaces so + * the client gets an immediate update */ + poll_interfaces(NULL); } /* our listener socket hung up - we are dead */ @@ -995,61 +1325,101 @@ if (!hash) g_error ("Failed to initialize the hash table\n"); - g_hash_table_insert (hash, "change", netdaemon_do_change_active); - g_hash_table_insert (hash, "disconnect", netdaemon_do_disconnect); - g_hash_table_insert (hash, "list_interfaces", - netdaemon_do_list_interfaces); + g_hash_table_insert (hash, "get_interfaces", netdaemon_do_get_interfaces); g_hash_table_insert (hash, "get_active", netdaemon_do_get_active); - g_hash_table_insert (hash, "wireless", netdaemon_do_get_wireless); - g_hash_table_insert (hash, "accesspoints", - netdaemon_do_get_accesspoints); - g_hash_table_insert (hash, "essid", netdaemon_do_change_essid); + g_hash_table_insert (hash, "set_active", netdaemon_do_set_active); + g_hash_table_insert (hash, "disconnect", netdaemon_do_disconnect); + g_hash_table_insert (hash, "get_wireless", netdaemon_do_get_wireless); + g_hash_table_insert (hash, "get_accesspoints", netdaemon_do_get_accesspoints); + g_hash_table_insert (hash, "get_preferred_aps", netdaemon_do_get_preferred_aps); + g_hash_table_insert (hash, "set_preferred_aps", netdaemon_do_set_preferred_aps); + g_hash_table_insert (hash, "set_essid", netdaemon_do_set_essid); + g_hash_table_insert (hash, "clr_essid", netdaemon_do_clr_essid); + g_hash_table_insert (hash, "get_keys", netdaemon_do_get_keys); } static gboolean poll_interfaces (gpointer user_data G_GNUC_UNUSED) { - GSList *iface_list; GSList *iter; - /* - * Skip this round of polling since we just activated an interface - * and don't want to be overzealous in case the interface doesn't - * come up right away. - */ - if (skip_poll) { - skip_poll = FALSE; - return TRUE; - } - - iface_list = get_interfaces (); - for (iter = current_connections; iter != NULL; iter = iter->next) { GIOChannel *channel = iter->data; - netdaemon_do_list_interfaces (channel, NULL); + netdaemon_do_get_interfaces (channel, NULL); netdaemon_do_get_active (channel, NULL); + netdaemon_do_list_accesspoints (channel, NULL); } - g_slist_foreach (iface_list, (GFunc) g_free, NULL); - g_slist_free (iface_list); - return TRUE; } +static gboolean +poll_interfaces_one_shot(gpointer user_data G_GNUC_UNUSED) +{ + poll_interfaces(NULL); + return FALSE; +} + static void netdaemon_init_timeouts (void) { g_timeout_add (TIMEOUT_INTERVAL, poll_interfaces, NULL); } +static void +netdaemon_print_usage (void) +{ + fprintf (stderr, "\n" "usage : netdaemon [--no-daemon] [--help]\n"); + fprintf (stderr, + "\n" + " --no-daemon Don't become a daemon\n" + " --help Show this information and exit\n" + "\n"); +} + int -main (void) +main (int argc, char *argv[]) { GMainLoop *loop; gboolean daemonize = TRUE; - /* FIXME: add cmdline option parsing here, e.g. for daemonize */ + /* Parse options: Copied from NetworkManager ;) */ + while (1) + { + int c; + int option_index = 0; + const char *opt; + + static struct option options[] = { + {"no-daemon", 0, NULL, 0}, + {"help", 0, NULL, 0}, + {NULL, 0, NULL, 0} + }; + + c = getopt_long (argc, argv, "", options, &option_index); + if (c == -1) + break; + + switch (c) + { + case 0: + opt = options[option_index].name; + if (strcmp (opt, "help") == 0) + { + netdaemon_print_usage (); + exit (EXIT_SUCCESS); + } + else if (strcmp (opt, "no-daemon") == 0) + daemonize = FALSE; + break; + + default: + netdaemon_print_usage (); + exit (EXIT_FAILURE); + break; + } + } if (daemonize) { int fd;