blob: 0ef5c87984534fd71d0b56c0a7f1fc05692056a7 [file] [log] [blame]
The Android Open Source Project00f06fc2009-03-03 19:32:15 -08001/* //device/system/rild/rild.c
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <dlfcn.h>
21#include <string.h>
22#include <stdint.h>
23#include <unistd.h>
24#include <fcntl.h>
25#include <errno.h>
26
27#include <telephony/ril.h>
28#define LOG_TAG "RILD"
29#include <utils/Log.h>
30#include <cutils/properties.h>
31#include <cutils/sockets.h>
Nick Kralevichfe4e1ec2013-02-28 14:16:41 -080032#include <sys/capability.h>
The Android Open Source Project00f06fc2009-03-03 19:32:15 -080033#include <linux/prctl.h>
34
35#include <private/android_filesystem_config.h>
Vladimir Chtchetkine385a7392011-08-04 14:03:07 -070036#include "hardware/qemu_pipe.h"
The Android Open Source Project00f06fc2009-03-03 19:32:15 -080037
38#define LIB_PATH_PROPERTY "rild.libpath"
39#define LIB_ARGS_PROPERTY "rild.libargs"
40#define MAX_LIB_ARGS 16
41
42static void usage(const char *argv0)
43{
44 fprintf(stderr, "Usage: %s -l <ril impl library> [-- <args for impl library>]\n", argv0);
Elliott Hughese2a70cf2013-11-20 13:51:45 -080045 exit(EXIT_FAILURE);
The Android Open Source Project00f06fc2009-03-03 19:32:15 -080046}
47
48extern void RIL_register (const RIL_RadioFunctions *callbacks);
49
50extern void RIL_onRequestComplete(RIL_Token t, RIL_Errno e,
51 void *response, size_t responselen);
52
53extern void RIL_onUnsolicitedResponse(int unsolResponse, const void *data,
54 size_t datalen);
55
Wink Saville2932f312010-10-07 16:35:15 -070056extern void RIL_requestTimedCallback (RIL_TimedCallback callback,
The Android Open Source Project00f06fc2009-03-03 19:32:15 -080057 void *param, const struct timeval *relativeTime);
58
59
60static struct RIL_Env s_rilEnv = {
61 RIL_onRequestComplete,
62 RIL_onUnsolicitedResponse,
Wink Saville2932f312010-10-07 16:35:15 -070063 RIL_requestTimedCallback
The Android Open Source Project00f06fc2009-03-03 19:32:15 -080064};
65
66extern void RIL_startEventLoop();
67
68static int make_argv(char * args, char ** argv)
69{
70 // Note: reserve argv[0]
71 int count = 1;
72 char * tok;
73 char * s = args;
74
75 while ((tok = strtok(s, " \0"))) {
76 argv[count] = tok;
77 s = NULL;
78 count++;
79 }
80 return count;
81}
82
83/*
84 * switchUser - Switches UID to radio, preserving CAP_NET_ADMIN capabilities.
85 * Our group, cache, was set by init.
86 */
87void switchUser() {
88 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
89 setuid(AID_RADIO);
90
91 struct __user_cap_header_struct header;
Elliott Hughese2a70cf2013-11-20 13:51:45 -080092 memset(&header, 0, sizeof(header));
93 header.version = _LINUX_CAPABILITY_VERSION_3;
The Android Open Source Project00f06fc2009-03-03 19:32:15 -080094 header.pid = 0;
Elliott Hughese2a70cf2013-11-20 13:51:45 -080095
96 struct __user_cap_data_struct data[2];
97 memset(&data, 0, sizeof(data));
98
99 data[CAP_TO_INDEX(CAP_NET_ADMIN)].effective |= CAP_TO_MASK(CAP_NET_ADMIN);
100 data[CAP_TO_INDEX(CAP_NET_ADMIN)].permitted |= CAP_TO_MASK(CAP_NET_ADMIN);
101
102 data[CAP_TO_INDEX(CAP_NET_RAW)].effective |= CAP_TO_MASK(CAP_NET_RAW);
103 data[CAP_TO_INDEX(CAP_NET_RAW)].permitted |= CAP_TO_MASK(CAP_NET_RAW);
104
105 if (capset(&header, &data[0]) == -1) {
106 RLOGE("capset failed: %s", strerror(errno));
107 exit(EXIT_FAILURE);
108 }
The Android Open Source Project00f06fc2009-03-03 19:32:15 -0800109}
110
111int main(int argc, char **argv)
112{
113 const char * rilLibPath = NULL;
114 char **rilArgv;
115 void *dlHandle;
116 const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **);
117 const RIL_RadioFunctions *funcs;
118 char libPath[PROPERTY_VALUE_MAX];
119 unsigned char hasLibArgs = 0;
120
121 int i;
122
Nick Kralevichaea7d5b2010-12-10 15:53:02 -0800123 umask(S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH);
The Android Open Source Project00f06fc2009-03-03 19:32:15 -0800124 for (i = 1; i < argc ;) {
125 if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) {
126 rilLibPath = argv[i + 1];
127 i += 2;
128 } else if (0 == strcmp(argv[i], "--")) {
129 i++;
130 hasLibArgs = 1;
131 break;
132 } else {
133 usage(argv[0]);
134 }
135 }
136
137 if (rilLibPath == NULL) {
138 if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) {
139 // No lib sepcified on the command line, and nothing set in props.
140 // Assume "no-ril" case.
141 goto done;
142 } else {
143 rilLibPath = libPath;
144 }
145 }
146
147 /* special override when in the emulator */
148#if 1
149 {
150 static char* arg_overrides[3];
151 static char arg_device[32];
152 int done = 0;
153
154#define REFERENCE_RIL_PATH "/system/lib/libreference-ril.so"
155
156 /* first, read /proc/cmdline into memory */
157 char buffer[1024], *p, *q;
158 int len;
159 int fd = open("/proc/cmdline",O_RDONLY);
160
161 if (fd < 0) {
Wink Saville8eb2a122012-11-19 16:05:13 -0800162 RLOGD("could not open /proc/cmdline:%s", strerror(errno));
The Android Open Source Project00f06fc2009-03-03 19:32:15 -0800163 goto OpenLib;
164 }
165
166 do {
167 len = read(fd,buffer,sizeof(buffer)); }
168 while (len == -1 && errno == EINTR);
169
170 if (len < 0) {
Wink Saville8eb2a122012-11-19 16:05:13 -0800171 RLOGD("could not read /proc/cmdline:%s", strerror(errno));
The Android Open Source Project00f06fc2009-03-03 19:32:15 -0800172 close(fd);
173 goto OpenLib;
174 }
175 close(fd);
176
177 if (strstr(buffer, "android.qemud=") != NULL)
178 {
179 /* the qemud daemon is launched after rild, so
180 * give it some time to create its GSM socket
181 */
182 int tries = 5;
The Android Open Source Projecte6e6fb22009-03-18 17:39:47 -0700183#define QEMUD_SOCKET_NAME "qemud"
The Android Open Source Project00f06fc2009-03-03 19:32:15 -0800184
185 while (1) {
186 int fd;
187
188 sleep(1);
189
Vladimir Chtchetkine385a7392011-08-04 14:03:07 -0700190 fd = qemu_pipe_open("qemud:gsm");
191 if (fd < 0) {
192 fd = socket_local_client(
193 QEMUD_SOCKET_NAME,
194 ANDROID_SOCKET_NAMESPACE_RESERVED,
195 SOCK_STREAM );
196 }
The Android Open Source Project00f06fc2009-03-03 19:32:15 -0800197 if (fd >= 0) {
198 close(fd);
199 snprintf( arg_device, sizeof(arg_device), "%s/%s",
200 ANDROID_SOCKET_DIR, QEMUD_SOCKET_NAME );
201
202 arg_overrides[1] = "-s";
203 arg_overrides[2] = arg_device;
204 done = 1;
205 break;
206 }
Wink Saville8eb2a122012-11-19 16:05:13 -0800207 RLOGD("could not connect to %s socket: %s",
The Android Open Source Project00f06fc2009-03-03 19:32:15 -0800208 QEMUD_SOCKET_NAME, strerror(errno));
209 if (--tries == 0)
210 break;
211 }
212 if (!done) {
Wink Saville8eb2a122012-11-19 16:05:13 -0800213 RLOGE("could not connect to %s socket (giving up): %s",
The Android Open Source Project00f06fc2009-03-03 19:32:15 -0800214 QEMUD_SOCKET_NAME, strerror(errno));
215 while(1)
216 sleep(0x00ffffff);
217 }
218 }
219
220 /* otherwise, try to see if we passed a device name from the kernel */
221 if (!done) do {
222#define KERNEL_OPTION "android.ril="
223#define DEV_PREFIX "/dev/"
224
225 p = strstr( buffer, KERNEL_OPTION );
226 if (p == NULL)
227 break;
228
229 p += sizeof(KERNEL_OPTION)-1;
230 q = strpbrk( p, " \t\n\r" );
231 if (q != NULL)
232 *q = 0;
233
234 snprintf( arg_device, sizeof(arg_device), DEV_PREFIX "%s", p );
235 arg_device[sizeof(arg_device)-1] = 0;
236 arg_overrides[1] = "-d";
237 arg_overrides[2] = arg_device;
238 done = 1;
239
240 } while (0);
241
242 if (done) {
243 argv = arg_overrides;
244 argc = 3;
245 i = 1;
246 hasLibArgs = 1;
247 rilLibPath = REFERENCE_RIL_PATH;
248
Wink Saville8eb2a122012-11-19 16:05:13 -0800249 RLOGD("overriding with %s %s", arg_overrides[1], arg_overrides[2]);
The Android Open Source Project00f06fc2009-03-03 19:32:15 -0800250 }
251 }
252OpenLib:
253#endif
254 switchUser();
255
256 dlHandle = dlopen(rilLibPath, RTLD_NOW);
257
258 if (dlHandle == NULL) {
Wink Saville8eb2a122012-11-19 16:05:13 -0800259 RLOGE("dlopen failed: %s", dlerror());
Elliott Hughese2a70cf2013-11-20 13:51:45 -0800260 exit(EXIT_FAILURE);
The Android Open Source Project00f06fc2009-03-03 19:32:15 -0800261 }
262
263 RIL_startEventLoop();
264
265 rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");
266
267 if (rilInit == NULL) {
Wink Saville8eb2a122012-11-19 16:05:13 -0800268 RLOGE("RIL_Init not defined or exported in %s\n", rilLibPath);
Elliott Hughese2a70cf2013-11-20 13:51:45 -0800269 exit(EXIT_FAILURE);
The Android Open Source Project00f06fc2009-03-03 19:32:15 -0800270 }
271
272 if (hasLibArgs) {
273 rilArgv = argv + i - 1;
274 argc = argc -i + 1;
275 } else {
276 static char * newArgv[MAX_LIB_ARGS];
277 static char args[PROPERTY_VALUE_MAX];
278 rilArgv = newArgv;
279 property_get(LIB_ARGS_PROPERTY, args, "");
280 argc = make_argv(args, rilArgv);
281 }
282
283 // Make sure there's a reasonable argv[0]
284 rilArgv[0] = argv[0];
285
286 funcs = rilInit(&s_rilEnv, argc, rilArgv);
287
288 RIL_register(funcs);
289
290done:
291
Elliott Hughes164d2052013-11-20 14:53:08 -0800292 while (true) {
293 sleep(UINT32_MAX);
The Android Open Source Project00f06fc2009-03-03 19:32:15 -0800294 }
295}