Brak opisu

sniffer.cpp 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. #include "sniffer.h"
  2. /// \fn Sniffer::Sniffer()
  3. /// \~English
  4. /// \brief Constructor, does nothing
  5. /// \~Spanish
  6. /// \brief Constructor, no hace nada
  7. Sniffer::Sniffer(){
  8. }
  9. /// \fn Sniffer::Sniffer(QWaitCondition *pw, QMutex *mx, int *ps)
  10. /// \~English
  11. /// \brief Sets the mutexes for the inter communication between
  12. /// the sniffer and the GUI.
  13. /// \param pw used to pause the capture of packets
  14. /// \param mx used to protect critical region
  15. /// \param ps flag to pause the packet capture
  16. /// \~Spanish
  17. /// \brief Ajusta los mutexes para la inter comunicacion entre
  18. /// el sniffer y el GUI.
  19. /// \param pw se usa para pausar la captura de paquetes
  20. /// \param mx usado para proteger la region critica
  21. /// \param ps bandera para pausar la captura de paquetes
  22. Sniffer::Sniffer(QWaitCondition *pw, QMutex *mx, int *ps){
  23. wait_pause = pw ;
  24. mutex = mx ;
  25. pause = ps ;
  26. }
  27. /// \fn Sniffer::~Sniffer()
  28. /// \~English
  29. /// \brief Destructor, does nothing
  30. /// \~Spanish
  31. /// \brief Destructor, no hace nada
  32. Sniffer::~Sniffer(){
  33. }
  34. /// \fn void Sniffer::process()
  35. /// \~English
  36. /// \brief The sniffer is run as a separate thread and the function process
  37. /// is the main function of the thread. It is the sniffer.
  38. /// \~Spanish
  39. /// \brief El sniffer se corre como un hilo por separado y la funcion process
  40. /// es la funcion principal de el hilo. Es el sniffer.
  41. void Sniffer::process() Q_DECL_OVERRIDE {
  42. char *dev = NULL; /* capture device name */
  43. /* nombre del dispositivo para capturar */
  44. char errbuf[PCAP_ERRBUF_SIZE]; /* error buffer */
  45. /* buffer de error */
  46. pcap_t *handle; /* packet capture handle */
  47. /* manejador de captura de paquete */
  48. struct pcap_pkthdr header; /* The header that pcap gives us */
  49. /* El header devuelto por pcap */
  50. const u_char *packet; /* The actual packet */
  51. /* El paquete como tal */
  52. int num_packets = 100; /* number of packets to capture */
  53. /* numero de paquetes a capturar */
  54. unsigned long iptu_count = 0 ; /* counter of tcp|udp packets */
  55. /* contador de paquetes tcp|udp */
  56. /* print capture info */
  57. /* imprime informacion de captura */
  58. printf("Device: %s\n", dev);
  59. printf("Number of packets: %d\n", num_packets);
  60. /* open capture device */
  61. /* abre el dispositivo para capturar */
  62. handle = pcap_open_live(device.c_str(), SNAP_LEN, 1, 1000, errbuf);
  63. if (handle == NULL) {
  64. fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
  65. exit(EXIT_FAILURE);
  66. }
  67. /* make sure we're capturing on an Ethernet device */
  68. /* se asegura que se esta caputando en un dispositivo de Ethernet */
  69. if (pcap_datalink(handle) != DLT_EN10MB) {
  70. fprintf(stderr, "%s is not an Ethernet\n", dev);
  71. exit(EXIT_FAILURE);
  72. }
  73. /* Check if device can be set to monitor */
  74. /* Revisa si el device puede ser ajustado a modo monitoreo */
  75. if (pcap_can_set_rfmon(handle)){
  76. pcap_set_rfmon(handle, 1) ;
  77. pcap_activate(handle) ;
  78. }
  79. /* now we can set our callback function in an infinite loop */
  80. /* ahora podemos ajustar la funcion de llamada devuelta en un cyclo infinito */
  81. for(;;){
  82. mutex->lock() ;
  83. if(*pause){
  84. wait_pause->wait(mutex) ;
  85. // Stop capturing, next we need to restart
  86. // Para de capturar, next we need to restart
  87. pcap_close(handle) ;
  88. /* open capture device */
  89. /* abre el dispositivo de captura */
  90. handle = pcap_open_live(device.c_str(), SNAP_LEN, 1, 1000, errbuf);
  91. if (handle == NULL) {
  92. fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
  93. exit(EXIT_FAILURE);
  94. }
  95. /* make sure we're capturing on an Ethernet device */
  96. /* se asegura que estamos capturando en un dispositivo Ethernet */
  97. if (pcap_datalink(handle) != DLT_EN10MB) {
  98. fprintf(stderr, "%s is not an Ethernet\n", dev);
  99. exit(EXIT_FAILURE);
  100. }
  101. }
  102. mutex->unlock();
  103. packet = pcap_next(handle, &header) ;
  104. /* If a packet is received then process the packet */
  105. /* Si se recibe un paquete entonces se procesa */
  106. if(packet)
  107. got_packet(&header, packet);
  108. /* If the packet will be displayed then send singal to GUI */
  109. /* Si el paquete va a ser desplegado se envia senal al GUI */
  110. if(iptu_count < packet_list.size()){
  111. iptu_count = packet_list.size() ;
  112. emit resultReady((unsigned long) packet_list.size());
  113. }
  114. }
  115. /* cleanup */
  116. /* limpio */
  117. pcap_close(handle);
  118. /* Termino de capturar */
  119. printf("\nCapture complete.\n");
  120. printf("PACKETS IN LIST %lu\n", packet_list.size()) ;
  121. }
  122. /*
  123. * print data in rows of 16 bytes: offset hex ascii
  124. *
  125. * 00000 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d 0a GET / HTTP/1.1..
  126. */
  127. /// \fn void Sniffer::print_hex_ascii_line(const u_char *payload, int len, int offset)
  128. /// \~English
  129. /// \brief Prints to std output the a payload in ascii
  130. /// \param payload payload of the packet
  131. /// \param len length of the packet
  132. /// \param offset offset
  133. /// \~Spanish
  134. /// \brief Imprime la carga en ascii a std output
  135. /// \param payload carga del paquete
  136. /// \param len largo de la carga
  137. /// \param offset distancia
  138. void
  139. Sniffer::print_hex_ascii_line(const u_char *payload, int len, int offset)
  140. {
  141. int i;
  142. int gap;
  143. const u_char *ch;
  144. /* offset */
  145. printf("%05d ", offset);
  146. /* hex */
  147. ch = payload;
  148. for(i = 0; i < len; i++) {
  149. printf("%02x ", *ch);
  150. ch++;
  151. /* print extra space after 8th byte for visual aid */
  152. if (i == 7)
  153. printf(" ");
  154. }
  155. /* print space to handle line less than 8 bytes */
  156. if (len < 8)
  157. printf(" ");
  158. /* fill hex gap with spaces if not full line */
  159. if (len < 16) {
  160. gap = 16 - len;
  161. for (i = 0; i < gap; i++) {
  162. printf(" ");
  163. }
  164. }
  165. printf(" ");
  166. /* ascii (if printable) */
  167. ch = payload;
  168. for(i = 0; i < len; i++) {
  169. if (isprint(*ch))
  170. printf("%c", *ch);
  171. else
  172. printf(".");
  173. ch++;
  174. }
  175. printf("\n");
  176. return;
  177. }
  178. /// \fn string Sniffer::format_hex_ascii_line(const char *payload, int len, int offset)
  179. /// \~English
  180. /// \brief Return string with the bytes of a payload line in ascii
  181. /// \param payload payload of the packet
  182. /// \param len length of the packet
  183. /// \param offset offset of packet
  184. /// \return a string with the bytes of a payload line in ascii
  185. /// \~Spanish
  186. /// \brief Devuelve una cadena de caracteres con los bytes de una linea
  187. /// de la carga en ascii
  188. /// \param payload carga del paquete
  189. /// \param len largo del paquete
  190. /// \param offset distancia del paquete
  191. /// \return a string with the bytes of a payload line in ascii
  192. string
  193. Sniffer::format_hex_ascii_line(const char *payload, int len, int offset)
  194. {
  195. int i;
  196. int gap;
  197. const char *ch;
  198. string line ;
  199. char temp[15] ;
  200. /* offset */
  201. sprintf(temp, "%05d ", offset);
  202. line.append(temp) ;
  203. /* hex */
  204. ch = payload;
  205. for(i = 0; i < len; i++) {
  206. sprintf(temp, "%02x ", (unsigned char) *ch);
  207. line.append(temp) ;
  208. ch++;
  209. /* print extra space after 8th byte for visual aid */
  210. if (i == 7)
  211. line.append(" ") ;
  212. }
  213. /* print space to handle line less than 8 bytes */
  214. if (len < 8)
  215. line.append(" ") ;
  216. /* fill hex gap with spaces if not full line */
  217. if (len < 16) {
  218. gap = 16 - len;
  219. for (i = 0; i < gap; i++) {
  220. line.append(" ") ;
  221. }
  222. }
  223. line.append(" ");
  224. /* ascii (if printable) */
  225. ch = payload;
  226. for(i = 0; i < len; i++) {
  227. if (isprint(*ch))
  228. line += (unsigned char) *ch ;
  229. else
  230. line.append(".") ;
  231. ch++;
  232. }
  233. line.append("\n") ;
  234. return line ;
  235. }
  236. /*
  237. * print packet payload data (avoid printing binary data)
  238. */
  239. /// \fn void Sniffer::print_payload(const u_char *payload, int len)
  240. /// \~English
  241. /// \brief Prints the payload in ascii
  242. /// \param payload payload of the packet
  243. /// \param len payload length
  244. /// \~Spanish
  245. /// \brief Imprime la carga en ascii
  246. /// \param payload carga del paquete
  247. /// \param len largo de la carga
  248. void Sniffer::print_payload(const u_char *payload, int len)
  249. {
  250. int len_rem = len;
  251. int line_width = 16; /* number of bytes per line */
  252. /* numero de bytes por linea */
  253. int line_len;
  254. int offset = 0; /* zero-based offset counter */
  255. /* basado a cero, contador de compensacion */
  256. const u_char *ch = payload;
  257. if (len <= 0)
  258. return;
  259. /* data fits on one line */
  260. /* data cabe en una linea */
  261. if (len <= line_width) {
  262. print_hex_ascii_line(ch, len, offset);
  263. return;
  264. }
  265. /* data spans multiple lines */
  266. /* data cubre multiples lineas */
  267. for ( ;; ) {
  268. /* compute current line length */
  269. /* computa el largo de la linea corriente */
  270. line_len = line_width % len_rem;
  271. /* print line */
  272. /* imprime linea */
  273. print_hex_ascii_line(ch, line_len, offset);
  274. /* compute total remaining */
  275. /* computa total que queda */
  276. len_rem = len_rem - line_len;
  277. /* shift pointer to remaining bytes to print */
  278. /* mueve el apuntado a los bytes que quedan para imprimir */
  279. ch = ch + line_len;
  280. /* add offset */
  281. /* anade compensacion */
  282. offset = offset + line_width;
  283. /* check if we have line width chars or less */
  284. /* revisa si tenemos una linea con ancho completo o menos */
  285. if (len_rem <= line_width) {
  286. /* print last line and get out */
  287. /* imprime la ultima linea y sale */
  288. print_hex_ascii_line(ch, len_rem, offset);
  289. break;
  290. }
  291. }
  292. return;
  293. }
  294. /// \fn string Sniffer::format_payload(const char *payload, int len)
  295. /// \~English
  296. /// \brief Formats the payload from a byte stream into a string of ascci
  297. /// \param payload payload of the packet
  298. /// \param len length of the packet
  299. /// \return the payload in a string of ascii
  300. /// \~Spanish
  301. /// \brief Formatea la carga de un torrente de bytes a un cadena de
  302. /// caracteres ascii
  303. /// \param payload carga del paquete
  304. /// \param len largo del paquete
  305. /// \return la carga en una cadena de caracteres ascii
  306. string Sniffer::format_payload(const char *payload, int len)
  307. {
  308. int len_rem = len;
  309. int line_width = 16; /* number of bytes per line */
  310. int line_len;
  311. int offset = 0; /* zero-based offset counter */
  312. const char *ch = payload;
  313. string formated ;
  314. if (len <= 0)
  315. return "";
  316. /* data fits on one line */
  317. if (len <= line_width) {
  318. formated += format_hex_ascii_line(ch, len, offset);
  319. return "";
  320. }
  321. /* data spans multiple lines */
  322. for ( ;; ) {
  323. /* compute current line length */
  324. line_len = line_width % len_rem;
  325. /* print line */
  326. formated += format_hex_ascii_line(ch, line_len, offset);
  327. /* compute total remaining */
  328. len_rem = len_rem - line_len;
  329. /* shift pointer to remaining bytes to print */
  330. ch = ch + line_len;
  331. /* add offset */
  332. offset = offset + line_width;
  333. /* check if we have line width chars or less */
  334. if (len_rem <= line_width) {
  335. /* print last line and get out */
  336. formated += format_hex_ascii_line(ch, len_rem, offset);
  337. break;
  338. }
  339. }
  340. return formated;
  341. }
  342. /// \fn void Sniffer::got_packet(const struct pcap_pkthdr *, const u_char *packet)
  343. /// \~English
  344. /// \brief Disects the received packet. Takes out the info needed.
  345. /// \param pcap_pkthdr header of the pcap packet
  346. /// \param packet recieved packet
  347. /// \~Spanish
  348. /// \brief Secciona el paquete recibido. Extrae la informacion necesaria.
  349. /// \param pcap_pkthdr encabezado del paquete de pcap
  350. /// \param packet paquete recibido
  351. void
  352. Sniffer::got_packet(const struct pcap_pkthdr *, const u_char *packet)
  353. {
  354. /* declare pointers to packet headers */
  355. /* declara apuntadores a los headers del paquete. */
  356. const struct sniff_ethernet *ethernet; /* The Ethernet header */
  357. /* El encabezado de Ethernet */
  358. const struct sniff_ip *ip; /* The IP header */
  359. /* Encabezado de IP */
  360. const struct sniff_tcp *tcp; /* The TCP header */
  361. /* Encabezado de TCP */
  362. const struct sniff_udp *udp ; /* The UDP header */
  363. /* Encabezado de UDP */
  364. const u_char *payload; /* Packet payload */
  365. /* Carga del paquete */
  366. ip_packet ip_pkt ; /* IP Packet */
  367. /* Paquete de IP */
  368. int size_ip; // to store the size of IP
  369. // para guardar el tamano de IP
  370. int size_tcp; // to store the size of tcp
  371. // para guardar el tamano de TCP
  372. int size_payload; // to store the size of payload
  373. // para guardar el tamano del payload
  374. ethernet = (struct sniff_ethernet*)(packet);
  375. /* define/compute IP header offset */
  376. /* define/computa donde empieza el header de IP */
  377. ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
  378. size_ip = IP_HL(ip)*4;
  379. if (size_ip < 20) {
  380. // qDebug() << " * Invalid IP header length: " << size_ip <<" bytes\n" ;
  381. printf(" * Invalid IP header length: %u bytes\n", size_ip);
  382. return ;
  383. }
  384. /* print source and destination IP addresses */
  385. /* imprime las direcciones fuente y destino de IP */
  386. printf(" From: %s\n", inet_ntoa(ip->ip_src));
  387. printf(" To: %s\n", inet_ntoa(ip->ip_dst));
  388. ip_pkt.setEtherSHost((u_char *)ethernet->ether_shost) ;
  389. ip_pkt.setEtherDHost((u_char *)ethernet->ether_dhost);
  390. ip_pkt.setIPSAddress(inet_ntoa(ip->ip_src));
  391. ip_pkt.setIPDAddress(inet_ntoa(ip->ip_dst));
  392. ip_pkt.setIPProto(ip->ip_p);
  393. /* determine protocol */
  394. /* determina el protocolo */
  395. switch(ip->ip_p) {
  396. case IPPROTO_TCP:
  397. printf(" Protocol: TCP\n");
  398. /* define/compute tcp header offset */
  399. /* define/computa el donde empieza el encabezado tcp */
  400. tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
  401. size_tcp = TH_OFF(tcp)*4;
  402. if (size_tcp < 20) {
  403. printf(" * Invalid TCP header length: %u bytes\n", size_tcp);
  404. return;
  405. }
  406. ip_pkt.setIPSPort(ntohs(tcp->th_sport)) ;
  407. ip_pkt.setIPDPort(ntohs(tcp->th_dport)) ;
  408. printf(" Src port: %d\n", ntohs(tcp->th_sport));
  409. printf(" Dst port: %d\n", ntohs(tcp->th_dport));
  410. /* define/compute tcp payload (segment) offset */
  411. /* define/computa donde empieza la carga tcp */
  412. payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp);
  413. /* compute tcp payload (segment) size */
  414. /* computa el tamano de la carga tcp */
  415. size_payload = ntohs(ip->ip_len) - (size_ip + size_tcp);
  416. ip_pkt.setPayload((char *) payload, size_payload);
  417. packet_list.push_back(ip_pkt);
  418. break ;
  419. case IPPROTO_UDP:
  420. printf(" Protocol: UDP\n");
  421. udp = (struct sniff_udp*)(packet + SIZE_ETHERNET + size_ip);
  422. ip_pkt.setIPSPort(ntohs(udp->th_sport)) ;
  423. ip_pkt.setIPDPort(ntohs(udp->th_dport)) ;
  424. printf(" Src port: %d\n", ntohs(udp->th_sport));
  425. printf(" Dst port: %d\n", ntohs(udp->th_dport));
  426. /* define/compute udp payload (segment) offset */
  427. /* define/computa donde comienza UDP */
  428. payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + 8);
  429. /* compute udp payload (segment) size */
  430. /* computa donde comienza la carga del UDP */
  431. size_payload = ntohs(ip->ip_len) - (size_ip + 8);
  432. ip_pkt.setPayload((char *)payload, size_payload);
  433. packet_list.push_back(ip_pkt);
  434. break;
  435. case IPPROTO_ICMP:
  436. printf(" Protocol: ICMP\n");
  437. break;
  438. case IPPROTO_IP:
  439. printf(" Protocol: IP\n");
  440. break;
  441. default:
  442. printf(" Protocol: unknown\n");
  443. break;
  444. }
  445. return;
  446. }
  447. /// \fn vector<ip_packet> *Sniffer::getPacketList()
  448. /// \~English
  449. /// \brief Returns the packet list that contains the packets that are
  450. /// Ethernet -> IP -> (TCP|UDP)
  451. /// \return vector of packets
  452. /// \~Spanish
  453. /// \brief Devuelve la lista de paquetes que contiene los paquetes que son
  454. /// Ethernet -> IP -> (TCP|UDP)
  455. /// \return vector de paquetes
  456. vector<ip_packet> *Sniffer::getPacketList(){
  457. return &packet_list ;
  458. }
  459. /// \fn void Sniffer::find_devices(vector<string> &devs)
  460. /// \~English
  461. /// \brief Find the network devices in the computer, and store them in vector devs.
  462. /// \param devs vector of string for device names
  463. /// \~Spanish
  464. /// \brief Encuentra los dispositivos de red en la computadora, y los almacena en
  465. /// el vector devs
  466. /// \param devs vector de cadenas de caracteres para los nombres
  467. void Sniffer::find_devices(vector<string> &devs){
  468. char errbuf[PCAP_ERRBUF_SIZE];
  469. pcap_if_t *devices ;
  470. if(pcap_findalldevs(&devices, errbuf) == 0 && devices != NULL){
  471. while(devices){
  472. string s(devices->name) ;
  473. devs.push_back(s) ;
  474. devices = devices->next ;
  475. }
  476. pcap_freealldevs(devices);
  477. }
  478. else{
  479. devs.push_back("None") ;
  480. }
  481. return ;
  482. }
  483. /// \fn void Sniffer::setDevice(string dev)
  484. /// \~English
  485. /// \brief Sets the device to capture packets to dev
  486. /// \param dev name of the device
  487. /// \~Spanish
  488. /// \brief Ajusta el dispositivo para caputurar paquetes a dev
  489. /// \param dev nombre del dispositivo
  490. void Sniffer::setDevice(string dev){
  491. device = dev ;
  492. }