Home | History | Annotate | Download | only in netd
      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