pcap.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright 2019 Ramon Fried <rfried.dev@gmail.com>
  4. */
  5. #include <common.h>
  6. #include <net.h>
  7. #include <net/pcap.h>
  8. #include <time.h>
  9. #include <asm/io.h>
  10. #define LINKTYPE_ETHERNET 1
  11. static bool initialized;
  12. static bool running;
  13. static bool buffer_full;
  14. static void *buf;
  15. static unsigned int max_size;
  16. static unsigned int pos;
  17. static unsigned long incoming_count;
  18. static unsigned long outgoing_count;
  19. struct pcap_header {
  20. u32 magic;
  21. u16 version_major;
  22. u16 version_minor;
  23. s32 thiszone;
  24. u32 sigfigs;
  25. u32 snaplen;
  26. u32 network;
  27. };
  28. struct pcap_packet_header {
  29. u32 ts_sec;
  30. u32 ts_usec;
  31. u32 incl_len;
  32. u32 orig_len;
  33. };
  34. static struct pcap_header file_header = {
  35. .magic = 0xa1b2c3d4,
  36. .version_major = 2,
  37. .version_minor = 4,
  38. .snaplen = 65535,
  39. .network = LINKTYPE_ETHERNET,
  40. };
  41. int pcap_init(phys_addr_t paddr, unsigned long size)
  42. {
  43. buf = map_physmem(paddr, size, 0);
  44. if (!buf) {
  45. printf("Failed mapping PCAP memory\n");
  46. return -ENOMEM;
  47. }
  48. printf("PCAP capture initialized: addr: 0x%lx max length: %lu\n",
  49. (unsigned long)buf, size);
  50. memcpy(buf, &file_header, sizeof(file_header));
  51. pos = sizeof(file_header);
  52. max_size = size;
  53. initialized = true;
  54. running = false;
  55. buffer_full = false;
  56. incoming_count = 0;
  57. outgoing_count = 0;
  58. return 0;
  59. }
  60. int pcap_start_stop(bool start)
  61. {
  62. if (!initialized) {
  63. printf("error: pcap was not initialized\n");
  64. return -ENODEV;
  65. }
  66. running = start;
  67. return 0;
  68. }
  69. int pcap_clear(void)
  70. {
  71. if (!initialized) {
  72. printf("error: pcap was not initialized\n");
  73. return -ENODEV;
  74. }
  75. pos = sizeof(file_header);
  76. incoming_count = 0;
  77. outgoing_count = 0;
  78. buffer_full = false;
  79. printf("pcap capture cleared\n");
  80. return 0;
  81. }
  82. int pcap_post(const void *packet, size_t len, bool outgoing)
  83. {
  84. struct pcap_packet_header header;
  85. u64 cur_time = timer_get_us();
  86. if (!initialized || !running || !buf)
  87. return -ENODEV;
  88. if (buffer_full)
  89. return -ENOMEM;
  90. if ((pos + len + sizeof(header)) >= max_size) {
  91. buffer_full = true;
  92. printf("\n!!! Buffer is full, consider increasing buffer size !!!\n");
  93. return -ENOMEM;
  94. }
  95. header.ts_sec = cur_time / 1000000;
  96. header.ts_usec = cur_time % 1000000;
  97. header.incl_len = len;
  98. header.orig_len = len;
  99. memcpy(buf + pos, &header, sizeof(header));
  100. pos += sizeof(header);
  101. memcpy(buf + pos, packet, len);
  102. pos += len;
  103. if (outgoing)
  104. outgoing_count++;
  105. else
  106. incoming_count++;
  107. env_set_hex("pcapsize", pos);
  108. return 0;
  109. }
  110. int pcap_print_status(void)
  111. {
  112. if (!initialized) {
  113. printf("pcap was not initialized\n");
  114. return -ENODEV;
  115. }
  116. printf("PCAP status:\n");
  117. printf("\tInitialized addr: 0x%lx\tmax length: %u\n",
  118. (unsigned long)buf, max_size);
  119. printf("\tStatus: %s.\t file size: %u\n", running ? "Active" : "Idle",
  120. pos);
  121. printf("\tIncoming packets: %lu Outgoing packets: %lu\n",
  122. incoming_count, outgoing_count);
  123. return 0;
  124. }
  125. bool pcap_active(void)
  126. {
  127. return running;
  128. }