mDnsForwarders = new NetAddressCollection();
mDaemonFd = -1;
mDaemonPid = 0;
+ mDhcpcdPid = 0;
}
TetherController::~TetherController() {
close(pipefd[0]);
}
- int num_processed_args = 5 + (num_addrs/2) + 1; // 1 null for termination
+ int num_processed_args = 7 + (num_addrs/2) + 1; // 1 null for termination
char **args = (char **)malloc(sizeof(char *) * num_processed_args);
args[num_processed_args - 1] = NULL;
args[0] = (char *)"/system/bin/dnsmasq";
- args[1] = (char *)"--no-daemon";
+ args[1] = (char *)"--keep-in-foreground";
args[2] = (char *)"--no-resolv";
args[3] = (char *)"--no-poll";
// TODO: pipe through metered status from ConnService
args[4] = (char *)"--dhcp-option-force=43,ANDROID_METERED";
+ args[5] = (char *)"--pid-file";
+ args[6] = (char *)"";
- int nextArg = 5;
+ int nextArg = 7;
for (int addrIndex=0; addrIndex < num_addrs;) {
char *start = strdup(inet_ntoa(addrs[addrIndex++]));
char *end = strdup(inet_ntoa(addrs[addrIndex++]));
ALOGE("execl failed (%s)", strerror(errno));
}
ALOGE("Should never get here!");
- free(args);
- return 0;
+ _exit(-1);
} else {
close(pipefd[0]);
mDaemonPid = pid;
mDaemonFd = pipefd[1];
+ applyDnsInterfaces();
ALOGD("Tethering services running");
}
return 0;
}
+// TODO(BT) remove
+int TetherController::startReverseTethering(const char* iface) {
+ if (mDhcpcdPid != 0) {
+ ALOGE("Reverse tethering already started");
+ errno = EBUSY;
+ return -1;
+ }
+
+ ALOGD("TetherController::startReverseTethering, Starting reverse tethering");
+
+ /*
+ * TODO: Create a monitoring thread to handle and restart
+ * the daemon if it exits prematurely
+ */
+ //cleanup the dhcp result
+ char dhcp_result_name[64];
+ snprintf(dhcp_result_name, sizeof(dhcp_result_name) - 1, "dhcp.%s.result", iface);
+ property_set(dhcp_result_name, "");
+
+ pid_t pid;
+ if ((pid = fork()) < 0) {
+ ALOGE("fork failed (%s)", strerror(errno));
+ return -1;
+ }
+
+ if (!pid) {
+
+ char *args[10];
+ int argc = 0;
+ args[argc++] = (char *)"/system/bin/dhcpcd";
+ char host_name[128];
+ if (property_get("net.hostname", host_name, NULL) && (host_name[0] != '\0'))
+ {
+ args[argc++] = (char *)"-h";
+ args[argc++] = host_name;
+ }
+ args[argc++] = (char*)iface;
+ args[argc] = NULL;
+ if (execv(args[0], args)) {
+ ALOGE("startReverseTethering, execv failed (%s)", strerror(errno));
+ }
+ ALOGE("startReverseTethering, Should never get here!");
+ // TODO(BT) inform parent of the failure.
+ // Parent process need wait for child to report error status
+ // before it set mDhcpcdPid and return 0.
+ _exit(-1);
+ } else {
+ mDhcpcdPid = pid;
+ ALOGD("Reverse Tethering running, pid:%d", pid);
+ }
+ return 0;
+}
+
+// TODO(BT) remove
+int TetherController::stopReverseTethering() {
+
+ if (mDhcpcdPid == 0) {
+ ALOGE("Tethering already stopped");
+ return 0;
+ }
+
+ ALOGD("Stopping tethering services");
+
+ kill(mDhcpcdPid, SIGTERM);
+ waitpid(mDhcpcdPid, NULL, 0);
+ mDhcpcdPid = 0;
+ ALOGD("Tethering services stopped");
+ return 0;
+}
bool TetherController::isTetheringStarted() {
return (mDaemonPid == 0 ? false : true);
}
return -1;
}
- cmdLen += strlen(servers[i]);
- if (cmdLen + 2 >= MAX_CMD_SIZE) {
+ cmdLen += (strlen(servers[i]) + 1);
+ if (cmdLen + 1 >= MAX_CMD_SIZE) {
ALOGD("Too many DNS servers listed");
break;
}
return mDnsForwarders;
}
+int TetherController::applyDnsInterfaces() {
+ int i;
+ char daemonCmd[MAX_CMD_SIZE];
+
+ strcpy(daemonCmd, "update_ifaces");
+ int cmdLen = strlen(daemonCmd);
+ InterfaceCollection::iterator it;
+ bool haveInterfaces = false;
+
+ for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
+ cmdLen += (strlen(*it) + 1);
+ if (cmdLen + 1 >= MAX_CMD_SIZE) {
+ ALOGD("Too many DNS ifaces listed");
+ break;
+ }
+
+ strcat(daemonCmd, ":");
+ strcat(daemonCmd, *it);
+ haveInterfaces = true;
+ }
+
+ if ((mDaemonFd != -1) && haveInterfaces) {
+ ALOGD("Sending update msg to dnsmasq [%s]", daemonCmd);
+ if (write(mDaemonFd, daemonCmd, strlen(daemonCmd) +1) < 0) {
+ ALOGE("Failed to send update command to dnsmasq (%s)", strerror(errno));
+ return -1;
+ }
+ }
+ return 0;
+}
+
int TetherController::tetherInterface(const char *interface) {
+ ALOGD("tetherInterface(%s)", interface);
mInterfaces->push_back(strdup(interface));
- return 0;
+
+ if (applyDnsInterfaces()) {
+ InterfaceCollection::iterator it;
+ for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
+ if (!strcmp(interface, *it)) {
+ free(*it);
+ mInterfaces->erase(it);
+ break;
+ }
+ }
+ return -1;
+ } else {
+ return 0;
+ }
}
int TetherController::untetherInterface(const char *interface) {
InterfaceCollection::iterator it;
+ ALOGD("untetherInterface(%s)", interface);
+
for (it = mInterfaces->begin(); it != mInterfaces->end(); ++it) {
if (!strcmp(interface, *it)) {
free(*it);
mInterfaces->erase(it);
- return 0;
+
+ return applyDnsInterfaces();
}
}
errno = ENOENT;