00001
00007 #include "include/NetSniff.h"
00008 #include "include/generic.h"
00009 #include "include/SIPPacket.h"
00010 #ifndef DEBUG_H_
00011 #include "include/Debug.h"
00012 #endif
00013 #include <string>
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #include <pcap-bpf.h>
00018 #include <pcap.h>
00019 #include <signal.h>
00020 #include <netinet/in.h>
00021 #include <sys/socket.h>
00022 #include <arpa/inet.h>
00023 #include <netdb.h>
00024 #include <sys/types.h>
00025 #include <unistd.h>
00026 #include <sys/time.h>
00027 #include <time.h>
00028
00029 #include <boost/thread/thread.hpp>
00030 #include <netinet/if_ether.h>
00031
00032 namespace network
00033 {
00034
00035 NetSniff::NetSniff(string device, string sniffport, string sniffproto)
00036 {
00037
00038 sniffed = 0;
00039 displayed = 0;
00040 stored = 0;
00041 snfshow = false;
00042 snfcap = false;
00043
00044 strncpy((char *)&dev, device.c_str(), sizeof(dev));
00045 strncpy((char *)&port, sniffport.c_str(), sizeof(port));
00046 strncpy((char *)&snfproto, sniffproto.c_str(), sizeof(snfproto));
00047
00048 ready = false;
00049 }
00050
00051 void NetSniff::SetShow(bool option)
00052 {
00053 snfshow = option;
00054 }
00055
00056 void NetSniff::SetCapture(bool option, string captpath)
00057 {
00058 snfcap = option;
00059 dbg->Prntdbg(CODEAT, 20, "Setting capture files path to " + captpath);
00060 snfcappath = captpath;
00061 }
00062
00063 bool NetSniff::Open()
00064 {
00065 #define ETH_LEN 14
00066 #define IP_MIN_LEN 20
00067 #define SNAP_LEN 65535
00068 #define PCAP_TIMEOUT 0
00069
00070 #define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)
00071 #define IP_V(ip) (((ip)->ip_vhl) >> 4)
00072
00073
00074 char errbuf[PCAP_ERRBUF_SIZE];
00075 if ((sniff = pcap_open_live(dev, SNAP_LEN, 1, PCAP_TIMEOUT, errbuf))==NULL) {
00076 dbgbuffer << "Unable to open device " << dev << " for sniffing: " << errbuf;
00077 dbg->Prnterr(CODEAT, dbgbuffer.str());
00078 ready = false;
00079 return ready;
00080 }
00081
00082 if (pcap_lookupnet(dev, &ip, &mask, errbuf) == -1) {
00083 dbgbuffer << "ERROR: Unable to obtain " << dev << " IP and mask";
00084 dbg->Prnterr(CODEAT, dbgbuffer.str());
00085 mask = 0;
00086 ip = 0;
00087 ready = false;
00088 return ready;
00089 }
00090
00091 dbg->Prntdbg(CODEAT, 20, "Device opened successfully");
00092
00093 pkghand.SetDebugger(dbg);
00094
00095 return true;
00096 }
00097
00098 bool NetSniff::isReady()
00099 {
00100 return ready;
00101 }
00102
00103 void NetSniff::startsniff()
00104 {
00105 dbg->Prntdbg(CODEAT, 10, "Start sniffing");
00106
00107 struct pcap_pkthdr *pkt_header;
00108 const u_char *pkt_data;
00109
00110 #define LINE_LEN 16
00111 dosniff = true;
00112
00113
00114 pcap_dumper_t *dumper;
00115 dumper = NULL;
00116
00117 if (snfcap)
00118 {
00119
00120 time_t seconds;
00121 seconds = time (NULL);
00122 dbgbuffer << seconds;
00123
00124 file = snfcappath;
00125 file += "voiphoney_"+ dbgbuffer.str() +".cap";
00126 dbgbuffer.str("");
00127 if ( (dumper = pcap_dump_open(sniff, file.c_str())) == NULL)
00128 dbg->Prnterr(CODEAT, "Could not open savefile "+ file);
00129 else
00130 dbg->Prntdbg(CODEAT, 20, "Saving capture to " + file);
00131 }
00132
00133 do {
00134 if (pcap_next_ex(sniff, &pkt_header, &pkt_data))
00135 {
00136 if (snfshow)
00137 PrintPacket(pkt_data, pkt_header);
00138 if (snfcap)
00139 {
00140 pcap_dump((u_char *) dumper, pkt_header, pkt_data);
00141 stored++;
00142 }
00143 }
00144 sniffed++;
00145 } while (dosniff);
00146
00147 if (sniffed > 0) {
00148 dbgbuffer << sniffed << " packets sniffed and " << displayed << " packets displayed";
00149 dbg->Prntdbg(CODEAT, 10, dbgbuffer.str());
00150 dbgbuffer.str("");
00151 }
00152 dbg->Prntdbg(CODEAT, 10, "Sniffing stopped");
00153 }
00154
00155 void NetSniff::stopsniff()
00156 {
00157 dbg->Prntdbg(CODEAT, 10, "Stopping sniffing");
00158 dosniff = false;
00159 }
00160
00161 void NetSniff::PrintPacket(const u_char *pkt_data, const struct pcap_pkthdr *pkt_header) {
00162
00163 dbg->Prntdbg(CODEAT, 50, "New packet for processing");
00164
00165 char timebuff[30];
00166 char hexc[3];
00167 struct iphdr *cip;
00168 struct ether_header *ethernet;
00169 int size_ip;
00170 u_int ipversion;
00171 const char* protocol;
00172
00173 string plain_text;
00174 string ascii_line;
00175 ostringstream databuffer;
00176 char ipbuffer[15];
00177
00178 if (pkt_header->len > 0)
00179 {
00180 time_t timestamp = pkt_header->ts.tv_sec;
00181 strftime(timebuff, 30, "%Y/%m/%d %T", localtime(×tamp));
00182
00183 ethernet = (struct ether_header*)(pkt_data);
00184
00185
00186 cip = (struct iphdr *)(pkt_data+ETH_LEN);
00187 size_ip = IP_HL(cip)*4;
00188 if (size_ip < 20) {
00189 dbgbuffer << "Invalid IP header length: " << size_ip << " bytes";
00190 dbg->Prnterr(CODEAT, dbgbuffer.str());
00191 dbgbuffer.str("");
00192 return;
00193 }
00194
00195 dbg->Prntdbg(CODEAT, 50, "Correct Packet for processing");
00196
00197
00198 ipversion = IP_V(cip);
00199
00200
00201 switch(cip->ip_p) {
00202 case IPPROTO_TCP:
00203 protocol = "TCP";
00204 break;
00205 case IPPROTO_UDP:
00206 protocol = "UDP";
00207 break;
00208 case IPPROTO_ICMP:
00209 protocol = "ICMP";
00210 break;
00211 case IPPROTO_IP:
00212 protocol = "IP";
00213 break;
00214 default:
00215 protocol = "unknown";
00216 break;
00217 }
00218
00219 int ttl = cip->ip_ttl;
00220 string sourceip;
00221 string destinationip;
00222 sprintf(ipbuffer, "%d.%d.%d.%d", cip->ip_src1, cip->ip_src2, cip->ip_src3, cip->ip_src4);
00223 sourceip = ipbuffer;
00224 sprintf(ipbuffer, "%d.%d.%d.%d", cip->ip_dst1, cip->ip_dst2, cip->ip_dst3, cip->ip_dst4);
00225 destinationip = ipbuffer;
00226
00227
00228 cout << endl << "┌───────────────────────────────────────────┬──────────────────────────────┐" << endl;
00229 cout << "│ Timestamp: " << timebuff << ".";
00230 cout.width(6);cout << pkt_header->ts.tv_usec;
00231 cout << " │ Size: ";
00232 cout.width(8);cout << pkt_header->len;
00233 cout <<" bytes │" << endl;
00234 cout << "├──────┬────────────────┬───────────────────┼──────────────────────────────┤" << endl;
00235 cout << "│ IPv" << ipversion << " │ Protocol: ";
00236 cout.width(4);
00237 cout << protocol;
00238 cout << " │ TTL: ";
00239 cout.width(3);
00240 cout << ttl;
00241 cout << " │ │" << endl;
00242 cout << "├──────┴────────────────┴──────────┬────────┴──────────────────────────────┤" << endl;
00243 cout << "│ Source: ";
00244 cout.width(15);
00245 cout << HWAddress(ethernet->ether_shost).c_str();
00246 cout << " │ Destination: ";
00247 cout.width(15);
00248 cout << HWAddress(ethernet->ether_dhost).c_str() << " │"<< endl;
00249 cout << "├──────────────────────────────────┼───────────────────────────────────────┤" << endl;
00250 cout << "│ Source: ";
00251 cout.fill(' ');cout.width(15);
00252 cout << sourceip.c_str();
00253 cout << " │ Destination: ";
00254 cout.fill(' ');cout.width(15);
00255 cout << destinationip.c_str();
00256 cout << " │" << endl;
00257 cout << "╞══════════════════════════════════╪═══════════════════════════════════════╡" << endl;
00258 cout << "├──────────────────────────────────┴────────────────┬──────────────────────┤" << endl;
00259
00260
00261
00262
00263 cout << "│ ";
00264 int offset, charpos;
00265
00266
00267 charpos = 0;
00268 for (unsigned int i=1; (i <= pkt_header->caplen) ; i++)
00269 {
00270 charpos++;
00271 sprintf(hexc, "%.2x", pkt_data[i-1]);
00272
00273 printf("%s ", hexc);
00274 unsigned int val;
00275 sscanf(hexc, "%x", &val);
00276 if (isprint (val) && val < 127)
00277 {
00278 databuffer << hex << pkt_data[i-1];
00279 plain_text += databuffer.str();
00280 ascii_line += databuffer.str();
00281 databuffer.str("");
00282 }
00283 else
00284 {
00285 plain_text += ".";
00286 ascii_line += ".";
00287 }
00288 if ( (i % LINE_LEN) == 0 || (i == pkt_header->caplen))
00289 {
00290 if (i != pkt_header->caplen)
00291 {
00292 cout << " │ " << ascii_line.c_str();
00293 ascii_line = "";
00294 cout << " │" << endl << "│ ";
00295 charpos = 0;
00296 }
00297 else
00298 {
00299 offset = LINE_LEN - charpos;
00300 for (int z=0; z <= (offset * 3); z++)
00301 cout << " ";
00302 if (offset >= 8)
00303 cout << " ";
00304 cout << "│ " << ascii_line.c_str();
00305 for (int z=0; z <= (offset); z++)
00306 cout << " ";
00307 if (offset >= 8)
00308 cout << " ";
00309 cout << " │" << endl;
00310 }
00311 }
00312 else if ( (i % (LINE_LEN / 2)) == 0)
00313 {
00314 cout << " ";
00315 ascii_line += " ";
00316 }
00317 }
00318 cout << "└───────────────────────────────────────────────────┴──────────────────────┘" << endl << endl;
00319
00320
00321
00322
00323
00324 sipp = new SIPPacket(plain_text);
00325 sipp->SetHeadder(pkt_header);
00326 pkghand.HandlePacket(sipp);
00327 free(sipp);
00328 displayed++;
00329 }
00330 }
00331
00332 string NetSniff::HWAddress(u_char *ptr)
00333 {
00334 string hwadd = "";
00335 char buffer[ETHER_ADDR_LEN];
00336
00337 int i = ETHER_ADDR_LEN;
00338 do{
00339 sprintf(buffer, "%s%x",(i == ETHER_ADDR_LEN) ? " " : ":",*ptr++);
00340 hwadd += buffer;
00341 }while(--i>0);
00342
00343 if (hwadd.length() >= 17)
00344 hwadd.insert(1,"0");
00345 return hwadd;
00346 }
00347
00348 bool NetSniff::ApplyFilter(const char* filter)
00349 {
00350 memset(BPFfilter, 0, 2048);
00351
00352
00353 strncat(BPFfilter, snfproto, sizeof(BPFfilter));
00354 strncat(BPFfilter, " and port ", sizeof(BPFfilter));
00355 strncat(BPFfilter, port, sizeof(BPFfilter));
00356 if (strcmp(filter,"default") != 0) {
00357 strncat(BPFfilter, " and ", sizeof(BPFfilter));
00358 strncat(BPFfilter, filter, sizeof(BPFfilter));
00359 }
00360
00361
00362 if (pcap_compile(sniff, &fp, BPFfilter, 1, mask) == -1) {
00363 dbgbuffer << "Unable to parse filter '" << filter << "': " << pcap_geterr(sniff);
00364 dbg->Prnterr(CODEAT, dbgbuffer.str());
00365 dbgbuffer.str("");
00366 ready = false;
00367 return ready;
00368 }
00369
00370
00371 if (pcap_setfilter(sniff, &fp) == -1) {
00372 dbgbuffer << "Unable to apply filter '" << filter << "': " << pcap_geterr(sniff);
00373 dbg->Prnterr(CODEAT, dbgbuffer.str());
00374 dbgbuffer.str("");
00375 ready = false;
00376 return ready;
00377 }
00378
00379 dbgbuffer << "OK, listening on interface " << dev << " port " << port;
00380 dbg->Prntdbg(CODEAT, 10, dbgbuffer.str());
00381 dbgbuffer.str("");
00382
00383 dbgbuffer << "BPF filter: '" << BPFfilter << "'";
00384 dbg->Prntdbg(CODEAT, 20, dbgbuffer.str());
00385 dbgbuffer.str("");
00386
00387
00388 ready = true;
00389
00390 return ready;
00391 }
00392
00393 string NetSniff::GetFullStatus()
00394 {
00395 dbgbuffer << "Device: " << FORE_CYAN << dev << ENDCOLOR;
00396 dbgbuffer << " Protocol: " << FORE_PURPLE << snfproto << ENDCOLOR;
00397 dbgbuffer << " Port: " << FORE_RED << port << ENDCOLOR << endl;
00398 dbgbuffer << "BPF filter: " << BPFfilter << endl << endl;
00399 dbgbuffer << "Number of packets: sniffed " << sniffed;
00400 dbgbuffer << " | displayed: " << displayed;
00401 dbgbuffer << " | saved: " << stored << endl;
00402 dbgbuffer << "Displaying packets: ";
00403 if (snfshow)
00404 dbgbuffer << FORE_GREEN;
00405 else
00406 dbgbuffer << FORE_RED;
00407 dbgbuffer << (snfshow ? "ENABLED" : "DISABLED") << ENDCOLOR;
00408 dbgbuffer << " Saving packets: ";
00409 if (snfcap)
00410 dbgbuffer << FORE_GREEN;
00411 else
00412 dbgbuffer << FORE_RED;
00413 dbgbuffer << (snfcap ? "ENABLED" : "DISABLED") << ENDCOLOR << endl;
00414 if (snfcap)
00415 dbgbuffer << "Storing capture in: " << file << endl;
00416
00417 string stats = dbgbuffer.str();
00418 dbgbuffer.str("");
00419 return stats;
00420 }
00421
00422 void NetSniff::setDebugger(Debug *dbg)
00423 {
00424 this->dbg = dbg;
00425 }
00426
00427 bool NetSniff::isSniffing()
00428 {
00429 return dosniff;
00430 }
00431
00432 NetSniff::~NetSniff()
00433 {
00434 if (sniffed > 0) {
00435 pcap_freecode(&fp);
00436 pcap_close(sniff);
00437 }
00438 }
00439 }