From dbcdf705de2d750ae3a23e91bbdfb8fced96fc09 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Thu, 26 Nov 2009 16:17:50 +0100 Subject: [PATCH] Added high-level interface for "/interface/print". --- src/Makefile.am | 2 +- src/interface.c | 211 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/routeros_api.h | 46 +++++++++++- 3 files changed, 255 insertions(+), 4 deletions(-) create mode 100644 src/interface.c diff --git a/src/Makefile.am b/src/Makefile.am index afb8331..89d6c07 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,7 +15,7 @@ librouteros_la_LIBADD = -lgcrypt if BUILD_WITH_LIBSOCKET librouteros_la_LIBADD += -lsocket endif -librouteros_la_SOURCES = main.c registration_table.c routeros_api.h routeros_version.h +librouteros_la_SOURCES = main.c registration_table.c interface.c routeros_api.h routeros_version.h bin_PROGRAMS = ros diff --git a/src/interface.c b/src/interface.c new file mode 100644 index 0000000..de62eeb --- /dev/null +++ b/src/interface.c @@ -0,0 +1,211 @@ +/** + * librouteros - src/interface.c + * Copyright (C) 2009 Florian octo Forster + * + * This program 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; only version 2 of the License is applicable. + * + * This program 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Florian octo Forster + **/ + +#ifndef _ISOC99_SOURCE +# define _ISOC99_SOURCE +#endif + +#ifndef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 200112L +#endif + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "routeros_api.h" + +/* + * Private data types + */ +struct rt_internal_data_s +{ + ros_interface_handler handler; + void *user_data; +}; +typedef struct rt_internal_data_s rt_internal_data_t; + +/* + * Private functions + */ +static unsigned int sstrtoui (const char *str) /* {{{ */ +{ + unsigned int ret; + char *endptr; + + if (str == NULL) + return (0); + + errno = 0; + endptr = NULL; + ret = (unsigned int) strtoul (str, &endptr, /* base = */ 10); + if ((endptr == str) || (errno != 0)) + return (0); + + return (ret); +} /* }}} unsigned int sstrtoui */ + +static _Bool sstrtob (const char *str) /* {{{ */ +{ + if (str == NULL) + return (false); + + if (strcasecmp ("true", str) == 0) + return (true); + return (false); +} /* }}} _Bool sstrtob */ + +static int string_to_rx_tx_counters (const char *str, /* {{{ */ + uint64_t *rx, uint64_t *tx) +{ + const char *ptr; + char *endptr; + + if ((rx == NULL) || (tx == NULL)) + return (EINVAL); + + *rx = 0; + *tx = 0; + + if (str == NULL) + return (EINVAL); + + ptr = str; + errno = 0; + endptr = NULL; + *rx = (uint64_t) strtoull (ptr, &endptr, /* base = */ 10); + if ((endptr == str) || (errno != 0)) + return (EIO); + + assert (endptr != NULL); + if (*endptr != '/') + return (EIO); + + ptr = endptr + 1; + errno = 0; + endptr = NULL; + *tx = (uint64_t) strtoull (ptr, &endptr, /* base = */ 10); + if ((endptr == str) || (errno != 0)) + return (EIO); + + return (0); +} /* }}} int string_to_rx_tx_counters */ + +static ros_interface_t *rt_reply_to_interface (const ros_reply_t *r) /* {{{ */ +{ + ros_interface_t *ret; + + if (r == NULL) + return (NULL); + + if (strcmp ("re", ros_reply_status (r)) != 0) + return (rt_reply_to_interface (ros_reply_next (r))); + + ret = malloc (sizeof (*ret)); + if (ret == NULL) + return (NULL); + memset (ret, 0, sizeof (*ret)); + + ret->name = ros_reply_param_val_by_key (r, "name"); + ret->type = ros_reply_param_val_by_key (r, "type"); + ret->comment = ros_reply_param_val_by_key (r, "comment"); + + string_to_rx_tx_counters (ros_reply_param_val_by_key (r, "packets"), + &ret->rx_packets, &ret->tx_packets); + string_to_rx_tx_counters (ros_reply_param_val_by_key (r, "bytes"), + &ret->rx_bytes, &ret->tx_bytes); + string_to_rx_tx_counters (ros_reply_param_val_by_key (r, "errors"), + &ret->rx_errors, &ret->tx_errors); + string_to_rx_tx_counters (ros_reply_param_val_by_key (r, "drops"), + &ret->rx_drops, &ret->tx_drops); + + ret->mtu = sstrtoui (ros_reply_param_val_by_key (r, "mtu")); + ret->l2mtu = sstrtoui (ros_reply_param_val_by_key (r, "l2mtu")); + + ret->dynamic = sstrtob (ros_reply_param_val_by_key (r, "dynamic")); + ret->running = sstrtob (ros_reply_param_val_by_key (r, "running")); + ret->enabled = !sstrtob (ros_reply_param_val_by_key (r, "disabled")); + + ret->next = rt_reply_to_interface (ros_reply_next (r)); + + return (ret); +} /* }}} ros_interface_t *rt_reply_to_interface */ + +static void if_interface_free (ros_interface_t *r) /* {{{ */ +{ + ros_interface_t *next; + + while (r != NULL) + { + next = r->next; + free (r); + r = next; + } +} /* }}} void if_interface_free */ + +static int if_internal_handler (ros_connection_t *c, /* {{{ */ + const ros_reply_t *r, void *user_data) +{ + ros_interface_t *if_data; + rt_internal_data_t *internal_data; + int status; + + if_data = rt_reply_to_interface (r); + if (if_data == NULL) + return (errno); + + internal_data = user_data; + + status = internal_data->handler (c, if_data, internal_data->user_data); + + if_interface_free (if_data); + + return (status); +} /* }}} int if_internal_handler */ + +/* + * Public functions + */ +int ros_interface (ros_connection_t *c, /* {{{ */ + ros_interface_handler handler, void *user_data) +{ + rt_internal_data_t data; + + if ((c == NULL) || (handler == NULL)) + return (EINVAL); + + data.handler = handler; + data.user_data = user_data; + + return (ros_query (c, "/interface/print", + /* args_num = */ 0, /* args = */ NULL, + if_internal_handler, &data)); +} /* }}} int ros_interface */ + +/* vim: set ts=2 sw=2 noet fdm=marker : */ diff --git a/src/routeros_api.h b/src/routeros_api.h index 16ea503..8c6b823 100644 --- a/src/routeros_api.h +++ b/src/routeros_api.h @@ -72,9 +72,48 @@ const char *ros_reply_param_val_by_index (const ros_reply_t *r, unsigned int index); const char *ros_reply_param_val_by_key (const ros_reply_t *r, const char *key); -/* - * High-level function for accessing /interface/wireless/registration-table - */ +/* High-level function for accessing /interface {{{ */ +struct ros_interface_s; +typedef struct ros_interface_s ros_interface_t; +struct ros_interface_s +{ + /* Name of the interface */ + const char *name; + const char *type; + const char *comment; + + /* Packet, octet and error counters. */ + uint64_t rx_packets; + uint64_t tx_packets; + uint64_t rx_bytes; + uint64_t tx_bytes; + uint64_t rx_errors; + uint64_t tx_errors; + uint64_t rx_drops; + uint64_t tx_drops; + + /* Maximum transfer unit */ + unsigned int mtu; + unsigned int l2mtu; + + /* Interface flags */ + _Bool dynamic; + _Bool running; + _Bool enabled; + + /* Next interface */ + ros_interface_t *next; +}; + +/* Callback function */ +typedef int (*ros_interface_handler) (ros_connection_t *c, + const ros_interface_t *i, void *user_data); + +int ros_interface (ros_connection_t *c, + ros_interface_handler handler, void *user_data); +/* }}} /interface */ + +/* High-level function for accessing /interface/wireless/registration-table {{{ */ struct ros_registration_table_s; typedef struct ros_registration_table_s ros_registration_table_t; struct ros_registration_table_s @@ -119,6 +158,7 @@ typedef int (*ros_registration_table_handler) (ros_connection_t *c, int ros_registration_table (ros_connection_t *c, ros_registration_table_handler handler, void *user_data); +/* }}} /interface/wireless/registration-table */ #ifdef __cplusplus } -- 2.11.0