diff --git a/zebra/main.c b/zebra/main.c index c8d7f83fb750..a0470251335e 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -49,6 +49,7 @@ #include "zebra/zebra_mpls.h" #include "zebra/label_manager.h" #include "zebra/zebra_netns_notify.h" +#include "zebra/zebra_wrap_script.h" #define ZEBRA_PTM_SUPPORT @@ -306,6 +307,7 @@ int main(int argc, char **argv) zebrad.master = frr_init(); /* Zebra related initialize. */ + zebra_wrap_init(); zserv_init(); rib_init(); zebra_if_init(); diff --git a/zebra/subdir.am b/zebra/subdir.am index 9dbff7d40c1b..47b3f361dd0c 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -71,6 +71,7 @@ zebra_zebra_SOURCES = \ zebra/zebra_netns_id.c \ zebra/zebra_netns_notify.c \ zebra/table_manager.c \ + zebra/zebra_wrap_script.c \ # end zebra/zebra_vty_clippy.c: $(CLIPPY_DEPS) @@ -115,6 +116,7 @@ noinst_HEADERS += \ zebra/zebra_netns_id.h \ zebra/zebra_netns_notify.h \ zebra/table_manager.h \ + zebra/zebra_wrap_script.h \ # end zebra_zebra_irdp_la_SOURCES = \ diff --git a/zebra/zebra_wrap_script.c b/zebra/zebra_wrap_script.c new file mode 100644 index 000000000000..68454aa62aed --- /dev/null +++ b/zebra/zebra_wrap_script.c @@ -0,0 +1,236 @@ +/* + * Zebra Script Wrapper + * Copyright (C) 2018 6WIND + * + * FRR is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * FRR is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FRR; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include + +#include "json.h" + +#include "zebra/debug.h" +#include "zebra/zebra_wrap_script.h" + +/* this struct temporarily stores the list of headers + * - name is used to store the name of the header field + * - attribute can be used to store values that have no column + * assigned ( extra param) + * ex: + * columnA columnB columnC columnD + * .. + * .. + * columnA .. columnD are stored in name field + * attribute us used to store .. or .. + */ +struct item_list { + char *name; + char *attribute; +}; + +#define SCRIPT_DEBUG (1<<1) +#define SCRIPT_ITEM_LIST (1<<2) +#define SCRIPT_ELEMENT_LIST (1<<3) + +static int zebra_wrap_debug; + + +void zebra_wrap_init(void) +{ + zebra_wrap_debug = 0; +} + + +/* script : command line to execute in a shell script + * return_data : set to true if want to get back some information + * begin_at_line : the line number where to begin parsing headers and other + * - ex: following dump example begins at line 2, where header is located + * # iptables -t mangle -L PREROUTING -v + * Chain PREROUTING (policy ACCEPT 150k packets, 7426 bytes) (## line 0) + * pkts bytes target prot opt in out source destination (## line 1) + * 0 0 DROP all -- any any anywhere anywhere match-set match0x55f44 + * (## line 2) + * json_obj_list : the json structure mapped to the output, ranked with linu number + * - ex: above dump gives following + * { "2":{"pkts":"0","bytes":"0","target":"MARK","prot":"all","opt":"--","in":"any",..}} + */ + +int zebra_wrap_script(char *script, bool return_data, + int begin_at_line, struct json_object *json_obj_list) +{ +#define DATA_LEN 4096 +#define ITEM_MAXIMUM 15 +#define DATA_LINE_MAX 200 + FILE *fp; + char data[DATA_LEN]; + struct item_list item[ITEM_MAXIMUM]; + char *current_str = NULL; + int line_nb = 0, i; + + /* initialise item list + */ + for (i = 0; i < ITEM_MAXIMUM; i++) + memset(&item[i], 0, sizeof(struct item_list)); + if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) + zlog_debug("SCRIPT : %s", script); + fp = popen(script, "r"); + if (!fp) { + zlog_err("NETLINK: error calling %s", script); + return -1; + } + if (!return_data) { + if (pclose(fp)) + zlog_err("NETLINK: error closing stream with %s", script); + return -1; + } + do { + json_object *json_obj = NULL; + int nb_items = 0; + bool keep_item = false; + + memset(data, 0, DATA_LEN); + current_str = fgets(data, DATA_LEN, fp); + if (current_str) { + /* data contains the line + */ + current_str = data; + nb_items = 0; + if (zebra_wrap_debug & SCRIPT_DEBUG) + zlog_debug("SCRIPT : [%d/%d] %s", line_nb, + (int)strlen(current_str), current_str); + if (strlen(current_str) <= 1) + continue; + if (line_nb >= begin_at_line) { + int k, l = 0; + char current_word[DATA_LINE_MAX]; + char *ptr_word; + bool search_word = false; + bool word_began = false; + + if (line_nb > begin_at_line) + json_obj = json_object_new_object(); + /* get headers from current_str */ + for (k = 0; k < (int)strlen(current_str); k++) { + if (search_word == true) { + search_word = false; + word_began = false; + } + /* a word is made up of a char or a digit + * or a character between '!' and '/' + */ + if (word_began == false && + (isalpha(current_str[k]) || isdigit(current_str[k]) + || (current_str[k] > 0x21 && current_str[k] < 0x2f))) { + ptr_word = &(current_str[k]); + word_began = true; + l = 0; + } + l++; + if (word_began == false) + continue; + if (word_began == true && + !isspace(current_str[k])) + continue; + memcpy(current_word, ptr_word, l - 1); + current_word[l - 1] = '\0'; + if (line_nb == begin_at_line) { + if (zebra_wrap_debug & SCRIPT_ITEM_LIST) + zlog_err("SCRIPT: (%d)ITEM %s ", nb_items, current_word); + item[nb_items].name = XSTRDUP(MTYPE_TMP, current_word); + } else { + if (!item[nb_items].name) { + item[nb_items].name = XSTRDUP(MTYPE_TMP, "misc"); + keep_item = true; + item[nb_items].attribute = XSTRDUP(MTYPE_TMP, current_word); + } else if (item[nb_items].attribute) { + /* store last elements in attribute + */ + char temp_word[DATA_LINE_MAX]; + + snprintf(temp_word, + DATA_LINE_MAX, + "%s %s", + item[nb_items].attribute, + current_word); + XFREE(MTYPE_TMP, item[nb_items].attribute); + item[nb_items].attribute = + XSTRDUP(MTYPE_TMP, temp_word); + } + if (!keep_item) { + json_object_string_add(json_obj, + item[nb_items].name, + current_word); + if (zebra_wrap_debug & SCRIPT_ELEMENT_LIST) + zlog_err("(%d)ITEM Obtained for %s is %s", + nb_items,item[nb_items].name, + current_word); + } + } + if (!keep_item) + nb_items++; + if (nb_items >= ITEM_MAXIMUM) { + int m; + + for (m = 0; m < ITEM_MAXIMUM; m++) + XFREE(MTYPE_TMP, item[m].name); + json_object_free(json_obj); + return -1; + } + search_word = true; + } + /* store last attribute to json + */ + if (keep_item) { + json_object_string_add(json_obj, + item[nb_items].name, + item[nb_items].attribute); + if (zebra_wrap_debug & SCRIPT_ITEM_LIST) + zlog_err("(%d)ITEM Obtained for %s is %s", + nb_items,item[nb_items].name, + item[nb_items].attribute); + XFREE(MTYPE_TMP, item[nb_items].attribute); + item[nb_items].attribute = NULL; + XFREE(MTYPE_TMP, item[nb_items].name); + item[nb_items].name = NULL; + } + if (line_nb > begin_at_line) { + char line[10]; + + snprintf(line, sizeof(line), "%d", line_nb); + json_object_object_add(json_obj_list, line, json_obj); + } + } + line_nb++; + } + } while (current_str != NULL); + /* initialise item list + */ + for (i = 0; i < ITEM_MAXIMUM; i++) { + if (item[i].name) { + XFREE(MTYPE_TMP, item[i].name); + item[i].name = NULL; + } + } + if (pclose(fp)) + zlog_err("NETLINK: error closing stream with %s", script); + return 0; +} + +int zebra_wrap_script_call_only(char *script) +{ + zebra_wrap_script(script, false, 0, NULL); + return 0; +} diff --git a/zebra/zebra_wrap_script.h b/zebra/zebra_wrap_script.h new file mode 100644 index 000000000000..eb7d2b077cb7 --- /dev/null +++ b/zebra/zebra_wrap_script.h @@ -0,0 +1,34 @@ +/* + * Zebra Wrap Script Definitions + * Copyright (C) 2018 6WIND + * + * FRR is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * FRR is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FRR; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _ZEBRA_WRAP_SCRIPT_H +#define _ZEBRA_WRAP_SCRIPT_H + +#include + +struct json_object; +extern int zebra_wrap_script(char *script, bool return_data, + int begin_at_line, struct json_object *json); + +extern int zebra_wrap_script_call_only(char *script); + +extern void zebra_wrap_init(void); + +#endif /* _ZEBRA_WRAP_SCRIPT_H */