1/* 2 ************************************************************************** 3 * Copyright (c) 2015, The Linux Foundation. All rights reserved. 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all copies. 7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 13 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 ************************************************************************** 15 */ 16 17#include <linux/version.h> 18#include <linux/types.h> 19#include <linux/ip.h> 20#include <linux/module.h> 21#include <linux/kthread.h> 22#include <linux/string.h> 23#include <linux/debugfs.h> 24#include <asm/unaligned.h> 25#include <asm/uaccess.h> /* for put_user */ 26#include <linux/inet.h> 27#include <linux/ipv6.h> 28#include <linux/netfilter_bridge.h> 29 30/* 31 * Debug output levels 32 * 0 = OFF 33 * 1 = ASSERTS / ERRORS 34 * 2 = 1 + WARN 35 * 3 = 2 + INFO 36 * 4 = 3 + TRACE 37 */ 38#define DEBUG_LEVEL ECM_STATE_DEBUG_LEVEL 39 40#include "ecm_types.h" 41#include "ecm_db_types.h" 42#include "ecm_state.h" 43#include "ecm_tracker.h" 44#include "ecm_classifier.h" 45#include "ecm_front_end_types.h" 46#include "ecm_classifier_default.h" 47#include "ecm_db.h" 48 49/* 50 * Magic numbers 51 */ 52#define ECM_STATE_FILE_INSTANCE_MAGIC 0xB3FE 53 54/* 55 * Debugfs dentry object. 56 */ 57static struct dentry *ecm_state_dentry; 58 59/* 60 * Locking of the state - concurrency control 61 */ 62static DEFINE_SPINLOCK(ecm_state_lock); /* Protect the table from SMP access. */ 63 64/* 65 * Character device stuff - used to communicate status back to user space 66 */ 67static int ecm_state_dev_major_id = 0; /* Major ID of registered char dev from which we can dump out state to userspace */ 68 69/* 70 * Buffer sizes 71 */ 72#define ECM_STATE_FILE_PREFIX_SIZE 128 73#define ECM_STATE_FILE_PREFIX_LEVELS_MAX 10 74#define ECM_STATE_FILE_BUFFER_SIZE 32768 75 76/* 77 * Output selection flags 78 */ 79#define ECM_STATE_FILE_OUTPUT_CONNECTIONS 1 80#define ECM_STATE_FILE_OUTPUT_MAPPINGS 2 81#define ECM_STATE_FILE_OUTPUT_HOSTS 4 82#define ECM_STATE_FILE_OUTPUT_NODES 8 83#define ECM_STATE_FILE_OUTPUT_INTERFACES 16 84#define ECM_STATE_FILE_OUTPUT_CONNECTIONS_CHAIN 32 85#define ECM_STATE_FILE_OUTPUT_MAPPINGS_CHAIN 64 86#define ECM_STATE_FILE_OUTPUT_HOSTS_CHAIN 128 87#define ECM_STATE_FILE_OUTPUT_NODES_CHAIN 256 88#define ECM_STATE_FILE_OUTPUT_INTERFACES_CHAIN 512 89#define ECM_STATE_FILE_OUTPUT_PROTOCOL_COUNTS 1024 90#ifdef ECM_DB_CTA_TRACK_ENABLE 91#define ECM_STATE_FILE_OUTPUT_CLASSIFIER_TYPE_ASSIGNMENTS 2048 92#endif 93 94/* 95 * struct ecm_state_file_instance 96 * Structure used as state per open instance of our db state file 97 */ 98struct ecm_state_file_instance { 99 int output_mask; /* The content types wanted by the user */ 100 struct ecm_db_connection_instance *ci; /* All connections list iterator */ 101 struct ecm_db_mapping_instance *mi; /* All mappings list iterator */ 102 struct ecm_db_host_instance *hi; /* All hosts list iterator */ 103 struct ecm_db_node_instance *ni; /* All nodes list iterator */ 104 struct ecm_db_iface_instance *ii; /* All interfaces list iterator */ 105#ifdef ECM_DB_CTA_TRACK_ENABLE 106 struct ecm_db_connection_instance *classifier_type_assignments[ECM_CLASSIFIER_TYPES]; 107 /* Classifier type connection assignments iterator, one for each classifier type */ 108#endif 109 int connection_hash_index; /* Connection hash table lengths iterator */ 110 int mapping_hash_index; /* Mapping hash table lengths iterator */ 111 int host_hash_index; /* Host hash table lengths iterator */ 112 int node_hash_index; /* Node hash table lengths iterator */ 113 int iface_hash_index; /* Interface hash table lengths iterator */ 114 int protocol; /* Protocol connection count iterator */ 115 116 char prefix[ECM_STATE_FILE_PREFIX_SIZE]; /* This is the prefix added to every message written */ 117 int prefix_levels[ECM_STATE_FILE_PREFIX_LEVELS_MAX]; 118 /* How many nested prefixes supported */ 119 int prefix_level; /* Prefix nest level */ 120 121 char msg[ECM_STATE_FILE_BUFFER_SIZE]; /* The message written / being returned to the reader */ 122 char *msgp; /* Points into the msg buffer as we output it to the reader piece by piece */ 123 int msg_len; /* Length of the msg buffer still to be written out */ 124#if (DEBUG_LEVEL > 0) 125 uint16_t magic; 126#endif 127}; 128static int ecm_state_file_output_mask = ECM_STATE_FILE_OUTPUT_CONNECTIONS; 129 /* Bit mask specifies which data to output in the state file */ 130 131/* 132 * ecm_state_write_reset() 133 * Reset the msg buffer, specifying a new initial prefix 134 * 135 * Returns 0 on success 136 */ 137int ecm_state_write_reset(struct ecm_state_file_instance *sfi, char *prefix) 138{ 139 int result; 140 141 DEBUG_CHECK_MAGIC(sfi, ECM_STATE_FILE_INSTANCE_MAGIC, "%p: magic failed", sfi); 142 sfi->msgp = sfi->msg; 143 sfi->msg_len = 0; 144 145 result = snprintf(sfi->prefix, ECM_STATE_FILE_PREFIX_SIZE, "%s", prefix); 146 if ((result < 0) || (result >= ECM_STATE_FILE_PREFIX_SIZE)) { 147 return -1; 148 } 149 sfi->prefix_level = 0; 150 sfi->prefix_levels[sfi->prefix_level] = result; 151 return 0; 152} 153EXPORT_SYMBOL(ecm_state_write_reset); 154 155/* 156 * ecm_state_prefix_add() 157 * Add another level to the prefix 158 * 159 * Returns 0 on success 160 */ 161int ecm_state_prefix_add(struct ecm_state_file_instance *sfi, char *prefix) 162{ 163 int pxsz; 164 int pxremain; 165 int result; 166 167 DEBUG_CHECK_MAGIC(sfi, ECM_STATE_FILE_INSTANCE_MAGIC, "%p: magic failed", sfi); 168 169 pxsz = sfi->prefix_levels[sfi->prefix_level]; 170 pxremain = ECM_STATE_FILE_PREFIX_SIZE - pxsz; 171 result = snprintf(sfi->prefix + pxsz, pxremain, ".%s", prefix); 172 if ((result < 0) || (result >= pxremain)) { 173 return -1; 174 } 175 176 sfi->prefix_level++; 177 DEBUG_ASSERT(sfi->prefix_level < ECM_STATE_FILE_PREFIX_LEVELS_MAX, "Bad prefix handling\n"); 178 sfi->prefix_levels[sfi->prefix_level] = pxsz + result; 179 return 0; 180} 181EXPORT_SYMBOL(ecm_state_prefix_add); 182 183/* 184 * ecm_state_prefix_index_add() 185 * Add another level (numeric) to the prefix 186 * 187 * Returns 0 on success 188 */ 189int ecm_state_prefix_index_add(struct ecm_state_file_instance *sfi, int index) 190{ 191 int pxsz; 192 int pxremain; 193 int result; 194 195 DEBUG_CHECK_MAGIC(sfi, ECM_STATE_FILE_INSTANCE_MAGIC, "%p: magic failed", sfi); 196 197 pxsz = sfi->prefix_levels[sfi->prefix_level]; 198 pxremain = ECM_STATE_FILE_PREFIX_SIZE - pxsz; 199 result = snprintf(sfi->prefix + pxsz, pxremain, ".%d", index); 200 if ((result < 0) || (result >= pxremain)) { 201 return -1; 202 } 203 204 sfi->prefix_level++; 205 DEBUG_ASSERT(sfi->prefix_level < ECM_STATE_FILE_PREFIX_LEVELS_MAX, "Bad prefix handling\n"); 206 sfi->prefix_levels[sfi->prefix_level] = pxsz + result; 207 return 0; 208} 209EXPORT_SYMBOL(ecm_state_prefix_index_add); 210 211/* 212 * ecm_state_prefix_remove() 213 * Remove level from the prefix 214 * 215 * Returns 0 on success 216 */ 217int ecm_state_prefix_remove(struct ecm_state_file_instance *sfi) 218{ 219 int pxsz; 220 221 DEBUG_CHECK_MAGIC(sfi, ECM_STATE_FILE_INSTANCE_MAGIC, "%p: magic failed", sfi); 222 223 sfi->prefix_level--; 224 DEBUG_ASSERT(sfi->prefix_level >= 0, "Bad prefix handling\n"); 225 pxsz = sfi->prefix_levels[sfi->prefix_level]; 226 sfi->prefix[pxsz] = 0; 227 return 0; 228} 229EXPORT_SYMBOL(ecm_state_prefix_remove); 230 231/* 232 * ecm_state_write() 233 * Write out to the message buffer, prefix is added automatically. 234 * 235 * Returns 0 on success 236 */ 237int ecm_state_write(struct ecm_state_file_instance *sfi, char *name, char *fmt, ...) 238{ 239 int remain; 240 char *ptr; 241 int result; 242 va_list args; 243 244 DEBUG_CHECK_MAGIC(sfi, ECM_STATE_FILE_INSTANCE_MAGIC, "%p: magic failed", sfi); 245 246 remain = ECM_STATE_FILE_BUFFER_SIZE - sfi->msg_len; 247 ptr = sfi->msg + sfi->msg_len; 248 result = snprintf(ptr, remain, "%s.%s=", sfi->prefix, name); 249 if ((result < 0) || (result >= remain)) { 250 return -1; 251 } 252 253 sfi->msg_len += result; 254 remain -= result; 255 ptr += result; 256 257 va_start(args, fmt); 258 result = vsnprintf(ptr, remain, fmt, args); 259 va_end(args); 260 if ((result < 0) || (result >= remain)) { 261 return -2; 262 } 263 264 sfi->msg_len += result; 265 remain -= result; 266 ptr += result; 267 268 result = snprintf(ptr, remain, "\n"); 269 if ((result < 0) || (result >= remain)) { 270 return -3; 271 } 272 273 sfi->msg_len += result; 274 return 0; 275} 276EXPORT_SYMBOL(ecm_state_write); 277 278/* 279 * ecm_state_char_dev_conn_msg_prep() 280 * Prepare a connection message 281 */ 282static bool ecm_state_char_dev_conn_msg_prep(struct ecm_state_file_instance *sfi) 283{ 284 int result; 285 286 DEBUG_TRACE("%p: Prep conn msg for %p\n", sfi, sfi->ci); 287 288 if ((result = ecm_state_write_reset(sfi, "conns"))) { 289 return result; 290 } 291 return ecm_db_connection_state_get(sfi, sfi->ci); 292} 293 294/* 295 * ecm_state_char_dev_mapping_msg_prep() 296 * Prepare a mapping message 297 */ 298static bool ecm_state_char_dev_mapping_msg_prep(struct ecm_state_file_instance *sfi) 299{ 300 int result; 301 302 DEBUG_TRACE("%p: Prep mapping msg for %p\n", sfi, sfi->mi); 303 304 if ((result = ecm_state_write_reset(sfi, "mappings"))) { 305 return result; 306 } 307 return ecm_db_mapping_state_get(sfi, sfi->mi); 308} 309 310/* 311 * ecm_state_char_dev_host_msg_prep() 312 * Prepare a host message 313 */ 314static bool ecm_state_char_dev_host_msg_prep(struct ecm_state_file_instance *sfi) 315{ 316 int result; 317 318 DEBUG_TRACE("%p: Prep host msg for %p\n", sfi, sfi->hi); 319 320 if ((result = ecm_state_write_reset(sfi, "hosts"))) { 321 return result; 322 } 323 324 return ecm_db_host_state_get(sfi, sfi->hi); 325} 326 327/* 328 * ecm_state_char_dev_node_msg_prep() 329 * Prepare a node message 330 */ 331static bool ecm_state_char_dev_node_msg_prep(struct ecm_state_file_instance *sfi) 332{ 333 int result; 334 335 DEBUG_TRACE("%p: Prep node msg for %p\n", sfi, sfi->ni); 336 337 if ((result = ecm_state_write_reset(sfi, "nodes"))) { 338 return result; 339 } 340 341 return ecm_db_node_state_get(sfi, sfi->ni); 342} 343 344/* 345 * ecm_state_char_dev_iface_msg_prep() 346 * Prepare an interface message 347 */ 348static int ecm_state_char_dev_iface_msg_prep(struct ecm_state_file_instance *sfi) 349{ 350 int result; 351 352 DEBUG_TRACE("%p: Prep iface msg for %p\n", sfi, sfi->ii); 353 354 if ((result = ecm_state_write_reset(sfi, "ifaces"))) { 355 return result; 356 } 357 return ecm_db_iface_state_get(sfi, sfi->ii); 358} 359 360/* 361 * ecm_state_char_dev_conn_chain_msg_prep() 362 * Generate an conn hash table chain message 363 */ 364static bool ecm_state_char_dev_conn_chain_msg_prep(struct ecm_state_file_instance *sfi) 365{ 366 int result; 367 int chain_len; 368 DEBUG_TRACE("%p: Prep conn chain msg\n", sfi); 369 370 /* 371 * Get hash table chain length 372 */ 373 chain_len = ecm_db_connection_hash_table_lengths_get(sfi->connection_hash_index); 374 375 if ((result = ecm_state_write_reset(sfi, "conn_chain"))) { 376 return result; 377 } 378 if ((result = ecm_state_prefix_index_add(sfi, sfi->connection_hash_index))) { 379 return result; 380 } 381 return ecm_state_write(sfi, "length", "%d", chain_len); 382} 383 384/* 385 * ecm_state_char_dev_mapping_chain_msg_prep() 386 * Generate an mapping hash table chain message 387 */ 388static bool ecm_state_char_dev_mapping_chain_msg_prep(struct ecm_state_file_instance *sfi) 389{ 390 int result; 391 int chain_len; 392 DEBUG_TRACE("%p: Prep mapping chain msg\n", sfi); 393 394 /* 395 * Get hash table chain length 396 */ 397 chain_len = ecm_db_mapping_hash_table_lengths_get(sfi->mapping_hash_index); 398 399 if ((result = ecm_state_write_reset(sfi, "mapping_chain"))) { 400 return result; 401 } 402 if ((result = ecm_state_prefix_index_add(sfi, sfi->mapping_hash_index))) { 403 return result; 404 } 405 return ecm_state_write(sfi, "length", "%d", chain_len); 406} 407 408/* 409 * ecm_state_char_dev_host_chain_msg_prep() 410 * Generate an host hash table chain message 411 */ 412static bool ecm_state_char_dev_host_chain_msg_prep(struct ecm_state_file_instance *sfi) 413{ 414 int result; 415 int chain_len; 416 DEBUG_TRACE("%p: Prep host chain msg\n", sfi); 417 418 /* 419 * Get hash table chain length 420 */ 421 chain_len = ecm_db_host_hash_table_lengths_get(sfi->host_hash_index); 422 423 if ((result = ecm_state_write_reset(sfi, "host_chain"))) { 424 return result; 425 } 426 if ((result = ecm_state_prefix_index_add(sfi, sfi->host_hash_index))) { 427 return result; 428 } 429 return ecm_state_write(sfi, "length", "%d", chain_len); 430} 431 432/* 433 * ecm_state_char_dev_node_chain_msg_prep() 434 * Generate an node hash table chain message 435 */ 436static bool ecm_state_char_dev_node_chain_msg_prep(struct ecm_state_file_instance *sfi) 437{ 438 int result; 439 int chain_len; 440 DEBUG_TRACE("%p: Prep node chain msg\n", sfi); 441 442 /* 443 * Get hash table chain length 444 */ 445 chain_len = ecm_db_node_hash_table_lengths_get(sfi->node_hash_index); 446 447 if ((result = ecm_state_write_reset(sfi, "node_chain"))) { 448 return result; 449 } 450 if ((result = ecm_state_prefix_index_add(sfi, sfi->node_hash_index))) { 451 return result; 452 } 453 return ecm_state_write(sfi, "length", "%d", chain_len); 454} 455 456/* 457 * ecm_state_char_dev_iface_chain_msg_prep() 458 * Generate an interface hash table chain message 459 */ 460static bool ecm_state_char_dev_iface_chain_msg_prep(struct ecm_state_file_instance *sfi) 461{ 462 int result; 463 int chain_len; 464 DEBUG_TRACE("%p: Prep iface chain msg\n", sfi); 465 466 /* 467 * Get hash table chain length 468 */ 469 chain_len = ecm_db_iface_hash_table_lengths_get(sfi->iface_hash_index); 470 471 if ((result = ecm_state_write_reset(sfi, "iface_chain"))) { 472 return result; 473 } 474 if ((result = ecm_state_prefix_index_add(sfi, sfi->iface_hash_index))) { 475 return result; 476 } 477 return ecm_state_write(sfi, "length", "%d", chain_len); 478} 479 480/* 481 * ecm_state_char_dev_protocol_count_msg_prep() 482 * Generate a protocol usage message 483 */ 484static bool ecm_state_char_dev_protocol_count_msg_prep(struct ecm_state_file_instance *sfi) 485{ 486 int result; 487 int count; 488 DEBUG_TRACE("%p: Prep protocol msg\n", sfi); 489 490 /* 491 * Get protocol connection total count 492 */ 493 count = ecm_db_connection_count_by_protocol_get(sfi->protocol); 494 495 if ((result = ecm_state_write_reset(sfi, "protocol"))) { 496 return result; 497 } 498 if ((result = ecm_state_prefix_index_add(sfi, sfi->protocol))) { 499 return result; 500 } 501 return ecm_state_write(sfi, "connections", "%d", count); 502} 503 504#ifdef ECM_DB_CTA_TRACK_ENABLE 505/* 506 * ecm_state_char_dev_cta_msg_prep() 507 * Generate a classifier type assignment message 508 */ 509static int ecm_state_char_dev_cta_msg_prep(struct ecm_state_file_instance *sfi, ecm_classifier_type_t ca_type) 510{ 511 struct ecm_db_connection_instance *ci; 512 int result; 513 514 DEBUG_TRACE("%p: Prep classifier type assignment msg: %d\n", sfi, ca_type); 515 516 ci = sfi->classifier_type_assignments[ca_type]; 517 if (!ci) { 518 return 0; 519 } 520 521 if ((result = ecm_state_write_reset(sfi, "cta"))) { 522 return result; 523 } 524 if ((result = ecm_state_prefix_index_add(sfi, ca_type))) { 525 return result; 526 } 527 if ((result = ecm_state_write(sfi, "conn.serial", "%u", ecm_db_connection_serial_get(ci)))) { 528 return result; 529 } 530 531 /* 532 * Prep next connection for when we are called again, releasing this one. 533 */ 534 sfi->classifier_type_assignments[ca_type] = ecm_db_connection_by_classifier_type_assignment_get_and_ref_next(ci, ca_type); 535 ecm_db_connection_by_classifier_type_assignment_deref(ci, ca_type); 536 return 0; 537} 538 539/* 540 * ecm_state_file_classifier_type_assignments_release() 541 * Releases any uniterated classifier assignments 542 */ 543static void ecm_state_file_classifier_type_assignments_release(struct ecm_state_file_instance *sfi) 544{ 545 ecm_classifier_type_t ca_type; 546 547 for (ca_type = 0; ca_type < ECM_CLASSIFIER_TYPES; ++ca_type) { 548 struct ecm_db_connection_instance *ci; 549 550 ci = sfi->classifier_type_assignments[ca_type]; 551 if (!ci) { 552 continue; 553 } 554 555 ecm_db_connection_by_classifier_type_assignment_deref(ci, ca_type); 556 } 557} 558#endif 559 560/* 561 * ecm_state_char_device_open() 562 * Opens the special char device file which we use to dump our state. 563 */ 564static int ecm_state_char_device_open(struct inode *inode, struct file *file) 565{ 566 struct ecm_state_file_instance *sfi; 567 568 DEBUG_INFO("State open\n"); 569 570 /* 571 * Allocate state information for the reading 572 */ 573 DEBUG_ASSERT(file->private_data == NULL, "unexpected double open: %p?\n", file->private_data); 574 575 sfi = (struct ecm_state_file_instance *)kzalloc(sizeof(struct ecm_state_file_instance), GFP_ATOMIC | __GFP_NOWARN); 576 if (!sfi) { 577 return -ENOMEM; 578 } 579 DEBUG_SET_MAGIC(sfi, ECM_STATE_FILE_INSTANCE_MAGIC); 580 file->private_data = sfi; 581 582 /* 583 * Snapshot output mask for this file 584 */ 585 spin_lock_bh(&ecm_state_lock); 586 sfi->output_mask = ecm_state_file_output_mask; 587 spin_unlock_bh(&ecm_state_lock); 588 589 /* 590 * Get the first indicies for hash and protocol stats should they be needed. 591 * NOTE: There are no references held here so it does not matter to get them all even if they are not wanted. 592 */ 593 sfi->connection_hash_index = ecm_db_connection_hash_index_get_first(); 594 sfi->mapping_hash_index = ecm_db_mapping_hash_index_get_first(); 595 sfi->host_hash_index = ecm_db_host_hash_index_get_first(); 596 sfi->node_hash_index = ecm_db_node_hash_index_get_first(); 597 sfi->iface_hash_index = ecm_db_iface_hash_index_get_first(); 598 sfi->protocol = ecm_db_protocol_get_first(); 599 600 /* 601 * Take references to each object list that we are going to generate state for. 602 */ 603 if (sfi->output_mask & ECM_STATE_FILE_OUTPUT_CONNECTIONS) { 604 sfi->ci = ecm_db_connections_get_and_ref_first(); 605 } 606 if (sfi->output_mask & ECM_STATE_FILE_OUTPUT_MAPPINGS) { 607 sfi->mi = ecm_db_mappings_get_and_ref_first(); 608 } 609 if (sfi->output_mask & ECM_STATE_FILE_OUTPUT_HOSTS) { 610 sfi->hi = ecm_db_hosts_get_and_ref_first(); 611 } 612 if (sfi->output_mask & ECM_STATE_FILE_OUTPUT_NODES) { 613 sfi->ni = ecm_db_nodes_get_and_ref_first(); 614 } 615 if (sfi->output_mask & ECM_STATE_FILE_OUTPUT_INTERFACES) { 616 sfi->ii = ecm_db_interfaces_get_and_ref_first(); 617 } 618#ifdef ECM_DB_CTA_TRACK_ENABLE 619 if (sfi->output_mask & ECM_STATE_FILE_OUTPUT_CLASSIFIER_TYPE_ASSIGNMENTS) { 620 ecm_classifier_type_t ca_type; 621 622 /* 623 * Iterate all classifier type assignments. 624 * Hold the head of each list to start us off on our iterating process. 625 */ 626 for (ca_type = 0; ca_type < ECM_CLASSIFIER_TYPES; ++ca_type) { 627 sfi->classifier_type_assignments[ca_type] = ecm_db_connection_by_classifier_type_assignment_get_and_ref_first(ca_type); 628 } 629 } 630#endif 631 632 DEBUG_INFO("State opened %p\n", sfi); 633 634 return 0; 635} 636 637/* 638 * ecm_state_char_device_release() 639 * Called when a process closes the device file. 640 */ 641static int ecm_state_char_device_release(struct inode *inode, struct file *file) 642{ 643 struct ecm_state_file_instance *sfi; 644 645 sfi = (struct ecm_state_file_instance *)file->private_data; 646 DEBUG_CHECK_MAGIC(sfi, ECM_STATE_FILE_INSTANCE_MAGIC, "%p: magic failed", sfi); 647 DEBUG_INFO("%p: State close\n", sfi); 648 649 /* 650 * Release any references held 651 */ 652 if (sfi->ci) { 653 ecm_db_connection_deref(sfi->ci); 654 } 655 if (sfi->mi) { 656 ecm_db_mapping_deref(sfi->mi); 657 } 658 if (sfi->hi) { 659 ecm_db_host_deref(sfi->hi); 660 } 661 if (sfi->ni) { 662 ecm_db_node_deref(sfi->ni); 663 } 664 if (sfi->ii) { 665 ecm_db_iface_deref(sfi->ii); 666 } 667#ifdef ECM_DB_CTA_TRACK_ENABLE 668 ecm_state_file_classifier_type_assignments_release(sfi); 669#endif 670 671 DEBUG_CLEAR_MAGIC(sfi); 672 kfree(sfi); 673 674 return 0; 675} 676 677/* 678 * ecm_state_char_device_read() 679 * Called to read the state 680 */ 681static ssize_t ecm_state_char_device_read(struct file *file, /* see include/linux/fs.h */ 682 char *buffer, /* buffer to fill with data */ 683 size_t length, /* length of the buffer */ 684 loff_t *offset) /* Doesn't apply - this is a char file */ 685{ 686 struct ecm_state_file_instance *sfi; 687 int bytes_read = 0; /* Number of bytes actually written to the buffer */ 688#ifdef ECM_DB_CTA_TRACK_ENABLE 689 ecm_classifier_type_t ca_type; 690#endif 691 692 sfi = (struct ecm_state_file_instance *)file->private_data; 693 DEBUG_CHECK_MAGIC(sfi, ECM_STATE_FILE_INSTANCE_MAGIC, "%p: magic failed", sfi); 694 DEBUG_TRACE("%p: State read up to length %d bytes\n", sfi, length); 695 696 /* 697 * If there is still some message remaining to be output then complete that first 698 */ 699 if (sfi->msg_len) { 700 goto char_device_read_output; 701 } 702 703 if (sfi->ci) { 704 struct ecm_db_connection_instance *cin; 705 if (ecm_state_char_dev_conn_msg_prep(sfi)) { 706 return -EIO; 707 } 708 709 /* 710 * Next connection for when we return 711 */ 712 cin = ecm_db_connection_get_and_ref_next(sfi->ci); 713 ecm_db_connection_deref(sfi->ci); 714 sfi->ci = cin; 715 716 goto char_device_read_output; 717 } 718 719 if (sfi->mi) { 720 struct ecm_db_mapping_instance *min; 721 if (ecm_state_char_dev_mapping_msg_prep(sfi)) { 722 return -EIO; 723 } 724 725 /* 726 * Next mapping for when we return 727 */ 728 min = ecm_db_mapping_get_and_ref_next(sfi->mi); 729 ecm_db_mapping_deref(sfi->mi); 730 sfi->mi = min; 731 732 goto char_device_read_output; 733 } 734 735 if (sfi->hi) { 736 struct ecm_db_host_instance *hin; 737 if (ecm_state_char_dev_host_msg_prep(sfi)) { 738 return -EIO; 739 } 740 741 /* 742 * Next host for when we return 743 */ 744 hin = ecm_db_host_get_and_ref_next(sfi->hi); 745 ecm_db_host_deref(sfi->hi); 746 sfi->hi = hin; 747 748 goto char_device_read_output; 749 } 750 751 if (sfi->ni) { 752 struct ecm_db_node_instance *nin; 753 if (ecm_state_char_dev_node_msg_prep(sfi)) { 754 return -EIO; 755 } 756 757 /* 758 * Next node for when we return 759 */ 760 nin = ecm_db_node_get_and_ref_next(sfi->ni); 761 ecm_db_node_deref(sfi->ni); 762 sfi->ni = nin; 763 764 goto char_device_read_output; 765 } 766 767 if (sfi->ii) { 768 struct ecm_db_iface_instance *iin; 769 if (ecm_state_char_dev_iface_msg_prep(sfi)) { 770 return -EIO; 771 } 772 773 /* 774 * Next iface for when we return 775 */ 776 iin = ecm_db_interface_get_and_ref_next(sfi->ii); 777 ecm_db_iface_deref(sfi->ii); 778 sfi->ii = iin; 779 780 goto char_device_read_output; 781 } 782 783 if ((sfi->output_mask & ECM_STATE_FILE_OUTPUT_CONNECTIONS_CHAIN) && (sfi->connection_hash_index >= 0)) { 784 if (ecm_state_char_dev_conn_chain_msg_prep(sfi)) { 785 return -EIO; 786 } 787 sfi->connection_hash_index = ecm_db_connection_hash_index_get_next(sfi->connection_hash_index); 788 goto char_device_read_output; 789 } 790 791 if ((sfi->output_mask & ECM_STATE_FILE_OUTPUT_MAPPINGS_CHAIN) && (sfi->mapping_hash_index >= 0)) { 792 if (ecm_state_char_dev_mapping_chain_msg_prep(sfi)) { 793 return -EIO; 794 } 795 sfi->mapping_hash_index = ecm_db_mapping_hash_index_get_next(sfi->mapping_hash_index); 796 goto char_device_read_output; 797 } 798 799 if ((sfi->output_mask & ECM_STATE_FILE_OUTPUT_HOSTS_CHAIN) && (sfi->host_hash_index >= 0)) { 800 if (ecm_state_char_dev_host_chain_msg_prep(sfi)) { 801 return -EIO; 802 } 803 sfi->host_hash_index = ecm_db_host_hash_index_get_next(sfi->host_hash_index); 804 goto char_device_read_output; 805 } 806 807 if ((sfi->output_mask & ECM_STATE_FILE_OUTPUT_NODES_CHAIN) && (sfi->node_hash_index >= 0)) { 808 if (ecm_state_char_dev_node_chain_msg_prep(sfi)) { 809 return -EIO; 810 } 811 sfi->node_hash_index = ecm_db_node_hash_index_get_next(sfi->node_hash_index); 812 goto char_device_read_output; 813 } 814 815 if ((sfi->output_mask & ECM_STATE_FILE_OUTPUT_INTERFACES_CHAIN) && (sfi->iface_hash_index >= 0)) { 816 if (ecm_state_char_dev_iface_chain_msg_prep(sfi)) { 817 return -EIO; 818 } 819 sfi->iface_hash_index = ecm_db_iface_hash_index_get_next(sfi->iface_hash_index); 820 goto char_device_read_output; 821 } 822 823 if ((sfi->output_mask & ECM_STATE_FILE_OUTPUT_PROTOCOL_COUNTS) && (sfi->protocol >= 0)) { 824 if (ecm_state_char_dev_protocol_count_msg_prep(sfi)) { 825 return -EIO; 826 } 827 sfi->protocol = ecm_db_protocol_get_next(sfi->protocol); 828 goto char_device_read_output; 829 } 830 831#ifdef ECM_DB_CTA_TRACK_ENABLE 832 for (ca_type = 0; ca_type < ECM_CLASSIFIER_TYPES; ++ca_type) { 833 if (!sfi->classifier_type_assignments[ca_type]) continue; 834 if (ecm_state_char_dev_cta_msg_prep(sfi, ca_type)) { 835 return -EIO; 836 } 837 goto char_device_read_output; 838 } 839#endif 840 841 /* 842 * EOF 843 */ 844 return 0; 845 846char_device_read_output: 847 848 /* 849 * If supplied buffer is small we limit what we output 850 */ 851 bytes_read = sfi->msg_len; 852 if (bytes_read > length) { 853 bytes_read = length; 854 } 855 if (copy_to_user(buffer, sfi->msgp, bytes_read)) { 856 return -EIO; 857 } 858 sfi->msg_len -= bytes_read; 859 sfi->msgp += bytes_read; 860 861 DEBUG_TRACE("State read done, bytes_read %d bytes\n", bytes_read); 862 863 /* 864 * Most read functions return the number of bytes put into the buffer 865 */ 866 return bytes_read; 867} 868 869/* 870 * ecm_state_char_device_write() 871 */ 872static ssize_t ecm_state_char_device_write(struct file *filp, const char *buff, size_t len, loff_t * off) 873{ 874 return -EINVAL; 875} 876 877/* 878 * File operations used in the char device 879 * NOTE: The char device is a simple file that allows us to dump our connection tracking state 880 */ 881static struct file_operations ecm_state_fops = { 882 .read = ecm_state_char_device_read, 883 .write = ecm_state_char_device_write, 884 .open = ecm_state_char_device_open, 885 .release = ecm_state_char_device_release 886}; 887 888/* 889 * ecm_state_init() 890 */ 891int ecm_state_init(struct dentry *dentry) 892{ 893 int result = -1; 894 DEBUG_INFO("ECM State init\n"); 895 896 ecm_state_dentry = debugfs_create_dir("ecm_state", dentry); 897 if (!ecm_state_dentry) { 898 DEBUG_ERROR("Failed to create ecm state directory in debugfs\n"); 899 return -1; 900 } 901 902 if (!debugfs_create_u32("state_dev_major", S_IRUGO, ecm_state_dentry, 903 (u32 *)&ecm_state_dev_major_id)) { 904 DEBUG_ERROR("Failed to create ecm state dev major file in debugfs\n"); 905 goto init_cleanup; 906 } 907 908 if (!debugfs_create_u32("state_file_output_mask", S_IRUGO | S_IWUSR, ecm_state_dentry, 909 (u32 *)&ecm_state_file_output_mask)) { 910 DEBUG_ERROR("Failed to create ecm state output mask file in debugfs\n"); 911 goto init_cleanup; 912 } 913 914 /* 915 * Register a char device that we will use to provide a dump of our state 916 */ 917 result = register_chrdev(0, "ecm_state", &ecm_state_fops); 918 if (result < 0) { 919 DEBUG_ERROR("Failed to register chrdev %d\n", result); 920 goto init_cleanup; 921 } 922 ecm_state_dev_major_id = result; 923 DEBUG_TRACE("registered chr dev major id assigned %d\n", ecm_state_dev_major_id); 924 925 return 0; 926 927init_cleanup: 928 929 debugfs_remove_recursive(ecm_state_dentry); 930 return result; 931} 932EXPORT_SYMBOL(ecm_state_init); 933 934/* 935 * ecm_state_exit() 936 */ 937void ecm_state_exit(void) 938{ 939 DEBUG_INFO("ECM State exit\n"); 940 941 unregister_chrdev(ecm_state_dev_major_id, "ecm_state"); 942 943 /* 944 * Remove the debugfs files recursively. 945 */ 946 if (ecm_state_dentry) { 947 debugfs_remove_recursive(ecm_state_dentry); 948 } 949} 950EXPORT_SYMBOL(ecm_state_exit); 951 952