├── README.md ├── busybox ├── Android.mk └── busybox ├── cells ├── Android.mk ├── array.c ├── array.h ├── cell.c ├── cell_config.c ├── cell_config.h ├── cell_console.c ├── cell_console.h ├── celld.c ├── celld.h ├── cellnet.c ├── cellnet.h ├── cellsocket.cpp ├── cellsocket.h ├── ext │ ├── glibc_openpty.c │ └── glibc_pty.h ├── network.c ├── network.h ├── nl.c ├── nl.h ├── nsexec.c ├── nsexec.h ├── shared_ops.c ├── socket_common.h ├── util.c └── util.h ├── cells_build.mk ├── cellsservice ├── Android.mk ├── CellsPrivateService.cpp ├── CellsPrivateService.h ├── ICellsPrivateService.cpp ├── ICellsPrivateService.h ├── cellnet.c ├── cellnet.h ├── cellssync.cpp ├── cellsupdownvm.cpp ├── cswitch.cpp └── main_cells.cpp └── switchsystem ├── Android.mk ├── AndroidManifest.xml ├── libs ├── okhttp-3.9.0.jar └── okio-1.13.0.jar ├── proguard-project.txt ├── res ├── anim │ ├── dialog_enter.xml │ ├── dialog_exit.xml │ └── rotate_animation.xml ├── drawable-hdpi │ ├── ic_launcher.png │ ├── ic_launcher_general.png │ └── ic_launcher_secure.png ├── drawable-mdpi │ ├── ic_launcher.png │ ├── ic_launcher_general.png │ └── ic_launcher_secure.png ├── drawable-xhdpi │ ├── ic_launcher.png │ ├── ic_launcher_general.png │ └── ic_launcher_secure.png ├── drawable-xxhdpi │ ├── dialog_loading_img.png │ ├── ic_launcher.png │ ├── ic_launcher_general.png │ ├── ic_launcher_secure.png │ └── loading_bg.9.png ├── drawable │ ├── bcs.xml │ ├── dialog_loading.xml │ ├── loading_bg.9.png │ └── popup_bg.9.png ├── layout │ ├── activity_main.xml │ ├── activity_main1.xml │ ├── dialog_loading.xml │ ├── loading_progressba.xml │ └── progressbar.xml ├── menu │ └── main.xml ├── values-v11 │ ├── strings.xml │ └── styles.xml ├── values-v14 │ ├── strings.xml │ └── styles.xml ├── values-w820dp │ └── dimens.xml ├── values-zh-rCN │ └── strings.xml └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml └── src └── com └── cells └── cellswitch └── secure ├── download ├── DensityUtil.java ├── DownloadCallback.java ├── DownloadDispatcher.java ├── DownloadRunnable.java ├── DownloadTask.java ├── FileManager.java ├── MeasureUtils.java ├── OkHttpManager.java └── Utils.java ├── view ├── BaseActivity.java ├── BootCompleteReceiver.java ├── ExitAnimation.java ├── SwitchActivity.java └── WeiboDialogUtils.java └── wifip2p ├── FileBean.java ├── FileUtils.java ├── Md5Util.java ├── ProgressDialog.java ├── ReceiveSocket.java ├── ScreenUtils.java ├── SendSocket.java ├── SendTask.java ├── Wifip2pActionListener.java ├── Wifip2pReceiver.java └── Wifip2pService.java /README.md: -------------------------------------------------------------------------------- 1 | # cells-of-container-android 2 | 基于容器技术(lxc、docker、cells)的Android系统 3 | 4 | cells --- 容器基础代码 5 | 6 | cellsservice --- 容器启动、切换、停止、迁移等功能基础服务 7 | 8 | switchsystem --- 启动、切换、迁移APP 9 | 10 | 备注:cells-android10 仓库,有完整源码 11 | -------------------------------------------------------------------------------- /busybox/Android.mk: -------------------------------------------------------------------------------- 1 | # celld Makefile 2 | # 3 | # Copyright (C) 2011-2013 Columbia University 4 | # Author: Jeremy C. Andrus 5 | # 6 | 7 | LOCAL_PATH:= $(call my-dir) 8 | 9 | include $(CLEAR_VARS) 10 | 11 | LOCAL_MODULE := busybox 12 | LOCAL_SRC_FILES := $(LOCAL_MODULE) 13 | LOCAL_MODULE_TAGS := optional 14 | LOCAL_MODULE_OWNER := cells 15 | LOCAL_MODULE_CLASS := EXECUTABLES 16 | LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/bin 17 | 18 | include $(BUILD_PREBUILT) 19 | 20 | 21 | -------------------------------------------------------------------------------- /busybox/busybox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/busybox/busybox -------------------------------------------------------------------------------- /cells/Android.mk: -------------------------------------------------------------------------------- 1 | # celld Makefile 2 | # 3 | # Copyright (C) 2011-2013 Columbia University 4 | # Author: Jeremy C. Andrus 5 | # 6 | 7 | LOCAL_PATH := $(call my-dir) 8 | 9 | 10 | #------------------------------------------------------------------- 11 | # copy switch APK 12 | #------------------------------------------------------------------- 13 | # include $(CLEAR_VARS) 14 | # LOCAL_MODULE := SwitchSystem 15 | # LOCAL_SRC_FILES := $(LOCAL_MODULE).apk 16 | # LOCAL_MODULE_TAGS := optional eng 17 | # LOCAL_MODULE_CLASS := APPS 18 | # LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX) 19 | # #LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS) 20 | # LOCAL_MODULE_PATH := $(TARGET_OUT_APPS) 21 | # LOCAL_CERTIFICATE := platform 22 | # 23 | # include $(BUILD_PREBUILT) 24 | 25 | 26 | # 27 | # celld (container control daemon) 28 | # 29 | include $(CLEAR_VARS) 30 | 31 | LOCAL_CFLAGS := 32 | 33 | LOCAL_SRC_FILES:= \ 34 | ext/glibc_openpty.c \ 35 | cell_console.c \ 36 | nsexec.c \ 37 | shared_ops.c \ 38 | util.c \ 39 | celld.c \ 40 | cell_config.c \ 41 | nl.c \ 42 | network.c \ 43 | cellnet.c \ 44 | array.c \ 45 | 46 | LOCAL_MODULE := celld 47 | LOCAL_MODULE_TAGS := optional 48 | LOCAL_MODULE_OWNER := cells 49 | LOCAL_SHARED_LIBRARIES := libm libcutils libc libselinux liblog 50 | #LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) 51 | include $(BUILD_EXECUTABLE) 52 | 53 | 54 | # 55 | # cell (container control front-end) 56 | # 57 | include $(CLEAR_VARS) 58 | 59 | LOCAL_SRC_FILES := \ 60 | ext/glibc_openpty.c \ 61 | cell_console.c \ 62 | shared_ops.c \ 63 | util.c \ 64 | cell.c 65 | 66 | LOCAL_MODULE:= cellc 67 | LOCAL_MODULE_TAGS := optional 68 | LOCAL_MODULE_OWNER := cells 69 | LOCAL_SHARED_LIBRARIES := libm libcutils libc liblog 70 | include $(BUILD_EXECUTABLE) 71 | 72 | 73 | -------------------------------------------------------------------------------- /cells/array.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "array.h" 23 | 24 | 25 | #define INITIAL_CAPACITY (4) 26 | #define MAX_CAPACITY ((int)(UINT_MAX/sizeof(void*))) 27 | 28 | struct Array { 29 | void** contents; 30 | int size; 31 | int capacity; 32 | }; 33 | 34 | Array* arrayCreate() { 35 | return calloc(1, sizeof(struct Array)); 36 | } 37 | 38 | void arrayFree(Array* array) { 39 | assert(array != NULL); 40 | 41 | // Free internal array. 42 | free(array->contents); 43 | 44 | // Free the Array itself. 45 | free(array); 46 | } 47 | 48 | /** Returns 0 if successful, < 0 otherwise.. */ 49 | static int ensureCapacity(Array* array, int capacity) { 50 | int oldCapacity = array->capacity; 51 | if (capacity > oldCapacity) { 52 | int newCapacity = (oldCapacity == 0) ? INITIAL_CAPACITY : oldCapacity; 53 | 54 | // Ensure we're not doing something nasty 55 | if (capacity > MAX_CAPACITY) 56 | return -1; 57 | 58 | // Keep doubling capacity until we surpass necessary capacity. 59 | while (newCapacity < capacity) { 60 | int newCap = newCapacity*2; 61 | // Handle integer overflows 62 | if (newCap < newCapacity || newCap > MAX_CAPACITY) { 63 | newCap = MAX_CAPACITY; 64 | } 65 | newCapacity = newCap; 66 | } 67 | 68 | // Should not happen, but better be safe than sorry 69 | if (newCapacity < 0 || newCapacity > MAX_CAPACITY) 70 | return -1; 71 | 72 | void** newContents; 73 | if (array->contents == NULL) { 74 | // Allocate new array. 75 | newContents = malloc(newCapacity * sizeof(void*)); 76 | if (newContents == NULL) { 77 | return -1; 78 | } 79 | } else { 80 | // Expand existing array. 81 | newContents = realloc(array->contents, sizeof(void*) * newCapacity); 82 | if (newContents == NULL) { 83 | return -1; 84 | } 85 | } 86 | 87 | array->capacity = newCapacity; 88 | array->contents = newContents; 89 | } 90 | 91 | return 0; 92 | } 93 | 94 | int arrayAdd(Array* array, void* pointer) { 95 | assert(array != NULL); 96 | int size = array->size; 97 | int result = ensureCapacity(array, size + 1); 98 | if (result < 0) { 99 | return result; 100 | } 101 | array->contents[size] = pointer; 102 | array->size++; 103 | return 0; 104 | } 105 | 106 | static inline void checkBounds(Array* array __attribute__((__unused__)), int index __attribute__((__unused__))) { 107 | assert(array != NULL); 108 | assert(index < array->size); 109 | assert(index >= 0); 110 | } 111 | 112 | void* arrayGet(Array* array, int index) { 113 | checkBounds(array, index); 114 | return array->contents[index]; 115 | } 116 | 117 | void* arrayRemove(Array* array, int index) { 118 | checkBounds(array, index); 119 | 120 | void* pointer = array->contents[index]; 121 | 122 | int newSize = array->size - 1; 123 | 124 | // Shift entries left. 125 | if (index != newSize) { 126 | memmove(array->contents + index, array->contents + index + 1, 127 | (sizeof(void*)) * (newSize - index)); 128 | } 129 | 130 | array->size = newSize; 131 | 132 | return pointer; 133 | } 134 | 135 | void* arraySet(Array* array, int index, void* pointer) { 136 | checkBounds(array, index); 137 | void* old = array->contents[index]; 138 | array->contents[index] = pointer; 139 | return old; 140 | } 141 | 142 | int arraySetSize(Array* array, int newSize) { 143 | assert(array != NULL); 144 | assert(newSize >= 0); 145 | 146 | int oldSize = array->size; 147 | 148 | if (newSize > oldSize) { 149 | // Expand. 150 | int result = ensureCapacity(array, newSize); 151 | if (result < 0) { 152 | return result; 153 | } 154 | 155 | // Zero out new entries. 156 | memset(array->contents + sizeof(void*) * oldSize, 0, 157 | sizeof(void*) * (newSize - oldSize)); 158 | } 159 | 160 | array->size = newSize; 161 | 162 | return 0; 163 | } 164 | 165 | int arraySize(Array* array) { 166 | assert(array != NULL); 167 | return array->size; 168 | } 169 | 170 | const void** arrayUnwrap(Array* array) { 171 | return (const void**)array->contents; 172 | } 173 | -------------------------------------------------------------------------------- /cells/array.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * A pointer array which intelligently expands its capacity ad needed. 19 | */ 20 | 21 | #ifndef __ARRAY_H 22 | #define __ARRAY_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | #include 29 | 30 | /** An array. */ 31 | typedef struct Array Array; 32 | 33 | /** Constructs a new array. Returns NULL if we ran out of memory. */ 34 | Array* arrayCreate(); 35 | 36 | /** Frees an array. Does not free elements themselves. */ 37 | void arrayFree(Array* array); 38 | 39 | /** Adds a pointer. Returns 0 is successful, < 0 otherwise. */ 40 | int arrayAdd(Array* array, void* pointer); 41 | 42 | /** Gets the pointer at the specified index. */ 43 | void* arrayGet(Array* array, int index); 44 | 45 | /** Removes the pointer at the given index and returns it. */ 46 | void* arrayRemove(Array* array, int index); 47 | 48 | /** Sets pointer at the given index. Returns old pointer. */ 49 | void* arraySet(Array* array, int index, void* pointer); 50 | 51 | /** Sets the array size. Sets new pointers to NULL. Returns 0 if successful, < 0 otherwise . */ 52 | int arraySetSize(Array* array, int size); 53 | 54 | /** Returns the size of the given array. */ 55 | int arraySize(Array* array); 56 | 57 | /** 58 | * Returns a pointer to a C-style array which will be valid until this array 59 | * changes. 60 | */ 61 | const void** arrayUnwrap(Array* array); 62 | 63 | #ifdef __cplusplus 64 | } 65 | #endif 66 | 67 | #endif /* __ARRAY_H */ 68 | -------------------------------------------------------------------------------- /cells/cell_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cell_config.h 3 | * 4 | * Cell configuration definitions and routines 5 | * 6 | * Copyright (C) 2010-2013 Columbia University 7 | * Authors: Christoffer Dall 8 | * Jeremy C. Andrus 9 | * Alexander Van't Hof 10 | * 11 | * This program is free software; you can redistribute it and/or 12 | * modify it under the terms of the GNU General Public License 13 | * as published by the Free Software Foundation; either version 2 14 | * of the License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program; if not, write to the Free Software 23 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 24 | * USA. 25 | */ 26 | #ifndef CELL_CONFIG_H 27 | #define CELL_CONFIG_H 28 | 29 | #define MAX_CONFIG_KEY_LEN 50 /* Max length of config keywords */ 30 | #define MAX_CONFIG_LINE_LEN MAX_CONFIG_KEY_LEN + MAX_MSG_LEN 31 | #define CONFIG_DIR ".cellconf" 32 | 33 | struct config_info { 34 | int newcell; 35 | int uts_ns; 36 | int ipc_ns; 37 | int user_ns; 38 | int net_ns; 39 | int pid_ns; 40 | int mount_ns; 41 | int mnt_rootfs; 42 | int mnt_tmpfs; 43 | int newpts; 44 | int newcgrp; 45 | int sdcard_branch; 46 | int autostart; 47 | int autoswitch; 48 | int initpid; 49 | int restart_pid; /* pid of restart process */ 50 | int id; 51 | int console; 52 | }; 53 | 54 | int cell_exists(char *name); 55 | int id_exists(int id); 56 | int read_config(char *name, struct config_info *config); 57 | int write_config(char *name, struct config_info *config); 58 | int remove_config(char *name); 59 | void init_config(struct config_info *config); 60 | 61 | char **get_cell_names(void); 62 | void free_cell_names(char **name_list); 63 | void start_args_to_config(struct cell_start_args *args, 64 | struct config_info *config); 65 | void config_to_start_args(struct config_info *config, 66 | struct cell_start_args *args); 67 | 68 | void init_cellvm_config(char* name); 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /cells/cell_console.c: -------------------------------------------------------------------------------- 1 | /* 2 | * cell_console.c 3 | * 4 | * Routines supporting consoles on pseudo terminals within a cell 5 | * 6 | * Copyright (C) 2010-2013 Columbia University 7 | * Authors: Christoffer Dall 8 | * Jeremy C. Andrus 9 | * 10 | * This program is free software; you can redistribute it and/or 11 | * modify it under the terms of the GNU General Public License 12 | * as published by the Free Software Foundation; either version 2 13 | * of the License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 23 | * USA. 24 | */ 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #define LOG_TAG "Cells/console" 40 | #include 41 | 42 | #include "cell_console.h" 43 | #include "ext/glibc_pty.h" 44 | 45 | #define PRINT_BUF_LEN 256 46 | static void cell_console_rw_loop(int ptm, const char *cmd, const char *args) 47 | { 48 | fd_set rfds; 49 | fd_set efds; 50 | char buf[PRINT_BUF_LEN]; 51 | int ret; 52 | 53 | FD_ZERO(&rfds); 54 | FD_ZERO(&efds); 55 | 56 | if (cmd) { 57 | write(ptm, cmd, strlen(cmd)); 58 | if (args && *args) { 59 | write(ptm, " ", 1); 60 | write(ptm, args, strlen(args)); 61 | } 62 | write(ptm, "\r\n", 2); 63 | } 64 | 65 | while (1) { 66 | FD_SET(0, &rfds); 67 | FD_SET(ptm, &rfds); 68 | FD_SET(ptm, &efds); 69 | 70 | ret = select(ptm + 1, &rfds, NULL, &efds, NULL); 71 | if (ret < 0 && errno != EINTR) { 72 | ALOGE("select error:%d", errno); 73 | break; 74 | } 75 | 76 | if (FD_ISSET(0, &rfds)) { 77 | /* Read something from stdin and write to pty */ 78 | if ((ret = read(0, buf, PRINT_BUF_LEN)) > 0) { 79 | if (ret == 1 && buf[0] == 0x4) { 80 | /* Catch ctrl+d control code */ 81 | kill(getppid(), SIGINT); 82 | break; 83 | } 84 | write(ptm, buf, ret); 85 | } 86 | } 87 | if (FD_ISSET(ptm, &rfds)) { 88 | /* Read something from pty and write to stdout */ 89 | ret = read(ptm, buf, PRINT_BUF_LEN); 90 | if (ret > 0) 91 | write(1, buf, ret); 92 | if (cmd && (ret <= 0 || buf[ret-1] == 0x4)) 93 | break; 94 | } 95 | if (FD_ISSET(ptm, &efds)) { 96 | ALOGE("console ptm:%d error: exiting", ptm); 97 | break; 98 | } 99 | } 100 | 101 | if (ret < 0) 102 | perror("read tty's ptm"); 103 | } 104 | 105 | static void console_run_cmd(int ptm, const char *cmd) 106 | { 107 | fd_set rfds; 108 | fd_set efds; 109 | char buf[PRINT_BUF_LEN]; 110 | int ret; 111 | 112 | FD_ZERO(&rfds); 113 | FD_ZERO(&efds); 114 | while (1) { 115 | FD_SET(0, &rfds); 116 | FD_SET(ptm, &rfds); 117 | FD_SET(ptm, &efds); 118 | 119 | ret = select(ptm + 1, &rfds, NULL, &efds, NULL); 120 | if (ret < 0 && errno != EINTR) { 121 | ALOGE("select error:%d", errno); 122 | break; 123 | } 124 | 125 | if (FD_ISSET(0, &rfds)) { 126 | /* Read something from stdin and write to pty */ 127 | if ((ret = read(0, buf, PRINT_BUF_LEN)) > 0) { 128 | if (ret == 1 && buf[0] == 0x4) { 129 | /* Catch ctrl+d control code */ 130 | kill(getppid(), SIGINT); 131 | break; 132 | } 133 | write(ptm, buf, ret); 134 | } 135 | } 136 | if (FD_ISSET(ptm, &rfds)) { 137 | /* Read something from pty and write to stdout */ 138 | if ((ret = read(ptm, buf, PRINT_BUF_LEN)) > 0) 139 | write(1, buf, ret); 140 | } 141 | if (FD_ISSET(ptm, &efds)) { 142 | ALOGE("console ptm:%d error: exiting", ptm); 143 | break; 144 | } 145 | } 146 | 147 | if (ret < 0) 148 | perror("read tty's ptm"); 149 | } 150 | 151 | int create_cell_console(const char *container_root, struct pty_info *pi) 152 | { 153 | struct stat tty_stat; 154 | int fd; 155 | char tty_path[PATH_MAX]; /* Host tty path to file inside container */ 156 | 157 | if (!pi || !container_root) 158 | return -EINVAL; 159 | 160 | if (openpty(&pi->ptm, &pi->pty, pi->name, NULL, NULL)) { 161 | perror("openpty"); 162 | return -errno; 163 | } 164 | 165 | /* Prevent leaking the file descriptors to the container */ 166 | fcntl(pi->ptm, F_SETFD, FD_CLOEXEC); 167 | fcntl(pi->pty, F_SETFD, FD_CLOEXEC); 168 | 169 | /* construct /dev/console path */ 170 | snprintf(pi->cont_path, sizeof(pi->cont_path), 171 | "%s/dev/console", container_root); 172 | 173 | ALOGI("[create_cell_console] pi->cont_path[%s]", pi->cont_path); 174 | /* create a file to mount on if doesn't exist */ 175 | if (stat(pi->cont_path, &tty_stat) < 0) { 176 | if ((fd = creat(pi->cont_path, 0666)) < 0) { 177 | perror("creat(pi->cont_path)"); 178 | return -errno; 179 | } else { 180 | close(fd); 181 | } 182 | } 183 | 184 | if (mount(pi->name, pi->cont_path, "none", MS_BIND, 0) < 0) { 185 | perror("mount --bind /dev/pts/X /dev/console"); 186 | return -errno; 187 | } 188 | 189 | snprintf(tty_path, sizeof(tty_path), 190 | "%s/dev/ttyHSL0", container_root); 191 | 192 | 193 | if (stat(tty_path, &tty_stat) < 0) { 194 | if ((fd = creat(tty_path, 0666)) < 0) { 195 | perror("creat(tty_path)"); 196 | //return -errno; 197 | } else { 198 | close(fd); 199 | } 200 | } 201 | if (mount(pi->name, tty_path, "none", MS_BIND, 0) < 0) { 202 | perror("mount --bind /dev/pts/X /dev/tty"); 203 | //return -errno; 204 | } 205 | 206 | return 0; 207 | } 208 | 209 | /** 210 | * Opens a console using a pseudo-terminal master file descriptor. 211 | * 212 | * Catches ctrl+d to exit the container gracefully. 213 | * 214 | * @ptm: The ptm fd associated with the console 215 | * @cmd: an initial command to send to the console 216 | */ 217 | int open_cell_console(int ptm, const char *cmd, const char *args) 218 | { 219 | struct termios oldtios, newtios; 220 | 221 | /* Save current terminal settings */ 222 | if (tcgetattr(STDIN_FILENO, &oldtios) < 0) { 223 | perror("cannot get stdin termios attr"); 224 | return -1; 225 | } 226 | 227 | /* Copy the old terminal settings and change required bits */ 228 | memcpy(&newtios, &oldtios, sizeof(struct termios)); 229 | newtios.c_iflag &= ~IGNBRK; 230 | newtios.c_iflag &= BRKINT; 231 | newtios.c_lflag &= ~(ECHO|ICANON|ISIG); 232 | newtios.c_cc[VMIN] = 1; 233 | newtios.c_cc[VTIME] = 0; 234 | 235 | /* Set new terminal settings */ 236 | if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &newtios) < 0) { 237 | perror("set stdin termoios attr"); 238 | return -1; 239 | } 240 | 241 | /* Do console i/o to the terminal until a signal or EOF */ 242 | cell_console_rw_loop(ptm, cmd, args); 243 | 244 | /* Reset the terminal settings */ 245 | if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &oldtios) < 0) { 246 | perror("set stdin termoios attr"); 247 | return -1; 248 | } 249 | return 0; 250 | } 251 | 252 | /** 253 | * Closes file descriptors and conatiner mounted slave pts. 254 | * Should be called when the container has exited. 255 | */ 256 | void cleanup_cell_console(struct pty_info *pi) 257 | { 258 | close(pi->ptm); 259 | close(pi->pty); 260 | /*printf("Unmounting %s\n", pi->cont_path);*/ 261 | umount2(pi->cont_path, MNT_FORCE); /* Ignore failure */ 262 | } 263 | -------------------------------------------------------------------------------- /cells/cell_console.h: -------------------------------------------------------------------------------- 1 | /* 2 | * cell_console.h 3 | * 4 | * Copyright (C) 2010-2013 Columbia University 5 | * Authors: Christoffer Dall 6 | * Jeremy C. Andrus 7 | * 8 | * This program is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU General Public License 10 | * as published by the Free Software Foundation; either version 2 11 | * of the License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU General Public License 19 | * along with this program; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 21 | * USA. 22 | */ 23 | #ifndef CELL_CONSOLE_H 24 | #define CELL_CONSOLE_H 25 | 26 | #define PATH_MAX 4096 27 | 28 | struct pty_info { 29 | int ptm; /* Master pts file descriptor */ 30 | int pty; /* Slave file descriptor */ 31 | char name[PATH_MAX]; /* Path to slave in host /dev/pts */ 32 | char cont_path[PATH_MAX]; /* Host path to file inside container */ 33 | }; 34 | 35 | int open_cell_console(int ptm, const char *cmd, const char *args); 36 | int create_cell_console(const char *container_root, struct pty_info *pi); 37 | void cleanup_cell_console(struct pty_info *pi); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /cells/celld.h: -------------------------------------------------------------------------------- 1 | /* 2 | * celld.h 3 | * 4 | * Structures and definitions for the Cells controlling daemon, celld 5 | * 6 | * Copyright (C) 2010-2013 Columbia University 7 | * Authors: Christoffer Dall 8 | * Jeremy C. Andrus 9 | * Alexander Van't Hof 10 | * 11 | * This program is free software; you can redistribute it and/or 12 | * modify it under the terms of the GNU General Public License 13 | * as published by the Free Software Foundation; either version 2 14 | * of the License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program; if not, write to the Free Software 23 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 24 | * USA. 25 | */ 26 | #ifndef CELLD_H 27 | #define CELLD_H 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | 40 | #include "cell_console.h" 41 | 42 | #define SOCKET_PATH "celld" 43 | #define PRIV_SOCKET_PATH "TODO" 44 | #define CELLD_LOCKFILE "/data/.celldlock" 45 | #define DEFL_CELL_DIR "/data/cells" 46 | #define DEFL_SDCARD_ROOT "/mnt/user/cells" 47 | #define DEFL_START_OPTS "-MSdgimpwun" 48 | 49 | #define CONSOLE_READY_MSG "ready" 50 | #define CONSOLE_READY_MSG_LEN 8 51 | #define MAX_MSG_LEN 512 52 | #define MAX_NAME_LEN 64 53 | #define MAX_ARGS 20 54 | #define MAX_PATH_LEN 256 55 | 56 | /* Update CELL_CMD_REV if you change this enum in any way */ 57 | enum cell_cmd { 58 | CELL_CREATE, 59 | CELL_DESTROY, 60 | CELL_LIST, 61 | CELL_NEXT, 62 | CELL_PREV, 63 | 64 | CELL_START, 65 | CELL_STOP, 66 | CELL_SWITCH, 67 | CELL_CONSOLE, 68 | 69 | CELL_AUTOSTART, 70 | CELL_AUTOSWITCH, 71 | CELL_GETID, 72 | CELL_SETID, 73 | CELL_GETACTIVE, 74 | CELL_MOUNT, 75 | CELL_UNMOUNT, 76 | 77 | CELL_RUNCMD, 78 | 79 | CELL_MAXCOMMAND 80 | }; 81 | 82 | /* Update CELL_CMD_REV if you change this struct in any way */ 83 | struct cell_create_args { 84 | int id; /* -1: unspecified */ 85 | }; 86 | 87 | /* Update CELL_CMD_REV if you change this struct in any way */ 88 | struct cell_list_args { 89 | char all; 90 | char running; 91 | char zombie; 92 | }; 93 | 94 | /* Update CELL_CMD_REV if you change this struct in any way */ 95 | struct cell_start_args { 96 | char noopt; /* no start opions - use default or stored */ 97 | char uts_ns; 98 | char ipc_ns; 99 | char user_ns; 100 | char net_ns; 101 | char pid_ns; 102 | char mount_ns; 103 | char mnt_rootfs; 104 | char mnt_tmpfs; 105 | char newpts; 106 | char newcgrp; 107 | char sdcard_branch; 108 | char open_console; 109 | char autoswitch; 110 | char pid_file[MAX_PATH_LEN]; 111 | char wait; 112 | }; 113 | 114 | /* Update CELL_CMD_REV if you change this struct in any way */ 115 | /* if neither field is set, the status is retrieved */ 116 | struct cell_autostart_args { 117 | char on; 118 | char off; 119 | }; 120 | 121 | /* Update CELL_CMD_REV if you change this struct in any way */ 122 | struct cell_setid_args { 123 | int id; 124 | }; 125 | 126 | /* Update CELL_CMD_REV if you change this struct in any way */ 127 | struct cell_mount_args { 128 | int all; 129 | }; 130 | 131 | /* Update CELL_CMD_REV if you change this struct in any way */ 132 | struct cell_runcmd_args { 133 | char cmd[MAX_PATH_LEN]; 134 | }; 135 | 136 | /* Update this number if you change cell_cmd_arg in any way */ 137 | #define CELL_CMD_REV (0xbabe0010) 138 | struct cell_cmd_arg { 139 | enum cell_cmd cmd; 140 | char cellname[MAX_NAME_LEN]; 141 | union { 142 | struct cell_create_args create_args; 143 | struct cell_list_args list_args; 144 | struct cell_start_args start_args; 145 | struct cell_setid_args setid_args; 146 | struct cell_mount_args mount_args; 147 | struct cell_autostart_args autostart_args; 148 | struct cell_runcmd_args runcmd_args; 149 | }; 150 | }; 151 | 152 | struct cell_args { 153 | struct cell_start_args start_args; 154 | char cellname[MAX_NAME_LEN]; 155 | struct timeval start_time; 156 | char *rootdir; 157 | int init_pid; 158 | int restart_pid; 159 | char **argv; 160 | int argc; 161 | int cell_socket; 162 | int wifi_socket; 163 | int child_pipe[2]; 164 | int init_pipe[2]; 165 | }; 166 | 167 | struct cell_node { 168 | short init_pid; 169 | char name[MAX_NAME_LEN]; 170 | struct pty_info console_pty; 171 | short starting; 172 | short wifi_proxy; 173 | short id; 174 | short non_child; 175 | struct timeval start_time; 176 | struct cell_node *next; 177 | struct cell_node *prev; 178 | }; 179 | 180 | struct cell_list { 181 | struct cell_node *head; 182 | struct cell_node *tail; 183 | pthread_mutex_t mutex; 184 | }; 185 | 186 | struct cell_monitor_state { 187 | char name[MAX_NAME_LEN]; 188 | int pid; 189 | int child_fd; 190 | int init_fd; 191 | }; 192 | 193 | extern struct cell_node *active_cell; 194 | struct cell_node *search_cells_path(char *root_path); 195 | void switch_to_next(void); 196 | 197 | int init_addr(struct sockaddr_un *addr); 198 | int _send_msg(int fd, const char *fmt, va_list ap); 199 | int send_msg(int fd, const char *fmt, ...); 200 | int recv_msg_len(int fd, char **tok, char **msg, int len); 201 | int recv_msg(int fd, char **tok, char **msg); 202 | int send_fd(int conn_fd, int fd); 203 | int recv_fd(int conn_fd); 204 | 205 | extern char *get_rw_path(const char *name); 206 | extern char *get_root_path(const char *name); 207 | 208 | int mount_cell(char *name, int sdcard_mnt); 209 | int unmount_all(const char *root_path, int mount_fs); 210 | 211 | /* non-exported bionic functions */ 212 | extern pid_t __pthread_gettid(pthread_t tid); 213 | 214 | #endif /* CELLD_H */ 215 | -------------------------------------------------------------------------------- /cells/cellnet.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define LOG_TAG "Cells/cellnet" 11 | #include 12 | #include 13 | #include 14 | 15 | #define INTERFACE "wlan0" 16 | #define VETH0 "vm_wlan_%d_0" 17 | #define VETH1 "vm_wlan_%d_1" 18 | 19 | #define VETHIFACEADDRBASE 16 20 | 21 | #define VETHMASK 16 22 | #define VETHADDRMASK "255.255.0.0" 23 | #define VETHGATEADDR "172.%d.0.0" 24 | 25 | #define VETHIFACEADDR0 "172.%d.3.2" 26 | #define VETHIFACEADDR1 "172.%d.3.3" 27 | 28 | void init_cell_net() 29 | { 30 | 31 | } 32 | 33 | void createveth(int index) 34 | { 35 | int ret = 0; 36 | char vethname0[24] = {0}; 37 | char vethname1[24] = {0}; 38 | char vethaddr0[64] = {0}; 39 | char vethgateaddr[64] = {0}; 40 | 41 | char cmd[256] = {0}; 42 | 43 | snprintf(vethname0, sizeof(vethname0), VETH0, index); 44 | snprintf(vethname1, sizeof(vethname1), VETH1, index); 45 | snprintf(vethgateaddr, sizeof(vethgateaddr), VETHGATEADDR, VETHIFACEADDRBASE + index); 46 | snprintf(vethaddr0, sizeof(vethaddr0), VETHIFACEADDR0, VETHIFACEADDRBASE + index); 47 | 48 | errno = 0; 49 | memset(cmd, 0, sizeof(cmd)); 50 | snprintf(cmd, sizeof(cmd), "ip link add name %s type veth peer name %s", vethname0, vethname1); 51 | ret = system(cmd); 52 | ALOGD("%s errno = %s",cmd ,strerror(errno)); 53 | 54 | errno = 0; 55 | memset(cmd, 0, sizeof(cmd)); 56 | snprintf(cmd, sizeof(cmd), "ifconfig %s %s netmask %s up", vethname0, vethaddr0, VETHADDRMASK); 57 | ret = system(cmd); 58 | ALOGD("%s errno = %s",cmd ,strerror(errno)); 59 | 60 | errno = 0; 61 | memset(cmd, 0, sizeof(cmd)); 62 | snprintf(cmd, sizeof(cmd), "iptables -t nat -A POSTROUTING -s %s/%d -o %s -j MASQUERADE", vethgateaddr, VETHMASK, INTERFACE); 63 | ret = system(cmd); 64 | ALOGD("%s errno = %s",cmd ,strerror(errno)); 65 | 66 | errno = 0; 67 | memset(cmd, 0, sizeof(cmd)); 68 | snprintf(cmd, sizeof(cmd), "iptables -t filter -A FORWARD -i %s -o %s -j ACCEPT", INTERFACE, vethname0); 69 | ret = system(cmd); 70 | ALOGD("%s errno = %s",cmd ,strerror(errno)); 71 | 72 | errno = 0; 73 | memset(cmd, 0, sizeof(cmd)); 74 | snprintf(cmd, sizeof(cmd), "iptables -t filter -A FORWARD -o %s -i %s -j ACCEPT", INTERFACE, vethname0); 75 | ret = system(cmd); 76 | ALOGD("%s errno = %s",cmd ,strerror(errno)); 77 | } 78 | 79 | void vethtons(int pid,int index) 80 | { 81 | int ret = 0; 82 | char vethname1[24] = {0}; 83 | char cmd[256]; 84 | 85 | snprintf(vethname1, sizeof(vethname1), VETH1, index); 86 | 87 | errno = 0; 88 | memset(cmd,0,sizeof(cmd)); 89 | snprintf(cmd, sizeof(cmd), "ip link set %s netns %d",vethname1 ,pid ); 90 | ret = system(cmd); 91 | ALOGD("%s errno = %s",cmd,strerror(errno)); 92 | } 93 | 94 | void rnameveth(int index) 95 | { 96 | int ret = 0; 97 | char vethname1[24] = {0}; 98 | char vethaddr0[64] = {0}; 99 | char vethaddr1[64] = {0}; 100 | char cmd[256]; 101 | 102 | snprintf(vethname1, sizeof(vethname1), VETH1, index); 103 | snprintf(vethaddr0, sizeof(vethaddr0), VETHIFACEADDR0, VETHIFACEADDRBASE + index); 104 | snprintf(vethaddr1, sizeof(vethaddr1), VETHIFACEADDR1, VETHIFACEADDRBASE + index); 105 | 106 | errno = 0; 107 | memset(cmd,0,sizeof(cmd)); 108 | snprintf(cmd, sizeof(cmd), "ip link set %s name %s",vethname1 ,INTERFACE ); 109 | ret = system(cmd); 110 | ALOGD("%s errno = %s",cmd,strerror(errno)); 111 | 112 | errno = 0; 113 | memset(cmd,0,sizeof(cmd)); 114 | snprintf(cmd, sizeof(cmd), "ifconfig %s %s netmask %s up",INTERFACE,vethaddr1,VETHADDRMASK); 115 | ret = system(cmd); 116 | ALOGD("%s errno = %s",cmd,strerror(errno)); 117 | 118 | errno = 0; 119 | memset(cmd,0,sizeof(cmd)); 120 | snprintf(cmd, sizeof(cmd), "ip ro add default via %s dev %s",vethaddr0 ,INTERFACE); 121 | ret = system(cmd); 122 | ALOGD("%s errno = %s",cmd,strerror(errno)); 123 | } 124 | 125 | void starttether(int index) 126 | { 127 | int ret = 0; 128 | char vethname0[24] = {0}; 129 | char vethaddr0[64] = {0}; 130 | char vethgateaddr[64] = {0}; 131 | 132 | char cmd[256] = {0}; 133 | 134 | snprintf(vethname0, sizeof(vethname0), VETH0, index); 135 | snprintf(vethgateaddr, sizeof(vethgateaddr), VETHGATEADDR, VETHIFACEADDRBASE + index); 136 | snprintf(vethaddr0, sizeof(vethaddr0), VETHIFACEADDR0, VETHIFACEADDRBASE + index); 137 | 138 | errno = 0; 139 | memset(cmd,0,sizeof(cmd)); 140 | snprintf(cmd, sizeof(cmd), "ndc interface setcfg %s %s %d up multicast broadcast",vethname0 ,vethaddr0 ,VETHMASK); 141 | ret = system(cmd); 142 | ALOGD("%s errno = %s",cmd,strerror(errno)); 143 | 144 | errno = 0; 145 | memset(cmd,0,sizeof(cmd)); 146 | snprintf(cmd, sizeof(cmd), "ndc tether interface add %s",vethname0); 147 | ret = system(cmd); 148 | ALOGD("%s errno = %s",cmd,strerror(errno)); 149 | 150 | errno = 0; 151 | memset(cmd,0,sizeof(cmd)); 152 | snprintf(cmd, sizeof(cmd), "ndc network interface add local %s",vethname0); 153 | ret = system(cmd); 154 | ALOGD("%s errno = %s",cmd,strerror(errno)); 155 | 156 | errno = 0; 157 | memset(cmd,0,sizeof(cmd)); 158 | snprintf(cmd, sizeof(cmd), "ndc network route add local %s %s/%d",vethname0,vethgateaddr,VETHMASK); 159 | ret = system(cmd); 160 | ALOGD("%s errno = %s",cmd,strerror(errno)); 161 | 162 | errno = 0; 163 | memset(cmd,0,sizeof(cmd)); 164 | snprintf(cmd, sizeof(cmd), "ndc ipfwd enable %s",vethname0); 165 | ret = system(cmd); 166 | ALOGD("%s errno = %s",cmd,strerror(errno)); 167 | 168 | errno = 0; 169 | memset(cmd,0,sizeof(cmd)); 170 | snprintf(cmd, sizeof(cmd), "ndc nat enable %s %s 1 %s/%d",vethname0,INTERFACE,vethgateaddr,VETHMASK); 171 | ret = system(cmd); 172 | ALOGD("%s errno = %s",cmd,strerror(errno)); 173 | 174 | errno = 0; 175 | memset(cmd,0,sizeof(cmd)); 176 | snprintf(cmd, sizeof(cmd), "ndc ipfwd add %s %s",vethname0,INTERFACE); 177 | ret = system(cmd); 178 | ALOGD("%s errno = %s",cmd,strerror(errno)); 179 | } 180 | 181 | void stoptether(int index) 182 | { 183 | int ret = 0; 184 | char vethname0[24] = {0}; 185 | 186 | char cmd[256] = {0}; 187 | 188 | snprintf(vethname0, sizeof(vethname0), VETH0, index); 189 | 190 | errno = 0; 191 | memset(cmd,0,sizeof(cmd)); 192 | snprintf(cmd, sizeof(cmd), "ndc tether interface remove %s",vethname0); 193 | ret = system(cmd); 194 | ALOGD("%s errno = %s",cmd,strerror(errno)); 195 | 196 | errno = 0; 197 | memset(cmd,0,sizeof(cmd)); 198 | snprintf(cmd, sizeof(cmd), "ndc network interface remove local %s",vethname0); 199 | ret = system(cmd); 200 | ALOGD("%s errno = %s",cmd,strerror(errno)); 201 | 202 | errno = 0; 203 | memset(cmd,0,sizeof(cmd)); 204 | snprintf(cmd, sizeof(cmd), "ndc ipfwd disable %s",vethname0); 205 | ret = system(cmd); 206 | ALOGD("%s errno = %s",cmd,strerror(errno)); 207 | } 208 | 209 | void delveth(int index) 210 | { 211 | int ret = 0; 212 | char vethname0[24] = {0}; 213 | char vethaddr0[64] = {0}; 214 | char vethgateaddr[64] = {0}; 215 | 216 | char cmd[256] = {0}; 217 | 218 | snprintf(vethname0, sizeof(vethname0), VETH0, index); 219 | snprintf(vethgateaddr, sizeof(vethgateaddr), VETHGATEADDR, VETHIFACEADDRBASE + index); 220 | snprintf(vethaddr0, sizeof(vethaddr0), VETHIFACEADDR0, VETHIFACEADDRBASE + index); 221 | 222 | errno = 0; 223 | memset(cmd,0,sizeof(cmd)); 224 | snprintf(cmd, sizeof(cmd), "iptables -t nat -D POSTROUTING -s %s/%d -o %s -j MASQUERADE",vethgateaddr,VETHMASK,INTERFACE); 225 | ret = system(cmd); 226 | ALOGD("%s errno = %s",cmd,strerror(errno)); 227 | 228 | errno = 0; 229 | memset(cmd,0,sizeof(cmd)); 230 | snprintf(cmd, sizeof(cmd), "iptables -t filter -D FORWARD -i %s -o %s -j ACCEPT",INTERFACE,vethname0); 231 | ret = system(cmd); 232 | ALOGD("%s errno = %s",cmd,strerror(errno)); 233 | 234 | errno = 0; 235 | memset(cmd,0,sizeof(cmd)); 236 | snprintf(cmd, sizeof(cmd), "iptables -t filter -D FORWARD -o %s -i %s -j ACCEPT",INTERFACE,vethname0); 237 | ret = system(cmd); 238 | ALOGD("%s errno = %s",cmd,strerror(errno)); 239 | 240 | errno = 0; 241 | memset(cmd,0,sizeof(cmd)); 242 | snprintf(cmd, sizeof(cmd), "ip link delete %s type veth",vethname0); 243 | ret = system(cmd); 244 | ALOGD("%s errno = %s",cmd,strerror(errno)); 245 | } 246 | -------------------------------------------------------------------------------- /cells/cellnet.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __CELLNET_H 3 | #define __CELLNET_H 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | extern void init_cell_net(); 10 | extern void createveth(int index); 11 | extern void vethtons(int pid,int index); 12 | extern void rnameveth(int index); 13 | extern void starttether(int index); 14 | extern void stoptether(int index); 15 | extern void delveth(int index); 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | 21 | #endif /* __CELLNET_H */ 22 | -------------------------------------------------------------------------------- /cells/cellsocket.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "cellsocket.h" 14 | 15 | #define LOG_TAG "CellSocket" 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #define MAX_MSG_LEN 1024 22 | #define MAX_HANDLE_MSG_INDEX 10 23 | 24 | static int daemon_fd = -1; 25 | static handle_message handle_message_vector[MAX_HANDLE_MSG_INDEX] = {0}; 26 | 27 | void register_cmd_handle(handle_message h,int flag) 28 | { 29 | if(flag > -1 && flag < MAX_HANDLE_MSG_INDEX){ 30 | handle_message_vector[flag] = h; 31 | } 32 | } 33 | 34 | void unregister_cmd_handle(int flag) 35 | { 36 | if(flag > -1 && flag < MAX_HANDLE_MSG_INDEX){ 37 | handle_message_vector[flag] = NULL; 38 | } 39 | } 40 | 41 | static void *handle_client_message(void *opaque) 42 | { 43 | int ret; 44 | int handle_flag; 45 | int cmd_flag; 46 | char* send_buf; 47 | int send_count; 48 | int rec_msg_cmd; 49 | struct client_message *client_msg = (struct client_message *)opaque; 50 | 51 | rec_msg_cmd = *((int*)client_msg->_rec_msg); 52 | handle_flag = (rec_msg_cmd >> 16) & 0xff; 53 | cmd_flag = rec_msg_cmd & 0xff; 54 | 55 | ALOGD("handle_client_message begin handle_flag[%d] cmd_flag[%d]", handle_flag, cmd_flag); 56 | if(handle_flag > -1 && handle_flag < MAX_HANDLE_MSG_INDEX){ 57 | if(handle_message_vector[handle_flag]) 58 | (*handle_message_vector[handle_flag])(client_msg,cmd_flag); 59 | } 60 | ALOGD("handle_client_message end send_msg_len[%d]", client_msg->_send_msg_len); 61 | 62 | /* Send the now prepared reply */ 63 | send_buf = (char*)client_msg->_send_msg; 64 | send_count = client_msg->_send_msg_len; 65 | while (send_count > 0) { 66 | ret = send(client_msg->_socket, send_buf, send_count, 0); 67 | if (ret <= 0) { 68 | ALOGE(" handle_client_message send reply: " 69 | "ERROR(%d) %s", errno, strerror(errno)); 70 | break; 71 | } 72 | send_count -= ret; 73 | send_buf += ret; 74 | } 75 | 76 | 77 | if(client_msg->_send_msg_len) 78 | free(client_msg->_send_msg); 79 | if(client_msg->_rec_msg_len) 80 | free(client_msg->_rec_msg); 81 | close(client_msg->_socket); 82 | free(client_msg); 83 | return (void *)0; /* Unused */ 84 | } 85 | 86 | /* 87 | * Listen for incoming connections and handle them one by one 88 | * 89 | * It's a bit rough, but we really expect all data to come through more or less 90 | * at once. 91 | */ 92 | static void listen_server_daemon(int daemon_fd) 93 | { 94 | int ret; 95 | int cmd_socket; 96 | int rec_msg_cmd; 97 | int rec_msg_len; 98 | void *message, *ptr; 99 | pthread_t handle_thread; 100 | struct client_message *c_message; 101 | int rec_count; 102 | 103 | /* OK, we're ready to accept some incoming connections */ 104 | if (listen(daemon_fd, 5) == -1) { 105 | ALOGE("listen client_data->socket: %s", strerror(errno)); 106 | goto out_err; 107 | } 108 | 109 | /* Main accept loop */ 110 | for (;;) { 111 | 112 | /* Block and wait for one */ 113 | cmd_socket = accept(daemon_fd,NULL, NULL); 114 | if (cmd_socket < 0) { 115 | ALOGE("accept err: %s", strerror(errno)); 116 | goto out_err; 117 | } 118 | 119 | /* Caught a fish - now fetch and validate the protocol fields */ 120 | ret = recv(cmd_socket, (void *)&rec_msg_len, 4, 0); 121 | if (ret != 4) { 122 | ALOGE("recv rec_msg_len err: %s", strerror(errno)); 123 | close(cmd_socket); 124 | continue; 125 | } 126 | 127 | if (rec_msg_len > MAX_MSG_LEN) { 128 | ALOGE("Unexpected rec_msg_len value: %u", rec_msg_len); 129 | close(cmd_socket); 130 | continue; 131 | } 132 | 133 | /* Let's get a buffer for the data */ 134 | message = malloc(rec_msg_len); 135 | if (!message) { 136 | ALOGE("malloc message buffer err: %s", strerror(errno)); 137 | close(cmd_socket); 138 | goto out_err; 139 | } 140 | 141 | /* This may not come all at once, so receive in chunks */ 142 | rec_count = rec_msg_len; 143 | while (rec_count > 0) { 144 | ptr = (char *)message + (rec_msg_len - rec_count); 145 | ret = recv(cmd_socket, ptr, rec_count, 0); 146 | if (ret <= 0) { 147 | ALOGE("recv message err: %s", strerror(errno)); 148 | free(message); 149 | close(cmd_socket); 150 | break; 151 | } 152 | 153 | rec_count -= ret; 154 | } 155 | 156 | /* 157 | * If we received the entire message then go ahead and process 158 | * it in its own thread and let the thread close the socket 159 | * (and free the message memory) when it's done with it. 160 | */ 161 | if (rec_count == 0) { 162 | c_message = (struct client_message *)malloc(sizeof(*c_message)); 163 | if (!c_message) { 164 | ALOGE("malloc client_message: " 165 | "err(%d) %s", errno, strerror(errno)); 166 | free(message); 167 | close(cmd_socket); 168 | goto out_err; 169 | } 170 | 171 | c_message->_socket = cmd_socket; 172 | c_message->_rec_msg_len = rec_msg_len; 173 | c_message->_rec_msg = message; 174 | c_message->_send_msg_len = 0; 175 | c_message->_send_msg = 0; 176 | 177 | /* TODO: keep track of these threads */ 178 | ret = pthread_create(&handle_thread, NULL, 179 | handle_client_message, (void *)c_message); 180 | if (ret) { 181 | ALOGE("pthread_create handle_thread: " 182 | "ERROR(%d) %s", errno, strerror(errno)); 183 | free(message); 184 | free(c_message); 185 | close(cmd_socket); 186 | goto out_err; 187 | } 188 | } else { 189 | ALOGE("Could not receive entire message " 190 | "(missing %u bytes)", rec_count); 191 | free(message); 192 | close(cmd_socket); 193 | } 194 | } 195 | 196 | out_err: 197 | return ; 198 | } 199 | 200 | static int create_socket(const char *path) 201 | { 202 | struct sockaddr_un local; 203 | size_t len; 204 | int sock; 205 | 206 | if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { 207 | return -1; 208 | } 209 | 210 | fcntl(sock, F_SETFD, FD_CLOEXEC); 211 | 212 | local.sun_family = AF_UNIX; 213 | strncpy(local.sun_path, path, sizeof(local.sun_path)); 214 | unlink(local.sun_path); 215 | len = strlen(local.sun_path) + sizeof(local.sun_family); 216 | if (bind(sock, (struct sockaddr *)&local, len) == -1) { 217 | return -1; 218 | } 219 | 220 | return sock; 221 | } 222 | 223 | /* 224 | * Creates the socket and registers it with the internal bookkeeping. Each call 225 | * will create a new thread that accepts new connections and handles incoming 226 | * data. Remember to close destroy the wifi host before exiting the program. 227 | */ 228 | void create_server_daemon(int bhost) 229 | { 230 | int ret; 231 | int fd; 232 | pthread_t daemon_thread; 233 | char socket_path[PATH_MAX]={0}; 234 | 235 | if(bhost){ 236 | snprintf(socket_path, PATH_MAX, "%s%s","/data/cells/cell1",VM_SOCKET_PATH_C); 237 | }else{ 238 | snprintf(socket_path, PATH_MAX, "%s",VM_SOCKET_PATH_H); 239 | } 240 | 241 | ALOGD("creating daemon socket at: %s", socket_path); 242 | 243 | fd = create_socket(socket_path); 244 | if (fd == -1){ 245 | ALOGD("creating daemon socket at: %s failed.", socket_path); 246 | return; 247 | } 248 | 249 | /* Start listening for connections in a main thread */ 250 | listen_server_daemon(fd); 251 | 252 | close(fd); 253 | } 254 | 255 | /* 256 | * Open connection with wifi_proxy and return file descriptor. 257 | */ 258 | static int open_conn(const char* server_socket) 259 | { 260 | int fd; 261 | struct sockaddr_un addr; 262 | size_t addr_len; 263 | 264 | /* Establish connection */ 265 | fd = socket(AF_UNIX, SOCK_STREAM, 0); 266 | if (fd == -1) { 267 | ALOGE("Failed to connect to celld"); 268 | return -1; 269 | } 270 | 271 | memset(&addr, 0, sizeof(addr)); 272 | addr.sun_family = AF_UNIX; 273 | strcpy(&addr.sun_path[0], server_socket); 274 | addr_len = strlen(server_socket) + 1 + offsetof(struct sockaddr_un, sun_path); 275 | if (connect(fd, (struct sockaddr *) &addr, addr_len) != 0) { 276 | if (errno == ENOENT) 277 | ALOGE("server does not appear to be running"); 278 | else 279 | ALOGE("Failed to connect to server"); 280 | return -1; 281 | } 282 | return fd; 283 | } 284 | 285 | static int send_buf(int fd, void *data, size_t len) 286 | { 287 | int ret, remain = len; 288 | char *buf = (char*)data; 289 | while (remain > 0) { 290 | if ((ret = write(fd, buf, remain)) <= 0) 291 | return -1; 292 | buf += ret; 293 | remain -= ret; 294 | } 295 | return 0; 296 | } 297 | 298 | static int recv_reply(int fd, size_t *len, char *msg) 299 | { 300 | int ret = 0; 301 | int ret_val; 302 | int reply = 0; 303 | int left = 0; 304 | char *ptr = NULL; 305 | 306 | ret = recv(fd, (void *)&reply, sizeof(int), 0); 307 | if (ret != sizeof(int)) { 308 | ALOGE("get reply :%d\n",ret); 309 | return 0; 310 | } 311 | 312 | *len = reply; 313 | 314 | msg = (char*)malloc(reply); 315 | if (NULL == msg) { 316 | ALOGE("malloc reply buf fail!\n"); 317 | return -1; 318 | } 319 | memset(msg, 0, reply); 320 | 321 | /* This may not come all at once, so receive in chunks */ 322 | left = reply; 323 | while (left > 0) { 324 | ptr = msg + (reply - left); 325 | ret = recv(fd, (void *)ptr, left, 0); 326 | if (ret <= 0) { 327 | ALOGE("get reply msg fail!\n"); 328 | free(msg); 329 | return -1; 330 | } 331 | left -= ret; 332 | } 333 | ALOGI("get reply msg %s, retval %d\n", msg, reply); 334 | 335 | return ret_val; 336 | } 337 | 338 | int send_msg(int bhost,int send_len, const char *send_msg, size_t *reply_len, char *reply_msg) 339 | { 340 | int fd = 0; 341 | int ret = 0; 342 | int pkt_len = sizeof(int) + send_len; /* send_len + send_msg */ 343 | char *pbuf = NULL; 344 | char socket_path[PATH_MAX]={0}; 345 | 346 | if(bhost){ 347 | snprintf(socket_path, PATH_MAX, "%s%s","/data/cells/cell1",VM_SOCKET_PATH_H); 348 | }else{ 349 | snprintf(socket_path, PATH_MAX, "%s",VM_SOCKET_PATH_C); 350 | } 351 | 352 | fd = open_conn(socket_path); 353 | if (fd < 0) { 354 | ALOGE("open_con fail! socket_path=%s \n",socket_path); 355 | return -1; 356 | } 357 | 358 | pbuf = (char*)malloc(pkt_len); 359 | if (NULL == pbuf) { 360 | ALOGE("malloc fail!\n"); 361 | ret = -1; 362 | goto END; 363 | } 364 | memset(pbuf, 0, pkt_len); 365 | 366 | memcpy(pbuf, &send_len, sizeof(int)); 367 | memcpy(pbuf+sizeof(int), send_msg, send_len); 368 | 369 | if (send_buf(fd, (void *)pbuf, pkt_len)) { 370 | ALOGE("sending msg num fail!\n"); 371 | ret = -1; 372 | goto END; 373 | } 374 | 375 | recv_reply(fd, reply_len, reply_msg); 376 | 377 | END: 378 | close(fd); 379 | if (NULL != pbuf) { 380 | free(pbuf); 381 | pbuf = NULL; 382 | } 383 | return ret; 384 | } 385 | 386 | 387 | 388 | -------------------------------------------------------------------------------- /cells/cellsocket.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | use for two system communication 4 | */ 5 | #ifndef CELL_SOCKET_H 6 | #define CELL_SOCKET_H 7 | 8 | #define VM_SOCKET_PATH_C "/dev/.c_bridge" 9 | #define VM_SOCKET_PATH_H "/dev/.h_bridge" 10 | 11 | #define HOST_BASE_CMD 0 12 | #define VM_BASE_CMD 0 13 | #define SYSTEM_SWITCH_ENTER 1 14 | #define SYSTEM_SWITCH_EXIT 2 15 | #define SYSTEM_STOP_SELF 3 16 | #define SYSTEM_VM_INIT_OK 4 17 | 18 | struct client_message { 19 | uint32_t _socket; 20 | 21 | uint32_t _rec_msg_len; 22 | void *_rec_msg; 23 | 24 | uint32_t _send_msg_len; 25 | void *_send_msg; 26 | }; 27 | 28 | typedef void (*handle_message)(struct client_message * ,const int ); 29 | 30 | void register_cmd_handle(handle_message h,int flag); 31 | 32 | void unregister_cmd_handle(int flag); 33 | 34 | void create_server_daemon(int bhost); 35 | 36 | int send_msg(int bhost,int send_len, const char *send_msg, size_t *reply_len, char *reply_msg); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /cells/ext/glibc_openpty.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc. 2 | This file is part of the GNU C Library. 3 | Contributed by Zack Weinberg , 1998. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, write to the Free 17 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 18 | 02111-1307 USA. */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "glibc_pty.h" 30 | 31 | 32 | /* Return the result of ptsname_r in the buffer pointed to by PTS, 33 | which should be of length BUF_LEN. If it is too long to fit in 34 | this buffer, a sufficiently long buffer is allocated using malloc, 35 | and returned in PTS. 0 is returned upon success, -1 otherwise. */ 36 | static int 37 | pts_name (int fd, char **pts, size_t buf_len) 38 | { 39 | int rv; 40 | char *buf = *pts; 41 | 42 | for (;;) 43 | { 44 | char *new_buf; 45 | 46 | if (buf_len) 47 | { 48 | rv = ptsname_r (fd, buf, buf_len); 49 | 50 | if (rv != 0 || memchr (buf, '\0', buf_len)) 51 | /* We either got an error, or we succeeded and the 52 | returned name fit in the buffer. */ 53 | break; 54 | 55 | /* Try again with a longer buffer. */ 56 | buf_len += buf_len; /* Double it */ 57 | } 58 | else 59 | /* No initial buffer; start out by mallocing one. */ 60 | buf_len = 128; /* First time guess. */ 61 | 62 | if (buf != *pts) 63 | /* We've already malloced another buffer at least once. */ 64 | new_buf = realloc (buf, buf_len); 65 | else 66 | new_buf = malloc (buf_len); 67 | if (! new_buf) 68 | { 69 | rv = -1; 70 | //__set_errno (ENOMEM); 71 | errno = -ENOMEM; 72 | break; 73 | } 74 | buf = new_buf; 75 | } 76 | 77 | if (rv == 0) 78 | *pts = buf; /* Return buffer to the user. */ 79 | else if (buf != *pts) 80 | free (buf); /* Free what we malloced when returning an error. */ 81 | 82 | return rv; 83 | } 84 | 85 | /* Create pseudo tty master slave pair and set terminal attributes 86 | according to TERMP and WINP. Return handles for both ends in 87 | AMASTER and ASLAVE, and return the name of the slave end in NAME. */ 88 | int 89 | openpty (int *amaster, int *aslave, char *name, 90 | const struct termios *termp, const struct winsize *winp) 91 | { 92 | #ifdef PATH_MAX 93 | char _buf[PATH_MAX]; 94 | #else 95 | char _buf[512]; 96 | #endif 97 | char *buf = _buf; 98 | int master, slave; 99 | 100 | master = getpt (); 101 | if (master == -1) 102 | return -1; 103 | 104 | if (grantpt (master)) 105 | goto fail; 106 | 107 | if (unlockpt (master)) 108 | goto fail; 109 | 110 | if (pts_name (master, &buf, sizeof (_buf))) 111 | goto fail; 112 | 113 | slave = open (buf, O_RDWR | O_NOCTTY); 114 | if (slave == -1) 115 | { 116 | if (buf != _buf) 117 | free (buf); 118 | 119 | goto fail; 120 | } 121 | 122 | /* XXX Should we ignore errors here? */ 123 | if(termp) 124 | tcsetattr (slave, TCSAFLUSH, termp); 125 | if (winp) 126 | ioctl (slave, TIOCSWINSZ, winp); 127 | 128 | *amaster = master; 129 | *aslave = slave; 130 | if (name != NULL) 131 | strcpy (name, buf); 132 | 133 | if (buf != _buf) 134 | free (buf); 135 | return 0; 136 | 137 | fail: 138 | close (master); 139 | return -1; 140 | } 141 | -------------------------------------------------------------------------------- /cells/ext/glibc_pty.h: -------------------------------------------------------------------------------- 1 | /* Functions for pseudo TTY handling. 2 | Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. 3 | This file is part of the GNU C Library. 4 | 5 | The GNU C Library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | The GNU C Library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with the GNU C Library; if not, write to the Free 17 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 18 | 02111-1307 USA. */ 19 | 20 | #ifndef _PTY_H 21 | #define _PTY_H 1 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | 29 | __BEGIN_DECLS 30 | 31 | extern int __set_errno(int n); 32 | 33 | /* Create pseudo tty master slave pair with NAME and set terminal 34 | attributes according to TERMP and WINP and return handles for both 35 | ends in AMASTER and ASLAVE. */ 36 | extern int openpty (int *__amaster, int *__aslave, char *__name, 37 | const struct termios *__termp, 38 | const struct winsize *__winp); 39 | 40 | /* Create child process and establish the slave pseudo terminal as the 41 | child's controlling terminal. */ 42 | extern int forkpty (int *__amaster, char *__name, 43 | const struct termios *__termp, 44 | const struct winsize *__winp); 45 | 46 | __END_DECLS 47 | 48 | #endif /* pty.h */ 49 | -------------------------------------------------------------------------------- /cells/network.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #undef _GNU_SOURCe 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "nl.h" 29 | #include "network.h" 30 | #define LOG_TAG "Cells/network" 31 | #include 32 | 33 | #ifndef VETH_INFO_PEER 34 | # define VETH_INFO_PEER 1 35 | #endif 36 | 37 | int wait_for_pid(pid_t pid) 38 | { 39 | int status, ret; 40 | 41 | again: 42 | ret = waitpid(pid, &status, 0); 43 | if (ret == -1) { 44 | if (errno == EINTR) 45 | goto again; 46 | return -1; 47 | } 48 | if (ret != pid) 49 | goto again; 50 | if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 51 | return -1; 52 | return 0; 53 | } 54 | 55 | int veth_peer_create(const char *name1, const char *name2) 56 | { 57 | struct nl_handler nlh; 58 | struct nlmsg *nlmsg = NULL, *answer = NULL; 59 | struct ifinfomsg *ifi; 60 | struct rtattr *nest1, *nest2, *nest3; 61 | int len, err; 62 | 63 | err = netlink_open(&nlh, NETLINK_ROUTE); 64 | if (err) 65 | return err; 66 | 67 | err = -EINVAL; 68 | len = strlen(name1); 69 | if (len == 1 || len >= IFNAMSIZ) 70 | goto out; 71 | 72 | len = strlen(name2); 73 | if (len == 1 || len >= IFNAMSIZ) 74 | goto out; 75 | 76 | err = -ENOMEM; 77 | nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); 78 | if (!nlmsg) 79 | goto out; 80 | 81 | answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE); 82 | if (!answer) 83 | goto out; 84 | 85 | nlmsg->nlmsghdr->nlmsg_flags = 86 | NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK; 87 | nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK; 88 | 89 | ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg)); 90 | ifi->ifi_family = AF_UNSPEC; 91 | 92 | err = -EINVAL; 93 | nest1 = nla_begin_nested(nlmsg, IFLA_LINKINFO); 94 | if (!nest1) 95 | goto out; 96 | 97 | if (nla_put_string(nlmsg, IFLA_INFO_KIND, "veth")) 98 | goto out; 99 | 100 | nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA); 101 | if (!nest2) 102 | goto out; 103 | 104 | nest3 = nla_begin_nested(nlmsg, VETH_INFO_PEER); 105 | if (!nest3) 106 | goto out; 107 | 108 | ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg)); 109 | if (!ifi) 110 | goto out; 111 | 112 | if (nla_put_string(nlmsg, IFLA_IFNAME, name2)) 113 | goto out; 114 | 115 | nla_end_nested(nlmsg, nest3); 116 | 117 | nla_end_nested(nlmsg, nest2); 118 | 119 | nla_end_nested(nlmsg, nest1); 120 | 121 | if (nla_put_string(nlmsg, IFLA_IFNAME, name1)) 122 | goto out; 123 | 124 | err = netlink_transaction(&nlh, nlmsg, answer); 125 | out: 126 | netlink_close(&nlh); 127 | nlmsg_free(answer); 128 | nlmsg_free(nlmsg); 129 | return err; 130 | } 131 | 132 | 133 | int switch_to_ns(pid_t pid, const char *ns) { 134 | int fd, ret; 135 | char nspath[MAXPATHLEN]; 136 | 137 | /* Switch to new ns */ 138 | ret = snprintf(nspath, MAXPATHLEN, "/proc/%d/ns/%s", pid, ns); 139 | if (ret < 0 || ret >= MAXPATHLEN) 140 | return -1; 141 | 142 | fd = open(nspath, O_RDONLY); 143 | if (fd < 0) { 144 | ALOGE("failed to open %s", nspath); 145 | return -1; 146 | } 147 | 148 | ret = setns(fd, 0); 149 | if (ret) { 150 | ALOGE("failed to set process %d to %s of %d.", pid, ns, fd); 151 | close(fd); 152 | return -1; 153 | } 154 | close(fd); 155 | return 0; 156 | } 157 | 158 | int netdev_rename_by_index(int ifindex, const char *newname) 159 | { 160 | struct nl_handler nlh; 161 | struct nlmsg *nlmsg = NULL, *answer = NULL; 162 | struct ifinfomsg *ifi; 163 | int len, err; 164 | 165 | err = netlink_open(&nlh, NETLINK_ROUTE); 166 | if (err) 167 | return err; 168 | 169 | len = strlen(newname); 170 | if (len == 1 || len >= IFNAMSIZ) 171 | goto out; 172 | 173 | err = -ENOMEM; 174 | nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE); 175 | if (!nlmsg) 176 | goto out; 177 | 178 | answer = nlmsg_alloc_reserve(NLMSG_GOOD_SIZE); 179 | if (!answer) 180 | goto out; 181 | 182 | nlmsg->nlmsghdr->nlmsg_flags = NLM_F_ACK|NLM_F_REQUEST; 183 | nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK; 184 | 185 | ifi = nlmsg_reserve(nlmsg, sizeof(struct ifinfomsg)); 186 | ifi->ifi_family = AF_UNSPEC; 187 | ifi->ifi_index = ifindex; 188 | 189 | if (nla_put_string(nlmsg, IFLA_IFNAME, newname)) 190 | goto out; 191 | 192 | err = netlink_transaction(&nlh, nlmsg, answer); 193 | out: 194 | netlink_close(&nlh); 195 | nlmsg_free(answer); 196 | nlmsg_free(nlmsg); 197 | return err; 198 | } 199 | 200 | 201 | int netdev_rename_by_name(const char *oldname, const char *newname) 202 | { 203 | int len, index; 204 | 205 | len = strlen(oldname); 206 | if (len == 1 || len >= IFNAMSIZ) 207 | return -EINVAL; 208 | 209 | index = if_nametoindex(oldname); 210 | if (!index) 211 | return -EINVAL; 212 | 213 | return netdev_rename_by_index(index, newname); 214 | } 215 | 216 | 217 | int 218 | netdev_rename_by_name_in_netns(pid_t pid, const char *old, const char *new) 219 | { 220 | pid_t fpid = fork(); 221 | 222 | if (fpid < 0) 223 | return -1; 224 | if (fpid != 0) 225 | return wait_for_pid(fpid); 226 | if (0 != switch_to_ns(pid, "net")) 227 | return -1; 228 | exit(netdev_rename_by_name(old, new)); 229 | } 230 | 231 | int 232 | netdev_move_to_netns(const char *ifname, pid_t pid, const char* newname) 233 | { 234 | int err = -1; 235 | pid_t fpid; 236 | char *cmd; 237 | #if 0 238 | fpid = fork(); 239 | if (fpid < 0) 240 | goto out1; 241 | if (fpid == 0) { 242 | char pidstr[30]; 243 | sprintf(pidstr, "%d", pid); 244 | if (execlp("ip", "link", "set", ifname, "netns", pidstr, NULL)) { 245 | ALOGE("set netns fail! errno=%d\n", errno); 246 | exit(1); 247 | } 248 | exit(0); // notreached 249 | } 250 | if (wait_for_pid(fpid)) { 251 | ALOGE("set netns fail! errno=%d\n", errno); 252 | goto out1; 253 | } 254 | #else 255 | int ret; 256 | char system_cmd[256]; 257 | snprintf(system_cmd, sizeof(system_cmd), "ip link set %s netns %d", ifname, pid); 258 | ret = system(system_cmd); 259 | ALOGE("set netns fail! ret=%d errno=%d\n", ret, errno); 260 | #endif 261 | err = 0; 262 | if (newname) 263 | err = netdev_rename_by_name_in_netns(pid, ifname, newname); 264 | 265 | out1: 266 | return err; 267 | } 268 | 269 | 270 | -------------------------------------------------------------------------------- /cells/network.h: -------------------------------------------------------------------------------- 1 | #ifndef _NETWORK_H_ 2 | #define _NETWORK_H_ 3 | 4 | int veth_peer_create(const char *name1, const char *name2); 5 | int switch_to_ns(pid_t pid, const char *ns); 6 | int netdev_rename_by_index(int ifindex, const char *newname); 7 | int netdev_rename_by_name(const char *oldname, const char *newname); 8 | int netdev_rename_by_name_in_netns(pid_t pid, const char *old, const char *new); 9 | int netdev_move_to_netns(const char *ifname, pid_t pid, const char* newname); 10 | 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /cells/nl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * lxc: linux Container library 3 | * 4 | * (C) Copyright IBM Corp. 2007, 2008 5 | * 6 | * Authors: 7 | * Daniel Lezcano 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2.1 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22 | */ 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "nl.h" 34 | 35 | #define NLMSG_TAIL(nmsg) \ 36 | ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) 37 | 38 | extern size_t nlmsg_len(const struct nlmsg *nlmsg) 39 | { 40 | return nlmsg->nlmsghdr->nlmsg_len - NLMSG_HDRLEN; 41 | } 42 | 43 | extern void *nlmsg_data(struct nlmsg *nlmsg) 44 | { 45 | char *data = ((char *)nlmsg) + NLMSG_HDRLEN; 46 | if (!nlmsg_len(nlmsg)) 47 | return NULL; 48 | return data; 49 | } 50 | 51 | static int nla_put(struct nlmsg *nlmsg, int attr, 52 | const void *data, size_t len) 53 | { 54 | struct rtattr *rta; 55 | size_t rtalen = RTA_LENGTH(len); 56 | size_t tlen = NLMSG_ALIGN(nlmsg->nlmsghdr->nlmsg_len) + RTA_ALIGN(rtalen); 57 | 58 | if (tlen > nlmsg->cap) 59 | return -ENOMEM; 60 | 61 | rta = NLMSG_TAIL(nlmsg->nlmsghdr); 62 | rta->rta_type = attr; 63 | rta->rta_len = rtalen; 64 | memcpy(RTA_DATA(rta), data, len); 65 | nlmsg->nlmsghdr->nlmsg_len = tlen; 66 | return 0; 67 | } 68 | 69 | extern int nla_put_buffer(struct nlmsg *nlmsg, int attr, 70 | const void *data, size_t size) 71 | { 72 | return nla_put(nlmsg, attr, data, size); 73 | } 74 | 75 | extern int nla_put_string(struct nlmsg *nlmsg, int attr, const char *string) 76 | { 77 | return nla_put(nlmsg, attr, string, strlen(string) + 1); 78 | } 79 | 80 | extern int nla_put_u32(struct nlmsg *nlmsg, int attr, int value) 81 | { 82 | return nla_put(nlmsg, attr, &value, sizeof(value)); 83 | } 84 | 85 | extern int nla_put_u16(struct nlmsg *nlmsg, int attr, unsigned short value) 86 | { 87 | return nla_put(nlmsg, attr, &value, 2); 88 | } 89 | 90 | extern int nla_put_attr(struct nlmsg *nlmsg, int attr) 91 | { 92 | return nla_put(nlmsg, attr, NULL, 0); 93 | } 94 | 95 | struct rtattr *nla_begin_nested(struct nlmsg *nlmsg, int attr) 96 | { 97 | struct rtattr *rtattr = NLMSG_TAIL(nlmsg->nlmsghdr); 98 | 99 | if (nla_put_attr(nlmsg, attr)) 100 | return NULL; 101 | 102 | return rtattr; 103 | } 104 | 105 | void nla_end_nested(struct nlmsg *nlmsg, struct rtattr *attr) 106 | { 107 | attr->rta_len = (void *)NLMSG_TAIL(nlmsg->nlmsghdr) - (void *)attr; 108 | } 109 | 110 | extern struct nlmsg *nlmsg_alloc(size_t size) 111 | { 112 | struct nlmsg *nlmsg; 113 | size_t len = NLMSG_HDRLEN + NLMSG_ALIGN(size); 114 | 115 | nlmsg = (struct nlmsg *)malloc(sizeof(struct nlmsg)); 116 | if (!nlmsg) 117 | return NULL; 118 | 119 | nlmsg->nlmsghdr = (struct nlmsghdr *)malloc(len); 120 | if (!nlmsg->nlmsghdr) 121 | goto errout; 122 | 123 | memset(nlmsg->nlmsghdr, 0, len); 124 | nlmsg->cap = len; 125 | nlmsg->nlmsghdr->nlmsg_len = NLMSG_HDRLEN; 126 | 127 | return nlmsg; 128 | errout: 129 | free(nlmsg); 130 | return NULL; 131 | } 132 | 133 | extern void *nlmsg_reserve(struct nlmsg *nlmsg, size_t len) 134 | { 135 | void *buf; 136 | size_t nlmsg_len = nlmsg->nlmsghdr->nlmsg_len; 137 | size_t tlen = NLMSG_ALIGN(len); 138 | 139 | if (nlmsg_len + tlen > nlmsg->cap) 140 | return NULL; 141 | 142 | buf = ((char *)(nlmsg->nlmsghdr)) + nlmsg_len; 143 | nlmsg->nlmsghdr->nlmsg_len += tlen; 144 | 145 | if (tlen > len) 146 | memset(buf + len, 0, tlen - len); 147 | 148 | return buf; 149 | } 150 | 151 | extern struct nlmsg *nlmsg_alloc_reserve(size_t size) 152 | { 153 | struct nlmsg *nlmsg; 154 | 155 | nlmsg = nlmsg_alloc(size); 156 | if (!nlmsg) 157 | return NULL; 158 | 159 | // just set message length to cap directly 160 | nlmsg->nlmsghdr->nlmsg_len = nlmsg->cap; 161 | return nlmsg; 162 | } 163 | 164 | extern void nlmsg_free(struct nlmsg *nlmsg) 165 | { 166 | if (!nlmsg) 167 | return; 168 | 169 | free(nlmsg->nlmsghdr); 170 | free(nlmsg); 171 | } 172 | 173 | extern int netlink_rcv(struct nl_handler *handler, struct nlmsg *answer) 174 | { 175 | int ret; 176 | struct sockaddr_nl nladdr; 177 | struct iovec iov = { 178 | .iov_base = answer->nlmsghdr, 179 | .iov_len = answer->nlmsghdr->nlmsg_len, 180 | }; 181 | 182 | struct msghdr msg = { 183 | .msg_name = &nladdr, 184 | .msg_namelen = sizeof(nladdr), 185 | .msg_iov = &iov, 186 | .msg_iovlen = 1, 187 | }; 188 | 189 | memset(&nladdr, 0, sizeof(nladdr)); 190 | nladdr.nl_family = AF_NETLINK; 191 | nladdr.nl_pid = 0; 192 | nladdr.nl_groups = 0; 193 | 194 | again: 195 | ret = recvmsg(handler->fd, &msg, 0); 196 | if (ret < 0) { 197 | if (errno == EINTR) 198 | goto again; 199 | return -errno; 200 | } 201 | 202 | if (!ret) 203 | return 0; 204 | 205 | if (msg.msg_flags & MSG_TRUNC && 206 | ret == answer->nlmsghdr->nlmsg_len) 207 | return -EMSGSIZE; 208 | 209 | return ret; 210 | } 211 | 212 | extern int netlink_send(struct nl_handler *handler, struct nlmsg *nlmsg) 213 | { 214 | struct sockaddr_nl nladdr; 215 | struct iovec iov = { 216 | .iov_base = nlmsg->nlmsghdr, 217 | .iov_len = nlmsg->nlmsghdr->nlmsg_len, 218 | }; 219 | struct msghdr msg = { 220 | .msg_name = &nladdr, 221 | .msg_namelen = sizeof(nladdr), 222 | .msg_iov = &iov, 223 | .msg_iovlen = 1, 224 | }; 225 | int ret; 226 | 227 | memset(&nladdr, 0, sizeof(nladdr)); 228 | nladdr.nl_family = AF_NETLINK; 229 | nladdr.nl_pid = 0; 230 | nladdr.nl_groups = 0; 231 | 232 | ret = sendmsg(handler->fd, &msg, 0); 233 | if (ret < 0) 234 | return -errno; 235 | 236 | return ret; 237 | } 238 | 239 | #ifndef NLMSG_ERROR 240 | #define NLMSG_ERROR 0x2 241 | #endif 242 | extern int netlink_transaction(struct nl_handler *handler, 243 | struct nlmsg *request, struct nlmsg *answer) 244 | { 245 | int ret; 246 | 247 | ret = netlink_send(handler, request); 248 | if (ret < 0) 249 | return ret; 250 | 251 | ret = netlink_rcv(handler, answer); 252 | if (ret < 0) 253 | return ret; 254 | 255 | if (answer->nlmsghdr->nlmsg_type == NLMSG_ERROR) { 256 | struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(answer->nlmsghdr); 257 | return err->error; 258 | } 259 | 260 | return 0; 261 | } 262 | 263 | extern int netlink_open(struct nl_handler *handler, int protocol) 264 | { 265 | socklen_t socklen; 266 | int sndbuf = 32768; 267 | int rcvbuf = 32768; 268 | 269 | memset(handler, 0, sizeof(*handler)); 270 | 271 | handler->fd = socket(AF_NETLINK, SOCK_RAW, protocol); 272 | if (handler->fd < 0) 273 | return -errno; 274 | 275 | if (setsockopt(handler->fd, SOL_SOCKET, SO_SNDBUF, 276 | &sndbuf, sizeof(sndbuf)) < 0) 277 | return -errno; 278 | 279 | if (setsockopt(handler->fd, SOL_SOCKET, SO_RCVBUF, 280 | &rcvbuf,sizeof(rcvbuf)) < 0) 281 | return -errno; 282 | 283 | memset(&handler->local, 0, sizeof(handler->local)); 284 | handler->local.nl_family = AF_NETLINK; 285 | handler->local.nl_groups = 0; 286 | 287 | if (bind(handler->fd, (struct sockaddr*)&handler->local, 288 | sizeof(handler->local)) < 0) 289 | return -errno; 290 | 291 | socklen = sizeof(handler->local); 292 | if (getsockname(handler->fd, (struct sockaddr*)&handler->local, 293 | &socklen) < 0) 294 | return -errno; 295 | 296 | if (socklen != sizeof(handler->local)) 297 | return -EINVAL; 298 | 299 | if (handler->local.nl_family != AF_NETLINK) 300 | return -EINVAL; 301 | 302 | handler->seq = time(NULL); 303 | 304 | return 0; 305 | } 306 | 307 | extern int netlink_close(struct nl_handler *handler) 308 | { 309 | close(handler->fd); 310 | handler->fd = -1; 311 | return 0; 312 | } 313 | 314 | -------------------------------------------------------------------------------- /cells/nl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * lxc: linux Container library 3 | * 4 | * (C) Copyright IBM Corp. 2007, 2008 5 | * 6 | * Authors: 7 | * Daniel Lezcano 8 | * 9 | * This library is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU Lesser General Public 11 | * License as published by the Free Software Foundation; either 12 | * version 2.1 of the License, or (at your option) any later version. 13 | * 14 | * This library is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 | * Lesser General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Lesser General Public 20 | * License along with this library; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22 | */ 23 | #ifndef __LXC_NL_H 24 | #define __LXC_NL_H 25 | 26 | /* 27 | * Use this as a good size to allocate generic netlink messages 28 | */ 29 | #ifndef PAGE_SIZE 30 | #define PAGE_SIZE 4096 31 | #endif 32 | #define NLMSG_GOOD_SIZE (2*PAGE_SIZE) 33 | #define NLMSG_TAIL(nmsg) \ 34 | ((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) 35 | #define NLA_DATA(na) ((void *)((char*)(na) + NLA_HDRLEN)) 36 | #define NLA_NEXT_ATTR(attr) ((void *)((char *)attr) + NLA_ALIGN(attr->nla_len)) 37 | 38 | /* 39 | * struct nl_handler : the handler for netlink sockets, this structure 40 | * is used all along the netlink socket life cycle to specify the 41 | * netlink socket to be used. 42 | * 43 | * @fd: the file descriptor of the netlink socket 44 | * @seq: the sequence number of the netlink messages 45 | * @local: the bind address 46 | * @peer: the peer address 47 | */ 48 | struct nl_handler { 49 | int fd; 50 | int seq; 51 | struct sockaddr_nl local; 52 | struct sockaddr_nl peer; 53 | }; 54 | 55 | /* 56 | * struct nlmsg : the netlink message structure. This message is to be used to 57 | * be allocated with netlink_alloc. 58 | * 59 | * @nlmsghdr: a pointer to a netlink message header 60 | * @cap: capacity of the netlink message, this is the initially allocated size 61 | * and later operations (e.g. reserve and put) can not exceed this limit. 62 | */ 63 | struct nlmsg { 64 | struct nlmsghdr *nlmsghdr; 65 | ssize_t cap; 66 | }; 67 | 68 | /* 69 | * netlink_open : open a netlink socket, the function will 70 | * fill the handler with the right value 71 | * 72 | * @handler: a netlink handler to be used all along the netlink 73 | * socket life cycle 74 | * @protocol: specify the protocol to be used when opening the 75 | * netlink socket 76 | * 77 | * Return 0 on success, < 0 otherwise 78 | */ 79 | int netlink_open(struct nl_handler *handler, int protocol); 80 | 81 | /* 82 | * netlink_close : close a netlink socket, after this call, 83 | * the handler is no longer valid 84 | * 85 | * @handler: a handler to the netlink socket 86 | * 87 | * Returns 0 on success, < 0 otherwise 88 | */ 89 | int netlink_close(struct nl_handler *handler); 90 | 91 | /* 92 | * netlink_rcv : receive a netlink message from the kernel. 93 | * It is up to the caller to manage the allocation of the 94 | * netlink message 95 | * 96 | * @handler: a handler to the netlink socket 97 | * @nlmsg: a netlink message 98 | * 99 | * Returns 0 on success, < 0 otherwise 100 | */ 101 | int netlink_rcv(struct nl_handler *handler, struct nlmsg *nlmsg); 102 | 103 | /* 104 | * netlink_send: send a netlink message to the kernel. It is up 105 | * to the caller to manage the allocate of the netlink message 106 | * 107 | * @handler: a handler to the netlink socket 108 | * @nlmsg: a netlink message 109 | * 110 | * Returns 0 on success, < 0 otherwise 111 | */ 112 | int netlink_send(struct nl_handler *handler, struct nlmsg *nlmsg); 113 | 114 | /* 115 | * netlink_transaction: send a request to the kernel and read the response. 116 | * This is useful for transactional protocol. It is up to the caller 117 | * to manage the allocation of the netlink message. 118 | * 119 | * @handler: a handler to a opened netlink socket 120 | * @request: a netlink message pointer containing the request 121 | * @answer: a netlink message pointer to receive the result 122 | * 123 | * Returns 0 on success, < 0 otherwise 124 | */ 125 | int netlink_transaction(struct nl_handler *handler, 126 | struct nlmsg *request, struct nlmsg *anwser); 127 | 128 | /* 129 | * nla_put_string: copy a null terminated string to a netlink message 130 | * attribute 131 | * 132 | * @nlmsg: the netlink message to be filled 133 | * @attr: the attribute name of the string 134 | * @string: a null terminated string to be copied to the netlink message 135 | * 136 | * Returns 0 on success, < 0 otherwise 137 | */ 138 | int nla_put_string(struct nlmsg *nlmsg, int attr, const char *string); 139 | 140 | /* 141 | * nla_put_buffer: copy a buffer with a specified size to a netlink 142 | * message attribute 143 | * 144 | * @nlmsg: the netlink message to be filled 145 | * @attr: the attribute name of the string 146 | * @data: a pointer to a buffer 147 | * @size: the size of the buffer 148 | * 149 | * Returns 0 on success, < 0 otherwise 150 | */ 151 | int nla_put_buffer(struct nlmsg *nlmsg, int attr, 152 | const void *data, size_t size); 153 | 154 | /* 155 | * nla_put_u32: copy an integer to a netlink message attribute 156 | * 157 | * @nlmsg: the netlink message to be filled 158 | * @attr: the attribute name of the integer 159 | * @string: an integer to be copied to the netlink message 160 | * 161 | * Returns 0 on success, < 0 otherwise 162 | */ 163 | int nla_put_u32(struct nlmsg *nlmsg, int attr, int value); 164 | 165 | /* 166 | * nla_put_u16: copy an integer to a netlink message attribute 167 | * 168 | * @nlmsg: the netlink message to be filled 169 | * @attr: the attribute name of the unsigned 16-bit value 170 | * @value: 16-bit attribute data value to be copied to the netlink message 171 | * 172 | * Returns 0 on success, < 0 otherwise 173 | */ 174 | int nla_put_u16(struct nlmsg *nlmsg, int attr, unsigned short value); 175 | 176 | /* 177 | * nla_put_attr: add an attribute name to a netlink 178 | * 179 | * @nlmsg: the netlink message to be filled 180 | * @attr: the attribute name of the integer 181 | * 182 | * Returns 0 on success, < 0 otherwise 183 | */ 184 | int nla_put_attr(struct nlmsg *nlmsg, int attr); 185 | 186 | /* 187 | * nla_begin_nested: begin the nesting attribute 188 | * 189 | * @nlmsg: the netlink message to be filled 190 | * @attr: the netsted attribute name 191 | * 192 | * Returns current nested pointer to be reused 193 | * to nla_end_nested. 194 | */ 195 | struct rtattr *nla_begin_nested(struct nlmsg *nlmsg, int attr); 196 | 197 | /* 198 | * nla_end_nested: end the nesting attribute 199 | * 200 | * @nlmsg: the netlink message 201 | * @nested: the nested pointer 202 | * 203 | * Returns the current 204 | */ 205 | void nla_end_nested(struct nlmsg *nlmsg, struct rtattr *attr); 206 | 207 | /* 208 | * nlmsg_allocate : allocate a netlink message. The netlink format message 209 | * is a header, a padding, a payload and a padding again. 210 | * When a netlink message is allocated, the size specify the 211 | * payload we want. So the real size of the allocated message 212 | * is sizeof(header) + sizeof(padding) + payloadsize + sizeof(padding), 213 | * in other words, the function will allocate more than specified. When 214 | * the buffer is allocated, the content is zeroed. 215 | * The function will also fill the field nlmsg_len with NLMSG_HDRLEN. 216 | * If the allocation must be for the specified size, just use malloc. 217 | * 218 | * @size: the capacity of the payload to be allocated 219 | * 220 | * Returns a pointer to the newly allocated netlink message, NULL otherwise 221 | */ 222 | struct nlmsg *nlmsg_alloc(size_t size); 223 | 224 | /* 225 | * nlmsg_alloc_reserve: like nlmsg_alloc(), but reserve the whole payload 226 | * after allocated, that is, the field nlmsg_len be set to the capacity 227 | * of nlmsg. Often used to allocate a message for the reply. 228 | * 229 | * @size: the capacity of the payload to be allocated. 230 | */ 231 | struct nlmsg *nlmsg_alloc_reserve(size_t size); 232 | 233 | /* 234 | * Reserve room for additional data at the tail of a netlink message 235 | * 236 | * @nlmsg: the netlink message 237 | * @len: length of additional data to reserve room for 238 | * 239 | * Returns a pointer to newly reserved room or NULL 240 | */ 241 | void *nlmsg_reserve(struct nlmsg *nlmsg, size_t len); 242 | 243 | /* 244 | * nlmsg_free : free a previously allocate message 245 | * 246 | * @nlmsg: the netlink message to be freed 247 | */ 248 | void nlmsg_free(struct nlmsg *nlmsg); 249 | 250 | /* 251 | * nlmsg_data : returns a pointer to the data contained in the netlink message 252 | * 253 | * @nlmsg : the netlink message to get the data 254 | * 255 | * Returns a pointer to the netlink data or NULL if there is no data 256 | */ 257 | void *nlmsg_data(struct nlmsg *nlmsg); 258 | 259 | 260 | #endif 261 | -------------------------------------------------------------------------------- /cells/nsexec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * nsexec.h 3 | * 4 | * Copyright (C) 2010-2013 Columbia University 5 | * Authors: Christoffer Dall 6 | * Jeremy C. Andrus 7 | * Alexander Van't Hof 8 | * 9 | * This program is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU General Public License 11 | * as published by the Free Software Foundation; either version 2 12 | * of the License, or (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 22 | * USA. 23 | */ 24 | #ifndef NSEXEC_H 25 | #define NSEXEC_H 26 | 27 | extern void tear_down_cell(struct cell_args *args, 28 | struct pty_info *console_pty); 29 | 30 | extern int cell_nsexec(int sd, struct cell_args *args, 31 | char *name, struct pty_info *pty); 32 | 33 | extern char *create_cgroup(char *cellname); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /cells/shared_ops.c: -------------------------------------------------------------------------------- 1 | /* 2 | * shared_ops.c 3 | * 4 | * shared client/server messaging code for Cells 5 | * 6 | * Copyright (C) 2010-2013 Columbia University 7 | * Authors: Christoffer Dall 8 | * Jeremy C. Andrus 9 | * Alexander Van't Hof 10 | * 11 | * This program is free software; you can redistribute it and/or 12 | * modify it under the terms of the GNU General Public License 13 | * as published by the Free Software Foundation; either version 2 14 | * of the License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU General Public License 22 | * along with this program; if not, write to the Free Software 23 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 24 | * USA. 25 | */ 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #define LOG_TAG "Cells" 37 | #include 38 | 39 | #include "celld.h" 40 | 41 | /* Initialize given sockaddr_un structure. 42 | * Returns address_length. 43 | */ 44 | int init_addr(struct sockaddr_un *addr) 45 | { 46 | int pathlen = strlen(SOCKET_PATH); 47 | memset(addr, 0, sizeof(struct sockaddr_un)); 48 | addr->sun_family = AF_UNIX; 49 | addr->sun_path[0] = 0; /* Make abstract */ 50 | strncpy(&addr->sun_path[1], SOCKET_PATH, pathlen); 51 | return pathlen + 1 + offsetof(struct sockaddr_un, sun_path); 52 | } 53 | 54 | int _send_msg(int fd, const char *fmt, va_list ap) 55 | { 56 | char buf[MAX_MSG_LEN]; 57 | char *ptr; 58 | int remain, ret; 59 | int len = vsnprintf(buf, MAX_MSG_LEN, fmt, ap) + 1; 60 | if (len > MAX_MSG_LEN) { 61 | ALOGE("Failed to send response: Message is too long"); 62 | return -1; /* msg too long */ 63 | } 64 | 65 | remain = len; 66 | ptr = buf; 67 | while (remain > 0) { 68 | if ((ret = write(fd, ptr, remain)) < 0) { 69 | ALOGE("Failed to send response: %s", strerror(errno)); 70 | return -1; 71 | } 72 | remain -= ret; 73 | ptr += ret; 74 | } 75 | return 0; 76 | } 77 | 78 | int send_msg(int fd, const char *fmt, ...) 79 | { 80 | int ret; 81 | 82 | va_list ap; 83 | va_start(ap, fmt); 84 | ret = _send_msg(fd, fmt, ap); 85 | va_end(ap); 86 | 87 | return ret; 88 | } 89 | 90 | int recv_msg_len(int fd, char **code, char **msg, int maxlen) 91 | { 92 | char buf[MAX_MSG_LEN+1]; 93 | int remain, ret, n; 94 | 95 | if (maxlen > MAX_MSG_LEN) 96 | return -1; 97 | 98 | memset(buf, 0, sizeof(buf)); 99 | 100 | n = 0; 101 | remain = maxlen; 102 | while (remain > 0) { 103 | ret = read(fd, buf + n, remain); 104 | if (ret < 0) 105 | return -1; 106 | if (ret == 0) 107 | break; 108 | n += ret; 109 | remain -= ret; 110 | } 111 | 112 | if (n == 0) 113 | return -1; 114 | 115 | /* 116 | * messages are generally in the form: 117 | * "CODE MESSAGE..." 118 | */ 119 | char *space_pos = strchr(buf, ' '); 120 | if (!space_pos) { 121 | /* 122 | * only a 1 part message: that's OK, 123 | * but we always want to free the msg buf, so 124 | * we'll create a 1-byte empty string. 125 | */ 126 | *msg = malloc(1); 127 | *msg[0] = '\0'; 128 | } else { 129 | *msg = malloc(n); 130 | strcpy(*msg, space_pos+1); 131 | /* formal separation */ 132 | *space_pos = '\0'; 133 | } 134 | *code = malloc(strlen(buf)); 135 | strcpy(*code, buf); 136 | /*printf("recv: |%s| |%s|\n", *code, *msg);*/ 137 | return 0; 138 | } 139 | 140 | /* Receives a message. Mallocs space and stores data in code and msg. 141 | * Returns 0 on success, -1 on failure */ 142 | int recv_msg(int fd, char **code, char **msg) 143 | { 144 | return recv_msg_len(fd, code, msg, MAX_MSG_LEN); 145 | } 146 | 147 | /* Code adapted from: UNIX Network Programming, Volume 1, Second Edition: 148 | * Networking APIs: Sockets and XTI, Prentice Hall, 1998, W. Richard Stevens */ 149 | int recv_fd(int conn_fd) 150 | { 151 | struct msghdr msg; 152 | struct iovec iov[1]; 153 | char c = 'x'; 154 | 155 | union { 156 | struct cmsghdr cm; 157 | char control[CMSG_SPACE(sizeof(int))]; 158 | } control_un; 159 | struct cmsghdr *cmptr; 160 | 161 | msg.msg_control = control_un.control; 162 | msg.msg_controllen = sizeof(control_un.control); 163 | 164 | msg.msg_name = NULL; 165 | msg.msg_namelen = 0; 166 | 167 | /* Need at least 1 data byte so recvmsg will block */ 168 | iov[0].iov_base = &c; 169 | iov[0].iov_len = sizeof(c); 170 | msg.msg_iov = iov; 171 | msg.msg_iovlen = 1; 172 | 173 | if (recvmsg(conn_fd, &msg, 0) <= 0) { 174 | perror("recvmsg failed"); 175 | return -1; 176 | } 177 | 178 | cmptr = CMSG_FIRSTHDR(&msg); 179 | 180 | if (cmptr == NULL && cmptr->cmsg_len != CMSG_LEN(sizeof(int))) 181 | return -1; 182 | if (cmptr->cmsg_level != SOL_SOCKET || cmptr->cmsg_type != SCM_RIGHTS) 183 | return -1; 184 | return *((int *)CMSG_DATA(cmptr)); 185 | } 186 | 187 | /* Code adapted from: UNIX Network Programming, Volume 1, Second Edition: 188 | * Networking APIs: Sockets and XTI, Prentice Hall, 1998, W. Richard Stevens */ 189 | int send_fd(int conn_fd, int fd) 190 | { 191 | struct msghdr msg; 192 | struct iovec iov[1]; 193 | char c = 'x'; 194 | 195 | union { 196 | struct cmsghdr cm; 197 | char control[CMSG_SPACE(sizeof(int))]; 198 | } control_un; 199 | struct cmsghdr *cmptr; 200 | 201 | msg.msg_control = control_un.control; 202 | msg.msg_controllen = sizeof(control_un.control); 203 | 204 | cmptr = CMSG_FIRSTHDR(&msg); 205 | cmptr->cmsg_len = CMSG_LEN(sizeof(int)); 206 | cmptr->cmsg_level = SOL_SOCKET; 207 | cmptr->cmsg_type = SCM_RIGHTS; 208 | *((int *)CMSG_DATA(cmptr)) = fd; 209 | 210 | msg.msg_name = NULL; 211 | msg.msg_namelen = 0; 212 | 213 | iov[0].iov_base = &c; 214 | iov[0].iov_len = sizeof(c); 215 | msg.msg_iov = iov; 216 | msg.msg_iovlen = 1; 217 | 218 | if (sendmsg(conn_fd, &msg, 0) <= 0) 219 | return -1; 220 | return 0; 221 | } 222 | -------------------------------------------------------------------------------- /cells/socket_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * socket_common.h 3 | * 4 | * Common socket routines used by cell and celld 5 | * 6 | * Copyright (C) 2010-2013 Columbia University 7 | * Authors: Christoffer Dall 8 | * Jeremy C. Andrus 9 | * 10 | * This program is free software; you can redistribute it and/or 11 | * modify it under the terms of the GNU General Public License 12 | * as published by the Free Software Foundation; either version 2 13 | * of the License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU General Public License 21 | * along with this program; if not, write to the Free Software 22 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 23 | * USA. 24 | */ 25 | #ifndef SOCKET_COMMON_H 26 | #define SOCKET_COMMON_H 27 | 28 | #include 29 | #include 30 | 31 | struct socket_client { 32 | char root_path[PATH_MAX]; 33 | int init_pid; 34 | void *data; 35 | 36 | struct socket_client *next; 37 | struct socket_client *prev; 38 | }; 39 | 40 | struct client_list { 41 | struct socket_client *head; 42 | struct socket_client *tail; 43 | pthread_mutex_t mutex; 44 | }; 45 | 46 | /* 47 | * Adds a client to the list of active possible containers that may start 48 | * sending socket control requests. 49 | */ 50 | static inline void add_socket_client(struct socket_client *client, 51 | struct client_list *list) 52 | { 53 | pthread_mutex_lock(&list->mutex); 54 | client->next = client->prev = NULL; 55 | if (list->tail == NULL) 56 | list->head = list->tail = client; 57 | else { 58 | client->prev = list->tail; 59 | list->tail->next = client; 60 | list->tail = client; 61 | } 62 | pthread_mutex_unlock(&list->mutex); 63 | } 64 | 65 | /* 66 | * Find the client in the list of registered clients. 67 | * Return NULL if none is found. 68 | */ 69 | static inline struct socket_client *find_socket_client(char *root_path, 70 | struct client_list *list) 71 | { 72 | struct socket_client *ptr; 73 | 74 | pthread_mutex_lock(&list->mutex); 75 | ptr = list->head; 76 | while (ptr != NULL) { 77 | if (strncmp(root_path, ptr->root_path, PATH_MAX) == 0) 78 | break; 79 | ptr = ptr->next; 80 | } 81 | pthread_mutex_unlock(&list->mutex); 82 | return ptr; 83 | } 84 | 85 | /* 86 | * Remove the client from the list of registered clients 87 | */ 88 | static inline void del_socket_client(struct socket_client *client, 89 | struct client_list *list) 90 | { 91 | if (client != NULL) { 92 | pthread_mutex_lock(&list->mutex); 93 | if (client->prev != NULL) 94 | client->prev->next = client->next; 95 | if (client->next != NULL) 96 | client->next->prev = client->prev; 97 | 98 | if (list->head == client) 99 | list->head = client->next; 100 | if (list->tail == client) 101 | list->tail = client->prev; 102 | pthread_mutex_unlock(&list->mutex); 103 | } 104 | } 105 | 106 | /* 107 | * Create a unix socket and bind to it. 108 | */ 109 | static inline int cell_socket(char *path) 110 | { 111 | struct sockaddr_un local; 112 | size_t len; 113 | int sock; 114 | 115 | if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { 116 | return -1; 117 | } 118 | 119 | fcntl(sock, F_SETFD, FD_CLOEXEC); 120 | 121 | local.sun_family = AF_UNIX; 122 | strncpy(local.sun_path, path, sizeof(local.sun_path)); 123 | unlink(local.sun_path); 124 | len = strlen(local.sun_path) + sizeof(local.sun_family); 125 | if (bind(sock, (struct sockaddr *)&local, len) == -1) { 126 | return -1; 127 | } 128 | 129 | return sock; 130 | } 131 | 132 | /* 133 | * Look at the registered list of clients and ask celld for each of them if the 134 | * client is the active_cell - return the client if that is the case. 135 | * 136 | * TODO: This suggests that the data in socket_client could go in the cell_node 137 | * and some funcionality be consolidated. 138 | */ 139 | static inline struct socket_client* 140 | active_socket_client(struct client_list *list) 141 | { 142 | struct socket_client *client; 143 | struct cell_node *node; 144 | 145 | pthread_mutex_lock(&list->mutex); 146 | 147 | client = list->head; 148 | while (client != NULL) { 149 | node = search_cells_path(client->root_path); 150 | if (node == active_cell) 151 | break; 152 | client = client->next; 153 | } 154 | 155 | pthread_mutex_unlock(&list->mutex); 156 | return client; 157 | } 158 | 159 | /* 160 | * Map a socket client (cell instance) to a client ID 161 | */ 162 | static inline int socket_client_id(struct socket_client *client) 163 | { 164 | struct cell_node *cell; 165 | if (!client) 166 | return -1; 167 | 168 | cell = search_cells_path(client->root_path); 169 | if (cell == NULL) 170 | return -1; 171 | return cell->id; 172 | } 173 | 174 | /* 175 | * Obtains the cell ID from its configuration file 176 | * 177 | * This lookup is what effectively chooses a cell into which an incoming call 178 | * or SMS, etc. will be placed. The digit must correspond to the digit 179 | * appended to the caller ID from the calling service 180 | */ 181 | static inline struct socket_client * 182 | socket_client_from_id(int cellID, struct client_list *list) 183 | { 184 | struct socket_client *client; 185 | char cellID_str[0]; 186 | 187 | cellID_str[1] = 0; 188 | pthread_mutex_lock(&list->mutex); 189 | 190 | client = list->head; 191 | while (client != NULL) { 192 | int cid = socket_client_id(client); 193 | if (cid == cellID) 194 | break; 195 | client = client->next; 196 | } 197 | 198 | pthread_mutex_unlock(&list->mutex); 199 | return client; 200 | } 201 | 202 | static size_t number_of_clients(struct client_list *list) 203 | { 204 | struct socket_client *client; 205 | size_t cnt = 0; 206 | 207 | pthread_mutex_lock(&list->mutex); 208 | 209 | client = list->head; 210 | while (client != NULL) { 211 | cnt++; 212 | client = client->next; 213 | } 214 | 215 | pthread_mutex_unlock(&list->mutex); 216 | return cnt; 217 | 218 | } 219 | 220 | #endif 221 | -------------------------------------------------------------------------------- /cells/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * util.h 3 | * 4 | * Copyright (C) 2010-2013 Columbia University 5 | * Authors: Christoffer Dall 6 | * Jeremy C. Andrus 7 | * Alexander Van't Hof 8 | * 9 | * This program is free software; you can redistribute it and/or 10 | * modify it under the terms of the GNU General Public License 11 | * as published by the Free Software Foundation; either version 2 12 | * of the License, or (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 22 | * USA. 23 | */ 24 | #ifndef UTIL_H 25 | #define UTIL_H 26 | 27 | #include 28 | 29 | #define __STR(X) #X 30 | #define _STR(X) __STR(X) 31 | #define STR(X) _STR(X) 32 | 33 | int vdir_exists(const char *fmt, ...); 34 | int dir_exists(const char *path); 35 | int file_exists(const char *path); 36 | void daemonize(void); 37 | void close_fds(void); 38 | int rmtree(const char *path); 39 | int walkdir_through(void *ctx, const char *base, const char *sdir, int depth, const char *through, 40 | void (*callback)(void *ctx, const char *path, const char *subpath, struct dirent *e)); 41 | int walkdir(void *ctx, const char *base, const char *sdir, int depth, 42 | void (*callback)(void *ctx, const char *path, const char *subpath, struct dirent *e)); 43 | int copy_file(const char *src, const char *dst); 44 | 45 | int is_mounted(const char *path); 46 | int __unmount_dir(const char *root_path, char *dir); 47 | 48 | int insert_module(const char *path, const char *params); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /cells_build.mk: -------------------------------------------------------------------------------- 1 | 2 | PRODUCT_PACKAGES += busybox celld cellc cellsservice switchsystem cellssync cellsupdownvm cswitch 3 | -------------------------------------------------------------------------------- /cellsservice/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | 4 | # 5 | # cells service 6 | # 7 | include $(CLEAR_VARS) 8 | 9 | LOCAL_CFLAGS := 10 | 11 | LOCAL_SRC_FILES:= \ 12 | CellsPrivateService.cpp \ 13 | ICellsPrivateService.cpp \ 14 | main_cells.cpp \ 15 | cellnet.c 16 | 17 | LOCAL_MODULE := cellsservice 18 | LOCAL_MODULE_TAGS := optional 19 | LOCAL_MODULE_OWNER := cells 20 | LOCAL_SHARED_LIBRARIES := libm libcutils libc libbinder libutils libgui libpowermanager liblog 21 | #LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) 22 | include $(BUILD_EXECUTABLE) 23 | 24 | 25 | #sync 26 | include $(CLEAR_VARS) 27 | 28 | LOCAL_SRC_FILES := \ 29 | cellssync.cpp \ 30 | ICellsPrivateService.cpp 31 | 32 | LOCAL_MODULE:= cellssync 33 | LOCAL_MODULE_TAGS := optional 34 | LOCAL_MODULE_OWNER := cells 35 | #LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) 36 | LOCAL_SHARED_LIBRARIES := libm libcutils libc libbinder libutils liblog 37 | include $(BUILD_EXECUTABLE) 38 | 39 | #cswitch 40 | include $(CLEAR_VARS) 41 | 42 | LOCAL_SRC_FILES := \ 43 | cswitch.cpp \ 44 | ICellsPrivateService.cpp 45 | 46 | LOCAL_MODULE:= cswitch 47 | LOCAL_MODULE_TAGS := optional 48 | LOCAL_MODULE_OWNER := cells 49 | #LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) 50 | LOCAL_SHARED_LIBRARIES := libm libcutils libc libbinder libutils liblog 51 | include $(BUILD_EXECUTABLE) 52 | 53 | 54 | 55 | #sync 56 | include $(CLEAR_VARS) 57 | 58 | LOCAL_SRC_FILES := \ 59 | cellsupdownvm.cpp 60 | 61 | LOCAL_MODULE:= cellsupdownvm 62 | LOCAL_MODULE_TAGS := optional 63 | LOCAL_MODULE_OWNER := cells 64 | #LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN) 65 | LOCAL_SHARED_LIBRARIES := libm libcutils libc libutils liblog 66 | include $(BUILD_EXECUTABLE) 67 | 68 | 69 | -------------------------------------------------------------------------------- /cellsservice/CellsPrivateService.h: -------------------------------------------------------------------------------- 1 | #pragma GCC system_header 2 | #ifndef __GUIEXT_SERVICE_H__ 3 | #define __GUIEXT_SERVICE_H__ 4 | 5 | #include 6 | #include "ICellsPrivateService.h" 7 | 8 | namespace android 9 | { 10 | 11 | class String16; 12 | class CellsPrivateService : 13 | public BinderService, 14 | public BnCellsPrivateService 15 | // public Thread 16 | { 17 | friend class BinderService; 18 | public: 19 | 20 | CellsPrivateService(); 21 | ~CellsPrivateService(); 22 | 23 | static char const* getServiceName() { return "CellsPrivateService"; } 24 | 25 | virtual status_t setProperty(const String16& name,const String16& value); 26 | virtual status_t startCellsVM(const String16& name); 27 | virtual status_t stopCellsVM(const String16& name); 28 | virtual status_t cellsSwitchVM(const String16& name); 29 | virtual status_t cellsSwitchHOST(const String16& name); 30 | virtual status_t enterCell(const String16& name); 31 | virtual status_t enterHost(const String16& name); 32 | virtual status_t exitCell(const String16& name); 33 | virtual status_t exitHost(const String16& name); 34 | virtual status_t switchCellsVM(const String16& name); 35 | virtual status_t uploadCellsVM(const String16& name); 36 | virtual status_t downloadCellsVM(const String16& name); 37 | virtual status_t untarCellsVM(const String16& name); 38 | virtual status_t tarCellsVM(const String16& name); 39 | virtual status_t vmSystemReady(const String16& name); 40 | virtual status_t sendCellsVM(const String16& path, const String16& address); 41 | 42 | int isInCellstar(); 43 | void setCellstaring(); 44 | void setCellstared(); 45 | void startCellstar(); 46 | 47 | private: 48 | int mtar_pthread_t; 49 | }; 50 | }; 51 | #endif 52 | -------------------------------------------------------------------------------- /cellsservice/ICellsPrivateService.h: -------------------------------------------------------------------------------- 1 | #ifndef __ICELLSSERVICE_H__ 2 | #define __ICELLSSERVICE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace android 11 | { 12 | 13 | class String16; 14 | class ICellsPrivateService : public IInterface 15 | { 16 | protected: 17 | enum { 18 | SETPROPERTY = IBinder::FIRST_CALL_TRANSACTION, 19 | STARTCELLSVM = IBinder::FIRST_CALL_TRANSACTION + 1, 20 | STOPCELLSVM = IBinder::FIRST_CALL_TRANSACTION + 2, 21 | SWITCHCELLSVM = IBinder::FIRST_CALL_TRANSACTION + 3, 22 | UPLOADCELLSVM = IBinder::FIRST_CALL_TRANSACTION + 4, 23 | DOWNLOADCELLSVM = IBinder::FIRST_CALL_TRANSACTION + 5, 24 | UNTARCELLSVM = IBinder::FIRST_CALL_TRANSACTION + 6, 25 | TARCELLSVM = IBinder::FIRST_CALL_TRANSACTION + 7, 26 | SYSTEMREADY = IBinder::FIRST_CALL_TRANSACTION + 8, 27 | CELLSSWITCHVM = IBinder::FIRST_CALL_TRANSACTION + 9, 28 | CELLSSWITCHHOST = IBinder::FIRST_CALL_TRANSACTION + 10, 29 | ENTERCELL = IBinder::FIRST_CALL_TRANSACTION + 11, 30 | ENTERHOST = IBinder::FIRST_CALL_TRANSACTION + 12, 31 | EXITCELL = IBinder::FIRST_CALL_TRANSACTION + 13, 32 | EXITHOST = IBinder::FIRST_CALL_TRANSACTION + 14, 33 | SENDCELLSVM = IBinder::FIRST_CALL_TRANSACTION + 15, 34 | }; 35 | 36 | public: 37 | DECLARE_META_INTERFACE(CellsPrivateService); 38 | 39 | virtual status_t setProperty(const String16& name,const String16& value) = 0; 40 | virtual status_t startCellsVM(const String16& name) = 0; 41 | virtual status_t stopCellsVM(const String16& name) = 0; 42 | virtual status_t cellsSwitchVM(const String16& name) = 0; 43 | virtual status_t cellsSwitchHOST(const String16& name) = 0; 44 | virtual status_t enterCell(const String16& name) = 0; 45 | virtual status_t enterHost(const String16& name) = 0; 46 | virtual status_t exitCell(const String16& name) = 0; 47 | virtual status_t exitHost(const String16& name) = 0; 48 | virtual status_t switchCellsVM(const String16& name) = 0; 49 | virtual status_t uploadCellsVM(const String16& name) = 0; 50 | virtual status_t downloadCellsVM(const String16& name) = 0; 51 | virtual status_t untarCellsVM(const String16& name) = 0; 52 | virtual status_t tarCellsVM(const String16& name) = 0; 53 | virtual status_t vmSystemReady(const String16& name) = 0; 54 | virtual status_t sendCellsVM(const String16& path, const String16& address) = 0; 55 | }; 56 | 57 | class BnCellsPrivateService : public BnInterface 58 | { 59 | virtual status_t onTransact(uint32_t code, 60 | const Parcel& data, 61 | Parcel* reply, 62 | uint32_t flags = 0); 63 | }; 64 | 65 | }; 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /cellsservice/cellnet.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define LOG_TAG "Cells/cellnet" 11 | #include 12 | #include 13 | #include 14 | 15 | #define INTERFACE "wlan0" 16 | #define VETH0 "vm_wlan_%d_0" 17 | #define VETH1 "vm_wlan_%d_1" 18 | 19 | #define VETHIFACEADDRBASE 16 20 | 21 | #define VETHMASK 16 22 | #define VETHADDRMASK "255.255.0.0" 23 | #define VETHGATEADDR "172.%d.0.0" 24 | 25 | #define VETHIFACEADDR0 "172.%d.3.2" 26 | #define VETHIFACEADDR1 "172.%d.3.3" 27 | 28 | void init_cell_net() 29 | { 30 | 31 | } 32 | 33 | void createveth(int index) 34 | { 35 | int ret = 0; 36 | char vethname0[24] = {0}; 37 | char vethname1[24] = {0}; 38 | char vethaddr0[64] = {0}; 39 | char vethgateaddr[64] = {0}; 40 | 41 | char cmd[256] = {0}; 42 | 43 | snprintf(vethname0, sizeof(vethname0), VETH0, index); 44 | snprintf(vethname1, sizeof(vethname1), VETH1, index); 45 | snprintf(vethgateaddr, sizeof(vethgateaddr), VETHGATEADDR, VETHIFACEADDRBASE + index); 46 | snprintf(vethaddr0, sizeof(vethaddr0), VETHIFACEADDR0, VETHIFACEADDRBASE + index); 47 | 48 | errno = 0; 49 | memset(cmd, 0, sizeof(cmd)); 50 | snprintf(cmd, sizeof(cmd), "ip link add name %s type veth peer name %s", vethname0, vethname1); 51 | ret = system(cmd); 52 | ALOGD("%s errno = %s",cmd ,strerror(errno)); 53 | 54 | errno = 0; 55 | memset(cmd, 0, sizeof(cmd)); 56 | snprintf(cmd, sizeof(cmd), "ifconfig %s %s netmask %s up", vethname0, vethaddr0, VETHADDRMASK); 57 | ret = system(cmd); 58 | ALOGD("%s errno = %s",cmd ,strerror(errno)); 59 | 60 | errno = 0; 61 | memset(cmd, 0, sizeof(cmd)); 62 | snprintf(cmd, sizeof(cmd), "iptables -t nat -A POSTROUTING -s %s/%d -o %s -j MASQUERADE", vethgateaddr, VETHMASK, INTERFACE); 63 | ret = system(cmd); 64 | ALOGD("%s errno = %s",cmd ,strerror(errno)); 65 | 66 | errno = 0; 67 | memset(cmd, 0, sizeof(cmd)); 68 | snprintf(cmd, sizeof(cmd), "iptables -t filter -A FORWARD -i %s -o %s -j ACCEPT", INTERFACE, vethname0); 69 | ret = system(cmd); 70 | ALOGD("%s errno = %s",cmd ,strerror(errno)); 71 | 72 | errno = 0; 73 | memset(cmd, 0, sizeof(cmd)); 74 | snprintf(cmd, sizeof(cmd), "iptables -t filter -A FORWARD -o %s -i %s -j ACCEPT", INTERFACE, vethname0); 75 | ret = system(cmd); 76 | ALOGD("%s errno = %s",cmd ,strerror(errno)); 77 | } 78 | 79 | void vethtons(int pid,int index) 80 | { 81 | int ret = 0; 82 | char vethname1[24] = {0}; 83 | char cmd[256]; 84 | 85 | snprintf(vethname1, sizeof(vethname1), VETH1, index); 86 | 87 | errno = 0; 88 | memset(cmd,0,sizeof(cmd)); 89 | snprintf(cmd, sizeof(cmd), "ip link set %s netns %d",vethname1 ,pid ); 90 | ret = system(cmd); 91 | ALOGD("%s errno = %s",cmd,strerror(errno)); 92 | } 93 | 94 | void rnameveth(int index) 95 | { 96 | int ret = 0; 97 | char vethname1[24] = {0}; 98 | char vethaddr0[64] = {0}; 99 | char vethaddr1[64] = {0}; 100 | char cmd[256]; 101 | 102 | snprintf(vethname1, sizeof(vethname1), VETH1, index); 103 | snprintf(vethaddr0, sizeof(vethaddr0), VETHIFACEADDR0, VETHIFACEADDRBASE + index); 104 | snprintf(vethaddr1, sizeof(vethaddr1), VETHIFACEADDR1, VETHIFACEADDRBASE + index); 105 | 106 | errno = 0; 107 | memset(cmd,0,sizeof(cmd)); 108 | snprintf(cmd, sizeof(cmd), "ip link set %s name %s",vethname1 ,INTERFACE ); 109 | ret = system(cmd); 110 | ALOGD("%s errno = %s",cmd,strerror(errno)); 111 | 112 | errno = 0; 113 | memset(cmd,0,sizeof(cmd)); 114 | snprintf(cmd, sizeof(cmd), "ifconfig %s %s netmask %s up",INTERFACE,vethaddr1,VETHADDRMASK); 115 | ret = system(cmd); 116 | ALOGD("%s errno = %s",cmd,strerror(errno)); 117 | 118 | errno = 0; 119 | memset(cmd,0,sizeof(cmd)); 120 | snprintf(cmd, sizeof(cmd), "ip ro add default via %s dev %s",vethaddr0 ,INTERFACE); 121 | ret = system(cmd); 122 | ALOGD("%s errno = %s",cmd,strerror(errno)); 123 | } 124 | 125 | void starttether(int index) 126 | { 127 | int ret = 0; 128 | char vethname0[24] = {0}; 129 | char vethaddr0[64] = {0}; 130 | char vethgateaddr[64] = {0}; 131 | 132 | char cmd[256] = {0}; 133 | 134 | snprintf(vethname0, sizeof(vethname0), VETH0, index); 135 | snprintf(vethgateaddr, sizeof(vethgateaddr), VETHGATEADDR, VETHIFACEADDRBASE + index); 136 | snprintf(vethaddr0, sizeof(vethaddr0), VETHIFACEADDR0, VETHIFACEADDRBASE + index); 137 | 138 | errno = 0; 139 | memset(cmd,0,sizeof(cmd)); 140 | snprintf(cmd, sizeof(cmd), "ndc interface setcfg %s %s %d up multicast broadcast",vethname0 ,vethaddr0 ,VETHMASK); 141 | ret = system(cmd); 142 | ALOGD("%s errno = %s",cmd,strerror(errno)); 143 | 144 | errno = 0; 145 | memset(cmd,0,sizeof(cmd)); 146 | snprintf(cmd, sizeof(cmd), "ndc tether interface add %s",vethname0); 147 | ret = system(cmd); 148 | ALOGD("%s errno = %s",cmd,strerror(errno)); 149 | 150 | errno = 0; 151 | memset(cmd,0,sizeof(cmd)); 152 | snprintf(cmd, sizeof(cmd), "ndc network interface add local %s",vethname0); 153 | ret = system(cmd); 154 | ALOGD("%s errno = %s",cmd,strerror(errno)); 155 | 156 | errno = 0; 157 | memset(cmd,0,sizeof(cmd)); 158 | snprintf(cmd, sizeof(cmd), "ndc network route add local %s %s/%d",vethname0,vethgateaddr,VETHMASK); 159 | ret = system(cmd); 160 | ALOGD("%s errno = %s",cmd,strerror(errno)); 161 | 162 | errno = 0; 163 | memset(cmd,0,sizeof(cmd)); 164 | snprintf(cmd, sizeof(cmd), "ndc ipfwd enable %s",vethname0); 165 | ret = system(cmd); 166 | ALOGD("%s errno = %s",cmd,strerror(errno)); 167 | 168 | errno = 0; 169 | memset(cmd,0,sizeof(cmd)); 170 | snprintf(cmd, sizeof(cmd), "ndc nat enable %s %s 1 %s/%d",vethname0,INTERFACE,vethgateaddr,VETHMASK); 171 | ret = system(cmd); 172 | ALOGD("%s errno = %s",cmd,strerror(errno)); 173 | 174 | errno = 0; 175 | memset(cmd,0,sizeof(cmd)); 176 | snprintf(cmd, sizeof(cmd), "ndc ipfwd add %s %s",vethname0,INTERFACE); 177 | ret = system(cmd); 178 | ALOGD("%s errno = %s",cmd,strerror(errno)); 179 | } 180 | 181 | void stoptether(int index) 182 | { 183 | int ret = 0; 184 | char vethname0[24] = {0}; 185 | 186 | char cmd[256] = {0}; 187 | 188 | snprintf(vethname0, sizeof(vethname0), VETH0, index); 189 | 190 | errno = 0; 191 | memset(cmd,0,sizeof(cmd)); 192 | snprintf(cmd, sizeof(cmd), "ndc tether interface remove %s",vethname0); 193 | ret = system(cmd); 194 | ALOGD("%s errno = %s",cmd,strerror(errno)); 195 | 196 | errno = 0; 197 | memset(cmd,0,sizeof(cmd)); 198 | snprintf(cmd, sizeof(cmd), "ndc network interface remove local %s",vethname0); 199 | ret = system(cmd); 200 | ALOGD("%s errno = %s",cmd,strerror(errno)); 201 | 202 | errno = 0; 203 | memset(cmd,0,sizeof(cmd)); 204 | snprintf(cmd, sizeof(cmd), "ndc ipfwd disable %s",vethname0); 205 | ret = system(cmd); 206 | ALOGD("%s errno = %s",cmd,strerror(errno)); 207 | } 208 | 209 | void delveth(int index) 210 | { 211 | int ret = 0; 212 | char vethname0[24] = {0}; 213 | char vethaddr0[64] = {0}; 214 | char vethgateaddr[64] = {0}; 215 | 216 | char cmd[256] = {0}; 217 | 218 | snprintf(vethname0, sizeof(vethname0), VETH0, index); 219 | snprintf(vethgateaddr, sizeof(vethgateaddr), VETHGATEADDR, VETHIFACEADDRBASE + index); 220 | snprintf(vethaddr0, sizeof(vethaddr0), VETHIFACEADDR0, VETHIFACEADDRBASE + index); 221 | 222 | errno = 0; 223 | memset(cmd,0,sizeof(cmd)); 224 | snprintf(cmd, sizeof(cmd), "iptables -t nat -D POSTROUTING -s %s/%d -o %s -j MASQUERADE",vethgateaddr,VETHMASK,INTERFACE); 225 | ret = system(cmd); 226 | ALOGD("%s errno = %s",cmd,strerror(errno)); 227 | 228 | errno = 0; 229 | memset(cmd,0,sizeof(cmd)); 230 | snprintf(cmd, sizeof(cmd), "iptables -t filter -D FORWARD -i %s -o %s -j ACCEPT",INTERFACE,vethname0); 231 | ret = system(cmd); 232 | ALOGD("%s errno = %s",cmd,strerror(errno)); 233 | 234 | errno = 0; 235 | memset(cmd,0,sizeof(cmd)); 236 | snprintf(cmd, sizeof(cmd), "iptables -t filter -D FORWARD -o %s -i %s -j ACCEPT",INTERFACE,vethname0); 237 | ret = system(cmd); 238 | ALOGD("%s errno = %s",cmd,strerror(errno)); 239 | 240 | errno = 0; 241 | memset(cmd,0,sizeof(cmd)); 242 | snprintf(cmd, sizeof(cmd), "ip link delete %s type veth",vethname0); 243 | ret = system(cmd); 244 | ALOGD("%s errno = %s",cmd,strerror(errno)); 245 | } 246 | -------------------------------------------------------------------------------- /cellsservice/cellnet.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef __CELLNET_H 3 | #define __CELLNET_H 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | extern void init_cell_net(); 10 | extern void createveth(int index); 11 | extern void vethtons(int pid,int index); 12 | extern void rnameveth(int index); 13 | extern void starttether(int index); 14 | extern void stoptether(int index); 15 | extern void delveth(int index); 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif 20 | 21 | #endif /* __CELLNET_H */ 22 | -------------------------------------------------------------------------------- /cellsservice/cellssync.cpp: -------------------------------------------------------------------------------- 1 | #define LOG_TAG "GuiExt" 2 | 3 | #include 4 | #include 5 | #include "ICellsPrivateService.h" 6 | 7 | using namespace android; 8 | 9 | int main(int argc, char** argv) 10 | { 11 | const sp sm = initdefaultServiceManager(); 12 | if (sm != NULL) { 13 | sp binder = sm->checkService(String16("CellsPrivateService")); 14 | if (binder != NULL) { 15 | sp pCellsPrivateService = interface_cast(binder); 16 | if(pCellsPrivateService == NULL){ 17 | ALOGE("could not get service CellsPrivateService \n"); 18 | return 0; 19 | } 20 | 21 | if (argc == 2) { 22 | char value[PROPERTY_VALUE_MAX]; 23 | property_get(argv[1], value, ""); 24 | pCellsPrivateService->setProperty(android::String16(argv[1]),android::String16(value)); 25 | }else if (argc == 3) { 26 | pCellsPrivateService->setProperty(android::String16(argv[1]),android::String16(argv[2])); 27 | } 28 | } 29 | } 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /cellsservice/cellsupdownvm.cpp: -------------------------------------------------------------------------------- 1 | #define LOG_TAG "GuiExt" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | static void thread_exit_handler(int sig) 20 | { 21 | sig; 22 | 23 | pthread_exit(0); 24 | } 25 | 26 | int main(int argc, char** argv) 27 | { 28 | struct sigaction actions; 29 | memset(&actions, 0, sizeof(actions)); 30 | sigemptyset(&actions.sa_mask); 31 | actions.sa_flags = 0; 32 | actions.sa_handler = thread_exit_handler; 33 | if (sigaction(SIGQUIT|SIGKILL, &actions, NULL) < 0){ 34 | ALOGE("sigaction error: %s",strerror(errno)); 35 | } 36 | 37 | if (argc == 2){ 38 | if(strcmp(argv[1],"up") == 0){ 39 | property_set("persist.sys.vm.up", "1"); 40 | 41 | system("rm -rf /data/cells/cell1.tar.gz"); 42 | ALOGE("rm -rf /data/cells/cell1.tar.gz \n"); 43 | 44 | system("cd /data/cells && busybox tar zcvfp cell1.tar.gz cell1-rw"); 45 | ALOGE("busybox tar zcvfp /data/cells/cell1.tar.gz /data/cells/cell1-rw \n"); 46 | 47 | system("cd /data/cells && busybox ftpput -u ftp-hw-user -p 1 129.204.70.73 cell1.tar.gz"); 48 | ALOGE("busybox ftpput -u ftp-hw-user -p 1 129.204.70.73 /data/cells/cell1.tar.gz err= %s \n", strerror(errno)); 49 | 50 | property_set("persist.sys.vm.up", "0"); 51 | 52 | property_set("persist.sys.vmup", "0"); 53 | }else if(strcmp(argv[1],"down") == 0){ 54 | 55 | property_set("persist.sys.vmstop", "1"); 56 | property_set("persist.sys.vmstop", "0"); 57 | 58 | property_set("persist.sys.vm.down", "1"); 59 | 60 | if(access("/data/cells/cell1.tar.gz",F_OK)!= 0){ 61 | system("touch /data/cells/cell1.tar.gz "); 62 | } 63 | 64 | system("cd /data/cells && busybox ftpget -c -u ftp-hw-user -p 1 129.204.70.73 cell1.tar.gz"); 65 | ALOGE("busybox ftpget -u ftp-hw-user -p 1 129.204.70.73 /data/cells/cell1.tar.gz err=%s \n", strerror(errno)); 66 | 67 | system("rm -rf /data/cells/cell1-rw && mkdir /data/cells/cell1-rw"); 68 | ALOGE("rm -rf /data/cells/cell1-rw \n"); 69 | 70 | system("cd /data/cells && busybox tar zxvfp cell1.tar.gz"); 71 | ALOGE("busybox tar zxvfp /data/cells/cell1.tar.gz /data/cells/cell1-rw \n"); 72 | 73 | property_set("persist.sys.vm.down", "0"); 74 | 75 | property_set("persist.sys.vmdown", "0"); 76 | }else if(strcmp(argv[1],"untar") == 0){ 77 | 78 | if(access("/sdcard/cell1.tar.gz",F_OK) == 0){ 79 | if(access("/data/cells/cell1.tar.gz",F_OK) == 0) 80 | system("rm /data/cells/cell1.tar.gz "); 81 | system("mv /sdcard/cell1.tar.gz /data/cells/cell1.tar.gz "); 82 | }else{ 83 | if(access("/data/cells/cell1.tar.gz",F_OK) != 0){ 84 | return 0; 85 | } 86 | } 87 | 88 | property_set("persist.sys.vmstop", "1"); 89 | property_set("persist.sys.vmstop", "0"); 90 | 91 | property_set("persist.sys.vm.untar", "1"); 92 | 93 | system("rm -rf /data/cells/cell1-rw && mkdir /data/cells/cell1-rw"); 94 | ALOGE("rm -rf /data/cells/cell1-rw \n"); 95 | 96 | system("cd /data/cells && busybox tar zxvfp cell1.tar.gz"); 97 | ALOGE("busybox tar zxvfp /data/cells/cell1.tar.gz /data/cells/cell1-rw \n"); 98 | 99 | property_set("persist.sys.vm.untar", "0"); 100 | } 101 | } 102 | 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /cellsservice/cswitch.cpp: -------------------------------------------------------------------------------- 1 | #define LOG_TAG "GuiExt" 2 | 3 | #include 4 | #include 5 | #include "ICellsPrivateService.h" 6 | 7 | using namespace android; 8 | 9 | int main(int argc, char** argv) 10 | { 11 | const sp sm = defaultServiceManager(); 12 | if (sm != NULL) { 13 | sp binder = sm->checkService(String16("CellsPrivateService")); 14 | if (binder != NULL) { 15 | sp pCellsPrivateService = interface_cast(binder); 16 | if(pCellsPrivateService == NULL){ 17 | ALOGE("could not get service CellsPrivateService \n"); 18 | return 0; 19 | } 20 | 21 | char value[PROPERTY_VALUE_MAX]; 22 | property_get("ro.boot.vm", value, "1"); 23 | if((strcmp(value, "0") == 0)){ 24 | if(argc == 2){ 25 | pCellsPrivateService->switchCellsVM(android::String16(argv[1])); 26 | } 27 | }else{ 28 | pCellsPrivateService->switchCellsVM(android::String16("host")); 29 | } 30 | } 31 | } 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /cellsservice/main_cells.cpp: -------------------------------------------------------------------------------- 1 | #define LOG_TAG "CellsService" 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "cellnet.h" 11 | 12 | using namespace android; 13 | 14 | static void init_vm_exit() 15 | { 16 | /*int vmfd = open("/.cell",O_RDONLY); 17 | if(vmfd >= 0){ 18 | char buf[10]; 19 | int len = read(vmfd, buf, 10); 20 | if(len > 0){ 21 | if(strcmp(buf,"0") == 0){ 22 | property_set("persist.sys.exit", "0"); 23 | }else{ 24 | property_set("persist.sys.exit", "1"); 25 | } 26 | } 27 | close(vmfd); 28 | }*/ 29 | 30 | property_set("persist.sys.exit", "1"); 31 | } 32 | 33 | static int init_vm_name() 34 | { 35 | int vmfd = open("/.name",O_RDONLY); 36 | if(vmfd >= 0){ 37 | char buf[125]; 38 | int len = read(vmfd, buf, 125); 39 | if(len > 0){ 40 | 41 | buf[len]='\0'; 42 | property_set("persist.sys.vm.name", buf); 43 | close(vmfd); 44 | 45 | ALOGI("persist.sys.vm.name = %s ", buf); 46 | 47 | int i = 0; 48 | sscanf(buf, "cell%d",&i); 49 | return i; 50 | } 51 | close(vmfd); 52 | } 53 | return 0; 54 | } 55 | 56 | int main(int /*argc*/, char** /*argv*/) 57 | { 58 | ALOGI("GuiExt service start..."); 59 | 60 | char value[PROPERTY_VALUE_MAX]; 61 | property_get("ro.boot.vm", value, "1"); 62 | if((strcmp(value, "0") == 0)){ 63 | property_set("persist.sys.exit", "0"); 64 | property_set("persist.sys.vm.name", ""); 65 | property_set("persist.sys.active", ""); 66 | }else{ 67 | init_vm_exit(); 68 | 69 | int i = init_vm_name(); 70 | if(i > 0){ 71 | rnameveth(i); 72 | } 73 | } 74 | 75 | CellsPrivateService::publishAndJoinThreadPool(true); 76 | 77 | ProcessState::self()->setThreadPoolMaxThreadCount(4); 78 | 79 | ALOGD("Cells service exit..."); 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /switchsystem/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | include $(CLEAR_VARS) 3 | 4 | LOCAL_STATIC_ANDROID_LIBRARIES := \ 5 | android-support-v4 \ 6 | android-support-v13 \ 7 | android-support-v7-appcompat \ 8 | android-support-v7-cardview \ 9 | android-support-v7-preference \ 10 | android-support-v7-recyclerview \ 11 | android-support-v14-preference 12 | 13 | LOCAL_STATIC_JAVA_LIBRARIES := \ 14 | okhttp3 \ 15 | okhttp-okio 16 | 17 | LOCAL_MODULE_TAGS := optional 18 | LOCAL_MODULE_OWNER := cells 19 | LOCAL_SRC_FILES := $(call all-subdir-java-files) 20 | LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/res 21 | LOCAL_PACKAGE_NAME := switchsystem 22 | LOCAL_CERTIFICATE := platform 23 | LOCAL_PRIVILEGED_MODULE := true 24 | LOCAL_PRIVATE_PLATFORM_APIS := true 25 | include $(BUILD_PACKAGE) 26 | 27 | include $(CLEAR_VARS) 28 | 29 | LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \ 30 | okhttp3:libs/okhttp-3.9.0.jar \ 31 | 32 | include $(BUILD_MULTI_PREBUILT) 33 | 34 | include $(CLEAR_VARS) 35 | 36 | LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \ 37 | okhttp-okio:libs/okio-1.13.0.jar \ 38 | 39 | include $(BUILD_MULTI_PREBUILT) 40 | 41 | # Use the folloing include to make our test apk. 42 | include $(call all-makefiles-under,$(LOCAL_PATH)) 43 | -------------------------------------------------------------------------------- /switchsystem/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /switchsystem/libs/okhttp-3.9.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/libs/okhttp-3.9.0.jar -------------------------------------------------------------------------------- /switchsystem/libs/okio-1.13.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/libs/okio-1.13.0.jar -------------------------------------------------------------------------------- /switchsystem/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /switchsystem/res/anim/dialog_enter.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /switchsystem/res/anim/dialog_exit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /switchsystem/res/anim/rotate_animation.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 13 | -------------------------------------------------------------------------------- /switchsystem/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /switchsystem/res/drawable-hdpi/ic_launcher_general.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/res/drawable-hdpi/ic_launcher_general.png -------------------------------------------------------------------------------- /switchsystem/res/drawable-hdpi/ic_launcher_secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/res/drawable-hdpi/ic_launcher_secure.png -------------------------------------------------------------------------------- /switchsystem/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /switchsystem/res/drawable-mdpi/ic_launcher_general.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/res/drawable-mdpi/ic_launcher_general.png -------------------------------------------------------------------------------- /switchsystem/res/drawable-mdpi/ic_launcher_secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/res/drawable-mdpi/ic_launcher_secure.png -------------------------------------------------------------------------------- /switchsystem/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /switchsystem/res/drawable-xhdpi/ic_launcher_general.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/res/drawable-xhdpi/ic_launcher_general.png -------------------------------------------------------------------------------- /switchsystem/res/drawable-xhdpi/ic_launcher_secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/res/drawable-xhdpi/ic_launcher_secure.png -------------------------------------------------------------------------------- /switchsystem/res/drawable-xxhdpi/dialog_loading_img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/res/drawable-xxhdpi/dialog_loading_img.png -------------------------------------------------------------------------------- /switchsystem/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /switchsystem/res/drawable-xxhdpi/ic_launcher_general.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/res/drawable-xxhdpi/ic_launcher_general.png -------------------------------------------------------------------------------- /switchsystem/res/drawable-xxhdpi/ic_launcher_secure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/res/drawable-xxhdpi/ic_launcher_secure.png -------------------------------------------------------------------------------- /switchsystem/res/drawable-xxhdpi/loading_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/res/drawable-xxhdpi/loading_bg.9.png -------------------------------------------------------------------------------- /switchsystem/res/drawable/bcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /switchsystem/res/drawable/dialog_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /switchsystem/res/drawable/loading_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/res/drawable/loading_bg.9.png -------------------------------------------------------------------------------- /switchsystem/res/drawable/popup_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jianglin-code/cells-of-container-android/72c2c15c8df00a3730d214083970f39c81cfdbbd/switchsystem/res/drawable/popup_bg.9.png -------------------------------------------------------------------------------- /switchsystem/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 |