Added high-level interface for "/interface/print".
[routeros-api.git] / src / interface.c
1 /**
2  * librouteros - src/interface.c
3  * Copyright (C) 2009  Florian octo Forster
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; only version 2 of the License is applicable.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
17  *
18  * Authors:
19  *   Florian octo Forster <octo at verplant.org>
20  **/
21
22 #ifndef _ISOC99_SOURCE
23 # define _ISOC99_SOURCE
24 #endif
25
26 #ifndef _POSIX_C_SOURCE
27 # define _POSIX_C_SOURCE 200112L
28 #endif
29
30 #include "config.h"
31
32 #include <stdlib.h>
33 #include <stdbool.h>
34 #include <math.h>
35 #include <errno.h>
36 #include <string.h>
37 #include <strings.h>
38 #include <stdint.h>
39 #include <inttypes.h>
40 #include <assert.h>
41
42 #include "routeros_api.h"
43
44 /*
45  * Private data types
46  */
47 struct rt_internal_data_s
48 {
49         ros_interface_handler handler;
50         void *user_data;
51 };
52 typedef struct rt_internal_data_s rt_internal_data_t;
53
54 /*
55  * Private functions
56  */
57 static unsigned int sstrtoui (const char *str) /* {{{ */
58 {
59         unsigned int ret;
60         char *endptr;
61
62         if (str == NULL)
63                 return (0);
64
65         errno = 0;
66         endptr = NULL;
67         ret = (unsigned int) strtoul (str, &endptr, /* base = */ 10);
68         if ((endptr == str) || (errno != 0))
69                 return (0);
70
71         return (ret);
72 } /* }}} unsigned int sstrtoui */
73
74 static _Bool sstrtob (const char *str) /* {{{ */
75 {
76         if (str == NULL)
77                 return (false);
78
79         if (strcasecmp ("true", str) == 0)
80                 return (true);
81         return (false);
82 } /* }}} _Bool sstrtob */
83
84 static int string_to_rx_tx_counters (const char *str, /* {{{ */
85                 uint64_t *rx, uint64_t *tx)
86 {
87         const char *ptr;
88         char *endptr;
89
90         if ((rx == NULL) || (tx == NULL))
91                 return (EINVAL);
92
93         *rx = 0;
94         *tx = 0;
95
96         if (str == NULL)
97                 return (EINVAL);
98
99         ptr = str;
100         errno = 0;
101         endptr = NULL;
102         *rx = (uint64_t) strtoull (ptr, &endptr, /* base = */ 10);
103         if ((endptr == str) || (errno != 0))
104                 return (EIO);
105
106         assert (endptr != NULL);
107         if (*endptr != '/')
108                 return (EIO);
109
110         ptr = endptr + 1;
111         errno = 0;
112         endptr = NULL;
113         *tx = (uint64_t) strtoull (ptr, &endptr, /* base = */ 10);
114         if ((endptr == str) || (errno != 0))
115                 return (EIO);
116
117         return (0);
118 } /* }}} int string_to_rx_tx_counters */
119
120 static ros_interface_t *rt_reply_to_interface (const ros_reply_t *r) /* {{{ */
121 {
122         ros_interface_t *ret;
123
124         if (r == NULL)
125                 return (NULL);
126
127         if (strcmp ("re", ros_reply_status (r)) != 0)
128                 return (rt_reply_to_interface (ros_reply_next (r)));
129
130         ret = malloc (sizeof (*ret));
131         if (ret == NULL)
132                 return (NULL);
133         memset (ret, 0, sizeof (*ret));
134
135         ret->name = ros_reply_param_val_by_key (r, "name");
136         ret->type = ros_reply_param_val_by_key (r, "type");
137         ret->comment = ros_reply_param_val_by_key (r, "comment");
138
139         string_to_rx_tx_counters (ros_reply_param_val_by_key (r, "packets"),
140                         &ret->rx_packets, &ret->tx_packets);
141         string_to_rx_tx_counters (ros_reply_param_val_by_key (r, "bytes"),
142                         &ret->rx_bytes, &ret->tx_bytes);
143         string_to_rx_tx_counters (ros_reply_param_val_by_key (r, "errors"),
144                         &ret->rx_errors, &ret->tx_errors);
145         string_to_rx_tx_counters (ros_reply_param_val_by_key (r, "drops"),
146                         &ret->rx_drops, &ret->tx_drops);
147
148         ret->mtu = sstrtoui (ros_reply_param_val_by_key (r, "mtu"));
149         ret->l2mtu = sstrtoui (ros_reply_param_val_by_key (r, "l2mtu"));
150
151         ret->dynamic = sstrtob (ros_reply_param_val_by_key (r, "dynamic"));
152         ret->running = sstrtob (ros_reply_param_val_by_key (r, "running"));
153         ret->enabled = !sstrtob (ros_reply_param_val_by_key (r, "disabled"));
154
155         ret->next = rt_reply_to_interface (ros_reply_next (r));
156
157         return (ret);
158 } /* }}} ros_interface_t *rt_reply_to_interface */
159
160 static void if_interface_free (ros_interface_t *r) /* {{{ */
161 {
162         ros_interface_t *next;
163
164         while (r != NULL)
165         {
166                 next = r->next;
167                 free (r);
168                 r = next;
169         }
170 } /* }}} void if_interface_free */
171
172 static int if_internal_handler (ros_connection_t *c, /* {{{ */
173                 const ros_reply_t *r, void *user_data)
174 {
175         ros_interface_t *if_data;
176         rt_internal_data_t *internal_data;
177         int status;
178
179         if_data = rt_reply_to_interface (r);
180         if (if_data == NULL)
181                 return (errno);
182
183         internal_data = user_data;
184
185         status = internal_data->handler (c, if_data, internal_data->user_data);
186
187         if_interface_free (if_data);
188
189         return (status);
190 } /* }}} int if_internal_handler */
191
192 /*
193  * Public functions
194  */
195 int ros_interface (ros_connection_t *c, /* {{{ */
196                 ros_interface_handler handler, void *user_data)
197 {
198         rt_internal_data_t data;
199
200         if ((c == NULL) || (handler == NULL))
201                 return (EINVAL);
202
203         data.handler = handler;
204         data.user_data = user_data;
205
206         return (ros_query (c, "/interface/print",
207                                 /* args_num = */ 0, /* args = */ NULL,
208                                 if_internal_handler, &data));
209 } /* }}} int ros_interface */
210
211 /* vim: set ts=2 sw=2 noet fdm=marker : */