void setup_io(void) { nmsg_output_t output_cb; nmsg_res res; io = nmsg_io_init(); assert(io != NULL); output_cb = nmsg_output_open_callback(nmsg_callback, NULL); if (output_cb == NULL) errx(EXIT_FAILURE, "nmsg_output_open_callback() failed"); res = nmsg_io_add_output(io, output_cb, NULL); if (res != nmsg_res_success) errx(EXIT_FAILURE, "nmsg_io_add_output() failed: %s", nmsg_res_lookup(res)); }
void out_flush(void) { nmsg_res res; ssize_t wlen; if (time_out_flush.tv_sec == 0) return; if (out_buf_len != 0) { wlen = write(out_fd, &out_buf[out_buf_base], out_buf_len - out_buf_base); if (wlen < 0) { if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) { error_msg("write(%s): %s", out_addr, strerror(errno)); out_close(true); } } else { out_buf_base += wlen; if (out_buf_base >= out_buf_len) out_buf_base = out_buf_len = 0; } } if (out_nmsg_output != NULL) { res = nmsg_output_flush(out_nmsg_output); if (res != nmsg_res_success && (out_sock_type != SOCK_DGRAM || res != nmsg_res_errno || !AXA_IGNORED_UDP_ERRNO(errno))) { error_msg("nmsg_output_flush(forward): %s", nmsg_res_lookup(res)); out_close(true); } } time_out_flush.tv_sec = 0; }
axa_w2n_res_t axa_whit2nmsg(axa_emsg_t *emsg, nmsg_input_t nmsg_input, nmsg_message_t *msgp, axa_p_whit_t *whit, size_t whit_len) { size_t msg_len; nmsg_message_t *msgs; size_t n_msgs; struct timespec ts; nmsg_res res; *msgp = NULL; msg_len = whit_len - sizeof(whit->nmsg.hdr); if (msg_len <= 0) { axa_pemsg(emsg, "truncated nmsg"); return (AXA_W2N_RES_FAIL); } ts.tv_sec = AXA_P2H32(whit->nmsg.hdr.ts.tv_sec); ts.tv_nsec = AXA_P2H32(whit->nmsg.hdr.ts.tv_nsec); res = nmsg_input_read_null(nmsg_input, whit->nmsg.b, msg_len, &ts, &msgs, &n_msgs); if (res != nmsg_res_success) { axa_pemsg(emsg, "nmsg_input_read_null(): %s", nmsg_res_lookup(res)); return (AXA_W2N_RES_FAIL); } /* if res == nmsg_res_success && n_msgs == 0, we have an NMSG fragment */ if (n_msgs < 1 || n_msgs > 1) { while (n_msgs > 0) nmsg_message_destroy(&msgs[--n_msgs]); free(msgs); return (AXA_W2N_RES_FRAGMENT); } *msgp = msgs[0]; free(msgs); return (AXA_W2N_RES_SUCCESS); }
int main(int argc, char **argv) { const char *fields_file = ""; const char *config_file = ""; #if LIBEDIT_IS_UNICODE wchar_t wc; #endif char cmd_buf[500]; const char *cmd; int cmd_len; bool version = false; const char *cfile = NULL; size_t n; nmsg_res res; char *p; int i; axa_set_me(argv[0]); AXA_ASSERT(axa_parse_log_opt(NULL, "trace,off,stderr")); AXA_ASSERT(axa_parse_log_opt(NULL, "error,off,stderr")); axa_syslog_init(); axa_set_core(); axa_client_init(&client); if (strcmp(axa_prog_name, "radtool") == 0) mode = RAD; if (isatty(STDIN_FILENO)) el_e = el_init(axa_prog_name, stdin, stdout, stderr); if (el_e != NULL) { int flag; if (0 > el_get(el_e, EL_EDITMODE, &flag) || !flag) { el_end(el_e); el_e = NULL; } } if (el_e != NULL) { /* prefer emacs mode but let the user choose in .editrc */ el_set(el_e, EL_EDITOR, "emacs"); /* bind emacs search to ^R */ el_set(el_e, EL_BIND, "\022", "em-inc-search-prev", NULL); el_source(el_e, NULL); el_history = history_init(); history(el_history, &el_event, H_SETSIZE, 800); history_get_savefile(); history(el_history, &el_event, H_LOAD, history_savefile); el_set(el_e, EL_HIST, history, el_history); el_set(el_e, EL_PROMPT, el_prompt); el_set(el_e, EL_SIGNAL, 1); el_set(el_e, EL_GETCFN, getcfn); } while ((i = getopt(argc, argv, "hVdNF:E:S:c:n:")) != -1) { switch (i) { case 'n': config_file = optarg; break; case 'V': version = true; break; case 'h': usage(); break; case 'd': ++axa_debug; break; case 'N': no_prompt = true; break; case 'F': fields_file = optarg; break; case 'E': if (axa_tls_cipher_list(&emsg, optarg) == NULL) error_msg("%s", emsg.c); break; case 'S': if (!axa_tls_certs_dir(&emsg, optarg)) error_msg("%s", emsg.c); break; case 'c': if (cfile != NULL) error_msg("only one -c allowed;" " ignoring all but the last"); cfile = optarg; break; default: usage(); } } argc -= optind; argv += optind; if (version) { version_cmd(AXA_TAG_NONE, "", NULL); if (argc == 0) stop(EX_OK); } signal(SIGPIPE, SIG_IGN); if (el_e != NULL) { signal(SIGINT, sigint); signal(SIGTERM, sigterm); signal(SIGHUP, sigterm); } AXA_DEBUG_TO_NMSG(axa_debug); res = nmsg_init(); if (res != nmsg_res_success) { error_msg("nmsg_init(): %s", nmsg_res_lookup(res)); exit(EX_SOFTWARE); } nmsg_input = nmsg_input_open_null(); AXA_ASSERT(nmsg_input != NULL); nmsg_pres = nmsg_output_open_pres(STDOUT_FILENO); axa_load_fields(fields_file); if (!axa_load_client_config(&emsg, config_file)) { axa_error_msg("can't load config file: %s", emsg.c); exit(EXIT_FAILURE); } /* Answer commands from the control file. */ if (cfile != NULL) { axa_asprintf(&p, "source %s", cfile); if (el_e != NULL) history(el_history, &el_event, H_ENTER, p); if (!do_cmds(p)) error_msg(" initial \"-c %s\" failed", cfile); free(p); } /* Answer commands from the command line. */ while (argc != 0) { if (el_e != NULL) history(el_history, &el_event, H_ENTER, *argv); if (!do_cmds(*argv)) { error_msg(" initial command \"%s\" failed", *argv); break; } ++argv; --argc; } for (;;) { cmd_input.tv_sec = 0; fflush(stderr); fflush(stdout); if (in_file_cur > 0) { /* Get a command from a "sourced" file. */ if (interrupted) { close_in_files(); continue; } cmd = axa_fgetln(in_files[in_file_cur].f, in_files[in_file_cur].name, &in_files[in_file_cur].lineno, &in_files[in_file_cur].buf, &in_files[in_file_cur].buf_size); if (cmd == NULL) { close_in_file_cur(); continue; } if (axa_debug != 0) { printf("< %s\n", cmd); fflush(stdout); } } else if (el_e != NULL) { /* Get a command from the terminal via editline(3). */ cmd = el_gets(el_e, &cmd_len); prompt_len = 0; if (!interrupted) { if (cmd == NULL) { fputc('\n', stdout); if (cmd_len == -1) error_msg("el_gets(): %s", strerror(errno)); stop(EX_OK); } /* Save nontrivial command lines. */ if (*(cmd+strspn(cmd, AXA_WHITESPACE)) != '\0') history(el_history, &el_event, H_ENTER, cmd); } } else if (!interrupted) { /* Get a command from stdin. */ n = 0; for (;;) { #if LIBEDIT_IS_UNICODE getcfn(NULL, &wc); cmd_buf[n] = wctob(wc); #else getcfn(NULL, &cmd_buf[n]); #endif if (cmd_buf[n++] == '\n' || n >= sizeof(cmd_buf)-1) break; } cmd_buf[n] = '\0'; cmd = cmd_buf; } if (interrupted) { interrupted = false; if (el_e != NULL) { el_set(el_e, EL_UNBUFFERED, 0); el_reset(el_e); if (prompt_cleared.tv_sec != 0) { packet_counting = true; packet_count = 0; packet_count_total = 0; } } close_in_files(); fputs(" (int)\n", stdout); continue; } if (!do_cmds(cmd)) { fputs(" ?\n", stderr); fflush(stdout); close_in_files(); } } }
/* forward watch hits as NMSG messages */ bool out_whit_nmsg(axa_p_whit_t *whit, size_t whit_len) { nmsg_message_t msg; struct timespec ts; static const union { uint e; uint8_t c[0]; } pkt_enum = { .e = NMSG__BASE__PACKET_TYPE__IP }; size_t len; struct timeval now; nmsg_res res; bool result; switch ((axa_p_whit_enum_t)whit->hdr.type) { case AXA_P_WHIT_NMSG: /* pass NMSG messages along */ if (whit2nmsg(&msg, whit, whit_len) == AXA_W2N_RES_FRAGMENT) { if (axa_debug != 0) printf("ignoring NMSG fragment from " AXA_OP_CH_PREFIX"%d", AXA_P2H_CH(whit->hdr.ch)); return (false); } if (msg == NULL) return (false); break; case AXA_P_WHIT_IP: /* Convert raw IP packets to nmsg BASE_PACKET */ len = whit_len - sizeof(whit->ip.hdr); if (AXA_P2H32(whit->ip.hdr.ip_len) != len) return (false); /* Ignore incomplete packets. */ if (!out_nmsg_mod_checked) { out_nmsg_mod_checked = true; out_nmsg_mod = nmsg_msgmod_lookup(NMSG_VENDOR_BASE_ID, NMSG_VENDOR_BASE_PACKET_ID); if (out_nmsg_mod == NULL) { out_error("cannot get BASE_PACKET module"); return (false); } res = nmsg_msgmod_init(out_nmsg_mod, &out_nmsg_clos); if (res != nmsg_res_success) { out_error("cannot init BASE_PACKET module"); out_nmsg_mod = NULL; return (false); } } if (out_nmsg_mod == NULL) { out_error("cannot forward IP as NMSG messages" " without PACKET nmsg_msgmod"); return (false); } msg = nmsg_message_init(out_nmsg_mod); AXA_ASSERT(msg != NULL); res = nmsg_message_set_field(msg, "payload_type", 0, pkt_enum.c, sizeof(pkt_enum)); AXA_ASSERT(res == nmsg_res_success); res = nmsg_message_set_field(msg, "payload", 0, whit->ip.b, len); AXA_ASSERT(res == nmsg_res_success); ts.tv_sec = AXA_P2H32(whit->ip.hdr.tv.tv_sec); ts.tv_nsec = AXA_P2H32(whit->ip.hdr.tv.tv_usec) * 1000; nmsg_message_set_time(msg, &ts); break; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunreachable-code" default: out_error("cannot forward SRA #%d messages as NMSG messages", whit->hdr.type); return (false); #pragma clang diagnostic pop } res = nmsg_output_write(out_nmsg_output, msg); if (res == nmsg_res_success) { result = true; } else { result = false; gettimeofday(&now, NULL); if (out_sock_type != SOCK_DGRAM || res != nmsg_res_errno || !AXA_IGNORED_UDP_ERRNO(errno)) { /* Stop on non-UDP errors. */ clear_prompt(); error_msg("nmsg_output_write(): %s", nmsg_res_lookup(res)); out_close(false); disconnect(true); } else if (output_errno != errno || 60*1000 <= axa_elapsed_ms(&now, &output_errno_time) || axa_debug >= AXA_DEBUG_TRACE) { /* Report occasional identical UDP errors. */ output_errno = errno; gettimeofday(&output_errno_time, NULL); clear_prompt(); error_msg("nmsg_output_write(): %s", strerror(output_errno)); } } nmsg_message_destroy(&msg); if (time_out_flush.tv_sec == 0) gettimeofday(&time_out_flush, NULL); return (result); }
int main(int argc, char *argv[]) { int n, c, rc, ec = EXIT_FAILURE, fd_in = -1, fd_out = -1, verbosity = 0; uint32_t ts_start = 0, ts_end = 0, count = 0, nmsg_cnt = 0; MDB_env *env = NULL; MDB_txn *txn = NULL; MDB_dbi dbi; MDB_val key, data; MDB_cursor *cursor = NULL; struct timespec ts, msg_ts; off_t *offset; nmsg_input_t nmsg_in = NULL; nmsg_output_t nmsg_out = NULL; nmsg_res res; nmsg_message_t msg; char *json; bool input_json = false, input_nmsg = false, is_counting = false, need_exact = false; const char *lmdb_filename = NULL, *nmsg_filename_in = NULL; char nmsg_filename_out[BUFSIZ] = {0}; while ((c = getopt(argc, argv, "c:e:f:j:r:s:hvx")) != EOF) { switch (c) { case 'c': count = atoi(optarg); is_counting = true; break; case 'e': ts_end = atoi(optarg); break; case 'f': lmdb_filename = optarg; break; case 'j': nmsg_filename_in = optarg; input_json = true; break; case 'r': nmsg_filename_in = optarg; input_nmsg = true; break; case 's': ts_start = atoi(optarg); break; case 'v': verbosity++; break; case 'x': need_exact = true; break; case 'h': default: usage(argv[0], NULL); goto done; } } if (ts_start == 0) { usage(argv[0], "Need a starting timestamp (-s)."); goto done; } if (lmdb_filename == NULL) { usage(argv[0], "Need a tsindex file (-f)."); goto done; return (EXIT_FAILURE); } if ((input_json == false && input_nmsg == false) || (input_json && input_nmsg)) { usage(argv[0], "Need either an nmsg json file (-j) or binary nmsg file (-r)."); goto done; return (EXIT_FAILURE); } if ((ts_end == 0 && count == 0) || (ts_end != 0 && count != 0)) { usage(argv[0], "Need either an ending timestamp (-e) or a count (-c)."); goto done; return (EXIT_FAILURE); } res = nmsg_init(); if (res != nmsg_res_success) { fprintf(stderr, "Error initializing NMSG library: %s\n", nmsg_res_lookup(res)); goto done; return (EXIT_FAILURE); } fd_in = open(nmsg_filename_in, O_RDONLY); if (fd_in < 0) { fprintf(stderr, "Can't open nmsg input file \"%s\": %s\n", nmsg_filename_in, strerror(errno)); goto done; return (EXIT_FAILURE); } n = strlcpy(nmsg_filename_out, nmsg_filename_in, sizeof (nmsg_filename_out)); snprintf(nmsg_filename_out + n, sizeof (nmsg_filename_out) - n, "-tsindex.%u.%s", getpid(), input_json ? "json" : "nmsg"); fd_out = open(nmsg_filename_out, O_CREAT | O_WRONLY, 0644); if (fd_out < 0) { fprintf(stderr, "Can't open nmsg output file \"%s\": %s\n", nmsg_filename_out, strerror(errno)); goto done; return (EXIT_FAILURE); } if (input_json) { nmsg_in = nmsg_input_open_json(fd_in); if (nmsg_in == NULL) { fprintf(stderr, "nmsg_input_open_json() failed\n"); goto done; } nmsg_out = nmsg_output_open_json(fd_out); if (nmsg_out == NULL) { fprintf(stderr, "nmsg_ouput_open_json() failed\n"); goto done; } } else if (input_nmsg) { nmsg_in = nmsg_input_open_file(fd_in); if (nmsg_in == NULL) { fprintf(stderr, "nmsg_input_open_file() failed\n"); goto done; } nmsg_out = nmsg_output_open_file(fd_out, NMSG_WBUFSZ_MAX); if (nmsg_out == NULL) { fprintf(stderr, "nmsg_ouput_open_file() failed\n"); goto done; } } rc = mdb_env_create(&env); if (rc != 0) { fprintf(stderr, "mdb_create() failed: %s\n", mdb_strerror(rc)); goto done; } rc = mdb_env_open(env, lmdb_filename, MDB_NOSUBDIR | MDB_RDONLY, 0664); if (rc != 0) { fprintf(stderr, "mdb_env_open failed(): %s\n", mdb_strerror(rc)); goto done; } rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn); if (rc != 0) { fprintf(stderr, "mdb_txn_begin failed(): %s\n", mdb_strerror(rc)); goto done; } rc = mdb_open(txn, NULL, MDB_INTEGERKEY, &dbi); if (rc) { fprintf(stderr, "mdb_open(): %s\n", mdb_strerror(rc)); goto done; } rc = mdb_set_compare(txn, dbi, axa_tsi_mdb_cmp); if (rc) { fprintf(stderr, "mdb_set_compare(): %s\n", mdb_strerror(rc)); goto done; } ts.tv_sec = ts_start; ts.tv_nsec = 0; key.mv_size = sizeof (ts); key.mv_data = &ts; rc = mdb_cursor_open(txn, dbi, &cursor); if (rc) { fprintf(stderr, "mdb_cursor_open(): %s\n", mdb_strerror(rc)); goto done; } rc = mdb_cursor_get(cursor, &key, &data, need_exact ? MDB_SET : MDB_SET_RANGE); if (rc == MDB_NOTFOUND) { printf("Did not find starting timestamp %u in %s.\n", ts_start, lmdb_filename); goto done; } if (rc) { fprintf(stderr, "mdb_cursor_get(): %s\n", mdb_strerror(rc)); goto done; } (void) mdb_cursor_close(cursor); offset = (off_t *)data.mv_data; if (verbosity > 0) printf("Found %u at offset 0x%"PRIu64".\n", ts_start, *offset); if (lseek(fd_in, *offset, SEEK_SET) == sizeof (off_t) - 1) { fprintf(stderr, "lseek(): %s\n", strerror(errno)); goto done; } while (1) { if (is_counting) { if (count-- <= 0) break; } res = nmsg_input_read(nmsg_in, &msg); if (res == nmsg_res_eof) { if (verbosity > 0) printf("End of file reached.\n"); break; } if (res != nmsg_res_success) { fprintf(stderr, "nmsg_input_read(): %s\n", nmsg_res_lookup(res)); goto done; } if (is_counting == false) { nmsg_message_get_time(msg, &msg_ts); if (msg_ts.tv_sec >= ts_end) { nmsg_message_destroy(&msg); break; } } res = nmsg_output_write(nmsg_out, msg); if (res != nmsg_res_success) { fprintf(stderr, "nmsg_output_write(): %s\n", nmsg_res_lookup(res)); nmsg_message_destroy(&msg); goto done; } if (verbosity > 1) { res = nmsg_message_to_json(msg, &json); if (res != nmsg_res_success) { fprintf(stderr, "nmsg_message_to_pres(): %s\n", nmsg_res_lookup(res)); nmsg_message_destroy(&msg); goto done; } printf("%s\n", json); free(json); } nmsg_cnt++; nmsg_message_destroy(&msg); } ec = EXIT_SUCCESS; printf("Wrote %u nmsgs to %s.\n", nmsg_cnt, nmsg_filename_out); done: if (fd_in != -1) close(fd_in); if (fd_out != -1) close(fd_out); if (nmsg_in != NULL) nmsg_input_close(&nmsg_in); if (nmsg_out != NULL) nmsg_output_close(&nmsg_out); if (txn != NULL) mdb_txn_abort(txn); if (env != NULL) mdb_env_close(env); return (ec); }