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