Fixed network setup scripts
authorGregor Riepl <onitake@gmail.com>
Sat, 7 Aug 2010 21:55:32 +0000 (23:55 +0200)
committerGregor Riepl <onitake@gmail.com>
Sat, 7 Aug 2010 21:55:32 +0000 (23:55 +0200)
Fixed update-sudoers install stages
Added lots of debugging to network setup scripts
Implemented waiting for child process return and check of return code

Makefile
debian/postinst
debian/postrm
hal.c
mtetherd-net-setup.sh
mtetherd-net-shutdown.sh
mtetherd.sudoers
net.c
plugin.c
util.c

index b450922..88c8112 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -7,8 +7,12 @@ DOC_DIR = $(PREFIX)/share/doc/mtetherd
 IMAGE_DIR = $(PREFIX)/share/pixmaps
 ETC_DIR = /etc
 TMP_DIR = /tmp
+RM = rm -f
+INSTALL = install
+FAKEROOT = fakeroot
+BUILDPKG = dpkg-buildpackage
 CC = gcc
-CFLAGS = -Wall -O2 -g -D_GNU_SOURCE -DIMAGE_DIR=\"$(IMAGE_DIR)\" -DBIN_DIR=\"$(BIN_DIR)\" -DSBIN_DIR=\"$(SBIN_DIR)\" -DTMP_DIR=\"$(TMP_DIR)\"
+CFLAGS = -DLAUNCH_SYNCHRONOUS -Wall -O2 -g -D_GNU_SOURCE -DIMAGE_DIR=\"$(IMAGE_DIR)\" -DBIN_DIR=\"$(BIN_DIR)\" -DSBIN_DIR=\"$(SBIN_DIR)\" -DTMP_DIR=\"$(TMP_DIR)\"
 INCLUDES = $(shell pkg-config --cflags dbus-1 libhildondesktop-1 hal glib-2.0 gtk+-2.0)
 LDFLAGS =
 LIBS_DBUS = $(shell pkg-config --libs dbus-1)
@@ -22,33 +26,36 @@ mtetherd: mtetherd.o device.o
 mtetherd-plugin.so: plugin.o hal.o net.o util.o
        $(CC) $(LDFLAGS) $(LIBS_HILDON) -shared -o $@ $^
 
-%PHONY: clean install uninstall
+%PHONY: clean install uninstall package
 
 clean:
-       rm -f *.o mtetherd mtetherd-plugin.so
+       $(RM) *.o mtetherd mtetherd-plugin.so
 
 install: mtetherd-plugin.so
-       install -m 644 -D README $(DESTDIR)/$(DOC_DIR)/README
-       install -m 644 -D mtetherd-plugin.desktop $(DESTDIR)/$(HILDON_DESKTOP_DIR)/mtetherd-plugin.desktop
-       install -m 755 -D mtetherd-plugin.so $(DESTDIR)/$(HILDON_PLUGIN_DIR)/mtetherd-plugin.so
-       install -m 755 -D mtetherd-usbnet-enable.sh $(DESTDIR)/$(SBIN_DIR)/mtetherd-usbnet-enable.sh
-       install -m 755 -D mtetherd-usbnet-disable.sh $(DESTDIR)/$(SBIN_DIR)/mtetherd-usbnet-disable.sh
-       install -m 755 -D mtetherd-net-setup.sh $(DESTDIR)/$(SBIN_DIR)/mtetherd-net-setup.sh
-       install -m 755 -D mtetherd-net-shutdown.sh $(DESTDIR)/$(SBIN_DIR)/mtetherd-net-shutdown.sh
-       install -m 644 -D mtetherd.sudoers $(DESTDIR)/$(ETC_DIR)/sudoers.d/mtetherd.sudoers
-       install -m 644 -D mtetherd-net-icon.png $(DESTDIR)/$(IMAGE_DIR)/mtetherd-net-icon.png
+       $(INSTALL) -m 644 -D README $(DESTDIR)/$(DOC_DIR)/README
+       $(INSTALL) -m 644 -D mtetherd-plugin.desktop $(DESTDIR)/$(HILDON_DESKTOP_DIR)/mtetherd-plugin.desktop
+       $(INSTALL) -m 755 -D mtetherd-plugin.so $(DESTDIR)/$(HILDON_PLUGIN_DIR)/mtetherd-plugin.so
+       $(INSTALL) -m 755 -D mtetherd-usbnet-enable.sh $(DESTDIR)/$(SBIN_DIR)/mtetherd-usbnet-enable.sh
+       $(INSTALL) -m 755 -D mtetherd-usbnet-disable.sh $(DESTDIR)/$(SBIN_DIR)/mtetherd-usbnet-disable.sh
+       $(INSTALL) -m 755 -D mtetherd-net-setup.sh $(DESTDIR)/$(SBIN_DIR)/mtetherd-net-setup.sh
+       $(INSTALL) -m 755 -D mtetherd-net-shutdown.sh $(DESTDIR)/$(SBIN_DIR)/mtetherd-net-shutdown.sh
+       $(INSTALL) -m 644 -D mtetherd.sudoers $(DESTDIR)/$(ETC_DIR)/sudoers.d/mtetherd.sudoers
+       $(INSTALL) -m 644 -D mtetherd-net-icon.png $(DESTDIR)/$(IMAGE_DIR)/mtetherd-net-icon.png
 
 uninstall:
-       rm -f $(DESTDIR)/$(ETC_DIR)/event.d/mtetherd
-       rm -rf $(DESTDIR)/$(PREFIX)/share/doc/mtetherd
-       rm -f $(DESTDIR)/$(HILDON_DESKTOP_DIR)/mtetherd-plugin.desktop
-       rm -f $(DESTDIR)/$(HILDON_PLUGIN_DIR)/mtetherd-plugin.so
-       rm -f $(DESTDIR)/$(SBIN_DIR)/mtetherd-usbnet-enable.sh
-       rm -f $(DESTDIR)/$(SBIN_DIR)/mtetherd-usbnet-disable.sh
-       rm -f $(DESTDIR)/$(SBIN_DIR)/mtetherd-net-setup.sh
-       rm -f $(DESTDIR)/$(SBIN_DIR)/mtetherd-net-shutdown.sh
-       rm -f $(DESTDIR)/$(ETC_DIR)/sudoers.d/mtetherd.sudoers
-       rm -f $(DESTDIR)/$(IMAGE_DIR)/mtetherd-net-icon.png
+       $(RM) $(DESTDIR)/$(ETC_DIR)/event.d/mtetherd
+       $(RM) -r $(DESTDIR)/$(PREFIX)/share/doc/mtetherd
+       $(RM) $(DESTDIR)/$(HILDON_DESKTOP_DIR)/mtetherd-plugin.desktop
+       $(RM) $(DESTDIR)/$(HILDON_PLUGIN_DIR)/mtetherd-plugin.so
+       $(RM) $(DESTDIR)/$(SBIN_DIR)/mtetherd-usbnet-enable.sh
+       $(RM) $(DESTDIR)/$(SBIN_DIR)/mtetherd-usbnet-disable.sh
+       $(RM) $(DESTDIR)/$(SBIN_DIR)/mtetherd-net-setup.sh
+       $(RM) $(DESTDIR)/$(SBIN_DIR)/mtetherd-net-shutdown.sh
+       $(RM) $(DESTDIR)/$(ETC_DIR)/sudoers.d/mtetherd.sudoers
+       $(RM) $(DESTDIR)/$(IMAGE_DIR)/mtetherd-net-icon.png
+
+package:
+       $(FAKEROOT) $(BUILDPKG)
 
 %.o: %.c
        $(CC) $(CFLAGS) $(INCLUDES) -o $@ -c $^
index 1f5ba8a..d766eba 100644 (file)
@@ -20,7 +20,7 @@ set -e
 
 case "$1" in
     configure)
-        update-sudoers
+        update-sudoers start
     ;;
 
     abort-upgrade|abort-remove|abort-deconfigure)
index c5232c6..50293d6 100644 (file)
@@ -21,7 +21,7 @@ set -e
 
 case "$1" in
     purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
-        update-sudoers
+        update-suoders start
     ;;
 
     *)
diff --git a/hal.c b/hal.c
index c55fb5e..7720d09 100644 (file)
--- a/hal.c
+++ b/hal.c
@@ -29,7 +29,7 @@ static void mtetherd_hal_device_condition(LibHalContext *ctx, const char *udi, c
        MTetherDStatusPlugin *plugin = MTETHERD_STATUS_PLUGIN(libhal_ctx_get_user_data(ctx));
        
        if (plugin) {
-               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, "Got HAL condition %s on %s: %s", condition, udi, detail);
+               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Got HAL condition %s on %s: %s", condition, udi, detail);
                if (g_strcmp0("ButtonPressed", condition) == 0) {
                        g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "is ButtonPressed");
                        if (g_strcmp0(USBDEV_PATH, udi) == 0) {
@@ -44,7 +44,7 @@ static void mtetherd_hal_device_added(LibHalContext *ctx, const char *udi) {
        MTetherDStatusPlugin *plugin = MTETHERD_STATUS_PLUGIN(libhal_ctx_get_user_data(ctx));
        
        if (plugin) {
-               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, "Got HAL device added on %s", udi);
+               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Got HAL device added on %s", udi);
                DBusError derr;
                dbus_error_init(&derr);
                char *interface = libhal_device_get_property_string(plugin->hal_context, udi, "net.interface", &derr);
@@ -66,7 +66,7 @@ static void mtetherd_hal_device_removed(LibHalContext *ctx, const char *udi) {
        MTetherDStatusPlugin *plugin = MTETHERD_STATUS_PLUGIN(libhal_ctx_get_user_data(ctx));
        
        if (plugin) {
-               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, "Got HAL device added on %s", udi);
+               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Got HAL device removed on %s", udi);
                mtetherd_status_plugin_device_removed(plugin, udi);
        }
 }
@@ -81,11 +81,12 @@ gboolean mtetherd_hal_init(MTetherDStatusPlugin *plugin) {
                        err = NULL;
                        return FALSE;
                } else {
-                       g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, "Got DBUS Glib connection: %p", plugin->dbus_connection);
+                       g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Got GDBUS connection: %p", plugin->dbus_connection);
                }
                if (plugin->dbus_connection) {
                        plugin->hal_context = libhal_ctx_new();
                        if (plugin->hal_context) {
+                               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Got HAL context: %p", plugin->hal_context);
                                if (libhal_ctx_set_dbus_connection(plugin->hal_context, dbus_g_connection_get_connection(plugin->dbus_connection))) {
                                        if (!libhal_ctx_set_user_data(plugin->hal_context, plugin)) {
                                                g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Can't set user data of HAL context");
@@ -123,6 +124,7 @@ gboolean mtetherd_hal_init(MTetherDStatusPlugin *plugin) {
                                return FALSE;
                        }
                }
+               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "HAL context initialized and connected");
                return TRUE;
                
        }
index 1de3181..e6b919e 100755 (executable)
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 INTERFACE=$1
-ADDR=$2
-DHCP_START=$3
-DHCP_END=$4
+WAN=$2
+ADDRESS=$3
+NETMASK=$4
+DHCP_START=$5
+DHCP_END=$6
 
-echo "Setting up routing for: $INTERFACE $ADDR $DHCP_START $DHCP_END" >> /tmp/mtetherd-net-setup.log
+log() {
+       echo $@
+       echo $(date): $@ >> /tmp/mtetherd-script.log
+}
+
+die() {
+       echo $@ >&2
+       echo $(date): $@ >> /tmp/mtetherd-script.log
+       exit 1
+}
+
+if [ "${INTERFACE}" = "" -o "${WAN}" = "" -o "${ADDRESS}" = "" -o "${NETMASK}" = "" -o "${DHCP_START}" = "" -o "${DHCP_END}" = "" ]; then
+       die "Usage: $0 <interface> <wan interface> <address> <netmask> <dhcp range start> <dhcp range end>"
+fi
+
+log "Setting up routing for: $INTERFACE $WAN $ADDRESS $NETMASK $DHCP_START $DHCP_END"
+
+echo "${INTERFACE}" | grep -E -q '^[a-zA-Z]+[0-9]+$' || die "Invalid interface name"
+echo "${WAN}" | grep -E -q '^[a-zA-Z]+[0-9]+$' || die "Invalid WAN interface name"
+echo "${ADDRESS}" | grep -E -q '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' || die "Invalid address"
+echo "${NETMASK}" | grep -E -q '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' || die "Invalid netmask"
+echo "${DHCP_START}" | grep -E -q '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' || die "Invalid DHCP start address"
+echo "${DHCP_END}" | grep -E -q '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$' || die "Invalid DHCP end address"
+
+RUNFILE="/var/run/mtetherd.${INTERFACE}.pid"
+log "PID file = ${RUNFILE}"
+
+log "/sbin/ifconfig ${INTERFACE} ${ADDRESS} netmask ${NETMASK}"
+msg=$(/sbin/ifconfig ${INTERFACE} ${ADDRESS} netmask ${NETMASK} 2>&1)
+log $msg
+log "/sbin/modprobe ipt_MASQUERADE"
+msg=$(/sbin/modprobe ipt_MASQUERADE 2>&1)
+log $msg
+log "/usr/sbin/iptables -t nat -A POSTROUTING -o ${WAN} -j MASQUERADE"
+msg=$(/usr/sbin/iptables -t nat -A POSTROUTING -o ${WAN} -j MASQUERADE 2>&1)
+log $msg
+#-a, --listen-address=ipaddr         Specify local address(es) to listen on.
+#-d, --no-daemon                     Do NOT fork into the background: run in debug mode.
+#-D, --domain-needed                 Do NOT forward queries with no domain part.
+#-f, --filterwin2k                   Don't forward spurious DNS requests from Windows hosts.
+#-F, --dhcp-range=ipaddr,ipaddr,time Enable DHCP in the range given with lease duration.
+#-g, --group=groupname               Change to this group after startup (defaults to dip).
+#-h, --no-hosts                      Do NOT load /etc/hosts file.
+#-i, --interface=interface           Specify interface(s) to listen on.
+#-I, --except-interface=int          Specify interface(s) NOT to listen on.
+#-k, --keep-in-foreground            Do NOT fork into the background, do NOT run in debug mode.
+#-K, --dhcp-authoritative            Assume we are the only DHCP server on the local network.
+#-l, --dhcp-leasefile=path           Specify where to store DHCP leases (defaults to /var/lib/misc/dnsmasq.leases).
+#-n, --no-poll                       Do NOT poll /etc/resolv.conf file, reload only on SIGHUP.
+#-N, --no-negcache                   Do NOT cache failed search results.
+#-o, --strict-order                  Use nameservers strictly in the order given in /etc/resolv.conf.
+#-p, --port=number                   Specify port to listen for DNS requests on (defaults to 53).
+#-q, --log-queries                   Log DNS queries.
+#-Q, --query-port=number             Force the originating port for upstream DNS queries.
+#-R, --no-resolv                     Do NOT read resolv.conf.
+#-s, --domain=<domain>               Specify the domain to be assigned in DHCP leases.
+#-u, --user=username                 Change to this user after startup. (defaults to nobody).
+#-x, --pid-file=path                 Specify path of PID file (defaults to /var/run/dnsmasq.pid).
+#-X, --dhcp-lease-max=number         Specify maximum number of DHCP leases (defaults to 150).
+#-z, --bind-interfaces               Bind only to interfaces in use.
+#-Z, --read-ethers                   Read DHCP static host information from /etc/ethers.
+#-1, --enable-dbus                   Enable the DBus interface for setting upstream servers, etc.
+#-2, --no-dhcp-interface=interface   Do not provide DHCP on this interface, only provide DNS.
+#-9, --leasefile-ro                  Do not use leasefile.
+#    --log-dhcp                      Extra logging for DHCP.
+#    --min-port=<port>               Specify lowest port available for DNS query transmission.
+log "/sbin/start-stop-daemon -S -p \"${RUNFILE}\" -b -x /usr/sbin/dnsmasq -- -x \"${RUNFILE}\" -k -I lo -i ${INTERFACE} -a ${ADDRESS} -z -F ${DHCP_START},${DHCP_END},3600"
+msg=$(/sbin/start-stop-daemon -S -p "${RUNFILE}" -b -x /usr/sbin/dnsmasq -- -x "${RUNFILE}" -k -I lo -i ${INTERFACE} -a ${ADDRESS} -z -F ${DHCP_START},${DHCP_END},3600 2>&1)
+log $msg
+log "echo 1 > /proc/sys/net/ipv4/conf/${INTERFACE}/forwarding"
+echo 1 > /proc/sys/net/ipv4/conf/${INTERFACE}/forwarding
+log "echo 1 > /proc/sys/net/ipv4/conf/${WAN}/forwarding"
+echo 1 > /proc/sys/net/ipv4/conf/${WAN}/forwarding
+
+log "Finished setting up routing for $INTERFACE"
 
index 29018d4..b2d1223 100755 (executable)
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 INTERFACE=$1
+WAN=$2
 
-echo "Shutting down routing for: $INTERFACE" >> /tmp/mtetherd-net-shutdown.log
+log() {
+       echo $@
+       echo $(date): $@ >> /tmp/mtetherd-script.log
+}
+
+die() {
+       echo $@ >&2
+       echo $(date): $@ >> /tmp/mtetherd-script.log
+       exit 1
+}
+
+if [ "${INTERFACE}" = "" ]; then
+       die "Usage: $0 <interface> [<wan interface>]"
+fi
+
+log "Shutting down routing for: ${INTERFACE} ${WAN}"
+
+echo "${INTERFACE}" | grep -E -q '^[a-zA-Z]+[0-9]+$' || die "Invalid interface name"
+if [ "${WAN}" != "" ]; then
+       echo "${WAN}" | grep -E -q '^[a-zA-Z]+[0-9]+$' || die "Invalid WAN interface name"
+fi
+
+RUNFILE="/var/run/mtetherd.${INTERFACE}.pid"
+
+log "echo 0 > /proc/sys/net/ipv4/conf/${INTERFACE}/forwarding"
+echo 0 > /proc/sys/net/ipv4/conf/${INTERFACE}/forwarding
+log "/sbin/start-stop-daemon -K -p \"${RUNFILE}\" -x /usr/sbin/dnsmasq"
+msg=$(/sbin/start-stop-daemon -K -p "${RUNFILE}" -x /usr/sbin/dnsmasq 2>&1)
+log "$msg"
+if [ "${WAN}" != "" ]; then
+       log "/usr/sbin/iptables -t nat -D POSTROUTING -o ${WAN} -j MASQUERADE"
+       msg=$(/usr/sbin/iptables -t nat -D POSTROUTING -o ${WAN} -j MASQUERADE 2>&1)
+       log $msg
+fi
+
+log "Finished shutting down routing for ${INTERFACE}"
 
index 24bb3d0..45de790 100644 (file)
@@ -1,2 +1,5 @@
 user ALL = NOPASSWD: /usr/sbin/mtetherd-usbnet-enable.sh
 user ALL = NOPASSWD: /usr/sbin/mtetherd-usbnet-disable.sh
+user ALL = NOPASSWD: /usr/sbin/mtetherd-net-setup.sh
+user ALL = NOPASSWD: /usr/sbin/mtetherd-net-shutdown.sh
+
diff --git a/net.c b/net.c
index 43d49f9..a727605 100644 (file)
--- a/net.c
+++ b/net.c
@@ -246,6 +246,7 @@ gboolean mtetherd_device_list_add(gpointer list, MTetherDDevice *device) {
                for (i = 0; i < MAX_DEVICES; i++) {
                        if (!array[i]) {
                                array[i] = (gpointer) device;
+                               mtetherd_device_set_index(device, i);
                                return TRUE;
                        }
                }
@@ -268,12 +269,15 @@ gboolean mtetherd_device_list_remove(gpointer list, const gchar *udi) {
 }
 
 gboolean mtetherd_device_ok(const gchar *interface) {
-       if (strncmp("usb", interface, sizeof("usb")) == 0) {
+       if (g_str_has_prefix(interface, "usb")) {
+               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%s has prefix %s", interface, "usb");
                return TRUE;
        }
-       if (strncmp("bnep", interface, sizeof("bnep")) == 0) {
+       if (g_str_has_prefix(interface, "bnep")) {
+               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%s has prefix %s", interface, "bnep");
                return TRUE;
        }
+       g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "%s has unknown prefix :(", interface);
        return FALSE;
 }
 
index acfc390..e7e9ad0 100644 (file)
--- a/plugin.c
+++ b/plugin.c
 
 #define MTETHERD_STATUS_PLUGIN_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE(obj, TYPE_MTETHERD_STATUS_PLUGIN, MTetherDStatusPluginPrivate))
 
-typedef enum {
-       MTETHERD_STATUS_PLUGIN_USB_NET_UNKNOWN = 0,
-       MTETHERD_STATUS_PLUGIN_USB_NET_DISABLED,
-       MTETHERD_STATUS_PLUGIN_USB_NET_ENABLED,
-} MTetherDStatusPluginUsbNetState;
-
 struct _MTetherDStatusPluginPrivate {
        GtkWidget *enable_button;
        gpointer devices;
        gboolean usb_plugged;
-       MTetherDStatusPluginUsbNetState usbnet_state;
+       gboolean usbnet_state;
        FILE *log_fp;
        guint log_handler;
 };
@@ -65,6 +59,7 @@ struct _MTetherDStatusPluginPrivate {
 // The UDI contains the MAC address and is thus unsuitable for
 // loaded status checking, so we just use the interface name
 static const char *USBNET_INTERFACE = "usb0";
+static const char *WAN_INTERFACE = "gprs0";
 const char *MTETHERD_LOG_DOMAIN = "mtetherd";
 
 HD_DEFINE_PLUGIN_MODULE(MTetherDStatusPlugin, mtetherd_status_plugin, HD_TYPE_STATUS_MENU_ITEM);
@@ -97,17 +92,11 @@ static void mtetherd_status_plugin_class_init(MTetherDStatusPluginClass *klass)
 
 static void mtetherd_status_plugin_enable_button_set_text(MTetherDStatusPlugin *plugin) {
        if (plugin && plugin->priv && plugin->priv->enable_button) {
-               switch (plugin->priv->usbnet_state) {
-                       case MTETHERD_STATUS_PLUGIN_USB_NET_ENABLED:
-                               hildon_button_set_text(HILDON_BUTTON(plugin->priv->enable_button), "USB networking", "Enabled");
-                               break;
-                       case MTETHERD_STATUS_PLUGIN_USB_NET_DISABLED:
-                               hildon_button_set_text(HILDON_BUTTON(plugin->priv->enable_button), "USB networking", "Disabled");
-                               break;
-                       default:
-                               hildon_button_set_text(HILDON_BUTTON(plugin->priv->enable_button), "USB networking", "Unknown");
-                               break;
-                       }
+               if (plugin->priv->usbnet_state) {
+                       hildon_button_set_text(HILDON_BUTTON(plugin->priv->enable_button), "USB networking", "Enabled");
+               } else {
+                       hildon_button_set_text(HILDON_BUTTON(plugin->priv->enable_button), "USB networking", "Disabled");
+               }
        }
 }
 
@@ -116,16 +105,10 @@ static void mtetherd_status_plugin_enable_button_clicked(GtkWidget *button, gpoi
 
        if (plugin && plugin->priv && button == plugin->priv->enable_button) {
                const char *arg;
-               switch (plugin->priv->usbnet_state) {
-                       case MTETHERD_STATUS_PLUGIN_USB_NET_ENABLED:
-                               arg = SBIN_DIR "/mtetherd-usbnet-disable.sh";
-                               break;
-                       case MTETHERD_STATUS_PLUGIN_USB_NET_DISABLED:
-                               arg = SBIN_DIR "/mtetherd-usbnet-enable.sh";
-                               break;
-                       default:
-                               arg = NULL;
-                               break;
+               if (plugin->priv->usbnet_state) {
+                       arg = SBIN_DIR "/mtetherd-usbnet-disable.sh";
+               } else {
+                       arg = SBIN_DIR "/mtetherd-usbnet-enable.sh";
                }
                if (arg) {
                        g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Launching %s", arg);
@@ -195,6 +178,7 @@ static void mtetherd_status_plugin_init(MTetherDStatusPlugin *plugin) {
                        plugin->priv->log_handler = g_log_set_handler(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_MASK, mtetherd_status_plugin_log, plugin);
                }
                
+               plugin->priv->usbnet_state = FALSE;
                plugin->priv->enable_button = hildon_button_new(HILDON_SIZE_AUTO_WIDTH | HILDON_SIZE_FINGER_HEIGHT, HILDON_BUTTON_ARRANGEMENT_VERTICAL);
                if (plugin->priv->enable_button) {
                        GError *err = NULL;
@@ -235,6 +219,7 @@ static void mtetherd_status_plugin_init(MTetherDStatusPlugin *plugin) {
 
 void mtetherd_status_plugin_device_added(MTetherDStatusPlugin *plugin, MTetherDDevice *device) {
        g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "mtetherd_status_plugin_device_added(%p, %p)", plugin, device);
+       gboolean added = FALSE;
        if (plugin && plugin->priv) {
                const gchar *interface = mtetherd_device_get_interface(device);
                g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "interface=%s", interface);
@@ -243,7 +228,7 @@ void mtetherd_status_plugin_device_added(MTetherDStatusPlugin *plugin, MTetherDD
                        if (mtetherd_device_list_add(plugin->priv->devices, device)) {
                                if (g_strcmp0(USBNET_INTERFACE, interface) == 0) {
                                        g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "is USB");
-                                       plugin->priv->usbnet_state = MTETHERD_STATUS_PLUGIN_USB_NET_ENABLED;
+                                       plugin->priv->usbnet_state = TRUE;
                                        mtetherd_status_plugin_enable_button_set_text(plugin);
                                }
                                hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Starting network on %s", interface);
@@ -252,8 +237,8 @@ void mtetherd_status_plugin_device_added(MTetherDStatusPlugin *plugin, MTetherDD
                                gchar *netmask = mtetherd_device_get_netmask(device);
                                gchar *dhcp_start = mtetherd_device_get_dhcp_start(device);
                                gchar *dhcp_end = mtetherd_device_get_dhcp_end(device);
-                               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "addr=%s netmask=%s dhcp_start=%s dhcp_end=%s", addr, netmask, dhcp_start, dhcp_end);
-                               const char *command[] = { BIN_DIR "/sudo", SBIN_DIR "/mtetherd-net-setup.sh", interface, addr, netmask, dhcp_start, dhcp_end, NULL };
+                               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "interface=%s wan=%s addr=%s netmask=%s dhcp_start=%s dhcp_end=%s", interface, WAN_INTERFACE, addr, netmask, dhcp_start, dhcp_end);
+                               const char *command[] = { BIN_DIR "/sudo", SBIN_DIR "/mtetherd-net-setup.sh", interface, WAN_INTERFACE, addr, netmask, dhcp_start, dhcp_end, NULL };
                                if (!mtetherd_launch_script(command)) {
                                        g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Error launching USB networking setup script");
                                }
@@ -262,28 +247,33 @@ void mtetherd_status_plugin_device_added(MTetherDStatusPlugin *plugin, MTetherDD
                                g_free(dhcp_start);
                                g_free(dhcp_end);
                                g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "done");
+                               added = TRUE;
                        } else {
                                g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Error adding network interface to list: Maximum number of devices exceeded");
                        }
                }
        }
+       if (!added) {
+               g_object_unref(G_OBJECT(device));
+       }
 }
 
 void mtetherd_status_plugin_device_removed(MTetherDStatusPlugin *plugin, const gchar *udi) {
        g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "mtetherd_status_plugin_device_removed(%s)", udi);
        if (plugin && plugin->priv) {
                MTetherDDevice *device = mtetherd_device_list_find(plugin->priv->devices, udi);
-               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "device=%p", device);
                if (device) {
+                       g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "device=%p", device);
                        const gchar *interface = mtetherd_device_get_interface(device);
                        g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "interface=%s", interface);
                        if (g_strcmp0(USBNET_INTERFACE, interface) == 0) {
                                g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "is USB");
-                               plugin->priv->usbnet_state = MTETHERD_STATUS_PLUGIN_USB_NET_DISABLED;
+                               plugin->priv->usbnet_state = FALSE;
                                mtetherd_status_plugin_enable_button_set_text(plugin);
                        }
                        hildon_banner_show_informationf(GTK_WIDGET(plugin), NULL, "Shutting down network on %s", interface);
                        g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Launching %s", SBIN_DIR "/mtetherd-net-shutdown.sh");
+                       // TODO: Check if this is the last interface to be shut down and pass WAN_INTERFACE after interface if yes
                        const char *command[] = { BIN_DIR "/sudo", SBIN_DIR "/mtetherd-net-shutdown.sh", interface, NULL };
                        if (!mtetherd_launch_script(command)) {
                                g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Error launching USB networking shutdown script");
@@ -291,7 +281,9 @@ void mtetherd_status_plugin_device_removed(MTetherDStatusPlugin *plugin, const g
                        g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "done");
                }
                if (!mtetherd_device_list_remove(plugin->priv->devices, udi)) {
-                       g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Error removing network interface from list: Not found");
+                       g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Device %s not found in list, nothing removed", udi);
+               } else {
+                       g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Device %s removed from list", udi);
                }
        }
 }
diff --git a/util.c b/util.c
index c746bf9..544699f 100644 (file)
--- a/util.c
+++ b/util.c
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 #include <glib.h>
 #include "util.h"
 #include "plugin.h"
 
 static const char *MODULE_LIST = "/proc/modules";
+// Wait x seconds for process termination
+static const unsigned int TERMINATE_WAIT = 5;
 
 gboolean mtetherd_scan_modules(const char *module) {
-       g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, "Scanning %s", MODULE_LIST);
+       g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Scanning %s", MODULE_LIST);
 
        FILE *fp = fopen(MODULE_LIST, "r");
        if (!fp) {
@@ -38,8 +43,8 @@ gboolean mtetherd_scan_modules(const char *module) {
        char *line = NULL;
        while (!found && getline(&line, NULL, fp) != -1) {
                g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Checking if '%s' starts with %s...", line, module);
-               if (g_str_has_prefix(line, module) == 0) {
-                       g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, "Found %s", module);
+               if (g_str_has_prefix(line, module)) {
+                       g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Found %s", module);
                        found = TRUE;
                }
                free(line);
@@ -49,17 +54,64 @@ gboolean mtetherd_scan_modules(const char *module) {
        return found;
 }
 
+#ifdef LAUNCH_SYNCHRONOUS
 gboolean mtetherd_launch_script(const char *command[]) {
-       pid_t pid = fork();
-       if (pid == 0) {
-               if (execv(command[0], (char **const) command) == -1) {
-                       exit(1);
+       if (command && command[0]) {
+               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Launching %s", command[0]);
+               pid_t pid = fork();
+               if (pid == 0) {
+                       if (execv(command[0], (char **const) command) == -1) {
+                               exit(1);
+                       }
+               } else if (pid == -1) {
+                       g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Error forking: %s", g_strerror(errno));
+                       return FALSE;
+               } else {
+                       size_t i;
+                       for (i = 0; i < TERMINATE_WAIT; i++) {
+                               int status = 0;
+                               if (waitpid(pid, &status, WNOHANG) == -1) {
+                                       g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Error waiting for child process completion: %s", g_strerror(errno));
+                                       return FALSE;
+                               }
+                               if (WIFEXITED(status)) {
+                                       if (WEXITSTATUS(status) != 0) {
+                                               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Child process returned error: %d", WEXITSTATUS(status));
+                                               return FALSE;
+                                       } else {
+                                               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Child process returned ok");
+                                               return TRUE;
+                                       }
+                               } else if (WIFSIGNALED(status)) {
+                                       g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Child process killed by signal: %d", WTERMSIG(status));
+                                       return FALSE;
+                               } else {
+                                       sleep(1);
+                               }
+                       }
+                       g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Child process still running after %u seconds, ignoring", TERMINATE_WAIT);
+                       return FALSE;
                }
-       } else if (pid == -1) {
-               // error forking
-               return FALSE;
        }
-       // launch ok
-       return TRUE;
+       return FALSE;
+}
+#else
+gboolean mtetherd_launch_script(const char *command[]) {
+       if (command && command[0]) {
+               g_log(MTETHERD_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "Launching %s", command[0]);
+               pid_t pid = fork();
+               if (pid == 0) {
+                       if (execv(command[0], (char **const) command) == -1) {
+                               exit(1);
+                       }
+               } else if (pid == -1) {
+                       // error forking
+                       return FALSE;
+               }
+               // launch ok
+               return TRUE;
+       }
+       return FALSE;
 }
+#endif