static pid_t fork_with_pipes(int pipefd_in[2], int pipefd_out[2]) { pid_t child_pid; if (pipe(pipefd_in) < 0) { messagef(HAKA_LOG_ERROR, MODULE_NAME, "%s", errno_error(errno)); return -1; } if (pipefd_out) { if (pipe(pipefd_out) < 0) { messagef(HAKA_LOG_ERROR, MODULE_NAME, "%s", errno_error(errno)); close(pipefd_in[0]); close(pipefd_in[1]); return -1; } } child_pid = fork(); if (child_pid < 0) { messagef(HAKA_LOG_ERROR, MODULE_NAME, "%s", errno_error(errno)); close(pipefd_in[0]); close(pipefd_in[1]); if (pipefd_out) { close(pipefd_out[0]); close(pipefd_out[1]); } return -1; } return child_pid; }
void id_trap(void) { short dir, row, col, d, t; messagef(0, "direction? "); while (!is_direction(dir = rgetchar(), &d)) { beep(); } check_message(); if (dir == CANCEL) { return; } row = rogue.row; col = rogue.col; get_dir_rc(d, &row, &col, 0); if ((dungeon[row][col] & TRAP) && (!(dungeon[row][col] & HIDDEN))) { t = trap_at(row, col); messagef(0, "%s", trap_strings[t*2]); } else { messagef(0, "no trap there"); } }
static int open_send_socket(bool mark) { int fd; int one = 1; fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (fd < 0) { messagef(HAKA_LOG_ERROR, MODULE_NAME, L"cannot open send socket: %s", errno_error(errno)); return -1; } if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)) < 0) { messagef(HAKA_LOG_ERROR, MODULE_NAME, L"cannot setup send socket: %s", errno_error(errno)); return -1; } if (mark) { one = 0xffff; if (setsockopt(fd, SOL_SOCKET, SO_MARK, &one, sizeof(one)) < 0) { messagef(HAKA_LOG_ERROR, MODULE_NAME, L"cannot setup send socket: %s", errno_error(errno)); return -1; } } return fd; }
void trap_player(short row, short col) { short t; if ((t = trap_at(row, col)) == NO_TRAP) { return; } dungeon[row][col] &= (~HIDDEN); if (rand_percent(rogue.exp + ring_exp)) { messagef(1, "the trap failed"); return; } switch(t) { case TRAP_DOOR: trap_door = 1; new_level_message = trap_strings[(t*2)+1]; break; case BEAR_TRAP: messagef(1, "%s", trap_strings[(t*2)+1]); bear_trap = get_rand(4, 7); break; case TELE_TRAP: mvaddch(rogue.row, rogue.col, '^'); tele(); break; case DART_TRAP: messagef(1, "%s", trap_strings[(t*2)+1]); rogue.hp_current -= get_damage("1d6", 1); if (rogue.hp_current <= 0) { rogue.hp_current = 0; } if ((!sustain_strength) && rand_percent(40) && (rogue.str_current >= 3)) { rogue.str_current--; } print_stats(STAT_HP | STAT_STRENGTH); if (rogue.hp_current <= 0) { killed_by((object *) 0, POISON_DART); } break; case SLEEPING_GAS_TRAP: messagef(1, "%s", trap_strings[(t*2)+1]); take_a_nap(); break; case RUST_TRAP: messagef(1, "%s", trap_strings[(t*2)+1]); rust((object *) 0); break; } }
void create_monster(void) { short row, col; short i; boolean found = 0; object *monster; row = rogue.row; col = rogue.col; for (i = 0; i < 9; i++) { rand_around(i, &row, &col); if (((row == rogue.row) && (col == rogue.col)) || (row < MIN_ROW) || (row > (DROWS-2)) || (col < 0) || (col > (DCOLS-1))) { continue; } if ((!(dungeon[row][col] & MONSTER)) && (dungeon[row][col] & (FLOOR|TUNNEL|STAIRS|DOOR))) { found = 1; break; } } if (found) { monster = gr_monster((object *)0, 0); put_m_at(row, col, monster); mvaddch(row, col, gmc(monster)); if (monster->m_flags & (WANDERS | WAKENS)) { wake_up(monster); } } else { messagef(0, "you hear a faint cry of anguish in the distance"); } }
static int packet_do_receive(struct packet_module_state *state, struct packet **pkt) { const int rv = recv(state->fd, state->receive_buffer, sizeof(state->receive_buffer), 0); if (rv < 0) { messagef(HAKA_LOG_ERROR, MODULE_NAME, L"packet reception failed, %s", errno_error(errno)); return 0; } if (nfq_handle_packet(state->handle, state->receive_buffer, rv) == 0) { if (state->current_packet) { state->current_packet->state = state; *pkt = (struct packet*)state->current_packet; if (pcap) { dump_pcap(&pcap->in, state->current_packet); } state->current_packet = NULL; return 0; } else { return state->error; } } else { message(HAKA_LOG_ERROR, MODULE_NAME, L"packet processing failed"); return 0; } }
static void report_error(struct luadebug_remote_user *user, int err) { if (!user->error) { messagef(HAKA_LOG_ERROR, MODULE, L"remote communication error: %s", errno_error(err)); user->error = true; } }
/* * try not to put in room NR */ void put_player(short nr) { short rn = nr, misses; short row, col; for (misses = 0; ((misses < 2) && (rn == nr)); misses++) { gr_row_col(&row, &col, (FLOOR | TUNNEL | OBJECT | STAIRS)); rn = get_room_number(row, col); } rogue.row = row; rogue.col = col; if (dungeon[rogue.row][rogue.col] & TUNNEL) { cur_room = PASSAGE; } else { cur_room = rn; } if (cur_room != PASSAGE) { light_up_room(cur_room); } else { light_passage(rogue.row, rogue.col); } rn = get_room_number(rogue.row, rogue.col); wake_room(rn, 1, rogue.row, rogue.col); if (new_level_message) { messagef(0, "%s", new_level_message); new_level_message = NULL; } mvaddch(rogue.row, rogue.col, rogue.fchar); }
int drop_check(void) { if (wizard) { return(1); } if (dungeon[rogue.row][rogue.col] & STAIRS) { if (levitate) { messagef(0, "you're floating in the air!"); return(0); } return(1); } messagef(0, "I see no way down"); return(0); }
void add_exp(int e, boolean promotion) { short new_exp; short i, hp; rogue.exp_points += e; if (rogue.exp_points >= level_points[rogue.exp-1]) { new_exp = get_exp_level(rogue.exp_points); if (rogue.exp_points > MAX_EXP) { rogue.exp_points = MAX_EXP + 1; } for (i = rogue.exp+1; i <= new_exp; i++) { messagef(0, "welcome to level %d", i); if (promotion) { hp = hp_raise(); rogue.hp_current += hp; rogue.hp_max += hp; } rogue.exp = i; print_stats(STAT_HP | STAT_EXP); } } else { print_stats(STAT_EXP); } }
void module_release(struct module *module) { if (atomic_dec(&module->ref) == 0) { /* Cleanup the module */ messagef(HAKA_LOG_INFO, L"core", L"unload module '%ls'", module->name); module->cleanup(); dlclose(module->handle); } }
static struct thread_state *init_thread_state(struct packet_module *packet_module, int thread_id, bool dissector_graph) { struct thread_state *state; assert(packet_module); state = malloc(sizeof(struct thread_state)); if (!state) { return NULL; } memset(state, 0, sizeof(struct thread_state)); state->thread_id = thread_id; state->packet_module = packet_module; state->state = STATE_NOTSARTED; state->engine = NULL; messagef(HAKA_LOG_INFO, "core", "initializing thread %d", thread_id); state->lua = lua_state_init(); if (!state->lua) { message(HAKA_LOG_FATAL, "core", "unable to create lua state"); cleanup_thread_state(state); return NULL; } /* Set grammar debugging */ lua_getglobal(state->lua->L, "haka"); lua_getfield(state->lua->L, -1, "grammar"); lua_pushboolean(state->lua->L, dissector_graph); lua_setfield(state->lua->L, -2, "debug"); /* Set state machine debugging */ lua_getglobal(state->lua->L, "haka"); lua_getfield(state->lua->L, -1, "state_machine"); lua_pushboolean(state->lua->L, dissector_graph); lua_setfield(state->lua->L, -2, "debug"); /* Load Lua sources */ lua_state_require(state->lua, "rule"); lua_state_require(state->lua, "rule_group"); lua_state_require(state->lua, "interactive"); lua_state_require(state->lua, "protocol/raw"); state->capture = packet_module->init_state(thread_id); if (!state->capture) { message(HAKA_LOG_FATAL, "core", "unable to create packet capture state"); cleanup_thread_state(state); return NULL; } return state; }
static int mkmount(register Cs_t* state, int mode, int uid, int gid, char* endserv, char* endhost, char* endtype) { *(state->control - 1) = 0; if (eaccess(state->mount, R_OK|W_OK|X_OK)) { if (errno != ENOENT) goto bad; if (!endserv && !(endserv = strrchr(state->mount, '/'))) goto bad; *endserv = 0; if (eaccess(state->mount, X_OK)) { if (!endhost && !(endhost = strrchr(state->mount, '/'))) goto bad; *endhost = 0; if (eaccess(state->mount, X_OK)) { if (!endtype && !(endtype = strrchr(state->mount, '/'))) goto bad; *endtype = 0; if (eaccess(state->mount, X_OK) && (mkdir(state->mount, S_IRWXU|S_IRWXG|S_IRWXO) || chmod(state->mount, S_IRWXU|S_IRWXG|S_IRWXO))) goto bad; *endtype = '/'; if (mkdir(state->mount, S_IRWXU|S_IRWXG|S_IRWXO) || chmod(state->mount, S_IRWXU|S_IRWXG|S_IRWXO)) goto bad; } *endhost = '/'; if (mkdir(state->mount, S_IRWXU|S_IRWXG|S_IRWXO) || chmod(state->mount, S_IRWXU|S_IRWXG|S_IRWXO)) goto bad; } *endserv = '/'; if (mkdir(state->mount, mode)) goto bad; if (mode != (S_IRWXU|S_IRWXG|S_IRWXO) && (uid >= 0 || gid >= 0 && (mode |= S_ISGID)) && (chown(state->mount, uid, gid) || chmod(state->mount, mode))) { rmdir(state->mount); goto bad; } } *(state->control - 1) = '/'; return 0; bad: if (endtype && !*endtype) *endtype = '/'; if (endhost && !*endhost) *endhost = '/'; if (endserv && !*endserv) *endserv = '/'; *(state->control - 1) = '/'; messagef((state->id, NiL, -1, "mkmount: %s: cannot access physical mount directory", state->mount)); return -1; }
void search(short n, boolean is_auto) { short s, i, j, row, col, t; short shown = 0, found = 0; static boolean reg_search; for (i = -1; i <= 1; i++) { for (j = -1; j <= 1; j++) { row = rogue.row + i; col = rogue.col + j; if ((row < MIN_ROW) || (row >= (DROWS-1)) || (col < 0) || (col >= DCOLS)) { continue; } if (dungeon[row][col] & HIDDEN) { found++; } } } for (s = 0; s < n; s++) { for (i = -1; i <= 1; i++) { for (j = -1; j <= 1; j++) { row = rogue.row + i; col = rogue.col + j ; if ((row < MIN_ROW) || (row >= (DROWS-1)) || (col < 0) || (col >= DCOLS)) { continue; } if (dungeon[row][col] & HIDDEN) { if (rand_percent(17 + (rogue.exp + ring_exp))) { dungeon[row][col] &= (~HIDDEN); if ((!blind) && ((row != rogue.row) || (col != rogue.col))) { mvaddch(row, col, get_dungeon_char(row, col)); } shown++; if (dungeon[row][col] & TRAP) { t = trap_at(row, col); messagef(1, "%s", trap_strings[t*2]); } } } if (((shown == found) && (found > 0)) || interrupted) { return; } } } if ((!is_auto) && (reg_search = !reg_search)) { (void) reg_move(); } } }
int check_up(void) { if (!wizard) { if (!(dungeon[rogue.row][rogue.col] & STAIRS)) { messagef(0, "I see no way up"); return(0); } if (!has_amulet()) { messagef(0, "your way is magically blocked"); return(0); } } new_level_message = "you feel a wrenching sensation in your gut"; if (cur_level == 1) { win(); } else { cur_level -= 2; return(1); } return(0); }
int csping(register Cs_t* state, const char* name) { register int fd; register int n; sfsprintf(state->temp, sizeof(state->path), "/dev/tcp/%s/inet.echo", name); if ((fd = csopen(state, state->temp, 0)) < 0) return -1; n = (cswrite(state, fd, M, N) != N || csread(state, fd, state->temp, N, CS_LINE) != N || strncmp(M, state->temp, N)) ? -1 : 0; close(fd); if (n) messagef((state->id, NiL, -1, "ping: %s: no contact", name)); return n; }
static int run_console(int fd, int argc, char *argv[]) { struct lua_state *state; struct luadebug_user *user; state = lua_state_init(); if (!state) { messagef(HAKA_LOG_FATAL, "hakactl", clear_error()); return COMMAND_FAILED; } console_fd = fd; lua_pushcfunction(state->L, luaopen_hakactl); lua_call(state->L, 0, 1); lua_setglobal(state->L, "hakactl"); if (!initialize_console(state)) { messagef(HAKA_LOG_FATAL, "hakactl", clear_error()); lua_state_close(state); return COMMAND_FAILED; } user = luadebug_user_readline(); if (!user) { messagef(HAKA_LOG_FATAL, "hakactl", clear_error()); lua_state_close(state); return COMMAND_FAILED; } /* Load Lua console utilities */ luadebug_interactive_enter(state->L, "> ", ">> ", NULL, -1, user); luadebug_user_release(&user); lua_state_close(state); return COMMAND_SUCCESS; }
void show_average_hp(void) { float real_average; float effective_average; if (rogue.exp == 1) { real_average = effective_average = 0.00; } else { real_average = (float) ((rogue.hp_max - extra_hp - INIT_HP) + less_hp) / (rogue.exp - 1); effective_average = (float)(rogue.hp_max - INIT_HP) / (rogue.exp - 1); } messagef(0, "R-Hp: %.2f, E-Hp: %.2f (!: %d, V: %d)", real_average, effective_average, extra_hp, less_hp); }
void aggravate(void) { object *monster; messagef(0, "you hear a high pitched humming noise"); monster = level_monsters.next_monster; while (monster) { wake_up(monster); monster->m_flags &= (~IMITATES); if (rogue_can_see(monster->row, monster->col)) { mvaddch(monster->row, monster->col, monster->m_char); } monster = monster->next_monster; } }
static int initiate(Cs_t* state, const char* svc, char* cmd) { pid_t pid; pid_t n; char* av[3]; #ifdef SIGCHLD Handler_t fun; children = 0; if ((fun = signal(SIGCHLD, child)) == SIG_DFL) signal(SIGCHLD, fun); else if (children) children++; #endif pathcanon(cmd, 0, 0); av[0] = cmd; av[1] = (char*)svc; av[2] = 0; if ((pid = spawnveg(av[0], av, environ, 0)) == -1) { messagef((state->id, NiL, -1, "local: %s: cannot initiate %s", svc, cmd)); return -1; } while ((n = waitpid(pid, NiL, 0)) == -1 && errno == EINTR); #ifdef SIGCHLD if (fun != SIG_DFL) { signal(SIGCHLD, fun); if (fun != SIG_IGN) while (--children > 0) (*fun)(SIGCHLD); } #endif /* * yuk: looks like we have to give fdp services time * to start up -- a few seconds shouldn't hurt */ sleep(2); return n; }
void luadebug_user_remote_server(int fd, struct luadebug_user *user) { char command; while ((read(fd, &command, 1) == 1)) { switch (command) { case 's': { char *line = read_string(fd); if (!line) { messagef(HAKA_LOG_ERROR, MODULE, L"remote communication error: %s", errno_error(errno)); return; } user->start(user, line); free(line); if (!luadebug_user_remote_server_session(fd, user)) { message(HAKA_LOG_ERROR, MODULE, L"remote communication error"); return; } break; } case 'P': { break; } default: message(HAKA_LOG_ERROR, MODULE, L"remote communication error"); return; } } luadebug_user_release(&user); }
int save_iptables(const char *table, char **conf, bool all_targets) { int pipefd_out[2]; int pipefd_err[2]; pid_t child_pid; int error = 0; assert(conf); child_pid = fork_with_pipes(pipefd_out, pipefd_err); if (child_pid < 0) { return error; } if (child_pid == 0) { /* child */ close(pipefd_out[0]); close(pipefd_err[0]); if (dup2(pipefd_out[1], STDOUT_FILENO) == -1 || dup2(pipefd_err[1], STDERR_FILENO) == -1) { fprintf(stderr, "%s\n", strerror(errno)); exit(1); } close(pipefd_out[1]); close(pipefd_err[1]); execl(IPTABLES_SAVE, "iptables-save", "-t", table, NULL); /* an error occured */ fprintf(stderr, "%s\n", strerror(errno)); exit(1); } else { /* parent */ int status; pid_t ret; char *buffer = NULL; size_t buffer_size = 0, read_size = 0; ssize_t line_size; FILE *input = fdopen(pipefd_out[0], "r"); FILE *err = fdopen(pipefd_err[0], "r"); bool filtering = false; bool pre_found = false, out_found = false; fd_set fds, curfds; int max_fd, fd_count; if (!input || !err) { messagef(HAKA_LOG_ERROR, MODULE_NAME, "iptables-save: %s", errno_error(errno)); fclose(input); fclose(err); return errno; } close(pipefd_out[1]); close(pipefd_err[1]); pipefd_out[1] = fileno(input); pipefd_err[1] = fileno(err); FD_ZERO(&fds); FD_SET(pipefd_out[1], &fds); FD_SET(pipefd_err[1], &fds); max_fd = pipefd_out[1] > pipefd_err[1] ? pipefd_out[1] : pipefd_err[1]; fd_count = 2; while (fd_count > 0) { int rc; curfds = fds; rc = select(max_fd+1, &curfds, NULL, NULL, NULL); if (rc < 0) { messagef(HAKA_LOG_ERROR, MODULE_NAME, "iptables-save: %s", errno_error(errno)); free(buffer); fclose(input); fclose(err); return errno; } if (FD_ISSET(pipefd_err[1], &curfds)) { line_size = getline(&buffer, &buffer_size, err); if (line_size > 1) { buffer[line_size-1] = '\0'; messagef(HAKA_LOG_INFO, MODULE_NAME, "iptables-save: %s", buffer); } else { FD_CLR(pipefd_err[1], &fds); --fd_count; } } if (FD_ISSET(pipefd_out[1], &curfds)) { line_size = getline(&buffer, &buffer_size, input); if (line_size > 0) { if (filtering) { if (strcmp(buffer, "COMMIT\n") != 0) { /* * If all_targets is true, we only want to include the rule in the * targets HAKA_TARGET_PRE and HAKA_TARGET_OUT. So we need to filter * each line to only include those but being careful not to add the * line from another target that jump to one of the haka target * (ie. -A PREROUTING -j haka-pre) */ char *pattern, *current = buffer; bool skip = true; while (true) { if ((pattern = strstr(current, "-j " HAKA_TARGET))) { pattern += 3; /* Skip '-j ' */ if (check_haka_target(pattern, HAKA_TARGET_PRE) || check_haka_target(pattern, HAKA_TARGET_OUT)) { skip = true; break; } /* * Advance one more to avoid the next test case to match * (ie. pattern = strstr(current, HAKA_TARGET)) */ current = pattern+1; } else if ((pattern = strstr(current, HAKA_TARGET))) { if (check_haka_target(pattern, HAKA_TARGET_PRE)) { skip = false; pre_found = true; break; } else if (check_haka_target(pattern, HAKA_TARGET_OUT)) { skip = false; out_found = true; break; } current = pattern+1; } else { skip = true; break; } } if (!all_targets && skip) { continue; } } else { /* * The target HAKA_TARGET_PRE or HAKA_TARGET_OUT do not * exist. * In this case, iptables-restore will be unable to remove them. * As a workaround, we just install new empty targets to cleanup * Haka rules. This case only appears when the user sets the option * enable_iptables=no which is not the default. */ if (!pre_found) { if (!append_string(conf, &read_size, iptables_empty_haka_pre_target, -1)) { free(buffer); fclose(input); fclose(err); return ENOMEM; } } if (!out_found) { if (!append_string(conf, &read_size, iptables_empty_haka_out_target, -1)) { free(buffer); fclose(input); fclose(err); return ENOMEM; } } /* COMMIT and the text after it should not be skipped */ filtering = false; } } if (buffer[0] == '*') { filtering = true; } if (!append_string(conf, &read_size, buffer, line_size)) { free(buffer); fclose(input); fclose(err); return ENOMEM; } } else { FD_CLR(pipefd_out[1], &fds); --fd_count; } } } free(buffer); fclose(input); fclose(err); if (error) { free(*conf); *conf = NULL; return error; } /* Wait for the child to finish */ do { ret = waitpid(child_pid, &status, 0); if (ret == -1) { free(*conf); *conf = NULL; return errno; } } while (!WIFEXITED(status) && !WIFSIGNALED(status)); if (WEXITSTATUS(status) != 0) { free(*conf); *conf = NULL; return 1; } return 0; } }
gboolean osm_download(GtkWidget *parent, settings_t *settings, project_t *project) { printf("download osm ...\n"); g_assert(project->server); /* check if server name contains string "0.5" and adjust it */ if(project->server == project->rserver) { if(strstr(project->rserver, "0.5") != NULL) { strstr(project->rserver, "0.5")[2] = '6'; messagef(parent, _("Server changed"), _("It seems your current project uses a server/protocol no " "longer in use by OSM. It has thus been changed to:\n\n%s"), project->server); } /* server url should not end with a slash */ if(project->rserver[strlen(project->rserver)-1] == '/') { printf("removing trailing slash\n"); project->rserver[strlen(project->rserver)-1] = 0; } if(strcmp(project->rserver, settings->server) == 0) { g_free(project->rserver); project->rserver = NULL; project->server = settings->server; } } char minlon[G_ASCII_DTOSTR_BUF_SIZE], minlat[G_ASCII_DTOSTR_BUF_SIZE]; char maxlon[G_ASCII_DTOSTR_BUF_SIZE], maxlat[G_ASCII_DTOSTR_BUF_SIZE]; g_ascii_formatd(minlon, sizeof(minlon), LL_FORMAT, project->min.lon); g_ascii_formatd(minlat, sizeof(minlat), LL_FORMAT, project->min.lat); g_ascii_formatd(maxlon, sizeof(maxlon), LL_FORMAT, project->max.lon); g_ascii_formatd(maxlat, sizeof(maxlat), LL_FORMAT, project->max.lat); gchar *url = g_strconcat(project->server, "/map?bbox=", minlon, ",", minlat, ",", maxlon, ",", maxlat, NULL); /* Download the new file to a new name. If something goes wrong then the * old file will still be in place to be opened. */ gchar *update = g_strconcat(project->path, "update.osm", NULL); g_remove(update); gboolean result = net_io_download_file(parent, settings, url, update, project->name); g_free(url); /* if there's a new file use this from now on */ if(result && g_file_test(update, G_FILE_TEST_IS_REGULAR)) { printf("download ok, replacing previous file\n"); if(project->osm[0] == '/') { g_rename(update, project->osm); } else { gchar *fname = g_strconcat(project->path, project->osm, NULL); g_rename(update, fname); g_free(fname); } result = TRUE; } g_free(update); return result; }
bool initialize_console(struct lua_state *state) { const char *haka_path_s = haka_path(); char *console_path; size_t size; DIR *dir; struct dirent entry, *result = NULL; /* Load all console utilities */ lua_newtable(state->L); lua_setglobal(state->L, "console"); lua_getglobal(state->L, "console"); /* <haka_path_s><HAKA_CONSOLE/\0 */ size = strlen(haka_path_s) + strlen(HAKA_CONSOLE) + 1; console_path = malloc(size); if (!console_path) { error("memory error"); return false; } snprintf(console_path, size, "%s%s", haka_path_s, HAKA_CONSOLE); dir = opendir(console_path); if (!dir) { error("cannot open console script folder: %s", console_path); return false; } else { while (!readdir_r(dir, &entry, &result) && result) { const size_t len = strlen(entry.d_name); char fullfilename[PATH_MAX]; const int level = lua_gettop(state->L); snprintf(fullfilename, sizeof(fullfilename), "%s/%s", console_path, entry.d_name); if (len > 4 && strcmp(entry.d_name + (len - 4), ".lua") == 0) { entry.d_name[len - 4] = 0; } else if (len > 3 && strcmp(entry.d_name + (len - 3), ".bc") == 0) { entry.d_name[len - 3] = 0; } else { continue; } messagef(HAKA_LOG_DEBUG, "hakactl", "loading console script '%s'", entry.d_name); if (luaL_dofile(state->L, fullfilename)) { const char *msg = lua_tostring(state->L, -1); messagef(HAKA_LOG_ERROR, "hakactl", "cannot open console script '%s': %s", entry.d_name, msg); lua_pop(state->L, 1); } else { const int res = lua_gettop(state->L) - level; if (res == 1) { lua_setfield(state->L, -2, entry.d_name); } else { lua_pop(state->L, res); } } } } return true; }
static bool luadebug_user_remote_server_session(int fd, struct luadebug_user *user) { char command; server_completion_fd = fd; user->completion = remote_completion; while ((read(fd, &command, 1) == 1)) { switch (command) { case 'e': { user->stop(user); return true; } case 'p': { char *line = read_string(fd); if (!line) { messagef(HAKA_LOG_ERROR, MODULE, L"remote communication error: %s", errno_error(errno)); return false; } user->print(user, line); free(line); break; } case 'h': { char *line = read_string(fd); if (!line) { messagef(HAKA_LOG_ERROR, MODULE, L"remote communication error: %s", errno_error(errno)); return false; } user->addhistory(user, line); free(line); break; } case 'r': { char *line = read_string(fd); if (!line) { messagef(HAKA_LOG_ERROR, MODULE, L"remote communication error: %s", errno_error(errno)); return false; } char *rdline = user->readline(user, line); if (!rdline) { messagef(HAKA_LOG_ERROR, MODULE, L"remote communication error: %s", errno_error(errno)); free(line); return false; } free(line); command = '1'; write(fd, &command, 1); write_string(fd, rdline); free(rdline); break; } case 'P': { break; } default: messagef(HAKA_LOG_ERROR, MODULE, L"remote communication error: %s", errno_error(errno)); return false; } } return false; }
int cslocal(register Cs_t* state, const char* path) { register char* s; register char* p; register char* t; register char* v; struct stat st; char cmd[PATH_MAX / 8]; char exe[PATH_MAX + 1]; char tmp[PATH_MAX + 1]; #if CS_LIB_STREAM || CS_LIB_V10 || CS_LIB_SOCKET_UN int fd; int n; #endif messagef((state->id, NiL, -8, "local(%s) call", path)); /* * validate the path */ p = (char*)path; if (strncmp(p, DEVLOCAL, sizeof(DEVLOCAL) - 1)) { messagef((state->id, NiL, -1, "local: %s: %s* expected", path, DEVLOCAL)); goto sorry; } p += sizeof(DEVLOCAL) - 1; for (t = p; *t && *t != '/'; t++); if (!streq(t + 1, "user")) { messagef((state->id, NiL, -1, "local: %s: %s*/user expected", path, DEVLOCAL)); goto sorry; } /* * locate the service */ s = cmd; for (v = p; p <= t; *s++ = *p++); t = s - 1; for (p = v; p <= t; *s++ = *p++); for (p = CS_SVC_SUFFIX; *s++ = *p++;); p = pathbin(); for (;;) { p = pathcat(p, ':', "../lib/cs/fdp", cmd, exe, PATH_MAX + 1); if (!eaccess(exe, X_OK) && !stat(exe, &st)) break; if (!p) { messagef((state->id, NiL, -1, "local: %s: %s: cannot locate service on ../lib/cs/fdp", path, cmd)); goto sorry; } } *t = 0; sfsprintf(tmp, sizeof(tmp), "%s/fdp/%s/%s/%d-%d-/%c%s", csvar(state, CS_VAR_LOCAL, 0), csname(state, 0), cmd, st.st_uid, geteuid(), CS_MNT_STREAM, CS_MNT_TAIL); #if CS_LIB_STREAM || CS_LIB_V10 for (n = 0; (fd = open(tmp, O_RDWR)) < 0; n++) if (n || errno == EACCES) { messagef((state->id, NiL, -1, "local: %s: %s: cannot open service", path, tmp)); return -1; } else if (initiate(state, path, exe) < 0) { messagef((state->id, NiL, -1, "local: %s: %s: cannot initiate service %s", path, tmp, exe)); return -1; } messagef((state->id, NiL, -8, "local(%s) fd=%d server=%s stream=%s", path, fd, exe, tmp)); return fd; #else #if CS_LIB_SOCKET_UN { int namlen; struct sockaddr_un nam; nam.sun_family = AF_UNIX; strcpy(nam.sun_path, tmp); namlen = sizeof(nam.sun_family) + strlen(tmp); n = 0; fd = -1; for (;;) { if (fd < 0 && (fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { messagef((state->id, NiL, -1, "local: %s: AF_UNIX socket error", path)); return -1; } if (!connect(fd, (struct sockaddr*)&nam, namlen)) { #if CS_LIB_SOCKET_RIGHTS if (read(fd, cmd, 1) != 1) messagef((state->id, NiL, -1, "local: %s: connect ack read error", path)); else if (cssend(state, fd, NiL, 0)) messagef((state->id, NiL, -1, "local: %s: connect authentication send error", path)); else #endif return fd; #if CS_LIB_SOCKET_RIGHTS close(fd); fd = -1; #endif } else messagef((state->id, NiL, -1, "local: %s: connect error", path)); if (errno != EACCES) errno = ENOENT; if (n || errno == EACCES || initiate(state, path, exe) < 0) { if (fd >= 0) close(fd); return -1; } n = 1; messagef((state->id, NiL, -1, "local: %s: connect retry", path)); } } #endif #endif sorry: errno = ENOENT; return -1; }
static int init(struct parameters *args) { char *new_iptables_config = NULL; char *interfaces_buf = NULL; char **ifaces = NULL; int thread_count = thread_get_packet_capture_cpu_count(); const char *file_in = NULL; const char *file_out = NULL; const char *file_drop = NULL; int count; bool dump = false; /* Setup iptables rules */ if (save_iptables("raw", &iptables_saved)) { message(HAKA_LOG_ERROR, MODULE_NAME, L"cannot save iptables rules"); cleanup(); return 1; } { const char *iter; const char *interfaces = parameters_get_string(args, "interfaces", NULL); if (!interfaces) { message(HAKA_LOG_ERROR, MODULE_NAME, L"no interfaces selected"); cleanup(); return 1; } for (count = 0, iter = interfaces; *iter; ++iter) { if (*iter == ',') ++count; } interfaces_buf = strdup(interfaces); if (!interfaces_buf) { error(L"memory error"); cleanup(); return 1; } ++count; } ifaces = malloc((sizeof(char *) * (count + 1))); if (!ifaces) { message(HAKA_LOG_ERROR, MODULE_NAME, L"memory error"); free(interfaces_buf); cleanup(); return 1; } messagef(HAKA_LOG_INFO, MODULE_NAME, L"installing iptables rules for device(s) %s", interfaces_buf); { int index = 0; char *str, *ptr = NULL; for (index = 0, str = interfaces_buf; index < count; index++, str = NULL) { char *token = strtok_r(str, ",", &ptr); assert(token != NULL); ifaces[index] = token; } ifaces[index] = NULL; } new_iptables_config = iptables_config(ifaces, thread_count); if (!new_iptables_config) { message(HAKA_LOG_ERROR, MODULE_NAME, L"cannot generate iptables rules"); free(ifaces); free(interfaces_buf); cleanup(); return 1; } free(ifaces); ifaces = NULL; free(interfaces_buf); interfaces_buf = NULL; if (apply_iptables(new_iptables_config)) { message(HAKA_LOG_ERROR, MODULE_NAME, L"cannot setup iptables rules"); free(new_iptables_config); cleanup(); return 1; } free(new_iptables_config); /* Setup pcap dump */ dump = parameters_get_boolean(args, "dump", false); if (dump) { file_in = parameters_get_string(args, "dump_input", NULL); file_out = parameters_get_string(args, "dump_output", NULL); file_drop = parameters_get_string(args, "dump_drop", NULL); if (!(file_in || file_out || file_drop)) { message(HAKA_LOG_WARNING, MODULE_NAME, L"no dump pcap files specified"); } else { pcap = malloc(sizeof(struct pcap_sinks)); if (!pcap) { message(HAKA_LOG_ERROR, MODULE_NAME, L"memory error"); cleanup(); return 1; } memset(pcap, 0, sizeof(struct pcap_sinks)); if (file_in) { open_pcap(&pcap->in, file_in); messagef(HAKA_LOG_INFO, MODULE_NAME, L"dumping received packets into '%s'", file_in); } if (file_out) { open_pcap(&pcap->out, file_out); messagef(HAKA_LOG_INFO, MODULE_NAME, L"dumping emitted packets into '%s'", file_out); } if (file_drop) { open_pcap(&pcap->drop, file_drop); messagef(HAKA_LOG_INFO, MODULE_NAME, L"dumping dropped packets into '%s'", file_drop); } } } return 0; }
int csopen(register Cs_t* state, const char* apath, int op) { register char* path = (char*)apath; register char* b; register char* s; register int n; int fd; char* t; char* u; char* type; char* endtype; char* host; char* endhost; char* serv; char* endserv; char* qual; char* endqual; char* opath; char* user = 0; char* group = 0; char* trust = 0; char* arg = 0; int nfd = -1; int uid = -1; int gid = -1; int sid = -1; int auth = 1; int mode; unsigned long addr; unsigned long port = 0; struct stat st; char buf[PATH_MAX]; char tmp[PATH_MAX]; if (!path) { errno = EFAULT; return -1; } csprotect(&cs); if (op < 0) op = CS_OPEN_TEST; messagef((state->id, NiL, -8, "open(%s,%o) call", path, op)); /* * blast out the parts */ opath = path; if (pathgetlink(path, buf, sizeof(buf)) <= 0) { if (strlen(path) >= sizeof(buf)) return -1; strcpy(buf, path); } else if ((state->flags & CS_ADDR_LOCAL) && (s = strrchr(buf, '/'))) { /* * dynamic ip assignment can change the addr * underfoot in some implementations so we * double check the local ip here */ strcpy(tmp, buf); if (tokscan(tmp, NiL, "/dev/%s/%s/%s", &type, NiL, &serv) == 3) sfsprintf(buf, sizeof(buf), "/dev/%s/%s/%s", type, csntoa(state, 0), serv); } path = buf; pathcanon(path, 0, 0); errno = ENOENT; strcpy(state->path, path); b = path; if ((*b++ != '/') || !(s = strchr(b, '/'))) return -1; *s++ = 0; if (!streq(b, "dev")) return -1; if (b = strchr(s, '/')) *b++ = 0; if (streq(s, "fdp")) { #if !( CS_LIB_SOCKET_UN || CS_LIB_STREAM || CS_LIB_V10 ) if (access(CS_PROC_FD_TST, F_OK)) { errno = ENODEV; messagef((state->id, NiL, -1, "open: %s: %s: not supported", state->path, s)); return -1; } #endif } else if (!streq(s, "tcp") && !streq(s, "udp")) { messagef((state->id, NiL, -1, "open: %s: %s: invalid type", state->path, s)); return -1; } #if !( CS_LIB_SOCKET || CS_LIB_STREAM || CS_LIB_V10 ) else { errno = ENODEV; messagef((state->id, NiL, -1, "open: %s: %s: not supported", state->path, s)); return -1; } #endif type = s; qual = state->qual; if (!b) host = serv = 0; else { host = b; if (!(s = strchr(b, '/'))) serv = 0; else { *s++ = 0; serv = s; /* * grab the next fd to preserve open semantics */ for (n = 0; n < 10; n++) if ((nfd = dup(n)) >= 0) break; /* * get qual, perm and arg */ mode = S_IRWXU|S_IRWXG|S_IRWXO; if (b = strchr(s, '/')) { *b++ = 0; do { if (*b == '#') { arg = b + 1; break; } if (u = strchr(b, '/')) *u++ = 0; if (s = strchr(b, '=')) *s++ = 0; for (n = 0, t = b; *t; n = HASHKEYPART(n, *t++)); switch (n) { case HASHKEY5('g','r','o','u','p'): group = s ? s : ""; break; case HASHKEY5('l','o','c','a','l'): op |= CS_OPEN_LOCAL; break; case HASHKEY3('n','o','w'): op |= CS_OPEN_NOW; break; case HASHKEY5('o','t','h','e','r'): auth = 0; break; case HASHKEY6('r','e','m','o','t','e'): op |= CS_OPEN_REMOTE; break; case HASHKEY5('s','h','a','r','e'): op |= CS_OPEN_SHARE; break; case HASHKEY5('s','l','a','v','e'): op |= CS_OPEN_SLAVE; break; case HASHKEY4('t','e','s','t'): op |= CS_OPEN_TEST; break; case HASHKEY5('t','r','u','s','t'): op |= CS_OPEN_TRUST; trust = s; break; case HASHKEY4('u','s','e','r'): user = s ? s : ""; break; default: qual += sfsprintf(qual, sizeof(state->qual) - (qual - state->qual) - 1, "%s%s", qual == state->qual ? "" : "-", b); if (s) *(s - 1) = '='; break; } } while (b = u); } } } if (*type != 't') auth = 0; strncpy(state->type, type, sizeof(state->type) - 1); qual = (qual == state->qual) ? (char*)0 : state->qual; messagef((state->id, NiL, -8, "open: type=%s host=%s serv=%s qual=%s", type, host, serv, qual)); if (host) { /* * validate host */ if (!(state->addr = addr = csaddr(state, host))) { if (serv && !(op & CS_OPEN_CREATE) && *type == 't' && (port = csport(state, type, serv)) >= CS_PORT_MIN && port <= CS_PORT_MAX) { /* * attempt proxy connection */ if (nfd >= 0) { close(nfd); nfd = -1; } if ((fd = state->proxy.addr ? csbind(state, type, state->proxy.addr, state->proxy.port, 0L) : reopen(state, csvar(state, CS_VAR_PROXY, 0))) >= 0) { state->proxy.addr = state->addr; state->proxy.port = state->port; n = sfsprintf(tmp, sizeof(tmp), "\n%s!%s!%d\n\n%s\n%s\n0\n-1\n-1\n", type, host, port, csname(state, 0), error_info.id ? error_info.id : state->id); if (cswrite(state, fd, tmp, n) == n && (n = csread(state, fd, tmp, sizeof(tmp), CS_LINE)) >= 2) { if (tmp[0] == '0' && tmp[1] == '\n') return fd; if (error_info.trace <= -4 && n > 2) { s = tmp; s[n - 1] = 0; while (*s && *s++ != '\n'); messagef((state->id, NiL, -4, "%s error message `%s'", csvar(state, CS_VAR_PROXY, 0), s)); } } close(fd); } } #ifdef EADDRNOTAVAIL errno = EADDRNOTAVAIL; #else errno = ENOENT; #endif goto bad; } if (op & CS_OPEN_LOCAL) { state->flags |= CS_ADDR_LOCAL; state->flags &= ~CS_ADDR_REMOTE; } if (op & CS_OPEN_NOW) state->flags |= CS_ADDR_NOW; if ((op & (CS_OPEN_AGENT|CS_OPEN_REMOTE)) == CS_OPEN_REMOTE) { state->flags |= CS_ADDR_REMOTE; state->flags &= ~CS_ADDR_LOCAL; } if (op & CS_OPEN_SHARE) state->flags |= CS_ADDR_SHARE; if (op & CS_OPEN_SLAVE) state->flags |= CS_DAEMON_SLAVE; if (op & CS_OPEN_TEST) state->flags |= CS_ADDR_TEST; if (op & CS_OPEN_TRUST) state->flags |= CS_ADDR_TRUST; if ((state->flags & CS_ADDR_REMOTE) && (!serv || !strneq(serv, CS_SVC_INET, sizeof(CS_SVC_INET) - 1) && (strtol(serv, &t, 0), *t))) return agent(state, state->host, state->user, state->path); if (s = user) { n = geteuid(); if (*s) { if ((uid = struid(s)) < 0) { uid = strtol(s, &t, 0); if (*t) { errno = EACCES; goto bad; } } if (n && uid != n) { errno = EACCES; goto bad; } } else uid = n; mode &= ~(S_IRWXG|S_IRWXO); } if (s = group) { n = getegid(); if (*s) { if ((gid = strgid(s)) < 0) { gid = strtol(s, &t, 0); if (*t) { errno = EACCES; goto bad; } } if (geteuid() && gid != n) { gid_t* groups; int g; if ((g = getgroups(0, NiL)) <= 0) g = getconf("NGROUPS_MAX"); if (groups = newof(0, gid_t, g, 0)) { for (n = getgroups(g, groups); n >= 0; n--) if (gid == groups[n]) break; free(groups); } else n = -1; if (n < 0) { errno = EACCES; goto bad; } } } else gid = n; mode &= ~S_IRWXO; } if (s = trust) { if (!*s) sid = geteuid(); else if ((sid = struid(s)) < 0) { sid = strtol(s, &t, 0); if (*t) { errno = EACCES; goto bad; } } } if (state->flags & CS_ADDR_SHARE) host = CS_HOST_SHARE; else { host = state->host; if (!(state->flags & CS_ADDR_LOCAL)) { if (*type == 'f') { errno = ENODEV; goto bad; } if (op & CS_OPEN_CREATE) { errno = EROFS; goto bad; } } if (serv && !qual && *type != 'f' && (port = csport(state, type, serv)) != CS_PORT_INVALID) { if (op & CS_OPEN_CREATE) addr = 0; else if (port == CS_PORT_RESERVED || port == CS_PORT_NORMAL) goto bad; if (nfd >= 0) { close(nfd); nfd = -1; } state->control = 0; if ((fd = csbind(state, type, addr, port, 0L)) >= 0) { if (mode != (S_IRWXU|S_IRWXG|S_IRWXO) && csauth(state, fd, NiL, NiL)) { close(fd); return -1; } return fd; } } } } /* * get the mount dir prefix */ if (opath == (b = path = state->mount)) { #ifdef ELOOP errno = ELOOP; #else errno = EINVAL; #endif goto bad; } if (*type == 'f') { if (host && !(state->flags & CS_ADDR_LOCAL)) { errno = ENODEV; goto bad; } b += sfsprintf(b, sizeof(state->mount) - (b - path), "%s", csvar(state, CS_VAR_LOCAL, 0)); if ((op & CS_OPEN_CREATE) && eaccess(path, X_OK) && (mkdir(path, S_IRWXU|S_IRWXG|S_IRWXO) || chmod(path, S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO))) goto bad; } else { if (op & CS_OPEN_TRUST) { if (!pathaccess(csvar(state, CS_VAR_TRUST, 1), csvar(state, CS_VAR_SHARE, 1), NiL, PATH_EXECUTE, b, sizeof(state->mount) - (b - state->mount))) goto bad; } else if (!pathpath(csvar(state, CS_VAR_SHARE, 0), "", PATH_EXECUTE, b, sizeof(state->mount) - (b - state->mount))) goto bad; b += strlen(b); } /* * add the type */ b += sfsprintf(b, sizeof(state->mount) - (b - path), "/%s", type); if (!host) { *(state->control = b + 1) = 0; if (nfd >= 0) close(nfd); if ((fd = open(path, O_RDONLY)) < 0) { mkmount(state, S_IRWXU|S_IRWXG|S_IRWXO, -1, -1, NiL, NiL, NiL); fd = open(path, O_RDONLY); } if (fd < 0) messagef((state->id, NiL, -1, "open: %s: %s: open error", state->path, path)); return fd; } endtype = b; /* * add the host */ if (strlen(host) <= CS_MNT_MAX) b += sfsprintf(b, sizeof(state->mount) - (b - path), "/%s", host); else { s = csntoa(state, addr); if (strlen(s) <= CS_MNT_MAX) b += sfsprintf(b, sizeof(state->mount) - (b - path), "/%s", s); else { unsigned char* a = (unsigned char*)&addr; b += sfsprintf(b, sizeof(state->mount) - (b - path), "/0x%X.%X.%X.%X", a[0], a[1], a[2], a[3]); } } messagef((state->id, NiL, -8, "%s:%d host=`%s' path=`%s'", __FILE__, __LINE__, host, path)); if (!serv) { *(state->control = b + 1) = 0; if (nfd >= 0) close(nfd); if ((fd = open(path, O_RDONLY)) < 0) messagef((state->id, NiL, -1, "open: %s: %s: open error", state->path, path)); return fd; } endhost = b; /* * add the service */ sfsprintf(b, sizeof(state->mount) - (b - path), "%s/%s/%s/%s%s", CS_SVC_DIR, type, serv, serv, CS_SVC_SUFFIX); if (!pathpath(b, "", PATH_ABSOLUTE|PATH_EXECUTE, tmp, sizeof(tmp)) || stat(tmp, &st)) op |= CS_OPEN_TEST; else { *strrchr(tmp, '/') = 0; if (!(op & CS_OPEN_TRUST)) sid = st.st_uid; if (!st.st_size) op |= CS_OPEN_TEST; } b += sfsprintf(b, sizeof(state->mount) - (b - path), "/%s", serv); endserv = b; /* * add the qualifier and perm */ if (sid >= 0) b += sfsprintf(b, sizeof(state->mount) - (b - path), "/%d-", sid); else b += sfsprintf(b, sizeof(state->mount) - (b - path), "/-"); if (uid >= 0) b += sfsprintf(b, sizeof(state->mount) - (b - path), "%d-", uid); else if (gid >= 0) b += sfsprintf(b, sizeof(state->mount) - (b - path), "-%d", gid); else b += sfsprintf(b, sizeof(state->mount) - (b - path), "-"); #if limit_qualifier_length endqual = endserv + CS_MNT_MAX + 1; #else endqual = state->mount + sizeof(state->mount) - 1; #endif if (qual) { if (b < endqual) *b++ = '-'; while (b < endqual && *qual) *b++ = *qual++; } if (*type == 't' && !auth) { if (b >= endqual) b--; *b++ = CS_MNT_OTHER; } /* * add in the connect stream control */ *b++ = '/'; *b = CS_MNT_STREAM; strcpy(b + 1, CS_MNT_TAIL); messagef((state->id, NiL, -8, "%s:%d %s", __FILE__, __LINE__, state->mount)); state->control = b; /* * create the mount subdirs if necessary */ if ((op & CS_OPEN_CREATE) && mkmount(state, mode, uid, gid, endserv, endhost, endtype)) goto bad; mode &= S_IRWXU|S_IRWXG|S_IRWXO; if (nfd >= 0) { close(nfd); nfd = -1; } if (op & CS_OPEN_MOUNT) { messagef((state->id, NiL, -1, "open(%s,%o) = %d, mount = %s", state->path, op, state->mount)); return 0; } if (*type == 'f') { /* * {fdp} */ if ((fd = doattach(state, path, op, mode, user, opath, tmp, serv, b)) < 0) return -1; } else { /* * {tcp,udp} */ messagef((state->id, NiL, -8, "%s:%d %s", __FILE__, __LINE__, state->mount)); if ((fd = reopen(state, path)) < 0) { /* * check for old single char cs mount */ *(state->control + 1) = 0; if ((fd = reopen(state, path)) < 0) messagef((state->id, NiL, -1, "open: %s: %s: reopen error", state->path, path)); *(state->control + 1) = CS_MNT_TAIL[0]; } if (op & CS_OPEN_CREATE) { if (fd >= 0) { close(fd); errno = EEXIST; return -1; } if (errno != ENOENT && errno != ENOTDIR) return -1; sigcritical(1); *state->control = CS_MNT_LOCK; if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0)) < 0) { if (stat(path, &st)) { messagef((state->id, NiL, -1, "open: %s: %s: creat error", state->path, path)); goto unblock; } if ((CSTIME() - (unsigned long)st.st_ctime) < 2 * 60) { errno = EEXIST; messagef((state->id, NiL, -1, "open: %s: %s: another server won the race", state->path, path)); goto unblock; } if (remove(path)) { messagef((state->id, NiL, -1, "open: %s: %s: remove error", state->path, path)); goto unblock; } if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0)) < 0) { messagef((state->id, NiL, -1, "open: %s: %s: creat error", state->path, path)); goto unblock; } } close(fd); if (!port && (n = strtol(serv, &t, 0)) && t > serv && !*t) port = n; else if (geteuid()) port = CS_NORMAL; else port = CS_RESERVED; if ((fd = csbind(state, type, 0L, port, 0L)) >= 0) { *state->control = CS_MNT_STREAM; remove(path); if (pathsetlink(cspath(state, fd, 0), path)) { messagef((state->id, NiL, -1, "open: %s: %s: link error", cspath(state, fd, 0), path)); close(fd); fd = -1; } } unblock: *state->control = CS_MNT_LOCK; remove(path); sigcritical(0); *state->control = CS_MNT_STREAM; if (fd < 0) return -1; } else if (fd < 0 && ((op & CS_OPEN_TEST) || initiate(state, user, opath, tmp, serv) || (fd = reopen(state, path)) < 0)) { messagef((state->id, NiL, -1, "open: %s: %s: reopen/initiate error", state->path, path)); return -1; } else if (!(op & CS_OPEN_AGENT)) { *state->control = CS_MNT_AUTH; n = csauth(state, fd, path, arg); *state->control = CS_MNT_STREAM; if (n) { close(fd); messagef((state->id, NiL, -1, "open: %s: %s: authentication error", state->path, path)); return -1; } } } /* * fd is open at this point * make sure its not a bogus mount */ if (mode != (S_IRWXU|S_IRWXG|S_IRWXO)) { *state->control = 0; n = stat(path, &st); *state->control = CS_MNT_STREAM; if (n) { messagef((state->id, NiL, -1, "open: %s: %s: stat error", state->path, path)); close(fd); return -1; } if (uid >= 0 && st.st_uid != uid || gid >= 0 && st.st_gid != gid) { close(fd); errno = EPERM; messagef((state->id, NiL, -1, "open: %s: %s: uid/gid error", state->path, path)); return -1; } } return fd; bad: if (nfd >= 0) close(nfd); return -1; }
int apply_iptables(const char *table, const char *conf, bool noflush) { int pipefd_in[2]; int pipefd_out[2]; pid_t child_pid; int error = 0; child_pid = fork_with_pipes(pipefd_in, pipefd_out); if (child_pid < 0) { return error; } if (child_pid == 0) { /* child */ close(pipefd_in[1]); close(pipefd_out[0]); if (dup2(pipefd_in[0], STDIN_FILENO) == -1 || dup2(pipefd_out[1], STDOUT_FILENO) == -1 || dup2(pipefd_out[1], STDERR_FILENO) == -1) { fprintf(stderr, "%s\n", strerror(errno)); exit(1); } close(pipefd_in[0]); close(pipefd_out[1]); if (noflush) { execl(IPTABLES_RESTORE, "iptables-restore", "-T", table, "-n", NULL); } else { execl(IPTABLES_RESTORE, "iptables-restore", "-T", table, NULL); } /* an error occured */ fprintf(stderr, "%s\n", strerror(errno)); exit(1); } else { /* parent */ int status; pid_t ret; char *buffer = NULL; size_t buffer_size = 0; ssize_t line_size; FILE *output = fdopen(pipefd_out[0], "r"); if (!output) { messagef(HAKA_LOG_ERROR, MODULE_NAME, "iptables-restore: %s", errno_error(errno)); return errno; } close(pipefd_in[0]); close(pipefd_out[1]); status = write(pipefd_in[1], conf, strlen(conf)); error = errno; close(pipefd_in[1]); if (status < 0) { fclose(output); return error; } while ((line_size = getline(&buffer, &buffer_size, output)) >= 0) { if (line_size > 1) { buffer[line_size-1] = '\0'; messagef(HAKA_LOG_INFO, MODULE_NAME, "iptables-restore: %s", buffer); } } free(buffer); fclose(output); /* wait for the child to finish */ do { ret = waitpid(child_pid, &status, 0); if (ret == -1) { return errno; } } while (!WIFEXITED(status) && !WIFSIGNALED(status)); return WEXITSTATUS(status); } }
static int doattach(register Cs_t* state, const char* path, int op, int mode, char* user, char* opath, char* tmp, char* serv, char*b) { register int n; int fd; char* s; #if CS_LIB_STREAM || CS_LIB_V10 int fds[2]; struct stat st; if (op & CS_OPEN_CREATE) { n = errno; if (chmod(path, mode)) { remove(path); if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, mode)) < 0) { messagef((state->id, NiL, -1, "open: %s: %s: creat %o error", state->path, path, mode)); return -1; } close(fd); chmod(path, mode); } errno = n; if (pipe(fds)) { messagef((state->id, NiL, -1, "open: %s: pipe error", state->path, path)); return -1; } #if CS_LIB_V10 if ((n = ioctl(fds[1], FIOPUSHLD, &conn_ld)) || fmount(3, fds[1], path, 0)) #else if ((n = ioctl(fds[1], I_PUSH, "connld")) || fattach(fds[1], path)) #endif { messagef((state->id, NiL, -1, "open: %s: %s: %s error", state->path, path, n ? "connld" : "fattach")); close(fds[0]); close(fds[1]); errno = ENXIO; return -1; } close(fds[1]); fd = fds[0]; } else for (;;) { if ((fd = open(path, O_RDWR)) >= 0) { if (!fstat(fd, &st) && !S_ISREG(st.st_mode)) break; close(fd); remove(path); } else if ((op & CS_OPEN_TEST) || errno == EACCES) { messagef((state->id, NiL, -1, "open: %s: %s: open error", state->path, path)); return -1; } if (initiate(state, user, opath, tmp, serv)) { messagef((state->id, NiL, -1, "open: %s: %s: service initiate error", state->path, path)); return -1; } op = CS_OPEN_TEST; } #else #if CS_LIB_SOCKET_UN int pid; int namlen; char c; struct sockaddr_un nam; messagef((state->id, NiL, -8, "%s:%d state.path=`%s' state.mount=`%s' path=`%s' opath=`%s' user=`%s' serv=`%s'", __FILE__, __LINE__, state->path, state->mount, path, opath, user, serv)); nam.sun_family = AF_UNIX; strcpy(nam.sun_path, path); namlen = sizeof(nam.sun_family) + strlen(path) + 1; for (n = 0;; n++) { if (n >= 10) { errno = ENXIO; badcon: close(fd); return -1; } if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { messagef((state->id, NiL, -1, "open: %s: %s: AF_UNIX socket error", state->path, path)); return -1; } if (!connect(fd, (struct sockaddr*)&nam, namlen)) { if (op & CS_OPEN_CREATE) { errno = EEXIST; goto badcon; } #if CS_LIB_SOCKET_RIGHTS if (read(fd, &c, 1) == 1 && !cssend(state, fd, NiL, 0)) break; #else break; #endif } else { messagef((state->id, NiL, -1, "open: %s: %s: connect error", state->path, path)); if (errno == EACCES) goto badcon; else if (errno == EADDRNOTAVAIL || errno == ECONNREFUSED) { c = 0; for (;;) { *b = CS_MNT_PROCESS; pid = pathgetlink(path, state->temp, sizeof(state->temp)); *b = CS_MNT_STREAM; if (pid > 0 || ++c >= 5) break; sleep(1); } if (pid > 0 && (s = strrchr(state->temp, '/')) && (pid = strtol(s + 1, NiL, 0)) > 0) { if (!kill(pid, 0) || errno != ESRCH) { if (op & CS_OPEN_CREATE) { errno = EEXIST; goto badcon; } close(fd); if (n) sleep(1); continue; } *b = CS_MNT_PROCESS; remove(path); *b = CS_MNT_STREAM; } } } close(fd); errno = ENOENT; if (op & CS_OPEN_CREATE) { if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { messagef((state->id, NiL, -1, "open: %s: %s: AF_UNIX socket error", state->path, path)); return -1; } if (!bind(fd, (struct sockaddr*)&nam, namlen)) { chmod(path, mode); if (listen(fd, 32)) { messagef((state->id, NiL, -1, "open: %s: %s: listen error", state->path, path)); n = errno; remove(path); errno = n; goto badcon; } break; } else messagef((state->id, NiL, -1, "open: %s: %s: bind error", state->path, path)); if (errno != EADDRINUSE || n && remove(path) && errno != ENOENT) goto badcon; close(fd); } else if (op & CS_OPEN_TEST) return -1; else if (!n && initiate(state, user, opath, tmp, serv)) { messagef((state->id, NiL, -1, "open: %s: %s: service initiate error", state->path, path)); return -1; } else sleep(2); } #else errno = (op & CS_OPEN_CREATE) ? ENXIO : ENOENT; messagef((state->id, NiL, -1, "open: %s: %s: not supported", state->path, path)); fd = -1; #endif #endif #if CS_LIB_SOCKET_UN || CS_LIB_STREAM || CS_LIB_V10 touch(path, (time_t)0, (time_t)0, 0); strcpy(state->path, path); #endif return fd; }