Base Code merged to SPIN 2.4 23/46223/2
authorSeonah Moon <seonah1.moon@samsung.com>
Fri, 16 Oct 2015 01:04:53 +0000 (10:04 +0900)
committerSeonah Moon <seonah1.moon@samsung.com>
Fri, 16 Oct 2015 01:05:17 +0000 (10:05 +0900)
Change-Id: Ia85d13025eed11f3f61ab58a9cd88945a1a49cab
Signed-off-by: Seonah Moon <seonah1.moon@samsung.com>
32 files changed:
CMakeLists.txt [changed mode: 0644->0755]
LICENSE.APLv2.0 [new file with mode: 0644]
LICENSE.Flora [deleted file]
NOTICE
include/mobileap.h
include/mobileap_bluetooth.h
include/mobileap_common.h [changed mode: 0644->0755]
include/mobileap_connman.h [deleted file]
include/mobileap_handler.h
include/mobileap_iptables.h [new file with mode: 0644]
include/mobileap_network.h
include/mobileap_notification.h
include/mobileap_softap.h [moved from include/mobileap_agent.h with 64% similarity, mode: 0755]
include/mobileap_usb.h
include/mobileap_wifi.h
include/tethering-dbus-interface.xml
mobileap-agent.manifest [new file with mode: 0644]
packaging/mobileap-agent.manifest [deleted file]
packaging/mobileap-agent.spec
packaging/org.tizen.tethering.service [moved from src/org.tizen.tethering.service with 100% similarity]
src/mobileap_bluetooth.c [changed mode: 0644->0755]
src/mobileap_common.c [changed mode: 0644->0755]
src/mobileap_connman.c [deleted file]
src/mobileap_handler.c
src/mobileap_iptables.c [new file with mode: 0755]
src/mobileap_main.c
src/mobileap_network.c
src/mobileap_notification.c
src/mobileap_softap.c [moved from src/mobileap_agent.c with 51% similarity, mode: 0755]
src/mobileap_usb.c [changed mode: 0644->0755]
src/mobileap_wifi.c [changed mode: 0644->0755]
tethering_dump.sh [new file with mode: 0644]

old mode 100644 (file)
new mode 100755 (executable)
index bc45e46..9505780
@@ -1,7 +1,7 @@
 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
 PROJECT(mobileap-agent C)
 
-SET(SRCS src/mobileap_agent.c
+SET(SRCS src/mobileap_softap.c
        src/mobileap_main.c
        src/mobileap_wifi.c
        src/mobileap_usb.c
@@ -10,12 +10,12 @@ SET(SRCS src/mobileap_agent.c
        src/mobileap_common.c
        src/mobileap_notification.c
        src/mobileap_network.c
-       src/mobileap_connman.c
+       src/mobileap_iptables.c
 )
 
 SET(CMAKE_INSTALL_PREFIX /usr)
 
-SET(APP_VENDOR "tizen")
+SET(APP_VENDOR "samsung")
 SET(APP_NAME mobileap-agent)
 SET(APP_DIR ${CMAKE_INSTALL_PREFIX}/bin)
 SET(INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include)
@@ -26,17 +26,18 @@ ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "")
 
 MESSAGE("Build type: ${CMAKE_BUILD_TYPE}")
 
-INCLUDE_DIRECTORIES(${INCLUDE_DIR})
+INCLUDE_DIRECTORIES(${INCLUDE_DIR} ${CMAKE_SOURCE_DIR})
 
 INCLUDE(FindPkgConfig)
-pkg_check_modules(pkgs REQUIRED dlog dbus-glib-1 gio-2.0 pmapi vconf notification libssl key-manager capi-network-connection capi-network-bluetooth ${PRIVATE_REQUIRED_PKGS})
+pkg_check_modules(pkgs REQUIRED gio-2.0 gio-unix-2.0 dbus-1 dlog  deviced vconf notification capi-network-connection capi-network-bluetooth appcore-common capi-network-wifi capi-network-wifi-direct alarm-service appsvc libssl)
+
 FOREACH(flag ${pkgs_CFLAGS})
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
 ENDFOREACH(flag)
 
-SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fpie -Wall")
-SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
-SET(CMAKE_C_FLAGS_RELEASE "-O2")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE -Wall")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g -fPIE")
+SET(CMAKE_C_FLAGS_RELEASE "-O2 -fPIE")
 
 FIND_PROGRAM(UNAME NAMES uname)
 EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH")
@@ -44,20 +45,35 @@ IF("${ARCH}" STREQUAL "arm")
        ADD_DEFINITIONS("-DTARGET")
        MESSAGE("add -DTARGET")
 ENDIF("${ARCH}" STREQUAL "arm")
-
-FIND_PROGRAM(DBUS_BINDING_TOOL NAMES dbus-binding-tool)
-EXEC_PROGRAM("${DBUS_BINDING_TOOL}" ARGS "--prefix=tethering ${INCLUDE_DIR}/tethering-dbus-interface.xml --mode=glib-server --output=${INCLUDE_DIR}/tethering-server-stub.h")
+IF(TIZEN_TV)
+       ADD_DEFINITIONS(-DTIZEN_TV)
+ENDIF(TIZEN_TV)
 
 ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"")
 ADD_DEFINITIONS("-DVENDOR=\"${APP_VENDOR}\"")
 ADD_DEFINITIONS("-DAPPNAME=\"${APP_NAME}\"")
 ADD_DEFINITIONS("-DAPP_DIR=\"${APP_DIR}\"")
 
+IF(TIZEN_WLAN_BOARD_SPRD)
+       ADD_DEFINITIONS(-DTIZEN_WLAN_BOARD_SPRD)
+ENDIF(TIZEN_WLAN_BOARD_SPRD)
+
 SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed -pie")
 
-ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS})
+ADD_CUSTOM_COMMAND(
+       WORKING_DIRECTORY
+       OUTPUT ${CMAKE_BINARY_DIR}/tethering-server-stub.c
+       COMMAND gdbus-codegen --interface-prefix org.tizen.
+                       --generate-c-code tethering-server-stub
+                       --c-generate-object-manager
+                       --generate-docbook generated-docs
+                       ${INCLUDE_DIR}/tethering-dbus-interface.xml
+                       COMMENT "Generating GDBus .c/.h")
+
+ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS} ${CMAKE_BINARY_DIR}/tethering-server-stub.c)
 TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS})
 
 INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin)
-INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/org.tizen.tethering.service DESTINATION share/dbus-1/system-services)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/packaging/org.tizen.tethering.service DESTINATION share/dbus-1/system-services)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tethering_dump.sh DESTINATION /opt/etc/dump.d/module.d/)
 
diff --git a/LICENSE.APLv2.0 b/LICENSE.APLv2.0
new file mode 100644 (file)
index 0000000..d645695
--- /dev/null
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/LICENSE.Flora b/LICENSE.Flora
deleted file mode 100644 (file)
index 571fe79..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-Flora License
-
-Version 1.1, April, 2013
-
-http://floralicense.org/license/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-"License" shall mean the terms and conditions for use, reproduction,
-and distribution as defined by Sections 1 through 9 of this document.
-
-"Licensor" shall mean the copyright owner or entity authorized by
-the copyright owner that is granting the License.
-
-"Legal Entity" shall mean the union of the acting entity and
-all other entities that control, are controlled by, or are
-under common control with that entity. For the purposes of
-this definition, "control" means (i) the power, direct or indirect,
-to cause the direction or management of such entity,
-whether by contract or otherwise, or (ii) ownership of fifty percent (50%)
-or more of the outstanding shares, or (iii) beneficial ownership of
-such entity.
-
-"You" (or "Your") shall mean an individual or Legal Entity
-exercising permissions granted by this License.
-
-"Source" form shall mean the preferred form for making modifications,
-including but not limited to software source code, documentation source,
-and configuration files.
-
-"Object" form shall mean any form resulting from mechanical
-transformation or translation of a Source form, including but
-not limited to compiled object code, generated documentation,
-and conversions to other media types.
-
-"Work" shall mean the work of authorship, whether in Source or Object form,
-made available under the License, as indicated by a copyright notice
-that is included in or attached to the work (an example is provided
-in the Appendix below).
-
-"Derivative Works" shall mean any work, whether in Source or Object form,
-that is based on (or derived from) the Work and for which the editorial
-revisions, annotations, elaborations, or other modifications represent,
-as a whole, an original work of authorship. For the purposes of this License,
-Derivative Works shall not include works that remain separable from,
-or merely link (or bind by name) to the interfaces of, the Work and
-Derivative Works thereof.
-
-"Contribution" shall mean any work of authorship, including the original
-version of the Work and any modifications or additions to that Work or
-Derivative Works thereof, that is intentionally submitted to Licensor
-for inclusion in the Work by the copyright owner or by an individual or
-Legal Entity authorized to submit on behalf of the copyright owner.
-For the purposes of this definition, "submitted" means any form of
-electronic, verbal, or written communication sent to the Licensor or
-its representatives, including but not limited to communication on
-electronic mailing lists, source code control systems, and issue
-tracking systems that are managed by, or on behalf of, the Licensor
-for the purpose of discussing and improving the Work, but excluding
-communication that is conspicuously marked or otherwise designated
-in writing by the copyright owner as "Not a Contribution."
-
-"Contributor" shall mean Licensor and any individual or Legal Entity
-on behalf of whom a Contribution has been received by Licensor and
-subsequently incorporated within the Work.
-
-"Tizen Certified Platform" shall mean a software platform that complies
-with the standards set forth in the Tizen Compliance Specification
-and passes the Tizen Compliance Tests as defined from time to time
-by the Tizen Technical Steering Group and certified by the Tizen
-Association or its designated agent.
-
-2. Grant of Copyright License.  Subject to the terms and conditions of
-this License, each Contributor hereby grants to You a perpetual,
-worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-copyright license to reproduce, prepare Derivative Works of,
-publicly display, publicly perform, sublicense, and distribute the
-Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License.  Subject to the terms and conditions of
-this License, each Contributor hereby grants to You a perpetual,
-worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-(except as stated in this section) patent license to make, have made,
-use, offer to sell, sell, import, and otherwise transfer the Work
-solely as incorporated into a Tizen Certified Platform, where such
-license applies only to those patent claims licensable by such
-Contributor that are necessarily infringed by their Contribution(s)
-alone or by combination of their Contribution(s) with the Work solely
-as incorporated into a Tizen Certified Platform to which such
-Contribution(s) was submitted. If You institute patent litigation
-against any entity (including a cross-claim or counterclaim
-in a lawsuit) alleging that the Work or a Contribution incorporated
-within the Work constitutes direct or contributory patent infringement,
-then any patent licenses granted to You under this License for that
-Work shall terminate as of the date such litigation is filed.
-
-4. Redistribution.  You may reproduce and distribute copies of the
-Work or Derivative Works thereof pursuant to the copyright license
-above, in any medium, with or without modifications, and in Source or
-Object form, provided that You meet the following conditions:
-
-  1. You must give any other recipients of the Work or Derivative Works
-     a copy of this License; and
-  2. You must cause any modified files to carry prominent notices stating
-     that You changed the files; and
-  3. You must retain, in the Source form of any Derivative Works that
-     You distribute, all copyright, patent, trademark, and attribution
-     notices from the Source form of the Work, excluding those notices
-     that do not pertain to any part of the Derivative Works; and
-  4. If the Work includes a "NOTICE" text file as part of its distribution,
-     then any Derivative Works that You distribute must include a readable
-     copy of the attribution notices contained within such NOTICE file,
-     excluding those notices that do not pertain to any part of
-     the Derivative Works, in at least one of the following places:
-     within a NOTICE text file distributed as part of the Derivative Works;
-     within the Source form or documentation, if provided along with the
-     Derivative Works; or, within a display generated by the Derivative Works,
-     if and wherever such third-party notices normally appear.
-     The contents of the NOTICE file are for informational purposes only
-     and do not modify the License. You may add Your own attribution notices 
-     within Derivative Works that You distribute, alongside or as an addendum 
-     to the NOTICE text from the Work, provided that such additional attribution 
-     notices cannot be construed as modifying the License. You may add Your own
-     copyright statement to Your modifications and may provide additional or
-     different license terms and conditions for use, reproduction, or
-     distribution of Your modifications, or for any such Derivative Works
-     as a whole, provided Your use, reproduction, and distribution of
-     the Work otherwise complies with the conditions stated in this License
-     and your own copyright statement or terms and conditions do not conflict
-     the conditions stated in the License including section 3.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
-any Contribution intentionally submitted for inclusion in the Work
-by You to the Licensor shall be under the terms and conditions of
-this License, without any additional terms or conditions.
-Notwithstanding the above, nothing herein shall supersede or modify
-the terms of any separate license agreement you may have executed
-with Licensor regarding such Contributions.
-
-6. Trademarks.  This License does not grant permission to use the trade
-names, trademarks, service marks, or product names of the Licensor,
-except as required for reasonable and customary use in describing the
-origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
-agreed to in writing, Licensor provides the Work (and each
-Contributor provides its Contributions) on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-implied, including, without limitation, any warranties or conditions
-of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-PARTICULAR PURPOSE. You are solely responsible for determining the
-appropriateness of using or redistributing the Work and assume any
-risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
-whether in tort (including negligence), contract, or otherwise,
-unless required by applicable law (such as deliberate and grossly
-negligent acts) or agreed to in writing, shall any Contributor be
-liable to You for damages, including any direct, indirect, special,
-incidental, or consequential damages of any character arising as a
-result of this License or out of the use or inability to use the
-Work (including but not limited to damages for loss of goodwill,
-work stoppage, computer failure or malfunction, or any and all
-other commercial damages or losses), even if such Contributor
-has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
-the Work or Derivative Works thereof, You may choose to offer,
-and charge a fee for, acceptance of support, warranty, indemnity,
-or other liability obligations and/or rights consistent with this
-License. However, in accepting such obligations, You may act only
-on Your own behalf and on Your sole responsibility, not on behalf
-of any other Contributor, and only if You agree to indemnify,
-defend, and hold each Contributor harmless for any liability
-incurred by, or claims asserted against, such Contributor by reason
-of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Flora License to your work
-
-To apply the Flora License to your work, attach the following
-boilerplate notice, with the fields enclosed by brackets "[]"
-replaced with your own identifying information. (Don't include
-the brackets!) The text should be enclosed in the appropriate
-comment syntax for the file format. We also recommend that a
-file or class name and description of purpose be included on the
-same "printed page" as the copyright notice for easier
-identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Flora License, Version 1.1 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://floralicense.org/license/
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
diff --git a/NOTICE b/NOTICE
index 94d56df..ccdad52 100644 (file)
--- a/NOTICE
+++ b/NOTICE
@@ -1,3 +1,3 @@
-Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
-Except as noted, this software is licensed under Flora License, Version 1.1
-Please, see the LICENSE.Flora file for Flora License, Version 1.1 terms and conditions.
+Copyright (c) Samsung Electronics Co., Ltd. All rights reserved.
+Except as noted, this software is licensed under Apache License, Version 2.
+Please, see the LICENSE file for Apache License terms and conditions.
index b4bb70d..095040b 100644 (file)
@@ -1,20 +1,18 @@
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
 #ifndef __MOBILEAP_INTERNAL_H__
 extern "C" {
 #endif
 
-/* Client / Agent common */
-#define DBUS_STRUCT_UINT_STRING (dbus_g_type_get_struct ("GValueArray", \
-                       G_TYPE_UINT, G_TYPE_STRING, G_TYPE_INVALID))
-
-#define DBUS_STRUCT_STATIONS (dbus_g_type_get_struct ("GValueArray", \
-                       G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, \
-                       G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INVALID))
-
-#define DBUS_STRUCT_STATION (dbus_g_type_get_struct ("GValueArray", \
-                       G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, \
-                       G_TYPE_INVALID))
-
-#define DBUS_STRUCT_INTERFACE (dbus_g_type_get_struct ("GValueArray", \
-                       G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, \
-                       G_TYPE_STRING, G_TYPE_INVALID))
-
-
 #define TETHERING_SERVICE_OBJECT_PATH  "/Tethering"
 #define TETHERING_SERVICE_NAME         "org.tizen.tethering"
 #define TETHERING_SERVICE_INTERFACE    "org.tizen.tethering"
@@ -54,14 +35,15 @@ extern "C" {
 #define SIGNAL_NAME_USB_TETHER_OFF     "usb_off"
 #define SIGNAL_NAME_BT_TETHER_ON       "bluetooth_on"
 #define SIGNAL_NAME_BT_TETHER_OFF      "bluetooth_off"
+#define SIGNAL_NAME_WIFI_AP_ON         "wifi_ap_on"
+#define SIGNAL_NAME_WIFI_AP_OFF                "wifi_ap_off"
 #define SIGNAL_NAME_NO_DATA_TIMEOUT    "no_data_timeout"
 #define SIGNAL_NAME_LOW_BATTERY_MODE   "low_batt_mode"
 #define SIGNAL_NAME_FLIGHT_MODE                "flight_mode"
-#define SIGNAL_NAME_DHCP_STATUS                "dhcp_status"
 #define SIGNAL_NAME_SECURITY_TYPE_CHANGED      "security_type_changed"
 #define SIGNAL_NAME_SSID_VISIBILITY_CHANGED    "ssid_visibility_changed"
 #define SIGNAL_NAME_PASSPHRASE_CHANGED         "passphrase_changed"
-
+#define SIGNAL_NAME_DHCP_STATUS                "dhcp_status"
 #define SIGNAL_MSG_NOT_AVAIL_INTERFACE "Interface is not available"
 #define SIGNAL_MSG_TIMEOUT             "There is no connection for a while"
 #define SIGNAL_MSG_SSID_VISIBLE                "ssid_visible"
@@ -80,6 +62,8 @@ typedef enum {
        E_SIGNAL_USB_TETHER_OFF,
        E_SIGNAL_BT_TETHER_ON,
        E_SIGNAL_BT_TETHER_OFF,
+       E_SIGNAL_WIFI_AP_ON,
+       E_SIGNAL_WIFI_AP_OFF,
        E_SIGNAL_NO_DATA_TIMEOUT,
        E_SIGNAL_LOW_BATTERY_MODE,
        E_SIGNAL_FLIGHT_MODE,
@@ -94,22 +78,22 @@ typedef enum {
 */
 #define MOBILE_AP_WIFI_CHANNEL         6       /**< Channel number */
 #define MOBILE_AP_WIFI_BSSID_LEN       6       /**< BSSID Length */
-#define MOBILE_AP_WIFI_SSID_MAX_LEN    31      /**< Maximum length of ssid */
+#define MOBILE_AP_WIFI_SSID_MAX_LEN    32      /**< Maximum length of ssid */
 #define MOBILE_AP_WIFI_KEY_MIN_LEN     8       /**< Minimum length of wifi key */
-#define MOBILE_AP_WIFI_KEY_MAX_LEN     63      /**< Maximum length of wifi key */
+#define MOBILE_AP_WIFI_PLAIN_TEXT_KEY_MAX_LEN  63      /**< Maximum length of wifi plain text key */
+#define MOBILE_AP_WIFI_KEY_MAX_LEN     64      /**< Maximum length of wifi hash key */
 
 /**
 * Common configuration
 */
-#define MOBILE_AP_MAX_WIFI_STA         8
-#define MOBILE_AP_MAX_BT_STA           7
-#define MOBILE_AP_MAX_USB_STA          1
-#define MOBILE_AP_MAX_CONNECTED_STA    16      /**< Maximum connected station. 8(Wi-Fi) + 7(BT) + 1(USB) */
+#define MOBILE_AP_MAX_WIFI_STA         10      /**< Firmware limitation (BCM4339) */
+#define MOBILE_AP_MAX_BT_STA           4       /**< Bluetooth specification (1 Master and 4 Slaves) */
+#define MOBILE_AP_MAX_USB_STA          1       /**< Only one usb connection is possible */
+#define MOBILE_AP_MAX_CONNECTED_STA    15      /**< Maximum connected station. 10(Wi-Fi) + 4(BT) + 1(USB) */
 
 #define MOBILE_AP_STR_INFO_LEN         20      /**< length of the ip or mac address*/
-#define MOBILE_AP_STR_HOSTNAME_LEN     32      /**< length of the hostname */
+#define MOBILE_AP_STR_HOSTNAME_LEN     33      /**< length of the hostname */
 #define MOBILE_AP_NAME_UNKNOWN         "UNKNOWN"
-
 /**
 * Mobile AP error code
 */
@@ -125,6 +109,7 @@ typedef enum {
        MOBILE_AP_ERROR_DHCP,                   /**< DHCP error */
        MOBILE_AP_ERROR_IN_PROGRESS,            /**< Request is in progress */
        MOBILE_AP_ERROR_NOT_PERMITTED,          /**< Operation is not permitted */
+       MOBILE_AP_ERROR_PERMISSION_DENIED,      /**< Permission Denied */
 
        MOBILE_AP_ERROR_MAX
 } mobile_ap_error_code_e;
@@ -146,6 +131,9 @@ typedef enum {
        MOBILE_AP_ENABLE_BT_TETHERING_CFM,      /* mobile_ap_enable_bt_tethering() */
        MOBILE_AP_DISABLE_BT_TETHERING_CFM,     /* mobile_ap_disable_bt_tethering() */
 
+       MOBILE_AP_ENABLE_WIFI_AP_CFM,           /* mobile_ap_enable_wifi_ap() */
+       MOBILE_AP_DISABLE_WIFI_AP_CFM,          /* mobile_ap_disable_wifi_ap() */
+
        MOBILE_AP_GET_STATION_INFO_CFM,         /* mobile_ap_get_station_info() */
        MOBILE_AP_GET_DATA_PACKET_USAGE_CFM,    /* mobile_ap_get_data_packet_usage() */
 
@@ -160,6 +148,9 @@ typedef enum {
        MOBILE_AP_ENABLED_BT_TETHERING_IND,     /* Turning on BT tethering indication */
        MOBILE_AP_DISABLED_BT_TETHERING_IND,    /* Turning off BT tethering indication */
 
+       MOBILE_AP_ENABLED_WIFI_AP_IND,          /* Turning on WiFi AP indication */
+       MOBILE_AP_DISABLED_WIFI_AP_IND,         /* Turning off WiFi AP indication */
+
        MOBILE_AP_STATION_CONNECT_IND,          /* Station connection indication */
        MOBILE_AP_STATION_DISCONNECT_IND,       /* Station disconnection indication */
        MOBILE_AP_USB_STATION_CONNECT_IND,
@@ -171,6 +162,7 @@ typedef enum {
        MOBILE_AP_TYPE_WIFI,
        MOBILE_AP_TYPE_USB,
        MOBILE_AP_TYPE_BT,
+       MOBILE_AP_TYPE_WIFI_AP,
        MOBILE_AP_TYPE_MAX,
 } mobile_ap_type_e;
 
@@ -183,7 +175,7 @@ typedef struct {
        mobile_ap_type_e interface;                     /**< interface type */
        char ip[MOBILE_AP_STR_INFO_LEN];                /**< assigned IP address */
        char mac[MOBILE_AP_STR_INFO_LEN];               /**< MAC Address */
-       char hostname[MOBILE_AP_STR_HOSTNAME_LEN];      /**< alphanumeric name */
+       char *hostname;
        time_t tm;      /**< connection time*/
 } mobile_ap_station_info_t;
 
index 44cfe8c..168b2dd 100644 (file)
@@ -1,33 +1,35 @@
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
 #ifndef __MOBILEAP_BLUETOOTH_H__
 #define __MOBILEAP_BLUETOOTH_H__
 
-#include "mobileap_agent.h"
+#include "mobileap_softap.h"
+
+#define PS_RECHECK_INTERVAL 500
+#define PS_RECHECK_COUNT_MAX 5
 
-void _bt_get_remote_device_name(TetheringObject *obj, const char *mac, char **name);
-mobile_ap_error_code_e _disable_bt_tethering(TetheringObject *obj);
+void _bt_get_remote_device_name(const char *mac, char **name);
+mobile_ap_error_code_e _disable_bt_tethering(Tethering *obj);
+gboolean _is_trying_bt_operation(void);
 
-gboolean tethering_enable_bt_tethering(TetheringObject *obj,
-               DBusGMethodInvocation *context);
-gboolean tethering_disable_bt_tethering(TetheringObject *obj,
-               DBusGMethodInvocation *context);
+gboolean tethering_enable_bt_tethering(Tethering *obj,
+               GDBusMethodInvocation *context);
+gboolean tethering_disable_bt_tethering(Tethering *obj,
+               GDBusMethodInvocation *context);
 
 #endif /* __MOBILEAP_BLUETOOTH_H__ */
old mode 100644 (file)
new mode 100755 (executable)
index b2a42ac..475ed7f
@@ -1,39 +1,33 @@
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
 #ifndef __MOBILEAP_COMMON_H__
 #define __MOBILEAP_COMMON_H__
 
 #include <glib.h>
+#include <gio/gio.h>
 
-#include "mobileap_agent.h"
-
-/* Need translation */
-#define MH_NOTI_STR    "Connected device (%d)"
-#define MH_NOTI_TITLE  "Tethering"
+#include "mobileap_softap.h"
+#include <tethering-server-stub.h>
 
 gint _slist_find_station_by_interface(gconstpointer a, gconstpointer b);
 gint _slist_find_station_by_mac(gconstpointer a, gconstpointer b);
 gint _slist_find_station_by_ip_addr(gconstpointer a, gconstpointer b);
 
-void _emit_mobileap_dbus_signal(TetheringObject *obj,
-               mobile_ap_sig_e num, const gchar *message);
 void _send_dbus_station_info(const char *member,
                mobile_ap_station_info_t *info);
 void _update_station_count(int count);
@@ -43,11 +37,13 @@ int _remove_station_info_all(mobile_ap_type_e type);
 int _get_station_info(gconstpointer data, GCompareFunc func,
                mobile_ap_station_info_t **si);
 int _get_station_count(gconstpointer data, GCompareFunc func, int *count);
-int _station_info_foreach(GFunc func, void *user_data);
-int _add_data_usage_rule(const char *src, const char *dest);
-int _del_data_usage_rule(const char *src, const char *dest);
-int _get_data_usage(const char *src, const char *dest, unsigned long long *tx, unsigned long long *rx);
+GVariant *_station_info_foreach(void);
+int _add_interface_routing(const char *interface, const in_addr_t gateway);
+int _del_interface_routing(const char *interface, const in_addr_t gateway);
+int _add_routing_rule(const char *interface);
+int _del_routing_rule(const char *interface);
+int _flush_ip_address(const char *interface);
 int _execute_command(const char *cmd);
 int _get_tethering_type_from_ip(const char *ip, mobile_ap_type_e *type);
-
+Tethering *_get_tethering_obj(void);
 #endif /* __MOBILEAP_COMMON_H__ */
diff --git a/include/mobileap_connman.h b/include/mobileap_connman.h
deleted file mode 100644 (file)
index 2cebdc3..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * mobileap-agent
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * Contact: Hocheol Seo <hocheol.seo@samsung.com>,
- *          Injun Yang <injun.yang@samsung.com>,
- *          Seungyoun Ju <sy39.ju@samsung.com>
- *
- * Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
- *
- * Contact: Guoqiang Liu <guoqiangx.liu@intel.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#ifndef __MOBILEAP_CONNMAN_H__
-#define __MOBILEAP_CONNMAN_H__
-
-#include "mobileap_agent.h"
-
-enum technology_type {
-       TECH_TYPE_WIFI,
-       TECH_TYPE_BLUETOOTH,
-       TECH_TYPE_USB,
-       TECH_TYPE_MAX,
-};
-
-#define CONNMAN_MANAGER_PATH           "/"
-#define CONNMAN_SERVICE                        "net.connman"
-#define CONNMAN_TECHNOLOGY_INTERFACE   "net.connman.Technology"
-#define CONNMAN_MANAGER_INTERFACE      "net.connman.Manager"
-
-int connman_enable_tethering(enum technology_type type, const char *ssid,
-                       const char *security, const char *key, int hide_mode);
-int connman_disable_tethering(enum technology_type type);
-#endif
index b2ff6f7..f221dce 100644 (file)
@@ -1,32 +1,38 @@
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
 #ifndef __MOBILEAP_HANDLER_H__
 #define __MOBILEAP_HANDLER_H__
 
+#include <time.h>
+#include <alarm.h>
+
+typedef struct {
+       void *obj;
+       unsigned int state;
+} changed_state_t;
+
 void _register_vconf_cb(void *user_data);
-void _unregister_vconf_cb(void *user_data);
+void _unregister_vconf_cb(void);
 
+int _sp_timeout_handler(alarm_id_t alarm_id, void *user_param);
 void _init_timeout_cb(mobile_ap_type_e type, void *user_data);
-void _start_timeout_cb(mobile_ap_type_e type);
+void _start_timeout_cb(mobile_ap_type_e type, time_t end_time);
 void _stop_timeout_cb(mobile_ap_type_e type);
 void _deinit_timeout_cb(mobile_ap_type_e type);
 
-
 #endif
diff --git a/include/mobileap_iptables.h b/include/mobileap_iptables.h
new file mode 100644 (file)
index 0000000..520764b
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MOBILEAP_IPTABLES_H__
+#define __MOBILEAP_IPTABLES_H__
+
+#define IPTABLES               "/usr/sbin/iptables"
+#define TABLE_FILTER           "filter"
+#define TABLE_NAT              "nat"
+#define TABLE_MANGLE           "mangle"
+#define CHAIN_FW               "FORWARD"
+#define CHAIN_POST             "POSTROUTING"
+#define CHAIN_PRE              "PREROUTING"
+#define TETH_FILTER_FW         "teth_filter_fw"
+#define TETH_NAT_POST          "teth_nat_post"
+#define TETH_NAT_PRE           "teth_nat_pre"
+#define STATE_RELATED_ESTAB    "RELATED,ESTABLISHED"
+#define STATE_INVALID          "INVALID"
+#define ACTION_DROP            "DROP"
+#define ACTION_RETURN          "RETURN"
+
+typedef enum {
+       PKT_REDIRECTION_RULE,
+       FORWARD_RULE_WITH_ACTION,
+       FORWARD_RULE_WITH_ACTION_AND_STATE,
+       DEFAULT_RULE,
+       PORT_FW_RULE,
+       MASQ_RULE,
+       CLAMP_MSS_RULE,
+} iptables_rule_e;
+
+int _iptables_create_chain(const char *table_name, const char *chain_name);
+int _iptables_flush_rules(const char *table_name, const char *chain_name);
+int _iptables_delete_chain(const char *table_name, const char *chain_name);
+int _iptables_add_rule(iptables_rule_e rule_type, const char *table,
+       const char *chain, ...);
+int _iptables_delete_rule(iptables_rule_e rule_type, const char *table,
+       const char *chain, ...);
+int _get_data_usage(const char *src, const char *dest, unsigned long long *tx,
+       unsigned long long *rx);
+#endif
index 3b56dc4..18f1dbf 100644 (file)
@@ -1,20 +1,18 @@
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
 #ifndef __MOBILEAP_NETWORK_H__
 
 #include <glib.h>
 
+#define TETHERING_NET_OPEN_RETRY_INTERVAL      2000    /* 2 secs */
+
 gboolean _get_network_interface_name(char **if_name);
+gboolean _get_network_gateway_address(char **ip);
 gboolean _is_trying_network_operation(void);
 gboolean _set_masquerade(void);
 gboolean _unset_masquerade(void);
-gboolean _open_network(void);
-gboolean _close_network(void);
+gboolean _add_default_router(void);
+gboolean _del_default_router(void);
+void _add_port_forward_rule(void);
+void _del_port_forward_rule(void);
+int _open_network(void);
+void _close_network(void);
 gboolean _init_network(void *user_data);
 gboolean _deinit_network(void);
 
index 6a7ee31..6b38ef6 100644 (file)
@@ -1,36 +1,56 @@
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
 #ifndef __MOBILEAP_NOTIFICATION_H__
 #define __MOBILEAP_NOTIFICATION_H__
 
+#include <appcore-common.h>
 #include <notification.h>
 
-#define MH_NOTI_STR_MAX                50
-#define MH_NOTI_ICON_PATH      "/usr/apps/org.tizen.tethering/res/images/Q02_Notification_MobileAP.png"
+#define MH_NOTI_STR_MAX                        50
+#define MH_NOTI_PATH_MAX               256
+
+#define MH_NOTI_ICON_PATH              "/usr/ug/res/images/ug-setting-mobileap-efl"
+#define MH_NOTI_ICON_BT                        MH_NOTI_ICON_PATH"/noti_tethering_bluetooth.png"
+#define MH_NOTI_ICON_GENERAL           MH_NOTI_ICON_PATH"/noti_tethering_general.png"
+#define MH_NOTI_ICON_USB               MH_NOTI_ICON_PATH"/noti_tethering_usb.png"
+#define MH_NOTI_ICON_WIFI              MH_NOTI_ICON_PATH"/noti_tethering_wifi_num.png"
+#define MH_NOTI_ICON_WIFI_PD           MH_NOTI_ICON_PATH"/noti_tethering_wifi_num_%02d.png"
+
+#define MOBILEAP_LOCALE_COMMON_PKG     "ug-setting-mobileap-efl"
+#define MOBILEAP_LOCALE_COMMON_RES     "/usr/ug/res/locale"
+
+#ifdef _
+#undef _
+#endif
+#define _(str)                         dgettext(MOBILEAP_LOCALE_COMMON_PKG, str)
+
+#define MH_STR_TETHERING                       "IDS_MOBILEAP_BODY_TETHERING"
+#define MH_STR_CONNECTED_DEV           "IDS_MOBILEAP_POP_CONNECTED_DEVICES_C_PD"
+#define MH_STR_CONNECTION_TIMEOUT              "IDS_ST_BODY_CONNECTION_TIMEOUT"
+#define MH_STR_CONFIGURE_TETHERING     "IDS_MOBILEAP_BODY_TAP_TO_CONFIGURE_TETHERING"
+#define MH_STR_TETHERING_ACTIVE        _("IDS_MOBILEAP_BODY_TETHERING_ACTIVE_ABB")
+#define MH_STR_BT_VISIBILITY   _("IDS_ST_BODY_BLUETOOTH_VISIBILITY_HAS_TIMED_OUT_YOUR_DEVICE_MIGHT_NOT_BE_FOUND")
 
-int _create_timeout_noti(const char *content, const char *title,
-               const char *icon_path);
+int _create_timeout_noti(const char *icon_path);
 int _delete_timeout_noti(void);
-int _create_connected_noti(const char *content, const char *title,
-               const char *icon_path);
-int _update_connected_noti(const char *content);
+int _create_connected_noti(int count, const char *icon_path);
+int _update_connected_noti(int count, const char *icon_path);
 int _delete_connected_noti(void);
-int _create_status_noti(const char *content);
+void _create_tethering_active_noti(void);
+void _create_bt_tethering_active_noti(void);
 #endif
old mode 100644 (file)
new mode 100755 (executable)
similarity index 64%
rename from include/mobileap_agent.h
rename to include/mobileap_softap.h
index 0354c83..f507323
@@ -1,39 +1,41 @@
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
-#ifndef __MOBILEAP_AGENT_H__
-#define __MOBILEAP_AGENT_H__
+#ifndef __MOBILEAP_SOFTAP_H__
+#define __MOBILEAP_SOFTAP_H__
 
+#include <glib.h>
+#include <glib-object.h>
 #include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
 #include <dlog.h>
 #include <vconf.h>
 #include <netinet/in.h>
 
 #include "mobileap.h"
 
-#define MH_MID "mh_agent"
-#define DBG(fmt, args...) LOG(LOG_DEBUG, MH_MID, "[%s()][Ln:%d] "fmt, \
-                                       __func__, __LINE__, ##args)
-#define ERR(fmt, args...) LOG(LOG_ERROR, MH_MID, "[%s()][Ln:%d] "fmt, \
-                                               __func__, __LINE__, ##args)
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG                "MOBILEAP_AGENT"
+
+#define DBG(fmt, args...)      LOGD(fmt, ##args)
+#define ERR(fmt, args...)      LOGE(fmt, ##args)
+#define SDBG(fmt, args...)     SECURE_LOGD(fmt, ##args)
+#define SERR(fmt, args...)     SECURE_LOGE(fmt, ##args)
 
 #define DRIVER_DELAY           250000  /* micro seconds */
 
 #define IP_SUBNET_MASK         "255.255.255.0"
 
 #define WIFI_IF                        "wlan0"
-#define IP_ADDRESS_WIFI                0xC0A83D02      /* 192.168.61.2 */
+#define IP_ADDRESS_WIFI                0xC0A82B02      /* 192.168.43.2 */
 
 #define SOFTAP_IF              "wl0.1"
-#define IP_ADDRESS_SOFTAP      0xC0A83D01      /* 192.168.61.1 */
+#define IP_ADDRESS_SOFTAP      0xC0A82B01      /* 192.168.43.1 */
 
 #define USB_IF                 "usb0"
 #define IP_ADDRESS_USB         0xC0A88103      /* 192.168.129.3 */
 
-#define TETHER_IF              "tether"
-
 #define BT_IF_PREFIX           "bnep"
 #define BT_IF_ALL              BT_IF_PREFIX"+"
 #define IP_ADDRESS_BT_1                0xC0A88201      /* 192.168.130.1 */
@@ -71,7 +71,8 @@
 #define MAX_BUF_SIZE           (256u)
 
 #define DNSMASQ_CONF_LEN       1024
-#define DNSMASQ_CONF   "dhcp-range=192.168.61.3,192.168.61.150,255.255.255.0\n" \
+#define DNSMASQ_CONF   \
+                       "dhcp-range=192.168.43.3,192.168.43.254,255.255.255.0\n" \
                        "dhcp-range=192.168.130.2,192.168.130.150,255.255.255.0\n" \
                        "dhcp-range=192.168.131.2,192.168.131.150,255.255.255.0\n" \
                        "dhcp-range=192.168.132.2,192.168.132.150,255.255.255.0\n" \
@@ -82,6 +83,8 @@
                        "dhcp-range=192.168.137.2,192.168.137.150,255.255.255.0\n" \
                        "dhcp-range=set:blue,192.168.129.4,192.168.129.150,255.255.255.0\n"\
                        "enable-dbus\n" \
+                       "group=app\n" \
+                       "user=app\n" \
                        "dhcp-option=tag:blue,option:router,192.168.129.3\n"
 #define DNSMASQ_CONF_FILE      "/tmp/dnsmasq.conf"
 
 #define HOSTAPD_CONF_FILE      "/opt/var/lib/misc/hostapd.conf"
 #define HOSTAPD_CTRL_INTF_DIR  "/opt/var/lib/misc/hostapd"
 #define HOSTAPD_CONF_LEN       1024
+#ifndef TIZEN_WLAN_BOARD_SPRD
 #define HOSTAPD_CONF           "interface=%s\n" \
                                "driver=nl80211\n" \
                                "ctrl_interface=%s\n" \
                                "ssid=%s\n" \
                                "channel=%d\n" \
                                "ignore_broadcast_ssid=%d\n" \
+                               "hw_mode=g\n" \
+                               "max_num_sta=%d\n" \
+                               "ieee80211n=1\n"
+#else
+#define HOSTAPD_CONF           "interface=%s\n" \
+                               "driver=nl80211\n" \
+                               "ctrl_interface=%s\n" \
+                               "ssid=%s\n" \
+                               "channel=%d\n" \
+                               "ignore_broadcast_ssid=%d\n" \
+                               "hw_mode=g\n" \
                                "max_num_sta=%d\n" \
                                "ieee80211n=1\n" \
-                               "%s\n"
-#define HOSTAPD_DEBUG_FILE     "/tmp/hostapd.log"
+                               "wowlan_triggers=any\n"
+#endif
+
+#define HOSTAPD_DEBUG_FILE     "/var/log/hostapd.log"
 #define HOSTAPD_REQ_MAX_LEN    128
 #define HOSTAPD_RETRY_MAX      5
 #define HOSTAPD_RETRY_DELAY    500000  /* us */
 #define HOSTAPD_STA_DISCONN    "AP-STA-DISCONNECTED "  /* from wpa_ctrl.h */
+#define HOSTAPD_STA_CONN       "AP-STA-CONNECTED "
+#define HOSTAPD_STA_DISCONN_LEN 20
+#define HOSTAPD_STA_CONN_LEN   17
 #define HOSTAPD_MONITOR_ATTACH "ATTACH"
 #define HOSTAPD_MONITOR_DETACH "DETACH"
-/* End of hostapd configuration */
+#define HOSTAPD_DHCP_MAX_INTERVAL 30000 /* 30 seconds */
 
-#define WLAN_SCRIPT    "/usr/bin/wlan.sh"
+/* Samsung VSIE value in beacon / probe response.
+ * Wi-Fi station can identify AP whether it is tethering or AP only using this value.
+ */
+#define HOSTAPD_VENDOR_ELEMENTS_TETH   "DD050016328000"        /* Samsung tethering device */
+#define HOSTAPD_VENDOR_ELEMENTS_WIFI_AP        "DD050016321000"        /* Specific application mode AP (e.g. GroupPlay) */
+/* End of hostapd configuration */
 
 #define IP_FORWARD     "/proc/sys/net/ipv4/ip_forward"
-#define IPTABLES       "/usr/sbin/iptables"
+#define IP_CMD         "/usr/sbin/ip"
 #define GREP           "/bin/grep"
 #define AWK            "/usr/bin/awk"
 #define DATA_USAGE_FILE        "/tmp/tethering_data_usage.txt"
-#define MASQUERADE_RULE                "-o %s -j MASQUERADE"
+
+#define TETHERING_ROUTING_TABLE        252
+#define SRC_ROUTING_RULE       "iif %s lookup %d"
+#define DEFAULT_ROUTER         "default via %s dev %s scope global table %d"
+#define INTERFACE_ROUTING      "%s/24 table %d dev %s"
 #define DNS_ORDER              1
 #define TCP_DNS_FORWARD_RULE   "-i %s -p tcp --dport 53 -j DNAT --to %s:53"
 #define UDP_DNS_FORWARD_RULE   "-i %s -p udp --dport 53 -j DNAT --to %s:53"
-#define FORWARD_RULE           "-i %s -o %s"
 
 #define MOBILE_AP_STATE_NONE   0
 #define MOBILE_AP_STATE_WIFI   1
 #define MOBILE_AP_STATE_USB    2
 #define MOBILE_AP_STATE_BT     4
-#define MOBILE_AP_STATE_ALL    7
+#define MOBILE_AP_STATE_WIFI_AP        8
+#define MOBILE_AP_STATE_ALL    15
 
 #define DNSMASQ_DBUS_INTERFACE "uk.org.thekelleys.dnsmasq"
-#define CONNMAN_DBUS_INTERFACE "net.connman.Technology"
 
 #define PROC_NET_DEV                   "/proc/net/dev"
-#define TETHERING_CONN_TIMEOUT         (1200000)       /* 20 Mins */
+#define TETHERING_CONN_TIMEOUT         (1200)  /* 20 Mins */
+#define WIFI_AP_CONN_TIMEOUT           (300)   /* 5 Mins */
 #define CHECK_NET_STATE_RETRY_COUNT    5
 #define PSK_ITERATION_COUNT            4096
 
 typedef struct {
-       /* The parent class object state. */
-       GObject parent;
-
-       /* instance member */
-       DBusGMethodInvocation *bt_context;
-       DBusGMethodInvocation *usb_context;
-       guint source_id;
-       GSList *bt_device;
-
-       int init_count;
        int hide_mode;
-       int transfer_check_count;
-       unsigned long long rx_bytes;
-       unsigned long long tx_bytes;
 
        char ssid[MOBILE_AP_WIFI_SSID_MAX_LEN + 1];
+       /* in AP case, hex key will be passed from library, so one extra byte is needed */
        char key[MOBILE_AP_WIFI_KEY_MAX_LEN + 1];
        char security_type[SECURITY_TYPE_LEN];
-} TetheringObject;
-
-typedef struct {
-       /* The parent class state. */
-       GObjectClass parent;
-
-       /* class member */
-       guint signals[E_SIGNAL_MAX];
-} TetheringObjectClass;
+} softap_settings_t;
 
 typedef struct {
        unsigned int number;    /* Number of connected device */
@@ -180,16 +189,20 @@ typedef struct {
        int *value;
 } vconf_reg_t;
 
-
 typedef enum {
        MOBILE_AP_DRV_INTERFACE_NONE,
        MOBILE_AP_WEXT,
        MOBILE_AP_NL80211,
 } mobile_ap_drv_interface_e;
 
+typedef struct {
+       guint tid;
+       char *mac_addr;
+} sta_timer_t;
+
 /* ssid : 32  key : 64 */
-int _mh_core_enable_softap(const char *ssid, const char *security,
-               const char *key, int hide_mode);
+int _mh_core_enable_softap(const mobile_ap_type_e type, const char *ssid,
+               const char *security, const char *key, int hide_mode);
 int _mh_core_disable_softap(void);
 int _mh_core_get_device_info(softap_device_info_t *di);
 int _mh_core_execute_dhcp_server(void);
@@ -198,16 +211,23 @@ int _mh_core_enable_masquerade(const char *ext_if);
 int _mh_core_disable_masquerade(const char *ext_if);
 void _mh_core_add_data_to_array(GPtrArray *array, guint type, gchar *dev_name);
 int _mh_core_set_ip_address(const char *if_name, const in_addr_t ip);
+void _register_wifi_station_handler(void);
+void _unregister_wifi_station_handler(void);
 
 
-gboolean _init_tethering(TetheringObject *obj);
-gboolean _deinit_tethering(TetheringObject *obj);
+void _block_device_sleep(void);
+void _unblock_device_sleep(void);
+int _init_tethering(void);
+gboolean _deinit_tethering(void);
 gboolean _mobileap_clear_state(int state);
+gboolean _terminate_mobileap_agent(gpointer user_data);
 
 
 gboolean _mobileap_is_disabled(void);
 gboolean _mobileap_is_enabled(int state);
 gboolean _mobileap_is_enabled_by_type(mobile_ap_type_e type);
 gboolean _mobileap_set_state(int state);
+void _flush_dhcp_ack_timer(void);
+void _destroy_dhcp_ack_timer(char *mac_addr);
 
 #endif
index 14c1a37..500bd82 100644 (file)
@@ -1,36 +1,30 @@
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
 #ifndef __MOBILEAP_USB_H__
 #define __MOBILEAP_USB_H__
 
-#include "mobileap_agent.h"
-
+#include "mobileap_softap.h"
 
-mobile_ap_error_code_e _disable_usb_tethering(TetheringObject *obj);
+mobile_ap_error_code_e _disable_usb_tethering(Tethering *obj);
+gboolean _is_trying_usb_operation(void);
 
-gboolean tethering_enable_usb_tethering(TetheringObject *obj,
-                                               DBusGMethodInvocation *context);
-gboolean tethering_disable_usb_tethering(TetheringObject *obj,
-                                               DBusGMethodInvocation *context);
-gboolean tethering_get_usb_station_info(TetheringObject *obj,
-                                               DBusGMethodInvocation *context);
-gboolean tethering_get_usb_interface_info(TetheringObject *obj,
-                                               DBusGMethodInvocation *context);
+gboolean tethering_enable_usb_tethering(Tethering *obj,
+                                               GDBusMethodInvocation *context);
+gboolean tethering_disable_usb_tethering(Tethering *obj,
+                                               GDBusMethodInvocation *context);
 #endif /* __MOBILEAP_USB_H__ */
index 01f3147..07534a0 100644 (file)
@@ -1,66 +1,78 @@
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
 #ifndef __MOBILEAP_WIFI_H__
 #define __MOBILEAP_WIFI_H__
 
-#include "mobileap_agent.h"
+#include "mobileap_softap.h"
 
+#define VCONFKEY_MOBILE_HOTSPOT_SSID           "memory/private/mobileap-agent/ssid"
 #define SOFTAP_SECURITY_TYPE_OPEN_STR          "open"
 #define SOFTAP_SECURITY_TYPE_WPA2_PSK_STR      "wpa2-psk"
 #define SOFTAP_PASSPHRASE_PATH                 "wifi_tethering.txt"
+#define SOFTAP_PASSPHRASE_GROUP_ID             "secure-storage::tethering"
 
 typedef enum {
        SOFTAP_SECURITY_TYPE_OPEN,
        SOFTAP_SECURITY_TYPE_WPA2_PSK,
 } softap_security_type_e;
 
-void _register_wifi_station_handler(void);
-void _add_wifi_device_to_array(softap_device_info_t *di, GPtrArray *array);
-mobile_ap_error_code_e _disable_wifi_tethering(TetheringObject *obj);
+typedef struct {
+       int hide_mode;
+       char *ssid;
+       char *key;
+       softap_security_type_e security_type;
+} wifi_saved_settings;
 
-/* Dbus method */
-gboolean tethering_enable_wifi_tethering(TetheringObject *obj, gchar *ssid,
-               gchar *key, gint hide_mode,
-               DBusGMethodInvocation *context);
+int _get_wifi_name_from_lease_info(const char *mac, char **name_buf);
+mobile_ap_error_code_e _enable_wifi_tethering(Tethering *obj, gchar *ssid,
+       gchar *passphrase, int hide_mode, softap_security_type_e security_type);
+mobile_ap_error_code_e _disable_wifi_tethering(Tethering *obj);
+gboolean _is_trying_wifi_operation(void);
+mobile_ap_error_code_e _reload_softap_settings(Tethering *obj,
+               gchar *ssid, gchar *key, gint hide_mode, gint security_type);
+mobile_ap_error_code_e _reload_softap_settings_for_ap(Tethering *obj,
+       gchar *ssid, gchar *key, gint hide_mode, gint security_type);
 
-gboolean tethering_disable_wifi_tethering(TetheringObject *obj,
-               DBusGMethodInvocation *context);
-
-gboolean tethering_get_wifi_tethering_hide_mode(TetheringObject *obj,
-               DBusGMethodInvocation *context);
+/* Dbus method */
+mobile_ap_error_code_e _enable_wifi_ap(Tethering *obj, gchar *ssid,
+               gchar *passphrase, int hide_mode,
+                softap_security_type_e security_type);
+mobile_ap_error_code_e _disable_wifi_ap(Tethering *obj);
+gboolean tethering_enable_wifi_tethering(Tethering *obj,
+               GDBusMethodInvocation *context, gchar *ssid,
+               gchar *key, gint visibility, gint security_type);
 
-gboolean tethering_set_wifi_tethering_hide_mode(TetheringObject *obj,
-               gint hide_mode, DBusGMethodInvocation *context);
+softap_settings_t  *_get_softap_settings();
 
-gboolean tethering_get_wifi_tethering_ssid(TetheringObject *obj,
-               DBusGMethodInvocation *context);
+gboolean tethering_disable_wifi_tethering(Tethering *obj,
+               GDBusMethodInvocation *context);
 
-gboolean tethering_get_wifi_tethering_security_type(TetheringObject *obj,
-               DBusGMethodInvocation *context);
+gboolean tethering_reload_wifi_settings(Tethering *obj,
+               GDBusMethodInvocation *context,
+               gchar *ssid, gchar *key, gint visibility, gint security_type);
 
-gboolean tethering_set_wifi_tethering_security_type(TetheringObject *obj,
-               gchar *security_type, DBusGMethodInvocation *context);
+gboolean tethering_reload_wifi_ap_settings(Tethering *obj,
+                               GDBusMethodInvocation *context, gchar *ssid, gchar *key,
+                               gint hide_mode, gint security);
 
-gboolean tethering_get_wifi_tethering_passphrase(TetheringObject *obj,
-               DBusGMethodInvocation *context);
+gboolean tethering_enable_wifi_ap(Tethering *obj, GDBusMethodInvocation *context,
+               gchar *ssid, gchar *key, gint hide_mode, gint security_type);
 
-gboolean tethering_set_wifi_tethering_passphrase(TetheringObject *obj,
-               gchar *passphrase, guint len, DBusGMethodInvocation *context);
+gboolean tethering_disable_wifi_ap(Tethering *obj,
+               GDBusMethodInvocation *context);
 #endif /* __MOBILEAP_WIFI_H__ */
index 3dbcac1..0448c2e 100644 (file)
 
                <!-- Method definitions -->
 
-               <method name="init">
-               </method>
-
-               <method name="deinit">
-               </method>
-
                <method name="disable">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
                        <arg type="u" name="type" direction="out"/>
                        <arg type="u" name="result" direction="out"/>
                </method>
 
                <method name="enable_wifi_tethering">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
                        <arg type="s" name="ssid" direction="in"/>
                        <arg type="s" name="key" direction="in"/>
                        <arg type="i" name="visibility" direction="in"/>
-                       <arg type="u" name="type" direction="out"/>
+                       <arg type="i" name="security" direction="in"/>
                        <arg type="u" name="result" direction="out"/>
                </method>
 
+               <method name="cont_enable_wifi_tethering">
+               </method>
+
+               <method name="cancel_enable_wifi_tethering">
+               </method>
+
                <method name="disable_wifi_tethering">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
                        <arg type="u" name="type" direction="out"/>
                        <arg type="u" name="result" direction="out"/>
                </method>
 
                <method name="enable_bt_tethering">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-                       <arg type="u" name="type" direction="out"/>
                        <arg type="u" name="result" direction="out"/>
                </method>
 
-               <method name="disable_bt_tethering">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-                       <arg type="u" name="type" direction="out"/>
-                       <arg type="u" name="result" direction="out"/>
+               <method name="cont_enable_bt_tethering">
                </method>
 
-               <method name="enable_usb_tethering">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-                       <arg type="u" name="type" direction="out"/>
-                       <arg type="u" name="result" direction="out"/>
+               <method name="cancel_enable_bt_tethering">
                </method>
 
-               <method name="disable_usb_tethering">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+               <method name="disable_bt_tethering">
                        <arg type="u" name="type" direction="out"/>
                        <arg type="u" name="result" direction="out"/>
                </method>
 
-               <method name="get_station_info">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-                       <arg type="u" name="type" direction="out"/>
-                       <arg type="a(usssu)" name="station" direction="out"/>
-               </method>
-
-               <method name="get_usb_station_info">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-                       <arg type="a(sss)" name="usb_station" direction="out"/>
+               <method name="enable_usb_tethering">
+                       <arg type="u" name="result" direction="out"/>
                </method>
 
-               <method name="get_data_packet_usage">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-                       <arg type="u" name="type" direction="out"/>
-                       <arg type="t" name="rx_data" direction="out"/>
-                       <arg type="t" name="tx_data" direction="out"/>
+               <method name="cont_enable_usb_tethering">
                </method>
 
-               <method name="get_usb_interface_info">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-                       <arg type="a(ssss)" name="interface" direction="out"/>
+               <method name="cancel_enable_usb_tethering">
                </method>
 
-                <method name="set_ip_forward_status">
-                        <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-                        <arg type="i" name="forward_status" direction="in"/>
-                        <arg type="i" name="result" direction="out"/>
-                </method>
-
-                <method name="get_ip_forward_status">
-                        <arg type="i" name="forward_status" direction="out"/>
-                </method>
-
-               <method name="get_wifi_tethering_hide_mode">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-                       <arg type="i" name="hide_mode" direction="out"/>
+               <method name="disable_usb_tethering">
+                       <arg type="u" name="type" direction="out"/>
+                       <arg type="u" name="result" direction="out"/>
                </method>
 
-               <method name="set_wifi_tethering_hide_mode">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-                       <arg type="i" name="hide_mode" direction="in"/>
+               <method name="enable_wifi_ap">
+                       <arg type="s" name="ssid" direction="in"/>
+                       <arg type="s" name="key" direction="in"/>
+                       <arg type="i" name="visibility" direction="in"/>
+                       <arg type="i" name="security" direction="in"/>
+                       <arg type="u" name="result" direction="out"/>
                </method>
 
-               <method name="get_wifi_tethering_ssid">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-                       <arg type="s" name="ssid" direction="out"/>
+               <method name="disable_wifi_ap">
+                       <arg type="u" name="type" direction="out"/>
+                       <arg type="u" name="result" direction="out"/>
                </method>
 
-               <method name="get_wifi_tethering_security_type">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-                       <arg type="s" name="security_type" direction="out"/>
+               <method name="reload_wifi_settings">
+                       <arg type="s" name="ssid" direction="in"/>
+                       <arg type="s" name="key" direction="in"/>
+                       <arg type="i" name="visibility" direction="in"/>
+                       <arg type="i" name="security" direction="in"/>
+                       <arg type="u" name="result" direction="out"/>
                </method>
 
-               <method name="set_wifi_tethering_security_type">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-                       <arg type="s" name="security_type" direction="in"/>
+               <method name="reload_wifi_ap_settings">
+                       <arg type="s" name="ssid" direction="in"/>
+                       <arg type="s" name="key" direction="in"/>
+                       <arg type="i" name="visibility" direction="in"/>
+                       <arg type="i" name="security" direction="in"/>
+                       <arg type="u" name="result" direction="out"/>
                </method>
 
-               <method name="get_wifi_tethering_passphrase">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-                       <arg type="s" name="passphrase" direction="out"/>
-                       <arg type="u" name="len" direction="out"/>
+               <method name="get_station_info">
+               <arg type="a(a{sv})" name="station" direction="out"/>
                </method>
 
-               <method name="set_wifi_tethering_passphrase">
-                       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
-                       <arg type="s" name="passphrase" direction="in"/>
-                       <arg type="u" name="len" direction="in"/>
+               <method name="get_data_packet_usage">
+                       <arg type="u" name="type" direction="out"/>
+                       <arg type="t" name="rx_data" direction="out"/>
+                       <arg type="t" name="tx_data" direction="out"/>
                </method>
 
                <!-- Signal (D-Bus) definitions -->
                <signal name="net_closed">
-                       <arg type="s" name="arg1" direction="out"/>
                </signal>
 
                <signal name="sta_connected">
                </signal>
 
                <signal name="wifi_on">
-                       <arg type="s" name="arg1" direction="out"/>
                </signal>
 
                <signal name="wifi_off">
                </signal>
 
                <signal name="usb_on">
-                       <arg type="s" name="arg1" direction="out"/>
                </signal>
 
                <signal name="usb_off">
                </signal>
 
                <signal name="bluetooth_on">
-                       <arg type="s" name="arg1" direction="out"/>
                </signal>
 
                <signal name="bluetooth_off">
                        <arg type="s" name="arg1" direction="out"/>
                </signal>
 
-               <signal name="no_data_timeout">
+               <signal name="wifi_ap_on">
+               </signal>
+
+               <signal name="wifi_ap_off">
                        <arg type="s" name="arg1" direction="out"/>
                </signal>
 
+               <signal name="no_data_timeout">
+               </signal>
+
                <signal name="low_batt_mode">
-                       <arg type="s" name="arg1" direction="out"/>
                </signal>
 
                <signal name="flight_mode">
-                       <arg type="s" name="arg1" direction="out"/>
                </signal>
 
                <signal name="dhcp_status">
-                       <arg type="s" name="member" direction="out"/>
+                       <arg type="s" name="signalName" direction="out"/>
+                       <arg type="u" name="type" direction="out"/>
                        <arg type="s" name="ip" direction="out"/>
                        <arg type="s" name="mac" direction="out"/>
-                       <arg type="s" name="name" direction="out"/>
-                       <arg type="u" name="time" direction="out"/>
+                       <arg type="s" name="hostName" direction="out"/>
+                       <arg type="u" name="tm" direction="out"/>
                </signal>
-
-               <signal name="security_type_changed">
-                       <arg type="s" name="arg1" direction="out"/>
-               </signal>
-
-               <signal name="ssid_visibility_changed">
-                       <arg type="s" name="arg1" direction="out"/>
-               </signal>
-
-               <signal name="passphrase_changed">
-                       <arg type="s" name="arg1" direction="out"/>
-               </signal>
-
        </interface>
 </node>
-
diff --git a/mobileap-agent.manifest b/mobileap-agent.manifest
new file mode 100644 (file)
index 0000000..327a05f
--- /dev/null
@@ -0,0 +1,52 @@
+<manifest>
+       <define>
+               <domain name="mobileap-agent"/>
+               <request>
+                       <smack request="bt-service" type="rw"/>
+                       <smack request="bt-service::platform" type="w"/>
+                       <smack request="bt-service::public" type="w"/>
+                       <smack request="secure-storage::tethering" type="rw"/>
+                       <smack request="deviced::display" type="rw"/>
+                       <smack request="connman" type="rw"/>
+                       <smack request="connman::get" type="rw"/>
+                       <smack request="net-config" type="rw"/>
+                       <smack request="alarm-server::alarm" type="w"/>
+                       <smack request="system::use_internet" type="w"/>
+                       <smack request="telephony_framework::api_ps_public" type="rw"/>
+                       <smack request="tizen::vconf::public::r" type="rwx"/>
+                       <smack request="tizen::vconf::wifidirect" type="rwx"/>
+                       <smack request="tizen::vconf::tethering::admin" type="rwx"/>
+                       <smack request="tizen::vconf::setting::admin" type="rl"/>
+                       <smack request="wifi-direct" type="w"/>
+                       <smack request="syslogd" type="w"/>
+                       <smack request="tizen::vconf::public::r::platform::rw" type="rl"/>
+                       <smack request="device::app_logging" type="rw"/>
+                       <smack request="device::sys_logging" type="rw"/>
+                       <smack request="notification::db" type="rw"/>
+                       <smack request="wpasupplicant" type="rwx"/>
+                       <smack request="_" type="wx"/>
+                       <smack request="sdbd" type="r"/>
+                       <smack request="pkgmgr::db" type="rw"/>
+                       <smack request="dbus" type="rx"/>
+                       <smack request="data-provider-master::notification" type="w"/>
+               </request>
+               <permit>
+                       <smack permit="system::use_internet" type="w"/>
+                       <smack permit="dbus" type="rx"/>
+               </permit>
+       </define>
+       <request>
+               <domain name="mobileap-agent"/>
+       </request>
+       <assign>
+               <filesystem path="/usr/share/dbus-1/system-services/org.tizen.tethering.service" label="_"/>
+               <dbus name="org.tizen.tethering" own="mobileap-agent" bus="system">
+                       <node name="/Tethering">
+                               <interface name="org.tizen.tethering">
+                                       <annotation name="org.tizen.smack" value="tethering::dbus-access"/>
+                               </interface>
+                       </node>
+               </dbus>
+               <filesystem path="/opt/etc/dump.d/module.d/tethering_dump.sh" label="_" exec_label="none" />
+       </assign>
+</manifest>
diff --git a/packaging/mobileap-agent.manifest b/packaging/mobileap-agent.manifest
deleted file mode 100644 (file)
index 017d22d..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<manifest>
- <request>
-    <domain name="_"/>
- </request>
-</manifest>
index 7a6889a..fac994f 100644 (file)
-Name:       mobileap-agent
-Summary:    Mobile AP daemon for setting tethering environments
-Version:    0.1.92
-Release:    1
-Group:      TO_BE/FILLED_IN
-License:    Flora License
-Source0:    %{name}-%{version}.tar.gz
-Source1001:    mobileap-agent.manifest
-BuildRequires: pkgconfig(dlog)
-BuildRequires: pkgconfig(dbus-glib-1)
-BuildRequires: pkgconfig(glib-2.0)
-BuildRequires: pkgconfig(gio-2.0)
-BuildRequires: pkgconfig(gthread-2.0)
-BuildRequires: pkgconfig(pmapi)
-BuildRequires: pkgconfig(vconf)
-BuildRequires: pkgconfig(notification)
-BuildRequires: pkgconfig(libssl)
-BuildRequires: pkgconfig(key-manager)
-BuildRequires: pkgconfig(capi-network-connection)
-BuildRequires: pkgconfig(capi-network-bluetooth)
-BuildRequires: cmake
-Requires(post): /usr/bin/vconftool
-Requires: iptables
-Requires: dnsmasq
+Name:          mobileap-agent
+Summary:       Mobile AP daemon for setting tethering environments
+Version:       1.0.37
+Release:       1
+Group:         System/Network
+License:       Apache-2.0
+Source0:       %{name}-%{version}.tar.gz
+
+%if "%{?tizen_profile_name}" == "tv"
+ExcludeArch: %{arm} %ix86 x86_64
+%endif
+
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(gio-2.0)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(gthread-2.0)
+BuildRequires: pkgconfig(deviced)
+BuildRequires: pkgconfig(vconf)
+BuildRequires: pkgconfig(notification)
+BuildRequires: pkgconfig(capi-network-connection)
+BuildRequires: pkgconfig(capi-network-bluetooth)
+BuildRequires: pkgconfig(syspopup-caller)
+BuildRequires: pkgconfig(bundle)
+BuildRequires: pkgconfig(appcore-common)
+BuildRequires: pkgconfig(capi-network-wifi-direct)
+BuildRequires: pkgconfig(capi-network-wifi)
+BuildRequires: pkgconfig(alarm-service)
+BuildRequires: pkgconfig(appsvc)
+BuildRequires: pkgconfig(libssl)
+BuildRequires: cmake
+Requires(post):        /usr/bin/vconftool
+%if "%{?tizen_profile_name}" != "tv"
+Requires(post):        bluetooth-agent
+%endif
+Requires:      iproute2
+Requires:      iptables
+Requires:      dnsmasq
+
 %description
 Mobile AP daemon for setting tethering environments
 
 %prep
 %setup -q
-cp %{SOURCE1001} .
+
 
 %build
-%cmake .
-%ifarch %arm
-CFLAGS+=" -DTIZEN_ARM"
+export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE"
+export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE"
+export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE"
+
+%cmake -DCMAKE_BUILD_TYPE="" \
+%if "%{?tizen_profile_name}" == "tv"
+       -DTIZEN_TV=1 \
 %endif
+%if "%{?tizen_target_name}" == "Z300H"
+       -DTIZEN_WLAN_BOARD_SPRD=1 \
+%endif
+       .
+
 make %{?jobs:-j%jobs}
 
+
 %install
 %make_install
 
 %post
-/usr/bin/vconftool set -t int memory/mobile_hotspot/connected_device "0" -u 0 -i -f
-/usr/bin/vconftool set -t int memory/mobile_hotspot/mode "0" -u 0 -i -f
-/usr/bin/vconftool set -t int db/mobile_hotspot/security "0" -u 0 -f
-/usr/bin/vconftool set -t int db/mobile_hotspot/hide "0" -u 0 -f
+/usr/bin/vconftool set -t string memory/private/mobileap-agent/ssid "" -u 0 -i -s system::vconf_network
+
+/bin/chmod +x /opt/etc/dump.d/module.d/tethering_dump.sh
 
 %files
-%manifest %{name}.manifest
+%manifest mobileap-agent.manifest
 %defattr(-,root,root,-)
 /usr/share/dbus-1/system-services/org.tizen.tethering.service
-%{_bindir}/mobileap-agent
-
-%changelog
-* Tue Apr 09 2013 Seungyoun Ju <sy39.ju@samsung.com> 0.1.86-1
-- Fix the multiple notification issue
-- Support i80211n
-- Channel is changed to 6
-- Implement status notification for bluetooth visibility
-- Change the power manager api
-- Implement connection timer
-- Reference count is used
-- Support Mobile AP
-
-* Sat Feb 16 2013 Seungyoun Ju <sy39.ju@samsung.com> 0.1.85-2
-- Function return value is checked
-- Private SSID is considered
-- Build option clean-up and g_type_init is deprecated from glib 2.35
-
-* Thu Feb 14 2013 Seungyoun Ju <sy39.ju@samsung.com> 0.1.84-1
-- User is specified in service file for Dbus auto activation
-
-* Mon Jan 28 2013 Seungyoun Ju <sy39.ju@samsung.com> 0.1.83-1
-- Remove unrequired log
-
-* Thu Jan 24 2013 Seungyoun Ju <sy39.ju@samsung.com> 0.1.82-1
-- Indications for Wi-Fi tethering setting change are added
-- DNS Forward and Use of Tethering cellular profile are removed
-- Dbus service / interface / object names are changed
-
-* Mon Jan 14 2013 Seungyoun Ju <sy39.ju@samsung.com> 0.1.81-1
-- dhcp lease delete is handled based on IP Address
-- DNS Forward by netfilter is implemented
-- Vconf key for flight mode is changed
-
-* Fri Dec 07 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.80-1
-- Notification API's usage is changed
-- Duplicated station information issue is fixed
-- Improper notification type is used
-- Timeout(Auto disconnection) feature is implemented
-- Notification for timeout event is implemented
-
-* Thu Nov 08 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.79-1
-- Notification's API usage is changed
-
-* Tue Nov 06 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.78-1
-- Unnecessary BT API is removed
-
-* Sat Nov 03 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.77-1
-- Prevent issues are fixed
-
-* Tue Oct 30 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.76-1
-- Vconf enum is changed (SETTING_USB_MOBILE_HOTSPOT -> SETTING_USB_TETHERING_MODE)
-- Private code is separated
 
-* Mon Oct 29 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.75-1
-- Code clean-up and path for notification icon is changed
-
-* Thu Oct 22 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.74-1
-- License is added
-
-* Thu Oct 11 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.73-1
-- Source package name is changed (libmobileap -> mobileap-agent)
-
-* Thu Oct 11 2012 Injun Yang <injun.yang@samsung.com> 0.1.72-1
-- Launch kcp-agent
-
-* Fri Sep 28 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.71-1
-- Fix memory corruption
-
-* Fri Sep 21 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.70-1
-- Manifest file is added for SMACK
-
-* Wed Sep 19 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.69-1
-- The code for Legacy APIs is removed
-
-* Wed Sep 14 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.68-1
-- Bluetooth PAN Managed APIs are applied
-- MDM Phase 2 implementation
-
-* Wed Sep 06 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.67-1
-- Connection Managed APIs are applied
-- Network status is not checked in agent
-
-* Wed Aug 01 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.66-1
-- Wi-Fi tethering setting values are managed here
-- Deprecated APIs from glib-2.3.0 are replaced
-- Notification Icon is changed
-
-* Fri Jul 13 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.65-1
-- Wi-Fi tethering disable / enable issues are fixed
-
-* Fri Jul 06 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.64-1
-- Unnecessary dependency is removed
-
-* Mon Jun 25 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.63-1
-- Data usage is fixed
-
-* Thu May 31 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.62-1
-- Wi-Fi tethering security is implemented
-- API for getting USB interface information is implemented
-
-* Wed May 23 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.61-1
-- Tethering app. dependency is added
-
-* Tue May 22 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.60-1
-- Wi-Fi interface name is changed from eth0 to wlan0
-
-* Tue May 22 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.59-1
-- Below changes are applied
-- Ignore mdm failure case
-- CAPI bugs are fixed
-- Bug of _remove_station_info_all() is fixed
-- Launch tethering applicatoin from notification
-
-* Tue May 08 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.58-1
-- Hostapd control interface is implemented
-
-* Mon Apr 09 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.57-1
-- Unused vconfkey is removed
-
-* Wed Mar 14 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.56-1
-- Export API's are changed
-
-* Mon Feb 06 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.55-2
-- Fix build error
+%{_bindir}/mobileap-agent
+/opt/etc/dump.d/module.d/tethering_dump.sh
 
-* Mon Feb 06 2012 Seungyoun Ju <sy39.ju@samsung.com> 0.1.55-1
-- Test code is modified
-- Code clean-up
-- Notification is implemented
-- MDM bug fix
old mode 100644 (file)
new mode 100755 (executable)
index dee5216..c7e7825
@@ -1,32 +1,30 @@
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
 #include <stdio.h>
 #include <glib.h>
 #include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
 #include <bluetooth.h>
+#ifndef TIZEN_TV
+#include <bluetooth_internal.h>
+#endif
 
-#include "mobileap_agent.h"
+#include "mobileap_softap.h"
 #include "mobileap_common.h"
-#include "mobileap_connman.h"
 #include "mobileap_bluetooth.h"
 #include "mobileap_handler.h"
 #include "mobileap_notification.h"
@@ -41,10 +39,16 @@ static __bt_remote_device_s __bt_remote_devices[MOBILE_AP_MAX_BT_STA] = {
        {NULL, NULL, IP_ADDRESS_BT_1},
        {NULL, NULL, IP_ADDRESS_BT_2},
        {NULL, NULL, IP_ADDRESS_BT_3},
-       {NULL, NULL, IP_ADDRESS_BT_4},
-       {NULL, NULL, IP_ADDRESS_BT_5},
-       {NULL, NULL, IP_ADDRESS_BT_6},
-       {NULL, NULL, IP_ADDRESS_BT_7}};
+       {NULL, NULL, IP_ADDRESS_BT_4}};
+
+static GDBusMethodInvocation *g_context = NULL;
+
+static void __bt_nap_connection_changed(bool connected, const char *remote_address,
+                               const char *interface_name, void *user_data);
+static void __bt_adapter_state_changed(int result, bt_adapter_state_e adapter_state, void *user_data);
+static void __handle_bt_adapter_visibility();
+
+int __recheck_bt_adapter_timer = 0;
 
 static __bt_remote_device_s *__find_bt_remote(const char *mac)
 {
@@ -59,7 +63,7 @@ static __bt_remote_device_s *__find_bt_remote(const char *mac)
        }
 
        if (i == MOBILE_AP_MAX_BT_STA) {
-               ERR("Not found : %s\n", mac);
+               SERR("Not found : %s\n", mac);
                return NULL;
        }
 
@@ -86,6 +90,9 @@ static __bt_remote_device_s *__add_bt_remote(bt_device_info_s *info, const char
                return NULL;
        }
 
+       _add_interface_routing(__bt_remote_devices[i].intf_name,
+                       __bt_remote_devices[i].intf_ip);
+       _add_routing_rule(__bt_remote_devices[i].intf_name);
        __bt_remote_devices[i].info = info;
 
        return &__bt_remote_devices[i];
@@ -104,10 +111,13 @@ static gboolean __del_bt_remote(const char *mac)
        }
 
        if (i == MOBILE_AP_MAX_BT_STA) {
-               ERR("Not found : %s\n", mac);
+               SERR("Not found : %s\n", mac);
                return FALSE;
        }
 
+       _del_routing_rule(__bt_remote_devices[i].intf_name);
+       _del_interface_routing(__bt_remote_devices[i].intf_name,
+                       __bt_remote_devices[i].intf_ip);
         bt_adapter_free_device_info(__bt_remote_devices[i].info);
         g_free(__bt_remote_devices[i].intf_name);
 
@@ -128,6 +138,9 @@ static void __del_bt_remote_all(void)
                }
 
                if (__bt_remote_devices[i].intf_name) {
+                       _del_routing_rule(__bt_remote_devices[i].intf_name);
+                       _del_interface_routing(__bt_remote_devices[i].intf_name,
+                               __bt_remote_devices[i].intf_ip);
                        g_free(__bt_remote_devices[i].intf_name);
                        __bt_remote_devices[i].intf_name = NULL;
                }
@@ -136,6 +149,219 @@ static void __del_bt_remote_all(void)
        return;
 }
 
+static mobile_ap_error_code_e __init_bt(Tethering *obj)
+{
+       int ret;
+
+       ret = bt_initialize();
+       if (ret != BT_ERROR_NONE) {
+               ERR("bt_initialize is failed : %d\n", ret);
+               return MOBILE_AP_ERROR_RESOURCE;
+       }
+
+       ret = bt_adapter_set_state_changed_cb(__bt_adapter_state_changed, (void *)obj);
+       if (ret != BT_ERROR_NONE) {
+               ERR("bt_adapter_set_state_changed_cb is failed : %d\n", ret);
+               bt_deinitialize();
+               return MOBILE_AP_ERROR_RESOURCE;
+       }
+
+       return MOBILE_AP_ERROR_NONE;
+}
+
+static void __deinit_bt(void)
+{
+       int ret;
+
+       ret = bt_adapter_unset_state_changed_cb();
+       if (ret != BT_ERROR_NONE)
+               ERR("bt_adapter_unset_state_changed_cb is failed : %d\n", ret);
+
+       ret = bt_deinitialize();
+       if (ret != BT_ERROR_NONE)
+               ERR("bt_deinitialize is failed : %d\n", ret);
+
+       return;
+}
+
+static gboolean __is_bt_adapter_on(void)
+{
+       int ret;
+       bt_adapter_state_e adapter_state = BT_ADAPTER_DISABLED;
+
+       ret = bt_adapter_get_state(&adapter_state);
+       if (ret != BT_ERROR_NONE) {
+               ERR("bt_adapter_get_state is failed : %d\n", ret);
+               return FALSE;
+       }
+
+       if (adapter_state == BT_ADAPTER_ENABLED)
+               return TRUE;
+       else
+               return FALSE;
+}
+
+gboolean __bt_adapter_timeout_cb(Tethering *obj)
+{
+       DBG("+\n");
+
+       static int retry_count = 0;
+       if (__is_bt_adapter_on() == TRUE) {
+               DBG("BT Adapter is enabled by other process \n");
+               retry_count = 0;
+               DBG("-\n");
+               return FALSE;
+       } else {
+               if (++retry_count >= PS_RECHECK_COUNT_MAX) {
+                       retry_count = 0;
+                       ERR("_enable_bt_tethering() is failed because of bt_adapter_eanbled() failed:n");
+                       _mobileap_clear_state(MOBILE_AP_STATE_BT);
+                       __deinit_bt();
+                       tethering_complete_enable_bt_tethering(obj, g_context, MOBILE_AP_ERROR_INTERNAL);
+                       g_context = NULL;
+                       _unblock_device_sleep();
+                       DBG("-\n");
+                       return FALSE;
+               } else {
+                       DBG("-\n");
+                       return TRUE;
+               }
+       }
+}
+
+static mobile_ap_error_code_e __turn_on_bt_adapter(gpointer data)
+{
+       int ret;
+
+       Tethering *obj = (Tethering *)data;
+
+       ret = bt_adapter_enable();
+       if (ret == BT_ERROR_NOW_IN_PROGRESS) {
+               if (__recheck_bt_adapter_timer) {
+                       g_source_remove(__recheck_bt_adapter_timer);
+               }
+               __recheck_bt_adapter_timer = g_timeout_add(PS_RECHECK_INTERVAL,
+                               __bt_adapter_timeout_cb, obj);
+               return MOBILE_AP_ERROR_NONE;
+       }
+
+       if (ret != BT_ERROR_NONE && ret != BT_ERROR_ALREADY_DONE) {
+               ERR("bt_adapter_enable is failed : %d\n", ret);
+#ifndef TIZEN_TV
+               if (ret == BT_ERROR_PERMISSION_DENIED)
+                       return MOBILE_AP_ERROR_PERMISSION_DENIED;
+               else
+#endif
+                       return MOBILE_AP_ERROR_RESOURCE;
+       }
+
+       return MOBILE_AP_ERROR_NONE;
+}
+
+static mobile_ap_error_code_e __turn_on_bt_nap(Tethering *obj)
+{
+       int bt_ret = BT_ERROR_NONE;
+
+       bt_ret = bt_nap_set_connection_state_changed_cb(__bt_nap_connection_changed, (void *)obj);
+       if (bt_ret != BT_ERROR_NONE) {
+               ERR("bt_nap_set_connection_state_changed_cb is failed : %d\n", bt_ret);
+               return MOBILE_AP_ERROR_RESOURCE;
+       }
+
+       bt_ret = bt_nap_activate();
+       if (bt_ret != BT_ERROR_NONE && bt_ret != BT_ERROR_ALREADY_DONE) {
+               bt_nap_unset_connection_state_changed_cb();
+               ERR("bt_nap_activate is failed : %d\n", bt_ret);
+#ifndef TIZEN_TV
+               if (bt_ret == BT_ERROR_PERMISSION_DENIED)
+                       return MOBILE_AP_ERROR_PERMISSION_DENIED;
+               else
+#endif
+                       return MOBILE_AP_ERROR_RESOURCE;
+       }
+
+       return MOBILE_AP_ERROR_NONE;
+}
+
+static void __turn_off_bt_nap(void)
+{
+       int bt_ret;
+
+       bt_ret = bt_nap_deactivate();
+       if (bt_ret != BT_ERROR_NONE)
+               ERR("bt_nap_deactivate is failed : %d\n", bt_ret);
+       else
+               DBG("bt_nap_deactivate is called\n");
+
+       bt_ret = bt_nap_unset_connection_state_changed_cb();
+       if (bt_ret != BT_ERROR_NONE)
+               ERR("bt_nap_unset_connection_state_changed_cb is failed : %d\n", bt_ret);
+
+       return;
+}
+
+mobile_ap_error_code_e _enable_bt_tethering(Tethering *obj)
+{
+       mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
+
+       DBG("+\n");
+       if (__recheck_bt_adapter_timer) {
+               g_source_remove(__recheck_bt_adapter_timer);
+               __recheck_bt_adapter_timer = 0;
+       }
+
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
+               ERR("Wi-Fi AP is enabled\n");
+               return MOBILE_AP_ERROR_RESOURCE;
+       }
+
+       ret = _init_tethering();
+       if (ret != MOBILE_AP_ERROR_NONE) {
+               return ret;
+       }
+
+       ret = __turn_on_bt_nap(obj);
+       if (ret != MOBILE_AP_ERROR_NONE) {
+               _deinit_tethering();
+               return ret;
+       }
+       _delete_timeout_noti();
+       _init_timeout_cb(MOBILE_AP_TYPE_BT, (void *)obj);
+       _start_timeout_cb(MOBILE_AP_TYPE_BT, time(NULL) + TETHERING_CONN_TIMEOUT);
+
+       DBG("-\n");
+       return ret;
+}
+
+mobile_ap_error_code_e _disable_bt_tethering(Tethering *obj)
+{
+       int ret = BT_ERROR_NONE;
+       if (!_mobileap_is_enabled(MOBILE_AP_STATE_BT)) {
+               ERR("BT tethering has not been enabled\n");
+               return MOBILE_AP_ERROR_NOT_ENABLED;
+       }
+       ret = bt_adapter_unset_visibility_mode_changed_cb();
+       if (ret != BT_ERROR_NONE)
+               ERR("bt_adapter_unset_visibility_mode_changed_cb is failed : %d\n", ret);
+
+       _block_device_sleep();
+       if (__is_bt_adapter_on()) {
+               __turn_off_bt_nap();
+               __deinit_bt();
+       }
+
+       _remove_station_info_all(MOBILE_AP_TYPE_BT);
+       __del_bt_remote_all();
+       _deinit_timeout_cb(MOBILE_AP_TYPE_BT);
+
+       _deinit_tethering();
+       _mobileap_clear_state(MOBILE_AP_STATE_BT);
+       _unblock_device_sleep();
+
+       return MOBILE_AP_ERROR_NONE;
+}
+
+
 static void __bt_nap_connection_changed(bool connected, const char *remote_address, const char *interface_name, void *user_data)
 {
        if (remote_address == NULL || interface_name == NULL || user_data == NULL) {
@@ -148,11 +374,10 @@ static void __bt_nap_connection_changed(bool connected, const char *remote_addre
        int ret;
        int n_station = 0;
 
-       DBG("Remote address : %s, Interface : %s, %s\n",
+       SDBG("Remote address : %s, Interface : %s, %s\n",
                        remote_address, interface_name,
                        connected ? "Connected" : "Disconnected");
 
-
        if (connected) {
                ret = bt_adapter_get_bonded_device_info(remote_address, &info);
                if (ret != BT_ERROR_NONE) {
@@ -166,6 +391,11 @@ static void __bt_nap_connection_changed(bool connected, const char *remote_addre
                         bt_adapter_free_device_info(info);
                        return;
                }
+
+               ret = _mh_core_set_ip_address(interface_name, remote->intf_ip);
+               if (ret != MOBILE_AP_ERROR_NONE) {
+                       ERR("Setting ip address error : %d\n", ret);
+               }
        } else {
                _remove_station_info(remote_address, _slist_find_station_by_mac);
                if (__del_bt_remote(remote_address) == FALSE) {
@@ -175,44 +405,9 @@ static void __bt_nap_connection_changed(bool connected, const char *remote_addre
                _get_station_count((gconstpointer)MOBILE_AP_TYPE_BT,
                                _slist_find_station_by_interface, &n_station);
                if (n_station == 0)
-                       _start_timeout_cb(MOBILE_AP_TYPE_BT);
-       }
-
-       return;
-}
-
-static mobile_ap_error_code_e __activate_bt_nap(TetheringObject *obj)
-{
-       int bt_ret = BT_ERROR_NONE;
-
-       bt_ret = bt_nap_set_connection_state_changed_cb(__bt_nap_connection_changed, (void *)obj);
-       if (bt_ret != BT_ERROR_NONE) {
-               ERR("bt_nap_set_connection_state_changed_cb is failed : %d\n", bt_ret);
-               return MOBILE_AP_ERROR_RESOURCE;
-       }
-
-       bt_ret = connman_enable_tethering(TECH_TYPE_BLUETOOTH, NULL, NULL,
-                               NULL, 0);
-       if (bt_ret != MOBILE_AP_ERROR_NONE) {
-               bt_nap_unset_connection_state_changed_cb();
-               ERR("connman_enable_tethering is failed : %d\n", bt_ret);
-               return MOBILE_AP_ERROR_RESOURCE;
+                       _start_timeout_cb(MOBILE_AP_TYPE_BT, time(NULL) + TETHERING_CONN_TIMEOUT);
        }
 
-       return MOBILE_AP_ERROR_NONE;
-}
-
-static void __deactivate_bt_nap(void)
-{
-       int bt_ret;
-       bt_ret = connman_disable_tethering(TECH_TYPE_BLUETOOTH);
-       if (bt_ret != MOBILE_AP_ERROR_NONE)
-               ERR("connman_disable_tethering is failed : %d\n", bt_ret);
-
-       bt_ret = bt_nap_unset_connection_state_changed_cb();
-       if (bt_ret != BT_ERROR_NONE)
-               ERR("bt_nap_unset_connection_state_changed_cb is failed : %d\n", bt_ret);
-
        return;
 }
 
@@ -223,61 +418,55 @@ static void __bt_adapter_state_changed(int result, bt_adapter_state_e adapter_st
                return;
        }
 
+       DBG("+\n");
+
        if (!_mobileap_is_enabled(MOBILE_AP_STATE_BT))
                return;
 
-       int ret;
-       int duration;
-       bt_adapter_visibility_mode_e mode;
-       TetheringObject *obj = (TetheringObject *)user_data;
-       DBusGMethodInvocation *context = obj->bt_context;
+       int ret = MOBILE_AP_ERROR_RESOURCE;
+       Tethering *obj = (Tethering *)user_data;
 
-       obj->bt_context = NULL;
        if (result != BT_ERROR_NONE) {
                ERR("BT Adapter operation is failed : %d\n", result);
-               if (context) {
-                       ret = MOBILE_AP_ERROR_RESOURCE;
-                       dbus_g_method_return(context,
-                                       MOBILE_AP_ENABLE_BT_TETHERING_CFM, ret);
-                       _mobileap_clear_state(MOBILE_AP_STATE_BT);
-               }
-               return;
+               goto FAIL;
        }
 
-       DBG("BT Adapter is %s\n", adapter_state == BT_ADAPTER_ENABLED ?
+       SDBG("BT Adapter is %s\n", adapter_state == BT_ADAPTER_ENABLED ?
                        "enabled" : "disabled");
        if (adapter_state == BT_ADAPTER_DISABLED) {
                _disable_bt_tethering(obj);
-               _emit_mobileap_dbus_signal(obj, E_SIGNAL_BT_TETHER_OFF,
-                               SIGNAL_MSG_NOT_AVAIL_INTERFACE);
+               tethering_emit_bluetooth_off(obj, SIGNAL_MSG_NOT_AVAIL_INTERFACE);
                return;
        } else {
-               ret = bt_adapter_get_visibility(&mode, &duration);
-               if (ret == BT_ERROR_NONE && mode == BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE)
-                       _create_status_noti("Bluetooth visible time is off. You may not find your device.");
-       }
+               ret = _enable_bt_tethering(obj);
+               if (ret != MOBILE_AP_ERROR_NONE) {
+                       ERR("_enable_bt_tethering() is failed : %d\n", ret);
+                       __deinit_bt();
+                       goto FAIL;
+               }
+
+               tethering_emit_bluetooth_on(obj);
+               _create_tethering_active_noti();
+               tethering_complete_enable_bt_tethering(obj, g_context, ret);
+               __handle_bt_adapter_visibility();
+               g_context = NULL;
+               _unblock_device_sleep();
 
-       ret = __activate_bt_nap(obj);
-       if (ret != MOBILE_AP_ERROR_NONE) {
-               bt_adapter_unset_state_changed_cb();
-               bt_deinitialize();
-               _deinit_tethering(obj);
-               dbus_g_method_return(context,
-                               MOBILE_AP_ENABLE_BT_TETHERING_CFM, ret);
-               _mobileap_clear_state(MOBILE_AP_STATE_BT);
                return;
        }
 
-       _emit_mobileap_dbus_signal(obj, E_SIGNAL_BT_TETHER_ON, NULL);
-       if (context)
-               dbus_g_method_return(context,
-                               MOBILE_AP_ENABLE_BT_TETHERING_CFM, ret);
+FAIL:
+       tethering_complete_enable_bt_tethering(obj, g_context, ret);
+       g_context = NULL;
+       _mobileap_clear_state(MOBILE_AP_STATE_BT);
+       _unblock_device_sleep();
+
        return;
 }
 
-void _bt_get_remote_device_name(TetheringObject *obj, const char *mac, char **name)
+void _bt_get_remote_device_name(const char *mac, char **name)
 {
-       if (obj == NULL || mac == NULL || name == NULL) {
+       if (mac == NULL || name == NULL) {
                ERR("Invalid param\n");
                return;
        }
@@ -297,162 +486,118 @@ void _bt_get_remote_device_name(TetheringObject *obj, const char *mac, char **na
        return;
 }
 
-mobile_ap_error_code_e _enable_bt_tethering(TetheringObject *obj,
-               DBusGMethodInvocation *context)
+static void __bt_adapter_visibility_changed_cb(int result,
+                               bt_adapter_visibility_mode_e visibility_mode, void *user_data)
 {
-       mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
-       int bt_ret;
-       int duration;
-       bt_adapter_visibility_mode_e mode;
-       bt_adapter_state_e adapter_state = BT_ADAPTER_DISABLED;
+       DBG("+\n");
 
-       if (_mobileap_is_enabled(MOBILE_AP_STATE_BT)) {
-               ERR("Bluetooth tethering is already enabled\n");
-               ret = MOBILE_AP_ERROR_ALREADY_ENABLED;
-               return ret;
-       }
+       int ret;
+       int duration;
+       bt_adapter_visibility_mode_e mode = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
 
-       if (obj->bt_context != NULL) {
-               ERR("Bluetooth tethering request is progressing\n");
-               ret = MOBILE_AP_ERROR_IN_PROGRESS;
-               return ret;
+       ret = bt_adapter_get_visibility(&mode, &duration);
+       if (ret != BT_ERROR_NONE) {
+               ERR("bt_adapter_get_visibility is failed 0x[%X]\n", ret);
        }
 
-       if (!_mobileap_set_state(MOBILE_AP_STATE_BT)) {
-               ret = MOBILE_AP_ERROR_RESOURCE;
-               goto FAIL;
+       if (mode == BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE) {
+                       ERR("_launch_toast_popup() is failed\n");
        }
 
-       if (!_init_tethering(obj)) {
-               ret = MOBILE_AP_ERROR_RESOURCE;
-               goto FAIL;
-       }
+       DBG("-\n");
+}
 
-       bt_ret = bt_initialize();
-       if (bt_ret != BT_ERROR_NONE) {
-               ERR("bt_initialize is failed : %d\n", bt_ret);
-               _deinit_tethering(obj);
-               ret = MOBILE_AP_ERROR_RESOURCE;
-               goto FAIL;
-       }
+static void __handle_bt_adapter_visibility()
+{
+       DBG("+\n");
 
-       bt_ret = bt_adapter_set_state_changed_cb(__bt_adapter_state_changed, (void *)obj);
-       if (bt_ret != BT_ERROR_NONE) {
-               ERR("bt_adapter_set_state_changed_cb is failed : %d\n", bt_ret);
-               bt_deinitialize();
-               _deinit_tethering(obj);
-               ret = MOBILE_AP_ERROR_RESOURCE;
-               goto FAIL;
-       }
+       int ret;
+       int duration;
+       bt_adapter_visibility_mode_e mode = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
 
-       bt_ret = bt_adapter_get_state(&adapter_state);
-       if (bt_ret != BT_ERROR_NONE) {
-               ERR("bt_adapter_get_state is failed : %d\n", bt_ret);
-               bt_adapter_unset_state_changed_cb();
-               bt_deinitialize();
-               _deinit_tethering(obj);
-               ret = MOBILE_AP_ERROR_RESOURCE;
-               goto FAIL;
+       ret = bt_adapter_get_visibility(&mode, &duration);
+       if (ret != BT_ERROR_NONE) {
+               ERR("bt_adapter_get_visibility is failed 0x[%X]\n", ret);
        }
 
-       if (adapter_state == BT_ADAPTER_DISABLED) {
-               bt_ret = bt_adapter_enable();
-               if (bt_ret != BT_ERROR_NONE) {
-                       ERR("bt_adapter_enable is failed : %d\n", bt_ret);
-                       bt_adapter_unset_state_changed_cb();
-                       bt_deinitialize();
-                       _deinit_tethering(obj);
-                       ret = MOBILE_AP_ERROR_RESOURCE;
-                       goto FAIL;
+       if (mode == BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE) {
+               ret = bt_adapter_set_visibility(BT_ADAPTER_VISIBILITY_MODE_LIMITED_DISCOVERABLE, 120);
+               if (ret != BT_ERROR_NONE) {
+                       ERR("bt_adapter_set_visibility is failed 0x[%X]\n", ret);
                }
-               obj->bt_context = context;
-               return ret;
-       } else {
-               bt_ret = bt_adapter_get_visibility(&mode, &duration);
-               if (bt_ret == BT_ERROR_NONE && mode == BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE)
-                       _create_status_noti("Bluetooth visible time is off. You may not find your device.");
-
-       }
-
-       ret = __activate_bt_nap(obj);
-       if (ret != MOBILE_AP_ERROR_NONE) {
-               bt_adapter_unset_state_changed_cb();
-               bt_deinitialize();
-               _deinit_tethering(obj);
-               ret = MOBILE_AP_ERROR_RESOURCE;
-               goto FAIL;
        }
-
-       _delete_timeout_noti();
-       _init_timeout_cb(MOBILE_AP_TYPE_BT, (void *)obj);
-       _start_timeout_cb(MOBILE_AP_TYPE_BT);
-
-       return ret;
-
-FAIL:
-       _mobileap_clear_state(MOBILE_AP_STATE_BT);
-
-       return ret;
+       bt_adapter_set_visibility_mode_changed_cb(__bt_adapter_visibility_changed_cb, NULL);
+       DBG("-\n");
 }
 
-mobile_ap_error_code_e _disable_bt_tethering(TetheringObject *obj)
+gboolean tethering_enable_bt_tethering(Tethering *obj,
+               GDBusMethodInvocation *context)
 {
-       int bt_ret;
-
-       if (!_mobileap_is_enabled(MOBILE_AP_STATE_BT)) {
-               ERR("BT tethering has not been enabled\n");
-               return MOBILE_AP_ERROR_NOT_ENABLED;
-       }
-
-       __deactivate_bt_nap();
+       mobile_ap_error_code_e ret;
+       gboolean ret_val = FALSE;
 
-       bt_ret = bt_adapter_unset_state_changed_cb();
-       if (bt_ret != BT_ERROR_NONE)
-               ERR("bt_adapter_unset_state_changed_cb is failed : %d\n", bt_ret);
+       DBG("+\n");
 
-       bt_ret = bt_deinitialize();
-       if (bt_ret != BT_ERROR_NONE)
-               ERR("bt_deinitialize is failed : %d\n", bt_ret);
+       g_assert(obj != NULL);
+       g_assert(context != NULL);
 
-       _remove_station_info_all(MOBILE_AP_TYPE_BT);
-       __del_bt_remote_all();
-       _deinit_timeout_cb(MOBILE_AP_TYPE_BT);
+       if (g_context) {
+               DBG("It is turnning on\n");
+               tethering_complete_enable_bt_tethering(obj, context,
+                               MOBILE_AP_ERROR_IN_PROGRESS);
+               return FALSE;
+       }
 
-       _deinit_tethering(obj);
-       _mobileap_clear_state(MOBILE_AP_STATE_BT);
+       g_context = context;
 
-       return MOBILE_AP_ERROR_NONE;
-}
+       _block_device_sleep();
 
-gboolean tethering_enable_bt_tethering(TetheringObject *obj,
-               DBusGMethodInvocation *context)
-{
-       mobile_ap_error_code_e ret;
+       ret = __init_bt(obj);
+       if (ret != MOBILE_AP_ERROR_NONE)
+               goto DONE;
 
-       DBG("+\n");
+       if (!_mobileap_set_state(MOBILE_AP_STATE_BT)) {
+               ret = MOBILE_AP_ERROR_RESOURCE;
+               __deinit_bt();
+               goto DONE;
+       }
 
-       g_assert(obj != NULL);
-       g_assert(context != NULL);
+       if (__is_bt_adapter_on() == FALSE) {
+               DBG("Bluetooth is deactivated\n");
+               if (__turn_on_bt_adapter((gpointer)obj) != MOBILE_AP_ERROR_NONE) {
+                       ERR("__turn_on_bt_adapter is failed\n");
+                       ret = MOBILE_AP_ERROR_INTERNAL;
+                       _mobileap_clear_state(MOBILE_AP_STATE_BT);
+                       __deinit_bt();
+                       goto DONE;
+               }
 
+               return TRUE;
+       }
 
-       ret = _enable_bt_tethering(obj, context);
+       ret = _enable_bt_tethering(obj);
        if (ret != MOBILE_AP_ERROR_NONE) {
                ERR("_enable_bt_tethering() is failed : %d\n", ret);
-               dbus_g_method_return(context,
-                               MOBILE_AP_ENABLE_BT_TETHERING_CFM, ret);
-               return FALSE;
-       } else if (obj->bt_context == NULL) {
-               _emit_mobileap_dbus_signal(obj, E_SIGNAL_BT_TETHER_ON, NULL);
-               dbus_g_method_return(context,
-                               MOBILE_AP_ENABLE_BT_TETHERING_CFM, ret);
+               _mobileap_clear_state(MOBILE_AP_STATE_BT);
+               __deinit_bt();
+       } else {
+               tethering_emit_bluetooth_on(obj);
+               _create_tethering_active_noti();
+               __handle_bt_adapter_visibility();
+               ret_val = TRUE;
        }
 
-       return TRUE;
-}
+DONE:
+       tethering_complete_enable_bt_tethering(obj, g_context, ret);
+       g_context = NULL;
 
+       _unblock_device_sleep();
+       DBG("-\n");
+       return ret_val;
+}
 
-gboolean tethering_disable_bt_tethering(TetheringObject *obj,
-               DBusGMethodInvocation *context)
+gboolean tethering_disable_bt_tethering(Tethering *obj,
+               GDBusMethodInvocation *context)
 {
        mobile_ap_error_code_e ret;
 
@@ -463,11 +608,18 @@ gboolean tethering_disable_bt_tethering(TetheringObject *obj,
 
        ret = _disable_bt_tethering(obj);
        if (ret != MOBILE_AP_ERROR_NONE) {
-               dbus_g_method_return(context, MOBILE_AP_DISABLE_BT_TETHERING_CFM, ret);
+               tethering_complete_disable_bt_tethering(obj, context,
+                               MOBILE_AP_DISABLE_BT_TETHERING_CFM, ret);
                return FALSE;
        }
 
-       _emit_mobileap_dbus_signal(obj, E_SIGNAL_BT_TETHER_OFF, NULL);
-       dbus_g_method_return(context, MOBILE_AP_DISABLE_BT_TETHERING_CFM, ret);
+       tethering_emit_bluetooth_off(obj, NULL);
+       tethering_complete_disable_bt_tethering(obj, context,
+                       MOBILE_AP_DISABLE_BT_TETHERING_CFM, ret);
        return TRUE;
 }
+
+gboolean _is_trying_bt_operation(void)
+{
+       return (g_context ? TRUE : FALSE);
+}
old mode 100644 (file)
new mode 100755 (executable)
index e088bc4..adbe599
@@ -1,20 +1,18 @@
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
 #include <stdio.h>
 #include <arpa/inet.h>
 
 #include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
 
 #include "mobileap_notification.h"
 #include "mobileap_common.h"
 
-#define TETHERING_OBJECT_GET_CLASS(obj) \
-       (G_TYPE_INSTANCE_GET_CLASS ((obj), \
-       TETHERING_TYPE_OBJECT , TetheringObjectClass))
-
-extern DBusConnection *tethering_conn;
-
 static GSList *station_list = NULL;
 
 gint _slist_find_station_by_interface(gconstpointer a, gconstpointer b)
@@ -67,69 +57,41 @@ gint _slist_find_station_by_ip_addr(gconstpointer a, gconstpointer b)
        return g_ascii_strcasecmp(si->ip, ip_addr);
 }
 
-void _emit_mobileap_dbus_signal(TetheringObject *obj,
-                               mobile_ap_sig_e num, const gchar *message)
-{
-       TetheringObjectClass *klass = TETHERING_OBJECT_GET_CLASS(obj);
-
-       DBG("Emitting signal id [%d], with message [%s]\n", num, message);
-       g_signal_emit(obj, klass->signals[num], 0, message);
-}
-
 void _send_dbus_station_info(const char *member, mobile_ap_station_info_t *info)
 {
-       if (tethering_conn == NULL)
-               return;
 
+       DBG("+\n");
        if (member == NULL || info == NULL) {
                ERR("Invalid param\n");
                return;
        }
-
-       DBusMessage *msg = NULL;
-       char *ip = info->ip;
-       char *mac = info->mac;
-       char *hostname = info->hostname;
-
-       msg = dbus_message_new_signal(TETHERING_SERVICE_OBJECT_PATH,
-                       TETHERING_SERVICE_INTERFACE,
-                       SIGNAL_NAME_DHCP_STATUS);
-       if (!msg) {
-               ERR("Unable to allocate D-Bus signal\n");
+       Tethering *obj = _get_tethering_obj();
+       if (obj == NULL) {
+               ERR("tethering object is null\n");
                return;
        }
-
-       if (!dbus_message_append_args(msg,
-                               DBUS_TYPE_STRING, &member,
-                               DBUS_TYPE_UINT32, &info->interface,
-                               DBUS_TYPE_STRING, &ip,
-                               DBUS_TYPE_STRING, &mac,
-                               DBUS_TYPE_STRING, &hostname,
-                               DBUS_TYPE_UINT32, &info->tm,
-                               DBUS_TYPE_INVALID)) {
-               ERR("Event sending failed\n");
-               dbus_message_unref(msg);
-               return;
-       }
-
-       dbus_connection_send(tethering_conn, msg, NULL);
-       dbus_message_unref(msg);
-
-       return;
+       DBG("signal is   %s", member);
+       tethering_emit_dhcp_status(obj, member, info->interface, info->ip, info->mac,
+                       info->hostname, info->tm);
+       DBG("-\n");
 }
 
-
 void _update_station_count(int count)
 {
        static int prev_cnt = 0;
-       char str[MH_NOTI_STR_MAX] = {0, };
+       char icon_path[MH_NOTI_PATH_MAX] = {0, };
+       int wifi_count = 0;
+       int bt_count = 0;
+       int usb_count = 0;
+
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
+               return;
+       }
 
        if (prev_cnt == count) {
-               DBG("No need to update\n");
                return;
        }
 
-       DBG("Update the number of station : %d\n", count);
        if (vconf_set_int(VCONFKEY_MOBILE_HOTSPOT_CONNECTED_DEVICE,
                                count) < 0) {
                ERR("Error setting up vconf\n");
@@ -142,13 +104,26 @@ void _update_station_count(int count)
                return;
        }
 
-       snprintf(str, MH_NOTI_STR_MAX, MH_NOTI_STR, count);
+       _get_station_count((gconstpointer)MOBILE_AP_TYPE_WIFI, _slist_find_station_by_interface, &wifi_count);
+       _get_station_count((gconstpointer)MOBILE_AP_TYPE_BT, _slist_find_station_by_interface, &bt_count);
+       _get_station_count((gconstpointer)MOBILE_AP_TYPE_USB, _slist_find_station_by_interface, &usb_count);
+
+       if (wifi_count > 0 && bt_count == 0 && usb_count == 0) {
+               g_strlcpy(icon_path, MH_NOTI_ICON_WIFI, sizeof(icon_path));
+       } else if (wifi_count == 0 && bt_count > 0 && usb_count == 0) {
+               g_strlcpy(icon_path, MH_NOTI_ICON_BT, sizeof(icon_path));
+       } else if (wifi_count == 0 && bt_count == 0 && usb_count > 0) {
+               g_strlcpy(icon_path, MH_NOTI_ICON_USB, sizeof(icon_path));
+       } else if (wifi_count == 0 && bt_count == 0 && usb_count == 0) {
+               return;
+       } else {
+               g_strlcpy(icon_path, MH_NOTI_ICON_GENERAL, sizeof(icon_path));
+       }
+
        if (prev_cnt == 0) {
-               DBG("Create notification\n");
-               _create_connected_noti(str, MH_NOTI_TITLE, MH_NOTI_ICON_PATH);
+               _create_connected_noti(count, icon_path);
        } else {
-               DBG("Update notification\n");
-               _update_connected_noti(str);
+               _update_connected_noti(count, icon_path);
        }
 
        prev_cnt = count;
@@ -169,18 +144,26 @@ int _add_station_info(mobile_ap_station_info_t *info)
 
        if (_get_station_info(info->mac, _slist_find_station_by_mac, &si) ==
                        MOBILE_AP_ERROR_NONE) {
-               DBG("Already exist station : %s\n", info->mac);
-               return MOBILE_AP_ERROR_INTERNAL;
+               if (!si) {
+                       return MOBILE_AP_ERROR_INTERNAL;
+               }
+
+               if (g_strcmp0(si->hostname, info->hostname) == 0 &&
+                               g_strcmp0(si->ip, info->ip) == 0) {
+                       return MOBILE_AP_ERROR_INTERNAL;
+               }
+
+               _remove_station_info(si->mac, _slist_find_station_by_mac);
        }
 
        station_list = g_slist_append(station_list, info);
        for (l = station_list; l != NULL; l = g_slist_next(l)) {
                si = (mobile_ap_station_info_t *)l->data;
-               DBG("[%d] interface : %d\n", i, si->interface);
-               DBG("[%d] station MAC : %s\n", i, si->mac);
-               DBG("[%d] station Hostname : %s\n", i, si->hostname);
-               DBG("[%d] station IP : %s\n", i, si->ip);
-               DBG("[%d] station connected time : %d\n", i, si->tm);
+               SDBG("[%d] interface : %d\n", i, si->interface);
+               SDBG("[%d] station MAC : %s\n", i, si->mac);
+               SDBG("[%d] station Hostname : %s\n", i, si->hostname);
+               SDBG("[%d] station IP : %s\n", i, si->ip);
+               SDBG("[%d] station connected time : %d\n", i, si->tm);
                i++;
        }
 
@@ -213,9 +196,10 @@ int _remove_station_info(gconstpointer data, GCompareFunc func)
        }
 
        si = (mobile_ap_station_info_t *)l->data;
-       DBG("Remove station MAC : %s\n", si->mac);
+       SDBG("Remove station MAC : %s\n", si->mac);
        station_list = g_slist_delete_link(station_list, l);
        _send_dbus_station_info("DhcpLeaseDeleted", si);
+       g_free(si->hostname);
        g_free(si);
 
        count = g_slist_length(station_list);
@@ -235,16 +219,18 @@ int _remove_station_info_all(mobile_ap_type_e type)
        mobile_ap_station_info_t *si = NULL;
        int count;
 
+       _flush_dhcp_ack_timer();
+
        while (l) {
                si = (mobile_ap_station_info_t *)l->data;
-               DBG("interface : %d\n", si->interface);
                if (si->interface != type) {
                        l = g_slist_next(l);
                        continue;
                }
 
-               DBG("Remove station MAC : %s\n", si->mac);
+               SDBG("Remove station MAC : %s\n", si->mac);
                _send_dbus_station_info("DhcpLeaseDeleted", si);
+               g_free(si->hostname);
                g_free(si);
 
                temp_l = l;
@@ -281,7 +267,7 @@ int _get_station_info(gconstpointer data, GCompareFunc func,
        }
 
        node = l->data;
-       DBG("Found station : %s\n", node->mac);
+       SDBG("Found station : %s\n", node->mac);
        *si = node;
 
        return MOBILE_AP_ERROR_NONE;
@@ -304,132 +290,161 @@ int _get_station_count(gconstpointer data, GCompareFunc func, int *count)
        }
 
        *count = _count;
-       DBG("Station count : %d\n", *count);
 
        return MOBILE_AP_ERROR_NONE;
 }
 
-int _station_info_foreach(GFunc func, void *user_data)
+GVariant * _station_info_foreach()
 {
-       if (func == NULL) {
-               ERR("Invalid param\n");
-               return MOBILE_AP_ERROR_INVALID_PARAM;
-       }
+       GSList *l = NULL;
+       GVariant *params = NULL;
+       GVariantBuilder *inner_builder;
+       GVariantBuilder *outer_builder;
+       mobile_ap_station_info_t *st = NULL;
 
-       g_slist_foreach(station_list, func, user_data);
+       outer_builder = g_variant_builder_new(G_VARIANT_TYPE ("a(a{sv})"));
 
-       return MOBILE_AP_ERROR_NONE;
+       for (l = station_list; l != NULL; l = g_slist_next(l)) {
+               st = (mobile_ap_station_info_t *)l->data;
+
+               inner_builder = g_variant_builder_new(G_VARIANT_TYPE ("a{sv}"));
+               g_variant_builder_add(inner_builder, "{sv}", "Type",
+                                       g_variant_new_int32(st->interface));
+               g_variant_builder_add(inner_builder, "{sv}", "IP",
+                                       g_variant_new_string(st->ip));
+               g_variant_builder_add(inner_builder, "{sv}", "MAC",
+                                       g_variant_new_string(st->mac));
+               if (st->hostname) {
+                       g_variant_builder_add(inner_builder, "{sv}", "Name",
+                                               g_variant_new_string(st->hostname));
+               }
+               g_variant_builder_add(inner_builder, "{sv}", "Time",
+                                       g_variant_new_int32(st->tm));
+
+               g_variant_builder_add(outer_builder, "(@a{sv})", g_variant_builder_end(inner_builder));
+
+               g_variant_builder_unref(inner_builder);
+       }
+
+       params = g_variant_new("(@a(a{sv}))", g_variant_builder_end(outer_builder));
+       if (params == NULL) {
+               ERR("params IS NULL\n");
+       } else {
+               SDBG("outer builder print  %s", g_variant_print(params, TRUE));
+       }
+       g_variant_builder_unref(outer_builder);
+       return params;
 }
 
-int _add_data_usage_rule(const char *src, const char *dest)
+int _add_interface_routing(const char *interface, const in_addr_t gateway)
 {
-       if (src == NULL || src[0] == '\0' ||
-                       dest == NULL || dest[0] == '\0' ||
-                       g_strcmp0(src, dest) == 0) {
+       if (interface == NULL || interface[0] == '\0') {
                ERR("Invalid parameter\n");
                return MOBILE_AP_ERROR_INVALID_PARAM;
        }
 
        char cmd[MAX_BUF_SIZE] = {0, };
+       struct in_addr addr;
+       char *interface_gw;
+       in_addr_t subnet;
 
-       snprintf(cmd, sizeof(cmd), "%s -A FORWARD "FORWARD_RULE,
-                       IPTABLES, src, dest);
-       DBG("ADD IPTABLES RULE : %s\n", cmd);
-       if (_execute_command(cmd)) {
-               ERR("iptables failed : %s\n", cmd);
-               return MOBILE_AP_ERROR_INTERNAL;
-       }
+       addr.s_addr = htonl(gateway);
+
+       subnet = inet_netof(addr);
+       addr = inet_makeaddr(subnet, 0);
+       interface_gw = inet_ntoa(addr);
 
-       snprintf(cmd, sizeof(cmd), "%s -A FORWARD "FORWARD_RULE,
-                       IPTABLES, dest, src);
-       DBG("ADD IPTABLES RULE : %s\n", cmd);
+       snprintf(cmd, sizeof(cmd), "%s route add "INTERFACE_ROUTING,
+                       IP_CMD, interface_gw, TETHERING_ROUTING_TABLE, interface);
        if (_execute_command(cmd)) {
-               ERR("iptables failed : %s\n", cmd);
+               ERR("cmd failed : %s\n", cmd);
                return MOBILE_AP_ERROR_INTERNAL;
        }
 
        return MOBILE_AP_ERROR_NONE;
 }
 
-int _del_data_usage_rule(const char *src, const char *dest)
+int _del_interface_routing(const char *interface, const in_addr_t gateway)
 {
-       if (src == NULL || src[0] == '\0' ||
-                       dest == NULL || dest[0] == '\0' ||
-                       g_strcmp0(src, dest) == 0) {
+       if (interface == NULL || interface[0] == '\0') {
                ERR("Invalid parameter\n");
                return MOBILE_AP_ERROR_INVALID_PARAM;
        }
 
        char cmd[MAX_BUF_SIZE] = {0, };
+       struct in_addr addr;
+       char *interface_gw;
+       in_addr_t subnet;
 
-       snprintf(cmd, sizeof(cmd), "%s -D FORWARD "FORWARD_RULE,
-                       IPTABLES, src, dest);
-       DBG("REMOVE IPTABLES RULE : %s\n", cmd);
-       if (_execute_command(cmd)) {
-               ERR("iptables failed : %s\n", cmd);
-               return MOBILE_AP_ERROR_INTERNAL;
-       }
+       addr.s_addr = htonl(gateway);
 
-       snprintf(cmd, sizeof(cmd), "%s -D FORWARD "FORWARD_RULE,
-                       IPTABLES, dest, src);
-       DBG("REMOVE IPTABLES RULE : %s\n", cmd);
+       subnet = inet_netof(addr);
+       addr = inet_makeaddr(subnet, 0);
+       interface_gw = inet_ntoa(addr);
+
+       snprintf(cmd, sizeof(cmd), "%s route del "INTERFACE_ROUTING,
+                       IP_CMD, interface_gw, TETHERING_ROUTING_TABLE, interface);
        if (_execute_command(cmd)) {
-               ERR("iptables failed : %s\n", cmd);
+               ERR("cmd failed : %s\n", cmd);
                return MOBILE_AP_ERROR_INTERNAL;
        }
 
        return MOBILE_AP_ERROR_NONE;
 }
 
-int _get_data_usage(const char *src, const char *dest,
-               unsigned long long *tx, unsigned long long *rx)
+int _add_routing_rule(const char *interface)
 {
-       if (src == NULL || src[0] == '\0' ||
-                       dest == NULL || dest[0] == '\0' ||
-                       tx == NULL || rx == NULL) {
+       if (interface == NULL || interface[0] == '\0') {
                ERR("Invalid parameter\n");
                return MOBILE_AP_ERROR_INVALID_PARAM;
        }
 
        char cmd[MAX_BUF_SIZE] = {0, };
-       char buf[MAX_BUF_SIZE] = {0, };
-       FILE *fp = NULL;
 
-       /* Tx : Src. -> Dest. */
-       snprintf(cmd, sizeof(cmd),
-                       "%s -L FORWARD -vx | %s \"%s[ ]*%s\" | %s '{ print $2 }' > %s",
-                       IPTABLES, GREP, src, dest, AWK, DATA_USAGE_FILE);
-       if (system(cmd) < 0) {
-               ERR("\"cmd\" is failed\n");
+       snprintf(cmd, sizeof(cmd), "%s rule add "SRC_ROUTING_RULE,
+                       IP_CMD, interface, TETHERING_ROUTING_TABLE);
+       if (_execute_command(cmd)) {
+               ERR("cmd failed : %s\n", cmd);
+               return MOBILE_AP_ERROR_INTERNAL;
        }
 
-       /* Rx : Dest. -> Src. */
-       snprintf(cmd, sizeof(cmd),
-                       "%s -L FORWARD -vx | %s \"%s[ ]*%s\" | %s '{ print $2 }' >> %s",
-                       IPTABLES, GREP, dest, src, AWK, DATA_USAGE_FILE);
-       if (system(cmd) < 0) {
-               ERR("\"cmd\" is failed\n");
+       return MOBILE_AP_ERROR_NONE;
+}
+
+int _del_routing_rule(const char *interface)
+{
+       if (interface == NULL || interface[0] == '\0') {
+               ERR("Invalid parameter\n");
+               return MOBILE_AP_ERROR_INVALID_PARAM;
        }
 
-       fp = fopen(DATA_USAGE_FILE, "r");
-       if (fp == NULL) {
-               ERR("%s open failed\n", DATA_USAGE_FILE);
-               ERR("%s\n", strerror(errno));
+       char cmd[MAX_BUF_SIZE] = {0, };
+
+       snprintf(cmd, sizeof(cmd), "%s rule del "SRC_ROUTING_RULE,
+                       IP_CMD, interface, TETHERING_ROUTING_TABLE);
+       if (_execute_command(cmd)) {
+               ERR("cmd failed : %s\n", cmd);
                return MOBILE_AP_ERROR_INTERNAL;
        }
 
-       if (fgets(buf, sizeof(buf), fp) == NULL)
-               *tx = 0LL;
-       else
-               *tx = atoll(buf);
+       return MOBILE_AP_ERROR_NONE;
+}
 
-       if (fgets(buf, sizeof(buf), fp) == NULL)
-               *rx = 0LL;
-       else
-               *rx = atoll(buf);
+int _flush_ip_address(const char *interface)
+{
+       if (interface == NULL || interface[0] == '\0') {
+               ERR("Invalid parameter\n");
+               return MOBILE_AP_ERROR_INVALID_PARAM;
+       }
+
+       char cmd[MAX_BUF_SIZE] = {0, };
 
-       fclose(fp);
-       unlink(DATA_USAGE_FILE);
+       snprintf(cmd, sizeof(cmd), "%s addr flush dev %s",
+                       IP_CMD, interface);
+       if (_execute_command(cmd)) {
+               ERR("cmd failed : %s\n", cmd);
+               return MOBILE_AP_ERROR_INTERNAL;
+       }
 
        return MOBILE_AP_ERROR_NONE;
 }
@@ -446,7 +461,7 @@ int _execute_command(const char *cmd)
        pid_t pid = 0;
        gchar **args = NULL;
 
-       DBG("cmd : %s\n", cmd);
+       SDBG("CMD : %s\n", cmd);
 
        args = g_strsplit_set(cmd, " ", -1);
        if (!args) {
@@ -467,8 +482,6 @@ int _execute_command(const char *cmd)
                ERR("Should never get here!\n");
                return EXIT_FAILURE;
        } else {
-               DBG("child pid : %d\n", pid);
-
                /* Need to add timeout */
                waitpid(pid, &status, 0);
                g_strfreev(args);
@@ -479,7 +492,6 @@ int _execute_command(const char *cmd)
                                ERR("child return : %d\n", exit_status);
                                return EXIT_FAILURE;
                        }
-                       DBG("child terminated normally\n");
                        return EXIT_SUCCESS;
                } else {
                        ERR("child is terminated without exit\n");
@@ -505,7 +517,7 @@ int _get_tethering_type_from_ip(const char *ip, mobile_ap_type_e *type)
        in_addr_t subnet;
 
        if (inet_aton(ip, &addr) == 0) {
-               ERR("Address : %s is invalid\n", ip);
+               SERR("Address : %s is invalid\n", ip);
                return MOBILE_AP_ERROR_INVALID_PARAM;
        }
        subnet = inet_netof(addr);
@@ -526,7 +538,10 @@ int _get_tethering_type_from_ip(const char *ip, mobile_ap_type_e *type)
        }
 
        if (subnet == subnet_wifi) {
-               *type = MOBILE_AP_TYPE_WIFI;
+               if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
+                       *type = MOBILE_AP_TYPE_WIFI;
+               else
+                       *type = MOBILE_AP_TYPE_WIFI_AP;
                return MOBILE_AP_ERROR_NONE;
        } else if (subnet >= subnet_bt_min && subnet <= subnet_bt_max) {
                *type = MOBILE_AP_TYPE_BT;
@@ -536,6 +551,7 @@ int _get_tethering_type_from_ip(const char *ip, mobile_ap_type_e *type)
                return MOBILE_AP_ERROR_NONE;
        }
 
-       ERR("Tethering type cannot be decided from %s\n", ip);
+       SERR("Tethering type cannot be decided from %s\n", ip);
+
        return MOBILE_AP_ERROR_INVALID_PARAM;
 }
diff --git a/src/mobileap_connman.c b/src/mobileap_connman.c
deleted file mode 100644 (file)
index d89cba2..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * mobileap-agent
- *
- * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
- * All rights reserved.
- *
- * Contact: Hocheol Seo <hocheol.seo@samsung.com>,
- *          Injun Yang <injun.yang@samsung.com>,
- *          Seungyoun Ju <sy39.ju@samsung.com>
- *
- * Copyright (C) 2011-2012  Intel Corporation. All rights reserved.
- *
- * Contact: Guoqiang Liu <guoqiangx.liu@intel.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-#include <stdio.h>
-#include <glib.h>
-#include <gio/gio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "mobileap_connman.h"
-
-gint __enable_tethering(const gchar *path, const gchar *ssid,
-               const gchar *security, const gchar *key, gint hide_mode)
-{
-       gint ret = MOBILE_AP_ERROR_NONE;
-       const gchar *psk = NULL;
-       gboolean hidden = hide_mode ? TRUE:FALSE;
-       GError *error = NULL;
-       GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_NONE
-               |G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
-               |G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS;
-       GDBusProxy *technology_proxy = NULL;
-
-       if (path == NULL) {
-               ERR("Invalid param\n");
-               ret = MOBILE_AP_ERROR_INTERNAL;
-               goto done;
-       }
-
-       technology_proxy = g_dbus_proxy_new_for_bus_sync(
-                                       G_BUS_TYPE_SYSTEM,
-                                       flags,
-                                       NULL,
-                                       CONNMAN_SERVICE,
-                                       path,
-                                       CONNMAN_TECHNOLOGY_INTERFACE,
-                                       NULL,
-                                       &error);
-       if (!technology_proxy) {
-               ERR("Couldn't create the proxy object: %s\n",
-                                       error->message);
-               g_error_free(error);
-               ret = MOBILE_AP_ERROR_INTERNAL;
-               goto done;
-       }
-
-       if (ssid != NULL && key != NULL && security != NULL) {
-               if (strcmp(security, "open") == 0)
-                       psk = "";
-               else
-                       psk = key;
-
-               g_dbus_proxy_call_sync(technology_proxy, "SetProperty",
-                                       g_variant_new("(sv)",
-                                       "TetheringIdentifier",
-                                       g_variant_new_string(ssid)),
-                                       G_DBUS_CALL_FLAGS_NONE,
-                                       -1,
-                                       NULL,
-                                       &error);
-               if (error) {
-                       ERR("SetProperty failed[%s]", error->message);
-                       g_error_free(error);
-                       ret = MOBILE_AP_ERROR_INTERNAL;
-                       goto done;
-               }
-
-               g_dbus_proxy_call_sync(technology_proxy, "SetProperty",
-                                       g_variant_new("(sv)",
-                                       "TetheringPassphrase",
-                                       g_variant_new_string(psk)),
-                                       G_DBUS_CALL_FLAGS_NONE,
-                                       -1,
-                                       NULL,
-                                       &error);
-               if (error) {
-                       ERR("SetProperties failed[%s]", error->message);
-                       g_error_free(error);
-                       ret = MOBILE_AP_ERROR_INTERNAL;
-                       goto done;
-               }
-
-               g_dbus_proxy_call_sync(technology_proxy, "SetProperty",
-                                       g_variant_new("(sv)",
-                                       "Hidden",
-                                       g_variant_new_boolean(hidden)),
-                                       G_DBUS_CALL_FLAGS_NONE,
-                                       -1,
-                                       NULL,
-                                       &error);
-               if (error) {
-                       ERR("SetProperties failed[%s]", error->message);
-                       g_error_free(error);
-                       ret = MOBILE_AP_ERROR_INTERNAL;
-                       goto done;
-               }
-       }
-
-       g_dbus_proxy_call_sync(technology_proxy, "SetProperty",
-                                       g_variant_new("(sv)",
-                                       "Tethering",
-                                       g_variant_new_boolean(TRUE)),
-                                       G_DBUS_CALL_FLAGS_NONE,
-                                       -1,
-                                       NULL,
-                                       &error);
-       if (error) {
-               ERR("SetProperties failed[%s]", error->message);
-               g_error_free(error);
-               ret = MOBILE_AP_ERROR_INTERNAL;
-               goto done;
-       }
-
-done:
-       return ret;
-}
-
-gint __disable_tethering(const gchar *path)
-{
-       gint ret = MOBILE_AP_ERROR_NONE;
-       GError *error = NULL;
-       GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_NONE
-               |G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
-               |G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS;
-       GDBusProxy *technology_proxy = NULL;
-
-       if (path == NULL) {
-               ERR("Invalid param\n");
-               ret = MOBILE_AP_ERROR_INTERNAL;
-               goto done;
-       }
-
-       technology_proxy = g_dbus_proxy_new_for_bus_sync(
-                                       G_BUS_TYPE_SYSTEM,
-                                       flags,
-                                       NULL,
-                                       CONNMAN_SERVICE ,
-                                       path,
-                                       CONNMAN_TECHNOLOGY_INTERFACE,
-                                       NULL,
-                                       &error);
-       if (!technology_proxy) {
-               ERR("Couldn't create the proxy object: %s\n",
-                               error->message);
-               g_error_free(error);
-               ret = MOBILE_AP_ERROR_INTERNAL;
-               goto done;
-       }
-
-       g_dbus_proxy_call_sync(technology_proxy, "SetProperty",
-                                       g_variant_new("(sv)",
-                                       "Tethering",
-                                       g_variant_new_boolean(FALSE)),
-                                       G_DBUS_CALL_FLAGS_NONE,
-                                       -1,
-                                       NULL,
-                                       &error);
-       if (error) {
-               ERR("SetProperties failed[%s]", error->message);
-               g_error_free(error);
-               ret = MOBILE_AP_ERROR_INTERNAL;
-               goto done;
-       }
-
-done:
-       return ret;
-}
-
-static const gchar *type2string(enum technology_type type)
-{
-       switch (type) {
-       case TECH_TYPE_WIFI:
-               return "wifi";
-       case TECH_TYPE_BLUETOOTH:
-               return "bluetooth";
-       case TECH_TYPE_USB:
-               return "gadget";
-       default:
-               return "unknown";
-       }
-}
-
-gboolean __get_technology_path_by_type(enum technology_type tech_type,
-                                       gchar **path)
-{
-       gboolean ret = TRUE;
-       GError *error = NULL;
-       GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_NONE
-               |G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
-               |G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS;
-       GDBusProxy *manager_proxy = NULL;
-       GVariant *technology_list = NULL;
-       const gchar *type_str = NULL;
-
-       if (path == NULL) {
-               ERR("Invalid param\n");
-               ret = MOBILE_AP_ERROR_INTERNAL;
-               goto done;
-       }
-
-       type_str = type2string(tech_type);
-       if (!g_strcmp0("unknown", type_str)) {
-               ERR("Error Type: %d\n", tech_type);
-               ret = FALSE;
-               goto done;
-       }
-
-       manager_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
-                                       flags,
-                                       NULL,
-                                       CONNMAN_SERVICE,
-                                       CONNMAN_MANAGER_PATH,
-                                       CONNMAN_MANAGER_INTERFACE,
-                                       NULL,
-                                       &error);
-       if (!manager_proxy) {
-               ERR("Couldn't create the proxy: %s\n", error->message);
-               g_error_free(error);
-               ret = FALSE;
-               goto done;
-       }
-
-       technology_list = g_dbus_proxy_call_sync(manager_proxy,
-                                       "GetTechnologies",
-                                       NULL,
-                                       G_DBUS_CALL_FLAGS_NONE,
-                                       -1,
-                                       NULL,
-                                       NULL);
-       if (!technology_list) {
-               ERR("GetTechnologies failed[%s]", error->message);
-               g_error_free(error);
-               ret = FALSE;
-               goto done;
-       }
-
-       if (!g_strcmp0("a(oa{sv})",
-                       g_variant_get_type_string(technology_list))) {
-               ERR("interface mismatch !!!");
-               g_variant_unref(technology_list);
-               ret = FALSE;
-               goto done;
-       }
-
-       GVariantIter iter;
-       GVariant *child;
-
-       g_variant_iter_init(&iter, technology_list);
-       child = g_variant_iter_next_value(&iter);
-       g_variant_iter_init(&iter, child);
-       g_variant_unref(child);
-
-       while ((child = g_variant_iter_next_value(&iter))) {
-               DBG("type '%s'\n", g_variant_get_type_string(child));
-               if (g_variant_is_container(child)) {
-                       GVariantIter iter_t;
-                       GVariant *child_t;
-
-                       g_variant_iter_init(&iter_t, child);
-                       child_t = g_variant_iter_next_value(&iter_t);
-
-                       if (!g_strcmp0("o",
-                                       g_variant_get_type_string(child_t))) {
-                               gsize size;
-                               const gchar *o_path = NULL;
-                               o_path = g_variant_get_string(child_t, &size);
-
-                               DBG("path '%s'\n", o_path);
-                               if (g_str_has_suffix(o_path, type_str)) {
-                                       *path = g_strdup(o_path);
-                                       g_variant_unref(child_t);
-                                       g_variant_unref(child);
-                                       return ret;
-                               }
-                       }
-                       g_variant_unref(child_t);
-               }
-               g_variant_unref(child);
-       }
-       ret = FALSE;
-
-done:
-       return ret;
-}
-
-int connman_enable_tethering(enum technology_type type, const char *ssid,
-                       const char *security, const char *key, int hide_mode)
-{
-       gchar *path = NULL;
-       int ret = MOBILE_AP_ERROR_INTERNAL;
-
-       if (type == TECH_TYPE_WIFI
-               && (ssid == NULL || security == NULL || key == NULL)) {
-               ERR("Invalid param\n");
-               return MOBILE_AP_ERROR_INTERNAL;
-       }
-
-       if (!__get_technology_path_by_type(type, &path)) {
-               ERR("Enable tethering Error, Uknown technology: %d\n", type);
-               return MOBILE_AP_ERROR_INTERNAL;
-       }
-
-       ret = __enable_tethering(path, ssid, security, key, hide_mode);
-
-       g_free(path);
-       return ret;
-}
-
-int connman_disable_tethering(enum technology_type type)
-{
-       gchar *path = NULL;
-       int ret = MOBILE_AP_ERROR_INTERNAL;
-
-       if (!__get_technology_path_by_type(type, &path)) {
-               ERR("Disable tethering Error, Uknown technology: %d\n", type);
-               return MOBILE_AP_ERROR_INTERNAL;
-       }
-
-       ret = __disable_tethering(path);
-
-       g_free(path);
-       return ret;
-}
index b23e147..e30a29a 100644 (file)
@@ -1,40 +1,37 @@
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
 #include <glib.h>
 #include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
+#include <stdlib.h>
 
-#include "mobileap_agent.h"
+#include "mobileap_softap.h"
 #include "mobileap_common.h"
 #include "mobileap_bluetooth.h"
 #include "mobileap_wifi.h"
 #include "mobileap_usb.h"
 #include "mobileap_notification.h"
+#include "mobileap_handler.h"
 
-/* Need translation */
-#define MH_NOTI_TIMEOUT_STR    "Tap for setting"
-#define MH_NOTI_TIMEOUT_TITLE  "Disable tethering by timeout"
+#define VCONF_IS_DEVICE_RENAMED_IN_UG "file/private/libug-setting-mobileap-efl/is_device_rename_local"
 
 typedef struct {
-       guint src_id;
+       alarm_id_t alarm_id;
+       time_t end_time;
        GSourceFunc func;
        void *user_data;
 } sp_timeout_handler_t;
@@ -43,42 +40,45 @@ static gboolean __wifi_timeout_cb(gpointer user_data);
 static gboolean __bt_timeout_cb(gpointer user_data);
 
 static sp_timeout_handler_t sp_timeout_handler[MOBILE_AP_TYPE_MAX] = {
-       {0, __wifi_timeout_cb, NULL},
-       {0, NULL, NULL},
-       {0, __bt_timeout_cb, NULL}};
-
+       {0, 0, __wifi_timeout_cb, NULL},
+       {0, 0, NULL, NULL},
+       {0, 0, __bt_timeout_cb, NULL},
+       {0, 0, NULL, NULL}};
 
-
-static void __handle_flight_mode_changed_cb(keynode_t *key, void *data)
+static void __handle_network_cellular_state_changed_cb(keynode_t *key, void *data)
 {
        if (key == NULL) {
                ERR("Parameter is NULL\n");
                return;
        }
 
-       TetheringObject *obj = (TetheringObject *)data;
+       Tethering *obj = (Tethering *)data;
        int vconf_key = 0;
 
-       if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
-               DBG("Wi-Fi tethering is not enabled\n");
+       if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI | MOBILE_AP_STATE_WIFI_AP)) {
                return;
        }
 
-       if (vconf_keynode_get_type(key) != VCONF_TYPE_BOOL) {
+       if (vconf_keynode_get_type(key) != VCONF_TYPE_INT) {
                ERR("Invalid vconf key type\n");
                return;
        }
 
-       vconf_key = vconf_keynode_get_bool(key);
-       DBG("key = %s, value = %d(bool)\n",
+       vconf_key = vconf_keynode_get_int(key);
+       SDBG("key = %s, value = %d(int)\n",
                        vconf_keynode_get_name(key), vconf_key);
 
-       if (vconf_key == FALSE)
+       if (vconf_key != VCONFKEY_NETWORK_CELLULAR_FLIGHT_MODE)
                return;
 
-       DBG("Flight mode\n");
-       _disable_wifi_tethering(obj);
-       _emit_mobileap_dbus_signal(obj, E_SIGNAL_FLIGHT_MODE, NULL);
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
+               _disable_wifi_tethering(obj);
+       else if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP))
+               _disable_wifi_ap(obj);
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_USB))
+               _disable_usb_tethering(obj);
+
+       tethering_emit_flight_mode(obj);
 
        return;
 }
@@ -90,11 +90,12 @@ static void __handle_device_name_changed_cb(keynode_t *key, void *data)
                return;
        }
 
-       TetheringObject *obj = (TetheringObject *)data;
+       Tethering *obj = (Tethering *)data;
        char *vconf_key = NULL;
+       softap_settings_t *new_settings = _get_softap_settings();
+       softap_security_type_e sec_type;
 
-       if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
-               DBG("Wi-Fi hotspot is not enabled\n");
+       if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI | MOBILE_AP_STATE_WIFI_AP)) {
                return;
        }
 
@@ -102,16 +103,46 @@ static void __handle_device_name_changed_cb(keynode_t *key, void *data)
                ERR("Invalid vconf key type\n");
                return;
        }
-
        vconf_key = vconf_keynode_get_str(key);
-       DBG("key = %s, value = %s(str)\n",
-                       vconf_keynode_get_name(key), vconf_key);
 
-       if (g_strcmp0(vconf_key, obj->ssid) == 0) {
-               DBG("ssid is not changed\n");
-       } else {
-               DBG("ssid is changed\n");
-               _disable_wifi_tethering(obj);
+       if (g_strcmp0(vconf_key, new_settings->ssid) != 0) {
+               DBG("Device name is changed\n");
+               if (!g_strcmp0(new_settings->security_type, SOFTAP_SECURITY_TYPE_WPA2_PSK_STR)) {
+                       sec_type = SOFTAP_SECURITY_TYPE_WPA2_PSK;
+               } else {
+                       sec_type = SOFTAP_SECURITY_TYPE_OPEN;
+               }
+               if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
+                       _reload_softap_settings(obj, vconf_key, new_settings->key,
+                                       new_settings->hide_mode, sec_type);
+               } else if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
+                       _reload_softap_settings_for_ap(obj, vconf_key, new_settings->key,
+                                       new_settings->hide_mode, sec_type);
+               }
+       }
+       return;
+}
+
+static void __handle_language_changed_cb(keynode_t *key, void *data)
+{
+       if (key == NULL || data == NULL) {
+               ERR("Parameter is NULL\n");
+               return;
+       }
+
+       char *language = NULL;
+
+       if (vconf_keynode_get_type(key) != VCONF_TYPE_STRING) {
+               ERR("Invalid vconf key type\n");
+               return;
+       }
+
+       language = vconf_get_str(VCONFKEY_LANGSET);
+       if (language) {
+               setenv("LANG", language, 1);
+               setenv("LC_MESSAGES",  language, 1);
+               setlocale(LC_ALL, language);
+               free(language);
        }
 
        return;
@@ -125,10 +156,12 @@ void _register_vconf_cb(void *user_data)
        }
 
        vconf_reg_t vconf_reg[] = {
-               {VCONFKEY_TELEPHONY_FLIGHT_MODE,
-                       __handle_flight_mode_changed_cb, NULL},
+               {VCONFKEY_NETWORK_CELLULAR_STATE,
+                       __handle_network_cellular_state_changed_cb, NULL},
                {VCONFKEY_SETAPPL_DEVICE_NAME_STR,
                        __handle_device_name_changed_cb, NULL},
+               {VCONFKEY_LANGSET,
+                       __handle_language_changed_cb, NULL},
                {NULL, NULL, NULL}
        };
 
@@ -136,7 +169,6 @@ void _register_vconf_cb(void *user_data)
        int ret = 0;
 
        while (vconf_reg[i].key != NULL && vconf_reg[i].cb != NULL) {
-               DBG("Register [%d] : %s\n", i, vconf_reg[i].key);
                ret = vconf_notify_key_changed(vconf_reg[i].key,
                                        vconf_reg[i].cb, user_data);
                if (ret != 0) {
@@ -157,18 +189,15 @@ void _register_vconf_cb(void *user_data)
        return;
 }
 
-void _unregister_vconf_cb(void *user_data)
+void _unregister_vconf_cb(void)
 {
-       if (user_data == NULL) {
-               ERR("Invalid param\n");
-               return;
-       }
-
        vconf_reg_t vconf_reg[] = {
-               {VCONFKEY_TELEPHONY_FLIGHT_MODE,
-                       __handle_flight_mode_changed_cb, NULL},
+               {VCONFKEY_NETWORK_CELLULAR_STATE,
+                       __handle_network_cellular_state_changed_cb, NULL},
                {VCONFKEY_SETAPPL_DEVICE_NAME_STR,
                        __handle_device_name_changed_cb, NULL},
+               {VCONFKEY_LANGSET,
+                       __handle_language_changed_cb, NULL},
                {NULL, NULL, NULL}
        };
 
@@ -176,7 +205,6 @@ void _unregister_vconf_cb(void *user_data)
        int ret = 0;
 
        while (vconf_reg[i].key != NULL && vconf_reg[i].cb != NULL) {
-               DBG("Register [%d] : %s\n", i, vconf_reg[i].key);
                ret = vconf_ignore_key_changed(vconf_reg[i].key,
                                vconf_reg[i].cb);
                if (ret != 0) {
@@ -197,7 +225,7 @@ static gboolean __wifi_timeout_cb(gpointer data)
                return FALSE;
        }
 
-       TetheringObject *obj = (TetheringObject *)data;
+       Tethering *obj = (Tethering *)data;
 
        if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI) == FALSE) {
                ERR("There is no conn. via Wi-Fi tethernig. But nothing to do\n");
@@ -205,12 +233,9 @@ static gboolean __wifi_timeout_cb(gpointer data)
        }
 
        _disable_wifi_tethering(obj);
-       _emit_mobileap_dbus_signal(obj,
-                       E_SIGNAL_WIFI_TETHER_OFF, SIGNAL_MSG_TIMEOUT);
-
-       _create_timeout_noti(MH_NOTI_TIMEOUT_STR, MH_NOTI_TIMEOUT_TITLE,
-                       MH_NOTI_ICON_PATH);
-
+       tethering_emit_wifi_off(obj, SIGNAL_MSG_TIMEOUT);
+       //_launch_toast_popup(MOBILE_AP_TETHERING_TIMEOUT_TOAST_POPUP);
+       _create_timeout_noti(MH_NOTI_ICON_WIFI);
        DBG("-\n");
        return FALSE;
 }
@@ -223,7 +248,7 @@ static gboolean __bt_timeout_cb(gpointer data)
                return FALSE;
        }
 
-       TetheringObject *obj = (TetheringObject *)data;
+       Tethering *obj = (Tethering *)data;
 
        if (_mobileap_is_enabled(MOBILE_AP_STATE_BT) == FALSE) {
                ERR("There is no conn. via BT tethering. But nothing to do\n");
@@ -231,20 +256,103 @@ static gboolean __bt_timeout_cb(gpointer data)
        }
 
        _disable_bt_tethering(obj);
-       _emit_mobileap_dbus_signal(obj,
-                       E_SIGNAL_BT_TETHER_OFF, SIGNAL_MSG_TIMEOUT);
-
-       _create_timeout_noti(MH_NOTI_TIMEOUT_STR, MH_NOTI_TIMEOUT_TITLE,
-                       MH_NOTI_ICON_PATH);
+       tethering_emit_bluetooth_off(obj, SIGNAL_MSG_TIMEOUT);
+       //_launch_toast_popup(MOBILE_AP_TETHERING_TIMEOUT_TOAST_POPUP);
+       _create_timeout_noti(MH_NOTI_ICON_BT);
        DBG("-\n");
        return FALSE;
 }
 
+static sp_timeout_handler_t *__find_next_timeout(void)
+{
+       sp_timeout_handler_t *next_timeout = &sp_timeout_handler[MOBILE_AP_TYPE_WIFI];
+       mobile_ap_type_e i;
+
+       for (i = MOBILE_AP_TYPE_USB; i < MOBILE_AP_TYPE_MAX; i++) {
+               if (sp_timeout_handler[i].end_time == 0)
+                       continue;
+
+               if (sp_timeout_handler[i].end_time < next_timeout->end_time ||
+                               next_timeout->end_time == 0)
+                       next_timeout = &sp_timeout_handler[i];
+       }
+
+       return next_timeout;
+}
+
+static void __expire_timeout(sp_timeout_handler_t *sp)
+{
+       if (sp->alarm_id > 0) {
+               alarmmgr_remove_alarm(sp->alarm_id);
+               sp->alarm_id = 0;
+       }
+
+       sp->end_time = 0;
+
+       if (sp->func)
+               sp->func(sp->user_data);
+}
+
+static void __reset_timeout(sp_timeout_handler_t *sp)
+{
+       if (sp->alarm_id > 0) {
+               alarmmgr_remove_alarm(sp->alarm_id);
+               sp->alarm_id = 0;
+       }
+
+       sp->end_time = 0;
+}
+
+int _sp_timeout_handler(alarm_id_t alarm_id, void *user_param)
+{
+       DBG("+\n");
+
+       int ret;
+       time_t now;
+       time_t interval;
+       mobile_ap_type_e i;
+       sp_timeout_handler_t *next_timeout;
+
+       now = time(NULL);
+       for (i = MOBILE_AP_TYPE_WIFI; i < MOBILE_AP_TYPE_MAX; i++) {
+               if (sp_timeout_handler[i].end_time == 0)
+                       continue;
+
+               if (sp_timeout_handler[i].alarm_id == alarm_id) {
+                       sp_timeout_handler[i].alarm_id = 0;
+                       __expire_timeout(&sp_timeout_handler[i]);
+                       continue;
+               }
+
+               interval = (time_t)difftime(sp_timeout_handler[i].end_time, now);
+               if (interval > 0)
+                       continue;
+
+               __expire_timeout(&sp_timeout_handler[i]);
+       }
+
+       next_timeout = __find_next_timeout();
+       if (next_timeout->end_time == 0)
+               return 0;
+
+       interval = (time_t)difftime(next_timeout->end_time, now);
+       ret = alarmmgr_add_alarm(ALARM_TYPE_VOLATILE, interval, 0, NULL,
+                       &next_timeout->alarm_id);
+       if (ret != ALARMMGR_RESULT_SUCCESS) {
+               ERR("alarmmgr_add_alarm is failed. end_time : %d\n",
+                               next_timeout->end_time);
+               return 0;
+       }
+
+       DBG("-\n");
+       return 0;
+}
+
 void _init_timeout_cb(mobile_ap_type_e type, void *user_data)
 {
        DBG("+\n");
+
        if (sp_timeout_handler[type].func == NULL) {
-               DBG("Not supported timeout : type[%d]\n", type);
                return;
        }
 
@@ -253,54 +361,103 @@ void _init_timeout_cb(mobile_ap_type_e type, void *user_data)
                return;
        }
 
-       if (sp_timeout_handler[type].src_id > 0) {
-               DBG("There is already registered timeout source\n");
-               g_source_remove(sp_timeout_handler[type].src_id);
-               sp_timeout_handler[type].src_id = 0;
-       }
-
+       sp_timeout_handler[type].alarm_id = 0;
+       sp_timeout_handler[type].end_time = 0;
        sp_timeout_handler[type].user_data = user_data;
 
        DBG("-\n");
        return;
 }
 
-void _start_timeout_cb(mobile_ap_type_e type)
+void _start_timeout_cb(mobile_ap_type_e type, time_t end_time)
 {
-       DBG("+\n");
+       int ret;
+       time_t interval;
+       mobile_ap_type_e i;
+       sp_timeout_handler_t *next_timeout;
+
        if (sp_timeout_handler[type].func == NULL) {
-               DBG("Not supported timeout : type[%d]\n", type);
                return;
        }
 
-       if (sp_timeout_handler[type].src_id > 0) {
-               ERR("It is not registered or stopped\n");
+       __reset_timeout(&sp_timeout_handler[type]);
+       sp_timeout_handler[type].end_time = end_time;
+
+       next_timeout = __find_next_timeout();
+       if (next_timeout->alarm_id > 0) {
                return;
        }
 
-       sp_timeout_handler[type].src_id = g_timeout_add(TETHERING_CONN_TIMEOUT,
-                       sp_timeout_handler[type].func,
-                       sp_timeout_handler[type].user_data);
+       for (i = MOBILE_AP_TYPE_WIFI; i < MOBILE_AP_TYPE_MAX; i++) {
+               if (sp_timeout_handler[i].alarm_id == 0)
+                       continue;
+
+               __reset_timeout(&sp_timeout_handler[i]);
+       }
+
+       interval = (time_t)difftime(next_timeout->end_time, time(NULL));
+       if (interval <= 0) {
+               __expire_timeout(next_timeout);
+               return;
+       }
+
+       ret = alarmmgr_add_alarm(ALARM_TYPE_VOLATILE, interval, 0, NULL,
+                       &next_timeout->alarm_id);
+       if (ret != ALARMMGR_RESULT_SUCCESS) {
+               ERR("alarmmgr_add_alarm is failed. type : %d, end_time : %d\n",
+                               type, end_time);
+               return;
+       }
 
-       DBG("-\n");
        return;
 }
 
 void _stop_timeout_cb(mobile_ap_type_e type)
 {
        DBG("+\n");
+
+       int ret;
+       time_t interval;
+       mobile_ap_type_e i;
+       sp_timeout_handler_t *next_timeout;
+
        if (sp_timeout_handler[type].func == NULL) {
-               DBG("Not supported timeout : type[%d]\n", type);
                return;
        }
 
-       if (sp_timeout_handler[type].src_id == 0) {
-               ERR("It is not started yet\n");
+       if (sp_timeout_handler[type].alarm_id == 0) {
+               sp_timeout_handler[type].end_time = 0;
                return;
        }
 
-       g_source_remove(sp_timeout_handler[type].src_id);
-       sp_timeout_handler[type].src_id = 0;
+       for (i = MOBILE_AP_TYPE_WIFI; i < MOBILE_AP_TYPE_MAX; i++) {
+               if (sp_timeout_handler[i].end_time != sp_timeout_handler[type].end_time ||
+                               type == i)
+                       continue;
+
+               sp_timeout_handler[i].alarm_id = sp_timeout_handler[type].alarm_id;
+               sp_timeout_handler[type].alarm_id = 0;
+               sp_timeout_handler[type].end_time = 0;
+               return;
+       }
+       __reset_timeout(&sp_timeout_handler[type]);
+
+       next_timeout = __find_next_timeout();
+       if (next_timeout->end_time == 0)
+               return;
+
+       interval = (time_t)difftime(next_timeout->end_time, time(NULL));
+       if (interval <= 0) {
+               __expire_timeout(next_timeout);
+               return;
+       }
+
+       ret = alarmmgr_add_alarm(ALARM_TYPE_VOLATILE, interval, 0, NULL,
+                       &next_timeout->alarm_id);
+       if (ret != ALARMMGR_RESULT_SUCCESS) {
+               ERR("alarmmgr_add_alarm is failed. type : %d, end_time : %d\n",
+                               type, next_timeout->end_time);
+       }
 
        DBG("-\n");
        return;
@@ -308,19 +465,18 @@ void _stop_timeout_cb(mobile_ap_type_e type)
 
 void _deinit_timeout_cb(mobile_ap_type_e type) {
        DBG("+\n");
+
        if (sp_timeout_handler[type].func == NULL) {
-               DBG("Not supported timeout : type[%d]\n", type);
                return;
        }
 
-       if (sp_timeout_handler[type].src_id > 0) {
-               g_source_remove(sp_timeout_handler[type].src_id);
-               sp_timeout_handler[type].src_id = 0;
+       if (sp_timeout_handler[type].alarm_id > 0) {
+               _stop_timeout_cb(type);
        }
 
        sp_timeout_handler[type].user_data = NULL;
+       sp_timeout_handler[type].end_time = 0;
 
        DBG("-\n");
        return;
 }
-
diff --git a/src/mobileap_iptables.c b/src/mobileap_iptables.c
new file mode 100755 (executable)
index 0000000..429cbf2
--- /dev/null
@@ -0,0 +1,329 @@
+/*
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include "mobileap_iptables.h"
+#include "mobileap_softap.h"
+#include "mobileap.h"
+#include "mobileap_common.h"
+
+#define CREATE_CHAIN_STR               "-t %s -N %s"  /* table_name, chain_name */
+#define REDIRECTION_ADD_RULE_STR       "-t %s -A %s -j %s"
+#define REDIRECTION_DEL_RULE_STR       "-t %s -D %s -j %s"
+#define FLUSH_CMD_STR          "-t %s -F %s"
+#define DELETE_CHAIN_STR       "-t %s -X %s"
+#define FORWARD_RULE_WITH_ACTION_STR           "-t %s -A %s -i %s -o %s -j %s"
+#define FORWARD_RULE_WITH_ACTION_AND_STATE_STR "-t %s -A %s -i %s -o %s -m state --state %s -j %s"
+#define MASQUERADE_RULE_STR            "-t %s -A %s -o %s -j MASQUERADE"
+#define PORT_FORWARD_RULE_STR  "-t %s -A %s -i %s -p %s -d %s --dport %d -j DNAT --to %s:%d"
+#define CLAMP_MSS_RULE_STR     "-t %s -A %s -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu"
+#define DEFAULT_RULE_STR       "-t %s -A %s -j %s"
+
+
+int _iptables_create_chain(const char *table_name, const char *chain_name)
+{
+       char cmd[MAX_BUF_SIZE] = { 0, };
+
+       snprintf(cmd, sizeof(cmd), "%s "CREATE_CHAIN_STR, IPTABLES, table_name,
+               chain_name);
+       SDBG("command [%s]\n", cmd);
+       if (_execute_command(cmd)) {
+               SERR("command [%s] failed\n", cmd);
+               return MOBILE_AP_ERROR_INTERNAL;
+       }
+
+       return MOBILE_AP_ERROR_NONE;
+}
+
+int _iptables_flush_rules(const char *table_name, const char *chain_name)
+{
+       char cmd[MAX_BUF_SIZE] = { 0, };
+
+       snprintf(cmd, sizeof(cmd), "%s "FLUSH_CMD_STR, IPTABLES, table_name,
+               chain_name);
+       SDBG("command [%s]\n", cmd);
+       if (_execute_command(cmd)) {
+               SERR("command [%s] failed\n", cmd);
+               return MOBILE_AP_ERROR_INTERNAL;
+       }
+
+       return MOBILE_AP_ERROR_NONE;
+}
+
+int _iptables_delete_chain(const char *table_name, const char *chain_name)
+{
+       char cmd[MAX_BUF_SIZE] = { 0, };
+
+       snprintf(cmd, sizeof(cmd), "%s "DELETE_CHAIN_STR, IPTABLES, table_name,
+               chain_name);
+       SDBG("command [%s]\n", cmd);
+       if (_execute_command(cmd)) {
+               SERR("command [%s] failed\n", cmd);
+               return MOBILE_AP_ERROR_INTERNAL;
+       }
+
+       return MOBILE_AP_ERROR_NONE;
+}
+
+int _iptables_add_rule(iptables_rule_e rule_type, const char *table, const char *chain, ...)
+{
+       if (table == NULL || chain == NULL) {
+               ERR("invalid parameters\n");
+               return MOBILE_AP_ERROR_INVALID_PARAM;
+       }
+
+       va_list ap;
+       char cmd[MAX_BUF_SIZE] = { 0, };
+
+       va_start(ap, chain);
+       switch (rule_type) {
+       case PKT_REDIRECTION_RULE: {
+               char *dst_chain;
+
+               dst_chain = va_arg(ap, char *);
+               if (dst_chain == NULL) {
+                       ERR("invalid parameters\n");
+                       goto ERROR_EXIT;
+               }
+
+               snprintf(cmd, sizeof(cmd), "%s "REDIRECTION_ADD_RULE_STR, IPTABLES,
+                               table, chain, dst_chain);
+               break;
+       }
+
+       case FORWARD_RULE_WITH_ACTION: {
+               char *in_iface = NULL;
+               char *out_iface = NULL;
+               char *action = NULL;
+
+               in_iface = va_arg(ap, char *);
+               out_iface = va_arg(ap, char *);
+               action = va_arg(ap, char *);
+
+               if (in_iface == NULL || out_iface == NULL || action == NULL) {
+                       ERR("invalid parameters\n");
+                       goto ERROR_EXIT;
+               }
+
+               snprintf(cmd, sizeof(cmd), "%s "FORWARD_RULE_WITH_ACTION_STR, IPTABLES,
+                       table, chain, in_iface, out_iface, action);
+               break;
+       }
+
+       case FORWARD_RULE_WITH_ACTION_AND_STATE: {
+               char *in_iface = NULL;
+               char *out_iface = NULL;
+               char *action = NULL;
+               char *state = NULL;
+
+               in_iface = va_arg(ap, char *);
+               out_iface = va_arg(ap, char *);
+               action = va_arg(ap, char *);
+               state = va_arg(ap, char *);
+
+               if (in_iface == NULL || out_iface == NULL || action == NULL ||
+                               state == NULL) {
+                       ERR("invalid parameters\n");
+                       goto ERROR_EXIT;
+               }
+
+               snprintf(cmd, sizeof(cmd), "%s "FORWARD_RULE_WITH_ACTION_AND_STATE_STR,
+                       IPTABLES, table, chain, in_iface, out_iface, state, action);
+
+               break;
+       }
+
+       case PORT_FW_RULE: {
+               char *ip_iface = NULL;
+               char *proto = NULL;
+               char *org_ip = NULL;
+               char *final_ip = NULL;
+               unsigned short org_port = 0;
+               unsigned short final_port = 0;
+
+               ip_iface = va_arg(ap, char *);
+               proto = va_arg(ap, char *);
+               org_ip = va_arg(ap, char *);
+               final_ip = va_arg(ap, char *);
+               org_port = va_arg(ap, int);
+               final_port = va_arg(ap, int);
+
+               if (ip_iface == NULL || proto == NULL || org_ip == NULL ||
+                               final_ip == NULL) {
+                       ERR("invalid parameters\n");
+                       goto ERROR_EXIT;
+               }
+
+               snprintf(cmd, sizeof(cmd), "%s "PORT_FORWARD_RULE_STR,
+                       IPTABLES, table, chain, ip_iface, proto,
+                       org_ip, org_port, final_ip, final_port);
+               break;
+       }
+
+       case MASQ_RULE: {
+               char *ext_iface = NULL;
+
+               ext_iface = va_arg(ap, char *);
+
+               if (ext_iface == NULL) {
+                       ERR("invalid parameters\n");
+                       goto ERROR_EXIT;
+               }
+
+               snprintf(cmd, sizeof(cmd), "%s "MASQUERADE_RULE_STR, IPTABLES,
+                               table, chain, ext_iface);
+               break;
+       }
+
+       case CLAMP_MSS_RULE: {
+               snprintf(cmd, sizeof(cmd), "%s "CLAMP_MSS_RULE_STR, IPTABLES,
+                       table, chain);
+               break;
+       }
+
+       case DEFAULT_RULE: {
+               char *action;
+
+               action = va_arg(ap, char *);
+
+               if (action == NULL) {
+                       ERR("invalid parameters\n");
+                       goto ERROR_EXIT;
+               }
+
+               snprintf(cmd, sizeof(cmd), "%s "DEFAULT_RULE_STR, IPTABLES,
+                       table, chain, action);
+               break;
+       }
+
+       default:
+               ERR("case not supported\n");
+               goto ERROR_EXIT;
+       }
+
+       if (_execute_command(cmd)) {
+               SERR("command [%s] failed\n", cmd);
+               goto ERROR_EXIT;
+       }
+
+       va_end(ap);
+       return MOBILE_AP_ERROR_NONE;
+
+ERROR_EXIT:
+       va_end(ap);
+       return MOBILE_AP_ERROR_INVALID_PARAM;
+}
+
+int _iptables_delete_rule(iptables_rule_e rule_type, const char *table, const char *chain, ...)
+{
+       va_list ap;
+       char cmd[MAX_BUF_SIZE] = { 0, };
+
+       va_start(ap, chain);
+       switch (rule_type) {
+       case PKT_REDIRECTION_RULE: {
+               char *dst_chain = NULL;
+
+               dst_chain = va_arg(ap, char *);
+               snprintf(cmd, sizeof(cmd), "%s "REDIRECTION_DEL_RULE_STR, IPTABLES,
+                       table, chain, dst_chain);
+               break;
+       }
+       default:
+               ERR("case not supported\n");
+               goto ERROR_EXIT;
+       }
+
+       if (_execute_command(cmd)) {
+               SERR("command [%s] failed\n", cmd);
+               return MOBILE_AP_ERROR_INTERNAL;
+       }
+       va_end(ap);
+       return MOBILE_AP_ERROR_NONE;
+
+ERROR_EXIT:
+       va_end(ap);
+       return MOBILE_AP_ERROR_INTERNAL;
+}
+
+int _get_data_usage(const char *src, const char *dest, unsigned long long *tx,
+               unsigned long long *rx)
+{
+       if (src == NULL || src[0] == '\0' || dest == NULL || dest[0] == '\0' ||
+                       tx == NULL || rx == NULL) {
+               ERR("Invalid parameter\n");
+               return MOBILE_AP_ERROR_INVALID_PARAM;
+       }
+
+       char cmd[MAX_BUF_SIZE] = {0, };
+       char buf[MAX_BUF_SIZE] = {0, };
+       FILE *fp = NULL;
+
+       /* Tx : Src. -> Dest. */
+       snprintf(cmd, sizeof(cmd),
+               "%s -t %s -L %s -vx | %s -v DROP | %s \"%s[ ]*%s\" | %s '{ print $2 }' > %s",
+               IPTABLES, TABLE_FILTER, TETH_FILTER_FW, GREP, GREP, src, dest, AWK, DATA_USAGE_FILE);
+       if (system(cmd) < 0) {
+               ERR("cmd %s is failed\n", cmd);
+       }
+
+       *tx = 0;
+
+       fp = fopen(DATA_USAGE_FILE, "r");
+       if (fp == NULL) {
+               ERR("%s open failed\n", DATA_USAGE_FILE);
+               ERR("%s\n", strerror(errno));
+               return MOBILE_AP_ERROR_INTERNAL;
+       }
+
+       while (fgets(buf, sizeof(buf), fp) != NULL) {
+               *tx += atoll(buf);
+       }
+
+       fclose(fp);
+       unlink(DATA_USAGE_FILE);
+
+       /* Rx : Dest. -> Src. */
+       snprintf(cmd, sizeof(cmd),
+               "%s -t %s -L %s -vx | %s -v DROP | %s \"%s[ ]*%s\" | %s '{ print $2 }' > %s",
+               IPTABLES, TABLE_FILTER, TETH_FILTER_FW, GREP, GREP, dest, src, AWK, DATA_USAGE_FILE);
+       if (system(cmd) < 0) {
+               ERR("cmd %s is failed\n", cmd);
+       }
+
+       *rx = 0;
+
+       fp = fopen(DATA_USAGE_FILE, "r");
+       if (fp == NULL) {
+               ERR("%s open failed\n", DATA_USAGE_FILE);
+               ERR("%s\n", strerror(errno));
+               return MOBILE_AP_ERROR_INTERNAL;
+       }
+
+       while (fgets(buf, sizeof(buf), fp) != NULL) {
+               *rx += atoll(buf);
+       }
+
+       fclose(fp);
+       unlink(DATA_USAGE_FILE);
+
+       return MOBILE_AP_ERROR_NONE;
+}
index 31ca74c..8d544c0 100644 (file)
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
 #include <fcntl.h>
 #include <unistd.h>
 #include <glib.h>
 #include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
-#include <pmapi.h>
+#include <time.h>
+#include <dd-display.h>
 #include <vconf.h>
 #include <net_connection.h>
+#include <appcore-common.h>
+#include <wifi.h>
+#include <alarm.h>
 
-#include "mobileap_agent.h"
+#include "mobileap_softap.h"
 #include "mobileap_handler.h"
 #include "mobileap_common.h"
 #include "mobileap_bluetooth.h"
 #include "mobileap_wifi.h"
 #include "mobileap_usb.h"
 #include "mobileap_network.h"
-
-GType tethering_object_get_type(void);
-#define TETHERING_TYPE_OBJECT (tethering_object_get_type())
-G_DEFINE_TYPE(TetheringObject, tethering_object, G_TYPE_OBJECT)
+#include "mobileap_notification.h"
+#include "mobileap_iptables.h"
 
 GMainLoop *mainloop = NULL;
 int mobileap_state = MOBILE_AP_STATE_NONE;
-DBusConnection *tethering_conn = NULL;
-
-gboolean tethering_init(TetheringObject *obj, GError **error);
-gboolean tethering_deinit(TetheringObject *obj, GError **error);
-gboolean tethering_disable(TetheringObject *obj, DBusGMethodInvocation *context);
-gboolean tethering_get_station_info(TetheringObject *obj,
-               DBusGMethodInvocation *context);
-gboolean tethering_get_data_packet_usage(TetheringObject *obj,
-               DBusGMethodInvocation *context);
-gboolean tethering_set_ip_forward_status(TetheringObject *obj,
-               gint forward_mode,  DBusGMethodInvocation *context);
-gboolean tethering_get_ip_forward_status(TetheringObject *obj, gint *forward_mode);
-
-#include "tethering-server-stub.h"
-
-int ref_agent = 0;
-
-static void tethering_object_init(TetheringObject *obj)
-{
-       DBG("+\n");
-       g_assert(obj != NULL);
-
-       obj->bt_context = NULL;
-       obj->usb_context = NULL;
-       obj->bt_device = NULL;
-       obj->rx_bytes = 0;
-       obj->tx_bytes = 0;
-       obj->transfer_check_count = 0;
-}
 
-static void tethering_object_finalize(GObject *obj)
+GDBusObjectManagerServer *manager_server = NULL;
+guint owner_id = 0;
+GDBusConnection *teth_gdbus_conn = NULL;
+Tethering *tethering_obj = NULL;
+static int init_count = 0;
+guint conn_sig_id = 0;
+guint deleted_sig_id = 0;
+gboolean tethering_disable(Tethering *obj, GDBusMethodInvocation *context);
+gboolean tethering_get_station_info(Tethering *obj,
+               GDBusMethodInvocation *context);
+gboolean tethering_get_data_packet_usage(Tethering *obj,
+               GDBusMethodInvocation *context);
+
+Tethering *_get_tethering_obj(void)
 {
-       DBG("+\n");
-
-       G_OBJECT_CLASS(tethering_object_parent_class)->finalize(obj);
-}
-
-static void tethering_object_class_init(TetheringObjectClass *klass)
-{
-       GObjectClass *object_class = (GObjectClass *)klass;
-       const gchar *signalNames[E_SIGNAL_MAX] = {
-               SIGNAL_NAME_NET_CLOSED,
-               SIGNAL_NAME_STA_CONNECT,
-               SIGNAL_NAME_STA_DISCONNECT,
-               SIGNAL_NAME_WIFI_TETHER_ON,
-               SIGNAL_NAME_WIFI_TETHER_OFF,
-               SIGNAL_NAME_USB_TETHER_ON,
-               SIGNAL_NAME_USB_TETHER_OFF,
-               SIGNAL_NAME_BT_TETHER_ON,
-               SIGNAL_NAME_BT_TETHER_OFF,
-               SIGNAL_NAME_NO_DATA_TIMEOUT,
-               SIGNAL_NAME_LOW_BATTERY_MODE,
-               SIGNAL_NAME_FLIGHT_MODE,
-               SIGNAL_NAME_SECURITY_TYPE_CHANGED,
-               SIGNAL_NAME_SSID_VISIBILITY_CHANGED,
-               SIGNAL_NAME_PASSPHRASE_CHANGED
-       };
-
-       int i = 0;
-
-       g_assert(klass != NULL);
-
-       object_class->finalize = tethering_object_finalize;
-
-       DBG("Creating signals\n");
-
-       for (i = 0; i < E_SIGNAL_MAX; i++) {
-               guint signalId;
-
-               signalId = g_signal_new(signalNames[i],
-                                       G_OBJECT_CLASS_TYPE(klass),
-                                       G_SIGNAL_RUN_LAST,
-                                       0, NULL, NULL,
-                                       g_cclosure_marshal_VOID__STRING,
-                                       G_TYPE_NONE, 1, G_TYPE_STRING);
-               klass->signals[i] = signalId;
-       }
-
-       DBG("Binding to GLib/D-Bus\n");
-
-       dbus_g_object_type_install_info(TETHERING_TYPE_OBJECT,
-                                       &dbus_glib_tethering_object_info);
-}
-
-static void __add_station_info_to_array(gpointer data, gpointer user_data)
-{
-       mobile_ap_station_info_t *si = (mobile_ap_station_info_t *)data;
-       GPtrArray *array = (GPtrArray *)user_data;
-       GValue value = {0, {{0}}};
-
-       g_value_init(&value, DBUS_STRUCT_STATIONS);
-       g_value_take_boxed(&value,
-                       dbus_g_type_specialized_construct(DBUS_STRUCT_STATIONS));
-       dbus_g_type_struct_set(&value, 0, si->interface, 1, si->ip,
-                       2, si->mac, 3, si->hostname, 4, (guint)(si->tm), G_MAXUINT);
-       g_ptr_array_add(array, g_value_get_boxed(&value));
+       return tethering_obj;
 }
 
 gboolean _mobileap_set_state(int state)
 {
        int vconf_ret = 0;
 
-       DBG("Before mobileap_state : %d\n", mobileap_state);
        mobileap_state |= state;
-       DBG("After mobileap_state : %d\n", mobileap_state);
 
        vconf_ret = vconf_set_int(VCONFKEY_MOBILE_HOTSPOT_MODE, mobileap_state);
        if (vconf_ret != 0) {
@@ -187,6 +104,11 @@ gboolean _mobileap_is_enabled_by_type(mobile_ap_type_e type)
                        return TRUE;
                break;
 
+       case MOBILE_AP_TYPE_WIFI_AP:
+               if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP))
+                       return TRUE;
+               break;
+
        default:
                ERR("Unknow type : %d\n", type);
                break;
@@ -199,9 +121,7 @@ gboolean _mobileap_clear_state(int state)
 {
        int vconf_ret = 0;
 
-       DBG("Before mobileap_state : %d\n", mobileap_state);
        mobileap_state &= (~state);
-       DBG("After mobileap_state : %d\n", mobileap_state);
 
        vconf_ret = vconf_set_int(VCONFKEY_MOBILE_HOTSPOT_MODE, mobileap_state);
        if (vconf_ret != 0) {
@@ -212,92 +132,119 @@ gboolean _mobileap_clear_state(int state)
        return TRUE;
 }
 
-static void __block_device_sleep(void)
+gboolean _terminate_mobileap_agent(gpointer user_data)
+{
+       if (mainloop == NULL) {
+               return FALSE;
+       }
+
+       if (!_mobileap_is_disabled()) {
+               DBG("Tethering is enabled\n");
+               return FALSE;
+       }
+
+       if (_is_trying_network_operation()) {
+               DBG("Network operation is going on\n");
+               return FALSE;
+       }
+
+       if (_is_trying_wifi_operation()) {
+               DBG("Wi-Fi operation is going on\n");
+               return FALSE;
+       }
+
+       if (_is_trying_bt_operation()) {
+               DBG("BT operation is going on\n");
+               return FALSE;
+       }
+
+       if (_is_trying_usb_operation()) {
+               DBG("USB operation is going on\n");
+               return FALSE;
+       }
+
+       DBG("All tethering / AP's are turned off\n");
+       g_main_loop_quit(mainloop);
+       mainloop = NULL;
+
+       return FALSE;
+}
+
+void _block_device_sleep(void)
 {
        int ret = 0;
 
-       ret = pm_lock_state(LCD_OFF, STAY_CUR_STATE, 0);
+       ret = display_lock_state(LCD_OFF, STAY_CUR_STATE, 0);
        if (ret < 0)
                ERR("PM control [ERROR] result = %d\n", ret);
        else
                DBG("PM control [SUCCESS]\n");
 }
 
-static void __unblock_device_sleep(void)
+void _unblock_device_sleep(void)
 {
        int ret = 0;
 
-       ret = pm_unlock_state(LCD_OFF, PM_SLEEP_MARGIN);
+       ret = display_unlock_state(LCD_OFF, PM_SLEEP_MARGIN);
        if (ret < 0)
                ERR("PM control [ERROR] result = %d\n", ret);
        else
                DBG("PM control [SUCCESS]\n");
 }
 
-gboolean _init_tethering(TetheringObject *obj)
+int _init_tethering(void)
 {
-       DBG("obj->init_count: %d\n", obj->init_count);
+       int ret = MOBILE_AP_ERROR_NONE;
 
-       if (obj->init_count > 0) {
-               DBG("Already env. is initialized for tethering: %d\n",
-                               obj->init_count);
-               obj->init_count++;
-               return TRUE;
-       }
+       DBG("init_count: %d\n", init_count);
 
-       obj->init_count++;
+       if (init_count > 0) {
+               init_count++;
+               return MOBILE_AP_ERROR_NONE;
+       }
 
-       __block_device_sleep();
+       if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
+               ret = _open_network();
+       }
+       _mh_core_execute_dhcp_server();
 
-       DBG("Open network\n");
-       _open_network();
+       init_count++;
 
-       return TRUE;
+       return ret;
 }
 
-gboolean _deinit_tethering(TetheringObject *obj)
+gboolean _deinit_tethering(void)
 {
-       DBG("obj->init_count: %d\n", obj->init_count);
+       DBG("obj->init_count: %d\n", init_count);
+
+       guint idle_id;
 
-       if (obj->init_count > 1) {
-               DBG("Already deinitialized\n");
-               obj->init_count--;
+       if (init_count > 1) {
+               init_count--;
                return TRUE;
-       } else if (obj->init_count <= 0) {
+       } else if (init_count <= 0) {
                ERR("Already deinitialized\n");
-               obj->init_count = 0;
+               init_count = 0;
                return TRUE;
        }
 
-       obj->init_count = 0;
-
-       _close_network();
-       __unblock_device_sleep();
-
-       return TRUE;
-}
+       init_count = 0;
 
-gboolean tethering_init(TetheringObject *obj, GError **error)
-{
-       DBG("There are [%d] references\n", ++ref_agent);
-
-       return TRUE;
-}
+       _mh_core_terminate_dhcp_server();
 
-gboolean tethering_deinit(TetheringObject *obj, GError **error)
-{
-       if (--ref_agent <= 0 && _mobileap_is_disabled() &&
-                       !_is_trying_network_operation()) {
-               DBG("Terminate mobileap-agent\n");
-               g_main_loop_quit(mainloop);
+       if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
+               _close_network();
        }
 
-       DBG("There are [%d] references\n", ref_agent);
+       idle_id = g_idle_add(_terminate_mobileap_agent, NULL);
+       if (idle_id == 0) {
+               ERR("g_idle_add is failed\n");
+       }
 
        return TRUE;
 }
 
-gboolean tethering_disable(TetheringObject *obj, DBusGMethodInvocation *context)
+gboolean tethering_disable(Tethering *obj, GDBusMethodInvocation *context)
 {
        int ret = MOBILE_AP_ERROR_NONE;
 
@@ -308,7 +255,7 @@ gboolean tethering_disable(TetheringObject *obj, DBusGMethodInvocation *context)
        if (_mobileap_is_disabled()) {
                ERR("Mobile hotspot has not been enabled\n");
                ret = MOBILE_AP_ERROR_NOT_ENABLED;
-               dbus_g_method_return(context, MOBILE_AP_DISABLE_CFM, ret);
+               tethering_complete_disable(obj, context, MOBILE_AP_DISABLE_CFM, ret);
                return FALSE;
        }
 
@@ -316,200 +263,138 @@ gboolean tethering_disable(TetheringObject *obj, DBusGMethodInvocation *context)
        _disable_bt_tethering(obj);
        _disable_usb_tethering(obj);
 
-       dbus_g_method_return(context, MOBILE_AP_DISABLE_CFM, ret);
+       tethering_complete_disable(obj, context, MOBILE_AP_DISABLE_CFM, ret);
 
        return TRUE;
 }
 
-gboolean tethering_get_station_info(TetheringObject *obj,
-                                               DBusGMethodInvocation *context)
+gboolean tethering_get_station_info(Tethering *obj,
+                       GDBusMethodInvocation *context)
 {
        DBG("+\n");
 
-       GPtrArray *array = g_ptr_array_new();
+       GVariant *var = NULL;
 
        g_assert(obj != NULL);
        g_assert(context != NULL);
 
-       _station_info_foreach(__add_station_info_to_array, array);
+       var = _station_info_foreach();
 
-       dbus_g_method_return(context, MOBILE_AP_GET_STATION_INFO_CFM, array);
-       g_ptr_array_free(array, TRUE);
+       g_dbus_method_invocation_return_value(context, var);
+       g_variant_unref(var);
 
        DBG("-\n");
-
        return TRUE;
 }
 
-gboolean tethering_get_data_packet_usage(TetheringObject *obj,
-                                               DBusGMethodInvocation *context)
+gboolean tethering_get_data_packet_usage(Tethering *obj,
+                               GDBusMethodInvocation *context)
 {
        char *if_name = NULL;
+       unsigned long long wifi_tx_bytes = 0;
+       unsigned long long wifi_rx_bytes = 0;
+       unsigned long long bt_tx_bytes = 0;
+       unsigned long long bt_rx_bytes = 0;
+       unsigned long long usb_tx_bytes = 0;
+       unsigned long long usb_rx_bytes = 0;
        unsigned long long tx_bytes = 0;
        unsigned long long rx_bytes = 0;
 
        if (_get_network_interface_name(&if_name) == FALSE) {
-               ERR("No network interface\n");
-               dbus_g_method_return(context, MOBILE_AP_GET_DATA_PACKET_USAGE_CFM,
+               tethering_complete_get_data_packet_usage(obj, context,
+                               MOBILE_AP_GET_DATA_PACKET_USAGE_CFM,
                                0ULL, 0ULL);
                return FALSE;
        }
 
-       if (!_mobileap_is_disabled())
-               _get_data_usage(TETHER_IF, if_name,
-                               &tx_bytes, &rx_bytes);
-       free(if_name);
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
+               _get_data_usage(WIFI_IF, if_name,
+                               &wifi_tx_bytes, &wifi_rx_bytes);
 
-       dbus_g_method_return(context, MOBILE_AP_GET_DATA_PACKET_USAGE_CFM,
-                       tx_bytes, rx_bytes);
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_BT))
+               _get_data_usage(BT_IF_ALL, if_name,
+                               &bt_tx_bytes, &bt_rx_bytes);
 
-       return TRUE;
-}
-
-gboolean tethering_set_ip_forward_status(TetheringObject *obj,
-               gint forward_mode,  DBusGMethodInvocation *context)
-{
-       g_assert(obj != NULL);
-
-       gboolean ret;
-
-       if (forward_mode == 0) {
-               ret = _unset_masquerade();
-       } else {
-               ret = _set_masquerade();
-       }
-
-       dbus_g_method_return(context, ret);
-
-       return TRUE;
-}
-
-gboolean tethering_get_ip_forward_status(TetheringObject *obj, gint *forward_mode)
-{
-       g_assert(obj != NULL);
-
-       int fd;
-       int ret;
-       char value[2] = {0, };
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_USB))
+               _get_data_usage(USB_IF, if_name,
+                               &usb_tx_bytes, &usb_rx_bytes);
+       free(if_name);
 
-       fd = open(IP_FORWARD, O_RDONLY);
-       if (fd < 0) {
-               ERR("open failed\n");
-               return FALSE;
-       }
+       tx_bytes = wifi_tx_bytes + bt_tx_bytes + usb_tx_bytes;
+       rx_bytes = wifi_rx_bytes + bt_rx_bytes + usb_rx_bytes;
 
-       ret = read(fd, value, sizeof(value));
-       if (ret < 0) {
-               ERR("read is failed\n");
-               close(fd);
-               return FALSE;
-       }
-       close(fd);
-
-       *forward_mode = atoi(value);
+       tethering_complete_get_data_packet_usage(obj, context, MOBILE_AP_GET_DATA_PACKET_USAGE_CFM,
+                       tx_bytes, rx_bytes);
 
        return TRUE;
 }
 
-mobile_ap_type_e _mobileap_type_convert(char *type)
+void static __handle_dnsmasq_dhcp_status_changed_cb(GDBusConnection *connection,
+                       const gchar *sender_name, const gchar *object_path,
+                       const gchar *interface_name, const gchar *signal_name,
+                       GVariant *parameters, gpointer user_data)
 {
-       mobile_ap_type_e result = MOBILE_AP_TYPE_MAX;
-       if (type == NULL)
-               return result;
-
-       if (g_strcmp0(type,"wifi") == 0)
-               result = MOBILE_AP_TYPE_WIFI;
-       else if (g_strcmp0(type,"gadget") == 0)
-               result = MOBILE_AP_TYPE_USB;
-       else if (g_strcmp0(type,"bluetooth") == 0)
-               result = MOBILE_AP_TYPE_BT;
-
-       return result;
-}
-
-static DBusHandlerResult __dnsmasq_signal_filter(DBusConnection *conn,
-               DBusMessage *msg, void *user_data)
-{
-       if (!user_data) {
-               ERR("Invalid param\n");
-               return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-       }
-
-       char *ap_type = NULL;
+       DBG("+\n");
        char *ip_addr = NULL;
        char *mac = NULL;
        char *name = NULL;
        char *bt_remote_device_name = NULL;
-       DBusError error;
        mobile_ap_type_e type = MOBILE_AP_TYPE_MAX;
-       TetheringObject *obj = (TetheringObject *)user_data;
        mobile_ap_station_info_t *info = NULL;
        int n_station = 0;
        time_t tm;
 
-       dbus_error_init(&error);
-       if (dbus_message_is_signal(msg, CONNMAN_DBUS_INTERFACE,
-                               "DhcpConnected")) {
-               if (!dbus_message_get_args(msg, &error,
-                                       DBUS_TYPE_STRING, &ap_type,
-                                       DBUS_TYPE_STRING, &ip_addr,
-                                       DBUS_TYPE_STRING, &mac,
-                                       DBUS_TYPE_STRING, &name,
-                                       DBUS_TYPE_INVALID)) {
-                       ERR("Cannot read message, cause: %s\n", error.message);
-                       dbus_error_free(&error);
-                       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-               }
-               DBG("DhcpConnected signal : %s  %s  %s %s\n",
-                                       ap_type, ip_addr, mac, name);
+       if (signal_name == NULL) {
+               ERR("singal name is NULL\n");
+               return;
+       }
+       g_variant_get(parameters, "(sss)",  &ip_addr, &mac, &name);
+       if (!g_strcmp0(signal_name, "DhcpConnected")) {
+               SDBG("DhcpConnected signal : %s  %s %s\n", ip_addr, mac, name);
                /*
+                * DHCP ACK received, destroy timeout if exists
+                */
+               if (ip_addr == NULL || mac == NULL) {
+                       goto EXIT;
+               }
+               _destroy_dhcp_ack_timer(mac);
+
                if (_get_tethering_type_from_ip(ip_addr, &type) != MOBILE_AP_ERROR_NONE)
-                       return DBUS_HANDLER_RESULT_HANDLED;
-               */
-               type = _mobileap_type_convert(ap_type);
-               if (type == MOBILE_AP_TYPE_MAX)
-                       return DBUS_HANDLER_RESULT_HANDLED;
+                       goto EXIT;
 
                if (_mobileap_is_enabled_by_type(type) == FALSE) {
-                       DBG("Tethering[%d] is disabled. Ignore ACK\n", type);
-                       return DBUS_HANDLER_RESULT_HANDLED;
+                       goto EXIT;
                }
 
-               info = (mobile_ap_station_info_t *)malloc(sizeof(mobile_ap_station_info_t));
+               info = (mobile_ap_station_info_t *)g_malloc(sizeof(mobile_ap_station_info_t));
                if (info == NULL) {
                        ERR("malloc failed\n");
-                       return DBUS_HANDLER_RESULT_HANDLED;
+                       goto EXIT;
                }
 
                info->interface = type;
                g_strlcpy(info->ip, ip_addr, sizeof(info->ip));
                g_strlcpy(info->mac, mac, sizeof(info->mac));
-               if (type == MOBILE_AP_TYPE_WIFI || type == MOBILE_AP_TYPE_USB) {
+               if (type == MOBILE_AP_TYPE_WIFI || type == MOBILE_AP_TYPE_USB ||
+                               type == MOBILE_AP_TYPE_WIFI_AP) {
                        if (name[0] == '\0')
-                               g_strlcpy(info->hostname,
-                                               MOBILE_AP_NAME_UNKNOWN,
-                                               sizeof(info->hostname));
+                               info->hostname = g_strdup(MOBILE_AP_NAME_UNKNOWN);
                        else
-                               g_strlcpy(info->hostname, name,
-                                               sizeof(info->hostname));
+                               info->hostname = g_strdup(name);
                } else if (type == MOBILE_AP_TYPE_BT) {
-                       _bt_get_remote_device_name(obj, mac, &bt_remote_device_name);
+                       _bt_get_remote_device_name(mac, &bt_remote_device_name);
                        if (bt_remote_device_name == NULL)
-                               g_strlcpy(info->hostname,
-                                               MOBILE_AP_NAME_UNKNOWN,
-                                               sizeof(info->hostname));
-                       else {
-                               g_strlcpy(info->hostname, bt_remote_device_name,
-                                               sizeof(info->hostname));
-                               free(bt_remote_device_name);
-                       }
+                               info->hostname = g_strdup(MOBILE_AP_NAME_UNKNOWN);
+                       else
+                               info->hostname = bt_remote_device_name;
                }
                time(&tm);
                info->tm = tm;
-
                if (_add_station_info(info) != MOBILE_AP_ERROR_NONE) {
-                       free(info);
-                       return DBUS_HANDLER_RESULT_HANDLED;
+                       ERR("_add_station_info is failed\n");
+                       g_free(info->hostname);
+                       g_free(info);
+                       goto EXIT;
                }
 
                _get_station_count((gconstpointer)type,
@@ -518,138 +403,184 @@ static DBusHandlerResult __dnsmasq_signal_filter(DBusConnection *conn,
                        _stop_timeout_cb(type);
 
                _send_dbus_station_info("DhcpConnected", info);
+       } else if (!g_strcmp0(signal_name, "DhcpLeaseDeleted")) {
+               SDBG("DhcpLeaseDeleted signal : %s %s %s\n", ip_addr, mac, name);
+               _remove_station_info(ip_addr, _slist_find_station_by_ip_addr);
+       } else {
+               SDBG("UNKNOWN member signal\n");
+       }
+EXIT :
+       g_free(ip_addr);
+       g_free(mac);
+       g_free(name);
+       DBG("-\n");
+}
 
-               return DBUS_HANDLER_RESULT_HANDLED;
-       } else if (dbus_message_is_signal(msg, CONNMAN_DBUS_INTERFACE,
-                               "DhcpLeaseDeleted")) {
-               if (!dbus_message_get_args(msg, &error,
-                                       DBUS_TYPE_STRING, &ap_type,
-                                       DBUS_TYPE_STRING, &ip_addr,
-                                       DBUS_TYPE_STRING, &mac,
-                                       DBUS_TYPE_STRING, &name,
-                                       DBUS_TYPE_INVALID)) {
-                       ERR("Cannot read message, cause: %s\n", error.message);
-                       dbus_error_free(&error);
-                       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-               }
+static void on_bus_acquired_cb (GDBusConnection *connection, const gchar *name,
+                               gpointer user_data)
+{
+       DBG("+\n");
+       GDBusInterfaceSkeleton *intf = NULL;
+       teth_gdbus_conn = connection;
 
-               DBG("DhcpLeaseDeleted signal : %s  %s %s %s\n",
-                                       ap_type, ip_addr, mac, name);
+       manager_server = g_dbus_object_manager_server_new(TETHERING_SERVICE_OBJECT_PATH);
+       if(manager_server == NULL) {
+               DBG("Manager server not created.");
+               return;
+       }
+       tethering_obj = tethering_skeleton_new();
+       intf = G_DBUS_INTERFACE_SKELETON(tethering_obj);
+       if (!g_dbus_interface_skeleton_export(intf, connection,
+                       TETHERING_SERVICE_OBJECT_PATH, NULL)) {
+               ERR("Export with path failed");
+       } else {
+               DBG("Export sucessss");
+       }
 
-               _remove_station_info(ip_addr, _slist_find_station_by_ip_addr);
+       g_signal_connect(tethering_obj, "handle-enable-wifi-tethering",
+                       G_CALLBACK(tethering_enable_wifi_tethering), NULL);
+       g_signal_connect(tethering_obj, "handle-enable-bt-tethering",
+                       G_CALLBACK(tethering_enable_bt_tethering), NULL);
+       g_signal_connect(tethering_obj, "handle-enable-usb-tethering",
+                       G_CALLBACK(tethering_enable_usb_tethering), NULL);
+       g_signal_connect(tethering_obj, "handle-disable-wifi-tethering",
+                       G_CALLBACK(tethering_disable_wifi_tethering), NULL);
+       g_signal_connect(tethering_obj, "handle-disable-bt-tethering",
+                       G_CALLBACK(tethering_disable_bt_tethering), NULL);
+       g_signal_connect(tethering_obj, "handle-disable-usb-tethering",
+                       G_CALLBACK(tethering_disable_usb_tethering), NULL);
+       g_signal_connect(tethering_obj, "handle-enable-wifi-ap",
+                       G_CALLBACK(tethering_enable_wifi_ap), NULL);
+
+       g_signal_connect(tethering_obj, "handle-disable-wifi-ap",
+                       G_CALLBACK(tethering_disable_wifi_ap), NULL);
+       g_signal_connect(tethering_obj, "handle-reload-wifi-settings",
+                       G_CALLBACK(tethering_reload_wifi_settings), NULL);
+       g_signal_connect(tethering_obj, "handle-reload-wifi-ap-settings",
+                       G_CALLBACK(tethering_reload_wifi_ap_settings), NULL);
+       g_signal_connect(tethering_obj, "handle-get-station-info",
+                       G_CALLBACK(tethering_get_station_info), NULL);
+       g_signal_connect(tethering_obj, "handle-get-data-packet-usage",
+                       G_CALLBACK(tethering_get_data_packet_usage), NULL);
+
+       _init_network((void *)tethering_obj);
+       _register_vconf_cb((void *)tethering_obj);
 
-               return DBUS_HANDLER_RESULT_HANDLED;
-       }
+       conn_sig_id = g_dbus_connection_signal_subscribe(connection, NULL, DNSMASQ_DBUS_INTERFACE,
+                       "DhcpConnected", NULL, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
+                       __handle_dnsmasq_dhcp_status_changed_cb, NULL, NULL);
+       deleted_sig_id = g_dbus_connection_signal_subscribe(connection, NULL, DNSMASQ_DBUS_INTERFACE,
+                       "DhcpLeaseDeleted", NULL, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
+                       __handle_dnsmasq_dhcp_status_changed_cb, NULL, NULL);
 
-       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+       g_dbus_object_manager_server_set_connection(manager_server, connection);
+       DBG("-\n");
 }
 
-int main(int argc, char **argv)
+static void on_name_acquired_cb(GDBusConnection *connection, const gchar *name,
+               gpointer user_data)
 {
-       TetheringObject *tethering_obj = NULL;
-       DBusError dbus_error;
-       char *rule = "type='signal',interface='"CONNMAN_DBUS_INTERFACE"'";
-       DBusGConnection *tethering_bus = NULL;
-       DBusGProxy *tethering_bus_proxy = NULL;
-       guint result = 0;
-       GError *error = NULL;
-       int mobileap_vconf_key = VCONFKEY_MOBILE_HOTSPOT_MODE_NONE;
-
-#if !GLIB_CHECK_VERSION(2,35,0)
-       g_type_init();
-#endif
+       DBG("+\n");
 
-       if (vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &mobileap_vconf_key)) {
-               ERR("vconf_get_int FAIL\n");
-               mobileap_state = MOBILE_AP_STATE_NONE;
-       } else {
-               ERR("vconf_get_int OK(mobileap_vconf_key value is %d)\n",
-                                mobileap_vconf_key);
-               mobileap_state = mobileap_vconf_key;
-       }
+       DBG("-\n");
+}
 
-       mainloop = g_main_loop_new(NULL, FALSE);
-       if (mainloop == NULL) {
-               ERR("Couldn't create GMainLoop\n");
-               goto failure;
-       }
+static void on_name_lost_db(GDBusConnection *conn, const gchar *name,
+               gpointer user_data)
+{
+       DBG("+\n");
+       /* May service name is already in use */
+       ERR("Service name is already in use");
 
-       tethering_bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
-       if (error != NULL) {
-               ERR("Couldn't connect to system bus[%s]\n", error->message);
-               goto failure;
-       }
+       /* The result of DBus name request is only permitted,
+        *  such as DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER.
+        */
+       exit(2);
 
-       tethering_conn = dbus_g_connection_get_connection(tethering_bus);
+       DBG("-\n");
+}
 
-       DBG("Registering the well-known name (%s)\n", TETHERING_SERVICE_NAME);
+static int __tethering_setup_gdbus(void)
+{
+       DBG("+\n");
 
-       tethering_bus_proxy = dbus_g_proxy_new_for_name(tethering_bus,
-                                                      DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
-       if (tethering_bus_proxy == NULL) {
-               ERR("Failed to get a proxy for D-Bus\n");
-               goto failure;
-       }
+       owner_id = g_bus_own_name(DBUS_BUS_SYSTEM, TETHERING_SERVICE_NAME,
+                               G_BUS_NAME_OWNER_FLAGS_NONE, on_bus_acquired_cb,
+                               on_name_acquired_cb, on_name_lost_db, NULL, NULL);
 
-       if (!dbus_g_proxy_call(tethering_bus_proxy,
-                              "RequestName",
-                              &error,
-                              G_TYPE_STRING,
-                              TETHERING_SERVICE_NAME,
-                              G_TYPE_UINT, 0, G_TYPE_INVALID, G_TYPE_UINT, &result, G_TYPE_INVALID)) {
-               ERR("D-Bus.RequestName RPC failed[%s]\n", error->message);
-               goto failure;
+       if (!owner_id) {
+               ERR("g_bus_own_name is failed\n");
+               return -1;
        }
+       return 0;
+}
+int main(int argc, char **argv)
+{
+       int ret = 0;
 
-       if (result != 1) {
-               ERR("Failed to get the primary well-known name.\n");
-               goto failure;
-       }
+       DBG("+\n");
 
-       g_object_unref(tethering_bus_proxy);
-       tethering_bus_proxy = NULL;
+#if !GLIB_CHECK_VERSION(2,36,0)
+       g_type_init();
+#endif
 
-       tethering_obj = g_object_new(TETHERING_TYPE_OBJECT, NULL);
-       if (tethering_obj == NULL) {
-               ERR("Failed to create one MobileAP instance.\n");
-               goto failure;
+       mainloop = g_main_loop_new(NULL, FALSE);
+       if (mainloop == NULL) {
+               ERR("Couldn't create GMainLoop\n");
+               return 0;
        }
 
-       /* Registering it on the D-Bus */
-       dbus_g_connection_register_g_object(tethering_bus,
-                       TETHERING_SERVICE_OBJECT_PATH, G_OBJECT(tethering_obj));
+       ret = __tethering_setup_gdbus();
+       if (ret < 0) {
+               ERR("tethering_setup_gdbus is failed\n");
+               return 0;
+       }
+       /* Platform modules */
+       if (appcore_set_i18n(MOBILEAP_LOCALE_COMMON_PKG, MOBILEAP_LOCALE_COMMON_RES) < 0) {
+               ERR("appcore_set_i18n is failed\n");
+       }
 
-       DBG("Ready to serve requests.\n");
+       if (vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_MODE, &mobileap_state) < 0) {
+               ERR("vconf_get_int is failed\n");
+               mobileap_state = MOBILE_AP_STATE_NONE;
+       }
 
-       _init_network(NULL);
        _register_wifi_station_handler();
-       _register_vconf_cb((void *)tethering_obj);
 
-       dbus_error_init(&dbus_error);
-       dbus_bus_add_match(tethering_conn, rule, &dbus_error);
-       if (dbus_error_is_set(&dbus_error)) {
-               ERR("Cannot add D-BUS match rule, cause: %s", dbus_error.message);
-               dbus_error_free(&dbus_error);
-               goto failure;
+       ret = wifi_initialize();
+       if (ret != WIFI_ERROR_NONE) {
+               ERR("wifi_initialize() is failed : %d\n", ret);
        }
 
-       DBG("Listening to D-BUS signals from dnsmasq");
-       dbus_connection_add_filter(tethering_conn, __dnsmasq_signal_filter, tethering_obj, NULL);
+       ret = alarmmgr_init(APPNAME);
+       if (ret != ALARMMGR_RESULT_SUCCESS) {
+               ERR("alarmmgr_init(%s) is failed : %d\n", APPNAME, ret);
+       } else {
+               ret = alarmmgr_set_cb(_sp_timeout_handler, NULL);
+               if (ret != ALARMMGR_RESULT_SUCCESS) {
+                       ERR("alarmmgr_set_cb is failed : %d\n", ret);
+               }
+       }
 
        g_main_loop_run(mainloop);
 
-       _unregister_vconf_cb((void *)tethering_obj);
-       _deinit_network();
+       alarmmgr_fini();
 
- failure:
-       ERR("Terminate the mobileap-agent\n");
+       ret = wifi_deinitialize();
+       if (ret != WIFI_ERROR_NONE) {
+               ERR("wifi_deinitialize() is failed : %d\n", ret);
+       }
 
-       if (tethering_bus)
-               dbus_g_connection_unref(tethering_bus);
-       if (tethering_bus_proxy)
-               g_object_unref(tethering_bus_proxy);
-       if (tethering_obj)
-               g_object_unref(tethering_obj);
+       _unregister_vconf_cb();
+       _unregister_wifi_station_handler();
+       _deinit_network();
 
+       g_dbus_connection_signal_unsubscribe(teth_gdbus_conn, conn_sig_id);
+       g_dbus_connection_signal_unsubscribe(teth_gdbus_conn, deleted_sig_id);
+
+       g_object_unref(tethering_obj);
+       g_bus_unown_name(owner_id);
+       g_object_unref(manager_server);
+       DBG("-\n");
        return 0;
 }
index 1b9972b..3f30fb7 100644 (file)
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
 #include <stdio.h>
+#include <unistd.h>
 #include <stdlib.h>
+#include <glib.h>
+#include <string.h>
 #include <net_connection.h>
 
-#include "mobileap_agent.h"
+#include "mobileap_softap.h"
 #include "mobileap_common.h"
 #include "mobileap_network.h"
+#include "mobileap_wifi.h"
+#include "mobileap_bluetooth.h"
+#include "mobileap_usb.h"
+#include "mobileap_iptables.h"
+
+typedef enum {
+       __NO_SERVICE,
+       __INTERNET,
+       __TETHERING_ONLY
+} tethering_cellular_service_type_e;
+
+typedef struct {
+       connection_profile_h handle;
+       tethering_cellular_service_type_e svc_type;
+} tethering_cellular_profile_s;
+
+#define        MH_PORT_FORWARD_CONF_FILEPATH   "/tmp/mobileap_agent_port_forward_info"
+#define        MH_MAX_PORT_FORWARD_RULE_LEN    64      /* interface(10) protocol(10) ip(15):port(5) ip(15):port(5) */
+#define        MH_MAX_NO_OF_PORT_FORWARD_RULE  64
+
+typedef struct {
+       char *input_interface;
+       char *proto;
+       char *org_dest_ip;
+       unsigned short org_dest_port;
+       char *new_dest_ip;
+       unsigned short new_dest_port;
+} port_forward_info_s;
+
+static Tethering *obj = NULL;
+static connection_h connection = NULL;
+static tethering_cellular_profile_s c_prof = {NULL, __NO_SERVICE};
+static guint net_timeout_id;
+static connection_profile_h tethered_prof = NULL;
+static GSList *port_forward_info = NULL;
 
 
-extern int ref_agent;
-static connection_h connection = NULL;
-static connection_profile_h cprof = NULL;
+static gboolean __try_to_open_tethering_profile(gpointer user_data);
 
-static void __print_profile(connection_profile_h profile)
+static mobile_ap_error_code_e __get_conn_error(int conn_error)
 {
-       if (profile == NULL)
-               return;
+       mobile_ap_error_code_e err = MOBILE_AP_ERROR_NONE;
+
+       switch (conn_error) {
+       case CONNECTION_ERROR_NONE:
+               err = MOBILE_AP_ERROR_NONE;
+               break;
+
+       case CONNECTION_ERROR_OUT_OF_MEMORY:
+               err = MOBILE_AP_ERROR_RESOURCE;
+               break;
+
+       case CONNECTION_ERROR_INVALID_OPERATION:
+               err = MOBILE_AP_ERROR_INTERNAL;
+               break;
+
+       case CONNECTION_ERROR_INVALID_PARAMETER:
+               err = MOBILE_AP_ERROR_INVALID_PARAM;
+               break;
+
+       case CONNECTION_ERROR_ALREADY_EXISTS:
+               err = MOBILE_AP_ERROR_ALREADY_ENABLED;
+               break;
+
+#ifndef TIZEN_TV
+       case CONNECTION_ERROR_PERMISSION_DENIED:
+               err = MOBILE_AP_ERROR_PERMISSION_DENIED;
+               break;
+#endif
+
+       case CONNECTION_ERROR_DHCP_FAILED:
+               err = MOBILE_AP_ERROR_DHCP;
+               break;
+
+       case CONNECTION_ERROR_NOW_IN_PROGRESS:
+               err = MOBILE_AP_ERROR_IN_PROGRESS;
+               break;
+
+       default:
+               ERR("Not defined error : %d\n", conn_error);
+               err = MOBILE_AP_ERROR_INTERNAL;
+               break;
+       }
+
+       return err;
+}
+
+static gboolean __is_valid_ipv4_addr(const char *ip)
+{
+       int i;
+       int len;
+       int dot_count = 0;
+       int addr;
+       char tmp_ip[16] = {0, };
+       char *p = tmp_ip;
+
+       if (ip == NULL)
+               return FALSE;
+
+       len = strlen(ip);
+       if (len > 15 /* 255.255.255.255 */ || len < 7 /* 0.0.0.0 */)
+               return FALSE;
+       g_strlcpy(tmp_ip, ip, sizeof(tmp_ip));
+
+       for (i = 0; i <= len; i++) {
+               if (tmp_ip[i] == '.') {
+                       if (++dot_count > 3)
+                               return FALSE;
+                       if (&tmp_ip[i] == p)
+                               return FALSE;
+                       tmp_ip[i] = '\0';
+                       addr = atoi(p);
+                       if (addr < 0 || addr > 255)
+                               return FALSE;
+                       p = &tmp_ip[i + 1];
+               } else if (tmp_ip[i] == '\0') {
+                       if (&tmp_ip[i] == p)
+                               return FALSE;
+                       addr = atoi(p);
+                       if (addr < 0 || addr > 255)
+                               return FALSE;
+                       break;
+               } else if (tmp_ip[i] < '0' || tmp_ip[i] > '9')
+                       return FALSE;
+       }
+
+       if (dot_count != 3)
+               return FALSE;
+
+       return TRUE;
+}
+
+static void __clear_port_forward_info(void)
+{
+       GSList *l;
+       GSList *temp_l;
+       port_forward_info_s *pf;
+
+       for (l = port_forward_info; l; ) {
+               pf = (port_forward_info_s *)l->data;
+               if (pf) {
+                       g_free(pf->new_dest_ip);
+                       g_free(pf->org_dest_ip);
+                       g_free(pf->proto);
+                       g_free(pf->input_interface);
+                       g_free(pf);
+               }
+
+               temp_l = l;
+               l = g_slist_next(l);
+               port_forward_info = g_slist_delete_link(port_forward_info, temp_l);
+       }
+
+       return;
+}
+
+static gboolean __read_port_forward_info(const char *conf_file)
+{
+       if (conf_file == NULL) {
+               ERR("Invalid parameter\n");
+               return FALSE;
+       }
+
+       DBG("+\n");
+
+       FILE *fp;
+       char buf[MH_MAX_PORT_FORWARD_RULE_LEN];
+       port_forward_info_s *pf;
+       int no_of_rule = 0;
+
+       __clear_port_forward_info();
+
+       fp = fopen(conf_file, "r");
+       if (fp == NULL) {
+               ERR("fopen is failed : %s\n", strerror(errno));
+               return FALSE;
+       }
+
+       while (fgets(buf, sizeof(buf), fp)) {
+               int i;
+               char *token;
+               char *saveptr1 = NULL;
+               char *saveptr2 = NULL;
+
+               char *input_interface;
+               char *proto;
+               char *dest_ip[2];
+               char *dest_port[2];
+
+               if (no_of_rule++ >= MH_MAX_NO_OF_PORT_FORWARD_RULE) {
+                       DBG("There are too many rules\n");
+                       break;
+               }
+
+               /* "Input interface" "Protocol" "Original destination IP:Port" "New destination IP:Port" */
+               /* pdp0 udp 10.90.50.38:23 192.168.43.10:23 */
+
+               input_interface = strtok_r(buf, " ", &saveptr1);
+               if (input_interface == NULL) {
+                       SERR("Invalid rule : %s\n", buf);
+                       continue;
+               }
+
+               proto = strtok_r(NULL, " ", &saveptr1);
+               if (proto == NULL) {
+                       SERR("Invalid rule : %s\n", buf);
+                       continue;
+               }
+
+               for (i = 0; i < sizeof(dest_ip) / sizeof(char *); i++) {
+                       token = strtok_r(NULL, " ", &saveptr1);
+                       if (token == NULL) {
+                               SERR("Invalid rule : %s\n", buf);
+                               break;
+                       }
+
+                       dest_ip[i] = strtok_r(token, ":", &saveptr2);
+                       if (dest_ip[i] == NULL ||
+                                       !__is_valid_ipv4_addr(dest_ip[i])) {
+                               SERR("Invalid rule : %s\n", buf);
+                               break;
+                       }
+
+                       dest_port[i] = strtok_r(NULL, ":", &saveptr2);
+                       if (dest_port[i] == NULL) {
+                               SERR("Invalid rule : %s\n", buf);
+                               break;
+                       }
+               }
+
+               if (i < sizeof(dest_ip) / sizeof(char *))
+                       continue;
+
+               pf = (port_forward_info_s *)malloc(sizeof(port_forward_info_s));
+               if (pf == NULL)
+                       break;
+
+               pf->input_interface = g_strdup(input_interface);
+               pf->proto = g_strdup(proto);
+               pf->org_dest_ip = g_strdup(dest_ip[0]);
+               pf->org_dest_port = (unsigned short)atoi(dest_port[0]);
+               pf->new_dest_ip = g_strdup(dest_ip[1]);
+               pf->new_dest_port = (unsigned short)atoi(dest_port[1]);
+               port_forward_info = g_slist_append(port_forward_info, pf);
+
+               SDBG("Port forward rule #%d : %s %s %s:%d %s:%d\n", no_of_rule,
+                               pf->input_interface, pf->proto,
+                               pf->org_dest_ip, pf->org_dest_port,
+                               pf->new_dest_ip, pf->new_dest_port);
+       }
+
+       fclose(fp);
+
+       return TRUE;
+}
+
+static gboolean __is_valid_port_forward_info(port_forward_info_s *pf)
+{
+       if (pf == NULL)
+               return FALSE;
+
+       if (!pf->input_interface || !pf->proto ||
+                       !pf->org_dest_ip || !pf->new_dest_ip)
+               return FALSE;
+
+       if (!strlen(pf->input_interface) || !strlen(pf->proto) ||
+                       !strlen(pf->org_dest_ip) || !strlen(pf->new_dest_ip))
+               return FALSE;
 
-       int conn_ret;
-       bool roaming;
+       return TRUE;
+}
+
+static void __print_cellular_profile(void)
+{
+       int ret = 0;
        char *apn = NULL;
        char *home_url = NULL;
+       bool roaming = false;
        connection_cellular_service_type_e service_type;
 
-       conn_ret = connection_profile_get_cellular_service_type(profile, &service_type);
-       if (conn_ret != CONNECTION_ERROR_NONE)
-               ERR("connection API fail : 0x%X\n", conn_ret);
+       if (c_prof.handle == NULL)
+               return;
+
+       ret = connection_profile_get_cellular_service_type(c_prof.handle, &service_type);
+       if (ret != CONNECTION_ERROR_NONE)
+               ERR("connection API fail: 0x%X\n", ret);
        else
-               DBG("Service type : %d\n", service_type);
+               SDBG("Service type: %d\n", service_type);
 
-       conn_ret = connection_profile_get_cellular_apn(profile, &apn);
-       if (conn_ret != CONNECTION_ERROR_NONE)
-               ERR("connection API fail : 0x%X\n", conn_ret);
+       ret = connection_profile_get_cellular_apn(c_prof.handle, &apn);
+       if (ret != CONNECTION_ERROR_NONE)
+               ERR("connection API fail: 0x%X\n", ret);
        else {
-               DBG("APN : %s\n", apn);
-               free(apn);
+               SDBG("APN: %s\n", apn);
+               g_free(apn);
        }
 
-       conn_ret = connection_profile_get_cellular_home_url(profile, &home_url);
-       if (conn_ret != CONNECTION_ERROR_NONE)
-               ERR("connection API fail : 0x%X\n", conn_ret);
+       ret = connection_profile_get_cellular_home_url(c_prof.handle, &home_url);
+       if (ret != CONNECTION_ERROR_NONE)
+               ERR("connection API fail: 0x%X\n", ret);
        else {
-               DBG("Home url : %s\n", home_url);
-               free(home_url);
+               SDBG("Home url: %s\n", home_url);
+               g_free(home_url);
        }
 
-       conn_ret = connection_profile_is_cellular_roaming(profile, &roaming);
-       if (conn_ret != CONNECTION_ERROR_NONE)
-               ERR("connection API fail : 0x%X\n", conn_ret);
+       ret = connection_profile_is_cellular_roaming(c_prof.handle, &roaming);
+       if (ret != CONNECTION_ERROR_NONE)
+               ERR("connection API fail: 0x%X\n", ret);
        else
-               DBG("Roaming : %d\n", roaming);
+               SDBG("Roaming: %d\n", roaming);
+}
 
-       return;
+static void __handle_open_network_error(void)
+{
+       int ret = MOBILE_AP_ERROR_NONE;
+
+       if (_mobileap_is_disabled()) {
+               return;
+       }
+
+       ret = _disable_wifi_tethering(obj);
+       DBG("_disable_wifi_tethering returns %d\n", ret);
+
+       ret = _disable_bt_tethering(obj);
+       DBG("_disable_bt_tethering returns %d\n", ret);
+
+       ret = _disable_usb_tethering(obj);
+       DBG("_disable_usb_tethering returns %d\n", ret);
+
+       tethering_emit_net_closed(obj);
+}
+
+static gboolean __is_equal_profile(connection_profile_h a, connection_profile_h b)
+{
+       char *a_id = NULL;
+       char *b_id = NULL;
+       int ret;
+
+       ret = connection_profile_get_id(a, &a_id);
+       if (ret != CONNECTION_ERROR_NONE || a_id == NULL) {
+               ERR("connection_profile_get_id is failed [0x%X]\n", ret);
+               return FALSE;
+       }
+
+       ret = connection_profile_get_id(b, &b_id);
+       if (ret != CONNECTION_ERROR_NONE || b_id == NULL) {
+               ERR("connection_profile_get_id is failed [0x%X]\n", ret);
+               g_free(a_id);
+               return FALSE;
+       }
+
+       ret = g_strcmp0(a_id, b_id);
+       g_free(a_id);
+       g_free(b_id);
+
+       return (ret == 0) ? TRUE : FALSE;
 }
 
 static gboolean __is_connected_profile(connection_profile_h profile)
@@ -79,17 +390,16 @@ static gboolean __is_connected_profile(connection_profile_h profile)
                return FALSE;
        }
 
-       int conn_ret;
+       int ret;
        connection_profile_state_e pstat = CONNECTION_PROFILE_STATE_DISCONNECTED;
 
-       conn_ret = connection_profile_get_state(profile, &pstat);
-       if (conn_ret != CONNECTION_ERROR_NONE) {
-               ERR("connection_profile_get_state is failed: 0x%X\n", conn_ret);
+       ret = connection_profile_get_state(profile, &pstat);
+       if (ret != CONNECTION_ERROR_NONE) {
+               ERR("connection_profile_get_state is failed: 0x%X\n", ret);
                return FALSE;
        }
 
        if (pstat != CONNECTION_PROFILE_STATE_CONNECTED) {
-               DBG("Profile is not connected\n");
                return FALSE;
        }
 
@@ -97,100 +407,368 @@ static gboolean __is_connected_profile(connection_profile_h profile)
        return TRUE;
 }
 
+static void __connection_type_changed_cb(connection_type_e type, void *user_data)
+{
+       DBG("Changed connection type is [%s]\n",
+                       type == CONNECTION_TYPE_DISCONNECTED ? "DISCONNECTED" :
+                       type == CONNECTION_TYPE_WIFI ? "Wi-Fi" :
+                       type == CONNECTION_TYPE_CELLULAR ? "Cellular" :
+                       type == CONNECTION_TYPE_ETHERNET ? "Ethernet" :
+                       "Unknown");
 
-static gboolean __get_connected_profile(connection_profile_h *r_prof, connection_profile_type_e *r_net_type)
+       if (_mobileap_is_disabled()) {
+               DBG("Tethering is disabled\n");
+               return;
+       }
+
+       if (_open_network() != MOBILE_AP_ERROR_NONE) {
+               ERR("_open_network() is failed\n");
+               __handle_open_network_error();
+       }
+
+       return;
+}
+
+void __cellular_state_changed_cb(keynode_t *node, void *user_data)
 {
-       if (r_prof == NULL || r_net_type == NULL) {
-               ERR("Invalid param [%p] [%p]\n", r_prof, r_net_type);
-               return FALSE;
+       if (node == NULL) {
+               ERR("Invalid parameter\n");
+               return;
+       }
+
+       if (vconf_keynode_get_type(node) != VCONF_TYPE_INT) {
+               ERR("Invalid vconf key type\n");
+               return;
        }
 
-       int conn_ret;
-       connection_profile_h profile = NULL;
-       connection_profile_type_e net_type = CONNECTION_PROFILE_TYPE_CELLULAR;
+       int ret;
+       int cellular_state;
+       connection_type_e net_type;
 
-       conn_ret = connection_get_current_profile(connection, &profile);
-       if (conn_ret != CONNECTION_ERROR_NONE) {
-               ERR("connection_get_current_profile is failed : %d\n", conn_ret);
-               return FALSE;
+       cellular_state = vconf_keynode_get_int(node);
+       SDBG("key = %s, value = %d(int)\n",
+                       vconf_keynode_get_name(node), cellular_state);
+
+       if (_mobileap_is_disabled())
+               return;
+
+       if (cellular_state != VCONFKEY_NETWORK_CELLULAR_ON)
+               return;
+
+       ret = connection_get_type(connection, &net_type);
+       if (ret != CONNECTION_ERROR_NONE) {
+               ERR("connection_get_type is failed [0x%X]\n", ret);
+               return;
        }
 
-       conn_ret = connection_profile_get_type(profile, &net_type);
-       if (conn_ret != CONNECTION_ERROR_NONE) {
-               ERR("connection_profile_get_type is failed : 0x%X\n", conn_ret);
+       if (net_type != CONNECTION_TYPE_DISCONNECTED &&
+                       net_type != CONNECTION_TYPE_CELLULAR)
+               return;
+
+       if (tethered_prof)
+               return;
+
+       DBG("VCONFKEY_NETWORK_CELLULAR_ON\n");
+       if (_open_network() != MOBILE_AP_ERROR_NONE) {
+               ERR("_open_network() is failed\n");
+               __handle_open_network_error();
+       }
+
+       return;
+}
+
+static void __profile_state_changed_cb(connection_profile_state_e state, void *user_data)
+{
+       if (c_prof.handle == NULL || c_prof.svc_type == __NO_SERVICE) {
+               ERR("There is no proper profile\n");
+               return;
+       }
+
+       DBG("Tethering cellular profile is %s\n",
+                       state == CONNECTION_PROFILE_STATE_DISCONNECTED ? "Disconnected" :
+                       state == CONNECTION_PROFILE_STATE_ASSOCIATION ? "Associated" :
+                       state == CONNECTION_PROFILE_STATE_CONFIGURATION ? "Configured" :
+                       state == CONNECTION_PROFILE_STATE_CONNECTED ? "Connected" :
+                       "Unknown");
+
+       int ret;
+       int cellular_state;
+
+       connection_profile_refresh(c_prof.handle);
+
+       if (_mobileap_is_disabled())
+               return;
+
+       if (c_prof.svc_type != __TETHERING_ONLY)
+               return;
+
+       if (tethered_prof) {
+               if (!__is_equal_profile(tethered_prof, c_prof.handle))
+                       return;
+               connection_profile_refresh(tethered_prof);
+       }
+
+       if (state != CONNECTION_PROFILE_STATE_DISCONNECTED)
+               return;
+
+       DBG("Cellular profile is disconnected\n");
+       _close_network();
+
+       ret = vconf_get_int(VCONFKEY_NETWORK_CELLULAR_STATE, &cellular_state);
+       if (ret < 0) {
+               ERR("vconf_get_int is failed : %d\n", ret);
+               if (vconf_ignore_key_changed(VCONFKEY_NETWORK_CELLULAR_STATE,
+                                       __cellular_state_changed_cb) < 0) {
+                       ERR("vconf_ignore_key_changed is failed\n");
+               }
+               return;
+       }
+
+       if (cellular_state != VCONFKEY_NETWORK_CELLULAR_ON)
+               return;
+
+       if (_open_network() != MOBILE_AP_ERROR_NONE) {
+               ERR("_open_network() is failed\n");
+               __handle_open_network_error();
+       }
+
+       DBG("-\n");
+       return;
+}
+
+static void __update_tethering_cellular_profile(void)
+{
+       int ret;
+       connection_profile_h profile;
+       tethering_cellular_service_type_e svc_type;
+
+       ret = connection_get_default_cellular_service_profile(connection,
+                       CONNECTION_CELLULAR_SERVICE_TYPE_TETHERING, &profile);
+       if (ret == CONNECTION_ERROR_NONE) {
+               svc_type = __TETHERING_ONLY;
+               goto DONE;
+       }
+       DBG("There is no tethering profile\n");
+
+       ret = connection_get_default_cellular_service_profile(connection,
+                       CONNECTION_CELLULAR_SERVICE_TYPE_INTERNET, &profile);
+       if (ret == CONNECTION_ERROR_NONE) {
+               svc_type = __INTERNET;
+               goto DONE;
+       }
+       ERR("Getting default connection for internet is failed\n");
+       /* To-Do : Need to consider prepaid internet profile */
+
+       if (c_prof.handle) {
+               connection_profile_unset_state_changed_cb(c_prof.handle);
+               connection_profile_destroy(c_prof.handle);
+               c_prof.handle = NULL;
+               c_prof.svc_type = __NO_SERVICE;
+       }
+       return;
+
+DONE:
+       if (c_prof.handle == NULL ||
+                       !__is_equal_profile(c_prof.handle, profile)) {
+               if (c_prof.handle) {
+                       DBG("Tethering cellular profile is updated\n");
+                       connection_profile_unset_state_changed_cb(c_prof.handle);
+                       connection_profile_destroy(c_prof.handle);
+               }
+
+               c_prof.handle = profile;
+               c_prof.svc_type = svc_type;
+               connection_profile_set_state_changed_cb(c_prof.handle,
+                               __profile_state_changed_cb, NULL);
+       } else {
                connection_profile_destroy(profile);
-               return FALSE;
+               connection_profile_refresh(c_prof.handle);
        }
 
-       *r_prof = profile;
-       *r_net_type = net_type;
-       return TRUE;
+       return;
+}
+
+static void __profile_closed_cb(connection_error_e result, void *user_data)
+{
+       connection_profile_refresh(c_prof.handle);
+
+       if (result != CONNECTION_ERROR_NONE) {
+               ERR("Unable to close profile [0x%X]", result);
+       } else {
+               DBG("Tethering profile is closed");
+       }
+
+       return;
 }
 
-static gboolean __get_network_profile(connection_profile_h *r_prof)
+static gboolean __close_tethering_profile(void)
 {
-       if (r_prof == NULL) {
-               ERR("r_prof is NULL\n");
+       if (c_prof.handle == NULL || c_prof.svc_type == __NO_SERVICE) {
+               ERR("There is no proper cellular profile\n");
                return FALSE;
        }
 
-       connection_profile_h profile;
-       connection_profile_type_e net_type = CONNECTION_PROFILE_TYPE_CELLULAR;
+       int ret;
+       connection_profile_state_e state;
+
+       DBG("+\n");
+
+       if (net_timeout_id) {
+               g_source_remove(net_timeout_id);
+               net_timeout_id = 0;
+       }
 
-       if (__get_connected_profile(&profile, &net_type) == FALSE) {
-               ERR("There is no available network\n");
+       if (c_prof.svc_type == __INTERNET) {
+               __profile_closed_cb(CONNECTION_ERROR_NONE, NULL);
+               return TRUE;
+       }
+
+       ret = connection_profile_get_state(c_prof.handle, &state);
+       if (ret != CONNECTION_ERROR_NONE) {
+               ERR("connection_profile_get_state is failed [0x%X]\n", ret);
                return FALSE;
        }
 
-       DBG("Current connected net_type : %d\n", net_type);
-       if (net_type == CONNECTION_PROFILE_TYPE_WIFI) {
-               *r_prof = profile;
+       if (state == CONNECTION_PROFILE_STATE_DISCONNECTED) {
+               DBG("Already disconnected profile\n");
                return TRUE;
        }
 
-       if (net_type != CONNECTION_PROFILE_TYPE_CELLULAR) {
-               ERR("Network type [%d] is not supported\n", net_type);
+       ret = connection_close_profile(connection, c_prof.handle,
+                       __profile_closed_cb, NULL);
+       if (ret != CONNECTION_ERROR_NONE) {
+               ERR("Connection close Failed!!\n");
                return FALSE;
        }
-       __print_profile(profile);
 
-       *r_prof = profile;
+       DBG("-\n");
        return TRUE;
 }
 
-static void __connection_type_changed_cb(connection_type_e type, void *user_data)
+static void __profile_opened_cb(connection_error_e result, void *user_data)
 {
-       DBG("Changed connection type is %s\n",
-                       type == CONNECTION_TYPE_DISCONNECTED ? "DISCONNECTED" :
-                       type == CONNECTION_TYPE_WIFI ? "Wi-Fi" :
-                       type == CONNECTION_TYPE_CELLULAR ? "Cellular" :
-                       type == CONNECTION_TYPE_ETHERNET ? "Ethernet" :
-                       "Unknown");
+       if (c_prof.handle == NULL || c_prof.svc_type == __NO_SERVICE) {
+               ERR("There is no proper profile\n");
+               return;
+       }
+
+       int ret;
+       connection_type_e net_type;
 
+       DBG("+\n");
+
+       connection_profile_refresh(c_prof.handle);
 
        if (_mobileap_is_disabled()) {
-               DBG("Tethering is not enabled\n");
+               __close_tethering_profile();
+               return;
+       }
+
+       if (result == CONNECTION_ERROR_OPERATION_ABORTED) {
+               DBG("connection_open_profile is cancelled\n");
                return;
        }
 
-       if (_unset_masquerade() == FALSE) {
-               ERR("_unset_masquerade is failed\n");
+       /* Check opened and retry context */
+       ret = connection_get_type(connection, &net_type);
+       if (ret != CONNECTION_ERROR_NONE) {
+               ERR("connection_get_type is failed\n");
+               __close_tethering_profile();
+               return;
        }
 
-       if (cprof) {
-               connection_profile_destroy(cprof);
-               cprof = NULL;
+       if (net_type != CONNECTION_TYPE_DISCONNECTED &&
+                       net_type != CONNECTION_TYPE_CELLULAR) {
+               DBG("Connection type is changed\n");
+               __close_tethering_profile();
+               return;
        }
 
-       if (type == CONNECTION_TYPE_DISCONNECTED) {
+       if (tethered_prof) {
+               connection_profile_refresh(tethered_prof);
+               return;
+       }
+       /* End of check */
+
+       if (result != CONNECTION_ERROR_ALREADY_EXISTS &&
+                       result != CONNECTION_ERROR_NONE) {
+               DBG("Retry to open profile [0x%X]\n", result);
+               if (net_timeout_id) {
+                       g_source_remove(net_timeout_id);
+                       net_timeout_id = 0;
+               }
+               net_timeout_id = g_timeout_add(TETHERING_NET_OPEN_RETRY_INTERVAL,
+                               __try_to_open_tethering_profile,
+                               NULL);
                return;
        }
 
+       DBG("Tethering profile is opened");
+
+       __print_cellular_profile();
+
+       connection_profile_clone(&tethered_prof, c_prof.handle);
+       _set_masquerade();
+       _add_default_router();
+       _add_port_forward_rule();
+
+       DBG("-\n");
+
        return;
 }
 
+static gboolean __open_tethering_profile(void)
+{
+       if (c_prof.handle == NULL || c_prof.svc_type == __NO_SERVICE) {
+               ERR("There is no proper cellular profile\n");
+               return FALSE;
+       }
+
+       int ret;
+
+       DBG("+\n");
+
+       if (c_prof.svc_type == __INTERNET) {
+               return TRUE;
+       }
+
+       if (__is_connected_profile(c_prof.handle)) {
+               DBG("Already connected profile\n");
+               return TRUE;
+       }
+
+       ret = connection_open_profile(connection, c_prof.handle,
+                       __profile_opened_cb, NULL);
+       if (ret != CONNECTION_ERROR_NONE) {
+               ERR("Unable to open profile [0x%X]", ret);
+               return FALSE;
+       }
+
+       DBG("-\n");
+       return TRUE;
+}
+
+static gboolean __try_to_open_tethering_profile(gpointer user_data)
+{
+       DBG("+\n");
+
+       if (_mobileap_is_disabled()) {
+               DBG("Tethering is disabled\n");
+               net_timeout_id = 0;
+               return FALSE;
+       }
+
+       if (__open_tethering_profile() == FALSE)
+               return TRUE;
+
+       net_timeout_id = 0;
+       return FALSE;
+}
+
 gboolean _is_trying_network_operation(void)
 {
+       if (net_timeout_id)
+               return TRUE;
 
        return FALSE;
 }
@@ -202,16 +780,48 @@ gboolean _get_network_interface_name(char **if_name)
                return FALSE;
        }
 
-       if (cprof == NULL) {
-               ERR("There is no connected profile\n");
+       if (tethered_prof == NULL) {
                return FALSE;
        }
 
-       int conn_ret = 0;
+       int ret = 0;
+
+       connection_profile_refresh(tethered_prof);
+
+       ret = connection_profile_get_network_interface_name(tethered_prof, if_name);
+       if (ret != CONNECTION_ERROR_NONE) {
+               ERR("connection_profile_get_network_interface_name is failed : 0x%X\n", ret);
+               return FALSE;
+       }
 
-       conn_ret = connection_profile_get_network_interface_name(cprof, if_name);
-       if (conn_ret != CONNECTION_ERROR_NONE) {
-               ERR("connection_profile_get_network_interface_name is failed : 0x%X\n", conn_ret);
+       if (strlen(*if_name) == 0) {
+               ERR("if_name is zero length\n");
+               free(*if_name);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+gboolean _get_network_gateway_address(char **ip)
+{
+       if (ip == NULL) {
+               ERR("ip is NULL\n");
+               return FALSE;
+       }
+
+       if (tethered_prof == NULL) {
+               return FALSE;
+       }
+
+       int ret = 0;
+
+       connection_profile_refresh(tethered_prof);
+
+       ret = connection_profile_get_gateway_address(tethered_prof,
+                       CONNECTION_ADDRESS_FAMILY_IPV4, ip);
+       if (ret != CONNECTION_ERROR_NONE) {
+               ERR("connection_profile_get_ip_address is failed : 0x%X\n", ret);
                return FALSE;
        }
 
@@ -226,7 +836,7 @@ gboolean _set_masquerade(void)
                ERR("_get_network_interface_name is failed\n");
                return FALSE;
        }
-       DBG("Network interface : %s\n", if_name);
+       SDBG("Network interface : %s\n", if_name);
 
        _mh_core_enable_masquerade(if_name);
        free(if_name);
@@ -236,7 +846,7 @@ gboolean _set_masquerade(void)
 
 gboolean _unset_masquerade(void)
 {
-       if (cprof == NULL) {
+       if (tethered_prof == NULL) {
                DBG("There is nothing to unset masquerading\n");
                return TRUE;
        }
@@ -247,7 +857,7 @@ gboolean _unset_masquerade(void)
                ERR("_get_network_interface_name is failed\n");
                return FALSE;
        }
-       DBG("Network interface : %s\n", if_name);
+       SDBG("Network interface : %s\n", if_name);
 
        _mh_core_disable_masquerade(if_name);
        free(if_name);
@@ -255,90 +865,331 @@ gboolean _unset_masquerade(void)
        return TRUE;
 }
 
-gboolean _open_network(void)
+gboolean _add_default_router(void)
 {
-       connection_profile_h profile = NULL;
+       if (tethered_prof == NULL) {
+               DBG("There is no network\n");
+               return TRUE;
+       }
 
-       DBG("+\n");
+       char cmd[MAX_BUF_SIZE] = {0, };
+       char *ip = NULL;
+       char *interface = NULL;
 
-       if (__get_network_profile(&profile) == FALSE) {
-               ERR("__get_network_profile is failed\n");
+       if (_get_network_gateway_address(&ip) == FALSE) {
                return FALSE;
        }
 
-       if (!__is_connected_profile(profile)) {
-               connection_profile_destroy(profile);
+       if (_get_network_interface_name(&interface) == FALSE) {
+               free(ip);
+               return FALSE;
+       }
+
+       snprintf(cmd, sizeof(cmd), "%s route replace "DEFAULT_ROUTER,
+                       IP_CMD, ip, interface, TETHERING_ROUTING_TABLE);
+       free(interface);
+       free(ip);
+
+       if (_execute_command(cmd)) {
+               ERR("%s is failed\n", cmd);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+gboolean _del_default_router(void)
+{
+       if (tethered_prof == NULL) {
+               DBG("There is no network\n");
                return TRUE;
        }
-       cprof = profile;
 
-       if (_set_masquerade() == FALSE) {
-               ERR("_set_masquerade is failed\n");
-               _close_network();
+       char cmd[MAX_BUF_SIZE] = {0, };
+       char *ip = NULL;
+       char *interface = NULL;
+
+       if (_get_network_gateway_address(&ip) == FALSE) {
                return FALSE;
        }
 
-       DBG("-\n");
+       if (_get_network_interface_name(&interface) == FALSE) {
+               free(ip);
+               return FALSE;
+       }
+
+       snprintf(cmd, sizeof(cmd), "%s route del "DEFAULT_ROUTER,
+                       IP_CMD, ip, interface, TETHERING_ROUTING_TABLE);
+       free(interface);
+       free(ip);
+
+       if (_execute_command(cmd)) {
+               ERR("%s is failed\n", cmd);
+               return FALSE;
+       }
 
        return TRUE;
 }
 
-gboolean _close_network(void)
+void _add_port_forward_rule(void)
 {
-       gboolean ret;
+       DBG("+\n");
+
+       GSList *l;
+       port_forward_info_s *pf;
+
+       if (access(MH_PORT_FORWARD_CONF_FILEPATH, F_OK) < 0) {
+               return;
+       }
+
+       if (__read_port_forward_info(MH_PORT_FORWARD_CONF_FILEPATH) == FALSE) {
+               ERR("__read_port_forward_info() is failed\n");
+               return;
+       }
+
+       _iptables_create_chain(TABLE_NAT, TETH_NAT_PRE);
+       _iptables_add_rule(PKT_REDIRECTION_RULE, TABLE_NAT, CHAIN_PRE,
+               TETH_NAT_PRE);
+
+       for (l = port_forward_info; l; l = g_slist_next(l)) {
+               pf = (port_forward_info_s *)l->data;
+
+               if (__is_valid_port_forward_info(pf) == FALSE)
+                       continue;
+
+               _iptables_add_rule(PORT_FW_RULE, TABLE_NAT, TETH_NAT_PRE,
+                       pf->input_interface, pf->proto, pf->org_dest_ip,
+                       pf->new_dest_ip, (int)pf->org_dest_port, (int)pf->new_dest_port);
+       }
+
+       return;
+}
+
+void _del_port_forward_rule(void)
+{
+       GSList *l;
+       GSList *temp_l;
+       port_forward_info_s *pf;
 
        DBG("+\n");
 
-       ret = _unset_masquerade();
-       if (ret == FALSE)
-               ERR("_unset_masquerade is failed\n");
+       if (port_forward_info == NULL) {
+               DBG("port forwarding rules were not applied, no need to deleted\n");
+               return;
+       }
 
-       connection_profile_destroy(cprof);
-       cprof = NULL;
+       for(l = port_forward_info; l;) {
+               pf = (port_forward_info_s *)l->data;
+               if (pf) {
+                       g_free(pf->new_dest_ip);
+                       g_free(pf->org_dest_ip);
+                       g_free(pf->proto);
+                       g_free(pf->input_interface);
+                       g_free(pf);
+               }
+
+               temp_l = l;
+               l = g_slist_next(l);
+               port_forward_info = g_slist_delete_link(port_forward_info,
+                                       temp_l);
+       }
+
+       _iptables_delete_rule(PKT_REDIRECTION_RULE, TABLE_NAT, CHAIN_PRE,
+               TETH_NAT_PRE);
+       _iptables_flush_rules(TABLE_NAT, TETH_NAT_PRE);
+       _iptables_delete_chain(TABLE_NAT, TETH_NAT_PRE);
+
+       return;
+}
+
+int _open_network(void)
+{
+       DBG("+\n");
+
+       int ret;
+       int con_ret;
+       int cellular_state;
+       connection_type_e net_type;
+
+       ret = connection_get_type(connection, &net_type);
+       if (ret != CONNECTION_ERROR_NONE) {
+               ERR("connection_get_type is failed\n");
+               con_ret = __get_conn_error(ret);
+               return con_ret;
+       }
+
+       if (vconf_get_int(VCONFKEY_NETWORK_CELLULAR_STATE, &cellular_state) < 0) {
+               ERR("vconf_get_int is failed\n");
+               return MOBILE_AP_ERROR_INTERNAL;
+       }
+
+       DBG("Connection type : %d, Cellular State : %d\n",
+                       net_type, cellular_state);
+
+       if (tethered_prof) {
+               if (net_type == CONNECTION_TYPE_CELLULAR) {
+                       __update_tethering_cellular_profile();
+                       if (__is_equal_profile(tethered_prof, c_prof.handle)) {
+                               DBG("Cellular profile is already configured\n");
+                               return MOBILE_AP_ERROR_NONE;
+                       }
+               }
+
+               DBG("There is already tethered profile\n");
+               _close_network();
+       }
+
+       if (net_type == CONNECTION_TYPE_DISCONNECTED &&
+                       cellular_state != VCONFKEY_NETWORK_CELLULAR_ON) {
+               DBG("There is no network\n");
+               /* Callback will handle this once Network type is changed */
+               return MOBILE_AP_ERROR_NONE;
+       }
+
+       switch (net_type) {
+       case CONNECTION_TYPE_DISCONNECTED:
+       case CONNECTION_TYPE_CELLULAR:
+               __update_tethering_cellular_profile();
+               if (c_prof.handle == NULL || c_prof.svc_type == __NO_SERVICE) {
+                       DBG("There is no proper cellular profile for tethering\n");
+                       return MOBILE_AP_ERROR_NONE;
+               }
+               __print_cellular_profile();
+
+               if (!__is_connected_profile(c_prof.handle)) {
+                       if (c_prof.svc_type != __TETHERING_ONLY) {
+                               return MOBILE_AP_ERROR_NONE;
+                       }
+
+                       if (net_timeout_id) {
+                               g_source_remove(net_timeout_id);
+                               net_timeout_id = 0;
+                       }
+                       net_timeout_id = g_timeout_add(TETHERING_NET_OPEN_RETRY_INTERVAL,
+                                       __try_to_open_tethering_profile, NULL);
+
+                       return MOBILE_AP_ERROR_NONE;
+               }
+               connection_profile_clone(&tethered_prof, c_prof.handle);
+               break;
+
+       case CONNECTION_TYPE_WIFI:
+       case CONNECTION_TYPE_ETHERNET:
+       case CONNECTION_TYPE_BT:
+               ret = connection_get_current_profile(connection, &tethered_prof);
+               if (ret != CONNECTION_ERROR_NONE) {
+                       ERR("connection_get_current_profile is failed [0x%X]\n", ret);
+                       con_ret = __get_conn_error(ret);
+                       return con_ret;
+               }
+               break;
+
+       default:
+               ERR("Unknown connection type : %d\n", net_type);
+               return MOBILE_AP_ERROR_INTERNAL;
+       }
+
+       _set_masquerade();
+       _add_default_router();
+       _add_port_forward_rule();
 
        DBG("-\n");
 
-       return TRUE;
+       return MOBILE_AP_ERROR_NONE;
 }
 
-gboolean _init_network(void *user_data)
+void _close_network(void)
 {
-       int conn_ret;
+       if (tethered_prof == NULL) {
+               DBG("There is no tethered profile\n");
+               return;
+       }
+
+       DBG("+\n");
+
+       _del_port_forward_rule();
+       _del_default_router();
+       _unset_masquerade();
+
+       connection_profile_destroy(tethered_prof);
+       tethered_prof = NULL;
+       __close_tethering_profile();
+
+       DBG("-\n");
+       return;
+}
 
-       conn_ret = connection_create(&connection);
-       if (conn_ret != CONNECTION_ERROR_NONE) {
-               ERR("connection_create is failed : 0x%X\n", conn_ret);
+gboolean _init_network(void *user_data)
+{
+       if (user_data == NULL) {
+               ERR("Invalid parameter\n");
                return FALSE;
        }
 
-       conn_ret = connection_set_type_changed_cb(connection,
+       int ret;
+
+       obj = (Tethering *)user_data;
+
+       ret = connection_create(&connection);
+       if (ret != CONNECTION_ERROR_NONE) {
+               ERR("connection_create is failed : 0x%X\n", ret);
+               goto FAIL;
+       }
+
+       ret = connection_set_type_changed_cb(connection,
                        __connection_type_changed_cb, user_data);
-       if (conn_ret != CONNECTION_ERROR_NONE) {
-               ERR("connection_set_type_changed cb is failed : 0x%X\n", conn_ret);
+       if (ret != CONNECTION_ERROR_NONE) {
+               ERR("connection_set_type_changed cb is failed : 0x%X\n", ret);
+               goto FAIL;
+       }
+
+       ret = vconf_notify_key_changed(VCONFKEY_NETWORK_CELLULAR_STATE,
+                       __cellular_state_changed_cb, NULL);
+       if (ret < 0) {
+               ERR("vconf_notify_key_changed is failed : %d\n", ret);
+               connection_unset_type_changed_cb(connection);
+               goto FAIL;
+       }
+
+       __update_tethering_cellular_profile();
+
+       return TRUE;
+
+FAIL:
+       if (connection) {
                connection_destroy(connection);
                connection = NULL;
-               return FALSE;
        }
 
-       return TRUE;
+       return FALSE;
 }
 
 gboolean _deinit_network(void)
 {
-       int conn_ret;
+       int ret;
 
        if (connection == NULL) {
                ERR("Connection handle is not initialized\n");
                return TRUE;
        }
 
-       conn_ret = connection_unset_type_changed_cb(connection);
-       if (conn_ret != CONNECTION_ERROR_NONE) {
-               ERR("connection_unset_type_changed_cb is failed : %d\n", conn_ret);
+       if (c_prof.handle) {
+               vconf_ignore_key_changed(VCONFKEY_NETWORK_CELLULAR_STATE,
+                               __cellular_state_changed_cb);
+               connection_profile_unset_state_changed_cb(c_prof.handle);
+               connection_profile_destroy(c_prof.handle);
+               c_prof.handle = NULL;
+               c_prof.svc_type = __NO_SERVICE;
+       }
+
+       ret = connection_unset_type_changed_cb(connection);
+       if (ret != CONNECTION_ERROR_NONE) {
+               ERR("connection_unset_type_changed_cb is failed : %d\n", ret);
        }
 
        connection_destroy(connection);
        connection = NULL;
+       obj = NULL;
 
        return TRUE;
 }
index 62783f1..b193af4 100644 (file)
@@ -1,50 +1,80 @@
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
 #include <glib.h>
 #include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
 #include <stdio.h>
 #include <string.h>
 #include <notification.h>
+#include <notification_list.h>
+#include <notification_text_domain.h>
+#include <notification_internal.h>
+#include <bluetooth.h>
+#include <bundle_internal.h>
 
-#include "mobileap_agent.h"
+#include "mobileap_softap.h"
+#include "mobileap_notification.h"
+
+#define MH_NOTI_LAUNCH_PKGNAME "ug-setting-mobileap-efl"
+#define MH_NOTI_CALLER_PKGNAME "mobileap-agent"
+#define MH_LOCALE_DOMAIN       "ug-setting-mobileap-efl"
+#define MH_LOCALE_DIR "/usr/ug/res/locale"
 
-#define MH_NOTI_APP_NAME       "org.tizen.tethering"
-#define MH_AGENT_PKG_NAME "mobileap-agent"
 
 static int connected_noti_id = 0;
 static int timeout_noti_id = 0;
 
-int _create_timeout_noti(const char *content, const char *title,
-               const char *icon_path)
+static int __create_status_noti(const char *content)
+{
+       if (content == NULL)
+               return MOBILE_AP_ERROR_INVALID_PARAM;
+
+       notification_error_e ret;
+
+       ret = notification_status_message_post(content);
+       if (ret != NOTIFICATION_ERROR_NONE) {
+               ERR("notification_status_message_post() is failed : %d\n", ret);
+               return MOBILE_AP_ERROR_INTERNAL;
+       }
+
+       return MOBILE_AP_ERROR_NONE;
+}
+
+int _create_timeout_noti(const char *icon_path)
 {
        DBG("+\n");
+
        notification_h noti = NULL;
        notification_error_e ret = NOTIFICATION_ERROR_NONE;
+       char *old_icon_path = NULL;
+       char *general_icon_path = NULL;
 
        if (timeout_noti_id) {
-               noti = notification_load(APPNAME, timeout_noti_id);
+               noti = notification_load(MH_NOTI_CALLER_PKGNAME, timeout_noti_id);
                if (noti == NULL) {
                        DBG("Notification can be deleted already\n");
                } else {
+                       ret = notification_get_image(noti,
+                                       NOTIFICATION_IMAGE_TYPE_ICON, &old_icon_path);
+                       if (ret == NOTIFICATION_ERROR_NONE) {
+                               if (g_strcmp0(icon_path, old_icon_path))
+                                       general_icon_path = MH_NOTI_ICON_GENERAL;
+                       }
+
                        ret = notification_delete(noti);
                        if (ret != NOTIFICATION_ERROR_NONE) {
                                ERR("Fail to notification_delete [%d]\n", ret);
@@ -58,9 +88,9 @@ int _create_timeout_noti(const char *content, const char *title,
                        ret = notification_free(noti);
                        if (ret != NOTIFICATION_ERROR_NONE) {
                                ERR("Fail to notification_free [%d]\n", ret);
-                               return MOBILE_AP_ERROR_INTERNAL;
                        }
                }
+
                timeout_noti_id = 0;
        }
 
@@ -70,6 +100,12 @@ int _create_timeout_noti(const char *content, const char *title,
                return MOBILE_AP_ERROR_INTERNAL;
        }
 
+       ret = notification_set_pkgname(noti, MH_NOTI_CALLER_PKGNAME);
+       if (ret != NOTIFICATION_ERROR_NONE) {
+               ERR("Fail to notification_set_pkgname [%d]\n", ret);
+               goto FAIL;
+       }
+
        ret = notification_set_property(noti,
                        NOTIFICATION_PROP_VOLATILE_DISPLAY);
        if (ret != NOTIFICATION_ERROR_NONE) {
@@ -79,42 +115,43 @@ int _create_timeout_noti(const char *content, const char *title,
 
        ret = notification_set_layout(noti, NOTIFICATION_LY_NOTI_EVENT_SINGLE);
        if (ret != NOTIFICATION_ERROR_NONE) {
-               ERR("Fail to notification_set_image [%d]\n", ret);
+               ERR("Fail to notification_set_layout [%d]\n", ret);
                goto FAIL;
        }
 
        ret = notification_set_image(noti,
-                       NOTIFICATION_IMAGE_TYPE_ICON, icon_path);
+                       NOTIFICATION_IMAGE_TYPE_ICON, general_icon_path ?
+                       general_icon_path : icon_path);
        if (ret != NOTIFICATION_ERROR_NONE) {
                ERR("Fail to notification_set_image [%d]\n", ret);
                goto FAIL;
        }
 
        ret = notification_set_text(noti,
-                       NOTIFICATION_TEXT_TYPE_TITLE,
-                       title,
-                       NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+                       NOTIFICATION_TEXT_TYPE_TITLE, NULL,
+                       MH_STR_CONNECTION_TIMEOUT,
+                       NOTIFICATION_VARIABLE_TYPE_NONE);
        if (ret != NOTIFICATION_ERROR_NONE) {
                ERR("Fail to notification_set_text [%d]\n", ret);
                goto FAIL;
        }
 
        ret = notification_set_text(noti,
-                       NOTIFICATION_TEXT_TYPE_CONTENT,
-                       content,
-                       NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+                       NOTIFICATION_TEXT_TYPE_CONTENT, NULL,
+                       MH_STR_CONFIGURE_TETHERING,
+                       NOTIFICATION_VARIABLE_TYPE_NONE);
        if (ret != NOTIFICATION_ERROR_NONE) {
                ERR("Fail to notification_set_text [%d]\n", ret);
                goto FAIL;
        }
 
-       ret = notification_set_pkgname(noti, APPNAME);
+       ret = notification_set_text_domain(noti, MH_LOCALE_DOMAIN, MH_LOCALE_DIR);
        if (ret != NOTIFICATION_ERROR_NONE) {
-               ERR("Fail to notification_set_pkgname [%d]\n", ret);
+               ERR("Fail to notification_set_text_domain [%d]\n", ret);
                goto FAIL;
        }
 
-       ret = notification_set_application(noti, MH_NOTI_APP_NAME);
+       ret = notification_set_application(noti, MH_NOTI_LAUNCH_PKGNAME);
        if (ret != NOTIFICATION_ERROR_NONE) {
                ERR("Fail to notification_set_application [%d]\n", ret);
                goto FAIL;
@@ -147,35 +184,52 @@ int _delete_timeout_noti(void)
 {
        notification_error_e ret = NOTIFICATION_ERROR_NONE;
        notification_list_h noti_list = NULL;
+       notification_list_h l = NULL;
        notification_h noti = NULL;
+       notification_ly_type_e layout;
 
-       ret = notification_get_detail_list(MH_AGENT_PKG_NAME,
-                                                            NOTIFICATION_GROUP_ID_NONE,
-                                                            NOTIFICATION_PRIV_ID_NONE,
-                                                            -1,
-                                                            &noti_list);
+       DBG("+\n");
+
+       ret = notification_get_detail_list(MH_NOTI_CALLER_PKGNAME,
+                       NOTIFICATION_GROUP_ID_NONE,
+                       NOTIFICATION_PRIV_ID_NONE,
+                       -1,
+                       &noti_list);
        if (ret != NOTIFICATION_ERROR_NONE) {
                ERR("Fail to notification_get_detail_list\n");
                return MOBILE_AP_ERROR_INTERNAL;
        }
 
-       if (noti_list) {
-               noti = notification_list_get_data(noti_list);
-               if (noti)
-                       notification_delete(noti);
+       if (noti_list == NULL) {
+               return MOBILE_AP_ERROR_NONE;
+       }
+
+       for (l = noti_list; l; l = notification_list_get_next(l)) {
+               noti = notification_list_get_data(l);
+               if (noti == NULL)
+                       break;
 
-               notification_free_list(noti_list);
+               ret = notification_get_layout(noti, &layout);
+               if (ret == NOTIFICATION_ERROR_NONE &&
+                               layout == NOTIFICATION_LY_NOTI_EVENT_SINGLE) {
+                       DBG("Found timeout noti\n");
+                       notification_delete(noti);
+               }
        }
 
+       notification_free_list(noti_list);
+
+       DBG("-\n");
+
        return MOBILE_AP_ERROR_NONE;
 }
 
-int _create_connected_noti(const char *content, const char *title,
-               const char *icon_path)
+int _create_connected_noti(int count, const char *icon_path)
 {
        DBG("+\n");
        notification_h noti = NULL;
        notification_error_e ret = NOTIFICATION_ERROR_NONE;
+       bundle *b = NULL;
 
        noti = notification_create(NOTIFICATION_TYPE_ONGOING);
        if (!noti) {
@@ -183,6 +237,12 @@ int _create_connected_noti(const char *content, const char *title,
                return MOBILE_AP_ERROR_INTERNAL;
        }
 
+       ret = notification_set_pkgname(noti, MH_NOTI_CALLER_PKGNAME);
+       if (ret != NOTIFICATION_ERROR_NONE) {
+               ERR("Fail to notification_set_pkgname [%d]\n", ret);
+               goto FAIL;
+       }
+
        ret = notification_set_property(noti,
                        NOTIFICATION_PROP_DISABLE_AUTO_DELETE |
                        NOTIFICATION_PROP_VOLATILE_DISPLAY);
@@ -191,6 +251,22 @@ int _create_connected_noti(const char *content, const char *title,
                goto FAIL;
        }
 
+       b = bundle_create();
+       bundle_add(b, "caller", "notification");
+
+#ifndef TIZEN_TV
+       appsvc_set_pkgname(b, "ug-setting-mobileap-efl");
+#endif
+
+       ret = notification_set_execute_option(noti,
+                       NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "Launch", NULL, b);
+       if (ret != NOTIFICATION_ERROR_NONE) {
+               ERR("Failed to notification_set_execute_option");
+               goto FAIL;
+       }
+
+       ERR("Successfully added notification");
+
        ret = notification_set_layout(noti, NOTIFICATION_LY_ONGOING_EVENT);
        if (ret != NOTIFICATION_ERROR_NONE) {
                ERR("Fail to notification_set_image [%d]\n", ret);
@@ -204,35 +280,43 @@ int _create_connected_noti(const char *content, const char *title,
        }
 
        ret = notification_set_text(noti,
-                       NOTIFICATION_TEXT_TYPE_TITLE,
-                       title,
-                       NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+                       NOTIFICATION_TEXT_TYPE_TITLE, NULL,
+                       MH_STR_TETHERING,
+                       NOTIFICATION_VARIABLE_TYPE_NONE);
        if (ret != NOTIFICATION_ERROR_NONE) {
                ERR("Fail to notification_set_text [%d]\n", ret);
                goto FAIL;
        }
 
        ret = notification_set_text(noti,
-                       NOTIFICATION_TEXT_TYPE_CONTENT,
-                       content,
-                       NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+                       NOTIFICATION_TEXT_TYPE_CONTENT, NULL,
+                       MH_STR_CONNECTED_DEV,
+                       NOTIFICATION_VARIABLE_TYPE_INT, count,
+                       NOTIFICATION_VARIABLE_TYPE_NONE);
        if (ret != NOTIFICATION_ERROR_NONE) {
                ERR("Fail to notification_set_text [%d]\n", ret);
                goto FAIL;
        }
 
-       ret = notification_set_pkgname(noti, APPNAME);
+       ret = notification_set_text_domain(noti, MH_LOCALE_DOMAIN, MH_LOCALE_DIR);
        if (ret != NOTIFICATION_ERROR_NONE) {
-               ERR("Fail to notification_set_pkgname [%d]\n", ret);
+               ERR("Fail to notification_set_text_domain [%d]\n", ret);
                goto FAIL;
        }
 
-       ret = notification_set_application(noti, MH_NOTI_APP_NAME);
+       ret = notification_set_application(noti, MH_NOTI_LAUNCH_PKGNAME);
        if (ret != NOTIFICATION_ERROR_NONE) {
                ERR("Fail to notification_set_application [%d]\n", ret);
                goto FAIL;
        }
 
+       ret = notification_set_display_applist(noti,
+                       NOTIFICATION_DISPLAY_APP_ALL ^ NOTIFICATION_DISPLAY_APP_INDICATOR);
+       if (ret != NOTIFICATION_ERROR_NONE) {
+               ERR("Fail to notification_set_display_applist [%d]\n", ret);
+               goto FAIL;
+       }
+
        ret = notification_insert(noti, &connected_noti_id);
        if (ret != NOTIFICATION_ERROR_NONE) {
                ERR("Fail to notification_insert [%d]\n", ret);
@@ -249,49 +333,48 @@ int _create_connected_noti(const char *content, const char *title,
        return MOBILE_AP_ERROR_NONE;
 
 FAIL:
+       if (b != NULL)
+               bundle_free(b);
        ret = notification_free(noti);
        if (ret != NOTIFICATION_ERROR_NONE)
                ERR("Fail to notification_free [%d]\n", ret);
        return MOBILE_AP_ERROR_INTERNAL;
 }
 
-int _update_connected_noti(const char *content)
+int _update_connected_noti(int count, const char *icon_path)
 {
        DBG("+\n");
 
-       if (content == NULL) {
-               ERR("Invalid param\n");
-               return MOBILE_AP_ERROR_INVALID_PARAM;
-       }
-
        notification_h noti = NULL;
        notification_error_e ret = NOTIFICATION_ERROR_NONE;
 
-       noti = notification_load(APPNAME, connected_noti_id);
+       noti = notification_load(MH_NOTI_CALLER_PKGNAME, connected_noti_id);
        if (noti == NULL) {
                ERR("notification_load is failed\n");
                return MOBILE_AP_ERROR_INTERNAL;
        }
 
-       ret = notification_set_text(noti, NOTIFICATION_TEXT_TYPE_CONTENT,
-                       content, NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+       ret = notification_set_image(noti,
+                       NOTIFICATION_IMAGE_TYPE_ICON, icon_path);
        if (ret != NOTIFICATION_ERROR_NONE) {
-               ERR("Fail to notification_set_text [%d]\n", ret);
+               ERR("Fail to notification_set_image [%d]\n", ret);
+               goto FAIL;
+       }
 
-               ret = notification_free(noti);
-               if (ret != NOTIFICATION_ERROR_NONE)
-                       ERR("Fail to notification_free [%d]\n", ret);
-               return MOBILE_AP_ERROR_INTERNAL;
+       ret = notification_set_text(noti,
+                       NOTIFICATION_TEXT_TYPE_CONTENT, NULL,
+                       MH_STR_CONNECTED_DEV,
+                       NOTIFICATION_VARIABLE_TYPE_INT, count,
+                       NOTIFICATION_VARIABLE_TYPE_NONE);
+       if (ret != NOTIFICATION_ERROR_NONE) {
+               ERR("Fail to notification_set_text [%d]\n", ret);
+               goto FAIL;
        }
 
        ret = notification_update(noti);
        if (ret != NOTIFICATION_ERROR_NONE) {
                ERR("Fail to notification_update [%d]\n", ret);
-
-               ret = notification_free(noti);
-               if (ret != NOTIFICATION_ERROR_NONE)
-                       ERR("Fail to notification_free [%d]\n", ret);
-               return MOBILE_AP_ERROR_INTERNAL;
+               goto FAIL;
        }
 
        ret = notification_free(noti);
@@ -302,6 +385,14 @@ int _update_connected_noti(const char *content)
 
        DBG("-\n");
        return MOBILE_AP_ERROR_NONE;
+
+FAIL:
+       ret = notification_free(noti);
+       if (ret != NOTIFICATION_ERROR_NONE) {
+               ERR("Fail to notification_free [%d]\n", ret);
+       }
+
+       return MOBILE_AP_ERROR_INTERNAL;
 }
 
 int _delete_connected_noti(void)
@@ -310,7 +401,7 @@ int _delete_connected_noti(void)
        notification_h noti = NULL;
        notification_error_e ret;
 
-       noti = notification_load(APPNAME, connected_noti_id);
+       noti = notification_load(MH_NOTI_CALLER_PKGNAME, connected_noti_id);
        if (noti == NULL) {
                ERR("notification_load is failed\n");
                connected_noti_id = 0;
@@ -338,18 +429,48 @@ int _delete_connected_noti(void)
        return MOBILE_AP_ERROR_NONE;
 }
 
-int _create_status_noti(const char *content)
+void _create_tethering_active_noti(void)
 {
-       if (content == NULL)
-               return MOBILE_AP_ERROR_INVALID_PARAM;
+       int active_count = 0;
 
-       notification_error_e ret;
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
+               active_count++;
 
-       ret = notification_status_message_post(content);
-       if (ret != NOTIFICATION_ERROR_NONE) {
-               ERR("notification_status_message_post() is failed : %d\n", ret);
-               return MOBILE_AP_ERROR_INTERNAL;
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_BT))
+               active_count++;
+
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_USB))
+               active_count++;
+
+       if (active_count == 1)
+               __create_status_noti(_("IDS_MOBILEAP_BODY_TETHERING_ACTIVE_ABB"));
+
+       return;
+}
+
+void _create_bt_tethering_active_noti(void)
+{
+       int ret;
+       bt_adapter_visibility_mode_e mode = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
+       int duration;
+       char *str1 = NULL;
+       char *str2 = NULL;
+
+       if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI) &&
+                       !_mobileap_is_enabled(MOBILE_AP_STATE_USB)) {
+               str1 = MH_STR_TETHERING_ACTIVE;
+               __create_status_noti(str1);
        }
 
-       return MOBILE_AP_ERROR_NONE;
+       ret = bt_adapter_get_visibility(&mode, &duration);
+       if (ret != BT_ERROR_NONE) {
+               ERR("bt_adapter_get_visibility is failed 0x[%X]\n", ret);
+       }
+
+       if (mode == BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE) {
+               str2 = MH_STR_BT_VISIBILITY;
+               __create_status_noti(str2);
+       }
+
+       return;
 }
old mode 100644 (file)
new mode 100755 (executable)
similarity index 51%
rename from src/mobileap_agent.c
rename to src/mobileap_softap.c
index 6fd898d..e6dc33e
@@ -1,21 +1,19 @@
 /*
-*  mobileap-agent
-*
-* Copyright 2012-2013  Samsung Electronics Co., Ltd
-*
-* Licensed under the Flora License, Version 1.1 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://floralicense.org/license
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*
-*/
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 
 #include <sys/stat.h>
 #include <sys/un.h>
 #include <sys/ioctl.h>
 #include <glib.h>
 #include <glib-object.h>
-#include <dbus/dbus-glib.h>
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <ctype.h>
 #include <sys/wait.h>
 #include <sys/types.h>
 #include <fcntl.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <linux/wireless.h>
-
 #include <openssl/evp.h>
 #include <openssl/sha.h>
 
 #include "mobileap_common.h"
-#include "mobileap_agent.h"
+#include "mobileap_softap.h"
 #include "mobileap_handler.h"
+#include "mobileap_wifi.h"
+#include "mobileap_iptables.h"
+
+#define NETCONFIG_SERVICE                              "net.netconfig"
+#define NETCONFIG_WIFI_INTERFACE               "net.netconfig.wifi"
+#define NETCONFIG_WIFI_PATH                            "/net/netconfig/wifi"
+
+#define NETCONFIG_DBUS_REPLY_TIMEOUT   (10 * 1000)
 
 static pid_t dnsmasq_pid = 0;
 static pid_t hostapd_pid = 0;
@@ -49,6 +54,25 @@ static int hostapd_ctrl_fd = 0;
 static int hostapd_monitor_fd = 0;
 static GIOChannel *hostapd_io_channel = NULL;
 static guint hostapd_io_source = 0;
+GSList *sta_timer_list = NULL;
+
+static gboolean __hostapd_connect_timer_cb(gpointer user_data);
+
+static char *__find_first_caps_char(char *str)
+{
+       if (str == NULL) {
+               ERR("NULL string passes\n");
+               return NULL;
+       }
+
+       while(*str) {
+               if (isupper(*str)) {
+                       return str;
+               }
+               str++;
+       }
+       return NULL;
+}
 
 static int __issue_ioctl(int sock_fd, char *if_name, char *cmd, char *buf)
 {
@@ -75,28 +99,25 @@ static int __issue_ioctl(int sock_fd, char *if_name, char *cmd, char *buf)
        return ret_val;
 }
 
-static int __get_psk_hexascii(const char *pass, const unsigned char *salt, char *psk, unsigned int psk_len)
+static int __get_psk_hexascii(const char *pass, const unsigned char *salt,
+               char *psk, unsigned int psk_len)
 {
-       if (pass == NULL || salt == NULL || psk == NULL || psk_len == 0) {
+       if (pass == NULL || salt == NULL || psk == NULL || psk_len <
+                       (SHA256_DIGEST_LENGTH * 2 + 1)) {
                ERR("Invalid parameter\n");
                return MOBILE_AP_ERROR_INVALID_PARAM;
        }
 
-       if (psk_len < SHA256_DIGEST_LENGTH * 2 + 1) {
-               ERR("Invalid parameter\n");
-               return MOBILE_AP_ERROR_INVALID_PARAM;
-       }
-
-       int i;
-       int d_16;
-       int r_16;
+       int i = 0;
+       int d_16 = 0;
+       int r_16 = 0;
        unsigned char buf[SHA256_DIGEST_LENGTH] = {0, };
 
        if (!PKCS5_PBKDF2_HMAC_SHA1(pass, strlen(pass),
                                salt, strlen((const char *)salt),
                                PSK_ITERATION_COUNT, sizeof(buf), buf)) {
                ERR("Getting psk is failed\n");
-               return MOBILE_AP_ERROR_INTERNAL;
+               return MOBILE_AP_ERROR_RESOURCE;
        }
 
        for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
@@ -111,44 +132,71 @@ static int __get_psk_hexascii(const char *pass, const unsigned char *salt, char
        return MOBILE_AP_ERROR_NONE;
 }
 
-static int __execute_hostapd(const char *ssid, const char *security,
-               const char *key, int hide_mode)
+static int __execute_hostapd(const mobile_ap_type_e type, const char *ssid,
+               const char *security, const char *passphrase, int hide_mode)
 {
        DBG("+\n");
 
-       char psk[2 * SHA256_DIGEST_LENGTH + 1] = {0, };
+       char *conf = NULL;
+       char *old_conf;
        char buf[HOSTAPD_CONF_LEN] = "";
-       char sec_buf[HOSTAPD_CONF_LEN] = "";
        FILE *fp = NULL;
        pid_t pid;
-
-       if (security != NULL && !strcmp(security, "wpa2-psk")) {
-               if (__get_psk_hexascii(key, (const unsigned char *)ssid, psk,
-                                       sizeof(psk)) != MOBILE_AP_ERROR_NONE) {
-                       ERR("Getting PSK(Hex ascii type) is failed\n");
-                       return MOBILE_AP_ERROR_INTERNAL;
-               }
-
-               snprintf(sec_buf, HOSTAPD_CONF_LEN,
-                               "wpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\nwps_state=2\neap_server=1",
-                               psk);
-       }
-
-       snprintf(buf, HOSTAPD_CONF_LEN, HOSTAPD_CONF,
+       int ret;
+       char key[MOBILE_AP_WIFI_KEY_MAX_LEN + 1];
+       /* Default conf. */
+       snprintf(buf, sizeof(buf), HOSTAPD_CONF,
                        WIFI_IF,
                        HOSTAPD_CTRL_INTF_DIR,
                        ssid,
                        MOBILE_AP_WIFI_CHANNEL,
                        hide_mode ? 2 : 0,
-                       MOBILE_AP_MAX_WIFI_STA,
-                       sec_buf);
+                       MOBILE_AP_MAX_WIFI_STA);
+       conf = g_strdup(buf);
+
+       /* Vendor elements conf. */
+       if (type == MOBILE_AP_TYPE_WIFI) {
+               snprintf(buf, sizeof(buf),
+                               "vendor_elements=%s\n", HOSTAPD_VENDOR_ELEMENTS_TETH);
+       } else if (type == MOBILE_AP_TYPE_WIFI_AP) {
+               snprintf(buf, sizeof(buf),
+                               "vendor_elements=%s\n", HOSTAPD_VENDOR_ELEMENTS_WIFI_AP);
+       } else {
+               ERR("Unknown type: %d\n", type);
+               g_free(conf);
+               return MOBILE_AP_ERROR_INVALID_PARAM;
+       }
+       old_conf = conf;
+       conf = g_strconcat(old_conf, buf, NULL);
+       g_free(old_conf);
+
+       /* Security conf. */
+       if (security != NULL && !strcmp(security, "wpa2-psk")) {
+               ret = __get_psk_hexascii(passphrase, (const unsigned char *)ssid, key, sizeof(key));
+               if (ret != MOBILE_AP_ERROR_NONE) {
+                       g_free(conf);
+                       ERR("hex conversion failed\n");
+                       return MOBILE_AP_ERROR_RESOURCE;
+               }
+               snprintf(buf, sizeof(buf),
+                               "wpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n", key);
+
+               old_conf = conf;
+               conf = g_strconcat(old_conf, buf, NULL);
+               g_free(old_conf);
+       }
 
        fp = fopen(HOSTAPD_CONF_FILE, "w");
        if (NULL == fp) {
                ERR("Could not create the file.\n");
+               g_free(conf);
                return MOBILE_AP_ERROR_RESOURCE;
        }
-       fputs(buf, fp);
+
+       if (conf) {
+               fputs(conf, fp);
+               g_free(conf);
+       }
        fclose(fp);
 
        pid = fork();
@@ -157,10 +205,10 @@ static int __execute_hostapd(const char *ssid, const char *security,
                return MOBILE_AP_ERROR_RESOURCE;
        }
 
-        if (pid == 0) {
+       if (pid == 0) {
                if (execl(HOSTAPD_BIN, HOSTAPD_BIN, "-e", HOSTAPD_ENTROPY_FILE,
                                        HOSTAPD_CONF_FILE,
-                                       "-f", HOSTAPD_DEBUG_FILE, "-dd",
+                                       "-f", HOSTAPD_DEBUG_FILE, "-ddd",
                                        (char *)NULL)) {
                        ERR("execl failed\n");
                }
@@ -178,8 +226,10 @@ static int __terminate_hostapd()
 {
        DBG("+\n");
 
+       int ret;
+
        if (hostapd_pid == 0) {
-               DBG("There is no hostapd\n");
+               ERR("There is no hostapd\n");
                return MOBILE_AP_ERROR_NONE;
        }
 
@@ -187,6 +237,11 @@ static int __terminate_hostapd()
        waitpid(hostapd_pid, NULL, 0);
        hostapd_pid = 0;
 
+       ret = unlink(HOSTAPD_CONF_FILE);
+       if (ret < 0) {
+               ERR("unlink is failed : %s\n", strerror(errno));
+       }
+
        return MOBILE_AP_ERROR_NONE;
 }
 
@@ -238,7 +293,7 @@ static int __send_hostapd_req(int fd, const char *req, const int req_len,
                }
 
                if (buf[0] == '<') {
-                       DBG("Unsolicited message\n");
+                       ERR("Unsolicited message\n");
                        continue;
                }
 
@@ -279,7 +334,6 @@ static int __open_hostapd_intf(int *fd, const char *intf)
        g_strlcpy(src.sun_path, intf, sizeof(src.sun_path));
 
        if (stat(src.sun_path, &stat_buf) == 0) {
-               DBG("There is already mh interface. It will be removed\n");
                unlink(src.sun_path);
        }
 
@@ -297,7 +351,6 @@ static int __open_hostapd_intf(int *fd, const char *intf)
        g_strlcpy(dest.sun_path, ctrl_intf, sizeof(dest.sun_path));
 
        while (connect(*fd, (struct sockaddr *)&dest, sizeof(dest)) < 0) {
-               DBG("connect is failed : %s\n", strerror(errno));
                if (++retry >= HOSTAPD_RETRY_MAX)
                        goto FAIL;
                usleep(HOSTAPD_RETRY_DELAY);
@@ -334,10 +387,17 @@ static gboolean __hostapd_monitor_cb(GIOChannel *source)
 {
        DBG("+\n");
 
-       char buf[HOSTAPD_REQ_MAX_LEN] = {0, };
+       GSList *l;
+       char buf[HOSTAPD_REQ_MAX_LEN + 1] = {0, };
        char *pbuf = NULL;
        gsize read = 0;
        int n_station = 0;
+       int type;
+       sta_timer_t *ptr = NULL;
+       char *mac = NULL;
+       char *end = NULL;
+       gboolean discon_event = FALSE;
+
 
 #if !GLIB_CHECK_VERSION(2, 31, 0)
        int ret = 0;
@@ -369,35 +429,127 @@ static gboolean __hostapd_monitor_cb(GIOChannel *source)
        if (pbuf != NULL)
                *pbuf = '\0';
 
-       if (buf[0] == '<' && (pbuf = strchr(buf, '>')) != NULL) {
-               pbuf++;
-       } else {
-               pbuf = buf;
-       }
-
-       DBG("Event : %s\n", pbuf);
-
-       if (!strncmp(pbuf, HOSTAPD_STA_DISCONN, strlen(HOSTAPD_STA_DISCONN))) {
-               pbuf = strchr(pbuf, ' ');
-               if (pbuf == NULL) {
-                       ERR("There is no info. for disconnected station\n");
-                       return TRUE;
+       SDBG("Read string from hostapd = [%s]\n", buf);
+       pbuf = buf;
+       /* concatenated string, containing multiple events can arrive */
+       while (pbuf && *pbuf) {
+               pbuf = __find_first_caps_char(pbuf);
+               if (!pbuf || !*pbuf) {
+                       break;
                }
-               pbuf++;
 
-               DBG("Disconnected station MAC : %s\n", pbuf);
-               _remove_station_info(pbuf, _slist_find_station_by_mac);
+               if (!strncmp(pbuf, HOSTAPD_STA_CONN, HOSTAPD_STA_CONN_LEN)) {
+                       pbuf = pbuf + HOSTAPD_STA_CONN_LEN;
+                       if (!pbuf || !*pbuf) {
+                               ERR("No mac address\n");
+                               return TRUE;
+                       }
+
+                       end = strchr(pbuf, '<');
+                       if (end && *end) {
+                               mac = g_strndup(pbuf, (long)(end - pbuf));
+                               pbuf = end + 1;
+                       } else {
+                               mac = g_strdup(pbuf);
+                               pbuf += strlen(mac);
+                       }
+
+                       if (mac == NULL) {
+                               ERR("strdup failed\n");
+                               return TRUE;
+                       }
+
+                       for (l = sta_timer_list; l != NULL; l = g_slist_next(l)) {
+                               ptr = (sta_timer_t *)l->data;
+                               if (ptr == NULL) {
+                                       continue;
+                               }
+
+                               if (g_strcmp0(ptr->mac_addr, mac) == 0) {
+                                       g_free(mac);
+                                       mac = NULL;
+                                       break;
+                               }
+                       }
+
+                       /* Matched station found, so skip */
+                       if (l != NULL) {
+                               continue;
+                       }
+
+                       SDBG("%s%s\n", HOSTAPD_STA_CONN, mac);
+                       ptr = (sta_timer_t *)g_malloc(sizeof(sta_timer_t));
+                       if (ptr == NULL) {
+                               ERR("g_malloc failed\n");
+                               g_free(mac);
+                               mac = NULL;
+                               return TRUE;
+                       }
+                       ptr->mac_addr = mac;
+                       ptr->tid = g_timeout_add(HOSTAPD_DHCP_MAX_INTERVAL,
+                                       __hostapd_connect_timer_cb, mac);
+                       sta_timer_list = g_slist_append(sta_timer_list, ptr);
+
+               } else if (!strncmp(pbuf, HOSTAPD_STA_DISCONN, HOSTAPD_STA_DISCONN_LEN)) {
+                       pbuf = pbuf + HOSTAPD_STA_DISCONN_LEN;
+                       if (!pbuf || !*pbuf) {
+                               break;
+                       }
+
+                       end = strchr(pbuf, '<');
+                       if (end && *end) {
+                               mac = g_strndup(pbuf, (long)(end - pbuf));
+                               pbuf = end + 1;
+                       } else {
+                               mac = g_strdup(pbuf);
+                               pbuf += strlen(mac);
+                       }
+
+                       if (mac == NULL) {
+                               ERR("strdup failed\n");
+                               return TRUE;
+                       }
+
+                       SDBG("%s%s\n", HOSTAPD_STA_DISCONN, mac);
+                       _remove_station_info(mac, _slist_find_station_by_mac);
+
+                       /*
+                        * Destroy the timer if its not expired before disconnection
+                        */
+                       _destroy_dhcp_ack_timer(mac);
+                       g_free(mac);
+                       mac = NULL;
+                       discon_event = TRUE;
+
+               } else {
+                       pbuf = strchr(pbuf, '>');
+                       if (pbuf == NULL)
+                               break;
+                       pbuf++;
+               }
+       }
 
-               _get_station_count((gconstpointer)MOBILE_AP_TYPE_WIFI,
-                               _slist_find_station_by_interface, &n_station);
-               if (n_station == 0)
-                       _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
+       if (discon_event == FALSE)
+               goto DONE;
 
-               return TRUE;
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
+               type = MOBILE_AP_TYPE_WIFI;
+       } else if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
+               type = MOBILE_AP_TYPE_WIFI_AP;
        } else {
-               DBG("Event is not handled\n");
+               goto DONE;
        }
 
+       _get_station_count((gconstpointer)type,
+                       _slist_find_station_by_interface, &n_station);
+
+       if (n_station == 0) {
+               if (type == MOBILE_AP_TYPE_WIFI)
+                       _start_timeout_cb(type, time(NULL) + TETHERING_CONN_TIMEOUT);
+               else if (type == MOBILE_AP_TYPE_WIFI_AP)
+                       _start_timeout_cb(type, time(NULL) + WIFI_AP_CONN_TIMEOUT);
+       }
+DONE:
        return TRUE;
 }
 
@@ -434,7 +586,6 @@ static int __open_hostapd_monitor(int *fd)
        buf_len = sizeof(buf);
        __send_hostapd_req(*fd, HOSTAPD_MONITOR_ATTACH,
                        strlen(HOSTAPD_MONITOR_ATTACH), buf, &buf_len);
-       DBG("return : %s\n", buf);
 
        return MOBILE_AP_ERROR_NONE;
 }
@@ -448,7 +599,6 @@ static int __close_hostapd_monitor(int *fd)
        buf_len = sizeof(buf);
        __send_hostapd_req(*fd, HOSTAPD_MONITOR_DETACH,
                        strlen(HOSTAPD_MONITOR_DETACH), buf, &buf_len);
-       DBG("return : %s\n", buf);
 
        if (hostapd_io_source != 0) {
                g_source_remove(hostapd_io_source);
@@ -506,8 +656,118 @@ static mobile_ap_drv_interface_e __get_drv_interface(void)
        return drv_interface;
 }
 
-int _mh_core_enable_softap(const char *ssid, const char *security,
-               const char *key, int hide_mode)
+static int __mh_core_softap_firmware_start(void)
+{
+       int err = 0;
+       DBusError error;
+       DBusMessageIter iter;
+       DBusMessage *reply = NULL;
+       DBusMessage *message = NULL;
+       DBusConnection *connection = NULL;
+       const char *device = "softap";
+
+       connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+       if (connection == NULL) {
+               ERR("Failed to get system bus");
+               return -EIO;
+       }
+
+       message = dbus_message_new_method_call(NETCONFIG_SERVICE,
+                       NETCONFIG_WIFI_PATH, NETCONFIG_WIFI_INTERFACE ".Firmware", "Start");
+       if (message == NULL) {
+               ERR("Failed DBus method call");
+               dbus_connection_unref(connection);
+               return -EIO;
+       }
+
+       dbus_message_iter_init_append(message, &iter);
+       dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &device);
+
+       dbus_error_init(&error);
+
+       reply = dbus_connection_send_with_reply_and_block(connection, message,
+                       NETCONFIG_DBUS_REPLY_TIMEOUT, &error);
+       if (dbus_error_is_set(&error) == TRUE) {
+               if (NULL != strstr(error.message, ".AlreadyExists")) {
+                       // softap already enabled
+               } else {
+                       ERR("dbus_connection_send_with_reply_and_block() failed. "
+                                       "DBus error [%s: %s]", error.name, error.message);
+
+                       err = -EIO;
+
+                       dbus_error_free(&error);
+               }
+
+               dbus_error_free(&error);
+       }
+
+       if (reply != NULL)
+               dbus_message_unref(reply);
+
+       dbus_message_unref(message);
+       dbus_connection_unref(connection);
+
+       return err;
+}
+
+static int __mh_core_softap_firmware_stop(void)
+{
+       int err = 0;
+       DBusError error;
+       DBusMessageIter iter;
+       DBusMessage *reply = NULL;
+       DBusMessage *message = NULL;
+       DBusConnection *connection = NULL;
+       const char *device = "softap";
+
+       connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+       if (connection == NULL) {
+               ERR("Failed to get system bus");
+               return -EIO;
+       }
+
+       message = dbus_message_new_method_call(NETCONFIG_SERVICE,
+                       NETCONFIG_WIFI_PATH, NETCONFIG_WIFI_INTERFACE ".Firmware", "Stop");
+       if (message == NULL) {
+               ERR("Failed DBus method call");
+               dbus_connection_unref(connection);
+               return -EIO;
+       }
+
+       dbus_message_iter_init_append(message, &iter);
+       dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &device);
+
+       dbus_error_init(&error);
+
+       reply = dbus_connection_send_with_reply_and_block(connection, message,
+                       NETCONFIG_DBUS_REPLY_TIMEOUT, &error);
+       if (dbus_error_is_set(&error) == TRUE) {
+               if (NULL != strstr(error.message, ".AlreadyExists")) {
+                       // softap already disabled
+               } else {
+                       ERR("dbus_connection_send_with_reply_and_block() failed. "
+                                       "DBus error [%s: %s]", error.name, error.message);
+
+                       err = -EIO;
+
+                       dbus_error_free(&error);
+               }
+
+               dbus_error_free(&error);
+       }
+
+       if (reply != NULL)
+               dbus_message_unref(reply);
+
+       dbus_message_unref(message);
+       dbus_connection_unref(connection);
+
+       return err;
+}
+
+int _mh_core_enable_softap(const mobile_ap_type_e type, const char *ssid,
+               const char *security, const char *key, int hide_mode)
 {
        if (ssid == NULL || security == NULL || key == NULL) {
                ERR("Invalid param\n");
@@ -522,11 +782,11 @@ int _mh_core_enable_softap(const char *ssid, const char *security,
        char *if_name = WIFI_IF;
        char buf[MAX_BUF_SIZE] = { 0 };
 
-       snprintf(cmd, sizeof(cmd), "%s softap", WLAN_SCRIPT);
-       if (_execute_command(cmd)) {
-               ERR("execute script failed : %s\n", cmd);
+       char wext_ssid[MOBILE_AP_WIFI_SSID_MAX_LEN] = { 0 };
+       char *ptr = NULL;
+
+       if (__mh_core_softap_firmware_start() < 0)
                return MOBILE_AP_ERROR_INTERNAL;
-       }
 
        drv_interface = __get_drv_interface();
 
@@ -538,11 +798,19 @@ int _mh_core_enable_softap(const char *ssid, const char *security,
                        break;
                }
 
+               /*
+                * In case of Wireless extension interface,
+                * 32 byte SSID including null character can be accepted.
+                */
+               g_strlcpy(wext_ssid, ssid, sizeof(wext_ssid));
+               if (!g_utf8_validate(wext_ssid, -1, (const char **)&ptr))
+                       *ptr = '\0';
+
                snprintf(cmd, MAX_BUF_SIZE, "ASCII_CMD=AP_CFG,"
                                        "SSID_LEN=%d,SSID=%s,"
                                        "SEC=%s,KEY_LEN=%d,KEY=%s,CHANNEL=%d,"
                                        "PREAMBLE=0,MAX_SCB=%d,HIDE=%d,END",
-                                       strlen(ssid), ssid,
+                                       strlen(wext_ssid), wext_ssid,
                                        security, strlen(key), key,
                                        MOBILE_AP_WIFI_CHANNEL,
                                        MOBILE_AP_MAX_WIFI_STA, hide_mode);
@@ -571,7 +839,6 @@ int _mh_core_enable_softap(const char *ssid, const char *security,
                        break;
                }
 
-               DBG("Setting softap is OK\n");
                ret_status = _mh_core_set_ip_address(WIFI_IF,
                                IP_ADDRESS_WIFI);
                if (ret_status != MOBILE_AP_ERROR_NONE) {
@@ -581,6 +848,7 @@ int _mh_core_enable_softap(const char *ssid, const char *security,
                break;
 
        case MOBILE_AP_NL80211:
+
                ret_status = _mh_core_set_ip_address(WIFI_IF,
                                IP_ADDRESS_SOFTAP);
                if (ret_status != MOBILE_AP_ERROR_NONE) {
@@ -588,7 +856,7 @@ int _mh_core_enable_softap(const char *ssid, const char *security,
                        break;
                }
 
-               ret_status = __execute_hostapd(ssid, security, key, hide_mode);
+               ret_status = __execute_hostapd(type, ssid, security, key, hide_mode);
                if (ret_status != MOBILE_AP_ERROR_NONE) {
                        ERR("__execute_hostapd is failed\n");
                        break;
@@ -612,16 +880,12 @@ int _mh_core_enable_softap(const char *ssid, const char *security,
                break;
 
        default:
-               DBG("Unknown driver interface : %d\n", drv_interface);
+               ERR("Unknown driver interface : %d\n", drv_interface);
                break;
        }
 
-       if (ret_status != MOBILE_AP_ERROR_NONE) {
-               snprintf(cmd, sizeof(cmd), "%s stop", WLAN_SCRIPT);
-               if (_execute_command(cmd)) {
-                       ERR("execute script failed : %s\n", cmd);
-               }
-       }
+       if (ret_status != MOBILE_AP_ERROR_NONE)
+               __mh_core_softap_firmware_stop();
 
        return ret_status;
 }
@@ -674,15 +938,12 @@ int _mh_core_disable_softap(void)
                break;
 
        default:
-               DBG("Unknown driver interface : %d\n", drv_interface);
+               ERR("Unknown driver interface : %d\n", drv_interface);
                break;
        }
 
-       snprintf(cmd, sizeof(cmd), "%s stop", WLAN_SCRIPT);
-       if (_execute_command(cmd)) {
-               ERR("execute script failed : %s\n", cmd);
+       if (__mh_core_softap_firmware_stop() < 0)
                ret_status = MOBILE_AP_ERROR_INTERNAL;
-       }
 
        return ret_status;
 }
@@ -716,7 +977,6 @@ static int __get_device_info_by_wext(softap_device_info_t *di)
        buf_ptr = buf;
 
        sscanf(buf_ptr, "%02x", &di->number);
-       DBG("connected station : %d\n", di->number);
 
        buf_ptr += 2;
        for (i = 0; i < di->number; i++) {
@@ -729,7 +989,7 @@ static int __get_device_info_by_wext(softap_device_info_t *di)
                                        l_bssid[0], l_bssid[1], l_bssid[2],
                                        l_bssid[3], l_bssid[4], l_bssid[5]);
 
-               DBG("STA[%d] address[%s]\n", i, di->bssid[i]);
+               SDBG("STA[%d] address[%s]\n", i, di->bssid[i]);
 
                buf_ptr += 12;
        }
@@ -782,7 +1042,7 @@ static int __get_device_info_by_nl80211(softap_device_info_t *di)
                        break;
                }
 
-               DBG("Station : %s\n", buf);
+               SDBG("Station : %s\n", buf);
                g_strlcpy(di->bssid[no_of_sta++], buf, MOBILE_AP_STR_INFO_LEN);
 
                buf_len = sizeof(buf);
@@ -865,8 +1125,10 @@ int _mh_core_execute_dhcp_server(void)
 
 int _mh_core_terminate_dhcp_server(void)
 {
+       int ret;
+
        if (dnsmasq_pid == 0) {
-               DBG("There is no dnsmasq\n");
+               ERR("There is no dnsmasq\n");
                return MOBILE_AP_ERROR_NONE;
        }
 
@@ -874,6 +1136,11 @@ int _mh_core_terminate_dhcp_server(void)
        waitpid(dnsmasq_pid, NULL, 0);
        dnsmasq_pid = 0;
 
+       ret = unlink(DNSMASQ_CONF_FILE);
+       if (ret < 0) {
+               ERR("unlink is failed : %s\n", strerror(errno));
+       }
+
        return MOBILE_AP_ERROR_NONE;
 }
 
@@ -884,7 +1151,63 @@ int _mh_core_enable_masquerade(const char *ext_if)
                return MOBILE_AP_ERROR_INVALID_PARAM;
        }
 
-       _add_data_usage_rule(TETHER_IF, ext_if);
+       int fd = -1;
+
+       fd = open(IP_FORWARD, O_WRONLY);
+       if (fd < 0) {
+               ERR("open failed\n");
+               return MOBILE_AP_ERROR_RESOURCE;
+       }
+
+       if (write(fd, "1", 1) != 1) {
+               ERR("write failed\n");
+               close(fd);
+               return MOBILE_AP_ERROR_INTERNAL;
+       }
+       close(fd);
+
+       _iptables_create_chain(TABLE_NAT, TETH_NAT_POST);
+       _iptables_add_rule(PKT_REDIRECTION_RULE, TABLE_NAT, CHAIN_POST,
+                       TETH_NAT_POST);
+       _iptables_add_rule(MASQ_RULE, TABLE_NAT, TETH_NAT_POST, ext_if);
+
+       _iptables_create_chain(TABLE_FILTER, TETH_FILTER_FW);
+
+       _iptables_add_rule(PKT_REDIRECTION_RULE, TABLE_FILTER, CHAIN_FW,
+                       TETH_FILTER_FW);
+
+       _iptables_add_rule(CLAMP_MSS_RULE, TABLE_FILTER, TETH_FILTER_FW);
+
+       _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
+               BT_IF_ALL, ext_if, ACTION_RETURN, STATE_RELATED_ESTAB);
+       _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
+               WIFI_IF, ext_if, ACTION_RETURN, STATE_RELATED_ESTAB);
+       _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
+               USB_IF, ext_if, ACTION_RETURN, STATE_RELATED_ESTAB);
+
+       _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
+               ext_if, BT_IF_ALL, ACTION_DROP, STATE_INVALID);
+       _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
+               ext_if, WIFI_IF, ACTION_DROP, STATE_INVALID);
+       _iptables_add_rule(FORWARD_RULE_WITH_ACTION_AND_STATE, TABLE_FILTER, TETH_FILTER_FW,
+               ext_if, USB_IF, ACTION_DROP, STATE_INVALID);
+
+       _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
+               ext_if, BT_IF_ALL, ACTION_RETURN);
+       _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
+               ext_if, WIFI_IF, ACTION_RETURN);
+       _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
+               ext_if, USB_IF, ACTION_RETURN);
+
+       _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
+               BT_IF_ALL, ext_if, ACTION_RETURN);
+       _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
+               WIFI_IF, ext_if, ACTION_RETURN);
+       _iptables_add_rule(FORWARD_RULE_WITH_ACTION, TABLE_FILTER, TETH_FILTER_FW,
+               USB_IF, ext_if, ACTION_RETURN);
+
+       _iptables_add_rule(DEFAULT_RULE, TABLE_FILTER, TETH_FILTER_FW,
+               ACTION_DROP);
 
        return MOBILE_AP_ERROR_NONE;
 }
@@ -896,20 +1219,32 @@ int _mh_core_disable_masquerade(const char *ext_if)
                return MOBILE_AP_ERROR_INVALID_PARAM;
        }
 
-       _del_data_usage_rule(TETHER_IF, ext_if);
+       int fd = -1;
 
-       return MOBILE_AP_ERROR_NONE;
-}
+       fd = open(IP_FORWARD, O_WRONLY);
+       if (fd < 0) {
+               ERR("open failed\n");
+               return MOBILE_AP_ERROR_RESOURCE;
+       }
 
-void _mh_core_add_data_to_array(GPtrArray *array, guint type, gchar *dev_name)
-{
-       GValue value = {0, {{0}}};
+       if (write(fd, "0", 1) != 1) {
+               ERR("write failed\n");
+               close(fd);
+               return MOBILE_AP_ERROR_INTERNAL;
+       }
+       close(fd);
+
+       _iptables_delete_rule(PKT_REDIRECTION_RULE, TABLE_NAT, CHAIN_POST,
+                       TETH_NAT_POST);
+       _iptables_flush_rules(TABLE_NAT, TETH_NAT_POST);
+       _iptables_delete_chain(TABLE_NAT, TETH_NAT_POST);
+
+       _iptables_delete_rule(PKT_REDIRECTION_RULE, TABLE_FILTER, CHAIN_FW,
+                       TETH_FILTER_FW);
+       _iptables_flush_rules(TABLE_FILTER, TETH_FILTER_FW);
+       _iptables_delete_chain(TABLE_FILTER, TETH_FILTER_FW);
 
-       g_value_init(&value, DBUS_STRUCT_UINT_STRING);
-       g_value_take_boxed(&value,
-                       dbus_g_type_specialized_construct(DBUS_STRUCT_UINT_STRING));
-       dbus_g_type_struct_set(&value, 0, type, 1, dev_name, G_MAXUINT);
-       g_ptr_array_add(array, g_value_get_boxed(&value));
+       return MOBILE_AP_ERROR_NONE;
 }
 
 int _mh_core_set_ip_address(const char *if_name, const in_addr_t ip)
@@ -918,11 +1253,10 @@ int _mh_core_set_ip_address(const char *if_name, const in_addr_t ip)
        struct sockaddr_in addr;
        int sock_fd;
 
-       DBG("if_name : %s ip address : 0x%X\n", if_name, ip);
+       SDBG("if_name : %s ip address : 0x%X\n", if_name, ip);
 
        if ((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
                ERR("socket open failed!!!\n");
-               perror("ioctl fail");
                return MOBILE_AP_ERROR_RESOURCE;
        }
 
@@ -936,14 +1270,12 @@ int _mh_core_set_ip_address(const char *if_name, const in_addr_t ip)
        memcpy(&ifr.ifr_addr, &addr, sizeof(struct sockaddr));
        if (ioctl(sock_fd, SIOCSIFADDR, &ifr) < 0) {
                ERR("ioctl failed...!!!\n");
-               perror("ioctl fail");
                close(sock_fd);
                return MOBILE_AP_ERROR_INTERNAL;
        }
 
        if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) < 0) {
                ERR("ioctl failed...!!!\n");
-               perror("ioctl fail");
                close(sock_fd);
                return MOBILE_AP_ERROR_INTERNAL;
        }
@@ -951,7 +1283,6 @@ int _mh_core_set_ip_address(const char *if_name, const in_addr_t ip)
        ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
        if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) < 0) {
                ERR("ioctl failed...!!!\n");
-               perror("ioctl fail");
                close(sock_fd);
                return MOBILE_AP_ERROR_INTERNAL;
        }
@@ -960,3 +1291,227 @@ int _mh_core_set_ip_address(const char *if_name, const in_addr_t ip)
 
        return MOBILE_AP_ERROR_NONE;
 }
+
+static gboolean __send_station_event_cb(gpointer data)
+{
+       int sig = GPOINTER_TO_INT(data);
+       int n_station = 0;
+       int type;
+       mobile_ap_station_info_t *si = NULL;
+
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
+               type = MOBILE_AP_TYPE_WIFI;
+       else if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP))
+               type = MOBILE_AP_TYPE_WIFI_AP;
+       else
+               return FALSE;
+
+       if (sig == SIGUSR1) {
+               DBG("STA connected(%d)\n", sig);
+               /* STA connection is handled in the dnsmasq signal handler */
+       } else if (sig == SIGUSR2) {
+               DBG("STA disconnected(%d)\n", sig);
+
+               /* Temporarily care only one station.
+                * Driver team should be support detail information */
+               if (_get_station_info((gconstpointer)type,
+                               _slist_find_station_by_interface,
+                               &si) != MOBILE_AP_ERROR_NONE) {
+                       return FALSE;
+               }
+               _remove_station_info(si->mac, _slist_find_station_by_mac);
+
+               _get_station_count((gconstpointer)type,
+                               _slist_find_station_by_interface, &n_station);
+               if (n_station == 0) {
+                       if (type == MOBILE_AP_TYPE_WIFI)
+                               _start_timeout_cb(type, time(NULL) + TETHERING_CONN_TIMEOUT);
+                       else if (type == MOBILE_AP_TYPE_WIFI_AP)
+                               _start_timeout_cb(type, time(NULL) + WIFI_AP_CONN_TIMEOUT);
+               }
+       }
+
+       return FALSE;
+}
+
+static void __handle_station_signal(int sig)
+{
+       int idle_id = 0;
+       idle_id = g_idle_add(__send_station_event_cb, GINT_TO_POINTER(sig));
+       if (idle_id == 0) {
+               ERR("g_idle_add is failed\n");
+       }
+}
+
+void _register_wifi_station_handler(void)
+{
+       struct sigaction sa;
+
+       if (__get_drv_interface() != MOBILE_AP_WEXT)
+               return;
+
+       memset(&sa, 0, sizeof(sa));
+       sa.sa_handler = __handle_station_signal;
+       sigaction(SIGUSR1, &sa, NULL);
+       sigaction(SIGUSR2, &sa, NULL);
+
+       return;
+}
+
+void _unregister_wifi_station_handler(void)
+{
+       struct sigaction sa;
+
+       if (__get_drv_interface() != MOBILE_AP_WEXT)
+               return;
+
+       memset(&sa, 0, sizeof(sa));
+       sa.sa_handler = SIG_DFL;
+       sigaction(SIGUSR1, &sa, NULL);
+       sigaction(SIGUSR2, &sa, NULL);
+
+       return;
+}
+
+static gboolean __hostapd_connect_timer_cb(gpointer user_data)
+{
+       char *mac = (char *)user_data;
+       GSList *l = NULL;
+       GSList *temp = NULL;
+       sta_timer_t *ptr = NULL;
+       mobile_ap_station_info_t *info = NULL;
+       time_t tm;
+       int n_station = 0;
+       int type;
+       int ret;
+
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
+               type = MOBILE_AP_TYPE_WIFI;
+       else if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP))
+               type = MOBILE_AP_TYPE_WIFI_AP;
+       else
+               return FALSE;
+
+       for (l = sta_timer_list; l != NULL; l = g_slist_next(l)) {
+               ptr = (sta_timer_t *)l->data;
+               if (ptr == NULL)
+                       continue;
+
+               if (!g_strcmp0(ptr->mac_addr, mac)) {
+                       DBG("client with Static IP, Add station\n");
+
+                       info = (mobile_ap_station_info_t *)g_malloc(sizeof(mobile_ap_station_info_t));
+                       if (info == NULL) {
+                               ERR("g_malloc failed\n");
+                               g_free(ptr->mac_addr);
+                               g_free(ptr);
+                               temp = l;
+                               l = g_slist_next(l);
+                               sta_timer_list = g_slist_delete_link(sta_timer_list, temp);
+                               break;
+                       }
+
+                       time(&tm);
+                       info->tm = tm;
+                       info->interface = type;
+                       g_strlcpy(info->ip, "", sizeof(info->ip));
+                       g_strlcpy(info->mac, mac, sizeof(info->mac));
+
+                       ret = _get_wifi_name_from_lease_info(mac, &info->hostname);
+                       if (ret != MOBILE_AP_ERROR_NONE)
+                               info->hostname = g_strdup(MOBILE_AP_NAME_UNKNOWN);
+
+                       g_free(ptr->mac_addr);
+                       g_free(ptr);
+                       temp = l;
+                       l = g_slist_next(l);
+                       sta_timer_list = g_slist_delete_link(sta_timer_list, temp);
+
+                       goto SUCCESS;
+               }
+       }
+
+       return FALSE;
+
+SUCCESS :
+       if (_add_station_info(info) != MOBILE_AP_ERROR_NONE) {
+               g_free(info->hostname);
+               g_free(info);
+               return FALSE;
+       }
+
+       _get_station_count((gconstpointer)type,
+                       _slist_find_station_by_interface, &n_station);
+       if (n_station == 1)
+               _stop_timeout_cb(type);
+
+       _send_dbus_station_info("DhcpConnected", info);
+
+       return FALSE;
+}
+
+void _flush_dhcp_ack_timer(void)
+{
+       DBG("+\n");
+
+       GSList *l = NULL;
+       GSList *temp = NULL;
+       sta_timer_t *ptr = NULL;
+
+       for (l = sta_timer_list; l != NULL; l = g_slist_next(l)) {
+               ptr = (sta_timer_t *)l->data;
+               if (ptr) {
+                       if (ptr->tid != 0) {
+                               g_source_remove(ptr->tid);
+                               ptr->tid = 0;
+                       }
+                       g_free(ptr->mac_addr);
+                       g_free(ptr);
+               }
+
+               temp = l;
+               l = g_slist_next(l);
+               sta_timer_list = g_slist_delete_link(sta_timer_list, temp);
+       }
+
+       DBG("-\n");
+       return;
+}
+
+void _destroy_dhcp_ack_timer(char *mac_addr)
+{
+       DBG("+\n");
+       if (mac_addr == NULL) {
+               ERR("mac address passed NULL\n");
+               return;
+       }
+
+       GSList *l = NULL;
+       GSList *temp = NULL;
+       sta_timer_t *ptr = NULL;
+
+       for (l = sta_timer_list; l != NULL; l = g_slist_next(l)) {
+
+               ptr = (sta_timer_t *)l->data;
+               if (ptr == NULL)
+                       continue;
+
+               if (!g_strcmp0(ptr->mac_addr, mac_addr)) {
+
+                       if (ptr->tid != 0) {
+                               g_source_remove(ptr->tid);
+                               ptr->tid = 0;
+                       }
+                       g_free(ptr->mac_addr);
+                       g_free(ptr);
+                       temp = l;
+                       l = g_slist_next(l);
+                       sta_timer_list = g_slist_delete_link(sta_timer_list,
+                                               temp);
+                       break;
+               }
+       }
+
+       DBG("-\n");
+       return;
+}
old mode 100644 (file)
new mode 100755 (executable)
index b5e86b5..ae444ac
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
 #include <glib.h>
 #include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <gio/gio.h>
 
-#include "mobileap_agent.h"
+#include "mobileap_softap.h"
 #include "mobileap_common.h"
-#include "mobileap_connman.h"
 #include "mobileap_usb.h"
 
+static GDBusMethodInvocation *g_context = NULL;
+static gboolean in_progress = FALSE;
+static GDBusConnection *conn = NULL;
+static guint subscription_id = 0;
+static int usb_client_state = 0;
+
+#define USB_SYSTEM_DEVICE_PATH "/Org/Tizen/System/DeviceD/Usb"
+#define USB_SYSTEM_DEVICE_IFACE        "org.tizen.system.deviced.Usb"
+#define USB_STATE_CHANGE_SIGNAL        "StateChanged"
+
+enum usbclient_state {
+       USBCLIENT_STATE_DISCONNECTED = 0x00, /* usb cable is detached */
+       USBCLIENT_STATE_CONNECTED    = 0x01, /* usb cable is attached */
+       /* usb cable is attached and available (ready to use) */
+       USBCLIENT_STATE_AVAILABLE    = 0x02,
+};
+
+/* GDbus Signal Handler for USB Device State Changes */
+static void __usb_device_state_change_cb(GDBusConnection *connection,
+       const gchar *sender_name, const gchar *object_path,
+       const gchar *interface_name, const gchar *signal_name,
+       GVariant *parameters, gpointer user_data)
+{
+       unsigned int value = 0;
+       Tethering *obj = (Tethering *)user_data;
+
+       if (NULL == parameters || NULL == obj) {
+               ERR("Paramters Invalid \n");
+               return;
+       }
+
+       if (strcmp(object_path, USB_SYSTEM_DEVICE_PATH) ||
+               strcmp(interface_name, USB_SYSTEM_DEVICE_IFACE) ||
+               strcmp(signal_name, USB_STATE_CHANGE_SIGNAL)) {
+               ERR("Unknown DBUS Signal\n");
+               return;
+       }
+       g_variant_get(parameters, "(u)", &value);
+       DBG("Received signal(%s), value: (%u)", signal_name, value);
+       DBG("USB connected ? (%s)", value & USBCLIENT_STATE_CONNECTED? "Yes":"No");
+       DBG("USB available ? (%s)", value & USBCLIENT_STATE_AVAILABLE? "Yes":"No");
+
+       if (USBCLIENT_STATE_DISCONNECTED == value) {
+               _disable_usb_tethering(obj);
+
+               if (g_context) {
+                       tethering_complete_enable_usb_tethering(obj, g_context, MOBILE_AP_ERROR_RESOURCE);
+                       g_context = NULL;
+               } else {
+                       tethering_emit_usb_off(obj, SIGNAL_MSG_NOT_AVAIL_INTERFACE);
+               }
+       }
+
+       usb_client_state = value;
+}
+
+int _dbus_register_usb_state_change_signal(void *data)
+{
+       mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
+       GError *error = NULL;
+
+#if !GLIB_CHECK_VERSION(2,36,0)
+       g_type_init();
+#endif
+
+       conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
+       if (error) {
+               ERR("Error occurred (%s)", error->message);
+               g_error_free(error);
+               ret = MOBILE_AP_ERROR_RESOURCE;
+               goto FAIL;
+       }
+       if (!conn) {
+               ERR("Failed to get gdbus connection");
+               ret = MOBILE_AP_ERROR_RESOURCE;
+               goto FAIL;
+       }
+
+       subscription_id = g_dbus_connection_signal_subscribe(
+                                               conn, NULL, USB_SYSTEM_DEVICE_IFACE,
+                                               USB_STATE_CHANGE_SIGNAL, USB_SYSTEM_DEVICE_PATH, NULL,
+                                               G_DBUS_SIGNAL_FLAGS_NONE, __usb_device_state_change_cb,
+                                               data, NULL);
+
+       if (subscription_id == 0) {
+               ERR("Failed to subscribe signal (%d)", USB_STATE_CHANGE_SIGNAL);
+               ret = MOBILE_AP_ERROR_RESOURCE;
+               goto FAIL;
+       }
+
+       usb_client_state = -1;
+       DBG("Successfully Subscribed USB State Signal Handler");
+       return ret;
+
+FAIL:
+       if (conn)
+               g_object_unref(conn);
+       return ret;
+}
 
 static void __handle_usb_disconnect_cb(keynode_t *key, void *data)
 {
@@ -40,9 +135,9 @@ static void __handle_usb_disconnect_cb(keynode_t *key, void *data)
                return;
        }
 
-       char *vconf_name;
+       char *vconf_name = NULL;
        int vconf_key;
-       TetheringObject *obj = (TetheringObject *)data;
+       Tethering *obj = (Tethering *)data;
 
        if (!_mobileap_is_enabled(MOBILE_AP_STATE_USB)) {
                ERR("USB tethering is not enabled\n");
@@ -55,21 +150,41 @@ static void __handle_usb_disconnect_cb(keynode_t *key, void *data)
        }
 
        vconf_name = vconf_keynode_get_name(key);
+       if (vconf_name == NULL) {
+               ERR("vconf_keynode_get_name is failed\n");
+               return;
+       }
        vconf_key = vconf_keynode_get_int(key);
-       DBG("key = %s, value = %d(int)\n", vconf_name, vconf_key);
+       if (vconf_key < 0) {
+               ERR("vconf_keynode_get_int is failed\n");
+               return;
+       }
+       SDBG("key = %s, value = %d(int)\n", vconf_name, vconf_key);
 
-       if (!strcmp(vconf_name, VCONFKEY_SYSMAN_USB_STATUS) &&
-                       vconf_key == VCONFKEY_SYSMAN_USB_DISCONNECTED)
+       /*
+        * P140305-02551: Disconnected State is implemented from DBUS instead of
+        * VCONF key.
+        */
+       if (usb_client_state == USBCLIENT_STATE_DISCONNECTED)
                DBG("USB is disconnected\n");
-       else if (!strcmp(vconf_name, VCONFKEY_SETAPPL_USB_MODE_INT) &&
+       else if (vconf_name && !strcmp(vconf_name, VCONFKEY_SETAPPL_USB_MODE_INT) &&
                        vconf_key != SETTING_USB_TETHERING_MODE)
-               DBG("USB Mode is changed [%d]\n", vconf_key);
+               SDBG("USB Mode is changed [%d]\n", vconf_key);
        else
                return;
 
        _disable_usb_tethering(obj);
-       _emit_mobileap_dbus_signal(obj, E_SIGNAL_USB_TETHER_OFF,
-                       SIGNAL_MSG_NOT_AVAIL_INTERFACE);
+
+       if (g_context) {
+               g_dbus_method_invocation_return_value(g_context,
+                               g_variant_new("(uu)", MOBILE_AP_ENABLE_USB_TETHERING_CFM,
+                                               MOBILE_AP_ERROR_RESOURCE));
+               g_context = NULL;
+       } else {
+               tethering_emit_usb_off(obj, SIGNAL_MSG_NOT_AVAIL_INTERFACE);
+       }
+
+       return;
 }
 
 static void __handle_usb_mode_change(keynode_t *key, void *data)
@@ -79,9 +194,10 @@ static void __handle_usb_mode_change(keynode_t *key, void *data)
                return;
        }
 
-       TetheringObject *obj = (TetheringObject *)data;
+       Tethering *obj = (Tethering *)data;
        int ret;
        int vconf_key;
+       guint idle_id;
 
        if (vconf_keynode_get_type(key) != VCONF_TYPE_INT) {
                ERR("Invalid vconf key\n");
@@ -89,7 +205,7 @@ static void __handle_usb_mode_change(keynode_t *key, void *data)
        }
 
        vconf_key = vconf_keynode_get_int(key);
-       DBG("key = %s, value = %d(int)\n",
+       SDBG("key = %s, value = %d(int)\n",
                        vconf_keynode_get_name(key), vconf_key);
 
        if (_mobileap_is_enabled(MOBILE_AP_STATE_USB)) {
@@ -98,29 +214,9 @@ static void __handle_usb_mode_change(keynode_t *key, void *data)
                        return;
                }
 
-               DBG("USB tethering mode enable\n");
-
-               ret = connman_enable_tethering(TECH_TYPE_USB, NULL,
-                                       NULL, NULL, 0);
-               if (ret != MOBILE_AP_ERROR_NONE) {
-                       _deinit_tethering(obj);
-                       ERR("connman_enable_tethering USB failed");
-                       vconf_ignore_key_changed(VCONFKEY_SYSMAN_USB_STATUS,
-                                       __handle_usb_disconnect_cb);
-                       _mobileap_clear_state(MOBILE_AP_STATE_USB);
-                       dbus_g_method_return(obj->usb_context,
-                               MOBILE_AP_ENABLE_USB_TETHERING_CFM, ret);
-                       obj->usb_context = NULL;
-                       return;
-               }
-
+               DBG("USB tethering is enabled\n");
                vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
                                __handle_usb_mode_change);
-               _emit_mobileap_dbus_signal(obj, E_SIGNAL_USB_TETHER_ON, NULL);
-               dbus_g_method_return(obj->usb_context,
-                               MOBILE_AP_ENABLE_USB_TETHERING_CFM,
-                               MOBILE_AP_ERROR_NONE);
-               obj->usb_context = NULL;
 
                /* USB Mode change is handled while USB tethering is enabled */
                vconf_notify_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
@@ -128,13 +224,24 @@ static void __handle_usb_mode_change(keynode_t *key, void *data)
                ret = vconf_get_int(VCONFKEY_SETAPPL_USB_MODE_INT, &vconf_key);
                if (ret != 0) {
                        ERR("vconf_get_int is failed. but ignored [%d]\n", ret);
-                       return;
                }
+
                if (vconf_key != SETTING_USB_TETHERING_MODE) {
                        ERR("USB Mode is changed suddenly\n");
                        _disable_usb_tethering(obj);
-                       _emit_mobileap_dbus_signal(obj, E_SIGNAL_USB_TETHER_OFF,
-                                       SIGNAL_MSG_NOT_AVAIL_INTERFACE);
+                       if (g_context) {
+                               tethering_complete_enable_usb_tethering(obj, g_context, MOBILE_AP_ERROR_RESOURCE);
+                               g_context = NULL;
+                       }
+                       return;
+               }
+               _add_interface_routing(USB_IF, IP_ADDRESS_USB);
+               _add_routing_rule(USB_IF);
+               tethering_emit_usb_on(obj);
+               _create_tethering_active_noti();
+               if (g_context) {
+                       tethering_complete_enable_usb_tethering(obj, g_context, MOBILE_AP_ERROR_NONE);
+                       g_context = NULL;
                }
        } else {
                if (vconf_key == SETTING_USB_TETHERING_MODE) {
@@ -145,16 +252,20 @@ static void __handle_usb_mode_change(keynode_t *key, void *data)
                DBG("USB tethering is disabled\n");
                vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
                                __handle_usb_mode_change);
-               _emit_mobileap_dbus_signal(obj, E_SIGNAL_USB_TETHER_OFF, NULL);
-               dbus_g_method_return(obj->usb_context,
-                               MOBILE_AP_DISABLE_USB_TETHERING_CFM,
-                               MOBILE_AP_ERROR_NONE);
-               obj->usb_context = NULL;
+               tethering_emit_usb_off(obj, NULL);
+               if (g_context) {
+                       tethering_complete_disable_usb_tethering(obj, g_context, MOBILE_AP_DISABLE_USB_TETHERING_CFM, NULL);
+                       g_context = NULL;
+               }
+
+               in_progress = FALSE;
+               idle_id = g_idle_add(_terminate_mobileap_agent, NULL);
+               if (idle_id == 0)
+                       ERR("g_idle_add is failed\n");
        }
 }
 
-mobile_ap_error_code_e _enable_usb_tethering(TetheringObject *obj,
-               DBusGMethodInvocation *context)
+mobile_ap_error_code_e _enable_usb_tethering(Tethering *obj)
 {
        mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
        int vconf_ret;
@@ -166,17 +277,15 @@ mobile_ap_error_code_e _enable_usb_tethering(TetheringObject *obj,
                return ret;
        }
 
-       if (obj->usb_context) {
-               ERR("USB request is progressing\n");
-               ret = MOBILE_AP_ERROR_IN_PROGRESS;
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
+               ERR("Wi-Fi AP is enabled\n");
+               ret = MOBILE_AP_ERROR_RESOURCE;
                return ret;
        }
 
-       vconf_notify_key_changed(VCONFKEY_SYSMAN_USB_STATUS,
-                       __handle_usb_disconnect_cb, obj);
-       vconf_ret = vconf_get_int(VCONFKEY_SYSMAN_USB_STATUS, &usb_mode);
-       if (vconf_ret != 0 || usb_mode == VCONFKEY_SYSMAN_USB_DISCONNECTED) {
-               ERR("Error getting vconf\n");
+       /* Register DBus Signal Handler for USB Client State */
+       if (_dbus_register_usb_state_change_signal(obj) != MOBILE_AP_ERROR_NONE) {
+               ERR("Failed to register dbus signal(%d)", ret);
                ret = MOBILE_AP_ERROR_RESOURCE;
                goto FAIL;
        }
@@ -186,44 +295,50 @@ mobile_ap_error_code_e _enable_usb_tethering(TetheringObject *obj,
                goto FAIL;
        }
 
-       if (!_init_tethering(obj)) {
-               ret = MOBILE_AP_ERROR_RESOURCE;
+       ret = _init_tethering();
+       if (ret != MOBILE_AP_ERROR_NONE) {
                goto FAIL;
        }
 
-       obj->usb_context = context;
        vconf_notify_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
                        __handle_usb_mode_change, (void *)obj);
 
        vconf_ret = vconf_get_int(VCONFKEY_SETAPPL_USB_MODE_INT, &usb_mode);
        if (vconf_ret != 0) {
                ERR("Error getting vconf\n");
-               obj->usb_context = NULL;
                vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
                                __handle_usb_mode_change);
-               _deinit_tethering(obj);
+               _deinit_tethering();
                ret = MOBILE_AP_ERROR_RESOURCE;
                goto FAIL;
        }
 
        if (usb_mode == SETTING_USB_TETHERING_MODE) {
-               obj->usb_context = NULL;
                vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
                                __handle_usb_mode_change);
+               _add_interface_routing(USB_IF, IP_ADDRESS_USB);
+               _add_routing_rule(USB_IF);
        }
 
        DBG("-\n");
        return MOBILE_AP_ERROR_NONE;
 
 FAIL:
-       vconf_ignore_key_changed(VCONFKEY_SYSMAN_USB_STATUS,
-                       __handle_usb_disconnect_cb);
+       /* Clear DBus Signal Handler for USB Client State */
+       if (conn) {
+               if (subscription_id > 0) {
+                       g_dbus_connection_signal_unsubscribe(conn, subscription_id);
+                       subscription_id = 0;
+               }
+               g_object_unref(conn);
+               conn = NULL;
+       }
        _mobileap_clear_state(MOBILE_AP_STATE_USB);
 
        return ret;
 }
 
-mobile_ap_error_code_e _disable_usb_tethering(TetheringObject *obj)
+mobile_ap_error_code_e _disable_usb_tethering(Tethering *obj)
 {
        mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
 
@@ -233,67 +348,73 @@ mobile_ap_error_code_e _disable_usb_tethering(TetheringObject *obj)
                return ret;
        }
 
-       _deinit_tethering(obj);
+       _deinit_tethering();
 
        if (_remove_station_info_all(MOBILE_AP_TYPE_USB) != MOBILE_AP_ERROR_NONE) {
                ERR("_remove_station_info_all is failed. Ignore it\n");
        }
 
+       /* Clear DBus Signal Handler for USB Client State */
+       if (conn) {
+               if (subscription_id > 0) {
+                       g_dbus_connection_signal_unsubscribe(conn, subscription_id);
+                       subscription_id = 0;
+               }
+               g_object_unref(conn);
+               conn = NULL;
+       }
+
        vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
                        __handle_usb_disconnect_cb);
-       vconf_ignore_key_changed(VCONFKEY_SYSMAN_USB_STATUS,
-                       __handle_usb_disconnect_cb);
-
-       ret = connman_disable_tethering(TECH_TYPE_USB);
-       if (ret != MOBILE_AP_ERROR_NONE) {
-               ERR("connman_disable_tethering is failed : %d\n", ret);
-               return ret;
-       }
 
        _mobileap_clear_state(MOBILE_AP_STATE_USB);
+       _del_routing_rule(USB_IF);
+       _del_interface_routing(USB_IF, IP_ADDRESS_USB);
+
        DBG("_disable_usb_tethering is done\n");
 
        return ret;
 }
 
-gboolean tethering_enable_usb_tethering(TetheringObject *obj,
-               DBusGMethodInvocation *context)
+gboolean tethering_enable_usb_tethering(Tethering *obj, GDBusMethodInvocation *context)
 {
        mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
+       gboolean ret_val = FALSE;
 
        DBG("+\n");
 
        g_assert(obj != NULL);
        g_assert(context != NULL);
 
+       if (g_context) {
+               DBG("It is turnning on\n");
+               tethering_complete_enable_usb_tethering(obj, g_context, MOBILE_AP_ERROR_IN_PROGRESS);
+               return FALSE;
+       }
+
+       g_context = context;
 
-       ret = _enable_usb_tethering(obj, context);
+       ret = _enable_usb_tethering(obj);
        if (ret != MOBILE_AP_ERROR_NONE) {
                ERR("_enable_usb_tethering() is failed : %d\n", ret);
-               dbus_g_method_return(context,
-                               MOBILE_AP_ENABLE_USB_TETHERING_CFM, ret);
-               return FALSE;
-       } else if (obj->usb_context == NULL) {
-               DBG("Don't need to wait for usb-setting\n");
-               ret = connman_enable_tethering(TECH_TYPE_USB, NULL, NULL,
-                                       NULL, 0);
-               if (ret != MOBILE_AP_ERROR_NONE) {
-                       _deinit_tethering(obj);
-                       return FALSE;
-               }
-               _emit_mobileap_dbus_signal(obj, E_SIGNAL_USB_TETHER_ON, NULL);
-               dbus_g_method_return(context,
-                               MOBILE_AP_ENABLE_USB_TETHERING_CFM, ret);
+               goto DONE;
        } else {
-               DBG("dbus will be returned by vconf callback\n");
+               DBG("Don't need to wait for usb-setting\n");
+               tethering_emit_usb_on(obj);
+               _create_tethering_active_noti();
+               ret_val = TRUE;
        }
 
-       return TRUE;
-}
+DONE:
+       tethering_complete_enable_usb_tethering(obj, g_context, ret);
+
+       g_context = NULL;
 
+       return ret_val;
+}
 
-gboolean tethering_disable_usb_tethering(TetheringObject *obj,
-               DBusGMethodInvocation *context)
+gboolean tethering_disable_usb_tethering(Tethering *obj,
+               GDBusMethodInvocation *context)
 {
        mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
        int usb_mode = SETTING_USB_NONE_MODE;
@@ -304,22 +425,24 @@ gboolean tethering_disable_usb_tethering(TetheringObject *obj,
        g_assert(obj != NULL);
        g_assert(context != NULL);
 
-       if (obj->usb_context) {
-               ERR("USB request is progressing\n");
-               ret = MOBILE_AP_ERROR_IN_PROGRESS;
-               dbus_g_method_return(context,
-                               MOBILE_AP_DISABLE_USB_TETHERING_CFM, ret);
+       if (g_context) {
+               DBG("It is turnning on\n");
+               tethering_complete_disable_usb_tethering(obj, context,
+                               MOBILE_AP_DISABLE_USB_TETHERING_CFM,
+                               MOBILE_AP_ERROR_IN_PROGRESS);
                return FALSE;
        }
 
+       g_context = context;
+
        ret = _disable_usb_tethering(obj);
        if (ret != MOBILE_AP_ERROR_NONE) {
-               dbus_g_method_return(context,
+               tethering_complete_disable_usb_tethering(obj, g_context,
                                MOBILE_AP_DISABLE_USB_TETHERING_CFM, ret);
+               g_context = NULL;
                return FALSE;
        }
 
-       obj->usb_context = context;
        vconf_notify_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
                        __handle_usb_mode_change, (void *)obj);
        vconf_ret = vconf_get_int(VCONFKEY_SETAPPL_USB_MODE_INT, &usb_mode);
@@ -327,81 +450,29 @@ gboolean tethering_disable_usb_tethering(TetheringObject *obj,
                ERR("Error getting vconf : %d. This error is ignored\n", vconf_ret);
                goto DONE;
        }
+
        if (usb_mode != SETTING_USB_TETHERING_MODE) {
                DBG("Don't need to wait for usb-setting\n");
                goto DONE;
        }
 
+       in_progress = TRUE;
+
        DBG("-\n");
        return TRUE;
 
 DONE:
        vconf_ignore_key_changed(VCONFKEY_SETAPPL_USB_MODE_INT,
                        __handle_usb_mode_change);
-       _emit_mobileap_dbus_signal(obj, E_SIGNAL_USB_TETHER_OFF, NULL);
-       dbus_g_method_return(context,
+       tethering_emit_usb_off(obj, NULL);
+       tethering_complete_disable_usb_tethering(obj, g_context,
                        MOBILE_AP_DISABLE_USB_TETHERING_CFM, ret);
-       return TRUE;
-}
-
-static void __add_usb_station_info_to_array(GPtrArray *array, mobile_ap_station_info_t *node)
-{
-       GValue value = {0, {{0}}};
-
-       g_value_init(&value, DBUS_STRUCT_STATION);
-       g_value_take_boxed(&value,
-                       dbus_g_type_specialized_construct(DBUS_STRUCT_STATION));
-       dbus_g_type_struct_set(&value, 0, node->ip, 1, node->mac,
-                       2, node->hostname, G_MAXUINT);
-       g_ptr_array_add(array, g_value_get_boxed(&value));
-}
-
-gboolean tethering_get_usb_station_info(TetheringObject *obj,
-                                               DBusGMethodInvocation *context)
-{
-       g_assert(obj != NULL);
-       g_assert(context != NULL);
-
-       GPtrArray *array = g_ptr_array_new();
-       mobile_ap_station_info_t *node = NULL;
-
-       if (_get_station_info((gconstpointer)MOBILE_AP_TYPE_USB,
-                               _slist_find_station_by_interface,
-                               &node) != MOBILE_AP_ERROR_NONE) {
-               DBG("There is no USB station\n");
-               dbus_g_method_return(context, array);
-               g_ptr_array_free(array, TRUE);
-               return TRUE;
-       }
-
-       __add_usb_station_info_to_array(array, node);
-       dbus_g_method_return(context, array);
-       g_ptr_array_free(array, TRUE);
+       g_context = NULL;
 
        return TRUE;
 }
 
-gboolean tethering_get_usb_interface_info(TetheringObject *obj,
-               DBusGMethodInvocation *context)
+gboolean _is_trying_usb_operation(void)
 {
-       g_assert(obj != NULL);
-       g_assert(context != NULL);
-
-       GPtrArray *array = g_ptr_array_new();
-       GValue value = {0, {{0}}};
-       struct in_addr addr;
-
-       addr.s_addr = htonl(IP_ADDRESS_USB);
-
-       g_value_init(&value, DBUS_STRUCT_INTERFACE);
-       g_value_take_boxed(&value,
-                       dbus_g_type_specialized_construct(DBUS_STRUCT_INTERFACE));
-       dbus_g_type_struct_set(&value, 0, USB_IF, 1, inet_ntoa(addr),
-                       2, inet_ntoa(addr), 3, IP_SUBNET_MASK, G_MAXUINT);
-
-       g_ptr_array_add(array, g_value_get_boxed(&value));
-       dbus_g_method_return(context, array);
-       g_ptr_array_free(array, TRUE);
-
-       return TRUE;
+       return (g_context ? TRUE : FALSE || in_progress);
 }
old mode 100644 (file)
new mode 100755 (executable)
index f2fcbee..9423947
 /*
- *  mobileap-agent
+ * mobileap-agent
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  *
- * Copyright 2012-2013  Samsung Electronics Co., Ltd
- *
- * Licensed under the Flora License, Version 1.1 (the "License");
+ * Licensed under the Apache License, Version 2.0 (the License);
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- * http://floralicense.org/license
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *
  */
 
 #include <glib.h>
 #include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
-#include <ckmc/ckmc-manager.h>
+#include <wifi.h>
+#include <wifi-direct.h>
 
-#include "mobileap_agent.h"
+#include "mobileap_softap.h"
 #include "mobileap_common.h"
-#include "mobileap_connman.h"
 #include "mobileap_wifi.h"
 #include "mobileap_handler.h"
 #include "mobileap_notification.h"
 
-#define TETHERING_WIFI_PASSPHRASE_STORE_KEY "tethering_wifi_passphrase"
-
-static int __generate_initial_passphrase(char *passphrase_buf);
-static mobile_ap_error_code_e __get_hide_mode(int *hide_mode);
-static mobile_ap_error_code_e __set_hide_mode(const int hide_mode);
-static mobile_ap_error_code_e __get_common_ssid(char *ssid, unsigned int size);
-static mobile_ap_error_code_e __get_security_type(char *security_type, unsigned int len);
-static mobile_ap_error_code_e __set_security_type(const char *security_type);
-static mobile_ap_error_code_e __get_passphrase(char *passphrase, unsigned int size, unsigned int *passphrase_len);
-static mobile_ap_error_code_e __set_passphrase(const char *passphrase, const unsigned int size);
-static gboolean __send_station_event_cb(gpointer data);
-static void __handle_station_signal(int sig);
-static mobile_ap_error_code_e __update_wifi_data(TetheringObject *obj);
-
-static int __generate_initial_passphrase(char *passphrase_buf)
+#define WIFI_RECOVERY_GUARD_TIME       1000    /* ms */
+
+static mobile_ap_error_code_e __update_softap_settings(softap_settings_t *st,
+       gchar *ssid, gchar *passphrase, int hide_mode, softap_security_type_e security_type);
+static int __turn_off_wifi(Tethering *obj);
+
+static GDBusMethodInvocation *g_context = NULL;
+static guint wifi_recovery_timeout_id = 0;
+static gboolean prev_wifi_on = FALSE;
+static wifi_saved_settings wifi_settings = {0, NULL, NULL, 0};
+static softap_settings_t obj_softap_settings = {0, "", "", ""};
+
+softap_settings_t *_get_softap_settings()
 {
+       return &obj_softap_settings;
+}
+static void _wifi_direct_state_cb(int error_code, wifi_direct_device_state_e state, void *user_data)
+{
+       bool wifi_state = false;
+
        DBG("+\n");
 
-       guint32 rand_int;
-       int index;
+       if (user_data == NULL) {
+               ERR("The param is NULL\n");
+               return;
+       }
+
+       Tethering *obj = (Tethering *)user_data;
+       int ret = 0;
+
+       if (state != WIFI_DIRECT_DEVICE_STATE_DEACTIVATED) {
+               ERR("Unknown state : %d\n", state);
+               return;
+       }
+
+       wifi_direct_unset_device_state_changed_cb();
+       wifi_direct_deinitialize();
+
+       if (error_code != 0) {
+               ERR("wifi_direct_deactivate fail in cb : %d\n", error_code);
+               ret = MOBILE_AP_ERROR_INTERNAL;
+               goto DONE;
+       }
+       DBG("Wi-Fi direct is turned off\n");
 
-       for (index = 0; index < MOBILE_AP_WIFI_KEY_MIN_LEN; index++) {
-               rand_int = g_random_int_range('a', 'z');
-               passphrase_buf[index] = rand_int;
+       wifi_is_activated(&wifi_state);
+       if (wifi_state) {
+               DBG("Wi-Fi is turned on. Turn off Wi-Fi");
+               if (__turn_off_wifi(obj) != MOBILE_AP_ERROR_NONE) {
+                       ERR("_turn_off_wifi is failed\n");
+                       ret = MOBILE_AP_ERROR_INTERNAL;
+                       goto DONE;
+               }
+               return;
+       }
+
+       ret = _enable_wifi_tethering(obj, wifi_settings.ssid, wifi_settings.key,
+                       wifi_settings.hide_mode, wifi_settings.security_type);
+       if (ret != MOBILE_AP_ERROR_NONE) {
+               ERR("_enable_wifi_tethering is failed\n");
+       } else {
+               tethering_emit_wifi_on(obj);
+               _create_tethering_active_noti();
        }
-       passphrase_buf[index] = '\0';
 
-       return index;
+DONE:
+       tethering_complete_enable_wifi_tethering(obj, g_context, ret);
+       g_context = NULL;
+
+       g_free(wifi_settings.ssid);
+       g_free(wifi_settings.key);
+       memset(&wifi_settings, 0, sizeof(wifi_settings));
+
+       DBG("-\n");
+       return;
 }
 
-static mobile_ap_error_code_e __get_hide_mode(int *hide_mode)
+static void __wifi_activated_cb(wifi_error_e result, void *user_data)
 {
-       if (hide_mode == NULL) {
-               ERR("Invalid param\n");
-               return MOBILE_AP_ERROR_INVALID_PARAM;
+       DBG("Wi-Fi on is done\n");
+
+       return;
+}
+
+static void __wifi_deactivated_cb(wifi_error_e result, void *user_data)
+{
+       DBG("+\n");
+
+       if (user_data == NULL) {
+               ERR("The param is NULL\n");
+               return;
        }
 
-       if (vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_HIDE, hide_mode) < 0) {
-               ERR("vconf_get_int is failed\n");
-               return MOBILE_AP_ERROR_RESOURCE;
+       Tethering *obj = (Tethering *)user_data;
+       int ret;
+
+       if (result != WIFI_ERROR_NONE) {
+               ERR("__wifi_deactivated_cb error : %d\n", result);
+               ret = MOBILE_AP_ERROR_INTERNAL;
+               goto DONE;
        }
 
-       return MOBILE_AP_ERROR_NONE;
+       DBG("Wi-Fi is turned off\n");
+
+       ret = _enable_wifi_tethering(obj, wifi_settings.ssid, wifi_settings.key,
+                       wifi_settings.hide_mode, wifi_settings.security_type);
+       if (ret != MOBILE_AP_ERROR_NONE) {
+               ERR("_enable_wifi_tethering is failed\n");
+       } else {
+               prev_wifi_on = TRUE;
+               tethering_emit_wifi_on(obj);
+               _create_tethering_active_noti();
+       }
+
+DONE:
+       tethering_complete_enable_wifi_tethering(obj, g_context, ret);
+
+       g_context = NULL;
+
+       g_free(wifi_settings.ssid);
+       g_free(wifi_settings.key);
+       memset(&wifi_settings, 0, sizeof(wifi_settings));
+
+       DBG("-\n");
+       return;
 }
 
-static mobile_ap_error_code_e __set_hide_mode(const int hide_mode)
+static int __turn_off_wifi(Tethering *obj)
 {
-       if (vconf_set_int(VCONFKEY_MOBILE_HOTSPOT_HIDE, hide_mode) < 0) {
-               ERR("vconf_set_int is failed\n");
-               return MOBILE_AP_ERROR_RESOURCE;
+       int ret;
+
+       ret = wifi_deactivate(__wifi_deactivated_cb, (void *)obj);
+       if (ret != WIFI_ERROR_NONE) {
+               ERR("wifi_deactivate() is failed : %d\n", ret);
+               return MOBILE_AP_ERROR_INTERNAL;
        }
 
        return MOBILE_AP_ERROR_NONE;
 }
 
-static mobile_ap_error_code_e __get_common_ssid(char *ssid, unsigned int size)
+static gboolean __turn_on_wifi_timeout_cb(gpointer user_data)
 {
-       if (ssid == NULL)
-               return MOBILE_AP_ERROR_INVALID_PARAM;
+       int ret;
+       guint idle_id;
 
-       char *ptr = NULL;
-       char *ptr_tmp = NULL;
+       wifi_recovery_timeout_id = 0;
 
-       ptr = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
-       if (ptr == NULL)
-               return MOBILE_AP_ERROR_RESOURCE;
+       ret = wifi_activate(__wifi_activated_cb, NULL);
+       if (ret != WIFI_ERROR_NONE) {
+               ERR("wifi_activate() is failed : %d\n", ret);
+       }
+
+       idle_id = g_idle_add(_terminate_mobileap_agent, NULL);
+       if (idle_id == 0) {
+               ERR("g_idle_add is failed\n");
+       }
 
-       if (!g_utf8_validate(ptr, -1, (const char **)&ptr_tmp))
-               *ptr_tmp = '\0';
+       return FALSE;
+}
+
+static int __turn_on_wifi(void)
+{
+       if (wifi_recovery_timeout_id > 0) {
+               g_source_remove(wifi_recovery_timeout_id);
+               wifi_recovery_timeout_id = 0;
+       }
 
-       g_strlcpy(ssid, ptr, size);
-       free(ptr);
+       wifi_recovery_timeout_id = g_timeout_add(WIFI_RECOVERY_GUARD_TIME,
+                       __turn_on_wifi_timeout_cb, NULL);
+       if (wifi_recovery_timeout_id == 0) {
+               ERR("g_timeout_add is failed\n");
+               return MOBILE_AP_ERROR_INTERNAL;
+       }
 
        return MOBILE_AP_ERROR_NONE;
 }
 
-static mobile_ap_error_code_e __get_security_type(char *security_type, unsigned int len)
+static gboolean __is_wifi_direct_on(void)
 {
-       if (security_type == NULL)
-               return MOBILE_AP_ERROR_INVALID_PARAM;
+       int wifi_direct_state = 0;
+       int ret;
 
-       char *type_str = NULL;
-       softap_security_type_e type;
-
-       if (vconf_get_int(VCONFKEY_MOBILE_HOTSPOT_SECURITY, (int *)&type) < 0) {
-               ERR("vconf_get_int is failed\n");
-               return MOBILE_AP_ERROR_RESOURCE;
+       ret = vconf_get_int(VCONFKEY_WIFI_DIRECT_STATE, &wifi_direct_state);
+       if (ret < 0) {
+               ERR("vconf_get_int() is failed : %d\n", ret);
+               return FALSE;
        }
 
-       switch (type) {
-       case SOFTAP_SECURITY_TYPE_OPEN:
-               type_str = SOFTAP_SECURITY_TYPE_OPEN_STR;
-               break;
+       return wifi_direct_state != 0 ? TRUE : FALSE;
+}
 
-       case SOFTAP_SECURITY_TYPE_WPA2_PSK:
-               type_str = SOFTAP_SECURITY_TYPE_WPA2_PSK_STR;
-               break;
+static int __turn_off_wifi_direct(Tethering *obj)
+{
+       int ret;
 
-       default:
-               ERR("Invalid data\n");
-               return MOBILE_AP_ERROR_RESOURCE;
+       ret = wifi_direct_initialize();
+       if (ret < 0) {
+               ERR("wifi_direct_initialize() is failed : %d\n", ret);
+               return MOBILE_AP_ERROR_INTERNAL;
+       }
+
+       ret = wifi_direct_set_device_state_changed_cb(_wifi_direct_state_cb, (void *)obj);
+       if (ret < 0) {
+               ERR("wifi_direct_set_device_state_changed_cb() is failed : %d\n", ret);
+               ret = wifi_direct_deinitialize();
+               DBG("wifi_direct_deinitialize() ret : %d\n", ret);
+               return MOBILE_AP_ERROR_INTERNAL;
        }
 
-       g_strlcpy(security_type, type_str, len);
+       ret = wifi_direct_deactivate();
+       if (ret < 0) {
+               ERR("wifi_direct_deactivate() is failed : %d\n", ret);
+               ret = wifi_direct_unset_device_state_changed_cb();
+               DBG("wifi_direct_unset_device_state_changed_cb() ret : %d\n", ret);
+               ret = wifi_direct_deinitialize();
+               DBG("wifi_direct_deinitialize() ret : %d\n", ret);
+               return MOBILE_AP_ERROR_INTERNAL;
+       }
 
        return MOBILE_AP_ERROR_NONE;
 }
 
-static mobile_ap_error_code_e __set_security_type(const char *security_type)
+static mobile_ap_error_code_e __update_softap_settings(softap_settings_t *st,
+       gchar *ssid, gchar *passphrase, int hide_mode, softap_security_type_e security_type)
 {
-       if (security_type == NULL) {
+       if (st == NULL) {
                ERR("Invalid param\n");
                return MOBILE_AP_ERROR_INVALID_PARAM;
        }
 
-       softap_security_type_e type;
+       g_strlcpy(st->ssid, ssid, sizeof(st->ssid));
 
-       if (!strcmp(security_type, SOFTAP_SECURITY_TYPE_OPEN_STR)) {
-               type = SOFTAP_SECURITY_TYPE_OPEN;
-       } else if (!strcmp(security_type, SOFTAP_SECURITY_TYPE_WPA2_PSK_STR)) {
-               type = SOFTAP_SECURITY_TYPE_WPA2_PSK;
+       if (security_type == SOFTAP_SECURITY_TYPE_WPA2_PSK) {
+               g_strlcpy(st->security_type, SOFTAP_SECURITY_TYPE_WPA2_PSK_STR,
+                       sizeof(st->security_type));
+               g_strlcpy(st->key, passphrase, sizeof(st->key));
+       } else if (security_type == SOFTAP_SECURITY_TYPE_OPEN) {
+               g_strlcpy(st->security_type, SOFTAP_SECURITY_TYPE_OPEN_STR,
+                       sizeof(st->security_type));
+               g_strlcpy(st->key, "00000000", sizeof(st->key));
        } else {
-               ERR("Invalid param\n");
-               return MOBILE_AP_ERROR_INVALID_PARAM;
+               ERR("Unknown security type\n");
+               return MOBILE_AP_ERROR_INTERNAL;
        }
 
-       if (vconf_set_int(VCONFKEY_MOBILE_HOTSPOT_SECURITY, type) < 0) {
-               ERR("vconf_set_int is failed\n");
-               return MOBILE_AP_ERROR_RESOURCE;
-       }
+       st->hide_mode = hide_mode;
+
+       SDBG("ssid : %s security type : %s hide mode : %d\n",
+                       st->ssid, st->security_type, st->hide_mode);
 
        return MOBILE_AP_ERROR_NONE;
 }
 
-static char *__add_shared_owner_prefix(const char *name)
+static gboolean __is_equal_softap_settings(softap_settings_t *a, softap_settings_t *b)
 {
-       char *ckm_alias = NULL;
+       if (a->hide_mode != b->hide_mode)
+               return FALSE;
 
-        if (name == NULL) {
-                ERR("Invalid parameter\n");
-                return MOBILE_AP_ERROR_INVALID_PARAM;
-        }
+       if (strcmp(a->ssid, b->ssid) != 0)
+               return FALSE;
+
+       if (strcmp(a->key, b->key) != 0)
+               return FALSE;
 
-        ckm_alias = g_strconcat(ckmc_owner_id_system, ckmc_owner_id_separator, name, NULL);
+       if (strcmp(a->security_type, b->security_type) != 0)
+               return FALSE;
 
-        return ckm_alias;
+       return TRUE;
 }
 
-static mobile_ap_error_code_e __get_passphrase(char *passphrase,
-               unsigned int size, unsigned int *passphrase_len)
+mobile_ap_error_code_e _reload_softap_settings(Tethering *obj,
+               gchar *ssid, gchar *key, gint hide_mode, gint security_type)
 {
-       if (passphrase == NULL || passphrase_len == NULL) {
-               ERR("Invalid parameter\n");
+       gboolean backup_prev_wifi_on = prev_wifi_on;
+       mobile_ap_error_code_e ret;
+       softap_settings_t *old_settings = _get_softap_settings();
+       softap_settings_t new_settings;
+
+       if (obj == NULL || ssid == NULL || !strlen(ssid)) {
+               ERR("invalid parameters\n");
                return MOBILE_AP_ERROR_INVALID_PARAM;
        }
 
-       int ret = 0;
-       char *password = NULL;
-       ckmc_raw_buffer_s *ckmc_buf;
-       char *alias = __add_shared_owner_prefix(TETHERING_WIFI_PASSPHRASE_STORE_KEY);
+       if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI))
+               return MOBILE_AP_ERROR_NONE;
 
-       ret = ckmc_get_data(alias, password, &ckmc_buf);
-       if (ret != CKMC_ERROR_NONE) {
-               ERR("Fail to get passphrase from key manager : %d\n", ret);
-               return MOBILE_AP_ERROR_RESOURCE;
+       ret = __update_softap_settings(&new_settings, ssid, key, hide_mode,
+                       (softap_security_type_e)security_type);
+       if (ret != MOBILE_AP_ERROR_NONE) {
+               ERR("__update_softap_settings is failed\n");
+               return ret;
        }
 
-       *passphrase_len = ckmc_buf->size;
-       g_strlcpy(passphrase, ckmc_buf->data, (*passphrase_len) + 1);
-       passphrase = (char*)ckmc_buf->data;
-
-       if (ckmc_buf)
-               ckmc_buffer_free(ckmc_buf);
-
-       return MOBILE_AP_ERROR_NONE;
-}
-
-static mobile_ap_error_code_e __set_passphrase(const char *passphrase, const unsigned int size)
-{
-       if (size < MOBILE_AP_WIFI_KEY_MIN_LEN || size > MOBILE_AP_WIFI_KEY_MAX_LEN ||
-                       passphrase == NULL) {
-               ERR("Invalid parameter\n");
-               return MOBILE_AP_ERROR_INVALID_PARAM;
+       if (__is_equal_softap_settings(&new_settings, old_settings) == TRUE) {
+               DBG("No need to reload settings\n");
+               return MOBILE_AP_ERROR_NONE;
        }
 
-       int ret = 0;
-       char *alias = __add_shared_owner_prefix(TETHERING_WIFI_PASSPHRASE_STORE_KEY);
-       ckmc_raw_buffer_s ckmc_buf;
-       ckmc_policy_s ckmc_policy;
-
-       ckmc_policy.password = NULL;
-       ckmc_policy.extractable = true;
+       prev_wifi_on = FALSE;
+       ret = _disable_wifi_tethering(obj);
 
-       ckmc_buf.data = (unsigned char *) passphrase;
-       ckmc_buf.size = strlen(passphrase);
+       prev_wifi_on = backup_prev_wifi_on;
+       if (ret != MOBILE_AP_ERROR_NONE) {
+               ERR("_disable_wifi_tethering is failed : %d\n", ret);
+               return ret;
+       }
 
-       ret = ckmc_save_data(alias, ckmc_buf, ckmc_policy);
-       if (ret != CKMC_ERROR_NONE) {
-               ERR("Fail to save the passphrase : %d\n", ret);
-               return MOBILE_AP_ERROR_RESOURCE;
+       ret = _enable_wifi_tethering(obj, ssid, key, hide_mode,
+                       (softap_security_type_e)security_type);
+       if (ret != MOBILE_AP_ERROR_NONE) {
+               ERR("_enable_wifi_tethering is failed : %d\n", ret);
+               return ret;
        }
+       tethering_emit_wifi_on(obj);
+       _create_tethering_active_noti();
 
        return MOBILE_AP_ERROR_NONE;
 }
 
-static gboolean __send_station_event_cb(gpointer data)
+mobile_ap_error_code_e _reload_softap_settings_for_ap(Tethering *obj,
+       gchar *ssid, gchar *key, gint hide_mode, gint security_type)
 {
-       int sig = GPOINTER_TO_INT(data);
-       int n_station = 0;
-       mobile_ap_station_info_t *si = NULL;
+       gboolean backup_prev_wifi_on = prev_wifi_on;
+       mobile_ap_error_code_e ret;
+       softap_settings_t *old_settings = _get_softap_settings();
+       softap_settings_t new_settings;
 
-       if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
-               return FALSE;
+       if (obj == NULL || ssid == NULL || !strlen(ssid)) {
+               ERR("invalid parameters\n");
+               return MOBILE_AP_ERROR_INVALID_PARAM;
        }
 
-       if (sig == SIGUSR1) {
-               DBG("STA connected(%d)\n", sig);
-               /* STA connection is handled in the dnsmasq signal handler */
-       } else if (sig == SIGUSR2) {
-               DBG("STA disconnected(%d)\n", sig);
-
-               /* Temporarily care only one station.
-                * Driver team should be support detail information */
-               if (_get_station_info(MOBILE_AP_TYPE_WIFI,
-                               _slist_find_station_by_interface,
-                               &si) != MOBILE_AP_ERROR_NONE) {
-                       return FALSE;
-               }
-               _remove_station_info(si->mac, _slist_find_station_by_mac);
+       ret = __update_softap_settings(&new_settings, ssid, key, hide_mode,
+                       (softap_security_type_e)security_type);
+       if (ret != MOBILE_AP_ERROR_NONE) {
+               ERR("__update_softap_settings is failed\n");
+               return ret;
+       }
 
-               _get_station_count((gconstpointer)MOBILE_AP_TYPE_WIFI,
-                               _slist_find_station_by_interface, &n_station);
-               if (n_station == 0)
-                       _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
+       if (__is_equal_softap_settings(&new_settings, old_settings) == TRUE) {
+               DBG("No need to reload settings\n");
+               return MOBILE_AP_ERROR_NONE;
        }
 
-       return FALSE;
-}
+       prev_wifi_on = FALSE;
 
-static void __handle_station_signal(int sig)
-{
-       g_idle_add(__send_station_event_cb, GINT_TO_POINTER(sig));
-       return;
-}
+       ret = _disable_wifi_ap(obj);
+       prev_wifi_on = backup_prev_wifi_on;
+       if (ret != MOBILE_AP_ERROR_NONE) {
+               ERR("_disable_wifi_ap is failed : %d\n", ret);
+               return ret;
+       }
 
-void _register_wifi_station_handler(void)
-{
-       struct sigaction sa;
+       ret = _enable_wifi_ap(obj, ssid, key, hide_mode,
+                       (softap_security_type_e)security_type);
+       if (ret != MOBILE_AP_ERROR_NONE) {
+               ERR("_enable_wifi_ap is failed : %d\n", ret);
+               return ret;
+       }
 
-       memset(&sa, 0, sizeof(sa));
-       sa.sa_handler = __handle_station_signal;
-       sigaction(SIGUSR1, &sa, NULL);
-       sigaction(SIGUSR2, &sa, NULL);
+       return MOBILE_AP_ERROR_NONE;
 }
 
-void _add_wifi_device_to_array(softap_device_info_t *di, GPtrArray *array)
+int _get_wifi_name_from_lease_info(const char *mac, char **name_buf)
 {
-       int i = 0;
-       GIOChannel *io = NULL;
-       gchar *line = NULL;
-       gchar *device_name = NULL;
-       gchar ip_addr[MOBILE_AP_STR_INFO_LEN] = {0, };
-       gchar mac_addr[MOBILE_AP_STR_INFO_LEN] = {0, };
-       gchar name[MOBILE_AP_STR_HOSTNAME_LEN] = {0, };
-       gchar expire[MOBILE_AP_STR_INFO_LEN] = {0, };
-       gchar extra[MOBILE_AP_STR_INFO_LEN] = {0, };
-
-       int found = 0;
-
-       for (i = 0; i < di->number; i++)
-               DBG("bssid[%d]:%s\n", i, di->bssid[i]);
+       if (mac == NULL || name_buf == NULL) {
+               return MOBILE_AP_ERROR_INVALID_PARAM;
+       }
 
-       DBG("Number of connected device:%d\n", di->number);
+       GIOChannel *io = NULL;
+       char *line = NULL;
+       char *device_name = MOBILE_AP_NAME_UNKNOWN;
+       char ip_addr[MOBILE_AP_STR_INFO_LEN] = {0, };
+       char mac_addr[MOBILE_AP_STR_INFO_LEN] = {0, };
+       char name[MOBILE_AP_STR_HOSTNAME_LEN] = {0, };
+       char expire[MOBILE_AP_STR_INFO_LEN] = {0, };
+       char extra[MOBILE_AP_STR_INFO_LEN] = {0, };
 
        io = g_io_channel_new_file(DNSMASQ_LEASES_FILE, "r", NULL);
+       if (io == NULL) {
+               return MOBILE_AP_ERROR_RESOURCE;
+       }
 
        while (g_io_channel_read_line(io, &line, NULL, NULL, NULL) ==
-                                                       G_IO_STATUS_NORMAL) {
-               sscanf(line, "%19s %19s %19s %19s %19s", expire, mac_addr,
-                                                       ip_addr, name, extra);
-               DBG("mac_addr:%s ip_addr:%s name:%s expire:%s\n", mac_addr,
-                                                       ip_addr, name, expire);
-
-               for (i = 0; i < di->number; i++) {
-                       if (g_ascii_strcasecmp(di->bssid[i], mac_addr) == 0) {
-                               if (!strcmp(name, "*"))
-                                       device_name = MOBILE_AP_NAME_UNKNOWN;
-                               else
-                                       device_name = name;
-
-                               _mh_core_add_data_to_array(array, MOBILE_AP_TYPE_WIFI,
-                                                               device_name);
-
-                               found++;
-
-                               break;
-                       }
-               }
-
+                       G_IO_STATUS_NORMAL) {
+               sscanf(line, "%19s %19s %19s %19s %19s",
+                               expire, mac_addr, ip_addr, name, extra);
                g_free(line);
+
+               if (g_ascii_strcasecmp(mac_addr, mac) == 0) {
+                       if (g_strcmp0(name, "*") != 0)
+                               device_name = name;
+                       break;
+               }
        }
        g_io_channel_unref(io);
 
-       /* Set the name UNKNOWN unless we got the name. */
-       for (i = found; i < di->number; i++) {
-               _mh_core_add_data_to_array(array, MOBILE_AP_TYPE_WIFI,
-                                                       MOBILE_AP_NAME_UNKNOWN);
-       }
+       *name_buf = g_strdup(device_name);
+
+       return MOBILE_AP_ERROR_NONE;
 }
 
-#ifdef TIZEN_ARM
-mobile_ap_error_code_e _wifi_softap_driverloader(gboolean action)
+mobile_ap_error_code_e _enable_wifi_tethering(Tethering *obj, gchar *ssid,
+       gchar *passphrase, int hide_mode, softap_security_type_e security_type)
 {
-       char cmd[MAX_BUF_SIZE];
-       int ret_status = MOBILE_AP_ERROR_NONE;
+       mobile_ap_error_code_e ret;
 
-       char *str = action ? "softap":"stop";
-       snprintf(cmd, sizeof(cmd), "%s %s", WLAN_SCRIPT, str);
-       if (_execute_command(cmd)) {
-               ERR("execute script failed : %s\n", cmd);
-               ret_status = MOBILE_AP_ERROR_INTERNAL;
+       if (obj == NULL || ssid == NULL || !strlen(ssid)) {
+               ERR("invalid parameters\n");
+               return MOBILE_AP_ERROR_INVALID_PARAM;
        }
-       return ret_status;
-}
-#endif
 
-mobile_ap_error_code_e _enable_wifi_tethering(TetheringObject *obj, gchar *ssid)
-{
-       mobile_ap_error_code_e ret;
+       if (security_type == SOFTAP_SECURITY_TYPE_WPA2_PSK && passphrase == NULL) {
+               ERR("passphrase is null\n");
+               return MOBILE_AP_ERROR_INVALID_PARAM;
+       }
+
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
+               ERR("Wi-Fi AP is already enabled\n");
+               ret = MOBILE_AP_ERROR_RESOURCE;
+               return ret;
+       }
 
        if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
                ERR("Wi-Fi tethering is already enabled\n");
@@ -375,352 +464,403 @@ mobile_ap_error_code_e _enable_wifi_tethering(TetheringObject *obj, gchar *ssid)
                return ret;
        }
 
-       /* Update Wi-Fi hotspot data to common object */
-       ret = __update_wifi_data(obj);
+       /* Update Wi-Fi hotspot data to global settings pointer */
+       ret = __update_softap_settings(&obj_softap_settings, ssid, passphrase,
+                       hide_mode, security_type);
        if (ret != MOBILE_AP_ERROR_NONE) {
                _mobileap_clear_state(MOBILE_AP_STATE_WIFI);
                return ret;
        }
 
-       if (ssid != NULL && strlen(ssid) > 0) {
-               DBG("Private(Passed) SSID is used : %s\n", ssid);
-               g_strlcpy(obj->ssid, ssid, sizeof(obj->ssid));
+       if (vconf_set_str(VCONFKEY_MOBILE_HOTSPOT_SSID,
+                       obj_softap_settings.ssid) < 0) {
+               ERR("vconf_set_str is failed\n");
        }
 
        /* Initialize tethering */
-       if (!_init_tethering(obj)) {
-               _mobileap_clear_state(MOBILE_AP_STATE_WIFI);
-               ret = MOBILE_AP_ERROR_RESOURCE;
-               return ret;
-       }
-
-       /* Upload driver */
-#ifdef TIZEN_ARM
-       ret = _wifi_softap_driverloader(TRUE);
+       _block_device_sleep();
+       ret = _init_tethering();
        if (ret != MOBILE_AP_ERROR_NONE) {
-               _deinit_tethering(obj);
                _mobileap_clear_state(MOBILE_AP_STATE_WIFI);
-               return ret;
+               goto DONE;
        }
-#endif
 
-       ret = connman_enable_tethering(TECH_TYPE_WIFI, obj->ssid,
-                       obj->security_type, obj->key, obj->hide_mode);
+       /* Upload driver */
+       ret = _mh_core_enable_softap(MOBILE_AP_TYPE_WIFI,
+                       obj_softap_settings.ssid,
+                       obj_softap_settings.security_type,
+                       obj_softap_settings.key,
+                       obj_softap_settings.hide_mode);
        if (ret != MOBILE_AP_ERROR_NONE) {
-#ifdef TIZEN_ARM
-               _wifi_softap_driverloader(FALSE);
-#endif
-               _deinit_tethering(obj);
+               _deinit_tethering();
                _mobileap_clear_state(MOBILE_AP_STATE_WIFI);
-               return ret;
+               goto DONE;
        }
-
        _delete_timeout_noti();
+
        _init_timeout_cb(MOBILE_AP_TYPE_WIFI, (void *)obj);
-       _start_timeout_cb(MOBILE_AP_TYPE_WIFI);
+       _start_timeout_cb(MOBILE_AP_TYPE_WIFI, time(NULL) + TETHERING_CONN_TIMEOUT);
 
-       return MOBILE_AP_ERROR_NONE;
+       _add_interface_routing(WIFI_IF, IP_ADDRESS_SOFTAP);
+       _add_routing_rule(WIFI_IF);
+
+DONE:
+       _unblock_device_sleep();
+       return ret;
 }
 
-mobile_ap_error_code_e _disable_wifi_tethering(TetheringObject *obj)
+mobile_ap_error_code_e _enable_wifi_ap(Tethering *obj,
+                                       gchar *ssid, gchar *passphrase, int hide_mode,
+                                       softap_security_type_e security_type)
 {
-       int ret = MOBILE_AP_ERROR_NONE;
+       mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
 
-       if (!_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
-               ERR("Wi-Fi tethering has not been activated\n");
-               ret = MOBILE_AP_ERROR_NOT_ENABLED;
-               return ret;
+       if (obj == NULL || ssid == NULL || !strlen(ssid)) {
+               ERR("invalid parameters\n");
+               return MOBILE_AP_ERROR_INVALID_PARAM;
        }
 
-       _deinit_timeout_cb(MOBILE_AP_TYPE_WIFI);
+       if (security_type == SOFTAP_SECURITY_TYPE_WPA2_PSK &&
+               (passphrase == NULL || strlen(passphrase) >= MOBILE_AP_WIFI_KEY_MAX_LEN)) {
+               ERR("hex key length is not correct\n");
+               return MOBILE_AP_ERROR_INVALID_PARAM;
+       }
 
-       if (_remove_station_info_all(MOBILE_AP_TYPE_WIFI) !=
-                       MOBILE_AP_ERROR_NONE) {
-               ERR("_remove_station_info_all is failed. Ignore it.\n");
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI | MOBILE_AP_STATE_BT
+                       | MOBILE_AP_STATE_USB)) {
+               ERR("Tethering is already enabled\n");
+               return MOBILE_AP_ERROR_RESOURCE;
+       }
+
+       if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI_AP)) {
+               ERR("Wi-Fi AP is already enabled\n");
+               return MOBILE_AP_ERROR_ALREADY_ENABLED;
        }
 
-       ret = connman_disable_tethering(TECH_TYPE_WIFI);
+       if (!_mobileap_set_state(MOBILE_AP_STATE_WIFI_AP)) {
+               return MOBILE_AP_ERROR_RESOURCE;
+       }
+       ret = __update_softap_settings(&obj_softap_settings, ssid, passphrase,
+                       hide_mode, security_type);
        if (ret != MOBILE_AP_ERROR_NONE) {
-               ERR("connman_disable_tethering is failed : %d\n", ret);
+               _mobileap_clear_state(MOBILE_AP_STATE_WIFI_AP);
                return ret;
        }
 
-       _deinit_tethering(obj);
-       _mobileap_clear_state(MOBILE_AP_STATE_WIFI);
+       _block_device_sleep();
+
+       if (_init_tethering() != MOBILE_AP_ERROR_NONE) {
+               _mobileap_clear_state(MOBILE_AP_STATE_WIFI_AP);
+               ret = MOBILE_AP_ERROR_RESOURCE;
+               goto DONE;
+       }
 
-#ifdef TIZEN_ARM
-       ret = _wifi_softap_driverloader(FALSE);
+       /* Upload driver */
+       ret = _mh_core_enable_softap(MOBILE_AP_TYPE_WIFI_AP,
+                       obj_softap_settings.ssid,
+                       obj_softap_settings.security_type,
+                       obj_softap_settings.key,
+                       obj_softap_settings.hide_mode);
        if (ret != MOBILE_AP_ERROR_NONE) {
-               ERR("unload softap driver is failed : %d\n", ret);
-               return ret;
+               _deinit_tethering();
+               _mobileap_clear_state(MOBILE_AP_STATE_WIFI_AP);
+               goto DONE;
        }
-#endif
 
-       DBG("_disable_wifi_tethering is done\n");
+       _delete_timeout_noti();
+       _init_timeout_cb(MOBILE_AP_TYPE_WIFI_AP, (void *)obj);
+       _start_timeout_cb(MOBILE_AP_TYPE_WIFI_AP, time(NULL) + WIFI_AP_CONN_TIMEOUT);
+       _add_interface_routing(WIFI_IF, IP_ADDRESS_SOFTAP);
+       _add_routing_rule(WIFI_IF);
 
+DONE:
+       _unblock_device_sleep();
        return ret;
 }
 
-static mobile_ap_error_code_e __update_wifi_data(TetheringObject *obj)
+mobile_ap_error_code_e _disable_wifi_tethering(Tethering *obj)
 {
-       if (obj == NULL) {
-               ERR("Invalid param\n");
-               return MOBILE_AP_ERROR_INVALID_PARAM;
-       }
+       int ret;
+       int state;
+       mobile_ap_type_e type;
 
-       mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
-       unsigned int read_len = 0;
+       type = MOBILE_AP_TYPE_WIFI;
+       state = MOBILE_AP_STATE_WIFI;
 
-       ret = __get_common_ssid(obj->ssid, sizeof(obj->ssid));
-       if (ret != MOBILE_AP_ERROR_NONE)
+       if (!_mobileap_is_enabled(state)) {
+               ERR("Wi-Fi tethering ap has not been activated\n");
+               ret = MOBILE_AP_ERROR_NOT_ENABLED;
                return ret;
+       }
 
-       ret = __get_security_type(obj->security_type, sizeof(obj->security_type));
-       if (ret != MOBILE_AP_ERROR_NONE)
-               return ret;
+       _block_device_sleep();
+       _del_routing_rule(WIFI_IF);
+       _del_interface_routing(WIFI_IF, IP_ADDRESS_SOFTAP);
+       _flush_ip_address(WIFI_IF);
+       _deinit_timeout_cb(type);
 
-       ret = __get_hide_mode(&obj->hide_mode);
-       if (ret != MOBILE_AP_ERROR_NONE)
-               return ret;
+       if (_remove_station_info_all(type) != MOBILE_AP_ERROR_NONE) {
+               ERR("_remove_station_info_all is failed. Ignore it.\n");
+       }
 
-       if (strcmp(obj->security_type, SOFTAP_SECURITY_TYPE_OPEN_STR) == 0) {
-               g_strlcpy(obj->key, "00000000", sizeof(obj->key));
-       } else if (strcmp(obj->security_type, SOFTAP_SECURITY_TYPE_WPA2_PSK_STR) == 0) {
-               ret = __get_passphrase(obj->key, sizeof(obj->key), &read_len);
-               if (ret != MOBILE_AP_ERROR_NONE)
-                       return ret;
-       } else {
-               ERR("Unknown security type\n");
-               return MOBILE_AP_ERROR_INTERNAL;
+       ret = _mh_core_disable_softap();
+       if (ret != MOBILE_AP_ERROR_NONE) {
+               ERR("_mh_core_disable_softap is failed : %d\n", ret);
+               goto DONE;
        }
 
-       DBG("ssid : %s security type : %s hide mode : %d\n",
-                       obj->ssid, obj->security_type, obj->hide_mode);
+       _deinit_tethering();
+       _mobileap_clear_state(state);
 
-       return MOBILE_AP_ERROR_NONE;
+       if (prev_wifi_on == TRUE) {
+               DBG("Previous Wi-Fi was turned on. Recover it\n");
+               if (__turn_on_wifi() != MOBILE_AP_ERROR_NONE) {
+                       ERR("__turn_on_wifi() is failed\n");
+               }
+               prev_wifi_on = FALSE;
+       }
+       DBG("_disable_wifi_tethering is done\n");
+
+DONE:
+       _unblock_device_sleep();
+       return ret;
 }
 
-gboolean tethering_enable_wifi_tethering(TetheringObject *obj, gchar *ssid,
-               gchar *key, gint hide_mode, DBusGMethodInvocation *context)
+mobile_ap_error_code_e _disable_wifi_ap(Tethering *obj)
 {
-       mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
-       gboolean ret_val = FALSE;
-
-       g_assert(obj != NULL);
-       g_assert(context != NULL);
+       int ret;
+       int state;
+       mobile_ap_type_e type;
 
+       type = MOBILE_AP_TYPE_WIFI_AP;
+       state = MOBILE_AP_STATE_WIFI_AP;
 
-       ret = _enable_wifi_tethering(obj, ssid);
-       if (ret != MOBILE_AP_ERROR_NONE) {
-               ERR("_enable_wifi_tethering is failed\n");
-       } else {
-               _emit_mobileap_dbus_signal(obj, E_SIGNAL_WIFI_TETHER_ON, NULL);
-               ret_val = TRUE;
+       if (!_mobileap_is_enabled(state)) {
+               ERR("Wi-Fi ap tethering has not been activated\n");
+               ret = MOBILE_AP_ERROR_NOT_ENABLED;
+               return ret;
        }
 
-       dbus_g_method_return(context, MOBILE_AP_ENABLE_WIFI_TETHERING_CFM, ret);
-
-       return ret_val;
-}
-
-
-gboolean tethering_disable_wifi_tethering(TetheringObject *obj,
-               DBusGMethodInvocation *context)
-{
-       int ret = MOBILE_AP_ERROR_NONE;
+       _block_device_sleep();
+       _del_routing_rule(WIFI_IF);
+       _del_interface_routing(WIFI_IF, IP_ADDRESS_SOFTAP);
+       _flush_ip_address(WIFI_IF);
+       _deinit_timeout_cb(type);
 
-       DBG("+\n");
-       g_assert(obj != NULL);
-       g_assert(context != NULL);
+       if (_remove_station_info_all(type) != MOBILE_AP_ERROR_NONE) {
+               ERR("_remove_station_info_all is failed. Ignore it.\n");
+       }
 
-       ret = _disable_wifi_tethering(obj);
+       ret = _mh_core_disable_softap();
+       if (ret != MOBILE_AP_ERROR_NONE) {
+               ERR("_mh_core_disable_softap is failed : %d\n", ret);
+               goto DONE;
+       }
 
-       _emit_mobileap_dbus_signal(obj, E_SIGNAL_WIFI_TETHER_OFF, NULL);
-       dbus_g_method_return(context, MOBILE_AP_DISABLE_WIFI_TETHERING_CFM, ret);
+       _deinit_tethering();
+       _mobileap_clear_state(state);
 
-       if (ret != MOBILE_AP_ERROR_NONE)
-               return FALSE;
+       DBG("_disable_wifi_ap is done\n");
 
-       return TRUE;
+DONE:
+       _unblock_device_sleep();
+       return ret;
 }
 
-gboolean tethering_get_wifi_tethering_hide_mode(TetheringObject *obj,
-               DBusGMethodInvocation *context)
+gboolean tethering_enable_wifi_tethering(Tethering *obj,
+               GDBusMethodInvocation *context, gchar *ssid,
+               gchar *key, gint visibility, gint security_type)
 {
-       mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
-       int hide_mode = 0;
-
        DBG("+\n");
+       mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
+       gboolean ret_val = FALSE;
+       bool wifi_state = false;
        g_assert(obj != NULL);
        g_assert(context != NULL);
 
-       ret = __get_hide_mode(&hide_mode);
-       if (ret != MOBILE_AP_ERROR_NONE) {
-               ERR("__get_hide_mode is failed : %d\n", ret);
+       if (g_context) {
+               DBG("It is turnning on\n");
+               tethering_complete_enable_wifi_tethering(obj, g_context,
+                               MOBILE_AP_ERROR_IN_PROGRESS);
+               return FALSE;
        }
+       g_context = context;
 
-       dbus_g_method_return(context, hide_mode);
+       wifi_settings.ssid = g_strdup(ssid);
+       if (security_type == SOFTAP_SECURITY_TYPE_WPA2_PSK) {
+               wifi_settings.key = g_strdup(key);
+               wifi_settings.security_type = SOFTAP_SECURITY_TYPE_WPA2_PSK;
+       } else {
+               wifi_settings.security_type = SOFTAP_SECURITY_TYPE_OPEN;
+       }
+       wifi_settings.hide_mode = (!visibility);
 
-       return TRUE;
-}
+       if (wifi_recovery_timeout_id) {
+               DBG("Wi-Fi recovery is cancelled\n");
+               g_source_remove(wifi_recovery_timeout_id);
+               wifi_recovery_timeout_id = 0;
+               prev_wifi_on = TRUE;
+       }
 
-gboolean tethering_set_wifi_tethering_hide_mode(TetheringObject *obj,
-               gint hide_mode, DBusGMethodInvocation *context)
-{
-       int ret = 0;
+       if (__is_wifi_direct_on() == TRUE) {
+               DBG("Wi-Fi and Wi-Fi direct are turned on\n");
+               if (__turn_off_wifi_direct(obj) != MOBILE_AP_ERROR_NONE) {
+                       ERR("_turn_off_wifi_direct is failed\n");
+                       ret = MOBILE_AP_ERROR_INTERNAL;
+                       goto DONE;
+               }
 
-       DBG("+\n");
-       g_assert(obj != NULL);
-       g_assert(context != NULL);
+               return TRUE;
+       }
 
-       int old_hide_mode;
+       wifi_is_activated(&wifi_state);
+       if (wifi_state == true) {
+               DBG("Wi-Fi is turned on\n");
+               if (__turn_off_wifi(obj) != MOBILE_AP_ERROR_NONE) {
+                       ERR("_turn_off_wifi is failed\n");
+                       ret = MOBILE_AP_ERROR_INTERNAL;
+                       goto DONE;
+               }
 
-       ret = __get_hide_mode(&old_hide_mode);
-       if (ret != MOBILE_AP_ERROR_NONE) {
-               ERR("__get_hide_mode is failed : %d\n", ret);
-       } else if (old_hide_mode == hide_mode) {
-               DBG("old_hide_mode == hide_mode\n");
-               dbus_g_method_return(context);
                return TRUE;
        }
 
-       ret = __set_hide_mode(hide_mode);
-       if (ret < 0) {
-               ERR("__set_hide_mode is failed : %d\n", ret);
+       ret = _enable_wifi_tethering(obj, ssid, key, !visibility,
+                       (softap_security_type_e)security_type);
+       if (ret != MOBILE_AP_ERROR_NONE) {
+               ERR("_enable_wifi_tethering is failed\n");
+       } else {
+               tethering_emit_wifi_on(obj);
+               _create_tethering_active_noti();
+               ret_val = TRUE;
        }
 
-       _emit_mobileap_dbus_signal(obj, E_SIGNAL_SSID_VISIBILITY_CHANGED,
-                       hide_mode == VCONFKEY_MOBILE_AP_HIDE_OFF ?
-                       SIGNAL_MSG_SSID_VISIBLE :
-                       SIGNAL_MSG_SSID_HIDE);
-       dbus_g_method_return(context);
+DONE:
+       tethering_complete_enable_wifi_tethering(obj, g_context, ret);
+       g_context = NULL;
 
-       return TRUE;
+       g_free(wifi_settings.ssid);
+       g_free(wifi_settings.key);
+       memset(&wifi_settings, 0, sizeof(wifi_settings));
+
+       return ret_val;
 }
 
-gboolean tethering_get_wifi_tethering_ssid(TetheringObject *obj,
-               DBusGMethodInvocation *context)
+gboolean tethering_disable_wifi_tethering(Tethering *obj,
+               GDBusMethodInvocation *context)
 {
-       mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
-       char ssid[MOBILE_AP_WIFI_SSID_MAX_LEN + 1] = {0, };
+       int ret = MOBILE_AP_ERROR_NONE;
 
        DBG("+\n");
        g_assert(obj != NULL);
        g_assert(context != NULL);
 
-       if (_mobileap_is_enabled(MOBILE_AP_STATE_WIFI)) {
-               g_strlcpy(ssid, obj->ssid, sizeof(ssid));
-       } else {
-               ret = __get_common_ssid(ssid, sizeof(ssid));
-               if (ret != MOBILE_AP_ERROR_NONE) {
-                       ERR("__get_common_ssid is failed : %d\n", ret);
-               }
-       }
+       ret = _disable_wifi_tethering(obj);
+
+       tethering_emit_wifi_off(obj, NULL);
+       tethering_complete_disable_wifi_tethering(obj, context,
+                       MOBILE_AP_DISABLE_WIFI_TETHERING_CFM, ret);
 
-       dbus_g_method_return(context, ssid);
+
+       if (ret != MOBILE_AP_ERROR_NONE)
+               return FALSE;
 
        return TRUE;
 }
 
-gboolean tethering_get_wifi_tethering_security_type(TetheringObject *obj,
-               DBusGMethodInvocation *context)
+gboolean tethering_enable_wifi_ap(Tethering *obj, GDBusMethodInvocation *context,
+               gchar *ssid, gchar *key, gint visibility, gint security_type)
 {
        mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
-       char security_type[SECURITY_TYPE_LEN] = {0, };
+       gboolean ret_val = FALSE;
 
        DBG("+\n");
        g_assert(obj != NULL);
        g_assert(context != NULL);
 
-       ret = __get_security_type(security_type, sizeof(security_type));
-       if (ret != MOBILE_AP_ERROR_NONE) {
-               ERR("__get_security_type is failed : %d\n", ret);
+       if (wifi_recovery_timeout_id) {
+               DBG("Wi-Fi recovery is cancelled\n");
+               g_source_remove(wifi_recovery_timeout_id);
+               wifi_recovery_timeout_id = 0;
        }
 
-       dbus_g_method_return(context, security_type);
-
-       return TRUE;
+       ret = _enable_wifi_ap(obj, ssid, key, !visibility,
+                       (softap_security_type_e)security_type);
+       if (ret != MOBILE_AP_ERROR_NONE) {
+               ERR("_enable_wifi_tethering is failed\n");
+       } else {
+               tethering_emit_wifi_ap_on(obj);
+               ret_val = TRUE;
+       }
+       tethering_complete_enable_wifi_ap(obj, context, ret);
+       return ret_val;
 }
 
-gboolean tethering_set_wifi_tethering_security_type(TetheringObject *obj,
-               gchar *security_type, DBusGMethodInvocation *context)
+gboolean tethering_disable_wifi_ap(Tethering *obj,
+               GDBusMethodInvocation *context)
 {
-       mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
-       char old_security_type[SECURITY_TYPE_LEN] = {0, };
+       int ret = MOBILE_AP_ERROR_NONE;
 
        DBG("+\n");
        g_assert(obj != NULL);
        g_assert(context != NULL);
 
-       ret = __get_security_type(old_security_type, sizeof(old_security_type));
-       if (ret != MOBILE_AP_ERROR_NONE) {
-               ERR("__get_security_type is failed : %d\n", ret);
-       } else if (g_strcmp0(old_security_type, security_type) == 0) {
-               DBG("old_security_type == security_type\n");
-               dbus_g_method_return(context);
-               return TRUE;
-       }
-
-       ret = __set_security_type(security_type);
-       if (ret < 0) {
-               ERR("__set_security_type is failed: %d\n", ret);
-       }
+       ret = _disable_wifi_ap(obj);
+       tethering_emit_wifi_ap_off(obj, NULL);
+       tethering_complete_disable_wifi_ap(obj, g_context,
+                       MOBILE_AP_ENABLE_WIFI_AP_CFM, ret);
 
-       _emit_mobileap_dbus_signal(obj, E_SIGNAL_SECURITY_TYPE_CHANGED,
-                       security_type);
-       dbus_g_method_return(context);
+       if (ret != MOBILE_AP_ERROR_NONE)
+               return FALSE;
 
        return TRUE;
 }
 
-gboolean tethering_get_wifi_tethering_passphrase(TetheringObject *obj,
-               DBusGMethodInvocation *context)
+gboolean tethering_reload_wifi_settings(Tethering *obj,
+               GDBusMethodInvocation *context, gchar *ssid,
+               gchar *key, gint visibility, gint security_type)
 {
        mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
-       char passphrase[MOBILE_AP_WIFI_KEY_MAX_LEN + 1] = {0, };
-       unsigned int len = 0;
+       gboolean ret_val = TRUE;
 
        DBG("+\n");
        g_assert(obj != NULL);
        g_assert(context != NULL);
 
-       ret = __get_passphrase(passphrase, sizeof(passphrase), &len);
+       ret = _reload_softap_settings(obj, ssid, key, !visibility, security_type);
        if (ret != MOBILE_AP_ERROR_NONE) {
-               len = 0;
-               ERR("__get_password is failed : %d\n", ret);
+               ERR("_reload_softap_settings is failed\n");
+               ret_val = FALSE;
        }
 
-       dbus_g_method_return(context, passphrase, len);
+       tethering_complete_reload_wifi_settings(obj, context, ret);
 
-       return TRUE;
+       return ret_val;
 }
 
-gboolean tethering_set_wifi_tethering_passphrase(TetheringObject *obj,
-               gchar *passphrase, guint len, DBusGMethodInvocation *context)
+gboolean tethering_reload_wifi_ap_settings(Tethering *obj,
+               GDBusMethodInvocation *context, gchar *ssid,
+       gchar *key, gint visibility, gint security)
 {
+
        mobile_ap_error_code_e ret = MOBILE_AP_ERROR_NONE;
-       char old_passphrase[MOBILE_AP_WIFI_KEY_MAX_LEN + 1] = {0, };
-       unsigned int old_len = 0;
+       gboolean ret_val = TRUE;
 
        DBG("+\n");
        g_assert(obj != NULL);
        g_assert(context != NULL);
 
-       ret = __get_passphrase(old_passphrase, sizeof(old_passphrase), &old_len);
-       if (ret != MOBILE_AP_ERROR_NONE) {
-               ERR("__get_passphrase is failed : %d\n", ret);
-       } else if (old_len == len && !g_strcmp0(old_passphrase, passphrase)) {
-               dbus_g_method_return(context);
-               return TRUE;
-       }
-
-       ret = __set_passphrase(passphrase, len);
+       ret = _reload_softap_settings_for_ap(obj, ssid, key, !visibility, security);
        if (ret != MOBILE_AP_ERROR_NONE) {
-               ERR("__set_passphrase is failed : %d\n", ret);
+               ERR("_reload_softap_settings_for_ap is failed\n");
+               ret_val = FALSE;
        }
 
-       _emit_mobileap_dbus_signal(obj, E_SIGNAL_PASSPHRASE_CHANGED, NULL);
-       dbus_g_method_return(context);
+       tethering_complete_reload_wifi_ap_settings(obj, context, ret);
+       return ret_val;
+}
 
-       return TRUE;
+gboolean _is_trying_wifi_operation(void)
+{
+       return (g_context || wifi_recovery_timeout_id ? TRUE : FALSE);
 }
diff --git a/tethering_dump.sh b/tethering_dump.sh
new file mode 100644 (file)
index 0000000..887c55f
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Tethering module log dump (tethering_dump.sh)
+#
+
+# Variables
+TETH_DEBUG=$1/tethering
+mkdir -p ${TETH_DEBUG}
+
+# copy files
+#/bin/cp -a /tmp/hostapd.log ${TETH_DEBUG}
+/bin/cp -rf /tmp/dnsmasq.conf /opt/var/lib/misc/* ${TETH_DEBUG}
+
+#vconftool get db/mobile_hotspot > ${TETH_DEBUG}/vconf_db.log
+#vconftool get memory/mobile_hotspot > ${TETH_DEBUG}/vconf_memory.log
+/usr/sbin/iptables -t nat -L -vv > ${TETH_DEBUG}/iptables_nat.log
+/usr/sbin/iptables -L -vv > ${TETH_DEBUG}/iptables_filter.log