1 /* 2 * Copyright (C) 2008 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 <stdio.h> 18 #include <stdlib.h> 19 #include <signal.h> 20 #include <errno.h> 21 #include <string.h> 22 #include <sys/stat.h> 23 #include <sys/types.h> 24 #include <sys/wait.h> 25 26 #include <fcntl.h> 27 #include <dirent.h> 28 29 #define LOG_TAG "Netd" 30 31 #include "cutils/log.h" 32 33 #include "CommandListener.h" 34 #include "NetlinkManager.h" 35 #include "DnsProxyListener.h" 36 #include "MDnsSdListener.h" 37 #include "FwmarkServer.h" 38 39 static void blockSigpipe(); 40 static void remove_pid_file(); 41 static bool write_pid_file(); 42 43 const char* const PID_FILE_PATH = "/data/misc/net/netd_pid"; 44 const int PID_FILE_FLAGS = O_CREAT | O_TRUNC | O_WRONLY | O_NOFOLLOW | O_CLOEXEC; 45 const mode_t PID_FILE_MODE = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // mode 0644, rw-r--r-- 46 47 int main() { 48 49 CommandListener *cl; 50 NetlinkManager *nm; 51 DnsProxyListener *dpl; 52 MDnsSdListener *mdnsl; 53 FwmarkServer* fwmarkServer; 54 55 ALOGI("Netd 1.0 starting"); 56 remove_pid_file(); 57 58 blockSigpipe(); 59 60 if (!(nm = NetlinkManager::Instance())) { 61 ALOGE("Unable to create NetlinkManager"); 62 exit(1); 63 }; 64 65 cl = new CommandListener(); 66 nm->setBroadcaster((SocketListener *) cl); 67 68 if (nm->start()) { 69 ALOGE("Unable to start NetlinkManager (%s)", strerror(errno)); 70 exit(1); 71 } 72 73 // Set local DNS mode, to prevent bionic from proxying 74 // back to this service, recursively. 75 setenv("ANDROID_DNS_MODE", "local", 1); 76 dpl = new DnsProxyListener(CommandListener::sNetCtrl); 77 if (dpl->startListener()) { 78 ALOGE("Unable to start DnsProxyListener (%s)", strerror(errno)); 79 exit(1); 80 } 81 82 mdnsl = new MDnsSdListener(); 83 if (mdnsl->startListener()) { 84 ALOGE("Unable to start MDnsSdListener (%s)", strerror(errno)); 85 exit(1); 86 } 87 88 fwmarkServer = new FwmarkServer(CommandListener::sNetCtrl); 89 if (fwmarkServer->startListener()) { 90 ALOGE("Unable to start FwmarkServer (%s)", strerror(errno)); 91 exit(1); 92 } 93 94 /* 95 * Now that we're up, we can respond to commands 96 */ 97 if (cl->startListener()) { 98 ALOGE("Unable to start CommandListener (%s)", strerror(errno)); 99 exit(1); 100 } 101 102 bool wrote_pid = write_pid_file(); 103 104 while(1) { 105 sleep(30); // 30 sec 106 if (!wrote_pid) { 107 wrote_pid = write_pid_file(); 108 } 109 } 110 111 ALOGI("Netd exiting"); 112 remove_pid_file(); 113 exit(0); 114 } 115 116 static bool write_pid_file() { 117 char pid_buf[20]; // current pid_max is 32768, so plenty of room 118 snprintf(pid_buf, sizeof(pid_buf), "%ld\n", (long)getpid()); 119 120 int fd = open(PID_FILE_PATH, PID_FILE_FLAGS, PID_FILE_MODE); 121 if (fd == -1) { 122 ALOGE("Unable to create pid file (%s)", strerror(errno)); 123 return false; 124 } 125 126 // File creation is affected by umask, so make sure the right mode bits are set. 127 if (fchmod(fd, PID_FILE_MODE) == -1) { 128 ALOGE("failed to set mode 0%o on %s (%s)", PID_FILE_MODE, PID_FILE_PATH, strerror(errno)); 129 close(fd); 130 remove_pid_file(); 131 return false; 132 } 133 134 if (write(fd, pid_buf, strlen(pid_buf)) != (ssize_t)strlen(pid_buf)) { 135 ALOGE("Unable to write to pid file (%s)", strerror(errno)); 136 close(fd); 137 remove_pid_file(); 138 return false; 139 } 140 close(fd); 141 return true; 142 } 143 144 static void remove_pid_file() { 145 unlink(PID_FILE_PATH); 146 } 147 148 static void blockSigpipe() 149 { 150 sigset_t mask; 151 152 sigemptyset(&mask); 153 sigaddset(&mask, SIGPIPE); 154 if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0) 155 ALOGW("WARNING: SIGPIPE not blocked\n"); 156 } 157