As a multicommand support preparation entry counters need to be made per-command as well, e.g. for the case -D and -I can be executed in a single batch, and we want to have separate counters for them. Signed-off-by: Mikhail Sennikovsky <mikhail.sennikovskii@xxxxxxxxxxxxxxx> --- src/conntrack.c | 117 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 81 insertions(+), 36 deletions(-) diff --git a/src/conntrack.c b/src/conntrack.c index a090542..4783825 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -1663,8 +1663,48 @@ nfct_filter(const struct ct_cmd *cmd, return 0; } -static int counter; static int dump_xml_header_done = 1; +static unsigned int cmd_executed = 0; +static const unsigned int cmd_no_entries_ok = 0 + | CT_LIST + | EXP_LIST + ; +static unsigned int cmd_counters[NUMBER_OF_CMD]; + +static int +print_cmd_counters(void) +{ + int i, ret = EXIT_FAILURE; + + if (!cmd_executed) + return EXIT_SUCCESS; + + for (i = 0; + i < (int)(sizeof(cmd_counters) / sizeof(cmd_counters[0])); + ++i) { + if (cmd_executed & 1 << i) { + if (exit_msg[i][0]) { + fprintf(stderr, "%s v%s (conntrack-tools): ", + PROGNAME, VERSION); + fprintf(stderr, exit_msg[i], cmd_counters[i]); + } + /* + * If there is at least one command which is supposed + * to return success, EXIT_SUCCESS is returned. + * I.e. for the --load-file case this would ensure that + * e.g. -D followed by a series of -I's + * would return success in case there are no entries + * to be deleted with the -D command preceding the -I's + */ + if (!exit_msg[i][0] + || cmd_counters[i] != 0 + || cmd_no_entries_ok & 1 << i) + ret &= EXIT_SUCCESS; + } + } + return ret; +} + static void __attribute__((noreturn)) event_sighandler(int s) @@ -1674,8 +1714,7 @@ event_sighandler(int s) fflush(stdout); } - fprintf(stderr, "%s v%s (conntrack-tools): ", PROGNAME, VERSION); - fprintf(stderr, "%d flow events have been shown.\n", counter); + print_cmd_counters(); mnl_socket_close(sock.mnl); exit(0); } @@ -1688,8 +1727,7 @@ exp_event_sighandler(int s) fflush(stdout); } - fprintf(stderr, "%s v%s (conntrack-tools): ", PROGNAME, VERSION); - fprintf(stderr, "%d expectation events have been shown.\n", counter); + print_cmd_counters(); nfct_close(cth); exit(0); } @@ -1938,7 +1976,7 @@ done: } fflush(stdout); - counter++; + cmd_counters[cmd->cmd]++; out: nfct_destroy(ct); return MNL_CB_OK; @@ -1981,7 +2019,7 @@ static int dump_cb(enum nf_conntrack_msg_type type, done: printf("%s\n", buf); - counter++; + cmd_counters[cmd->cmd]++; return NFCT_CB_CONTINUE; } @@ -2022,7 +2060,7 @@ static int delete_cb(enum nf_conntrack_msg_type type, done: printf("%s\n", buf); - counter++; + cmd_counters[cmd->cmd]++; return NFCT_CB_CONTINUE; } @@ -2207,7 +2245,7 @@ static int update_cb(enum nf_conntrack_msg_type type, nfct_destroy(tmp); nfct_callback_unregister(ith); - counter++; + cmd_counters[cmd->cmd]++; return NFCT_CB_CONTINUE; } @@ -2217,6 +2255,7 @@ static int dump_exp_cb(enum nf_conntrack_msg_type type, void *data) { char buf[1024]; + struct ct_cmd *cmd = data; unsigned int op_type = NFCT_O_DEFAULT; unsigned int op_flags = 0; @@ -2239,7 +2278,7 @@ static int dump_exp_cb(enum nf_conntrack_msg_type type, nfexp_snprintf(buf,sizeof(buf), exp, NFCT_T_UNKNOWN, op_type, op_flags); printf("%s\n", buf); - counter++; + cmd_counters[cmd->cmd]++; return NFCT_CB_CONTINUE; } @@ -2248,6 +2287,7 @@ static int event_exp_cb(enum nf_conntrack_msg_type type, struct nf_expect *exp, void *data) { char buf[1024]; + struct ct_cmd *cmd = data; unsigned int op_type = NFCT_O_DEFAULT; unsigned int op_flags = 0; @@ -2271,7 +2311,7 @@ static int event_exp_cb(enum nf_conntrack_msg_type type, nfexp_snprintf(buf,sizeof(buf), exp, type, op_type, op_flags); printf("%s\n", buf); fflush(stdout); - counter++; + cmd_counters[cmd->cmd]++; return NFCT_CB_CONTINUE; } @@ -2280,7 +2320,9 @@ static int count_exp_cb(enum nf_conntrack_msg_type type, struct nf_expect *exp, void *data) { - counter++; + struct ct_cmd *cmd = data; + + cmd_counters[cmd->cmd]++; return NFCT_CB_CONTINUE; } @@ -2396,7 +2438,9 @@ static void nfct_mnl_socket_close(void) } static int -nfct_mnl_dump(uint16_t subsys, uint16_t type, mnl_cb_t cb, uint8_t family) +nfct_mnl_dump(uint16_t subsys, uint16_t type, + mnl_cb_t cb, void *data, + uint8_t family) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; @@ -2411,7 +2455,7 @@ nfct_mnl_dump(uint16_t subsys, uint16_t type, mnl_cb_t cb, uint8_t family) res = mnl_socket_recvfrom(sock.mnl, buf, sizeof(buf)); while (res > 0) { res = mnl_cb_run(buf, res, nlh->nlmsg_seq, sock.portid, - cb, NULL); + cb, data); if (res <= MNL_CB_STOP) break; @@ -2581,6 +2625,7 @@ static int mnl_nfct_dump_cb(const struct nlmsghdr *nlh, void *data) { struct nf_conntrack *ct; char buf[4096]; + struct ct_cmd *cmd = data; ct = nfct_new(); if (ct == NULL) @@ -2593,7 +2638,7 @@ static int mnl_nfct_dump_cb(const struct nlmsghdr *nlh, void *data) nfct_destroy(ct); - counter++; + cmd_counters[cmd->cmd]++; return MNL_CB_OK; } @@ -3051,6 +3096,10 @@ static void do_parse(struct ct_cmd *ct_cmd, int argc, char *argv[]) } } + if (!command) + /* invalid args */ + exit_error(PARAMETER_PROBLEM, "invalid cmd line syntax"); + /* default family only for the following commands */ if (family == AF_UNSPEC) { switch (command) { @@ -3106,11 +3155,14 @@ static void do_parse(struct ct_cmd *ct_cmd, int argc, char *argv[]) ct_cmd->socketbuffersize = socketbuffersize; } -static int do_command_ct(const char *progname, struct ct_cmd *cmd) +static void do_command_ct(const char *progname, struct ct_cmd *cmd) { struct nfct_filter_dump *filter_dump; int res = 0; + assert(cmd->cmd < sizeof(cmd_counters) / sizeof(cmd_counters[0])); + cmd_executed |= cmd->command; + switch(cmd->command) { case CT_LIST: if (cmd->type == CT_TABLE_DYING) { @@ -3119,7 +3171,7 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd) res = nfct_mnl_dump(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET_DYING, - mnl_nfct_dump_cb, cmd->family); + mnl_nfct_dump_cb, cmd, cmd->family); nfct_mnl_socket_close(); break; @@ -3129,7 +3181,7 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd) res = nfct_mnl_dump(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET_UNCONFIRMED, - mnl_nfct_dump_cb, cmd->family); + mnl_nfct_dump_cb, cmd, cmd->family); nfct_mnl_socket_close(); break; @@ -3182,7 +3234,7 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd) if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); - nfexp_callback_register(cth, NFCT_T_ALL, dump_exp_cb, NULL); + nfexp_callback_register(cth, NFCT_T_ALL, dump_exp_cb, cmd); res = nfexp_query(cth, NFCT_Q_DUMP, &cmd->family); nfct_close(cth); @@ -3211,7 +3263,7 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd) res = nfct_query(cth, NFCT_Q_CREATE, cmd->tmpl.ct); if (res != -1) - counter++; + cmd_counters[cmd->cmd]++; nfct_close(cth); break; @@ -3303,7 +3355,7 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd) if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); - nfexp_callback_register(cth, NFCT_T_ALL, dump_exp_cb, NULL); + nfexp_callback_register(cth, NFCT_T_ALL, dump_exp_cb, cmd); res = nfexp_query(cth, NFCT_Q_GET, cmd->tmpl.exp); nfct_close(cth); break; @@ -3424,7 +3476,7 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd) exit_error(OTHER_PROBLEM, "Can't open handler"); signal(SIGINT, exp_event_sighandler); signal(SIGTERM, exp_event_sighandler); - nfexp_callback_register(cth, NFCT_T_ALL, event_exp_cb, NULL); + nfexp_callback_register(cth, NFCT_T_ALL, event_exp_cb, cmd); res = nfexp_catch(cth); nfct_close(cth); break; @@ -3468,10 +3520,10 @@ try_proc_count: if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); - nfexp_callback_register(cth, NFCT_T_ALL, count_exp_cb, NULL); + nfexp_callback_register(cth, NFCT_T_ALL, count_exp_cb, cmd); res = nfexp_query(cth, NFCT_Q_DUMP, &cmd->family); nfct_close(cth); - printf("%d\n", counter); + printf("%d\n", cmd_counters[cmd->cmd]); break; case CT_STATS: /* If we fail with netlink, fall back to /proc to ensure @@ -3482,7 +3534,7 @@ try_proc_count: res = nfct_mnl_dump(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET_STATS_CPU, - nfct_stats_cb, AF_UNSPEC); + nfct_stats_cb, NULL, AF_UNSPEC); nfct_mnl_socket_close(); @@ -3501,7 +3553,7 @@ try_proc_count: res = nfct_mnl_dump(NFNL_SUBSYS_CTNETLINK_EXP, IPCTNL_MSG_EXP_GET_STATS_CPU, - nfexp_stats_cb, AF_UNSPEC); + nfexp_stats_cb, NULL, AF_UNSPEC); nfct_mnl_socket_close(); @@ -3533,15 +3585,6 @@ try_proc: free_options(); if (labelmap) nfct_labelmap_destroy(labelmap); - - if (cmd->command && exit_msg[cmd->cmd][0]) { - fprintf(stderr, "%s v%s (conntrack-tools): ",PROGNAME,VERSION); - fprintf(stderr, exit_msg[cmd->cmd], counter); - if (counter == 0 && !(cmd->command & (CT_LIST | EXP_LIST))) - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; } int main(int argc, char *argv[]) @@ -3560,5 +3603,7 @@ int main(int argc, char *argv[]) do_parse(cmd, argc, argv); - return do_command_ct(argv[0], cmd); + do_command_ct(argv[0], cmd); + + return print_cmd_counters(); } -- 2.25.1