9322b745d8fdef0e0871b305bc56bde7d7b5f372
[my-code/hdw-sniff.git] / main.c
1 /*
2  * main.c - main hdw-sniff
3  *
4  * Copyright (C) 2004/05 hackbard@hackdaworld.org
5  *
6  */
7
8 #include "main.h"
9
10 /* functions */
11
12 int display_console(t_info *info,char *string) {
13
14   int x,y,size,count,cnt,i,s;
15   t_display *display;
16   t_sta *sta;
17   char help[32];
18
19   display=(t_display *)&(info->display);
20
21   x=display->max_x-1;
22   y=display->max_y-1;
23
24   size=strlen(string);
25
26   if(info->view==VIEW_ALL) {
27     count=list_count(&(info->sniffed_sta));
28     cnt=((count>y-5)?y-5:count);
29
30     display_line(display,0,0,x,0,'-');
31     display_string(display,GUI_OFFSET_STA,1,"sta/ap",6);
32     display_string(display,GUI_OFFSET_SSID,1,"| ssid",6);
33     display_string(display,GUI_OFFSET_AP,1,"| ap",4);
34     display_string(display,GUI_OFFSET_WEP,1,"| wep",5);
35     display_string(display,GUI_OFFSET_MGMT,1,"| mgmt",6);
36     display_string(display,GUI_OFFSET_CTRL,1,"| ctrl",6);
37     display_string(display,GUI_OFFSET_DATA,1,"| data",6);
38     display_string(display,GUI_OFFSET_ACTIVE,1,"| act",5);
39     display_string(display,GUI_OFFSET_SIGNAL,1,"| sq",4);
40     display_line(display,0,2,x,2,'-');
41
42     list_reset(&(info->sniffed_sta));
43
44     for(i=0;i<cnt;i++) {
45       sta=(t_sta *)info->sniffed_sta.current->data;
46       snprintf(help,32,"%02x:%02x:%02x:%02x:%02x:%02x",
47                sta->addr[0],sta->addr[1],sta->addr[2],
48                sta->addr[3],sta->addr[4],sta->addr[5]);
49       display_string(display,GUI_OFFSET_STA,3+i,help,17);
50       s=strlen(sta->ssid);
51       s=((s>=16)?16:s);
52       help[0]='|'; help[1]=' ';
53       memcpy(&help[2],sta->ssid,s);
54       display_string(display,GUI_OFFSET_SSID,3+i,help,s+2);
55       snprintf(help,4,"| %c",sta->ap?'y':'n');
56       display_string(display,GUI_OFFSET_AP,3+i,help,3);
57       snprintf(help,5,"|  %c",sta->wep?'y':'n');
58       display_string(display,GUI_OFFSET_WEP,3+i,help,4);
59       snprintf(help,21,"| %04d | n.a. | n.a.",
60                sta->count_mgmt);
61       display_string(display,GUI_OFFSET_MGMT,3+i,help,20);
62       snprintf(help,5,"|  %c",sta->active);
63       display_string(display,GUI_OFFSET_ACTIVE,3+i,help,4);
64       snprintf(help,5,"| %02u",sta->sq);
65       display_string(display,GUI_OFFSET_SIGNAL,3+i,help,4);
66       list_next(&(info->sniffed_sta));
67     }
68   }
69
70   else if(info->view==VIEW_SINGLE) {
71     list_reset(&(info->sniffed_sta));
72     for(i=0;i<info->c_line;i++) list_next(&(info->sniffed_sta));
73     sta=(t_sta *)info->sniffed_sta.current->data;
74     display_line(display,0,0,x,0,'-');
75     snprintf(help,22,"sta %02x:%02x:%02x:%02x:%02x:%02x",
76              sta->addr[0],sta->addr[1],sta->addr[2],
77              sta->addr[3],sta->addr[4],sta->addr[5]);
78     display_string(display,1,1,help,21);
79     if(sta->ap) strcpy(help,"(access point)");
80     else strcpy(help,"(station)");
81     s=strlen(help);
82     display_string(display,23,1,help,s);
83     snprintf(help,2,"%c",sta->active);
84     display_string(display,x-1,1,help,1);
85     snprintf(help,7,"sq: %02d",sta->sq);
86     display_string(display,x-8,1,help,6);
87     display_line(display,0,2,x,2,'-');
88     display_string(display,1,3,"ssid: ",6);
89     s=strlen(sta->ssid);
90     memcpy(help,sta->ssid,s);
91     display_string(display,7,3,help,s);
92     if(sta->wep) strcpy(help,"crypted");
93     else strcpy(help,"not crypted");
94     s=strlen(help);
95     display_string(display,x-s-1,3,help,s);
96
97     snprintf(help,13,"mgmt: %06d",sta->count_mgmt);
98     display_string(display,1,5,help,12);
99     snprintf(help,13,"ctrl: %06d",sta->count_ctrl);
100     display_string(display,1,6,help,12);
101     snprintf(help,13,"data: %06d",sta->count_data);
102     display_string(display,1,7,help,12);
103   }
104
105   /* footer */
106   display_line(display,0,y-3,x,y-3,'-');
107
108   snprintf(help,14,"total: %06d",info->count);
109   display_string(display,1,y-2,help,13);
110   snprintf(help,13,"mgmt: %06d",info->count_m);
111   display_string(display,15,y-2,help,12);
112   snprintf(help,12,"ctrl: %06d",info->count_c);
113   display_string(display,28,y-2,help,11);
114   snprintf(help,13,"data: %06d",info->count_d);
115   display_string(display,40,y-2,help,12);
116
117   display_line(display,0,y-1,x,y-1,'-');
118
119   if(size!=0) {
120     display_string(display,0,y,info->clean_line,x);
121     display_string(display,1,y,string,size);
122   }
123
124   display_draw(display);
125
126   if(info->view==VIEW_ALL)
127     display_set_cursor(display,0,3+info->c_line);
128
129
130   return 23;
131 }
132
133 int noop(t_input *input,void *ptr) {
134
135   return 23;
136 }
137
138 int get_user_interaction(t_info *info) {
139
140   char *string;
141   int hlp=0;
142
143   string=(char *)malloc(info->display.max_x*sizeof(char));
144
145   input_get_event(&(info->input),noop,info);
146
147   /* clear display */
148   display_clear_screen(&(info->display));
149
150   if(info->input.content[0]=='x') {
151     info->mode^=MODE_HEXOUT;
152     display_console(info,"toggled hex output");
153   }
154
155   else if(info->input.content[0]=='a') {
156     info->mode^=MODE_ASCIIOUT;
157     display_console(info,"toggled ascii output");
158   }
159
160   else if(info->input.content[0]=='q') {
161     event_stop(&(info->event));
162     display_console(info,"quit!");
163   }
164   else if(info->input.content[0]=='n') {
165     hlp=list_count(&(info->sniffed_sta)); 
166     if(info->c_line<hlp-1) info->c_line++;
167   }
168   else if(info->input.content[0]=='p') {
169     if(info->c_line>0) info->c_line--;
170   }
171   else if(info->input.content[0]==0x0d) {
172     display_clear_screen(&(info->display));
173     if(info->view==VIEW_ALL) info->view=VIEW_SINGLE;
174     else info->view=VIEW_ALL;
175   }
176   else {
177     snprintf(string,info->display.max_x,"unknown event (%x)",
178              info->input.content[0]);
179     display_console(info,string);
180   }
181
182   return 23;
183 }
184
185 int react_on_event(t_event *event,void *ptr) {
186
187   t_info *info;
188
189   info=(t_info *)ptr;
190
191   if(event_check(event,0)==E_FD_YES) get_user_interaction(info);
192   else pcap_dispatch(info->pcap_handle,-1,parse_package,(u_char *)ptr);
193
194   return 23;
195 }
196
197 int usage(void) {
198   puts("usage: hdw-sniff <options>");
199   puts("\toptions:");
200   puts("\t\t-m <mode> \tieee80211 or prism");
201   puts("\t\t-d <device> \twlan0,eth0");
202   puts("\t\t-l <logfile>");
203   puts("\t\t-k <key> \t(string)");
204   puts("\t\t-D <file> \t(dump packages to file)");
205   puts("\t\t-h \tdisplay this help message");
206   puts("");
207
208   return 23;
209 }
210
211 int hop_channel(t_event *event,void *ptr) {
212  
213   struct iwreq iwreq;
214   t_info *info;
215
216   info=(t_info *)ptr;
217
218   if((info->current_channel>CHANNEL_MAX)|(info->current_channel==0))
219     info->current_channel=1;
220   memset(&iwreq,0,sizeof(iwreq));
221   strcpy(iwreq.ifr_name,info->device);
222   iwreq.u.freq.e=0;
223   iwreq.u.freq.m=info->current_channel;
224   if(ioctl(info->channel_hop_fd,SIOCSIWFREQ,&iwreq)<0) {
225     puts("unable to hop channel");
226     perror("ioctl");
227     return -23;
228   }
229   ++(info->current_channel);
230
231   return 23;
232 }
233
234 int main(int argc, char **argv) {
235
236   t_info info;
237   int pcap_fd;
238   int i;
239   char sys_call[MAX_SYSCALL_CHARS];
240   char pcap_error[PCAP_ERRBUF_SIZE];
241
242   memset(&info,0,sizeof(t_info));
243
244  /* parse arguments */
245  for(i=1;i<argc;i++) {
246   if(argv[i][0]=='-') {
247    switch(argv[i][1]) {
248     case 'h':
249      usage();
250     case 'm':
251      if(!strncmp(argv[i+1],"ieee80211",9)) {
252       info.mode|=MODE_IEEE80211;
253       puts("expecting ieee802.11 header in package");
254      }
255      else if(!strncmp(argv[i+1],"prism",5)) {
256       info.mode|=MODE_PRISM;
257       puts("expecting prism header in package.");
258      }
259      else {
260       printf("unknown mode: %s\n",argv[1]);
261       return -23;
262      }
263      ++i;
264      break;
265     case 'l':
266      if((info.log_fd=open(argv[i+1],O_RDWR|O_CREAT|O_APPEND))!=0)
267       printf("logfile -> %s\n",argv[i+1]);
268      else
269       puts("warning: can't write to logfile.");
270      ++i;
271      break;
272     case 'D':
273      if((info.dump_fd=open(argv[i+1],O_RDWR|O_CREAT))!=0)
274       printf("dump file -> %s\n",argv[i+1]);
275      else
276       puts("warning: can't dump to file.");
277      ++i;
278      break;
279     case 'd':
280      strncpy(info.device,argv[i+1],MAX_DEV_CHARS);
281      ++i;
282      break;
283     default:
284      usage();
285      return -23;
286    }
287   } else {
288    usage();
289    return -23;
290   }
291  }
292
293  /* setting up device */
294  if(info.mode&MODE_IEEE80211)
295   sprintf(sys_call,"iwpriv %s monitor 2",info.device);
296  else if(info.mode&MODE_PRISM)
297   sprintf(sys_call,"iwpriv %s monitor 3",info.device);
298
299  puts("set monitoring mode ...");
300  system(sys_call);
301  
302  sprintf(sys_call,"ifconfig %s up",info.device);
303  puts("setting up device ...");
304  system(sys_call);
305
306  if(info.log_fd==0) {
307    if((info.log_fd=open("/tmp/hdw-sniff.log",O_RDWR|O_CREAT|O_APPEND))!=0)
308      puts("using logfile /tmp/hdw-sniff.log ...");
309    else {
310      puts("failed to open logfile ...");
311      return -23;
312    }
313  }
314
315  /* pcap */
316  if((info.pcap_handle=pcap_open_live(info.device,BUFSIZ,1,-1,pcap_error))==NULL)
317  {
318   printf("%s: %s\n",argv[0],pcap_error);
319   return -23;
320  }
321  pcap_fd=pcap_fileno(info.pcap_handle);
322  /* -> non blocking? */
323
324  /* socket fd for channel hopping */
325  info.channel_hop_fd=socket(AF_INET,SOCK_DGRAM,0);
326
327  display_init(&(info.display),info.log_fd);
328  if(info.display.max_x<HDW_SNIFF_MAX_WIDTH) {
329    display_shutdown(&(info.display));
330    puts("");
331    puts("");
332    puts("fatal! please increase your terminals width");
333    puts("");
334    return -23;
335  }
336  if(info.display.max_y<HDW_SNIFF_MAX_HEIGHT) {
337    display_shutdown(&(info.display));
338    puts("");
339    puts("");
340    puts("fatal! please increase your terminals width");
341    puts("");
342    return -23;
343  }
344  info.clean_line=(char *)malloc(info.display.max_x);
345  memset(info.clean_line,0x20,info.display.max_x);
346  info.view=VIEW_ALL;
347
348  display_console(&info,
349    "Welcome to hdw-sniff, Copyright (C) 2004/05 hackbard");
350  sleep(2);
351
352  input_init(&(info.input),info.log_fd);
353  input_ios_init(&info.input);
354
355  list_init(&(info.sniffed_sta),info.log_fd);
356
357  event_init(&(info.event),info.log_fd);
358  event_set_timeout(&(info.event),HOP_SEC,HOP_USEC);
359
360  event_math(0,&(info.event),READ,ADD);
361  event_math(pcap_fd,&(info.event),READ,ADD);
362
363  event_start(&(info.event),&info,react_on_event,hop_channel);
364
365  list_shutdown(&(info.sniffed_sta));
366  input_shutdown(&(info.input));
367  display_shutdown(&(info.display));
368  
369  puts("");
370  puts("");
371  puts("thanks for using hdw-sniff (C) 2004/05 hackbard");
372  puts("");
373  puts("bugreports: hackbard@hackdaworld.org");
374
375  return 23;
376 }