Пример #1
0
void SingleStreamReceiver_Init (SingleStreamReceiver *o, uint8_t *packet, int packet_len, StreamRecvInterface *input, BPendingGroup *pg, void *user, SingleStreamReceiver_handler handler)
{
    ASSERT(packet_len > 0)
    ASSERT(handler)
    
    // init arguments
    o->packet = packet;
    o->packet_len = packet_len;
    o->input = input;
    o->user = user;
    o->handler = handler;
    
    // set position zero
    o->pos = 0;
    
    // init output
    StreamRecvInterface_Receiver_Init(o->input, (StreamRecvInterface_handler_done)input_handler_done, o);
    
    // start receiving
    StreamRecvInterface_Receiver_Recv(o->input, o->packet + o->pos, o->packet_len - o->pos);
    
    DebugError_Init(&o->d_err, pg);
    DebugObject_Init(&o->d_obj);
}
Пример #2
0
int BProcess_Init2 (BProcess *o, BProcessManager *m, BProcess_handler handler, void *user, const char *file, char *const argv[], struct BProcess_params params)
{
    // init arguments
    o->m = m;
    o->handler = handler;
    o->user = user;
    
    // count fds
    size_t num_fds;
    for (num_fds = 0; params.fds[num_fds] >= 0; num_fds++);
    
    // block signals
    // needed to prevent parent's signal handlers from being called
    // in the child
    sigset_t sset_all;
    sigfillset(&sset_all);
    sigset_t sset_old;
    if (sigprocmask(SIG_SETMASK, &sset_all, &sset_old) < 0) {
        BLog(BLOG_ERROR, "sigprocmask failed");
        goto fail0;
    }
    
    // fork
    pid_t pid = fork();
    
    if (pid == 0) {
        // this is child
        
        // restore signal dispositions
        for (int i = 1; i < NSIG; i++) {
            struct sigaction sa;
            memset(&sa, 0, sizeof(sa));
            sa.sa_handler = SIG_DFL;
            sa.sa_flags = 0;
            sigaction(i, &sa, NULL);
        }
        
        // unblock signals
        sigset_t sset_none;
        sigemptyset(&sset_none);
        if (sigprocmask(SIG_SETMASK, &sset_none, NULL) < 0) {
            abort();
        }
        
        // copy fds array
        int *fds2 = malloc((num_fds + 1) * sizeof(fds2[0]));
        if (!fds2) {
            abort();
        }
        memcpy(fds2, params.fds, (num_fds + 1) * sizeof(fds2[0]));
        
        // find maximum file descriptors
        int max_fd = sysconf(_SC_OPEN_MAX);
        if (max_fd < 0) {
            abort();
        }
        
        // close file descriptors
        for (int i = 0; i < max_fd; i++) {
            // if it's one of the given fds, don't close it
            if (fds_contains(fds2, i, NULL)) {
                continue;
            }
            
            close(i);
        }
        
        const int *orig_fds_map = params.fds_map;
        
        // map fds to requested fd numbers
        while (*fds2 >= 0) {
            // resolve possible conflict
            size_t cpos;
            if (fds_contains(fds2 + 1, *params.fds_map, &cpos)) {
                // dup() the fd to a new number; the old one will be closed
                // in the following dup2()
                if ((fds2[1 + cpos] = dup(fds2[1 + cpos])) < 0) {
                    abort();
                }
            }
            
            if (*fds2 != *params.fds_map) {
                // dup fd
                if (dup2(*fds2, *params.fds_map) < 0) {
                    abort();
                }
                
                // close original fd
                close(*fds2);
            }
            
            fds2++;
            params.fds_map++;
        }
        
        // make sure standard streams are open
        open_standard_streams();
        
        // make session leader if requested
        if (params.do_setsid) {
            setsid();
        }
        
        // assume identity of username, if requested
        if (params.username) {
            long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
            if (bufsize < 0) {
                bufsize = 16384;
            }
            
            char *buf = malloc(bufsize);
            if (!buf) {
                abort();
            }
            
            struct passwd pwd;
            struct passwd *res;
            getpwnam_r(params.username, &pwd, buf, bufsize, &res);
            if (!res) {
                abort();
            }
            
            if (initgroups(params.username, pwd.pw_gid) < 0) {
                abort();
            }
            
            if (setgid(pwd.pw_gid) < 0) {
                abort();
            }
            
            if (setuid(pwd.pw_uid) < 0) {
                abort();
            }
        }
        
        execv(file, argv);
        
        abort();
    }
    
    // restore original signal mask
    ASSERT_FORCE(sigprocmask(SIG_SETMASK, &sset_old, NULL) == 0)
    
    if (pid < 0) {
        BLog(BLOG_ERROR, "fork failed");
        goto fail0;
    }
    
    // remember pid
    o->pid = pid;
    
    // add to processes list
    LinkedList2_Append(&o->m->processes, &o->list_node);
    
    DebugObject_Init(&o->d_obj);
    DebugError_Init(&o->d_err, BReactor_PendingGroup(m->reactor));
    
    return 1;
    
fail0:
    return 0;
}
Пример #3
0
int NCDUdevMonitor_Init (NCDUdevMonitor *o, BReactor *reactor, BProcessManager *manager, int mode, void *user,
                         NCDUdevMonitor_handler_event handler_event,
                         NCDUdevMonitor_handler_error handler_error)
{
    ASSERT(mode == NCDUDEVMONITOR_MODE_MONITOR_UDEV || mode == NCDUDEVMONITOR_MODE_INFO || mode == NCDUDEVMONITOR_MODE_MONITOR_KERNEL)
    
    // init arguments
    o->user = user;
    o->handler_event = handler_event;
    o->handler_error = handler_error;
    
    // find programs
    char *stdbuf_exec = badvpn_find_program("stdbuf");
    char *udevadm_exec = badvpn_find_program("udevadm");
    if (!stdbuf_exec) {
        BLog(BLOG_ERROR, "failed to find stdbuf program");
        goto fail0;
    }
    if (!udevadm_exec) {
        BLog(BLOG_ERROR, "failed to find udevadm program");
        goto fail0;
    }
    
    // construct arguments
    const char *argv_monitor_udev[] = {stdbuf_exec, "-o", "L", udevadm_exec, "monitor", "--udev", "--environment", NULL};
    const char *argv_monitor_kernel[] = {stdbuf_exec, "-o", "L", udevadm_exec, "monitor", "--kernel", "--environment", NULL};
    const char *argv_info[] = {stdbuf_exec, "-o", "L", udevadm_exec, "info", "--query", "all", "--export-db", NULL};
    
    // choose arguments based on mode
    const char **argv;
    switch (mode) {
        case NCDUDEVMONITOR_MODE_MONITOR_UDEV:   argv = argv_monitor_udev; break;
        case NCDUDEVMONITOR_MODE_INFO:           argv = argv_info; break;
        case NCDUDEVMONITOR_MODE_MONITOR_KERNEL: argv = argv_monitor_kernel; break;
        default: ASSERT(0);
    }
    
    // init process
    if (!BInputProcess_Init(&o->process, reactor, manager, o,
                            (BInputProcess_handler_terminated)process_handler_terminated,
                            (BInputProcess_handler_closed)process_handler_closed
    )) {
        BLog(BLOG_ERROR, "BInputProcess_Init failed");
        goto fail0;
    }
    
    // init connector
    StreamRecvConnector_Init(&o->connector, BReactor_PendingGroup(reactor));
    StreamRecvConnector_ConnectInput(&o->connector, BInputProcess_GetInput(&o->process));
    
    // init parser
    if (!NCDUdevMonitorParser_Init(&o->parser, StreamRecvConnector_GetOutput(&o->connector), PARSER_BUF_SIZE, PARSER_MAX_PROPERTIES,
                                   (mode == NCDUDEVMONITOR_MODE_INFO), BReactor_PendingGroup(reactor), o,
                                   (NCDUdevMonitorParser_handler)parser_handler
    )) {
        BLog(BLOG_ERROR, "NCDUdevMonitorParser_Init failed");
        goto fail1;
    }
    
    // start process
    if (!BInputProcess_Start(&o->process, stdbuf_exec, (char **)argv, NULL)) {
        BLog(BLOG_ERROR, "BInputProcess_Start failed");
        goto fail2;
    }
    
    // set process running, input running
    o->process_running = 1;
    o->input_running = 1;
    
    free(udevadm_exec);
    free(stdbuf_exec);
    
    DebugError_Init(&o->d_err, BReactor_PendingGroup(reactor));
    DebugObject_Init(&o->d_obj);
    return 1;
    
fail2:
    NCDUdevMonitorParser_Free(&o->parser);
fail1:
    StreamRecvConnector_Free(&o->connector);
    BInputProcess_Free(&o->process);
fail0:
    free(udevadm_exec);
    free(stdbuf_exec);
    return 0;
}
Пример #4
0
int BArpProbe_Init (BArpProbe *o, const char *ifname, uint32_t addr, BReactor *reactor, void *user, BArpProbe_handler handler)
{
    ASSERT(ifname)
    ASSERT(handler)
    
    // init arguments
    o->addr = addr;
    o->reactor = reactor;
    o->user = user;
    o->handler = handler;
    
    // get interface information
    int if_mtu;
    int if_index;
    if (!badvpn_get_iface_info(ifname, o->if_mac, &if_mtu, &if_index)) {
        BLog(BLOG_ERROR, "failed to get interface information");
        goto fail0;
    }
    
    uint8_t *if_mac = o->if_mac;
    BLog(BLOG_INFO, "if_mac=%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8" if_mtu=%d if_index=%d",
         if_mac[0], if_mac[1], if_mac[2], if_mac[3], if_mac[4], if_mac[5], if_mtu, if_index);
    
    // check MTU
    if (if_mtu < sizeof(struct arp_packet)) {
        BLog(BLOG_ERROR, "MTU is too small for ARP !?!");
        goto fail0;
    }
    
    // init dgram
    if (!BDatagram_Init(&o->dgram, BADDR_TYPE_PACKET, o->reactor, o, (BDatagram_handler)dgram_handler)) {
        BLog(BLOG_ERROR, "BDatagram_Init failed");
        goto fail0;
    }
    
    // bind dgram
    BAddr bind_addr;
    BAddr_InitPacket(&bind_addr, hton16(ETHERTYPE_ARP), if_index, BADDR_PACKET_HEADER_TYPE_ETHERNET, BADDR_PACKET_PACKET_TYPE_HOST, if_mac);
    if (!BDatagram_Bind(&o->dgram, bind_addr)) {
        BLog(BLOG_ERROR, "BDatagram_Bind failed");
        goto fail1;
    }
    
    // set dgram send addresses
    BAddr dest_addr;
    uint8_t broadcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
    BAddr_InitPacket(&dest_addr, hton16(ETHERTYPE_ARP), if_index, BADDR_PACKET_HEADER_TYPE_ETHERNET, BADDR_PACKET_PACKET_TYPE_BROADCAST, broadcast_mac);
    BIPAddr local_addr;
    BIPAddr_InitInvalid(&local_addr);
    BDatagram_SetSendAddrs(&o->dgram, dest_addr, local_addr);
    
    // init send interface
    BDatagram_SendAsync_Init(&o->dgram, sizeof(struct arp_packet));
    o->send_if = BDatagram_SendAsync_GetIf(&o->dgram);
    PacketPassInterface_Sender_Init(o->send_if, (PacketPassInterface_handler_done)send_if_handler_done, o);
    
    // set not sending
    o->send_sending = 0;
    
    // init recv interface
    BDatagram_RecvAsync_Init(&o->dgram, sizeof(struct arp_packet));
    o->recv_if = BDatagram_RecvAsync_GetIf(&o->dgram);
    PacketRecvInterface_Receiver_Init(o->recv_if, (PacketRecvInterface_handler_done)recv_if_handler_done, o);
    
    // init timer
    BTimer_Init(&o->timer, 0, (BTimer_handler)timer_handler, o);
    
    // receive first packet
    PacketRecvInterface_Receiver_Recv(o->recv_if, (uint8_t *)&o->recv_packet);
    
    // send request
    send_request(o);
    
    // set timer
    BReactor_SetTimerAfter(o->reactor, &o->timer, BARPPROBE_INITIAL_WAITRECV);
    
    // set zero missed
    o->num_missed = 0;
    
    // set state initial
    o->state = STATE_INITIAL;
    
    DebugError_Init(&o->d_err, BReactor_PendingGroup(o->reactor));
    DebugObject_Init(&o->d_obj);
    return 1;
    
fail1:
    BDatagram_Free(&o->dgram);
fail0:
    return 0;
}