Added empty network setup scripts
[mtetherd] / plugin.c
1 /*
2   mtetherd
3   (c) 2010 Gregor Riepl <onitake@gmail.com>
4   
5   Tethering utility for Maemo
6   
7   This program is free software: you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation, either version 3 of the License, or
10   (at your option) any later version.
11   
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16   
17   You should have received a copy of the GNU General Public License
18   along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <pwd.h>
26 #include <sys/types.h>
27 #include <gtk/gtk.h>
28 #include <hildon/hildon.h>
29 #include "plugin.h"
30 #include "hal.h"
31 #include "net.h"
32 #include "util.h"
33
34 #define MTETHERD_STATUS_PLUGIN_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE(obj, TYPE_MTETHERD_STATUS_PLUGIN, MTetherDStatusPluginPrivate))
35
36 typedef enum {
37         MTETHERD_STATUS_PLUGIN_USB_NET_UNKNOWN = 0,
38         MTETHERD_STATUS_PLUGIN_USB_NET_DISABLED,
39         MTETHERD_STATUS_PLUGIN_USB_NET_ENABLED,
40 } MTetherDStatusPluginUsbNetState;
41
42 struct _MTetherDStatusPluginPrivate {
43         GtkWidget *enable_button;
44         gpointer devices;
45         gboolean usb_plugged;
46         MTetherDStatusPluginUsbNetState usbnet_state;
47 };
48
49 #ifndef IMAGE_DIR
50 #define IMAGE_DIR "/usr/share/pixmaps"
51 #endif
52 #ifndef SBIN_DIR
53 #define SBIN_DIR "/usr/sbin"
54 #endif
55
56 // The UDI contains the MAC address and is thus unsuitable for
57 // loaded status checking, so we just use the interface name
58 static const char *USBNET_INTERFACE = "usb0";
59
60 HD_DEFINE_PLUGIN_MODULE(MTetherDStatusPlugin, mtetherd_status_plugin, HD_TYPE_STATUS_MENU_ITEM);
61
62 static void mtetherd_status_plugin_class_finalize(MTetherDStatusPluginClass *klass) { }
63
64 static void mtetherd_status_plugin_finalize(GObject *object) {
65         g_message("Destroying mtetherd status plugin");
66
67         MTetherDStatusPlugin *plugin = MTETHERD_STATUS_PLUGIN(object);
68
69         if (plugin && plugin->priv) {
70                 mtetherd_hal_finalize(plugin);
71                 mtetherd_device_list_free(plugin->priv->devices);
72         }
73 }
74
75 static void mtetherd_status_plugin_class_init(MTetherDStatusPluginClass *klass) {
76         GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
77
78         if (gobject_class) {
79                 gobject_class->finalize = mtetherd_status_plugin_finalize;
80                 g_type_class_add_private(klass, sizeof(MTetherDStatusPluginPrivate));
81         }
82 }
83
84 static void mtetherd_status_plugin_enable_button_set_text(MTetherDStatusPlugin *plugin) {
85         if (plugin && plugin->priv && plugin->priv->enable_button) {
86                 switch (plugin->priv->usbnet_state) {
87                         case MTETHERD_STATUS_PLUGIN_USB_NET_ENABLED:
88                                 hildon_button_set_text(HILDON_BUTTON(plugin->priv->enable_button), "Toggle USB Networking", "Enabled");
89                                 break;
90                         case MTETHERD_STATUS_PLUGIN_USB_NET_DISABLED:
91                                 hildon_button_set_text(HILDON_BUTTON(plugin->priv->enable_button), "Toggle USB Networking", "Disabled");
92                                 break;
93                         default:
94                                 hildon_button_set_text(HILDON_BUTTON(plugin->priv->enable_button), "Toggle USB Networking", "Unknown");
95                                 break;
96                         }
97         }
98 }
99
100 static void mtetherd_status_plugin_enable_button_clicked(GtkWidget *button, gpointer data) {
101         MTetherDStatusPlugin *plugin = MTETHERD_STATUS_PLUGIN(data);
102
103         if (plugin && plugin->priv && button == plugin->priv->enable_button) {
104                 const char *arg;
105                 switch (plugin->priv->usbnet_state) {
106                         case MTETHERD_STATUS_PLUGIN_USB_NET_ENABLED:
107                                 arg = SBIN_DIR "mtetherd-usbnet-disable.sh";
108                                 break;
109                         case MTETHERD_STATUS_PLUGIN_USB_NET_DISABLED:
110                                 arg = SBIN_DIR "mtetherd-usbnet-enable.sh";
111                                 break;
112                         default:
113                                 arg = NULL;
114                                 break;
115                 }
116                 if (arg) {
117                         g_debug("Launching %s", arg);
118                         const char *command[] = { "/usr/bin/sudo", arg, NULL };
119                         if (!mtetherd_launch_script(command)) {
120                                 g_error("Error launching USB networking script");
121                         }
122                 }
123         }
124 }
125
126 static void mtetherd_status_plugin_usb_plugged_show(MTetherDStatusPlugin *plugin) {
127         if (plugin && plugin->priv) {
128                 if (plugin->priv->usb_plugged) {
129                         gtk_widget_show(GTK_WIDGET(plugin));
130                 } else {
131                         gtk_widget_hide(GTK_WIDGET(plugin));
132                 }
133         }
134 }
135
136 static void mtetherd_status_plugin_init(MTetherDStatusPlugin *plugin) {
137         plugin->priv = MTETHERD_STATUS_PLUGIN_GET_PRIVATE(plugin);
138
139         plugin->priv->enable_button = hildon_button_new(HILDON_SIZE_AUTO_WIDTH | HILDON_SIZE_FINGER_HEIGHT, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
140         if (plugin->priv->enable_button) {
141                 GError *err = NULL;
142                 GdkPixbuf *icon = gdk_pixbuf_new_from_file(IMAGE_DIR "/mtetherd-net-icon.png", &err);
143                 if (err) {
144                         g_warning("Can't load mtetherd icon: %s", err->message);
145                         g_error_free(err);
146                         err = NULL;
147                 }
148                 if (icon) {
149                         GtkWidget *image = gtk_image_new_from_pixbuf(icon);
150                         hildon_button_set_image(HILDON_BUTTON(plugin->priv->enable_button), image);
151                         hildon_button_set_image_position(HILDON_BUTTON(plugin->priv->enable_button), GTK_POS_LEFT);
152                         g_object_unref(icon);
153                 }
154                 mtetherd_status_plugin_enable_button_set_text(plugin);
155                 g_signal_connect(plugin->priv->enable_button, "clicked", G_CALLBACK(mtetherd_status_plugin_enable_button_clicked), plugin);
156                 gtk_container_add(GTK_CONTAINER(plugin), plugin->priv->enable_button);
157                 gtk_widget_show_all(plugin->priv->enable_button);
158         }
159
160         if (mtetherd_hal_init(plugin)) {
161                 plugin->priv->usb_plugged = mtetherd_usb_state(plugin);
162                 plugin->priv->devices = mtetherd_device_list_new();
163                 mtetherd_hal_device_scan(plugin);
164         } else {
165                 plugin->priv->usb_plugged = FALSE;
166         }
167         
168         // Update the button status
169         mtetherd_status_plugin_usb_plugged_show(plugin);
170
171         hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Initialized mtetherd status plugin");
172 }
173
174 void mtetherd_status_plugin_device_added(MTetherDStatusPlugin *plugin, MTetherDDevice *device) {
175         if (plugin && plugin->priv) {
176                 const gchar *interface = mtetherd_device_get_interface(device);
177                 if (mtetherd_device_ok(interface)) {
178                         if (mtetherd_device_list_add(plugin->priv->devices, device)) {
179                                 if (g_strcmp0(USBNET_INTERFACE, interface) == 0) {
180                                         plugin->priv->usbnet_state = MTETHERD_STATUS_PLUGIN_USB_NET_ENABLED;
181                                         mtetherd_status_plugin_enable_button_set_text(plugin);
182                                 }
183                                 hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Starting network on %s", interface);
184                                 g_debug("Launching " SBIN_DIR "/mtetherd-net-setup.sh");
185                                 gchar *addr = mtetherd_device_get_addr(device);
186                                 gchar *netmask = mtetherd_device_get_netmask(device);
187                                 gchar *dhcp_start = mtetherd_device_get_dhcp_start(device);
188                                 gchar *dhcp_end = mtetherd_device_get_dhcp_end(device);
189                                 const char *command[] = { "/usr/bin/sudo", SBIN_DIR "/mtetherd-net-setup.sh", interface, addr, netmask, dhcp_start, dhcp_end, NULL };
190                                 if (!mtetherd_launch_script(command)) {
191                                         g_warning("Error launching USB networking setup script");
192                                 }
193                                 g_free(addr);
194                                 g_free(netmask);
195                                 g_free(dhcp_start);
196                                 g_free(dhcp_end);
197                         } else {
198                                 g_warning("Error adding network interface to list: Maximum number of devices exceeded");
199                         }
200                 }
201         }
202 }
203
204 void mtetherd_status_plugin_device_removed(MTetherDStatusPlugin *plugin, const gchar *udi) {
205         if (plugin && plugin->priv) {
206                 MTetherDDevice *device = mtetherd_device_list_find(plugin->priv->devices, udi);
207                 if (device) {
208                         const gchar *interface = mtetherd_device_get_interface(device);
209                         if (g_strcmp0(USBNET_INTERFACE, interface) == 0) {
210                                 plugin->priv->usbnet_state = MTETHERD_STATUS_PLUGIN_USB_NET_DISABLED;
211                                 mtetherd_status_plugin_enable_button_set_text(plugin);
212                         }
213                         hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Shutting down network on %s", interface);
214                         g_debug("Launching " SBIN_DIR "/mtetherd-net-shutdown.sh");
215                         const char *command[] = { "/usr/bin/sudo", SBIN_DIR "/mtetherd-net-shutdown.sh", interface, NULL };
216                         if (!mtetherd_launch_script(command)) {
217                                 g_warning("Error launching USB networking shutdown script");
218                         }
219                 }
220                 if (!mtetherd_device_list_remove(plugin->priv->devices, udi)) {
221                         g_warning("Error removing network interface from list: Not found");
222                 }
223         }
224 }
225
226 void mtetherd_status_plugin_usb_plugged(MTetherDStatusPlugin *plugin) {
227         mtetherd_status_plugin_usb_plugged_show(plugin);
228 }
229