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 "UidMarkMap.h" 38 39 static void coldboot(const char *path); 40 static void sigchld_handler(int sig); 41 static void blockSigpipe(); 42 43 int main() { 44 45 CommandListener *cl; 46 NetlinkManager *nm; 47 DnsProxyListener *dpl; 48 MDnsSdListener *mdnsl; 49 50 ALOGI("Netd 1.0 starting"); 51 52 // signal(SIGCHLD, sigchld_handler); 53 blockSigpipe(); 54 55 if (!(nm = NetlinkManager::Instance())) { 56 ALOGE("Unable to create NetlinkManager"); 57 exit(1); 58 }; 59 60 UidMarkMap *rangeMap = new UidMarkMap(); 61 62 cl = new CommandListener(rangeMap); 63 nm->setBroadcaster((SocketListener *) cl); 64 65 if (nm->start()) { 66 ALOGE("Unable to start NetlinkManager (%s)", strerror(errno)); 67 exit(1); 68 } 69 70 // Set local DNS mode, to prevent bionic from proxying 71 // back to this service, recursively. 72 setenv("ANDROID_DNS_MODE", "local", 1); 73 dpl = new DnsProxyListener(rangeMap); 74 if (dpl->startListener()) { 75 ALOGE("Unable to start DnsProxyListener (%s)", strerror(errno)); 76 exit(1); 77 } 78 79 mdnsl = new MDnsSdListener(); 80 if (mdnsl->startListener()) { 81 ALOGE("Unable to start MDnsSdListener (%s)", strerror(errno)); 82 exit(1); 83 } 84 /* 85 * Now that we're up, we can respond to commands 86 */ 87 if (cl->startListener()) { 88 ALOGE("Unable to start CommandListener (%s)", strerror(errno)); 89 exit(1); 90 } 91 92 // Eventually we'll become the monitoring thread 93 while(1) { 94 sleep(1000); 95 } 96 97 ALOGI("Netd exiting"); 98 exit(0); 99 } 100 101 static void do_coldboot(DIR *d, int lvl) 102 { 103 struct dirent *de; 104 int dfd, fd; 105 106 dfd = dirfd(d); 107 108 fd = openat(dfd, "uevent", O_WRONLY); 109 if(fd >= 0) { 110 write(fd, "add\n", 4); 111 close(fd); 112 } 113 114 while((de = readdir(d))) { 115 DIR *d2; 116 117 if (de->d_name[0] == '.') 118 continue; 119 120 if (de->d_type != DT_DIR && lvl > 0) 121 continue; 122 123 fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY); 124 if(fd < 0) 125 continue; 126 127 d2 = fdopendir(fd); 128 if(d2 == 0) 129 close(fd); 130 else { 131 do_coldboot(d2, lvl + 1); 132 closedir(d2); 133 } 134 } 135 } 136 137 static void coldboot(const char *path) 138 { 139 DIR *d = opendir(path); 140 if(d) { 141 do_coldboot(d, 0); 142 closedir(d); 143 } 144 } 145 146 static void sigchld_handler(int sig) { 147 pid_t pid = wait(NULL); 148 ALOGD("Child process %d exited", pid); 149 } 150 151 static void blockSigpipe() 152 { 153 sigset_t mask; 154 155 sigemptyset(&mask); 156 sigaddset(&mask, SIGPIPE); 157 if (sigprocmask(SIG_BLOCK, &mask, NULL) != 0) 158 ALOGW("WARNING: SIGPIPE not blocked\n"); 159 } 160