Fix dereference after null check
[platform/upstream/connman.git] / src / rfkill.c
old mode 100644 (file)
new mode 100755 (executable)
index 77c5b92..99b337d
@@ -2,7 +2,7 @@
  *
  *  Connection Manager
  *
- *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2007-2013  Intel Corporation. All rights reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -23,7 +23,6 @@
 #include <config.h>
 #endif
 
-#define _GNU_SOURCE
 #include <stdio.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -38,7 +37,6 @@ enum rfkill_type {
        RFKILL_TYPE_WLAN,
        RFKILL_TYPE_BLUETOOTH,
        RFKILL_TYPE_UWB,
-       RFKILL_TYPE_WIMAX,
        RFKILL_TYPE_WWAN,
        RFKILL_TYPE_GPS,
        RFKILL_TYPE_FM,
@@ -67,8 +65,6 @@ static enum connman_service_type convert_type(uint8_t type)
                return CONNMAN_SERVICE_TYPE_WIFI;
        case RFKILL_TYPE_BLUETOOTH:
                return CONNMAN_SERVICE_TYPE_BLUETOOTH;
-       case RFKILL_TYPE_WIMAX:
-               return CONNMAN_SERVICE_TYPE_WIMAX;
        case RFKILL_TYPE_WWAN:
                return CONNMAN_SERVICE_TYPE_CELLULAR;
        }
@@ -76,6 +72,7 @@ static enum connman_service_type convert_type(uint8_t type)
        return CONNMAN_SERVICE_TYPE_UNKNOWN;
 }
 
+#if !defined TIZEN_EXT
 static enum rfkill_type convert_service_type(enum connman_service_type type)
 {
        switch (type) {
@@ -83,8 +80,6 @@ static enum rfkill_type convert_service_type(enum connman_service_type type)
                return RFKILL_TYPE_WLAN;
        case CONNMAN_SERVICE_TYPE_BLUETOOTH:
                return RFKILL_TYPE_BLUETOOTH;
-       case CONNMAN_SERVICE_TYPE_WIMAX:
-               return RFKILL_TYPE_WIMAX;
        case CONNMAN_SERVICE_TYPE_CELLULAR:
                return RFKILL_TYPE_WWAN;
        case CONNMAN_SERVICE_TYPE_GPS:
@@ -93,12 +88,14 @@ static enum rfkill_type convert_service_type(enum connman_service_type type)
        case CONNMAN_SERVICE_TYPE_ETHERNET:
        case CONNMAN_SERVICE_TYPE_VPN:
        case CONNMAN_SERVICE_TYPE_GADGET:
+       case CONNMAN_SERVICE_TYPE_P2P:
        case CONNMAN_SERVICE_TYPE_UNKNOWN:
                return NUM_RFKILL_TYPES;
        }
 
        return NUM_RFKILL_TYPES;
 }
+#endif
 
 static GIOStatus rfkill_process(GIOChannel *chan)
 {
@@ -146,8 +143,7 @@ static GIOStatus rfkill_process(GIOChannel *chan)
        return status;
 }
 
-static gboolean rfkill_event(GIOChannel *chan,
-                               GIOCondition cond, gpointer data)
+static gboolean rfkill_event(GIOChannel *chan, GIOCondition cond, gpointer data)
 {
        if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
                return FALSE;
@@ -158,24 +154,31 @@ static gboolean rfkill_event(GIOChannel *chan,
        return TRUE;
 }
 
-static GIOChannel *channel = NULL;
+static guint watch = 0;
 
-int __connman_rfkill_block(enum connman_service_type type, connman_bool_t block)
+int __connman_rfkill_block(enum connman_service_type type, bool block)
 {
+#if !defined TIZEN_EXT
        uint8_t rfkill_type;
        struct rfkill_event event;
        ssize_t len;
-       int fd;
+       int fd, err = 0;
+#endif
 
        DBG("type %d block %d", type, block);
 
+#if defined TIZEN_EXT
+       DBG("try to set rfkill block %d, but it's not permitted", block);
+
+       return 0;
+#else
        rfkill_type = convert_service_type(type);
        if (rfkill_type == NUM_RFKILL_TYPES)
                return -EINVAL;
 
        fd = open("/dev/rfkill", O_RDWR | O_CLOEXEC);
        if (fd < 0)
-               return fd;
+               return -errno;
 
        memset(&event, 0, sizeof(event));
        event.op = RFKILL_OP_CHANGE_ALL;
@@ -183,22 +186,26 @@ int __connman_rfkill_block(enum connman_service_type type, connman_bool_t block)
        event.soft = block;
 
        len = write(fd, &event, sizeof(event));
-       if (len < 0)
+       if (len < 0) {
+               err = -errno;
                connman_error("Failed to change RFKILL state");
+       }
 
        close(fd);
 
-       return 0;
+       return err;
+#endif
 }
 
 int __connman_rfkill_init(void)
 {
+       GIOChannel *channel;
        GIOFlags flags;
        int fd;
 
        DBG("");
 
-       fd = open("/dev/rfkill", O_RDWR | O_CLOEXEC);
+       fd = open("/dev/rfkill", O_RDONLY | O_CLOEXEC);
        if (fd < 0) {
                connman_error("Failed to open RFKILL control device");
                return -EIO;
@@ -217,21 +224,21 @@ int __connman_rfkill_init(void)
        /* Process current RFKILL events sent on device open */
        while (rfkill_process(channel) == G_IO_STATUS_NORMAL);
 
-       g_io_add_watch(channel, G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
-                                                       rfkill_event, NULL);
+       watch = g_io_add_watch(channel,
+                               G_IO_IN | G_IO_NVAL | G_IO_HUP | G_IO_ERR,
+                               rfkill_event, NULL);
 
-       return 0;
+       g_io_channel_unref(channel);
+
+       return watch ? 0 : -EIO;
 }
 
 void __connman_rfkill_cleanup(void)
 {
        DBG("");
 
-       if (channel == NULL)
-               return;
-
-       g_io_channel_shutdown(channel, TRUE, NULL);
-       g_io_channel_unref(channel);
-
-       channel = NULL;
+       if (watch) {
+               g_source_remove(watch);
+               watch = 0;
+       }
 }