pipacs.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. // http://www.phj.hu/freesoft.asp
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include "parser.h"
  5. #ifndef LINUX
  6. #include <mstcpip.h>
  7. #include <ws2tcpip.h>
  8. #else
  9. #include <termios.h>
  10. struct promisc_device
  11. {
  12. char name[16]; /* name (e.g. eth0) */
  13. int reset; /* do we have to reset it on exit ? */
  14. struct ifreq oldifr; /* old settings */
  15. struct promisc_device *next;
  16. };
  17. #endif
  18. DWORD dwIoControlCode=SIO_RCVALL;
  19. DWORD dwProtocol=IPPROTO_IP, dwInterface=0;
  20. #define MAXVER 2
  21. #define MINVER 6
  22. SOCKET s;
  23. //
  24. // Filters (Globals)
  25. //
  26. unsigned int uiSourceAddr=0, uiDestAddr=0, uiXAddr=0;
  27. unsigned short usSourcePort = 0, usDestPort = 0, usXPort = 0;
  28. unsigned short usSourceNet = 32, usDestNet = 32, usXNet = 32;
  29. unsigned long ulDestNet=0xffffffff, ulSourceNet=0xffffffff, ulXNet=0xffffffff;
  30. BOOL bFilter=FALSE;
  31. int iline=25;
  32. char myipname[64];
  33. char pattern[1024];
  34. int justheader=0;
  35. int gre=0;
  36. int sortbysize,fromip,toip;
  37. int skipvlan=0;
  38. extern char filename[128];
  39. extern char intlist[128];
  40. #ifndef LINUX
  41. void PrintInterfaceList( void );
  42. int GetInterface(SOCKET , SOCKADDR_IN *, int );
  43. #endif
  44. extern int InitIPAcc( void );
  45. extern int CloseIPAcc( void );
  46. extern int iCycle;
  47. extern int iScreen;
  48. extern int iFile;
  49. extern int iDetail;
  50. extern int iRun;
  51. extern long lNum;
  52. extern FILE *f;
  53. extern int iProto;
  54. extern int iSum;
  55. extern char execname[];
  56. extern int mostird;
  57. extern int iLnxplus;
  58. int set_raw_mode(void)
  59. {
  60. int fd = STDIN_FILENO;
  61. struct termios t;
  62. if (tcgetattr(fd, &t) < 0) { perror("tcgetattr"); return -1; }
  63. t.c_lflag &= ~ICANON;
  64. if (tcsetattr(fd, TCSANOW, &t) < 0) { perror("tcsetattr"); return -1; }
  65. setbuf(stdin, NULL);
  66. return 0;
  67. }//
  68. // Function: usage
  69. //
  70. // Description:
  71. // Prints usage information.
  72. //
  73. char *author = "phj";
  74. void usage(char *progname)
  75. {
  76. printf(" usage: %s options\n where options:\n", progname);
  77. printf(" [-c:sec] Dump cycle in sec (10)\n");
  78. printf(" [-f:file[-e:program]] Results into a file [and exec program](-)\n");
  79. printf(" [-n:db] Execute just db cycle (0)\n");
  80. printf(" [-l:lineno] Print lineno lines of hosts(25)\n");
  81. printf(" [-k] Sort result by packet count (size)\n");
  82. printf(" [-1] Ignore source IP (don't ignore)\n");
  83. printf(" [-2] Ignore destination IP (don't ignore)\n");
  84. printf(" [-h] Print just the header(use -a!)\n");
  85. printf(" [-a] Print packet info&data (-)\n");
  86. printf(" [-p] Print just summary info (-)\n");
  87. printf(" Otherwise print sum&ip pairs\n");
  88. //#ifndef LINUX
  89. printf(" [-t:[tcp|udp|icmp|....|number]] Filter on IP protocoll (ALL)\n");
  90. //#endif
  91. printf(" [-g] Make GRE encapsulation trasparent (-)\n");
  92. printf(" [-v] Skip VLAN headers (-)\n");
  93. printf(" [-sa:IP[/Net]] Filter on source address (-)/net\n");
  94. printf(" [-sp:Port] Filter on source port (-)\n");
  95. printf(" [-da:IP[/Net]] Filter on dest address/net (-)\n");
  96. printf(" [-dp:Port] Filter on dest port(-)\n");
  97. printf(" [-xa:IP[/Net]] Filter on src|dest address/net (-)\n");
  98. printf(" [-xp:Port] Filter on src|dest port (-)\n");
  99. printf(" [-pa:pattern] String match (0), last param!!!\n");
  100. #ifndef LINUX
  101. printf(" [-i:int] Capture on this interface (0)\n");
  102. printf(" Available interfaces:\n");
  103. PrintInterfaceList();
  104. #else
  105. printf(" [-i:int[,int]] Capture on this interface (eth0)\n");
  106. #endif
  107. printf(" Filtering rules: t && (sa|da|xa) && (sp|dp|xp)");
  108. printf("\nVer. %d.%d (c):2000-2006, P l¢czi-Horv th J nos\n",MAXVER,MINVER);
  109. #ifndef LINUX
  110. WSACleanup();
  111. ExitProcess(-1);
  112. #else
  113. exit(5);
  114. #endif
  115. }
  116. //
  117. // Function: ValidateArgs
  118. //
  119. // Description:
  120. // This function parses the command line arguments and
  121. // sets global variables to indicate how the app should act.
  122. //
  123. void ValidateArgs(int argc, char **argv)
  124. {
  125. int i,j;
  126. char *ptr;
  127. sortbysize=1; fromip=1; toip=1;
  128. if (argc <2) { usage(argv[0]); return; }
  129. if (*(author+2) != 'j') { usage(argv[0]); return; }
  130. for(i=1; i < argc ;i++) {
  131. if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
  132. switch (tolower(argv[i][1])) {
  133. case 't': // traffic type
  134. ptr = &argv[i][2];
  135. while (*++ptr) *ptr = toupper(*ptr);
  136. ptr = &argv[i][3];
  137. for ( j=0;j<134;j++) {
  138. if (!strcmp(ptr, szProto[j])) {
  139. // dwIoControlCode = SIO_RCVALL;
  140. #ifdef LINUX
  141. dwProtocol = j;
  142. #endif
  143. iProto=j;
  144. break;
  145. }
  146. }
  147. if ((j>133) && atoi(&argv[i][3])) {
  148. // dwIoControlCode = SIO_RCVALL;
  149. #ifdef LINUX
  150. dwProtocol = atoi(&argv[i][3]);
  151. #endif
  152. iProto=atoi(&argv[i][3]);
  153. } else if (j>133) usage(argv[0]);
  154. break;
  155. case 'i': // interface number
  156. #ifndef LINUX
  157. dwInterface = atoi(&argv[i][3]);
  158. #else
  159. strcpy(intlist,&argv[i][3]);
  160. ptr=strchr(intlist,' ');
  161. if (ptr) *ptr=0;
  162. #endif
  163. break;
  164. case 'g': // gre
  165. gre=1;
  166. break;
  167. case 'c': // cycle time
  168. iCycle = atoi(&argv[i][3]);
  169. break;
  170. case 'a': // cycle time
  171. iDetail = 1;
  172. break;
  173. case 'h': // cycle time
  174. iDetail = justheader = 1;
  175. break;
  176. case 'n': // just n cycle
  177. lNum = atol(&argv[i][3]);
  178. break;
  179. case 'l': // lineno lines
  180. iline = atoi(&argv[i][3]);
  181. break;
  182. case 'p': // just summary
  183. if ((tolower(argv[i][2]) == 'a')) {
  184. strcpy(pattern,&argv[i][4]); printf("\n Pattern: \'%s",&argv[i][4]);
  185. while (++i<argc) { strcat(pattern," "); strcat(pattern,&argv[i][0]); printf(" %s",argv[i]); }
  186. printf("\'\n");
  187. } else iSum=1;
  188. break;
  189. case 'f': // filename to write
  190. strcpy(filename,&argv[i][3]);
  191. iFile=1; //iScreen=0;
  192. break;
  193. case 'e': // execname
  194. strcpy(execname,&argv[i][3]);
  195. break;
  196. case 'k': // sor by count
  197. sortbysize = 0;
  198. break;
  199. case '1': // ignore src
  200. fromip = 0;
  201. break;
  202. case '2': // ignore dst
  203. toip = 0;
  204. break;
  205. case 'v': // sor by count
  206. skipvlan = 4;
  207. if ((tolower(argv[i][2]) == ':')) {
  208. skipvlan=atoi(&argv[i][3]);
  209. }
  210. break;
  211. case 's': // Filter on source ip or port
  212. if (tolower(argv[i][2]) == 'a') {
  213. ptr=strchr(&argv[i][4],'/');
  214. if (ptr) { usSourceNet=atoi(ptr+1); *ptr=0;}
  215. uiSourceAddr = ntohl(inet_addr(&argv[i][4]));
  216. } else if (tolower(argv[i][2]) == 'p')
  217. usSourcePort = (unsigned short)atoi(&argv[i][4]);
  218. else
  219. usage(argv[0]);
  220. bFilter = TRUE;
  221. break;
  222. case 'd': // Filter on dest ip or port
  223. if (tolower(argv[i][2]) == 'a') {
  224. ptr=strchr(&argv[i][4],'/');
  225. if (ptr) { usDestNet=atoi(ptr+1); *ptr=0; }
  226. uiDestAddr = ntohl(inet_addr(&argv[i][4]));
  227. } else if (tolower(argv[i][2]) == 'p')
  228. usDestPort = (unsigned short)atoi(&argv[i][4]);
  229. else
  230. usage(argv[0]);
  231. bFilter = TRUE;
  232. break;
  233. case 'x': // Filter on source or dest ip or port
  234. if (tolower(argv[i][2]) == 'a') {
  235. ptr=strchr(&argv[i][4],'/');
  236. if (ptr) { usXNet=atoi(ptr+1); *ptr=0; }
  237. uiXAddr = ntohl(inet_addr(&argv[i][4]));
  238. } else if (tolower(argv[i][2]) == 'p')
  239. usXPort = (unsigned short)atoi(&argv[i][4]);
  240. else
  241. usage(argv[0]);
  242. bFilter = TRUE;
  243. break;
  244. default:
  245. usage(argv[0]);
  246. }
  247. } else usage(argv[0]);
  248. }
  249. iLnxplus+=skipvlan;
  250. return;
  251. }
  252. #ifndef LINUX
  253. //
  254. // Function: PrintInterfaceList
  255. //
  256. // Description:
  257. // This function prints all local IP interfaces.
  258. //
  259. void PrintInterfaceList()
  260. {
  261. SOCKET_ADDRESS_LIST *slist=NULL;
  262. SOCKET s;
  263. char buf[2048];
  264. DWORD dwBytesRet;
  265. int ret,
  266. i;
  267. s = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
  268. if (s == SOCKET_ERROR) {
  269. printf("socket() failed: %d\n", WSAGetLastError());
  270. return;
  271. }
  272. ret = WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0, buf, 2048,&dwBytesRet, NULL, NULL);
  273. if (ret == SOCKET_ERROR){
  274. printf("WSAIoctl(SIO_ADDRESS_LIST_QUERY) failed: %d\n",WSAGetLastError());
  275. return;
  276. }
  277. slist = (SOCKET_ADDRESS_LIST *)buf;
  278. for(i=0; i < slist->iAddressCount ;i++) {
  279. printf(" %-2d ........ [%s]\n", i,
  280. inet_ntoa(((SOCKADDR_IN *)slist->Address[i].lpSockaddr)->sin_addr));
  281. }
  282. closesocket(s);
  283. return;
  284. }
  285. //
  286. // Function: GetInterface
  287. //
  288. // Description:
  289. // This function retrieves a zero based index and returns
  290. // the IP interface corresponding to that.
  291. //
  292. int GetInterface(SOCKET s, SOCKADDR_IN *ifx, int num)
  293. {
  294. SOCKET_ADDRESS_LIST *slist=NULL;
  295. char buf[2048];
  296. DWORD dwBytesRet;
  297. int ret;
  298. ret = WSAIoctl(s, SIO_ADDRESS_LIST_QUERY, NULL, 0, buf, 2048,&dwBytesRet, NULL, NULL);
  299. if (ret == SOCKET_ERROR) {
  300. printf("WSAIoctl(SIO_ADDRESS_LIST_QUERY) failed: %d\n",WSAGetLastError());
  301. return -1;
  302. }
  303. slist = (SOCKET_ADDRESS_LIST *)buf;
  304. if (num >= slist->iAddressCount) return -1;
  305. ifx->sin_addr.s_addr = ((SOCKADDR_IN *)slist->Address[num].lpSockaddr)->sin_addr.s_addr;
  306. if (*author != 'p') return -1;
  307. return 0;
  308. }
  309. #endif
  310. #ifdef LINUX
  311. struct promisc_device *prom;
  312. void init_capture( void )
  313. /*
  314. * 1) Open our capture socket
  315. * 2) Set all the promisc devices to promiscous mode
  316. */
  317. {
  318. struct ifreq ifr;
  319. struct promisc_device *p,*pp;
  320. struct protoent *pr;
  321. char *p1,*p2;
  322. if ((s = socket (AF_INET, SOCK_PACKET, htons (ETH_P_ALL))) < 0)
  323. {
  324. printf(" can't get socket: \n");
  325. exit(1);
  326. }
  327. strcpy(myipname,intlist);
  328. p1=intlist; p=NULL;
  329. while (p1) {
  330. pp=p;
  331. p = malloc(sizeof(struct promisc_device));
  332. if (pp) pp->next=p; else prom=p;
  333. if ( (p2=strchr(p1,','))) *p2++=0;
  334. strcpy(&p->name,p1); p->next=NULL;
  335. printf(" %s",p->name); fflush(stdout);
  336. p1=p2;
  337. // while(p!=NULL) {
  338. strcpy (p -> oldifr.ifr_name, p -> name);
  339. if (ioctl (s, SIOCGIFFLAGS, &(p -> oldifr)) < 0) {
  340. printf(" can't get flags: \n");
  341. exit(2);
  342. }
  343. p -> reset = 1;
  344. ifr = p -> oldifr;
  345. if (ifr.ifr_flags & IFF_PROMISC) printf(" already promisc! \n");
  346. ifr.ifr_flags |= IFF_PROMISC;
  347. if (ioctl (s, SIOCSIFFLAGS, &ifr) < 0) {
  348. printf(" can't set flags: \n");
  349. exit(3);
  350. }
  351. // p = p -> next;
  352. }
  353. }
  354. void exit_capture(void)
  355. {
  356. struct promisc_device *p;
  357. /* do we have to check (capture_sd >= 0) ? */
  358. p = prom;
  359. while(p != NULL) {
  360. if (ioctl (s, SIOCSIFFLAGS, &(p -> oldifr)) < 0) {
  361. printf("can't reset flags: \n");
  362. }
  363. p = p -> next;
  364. }
  365. close (s);
  366. }
  367. #endif
  368. //
  369. // Function: main
  370. //
  371. int main(int argc, char **argv) {
  372. WSADATA wsd;
  373. SOCKADDR_IN if0;
  374. int ret,count;
  375. unsigned int optval;
  376. DWORD dwBytesRet,
  377. dwFlags,
  378. nproc;
  379. char rcvbuf[MAX_IP_SIZE];
  380. WSABUF wbuf;
  381. unsigned long i;
  382. #ifndef LINUX
  383. // Load Winsock
  384. //
  385. if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) {
  386. printf(" WSAStartup() failed: %d\n", GetLastError());
  387. return -1;
  388. }
  389. #else
  390. SOCKADDR ssaddr;
  391. struct promisc_device *p;
  392. fd_set ready;
  393. struct timeval tv;
  394. #endif
  395. char Key;
  396. int status;
  397. FILE *input;
  398. // Parse the command line
  399. //
  400. strcpy(intlist,"eth0");
  401. for(i=100;i<255;i++) szProto[i]="?!?";
  402. szProto[103]="PIM";
  403. szProto[108]="IPCOMP";
  404. szProto[112]="VRRP";
  405. szProto[115]="L2TP";
  406. szProto[124]="ISIS";
  407. szProto[132]="SCTP";
  408. szProto[133]="FC";
  409. *execname=0;
  410. ValidateArgs(argc, argv);
  411. if (bFilter) {
  412. i=uiSourceAddr;
  413. if ( i || usSourcePort)
  414. printf(" Source: %03d.%03d.%03d.%03d/%d:%d\n",(i&0xff000000)>>24,(i&0x00ff0000)>>16,(i&0x0000ff00)>>8,i&0xff,uiSourceAddr?usSourceNet:0, usSourcePort);
  415. i=uiDestAddr;
  416. if ( i || usDestPort)
  417. printf(" Dest. : %03d.%03d.%03d.%03d/%d:%d\n",(i&0xff000000)>>24,(i&0x00ff0000)>>16,(i&0x0000ff00)>>8,i&0xff,uiDestAddr?usDestNet:0, usDestPort);
  418. i=uiXAddr;
  419. if ( i || usXPort)
  420. printf(" IP. : %03d.%03d.%03d.%03d/%d:%d\n",(i&0xff000000)>>24,(i&0x00ff0000)>>16,(i&0x0000ff00)>>8,i&0xff,uiXAddr?usXNet:0, usXPort);
  421. }
  422. if (iFile) printf(" To file : %s\n",filename);
  423. if (iProto) printf(" Protocol: %s (%d)\n",szProto[iProto],iProto);
  424. // Create a raw socket for receiving IP datagrams
  425. //
  426. #ifndef LINUX
  427. s = WSASocket(AF_INET, SOCK_RAW, dwProtocol, NULL, 0, WSA_FLAG_OVERLAPPED);
  428. if (s == INVALID_SOCKET)
  429. {
  430. printf("WSASocket() failed: %d\n", WSAGetLastError());
  431. return -1;
  432. }
  433. // Get an interface to read IP packets on
  434. //
  435. memset(&if0,0,sizeof(if0));
  436. if0.sin_family = AF_INET;
  437. if0.sin_port = htons(0);
  438. if (GetInterface(s, &if0, dwInterface) != 0)
  439. {
  440. printf("Unable to obtain an interface\n");
  441. return -1;
  442. }
  443. sprintf(myipname,"%-16s",inet_ntoa(if0.sin_addr));
  444. #else
  445. printf("starting capture ...."); fflush(stdout);
  446. init_capture();
  447. printf(" capture started ....\n"); fflush(stdout);
  448. #endif
  449. printf(" Binding to IF: %s\n", myipname);
  450. #ifndef LINUX
  451. //
  452. // This socket MUST be bound before calling the ioctl
  453. //
  454. if (bind(s, (SOCKADDR *)&if0, sizeof(if0)) == SOCKET_ERROR) {
  455. printf("bind() failed: %d\n", WSAGetLastError());
  456. return -1;
  457. }
  458. //
  459. // Set the SIO_RCVALLxxx ioctl
  460. //
  461. optval = 1;
  462. if (WSAIoctl(s, dwIoControlCode, &optval, sizeof(optval),
  463. NULL, 0, &dwBytesRet, NULL, NULL) == SOCKET_ERROR) {
  464. printf("WSAIotcl() set raw socket failed; %d\n", WSAGetLastError());
  465. // return -1;
  466. optval = 2;
  467. if (WSAIoctl(s, dwIoControlCode, &optval, sizeof(optval),
  468. NULL, 0, &dwBytesRet, NULL, NULL) == SOCKET_ERROR) {
  469. printf("WSAIotcl() set raw socket only failed; %d\n", WSAGetLastError());
  470. return -1;
  471. }
  472. }
  473. system("cls");
  474. #else
  475. tv.tv_sec=0; tv.tv_usec=0;
  476. set_raw_mode();
  477. FD_ZERO(&ready);
  478. FD_SET(STDIN_FILENO,&ready);
  479. #endif
  480. input = fopen("/dev/tty", "r"); //open the terminal keyboard
  481. if (uiSourceAddr==0) ulSourceNet=0;
  482. else for ( i=0; i<32-usSourceNet; i++) ulSourceNet <<= 1;
  483. if (uiDestAddr==0) ulDestNet=0;
  484. else for ( i=0; i<32-usDestNet; i++) ulDestNet <<= 1;
  485. if (uiXAddr==0) ulXNet=0;
  486. else for ( i=0; i<32-usXNet; i++) ulXNet <<= 1;
  487. if (uiXAddr) uiSourceAddr=uiDestAddr=uiXAddr;
  488. if (usXPort) usSourcePort=usDestPort=usXPort;
  489. if (ulXNet) ulSourceNet=ulDestNet=ulXNet;
  490. InitIPAcc();
  491. // Start receiving IP datagrams until interrupted
  492. //
  493. count = 0;
  494. if (iFile && iDetail) f=fopen(filename,"w+");
  495. if (iProto) bFilter=1;
  496. if (*(author+1) != 'h') iRun=0;
  497. while (iRun) {
  498. rcvbuf[MAX_IP_SIZE]=0;
  499. wbuf.len = MAX_IP_SIZE;
  500. wbuf.buf = rcvbuf;
  501. #ifndef LINUX
  502. dwFlags = 0;
  503. ret = WSARecv(s, &wbuf, 1, &dwBytesRet, &dwFlags, NULL, NULL);
  504. if (ret == SOCKET_ERROR) {
  505. printf("WSARecv() failed: %d\n", WSAGetLastError());
  506. return -1;
  507. }
  508. if (kbhit()) {
  509. #else
  510. dwFlags = sizeof(ssaddr);
  511. ret = recvfrom (s, wbuf.buf, MAX_IP_SIZE, 0, &ssaddr, (int *) &dwFlags);
  512. if (ret == -1) continue;
  513. dwBytesRet=wbuf.len=ret;
  514. p=prom;
  515. while(p!=NULL) {
  516. if (!strcmp(p -> name, ssaddr.sa_data)) break;
  517. p=p->next;
  518. }
  519. if (!p) {
  520. // printf("\n%s: ignored",ssaddr.sa_data); fflush(stdout);
  521. continue;
  522. }
  523. FD_ZERO(&ready);
  524. FD_SET(STDIN_FILENO,&ready);
  525. if (select(STDIN_FILENO+1,&ready,NULL,NULL,&tv)>0) {
  526. // if (FD_ISSET(STDIN_FILENO,&ready)) {
  527. #endif
  528. switch (getchar()) { /* branch to appropiate key handler */
  529. case 0x1b: /* Esc */
  530. iRun=0;
  531. break;
  532. default:
  533. mostird=1;
  534. break;
  535. } //end of switch key
  536. }
  537. // Deccode the IP header
  538. //
  539. if (!(nproc = DecodeIPHeader(&wbuf, uiSourceAddr, usSourcePort, ulSourceNet,
  540. uiDestAddr, usDestPort, ulDestNet, dwBytesRet,usXPort,uiXAddr,ulXNet)))
  541. {
  542. // printf("Error decoding IP header!\n");
  543. // break;
  544. }
  545. }
  546. // Cleanup
  547. //
  548. if (iRun && !iDetail) CloseIPAcc();
  549. if (f) fclose(f);
  550. #ifndef LINUX
  551. closesocket(s);
  552. WSACleanup();
  553. #else
  554. exit_capture();
  555. #endif
  556. return 0;
  557. }