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); }
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; }
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; }
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; }