From f4eb0d19c92fb621a6d096062597800cfe98dcf2 Mon Sep 17 00:00:00 2001 From: Gregor Riepl Date: Sat, 7 Aug 2010 23:55:32 +0200 Subject: [PATCH 1/1] Fixed network setup scripts 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 | 51 ++++++++++++++++------------ debian/postinst | 2 +- debian/postrm | 2 +- hal.c | 10 +++--- mtetherd-net-setup.sh | 84 +++++++++++++++++++++++++++++++++++++++++++--- mtetherd-net-shutdown.sh | 38 ++++++++++++++++++++- mtetherd.sudoers | 3 ++ net.c | 8 +++-- plugin.c | 60 ++++++++++++++------------------- util.c | 76 ++++++++++++++++++++++++++++++++++------- 10 files changed, 253 insertions(+), 81 deletions(-) diff --git a/Makefile b/Makefile index b450922..88c8112 100644 --- 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 $^ diff --git a/debian/postinst b/debian/postinst index 1f5ba8a..d766eba 100644 --- a/debian/postinst +++ b/debian/postinst @@ -20,7 +20,7 @@ set -e case "$1" in configure) - update-sudoers + update-sudoers start ;; abort-upgrade|abort-remove|abort-deconfigure) diff --git a/debian/postrm b/debian/postrm index c5232c6..50293d6 100644 --- a/debian/postrm +++ b/debian/postrm @@ -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 --- 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; } diff --git a/mtetherd-net-setup.sh b/mtetherd-net-setup.sh index 1de3181..e6b919e 100755 --- a/mtetherd-net-setup.sh +++ b/mtetherd-net-setup.sh @@ -17,9 +17,85 @@ # along with this program. If not, see . 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
" +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= 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= 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" diff --git a/mtetherd-net-shutdown.sh b/mtetherd-net-shutdown.sh index 29018d4..b2d1223 100755 --- a/mtetherd-net-shutdown.sh +++ b/mtetherd-net-shutdown.sh @@ -17,6 +17,42 @@ # along with this program. If not, see . 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 []" +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}" diff --git a/mtetherd.sudoers b/mtetherd.sudoers index 24bb3d0..45de790 100644 --- a/mtetherd.sudoers +++ b/mtetherd.sudoers @@ -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 --- 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; } diff --git a/plugin.c b/plugin.c index acfc390..e7e9ad0 100644 --- a/plugin.c +++ b/plugin.c @@ -34,17 +34,11 @@ #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 --- a/util.c +++ b/util.c @@ -21,14 +21,19 @@ #include #include #include +#include +#include +#include #include #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 -- 1.7.9.5