Advertisement
Guest User

Untitled

a guest
May 27th, 2015
333
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.88 KB | None | 0 0
  1. // (c)2015 befinitiv/malkauns
  2.  
  3. /*
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; version 2.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License along
  14. * with this program; if not, write to the Free Software Foundation, Inc.,
  15. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. */
  17.  
  18.  
  19.  
  20. #include "lib.h"
  21. #include "wifibroadcast.h"
  22. #include "radiotap.h"
  23. #include <pthread.h>
  24. #include <limits.h>
  25.  
  26. #define MAX_PACKET_LENGTH 4192
  27. #define BLOCKCACHE_SIZE 5
  28.  
  29. // this is where we store a summary of the
  30. // information from the radiotap header
  31.  
  32. typedef struct {
  33. int m_nChannel;
  34. int m_nChannelFlags;
  35. int m_nRate;
  36. int m_nAntenna;
  37. int m_nRadiotapFlags;
  38. } __attribute__((packed)) PENUMBRA_RADIOTAP_DATA;
  39.  
  40.  
  41.  
  42. int flagHelp = 0;
  43. int param_port = 0;
  44. int param_retransmission_block_size = 1;
  45. int num_sent = 0, num_lost = 0;
  46. packet_buffer_t *packet_buffer_list_cache[BLOCKCACHE_SIZE];
  47. int block_nums[BLOCKCACHE_SIZE];
  48. int last_block_written = 0;
  49. pthread_mutex_t thread_mutex;
  50.  
  51. void
  52. usage(void)
  53. {
  54. printf(
  55. "(c)2015 befinitiv. Based on packetspammer by Andy Green. Licensed under GPL2\n"
  56. "\n"
  57. "Usage: rx [options] <interfaces>\n\nOptions\n"
  58. "-p <port> Port number 0-255 (default 0)\n"
  59. "-b <block_numsize> Number of packets in a retransmission block (default 1). Needs to match with tx.\n"
  60. "Example:\n"
  61. " echo -n mon0 > /sys/class/ieee80211/phy0/add_iface\n"
  62. " iwconfig mon0 mode monitor\n"
  63. " ifconfig mon0 up\n"
  64. " rx mon0 Receive raw packets on mon0 and output the payload to stdout\n"
  65. "\n");
  66. exit(1);
  67. }
  68.  
  69. typedef struct {
  70. pcap_t *ppcap;
  71. int selectable_fd;
  72. int n80211HeaderLength;
  73. char name[16];
  74. int last_block_num;
  75. } monitor_interface_t;
  76.  
  77. void open_and_configure_interface(const char *name, int port, monitor_interface_t *interface) {
  78. struct bpf_program bpfprogram;
  79. char szProgram[512];
  80. char szErrbuf[PCAP_ERRBUF_SIZE];
  81. // open the interface in pcap
  82.  
  83. szErrbuf[0] = '\0';
  84. strcpy(interface->name, name);
  85. interface->last_block_num = -1;
  86. interface->ppcap = pcap_open_live(name, 2048, 1, 0, szErrbuf);
  87. if (interface->ppcap == NULL) {
  88. fprintf(stderr, "Unable to open interface %s in pcap: %s\n",
  89. name, szErrbuf);
  90. exit(1);
  91. }
  92.  
  93.  
  94. if(pcap_setnonblock(interface->ppcap, 0, szErrbuf) < 0) {
  95. fprintf(stderr, "Error setting %s to nonblocking mode: %s\n", name, szErrbuf);
  96. }
  97.  
  98. int nLinkEncap = pcap_datalink(interface->ppcap);
  99.  
  100. switch (nLinkEncap) {
  101.  
  102. case DLT_PRISM_HEADER:
  103. fprintf(stderr, "DLT_PRISM_HEADER Encap [%s]\n", interface->name);
  104. interface->n80211HeaderLength = 0x20; // ieee80211 comes after this
  105. sprintf(szProgram, "radio[0x4a:4]==0x13223344 && radio[0x4e:2] == 0x55%.2x", port);
  106. break;
  107.  
  108. case DLT_IEEE802_11_RADIO:
  109. fprintf(stderr, "DLT_IEEE802_11_RADIO Encap [%s]\n", interface->name);
  110. interface->n80211HeaderLength = 0x18; // ieee80211 comes after this
  111. sprintf(szProgram, "ether[0x0a:4]==0x13223344 && ether[0x0e:2] == 0x55%.2x", port);
  112. break;
  113.  
  114. default:
  115. fprintf(stderr, "!!! unknown encapsulation on %s !\n", name);
  116. exit(1);
  117.  
  118. }
  119.  
  120. if (pcap_compile(interface->ppcap, &bpfprogram, szProgram, 1, 0) == -1) {
  121. puts(szProgram);
  122. puts(pcap_geterr(interface->ppcap));
  123. exit(1);
  124. } else {
  125. if (pcap_setfilter(interface->ppcap, &bpfprogram) == -1) {
  126. fprintf(stderr, "%s\n", szProgram);
  127. fprintf(stderr, "%s\n", pcap_geterr(interface->ppcap));
  128. } else {
  129. }
  130. pcap_freecode(&bpfprogram);
  131. }
  132.  
  133. interface->selectable_fd = pcap_get_selectable_fd(interface->ppcap);
  134. }
  135.  
  136. void writeblock(monitor_interface_t *interface, packet_buffer_t *packet_buffer_list) {
  137. int i;
  138. for(i=0; i<param_retransmission_block_size; ++i) {
  139. packet_buffer_t *p = packet_buffer_list + i;
  140. if(p->valid) {
  141. write(STDOUT_FILENO, p->data, p->len);
  142. }
  143. else {
  144. //fprintf(stderr, "%s Lost a packet %x! Lossrate: %f\t(%d / %d)\n", interface->name, i+(block_num-1)*param_retransmission_block_size, 1.0 * num_lost/num_sent, num_lost, num_sent);
  145. num_lost++;
  146. }
  147. p->valid = 0;
  148. p->crc_correct = 0;
  149. p->len = 0;
  150. }
  151. }
  152.  
  153. void process_packet(monitor_interface_t *interface) {
  154.  
  155. struct pcap_pkthdr * ppcapPacketHeader = NULL;
  156. struct ieee80211_radiotap_iterator rti;
  157. PENUMBRA_RADIOTAP_DATA prd;
  158. u8 payloadBuffer[MAX_PACKET_LENGTH];
  159. u8 *pu8Payload = payloadBuffer;
  160. int bytes;
  161. int n;
  162. uint32_t seq_nr;
  163. int block_num;
  164. int packet_num;
  165. int checksum_correct;
  166. int retval;
  167. int u16HeaderLen;
  168.  
  169. // receive
  170.  
  171. retval = pcap_next_ex(interface->ppcap, &ppcapPacketHeader,
  172. (const u_char**)&pu8Payload);
  173. if (retval < 0) {
  174. fprintf(stderr, "Socket broken\n");
  175. fprintf(stderr, "%s\n", pcap_geterr(interface->ppcap));
  176. exit(1);
  177. }
  178. if (retval != 1) {
  179. return;
  180. }
  181.  
  182. u16HeaderLen = (pu8Payload[2] + (pu8Payload[3] << 8));
  183.  
  184. if (ppcapPacketHeader->len <
  185. (u16HeaderLen + interface->n80211HeaderLength))
  186. return;
  187.  
  188. bytes = ppcapPacketHeader->len -
  189. (u16HeaderLen + interface->n80211HeaderLength);
  190. if (bytes < 0)
  191. return;
  192.  
  193. if (ieee80211_radiotap_iterator_init(&rti,
  194. (struct ieee80211_radiotap_header *)pu8Payload,
  195. ppcapPacketHeader->len) < 0)
  196. return;
  197.  
  198. while ((n = ieee80211_radiotap_iterator_next(&rti)) == 0) {
  199.  
  200. switch (rti.this_arg_index) {
  201. case IEEE80211_RADIOTAP_RATE:
  202. prd.m_nRate = (*rti.this_arg);
  203. break;
  204.  
  205. case IEEE80211_RADIOTAP_CHANNEL:
  206. prd.m_nChannel =
  207. le16_to_cpu(*((u16 *)rti.this_arg));
  208. prd.m_nChannelFlags =
  209. le16_to_cpu(*((u16 *)(rti.this_arg + 2)));
  210. break;
  211.  
  212. case IEEE80211_RADIOTAP_ANTENNA:
  213. prd.m_nAntenna = (*rti.this_arg) + 1;
  214. break;
  215.  
  216. case IEEE80211_RADIOTAP_FLAGS:
  217. prd.m_nRadiotapFlags = *rti.this_arg;
  218. break;
  219. }
  220. }
  221. pu8Payload += u16HeaderLen + interface->n80211HeaderLength;
  222.  
  223. if (prd.m_nRadiotapFlags & IEEE80211_RADIOTAP_F_FCS)
  224. bytes -= 4;
  225.  
  226. checksum_correct = (prd.m_nRadiotapFlags & 0x40) == 0;
  227.  
  228. //first 4 bytes are the sequence number
  229. seq_nr = *(uint32_t*)pu8Payload;
  230. pu8Payload += 4;
  231. bytes -= 4;
  232. block_num = seq_nr / param_retransmission_block_size; //if retr_block_size would be limited to powers of two, this could be replaced by a logical AND operation
  233.  
  234. //sometimes block_num can arrive malformed so handle this error by ignoring it
  235. if(abs((block_num - last_block_written)) > 1000 //TODO: what if we stopped receiving data for a while on all adapters??
  236. && last_block_written != 0) return;
  237.  
  238. //if we received the start of a new block, we need to write out the old one
  239. /*if(block_num > interface->last_block_num && interface->last_block_num >= 0 && checksum_correct) {
  240. //remove the write from here
  241. if(block_num > interface->last_block_num + 1) {
  242. int lost_block_nums = block_num - interface->last_block_num - 1;
  243. num_lost += lost_block_nums * param_retransmission_block_size;
  244. num_sent += lost_block_nums * param_retransmission_block_size;
  245. fprintf(stderr, "[%s] Lost %d blocks! Lossrate %f\t(%d / %d)\n",
  246. interface->name, block_num - interface->last_block_num - 1, 1.0 * num_lost/num_sent, num_lost, num_sent);
  247. }
  248. }*/
  249.  
  250. //safety first: we only go to the next block if the FCS is correct
  251. if(checksum_correct && block_num > interface->last_block_num)
  252. interface->last_block_num = block_num;
  253.  
  254. packet_num = seq_nr % param_retransmission_block_size; //if retr_block_size would be limited to powers of two, this could be replace by a locical and operation
  255.  
  256. //only overwrite packets where the checksum is not yet correct. otherwise the packets are already received correctly
  257.  
  258. pthread_mutex_lock(&thread_mutex);
  259.  
  260. if(checksum_correct) {
  261. packet_buffer_t *packet_buffer_list = NULL;
  262. int a;
  263. int o;
  264. int lb = INT_MAX;
  265. for(a=0; a<BLOCKCACHE_SIZE; a++) {
  266. if(block_nums[a] == block_num) {
  267. //fprintf(stderr, "%s match block=%d last_block_written=%d crc=%d\n", interface->name, block_num, last_block_written, checksum_correct);
  268. packet_buffer_list = packet_buffer_list_cache[a];
  269. break;
  270. }
  271. if(block_nums[a] < lb) {
  272. lb = block_nums[a];
  273. o = a;
  274. }
  275. }
  276. if(packet_buffer_list == NULL) {
  277. if(block_nums[o] > last_block_written) {
  278. //fprintf(stderr, "%s writing block=%d, newblock=%d\n", interface->name, block_nums[o], block_num);
  279. if(block_nums[o]-1 != last_block_written
  280. && last_block_written != 0) {
  281. fprintf(stderr, "ERROR: lost block [%d]\n", (block_nums[o]-1));
  282. packet_buffer_list = packet_buffer_list_cache[o];
  283. packet_buffer_list[packet_num].valid = 1;
  284. writeblock(interface, packet_buffer_list); //fill in
  285. }
  286. writeblock(interface, packet_buffer_list_cache[o]);
  287. last_block_written = block_nums[o];
  288. }
  289. packet_buffer_list = packet_buffer_list_cache[o];
  290. block_nums[o] = block_num;
  291. }
  292. memcpy(packet_buffer_list[packet_num].data, pu8Payload, bytes);
  293. packet_buffer_list[packet_num].len = bytes;
  294. packet_buffer_list[packet_num].valid = 1;
  295. packet_buffer_list[packet_num].crc_correct = checksum_correct;
  296. }
  297. pthread_mutex_unlock(&thread_mutex);
  298.  
  299. return;
  300. }
  301.  
  302. void *capture(void *i) {
  303. monitor_interface_t *interface = (monitor_interface_t*)i;
  304. for(;;) {
  305. process_packet(interface);
  306. }
  307. }
  308.  
  309. int
  310. main(int argc, char *argv[])
  311. {
  312. monitor_interface_t interfaces[MAX_PENUMBRA_INTERFACES];
  313. int num_interfaces = 0;
  314. memset(block_nums, 0, sizeof(block_nums));
  315. while (1) {
  316. int nOptionIndex;
  317. static const struct option optiona[] = {
  318. { "help", no_argument, &flagHelp, 1 },
  319. { 0, 0, 0, 0 }
  320. };
  321. int c = getopt_long(argc, argv, "hp:b:",
  322. optiona, &nOptionIndex);
  323.  
  324. if (c == -1)
  325. break;
  326. switch (c) {
  327. case 0: //long option
  328. break;
  329.  
  330. case 'h': //help
  331. usage();
  332.  
  333. case 'p': //port
  334. param_port = atoi(optarg);
  335. break;
  336.  
  337. case 'b': //retransmission block size
  338. param_retransmission_block_size = atoi(optarg);
  339. break;
  340.  
  341. default:
  342. fprintf(stderr, "unknown switch %c\n", c);
  343. usage();
  344. break;
  345. }
  346. }
  347.  
  348. if (optind >= argc)
  349. usage();
  350.  
  351. int a;
  352. for(a=0; a<BLOCKCACHE_SIZE; a++) {
  353. packet_buffer_list_cache[a] = lib_alloc_packet_buffer_list(param_retransmission_block_size, MAX_PACKET_LENGTH);
  354. }
  355.  
  356. int x = optind;
  357. while(x < argc && num_interfaces < MAX_PENUMBRA_INTERFACES) {
  358. open_and_configure_interface(argv[x], param_port, interfaces + num_interfaces);
  359. pthread_t tid;
  360. pthread_create(&tid, NULL, capture, interfaces + num_interfaces);
  361. ++num_interfaces;
  362. ++x;
  363. }
  364. sleep(1000000L);
  365. return (0);
  366. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement