Jerome Stanislaus | 597482d | 2016-03-04 14:08:46 -0700 | [diff] [blame] | 1 | /************************************************************************ |
| 2 | Copyright (c) 2016, The Linux Foundation. All rights reserved. |
| 3 | |
| 4 | Redistribution and use in source and binary forms, with or without |
| 5 | modification, are permitted provided that the following conditions are |
| 6 | met: |
| 7 | * Redistributions of source code must retain the above copyright |
| 8 | notice, this list of conditions and the following disclaimer. |
| 9 | * Redistributions in binary form must reproduce the above |
| 10 | copyright notice, this list of conditions and the following |
| 11 | disclaimer in the documentation and/or other materials provided |
| 12 | with the distribution. |
| 13 | * Neither the name of The Linux Foundation nor the names of its |
| 14 | contributors may be used to endorse or promote products derived |
| 15 | from this software without specific prior written permission. |
| 16 | |
| 17 | THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| 18 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| 19 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| 21 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| 24 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 25 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| 26 | OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| 27 | IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 | ************************************************************************/ |
| 29 | |
| 30 | /** |
| 31 | * @file datatop_ip_table_poll.c |
| 32 | * @brief Adds ability for TP Tables, Rules and Routes data collection |
| 33 | Unlike other polls, this is intended for running as a separate |
| 34 | thread as it can cause delays of > 3sec per poll |
| 35 | * |
| 36 | */ |
| 37 | |
| 38 | #include <stdio.h> |
| 39 | #include <string.h> |
| 40 | #include <stdlib.h> |
| 41 | #include <unistd.h> |
| 42 | #include <time.h> |
| 43 | #include <pthread.h> |
| 44 | #include "datatop_interface.h" |
| 45 | #include "datatop_fileops.h" |
| 46 | #include "datatop_str.h" |
| 47 | #include "datatop_polling.h" |
| 48 | |
| 49 | #define DTOP_IPTRR_POLL_PERIOD 5.00 |
| 50 | |
| 51 | /** |
| 52 | * @struct dtop_ip_table_vars |
| 53 | * @brief Struct used to hold necessary variables for /proc/stat dpg |
| 54 | * |
| 55 | * @var dtop_ip_table_vars::line |
| 56 | * Array of strings where necessary dp names and values are held. |
| 57 | * @var dtop_ip_table_vars::line_count |
| 58 | * Number of lines the file is that the dpg represents. |
| 59 | */ |
| 60 | struct dtop_ip_table_vars { |
| 61 | char *out_dir; |
| 62 | }dtop_ip_table_storage; |
| 63 | |
| 64 | struct dtop_linked_list *ip_dpg_list = NULL; |
| 65 | |
| 66 | pthread_mutex_t dtop_ip_table_lock; |
| 67 | |
| 68 | /** |
| 69 | * @brief Perform IP table command and store it in a file |
| 70 | * |
| 71 | * @param dpg Struct that polled data is added to. |
| 72 | * @return DTOP_POLL_IO_ERR - Poll of dpg unsuccessful. |
| 73 | * @return DTOP_POLL_OK - Poll of dpg successful. |
| 74 | */ |
| 75 | int dtop_ip_table_poll(struct dtop_data_point_gatherer *dpg) |
| 76 | { |
| 77 | FILE *fd; |
| 78 | FILE *fo = (FILE *)dpg->file; |
| 79 | char buf[1001]; |
| 80 | |
| 81 | time_t rawtime; |
| 82 | struct tm * timeinfo; |
| 83 | |
| 84 | if(fo == NULL) |
| 85 | { |
| 86 | fprintf(stderr, "Could not fopen: %s\n", dpg->file); |
| 87 | return DTOP_POLL_IO_ERR; |
| 88 | } |
| 89 | |
| 90 | time ( &rawtime ); |
| 91 | timeinfo = gmtime ( &rawtime ); |
| 92 | |
| 93 | fprintf ( fo, "============\nStart: %s==========\n", asctime (timeinfo) ); |
| 94 | fflush(fo); |
| 95 | |
| 96 | /* redirect stderr to output file */ |
| 97 | dup2(fileno(fo), 2); |
| 98 | |
| 99 | fd = popen((char *)dpg->priv, "r"); |
| 100 | if(fd == NULL) |
| 101 | { |
| 102 | fprintf(stderr, "Could not popen: %s\n", (char *)dpg->priv); |
| 103 | return DTOP_POLL_IO_ERR; |
| 104 | } |
| 105 | |
| 106 | while(fgets(buf, 1000, fd) != NULL) |
| 107 | { |
| 108 | fputs(buf, fo); |
| 109 | } |
| 110 | |
| 111 | fprintf ( fo, "============\nEnd: %s==========\n\n", asctime (timeinfo) ); |
| 112 | fflush(fo); |
| 113 | pclose(fd); |
| 114 | return DTOP_POLL_OK; |
| 115 | } |
| 116 | |
| 117 | /** |
| 118 | * @brief Frees dynamically allocated IP table dpg. |
| 119 | * |
| 120 | * Frees the memory of the dpg along with it's data_points |
| 121 | * and other malloc'd memory no longer needed. |
| 122 | * |
| 123 | * @param dpg Dpg to deconstruct and deallocate memory for. |
| 124 | */ |
| 125 | static void dtop_ip_table_dpg_deconstructor |
| 126 | (struct dtop_data_point_gatherer *dpset) |
| 127 | { |
Jerome Stanislaus | 597482d | 2016-03-04 14:08:46 -0700 | [diff] [blame] | 128 | free(dpset->prefix); |
| 129 | if(dpset->file) |
| 130 | { |
| 131 | fclose((FILE *)dpset->file); |
| 132 | } |
| 133 | |
| 134 | free(dpset); |
| 135 | } |
| 136 | |
| 137 | /** |
| 138 | * @brief Registers a new IP table dpg to the list. |
| 139 | * |
| 140 | * @param dpg Dpg to construct and allocate memory for. |
| 141 | */ |
| 142 | void dtop_ip_table_register(struct dtop_data_point_gatherer *dpg) |
| 143 | { |
| 144 | if (dpg) |
| 145 | ip_dpg_list = dtop_add_linked_list(dpg, ip_dpg_list); |
| 146 | } |
| 147 | |
| 148 | /** |
| 149 | * @brief Open the files for writing the output for each dpg. |
| 150 | * |
| 151 | * @param None |
| 152 | */ |
| 153 | int dtop_ip_table_init_files() |
| 154 | { |
| 155 | struct dtop_data_point_gatherer *dpset; |
| 156 | struct dtop_linked_list *curr_ptr = ip_dpg_list; |
| 157 | FILE *fd; |
| 158 | |
| 159 | while(curr_ptr) |
| 160 | { |
| 161 | dpset = (struct dtop_data_point_gatherer *) curr_ptr->data; |
| 162 | fd = fopen(dpset->prefix, "a+"); |
| 163 | if(!fd) |
| 164 | { |
| 165 | fprintf(stderr, "Could not fopen: %s\n", dpset->prefix); |
| 166 | return DTOP_POLL_IO_ERR; |
| 167 | } |
| 168 | dpset->file = (char *)fd; |
| 169 | curr_ptr = curr_ptr->next_ptr; |
| 170 | } |
| 171 | return DTOP_POLL_OK; |
| 172 | } |
| 173 | |
| 174 | /** |
| 175 | * @brief Perform cleanup of IP table dgp list at exit. |
| 176 | * |
| 177 | * @param None |
| 178 | */ |
| 179 | void dtop_ip_table_poll_cleanup() |
| 180 | { |
Jerome Stanislaus | 597482d | 2016-03-04 14:08:46 -0700 | [diff] [blame] | 181 | pthread_mutex_lock(&dtop_ip_table_lock); |
| 182 | deconstruct_dpgs(ip_dpg_list); |
| 183 | dtop_rem_linked_list(ip_dpg_list); |
| 184 | pthread_mutex_unlock(&dtop_ip_table_lock); |
| 185 | |
| 186 | } |
| 187 | |
| 188 | /** |
| 189 | * @brief The thread to poll for IP table data. |
| 190 | * |
| 191 | * @param arg ptr |
| 192 | */ |
| 193 | void *dtop_ip_table_start_poll(void *arg) |
| 194 | { |
| 195 | time_t start_t, curr_t; |
| 196 | double diff_t = 9999999.00; /* some high # > DTOP_IPTRR_POLL_PERIOD */ |
| 197 | int ret = DTOP_POLL_OK; |
| 198 | |
Sean Tranchetti | 48ccbdb | 2018-04-03 15:18:51 -0600 | [diff] [blame] | 199 | (void) arg; |
| 200 | |
Jerome Stanislaus | 597482d | 2016-03-04 14:08:46 -0700 | [diff] [blame] | 201 | if (pthread_mutex_init(&dtop_ip_table_lock, NULL) != 0) |
| 202 | { |
| 203 | printf("\n mutex init failed\n"); |
| 204 | return NULL; |
| 205 | } |
| 206 | |
| 207 | atexit(dtop_ip_table_poll_cleanup); |
| 208 | |
| 209 | if(DTOP_POLL_OK != ( ret = dtop_ip_table_init_files())) |
| 210 | { |
| 211 | return NULL; |
| 212 | } |
| 213 | |
| 214 | while(1) |
| 215 | { |
| 216 | struct dtop_linked_list *curr_ptr = ip_dpg_list; |
| 217 | struct dtop_data_point_gatherer *dpset; |
| 218 | |
| 219 | pthread_mutex_lock(&dtop_ip_table_lock); |
| 220 | |
| 221 | if (diff_t >= DTOP_IPTRR_POLL_PERIOD) |
| 222 | { |
| 223 | printf("Poll for IP Tables, Rules & Routes\n"); |
| 224 | time(&start_t); |
| 225 | while (curr_ptr) |
| 226 | { |
| 227 | dpset = (struct dtop_data_point_gatherer *) curr_ptr->data; |
| 228 | dpset->poll(dpset); |
| 229 | curr_ptr = curr_ptr->next_ptr; |
| 230 | } |
| 231 | } |
| 232 | pthread_mutex_unlock(&dtop_ip_table_lock); |
| 233 | |
| 234 | /* sleep for 500 milliseconds */ |
| 235 | usleep(500 * 1000); |
| 236 | time(&curr_t); |
| 237 | diff_t = difftime(curr_t, start_t); |
| 238 | } |
| 239 | return NULL; |
| 240 | } |
| 241 | |
| 242 | /** |
| 243 | * @brief Creates a dpg for ip table command |
| 244 | * |
| 245 | * Dynamically allocates memory for dpg which is then added to a linked list |
| 246 | * via the dtop_register(dpg) function call. |
| 247 | * |
| 248 | * @param data_points dtop_data_point struct that dpg points to. |
| 249 | * @param storage dtop_ip_table_vars struct that holds relevant dpg variables. |
| 250 | */ |
| 251 | /*static void construct_ip_table_dpg(struct dtop_data_point |
| 252 | *data_points, struct dtop_ip_table_vars *command, int dp_count) |
| 253 | */ |
| 254 | static void construct_ip_table_dpg(char *command) |
| 255 | { |
| 256 | struct dtop_data_point_gatherer *dpg = malloc |
| 257 | (sizeof(struct dtop_data_point_gatherer)); |
| 258 | char *file_name = (char *)malloc(strlen(command)+ 1 + 1 + strlen(dtop_ip_table_storage.out_dir) + 4); |
| 259 | int i, fname_start_ind; |
| 260 | |
| 261 | strcpy(file_name, dtop_ip_table_storage.out_dir); |
| 262 | strcat(file_name, "/"); |
| 263 | |
| 264 | fname_start_ind = strlen(file_name); |
| 265 | strcat(file_name, command); |
| 266 | strcat(file_name, ".txt"); |
| 267 | |
| 268 | for(i=fname_start_ind; file_name[i]; i++) |
| 269 | { |
| 270 | if(file_name[i] == ' ') |
| 271 | file_name[i] = '_'; |
| 272 | if(file_name[i] == '/') |
| 273 | file_name[i] = '-'; |
| 274 | } |
| 275 | |
| 276 | dpg->prefix = file_name; |
| 277 | dpg->poll = dtop_ip_table_poll; |
| 278 | dpg->priv = (char *)command; |
| 279 | dpg->file = NULL; |
| 280 | dpg->deconstruct = dtop_ip_table_dpg_deconstructor; |
| 281 | |
| 282 | dtop_ip_table_register(dpg); |
| 283 | } |
| 284 | |
| 285 | /* |
| 286 | * @brief Scans "/proc/stat" in order to autodetect dps. |
| 287 | * |
| 288 | * Searches through "/proc/stat" file for all available data |
| 289 | * points to create as dp structs. |
| 290 | * |
| 291 | * @param storage dtop_ip_table_vars struct where relevant variables are stored. |
| 292 | */ |
| 293 | |
| 294 | /** |
| 295 | * @brief Calls dtop_search for "/proc/stat" file. |
| 296 | */ |
| 297 | void dtop_ip_table_init(char *out_dir) |
| 298 | { |
| 299 | dtop_ip_table_storage.out_dir = out_dir; |
| 300 | construct_ip_table_dpg("ip xfrm state show"); |
| 301 | construct_ip_table_dpg("ip xfrm policy show"); |
| 302 | construct_ip_table_dpg("ip addr"); |
| 303 | construct_ip_table_dpg("iptables -t raw -L -n -v"); |
| 304 | construct_ip_table_dpg("iptables -t mangle -L -n -v"); |
| 305 | construct_ip_table_dpg("iptables -L -n -v"); |
| 306 | construct_ip_table_dpg("iptables -t nat -L -n -v"); |
| 307 | construct_ip_table_dpg("ip6tables -t raw -L -n -v"); |
| 308 | construct_ip_table_dpg("ip6tables -t mangle -L -n -v"); |
| 309 | construct_ip_table_dpg("ip6tables -L -n -v"); |
| 310 | construct_ip_table_dpg("ip6tables -t nat -L -n -v"); |
| 311 | construct_ip_table_dpg("ip rule show"); |
| 312 | construct_ip_table_dpg("ip -6 rule show"); |
| 313 | construct_ip_table_dpg("ip route show table all"); |
| 314 | construct_ip_table_dpg("ip -6 route show table all"); |
| 315 | construct_ip_table_dpg("ip route show table rmnet_data0"); |
| 316 | construct_ip_table_dpg("ip route show table rmnet_data1"); |
| 317 | construct_ip_table_dpg("ip route show table rmnet_data2"); |
| 318 | construct_ip_table_dpg("ip route show table rmnet_data6"); |
| 319 | construct_ip_table_dpg("ip route show table rmnet_data7"); |
| 320 | construct_ip_table_dpg("ip route show table r_rmnet_data0"); |
| 321 | construct_ip_table_dpg("ip route show table r_rmnet_data1"); |
| 322 | construct_ip_table_dpg("ip route show table r_rmnet_data2"); |
| 323 | construct_ip_table_dpg("ip route show table r_rmnet_data6"); |
| 324 | construct_ip_table_dpg("ip route show table r_rmnet_data7"); |
| 325 | construct_ip_table_dpg("ip -6 route show table rmnet_data0"); |
| 326 | construct_ip_table_dpg("ip -6 route show table rmnet_data1"); |
| 327 | construct_ip_table_dpg("ip -6 route show table rmnet_data2"); |
| 328 | construct_ip_table_dpg("ip -6 route show table rmnet_data6"); |
| 329 | construct_ip_table_dpg("ip -6 route show table rmnet_data7"); |
| 330 | construct_ip_table_dpg("ip -6 route show table r_rmnet_data0"); |
| 331 | construct_ip_table_dpg("ip -6 route show table r_rmnet_data1"); |
| 332 | construct_ip_table_dpg("ip -6 route show table r_rmnet_data2"); |
| 333 | construct_ip_table_dpg("ip -6 route show table r_rmnet_data6"); |
| 334 | construct_ip_table_dpg("ip -6 route show table r_rmnet_data7"); |
| 335 | construct_ip_table_dpg("ip route show table wlan0"); |
| 336 | construct_ip_table_dpg("ip -6 route show table wlan0"); |
| 337 | construct_ip_table_dpg("ip route show table dummy0"); |
| 338 | construct_ip_table_dpg("ip -6 route show table dummy0"); |
| 339 | construct_ip_table_dpg("cat /proc/net/xfrm_stat"); |
| 340 | construct_ip_table_dpg("cat /proc/sys/net/ipv4/ip_forward"); |
| 341 | construct_ip_table_dpg("cat /proc/sys/net/ipv6/conf/all/forwarding"); |
| 342 | |
| 343 | printf("Poll for IP Tables, Rules & Routes every 5 seconds\n"); |
| 344 | } |