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