f016a85bbc5dac0c708aae75c30c32afb6ff87d5
[routeros-api.git] / src / registration_table.c
1 /**
2  * librouteros - src/registration_table.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 <math.h>
34 #include <errno.h>
35 #include <string.h>
36 #include <stdint.h>
37 #include <inttypes.h>
38 #include <assert.h>
39
40 #include "routeros_api.h"
41
42 /*
43 Status: re
44   Param 0: .id = *C
45   Param 1: interface = wlan2
46   Param 2: radio-name = 000C423AECCF
47   Param 3: mac-address = 00:0C:42:3A:EC:CF
48   Param 4: ap = true
49   Param 5: wds = false
50   Param 6: rx-rate = 58.5Mbps-HT
51   Param 7: tx-rate = 52.0Mbps-HT
52   Param 8: packets = 6962070,10208268
53   Param 9: bytes = 1090924066,2872515632
54   Param 10: frames = 6662813,9698341
55   Param 11: frame-bytes = 1111022872,2846535122
56   Param 12: hw-frames = 8338229,9718084
57   Param 13: hw-frame-bytes = 1941643579,3255546365
58   Param 14: tx-frames-timed-out = 0
59   Param 15: uptime = 2w6d13:21:53
60   Param 16: last-activity = 00:00:00.060
61   Param 17: signal-strength = -74dBm@6Mbps
62   Param 18: signal-to-noise = 42
63   Param 19: strength-at-rates = -74dBm@6Mbps 10ms,-78dBm@9Mbps 2w2d16h56m20s890ms,-78dBm@12Mbps 2w2d16h55m51s670ms,-77dBm@18Mbps 2w2d16h55m35s880ms,-78dBm@24Mbps 2w2d16h55m5s590ms,-75dBm@36Mbps 1d10h58m48s840ms,-75dBm@48Mbps 1d10h48m34s130ms,-77dBm@54Mbps 1d10h47m34s680ms,-73dBm@HT20-4 38m45s600ms,-73dBm@HT20-5 4m700ms,-74dBm@HT20-6 60ms,-78dBm@HT20-7 1d10h30m34s410ms
64   Param 20: tx-signal-strength = -76
65   Param 21: tx-ccq = 51
66   Param 22: rx-ccq = 77
67   Param 23: p-throughput = 36877
68   Param 24: ack-timeout = 30
69   Param 25: nstreme = false
70   Param 26: framing-mode = none
71   Param 27: routeros-version = 4.2
72   Param 28: last-ip = 62.128.1.53
73   Param 29: 802.1x-port-enabled = true
74   Param 30: authentication-type = wpa2-psk
75   Param 31: encryption = aes-ccm
76   Param 32: group-encryption = aes-ccm
77   Param 33: compression = false
78   Param 34: wmm-enabled = true
79 ===
80 Status: done
81 ===
82  */
83
84 /*
85  * Private data types
86  */
87 struct rt_internal_data_s
88 {
89         ros_registration_table_handler handler;
90         void *user_data;
91 };
92 typedef struct rt_internal_data_s rt_internal_data_t;
93
94 /*
95  * Private functions
96  */
97 static double sstrtod (const char *str) /* {{{ */
98 {
99         double ret;
100         char *endptr;
101
102         if (str == NULL)
103                 return (NAN);
104
105         errno = 0;
106         endptr = NULL;
107         ret = strtod (str, &endptr);
108         if ((endptr == str) || (errno != 0))
109                 return (NAN);
110
111         return (ret);
112 } /* }}} double sstrtod */
113
114 static int string_to_rx_tx_counters (const char *str, /* {{{ */
115                 uint64_t *rx, uint64_t *tx)
116 {
117         const char *ptr;
118         char *endptr;
119
120         if ((str == NULL) || (rx == NULL) || (tx == NULL))
121                 return (EINVAL);
122
123         ptr = str;
124         errno = 0;
125         endptr = NULL;
126         *rx = (uint64_t) strtoull (ptr, &endptr, /* base = */ 10);
127         if ((endptr == str) || (errno != 0))
128                 return (EIO);
129
130         assert (endptr != NULL);
131         if (*endptr != ',')
132                 return (EIO);
133
134         ptr = endptr + 1;
135         errno = 0;
136         endptr = NULL;
137         *tx = (uint64_t) strtoull (ptr, &endptr, /* base = */ 10);
138         if ((endptr == str) || (errno != 0))
139                 return (EIO);
140
141         return (0);
142 } /* }}} int string_to_rx_tx_counters */
143
144 static ros_registration_table_t *rt_reply_to_regtable (const ros_reply_t *r) /* {{{ */
145 {
146         ros_registration_table_t *ret;
147
148         if (r == NULL)
149                 return (NULL);
150
151         if (strcmp ("re", ros_reply_status (r)) != 0)
152                 return (rt_reply_to_regtable (ros_reply_next (r)));
153
154         ret = malloc (sizeof (*ret));
155         if (ret == NULL)
156                 return (NULL);
157         memset (ret, 0, sizeof (*ret));
158
159         ret->interface = ros_reply_param_val_by_key (r, "interface");
160
161         ret->rx_rate = sstrtod (ros_reply_param_val_by_key (r, "rx-rate"));
162         ret->tx_rate = sstrtod (ros_reply_param_val_by_key (r, "tx-rate"));
163
164         string_to_rx_tx_counters (ros_reply_param_val_by_key (r, "packets"),
165                         &ret->rx_packets, &ret->tx_packets);
166         string_to_rx_tx_counters (ros_reply_param_val_by_key (r, "bytes"),
167                         &ret->rx_bytes, &ret->tx_bytes);
168         string_to_rx_tx_counters (ros_reply_param_val_by_key (r, "frames"),
169                         &ret->rx_frames, &ret->tx_frames);
170         string_to_rx_tx_counters (ros_reply_param_val_by_key (r, "frame-bytes"),
171                         &ret->rx_frame_bytes, &ret->tx_frame_bytes);
172         string_to_rx_tx_counters (ros_reply_param_val_by_key (r, "hw-frames"),
173                         &ret->rx_hw_frames, &ret->tx_hw_frames);
174         string_to_rx_tx_counters (ros_reply_param_val_by_key (r, "hw-frame-bytes"),
175                         &ret->rx_hw_frame_bytes, &ret->tx_hw_frame_bytes);
176
177         ret->rx_signal_strength = sstrtod (ros_reply_param_val_by_key (r, "signal-strength"));
178         ret->tx_signal_strength = sstrtod (ros_reply_param_val_by_key (r, "tx-signal-strength"));
179         ret->signal_to_noise = sstrtod (ros_reply_param_val_by_key (r, "signal-to-noise"));
180
181         ret->rx_ccq = sstrtod (ros_reply_param_val_by_key (r, "rx-ccq"));
182         ret->tx_ccq = sstrtod (ros_reply_param_val_by_key (r, "tx-ccq"));
183
184         ret->next = rt_reply_to_regtable (ros_reply_next (r));
185
186         return (ret);
187 } /* }}} ros_registration_table_t *rt_reply_to_regtable */
188
189 static void rt_regtable_free (ros_registration_table_t *r) /* {{{ */
190 {
191         ros_registration_table_t *next;
192
193         while (r != NULL)
194         {
195                 next = r->next;
196                 free (r);
197                 r = next;
198         }
199 } /* }}} void rt_regtable_free */
200
201 static int rt_internal_handler (ros_connection_t *c, /* {{{ */
202                 const ros_reply_t *r, void *user_data)
203 {
204         ros_registration_table_t *rt_data;
205         rt_internal_data_t *internal_data;
206         int status;
207
208         rt_data = rt_reply_to_regtable (r);
209         if (rt_data == NULL)
210                 return (errno);
211
212         internal_data = user_data;
213
214         status = internal_data->handler (c, rt_data, internal_data->user_data);
215
216         rt_regtable_free (rt_data);
217
218         return (status);
219 } /* }}} int rt_internal_handler */
220
221 /*
222  * Public functions
223  */
224 int ros_registration_table (ros_connection_t *c, /* {{{ */
225                 ros_registration_table_handler handler, void *user_data)
226 {
227         rt_internal_data_t data;
228
229         if ((c == NULL) || (handler == NULL))
230                 return (EINVAL);
231
232         data.handler = handler;
233         data.user_data = user_data;
234
235         return (ros_query (c, "/interface/wireless/registration-table/print",
236                                 /* args_num = */ 0, /* args = */ NULL,
237                                 rt_internal_handler, &data));
238 } /* }}} int ros_registration_table */
239
240 /* vim: set ts=2 sw=2 noet fdm=marker : */